Jump to:
Screenshot
Attributes
Emails
<?php
// errors
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// config
class config
{
// DEFAULT CONFIG
// Only edit directly if it is a temporary installation. Settings added here will be lost when updating!
// Instead, add options from external config file in your storage_path [_files/config/config.php]
// READ MORE: https://forum.photo.gallery/viewtopic.php?f=66&t=9964
public static $default = array(
// paths
'root' => '',
// root path relative to script / empty is same as files app location
'start_path' => false,
// start path relative to script. If empty, root is start path
// login
'username' => '',
'password' => '',
// Add password directly or use https://files.photo.gallery/tools/hash/ to encrypt the password (encrypted password is more secure, as it prevents your password from being exposed directly in a file).
// images
'load_images' => true,
'load_files_proxy_php' => false,
'load_images_max_filesize' => 1000000,
// maximum file size (bytes) for un-resized images loaded into list
'load_svg_max_filesize' => 100000,
// 100k
'image_resize_enabled' => true,
// resize images for the interface
'image_resize_cache' => true,
// todo: remove this option and just use 'cache?
'image_resize_dimensions' => 320,
'image_resize_dimensions_retina' => 480,
'image_resize_dimensions_allowed' => '',
// comma-separated list of allowed resize dimensions
'image_resize_types' => 'jpeg, png, gif, webp, bmp',
// image types to resize / jpeg, png, gif, webp, bmp
'image_resize_quality' => 85,
'image_resize_function' => 'imagecopyresampled',
// imagecopyresampled / imagecopyresized
'image_resize_sharpen' => true,
'image_resize_memory_limit' => 128,
// 128 MB is suffient to resize images around 6000 px / 0 = ignore memory
'image_resize_max_pixels' => 30000000,
// 30 MP equivalent to an image 6000 x 5000 / 0 = no limit
'image_resize_min_ratio' => 1.5,
// min size diff original vs resize. Only resizes if ratio > min ratio
'image_resize_cache_direct' => false,
// if enabled and delete cache, must increase cache_key
'folder_preview_image' => true,
// enable folder preview images / might be slow as it requires searching each dir for images
'folder_preview_default' => '_filespreview.jpg',
// use this image as folder preview if exists in dir
// menu
'menu_enabled' => true,
'menu_show' => true,
'menu_max_depth' => 5,
'menu_sort' => 'name_asc',
// name_asc, name_desc, date_asc, date_desc
'menu_cache_validate' => true,
'menu_load_all' => false,
'menu_recursive_symlinks' => true,
// List sub-directories of symlinks in the main menu. May cause loops and duplicates
// files layout
'layout' => 'rows',
// list, imagelist, blocks, grid, rows, columns
'sort' => 'name_asc',
// name, date, filesize, kind / asc, desc
'sort_dirs_first' => true,
// sort dirs on top
// cache
'cache' => true,
'cache_key' => 0,
'storage_path' => '_files',
// exclude files directories regex
'files_exclude' => '',
// '/\.(pdf|jpe?g)$/i'
'dirs_exclude' => '',
//'/\/Convert|\/football|\/node_modules(\/|$)/i',
'allow_symlinks' => true,
// allow symlinks
// various
'history' => true,
'breadcrumbs' => true,
'transitions' => true,
'click' => 'popup',
// popup, modal, download, window, menu / default item click
'click_window' => '',
// 'pdf, html, php, zip' / list of file extensions to open directly on click
'click_window_popup' => true,
// Popup instead of new tab. Useful for viewing PDF, HTML and text type documents / desktop only
'code_max_load' => 100000,
// max filesize of text files to load and preview
'topbar_sticky' => 'scroll',
// true, false, 'scroll'
'check_updates' => false,
// show notification in topbar with option to update when new version is available
'allow_tasks' => false,
'get_mime_type' => false,
// get file mime type from server (slow) instead of from extension (fast)
'context_menu' => true,
// disable context-menu button and right-click menu
'prevent_right_click' => false,
// blocks browser right-click menu on sensitive items (images, list items, menu)
'license_key' => '',
'filter_live' => true,
// live search filtering on keyboard input / does not apply for mobile devices
'filter_props' => 'name, filetype, mime, features, title',
// file properties to filter / name, filetype, mime, features, title, headline, description, creator, credit, copyright, keywords, city, sub-location, province-state'
'download_dir' => 'zip',
// download all files in folder / 'zip' / 'files' / '' false (disabled)
'download_dir_cache' => 'dir',
// enable caching of created zip dirs / 'dir' / 'storage' / '' false (disabled)
// filemanager options
'allow_upload' => false,
// allow uploader
'allow_delete' => false,
// allow deleting files and folders
'allow_rename' => false,
// allow renaming files and folders
'allow_new_folder' => false,
// allow make new directory
'allow_new_file' => false,
// allow make new empty file
'allow_duplicate' => false,
// allow duplicate files
'allow_text_edit' => false,
// allow editing text-based files in modal
'demo_mode' => false,
// block all filemanager operations but allow them to show in interface / used in Files app demo
// uploader options
'upload_allowed_file_types' => '',
// comma-separated list of allowed upload file types / empty = allow any / 'jpeg, jpg, image/*'
'upload_max_filesize' => 0,
// [bytes] / 0 = unlimited (but limited by server PHP upload_max_filesize)
'upload_note' => '',
// include a small text note at bottom of uploader / 'Max file size %upload_max_filesize%'
'upload_exists' => 'increment',
// 'increment' / 'overwrite' / 'fail'
// popup options
'popup_video' => true,
// opens videos in the popup (instead of modal)
'popup_transition' => 'glide',
// none, slide, glide, fade, zoom, pop, elastic
'popup_transition_play' => 'inherit',
// transition in play mode
'popup_interval' => 5000,
// interval ms between slides in play mode
'popup_caption' => true,
// enable popup caption
'popup_caption_hide' => true,
// autohide popup caption after a few seconds without user input
'popup_caption_style' => 'block',
// block, box, gradient, topbar, none
'popup_caption_align' => 'center-left',
// left, center-left, center, right
// video
'video_thumbs' => true,
// allow video thumbnails / requires FFmpeg and PHP exec() function enabled.
'video_ffmpeg_path' => 'ffmpeg',
// path to ffmpeg command, normally 'ffmpeg' http://ffmpeg.org/
'video_autoplay' => true,
// video autoplay on click
// language
'lang_default' => 'en',
// default language if browser lang is not supported/detected or lang_auto is disabled
'lang_auto' => true,
// automatically load language based on detected browser language
'lang_menu' => false,
);
// config (will popuplate)
public static $config = array();
// app vars
static $__dir__ = "/var/www/html";
static $__file__ = "/var/www/html/manager3.php.cf6eb2c9bf1fb4ebc58b7883af08523b.bin";
static $assets;
static $prod = true;
static $version = '0.3.1';
static $root;
static $doc_root;
static $has_login = false;
static $storage_path;
static $storage_is_within_doc_root = false;
static $storage_config_realpath;
static $storage_config;
static $cache_path;
static $image_resize_cache_direct;
static $image_resize_dimensions_retina = false;
static $dirs_hash = false;
static $local_config_file = '_filesconfig.php';
static $username = false;
static $password = false;
static $x3_path = false;
// get config
private function get_config($path)
{
if (empty($path) || !file_exists($path)) {
return array();
}
$config = (include $path);
return empty($config) || !is_array($config) ? array() : array_map(function ($v) {
return is_string($v) ? trim($v) : $v;
}, $config);
}
// files check system and config [diagnostics]
private function files_check($local_config, $storage_path, $storage_config, $user_config, $user_valid)
{
echo '<!doctype html><html><head><title>Files App check system and config.</title><meta name="robots" content="noindex,nofollow"><style>body{font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; color: #444;line-height:1.6;margin:0 auto;max-width:700px}.container{background-color:#F3F3F3;padding:.5vw 2vw 2vw;border-radius:3px;margin:1vw;overflow:scroll}.test:before{display:inline-block;width:18px;text-align:center;margin-right:5px}.neutral:before{color:#BBB}.success:before{color:#78a642}.success:before,.neutral:before{content:"\\2713"}.fail:before{content:"\\2716";color:firebrick}</style></head><body><div class="container"><h2>Files App ' . config::$version . '</h2><div style="margin:-1rem 0 .5rem">' . (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] . '<br>' : '') . 'PHP ' . phpversion() . '<br>' . (isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : '') . '<p><i>* The following tests are only to help diagnose feature-specific issues.</i></p></div>';
// output helper
function prop($name, $success = 'neutral', $val = false)
{
return '<div class="test ' . (is_bool($success) ? $success ? 'success' : 'fail' : $success) . '">' . $name . ($val ? ': <b>' . $val . '</b>' : '') . '</div>';
}
echo prop('storage_path exists', file_exists(config::$config['storage_path']));
if (file_exists(config::$config['storage_path'])) {
echo prop('storage_path is_writeable', is_writable(config::$config['storage_path']));
}
echo prop('root is_writeable', is_writable(config::$config['root']));
// extension_loaded
if (function_exists('extension_loaded')) {
foreach (['gd', 'exif'] as $name) {
echo prop($name, extension_loaded($name));
}
}
echo prop('ZipArchive', class_exists('ZipArchive'));
// function_exsists
foreach (['mime_content_type', 'finfo_file', 'iptcparse', 'exif_imagetype', 'session_start', 'ini_get', 'exec'] as $name) {
echo prop($name . '()', function_exists($name));
}
// ffmpeg
if (function_exists('exec')) {
echo prop('ffmpeg', !!exec('type -P ' . config::$config['video_ffmpeg_path']));
}
// ini_get
if (function_exists('ini_get')) {
foreach (['memory_limit', 'file_uploads', 'upload_max_filesize', 'post_max_size', 'max_file_uploads'] as $name) {
echo prop($name, 'neutral', @ini_get($name));
}
}
echo "</div><div class=\"container\"><h3>Config</h3>";
// invalid and duplicate arrays
$user_invalid = array_diff_key($user_config, self::$default);
$user_duplicate = array_intersect_assoc($user_valid, self::$default);
// items
$items = array(['arr' => $local_config, 'comment' => "// LOCAL CONFIG\n// " . self::$local_config_file], ['arr' => $storage_config, 'comment' => "// STORAGE CONFIG\n// " . rtrim($storage_path ?: '', '\\/') . '/config/config.php'], ['arr' => $user_invalid, 'comment' => "// INVALID PARAMS\n// The following custom parameters will be ignored as they are not valid:", 'var' => '$invalid', 'hide' => empty($user_invalid)], ['arr' => $user_duplicate, 'comment' => "// DUPLICATE DEFAULT PARAMS\n// The following custom parameters will have no effect as they are identical to defaults:", 'var' => '$duplicate', 'hide' => empty($user_duplicate)], ['arr' => $user_valid, 'comment' => "// USER CONFIG\n// User config parameters.", 'var' => '$user', 'hide' => (empty($local_config) || empty($storage_config)) && empty($user_invalid)], ['arr' => self::$config, 'comment' => "// CONFIG\n// User parameters merged with default parameters.", 'var' => '$config'], ['arr' => self::$default, 'comment' => "// DEFAULT CONFIG\n// Default config parameters.", 'var' => '$default']);
// loop
$output = "<?php\n";
foreach ($items as $arr => $props) {
$is_empty = empty($props['arr']);
if (isset($props['hide']) && $props['hide']) {
continue;
}
foreach (['username', 'password', 'license_key', 'allow_tasks', '__dir__', '__file__'] as $prop) {
if (isset($props['arr'][$prop]) && !empty($props['arr'][$prop]) && is_string($props['arr'][$prop])) {
$props['arr'][$prop] = '***';
}
}
$export = $is_empty ? 'array ()' : var_export($props['arr'], true);
$comment = preg_replace('/\\n/', " [" . count($props['arr']) . "]\n", $props['comment'], 1);
$var = isset($props['var']) ? $props['var'] . ' = ' : 'return ';
$output .= PHP_EOL . $comment . PHP_EOL . $var . $export . ';' . PHP_EOL;
}
highlight_string($output . PHP_EOL . ';?>');
echo "</div></body></html>";
exit;
}
// save config
public static function save_config($config = array())
{
$save_config = array_intersect_key(array_replace(self::$storage_config, $config), self::$default);
$export = preg_replace("/ '/", " //'", var_export(array_replace(self::$default, $save_config), true));
foreach ($save_config as $key => $value) {
if ($value !== self::$default[$key]) {
$export = str_replace("//'" . $key, "'" . $key, $export);
}
}
return @file_put_contents(config::$storage_config_realpath, "<?php \n\n// CONFIG / https://forum.photo.gallery/viewtopic.php?f=66&t=9964\n// Uncomment the parameters you want to edit.\nreturn " . $export . ';');
}
// construct
function __construct($is_doc = false)
{
// normalize OS paths
self::$__dir__ = real_path("/var/www/html");
self::$__file__ = real_path("/var/www/html/manager3.php.cf6eb2c9bf1fb4ebc58b7883af08523b.bin");
// local config
$local_config = self::get_config(self::$local_config_file);
// storage config
$storage_path = isset($local_config['storage_path']) ? $local_config['storage_path'] : self::$default['storage_path'];
$storage_realpath = !empty($storage_path) ? real_path($storage_path) : false;
if ($is_doc && $storage_realpath === self::$__dir__) {
error('<strong>storage_path must be a unique dir.</strong>');
}
self::$storage_config_realpath = $storage_realpath ? $storage_realpath . '/config/config.php' : false;
self::$storage_config = self::get_config(self::$storage_config_realpath);
// config
$user_config = array_replace(self::$storage_config, $local_config);
$user_valid = array_intersect_key($user_config, self::$default);
self::$config = array_replace(self::$default, $user_valid);
// files check with ?check=true
if (get('check')) {
self::files_check($local_config, $storage_path, self::$storage_config, $user_config, $user_valid);
}
// if(get('phpinfo')) { phpinfo(); exit; } // check system phpinfo with ?phpinfo=true / disabled for security / un-comment if you want to use
// CDN assets
self::$assets = self::$prod ? 'https://cdn.jsdelivr.net/npm/files.photo.gallery@' . self::$version . '/' : '';
// root
self::$root = real_path(self::$config['root']);
if ($is_doc && !self::$root) {
error('root dir "' . self::$config['root'] . '" does not exist.');
}
// doc root
self::$doc_root = real_path($_SERVER['DOCUMENT_ROOT']);
// login credentials
self::$username = self::$config['username'];
self::$password = self::$config['password'];
// X3 compatibility / x3 login / images from X3 resize cache / invalidate X3 cache on filemanager op / X3 license
$x3_path = dirname(self::$root);
self::$x3_path = file_exists($x3_path . '/app/x3.inc.php') ? $x3_path : false;
if (self::$x3_path && self::$username === 'x3') {
$x3_config = file_exists($x3_path . '/config/config.user.json') ? json_decode(file_get_contents($x3_path . '/config/config.user.json'), true) : false;
self::$username = isset($x3_config['back']['panel']['username']) ? $x3_config['back']['panel']['username'] : 'admin';
self::$password = isset($x3_config['back']['panel']['password']) ? $x3_config['back']['panel']['password'] : 'admin';
if (self::$username === 'admin' && self::$password === 'admin' && isset($x3_config['back']['panel']['use_db'])) {
error('Sorry, Files app is not compatible with X3 panel database login. Assign "username" and "password" separately in _files/config/config.php.', 403);
}
}
// has_login
self::$has_login = self::$username || self::$password ? true : false;
// $image_cache
$image_cache = self::$config['image_resize_enabled'] && self::$config['image_resize_cache'] && self::$config['load_images'] ? true : false;
// cache enabled
if ($image_cache || self::$config['cache']) {
// create storage_path
if (empty($storage_realpath)) {
$storage_path = is_string($storage_path) ? rtrim($storage_path, '\\/') : false;
if (empty($storage_path)) {
error('Invalid storage_path parameter.');
}
mkdir_or_error($storage_path);
$storage_realpath = real_path($storage_path);
if (empty($storage_realpath)) {
error("storage_path <strong>{$storage_path}</strong> does not exist and can't be created.");
}
self::$storage_config_realpath = $storage_realpath . '/config/config.php';
// update since it wasn't assigned
}
self::$storage_path = $storage_realpath;
// storage path is within doc root
if (is_within_docroot(self::$storage_path)) {
self::$storage_is_within_doc_root = true;
}
// cache_path real path
self::$cache_path = self::$storage_path . '/cache';
// create storage dirs
if ($is_doc) {
$create_dirs = [$storage_realpath . '/config'];
if ($image_cache) {
$create_dirs[] = self::$cache_path . '/images';
}
if (self::$config['cache']) {
array_push($create_dirs, self::$cache_path . '/folders', self::$cache_path . '/menu');
}
foreach ($create_dirs as $create_dir) {
mkdir_or_error($create_dir);
}
}
// create/update config file, with default parameters commented out.
if ($is_doc && self::$storage_config_realpath && (!file_exists(self::$storage_config_realpath) || filemtime(self::$storage_config_realpath) < filemtime("/var/www/html/manager3.php.cf6eb2c9bf1fb4ebc58b7883af08523b.bin"))) {
self::save_config();
}
// image resize cache direct
if (self::$config['image_resize_cache_direct'] && !self::$has_login && self::$config['load_images'] && self::$config['image_resize_cache'] && self::$config['image_resize_enabled'] && self::$storage_is_within_doc_root) {
self::$image_resize_cache_direct = true;
}
}
// image_resize_dimensions_retina
if (self::$config['image_resize_dimensions_retina'] && self::$config['image_resize_dimensions_retina'] > self::$config['image_resize_dimensions']) {
self::$image_resize_dimensions_retina = self::$config['image_resize_dimensions_retina'];
}
// dirs hash
self::$dirs_hash = substr(md5(self::$doc_root . self::$__dir__ . self::$root . self::$version . self::$config['cache_key'] . self::$image_resize_cache_direct . self::$config['files_exclude'] . self::$config['dirs_exclude']), 0, 6);
// login
if (self::$has_login) {
check_login($is_doc);
}
}
}
// login page
function login_page($is_login_attempt, $sidx, $is_logout, $client_hash)
{
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover, user-scalable=no, shrink-to-fit=no">
<meta name="robots" content="noindex,nofollow">
<title>Login</title>
<link href="<?php
echo config::$assets;
?>css/files.css" rel="stylesheet">
<?php
get_include('css/custom.css');
?>
</head>
<body><div id="files-login-container"></div></body>
<script>
document.getElementById('files-login-container').innerHTML = '\
<h1 class="header mb-5">Login</h1>\
<?php
if ($is_login_attempt && $_POST['sidx'] !== $sidx) {
?><div class="alert alert-danger" role="alert"><strong>PHP session ID mismatch</strong><br>If the error persists, your PHP is incorrectly creating new session ID for each request.</div><?php
} else {
if ($is_login_attempt) {
?>\
<div class="alert alert-danger" role="alert">Incorrect login!</div><?php
} else {
if ($is_logout) {
?>\
<div class="alert alert-warning" role="alert">You are now logged out.</div><?php
}
}
}
?>\
<form>\
<div class="mylogin">\
<input type="text" name="username" placeholder="Username">\
<input type="password" name="password" placeholder="Password">\
</div>\
<input type="text" name="fusername" class="form-control form-control-lg mb-3" placeholder="Username" required autofocus spellcheck="false" autocorrect="off" autocapitalize="off">\
<input type="password" name="fpassword" class="form-control form-control-lg mb-3" placeholder="Password" required spellcheck="false">\
<input type="hidden" name="client_hash" value="<?php
echo $client_hash;
?>">\
<input type="hidden" name="sidx" value="<?php
echo $sidx;
?>">\
<input type="submit" value="Login" class="btn btn-lg btn-files-light btn-login">\
</form>';
document.getElementsByTagName('form')[0].addEventListener('submit', function(){
this.action = '<?php
echo isset($_GET['logout']) ? strtok($_SERVER['REQUEST_URI'], '?') : $_SERVER['REQUEST_URI'];
?>';
this.method = 'post';
}, false);
</script>
</html>
<?php
exit;
}
// check login
function check_login($is_doc)
{
if ($is_doc && empty(config::$username)) {
error('Username cannot be empty.');
}
if ($is_doc && empty(config::$password)) {
error('Password cannot be empty.');
}
if (!session_start() && !$is_dor) {
error('Failed to initiate PHP session_start();', 500);
}
function get_client_hash()
{
foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key) {
if (isset($_SERVER[$key]) && !empty($_SERVER[$key]) && filter_var($_SERVER[$key], FILTER_VALIDATE_IP)) {
return md5($_SERVER[$key] . $_SERVER['HTTP_USER_AGENT'] . "/var/www/html/manager3.php.cf6eb2c9bf1fb4ebc58b7883af08523b.bin" . $_SERVER['HTTP_HOST']);
}
}
error('Invalid IP', 401);
}
// hash
$client_hash = get_client_hash();
$login_hash = md5(config::$username . config::$password . $client_hash);
// login status
$is_logout = isset($_GET['logout']) && isset($_SESSION['login']);
if ($is_logout) {
unset($_SESSION['login']);
}
$is_logged_in = !$is_logout && isset($_SESSION['login']) && $_SESSION['login'] === $login_hash;
// not logged in
if (!$is_logged_in) {
// login only on html pages
if ($is_doc) {
// vars
$sidx = md5(session_id());
$is_login_attempt = isset($_POST['fusername']) && isset($_POST['fpassword']) && isset($_POST['client_hash']) && isset($_POST['sidx']);
// correct login set $_SESSION['login']
if ($is_login_attempt && trim($_POST['fusername']) == config::$username && (phpversion() >= 5.5 && !password_needs_rehash(config::$password, PASSWORD_DEFAULT) ? password_verify(trim($_POST['fpassword']), config::$password) : trim($_POST['fpassword']) == config::$password) && $_POST['client_hash'] === $client_hash && $_POST['sidx'] === $sidx) {
$_SESSION['login'] = $login_hash;
// display login page and exit
} else {
login_page($is_login_attempt, $sidx, $is_logout, $client_hash);
}
// not logged in (images or post API requests), don't show form.
} else {
if (post('action')) {
json_error('login');
} else {
error('You are not logged in.', 401);
}
}
}
}
//
function mkdir_or_error($path)
{
if (!file_exists($path) && !mkdir($path, 0777, true)) {
error('Failed to create ' . $path, 500);
}
}
function real_path($path)
{
$real_path = realpath($path);
return $real_path ? str_replace('\\', '/', $real_path) : false;
}
function root_relative($dir)
{
return ltrim(substr($dir, strlen(config::$root)), '\\/');
}
function root_absolute($dir)
{
return config::$root . ($dir ? '/' . $dir : '');
}
function is_within_path($path, $root)
{
return strpos($path . '/', $root . '/') === 0;
}
function is_within_root($path)
{
return is_within_path($path, config::$root);
}
function is_within_docroot($path)
{
return is_within_path($path, config::$doc_root);
}
function get_folders_cache_path($name)
{
return config::$cache_path . '/folders/' . $name . '.json';
}
function get_json_cache_url($name)
{
$file = get_folders_cache_path($name);
return file_exists($file) ? get_url_path($file) : false;
}
function get_dir_cache_path($dir, $mtime = false)
{
if (!config::$config['cache'] || !$dir) {
return;
}
return get_folders_cache_path(get_dir_cache_hash($dir, $mtime));
}
function get_dir_cache_hash($dir, $mtime = false)
{
return config::$dirs_hash . '.' . substr(md5($dir), 0, 6) . '.' . ($mtime ?: filemtime($dir));
}
function header_memory_time()
{
return (isset($_SERVER['REQUEST_TIME_FLOAT']) ? round(microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'], 3) . 's, ' : '') . round(memory_get_peak_usage() / 1048576, 1) . 'M';
}
// read file
// todo: add files-date header
function read_file($path, $mime = false, $msg = false, $props = false, $cache_headers = false, $clone = false)
{
if (!$path || !file_exists($path)) {
return false;
}
$cloned = $clone && @copy($path, $clone) ? true : false;
//if($mime == 'image/svg') $mime .= '+xml';
header('content-type: ' . ($mime ?: 'image/jpeg'));
header('content-length: ' . filesize($path));
header('content-disposition: filename="' . basename($path) . '"');
if ($msg) {
header('files-msg: ' . $msg . ($cloned ? ' [cloned to ' . basename($clone) . ']' : '') . ' [' . ($props ? $props . ', ' : '') . header_memory_time() . ']');
}
if ($cache_headers) {
set_cache_headers();
}
if (!is_readable($path) || readfile($path) === false) {
error('Failed to read file ' . $path . '.', 400);
}
exit;
}
// get mime
function get_mime($path)
{
if (function_exists('mime_content_type')) {
return mime_content_type($path);
} else {
return function_exists('finfo_file') ? finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path) : false;
}
}
// set cache headers
function set_cache_headers()
{
$seconds = 31536000;
// 1 year;
header('expires: ' . gmdate('D, d M Y H:i:s', time() + $seconds) . ' GMT');
header("cache-control: public, max-age=31536000, s-maxage=31536000, immutable");
header('pragma: cache');
// header("Last-Modified:" . gmdate('D, d M Y H:i:s', time() - $seconds) . ' GMT');
// etag?
}
// get image cache path
function get_image_cache_path($path, $image_resize_dimensions, $filesize, $filemtime)
{
return config::$cache_path . '/images/' . substr(md5($path), 0, 6) . '.' . $filesize . '.' . $filemtime . '.' . $image_resize_dimensions . '.jpg';
}
// is exclude
function is_exclude($path = false, $is_dir = true, $symlinked = false)
{
// early exit
if (!$path || $path === config::$root) {
return;
}
// exclude all paths that start with /_files* (reserved for any files and folders to be ignored and hidden from Files app)
if (strpos($path, '/_files') !== false) {
return true;
}
// exclude files PHP application
if ($path === config::$__file__) {
return true;
}
// symlinks not allowed
if ($symlinked && !config::$config['allow_symlinks']) {
return true;
}
// exclude storage path
if (config::$storage_path && is_within_path($path, config::$storage_path)) {
return true;
}
// dirs_exclude: check root relative dir path
if (config::$config['dirs_exclude']) {
$dirname = $is_dir ? $path : dirname($path);
if ($dirname !== config::$root && preg_match(config::$config['dirs_exclude'], substr($dirname, strlen(config::$root)))) {
return true;
}
}
// files_exclude: check vs basename
if (!$is_dir) {
$basename = basename($path);
if ($basename === config::$local_config_file) {
return true;
}
if (config::$config['files_exclude'] && preg_match(config::$config['files_exclude'], $basename)) {
return true;
}
}
}
// valid root path
function valid_root_path($path, $is_dir = false)
{
// invalid
if ($path === false) {
return;
}
if (!$is_dir && empty($path)) {
return;
}
// path cannot be empty if file
if ($path && substr($path, -1) == '/') {
return;
}
// path should never be root absolute or end with /
// absolute path may differ if path contains symlink
$root_absolute = root_absolute($path);
$real_path = real_path($root_absolute);
// file does not exist
if (!$real_path) {
return;
}
// security checks if path contains symlink
if ($root_absolute !== $real_path) {
if (strpos($is_dir ? $path : dirname($path), ':') !== false) {
return;
}
// dir may not contain ':'
if (strpos($path, '..') !== false) {
return;
}
// path may not contain '..'
if (is_exclude($root_absolute, $is_dir, true)) {
return;
}
}
// nope
if (!is_readable($real_path)) {
return;
}
// not readable
if ($is_dir && !is_dir($real_path)) {
return;
}
// dir check
if (!$is_dir && !is_file($real_path)) {
return;
}
// file check
if (is_exclude($real_path, $is_dir)) {
return;
}
// exclude path
// return root_absolute
return $root_absolute;
}
// image create from
function image_create_from($path, $type)
{
if (!$path || !$type) {
return;
}
if ($type === IMAGETYPE_JPEG) {
return imagecreatefromjpeg($path);
} else {
if ($type === IMAGETYPE_PNG) {
return imagecreatefrompng($path);
} else {
if ($type === IMAGETYPE_GIF) {
return imagecreatefromgif($path);
} else {
if ($type === 18) {
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
return imagecreatefromwebp($path);
}
} else {
if ($type === IMAGETYPE_BMP) {
if (version_compare(PHP_VERSION, '7.2.0') >= 0) {
return imagecreatefrombmp($path);
}
}
}
}
}
}
}
// get file (proxy or resize image)
function get_file($path, $resize = false)
{
// validate
if (!$path) {
error('Invalid file request.', 404);
}
$path = real_path($path);
// in case of symlink path
$mime = get_mime($path);
// may return false if server does not support mime_content_type() or finfo_file()
// video thumbnail (FFmpeg)
if ($resize == 'video') {
// requirements with diagnostics / only check $mime if $mime detected
if ($mime && strtok($mime, '/') !== 'video') {
error('<strong>' . basename($path) . '</strong> (' . $mime . ') is not a video.', 415);
}
foreach (array('video_thumbs', 'load_images', 'image_resize_cache', 'video_ffmpeg_path') as $key) {
if (empty(config::$config[$key])) {
error($key . ' option disabled.', 400);
}
}
if (!function_exists('exec')) {
error('PHP <a href="https://www.php.net/manual/en/function.exec.php" target="_blank">exec()</a> function is disabled on this server.', 400);
}
if (empty(exec('type -P ' . config::$config['video_ffmpeg_path']))) {
error('Can\'t find <a href="http://ffmpeg.org/" target="_blank">FFmpeg</a> in location "' . config::$config['video_ffmpeg_path'] . '".', 400);
}
// get cache path
$cache = get_image_cache_path($path, 480, filesize($path), filemtime($path));
// check for cached video thumbnail / $path, $mime, $msg, $props, $cache_headers
if ($cache) {
read_file($cache, null, 'Video thumb served from cache', null, true);
}
// ffmpeg command
$cmd = escapeshellarg(config::$config['video_ffmpeg_path']) . ' -i ' . escapeshellarg($path) . ' -deinterlace -an -ss 1 -t 1 -vf "thumbnail,scale=480:320:force_original_aspect_ratio=increase,crop=480:320" -r 1 -y -f mjpeg ' . $cache . ' 2>&1';
// try to execute command
exec($cmd, $output, $result_code);
// fail if result_code is anything else than 0
if ($result_code) {
error("Error generating thumbnail for video (\$result_code {$result_code})", 400);
}
// output created video thumbnail
read_file($cache, null, 'Video thumb created', null, true);
// resize image
} else {
if ($resize) {
if ($mime && strtok($mime, '/') !== 'image') {
error('<strong>' . basename($path) . '</strong> (' . $mime . ') is not an image.', 415);
}
foreach (['load_images', 'image_resize_enabled'] as $key) {
if (!config::$config[$key]) {
error('[' . $key . '] disabled.', 400);
}
}
$resize_dimensions = intval($resize);
if (!$resize_dimensions) {
error("Invalid resize parameter <strong>{$resize}</strong>.", 400);
}
$allowed = config::$config['image_resize_dimensions_allowed'] ?: [];
if (!in_array($resize_dimensions, array_merge([config::$config['image_resize_dimensions'], config::$config['image_resize_dimensions_retina']], array_map('intval', is_array($allowed) ? $allowed : explode(',', $allowed))))) {
error("Resize parameter <strong>{$resize_dimensions}</strong> is not allowed.", 400);
}
resize_image($path, $resize_dimensions);
// proxy file
} else {
// disable if !proxy and path is within document root (file should never be proxied)
if (!config::$config['load_files_proxy_php'] && is_within_docroot($path)) {
error('File cannot be proxied.', 400);
}
// read file / $mime or 'application/octet-stream'
read_file($path, $mime ?: 'application/octet-stream', $msg = 'File ' . basename($path) . ' proxied.', false, true);
}
}
}
// sharpen resized image
function sharpen_image($image)
{
$matrix = array(array(-1, -1, -1), array(-1, 20, -1), array(-1, -1, -1));
$divisor = array_sum(array_map('array_sum', $matrix));
$offset = 0;
imageconvolution($image, $matrix, $divisor, $offset);
}
// exif orientation
// https://github.com/gumlet/php-image-resize/blob/master/lib/ImageResize.php
function exif_orientation($orientation, &$image)
{
if (empty($orientation) || !is_numeric($orientation) || $orientation < 3 || $orientation > 8) {
return;
}
$image = imagerotate($image, array(6 => 270, 5 => 270, 3 => 180, 4 => 180, 8 => 90, 7 => 90)[$orientation], null);
if (in_array($orientation, array(5, 4, 7)) && function_exists('imageflip')) {
imageflip($image, IMG_FLIP_HORIZONTAL);
}
return true;
}
// resize image
function resize_image($path, $resize_dimensions, $clone = false)
{
// file size
$file_size = filesize($path);
// header props
$header_props = 'w:' . $resize_dimensions . ', q:' . config::$config['image_resize_quality'] . ', ' . config::$config['image_resize_function'] . ', cache:' . (config::$config['image_resize_cache'] ? '1' : '0');
// cache
$cache = config::$config['image_resize_cache'] ? get_image_cache_path($path, $resize_dimensions, $file_size, filemtime($path)) : NULL;
if ($cache) {
read_file($cache, null, 'Resized image served from cache', $header_props, true, $clone);
}
// imagesize
$info = getimagesize($path);
if (empty($info) || !is_array($info)) {
error('Invalid image / failed getimagesize().', 500);
}
$resize_ratio = max($info[0], $info[1]) / $resize_dimensions;
// image_resize_max_pixels early exit
if (config::$config['image_resize_max_pixels'] && $info[0] * $info[1] > config::$config['image_resize_max_pixels']) {
error('Image resolution <strong>' . $info[0] . ' x ' . $info[1] . '</strong> (' . $info[0] * $info[1] . ' px) exceeds <strong>image_resize_max_pixels</strong> (' . config::$config['image_resize_max_pixels'] . ' px).', 400);
}
// header props
$header_props .= ', ' . $info['mime'] . ', ' . $info[0] . 'x' . $info[1] . ', ratio:' . round($resize_ratio, 2);
// check if image type is in image_resize_types / jpeg, png, gif, webp, bmp
$is_resize_type = in_array(image_type_to_extension($info[2], false), array_map(function ($key) {
$type = trim(strtolower($key));
return $type === 'jpg' ? 'jpeg' : $type;
}, explode(',', config::$config['image_resize_types'])));
// serve original if !$is_resize_type || resize ratio < image_resize_min_ratio
if ((!$is_resize_type || $resize_ratio < max(config::$config['image_resize_min_ratio'], 1)) && !read_file($path, $info['mime'], 'Original image served', $header_props, true, $clone)) {
error('File does not exist.', 404);
}
// Calculate new image dimensions.
$resize_width = round($info[0] / $resize_ratio);
$resize_height = round($info[1] / $resize_ratio);
// memory
$memory_limit = config::$config['image_resize_memory_limit'] && function_exists('ini_get') ? (int) @ini_get('memory_limit') : false;
if ($memory_limit && $memory_limit > -1) {
// $memory_required = ceil(($info[0] * $info[1] * 4 + $resize_width * $resize_height * 4) / 1048576);
$memory_required = round(($info[0] * $info[1] * (isset($info['bits']) ? $info['bits'] / 8 : 1) * (isset($info['channels']) ? $info['channels'] : 3) * 1.33 + $resize_width * $resize_height * 4) / 1048576, 1);
$new_memory_limit = function_exists('ini_set') ? max($memory_limit, config::$config['image_resize_memory_limit']) : $memory_limit;
if ($memory_required > $new_memory_limit) {
error('Resizing this image requires at least <strong>' . $memory_required . 'M</strong>. Your current PHP memory_limit is <strong>' . $new_memory_limit . 'M</strong>.', 400);
}
if ($memory_limit < $new_memory_limit && @ini_set('memory_limit', $new_memory_limit . 'M')) {
$header_props .= ', ' . $memory_limit . 'M => ' . $new_memory_limit . 'M (min ' . $memory_required . 'M)';
}
}
// new dimensions headers
$header_props .= ', ' . $resize_width . 'x' . $resize_height;
// create new $image
$image = image_create_from($path, $info[2]);
if (!$image) {
error('Failed to create image resource.', 500);
}
// Create final image with new dimensions.
$new_image = imagecreatetruecolor($resize_width, $resize_height);
if (!call_user_func(config::$config['image_resize_function'], $new_image, $image, 0, 0, 0, 0, $resize_width, $resize_height, $info[0], $info[1])) {
error('Failed to resize image.', 500);
}
// destroy original $image resource
imagedestroy($image);
// exif orientation
$exif = function_exists('exif_read_data') ? @exif_read_data($path) : false;
if (!empty($exif) && is_array($exif) && isset($exif['Orientation']) && exif_orientation($exif['Orientation'], $new_image)) {
$header_props .= ', orientated from EXIF:' . $exif['Orientation'];
}
// sharpen resized image
if (config::$config['image_resize_sharpen']) {
sharpen_image($new_image);
}
// save to cache
if ($cache) {
if (!imagejpeg($new_image, $cache, config::$config['image_resize_quality'])) {
error('<strong>imagejpeg()</strong> failed to create and cache resized image.', 500);
}
// clone cache (used for folder previews)
if ($clone) {
@copy($cache, $clone);
}
// cache disabled / direct output
} else {
set_cache_headers();
header('content-type: image/jpeg');
header('files-msg: Resized image served [' . $header_props . ', ' . header_memory_time() . ']');
if (!imagejpeg($new_image, null, config::$config['image_resize_quality'])) {
error('<strong>imagejpeg()</strong> failed to create and output resized image.', 500);
}
}
// destroy image
imagedestroy($new_image);
// cache readfile
if ($cache && !read_file($cache, null, 'Resized image cached and served', $header_props, true, $clone)) {
error('Cache file does not exist.', 404);
}
//
exit;
}
function get_url_path($dir)
{
if (!is_within_docroot($dir)) {
return false;
}
// if in __dir__ path, __dir__ relative
if (is_within_path($dir, config::$__dir__)) {
return $dir === config::$__dir__ ? '.' : substr($dir, strlen(config::$__dir__) + 1);
}
// doc root, doc root relative
return $dir === config::$doc_root ? '/' : substr($dir, strlen(config::$doc_root));
}
// get dir
function get_dir($path, $files = false, $json_url = false)
{
// realpath
$realpath = $path ? real_path($path) : false;
if (!$realpath) {
return;
}
// no real path for any reason
$symlinked = $realpath !== $path;
// path is symlinked at some point
// exclude
if (is_exclude($path, true, $symlinked)) {
return;
}
// exclude
if ($symlinked && is_exclude($realpath, true, $symlinked)) {
return;
}
// exclude check again symlink realpath
// vars
$filemtime = filemtime($realpath);
$url_path = get_url_path($realpath) ?: ($symlinked ? get_url_path($path) : false);
$is_readable = is_readable($realpath);
// array
$arr = array('basename' => (basename($realpath) ?: basename($path)) ?: '', 'fileperms' => substr(sprintf('%o', fileperms($realpath)), -4), 'filetype' => 'dir', 'is_readable' => $is_readable, 'is_writeable' => is_writeable($realpath), 'is_link' => $symlinked ? is_link($path) : false, 'is_dir' => true, 'mime' => 'directory', 'mtime' => $filemtime, 'path' => root_relative($path));
// url path
if ($url_path) {
$arr['url_path'] = $url_path;
}
// get_files() || config::menu_load_all
if ($files && $is_readable) {
// files array
$arr['files'] = get_files_data($path, $url_path, $arr['dirsize'], $arr['files_count'], $arr['images_count'], $arr['preview']);
// download_dir cache direct access to zip / better caching and no need to access PHP / only works when download_dir_cache === 'dir'
/*if($url_path && config::$config['download_dir'] === 'zip' && config::$config['download_dir_cache'] === 'dir') {
$zip = $realpath . '/_files.zip';
if(file_exists($zip) && filemtime($zip) >= $filemtime) $arr['zip'] = get_url_path($zip);
}*/
}
// json cache path
if ($json_url && config::$storage_is_within_doc_root && !config::$has_login && config::$config['cache']) {
$json_cache = get_json_cache_url(get_dir_cache_hash($realpath, $filemtime));
if ($json_cache) {
$arr['json_cache'] = $json_cache;
}
}
//
return $arr;
}
// get menu sort
function get_menu_sort($dirs)
{
if (strpos(config::$config['menu_sort'], 'date') === 0) {
usort($dirs, function ($a, $b) {
return filemtime($a) - filemtime($b);
});
} else {
natcasesort($dirs);
}
return substr(config::$config['menu_sort'], -4) === 'desc' ? array_reverse($dirs) : $dirs;
}
// recursive directory scan
function get_dirs($path = false, &$arr = array(), $depth = 0)
{
// get this dir (ignore root, unless load all ... root already loaded into page)
if ($depth || config::$config['menu_load_all']) {
$data = get_dir($path, config::$config['menu_load_all'], !config::$config['menu_load_all']);
if (!$data) {
return $arr;
}
//
$arr[] = $data;
// max depth
if (config::$config['menu_max_depth'] && $depth >= config::$config['menu_max_depth']) {
return $arr;
}
// don't recursive if symlink
if ($data['is_link'] && !config::$config['menu_recursive_symlinks']) {
return $arr;
}
}
// get dirs from files array if $data['files'] or glob subdirs
$subdirs = isset($data['files']) ? array_filter(array_map(function ($file) {
return $file['filetype'] === 'dir' ? root_absolute($file['path']) : false;
}, $data['files'])) : glob($path . '/*', "GLOB_OO__V]R");
// sort and loop subdirs
if (!empty($subdirs)) {
foreach (get_menu_sort($subdirs) as $subdir) {
get_dirs($subdir, $arr, $depth + 1);
}
}
// return
return $arr;
}
// encode to UTF-8 when required
function safe_iptc_tag($val)
{
$val = @substr($val, 0, 1000);
return @mb_detect_encoding($val, 'UTF-8', true) ? $val : @utf8_encode($val);
}
// get IPTC
function get_iptc($image_info)
{
if (!$image_info || !isset($image_info['APP13']) || !function_exists('iptcparse')) {
return;
}
$app13 = @iptcparse($image_info['APP13']);
if (empty($app13)) {
return;
}
$iptc = array();
// loop title, headline, description, creator, credit, copyright, keywords, city, sub-location and province-state
foreach (['title' => '005', 'headline' => '105', 'description' => '120', 'creator' => '080', 'credit' => '110', 'copyright' => '116', 'keywords' => '025', 'city' => '090', 'sub-location' => '092', 'province-state' => '095'] as $name => $code) {
if (isset($app13['2#' . $code][0]) && !empty($app13['2#' . $code][0])) {
$iptc[$name] = $name === 'keywords' ? $app13['2#' . $code] : safe_iptc_tag($app13['2#' . $code][0]);
}
}
// return IPTC
return $iptc;
}
// get exif
function get_exif($path)
{
if (!function_exists('exif_read_data')) {
return;
}
$exif_data = @exif_read_data($path, 'ANY_TAG', 0);
// @exif_read_data($path);
if (empty($exif_data) || !is_array($exif_data)) {
return;
}
$exif = array();
foreach (array('DateTime', 'DateTimeOriginal', 'ExposureTime', 'FNumber', 'FocalLength', 'Make', 'Model', 'Orientation', 'ISOSpeedRatings', 'Software') as $name) {
if (isset($exif_data[$name])) {
$exif[$name] = trim($exif_data[$name]);
}
}
if (isset($exif['DateTime'])) {
$exif['DateTime'] = @strtotime($exif['DateTime']);
}
if (isset($exif['DateTimeOriginal'])) {
$exif['DateTimeOriginal'] = @strtotime($exif['DateTimeOriginal']);
}
/*LensInfo 24-70mm f/?
Lens EF24-70mm f/2.8L USM
LensID 230*/
// ApertureFNumber (f_stop)
if (isset($exif_data['COMPUTED']['ApertureFNumber'])) {
$exif['ApertureFNumber'] = $exif_data['COMPUTED']['ApertureFNumber'];
}
// flash
if (isset($exif_data['Flash'])) {
$exif['Flash'] = ($exif_data['Flash'] & 1) != 0;
}
// GPS
$gps = get_image_location($exif_data);
if (!empty($gps)) {
$exif['gps'] = $gps;
}
// return
return $exif;
}
// exif GPS / get_image_location
function get_image_location($exif)
{
$arr = array();
foreach (array('GPSLatitude', 'GPSLongitude') as $key) {
if (!isset($exif[$key]) || !isset($exif[$key . 'Ref'])) {
return false;
}
$coordinate = $exif[$key];
if (is_string($coordinate)) {
$coordinate = array_map('trim', explode(',', $coordinate));
}
for ($i = 0; $i < 3; $i++) {
$part = explode('/', $coordinate[$i]);
if (count($part) == 1) {
$coordinate[$i] = $part[0];
} else {
if (count($part) == 2) {
if ($part[1] == 0) {
return false;
}
// can't be 0 / invalid GPS
$coordinate[$i] = floatval($part[0]) / floatval($part[1]);
} else {
$coordinate[$i] = 0;
}
}
}
list($degrees, $minutes, $seconds) = $coordinate;
$sign = $exif[$key . 'Ref'] == 'W' || $exif[$key . 'Ref'] == 'S' ? -1 : 1;
$arr[] = $sign * ($degrees + $minutes / 60 + $seconds / 3600);
}
return $arr;
}
/*function get_image_location($exif){
$arr = array('GPSLatitudeRef', 'GPSLatitude', 'GPSLongitudeRef', 'GPSLongitude');
foreach ($arr as $val) {
if(!isset($exif[$val])) return false;
}
$GPSLatitudeRef = $exif[$arr[0]];
$GPSLatitude = $exif[$arr[1]];
$GPSLongitudeRef= $exif[$arr[2]];
$GPSLongitude = $exif[$arr[3]];
$lat_degrees = count($GPSLatitude) > 0 ? gps2Num($GPSLatitude[0]) : 0;
$lat_minutes = count($GPSLatitude) > 1 ? gps2Num($GPSLatitude[1]) : 0;
$lat_seconds = count($GPSLatitude) > 2 ? gps2Num($GPSLatitude[2]) : 0;
$lon_degrees = count($GPSLongitude) > 0 ? gps2Num($GPSLongitude[0]) : 0;
$lon_minutes = count($GPSLongitude) > 1 ? gps2Num($GPSLongitude[1]) : 0;
$lon_seconds = count($GPSLongitude) > 2 ? gps2Num($GPSLongitude[2]) : 0;
$lat_direction = ($GPSLatitudeRef == 'W' or $GPSLatitudeRef == 'S') ? -1 : 1;
$lon_direction = ($GPSLongitudeRef == 'W' or $GPSLongitudeRef == 'S') ? -1 : 1;
$latitude = $lat_direction * ($lat_degrees + ($lat_minutes / 60) + ($lat_seconds / (60*60)));
$longitude = $lon_direction * ($lon_degrees + ($lon_minutes / 60) + ($lon_seconds / (60*60)));
return array($latitude, $longitude);
}
function gps2Num($coordPart){
$parts = explode('/', $coordPart);
if(count($parts) <= 0) return 0;
if(count($parts) == 1) return $parts[0];
if($parts[1] == 0) return 0;
return floatval($parts[0]) / floatval($parts[1]);
}*/
//
function get_files_data($dir, $url_path = false, &$dirsize = 0, &$files_count = 0, &$images_count = 0, &$preview = false)
{
// scandir
$filenames = scandir($dir, SCANDIR_SORT_NONE);
if (empty($filenames)) {
return array();
}
$items = array();
// look for folder_preview_default (might be excluded in loop)
if (config::$config['folder_preview_default'] && in_array(config::$config['folder_preview_default'], $filenames)) {
$preview = config::$config['folder_preview_default'];
}
// loop filenames
foreach ($filenames as $filename) {
//
if ($filename === '.' || $filename === '..') {
continue;
}
$path = $dir . '/' . $filename;
// paths
$realpath = real_path($path);
// differs from $path only if is symlinked
if (!$realpath) {
continue;
}
// no real path for any reason, for example symlink dead
$symlinked = $realpath !== $path;
// path is symlinked at some point
// filetype
$filetype = filetype($realpath);
$is_dir = $filetype === 'dir' ? true : false;
// exclude
if (is_exclude($path, $is_dir, $symlinked)) {
continue;
}
// exclude
if ($symlinked && is_exclude($realpath, $is_dir, $symlinked)) {
continue;
}
// exclude check again symlink realpath
// vars
if (!$is_dir) {
$files_count++;
}
// files count
$is_link = $symlinked ? is_link($path) : false;
// symlink
$basename = $is_link ? basename($realpath) ?: $filename : $filename;
$filemtime = filemtime($realpath);
$is_readable = is_readable($realpath);
$filesize = $is_dir ? false : filesize($realpath);
if ($filesize) {
$dirsize += $filesize;
}
// url_path / symlink
$item_url_path = $symlinked ? get_url_path($realpath) : false;
// url_path from realpath if symlinked
if (!$item_url_path && $url_path) {
$item_url_path = $url_path . ($url_path === '/' ? '' : '/') . ($is_link ? basename($path) : $basename);
}
// root path // path relative to config::$root
if (!$symlinked || is_within_root($realpath)) {
$root_path = root_relative($realpath);
// path is symlinked and !is_within_root(), get path-relative
} else {
// root path to symlink
$root_path = root_relative($path);
// check for symlink loop
if ($is_link && $is_dir && $path && $root_path) {
$basename_path = basename($root_path);
if ($basename_path && preg_match('/(\\/|^)' . $basename_path . '\\//', $root_path)) {
$loop_path = '';
$segments = explode('/', $root_path);
array_pop($segments);
foreach ($segments as $segment) {
$loop_path .= ($loop_path ? '/' : '') . $segment;
if ($segment !== $basename_path) {
continue;
}
$loop_abs_path = root_absolute($loop_path);
if (!is_link($loop_abs_path) || $realpath !== real_path($loop_abs_path)) {
continue;
}
$root_path = $loop_path;
$item_url_path = get_url_path($loop_abs_path) ?: $item_url_path;
// new symlink is within doc_root
break;
}
}
}
}
// add properties
$item = array('basename' => $basename, 'fileperms' => substr(sprintf('%o', fileperms($realpath)), -4), 'filetype' => $filetype, 'filesize' => $filesize, 'is_readable' => $is_readable, 'is_writeable' => is_writeable($realpath), 'is_link' => $is_link, 'is_dir' => $is_dir, 'mtime' => $filemtime, 'path' => $root_path);
// optional props
//$ext = !$is_dir ? pathinfo($realpath, PATHINFO_EXTENSION) : false;
$ext = !$is_dir ? substr(strrchr($realpath, '.'), 1) : false;
if ($ext) {
$ext = strtolower($ext);
$item['ext'] = $ext;
}
$mime = $is_dir ? 'directory' : ($is_readable && (!$ext || $ext === 'ts' || config::$config['get_mime_type']) ? get_mime($realpath) : false);
if ($mime) {
$item['mime'] = $mime;
}
if ($item_url_path) {
$item['url_path'] = $item_url_path;
}
// image / check from mime, fallback to extension
$is_image = $is_dir ? false : ($mime ? strtok($mime, '/') === 'image' && !strpos($mime, 'svg') : in_array($ext, array('gif', 'jpg', 'jpeg', 'jpc', 'jp2', 'jpx', 'jb2', 'png', 'swf', 'psd', 'bmp', 'tiff', 'tif', 'wbmp', 'xbm', 'ico', 'webp')));
if ($is_image) {
// imagesize
$imagesize = $is_readable ? @getimagesize($realpath, $info) : false;
// image count and icon
$images_count++;
$item['icon'] = 'image';
// is imagesize
if (!empty($imagesize) && is_array($imagesize)) {
// set folder_preview
if (!$preview && in_array($ext, array('gif', 'jpg', 'jpeg', 'png'))) {
$preview = $basename;
}
// start image array
$image = array();
foreach (array(0 => 'width', 1 => 'height', 2 => 'type', 'bits' => 'bits', 'channels' => 'channels', 'mime' => 'mime') as $key => $name) {
if (isset($imagesize[$key])) {
$image[$name] = $imagesize[$key];
}
}
// mime from image
if (!$mime && isset($image['mime'])) {
$item['mime'] = $image['mime'];
}
// IPTC
$iptc = $info ? get_iptc($info) : false;
if (!empty($iptc)) {
$image['iptc'] = $iptc;
}
// EXIF
$exif = get_exif($realpath);
if (!empty($exif)) {
$image['exif'] = $exif;
if (isset($exif['DateTimeOriginal'])) {
$item['DateTimeOriginal'] = $exif['DateTimeOriginal'];
}
// invert width/height if exif orientation
if (isset($exif['Orientation']) && $exif['Orientation'] > 4 && $exif['Orientation'] < 9) {
$image['width'] = $imagesize[1];
$image['height'] = $imagesize[0];
}
}
// image resize cache direct
if (config::$image_resize_cache_direct) {
$resize1 = get_image_cache_path($realpath, config::$config['image_resize_dimensions'], $filesize, $filemtime);
if (file_exists($resize1)) {
$image['resize' . config::$config['image_resize_dimensions']] = get_url_path($resize1);
}
$retina = config::$image_resize_dimensions_retina;
if ($retina) {
$resize2 = get_image_cache_path($realpath, $retina, $filesize, $filemtime);
if (file_exists($resize2)) {
$image['resize' . $retina] = get_url_path($resize2);
}
}
}
// add image to item
$item['image'] = $image;
// get real mime if getimagesize fails. Could be non-image disguised as image extension
} else {
if ($is_readable && !$mime) {
$mime = get_mime($realpath);
if ($mime) {
$item['mime'] = $mime;
if (strtok($mime, '/') !== 'image') {
// unset images_count and icon because is not image after all
$images_count--;
unset($item['icon']);
}
}
}
}
}
// add to items with basename as key
$items[$basename] = $item;
}
// Sort dirs on top and natural case sort / need to do in JS anyway
uasort($items, function ($a, $b) {
if (!config::$config['sort_dirs_first'] || $a['is_dir'] === $b['is_dir']) {
return strnatcasecmp($a['basename'], $b['basename']);
}
return $b['is_dir'] ? 1 : -1;
});
//
return $items;
}
// get files
function get_files($dir)
{
// invalid $dir
if (!$dir) {
json_error('Invalid directory');
}
// cache
$cache = get_dir_cache_path(real_path($dir));
// read cache or get dir and cache
if (!read_file($cache, 'application/json', 'files json served from cache')) {
json_cache(get_dir($dir, true), 'files json created' . ($cache ? ' and cached' : ''), $cache);
}
}
/* start here */
function post($param)
{
return isset($_POST[$param]) && !empty($_POST[$param]) ? $_POST[$param] : false;
}
function get($param)
{
return isset($_GET[$param]) && !empty($_GET[$param]) ? $_GET[$param] : false;
}
function json_cache($arr = array(), $msg = false, $cache = true)
{
$json = empty($arr) ? '{}' : json_encode($arr, "JSON_UOWWKA\\_O_W^]W_O__ERROR");
if (empty($json)) {
json_error(json_last_error() ? json_last_error_msg() : 'json_encode() error');
}
if ($cache) {
@file_put_contents($cache, $json);
}
if ($msg) {
header('files-msg: ' . $msg . ' [' . header_memory_time() . ']');
}
header('content-type: application/json');
echo $json;
}
function json_error($error = 'Error')
{
json_exit(array('error' => $error));
}
function json_success($success = 'Success')
{
json_exit(array('success' => $success));
}
function json_toggle($success, $error)
{
json_exit(array_filter(array('success' => $success, 'error' => empty($success) ? $error : 0)));
}
function json_exit($arr = array())
{
header('content-type: application/json');
exit(json_encode($arr));
}
function error($msg, $code = false)
{
// 400 Bad Request, 403 Forbidden, 401 Unauthorized, 404 Not Found, 500 Internal Server Error
if ($code) {
http_response_code($code);
}
header('content-type: text/html');
header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0, s-maxage=0');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
exit('<h2>Error</h2>' . $msg);
}
// get valid menu cache
function get_valid_menu_cache($cache)
{
if (!$cache || !file_exists($cache)) {
return;
}
$json = @file_get_contents($cache);
if (empty($json)) {
return;
}
if (!config::$config['menu_cache_validate']) {
return $json;
}
$arr = @json_decode($json, true);
if (empty($arr)) {
return;
}
foreach ($arr as $key => $val) {
$path = $val['path'];
if (strpos($path, '/') !== false && $val['mtime'] !== @filemtime(root_absolute($path))) {
return;
}
// skip shallow 1st level dirs, and compare filemtime
}
return $json;
}
// get root dirs
function get_root_dirs()
{
$root_dirs = glob(config::$root . '/*', "GLOB_OO__V]R");
if (empty($root_dirs)) {
return array();
}
return array_filter($root_dirs, function ($dir) {
return !is_exclude($dir, true, is_link($dir));
});
}
// get menu cache hash
function get_menu_cache_hash($root_dirs)
{
$mtime_count = filemtime(config::$root);
foreach ($root_dirs as $root_dir) {
$mtime_count += filemtime($root_dir);
}
return substr(md5(config::$doc_root . config::$__dir__ . config::$root), 0, 6) . '.' . substr(md5(config::$version . config::$config['cache_key'] . config::$config['menu_max_depth'] . config::$config['menu_load_all'] . (config::$config['menu_load_all'] ? config::$config['files_exclude'] . config::$image_resize_cache_direct : '') . config::$has_login . config::$config['dirs_exclude'] . config::$config['menu_sort']), 0, 6) . '.' . $mtime_count;
}
// get dirs
function dirs()
{
// get menu_cache_hash
if (config::$config['cache']) {
$menu_cache_hash = post('menu_cache_hash');
// get menu cache hash
$menu_cache_arr = $menu_cache_hash ? explode('.', $menu_cache_hash) : false;
if (!$menu_cache_arr || count($menu_cache_arr) !== 3 || strlen($menu_cache_arr[0]) !== 6 || strlen($menu_cache_arr[1]) !== 6 || !is_numeric($menu_cache_arr[2])) {
json_error('Invalid menu cache hash');
}
// early exit
}
$cache = config::$config['cache'] ? config::$cache_path . '/menu/' . $menu_cache_hash . '.json' : false;
// get cache path
$json = $cache ? get_valid_menu_cache($cache) : false;
// get valid json menu cache
// $json is valid from menu cache file
if ($json) {
header('content-type: application/json');
header('files-msg: valid menu cache hash [' . $menu_cache_hash . ']' . (!config::$config['menu_cache_validate'] ? '[deep validation disabled]' : '') . '[' . header_memory_time() . ']');
echo post('localstorage') ? '{"localstorage":"1"}' : $json;
// reload dirs
} else {
json_cache(get_dirs(config::$root), 'dirs reloaded' . ($cache ? ' and cached.' : ' [cache disabled]'), $cache);
}
}
// include file html, php, css, js
function get_include($file)
{
if (!config::$storage_path) {
return;
}
$path = config::$storage_path . '/' . $file;
if (!file_exists($path)) {
return;
}
$ext = pathinfo($path, PATHINFO_EXTENSION);
if (in_array($ext, ['html', 'php'])) {
return include $path;
}
if (!config::$storage_is_within_doc_root) {
return;
}
$src = get_url_path($path) . '?' . filemtime($path);
if ($ext === 'js') {
echo '<script src="' . $src . '"></script>';
}
if ($ext === 'css') {
echo '<link href="' . $src . '" rel="stylesheet">';
}
}
// POST
if (post('action')) {
// post action
$action = post('action');
//
new config();
// filemanager actions [beta]
if ($action === 'fm') {
// validate task
$task = post('task');
if (empty($task) || !isset(config::$config['allow_' . $task]) || !config::$config['allow_' . $task]) {
json_error('invalid task');
}
// demo_mode
if (config::$config['demo_mode']) {
json_error('Action not allowed in demo mode');
}
// license required for file manager action
if (!config::$config['license_key']) {
json_error('License required!');
}
// valid path / path must be inside assigned root
$is_dir = post('is_dir');
$path = valid_root_path(post('path'), $is_dir);
if (empty($path)) {
json_error('invalid path ' . post('path'));
}
$path = real_path($path);
// in case of symlink path
// name_is_allowed / trim name, fail if empty or dodgy characters, mkfile, mkdir, rename, duplicate
function name_is_allowed($name)
{
$name = $name ? trim($name) : false;
// trim
// block empty / <>:"'/\|?*# chars / .. / endswith .
if (empty($name) || preg_match('/[<>:"\'\\/\\\\|?*#]|\\.\\.|\\.$/', $name)) {
json_error('invalid name ' . $name);
}
return $name;
}
// filemanager json_toggle
function fm_json_toggle($success, $error)
{
fm_json_exit($success, array_filter(array('success' => $success, 'error' => empty($success) ? $error : 0)));
}
// filemanager json_exit / includes feature to invalidate X3 cache if $x3_path
function fm_json_exit($success, $arr)
{
if ($success && config::$x3_path) {
touch(config::$x3_path . '/app/x3.inc.php');
}
json_exit($arr);
}
// UPLOAD
if ($task === 'upload') {
// upload path must be dir
if (!$is_dir) {
json_error('invalid dir ' . post('path'));
}
// upload path must be writeable
if (!is_writable($path)) {
json_error('upload dir ' . post('path') . ' is not writeable');
}
// get $_FILES['file']
$file = isset($_FILES) && isset($_FILES['file']) && is_array($_FILES['file']) ? $_FILES['file'] : false;
// invalid $_FILES['file']
if (empty($file) || !isset($file['error']) || is_array($file['error'])) {
json_error('invalid $_FILES[]');
}
// PHP meaningful file upload errors / https://www.php.net/manual/en/features.file-upload.errors.php
if ($file['error'] !== 0) {
$upload_errors = array(1 => 'Uploaded file exceeds upload_max_filesize directive in php.ini', 2 => 'Uploaded file exceeds MAX_FILE_SIZE directive specified in the HTML form', 3 => 'The uploaded file was only partially uploaded', 4 => 'No file was uploaded', 6 => 'Missing a temporary folder', 7 => 'Failed to write file to disk.', 8 => 'A PHP extension stopped the file upload.');
json_error(isset($upload_errors[$file['error']]) ? $upload_errors[$file['error']] : 'unknown error');
}
// invalid $file['size']
if (!isset($file['size']) || empty($file['size'])) {
json_error('invalid file size');
}
// $file['size'] must not exceed $config['upload_max_filesize']
if (config::$config['upload_max_filesize'] && $file['size'] > config::$config['upload_max_filesize']) {
json_error('File size [' . $file['size'] . '] exceeds upload_max_filesize option [' . config::$config['upload_max_filesize'] . ']');
}
// filename
$filename = $file['name'];
// security: slashes are never ever allowed in filenames / always basenamed() but just in case
if (strpos($filename, '/') !== false || strpos($filename, '\\') !== false) {
json_error('Illegal \\slash/ in filename ' . $filename);
}
// allow only valid file types from config::$config['upload_allowed_file_types'] / 'image/*, .pdf, .mp4'
$allowed_file_types = !empty(config::$config['upload_allowed_file_types']) ? array_filter(array_map('trim', explode(',', config::$config['upload_allowed_file_types']))) : false;
if (!empty($allowed_file_types)) {
$mime = get_mime($file['tmp_name']) ?: $file['type'];
// mime from PHP or upload[type]
$ext = strrchr(strtolower($filename), '.');
$is_valid = false;
// check if extension match || wildcard match mime type image/*
foreach ($allowed_file_types as $allowed_file_type) {
if ($ext === '.' . ltrim($allowed_file_type, '.') || fnmatch($allowed_file_type, $mime)) {
$is_valid = true;
break;
}
}
if (!$is_valid) {
json_error('invalid file type ' . $filename);
}
// extra security: check if image is image
if (function_exists('exif_imagetype') && in_array($ext, ['.gif', '.jpeg', '.jpg', '.png', '.swf', '.psd', '.bmp', '.tif', '.tiff', 'webp']) && !@exif_imagetype($file['tmp_name'])) {
json_error('invalid image type ' . $filename);
}
}
// file naming if !overwrite and file exists
if (config::$config['upload_exists'] !== 'overwrite' && file_exists("{$path}/{$filename}")) {
// fail if !increment / 'upload_exists' => 'fail' || false || '' empty
if (config::$config['upload_exists'] !== 'increment') {
json_error("{$filename} already exists");
}
// increment filename / 'upload_exists' => 'increment'
$name = pathinfo($filename, PATHINFO_FILENAME);
$ext = pathinfo($filename, PATHINFO_EXTENSION);
$inc = 1;
while (file_exists($path . '/' . $name . '-' . $inc . '.' . $ext)) {
$inc++;
}
$filename = $name . '-' . $inc . '.' . $ext;
}
// all is well! attempt to move_uploaded_file()
if (@move_uploaded_file($file['tmp_name'], "{$path}/{$filename}")) {
fm_json_exit(true, array(
'success' => true,
'filename' => $filename,
// return filename in case it was incremented or renamed
'url' => get_url_path("{$path}/{$filename}"),
));
}
// error if failed to move uploaded file
json_error('failed to move_uploaded_file()');
// DELETE
} else {
if ($task === 'delete') {
// dir recursive
if ($is_dir) {
// success/fail count
$success = 0;
$fail = 0;
// recursive rmdir
function rrmdir($dir, &$success, &$fail)
{
//global $success, $fail;
if (!is_readable($dir)) {
return $fail++;
}
$files = array_diff(scandir($dir), array('.', '..'));
if (!empty($files)) {
foreach ($files as $file) {
is_dir("{$dir}/{$file}") ? rrmdir("{$dir}/{$file}", $success, $fail) : (@unlink("{$dir}/{$file}") ? $success++ : $fail++);
}
}
@rmdir($dir) ? $success++ : $fail++;
}
// recursive rmdir start
rrmdir($path, $success, $fail);
// response with partial success/fail count or error if there is !$success
fm_json_exit($success, array_filter(array('success' => $success, 'fail' => $fail, 'error' => empty($success) ? 'Failed to delete dir' : 0)));
// single file
} else {
fm_json_toggle(@unlink($path), 'PHP unlink() failed');
}
// new_folder || new_file
} else {
if ($task === 'new_folder' || $task === 'new_file') {
if (!$is_dir) {
json_error('invalid dir ' . post('path'));
}
// parent path must be dir
if (!is_writable($path)) {
json_error(post('path') . ' is not writeable.');
}
// dir must be writeable
$name = name_is_allowed(post('name'));
// trim and check valid
$file_path = $path . '/' . $name;
if (file_exists($file_path)) {
json_error($name . ' already exists');
}
fm_json_toggle($task === 'new_folder' ? @mkdir($file_path) : @touch($file_path), $task . ' failed');
// rename $path (file or dir)
} else {
if ($task === 'rename') {
if (!is_writable($path)) {
json_error(post('path') . ' is not writeable.');
}
// path must be writeable
$name = name_is_allowed(post('name'));
// trim and check valid
$new_path = dirname($path) . '/' . $name;
if (file_exists($new_path)) {
json_error("{$name} already exists.");
}
// new name exists
// security: prevent renaming 'file.html' to 'file.php' / file must already be *.php when renaming
if (!$is_dir && stripos($path, '.php') === false && stripos($name, '.php') !== false) {
json_error('cannot rename files to .php');
}
fm_json_toggle(@rename($path, $new_path), 'PHP rename() failed');
// duplicate file
} else {
if ($task === 'duplicate') {
if ($is_dir) {
json_error('Can\'t duplicate dir');
}
$parent_dir = dirname($path);
if (!is_writable($parent_dir)) {
json_error(basename($parent_dir) . ' is not writeable.');
}
// dir must be writeable
$name = name_is_allowed(post('name'));
// trim and check valid
$copy_path = $parent_dir . '/' . $name;
if (file_exists($copy_path)) {
json_error($name . ' already exists.');
}
fm_json_toggle(@copy($path, $copy_path), 'PHP copy() failed');
// text / code edit
} else {
if ($task === 'text_edit') {
if ($is_dir) {
json_error('Can\'t write text to directory');
}
if (!is_writeable($path) || !is_file($path)) {
json_error('File is not writeable');
}
$success = isset($_POST['text']) && @file_put_contents($path, $_POST['text']) !== false ? 1 : 0;
// text could be '' (empty)
if ($success) {
@touch(dirname($path));
}
// invalidate any cache by updating parent dir mtime
fm_json_toggle($success, 'PHP file_put_contents() failed');
}
}
}
}
}
}
// dirs
} else {
if ($action === 'dirs') {
dirs(post('localstorage'));
// files
} else {
if ($action === 'files') {
if (!isset($_POST['dir'])) {
json_error('Missing dir parameter');
}
get_files(valid_root_path($_POST['dir'], true));
// file read
} else {
if ($action === 'file') {
// valid path
$file = valid_root_path(post('file'));
if (!$file) {
error('Invalid file path');
}
// read text file
header('content-type:text/plain;charset=utf-8');
if (@readfile(real_path($file)) === false) {
error('failed to read file ' . post('file'), 500);
}
// check login
} else {
if ($action === 'check_login') {
json_success(true);
// check updates
} else {
if ($action === 'check_updates') {
$json = @json_decode(@file_get_contents('https://data.jsdelivr.com/v1/package/npm/files.photo.gallery'), true);
$latest = !empty($json) && isset($json['versions'][0]) && version_compare($json['versions'][0], config::$version) > 0 ? $json['versions'][0] : false;
json_exit(array('success' => $latest, 'writeable' => $latest && is_writable("/var/www/html/manager3.php.cf6eb2c9bf1fb4ebc58b7883af08523b.bin")));
// do update
} else {
if ($action === 'do_update') {
$version = post('version');
if (!$version || version_compare($version, config::$version) <= 0 || !is_writable("/var/www/html/manager3.php.cf6eb2c9bf1fb4ebc58b7883af08523b.bin")) {
json_error();
}
// requirements
$get = @file_get_contents('https://cdn.jsdelivr.net/npm/files.photo.gallery@' . $version . '/index.php');
if (empty($get) || strpos($get, '<?php') !== 0) {
json_error();
}
// basic validation
json_success(array('success' => @file_put_contents("/var/www/html/manager3.php.cf6eb2c9bf1fb4ebc58b7883af08523b.bin", $get)));
// store license
} else {
if ($action === 'license') {
$key = post('key') ? trim(post('key')) : false;
json_exit(array('success' => $key && config::$storage_config_realpath && config::save_config(array('license_key' => $key)), 'md5' => $key ? md5($key) : false));
// invalid action
} else {
json_error('invalid action: ' . $action);
}
}
}
}
}
}
}
}
// GET
} else {
/*if($_SERVER['REQUEST_METHOD'] === 'GET')*/
// download_dir_zip / download files in directory as zip file
if (get('download_dir_zip')) {
new config();
// check download_dir enabled
if (config::$config['download_dir'] !== 'zip') {
error('<strong>download_dir</strong> Zip disabled.', 403);
}
// valid dir
$dir = valid_root_path(get('download_dir_zip'), true);
if (!$dir) {
error('Invalid download path <strong>' . get('download_dir_zip') . '</strong>', 404);
}
$dir = real_path($dir);
// in case of symlink path
// create zip cache directly in dir (recommended, so that dir can be renamed while zip cache remains)
if (!config::$storage_path || config::$config['download_dir_cache'] === 'dir') {
if (!is_writable($dir)) {
error('Dir ' . basename($dir) . ' is not writeable.', 500);
}
$zip_file_name = '_files.zip';
$zip_file = $dir . '/' . $zip_file_name;
// create zip file in storage _files/zip/$dirname.$md5.zip /
} else {
mkdir_or_error(config::$storage_path . '/zip');
$zip_file_name = basename($dir) . '.' . substr(md5($dir), 0, 6) . '.zip';
$zip_file = config::$storage_path . '/zip/' . $zip_file_name;
}
// cached / download_dir_cache && file_exists() && zip is not older than dir time
$cached = !empty(config::$config['download_dir_cache']) && file_exists($zip_file) && filemtime($zip_file) >= filemtime($dir);
// create zip if !cached
if (!$cached) {
// use shell zip command instead / probably faster and more robust than PHP / if use, comment out PHP ZipArchive method starting below
// exec('zip ' . $zip_file . ' ' . $dir . '/*.* -j -x _files*', $out, $res);
// check that ZipArchive class exists
if (!class_exists('ZipArchive')) {
error('Missing PHP ZipArchive class.', 500);
}
// glob files / must be readable / is_file / !symlink / !is_exclude
$files = array_filter(glob($dir . '/*', GLOB_NOSORT), function ($file) {
return is_readable($file) && is_file($file) && !is_link($file) && !is_exclude($file, false);
});
// !no files available to zip
if (empty($files)) {
error('No files to zip!', 400);
}
// new ZipArchive
$zip = new ZipArchive();
// create new $zip_file
if ($zip->open($zip_file, ZipArchive::CREATE | ZIPARCHIVE::OVERWRITE) !== true) {
error('Failed to create ZIP file ' . $zip_file_name . '.', 500);
}
// add files to zip / flatten with basename()
foreach ($files as $file) {
$zip->addFile($file, basename($file));
}
// no files added (for some reason)
if (!$zip->numFiles) {
error('Could not add any files to ' . $zip_file_name . '.', 500);
}
// close zip
$zip->close();
// make sure created zip file exists / just in case
if (!file_exists($zip_file)) {
error('Zip file ' . $zip_file_name . ' does not exist.', 500);
}
}
// redirect instead of readfile() / might be useful if readfile() fails and/or for caching and performance
/*$zip_url = get_url_path($zip_file);
if($zip_url){
header('Location:' . $zip_url . '?' . filemtime($dir), true, 302);
exit;
}*/
// output headers
if (config::$has_login) {
header('cache-control: must-revalidate, post-check=0, pre-check=0');
header('cache-control: public');
header('expires: 0');
header('pragma: public');
} else {
set_cache_headers();
}
header('content-description: File Transfer');
header('content-disposition: attachment; filename="' . addslashes(basename($dir)) . '.zip"');
$content_length = filesize($zip_file);
header('content-length: ' . $content_length);
header('content-transfer-encoding: binary');
header('content-type: application/zip');
header('files-msg: [' . $zip_file_name . '][' . ($cached ? 'cached' : 'created') . ']');
// ignore user abort so we can delete file also on download cancel
if (empty(config::$config['download_dir_cache'])) {
@ignore_user_abort(true);
}
// clear output buffer for large files
while (ob_get_level()) {
ob_end_clean();
}
// output zip readfile()
if (!readfile($zip_file)) {
error('Failed to readfile(' . $zip_file_name . ').', 500);
}
// delete temp zip file if cache disable
if (empty(config::$config['download_dir_cache'])) {
@unlink($zip_file);
}
// folder preview image
} else {
if (get('preview')) {
new config();
// allow only if only if folder_preview_image + load_images + image_resize_enabled
foreach (['folder_preview_image', 'load_images', 'image_resize_enabled'] as $key) {
if (!config::$config[$key]) {
error('[' . $key . '] disabled.', 400);
}
}
// get real path and validate
$path = valid_root_path(get('preview'), true);
// make sure is valid dir
if (!$path) {
error('Invalid directory.', 404);
}
// 1. first check for default '_filespreview.jpg' inside dir
$default = config::$config['folder_preview_default'] ? $path . '/' . config::$config['folder_preview_default'] : false;
if ($default && file_exists($default)) {
header('files-preview: folder_preview_default found [' . config::$config['folder_preview_default'] . ']');
resize_image($default, config::$config['image_resize_dimensions']);
}
// 2. check preview cache
$cache = config::$cache_path . '/images/preview.' . substr(md5($path), 0, 6) . '.jpg';
// cache file exists
if (file_exists($cache)) {
// make sure cache file is valid (must be newer than dir updated time)
if (filemtime($cache) >= filemtime($path)) {
read_file($cache, null, 'preview image served from cache', null, true);
}
// delete expired cache file if is older than dir updated time [silent]
@unlink($cache);
}
// 3. glob images / GLOB_BRACE may fail on some non GNU systems, like Solaris.
$images = @glob($path . '/*.{jpg,JPG,jpeg,JPEG,png,PNG,gif,GIF}', "GLOB_N_SOWT");
// loop images to locate first match that is not excluded
if (!empty($images)) {
foreach ($images as $image) {
if (!is_exclude($image, false)) {
header('files-preview: glob() found [' . basename($image) . ']');
resize_image($image, config::$config['image_resize_dimensions'], $cache);
// + clone into $cache
break;
}
}
}
// 4. nothing found (no images in dir)
// create empty 1px in $cache, and output (so next check knows dir is empty or has no images, unless updated)
if (imagejpeg(imagecreate(1, 1), $cache)) {
read_file($cache, 'image/jpeg', '1px placeholder image created and cached', null, true);
}
// file/image
} else {
if (isset($_GET['file'])) {
new config();
get_file(valid_root_path(get('file')), get('resize'));
// download
} else {
if (isset($_GET['download'])) {
new config();
// valid download
$download = valid_root_path(get('download'));
if (!$download) {
error('Invalid download path <strong>' . get('download') . '</strong>', 404);
}
$download = real_path($download);
// in case of symlink path
// required for some browsers
if (@ini_get('zlib.output_compression')) {
@ini_set('zlib.output_compression', 'Off');
}
// headers
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($download) . '"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($download));
while (ob_get_level()) {
ob_end_clean();
}
readfile($download);
// tasks plugin
} else {
if (get('task')) {
// new config with tests
new config(true);
// get plugin
$tasks_path = config::$storage_path . '/plugins/tasks.php';
if (!file_exists($tasks_path)) {
error("Tasks plugin does not exist at <strong>{$tasks_path}</strong>", 404);
}
include $tasks_path;
exit;
} else {
// new config, with tests
new config(true);
// validate exclude regex
if (config::$config['files_exclude'] && @preg_match(config::$config['files_exclude'], '') === false) {
error('Invalid files_exclude regex <strong>' . config::$config['files_exclude'] . '</strong>');
}
if (config::$config['dirs_exclude'] && @preg_match(config::$config['dirs_exclude'], '') === false) {
error('Invalid dirs_exclude regex <strong>' . config::$config['dirs_exclude'] . '</strong>');
}
// start path
$start_path = config::$config['start_path'];
if ($start_path) {
$real_start_path = real_path($start_path);
if (!$real_start_path) {
error('start_path ' . $start_path . ' does not exist.');
}
if (!is_within_root($real_start_path)) {
error('start_path ' . $start_path . ' is not within root dir ' . config::$config['root']);
}
$start_path = root_relative($real_start_path);
}
// root dirs (if menu)
$root_dirs = config::$config['menu_enabled'] || config::$config['breadcrumbs'] ? get_root_dirs() : false;
$menu_enabled = config::$config['menu_enabled'] && !empty($root_dirs) ? true : false;
$breadcrumbs = config::$config['breadcrumbs'] && !empty($root_dirs) ? true : false;
// get menu cache hash
$menu_cache_hash = false;
$menu_cache_file = false;
if ($menu_enabled) {
$menu_cache_hash = get_menu_cache_hash($root_dirs);
// menu cache file (if cache, !menu_cache_validate, exists and is within doc root)
if (config::$storage_is_within_doc_root && config::$config['cache'] && !config::$config['menu_cache_validate']) {
$menu_cache_path = config::$cache_path . '/menu/' . $menu_cache_hash . '.json';
$menu_cache_file = file_exists($menu_cache_path) ? get_url_path($menu_cache_path) : false;
if ($menu_cache_file) {
$menu_cache_file .= '?' . filemtime($menu_cache_path);
}
}
}
// init path
$query = config::$config['history'] && isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING']) ? explode('&', $_SERVER['QUERY_STRING']) : false;
$query_path = $query && strpos($query[0], '=') === false ? rtrim(rawurldecode($query[0]), '/') : false;
$query_path_valid = $query_path ? valid_root_path($query_path, true) : false;
$init_path = ($query_path ?: $start_path) ?: '';
// init dirs, with files if cache
function get_dir_init($dir)
{
$cache = get_dir_cache_path(real_path($dir));
if (file_exists($cache)) {
return json_decode(file_get_contents($cache), true);
}
return get_dir($dir);
}
// get dirs for root and start path
$dirs = array('' => get_dir_init(config::$root));
if ($query_path) {
if ($query_path_valid) {
$dirs[$query_path] = get_dir_init($query_path_valid);
}
} else {
if ($start_path) {
$dirs[$start_path] = get_dir_init($real_start_path);
}
}
// resize image types
$resize_image_types = array('jpeg', 'jpg', 'png', 'gif');
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
$resize_image_types[] = 'webp';
if (version_compare(PHP_VERSION, '7.2.0') >= 0) {
$resize_image_types[] = 'bmp';
}
}
// image resize memory limit
$image_resize_memory_limit = config::$config['image_resize_enabled'] && config::$config['image_resize_memory_limit'] && function_exists('ini_get') ? (int) @ini_get('memory_limit') : 0;
if ($image_resize_memory_limit && function_exists('ini_set')) {
$image_resize_memory_limit = max($image_resize_memory_limit, config::$config['image_resize_memory_limit']);
}
// wtc
$wtc = config::$config["license_key"];
// look for custom language files _files/lang/*.json
function lang_custom()
{
$dir = config::$storage_path ? config::$storage_path . '/lang' : false;
$files = $dir && file_exists($dir) ? glob($dir . '/*.json') : false;
if (empty($files)) {
return false;
}
$langs = array();
foreach ($files as $path) {
$json = @file_get_contents($path);
$data = !empty($json) ? @json_decode($json, true) : false;
if (!empty($data)) {
$langs[strtok(basename($path), '.')] = $data;
}
}
return !empty($langs) ? $langs : false;
}
// exclude some user settings from frontend
$exclude = array_diff_key(config::$config, array_flip(array('root', 'start_path', 'image_resize_cache', 'image_resize_quality', 'image_resize_function', 'image_resize_cache_direct', 'menu_sort', 'menu_load_all', 'cache_key', 'storage_path', 'files_exclude', 'dirs_exclude', 'username', 'password', 'breadcrumbs', 'allow_tasks', 'allow_symlinks', 'menu_recursive_symlinks', 'image_resize_sharpen', 'get_mime_type', 'license_key', 'video_thumbs', 'video_ffmpeg_path', 'folder_preview_default', 'image_resize_dimensions_allowed', 'download_dir_cache')));
// json config
$json_config = array_replace($exclude, array('breadcrumbs' => $breadcrumbs, 'script' => basename("/var/www/html/manager3.php.cf6eb2c9bf1fb4ebc58b7883af08523b.bin"), 'menu_enabled' => $menu_enabled, 'menu_cache_hash' => $menu_cache_hash, 'menu_cache_file' => $menu_cache_file, 'query_path' => $query_path, 'query_path_valid' => $query_path_valid ? true : false, 'init_path' => $init_path, 'dirs' => $dirs, 'dirs_hash' => config::$dirs_hash, 'resize_image_types' => $resize_image_types, 'image_cache_hash' => config::$config['load_images'] ? substr(md5(config::$doc_root . config::$root . config::$config['image_resize_function'] . config::$config['image_resize_quality']), 0, 6) : false, 'image_resize_dimensions_retina' => config::$image_resize_dimensions_retina, 'location_hash' => md5(config::$root), 'has_login' => config::$has_login, 'version' => config::$version, 'index_html' => intval(get('index_html')), 'server_exif' => function_exists('exif_read_data'), 'image_resize_memory_limit' => $image_resize_memory_limit, 'qrx' => $wtc && is_string($wtc) ? substr(md5($wtc), 0, strlen($wtc)) : false, 'video_thumbs_enabled' => config::$config['video_thumbs'] && config::$config['video_ffmpeg_path'] && config::$config['load_images'] && config::$config['image_resize_cache'] && @function_exists('exec') && @exec('type -P ' . config::$config['video_ffmpeg_path']), 'lang_custom' => lang_custom(), 'x3_path' => config::$x3_path ? get_url_path(config::$x3_path) : false));
function php_directive_value_to_bytes($directive)
{
$val = function_exists('ini_get') ? @ini_get($directive) : false;
if (empty($val) || !is_string($val)) {
return 0;
}
preg_match('/^(?<value>\\d+)(?<option>[K|M|G]*)$/i', $val, $matches);
$value = (int) $matches['value'];
$option = strtoupper($matches['option']);
if ($option === 'K') {
$value *= 1024;
} elseif ($option === 'M') {
$value *= 1048576;
} elseif ($option === 'G') {
$value *= 1073741824;
}
return $value;
}
// upload options
if (config::$config['allow_upload']) {
if (function_exists('ini_get') && !@ini_get('file_uploads')) {
error('PHP file_uploads disabled on this server.', 500);
}
// get max_filesize from all potential limitations (must be > 0)
$max_sizes = array_filter(array(php_directive_value_to_bytes('upload_max_filesize'), php_directive_value_to_bytes('post_max_size'), config::$config['upload_max_filesize']));
// get min val from max_sizes[] || no limit
$json_config['upload_max_filesize'] = !empty($max_sizes) ? min($max_sizes) : 0;
}
// memory and time
header('files-msg: [' . header_memory_time() . ']');
// htmlstart
?>
<!doctype html>
<html<?php
echo ' class="menu-' . ($menu_enabled ? 'enabled' : 'disabled sidebar-closed') . '"';
?>>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="noindex,nofollow">
<title><?php
echo $init_path ? basename($init_path) : '/';
?></title>
<?php
get_include('include/head.html');
?>
<link href="<?php
echo config::$assets;
?>css/files.css" rel="stylesheet">
<?php
get_include('css/custom.css');
?>
</head>
<body class="body-loading"><svg viewBox="0 0 18 18" class="svg-preloader svg-preloader-active preloader-body"><circle cx="9" cy="9" r="8" pathLength="100" class="svg-preloader-circle"></svg>
<main id="main">
<?php
$topbar_classes = array();
if (config::$config['topbar_sticky']) {
array_push($topbar_classes, 'topbar-sticky');
}
if ($breadcrumbs) {
array_push($topbar_classes, 'has-breadcrumbs');
}
?>
<nav id="topbar"<?php
if (!empty($topbar_classes)) {
echo ' class="' . join(' ', $topbar_classes) . '"';
}
?>>
<div id="topbar-top">
<div id="search-container"><input id="search" type="search" placeholder="search" size="1" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off" disabled></div>
<div id="change-layout" class="dropdown"></div>
<div id="change-sort" class="dropdown"></div>
</div>
<?php
if ($breadcrumbs) {
?>
<div id="topbar-breadcrumbs">
<div class="breadcrumbs-info"></div>
<div id="breadcrumbs"></div>
</div>
<?php
}
?>
<div id="topbar-info" class="info-hidden"></div>
<div id="files-sortbar"></div>
</nav>
<!-- files list container -->
<div><div id="files" class="list files-<?php
echo config::$config['layout'];
?>"></div></div>
</main>
<?php
if ($menu_enabled) {
?>
<aside id="sidebar">
<button id="sidebar-toggle" type="button" class="btn-icon"></button>
<div id="sidebar-inner">
<div id="sidebar-topbar"></div>
<div id="sidebar-menu"></div>
</div>
</aside>
<div id="sidebar-bg"></div>
<?php
}
?>
<!-- modal -->
<div id="modal-bg"></div>
<div class="modal" id="files_modal" tabindex="-1" role="dialog" data-action="close"></div>
<!-- context menu -->
<div id="contextmenu" class="dropdown-menu"></div>
<!-- custom footer html -->
<?php
get_include('include/footer.html');
?>
<!-- Javascript -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11.1.9/dist/sweetalert2.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js"></script>
<!--<script src="https://cdn.jsdelivr.net/npm/list.js@2.3.1/dist/list.min.js"></script>-->
<script src="https://cdn.jsdelivr.net/npm/@exeba/list.js@2.3.1/dist/list.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/yall-js@3.2.0/dist/yall.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/filesize@8.0.6/lib/filesize.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/screenfull@5.1.0/dist/screenfull.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@1.10.7/dayjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@1.10.7/plugin/localizedFormat.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@1.10.7/plugin/relativeTime.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js"></script>
<?php
if (config::$config['download_dir'] === 'files') {
?>
<script src="https://cdn.jsdelivr.net/npm/js-file-downloader@1.1.22/dist/js-file-downloader.min.js"></script>
<?php
}
?>
<script>
var _c = <?php
echo json_encode($json_config, "JSON_U_WW_Y_____^]W_OO_ERROR");
?>;
var CodeMirror = {};
</script>
<script src="https://cdn.jsdelivr.net/npm/codemirror@5.63.3/mode/meta.js"></script>
<!-- custom -->
<?php
get_include('js/custom.js');
?>
<!-- files -->
<script src="<?php
echo config::$assets;
?>js/files.js"></script>
</body>
</html>
<?php
}
}
}
}
}
}
// htmlend
Version: 3.1.0beta2
File format: 4
TRACE START [2023-02-12 23:33:16.568101]
1 0 1 0.000235 393528
1 3 0 0.002813 935768 {main} 1 /var/www/html/uploads/manager3.php 0 0
2 4 0 0.002838 935768 ini_set 0 /var/www/html/uploads/manager3.php 4 2 'display_errors' 1
2 4 1 0.002857 935840
2 4 R ''
2 5 0 0.002872 935768 ini_set 0 /var/www/html/uploads/manager3.php 5 2 'display_startup_errors' 1
2 5 1 0.002886 935840
2 5 R ''
2 6 0 0.002899 935768 error_reporting 0 /var/www/html/uploads/manager3.php 6 1 32767
2 6 1 0.002913 935840
2 6 R 22527
2 7 0 0.002929 935800 post 1 /var/www/html/uploads/manager3.php 1289 1 'action'
2 7 1 0.002945 935800
2 7 R FALSE
2 8 0 0.002959 935800 get 1 /var/www/html/uploads/manager3.php 1531 1 'download_dir_zip'
2 8 1 0.002973 935800
2 8 R FALSE
2 9 0 0.002986 935800 get 1 /var/www/html/uploads/manager3.php 1632 1 'preview'
2 9 1 0.002999 935800
2 9 R FALSE
2 10 0 0.003012 935800 get 1 /var/www/html/uploads/manager3.php 1713 1 'task'
2 10 1 0.003025 935800
2 10 R FALSE
2 11 0 0.003039 935840 config->__construct 1 /var/www/html/uploads/manager3.php 1728 1 TRUE
3 12 0 0.003053 935840 real_path 1 /var/www/html/uploads/manager3.php 231 1 '/var/www/html/uploads'
4 13 0 0.003067 935840 realpath 0 /var/www/html/uploads/manager3.php 429 1 '/var/www/html/uploads'
4 13 1 0.003081 935920
4 13 R '/var/www/html/uploads'
3 A /var/www/html/uploads/manager3.php 429 $real_path = '/var/www/html/uploads'
4 14 0 0.003108 935888 str_replace 0 /var/www/html/uploads/manager3.php 430 3 '\\' '/' '/var/www/html/uploads'
4 14 1 0.003123 935984
4 14 R '/var/www/html/uploads'
3 12 1 0.003139 935888
3 12 R '/var/www/html/uploads'
2 A /var/www/html/uploads/manager3.php 231 self::__dir__ = '/var/www/html/uploads'
3 15 0 0.003165 935824 real_path 1 /var/www/html/uploads/manager3.php 232 1 '/var/www/html/uploads/manager3.php'
4 16 0 0.003178 935824 realpath 0 /var/www/html/uploads/manager3.php 429 1 '/var/www/html/uploads/manager3.php'
4 16 1 0.003191 935920
4 16 R '/var/www/html/uploads/manager3.php'
3 A /var/www/html/uploads/manager3.php 429 $real_path = '/var/www/html/uploads/manager3.php'
4 17 0 0.003218 935888 str_replace 0 /var/www/html/uploads/manager3.php 430 3 '\\' '/' '/var/www/html/uploads/manager3.php'
4 17 1 0.003232 935984
4 17 R '/var/www/html/uploads/manager3.php'
3 15 1 0.003248 935888
3 15 R '/var/www/html/uploads/manager3.php'
2 A /var/www/html/uploads/manager3.php 232 self::__file__ = '/var/www/html/uploads/manager3.php'
3 18 0 0.003276 935888 config->get_config 1 /var/www/html/uploads/manager3.php 235 1 '_filesconfig.php'
4 19 0 0.003291 935888 file_exists 0 /var/www/html/uploads/manager3.php 154 1 '_filesconfig.php'
4 19 1 0.003315 935928
4 19 R FALSE
3 18 1 0.003330 935888
3 18 R []
2 A /var/www/html/uploads/manager3.php 235 $local_config = []
2 A /var/www/html/uploads/manager3.php 238 $storage_path = '_files'
3 20 0 0.003366 935888 real_path 1 /var/www/html/uploads/manager3.php 239 1 '_files'
4 21 0 0.003378 935888 realpath 0 /var/www/html/uploads/manager3.php 429 1 '_files'
4 21 1 0.003396 935920
4 21 R FALSE
3 A /var/www/html/uploads/manager3.php 429 $real_path = FALSE
3 20 1 0.003421 935888
3 20 R FALSE
2 A /var/www/html/uploads/manager3.php 239 $storage_realpath = FALSE
2 A /var/www/html/uploads/manager3.php 241 self::storage_config_realpath = FALSE
3 22 0 0.003458 935888 config->get_config 1 /var/www/html/uploads/manager3.php 242 1 FALSE
3 22 1 0.003471 935888
3 22 R []
2 A /var/www/html/uploads/manager3.php 242 self::storage_config = []
3 23 0 0.003495 935888 array_replace 0 /var/www/html/uploads/manager3.php 245 2 [] []
3 23 1 0.003510 936008
3 23 R []
2 A /var/www/html/uploads/manager3.php 245 $user_config = []
3 24 0 0.003534 935944 array_intersect_key 0 /var/www/html/uploads/manager3.php 246 2 [] ['root' => '', 'start_path' => FALSE, 'username' => '', 'password' => '', 'load_images' => TRUE, 'load_files_proxy_php' => FALSE, 'load_images_max_filesize' => 1000000, 'load_svg_max_filesize' => 100000, 'image_resize_enabled' => TRUE, 'image_resize_cache' => TRUE, 'image_resize_dimensions' => 320, 'image_resize_dimensions_retina' => 480, 'image_resize_dimensions_allowed' => '', 'image_resize_types' => 'jpeg, png, gif, webp, bmp', 'image_resize_quality' => 85, 'image_resize_function' => 'imagecopyresampled', 'image_resize_sharpen' => TRUE, 'image_resize_memory_limit' => 128, 'image_resize_max_pixels' => 30000000, 'image_resize_min_ratio' => 1.5, 'image_resize_cache_direct' => FALSE, 'folder_preview_image' => TRUE, 'folder_preview_default' => '_filespreview.jpg', 'menu_enabled' => TRUE, 'menu_show' => TRUE, 'menu_max_depth' => 5, 'menu_sort' => 'name_asc', 'menu_cache_validate' => TRUE, 'menu_load_all' => FALSE, 'menu_recursive_symlinks' => TRUE, 'layout' => 'rows', 'sort' => 'name_asc', 'sort_dirs_first' => TRUE, 'cache' => TRUE, 'cache_key' => 0, 'storage_path' => '_files', 'files_exclude' => '', 'dirs_exclude' => '', 'allow_symlinks' => TRUE, 'history' => TRUE, 'breadcrumbs' => TRUE, 'transitions' => TRUE, 'click' => 'popup', 'click_window' => '', 'click_window_popup' => TRUE, 'code_max_load' => 100000, 'topbar_sticky' => 'scroll', 'check_updates' => FALSE, 'allow_tasks' => FALSE, 'get_mime_type' => FALSE, 'context_menu' => TRUE, 'prevent_right_click' => FALSE, 'license_key' => '', 'filter_live' => TRUE, 'filter_props' => 'name, filetype, mime, features, title', 'download_dir' => 'zip', 'download_dir_cache' => 'dir', 'allow_upload' => FALSE, 'allow_delete' => FALSE, 'allow_rename' => FALSE, 'allow_new_folder' => FALSE, 'allow_new_file' => FALSE, 'allow_duplicate' => FALSE, 'allow_text_edit' => FALSE, 'demo_mode' => FALSE, 'upload_allowed_file_types' => '', 'upload_max_filesize' => 0, 'upload_note' => '', 'upload_exists' => 'increment', 'popup_video' => TRUE, 'popup_transition' => 'glide', 'popup_transition_play' => 'inherit', 'popup_interval' => 5000, 'popup_caption' => TRUE, 'popup_caption_hide' => TRUE, 'popup_caption_style' => 'block', 'popup_caption_align' => 'center-left', 'video_thumbs' => TRUE, 'video_ffmpeg_path' => 'ffmpeg', 'video_autoplay' => TRUE, 'lang_default' => 'en', 'lang_auto' => TRUE, 'lang_menu' => FALSE]
3 24 1 0.003636 936064
3 24 R []
2 A /var/www/html/uploads/manager3.php 246 $user_valid = []
3 25 0 0.003660 936000 array_replace 0 /var/www/html/uploads/manager3.php 247 2 ['root' => '', 'start_path' => FALSE, 'username' => '', 'password' => '', 'load_images' => TRUE, 'load_files_proxy_php' => FALSE, 'load_images_max_filesize' => 1000000, 'load_svg_max_filesize' => 100000, 'image_resize_enabled' => TRUE, 'image_resize_cache' => TRUE, 'image_resize_dimensions' => 320, 'image_resize_dimensions_retina' => 480, 'image_resize_dimensions_allowed' => '', 'image_resize_types' => 'jpeg, png, gif, webp, bmp', 'image_resize_quality' => 85, 'image_resize_function' => 'imagecopyresampled', 'image_resize_sharpen' => TRUE, 'image_resize_memory_limit' => 128, 'image_resize_max_pixels' => 30000000, 'image_resize_min_ratio' => 1.5, 'image_resize_cache_direct' => FALSE, 'folder_preview_image' => TRUE, 'folder_preview_default' => '_filespreview.jpg', 'menu_enabled' => TRUE, 'menu_show' => TRUE, 'menu_max_depth' => 5, 'menu_sort' => 'name_asc', 'menu_cache_validate' => TRUE, 'menu_load_all' => FALSE, 'menu_recursive_symlinks' => TRUE, 'layout' => 'rows', 'sort' => 'name_asc', 'sort_dirs_first' => TRUE, 'cache' => TRUE, 'cache_key' => 0, 'storage_path' => '_files', 'files_exclude' => '', 'dirs_exclude' => '', 'allow_symlinks' => TRUE, 'history' => TRUE, 'breadcrumbs' => TRUE, 'transitions' => TRUE, 'click' => 'popup', 'click_window' => '', 'click_window_popup' => TRUE, 'code_max_load' => 100000, 'topbar_sticky' => 'scroll', 'check_updates' => FALSE, 'allow_tasks' => FALSE, 'get_mime_type' => FALSE, 'context_menu' => TRUE, 'prevent_right_click' => FALSE, 'license_key' => '', 'filter_live' => TRUE, 'filter_props' => 'name, filetype, mime, features, title', 'download_dir' => 'zip', 'download_dir_cache' => 'dir', 'allow_upload' => FALSE, 'allow_delete' => FALSE, 'allow_rename' => FALSE, 'allow_new_folder' => FALSE, 'allow_new_file' => FALSE, 'allow_duplicate' => FALSE, 'allow_text_edit' => FALSE, 'demo_mode' => FALSE, 'upload_allowed_file_types' => '', 'upload_max_filesize' => 0, 'upload_note' => '', 'upload_exists' => 'increment', 'popup_video' => TRUE, 'popup_transition' => 'glide', 'popup_transition_play' => 'inherit', 'popup_interval' => 5000, 'popup_caption' => TRUE, 'popup_caption_hide' => TRUE, 'popup_caption_style' => 'block', 'popup_caption_align' => 'center-left', 'video_thumbs' => TRUE, 'video_ffmpeg_path' => 'ffmpeg', 'video_autoplay' => TRUE, 'lang_default' => 'en', 'lang_auto' => TRUE, 'lang_menu' => FALSE] []
3 25 1 0.003747 944312
3 25 R ['root' => '', 'start_path' => FALSE, 'username' => '', 'password' => '', 'load_images' => TRUE, 'load_files_proxy_php' => FALSE, 'load_images_max_filesize' => 1000000, 'load_svg_max_filesize' => 100000, 'image_resize_enabled' => TRUE, 'image_resize_cache' => TRUE, 'image_resize_dimensions' => 320, 'image_resize_dimensions_retina' => 480, 'image_resize_dimensions_allowed' => '', 'image_resize_types' => 'jpeg, png, gif, webp, bmp', 'image_resize_quality' => 85, 'image_resize_function' => 'imagecopyresampled', 'image_resize_sharpen' => TRUE, 'image_resize_memory_limit' => 128, 'image_resize_max_pixels' => 30000000, 'image_resize_min_ratio' => 1.5, 'image_resize_cache_direct' => FALSE, 'folder_preview_image' => TRUE, 'folder_preview_default' => '_filespreview.jpg', 'menu_enabled' => TRUE, 'menu_show' => TRUE, 'menu_max_depth' => 5, 'menu_sort' => 'name_asc', 'menu_cache_validate' => TRUE, 'menu_load_all' => FALSE, 'menu_recursive_symlinks' => TRUE, 'layout' => 'rows', 'sort' => 'name_asc', 'sort_dirs_first' => TRUE, 'cache' => TRUE, 'cache_key' => 0, 'storage_path' => '_files', 'files_exclude' => '', 'dirs_exclude' => '', 'allow_symlinks' => TRUE, 'history' => TRUE, 'breadcrumbs' => TRUE, 'transitions' => TRUE, 'click' => 'popup', 'click_window' => '', 'click_window_popup' => TRUE, 'code_max_load' => 100000, 'topbar_sticky' => 'scroll', 'check_updates' => FALSE, 'allow_tasks' => FALSE, 'get_mime_type' => FALSE, 'context_menu' => TRUE, 'prevent_right_click' => FALSE, 'license_key' => '', 'filter_live' => TRUE, 'filter_props' => 'name, filetype, mime, features, title', 'download_dir' => 'zip', 'download_dir_cache' => 'dir', 'allow_upload' => FALSE, 'allow_delete' => FALSE, 'allow_rename' => FALSE, 'allow_new_folder' => FALSE, 'allow_new_file' => FALSE, 'allow_duplicate' => FALSE, 'allow_text_edit' => FALSE, 'demo_mode' => FALSE, 'upload_allowed_file_types' => '', 'upload_max_filesize' => 0, 'upload_note' => '', 'upload_exists' => 'increment', 'popup_video' => TRUE, 'popup_transition' => 'glide', 'popup_transition_play' => 'inherit', 'popup_interval' => 5000, 'popup_caption' => TRUE, 'popup_caption_hide' => TRUE, 'popup_caption_style' => 'block', 'popup_caption_align' => 'center-left', 'video_thumbs' => TRUE, 'video_ffmpeg_path' => 'ffmpeg', 'video_autoplay' => TRUE, 'lang_default' => 'en', 'lang_auto' => TRUE, 'lang_menu' => FALSE]
2 A /var/www/html/uploads/manager3.php 247 self::config = ['root' => '', 'start_path' => FALSE, 'username' => '', 'password' => '', 'load_images' => TRUE, 'load_files_proxy_php' => FALSE, 'load_images_max_filesize' => 1000000, 'load_svg_max_filesize' => 100000, 'image_resize_enabled' => TRUE, 'image_resize_cache' => TRUE, 'image_resize_dimensions' => 320, 'image_resize_dimensions_retina' => 480, 'image_resize_dimensions_allowed' => '', 'image_resize_types' => 'jpeg, png, gif, webp, bmp', 'image_resize_quality' => 85, 'image_resize_function' => 'imagecopyresampled', 'image_resize_sharpen' => TRUE, 'image_resize_memory_limit' => 128, 'image_resize_max_pixels' => 30000000, 'image_resize_min_ratio' => 1.5, 'image_resize_cache_direct' => FALSE, 'folder_preview_image' => TRUE, 'folder_preview_default' => '_filespreview.jpg', 'menu_enabled' => TRUE, 'menu_show' => TRUE, 'menu_max_depth' => 5, 'menu_sort' => 'name_asc', 'menu_cache_validate' => TRUE, 'menu_load_all' => FALSE, 'menu_recursive_symlinks' => TRUE, 'layout' => 'rows', 'sort' => 'name_asc', 'sort_dirs_first' => TRUE, 'cache' => TRUE, 'cache_key' => 0, 'storage_path' => '_files', 'files_exclude' => '', 'dirs_exclude' => '', 'allow_symlinks' => TRUE, 'history' => TRUE, 'breadcrumbs' => TRUE, 'transitions' => TRUE, 'click' => 'popup', 'click_window' => '', 'click_window_popup' => TRUE, 'code_max_load' => 100000, 'topbar_sticky' => 'scroll', 'check_updates' => FALSE, 'allow_tasks' => FALSE, 'get_mime_type' => FALSE, 'context_menu' => TRUE, 'prevent_right_click' => FALSE, 'license_key' => '', 'filter_live' => TRUE, 'filter_props' => 'name, filetype, mime, features, title', 'download_dir' => 'zip', 'download_dir_cache' => 'dir', 'allow_upload' => FALSE, 'allow_delete' => FALSE, 'allow_rename' => FALSE, 'allow_new_folder' => FALSE, 'allow_new_file' => FALSE, 'allow_duplicate' => FALSE, 'allow_text_edit' => FALSE, 'demo_mode' => FALSE, 'upload_allowed_file_types' => '', 'upload_max_filesize' => 0, 'upload_note' => '', 'upload_exists' => 'increment', 'popup_video' => TRUE, 'popup_transition' => 'glide', 'popup_transition_play' => 'inherit', 'popup_interval' => 5000, 'popup_caption' => TRUE, 'popup_caption_hide' => TRUE, 'popup_caption_style' => 'block', 'popup_caption_align' => 'center-left', 'video_thumbs' => TRUE, 'video_ffmpeg_path' => 'ffmpeg', 'video_autoplay' => TRUE, 'lang_default' => 'en', 'lang_auto' => TRUE, 'lang_menu' => FALSE]
3 26 0 0.003939 944192 get 1 /var/www/html/uploads/manager3.php 250 1 'check'
3 26 1 0.003953 944192
3 26 R FALSE
2 A /var/www/html/uploads/manager3.php 254 self::assets = 'https://cdn.jsdelivr.net/npm/files.photo.gallery@0.3.1/'
3 27 0 0.003983 944272 real_path 1 /var/www/html/uploads/manager3.php 257 1 ''
4 28 0 0.003996 944272 realpath 0 /var/www/html/uploads/manager3.php 429 1 ''
4 28 1 0.004010 944352
4 28 R '/var/www/html/uploads'
3 A /var/www/html/uploads/manager3.php 429 $real_path = '/var/www/html/uploads'
4 29 0 0.004037 944320 str_replace 0 /var/www/html/uploads/manager3.php 430 3 '\\' '/' '/var/www/html/uploads'
4 29 1 0.004051 944416
4 29 R '/var/www/html/uploads'
3 27 1 0.004067 944320
3 27 R '/var/www/html/uploads'
2 A /var/www/html/uploads/manager3.php 257 self::root = '/var/www/html/uploads'
3 30 0 0.004098 944320 real_path 1 /var/www/html/uploads/manager3.php 261 1 '/var/www/html'
4 31 0 0.004111 944320 realpath 0 /var/www/html/uploads/manager3.php 429 1 '/var/www/html'
4 31 1 0.004124 944392
4 31 R '/var/www/html'
3 A /var/www/html/uploads/manager3.php 429 $real_path = '/var/www/html'
4 32 0 0.004148 944360 str_replace 0 /var/www/html/uploads/manager3.php 430 3 '\\' '/' '/var/www/html'
4 32 1 0.004163 944456
4 32 R '/var/www/html'
3 30 1 0.004177 944360
3 30 R '/var/www/html'
2 A /var/www/html/uploads/manager3.php 261 self::doc_root = '/var/www/html'
2 A /var/www/html/uploads/manager3.php 264 self::username = ''
2 A /var/www/html/uploads/manager3.php 265 self::password = ''
3 33 0 0.004223 944360 dirname 0 /var/www/html/uploads/manager3.php 268 1 '/var/www/html/uploads'
3 33 1 0.004236 944440
3 33 R '/var/www/html'
2 A /var/www/html/uploads/manager3.php 268 $x3_path = '/var/www/html'
3 34 0 0.004261 944464 file_exists 0 /var/www/html/uploads/manager3.php 269 1 '/var/www/html/app/x3.inc.php'
3 34 1 0.004281 944504
3 34 R FALSE
2 A /var/www/html/uploads/manager3.php 269 self::x3_path = FALSE
2 A /var/www/html/uploads/manager3.php 278 self::has_login = FALSE
2 A /var/www/html/uploads/manager3.php 281 $image_cache = TRUE
3 35 0 0.004331 944408 rtrim 0 /var/www/html/uploads/manager3.php 288 2 '_files' '\\/'
3 35 1 0.004345 944480
3 35 R '_files'
2 A /var/www/html/uploads/manager3.php 288 $storage_path = '_files'
3 36 0 0.004370 944408 mkdir_or_error 1 /var/www/html/uploads/manager3.php 290 1 '_files'
4 37 0 0.004383 944408 file_exists 0 /var/www/html/uploads/manager3.php 426 1 '_files'
4 37 1 0.004398 944448
4 37 R FALSE
4 38 0 0.004412 944408 mkdir 0 /var/www/html/uploads/manager3.php 426 3 '_files' 511 TRUE
4 38 1 0.004464 944632
4 38 R TRUE
3 36 1 0.004480 944520
3 39 0 0.004487 944520 real_path 1 /var/www/html/uploads/manager3.php 291 1 '_files'
4 40 0 0.004500 944520 realpath 0 /var/www/html/uploads/manager3.php 429 1 '_files'
4 40 1 0.004516 944608
4 40 R '/var/www/html/uploads/_files'
3 A /var/www/html/uploads/manager3.php 429 $real_path = '/var/www/html/uploads/_files'
4 41 0 0.004542 944576 str_replace 0 /var/www/html/uploads/manager3.php 430 3 '\\' '/' '/var/www/html/uploads/_files'
4 41 1 0.004557 944672
4 41 R '/var/www/html/uploads/_files'
3 39 1 0.004572 944576
3 39 R '/var/www/html/uploads/_files'
2 A /var/www/html/uploads/manager3.php 291 $storage_realpath = '/var/www/html/uploads/_files'
2 A /var/www/html/uploads/manager3.php 293 self::storage_config_realpath = '/var/www/html/uploads/_files/config/config.php'
2 A /var/www/html/uploads/manager3.php 295 self::storage_path = '/var/www/html/uploads/_files'
3 42 0 0.004625 944656 is_within_docroot 1 /var/www/html/uploads/manager3.php 298 1 '/var/www/html/uploads/_files'
4 43 0 0.004639 944656 is_within_path 1 /var/www/html/uploads/manager3.php 445 2 '/var/www/html/uploads/_files' '/var/www/html'
5 44 0 0.004653 944752 strpos 0 /var/www/html/uploads/manager3.php 439 2 '/var/www/html/uploads/_files/' '/var/www/html/'
5 44 1 0.004668 944824
5 44 R 0
4 43 1 0.004681 944656
4 43 R TRUE
3 42 1 0.004694 944656
3 42 R TRUE
2 A /var/www/html/uploads/manager3.php 298 self::storage_is_within_doc_root = TRUE
2 A /var/www/html/uploads/manager3.php 301 self::cache_path = '/var/www/html/uploads/_files/cache'
2 A /var/www/html/uploads/manager3.php 305 $create_dirs = [0 => '/var/www/html/uploads/_files/config']
2 A /var/www/html/uploads/manager3.php 306 $create_dirs[] = '/var/www/html/uploads/_files/cache/images'
3 45 0 0.004757 945408 array_push 0 /var/www/html/uploads/manager3.php 307 3 [0 => '/var/www/html/uploads/_files/config', 1 => '/var/www/html/uploads/_files/cache/images'] '/var/www/html/uploads/_files/cache/folders' '/var/www/html/uploads/_files/cache/menu'
3 45 1 0.004774 945472
3 45 R 4
3 46 0 0.004787 945408 mkdir_or_error 1 /var/www/html/uploads/manager3.php 308 1 '/var/www/html/uploads/_files/config'
4 47 0 0.004801 945408 file_exists 0 /var/www/html/uploads/manager3.php 426 1 '/var/www/html/uploads/_files/config'
4 47 1 0.004820 945448
4 47 R FALSE
4 48 0 0.004833 945408 mkdir 0 /var/www/html/uploads/manager3.php 426 3 '/var/www/html/uploads/_files/config' 511 TRUE
4 48 1 0.004872 945520
4 48 R TRUE
3 46 1 0.004887 945408
3 49 0 0.004894 945408 mkdir_or_error 1 /var/www/html/uploads/manager3.php 308 1 '/var/www/html/uploads/_files/cache/images'
4 50 0 0.004908 945408 file_exists 0 /var/www/html/uploads/manager3.php 426 1 '/var/www/html/uploads/_files/cache/images'
4 50 1 0.004926 945448
4 50 R FALSE
4 51 0 0.004940 945408 mkdir 0 /var/www/html/uploads/manager3.php 426 3 '/var/www/html/uploads/_files/cache/images' 511 TRUE
4 51 1 0.004991 945520
4 51 R TRUE
3 49 1 0.005006 945408
3 52 0 0.005013 945408 mkdir_or_error 1 /var/www/html/uploads/manager3.php 308 1 '/var/www/html/uploads/_files/cache/folders'
4 53 0 0.005027 945408 file_exists 0 /var/www/html/uploads/manager3.php 426 1 '/var/www/html/uploads/_files/cache/folders'
4 53 1 0.005044 945448
4 53 R FALSE
4 54 0 0.005058 945408 mkdir 0 /var/www/html/uploads/manager3.php 426 3 '/var/www/html/uploads/_files/cache/folders' 511 TRUE
4 54 1 0.005091 945520
4 54 R TRUE
3 52 1 0.005105 945408
3 55 0 0.005112 945408 mkdir_or_error 1 /var/www/html/uploads/manager3.php 308 1 '/var/www/html/uploads/_files/cache/menu'
4 56 0 0.005125 945408 file_exists 0 /var/www/html/uploads/manager3.php 426 1 '/var/www/html/uploads/_files/cache/menu'
4 56 1 0.005143 945448
4 56 R FALSE
4 57 0 0.005156 945408 mkdir 0 /var/www/html/uploads/manager3.php 426 3 '/var/www/html/uploads/_files/cache/menu' 511 TRUE
4 57 1 0.005188 945520
4 57 R TRUE
3 55 1 0.005202 945408
3 58 0 0.005209 945408 file_exists 0 /var/www/html/uploads/manager3.php 312 1 '/var/www/html/uploads/_files/config/config.php'
3 58 1 0.005228 945448
3 58 R FALSE
3 59 0 0.005242 945408 config::save_config 1 /var/www/html/uploads/manager3.php 312 1 ???
4 60 0 0.005256 945408 array_replace 0 /var/www/html/uploads/manager3.php 221 2 [] []
4 60 1 0.005269 945528
4 60 R []
4 61 0 0.005282 945464 array_intersect_key 0 /var/www/html/uploads/manager3.php 221 2 [] ['root' => '', 'start_path' => FALSE, 'username' => '', 'password' => '', 'load_images' => TRUE, 'load_files_proxy_php' => FALSE, 'load_images_max_filesize' => 1000000, 'load_svg_max_filesize' => 100000, 'image_resize_enabled' => TRUE, 'image_resize_cache' => TRUE, 'image_resize_dimensions' => 320, 'image_resize_dimensions_retina' => 480, 'image_resize_dimensions_allowed' => '', 'image_resize_types' => 'jpeg, png, gif, webp, bmp', 'image_resize_quality' => 85, 'image_resize_function' => 'imagecopyresampled', 'image_resize_sharpen' => TRUE, 'image_resize_memory_limit' => 128, 'image_resize_max_pixels' => 30000000, 'image_resize_min_ratio' => 1.5, 'image_resize_cache_direct' => FALSE, 'folder_preview_image' => TRUE, 'folder_preview_default' => '_filespreview.jpg', 'menu_enabled' => TRUE, 'menu_show' => TRUE, 'menu_max_depth' => 5, 'menu_sort' => 'name_asc', 'menu_cache_validate' => TRUE, 'menu_load_all' => FALSE, 'menu_recursive_symlinks' => TRUE, 'layout' => 'rows', 'sort' => 'name_asc', 'sort_dirs_first' => TRUE, 'cache' => TRUE, 'cache_key' => 0, 'storage_path' => '_files', 'files_exclude' => '', 'dirs_exclude' => '', 'allow_symlinks' => TRUE, 'history' => TRUE, 'breadcrumbs' => TRUE, 'transitions' => TRUE, 'click' => 'popup', 'click_window' => '', 'click_window_popup' => TRUE, 'code_max_load' => 100000, 'topbar_sticky' => 'scroll', 'check_updates' => FALSE, 'allow_tasks' => FALSE, 'get_mime_type' => FALSE, 'context_menu' => TRUE, 'prevent_right_click' => FALSE, 'license_key' => '', 'filter_live' => TRUE, 'filter_props' => 'name, filetype, mime, features, title', 'download_dir' => 'zip', 'download_dir_cache' => 'dir', 'allow_upload' => FALSE, 'allow_delete' => FALSE, 'allow_rename' => FALSE, 'allow_new_folder' => FALSE, 'allow_new_file' => FALSE, 'allow_duplicate' => FALSE, 'allow_text_edit' => FALSE, 'demo_mode' => FALSE, 'upload_allowed_file_types' => '', 'upload_max_filesize' => 0, 'upload_note' => '', 'upload_exists' => 'increment', 'popup_video' => TRUE, 'popup_transition' => 'glide', 'popup_transition_play' => 'inherit', 'popup_interval' => 5000, 'popup_caption' => TRUE, 'popup_caption_hide' => TRUE, 'popup_caption_style' => 'block', 'popup_caption_align' => 'center-left', 'video_thumbs' => TRUE, 'video_ffmpeg_path' => 'ffmpeg', 'video_autoplay' => TRUE, 'lang_default' => 'en', 'lang_auto' => TRUE, 'lang_menu' => FALSE]
4 61 1 0.005372 945584
4 61 R []
3 A /var/www/html/uploads/manager3.php 221 $save_config = []
4 62 0 0.005398 945464 array_replace 0 /var/www/html/uploads/manager3.php 222 2 ['root' => '', 'start_path' => FALSE, 'username' => '', 'password' => '', 'load_images' => TRUE, 'load_files_proxy_php' => FALSE, 'load_images_max_filesize' => 1000000, 'load_svg_max_filesize' => 100000, 'image_resize_enabled' => TRUE, 'image_resize_cache' => TRUE, 'image_resize_dimensions' => 320, 'image_resize_dimensions_retina' => 480, 'image_resize_dimensions_allowed' => '', 'image_resize_types' => 'jpeg, png, gif, webp, bmp', 'image_resize_quality' => 85, 'image_resize_function' => 'imagecopyresampled', 'image_resize_sharpen' => TRUE, 'image_resize_memory_limit' => 128, 'image_resize_max_pixels' => 30000000, 'image_resize_min_ratio' => 1.5, 'image_resize_cache_direct' => FALSE, 'folder_preview_image' => TRUE, 'folder_preview_default' => '_filespreview.jpg', 'menu_enabled' => TRUE, 'menu_show' => TRUE, 'menu_max_depth' => 5, 'menu_sort' => 'name_asc', 'menu_cache_validate' => TRUE, 'menu_load_all' => FALSE, 'menu_recursive_symlinks' => TRUE, 'layout' => 'rows', 'sort' => 'name_asc', 'sort_dirs_first' => TRUE, 'cache' => TRUE, 'cache_key' => 0, 'storage_path' => '_files', 'files_exclude' => '', 'dirs_exclude' => '', 'allow_symlinks' => TRUE, 'history' => TRUE, 'breadcrumbs' => TRUE, 'transitions' => TRUE, 'click' => 'popup', 'click_window' => '', 'click_window_popup' => TRUE, 'code_max_load' => 100000, 'topbar_sticky' => 'scroll', 'check_updates' => FALSE, 'allow_tasks' => FALSE, 'get_mime_type' => FALSE, 'context_menu' => TRUE, 'prevent_right_click' => FALSE, 'license_key' => '', 'filter_live' => TRUE, 'filter_props' => 'name, filetype, mime, features, title', 'download_dir' => 'zip', 'download_dir_cache' => 'dir', 'allow_upload' => FALSE, 'allow_delete' => FALSE, 'allow_rename' => FALSE, 'allow_new_folder' => FALSE, 'allow_new_file' => FALSE, 'allow_duplicate' => FALSE, 'allow_text_edit' => FALSE, 'demo_mode' => FALSE, 'upload_allowed_file_types' => '', 'upload_max_filesize' => 0, 'upload_note' => '', 'upload_exists' => 'increment', 'popup_video' => TRUE, 'popup_transition' => 'glide', 'popup_transition_play' => 'inherit', 'popup_interval' => 5000, 'popup_caption' => TRUE, 'popup_caption_hide' => TRUE, 'popup_caption_style' => 'block', 'popup_caption_align' => 'center-left', 'video_thumbs' => TRUE, 'video_ffmpeg_path' => 'ffmpeg', 'video_autoplay' => TRUE, 'lang_default' => 'en', 'lang_auto' => TRUE, 'lang_menu' => FALSE] []
4 62 1 0.005485 953776
4 62 R ['root' => '', 'start_path' => FALSE, 'username' => '', 'password' => '', 'load_images' => TRUE, 'load_files_proxy_php' => FALSE, 'load_images_max_filesize' => 1000000, 'load_svg_max_filesize' => 100000, 'image_resize_enabled' => TRUE, 'image_resize_cache' => TRUE, 'image_resize_dimensions' => 320, 'image_resize_dimensions_retina' => 480, 'image_resize_dimensions_allowed' => '', 'image_resize_types' => 'jpeg, png, gif, webp, bmp', 'image_resize_quality' => 85, 'image_resize_function' => 'imagecopyresampled', 'image_resize_sharpen' => TRUE, 'image_resize_memory_limit' => 128, 'image_resize_max_pixels' => 30000000, 'image_resize_min_ratio' => 1.5, 'image_resize_cache_direct' => FALSE, 'folder_preview_image' => TRUE, 'folder_preview_default' => '_filespreview.jpg', 'menu_enabled' => TRUE, 'menu_show' => TRUE, 'menu_max_depth' => 5, 'menu_sort' => 'name_asc', 'menu_cache_validate' => TRUE, 'menu_load_all' => FALSE, 'menu_recursive_symlinks' => TRUE, 'layout' => 'rows', 'sort' => 'name_asc', 'sort_dirs_first' => TRUE, 'cache' => TRUE, 'cache_key' => 0, 'storage_path' => '_files', 'files_exclude' => '', 'dirs_exclude' => '', 'allow_symlinks' => TRUE, 'history' => TRUE, 'breadcrumbs' => TRUE, 'transitions' => TRUE, 'click' => 'popup', 'click_window' => '', 'click_window_popup' => TRUE, 'code_max_load' => 100000, 'topbar_sticky' => 'scroll', 'check_updates' => FALSE, 'allow_tasks' => FALSE, 'get_mime_type' => FALSE, 'context_menu' => TRUE, 'prevent_right_click' => FALSE, 'license_key' => '', 'filter_live' => TRUE, 'filter_props' => 'name, filetype, mime, features, title', 'download_dir' => 'zip', 'download_dir_cache' => 'dir', 'allow_upload' => FALSE, 'allow_delete' => FALSE, 'allow_rename' => FALSE, 'allow_new_folder' => FALSE, 'allow_new_file' => FALSE, 'allow_duplicate' => FALSE, 'allow_text_edit' => FALSE, 'demo_mode' => FALSE, 'upload_allowed_file_types' => '', 'upload_max_filesize' => 0, 'upload_note' => '', 'upload_exists' => 'increment', 'popup_video' => TRUE, 'popup_transition' => 'glide', 'popup_transition_play' => 'inherit', 'popup_interval' => 5000, 'popup_caption' => TRUE, 'popup_caption_hide' => TRUE, 'popup_caption_style' => 'block', 'popup_caption_align' => 'center-left', 'video_thumbs' => TRUE, 'video_ffmpeg_path' => 'ffmpeg', 'video_autoplay' => TRUE, 'lang_default' => 'en', 'lang_auto' => TRUE, 'lang_menu' => FALSE]
4 63 0 0.005593 953712 var_export 0 /var/www/html/uploads/manager3.php 222 2 ['root' => '', 'start_path' => FALSE, 'username' => '', 'password' => '', 'load_images' => TRUE, 'load_files_proxy_php' => FALSE, 'load_images_max_filesize' => 1000000, 'load_svg_max_filesize' => 100000, 'image_resize_enabled' => TRUE, 'image_resize_cache' => TRUE, 'image_resize_dimensions' => 320, 'image_resize_dimensions_retina' => 480, 'image_resize_dimensions_allowed' => '', 'image_resize_types' => 'jpeg, png, gif, webp, bmp', 'image_resize_quality' => 85, 'image_resize_function' => 'imagecopyresampled', 'image_resize_sharpen' => TRUE, 'image_resize_memory_limit' => 128, 'image_resize_max_pixels' => 30000000, 'image_resize_min_ratio' => 1.5, 'image_resize_cache_direct' => FALSE, 'folder_preview_image' => TRUE, 'folder_preview_default' => '_filespreview.jpg', 'menu_enabled' => TRUE, 'menu_show' => TRUE, 'menu_max_depth' => 5, 'menu_sort' => 'name_asc', 'menu_cache_validate' => TRUE, 'menu_load_all' => FALSE, 'menu_recursive_symlinks' => TRUE, 'layout' => 'rows', 'sort' => 'name_asc', 'sort_dirs_first' => TRUE, 'cache' => TRUE, 'cache_key' => 0, 'storage_path' => '_files', 'files_exclude' => '', 'dirs_exclude' => '', 'allow_symlinks' => TRUE, 'history' => TRUE, 'breadcrumbs' => TRUE, 'transitions' => TRUE, 'click' => 'popup', 'click_window' => '', 'click_window_popup' => TRUE, 'code_max_load' => 100000, 'topbar_sticky' => 'scroll', 'check_updates' => FALSE, 'allow_tasks' => FALSE, 'get_mime_type' => FALSE, 'context_menu' => TRUE, 'prevent_right_click' => FALSE, 'license_key' => '', 'filter_live' => TRUE, 'filter_props' => 'name, filetype, mime, features, title', 'download_dir' => 'zip', 'download_dir_cache' => 'dir', 'allow_upload' => FALSE, 'allow_delete' => FALSE, 'allow_rename' => FALSE, 'allow_new_folder' => FALSE, 'allow_new_file' => FALSE, 'allow_duplicate' => FALSE, 'allow_text_edit' => FALSE, 'demo_mode' => FALSE, 'upload_allowed_file_types' => '', 'upload_max_filesize' => 0, 'upload_note' => '', 'upload_exists' => 'increment', 'popup_video' => TRUE, 'popup_transition' => 'glide', 'popup_transition_play' => 'inherit', 'popup_interval' => 5000, 'popup_caption' => TRUE, 'popup_caption_hide' => TRUE, 'popup_caption_style' => 'block', 'popup_caption_align' => 'center-left', 'video_thumbs' => TRUE, 'video_ffmpeg_path' => 'ffmpeg', 'video_autoplay' => TRUE, 'lang_default' => 'en', 'lang_auto' => TRUE, 'lang_menu' => FALSE] TRUE
4 63 1 0.005739 957872
4 63 R 'array (\n \'root\' => \'\',\n \'start_path\' => false,\n \'username\' => \'\',\n \'password\' => \'\',\n \'load_images\' => true,\n \'load_files_proxy_php\' => false,\n \'load_images_max_filesize\' => 1000000,\n \'load_svg_max_filesize\' => 100000,\n \'image_resize_enabled\' => true,\n \'image_resize_cache\' => true,\n \'image_resize_dimensions\' => 320,\n \'image_resize_dimensions_retina\' => 480,\n \'image_resize_dimensions_allowed\' => \'\',\n \'image_resize_types\' => \'jpeg, png, gif, web'
4 64 0 0.005789 949560 preg_replace 0 /var/www/html/uploads/manager3.php 222 3 '/ \'/' ' //\'' 'array (\n \'root\' => \'\',\n \'start_path\' => false,\n \'username\' => \'\',\n \'password\' => \'\',\n \'load_images\' => true,\n \'load_files_proxy_php\' => false,\n \'load_images_max_filesize\' => 1000000,\n \'load_svg_max_filesize\' => 100000,\n \'image_resize_enabled\' => true,\n \'image_resize_cache\' => true,\n \'image_resize_dimensions\' => 320,\n \'image_resize_dimensions_retina\' => 480,\n \'image_resize_dimensions_allowed\' => \'\',\n \'image_resize_types\' => \'jpeg, png, gif, web'
4 64 1 0.005873 952728
4 64 R 'array (\n //\'root\' => \'\',\n //\'start_path\' => false,\n //\'username\' => \'\',\n //\'password\' => \'\',\n //\'load_images\' => true,\n //\'load_files_proxy_php\' => false,\n //\'load_images_max_filesize\' => 1000000,\n //\'load_svg_max_filesize\' => 100000,\n //\'image_resize_enabled\' => true,\n //\'image_resize_cache\' => true,\n //\'image_resize_dimensions\' => 320,\n //\'image_resize_dimensions_retina\' => 480,\n //\'image_resize_dimensions_allowed\' => \'\',\n //\'image_resize_type'
3 A /var/www/html/uploads/manager3.php 222 $export = 'array (\n //\'root\' => \'\',\n //\'start_path\' => false,\n //\'username\' => \'\',\n //\'password\' => \'\',\n //\'load_images\' => true,\n //\'load_files_proxy_php\' => false,\n //\'load_images_max_filesize\' => 1000000,\n //\'load_svg_max_filesize\' => 100000,\n //\'image_resize_enabled\' => true,\n //\'image_resize_cache\' => true,\n //\'image_resize_dimensions\' => 320,\n //\'image_resize_dimensions_retina\' => 480,\n //\'image_resize_dimensions_allowed\' => \'\',\n //\'image_resize_type'
4 65 0 0.005962 951608 file_put_contents 0 /var/www/html/uploads/manager3.php 224 2 '/var/www/html/uploads/_files/config/config.php' '<?php \n\n// CONFIG / https://forum.photo.gallery/viewtopic.php?f=66&t=9964\n// Uncomment the parameters you want to edit.\nreturn array (\n //\'root\' => \'\',\n //\'start_path\' => false,\n //\'username\' => \'\',\n //\'password\' => \'\',\n //\'load_images\' => true,\n //\'load_files_proxy_php\' => false,\n //\'load_images_max_filesize\' => 1000000,\n //\'load_svg_max_filesize\' => 100000,\n //\'image_resize_enabled\' => true,\n //\'image_resize_cache\' => true,\n //\'image_resize_dimensions\''
4 65 1 0.006056 951680
4 65 R 2837
3 59 1 0.006081 945408
2 A /var/www/html/uploads/manager3.php 319 self::image_resize_dimensions_retina = 480
3 66 0 0.006121 945504 md5 0 /var/www/html/uploads/manager3.php 322 1 '/var/www/html/var/www/html/uploads/var/www/html/uploads0.3.10'
3 66 1 0.006144 945600
3 66 R '17042622a2c53ec164000929593e308e'
3 67 0 0.006167 945472 substr 0 /var/www/html/uploads/manager3.php 322 3 '17042622a2c53ec164000929593e308e' 0 6
3 67 1 0.006190 945600
3 67 R '170426'
2 A /var/www/html/uploads/manager3.php 322 self::dirs_hash = '170426'
2 11 1 0.006229 944592
1 A /var/www/html/uploads/manager3.php 1735 $start_path = FALSE
2 68 0 0.006260 944552 get_root_dirs 1 /var/www/html/uploads/manager3.php 1744 0
3 69 0 0.006279 944600 glob 0 /var/www/html/uploads/manager3.php 1232 2 '/var/www/html/uploads/*' 8196
3 69 1 0.006329 945152
3 69 R [0 => '/var/www/html/uploads/_files', 1 => '/var/www/html/uploads/data']
2 A /var/www/html/uploads/manager3.php 1232 $root_dirs = [0 => '/var/www/html/uploads/_files', 1 => '/var/www/html/uploads/data']
3 70 0 0.006379 945360 array_filter 0 /var/www/html/uploads/manager3.php 1236 2 [0 => '/var/www/html/uploads/_files', 1 => '/var/www/html/uploads/data'] class Closure { virtual $closure = "{closure}", public $parameter = ['$dir' => '<required>'] }
4 71 0 0.006435 945488 {closure:/var/www/html/uploads/manager3.php:1234-1236} 1 /var/www/html/uploads/manager3.php 1236 1 '/var/www/html/uploads/_files'
5 72 0 0.006459 945488 is_link 0 /var/www/html/uploads/manager3.php 1235 1 '/var/www/html/uploads/_files'
5 72 1 0.006489 945560
5 72 R FALSE
5 73 0 0.006511 945520 is_exclude 1 /var/www/html/uploads/manager3.php 1235 3 '/var/www/html/uploads/_files' TRUE FALSE
6 74 0 0.006533 945520 strpos 0 /var/www/html/uploads/manager3.php 512 2 '/var/www/html/uploads/_files' '/_files'
6 74 1 0.006567 945592
6 74 R 21
5 73 1 0.006588 945520
5 73 R TRUE
4 71 1 0.006609 945520
4 71 R FALSE
4 75 0 0.006630 945520 {closure:/var/www/html/uploads/manager3.php:1234-1236} 1 /var/www/html/uploads/manager3.php 1236 1 '/var/www/html/uploads/data'
5 76 0 0.006654 945520 is_link 0 /var/www/html/uploads/manager3.php 1235 1 '/var/www/html/uploads/data'
5 76 1 0.006677 945560
5 76 R FALSE
5 77 0 0.006697 945520 is_exclude 1 /var/www/html/uploads/manager3.php 1235 3 '/var/www/html/uploads/data' TRUE FALSE
6 78 0 0.006719 945520 strpos 0 /var/www/html/uploads/manager3.php 512 2 '/var/www/html/uploads/data' '/_files'
6 78 1 0.006740 945592
6 78 R FALSE
6 79 0 0.006761 945520 is_within_path 1 /var/www/html/uploads/manager3.php 521 2 '/var/www/html/uploads/data' '/var/www/html/uploads/_files'
7 80 0 0.006782 945632 strpos 0 /var/www/html/uploads/manager3.php 439 2 '/var/www/html/uploads/data/' '/var/www/html/uploads/_files/'
7 80 1 0.006803 945704
7 80 R FALSE
6 79 1 0.006823 945520
6 79 R FALSE
5 77 1 0.006845 945520
5 77 R NULL
4 75 1 0.006865 945520
4 75 R TRUE
3 70 1 0.006885 945840
3 70 R [1 => '/var/www/html/uploads/data']
2 68 1 0.006910 945016
2 68 R [1 => '/var/www/html/uploads/data']
1 A /var/www/html/uploads/manager3.php 1744 $root_dirs = [1 => '/var/www/html/uploads/data']
1 A /var/www/html/uploads/manager3.php 1745 $menu_enabled = TRUE
1 A /var/www/html/uploads/manager3.php 1746 $breadcrumbs = TRUE
1 A /var/www/html/uploads/manager3.php 1749 $menu_cache_hash = FALSE
1 A /var/www/html/uploads/manager3.php 1750 $menu_cache_file = FALSE
2 81 0 0.007002 945016 get_menu_cache_hash 1 /var/www/html/uploads/manager3.php 1752 1 [1 => '/var/www/html/uploads/data']
3 82 0 0.007018 945016 filemtime 0 /var/www/html/uploads/manager3.php 1241 1 '/var/www/html/uploads'
3 82 1 0.007035 945080
3 82 R 1676251970
2 A /var/www/html/uploads/manager3.php 1241 $mtime_count = 1676251970
3 83 0 0.007060 945040 filemtime 0 /var/www/html/uploads/manager3.php 1242 1 '/var/www/html/uploads/data'
3 83 1 0.007075 945088
3 83 R 1676251970
2 A /var/www/html/uploads/manager3.php 1242 $mtime_count += 1676251970
3 84 0 0.007101 945128 md5 0 /var/www/html/uploads/manager3.php 1243 1 '/var/www/html/var/www/html/uploads/var/www/html/uploads'
3 84 1 0.007115 945224
3 84 R '356888cdb6aec723f199c5dc79a286d0'
3 85 0 0.007130 945112 substr 0 /var/www/html/uploads/manager3.php 1243 3 '356888cdb6aec723f199c5dc79a286d0' 0 6
3 85 1 0.007144 945240
3 85 R '356888'
3 86 0 0.007160 945120 md5 0 /var/www/html/uploads/manager3.php 1243 1 '0.3.105name_asc'
3 86 1 0.007173 945216
3 86 R '295aa76f3a02cf22574cd0ae0fe9420c'
3 87 0 0.007187 945144 substr 0 /var/www/html/uploads/manager3.php 1243 3 '295aa76f3a02cf22574cd0ae0fe9420c' 0 6
3 87 1 0.007201 945272
3 87 R '295aa7'
2 81 1 0.007216 945104
2 81 R '356888.295aa7.3352503940'
1 A /var/www/html/uploads/manager3.php 1752 $menu_cache_hash = '356888.295aa7.3352503940'
1 A /var/www/html/uploads/manager3.php 1762 $query = FALSE
1 A /var/www/html/uploads/manager3.php 1763 $query_path = FALSE
1 A /var/www/html/uploads/manager3.php 1764 $query_path_valid = FALSE
1 A /var/www/html/uploads/manager3.php 1765 $init_path = ''
2 88 0 0.007291 945104 get_dir_init 1 /var/www/html/uploads/manager3.php 1775 1 '/var/www/html/uploads'
3 89 0 0.007305 945104 real_path 1 /var/www/html/uploads/manager3.php 1769 1 '/var/www/html/uploads'
4 90 0 0.007319 945104 realpath 0 /var/www/html/uploads/manager3.php 429 1 '/var/www/html/uploads'
4 90 1 0.007334 945184
4 90 R '/var/www/html/uploads'
3 A /var/www/html/uploads/manager3.php 429 $real_path = '/var/www/html/uploads'
4 91 0 0.007360 945152 str_replace 0 /var/www/html/uploads/manager3.php 430 3 '\\' '/' '/var/www/html/uploads'
4 91 1 0.007376 945248
4 91 R '/var/www/html/uploads'
3 89 1 0.007392 945152
3 89 R '/var/www/html/uploads'
3 92 0 0.007412 945152 get_dir_cache_path 1 /var/www/html/uploads/manager3.php 1769 2 '/var/www/html/uploads' ???
4 93 0 0.007427 945152 get_dir_cache_hash 1 /var/www/html/uploads/manager3.php 456 2 '/var/www/html/uploads' FALSE
5 94 0 0.007442 945184 md5 0 /var/www/html/uploads/manager3.php 459 1 '/var/www/html/uploads'
5 94 1 0.007455 945280
5 94 R 'efc1f9341a6f3e19acc38a2871eef237'
5 95 0 0.007470 945248 substr 0 /var/www/html/uploads/manager3.php 459 3 'efc1f9341a6f3e19acc38a2871eef237' 0 6
5 95 1 0.007484 945376
5 95 R 'efc1f9'
5 96 0 0.007498 945192 filemtime 0 /var/www/html/uploads/manager3.php 459 1 '/var/www/html/uploads'
5 96 1 0.007513 945224
5 96 R 1676251970
4 93 1 0.007528 945200
4 93 R '170426.efc1f9.1676251970'
4 97 0 0.007542 945200 get_folders_cache_path 1 /var/www/html/uploads/manager3.php 456 1 '170426.efc1f9.1676251970'
4 97 1 0.007557 945312
4 97 R '/var/www/html/uploads/_files/cache/folders/170426.efc1f9.1676251970.json'
3 92 1 0.007575 945256
3 92 R '/var/www/html/uploads/_files/cache/folders/170426.efc1f9.1676251970.json'
2 A /var/www/html/uploads/manager3.php 1769 $cache = '/var/www/html/uploads/_files/cache/folders/170426.efc1f9.1676251970.json'
3 98 0 0.007605 945208 file_exists 0 /var/www/html/uploads/manager3.php 1770 1 '/var/www/html/uploads/_files/cache/folders/170426.efc1f9.1676251970.json'
3 98 1 0.007635 945248
3 98 R FALSE
3 99 0 0.007650 945208 get_dir 1 /var/www/html/uploads/manager3.php 1771 3 '/var/www/html/uploads' ??? ???
4 100 0 0.007664 945208 real_path 1 /var/www/html/uploads/manager3.php 773 1 '/var/www/html/uploads'
5 101 0 0.007691 945208 realpath 0 /var/www/html/uploads/manager3.php 429 1 '/var/www/html/uploads'
5 101 1 0.007706 945288
5 101 R '/var/www/html/uploads'
4 A /var/www/html/uploads/manager3.php 429 $real_path = '/var/www/html/uploads'
5 102 0 0.007732 945256 str_replace 0 /var/www/html/uploads/manager3.php 430 3 '\\' '/' '/var/www/html/uploads'
5 102 1 0.007765 945352
5 102 R '/var/www/html/uploads'
4 100 1 0.007780 945256
4 100 R '/var/www/html/uploads'
3 A /var/www/html/uploads/manager3.php 773 $realpath = '/var/www/html/uploads'
3 A /var/www/html/uploads/manager3.php 775 $symlinked = FALSE
4 103 0 0.007818 945256 is_exclude 1 /var/www/html/uploads/manager3.php 778 3 '/var/www/html/uploads' TRUE FALSE
4 103 1 0.007832 945256
4 103 R NULL
4 104 0 0.007846 945256 filemtime 0 /var/www/html/uploads/manager3.php 782 1 '/var/www/html/uploads'
4 104 1 0.007859 945296
4 104 R 1676251970
3 A /var/www/html/uploads/manager3.php 782 $filemtime = 1676251970
4 105 0 0.007883 945256 get_url_path 1 /var/www/html/uploads/manager3.php 783 1 '/var/www/html/uploads'
5 106 0 0.007897 945256 is_within_docroot 1 /var/www/html/uploads/manager3.php 760 1 '/var/www/html/uploads'
6 107 0 0.007910 945256 is_within_path 1 /var/www/html/uploads/manager3.php 445 2 '/var/www/html/uploads' '/var/www/html'
7 108 0 0.007924 945344 strpos 0 /var/www/html/uploads/manager3.php 439 2 '/var/www/html/uploads/' '/var/www/html/'
7 108 1 0.007938 945416
7 108 R 0
6 107 1 0.007952 945256
6 107 R TRUE
5 106 1 0.007965 945256
5 106 R TRUE
5 109 0 0.007977 945256 is_within_path 1 /var/www/html/uploads/manager3.php 763 2 '/var/www/html/uploads' '/var/www/html/uploads'
6 110 0 0.007991 945352 strpos 0 /var/www/html/uploads/manager3.php 439 2 '/var/www/html/uploads/' '/var/www/html/uploads/'
6 110 1 0.008004 945424
6 110 R 0
5 109 1 0.008017 945256
5 109 R TRUE
4 105 1 0.008031 945256
4 105 R '.'
3 A /var/www/html/uploads/manager3.php 783 $url_path = '.'
4 111 0 0.008055 945256 is_readable 0 /var/www/html/uploads/manager3.php 784 1 '/var/www/html/uploads'
4 111 1 0.008071 945296
4 111 R TRUE
3 A /var/www/html/uploads/manager3.php 784 $is_readable = TRUE
4 112 0 0.008095 945256 basename 0 /var/www/html/uploads/manager3.php 788 1 '/var/www/html/uploads'
4 112 1 0.008111 945320
4 112 R 'uploads'
4 113 0 0.008126 945984 fileperms 0 /var/www/html/uploads/manager3.php 789 1 '/var/www/html/uploads'
4 113 1 0.008139 946024
4 113 R 16895
4 114 0 0.008152 945984 sprintf 0 /var/www/html/uploads/manager3.php 789 2 '%o' 16895
4 114 1 0.008167 946368
4 114 R '40777'
4 115 0 0.008179 946304 substr 0 /var/www/html/uploads/manager3.php 789 2 '40777' -4
4 115 1 0.008197 946400
4 115 R '0777'
4 116 0 0.008211 946016 is_writeable 0 /var/www/html/uploads/manager3.php 792 1 '/var/www/html/uploads'
4 116 1 0.008227 946056
4 116 R TRUE
4 117 0 0.008241 946016 root_relative 1 /var/www/html/uploads/manager3.php 797 1 '/var/www/html/uploads'
5 118 0 0.008256 946016 substr 0 /var/www/html/uploads/manager3.php 433 2 '/var/www/html/uploads' 21
5 118 1 0.008269 946080
5 118 R ''
5 119 0 0.008281 946016 ltrim 0 /var/www/html/uploads/manager3.php 433 2 '' '\\/'
5 119 1 0.008295 946088
5 119 R ''
4 117 1 0.008307 946016
4 117 R ''
3 A /var/www/html/uploads/manager3.php 797 $arr = ['basename' => 'uploads', 'fileperms' => '0777', 'filetype' => 'dir', 'is_readable' => TRUE, 'is_writeable' => TRUE, 'is_link' => FALSE, 'is_dir' => TRUE, 'mime' => 'directory', 'mtime' => 1676251970, 'path' => '']
3 A /var/www/html/uploads/manager3.php 801 $arr['url_path'] = '.'
3 99 1 0.008357 945968
3 99 R ['basename' => 'uploads', 'fileperms' => '0777', 'filetype' => 'dir', 'is_readable' => TRUE, 'is_writeable' => TRUE, 'is_link' => FALSE, 'is_dir' => TRUE, 'mime' => 'directory', 'mtime' => 1676251970, 'path' => '', 'url_path' => '.']
2 88 1 0.008385 945856
2 88 R ['basename' => 'uploads', 'fileperms' => '0777', 'filetype' => 'dir', 'is_readable' => TRUE, 'is_writeable' => TRUE, 'is_link' => FALSE, 'is_dir' => TRUE, 'mime' => 'directory', 'mtime' => 1676251970, 'path' => '', 'url_path' => '.']
1 A /var/www/html/uploads/manager3.php 1775 $dirs = ['' => ['basename' => 'uploads', 'fileperms' => '0777', 'filetype' => 'dir', 'is_readable' => TRUE, 'is_writeable' => TRUE, 'is_link' => FALSE, 'is_dir' => TRUE, 'mime' => 'directory', 'mtime' => 1676251970, 'path' => '', 'url_path' => '.']]
1 A /var/www/html/uploads/manager3.php 1783 $resize_image_types = [0 => 'jpeg', 1 => 'jpg', 2 => 'png', 3 => 'gif']
2 120 0 0.008452 946232 version_compare 0 /var/www/html/uploads/manager3.php 1784 2 '7.2.34-37+ubuntu22.04.1+deb.sury.org+1' '5.4.0'
2 120 1 0.008469 946296
2 120 R 1
1 A /var/www/html/uploads/manager3.php 1785 $resize_image_types[] = 'webp'
2 121 0 0.008494 946608 version_compare 0 /var/www/html/uploads/manager3.php 1786 2 '7.2.34-37+ubuntu22.04.1+deb.sury.org+1' '7.2.0'
2 121 1 0.008510 946672
2 121 R 1
1 A /var/www/html/uploads/manager3.php 1786 $resize_image_types[] = 'bmp'
2 122 0 0.008535 946608 function_exists 0 /var/www/html/uploads/manager3.php 1790 1 'ini_get'
2 122 1 0.008550 946648
2 122 R TRUE
2 123 0 0.008563 946608 ini_get 0 /var/www/html/uploads/manager3.php 1790 1 'memory_limit'
2 123 1 0.008578 946672
2 123 R '128M'
1 A /var/www/html/uploads/manager3.php 1790 $image_resize_memory_limit = 128
2 124 0 0.008604 946608 function_exists 0 /var/www/html/uploads/manager3.php 1791 1 'ini_set'
2 124 1 0.008618 946648
2 124 R TRUE
2 125 0 0.008632 946608 max 0 /var/www/html/uploads/manager3.php 1791 2 128 128
2 125 1 0.008646 946640
2 125 R 128
1 A /var/www/html/uploads/manager3.php 1791 $image_resize_memory_limit = 128
2 126 0 0.008670 946608 base64_decode 0 /var/www/html/uploads/manager3.php 1794 1 'bGljZW5zZV9rZXk'
2 126 1 0.008685 946680
2 126 R 'license_key'
1 A /var/www/html/uploads/manager3.php 1794 $wtc = ''
2 127 0 0.008711 946608 array_flip 0 /var/www/html/uploads/manager3.php 1811 1 [0 => 'root', 1 => 'start_path', 2 => 'image_resize_cache', 3 => 'image_resize_quality', 4 => 'image_resize_function', 5 => 'image_resize_cache_direct', 6 => 'menu_sort', 7 => 'menu_load_all', 8 => 'cache_key', 9 => 'storage_path', 10 => 'files_exclude', 11 => 'dirs_exclude', 12 => 'username', 13 => 'password', 14 => 'breadcrumbs', 15 => 'allow_tasks', 16 => 'allow_symlinks', 17 => 'menu_recursive_symlinks', 18 => 'image_resize_sharpen', 19 => 'get_mime_type', 20 => 'license_key', 21 => 'video_thumbs', 22 => 'video_ffmpeg_path', 23 => 'folder_preview_default', 24 => 'image_resize_dimensions_allowed', 25 => 'download_dir_cache']
2 127 1 0.008748 947976
2 127 R ['root' => 0, 'start_path' => 1, 'image_resize_cache' => 2, 'image_resize_quality' => 3, 'image_resize_function' => 4, 'image_resize_cache_direct' => 5, 'menu_sort' => 6, 'menu_load_all' => 7, 'cache_key' => 8, 'storage_path' => 9, 'files_exclude' => 10, 'dirs_exclude' => 11, 'username' => 12, 'password' => 13, 'breadcrumbs' => 14, 'allow_tasks' => 15, 'allow_symlinks' => 16, 'menu_recursive_symlinks' => 17, 'image_resize_sharpen' => 18, 'get_mime_type' => 19, 'license_key' => 20, 'video_thumbs' => 21, 'video_ffmpeg_path' => 22, 'folder_preview_default' => 23, 'image_resize_dimensions_allowed' => 24, 'download_dir_cache' => 25]
2 128 0 0.008788 947944 array_diff_key 0 /var/www/html/uploads/manager3.php 1811 2 ['root' => '', 'start_path' => FALSE, 'username' => '', 'password' => '', 'load_images' => TRUE, 'load_files_proxy_php' => FALSE, 'load_images_max_filesize' => 1000000, 'load_svg_max_filesize' => 100000, 'image_resize_enabled' => TRUE, 'image_resize_cache' => TRUE, 'image_resize_dimensions' => 320, 'image_resize_dimensions_retina' => 480, 'image_resize_dimensions_allowed' => '', 'image_resize_types' => 'jpeg, png, gif, webp, bmp', 'image_resize_quality' => 85, 'image_resize_function' => 'imagecopyresampled', 'image_resize_sharpen' => TRUE, 'image_resize_memory_limit' => 128, 'image_resize_max_pixels' => 30000000, 'image_resize_min_ratio' => 1.5, 'image_resize_cache_direct' => FALSE, 'folder_preview_image' => TRUE, 'folder_preview_default' => '_filespreview.jpg', 'menu_enabled' => TRUE, 'menu_show' => TRUE, 'menu_max_depth' => 5, 'menu_sort' => 'name_asc', 'menu_cache_validate' => TRUE, 'menu_load_all' => FALSE, 'menu_recursive_symlinks' => TRUE, 'layout' => 'rows', 'sort' => 'name_asc', 'sort_dirs_first' => TRUE, 'cache' => TRUE, 'cache_key' => 0, 'storage_path' => '_files', 'files_exclude' => '', 'dirs_exclude' => '', 'allow_symlinks' => TRUE, 'history' => TRUE, 'breadcrumbs' => TRUE, 'transitions' => TRUE, 'click' => 'popup', 'click_window' => '', 'click_window_popup' => TRUE, 'code_max_load' => 100000, 'topbar_sticky' => 'scroll', 'check_updates' => FALSE, 'allow_tasks' => FALSE, 'get_mime_type' => FALSE, 'context_menu' => TRUE, 'prevent_right_click' => FALSE, 'license_key' => '', 'filter_live' => TRUE, 'filter_props' => 'name, filetype, mime, features, title', 'download_dir' => 'zip', 'download_dir_cache' => 'dir', 'allow_upload' => FALSE, 'allow_delete' => FALSE, 'allow_rename' => FALSE, 'allow_new_folder' => FALSE, 'allow_new_file' => FALSE, 'allow_duplicate' => FALSE, 'allow_text_edit' => FALSE, 'demo_mode' => FALSE, 'upload_allowed_file_types' => '', 'upload_max_filesize' => 0, 'upload_note' => '', 'upload_exists' => 'increment', 'popup_video' => TRUE, 'popup_transition' => 'glide', 'popup_transition_play' => 'inherit', 'popup_interval' => 5000, 'popup_caption' => TRUE, 'popup_caption_hide' => TRUE, 'popup_caption_style' => 'block', 'popup_caption_align' => 'center-left', 'video_thumbs' => TRUE, 'video_ffmpeg_path' => 'ffmpeg', 'video_autoplay' => TRUE, 'lang_default' => 'en', 'lang_auto' => TRUE, 'lang_menu' => FALSE] ['root' => 0, 'start_path' => 1, 'image_resize_cache' => 2, 'image_resize_quality' => 3, 'image_resize_function' => 4, 'image_resize_cache_direct' => 5, 'menu_sort' => 6, 'menu_load_all' => 7, 'cache_key' => 8, 'storage_path' => 9, 'files_exclude' => 10, 'dirs_exclude' => 11, 'username' => 12, 'password' => 13, 'breadcrumbs' => 14, 'allow_tasks' => 15, 'allow_symlinks' => 16, 'menu_recursive_symlinks' => 17, 'image_resize_sharpen' => 18, 'get_mime_type' => 19, 'license_key' => 20, 'video_thumbs' => 21, 'video_ffmpeg_path' => 22, 'folder_preview_default' => 23, 'image_resize_dimensions_allowed' => 24, 'download_dir_cache' => 25]
2 128 1 0.008908 950624
2 128 R ['load_images' => TRUE, 'load_files_proxy_php' => FALSE, 'load_images_max_filesize' => 1000000, 'load_svg_max_filesize' => 100000, 'image_resize_enabled' => TRUE, 'image_resize_dimensions' => 320, 'image_resize_dimensions_retina' => 480, 'image_resize_types' => 'jpeg, png, gif, webp, bmp', 'image_resize_memory_limit' => 128, 'image_resize_max_pixels' => 30000000, 'image_resize_min_ratio' => 1.5, 'folder_preview_image' => TRUE, 'menu_enabled' => TRUE, 'menu_show' => TRUE, 'menu_max_depth' => 5, 'menu_cache_validate' => TRUE, 'layout' => 'rows', 'sort' => 'name_asc', 'sort_dirs_first' => TRUE, 'cache' => TRUE, 'history' => TRUE, 'transitions' => TRUE, 'click' => 'popup', 'click_window' => '', 'click_window_popup' => TRUE, 'code_max_load' => 100000, 'topbar_sticky' => 'scroll', 'check_updates' => FALSE, 'context_menu' => TRUE, 'prevent_right_click' => FALSE, 'filter_live' => TRUE, 'filter_props' => 'name, filetype, mime, features, title', 'download_dir' => 'zip', 'allow_upload' => FALSE, 'allow_delete' => FALSE, 'allow_rename' => FALSE, 'allow_new_folder' => FALSE, 'allow_new_file' => FALSE, 'allow_duplicate' => FALSE, 'allow_text_edit' => FALSE, 'demo_mode' => FALSE, 'upload_allowed_file_types' => '', 'upload_max_filesize' => 0, 'upload_note' => '', 'upload_exists' => 'increment', 'popup_video' => TRUE, 'popup_transition' => 'glide', 'popup_transition_play' => 'inherit', 'popup_interval' => 5000, 'popup_caption' => TRUE, 'popup_caption_hide' => TRUE, 'popup_caption_style' => 'block', 'popup_caption_align' => 'center-left', 'video_autoplay' => TRUE, 'lang_default' => 'en', 'lang_auto' => TRUE, 'lang_menu' => FALSE]
1 A /var/www/html/uploads/manager3.php 1811 $exclude = ['load_images' => TRUE, 'load_files_proxy_php' => FALSE, 'load_images_max_filesize' => 1000000, 'load_svg_max_filesize' => 100000, 'image_resize_enabled' => TRUE, 'image_resize_dimensions' => 320, 'image_resize_dimensions_retina' => 480, 'image_resize_types' => 'jpeg, png, gif, webp, bmp', 'image_resize_memory_limit' => 128, 'image_resize_max_pixels' => 30000000, 'image_resize_min_ratio' => 1.5, 'folder_preview_image' => TRUE, 'menu_enabled' => TRUE, 'menu_show' => TRUE, 'menu_max_depth' => 5, 'menu_cache_validate' => TRUE, 'layout' => 'rows', 'sort' => 'name_asc', 'sort_dirs_first' => TRUE, 'cache' => TRUE, 'history' => TRUE, 'transitions' => TRUE, 'click' => 'popup', 'click_window' => '', 'click_window_popup' => TRUE, 'code_max_load' => 100000, 'topbar_sticky' => 'scroll', 'check_updates' => FALSE, 'context_menu' => TRUE, 'prevent_right_click' => FALSE, 'filter_live' => TRUE, 'filter_props' => 'name, filetype, mime, features, title', 'download_dir' => 'zip', 'allow_upload' => FALSE, 'allow_delete' => FALSE, 'allow_rename' => FALSE, 'allow_new_folder' => FALSE, 'allow_new_file' => FALSE, 'allow_duplicate' => FALSE, 'allow_text_edit' => FALSE, 'demo_mode' => FALSE, 'upload_allowed_file_types' => '', 'upload_max_filesize' => 0, 'upload_note' => '', 'upload_exists' => 'increment', 'popup_video' => TRUE, 'popup_transition' => 'glide', 'popup_transition_play' => 'inherit', 'popup_interval' => 5000, 'popup_caption' => TRUE, 'popup_caption_hide' => TRUE, 'popup_caption_style' => 'block', 'popup_caption_align' => 'center-left', 'video_autoplay' => TRUE, 'lang_default' => 'en', 'lang_auto' => TRUE, 'lang_menu' => FALSE]
2 129 0 0.009042 950560 basename 0 /var/www/html/uploads/manager3.php 1816 1 '/var/www/html/uploads/manager3.php'
2 129 1 0.009058 950632
2 129 R 'manager3.php'
2 130 0 0.009075 950680 md5 0 /var/www/html/uploads/manager3.php 1826 1 '/var/www/html/var/www/html/uploadsimagecopyresampled85'
2 130 1 0.009090 950776
2 130 R 'f53b3cea7b4c2970384c976d83e7dbd0'
2 131 0 0.009105 950664 substr 0 /var/www/html/uploads/manager3.php 1826 3 'f53b3cea7b4c2970384c976d83e7dbd0' 0 6
2 131 1 0.009120 950792
2 131 R 'f53b3c'
2 132 0 0.009134 950632 md5 0 /var/www/html/uploads/manager3.php 1828 1 '/var/www/html/uploads'
2 132 1 0.009147 950728
2 132 R 'efc1f9341a6f3e19acc38a2871eef237'
2 133 0 0.009163 950696 get 1 /var/www/html/uploads/manager3.php 1831 1 'index_html'
2 133 1 0.009177 950696
2 133 R FALSE
2 134 0 0.009190 950696 function_exists 0 /var/www/html/uploads/manager3.php 1832 1 'exif_read_data'
2 134 1 0.009204 950736
2 134 R TRUE
2 135 0 0.009219 950696 function_exists 0 /var/www/html/uploads/manager3.php 1835 1 'exec'
2 135 1 0.009233 950736
2 135 R TRUE
2 136 0 0.009246 950736 exec 0 /var/www/html/uploads/manager3.php 1835 1 'type -P ffmpeg'
2 136 1 0.009969 950816
2 136 R 'ffmpeg: not found'
2 137 0 0.010000 950696 lang_custom 1 /var/www/html/uploads/manager3.php 1836 0
2 A /var/www/html/uploads/manager3.php 1798 $dir = '/var/www/html/uploads/_files/lang'
3 138 0 0.010030 950760 file_exists 0 /var/www/html/uploads/manager3.php 1799 1 '/var/www/html/uploads/_files/lang'
3 138 1 0.010055 950800
3 138 R FALSE
2 A /var/www/html/uploads/manager3.php 1799 $files = FALSE
2 137 1 0.010082 950696
2 137 R FALSE
2 139 0 0.010096 950696 array_replace 0 /var/www/html/uploads/manager3.php 1815 2 ['load_images' => TRUE, 'load_files_proxy_php' => FALSE, 'load_images_max_filesize' => 1000000, 'load_svg_max_filesize' => 100000, 'image_resize_enabled' => TRUE, 'image_resize_dimensions' => 320, 'image_resize_dimensions_retina' => 480, 'image_resize_types' => 'jpeg, png, gif, webp, bmp', 'image_resize_memory_limit' => 128, 'image_resize_max_pixels' => 30000000, 'image_resize_min_ratio' => 1.5, 'folder_preview_image' => TRUE, 'menu_enabled' => TRUE, 'menu_show' => TRUE, 'menu_max_depth' => 5, 'menu_cache_validate' => TRUE, 'layout' => 'rows', 'sort' => 'name_asc', 'sort_dirs_first' => TRUE, 'cache' => TRUE, 'history' => TRUE, 'transitions' => TRUE, 'click' => 'popup', 'click_window' => '', 'click_window_popup' => TRUE, 'code_max_load' => 100000, 'topbar_sticky' => 'scroll', 'check_updates' => FALSE, 'context_menu' => TRUE, 'prevent_right_click' => FALSE, 'filter_live' => TRUE, 'filter_props' => 'name, filetype, mime, features, title', 'download_dir' => 'zip', 'allow_upload' => FALSE, 'allow_delete' => FALSE, 'allow_rename' => FALSE, 'allow_new_folder' => FALSE, 'allow_new_file' => FALSE, 'allow_duplicate' => FALSE, 'allow_text_edit' => FALSE, 'demo_mode' => FALSE, 'upload_allowed_file_types' => '', 'upload_max_filesize' => 0, 'upload_note' => '', 'upload_exists' => 'increment', 'popup_video' => TRUE, 'popup_transition' => 'glide', 'popup_transition_play' => 'inherit', 'popup_interval' => 5000, 'popup_caption' => TRUE, 'popup_caption_hide' => TRUE, 'popup_caption_style' => 'block', 'popup_caption_align' => 'center-left', 'video_autoplay' => TRUE, 'lang_default' => 'en', 'lang_auto' => TRUE, 'lang_menu' => FALSE] ['breadcrumbs' => TRUE, 'script' => 'manager3.php', 'menu_enabled' => TRUE, 'menu_cache_hash' => '356888.295aa7.3352503940', 'menu_cache_file' => FALSE, 'query_path' => FALSE, 'query_path_valid' => FALSE, 'init_path' => '', 'dirs' => ['' => [...]], 'dirs_hash' => '170426', 'resize_image_types' => [0 => 'jpeg', 1 => 'jpg', 2 => 'png', 3 => 'gif', 4 => 'webp', 5 => 'bmp'], 'image_cache_hash' => 'f53b3c', 'image_resize_dimensions_retina' => 480, 'location_hash' => 'efc1f9341a6f3e19acc38a2871eef237', 'has_login' => FALSE, 'version' => '0.3.1', 'index_html' => 0, 'server_exif' => TRUE, 'image_resize_memory_limit' => 128, 'qrx' => FALSE, 'video_thumbs_enabled' => TRUE, 'lang_custom' => FALSE, 'x3_path' => FALSE]
2 139 1 0.010199 959008
2 139 R ['load_images' => TRUE, 'load_files_proxy_php' => FALSE, 'load_images_max_filesize' => 1000000, 'load_svg_max_filesize' => 100000, 'image_resize_enabled' => TRUE, 'image_resize_dimensions' => 320, 'image_resize_dimensions_retina' => 480, 'image_resize_types' => 'jpeg, png, gif, webp, bmp', 'image_resize_memory_limit' => 128, 'image_resize_max_pixels' => 30000000, 'image_resize_min_ratio' => 1.5, 'folder_preview_image' => TRUE, 'menu_enabled' => TRUE, 'menu_show' => TRUE, 'menu_max_depth' => 5, 'menu_cache_validate' => TRUE, 'layout' => 'rows', 'sort' => 'name_asc', 'sort_dirs_first' => TRUE, 'cache' => TRUE, 'history' => TRUE, 'transitions' => TRUE, 'click' => 'popup', 'click_window' => '', 'click_window_popup' => TRUE, 'code_max_load' => 100000, 'topbar_sticky' => 'scroll', 'check_updates' => FALSE, 'context_menu' => TRUE, 'prevent_right_click' => FALSE, 'filter_live' => TRUE, 'filter_props' => 'name, filetype, mime, features, title', 'download_dir' => 'zip', 'allow_upload' => FALSE, 'allow_delete' => FALSE, 'allow_rename' => FALSE, 'allow_new_folder' => FALSE, 'allow_new_file' => FALSE, 'allow_duplicate' => FALSE, 'allow_text_edit' => FALSE, 'demo_mode' => FALSE, 'upload_allowed_file_types' => '', 'upload_max_filesize' => 0, 'upload_note' => '', 'upload_exists' => 'increment', 'popup_video' => TRUE, 'popup_transition' => 'glide', 'popup_transition_play' => 'inherit', 'popup_interval' => 5000, 'popup_caption' => TRUE, 'popup_caption_hide' => TRUE, 'popup_caption_style' => 'block', 'popup_caption_align' => 'center-left', 'video_autoplay' => TRUE, 'lang_default' => 'en', 'lang_auto' => TRUE, 'lang_menu' => FALSE, 'breadcrumbs' => TRUE, 'script' => 'manager3.php', 'menu_cache_hash' => '356888.295aa7.3352503940', 'menu_cache_file' => FALSE, 'query_path' => FALSE, 'query_path_valid' => FALSE, 'init_path' => '', 'dirs' => ['' => [...]], 'dirs_hash' => '170426', 'resize_image_types' => [0 => 'jpeg', 1 => 'jpg', 2 => 'png', 3 => 'gif', 4 => 'webp', 5 => 'bmp'], 'image_cache_hash' => 'f53b3c', 'location_hash' => 'efc1f9341a6f3e19acc38a2871eef237', 'has_login' => FALSE, 'version' => '0.3.1', 'index_html' => 0, 'server_exif' => TRUE, 'qrx' => FALSE, 'video_thumbs_enabled' => TRUE, 'lang_custom' => FALSE, 'x3_path' => FALSE]
1 A /var/www/html/uploads/manager3.php 1815 $json_config = ['load_images' => TRUE, 'load_files_proxy_php' => FALSE, 'load_images_max_filesize' => 1000000, 'load_svg_max_filesize' => 100000, 'image_resize_enabled' => TRUE, 'image_resize_dimensions' => 320, 'image_resize_dimensions_retina' => 480, 'image_resize_types' => 'jpeg, png, gif, webp, bmp', 'image_resize_memory_limit' => 128, 'image_resize_max_pixels' => 30000000, 'image_resize_min_ratio' => 1.5, 'folder_preview_image' => TRUE, 'menu_enabled' => TRUE, 'menu_show' => TRUE, 'menu_max_depth' => 5, 'menu_cache_validate' => TRUE, 'layout' => 'rows', 'sort' => 'name_asc', 'sort_dirs_first' => TRUE, 'cache' => TRUE, 'history' => TRUE, 'transitions' => TRUE, 'click' => 'popup', 'click_window' => '', 'click_window_popup' => TRUE, 'code_max_load' => 100000, 'topbar_sticky' => 'scroll', 'check_updates' => FALSE, 'context_menu' => TRUE, 'prevent_right_click' => FALSE, 'filter_live' => TRUE, 'filter_props' => 'name, filetype, mime, features, title', 'download_dir' => 'zip', 'allow_upload' => FALSE, 'allow_delete' => FALSE, 'allow_rename' => FALSE, 'allow_new_folder' => FALSE, 'allow_new_file' => FALSE, 'allow_duplicate' => FALSE, 'allow_text_edit' => FALSE, 'demo_mode' => FALSE, 'upload_allowed_file_types' => '', 'upload_max_filesize' => 0, 'upload_note' => '', 'upload_exists' => 'increment', 'popup_video' => TRUE, 'popup_transition' => 'glide', 'popup_transition_play' => 'inherit', 'popup_interval' => 5000, 'popup_caption' => TRUE, 'popup_caption_hide' => TRUE, 'popup_caption_style' => 'block', 'popup_caption_align' => 'center-left', 'video_autoplay' => TRUE, 'lang_default' => 'en', 'lang_auto' => TRUE, 'lang_menu' => FALSE, 'breadcrumbs' => TRUE, 'script' => 'manager3.php', 'menu_cache_hash' => '356888.295aa7.3352503940', 'menu_cache_file' => FALSE, 'query_path' => FALSE, 'query_path_valid' => FALSE, 'init_path' => '', 'dirs' => ['' => [...]], 'dirs_hash' => '170426', 'resize_image_types' => [0 => 'jpeg', 1 => 'jpg', 2 => 'png', 3 => 'gif', 4 => 'webp', 5 => 'bmp'], 'image_cache_hash' => 'f53b3c', 'location_hash' => 'efc1f9341a6f3e19acc38a2871eef237', 'has_login' => FALSE, 'version' => '0.3.1', 'index_html' => 0, 'server_exif' => TRUE, 'qrx' => FALSE, 'video_thumbs_enabled' => TRUE, 'lang_custom' => FALSE, 'x3_path' => FALSE]
2 140 0 0.010378 957608 header_memory_time 1 /var/www/html/uploads/manager3.php 1866 0
3 141 0 0.010392 957608 microtime 0 /var/www/html/uploads/manager3.php 463 1 TRUE
3 141 1 0.010406 957648
3 141 R 1676251970.6806
3 142 0 0.010422 957608 round 0 /var/www/html/uploads/manager3.php 463 2 0.010602951049805 3
3 142 1 0.010436 957680
3 142 R 0.011
3 143 0 0.010451 957648 memory_get_peak_usage 0 /var/www/html/uploads/manager3.php 463 0
3 143 1 0.010464 957648
3 143 R 1511312
3 144 0 0.010478 957648 round 0 /var/www/html/uploads/manager3.php 463 2 1.4412994384766 1
3 144 1 0.010491 957720
3 144 R 1.4
2 140 1 0.010504 957648
2 140 R '0.011s, 1.4M'
2 145 0 0.010519 957664 header 0 /var/www/html/uploads/manager3.php 1866 1 'files-msg: [0.011s, 1.4M]'
2 145 1 0.010537 957768
2 145 R NULL
2 146 0 0.010565 957680 get_include 1 /var/www/html/uploads/manager3.php 1877 1 'include/head.html'
2 A /var/www/html/uploads/manager3.php 1278 $path = '/var/www/html/uploads/_files/include/head.html'
3 147 0 0.010593 957760 file_exists 0 /var/www/html/uploads/manager3.php 1279 1 '/var/www/html/uploads/_files/include/head.html'
3 147 1 0.010612 957800
3 147 R FALSE
2 146 1 0.010626 957680
2 148 0 0.010634 957680 get_include 1 /var/www/html/uploads/manager3.php 1879 1 'css/custom.css'
2 A /var/www/html/uploads/manager3.php 1278 $path = '/var/www/html/uploads/_files/css/custom.css'
3 149 0 0.010660 957760 file_exists 0 /var/www/html/uploads/manager3.php 1279 1 '/var/www/html/uploads/_files/css/custom.css'
3 149 1 0.010678 957800
3 149 R FALSE
2 148 1 0.010692 957680
1 A /var/www/html/uploads/manager3.php 1885 $topbar_classes = []
2 150 0 0.010711 957704 array_push 0 /var/www/html/uploads/manager3.php 1886 2 [] 'topbar-sticky'
2 150 1 0.010726 958144
2 150 R 1
2 151 0 0.010739 958080 array_push 0 /var/www/html/uploads/manager3.php 1887 2 [0 => 'topbar-sticky'] 'has-breadcrumbs'
2 151 1 0.010759 958144
2 151 R 2
2 152 0 0.010773 958080 join 0 /var/www/html/uploads/manager3.php 1889 2 ' ' [0 => 'topbar-sticky', 1 => 'has-breadcrumbs']
2 152 1 0.010790 958208
2 152 R 'topbar-sticky has-breadcrumbs'
2 153 0 0.010807 958080 get_include 1 /var/www/html/uploads/manager3.php 1926 1 'include/footer.html'
2 A /var/www/html/uploads/manager3.php 1278 $path = '/var/www/html/uploads/_files/include/footer.html'
3 154 0 0.010834 958160 file_exists 0 /var/www/html/uploads/manager3.php 1279 1 '/var/www/html/uploads/_files/include/footer.html'
3 154 1 0.010850 958200
3 154 R FALSE
2 153 1 0.010864 958080
2 155 0 0.010872 958080 json_encode 0 /var/www/html/uploads/manager3.php 1944 2 ['load_images' => TRUE, 'load_files_proxy_php' => FALSE, 'load_images_max_filesize' => 1000000, 'load_svg_max_filesize' => 100000, 'image_resize_enabled' => TRUE, 'image_resize_dimensions' => 320, 'image_resize_dimensions_retina' => 480, 'image_resize_types' => 'jpeg, png, gif, webp, bmp', 'image_resize_memory_limit' => 128, 'image_resize_max_pixels' => 30000000, 'image_resize_min_ratio' => 1.5, 'folder_preview_image' => TRUE, 'menu_enabled' => TRUE, 'menu_show' => TRUE, 'menu_max_depth' => 5, 'menu_cache_validate' => TRUE, 'layout' => 'rows', 'sort' => 'name_asc', 'sort_dirs_first' => TRUE, 'cache' => TRUE, 'history' => TRUE, 'transitions' => TRUE, 'click' => 'popup', 'click_window' => '', 'click_window_popup' => TRUE, 'code_max_load' => 100000, 'topbar_sticky' => 'scroll', 'check_updates' => FALSE, 'context_menu' => TRUE, 'prevent_right_click' => FALSE, 'filter_live' => TRUE, 'filter_props' => 'name, filetype, mime, features, title', 'download_dir' => 'zip', 'allow_upload' => FALSE, 'allow_delete' => FALSE, 'allow_rename' => FALSE, 'allow_new_folder' => FALSE, 'allow_new_file' => FALSE, 'allow_duplicate' => FALSE, 'allow_text_edit' => FALSE, 'demo_mode' => FALSE, 'upload_allowed_file_types' => '', 'upload_max_filesize' => 0, 'upload_note' => '', 'upload_exists' => 'increment', 'popup_video' => TRUE, 'popup_transition' => 'glide', 'popup_transition_play' => 'inherit', 'popup_interval' => 5000, 'popup_caption' => TRUE, 'popup_caption_hide' => TRUE, 'popup_caption_style' => 'block', 'popup_caption_align' => 'center-left', 'video_autoplay' => TRUE, 'lang_default' => 'en', 'lang_auto' => TRUE, 'lang_menu' => FALSE, 'breadcrumbs' => TRUE, 'script' => 'manager3.php', 'menu_cache_hash' => '356888.295aa7.3352503940', 'menu_cache_file' => FALSE, 'query_path' => FALSE, 'query_path_valid' => FALSE, 'init_path' => '', 'dirs' => ['' => [...]], 'dirs_hash' => '170426', 'resize_image_types' => [0 => 'jpeg', 1 => 'jpg', 2 => 'png', 3 => 'gif', 4 => 'webp', 5 => 'bmp'], 'image_cache_hash' => 'f53b3c', 'location_hash' => 'efc1f9341a6f3e19acc38a2871eef237', 'has_login' => FALSE, 'version' => '0.3.1', 'index_html' => 0, 'server_exif' => TRUE, 'qrx' => FALSE, 'video_thumbs_enabled' => TRUE, 'lang_custom' => FALSE, 'x3_path' => FALSE] 896
2 155 1 0.010971 962240
2 155 R '{\n "load_images": true,\n "load_files_proxy_php": false,\n "load_images_max_filesize": 1000000,\n "load_svg_max_filesize": 100000,\n "image_resize_enabled": true,\n "image_resize_dimensions": 320,\n "image_resize_dimensions_retina": 480,\n "image_resize_types": "jpeg, png, gif, webp, bmp",\n "image_resize_memory_limit": 128,\n "image_resize_max_pixels": 30000000,\n "image_resize_min_ratio": 1.5,\n "folder_preview_image": true,\n "menu_enabled": true,\n "menu_show":'
2 156 0 0.011011 958192 get_include 1 /var/www/html/uploads/manager3.php 1949 1 'js/custom.js'
2 A /var/www/html/uploads/manager3.php 1278 $path = '/var/www/html/uploads/_files/js/custom.js'
3 157 0 0.011037 958272 file_exists 0 /var/www/html/uploads/manager3.php 1279 1 '/var/www/html/uploads/_files/js/custom.js'
3 157 1 0.011057 958312
3 157 R FALSE
2 156 1 0.011072 958192
1 3 1 0.011083 958192
0.011137 708192
TRACE END [2023-02-12 23:33:16.579116]
<html class="menu-disabled sidebar-closed has-scrollbars"><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="noindex,nofollow">
<title>html</title>
<link href="https://cdn.jsdelivr.net/npm/files.photo.gallery@0.3.1/css/files.css" rel="stylesheet">
<script src="https://www.paypal.com/tagmanager/pptm.js?id=localhost&t=xo&v=5.0.352&source=payments_sdk&client_id=ARE4H7QcoXmKKWTfKk-pXAnsIfW1Zox3buwKma_y-mn4RjQZjS8Ghp1-JUxcevnkl5KI0vL-UIJ-uEfU&vault=false" id="xo-pptm" async=""></script></head>
<body class="modal-open" data-current-path="/" style="opacity: 1; overflow: hidden; padding-right: 0px;">
<main id="main">
<nav id="topbar" class="topbar-sticky headroom headroom--top headroom--bottom">
<div id="topbar-top">
<div id="search-container"><input id="search" type="search" placeholder="filter" size="1" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off" title="ctrl-F"><svg viewBox="0 0 24 24" class="svg-icon svg-search"><path class="svg-path-search" d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z"></path></svg></div>
<div id="change-layout" class="dropdown mouse-hover"><button type="button" class="btn-icon btn-topbar"><svg viewBox="0 0 24 24" class="svg-icon svg-layout_rows"><path class="svg-path-layout_rows" d="M3,19H9V12H3V19M10,19H22V12H10V19M3,5V11H22V5H3Z"></path></svg></button><div class="dropdown-menu dropdown-menu-topbar dropdown-menu-center"><h6 class="dropdown-header" data-lang="layout">layout</h6><div><button class="dropdown-item" data-action="list"><svg viewBox="0 0 24 24" class="svg-icon svg-layout_list"><path class="svg-path-layout_list" d="M7,5H21V7H7V5M7,13V11H21V13H7M4,4.5A1.5,1.5 0 0,1 5.5,6A1.5,1.5 0 0,1 4,7.5A1.5,1.5 0 0,1 2.5,6A1.5,1.5 0 0,1 4,4.5M4,10.5A1.5,1.5 0 0,1 5.5,12A1.5,1.5 0 0,1 4,13.5A1.5,1.5 0 0,1 2.5,12A1.5,1.5 0 0,1 4,10.5M7,19V17H21V19H7M4,16.5A1.5,1.5 0 0,1 5.5,18A1.5,1.5 0 0,1 4,19.5A1.5,1.5 0 0,1 2.5,18A1.5,1.5 0 0,1 4,16.5Z"></path></svg><span class="dropdown-text" data-lang="list">list<span></span></span></button><button class="dropdown-item" data-action="imagelist"><svg viewBox="0 0 24 24" class="svg-icon svg-layout_imagelist"><path class="svg-path-layout_imagelist" d="M3,4H7V8H3V4M9,5V7H21V5H9M3,10H7V14H3V10M9,11V13H21V11H9M3,16H7V20H3V16M9,17V19H21V17H9"></path></svg><span class="dropdown-text" data-lang="imagelist">imagelist<span></span></span></button><button class="dropdown-item" data-action="blocks"><svg viewBox="0 0 24 24" class="svg-icon svg-layout_blocks"><path class="svg-path-layout_blocks" d="M2 14H8V20H2M16 8H10V10H16M2 10H8V4H2M10 4V6H22V4M10 20H16V18H10M10 16H22V14H10"></path></svg><span class="dropdown-text" data-lang="blocks">blocks<span></span></span></button><button class="dropdown-item" data-action="grid"><svg viewBox="0 0 24 24" class="svg-icon svg-layout_grid"><path class="svg-path-layout_grid" d="M3,9H7V5H3V9M3,14H7V10H3V14M8,14H12V10H8V14M13,14H17V10H13V14M8,9H12V5H8V9M13,5V9H17V5H13M18,14H22V10H18V14M3,19H7V15H3V19M8,19H12V15H8V19M13,19H17V15H13V19M18,19H22V15H18V19M18,5V9H22V5H18Z"></path></svg><span class="dropdown-text" data-lang="grid">grid<span></span></span></button><button class="dropdown-item active" data-action="rows"><svg viewBox="0 0 24 24" class="svg-icon svg-layout_rows"><path class="svg-path-layout_rows" d="M3,19H9V12H3V19M10,19H22V12H10V19M3,5V11H22V5H3Z"></path></svg><span class="dropdown-text" data-lang="rows">rows<span></span></span></button><button class="dropdown-item" data-action="columns"><svg viewBox="0 0 24 24" class="svg-icon svg-layout_columns"><path class="svg-path-layout_columns" d="M2,5V19H8V5H2M9,5V10H15V5H9M16,5V14H22V5H16M9,11V19H15V11H9M16,15V19H22V15H16Z"></path></svg><span class="dropdown-text" data-lang="columns">columns<span></span></span></button></div><div id="layout-options"><div id="layout-sizer"><label for="layout-sizer-range" class="form-label mb-0"><span data-lang="size">size</span><span data-lang="rows" class="layout-label-type">rows</span></label><input type="range" class="form-range" id="layout-sizer-range" value="200" min="80" max="220" list="layout-size-default" style="--range-default-pos:0.5;"><datalist id="layout-size-default"><option value="150"></option></datalist></div><div id="layout-spacer"><label for="layout-spacer-range" class="form-label mb-0"><span data-lang="space">space</span><span data-lang="rows" class="layout-label-type">rows</span></label><input type="range" class="form-range" id="layout-spacer-range" value="50" min="0" max="100" list="layout-space-default"><datalist id="layout-space-default"><option value="50"></option></datalist></div><div id="cover-toggle" style="display: none;"><div class="form-check"><input class="form-check-input" type="checkbox" id="covertoggle" checked=""><label class="form-check-label" for="covertoggle" data-lang="uniform">uniform</label></div></div><div id="imagelist-square" style="display: none;"><div class="form-check"><input class="form-check-input" type="checkbox" id="imagelistsquare" checked=""><label class="form-check-label" for="imagelistsquare" data-lang="uniform">uniform</label></div></div></div></div></div>
<div id="change-sort" class="dropdown mouse-hover"><button type="button" class="btn-icon btn-topbar"><svg viewBox="0 0 24 24" class="svg-icon svg-sort_name_asc"><path class="svg-path-sort_name_asc" d="M9.25 5L12.5 1.75L15.75 5H9.25M8.89 14.3H6L5.28 17H2.91L6 7H9L12.13 17H9.67L8.89 14.3M6.33 12.68H8.56L7.93 10.56L7.67 9.59L7.42 8.63H7.39L7.17 9.6L6.93 10.58L6.33 12.68M13.05 17V15.74L17.8 8.97V8.91H13.5V7H20.73V8.34L16.09 15V15.08H20.8V17H13.05Z"></path></svg></button><div class="dropdown-menu dropdown-menu-topbar dropdown-menu-center"><h6 class="dropdown-header" data-lang="sort">sort</h6><button class="dropdown-item active sort-asc" data-action="name"><svg viewBox="0 0 24 24" class="svg-icon svg-menu_down"><path class="svg-path-menu_down" d="M7,13L12,18L17,13H7Z"></path><path class="svg-path-menu_up" d="M7,12L12,7L17,12H7Z"></path></svg><svg viewBox="0 0 24 24" class="svg-icon svg-sort_name_asc"><path class="svg-path-sort_name_asc" d="M9.25 5L12.5 1.75L15.75 5H9.25M8.89 14.3H6L5.28 17H2.91L6 7H9L12.13 17H9.67L8.89 14.3M6.33 12.68H8.56L7.93 10.56L7.67 9.59L7.42 8.63H7.39L7.17 9.6L6.93 10.58L6.33 12.68M13.05 17V15.74L17.8 8.97V8.91H13.5V7H20.73V8.34L16.09 15V15.08H20.8V17H13.05Z"></path><path class="svg-path-sort_name_desc" d="M15.75 19L12.5 22.25L9.25 19H15.75M8.89 14.3H6L5.28 17H2.91L6 7H9L12.13 17H9.67L8.89 14.3M6.33 12.68H8.56L7.93 10.56L7.67 9.59L7.42 8.63H7.39L7.17 9.6L6.93 10.58L6.33 12.68M13.05 17V15.74L17.8 8.97V8.91H13.5V7H20.73V8.34L16.09 15V15.08H20.8V17H13.05Z"></path></svg><span class="dropdown-text" data-lang="name">name</span></button><button class="dropdown-item" data-action="kind"><svg viewBox="0 0 24 24" class="svg-icon svg-menu_down"><path class="svg-path-menu_down" d="M7,13L12,18L17,13H7Z"></path><path class="svg-path-menu_up" d="M7,12L12,7L17,12H7Z"></path></svg><svg viewBox="0 0 24 24" class="svg-icon svg-sort_kind_asc"><path class="svg-path-sort_kind_asc" d="M3 11H15V13H3M3 18V16H21V18M3 6H9V8H3Z"></path><path class="svg-path-sort_kind_desc" d="M3,13H15V11H3M3,6V8H21V6M3,18H9V16H3V18Z"></path></svg><span class="dropdown-text" data-lang="kind">kind</span></button><button class="dropdown-item" data-action="size"><svg viewBox="0 0 24 24" class="svg-icon svg-menu_down"><path class="svg-path-menu_down" d="M7,13L12,18L17,13H7Z"></path><path class="svg-path-menu_up" d="M7,12L12,7L17,12H7Z"></path></svg><svg viewBox="0 0 24 24" class="svg-icon svg-sort_size_asc"><path class="svg-path-sort_size_asc" d="M10,13V11H18V13H10M10,19V17H14V19H10M10,7V5H22V7H10M6,17H8.5L5,20.5L1.5,17H4V7H1.5L5,3.5L8.5,7H6V17Z"></path><path class="svg-path-sort_size_desc" d="M10,13V11H18V13H10M10,19V17H14V19H10M10,7V5H22V7H10M6,17H8.5L5,20.5L1.5,17H4V7H1.5L5,3.5L8.5,7H6V17Z"></path></svg><span class="dropdown-text" data-lang="size">size</span></button><button class="dropdown-item" data-action="date"><svg viewBox="0 0 24 24" class="svg-icon svg-menu_down"><path class="svg-path-menu_down" d="M7,13L12,18L17,13H7Z"></path><path class="svg-path-menu_up" d="M7,12L12,7L17,12H7Z"></path></svg><svg viewBox="0 0 24 24" class="svg-icon svg-sort_date_asc"><path class="svg-path-sort_date_asc" d="M7.78 7C9.08 7.04 10 7.53 10.57 8.46C11.13 9.4 11.41 10.56 11.39 11.95C11.4 13.5 11.09 14.73 10.5 15.62C9.88 16.5 8.95 16.97 7.71 17C6.45 16.96 5.54 16.5 4.96 15.56C4.38 14.63 4.09 13.45 4.09 12S4.39 9.36 5 8.44C5.59 7.5 6.5 7.04 7.78 7M7.75 8.63C7.31 8.63 6.96 8.9 6.7 9.46C6.44 10 6.32 10.87 6.32 12C6.31 13.15 6.44 14 6.69 14.54C6.95 15.1 7.31 15.37 7.77 15.37C8.69 15.37 9.16 14.24 9.17 12C9.17 9.77 8.7 8.65 7.75 8.63M13.33 17V15.22L13.76 15.24L14.3 15.22L15.34 15.03C15.68 14.92 16 14.78 16.26 14.58C16.59 14.35 16.86 14.08 17.07 13.76C17.29 13.45 17.44 13.12 17.53 12.78L17.5 12.77C17.05 13.19 16.38 13.4 15.47 13.41C14.62 13.4 13.91 13.15 13.34 12.65S12.5 11.43 12.46 10.5C12.47 9.5 12.81 8.69 13.47 8.03C14.14 7.37 15 7.03 16.12 7C17.37 7.04 18.29 7.45 18.88 8.24C19.47 9 19.76 10 19.76 11.19C19.75 12.15 19.61 13 19.32 13.76C19.03 14.5 18.64 15.13 18.12 15.64C17.66 16.06 17.11 16.38 16.47 16.61C15.83 16.83 15.12 16.96 14.34 17H13.33M16.06 8.63C15.65 8.64 15.32 8.8 15.06 9.11C14.81 9.42 14.68 9.84 14.68 10.36C14.68 10.8 14.8 11.16 15.03 11.46C15.27 11.77 15.63 11.92 16.11 11.93C16.43 11.93 16.7 11.86 16.92 11.74C17.14 11.61 17.3 11.46 17.41 11.28C17.5 11.17 17.53 10.97 17.53 10.71C17.54 10.16 17.43 9.69 17.2 9.28C16.97 8.87 16.59 8.65 16.06 8.63M9.25 5L12.5 1.75L15.75 5H9.25"></path><path class="svg-path-sort_date_desc" d="M7.78 7C9.08 7.04 10 7.53 10.57 8.46C11.13 9.4 11.41 10.56 11.39 11.95C11.4 13.5 11.09 14.73 10.5 15.62C9.88 16.5 8.95 16.97 7.71 17C6.45 16.96 5.54 16.5 4.96 15.56C4.38 14.63 4.09 13.45 4.09 12S4.39 9.36 5 8.44C5.59 7.5 6.5 7.04 7.78 7M7.75 8.63C7.31 8.63 6.96 8.9 6.7 9.46C6.44 10 6.32 10.87 6.32 12C6.31 13.15 6.44 14 6.69 14.54C6.95 15.1 7.31 15.37 7.77 15.37C8.69 15.37 9.16 14.24 9.17 12C9.17 9.77 8.7 8.65 7.75 8.63M13.33 17V15.22L13.76 15.24L14.3 15.22L15.34 15.03C15.68 14.92 16 14.78 16.26 14.58C16.59 14.35 16.86 14.08 17.07 13.76C17.29 13.45 17.44 13.12 17.53 12.78L17.5 12.77C17.05 13.19 16.38 13.4 15.47 13.41C14.62 13.4 13.91 13.15 13.34 12.65S12.5 11.43 12.46 10.5C12.47 9.5 12.81 8.69 13.47 8.03C14.14 7.37 15 7.03 16.12 7C17.37 7.04 18.29 7.45 18.88 8.24C19.47 9 19.76 10 19.76 11.19C19.75 12.15 19.61 13 19.32 13.76C19.03 14.5 18.64 15.13 18.12 15.64C17.66 16.06 17.11 16.38 16.47 16.61C15.83 16.83 15.12 16.96 14.34 17H13.33M16.06 8.63C15.65 8.64 15.32 8.8 15.06 9.11C14.81 9.42 14.68 9.84 14.68 10.36C14.68 10.8 14.8 11.16 15.03 11.46C15.27 11.77 15.63 11.92 16.11 11.93C16.43 11.93 16.7 11.86 16.92 11.74C17.14 11.61 17.3 11.46 17.41 11.28C17.5 11.17 17.53 10.97 17.53 10.71C17.54 10.16 17.43 9.69 17.2 9.28C16.97 8.87 16.59 8.65 16.06 8.63M15.75 19L12.5 22.25L9.25 19H15.75Z"></path></svg><span class="dropdown-text" data-lang="date">date</span></button></div></div>
<button class="btn-icon btn-topbar" id="topbar-fullscreen"><svg viewBox="0 0 24 24" class="svg-icon svg-expand"><path class="svg-path-expand" d="M10,21V19H6.41L10.91,14.5L9.5,13.09L5,17.59V14H3V21H10M14.5,10.91L19,6.41V10H21V3H14V5H17.59L13.09,9.5L14.5,10.91Z"></path><path class="svg-path-collapse" d="M19.5,3.09L15,7.59V4H13V11H20V9H16.41L20.91,4.5L19.5,3.09M4,13V15H7.59L3.09,19.5L4.5,20.91L9,16.41V20H11V13H4Z"></path></svg></button></div>
<div id="topbar-info" class="info-hidden"></div>
<div id="files-sortbar" class="sortbar-rows"><div class="sortbar-inner"><div class="sortbar-item sortbar-name sortbar-active sort-asc" data-action="name"><span data-lang="name" class="sortbar-item-text">name</span><svg viewBox="0 0 24 24" class="svg-icon svg-menu_down"><path class="svg-path-menu_down" d="M7,13L12,18L17,13H7Z"></path><path class="svg-path-menu_up" d="M7,12L12,7L17,12H7Z"></path></svg></div><div class="sortbar-item sortbar-kind" data-action="kind"><span data-lang="kind" class="sortbar-item-text">kind</span><svg viewBox="0 0 24 24" class="svg-icon svg-menu_down"><path class="svg-path-menu_down" d="M7,13L12,18L17,13H7Z"></path><path class="svg-path-menu_up" d="M7,12L12,7L17,12H7Z"></path></svg></div><div class="sortbar-item sortbar-size" data-action="size"><span data-lang="size" class="sortbar-item-text">size</span><svg viewBox="0 0 24 24" class="svg-icon svg-menu_down"><path class="svg-path-menu_down" d="M7,13L12,18L17,13H7Z"></path><path class="svg-path-menu_up" d="M7,12L12,7L17,12H7Z"></path></svg></div><div class="sortbar-item sortbar-date" data-action="date"><span data-lang="date" class="sortbar-item-text">date</span><svg viewBox="0 0 24 24" class="svg-icon svg-menu_down"><path class="svg-path-menu_down" d="M7,13L12,18L17,13H7Z"></path><path class="svg-path-menu_up" d="M7,12L12,7L17,12H7Z"></path></svg></div></div></div>
</nav>
<!-- files list container -->
<div><div id="files" class="list files-rows" style="--imagelist-height:100px; --imagelist-min-height:auto;"><a href="./beneri.se_malware_analysis" target="_blank" class="files-a files-a-svg" data-name="beneri.se_malware_analysis" style="opacity: 1;"><svg viewBox="0 0 56 56" class="svg-file svg-none files-svg"><path class="svg-file-bg" d="M36.985,0H7.963C7.155,0,6.5,0.655,6.5,1.926V55c0,0.345,0.655,1,1.463,1h40.074 c0.808,0,1.463-0.655,1.463-1V12.978c0-0.696-0.093-0.92-0.257-1.085L37.607,0.257C37.442,0.093,37.218,0,36.985,0z"></path><polygon class="svg-file-flip" points="37.5,0.151 37.5,12 49.349,12"></polygon></svg><div class="files-data"><span class="name">beneri.se_malware_analysis</span><span class="icon"><svg viewBox="0 0 24 24" class="svg-icon svg-file_default"><path class="svg-path-file_default" d="M14,10H19.5L14,4.5V10M5,3H15L21,9V19A2,2 0 0,1 19,21H5C3.89,21 3,20.1 3,19V5C3,3.89 3.89,3 5,3M5,5V19H19V12H12V5H5Z"></path></svg></span><span class="size">0 B</span><span class="ext"><span class="ext-inner">se_malware_analysis</span></span><span class="date"><time datetime="2023-02-12T20:32:43-05:00" data-time="1676251963" data-format="ll" title="Sunday, February 12, 2023 8:32 PM ~ a few seconds ago" data-title-format="LLLL">Feb 12, 2023</time></span><span class="flex"></span></div><span class="context-button files-context" data-action="context"><svg viewBox="0 0 24 24" class="svg-icon svg-dots"><path class="svg-path-dots" d="M12,16A2,2 0 0,1 14,18A2,2 0 0,1 12,20A2,2 0 0,1 10,18A2,2 0 0,1 12,16M12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12A2,2 0 0,1 12,10M12,4A2,2 0 0,1 14,6A2,2 0 0,1 12,8A2,2 0 0,1 10,6A2,2 0 0,1 12,4Z"></path><path class="svg-path-minus" d="M19,13H5V11H19V13Z"></path></svg></span></a></div></div>
</main>
<!-- modal -->
<div id="modal-bg"></div>
<div class="modal" id="files_modal" tabindex="-1" role="dialog" data-action="close"><div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title"></h5> <div class="modal-buttons"> <div class="modal-code-buttons" style="display: none"><button type="button" class="btn btn-1 is-icon" data-action="copy" data-tooltip="copy text" data-lang="copy text"><svg viewBox="0 0 24 24" class="svg-icon svg-clipboard"><path class="svg-path-clipboard" d="M19,3H14.82C14.4,1.84 13.3,1 12,1C10.7,1 9.6,1.84 9.18,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3M12,3A1,1 0 0,1 13,4A1,1 0 0,1 12,5A1,1 0 0,1 11,4A1,1 0 0,1 12,3M7,7H17V5H19V19H5V5H7V7M7.5,13.5L9,12L11,14L15.5,9.5L17,11L11,17L7.5,13.5Z"></path></svg></button><button type="button" class="btn btn-1 is-icon" data-action="fullscreen"><svg viewBox="0 0 24 24" class="svg-icon svg-expand"><path class="svg-path-expand" d="M10,21V19H6.41L10.91,14.5L9.5,13.09L5,17.59V14H3V21H10M14.5,10.91L19,6.41V10H21V3H14V5H17.59L13.09,9.5L14.5,10.91Z"></path><path class="svg-path-collapse" d="M19.5,3.09L15,7.59V4H13V11H20V9H16.41L20.91,4.5L19.5,3.09M4,13V15H7.59L3.09,19.5L4.5,20.91L9,16.41V20H11V13H4Z"></path></svg></button></div><button class="btn btn-1 is-icon" data-action="close" data-lang="close" title="Close"><svg viewBox="0 0 24 24" class="svg-icon svg-close"><path class="svg-path-close" d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"></path></svg></button> </div> </div> <div class="modal-body"></div> </div> </div></div>
<!-- context menu -->
<div id="contextmenu" class="dropdown-menu"></div>
<!-- custom footer html -->
<!-- Javascript -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11.1.9/dist/sweetalert2.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js"></script>
<!--<script src="https://cdn.jsdelivr.net/npm/list.js@2.3.1/dist/list.min.js"></script>-->
<script src="https://cdn.jsdelivr.net/npm/@exeba/list.js@2.3.1/dist/list.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/yall-js@3.2.0/dist/yall.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/filesize@8.0.6/lib/filesize.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/screenfull@5.1.0/dist/screenfull.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@1.10.7/dayjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@1.10.7/plugin/localizedFormat.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@1.10.7/plugin/relativeTime.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js"></script>
<script>
var _c = {
"load_images": true,
"load_files_proxy_php": false,
"load_images_max_filesize": 1000000,
"load_svg_max_filesize": 100000,
"image_resize_enabled": true,
"image_resize_dimensions": 320,
"image_resize_dimensions_retina": 480,
"image_resize_types": "jpeg, png, gif, webp, bmp",
"image_resize_memory_limit": 128,
"image_resize_max_pixels": 30000000,
"image_resize_min_ratio": 1.5,
"folder_preview_image": true,
"menu_enabled": false,
"menu_show": true,
"menu_max_depth": 5,
"menu_cache_validate": true,
"layout": "rows",
"sort": "name_asc",
"sort_dirs_first": true,
"cache": true,
"history": true,
"transitions": true,
"click": "popup",
"click_window": "",
"click_window_popup": true,
"code_max_load": 100000,
"topbar_sticky": "scroll",
"check_updates": false,
"context_menu": true,
"prevent_right_click": false,
"filter_live": true,
"filter_props": "name, filetype, mime, features, title",
"download_dir": "zip",
"allow_upload": false,
"allow_delete": false,
"allow_rename": false,
"allow_new_folder": false,
"allow_new_file": false,
"allow_duplicate": false,
"allow_text_edit": false,
"demo_mode": false,
"upload_allowed_file_types": "",
"upload_max_filesize": 0,
"upload_note": "",
"upload_exists": "increment",
"popup_video": true,
"popup_transition": "glide",
"popup_transition_play": "inherit",
"popup_interval": 5000,
"popup_caption": true,
"popup_caption_hide": true,
"popup_caption_style": "block",
"popup_caption_align": "center-left",
"video_autoplay": true,
"lang_default": "en",
"lang_auto": true,
"lang_menu": false,
"breadcrumbs": false,
"script": "manager3.php",
"menu_cache_hash": false,
"menu_cache_file": false,
"query_path": false,
"query_path_valid": false,
"init_path": "",
"dirs": {
"": {
"basename": "html",
"fileperms": "0777",
"filetype": "dir",
"is_readable": true,
"is_writeable": true,
"is_link": false,
"is_dir": true,
"mime": "directory",
"mtime": 1676251964,
"path": "",
"url_path": "."
}
},
"dirs_hash": "0025e3",
"resize_image_types": [
"jpeg",
"jpg",
"png",
"gif",
"webp",
"bmp"
],
"image_cache_hash": "483187",
"location_hash": "40d1b2d83998fabacb726e5bc3d22129",
"has_login": false,
"version": "0.3.1",
"index_html": 0,
"server_exif": true,
"qrx": false,
"video_thumbs_enabled": true,
"lang_custom": false,
"x3_path": false
};
var CodeMirror = {};
</script>
<script src="https://cdn.jsdelivr.net/npm/codemirror@5.63.3/mode/meta.js"></script>
<!-- custom -->
<!-- files -->
<script src="https://cdn.jsdelivr.net/npm/files.photo.gallery@0.3.1/js/files.js"></script><script src="https://cdn.jsdelivr.net/npm/mousetrap@1.6.5/mousetrap.min.js"></script><script src="https://cdn.jsdelivr.net/npm/headroom.js@0.12.0/dist/headroom.min.js"></script> <div class="pswp pswp--has_mouse" tabindex="-1" role="dialog" aria-hidden="true"> <div class="pswp__bg"></div> <div class="pswp__scroll-wrap"> <div class="pswp__container server-exif"> <div class="pswp__item"></div> <div class="pswp__item"></div> <div class="pswp__item"></div> </div> <div class="pswp__ui pswp__ui--hidden pswp__caption-align-center-left"> <div class="pswp__top-bar"> <div class="pswp__counter"></div> <div class="pswp__search"></div> <div class="pswp__topbar-spacer"></div> <svg viewBox="0 0 18 18" class="pswp__preloader svg-preloader"><circle cx="9" cy="9" r="8" pathLength="100" class="svg-preloader-circle"></circle></svg><span class="context-button pswp__button pswp__button--contextmenu" data-action="context"><svg viewBox="0 0 24 24" class="svg-icon svg-dots"><path class="svg-path-dots" d="M12,16A2,2 0 0,1 14,18A2,2 0 0,1 12,20A2,2 0 0,1 10,18A2,2 0 0,1 12,16M12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12A2,2 0 0,1 12,10M12,4A2,2 0 0,1 14,6A2,2 0 0,1 12,8A2,2 0 0,1 10,6A2,2 0 0,1 12,4Z"></path><path class="svg-path-minus" d="M19,13H5V11H19V13Z"></path></svg></span><button class="pswp__button pswp__button--zoom"><svg viewBox="0 0 24 24" class="svg-icon svg-zoom_in"><path class="svg-path-zoom_in" d="M15.5,14L20.5,19L19,20.5L14,15.5V14.71L13.73,14.43C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.43,13.73L14.71,14H15.5M9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14M12,10H10V12H9V10H7V9H9V7H10V9H12V10Z"></path><path class="svg-path-zoom_out" d="M15.5,14H14.71L14.43,13.73C15.41,12.59 16,11.11 16,9.5A6.5,6.5 0 0,0 9.5,3A6.5,6.5 0 0,0 3,9.5A6.5,6.5 0 0,0 9.5,16C11.11,16 12.59,15.41 13.73,14.43L14,14.71V15.5L19,20.5L20.5,19L15.5,14M9.5,14C7,14 5,12 5,9.5C5,7 7,5 9.5,5C12,5 14,7 14,9.5C14,12 12,14 9.5,14M7,9H12V10H7V9Z"></path></svg></button> <button class="pswp__button pswp__button--play"><svg viewBox="0 0 24 24" class="svg-icon svg-play"><path class="svg-path-play" d="M8,5.14V19.14L19,12.14L8,5.14Z"></path><path class="svg-path-pause" d="M14,19H18V5H14M6,19H10V5H6V19Z"></path></svg></button> <button class="pswp__button pswp__button--fs"><svg viewBox="0 0 24 24" class="svg-icon svg-expand"><path class="svg-path-expand" d="M10,21V19H6.41L10.91,14.5L9.5,13.09L5,17.59V14H3V21H10M14.5,10.91L19,6.41V10H21V3H14V5H17.59L13.09,9.5L14.5,10.91Z"></path><path class="svg-path-collapse" d="M19.5,3.09L15,7.59V4H13V11H20V9H16.41L20.91,4.5L19.5,3.09M4,13V15H7.59L3.09,19.5L4.5,20.91L9,16.41V20H11V13H4Z"></path></svg></button> <button class="pswp__button pswp__button--close"><svg viewBox="0 0 24 24" class="svg-icon svg-close"><path class="svg-path-close" d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"></path></svg></button> </div> <button class="pswp__button pswp__button--arrow--left"><svg viewBox="0 0 24 24" class="svg-icon svg-chevron_left"><path class="svg-path-chevron_left" d="M15.41,16.58L10.83,12L15.41,7.41L14,6L8,12L14,18L15.41,16.58Z"></path></svg></button><button class="pswp__button pswp__button--arrow--right"><svg viewBox="0 0 24 24" class="svg-icon svg-chevron_right"><path class="svg-path-chevron_right" d="M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z"></path></svg></button> <div class="pswp__timer"></div> <div class="pswp__caption pswp__caption-style-block pswp__caption-hide"> <button class="pswp__button pswp__button--lock-caption"><svg viewBox="0 0 24 24" class="svg-icon svg-lock_outline"><path class="svg-path-lock_outline" d="M12,17C10.89,17 10,16.1 10,15C10,13.89 10.89,13 12,13A2,2 0 0,1 14,15A2,2 0 0,1 12,17M18,20V10H6V20H18M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V10C4,8.89 4.89,8 6,8H7V6A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,3A3,3 0 0,0 9,6V8H15V6A3,3 0 0,0 12,3Z"></path><path class="svg-path-lock_open_outline" d="M18,20V10H6V20H18M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V10A2,2 0 0,1 6,8H15V6A3,3 0 0,0 12,3A3,3 0 0,0 9,6H7A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,17A2,2 0 0,1 10,15A2,2 0 0,1 12,13A2,2 0 0,1 14,15A2,2 0 0,1 12,17Z"></path></svg></button> <div class="pswp__caption__center"></div> </div> </div> </div> </div>
<script src="https://www.paypal.com/sdk/js?client-id=ARE4H7QcoXmKKWTfKk-pXAnsIfW1Zox3buwKma_y-mn4RjQZjS8Ghp1-JUxcevnkl5KI0vL-UIJ-uEfU" data-uid-auto="uid_ldjccltlhrxlfzzisewywfrqccypzs"></script><div class="modal fade show" id="license_modal" tabindex="-1" aria-labelledby="license_modal-label" aria-modal="true" role="dialog" style="display: block;"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-body"><div id="pay" class="mb-2"><div id="pay_info" class="mb-3 mt-1"><strong>Purchase a license [$39]</strong> to unlock features and support dev! <div><div class="license-features"><div class="license-feature"><svg viewBox="0 0 24 24" class="svg-icon svg-check"><path class="svg-path-check" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg>Remove this popup</div><div class="license-feature"><svg viewBox="0 0 24 24" class="svg-icon svg-check"><path class="svg-path-check" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg>Upload</div><div class="license-feature"><svg viewBox="0 0 24 24" class="svg-icon svg-check"><path class="svg-path-check" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg>Download folder</div><div class="license-feature"><svg viewBox="0 0 24 24" class="svg-icon svg-check"><path class="svg-path-check" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg>Code and text editor</div><div class="license-feature"><svg viewBox="0 0 24 24" class="svg-icon svg-check"><path class="svg-path-check" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg>Create new file</div><div class="license-feature"><svg viewBox="0 0 24 24" class="svg-icon svg-check"><path class="svg-path-check" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg>Create new folder</div><div class="license-feature"><svg viewBox="0 0 24 24" class="svg-icon svg-check"><path class="svg-path-check" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg>Rename</div><div class="license-feature"><svg viewBox="0 0 24 24" class="svg-icon svg-check"><path class="svg-path-check" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg>Delete</div><div class="license-feature"><svg viewBox="0 0 24 24" class="svg-icon svg-check"><path class="svg-path-check" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg>Duplicate file</div><div class="license-feature"><svg viewBox="0 0 24 24" class="svg-icon svg-check"><path class="svg-path-check" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg>Dedicated support</div><div class="license-feature"><svg viewBox="0 0 24 24" class="svg-icon svg-check"><path class="svg-path-check" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg>Multi-user, panorama and much more coming soon!</div></div></div><small>* After purchase, you will receive <strong>license key</strong> by email.</small> </div><div id="pay_pp"><div id="zoid-paypal-buttons-uid_6707980b5f_mde6mzi6ndc" class="paypal-buttons paypal-buttons-context-iframe paypal-buttons-label-unknown paypal-buttons-layout-vertical" data-paypal-smart-button-version="5.0.352" style="height: 142px; transition: all 0.2s ease-in-out 0s;"><style nonce="">
#zoid-paypal-buttons-uid_6707980b5f_mde6mzi6ndc {
position: relative;
display: inline-block;
width: 100%;
min-height: 35px;
min-width: 200px;
max-width: 750px;
font-size: 0;
}
#zoid-paypal-buttons-uid_6707980b5f_mde6mzi6ndc > iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#zoid-paypal-buttons-uid_6707980b5f_mde6mzi6ndc > iframe.component-frame {
z-index: 100;
}
#zoid-paypal-buttons-uid_6707980b5f_mde6mzi6ndc > iframe.prerender-frame {
transition: opacity .2s linear;
z-index: 200;
}
#zoid-paypal-buttons-uid_6707980b5f_mde6mzi6ndc > iframe.visible {
opacity: 1;
}
#zoid-paypal-buttons-uid_6707980b5f_mde6mzi6ndc > iframe.invisible {
opacity: 0;
pointer-events: none;
}
#zoid-paypal-buttons-uid_6707980b5f_mde6mzi6ndc > .smart-menu {
position: absolute;
z-index: 300;
top: 0;
left: 0;
width: 100%;
}
</style><iframe allowtransparency="true" name="__zoid__paypal_buttons__eyJzZW5kZXIiOnsiZG9tYWluIjoiaHR0cDovL2xvY2FsaG9zdCJ9LCJtZXRhRGF0YSI6eyJ3aW5kb3dSZWYiOnsidHlwZSI6InBhcmVudCIsImRpc3RhbmNlIjowfX0sInJlZmVyZW5jZSI6eyJ0eXBlIjoicmF3IiwidmFsIjoie1widWlkXCI6XCJ6b2lkLXBheXBhbC1idXR0b25zLXVpZF82NzA3OTgwYjVmX21kZTZtemk2bmRjXCIsXCJjb250ZXh0XCI6XCJpZnJhbWVcIixcInRhZ1wiOlwicGF5cGFsLWJ1dHRvbnNcIixcImNoaWxkRG9tYWluTWF0Y2hcIjp7XCJfX3R5cGVfX1wiOlwicmVnZXhcIixcIl9fdmFsX19cIjpcIlxcXFwucGF5cGFsXFxcXC4oY29tfGNuKSg6XFxcXGQrKT8kXCJ9LFwidmVyc2lvblwiOlwiMTBfMV8wXCIsXCJwcm9wc1wiOntcImNyZWF0ZU9yZGVyXCI6e1wiX190eXBlX19cIjpcImNyb3NzX2RvbWFpbl9mdW5jdGlvblwiLFwiX192YWxfX1wiOntcImlkXCI6XCJ1aWRfZDZkZTY5MDM0Yl9tZGU2bXppNm5kY1wiLFwibmFtZVwiOlwiY3JlYXRlT3JkZXJcIn19LFwib25BcHByb3ZlXCI6e1wiX190eXBlX19cIjpcImNyb3NzX2RvbWFpbl9mdW5jdGlvblwiLFwiX192YWxfX1wiOntcImlkXCI6XCJ1aWRfZDE1MGQzMmYxZl9tZGU2bXppNm5kY1wiLFwibmFtZVwiOlwib25BcHByb3ZlXCJ9fSxcImNzcE5vbmNlXCI6e1wiX190eXBlX19cIjpcInVuZGVmaW5lZFwifSxcImZ1bmRpbmdTb3VyY2VcIjp7XCJfX3R5cGVfX1wiOlwidW5kZWZpbmVkXCJ9LFwic3R5bGVcIjp7XCJjdXN0b21cIjp7XCJfX3R5cGVfX1wiOlwidW5kZWZpbmVkXCJ9LFwibGFiZWxcIjp7XCJfX3R5cGVfX1wiOlwidW5kZWZpbmVkXCJ9LFwibGF5b3V0XCI6XCJ2ZXJ0aWNhbFwiLFwiY29sb3JcIjpcImdvbGRcIixcInNoYXBlXCI6XCJyZWN0XCIsXCJ0YWdsaW5lXCI6ZmFsc2UsXCJoZWlnaHRcIjp7XCJfX3R5cGVfX1wiOlwidW5kZWZpbmVkXCJ9LFwicGVyaW9kXCI6e1wiX190eXBlX19cIjpcInVuZGVmaW5lZFwifSxcIm1lbnVQbGFjZW1lbnRcIjpcImJlbG93XCJ9LFwic3RvcmFnZVN0YXRlXCI6e1wiZ2V0XCI6e1wiX190eXBlX19cIjpcImNyb3NzX2RvbWFpbl9mdW5jdGlvblwiLFwiX192YWxfX1wiOntcImlkXCI6XCJ1aWRfNGFhMjdhNzQ3OV9tZGU2bXppNm5kY1wiLFwibmFtZVwiOlwiZ2V0XCJ9fSxcInNldFwiOntcIl9fdHlwZV9fXCI6XCJjcm9zc19kb21haW5fZnVuY3Rpb25cIixcIl9fdmFsX19cIjp7XCJpZFwiOlwidWlkX2MxZDJjOWJlN2ZfbWRlNm16aTZuZGNcIixcIm5hbWVcIjpcInNldFwifX19LFwic2Vzc2lvblN0YXRlXCI6e1wiZ2V0XCI6e1wiX190eXBlX19cIjpcImNyb3NzX2RvbWFpbl9mdW5jdGlvblwiLFwiX192YWxfX1wiOntcImlkXCI6XCJ1aWRfODI5NzU3ZGI0OF9tZGU2bXppNm5kY1wiLFwibmFtZVwiOlwiZ2V0XCJ9fSxcInNldFwiOntcIl9fdHlwZV9fXCI6XCJjcm9zc19kb21haW5fZnVuY3Rpb25cIixcIl9fdmFsX19cIjp7XCJpZFwiOlwidWlkXzJhYTllZDBjYmJfbWRlNm16aTZuZGNcIixcIm5hbWVcIjpcInNldFwifX19LFwiY29tcG9uZW50c1wiOltcImJ1dHRvbnNcIl0sXCJsb2NhbGVcIjp7XCJjb3VudHJ5XCI6XCJVU1wiLFwibGFuZ1wiOlwiZW5cIn0sXCJjcmVhdGVCaWxsaW5nQWdyZWVtZW50XCI6e1wiX190eXBlX19cIjpcInVuZGVmaW5lZFwifSxcImNyZWF0ZVN1YnNjcmlwdGlvblwiOntcIl9fdHlwZV9fXCI6XCJ1bmRlZmluZWRcIn0sXCJvbkNvbXBsZXRlXCI6e1wiX190eXBlX19cIjpcInVuZGVmaW5lZFwifSxcIm9uU2hpcHBpbmdDaGFuZ2VcIjp7XCJfX3R5cGVfX1wiOlwidW5kZWZpbmVkXCJ9LFwib25TaGlwcGluZ0FkZHJlc3NDaGFuZ2VcIjp7XCJfX3R5cGVfX1wiOlwidW5kZWZpbmVkXCJ9LFwib25TaGlwcGluZ09wdGlvbnNDaGFuZ2VcIjp7XCJfX3R5cGVfX1wiOlwidW5kZWZpbmVkXCJ9LFwib25DYW5jZWxcIjp7XCJfX3R5cGVfX1wiOlwidW5kZWZpbmVkXCJ9LFwib25DbGlja1wiOntcIl9fdHlwZV9fXCI6XCJ1bmRlZmluZWRcIn0sXCJnZXRQcmVyZW5kZXJEZXRhaWxzXCI6e1wiX190eXBlX19cIjpcImNyb3NzX2RvbWFpbl9mdW5jdGlvblwiLFwiX192YWxfX1wiOntcImlkXCI6XCJ1aWRfY2E4YmFiNGY5Nl9tZGU2bXppNm5kY1wiLFwibmFtZVwiOlwiZ2V0UHJlcmVuZGVyRGV0YWlsc1wifX0sXCJnZXRQb3B1cEJyaWRnZVwiOntcIl9fdHlwZV9fXCI6XCJjcm9zc19kb21haW5fZnVuY3Rpb25cIixcIl9fdmFsX19cIjp7XCJpZFwiOlwidWlkXzY2ZmFjMDRkYTZfbWRlNm16aTZuZGNcIixcIm5hbWVcIjpcImdldFBvcHVwQnJpZGdlXCJ9fSxcIm9uSW5pdFwiOntcIl9fdHlwZV9fXCI6XCJjcm9zc19kb21haW5fZnVuY3Rpb25cIixcIl9fdmFsX19cIjp7XCJpZFwiOlwidWlkX2FlODdhZWFjMmFfbWRlNm16aTZuZGNcIixcIm5hbWVcIjpcIm9uSW5pdFwifX0sXCJnZXRRdWVyaWVkRWxpZ2libGVGdW5kaW5nXCI6e1wiX190eXBlX19cIjpcImNyb3NzX2RvbWFpbl9mdW5jdGlvblwiLFwiX192YWxfX1wiOntcImlkXCI6XCJ1aWRfMjYwZTgzOWFjOF9tZGU2bXppNm5kY1wiLFwibmFtZVwiOlwiZ2V0UXVlcmllZEVsaWdpYmxlRnVuZGluZ1wifX0sXCJjbGllbnRJRFwiOlwiQVJFNEg3UWNvWG1LS1dUZktrLXBYQW5zSWZXMVpveDNidXdLbWFfeS1tbjRSalFaalM4R2hwMS1KVXhjZXZua2w1S0kwdkwtVUlKLXVFZlVcIixcImNsaWVudEFjY2Vzc1Rva2VuXCI6e1wiX190eXBlX19cIjpcInVuZGVmaW5lZFwifSxcInBhcnRuZXJBdHRyaWJ1dGlvbklEXCI6e1wiX190eXBlX19cIjpcInVuZGVmaW5lZFwifSxcIm1lcmNoYW50UmVxdWVzdGVkUG9wdXBzRGlzYWJsZWRcIjpmYWxzZSxcImVuYWJsZVRocmVlRG9tYWluU2VjdXJlXCI6ZmFsc2UsXCJzZGtDb3JyZWxhdGlvbklEXCI6XCJmMTAwNDY0ZmZlNDM5XCIsXCJzdG9yYWdlSURcIjpcInVpZF82ODBkOTg5MWJkX21kZTZtemk2bmRjXCIsXCJzZXNzaW9uSURcIjpcInVpZF9mNTVlMzliYzc3X21kZTZtemk2bmRjXCIsXCJidXR0b25Mb2NhdGlvblwiOlwibG9jYWxob3N0XCIsXCJidXR0b25TZXNzaW9uSURcIjpcInVpZF8xNjBhOWRhNTE2X21kZTZtemk2bmRjXCIsXCJlbmFibGVWYXVsdFwiOntcIl9fdHlwZV9fXCI6XCJ1bmRlZmluZWRcIn0sXCJlbnZcIjpcInByb2R1Y3Rpb25cIixcImFtb3VudFwiOntcIl9fdHlwZV9fXCI6XCJ1bmRlZmluZWRcIn0sXCJzdGFnZUhvc3RcIjp7XCJfX3R5cGVfX1wiOlwidW5kZWZpbmVkXCJ9LFwiYnV0dG9uU2l6ZVwiOntcIl9fdHlwZV9fXCI6XCJ1bmRlZmluZWRcIn0sXCJhcGlTdGFnZUhvc3RcIjp7XCJfX3R5cGVfX1wiOlwidW5kZWZpbmVkXCJ9LFwiZnVuZGluZ0VsaWdpYmlsaXR5XCI6e1wicGF5cGFsXCI6e1wiZWxpZ2libGVcIjp0cnVlLFwidmF1bHRhYmxlXCI6dHJ1ZX0sXCJwYXlsYXRlclwiOntcImVsaWdpYmxlXCI6ZmFsc2UsXCJwcm9kdWN0c1wiOntcInBheUluM1wiOntcImVsaWdpYmxlXCI6ZmFsc2UsXCJ2YXJpYW50XCI6bnVsbH0sXCJwYXlJbjRcIjp7XCJlbGlnaWJsZVwiOmZhbHNlLFwidmFyaWFudFwiOm51bGx9LFwicGF5bGF0ZXJcIjp7XCJlbGlnaWJsZVwiOmZhbHNlLFwidmFyaWFudFwiOm51bGx9fX0sXCJjYXJkXCI6e1wiZWxpZ2libGVcIjp0cnVlLFwiYnJhbmRlZFwiOnRydWUsXCJpbnN0YWxsbWVudHNcIjpmYWxzZSxcInZlbmRvcnNcIjp7XCJ2aXNhXCI6e1wiZWxpZ2libGVcIjp0cnVlLFwidmF1bHRhYmxlXCI6dHJ1ZX0sXCJtYXN0ZXJjYXJkXCI6e1wiZWxpZ2libGVcIjp0cnVlLFwidmF1bHRhYmxlXCI6dHJ1ZX0sXCJhbWV4XCI6e1wiZWxpZ2libGVcIjp0cnVlLFwidmF1bHRhYmxlXCI6dHJ1ZX0sXCJkaXNjb3ZlclwiOntcImVsaWdpYmxlXCI6ZmFsc2UsXCJ2YXVsdGFibGVcIjp0cnVlfSxcImhpcGVyXCI6e1wiZWxpZ2libGVcIjpmYWxzZSxcInZhdWx0YWJsZVwiOmZhbHNlfSxcImVsb1wiOntcImVsaWdpYmxlXCI6ZmFsc2UsXCJ2YXVsdGFibGVcIjp0cnVlfSxcImpjYlwiOntcImVsaWdpYmxlXCI6ZmFsc2UsXCJ2YXVsdGFibGVcIjp0cnVlfX0sXCJndWVzdEVuYWJsZWRcIjpmYWxzZX0sXCJ2ZW5tb1wiOntcImVsaWdpYmxlXCI6ZmFsc2V9LFwiaXRhdVwiOntcImVsaWdpYmxlXCI6ZmFsc2V9LFwiY3JlZGl0XCI6e1wiZWxpZ2libGVcIjpmYWxzZX0sXCJhcHBsZXBheVwiOntcImVsaWdpYmxlXCI6ZmFsc2V9LFwic2VwYVwiOntcImVsaWdpYmxlXCI6ZmFsc2V9LFwiaWRlYWxcIjp7XCJlbGlnaWJsZVwiOmZhbHNlfSxcImJhbmNvbnRhY3RcIjp7XCJlbGlnaWJsZVwiOmZhbHNlfSxcImdpcm9wYXlcIjp7XCJlbGlnaWJsZVwiOmZhbHNlfSxcImVwc1wiOntcImVsaWdpYmxlXCI6ZmFsc2V9LFwic29mb3J0XCI6e1wiZWxpZ2libGVcIjpmYWxzZX0sXCJteWJhbmtcIjp7XCJlbGlnaWJsZVwiOmZhbHNlfSxcInAyNFwiOntcImVsaWdpYmxlXCI6ZmFsc2V9LFwiemltcGxlclwiOntcImVsaWdpYmxlXCI6ZmFsc2V9LFwid2VjaGF0cGF5XCI6e1wiZWxpZ2libGVcIjpmYWxzZX0sXCJwYXl1XCI6e1wiZWxpZ2libGVcIjpmYWxzZX0sXCJibGlrXCI6e1wiZWxpZ2libGVcIjpmYWxzZX0sXCJ0cnVzdGx5XCI6e1wiZWxpZ2libGVcIjpmYWxzZX0sXCJveHhvXCI6e1wiZWxpZ2libGVcIjpmYWxzZX0sXCJtYXhpbWFcIjp7XCJlbGlnaWJsZVwiOmZhbHNlfSxcImJvbGV0b1wiOntcImVsaWdpYmxlXCI6ZmFsc2V9LFwiYm9sZXRvYmFuY2FyaW9cIjp7XCJlbGlnaWJsZVwiOmZhbHNlfSxcIm1lcmNhZG9wYWdvXCI6e1wiZWxpZ2libGVcIjpmYWxzZX0sXCJtdWx0aWJhbmNvXCI6e1wiZWxpZ2libGVcIjpmYWxzZX0sXCJzYXRpc3BheVwiOntcImVsaWdpYmxlXCI6ZmFsc2V9fSxcInBsYXRmb3JtXCI6XCJkZXNrdG9wXCIsXCJyZW1lbWJlcmVkXCI6W10sXCJleHBlcmltZW50XCI6e1wiZW5hYmxlVmVubW9cIjpmYWxzZSxcImVuYWJsZVZlbm1vQXBwTGFiZWxcIjpmYWxzZX0sXCJwYXltZW50UmVxdWVzdFwiOntcIl9fdHlwZV9fXCI6XCJ1bmRlZmluZWRcIn0sXCJmbG93XCI6XCJwdXJjaGFzZVwiLFwicmVtZW1iZXJcIjp7XCJfX3R5cGVfX1wiOlwiY3Jvc3NfZG9tYWluX2Z1bmN0aW9uXCIsXCJfX3ZhbF9fXCI6e1wiaWRcIjpcInVpZF82ZjNmOGRkYTc3X21kZTZtemk2bmRjXCIsXCJuYW1lXCI6XCJyZW1lbWJlclwifX0sXCJjdXJyZW5jeVwiOlwiVVNEXCIsXCJpbnRlbnRcIjpcImNhcHR1cmVcIixcImJ1eWVyQ291bnRyeVwiOntcIl9fdHlwZV9fXCI6XCJ1bmRlZmluZWRcIn0sXCJjb21taXRcIjp0cnVlLFwidmF1bHRcIjpmYWxzZSxcImVuYWJsZUZ1bmRpbmdcIjpbXSxcImRpc2FibGVGdW5kaW5nXCI6W10sXCJkaXNhYmxlQ2FyZFwiOltdLFwibWVyY2hhbnRJRFwiOltdLFwicmVuZGVyZWRCdXR0b25zXCI6W1wicGF5cGFsXCIsXCJjYXJkXCJdLFwiY3NwXCI6e1wibm9uY2VcIjpcIlwifSxcIm5vbmNlXCI6XCJcIixcImdldFBhZ2VVcmxcIjp7XCJfX3R5cGVfX1wiOlwiY3Jvc3NfZG9tYWluX2Z1bmN0aW9uXCIsXCJfX3ZhbF9fXCI6e1wiaWRcIjpcInVpZF8zMjZlMjg0YzEzX21kZTZtemk2bmRjXCIsXCJuYW1lXCI6XCJnZXRQYWdlVXJsXCJ9fSxcInVzZXJJRFRva2VuXCI6e1wiX190eXBlX19cIjpcInVuZGVmaW5lZFwifSxcImNsaWVudE1ldGFkYXRhSURcIjp7XCJfX3R5cGVfX1wiOlwidW5kZWZpbmVkXCJ9LFwiZGVidWdcIjpmYWxzZSxcInRlc3RcIjp7XCJhY3Rpb25cIjpcImNoZWNrb3V0XCJ9LFwid2FsbGV0XCI6e1wiX190eXBlX19cIjpcInVuZGVmaW5lZFwifSxcInBheW1lbnRNZXRob2ROb25jZVwiOntcIl9fdHlwZV9fXCI6XCJ1bmRlZmluZWRcIn0sXCJwYXltZW50TWV0aG9kVG9rZW5cIjp7XCJfX3R5cGVfX1wiOlwidW5kZWZpbmVkXCJ9LFwiYnJhbmRlZFwiOntcIl9fdHlwZV9fXCI6XCJ1bmRlZmluZWRcIn0sXCJhcHBsZVBheVN1cHBvcnRcIjpmYWxzZSxcInN1cHBvcnRzUG9wdXBzXCI6dHJ1ZSxcInN1cHBvcnRlZE5hdGl2ZUJyb3dzZXJcIjpmYWxzZSxcInVzZXJFeHBlcmllbmNlRmxvd1wiOntcIl9fdHlwZV9fXCI6XCJ1bmRlZmluZWRcIn0sXCJhcHBsZVBheVwiOntcIl9fdHlwZV9fXCI6XCJ1bmRlZmluZWRcIn0sXCJleHBlcmllbmNlXCI6XCJcIixcImFsbG93QmlsbGluZ1BheW1lbnRzXCI6dHJ1ZX0sXCJleHBvcnRzXCI6e1wiaW5pdFwiOntcIl9fdHlwZV9fXCI6XCJjcm9zc19kb21haW5fZnVuY3Rpb25cIixcIl9fdmFsX19cIjp7XCJpZFwiOlwidWlkXzUxODUxNDFjMTRfbWRlNm16aTZuZGNcIixcIm5hbWVcIjpcImluaXRcIn19LFwiY2xvc2VcIjp7XCJfX3R5cGVfX1wiOlwiY3Jvc3NfZG9tYWluX2Z1bmN0aW9uXCIsXCJfX3ZhbF9fXCI6e1wiaWRcIjpcInVpZF8xZGJhZWYzYTg2X21kZTZtemk2bmRjXCIsXCJuYW1lXCI6XCJjbG9zZTo6bWVtb2l6ZWRcIn19LFwiY2hlY2tDbG9zZVwiOntcIl9fdHlwZV9fXCI6XCJjcm9zc19kb21haW5fZnVuY3Rpb25cIixcIl9fdmFsX19cIjp7XCJpZFwiOlwidWlkXzU3MTdhNWY5OThfbWRlNm16aTZuZGNcIixcIm5hbWVcIjpcImNoZWNrQ2xvc2VcIn19LFwicmVzaXplXCI6e1wiX190eXBlX19cIjpcImNyb3NzX2RvbWFpbl9mdW5jdGlvblwiLFwiX192YWxfX1wiOntcImlkXCI6XCJ1aWRfYzBhNWIxNjY0N19tZGU2bXppNm5kY1wiLFwibmFtZVwiOlwiTmVcIn19LFwib25FcnJvclwiOntcIl9fdHlwZV9fXCI6XCJjcm9zc19kb21haW5fZnVuY3Rpb25cIixcIl9fdmFsX19cIjp7XCJpZFwiOlwidWlkXzVjOWVhOGI5MTFfbWRlNm16aTZuZGNcIixcIm5hbWVcIjpcIkJlXCJ9fSxcInNob3dcIjp7XCJfX3R5cGVfX1wiOlwiY3Jvc3NfZG9tYWluX2Z1bmN0aW9uXCIsXCJfX3ZhbF9fXCI6e1wiaWRcIjpcInVpZF81ZGMxOWYyZmRhX21kZTZtemk2bmRjXCIsXCJuYW1lXCI6XCJoZVwifX0sXCJoaWRlXCI6e1wiX190eXBlX19cIjpcImNyb3NzX2RvbWFpbl9mdW5jdGlvblwiLFwiX192YWxfX1wiOntcImlkXCI6XCJ1aWRfMzliODI5YWZhYV9tZGU2bXppNm5kY1wiLFwibmFtZVwiOlwiZ2VcIn19LFwiZXhwb3J0XCI6e1wiX190eXBlX19cIjpcImNyb3NzX2RvbWFpbl9mdW5jdGlvblwiLFwiX192YWxfX1wiOntcImlkXCI6XCJ1aWRfY2FjOTc0ZWRhNF9tZGU2bXppNm5kY1wiLFwibmFtZVwiOlwiVWVcIn19fX0ifX0__" title="PayPal" allowpaymentrequest="allowpaymentrequest" scrolling="no" id="jsx-iframe-293b5f0222" class="component-frame visible" style="background-color: transparent; border: none;"></iframe><div id="smart-menu" class="smart-menu"></div><div id="installments-modal" class="installments-modal"></div><iframe name="__detect_close_uid_f29fa2f92b_mde6mzi6ndc__" style="display: none;"></iframe></div></div></div> <form id="license_form" novalidate=""> <input id="license_key" class="form-control" type="text" placeholder="LICENSE-KEY" required=""> <div class="float-right mt-3"> <button id="continue_free" type="button" class="btn btn-light" data-bs-dismiss="modal">No thanks!</button> <button id="license_save_button" type="submit" class="btn btn-success text-light" style="display:none;">Save</button> </div> </form></div> </div> </div> </div><div class="modal-backdrop fade show"></div></body></html>
<?php
// errors
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// config
class config {
// DEFAULT CONFIG
// Only edit directly if it is a temporary installation. Settings added here will be lost when updating!
// Instead, add options from external config file in your storage_path [_files/config/config.php]
// READ MORE: https://forum.photo.gallery/viewtopic.php?f=66&t=9964
public static $default = array(
// paths
'root' => '', // root path relative to script / empty is same as files app location
'start_path' => false, // start path relative to script. If empty, root is start path
// login
'username' => '',
'password' => '', // Add password directly or use https://files.photo.gallery/tools/hash/ to encrypt the password (encrypted password is more secure, as it prevents your password from being exposed directly in a file).
// images
'load_images' => true,
'load_files_proxy_php' => false,
'load_images_max_filesize' => 1000000, // maximum file size (bytes) for un-resized images loaded into list
'load_svg_max_filesize' => 100000, // 100k
'image_resize_enabled' => true, // resize images for the interface
'image_resize_cache' => true, // todo: remove this option and just use 'cache?
'image_resize_dimensions' => 320,
'image_resize_dimensions_retina' => 480,
'image_resize_dimensions_allowed' => '', // comma-separated list of allowed resize dimensions
'image_resize_types' => 'jpeg, png, gif, webp, bmp', // image types to resize / jpeg, png, gif, webp, bmp
'image_resize_quality' => 85,
'image_resize_function' => 'imagecopyresampled', // imagecopyresampled / imagecopyresized
'image_resize_sharpen' => true,
'image_resize_memory_limit' => 128, // 128 MB is suffient to resize images around 6000 px / 0 = ignore memory
'image_resize_max_pixels' => 30000000, // 30 MP equivalent to an image 6000 x 5000 / 0 = no limit
'image_resize_min_ratio' => 1.5, // min size diff original vs resize. Only resizes if ratio > min ratio
'image_resize_cache_direct' => false, // if enabled and delete cache, must increase cache_key
'folder_preview_image' => true, // enable folder preview images / might be slow as it requires searching each dir for images
'folder_preview_default' => '_filespreview.jpg', // use this image as folder preview if exists in dir
// menu
'menu_enabled' => true,
'menu_show' => true,
'menu_max_depth' => 5,
'menu_sort' => 'name_asc', // name_asc, name_desc, date_asc, date_desc
'menu_cache_validate' => true,
'menu_load_all' => false,
'menu_recursive_symlinks' => true, // List sub-directories of symlinks in the main menu. May cause loops and duplicates
// files layout
'layout' => 'rows', // list, imagelist, blocks, grid, rows, columns
'sort' => 'name_asc', // name, date, filesize, kind / asc, desc
'sort_dirs_first' => true, // sort dirs on top
// cache
'cache' => true,
'cache_key' => 0,
'storage_path' => '_files',
// exclude files directories regex
'files_exclude' => '', // '/\.(pdf|jpe?g)$/i'
'dirs_exclude' => '', //'/\/Convert|\/football|\/node_modules(\/|$)/i',
'allow_symlinks' => true, // allow symlinks
// various
'history' => true,
'breadcrumbs' => true,
'transitions' => true,
'click' => 'popup', // popup, modal, download, window, menu / default item click
'click_window' => '', // 'pdf, html, php, zip' / list of file extensions to open directly on click
'click_window_popup' => true, // Popup instead of new tab. Useful for viewing PDF, HTML and text type documents / desktop only
'code_max_load' => 100000, // max filesize of text files to load and preview
'topbar_sticky' => 'scroll', // true, false, 'scroll'
'check_updates' => false, // show notification in topbar with option to update when new version is available
'allow_tasks' => false,
'get_mime_type' => false, // get file mime type from server (slow) instead of from extension (fast)
'context_menu' => true, // disable context-menu button and right-click menu
'prevent_right_click' => false, // blocks browser right-click menu on sensitive items (images, list items, menu)
'license_key' => '',
'filter_live' => true, // live search filtering on keyboard input / does not apply for mobile devices
'filter_props' => 'name, filetype, mime, features, title', // file properties to filter / name, filetype, mime, features, title, headline, description, creator, credit, copyright, keywords, city, sub-location, province-state'
'download_dir' => 'zip', // download all files in folder / 'zip' / 'files' / '' false (disabled)
'download_dir_cache' => 'dir', // enable caching of created zip dirs / 'dir' / 'storage' / '' false (disabled)
// filemanager options
'allow_upload' => false, // allow uploader
'allow_delete' => false, // allow deleting files and folders
'allow_rename' => false, // allow renaming files and folders
'allow_new_folder' => false, // allow make new directory
'allow_new_file' => false, // allow make new empty file
'allow_duplicate' => false, // allow duplicate files
'allow_text_edit' => false, // allow editing text-based files in modal
'demo_mode' => false, // block all filemanager operations but allow them to show in interface / used in Files app demo
// uploader options
'upload_allowed_file_types' => '', // comma-separated list of allowed upload file types / empty = allow any / 'jpeg, jpg, image/*'
'upload_max_filesize' => 0, // [bytes] / 0 = unlimited (but limited by server PHP upload_max_filesize)
'upload_note' => '', // include a small text note at bottom of uploader / 'Max file size %upload_max_filesize%'
'upload_exists' => 'increment', // 'increment' / 'overwrite' / 'fail'
// popup options
'popup_video' => true, // opens videos in the popup (instead of modal)
'popup_transition' => 'glide', // none, slide, glide, fade, zoom, pop, elastic
'popup_transition_play' => 'inherit', // transition in play mode
'popup_interval' => 5000, // interval ms between slides in play mode
'popup_caption' => true, // enable popup caption
'popup_caption_hide' => true, // autohide popup caption after a few seconds without user input
'popup_caption_style' => 'block', // block, box, gradient, topbar, none
'popup_caption_align' => 'center-left', // left, center-left, center, right
// video
'video_thumbs' => true, // allow video thumbnails / requires FFmpeg and PHP exec() function enabled.
'video_ffmpeg_path' => 'ffmpeg', // path to ffmpeg command, normally 'ffmpeg' http://ffmpeg.org/
'video_autoplay' => true, // video autoplay on click
// language
'lang_default' => 'en', // default language if browser lang is not supported/detected or lang_auto is disabled
'lang_auto' => true, // automatically load language based on detected browser language
'lang_menu' => false, // display dropdown menu to select language
);
// config (will popuplate)
public static $config = array();
// app vars
static $__dir__ = __DIR__;
static $__file__ = __FILE__;
static $assets;
static $prod = true;
static $version = '0.3.1';
static $root;
static $doc_root;
static $has_login = false;
static $storage_path;
static $storage_is_within_doc_root = false;
static $storage_config_realpath;
static $storage_config;
static $cache_path;
static $image_resize_cache_direct;
static $image_resize_dimensions_retina = false;
static $dirs_hash = false;
static $local_config_file = '_filesconfig.php';
static $username = false;
static $password = false;
static $x3_path = false;
// get config
private function get_config($path) {
if(empty($path) || !file_exists($path)) return array();
$config = include $path;
return empty($config) || !is_array($config) ? array() : array_map(function($v){
return is_string($v) ? trim($v) : $v;
}, $config);
}
// files check system and config [diagnostics]
private function files_check($local_config, $storage_path, $storage_config, $user_config, $user_valid){
// BASIC DIAGNOSTICS
echo '<!doctype html><html><head><title>Files App check system and config.</title><meta name="robots" content="noindex,nofollow"><style>body{font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; color: #444;line-height:1.6;margin:0 auto;max-width:700px}.container{background-color:#F3F3F3;padding:.5vw 2vw 2vw;border-radius:3px;margin:1vw;overflow:scroll}.test:before{display:inline-block;width:18px;text-align:center;margin-right:5px}.neutral:before{color:#BBB}.success:before{color:#78a642}.success:before,.neutral:before{content:"\2713"}.fail:before{content:"\2716";color:firebrick}</style></head><body><div class="container"><h2>Files App ' . config::$version . '</h2><div style="margin:-1rem 0 .5rem">' . (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] . '<br>' : '') . 'PHP ' . phpversion() . '<br>' . (isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : '') . '<p><i>* The following tests are only to help diagnose feature-specific issues.</i></p></div>';
// output helper
function prop($name, $success = 'neutral', $val = false){
return '<div class="test ' . (is_bool($success) ? ($success ? 'success' : 'fail') : $success) . '">'. $name . ($val ? ': <b>' . $val . '</b>' : '') . '</div>';
}
// filesystem
echo prop('storage_path exists', file_exists(config::$config['storage_path']));
if(file_exists(config::$config['storage_path'])) echo prop('storage_path is_writeable', is_writable(config::$config['storage_path']));
echo prop('root is_writeable', is_writable(config::$config['root']));
// extension_loaded
if(function_exists('extension_loaded')) foreach (['gd', 'exif'] as $name) echo prop($name, extension_loaded($name));
// zip
echo prop('ZipArchive', class_exists('ZipArchive'));
// function_exsists
foreach (['mime_content_type', 'finfo_file', 'iptcparse', 'exif_imagetype', 'session_start', 'ini_get', 'exec'] as $name) echo prop($name . '()', function_exists($name));
// ffmpeg
if(function_exists('exec')) echo prop('ffmpeg', !!exec('type -P ' . config::$config['video_ffmpeg_path']));
// ini_get
if(function_exists('ini_get')) foreach (['memory_limit', 'file_uploads', 'upload_max_filesize', 'post_max_size', 'max_file_uploads'] as $name) echo prop($name, 'neutral', @ini_get($name));
// CONFIG OUTPUT
echo '</div><div class="container"><h3>Config</h3>';
// invalid and duplicate arrays
$user_invalid = array_diff_key($user_config, self::$default);
$user_duplicate = array_intersect_assoc($user_valid, self::$default);
// items
$items = array(
['arr' => $local_config, 'comment' => "// LOCAL CONFIG\n// " . self::$local_config_file],
['arr' => $storage_config, 'comment' => "// STORAGE CONFIG\n// " . rtrim($storage_path ?: '', '\/') . '/config/config.php'],
['arr' => $user_invalid, 'comment' => "// INVALID PARAMS\n// The following custom parameters will be ignored as they are not valid:", 'var' => '$invalid', 'hide' => empty($user_invalid)],
['arr' => $user_duplicate, 'comment' => "// DUPLICATE DEFAULT PARAMS\n// The following custom parameters will have no effect as they are identical to defaults:", 'var' => '$duplicate', 'hide' => empty($user_duplicate)],
['arr' => $user_valid, 'comment' => "// USER CONFIG\n// User config parameters.", 'var' => '$user', 'hide' => (empty($local_config) || empty($storage_config)) && empty($user_invalid)],
['arr' => self::$config, 'comment' => "// CONFIG\n// User parameters merged with default parameters.", 'var' => '$config'],
['arr' => self::$default, 'comment' => "// DEFAULT CONFIG\n// Default config parameters.", 'var' => '$default'],
//['arr' => array_diff_key(get_class_vars('config'), array_flip(['default', 'config'])), 'comment' => "// STATIC VARS\n// Static app vars.", 'var' => '$static']
);
// loop
$output = '<?php' . PHP_EOL;
foreach ($items as $arr => $props) {
$is_empty = empty($props['arr']);
if(isset($props['hide']) && $props['hide']) continue;
foreach (['username', 'password', 'license_key', 'allow_tasks', '__dir__', '__file__'] as $prop) if(isset($props['arr'][$prop]) && !empty($props['arr'][$prop]) && is_string($props['arr'][$prop])) $props['arr'][$prop] = '***';
$export = $is_empty ? 'array ()' : var_export($props['arr'], true);
$comment = preg_replace('/\n/', " [" . count($props['arr']) . "]\n", $props['comment'], 1);
$var = isset($props['var']) ? $props['var'] . ' = ' : 'return ';
$output .= PHP_EOL . $comment . PHP_EOL . $var . $export . ';' . PHP_EOL;
}
highlight_string($output . PHP_EOL . ';?>');
echo '</div></body></html>';
exit;
}
// save config
public static function save_config($config = array()){
$save_config = array_intersect_key(array_replace(self::$storage_config, $config), self::$default);
$export = preg_replace("/ '/", " //'", var_export(array_replace(self::$default, $save_config), true));
foreach ($save_config as $key => $value) if($value !== self::$default[$key]) $export = str_replace("//'" . $key, "'" . $key, $export);
return @file_put_contents(config::$storage_config_realpath, '<?php ' . PHP_EOL . PHP_EOL . '// CONFIG / https://forum.photo.gallery/viewtopic.php?f=66&t=9964' . PHP_EOL . '// Uncomment the parameters you want to edit.' . PHP_EOL . 'return ' . $export . ';');
}
// construct
function __construct($is_doc = false) {
// normalize OS paths
self::$__dir__ = real_path(__DIR__);
self::$__file__ = real_path(__FILE__);
// local config
$local_config = self::get_config(self::$local_config_file);
// storage config
$storage_path = isset($local_config['storage_path']) ? $local_config['storage_path'] : self::$default['storage_path'];
$storage_realpath = !empty($storage_path) ? real_path($storage_path) : false;
if($is_doc && $storage_realpath === self::$__dir__) error('<strong>storage_path must be a unique dir.</strong>');
self::$storage_config_realpath = $storage_realpath ? $storage_realpath . '/config/config.php' : false;
self::$storage_config = self::get_config(self::$storage_config_realpath);
// config
$user_config = array_replace(self::$storage_config, $local_config);
$user_valid = array_intersect_key($user_config, self::$default);
self::$config = array_replace(self::$default, $user_valid);
// files check with ?check=true
if(get('check')) self::files_check($local_config, $storage_path, self::$storage_config, $user_config, $user_valid);
// if(get('phpinfo')) { phpinfo(); exit; } // check system phpinfo with ?phpinfo=true / disabled for security / un-comment if you want to use
// CDN assets
self::$assets = self::$prod ? 'https://cdn.jsdelivr.net/npm/files.photo.gallery@' . self::$version . '/' : '';
// root
self::$root = real_path(self::$config['root']);
if($is_doc && !self::$root) error('root dir "' . self::$config['root'] . '" does not exist.');
// doc root
self::$doc_root = real_path($_SERVER['DOCUMENT_ROOT']);
// login credentials
self::$username = self::$config['username'];
self::$password = self::$config['password'];
// X3 compatibility / x3 login / images from X3 resize cache / invalidate X3 cache on filemanager op / X3 license
$x3_path = dirname(self::$root);
self::$x3_path = file_exists($x3_path . '/app/x3.inc.php') ? $x3_path : false;
if(self::$x3_path && self::$username === 'x3'){
$x3_config = file_exists($x3_path . '/config/config.user.json') ? json_decode(file_get_contents($x3_path . '/config/config.user.json'), true) : false;
self::$username = isset($x3_config['back']['panel']['username']) ? $x3_config['back']['panel']['username'] : 'admin';
self::$password = isset($x3_config['back']['panel']['password']) ? $x3_config['back']['panel']['password'] : 'admin';
if(self::$username === 'admin' && self::$password === 'admin' && isset($x3_config['back']['panel']['use_db'])) error('Sorry, Files app is not compatible with X3 panel database login. Assign "username" and "password" separately in _files/config/config.php.', 403);
}
// has_login
self::$has_login = self::$username || self::$password ? true : false;
// $image_cache
$image_cache = self::$config['image_resize_enabled'] && self::$config['image_resize_cache'] && self::$config['load_images'] ? true : false;
// cache enabled
if($image_cache || self::$config['cache']){
// create storage_path
if(empty($storage_realpath)){
$storage_path = is_string($storage_path) ? rtrim($storage_path, '\/') : false;
if(empty($storage_path)) error('Invalid storage_path parameter.');
mkdir_or_error($storage_path);
$storage_realpath = real_path($storage_path);
if(empty($storage_realpath)) error("storage_path <strong>$storage_path</strong> does not exist and can't be created.");
self::$storage_config_realpath = $storage_realpath . '/config/config.php'; // update since it wasn't assigned
}
self::$storage_path = $storage_realpath;
// storage path is within doc root
if(is_within_docroot(self::$storage_path)) self::$storage_is_within_doc_root = true;
// cache_path real path
self::$cache_path = self::$storage_path . '/cache';
// create storage dirs
if($is_doc){
$create_dirs = [$storage_realpath . '/config'];
if($image_cache) $create_dirs[] = self::$cache_path . '/images';
if(self::$config['cache']) array_push($create_dirs, self::$cache_path . '/folders', self::$cache_path . '/menu');
foreach($create_dirs as $create_dir) mkdir_or_error($create_dir);
}
// create/update config file, with default parameters commented out.
if($is_doc && self::$storage_config_realpath && (!file_exists(self::$storage_config_realpath) || filemtime(self::$storage_config_realpath) < filemtime(__FILE__))) self::save_config();
// image resize cache direct
if(self::$config['image_resize_cache_direct'] && !self::$has_login && self::$config['load_images'] && self::$config['image_resize_cache'] && self::$config['image_resize_enabled'] && self::$storage_is_within_doc_root) self::$image_resize_cache_direct = true;
}
// image_resize_dimensions_retina
if(self::$config['image_resize_dimensions_retina'] && self::$config['image_resize_dimensions_retina'] > self::$config['image_resize_dimensions']) self::$image_resize_dimensions_retina = self::$config['image_resize_dimensions_retina'];
// dirs hash
self::$dirs_hash = substr(md5(self::$doc_root . self::$__dir__ . self::$root . self::$version . self::$config['cache_key'] . self::$image_resize_cache_direct . self::$config['files_exclude'] . self::$config['dirs_exclude']), 0, 6);
// login
if(self::$has_login) check_login($is_doc);
}
};
// login page
function login_page($is_login_attempt, $sidx, $is_logout, $client_hash){
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover, user-scalable=no, shrink-to-fit=no">
<meta name="robots" content="noindex,nofollow">
<title>Login</title>
<link href="<?php echo config::$assets ?>css/files.css" rel="stylesheet">
<?php get_include('css/custom.css'); ?>
</head>
<body><div id="files-login-container"></div></body>
<script>
document.getElementById('files-login-container').innerHTML = '\
<h1 class="header mb-5">Login</h1>\
<?php if($is_login_attempt && $_POST['sidx'] !== $sidx) { ?><div class="alert alert-danger" role="alert"><strong>PHP session ID mismatch</strong><br>If the error persists, your PHP is incorrectly creating new session ID for each request.</div><?php } else if($is_login_attempt) { ?>\
<div class="alert alert-danger" role="alert">Incorrect login!</div><?php } else if($is_logout) { ?>\
<div class="alert alert-warning" role="alert">You are now logged out.</div><?php } ?>\
<form>\
<div class="mylogin">\
<input type="text" name="username" placeholder="Username">\
<input type="password" name="password" placeholder="Password">\
</div>\
<input type="text" name="fusername" class="form-control form-control-lg mb-3" placeholder="Username" required autofocus spellcheck="false" autocorrect="off" autocapitalize="off">\
<input type="password" name="fpassword" class="form-control form-control-lg mb-3" placeholder="Password" required spellcheck="false">\
<input type="hidden" name="client_hash" value="<?php echo $client_hash; ?>">\
<input type="hidden" name="sidx" value="<?php echo $sidx; ?>">\
<input type="submit" value="Login" class="btn btn-lg btn-files-light btn-login">\
</form>';
document.getElementsByTagName('form')[0].addEventListener('submit', function(){
this.action = '<?php echo isset($_GET['logout']) ? strtok($_SERVER['REQUEST_URI'], '?') : $_SERVER['REQUEST_URI']; ?>';
this.method = 'post';
}, false);
</script>
</html>
<?php exit; // end form and exit
}
// check login
function check_login($is_doc){
if($is_doc && empty(config::$username)) error('Username cannot be empty.');
if($is_doc && empty(config::$password)) error('Password cannot be empty.');
if(!session_start() && !$is_dor) error('Failed to initiate PHP session_start();', 500);
function get_client_hash(){
foreach(array('HTTP_CLIENT_IP','HTTP_X_FORWARDED_FOR','HTTP_X_FORWARDED','HTTP_FORWARDED_FOR','HTTP_FORWARDED','REMOTE_ADDR') as $key){
if(isset($_SERVER[$key]) && !empty($_SERVER[$key]) && filter_var($_SERVER[$key], FILTER_VALIDATE_IP)) return md5($_SERVER[$key] . $_SERVER['HTTP_USER_AGENT'] . __FILE__ . $_SERVER['HTTP_HOST']);
}
error('Invalid IP', 401);
}
// hash
$client_hash = get_client_hash();
$login_hash = md5(config::$username . config::$password . $client_hash);
// login status
$is_logout = isset($_GET['logout']) && isset($_SESSION['login']);
if($is_logout) unset($_SESSION['login']);
$is_logged_in = !$is_logout && isset($_SESSION['login']) && $_SESSION['login'] === $login_hash;
// not logged in
if(!$is_logged_in){
// login only on html pages
if($is_doc){
// vars
$sidx = md5(session_id());
$is_login_attempt = isset($_POST['fusername']) && isset($_POST['fpassword']) && isset($_POST['client_hash']) && isset($_POST['sidx']);
// correct login set $_SESSION['login']
if($is_login_attempt &&
trim($_POST['fusername']) == config::$username &&
(phpversion() >= 5.5 && !password_needs_rehash(config::$password, PASSWORD_DEFAULT) ? password_verify(trim($_POST['fpassword']), config::$password) : (trim($_POST['fpassword']) == config::$password)) &&
$_POST['client_hash'] === $client_hash &&
$_POST['sidx'] === $sidx
){
$_SESSION['login'] = $login_hash;
// display login page and exit
} else {
login_page($is_login_attempt, $sidx, $is_logout, $client_hash);
}
// not logged in (images or post API requests), don't show form.
} else if(post('action')){
json_error('login');
} else {
error('You are not logged in.', 401);
}
}
}
//
function mkdir_or_error($path){
if(!file_exists($path) && !mkdir($path, 0777, true)) error('Failed to create ' . $path, 500);
}
function real_path($path){
$real_path = realpath($path);
return $real_path ? str_replace('\\', '/', $real_path) : false;
}
function root_relative($dir){
return ltrim(substr($dir, strlen(config::$root)), '\/');
}
function root_absolute($dir){
return config::$root . ($dir ? '/' . $dir : '');
}
function is_within_path($path, $root){
return strpos($path . '/', $root . '/') === 0;
}
function is_within_root($path){
return is_within_path($path, config::$root);
}
function is_within_docroot($path){
return is_within_path($path, config::$doc_root);
}
function get_folders_cache_path($name){
return config::$cache_path . '/folders/' . $name . '.json';
}
function get_json_cache_url($name){
$file = get_folders_cache_path($name);
return file_exists($file) ? get_url_path($file) : false;
}
function get_dir_cache_path($dir, $mtime = false){
if(!config::$config['cache'] || !$dir) return;
return get_folders_cache_path(get_dir_cache_hash($dir, $mtime));
}
function get_dir_cache_hash($dir, $mtime = false){
return config::$dirs_hash . '.' . substr(md5($dir), 0, 6) . '.' . ($mtime ?: filemtime($dir));
//
}
function header_memory_time(){
return (isset($_SERVER['REQUEST_TIME_FLOAT']) ? round(microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'], 3) . 's, ' : '') . round(memory_get_peak_usage() / 1048576, 1) . 'M';
}
// read file
// todo: add files-date header
function read_file($path, $mime = false, $msg = false, $props = false, $cache_headers = false, $clone = false){
if(!$path || !file_exists($path)) return false;
$cloned = $clone && @copy($path, $clone) ? true : false;
//if($mime == 'image/svg') $mime .= '+xml';
header('content-type: ' . ($mime ?: 'image/jpeg'));
header('content-length: ' . filesize($path));
header('content-disposition: filename="' . basename($path) . '"');
if($msg) header('files-msg: ' . $msg . ($cloned ? ' [cloned to ' . basename($clone) . ']' : '') . ' [' . ($props ? $props . ', ' : '') . header_memory_time() . ']');
if($cache_headers) set_cache_headers();
if(!is_readable($path) || readfile($path) === false) error('Failed to read file ' . $path . '.', 400);
exit;
}
// get mime
function get_mime($path){
if(function_exists('mime_content_type')){
return mime_content_type($path);
} else {
return function_exists('finfo_file') ? finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path) : false;
}
}
// set cache headers
function set_cache_headers(){
$seconds = 31536000; // 1 year;
header('expires: ' . gmdate('D, d M Y H:i:s', time() + $seconds) . ' GMT');
header("cache-control: public, max-age=$seconds, s-maxage=$seconds, immutable");
header('pragma: cache');
// header("Last-Modified:" . gmdate('D, d M Y H:i:s', time() - $seconds) . ' GMT');
// etag?
}
// get image cache path
function get_image_cache_path($path, $image_resize_dimensions, $filesize, $filemtime){
return config::$cache_path . '/images/' . substr(md5($path), 0, 6) . '.' . $filesize . '.' . $filemtime . '.' . $image_resize_dimensions . '.jpg';
}
// is exclude
function is_exclude($path = false, $is_dir = true, $symlinked = false){
// early exit
if(!$path || $path === config::$root) return;
// exclude all paths that start with /_files* (reserved for any files and folders to be ignored and hidden from Files app)
if(strpos($path, '/_files') !== false) return true;
// exclude files PHP application
if($path === config::$__file__) return true;
// symlinks not allowed
if($symlinked && !config::$config['allow_symlinks']) return true;
// exclude storage path
if(config::$storage_path && is_within_path($path, config::$storage_path)) return true;
// dirs_exclude: check root relative dir path
if(config::$config['dirs_exclude']) {
$dirname = $is_dir ? $path : dirname($path);
if($dirname !== config::$root && preg_match(config::$config['dirs_exclude'], substr($dirname, strlen(config::$root)))) return true;
}
// files_exclude: check vs basename
if(!$is_dir){
$basename = basename($path);
if($basename === config::$local_config_file) return true;
if(config::$config['files_exclude'] && preg_match(config::$config['files_exclude'], $basename)) return true;
}
}
// valid root path
function valid_root_path($path, $is_dir = false){
// invalid
if($path === false) return;
if(!$is_dir && empty($path)) return; // path cannot be empty if file
if($path && substr($path, -1) == '/') return; // path should never be root absolute or end with /
// absolute path may differ if path contains symlink
$root_absolute = root_absolute($path);
$real_path = real_path($root_absolute);
// file does not exist
if(!$real_path) return;
// security checks if path contains symlink
if($root_absolute !== $real_path) {
if(strpos(($is_dir ? $path : dirname($path)), ':') !== false) return; // dir may not contain ':'
if(strpos($path, '..') !== false) return; // path may not contain '..'
if(is_exclude($root_absolute, $is_dir, true)) return;
}
// nope
if(!is_readable($real_path)) return; // not readable
if($is_dir && !is_dir($real_path)) return; // dir check
if(!$is_dir && !is_file($real_path)) return; // file check
if(is_exclude($real_path, $is_dir)) return; // exclude path
// return root_absolute
return $root_absolute;
}
// image create from
function image_create_from($path, $type){
if(!$path || !$type) return;
if($type === IMAGETYPE_JPEG){
return imagecreatefromjpeg($path);
} else if ($type === IMAGETYPE_PNG) {
return imagecreatefrompng($path);
} else if ($type === IMAGETYPE_GIF) {
return imagecreatefromgif($path);
} else if ($type === 18/*IMAGETYPE_WEBP*/) {
if(version_compare(PHP_VERSION, '5.4.0') >= 0) return imagecreatefromwebp($path);
} else if ($type === IMAGETYPE_BMP) {
if(version_compare(PHP_VERSION, '7.2.0') >= 0) return imagecreatefrombmp($path);
}
}
// get file (proxy or resize image)
function get_file($path, $resize = false){
// validate
if(!$path) error('Invalid file request.', 404);
$path = real_path($path); // in case of symlink path
$mime = get_mime($path); // may return false if server does not support mime_content_type() or finfo_file()
// video thumbnail (FFmpeg)
if($resize == 'video') {
// requirements with diagnostics / only check $mime if $mime detected
if($mime && strtok($mime, '/') !== 'video') error('<strong>' . basename($path) . '</strong> (' . $mime . ') is not a video.', 415);
foreach (array('video_thumbs', 'load_images', 'image_resize_cache', 'video_ffmpeg_path') as $key) if(empty(config::$config[$key])) error($key . ' option disabled.', 400);
if(!function_exists('exec')) error('PHP <a href="https://www.php.net/manual/en/function.exec.php" target="_blank">exec()</a> function is disabled on this server.', 400);
if(empty(exec('type -P ' . config::$config['video_ffmpeg_path']))) error('Can\'t find <a href="http://ffmpeg.org/" target="_blank">FFmpeg</a> in location "' . config::$config['video_ffmpeg_path'] . '".', 400);
// get cache path
$cache = get_image_cache_path($path, 480, filesize($path), filemtime($path));
// check for cached video thumbnail / $path, $mime, $msg, $props, $cache_headers
if($cache) read_file($cache, null, 'Video thumb served from cache', null, true);
// ffmpeg command
$cmd = escapeshellarg(config::$config['video_ffmpeg_path']) . ' -i ' . escapeshellarg($path) . ' -deinterlace -an -ss 1 -t 1 -vf "thumbnail,scale=480:320:force_original_aspect_ratio=increase,crop=480:320" -r 1 -y -f mjpeg ' . $cache . ' 2>&1';
// try to execute command
exec($cmd, $output, $result_code);
// fail if result_code is anything else than 0
if($result_code) error("Error generating thumbnail for video (\$result_code $result_code)", 400);
// output created video thumbnail
read_file($cache, null, 'Video thumb created', null, true);
// resize image
} else if($resize){
if($mime && strtok($mime, '/') !== 'image') error('<strong>' . basename($path) . '</strong> (' . $mime . ') is not an image.', 415);
foreach (['load_images', 'image_resize_enabled'] as $key) if(!config::$config[$key]) error('[' .$key . '] disabled.', 400);
$resize_dimensions = intval($resize);
if(!$resize_dimensions) error("Invalid resize parameter <strong>$resize</strong>.", 400);
$allowed = config::$config['image_resize_dimensions_allowed'] ?: [];
if(!in_array($resize_dimensions, array_merge([config::$config['image_resize_dimensions'], config::$config['image_resize_dimensions_retina']], array_map('intval', is_array($allowed) ? $allowed : explode(',', $allowed))))) error("Resize parameter <strong>$resize_dimensions</strong> is not allowed.", 400);
resize_image($path, $resize_dimensions);
// proxy file
} else {
// disable if !proxy and path is within document root (file should never be proxied)
if(!config::$config['load_files_proxy_php'] && is_within_docroot($path)) error('File cannot be proxied.', 400);
// read file / $mime or 'application/octet-stream'
read_file($path, ($mime ?: 'application/octet-stream'), $msg = 'File ' . basename($path) . ' proxied.', false, true);
}
}
// sharpen resized image
function sharpen_image($image){
$matrix = array(
array(-1, -1, -1),
array(-1, 20, -1),
array(-1, -1, -1),
);
$divisor = array_sum(array_map('array_sum', $matrix));
$offset = 0;
imageconvolution($image, $matrix, $divisor, $offset);
}
// exif orientation
// https://github.com/gumlet/php-image-resize/blob/master/lib/ImageResize.php
function exif_orientation($orientation, &$image){
if(empty($orientation) || !is_numeric($orientation) || $orientation < 3 || $orientation > 8) return;
$image = imagerotate($image, array(6 => 270, 5 => 270, 3 => 180, 4 => 180, 8 => 90, 7 => 90)[$orientation], null);
if(in_array($orientation, array(5, 4, 7)) && function_exists('imageflip')) imageflip($image, IMG_FLIP_HORIZONTAL);
return true;
}
// resize image
function resize_image($path, $resize_dimensions, $clone = false){
// file size
$file_size = filesize($path);
// header props
$header_props = 'w:' . $resize_dimensions . ', q:' . config::$config['image_resize_quality'] . ', ' . config::$config['image_resize_function'] . ', cache:' . (config::$config['image_resize_cache'] ? '1' : '0');
// cache
$cache = config::$config['image_resize_cache'] ? get_image_cache_path($path, $resize_dimensions, $file_size, filemtime($path)) : NULL;
if($cache) read_file($cache, null, 'Resized image served from cache', $header_props, true, $clone);
// imagesize
$info = getimagesize($path);
if(empty($info) || !is_array($info)) error('Invalid image / failed getimagesize().', 500);
$resize_ratio = max($info[0], $info[1]) / $resize_dimensions;
// image_resize_max_pixels early exit
if(config::$config['image_resize_max_pixels'] && $info[0] * $info[1] > config::$config['image_resize_max_pixels']) error('Image resolution <strong>' . $info[0] . ' x ' . $info[1] . '</strong> (' . ($info[0] * $info[1]) . ' px) exceeds <strong>image_resize_max_pixels</strong> (' . config::$config['image_resize_max_pixels'] . ' px).', 400);
// header props
$header_props .= ', ' . $info['mime'] . ', ' . $info[0] . 'x' . $info[1] . ', ratio:' . round($resize_ratio, 2);
// check if image type is in image_resize_types / jpeg, png, gif, webp, bmp
$is_resize_type = in_array(image_type_to_extension($info[2], false), array_map(function($key){
$type = trim(strtolower($key));
return $type === 'jpg' ? 'jpeg' : $type;
}, explode(',', config::$config['image_resize_types'])));
// serve original if !$is_resize_type || resize ratio < image_resize_min_ratio
if((!$is_resize_type || $resize_ratio < max(config::$config['image_resize_min_ratio'], 1)) && !read_file($path, $info['mime'], 'Original image served', $header_props, true, $clone)) error('File does not exist.', 404);
// Calculate new image dimensions.
$resize_width = round($info[0] / $resize_ratio);
$resize_height = round($info[1] / $resize_ratio);
// memory
$memory_limit = config::$config['image_resize_memory_limit'] && function_exists('ini_get') ? (int) @ini_get('memory_limit') : false;
if($memory_limit && $memory_limit > -1){
// $memory_required = ceil(($info[0] * $info[1] * 4 + $resize_width * $resize_height * 4) / 1048576);
$memory_required = round(($info[0] * $info[1] * (isset($info['bits']) ? $info['bits'] / 8 : 1) * (isset($info['channels']) ? $info['channels'] : 3) * 1.33 + $resize_width * $resize_height * 4) / 1048576, 1);
$new_memory_limit = function_exists('ini_set') ? max($memory_limit, config::$config['image_resize_memory_limit']) : $memory_limit;
if($memory_required > $new_memory_limit) error('Resizing this image requires at least <strong>' . $memory_required . 'M</strong>. Your current PHP memory_limit is <strong>' . $new_memory_limit .'M</strong>.', 400);
if($memory_limit < $new_memory_limit && @ini_set('memory_limit', $new_memory_limit . 'M')) $header_props .= ', ' . $memory_limit . 'M => ' . $new_memory_limit . 'M (min ' . $memory_required . 'M)';
}
// new dimensions headers
$header_props .= ', ' . $resize_width . 'x' . $resize_height;
// create new $image
$image = image_create_from($path, $info[2]);
if(!$image) error('Failed to create image resource.', 500);
// Create final image with new dimensions.
$new_image = imagecreatetruecolor($resize_width, $resize_height);
if(!call_user_func(config::$config['image_resize_function'], $new_image, $image, 0, 0, 0, 0, $resize_width, $resize_height, $info[0], $info[1])) error('Failed to resize image.', 500);
// destroy original $image resource
imagedestroy($image);
// exif orientation
$exif = function_exists('exif_read_data') ? @exif_read_data($path) : false;
if(!empty($exif) && is_array($exif) && isset($exif['Orientation']) && exif_orientation($exif['Orientation'], $new_image)) $header_props .= ', orientated from EXIF:' . $exif['Orientation'];
// sharpen resized image
if(config::$config['image_resize_sharpen']) sharpen_image($new_image);
// save to cache
if($cache){
if(!imagejpeg($new_image, $cache, config::$config['image_resize_quality'])) error('<strong>imagejpeg()</strong> failed to create and cache resized image.', 500);
// clone cache (used for folder previews)
if($clone) @copy($cache, $clone);
// cache disabled / direct output
} else {
set_cache_headers();
header('content-type: image/jpeg');
header('files-msg: Resized image served [' . $header_props . ', ' . header_memory_time() . ']');
if(!imagejpeg($new_image, null, config::$config['image_resize_quality'])) error('<strong>imagejpeg()</strong> failed to create and output resized image.', 500);
}
// destroy image
imagedestroy($new_image);
// cache readfile
if($cache && !read_file($cache, null, 'Resized image cached and served', $header_props, true, $clone)) error('Cache file does not exist.', 404);
//
exit;
// https://github.com/maxim/smart_resize_image/blob/master/smart_resize_image.function.php
// https://github.com/gavmck/resize/blob/master/php/lib/resize-class.php
// https://github.com/gumlet/php-image-resize/blob/master/lib/ImageResize.php
// https://www.bitrepository.com/resize-an-image-keeping-its-aspect-ratio-using-php-and-gd.html
}
function get_url_path($dir){
if(!is_within_docroot($dir)) return false;
// if in __dir__ path, __dir__ relative
if(is_within_path($dir, config::$__dir__)) return $dir === config::$__dir__ ? '.' : substr($dir, strlen(config::$__dir__) + 1);
// doc root, doc root relative
return $dir === config::$doc_root ? '/' : substr($dir, strlen(config::$doc_root));
}
// get dir
function get_dir($path, $files = false, $json_url = false){
// realpath
$realpath = $path ? real_path($path) : false;
if(!$realpath) return; // no real path for any reason
$symlinked = $realpath !== $path; // path is symlinked at some point
// exclude
if(is_exclude($path, true, $symlinked)) return; // exclude
if($symlinked && is_exclude($realpath, true, $symlinked)) return; // exclude check again symlink realpath
// vars
$filemtime = filemtime($realpath);
$url_path = get_url_path($realpath) ?: ($symlinked ? get_url_path($path) : false);
$is_readable = is_readable($realpath);
// array
$arr = array(
'basename' => basename($realpath) ?: basename($path) ?: '',
'fileperms' => substr(sprintf('%o', fileperms($realpath)), -4),
'filetype' => 'dir',
'is_readable' => $is_readable,
'is_writeable' => is_writeable($realpath),
'is_link' => $symlinked ? is_link($path) : false,
'is_dir' => true,
'mime' => 'directory',
'mtime' => $filemtime,
'path' => root_relative($path)
);
// url path
if($url_path) $arr['url_path'] = $url_path;
// get_files() || config::menu_load_all
if($files && $is_readable) {
// files array
$arr['files'] = get_files_data($path, $url_path, $arr['dirsize'], $arr['files_count'], $arr['images_count'], $arr['preview']);
// download_dir cache direct access to zip / better caching and no need to access PHP / only works when download_dir_cache === 'dir'
/*if($url_path && config::$config['download_dir'] === 'zip' && config::$config['download_dir_cache'] === 'dir') {
$zip = $realpath . '/_files.zip';
if(file_exists($zip) && filemtime($zip) >= $filemtime) $arr['zip'] = get_url_path($zip);
}*/
}
// json cache path
if($json_url && config::$storage_is_within_doc_root && !config::$has_login && config::$config['cache']){
$json_cache = get_json_cache_url(get_dir_cache_hash($realpath, $filemtime));
if($json_cache) $arr['json_cache'] = $json_cache;
}
//
return $arr;
}
// get menu sort
function get_menu_sort($dirs){
if(strpos(config::$config['menu_sort'], 'date') === 0){
usort($dirs, function($a, $b) {
return filemtime($a) - filemtime($b);
});
} else {
natcasesort($dirs);
}
return substr(config::$config['menu_sort'], -4) === 'desc' ? array_reverse($dirs) : $dirs;
}
// recursive directory scan
function get_dirs($path = false, &$arr = array(), $depth = 0) {
// get this dir (ignore root, unless load all ... root already loaded into page)
if($depth || config::$config['menu_load_all']) {
$data = get_dir($path, config::$config['menu_load_all'], !config::$config['menu_load_all']);
if(!$data) return $arr;
//
$arr[] = $data;
// max depth
if(config::$config['menu_max_depth'] && $depth >= config::$config['menu_max_depth']) return $arr;
// don't recursive if symlink
if($data['is_link'] && !config::$config['menu_recursive_symlinks']) return $arr;
}
// get dirs from files array if $data['files'] or glob subdirs
$subdirs = isset($data['files']) ? array_filter(array_map(function($file){
return $file['filetype'] === 'dir' ? root_absolute($file['path']) : false;
}, $data['files'])) : glob($path . '/*', GLOB_NOSORT|GLOB_ONLYDIR);
// sort and loop subdirs
if(!empty($subdirs)) foreach(get_menu_sort($subdirs) as $subdir) get_dirs($subdir, $arr, $depth + 1);
// return
return $arr;
}
// encode to UTF-8 when required
function safe_iptc_tag($val){
$val = @substr($val, 0, 1000);
return @mb_detect_encoding($val, 'UTF-8', true) ? $val : @utf8_encode($val);
}
// get IPTC
function get_iptc($image_info){
if(!$image_info || !isset($image_info['APP13']) || !function_exists('iptcparse')) return;
$app13 = @iptcparse($image_info['APP13']);
if(empty($app13)) return;
$iptc = array();
// loop title, headline, description, creator, credit, copyright, keywords, city, sub-location and province-state
foreach (['title'=>'005', 'headline'=>'105', 'description'=>'120', 'creator'=>'080', 'credit'=>'110', 'copyright'=>'116', 'keywords'=>'025', 'city'=>'090', 'sub-location'=>'092', 'province-state'=>'095'] as $name => $code) {
if(isset($app13['2#' . $code][0]) && !empty($app13['2#' . $code][0])) $iptc[$name] = $name === 'keywords' ? $app13['2#' . $code] : safe_iptc_tag($app13['2#' . $code][0]);
}
// return IPTC
return $iptc;
}
// get exif
function get_exif($path){
if(!function_exists('exif_read_data')) return;
$exif_data = @exif_read_data($path, 'ANY_TAG', 0); // @exif_read_data($path);
if(empty($exif_data) || !is_array($exif_data)) return;
$exif = array();
foreach (array('DateTime', 'DateTimeOriginal', 'ExposureTime', 'FNumber', 'FocalLength', 'Make', 'Model', 'Orientation', 'ISOSpeedRatings', 'Software') as $name) {
if(isset($exif_data[$name])) $exif[$name] = trim($exif_data[$name]);
}
if(isset($exif['DateTime'])) $exif['DateTime'] = @strtotime($exif['DateTime']);
if(isset($exif['DateTimeOriginal'])) $exif['DateTimeOriginal'] = @strtotime($exif['DateTimeOriginal']);
/*LensInfo 24-70mm f/?
Lens EF24-70mm f/2.8L USM
LensID 230*/
// ApertureFNumber (f_stop)
if(isset($exif_data['COMPUTED']['ApertureFNumber'])) $exif['ApertureFNumber'] = $exif_data['COMPUTED']['ApertureFNumber'];
// flash
if(isset($exif_data['Flash'])) $exif['Flash'] = ($exif_data['Flash'] & 1) != 0;
// GPS
$gps = get_image_location($exif_data);
if(!empty($gps)) $exif['gps'] = $gps;
// return
return $exif;
}
// exif GPS / get_image_location
function get_image_location($exif) {
$arr = array();
foreach (array('GPSLatitude', 'GPSLongitude') as $key) {
if(!isset($exif[$key]) || !isset($exif[$key.'Ref'])) return false;
$coordinate = $exif[$key];
if(is_string($coordinate)) $coordinate = array_map('trim', explode(',', $coordinate));
for ($i = 0; $i < 3; $i++) {
$part = explode('/', $coordinate[$i]);
if (count($part) == 1) {
$coordinate[$i] = $part[0];
} else if (count($part) == 2) {
if($part[1] == 0) return false; // can't be 0 / invalid GPS
$coordinate[$i] = floatval($part[0])/floatval($part[1]);
} else {
$coordinate[$i] = 0;
}
}
list($degrees, $minutes, $seconds) = $coordinate;
$sign = ($exif[$key.'Ref'] == 'W' || $exif[$key.'Ref'] == 'S') ? -1 : 1;
$arr[] = $sign * ($degrees + $minutes/60 + $seconds/3600);
}
return $arr;
}
/*function get_image_location($exif){
$arr = array('GPSLatitudeRef', 'GPSLatitude', 'GPSLongitudeRef', 'GPSLongitude');
foreach ($arr as $val) {
if(!isset($exif[$val])) return false;
}
$GPSLatitudeRef = $exif[$arr[0]];
$GPSLatitude = $exif[$arr[1]];
$GPSLongitudeRef= $exif[$arr[2]];
$GPSLongitude = $exif[$arr[3]];
$lat_degrees = count($GPSLatitude) > 0 ? gps2Num($GPSLatitude[0]) : 0;
$lat_minutes = count($GPSLatitude) > 1 ? gps2Num($GPSLatitude[1]) : 0;
$lat_seconds = count($GPSLatitude) > 2 ? gps2Num($GPSLatitude[2]) : 0;
$lon_degrees = count($GPSLongitude) > 0 ? gps2Num($GPSLongitude[0]) : 0;
$lon_minutes = count($GPSLongitude) > 1 ? gps2Num($GPSLongitude[1]) : 0;
$lon_seconds = count($GPSLongitude) > 2 ? gps2Num($GPSLongitude[2]) : 0;
$lat_direction = ($GPSLatitudeRef == 'W' or $GPSLatitudeRef == 'S') ? -1 : 1;
$lon_direction = ($GPSLongitudeRef == 'W' or $GPSLongitudeRef == 'S') ? -1 : 1;
$latitude = $lat_direction * ($lat_degrees + ($lat_minutes / 60) + ($lat_seconds / (60*60)));
$longitude = $lon_direction * ($lon_degrees + ($lon_minutes / 60) + ($lon_seconds / (60*60)));
return array($latitude, $longitude);
}
function gps2Num($coordPart){
$parts = explode('/', $coordPart);
if(count($parts) <= 0) return 0;
if(count($parts) == 1) return $parts[0];
if($parts[1] == 0) return 0;
return floatval($parts[0]) / floatval($parts[1]);
}*/
//
function get_files_data($dir, $url_path = false, &$dirsize = 0, &$files_count = 0, &$images_count = 0, &$preview = false){
// scandir
$filenames = scandir($dir, SCANDIR_SORT_NONE);
if(empty($filenames)) return array();
$items = array();
// look for folder_preview_default (might be excluded in loop)
if(config::$config['folder_preview_default'] && in_array(config::$config['folder_preview_default'], $filenames)) $preview = config::$config['folder_preview_default'];
// loop filenames
foreach($filenames as $filename) {
//
if($filename === '.' || $filename === '..') continue;
$path = $dir . '/' . $filename;
// paths
$realpath = real_path($path); // differs from $path only if is symlinked
if(!$realpath) continue; // no real path for any reason, for example symlink dead
$symlinked = $realpath !== $path; // path is symlinked at some point
// filetype
$filetype = filetype($realpath);
$is_dir = $filetype === 'dir' ? true : false;
// exclude
if(is_exclude($path, $is_dir, $symlinked)) continue; // exclude
if($symlinked && is_exclude($realpath, $is_dir, $symlinked)) continue; // exclude check again symlink realpath
// vars
if(!$is_dir) $files_count ++; // files count
$is_link = $symlinked ? is_link($path) : false; // symlink
$basename = $is_link ? (basename($realpath) ?: $filename) : $filename;
$filemtime = filemtime($realpath);
$is_readable = is_readable($realpath);
$filesize = $is_dir ? false : filesize($realpath);
if($filesize) $dirsize += $filesize;
// url_path / symlink
$item_url_path = $symlinked ? get_url_path($realpath) : false; // url_path from realpath if symlinked
if(!$item_url_path && $url_path) $item_url_path = $url_path . ($url_path === '/' ? '' : '/') . ($is_link ? basename($path) : $basename);
// root path // path relative to config::$root
if(!$symlinked || is_within_root($realpath)){
$root_path = root_relative($realpath);
// path is symlinked and !is_within_root(), get path-relative
} else {
// root path to symlink
$root_path = root_relative($path);
// check for symlink loop
if($is_link && $is_dir && $path && $root_path) {
$basename_path = basename($root_path);
if($basename_path && preg_match('/(\/|^)' . $basename_path. '\//', $root_path)){
$loop_path = '';
$segments = explode('/', $root_path);
array_pop($segments);
foreach ($segments as $segment) {
$loop_path .= ($loop_path ? '/' : '') . $segment;
if($segment !== $basename_path) continue;
$loop_abs_path = root_absolute($loop_path);
if(!is_link($loop_abs_path) || $realpath !== real_path($loop_abs_path)) continue;
$root_path = $loop_path;
$item_url_path = get_url_path($loop_abs_path) ?: $item_url_path; // new symlink is within doc_root
break;
}
}
}
}
// add properties
$item = array(
'basename' => $basename,
'fileperms' => substr(sprintf('%o', fileperms($realpath)), -4),
'filetype' => $filetype,
'filesize' => $filesize,
'is_readable' => $is_readable,
'is_writeable' => is_writeable($realpath),
'is_link' => $is_link,
'is_dir' => $is_dir,
'mtime' => $filemtime,
'path' => $root_path
);
// optional props
//$ext = !$is_dir ? pathinfo($realpath, PATHINFO_EXTENSION) : false;
$ext = !$is_dir ? substr(strrchr($realpath, '.'), 1) : false;
if($ext) {
$ext = strtolower($ext);
$item['ext'] = $ext;
}
$mime = $is_dir ? 'directory' : ($is_readable && (!$ext || $ext === 'ts' || config::$config['get_mime_type']) ? get_mime($realpath) : false);
if($mime) $item['mime'] = $mime;
if($item_url_path) $item['url_path'] = $item_url_path;
// image / check from mime, fallback to extension
$is_image = $is_dir ? false : ($mime ? (strtok($mime, '/') === 'image' && !strpos($mime, 'svg')) : in_array($ext, array('gif','jpg','jpeg','jpc','jp2','jpx','jb2','png','swf','psd','bmp','tiff','tif','wbmp','xbm','ico','webp')));
if($is_image){
// imagesize
$imagesize = $is_readable ? @getimagesize($realpath, $info) : false;
// image count and icon
$images_count ++;
$item['icon'] = 'image';
// is imagesize
if(!empty($imagesize) && is_array($imagesize)){
// set folder_preview
if(!$preview && in_array($ext, array('gif','jpg','jpeg','png'))) $preview = $basename;
// start image array
$image = array();
foreach (array(0 => 'width', 1 => 'height', 2 => 'type', 'bits' => 'bits', 'channels' => 'channels', 'mime' => 'mime') as $key => $name) if(isset($imagesize[$key])) $image[$name] = $imagesize[$key];
// mime from image
if(!$mime && isset($image['mime'])) $item['mime'] = $image['mime'];
// IPTC
$iptc = $info ? get_iptc($info) : false;
if(!empty($iptc)) $image['iptc'] = $iptc;
// EXIF
$exif = get_exif($realpath);
if(!empty($exif)) {
$image['exif'] = $exif;
if(isset($exif['DateTimeOriginal'])) $item['DateTimeOriginal'] = $exif['DateTimeOriginal'];
// invert width/height if exif orientation
if(isset($exif['Orientation']) && $exif['Orientation'] > 4 && $exif['Orientation'] < 9){
$image['width'] = $imagesize[1];
$image['height'] = $imagesize[0];
}
}
// image resize cache direct
if(config::$image_resize_cache_direct){
$resize1 = get_image_cache_path($realpath, config::$config['image_resize_dimensions'], $filesize, $filemtime);
if(file_exists($resize1)) $image['resize' . config::$config['image_resize_dimensions']] = get_url_path($resize1);
$retina = config::$image_resize_dimensions_retina;
if($retina){
$resize2 = get_image_cache_path($realpath, $retina, $filesize, $filemtime);
if(file_exists($resize2)) $image['resize' . $retina] = get_url_path($resize2);
}
}
// add image to item
$item['image'] = $image;
// get real mime if getimagesize fails. Could be non-image disguised as image extension
} else if($is_readable && !$mime){
$mime = get_mime($realpath);
if($mime) {
$item['mime'] = $mime;
if(strtok($mime, '/') !== 'image'){ // unset images_count and icon because is not image after all
$images_count --;
unset($item['icon']);
}
}
}
}
// add to items with basename as key
$items[$basename] = $item;
}
// Sort dirs on top and natural case sort / need to do in JS anyway
uasort($items, function($a, $b){
if(!config::$config['sort_dirs_first'] || $a['is_dir'] === $b['is_dir']) return strnatcasecmp($a['basename'], $b['basename']);
return $b['is_dir'] ? 1 : -1;
});
//
return $items;
}
// get files
function get_files($dir){
// invalid $dir
if(!$dir) json_error('Invalid directory');
// cache
$cache = get_dir_cache_path(real_path($dir));
// read cache or get dir and cache
if(!read_file($cache, 'application/json', 'files json served from cache')) {
json_cache(get_dir($dir, true), 'files json created' . ($cache ? ' and cached' : ''), $cache);
}
}
/* start here */
function post($param){
return isset($_POST[$param]) && !empty($_POST[$param]) ? $_POST[$param] : false;
}
function get($param){
return isset($_GET[$param]) && !empty($_GET[$param]) ? $_GET[$param] : false;
}
function json_cache($arr = array(), $msg = false, $cache = true){
$json = empty($arr) ? '{}' : json_encode($arr, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_PARTIAL_OUTPUT_ON_ERROR);
if(empty($json)) json_error(json_last_error() ? json_last_error_msg() : 'json_encode() error');
if($cache) @file_put_contents($cache, $json);
if($msg) header('files-msg: ' . $msg . ' [' . header_memory_time() . ']');
header('content-type: application/json');
echo $json;
}
function json_error($error = 'Error'){
json_exit(array('error' => $error));
}
function json_success($success = 'Success'){
json_exit(array('success' => $success));
}
function json_toggle($success, $error){
json_exit(array_filter(array('success' => $success, 'error' => empty($success) ? $error : 0)));
}
function json_exit($arr = array()){
header('content-type: application/json');
exit(json_encode($arr));
}
function error($msg, $code = false){
// 400 Bad Request, 403 Forbidden, 401 Unauthorized, 404 Not Found, 500 Internal Server Error
if($code) http_response_code($code);
header('content-type: text/html');
header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0, s-maxage=0');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
exit('<h2>Error</h2>' . $msg);
}
// get valid menu cache
function get_valid_menu_cache($cache){
if(!$cache || !file_exists($cache)) return;
$json = @file_get_contents($cache);
if(empty($json)) return;
if(!config::$config['menu_cache_validate']) return $json;
$arr = @json_decode($json, true);
if(empty($arr)) return;
foreach ($arr as $key => $val) {
$path = $val['path'];
if(strpos($path, '/') !== false && $val['mtime'] !== @filemtime(root_absolute($path))) return; // skip shallow 1st level dirs, and compare filemtime
}
return $json;
}
// get root dirs
function get_root_dirs(){
$root_dirs = glob(config::$root . '/*', GLOB_ONLYDIR|GLOB_NOSORT);
if(empty($root_dirs)) return array();
return array_filter($root_dirs, function($dir){
return !is_exclude($dir, true, is_link($dir));
});
}
// get menu cache hash
function get_menu_cache_hash($root_dirs){
$mtime_count = filemtime(config::$root);
foreach ($root_dirs as $root_dir) $mtime_count += filemtime($root_dir);
return substr(md5(config::$doc_root . config::$__dir__ . config::$root), 0, 6) . '.' . substr(md5(config::$version . config::$config['cache_key'] . config::$config['menu_max_depth'] . config::$config['menu_load_all'] . (config::$config['menu_load_all'] ? config::$config['files_exclude'] . config::$image_resize_cache_direct : '') . config::$has_login . config::$config['dirs_exclude'] . config::$config['menu_sort']), 0, 6) . '.' . $mtime_count;
}
// get dirs
function dirs(){
// get menu_cache_hash
if(config::$config['cache']){
$menu_cache_hash = post('menu_cache_hash'); // get menu cache hash
$menu_cache_arr = $menu_cache_hash ? explode('.', $menu_cache_hash) : false;
if(!$menu_cache_arr ||
count($menu_cache_arr) !== 3 ||
strlen($menu_cache_arr[0]) !== 6 ||
strlen($menu_cache_arr[1]) !== 6 ||
!is_numeric($menu_cache_arr[2])
) json_error('Invalid menu cache hash'); // early exit
}
$cache = config::$config['cache'] ? config::$cache_path . '/menu/' . $menu_cache_hash . '.json' : false; // get cache path
$json = $cache ? get_valid_menu_cache($cache) : false; // get valid json menu cache
// $json is valid from menu cache file
if($json){
header('content-type: application/json');
header('files-msg: valid menu cache hash [' . $menu_cache_hash . ']' . (!config::$config['menu_cache_validate'] ? '[deep validation disabled]' : '') . '[' . header_memory_time() . ']');
echo (post('localstorage') ? '{"localstorage":"1"}' : $json);
// reload dirs
} else {
json_cache(get_dirs(config::$root), 'dirs reloaded' . ($cache ? ' and cached.' : ' [cache disabled]'), $cache);
}
}
// include file html, php, css, js
function get_include($file){
if(!config::$storage_path) return;
$path = config::$storage_path . '/' . $file;
if(!file_exists($path)) return;
$ext = pathinfo($path, PATHINFO_EXTENSION);
if(in_array($ext, ['html', 'php'])) return include $path;
if(!config::$storage_is_within_doc_root) return;
$src = get_url_path($path) . '?' . filemtime($path);
if($ext === 'js') echo '<script src="' . $src . '"></script>';
if($ext === 'css') echo '<link href="' . $src . '" rel="stylesheet">';
}
// POST
if(post('action')){
// post action
$action = post('action');
//
new config();
// filemanager actions [beta]
if($action === 'fm') {
// validate task
$task = post('task');
if(empty($task) || !isset(config::$config['allow_' . $task]) || !config::$config['allow_' . $task]) json_error('invalid task');
// demo_mode
if(config::$config['demo_mode']) json_error('Action not allowed in demo mode');
// license required for file manager action
if(!config::$config['license_key']) json_error('License required!');
// valid path / path must be inside assigned root
$is_dir = post('is_dir');
$path = valid_root_path(post('path'), $is_dir);
if(empty($path)) json_error('invalid path ' . post('path'));
$path = real_path($path); // in case of symlink path
// name_is_allowed / trim name, fail if empty or dodgy characters, mkfile, mkdir, rename, duplicate
function name_is_allowed($name){
$name = $name ? trim($name) : false; // trim
// block empty / <>:"'/\|?*# chars / .. / endswith .
if(empty($name) || preg_match('/[<>:"\'\/\\\|?*#]|\.\.|\.$/', $name)) json_error('invalid name ' . $name);
return $name; // return valid trimmed name
}
// filemanager json_toggle
function fm_json_toggle($success, $error){
fm_json_exit($success, array_filter(array('success' => $success, 'error' => empty($success) ? $error : 0)));
}
// filemanager json_exit / includes feature to invalidate X3 cache if $x3_path
function fm_json_exit($success, $arr){
if($success && config::$x3_path) touch(config::$x3_path . '/app/x3.inc.php');
json_exit($arr);
}
// UPLOAD
if($task === 'upload'){
// upload path must be dir
if(!$is_dir) json_error('invalid dir ' . post('path'));
// upload path must be writeable
if(!is_writable($path)) json_error('upload dir ' . post('path') . ' is not writeable');
// get $_FILES['file']
$file = isset($_FILES) && isset($_FILES['file']) && is_array($_FILES['file']) ? $_FILES['file'] : false;
// invalid $_FILES['file']
if(empty($file) || !isset($file['error']) || is_array($file['error'])) json_error('invalid $_FILES[]');
// PHP meaningful file upload errors / https://www.php.net/manual/en/features.file-upload.errors.php
if($file['error'] !== 0) {
$upload_errors = array(
1 => 'Uploaded file exceeds upload_max_filesize directive in php.ini',
2 => 'Uploaded file exceeds MAX_FILE_SIZE directive specified in the HTML form',
3 => 'The uploaded file was only partially uploaded',
4 => 'No file was uploaded',
6 => 'Missing a temporary folder',
7 => 'Failed to write file to disk.',
8 => 'A PHP extension stopped the file upload.'
);
json_error(isset($upload_errors[$file['error']]) ? $upload_errors[$file['error']] : 'unknown error');
}
// invalid $file['size']
if(!isset($file['size']) || empty($file['size'])) json_error('invalid file size');
// $file['size'] must not exceed $config['upload_max_filesize']
if(config::$config['upload_max_filesize'] && $file['size'] > config::$config['upload_max_filesize']) json_error('File size [' . $file['size'] . '] exceeds upload_max_filesize option [' . config::$config['upload_max_filesize'] . ']');
// filename
$filename = $file['name'];
// security: slashes are never ever allowed in filenames / always basenamed() but just in case
if(strpos($filename, '/') !== false || strpos($filename, '\\') !== false) json_error('Illegal \slash/ in filename ' . $filename);
// allow only valid file types from config::$config['upload_allowed_file_types'] / 'image/*, .pdf, .mp4'
$allowed_file_types = !empty(config::$config['upload_allowed_file_types']) ? array_filter(array_map('trim', explode(',', config::$config['upload_allowed_file_types']))) : false;
if(!empty($allowed_file_types)){
$mime = get_mime($file['tmp_name']) ?: $file['type']; // mime from PHP or upload[type]
$ext = strrchr(strtolower($filename), '.');
$is_valid = false;
// check if extension match || wildcard match mime type image/*
foreach ($allowed_file_types as $allowed_file_type) if($ext === ('.'.ltrim($allowed_file_type, '.')) || fnmatch($allowed_file_type, $mime)) {
$is_valid = true;
break;
}
if(!$is_valid) json_error('invalid file type ' . $filename);
// extra security: check if image is image
if(function_exists('exif_imagetype') && in_array($ext, ['.gif', '.jpeg', '.jpg', '.png', '.swf', '.psd', '.bmp', '.tif', '.tiff', 'webp']) && !@exif_imagetype($file['tmp_name'])) json_error('invalid image type ' . $filename);
}
// file naming if !overwrite and file exists
if(config::$config['upload_exists'] !== 'overwrite' && file_exists("$path/$filename")){
// fail if !increment / 'upload_exists' => 'fail' || false || '' empty
if(config::$config['upload_exists'] !== 'increment') json_error("$filename already exists");
// increment filename / 'upload_exists' => 'increment'
$name = pathinfo($filename, PATHINFO_FILENAME);
$ext = pathinfo($filename, PATHINFO_EXTENSION);
$inc = 1;
while(file_exists($path . '/' . $name . '-' . $inc . '.' . $ext)) $inc ++;
$filename = $name . '-' . $inc . '.' . $ext;
}
// all is well! attempt to move_uploaded_file()
if(@move_uploaded_file($file['tmp_name'], "$path/$filename")) fm_json_exit(true, array(
'success' => true,
'filename' => $filename, // return filename in case it was incremented or renamed
'url' => get_url_path("$path/$filename") // for usage with showLinkToFileUploadResult
));
// error if failed to move uploaded file
json_error('failed to move_uploaded_file()');
// DELETE
} else if($task === 'delete'){
// dir recursive
if($is_dir){
// success/fail count
$success = 0;
$fail = 0;
// recursive rmdir
function rrmdir($dir, &$success, &$fail) {
//global $success, $fail;
if(!is_readable($dir)) return $fail ++;
$files = array_diff(scandir($dir), array('.','..'));
if(!empty($files)) foreach ($files as $file) {
is_dir("$dir/$file") ? rrmdir("$dir/$file", $success, $fail) : (@unlink("$dir/$file") ? $success++ : $fail++);
}
@rmdir($dir) ? $success ++ : $fail ++;
}
// recursive rmdir start
rrmdir($path, $success, $fail);
// response with partial success/fail count or error if there is !$success
fm_json_exit($success, array_filter(array('success' => $success, 'fail' => $fail, 'error' => (empty($success) ? 'Failed to delete dir' : 0))));
// single file
} else {
fm_json_toggle(@unlink($path), 'PHP unlink() failed');
}
// new_folder || new_file
} else if($task === 'new_folder' || $task === 'new_file'){
if(!$is_dir) json_error('invalid dir ' . post('path')); // parent path must be dir
if(!is_writable($path)) json_error(post('path') . ' is not writeable.'); // dir must be writeable
$name = name_is_allowed(post('name')); // trim and check valid
$file_path = $path . '/' . $name;
if(file_exists($file_path)) json_error($name . ' already exists');
fm_json_toggle($task === 'new_folder' ? @mkdir($file_path) : @touch($file_path), $task . ' failed');
// rename $path (file or dir)
} else if($task === 'rename'){
if(!is_writable($path)) json_error(post('path') . ' is not writeable.'); // path must be writeable
$name = name_is_allowed(post('name')); // trim and check valid
$new_path = dirname($path) . '/' . $name;
if(file_exists($new_path)) json_error("$name already exists."); // new name exists
// security: prevent renaming 'file.html' to 'file.php' / file must already be *.php when renaming
if(!$is_dir && stripos($path, '.php') === false && stripos($name, '.php') !== false) json_error('cannot rename files to .php');
fm_json_toggle(@rename($path, $new_path), 'PHP rename() failed');
// duplicate file
} else if($task === 'duplicate'){
if($is_dir) json_error('Can\'t duplicate dir');
$parent_dir = dirname($path);
if(!is_writable($parent_dir)) json_error(basename($parent_dir) . ' is not writeable.'); // dir must be writeable
$name = name_is_allowed(post('name')); // trim and check valid
$copy_path = $parent_dir . '/' . $name;
if(file_exists($copy_path)) json_error($name . ' already exists.');
fm_json_toggle(@copy($path, $copy_path), 'PHP copy() failed');
// text / code edit
} else if($task === 'text_edit'){
if($is_dir) json_error('Can\'t write text to directory');
if(!is_writeable($path) || !is_file($path)) json_error('File is not writeable');
$success = isset($_POST['text']) && @file_put_contents($path, $_POST['text']) !== false ? 1 : 0; // text could be '' (empty)
if($success) @touch(dirname($path)); // invalidate any cache by updating parent dir mtime
fm_json_toggle($success, 'PHP file_put_contents() failed');
}
// dirs
} else if($action === 'dirs'){
dirs(post('localstorage'));
// files
} else if($action === 'files'){
if(!isset($_POST['dir'])) json_error('Missing dir parameter');
get_files(valid_root_path($_POST['dir'], true));
// file read
} else if($action === 'file'){
// valid path
$file = valid_root_path(post('file'));
if(!$file) error('Invalid file path');
// read text file
header('content-type:text/plain;charset=utf-8');
if(@readfile(real_path($file)) === false) error('failed to read file ' . post('file'), 500);
// check login
} else if($action === 'check_login'){
json_success(true);
// check updates
} else if($action === 'check_updates'){
$json = @json_decode(@file_get_contents('https://data.jsdelivr.com/v1/package/npm/files.photo.gallery'), true);
$latest = !empty($json) && isset($json['versions'][0]) && version_compare($json['versions'][0], config::$version) > 0 ? $json['versions'][0] : false;
json_exit(array(
'success' => $latest,
'writeable' => $latest && is_writable(__FILE__) // only check writeable if $latest
));
// do update
} else if($action === 'do_update'){
$version = post('version');
if(!$version || version_compare($version, config::$version) <= 0 || !is_writable(__FILE__)) json_error(); // requirements
$get = @file_get_contents('https://cdn.jsdelivr.net/npm/files.photo.gallery@' . $version . '/index.php');
if(empty($get) || strpos($get, '<?php') !== 0) json_error(); // basic validation
json_success(array('success' => @file_put_contents(__FILE__, $get)));
// store license
} else if($action === 'license'){
$key = post('key') ? trim(post('key')) : false;
json_exit(array(
'success' => $key && config::$storage_config_realpath && config::save_config(array('license_key' => $key)),
'md5' => $key ? md5($key) : false
));
// invalid action
} else {
json_error('invalid action: ' . $action);
}
// GET
} else /*if($_SERVER['REQUEST_METHOD'] === 'GET')*/{
// download_dir_zip / download files in directory as zip file
if(get('download_dir_zip')) {
new config();
// check download_dir enabled
if(config::$config['download_dir'] !== 'zip') error('<strong>download_dir</strong> Zip disabled.', 403);
// valid dir
$dir = valid_root_path(get('download_dir_zip'), true);
if(!$dir) error('Invalid download path <strong>' . get('download_dir_zip') . '</strong>', 404);
$dir = real_path($dir); // in case of symlink path
// create zip cache directly in dir (recommended, so that dir can be renamed while zip cache remains)
if(!config::$storage_path || config::$config['download_dir_cache'] === 'dir') {
if(!is_writable($dir)) error('Dir ' . basename($dir) . ' is not writeable.', 500);
$zip_file_name = '_files.zip';
$zip_file = $dir . '/' . $zip_file_name;
// create zip file in storage _files/zip/$dirname.$md5.zip /
} else {
mkdir_or_error(config::$storage_path . '/zip');
$zip_file_name = basename($dir) . '.' . substr(md5($dir), 0, 6) . '.zip';
$zip_file = config::$storage_path . '/zip/' . $zip_file_name;
}
// cached / download_dir_cache && file_exists() && zip is not older than dir time
$cached = !empty(config::$config['download_dir_cache']) && file_exists($zip_file) && filemtime($zip_file) >= filemtime($dir);
// create zip if !cached
if(!$cached){
// use shell zip command instead / probably faster and more robust than PHP / if use, comment out PHP ZipArchive method starting below
// exec('zip ' . $zip_file . ' ' . $dir . '/*.* -j -x _files*', $out, $res);
// check that ZipArchive class exists
if(!class_exists('ZipArchive')) error('Missing PHP ZipArchive class.', 500);
// glob files / must be readable / is_file / !symlink / !is_exclude
$files = array_filter(glob($dir. '/*', GLOB_NOSORT), function($file){
return is_readable($file) && is_file($file) && !is_link($file) && !is_exclude($file, false);
});
// !no files available to zip
if(empty($files)) error('No files to zip!', 400);
// new ZipArchive
$zip = new ZipArchive();
// create new $zip_file
if($zip->open($zip_file, ZipArchive::CREATE | ZIPARCHIVE::OVERWRITE) !== true) error('Failed to create ZIP file ' . $zip_file_name . '.', 500);
// add files to zip / flatten with basename()
foreach($files as $file) $zip->addFile($file, basename($file));
// no files added (for some reason)
if(!$zip->numFiles) error('Could not add any files to ' . $zip_file_name . '.', 500);
// close zip
$zip->close();
// make sure created zip file exists / just in case
if(!file_exists($zip_file)) error('Zip file ' . $zip_file_name . ' does not exist.', 500);
}
// redirect instead of readfile() / might be useful if readfile() fails and/or for caching and performance
/*$zip_url = get_url_path($zip_file);
if($zip_url){
header('Location:' . $zip_url . '?' . filemtime($dir), true, 302);
exit;
}*/
// output headers
if(config::$has_login) {
header('cache-control: must-revalidate, post-check=0, pre-check=0');
header('cache-control: public');
header('expires: 0');
header('pragma: public');
} else {
set_cache_headers();
}
header('content-description: File Transfer');
header('content-disposition: attachment; filename="' . addslashes(basename($dir)) . '.zip"');
$content_length = filesize($zip_file);
header('content-length: ' . $content_length);
header('content-transfer-encoding: binary');
header('content-type: application/zip');
header('files-msg: [' . $zip_file_name . '][' . ($cached ? 'cached' : 'created') . ']');
// ignore user abort so we can delete file also on download cancel
if(empty(config::$config['download_dir_cache'])) @ignore_user_abort(true);
// clear output buffer for large files
while (ob_get_level()) ob_end_clean();
// output zip readfile()
if(!readfile($zip_file)) error('Failed to readfile(' . $zip_file_name . ').', 500);
// delete temp zip file if cache disable
if(empty(config::$config['download_dir_cache'])) @unlink($zip_file);
// folder preview image
} else if(get('preview')){
new config();
// allow only if only if folder_preview_image + load_images + image_resize_enabled
foreach (['folder_preview_image', 'load_images', 'image_resize_enabled'] as $key) if(!config::$config[$key]) error('[' .$key . '] disabled.', 400);
// get real path and validate
$path = valid_root_path(get('preview'), true); // make sure is valid dir
if(!$path) error('Invalid directory.', 404);
// 1. first check for default '_filespreview.jpg' inside dir
$default = config::$config['folder_preview_default'] ? $path . '/' . config::$config['folder_preview_default'] : false;
if($default && file_exists($default)) {
header('files-preview: folder_preview_default found [' . config::$config['folder_preview_default'] . ']');
resize_image($default, config::$config['image_resize_dimensions']);
}
// 2. check preview cache
$cache = config::$cache_path . '/images/preview.' . substr(md5($path), 0, 6) . '.jpg';
// cache file exists
if(file_exists($cache)) {
// make sure cache file is valid (must be newer than dir updated time)
if(filemtime($cache) >= filemtime($path)) read_file($cache, null, 'preview image served from cache', null, true);
// delete expired cache file if is older than dir updated time [silent]
@unlink($cache);
}
// 3. glob images / GLOB_BRACE may fail on some non GNU systems, like Solaris.
$images = @glob($path . '/*.{jpg,JPG,jpeg,JPEG,png,PNG,gif,GIF}', GLOB_NOSORT|GLOB_BRACE);
// loop images to locate first match that is not excluded
if(!empty($images)) foreach ($images as $image) {
if(!is_exclude($image, false)) {
header('files-preview: glob() found [' . basename($image) . ']');
resize_image($image, config::$config['image_resize_dimensions'], $cache); // + clone into $cache
break; exit; // just in case
}
}
// 4. nothing found (no images in dir)
// create empty 1px in $cache, and output (so next check knows dir is empty or has no images, unless updated)
if(imagejpeg(imagecreate(1, 1), $cache)) read_file($cache, 'image/jpeg', '1px placeholder image created and cached', null, true);
// file/image
} else if(isset($_GET['file'])){
new config();
get_file(valid_root_path(get('file')), get('resize'));
// download
} else if(isset($_GET['download'])){
new config();
// valid download
$download = valid_root_path(get('download'));
if(!$download) error('Invalid download path <strong>' . get('download') . '</strong>', 404);
$download = real_path($download); // in case of symlink path
// required for some browsers
if(@ini_get('zlib.output_compression')) @ini_set('zlib.output_compression', 'Off');
// headers
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($download) . '"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($download));
while (ob_get_level()) ob_end_clean();
readfile($download);
// tasks plugin
} else if(get('task')){
// new config with tests
new config(true);
// get plugin
$tasks_path = config::$storage_path . '/plugins/tasks.php';
if(!file_exists($tasks_path)) error("Tasks plugin does not exist at <strong>$tasks_path</strong>", 404);
include $tasks_path;
exit;
// main document
} else {
// new config, with tests
new config(true);
// validate exclude regex
if(config::$config['files_exclude'] && @preg_match(config::$config['files_exclude'], '') === false) error('Invalid files_exclude regex <strong>' . config::$config['files_exclude'] . '</strong>');
if(config::$config['dirs_exclude'] && @preg_match(config::$config['dirs_exclude'], '') === false) error('Invalid dirs_exclude regex <strong>' . config::$config['dirs_exclude'] . '</strong>');
// start path
$start_path = config::$config['start_path'];
if($start_path){
$real_start_path = real_path($start_path);
if(!$real_start_path) error('start_path ' . $start_path . ' does not exist.');
if(!is_within_root($real_start_path)) error('start_path ' . $start_path . ' is not within root dir ' . config::$config['root']);
$start_path = root_relative($real_start_path);
}
// root dirs (if menu)
$root_dirs = config::$config['menu_enabled'] || config::$config['breadcrumbs'] ? get_root_dirs() : false;
$menu_enabled = config::$config['menu_enabled'] && !empty($root_dirs) ? true : false;
$breadcrumbs = config::$config['breadcrumbs'] && !empty($root_dirs) ? true : false;
// get menu cache hash
$menu_cache_hash = false;
$menu_cache_file = false;
if($menu_enabled){
$menu_cache_hash = get_menu_cache_hash($root_dirs);
// menu cache file (if cache, !menu_cache_validate, exists and is within doc root)
if(config::$storage_is_within_doc_root && config::$config['cache'] && !config::$config['menu_cache_validate']) {
$menu_cache_path = config::$cache_path . '/menu/' . $menu_cache_hash . '.json';
$menu_cache_file = file_exists($menu_cache_path) ? get_url_path($menu_cache_path) : false;
if($menu_cache_file) $menu_cache_file .= '?' . filemtime($menu_cache_path);
}
}
// init path
$query = config::$config['history'] && isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING']) ? explode('&', $_SERVER['QUERY_STRING']) : false;
$query_path = $query && strpos($query[0], '=') === false ? rtrim(rawurldecode($query[0]), '/') : false;
$query_path_valid = $query_path ? valid_root_path($query_path, true) : false;
$init_path = $query_path ?: $start_path ?: '';
// init dirs, with files if cache
function get_dir_init($dir){
$cache = get_dir_cache_path(real_path($dir));
if(file_exists($cache)) return json_decode(file_get_contents($cache), true);
return get_dir($dir);
}
// get dirs for root and start path
$dirs = array('' => get_dir_init(config::$root));
if($query_path){
if($query_path_valid) $dirs[$query_path] = get_dir_init($query_path_valid);
} else if($start_path){
$dirs[$start_path] = get_dir_init($real_start_path);
}
// resize image types
$resize_image_types = array('jpeg', 'jpg', 'png', 'gif');
if(version_compare(PHP_VERSION, '5.4.0') >= 0) {
$resize_image_types[] = 'webp';
if(version_compare(PHP_VERSION, '7.2.0') >= 0) $resize_image_types[] = 'bmp';
}
// image resize memory limit
$image_resize_memory_limit = config::$config['image_resize_enabled'] && config::$config['image_resize_memory_limit'] && function_exists('ini_get') ? (int) @ini_get('memory_limit') : 0;
if($image_resize_memory_limit && function_exists('ini_set')) $image_resize_memory_limit = max($image_resize_memory_limit, config::$config['image_resize_memory_limit']);
// wtc
$wtc = config::$config[base64_decode('bGljZW5zZV9rZXk')];
// look for custom language files _files/lang/*.json
function lang_custom() {
$dir = config::$storage_path ? config::$storage_path . '/lang' : false;
$files = $dir && file_exists($dir) ? glob($dir . '/*.json') : false;
if(empty($files)) return false;
$langs = array();
foreach ($files as $path) {
$json = @file_get_contents($path);
$data = !empty($json) ? @json_decode($json, true) : false;
if(!empty($data)) $langs[strtok(basename($path), '.')] = $data;
}
return !empty($langs) ? $langs : false;
}
// exclude some user settings from frontend
$exclude = array_diff_key(config::$config, array_flip(array('root', 'start_path', 'image_resize_cache', 'image_resize_quality', 'image_resize_function', 'image_resize_cache_direct', 'menu_sort', 'menu_load_all', 'cache_key', 'storage_path', 'files_exclude', 'dirs_exclude', 'username', 'password', 'breadcrumbs', 'allow_tasks', 'allow_symlinks', 'menu_recursive_symlinks', 'image_resize_sharpen', 'get_mime_type', 'license_key', 'video_thumbs', 'video_ffmpeg_path', 'folder_preview_default', 'image_resize_dimensions_allowed', 'download_dir_cache')));
// json config
$json_config = array_replace($exclude, array(
'breadcrumbs' => $breadcrumbs,
'script' => basename(__FILE__),
'menu_enabled' => $menu_enabled,
'menu_cache_hash' => $menu_cache_hash,
'menu_cache_file' => $menu_cache_file,
'query_path' => $query_path,
'query_path_valid' => $query_path_valid ? true : false,
'init_path' => $init_path,
'dirs' => $dirs,
'dirs_hash' => config::$dirs_hash,
'resize_image_types' => $resize_image_types,
'image_cache_hash' => config::$config['load_images'] ? substr(md5(config::$doc_root . config::$root . config::$config['image_resize_function'] . config::$config['image_resize_quality']), 0, 6) : false,
'image_resize_dimensions_retina' => config::$image_resize_dimensions_retina,
'location_hash' => md5(config::$root),
'has_login' => config::$has_login,
'version' => config::$version,
'index_html' => intval(get('index_html')),
'server_exif' => function_exists('exif_read_data'),
'image_resize_memory_limit' => $image_resize_memory_limit,
'qrx' => $wtc && is_string($wtc) ? substr(md5($wtc), 0, strlen($wtc)) : false,
'video_thumbs_enabled' => config::$config['video_thumbs'] && config::$config['video_ffmpeg_path'] && config::$config['load_images'] && config::$config['image_resize_cache'] && @function_exists('exec') && @exec('type -P ' . config::$config['video_ffmpeg_path']),
'lang_custom' => lang_custom(),
'x3_path' => config::$x3_path ? get_url_path(config::$x3_path) : false
));
function php_directive_value_to_bytes($directive) {
$val = function_exists('ini_get') ? @ini_get($directive) : false;
if (empty($val) || !is_string($val)) return 0;
preg_match('/^(?<value>\d+)(?<option>[K|M|G]*)$/i', $val, $matches);
$value = (int) $matches['value'];
$option = strtoupper($matches['option']);
if ($option === 'K') {
$value *= 1024;
} elseif ($option === 'M') {
$value *= 1024 * 1024;
} elseif ($option === 'G') {
$value *= 1024 * 1024 * 1024;
}
return $value;
}
// upload options
if(config::$config['allow_upload']) {
if(function_exists('ini_get') && !@ini_get('file_uploads')) error('PHP file_uploads disabled on this server.', 500);
// get max_filesize from all potential limitations (must be > 0)
$max_sizes = array_filter(array(php_directive_value_to_bytes('upload_max_filesize'), php_directive_value_to_bytes('post_max_size'), config::$config['upload_max_filesize']));
// get min val from max_sizes[] || no limit
$json_config['upload_max_filesize'] = !empty($max_sizes) ? min($max_sizes) : 0;
}
// memory and time
header('files-msg: [' . header_memory_time() . ']');
// htmlstart
?>
<!doctype html>
<html<?php echo ' class="menu-' . ($menu_enabled ? 'enabled' : 'disabled sidebar-closed') . '"'; ?>>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="noindex,nofollow">
<title><?php echo $init_path ? basename($init_path) : '/'; ?></title>
<?php get_include('include/head.html'); ?>
<link href="<?php echo config::$assets ?>css/files.css" rel="stylesheet">
<?php get_include('css/custom.css'); ?>
</head>
<body class="body-loading"><svg viewBox="0 0 18 18" class="svg-preloader svg-preloader-active preloader-body"><circle cx="9" cy="9" r="8" pathLength="100" class="svg-preloader-circle"></svg>
<main id="main">
<?php
$topbar_classes = array();
if(config::$config['topbar_sticky']) array_push($topbar_classes, 'topbar-sticky');
if($breadcrumbs) array_push($topbar_classes, 'has-breadcrumbs');
?>
<nav id="topbar"<?php if(!empty($topbar_classes)) echo ' class="' . join(' ', $topbar_classes) . '"'; ?>>
<div id="topbar-top">
<div id="search-container"><input id="search" type="search" placeholder="search" size="1" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off" disabled></div>
<div id="change-layout" class="dropdown"></div>
<div id="change-sort" class="dropdown"></div>
</div>
<?php if($breadcrumbs) { ?>
<div id="topbar-breadcrumbs">
<div class="breadcrumbs-info"></div>
<div id="breadcrumbs"></div>
</div>
<?php } ?>
<div id="topbar-info" class="info-hidden"></div>
<div id="files-sortbar"></div>
</nav>
<!-- files list container -->
<div><div id="files" class="list files-<?php echo config::$config['layout']; ?>"></div></div>
</main>
<?php if($menu_enabled) { ?>
<aside id="sidebar">
<button id="sidebar-toggle" type="button" class="btn-icon"></button>
<div id="sidebar-inner">
<div id="sidebar-topbar"></div>
<div id="sidebar-menu"></div>
</div>
</aside>
<div id="sidebar-bg"></div>
<?php } ?>
<!-- modal -->
<div id="modal-bg"></div>
<div class="modal" id="files_modal" tabindex="-1" role="dialog" data-action="close"></div>
<!-- context menu -->
<div id="contextmenu" class="dropdown-menu"></div>
<!-- custom footer html -->
<?php get_include('include/footer.html'); ?>
<!-- Javascript -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11.1.9/dist/sweetalert2.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js"></script>
<!--<script src="https://cdn.jsdelivr.net/npm/list.js@2.3.1/dist/list.min.js"></script>-->
<script src="https://cdn.jsdelivr.net/npm/@exeba/list.js@2.3.1/dist/list.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/yall-js@3.2.0/dist/yall.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/filesize@8.0.6/lib/filesize.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/screenfull@5.1.0/dist/screenfull.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@1.10.7/dayjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@1.10.7/plugin/localizedFormat.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@1.10.7/plugin/relativeTime.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js"></script>
<?php if(config::$config['download_dir'] === 'files') { ?>
<script src="https://cdn.jsdelivr.net/npm/js-file-downloader@1.1.22/dist/js-file-downloader.min.js"></script>
<?php } ?>
<script>
var _c = <?php echo json_encode($json_config, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE|JSON_PARTIAL_OUTPUT_ON_ERROR); ?>;
var CodeMirror = {};
</script>
<script src="https://cdn.jsdelivr.net/npm/codemirror@5.63.3/mode/meta.js"></script>
<!-- custom -->
<?php get_include('js/custom.js'); ?>
<!-- files -->
<script src="<?php echo config::$assets ?>js/files.js"></script>
</body>
</html>
<?php }}
// htmlend
?>