fix(scanner): resolve dirs via CLI/env/constants; write per-item JSON; skip trash
This commit is contained in:
@@ -1,5 +1,14 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Changes 10/4/2025 v1.3.13
|
||||||
|
|
||||||
|
fix(scanner): resolve dirs via CLI/env/constants; write per-item JSON; skip trash
|
||||||
|
|
||||||
|
- scan_uploads.php now falls back to UPLOAD_DIR/META_DIR from config.php
|
||||||
|
- prevents double slashes in metadata paths; respects app timezone
|
||||||
|
- skips trash/profile_pics and symlinks; writes JSON only when missing
|
||||||
|
- unblocks SCAN_ON_START so externally added files are indexed at boot
|
||||||
|
|
||||||
## Changes 10/4/2025 v1.3.12
|
## Changes 10/4/2025 v1.3.12
|
||||||
|
|
||||||
Fix: robust PUID/PGID handling; optional ownership normalization (closes #43)
|
Fix: robust PUID/PGID handling; optional ownership normalization (closes #43)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { loadAdminConfigFunc } from './auth.js';
|
|||||||
import { showToast, toggleVisibility, attachEnterKeyListener } from './domUtils.js';
|
import { showToast, toggleVisibility, attachEnterKeyListener } from './domUtils.js';
|
||||||
import { sendRequest } from './networkUtils.js';
|
import { sendRequest } from './networkUtils.js';
|
||||||
|
|
||||||
const version = "v1.3.12";
|
const version = "v1.3.13";
|
||||||
const adminTitle = `${t("admin_panel")} <small style="font-size:12px;color:gray;">${version}</small>`;
|
const adminTitle = `${t("admin_panel")} <small style="font-size:12px;color:gray;">${version}</small>`;
|
||||||
|
|
||||||
// ————— Inject updated styles —————
|
// ————— Inject updated styles —————
|
||||||
|
|||||||
@@ -1,63 +1,95 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* scan_uploads.php
|
* scan_uploads.php
|
||||||
* Scans the uploads directory and creates metadata entries for new files/folders using config settings.
|
* Scans the uploads directory and creates metadata entries for new files/folders.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once __DIR__ . '/../config/config.php';
|
require_once __DIR__ . '/../config/config.php';
|
||||||
|
|
||||||
if (!isset($config['upload_dir']) || !isset($config['metadata_dir'])) {
|
// Resolve directories from CLI opts, env, or config.php constants (in that order).
|
||||||
die("Missing configuration for upload_dir or metadata_dir\n");
|
$opt = getopt('', ['upload-dir::','metadata-dir::']) ?: [];
|
||||||
|
$uploadDir = $opt['upload-dir'] ?? getenv('upload_dir') ?? getenv('UPLOAD_DIR') ?? (defined('UPLOAD_DIR') ? UPLOAD_DIR : null);
|
||||||
|
$metadataDir = $opt['metadata-dir'] ?? getenv('metadata_dir') ?? getenv('META_DIR') ?? (defined('META_DIR') ? META_DIR : null);
|
||||||
|
|
||||||
|
if (!$uploadDir || !$metadataDir) {
|
||||||
|
fwrite(STDERR, "Missing configuration for upload_dir or metadata_dir\n");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$uploadDir = $config['upload_dir'];
|
// Normalize with exactly one trailing slash
|
||||||
$metadataDir = $config['metadata_dir'];
|
$uploadDir = rtrim($uploadDir, '/\\') . '/';
|
||||||
date_default_timezone_set('UTC');
|
$metadataDir = rtrim($metadataDir, '/\\') . '/';
|
||||||
|
|
||||||
|
// Respect the app-wide timezone already set in config.php (do NOT force UTC here)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively list files and folders under $dir.
|
||||||
|
* Skips symlinks and internal folders we don't want to index.
|
||||||
|
*/
|
||||||
|
function scanDirectory(string $dir): array {
|
||||||
|
$entries = @scandir($dir);
|
||||||
|
if ($entries === false) return [];
|
||||||
|
|
||||||
function scanDirectory($dir) {
|
|
||||||
$items = array_diff(scandir($dir), ['.', '..']);
|
|
||||||
$results = [];
|
$results = [];
|
||||||
|
foreach ($entries as $name) {
|
||||||
|
if ($name === '.' || $name === '..') continue;
|
||||||
|
$path = $dir . $name;
|
||||||
|
|
||||||
foreach ($items as $item) {
|
// Skip symlinks to avoid loops
|
||||||
$path = $dir . DIRECTORY_SEPARATOR . $item;
|
if (is_link($path)) continue;
|
||||||
$results[] = $path;
|
|
||||||
|
|
||||||
|
// Recurse into directories
|
||||||
if (is_dir($path)) {
|
if (is_dir($path)) {
|
||||||
$results = array_merge($results, scanDirectory($path));
|
$results[] = $path . '/';
|
||||||
|
$results = array_merge($results, scanDirectory($path . '/'));
|
||||||
|
} else {
|
||||||
|
$results[] = $path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $results;
|
return $results;
|
||||||
}
|
}
|
||||||
|
|
||||||
function metadataPath($filePath, $uploadDir, $metadataDir) {
|
/**
|
||||||
$relativePath = ltrim(str_replace($uploadDir, '', $filePath), '/');
|
* Build the metadata JSON path parallel to uploads/ for a given item.
|
||||||
return $metadataDir . '/' . $relativePath . '.json';
|
*/
|
||||||
|
function metadataPath(string $itemPath, string $uploadDir, string $metadataDir): string {
|
||||||
|
$relative = ltrim(str_replace($uploadDir, '', $itemPath), '/\\');
|
||||||
|
return $metadataDir . $relative . '.json';
|
||||||
}
|
}
|
||||||
|
|
||||||
$allItems = scanDirectory($uploadDir);
|
$allItems = scanDirectory($uploadDir);
|
||||||
|
|
||||||
foreach ($allItems as $item) {
|
foreach ($allItems as $item) {
|
||||||
|
// Derive a relative path (used in metadata and for skip rules)
|
||||||
|
$relative = ltrim(str_replace($uploadDir, '', $item), '/\\');
|
||||||
|
|
||||||
|
// Skip some internal areas under uploads/
|
||||||
|
if (strpos($relative, 'trash/') === 0 || strpos($relative, 'profile_pics/') === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$metaPath = metadataPath($item, $uploadDir, $metadataDir);
|
$metaPath = metadataPath($item, $uploadDir, $metadataDir);
|
||||||
|
|
||||||
if (!file_exists($metaPath)) {
|
if (!file_exists($metaPath)) {
|
||||||
$type = is_dir($item) ? 'folder' : 'file';
|
$isDir = is_dir($item);
|
||||||
$size = is_file($item) ? filesize($item) : 0;
|
|
||||||
|
|
||||||
$metadata = [
|
$metadata = [
|
||||||
'path' => str_replace($uploadDir, '', $item),
|
'path' => rtrim($relative, '/'),
|
||||||
'type' => $type,
|
'type' => $isDir ? 'folder' : 'file',
|
||||||
'size' => $size,
|
'size' => (!$isDir && is_file($item)) ? (int)filesize($item) : 0,
|
||||||
'user' => 'Imported',
|
'user' => 'Imported',
|
||||||
'uploadDate' => date('c')
|
'uploadDate' => date('c'),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!is_dir(dirname($metaPath))) {
|
// Ensure parent directory exists with sane perms (umask from start.sh handles final modes)
|
||||||
mkdir(dirname($metaPath), 0775, true);
|
$parent = dirname($metaPath);
|
||||||
|
if (!is_dir($parent)) {
|
||||||
|
@mkdir($parent, 0775, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
file_put_contents($metaPath, json_encode($metadata, JSON_PRETTY_PRINT));
|
if (@file_put_contents($metaPath, json_encode($metadata, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)) === false) {
|
||||||
echo "Created metadata for: {$item}\n";
|
fwrite(STDERR, "Failed to write metadata: {$metaPath}\n");
|
||||||
|
} else {
|
||||||
|
echo "Created metadata for: {$relative}\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user