mirror of
https://github.com/Terranom674/Piwigo_Bratonien_Tools.git
synced 2026-11-13 23:28:23 +00:00
Compare commits
20
Commits
54a9c97525
...
abd0cc5d21
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
abd0cc5d21 | ||
|
|
fced2eac49 | ||
|
|
14aac0d7a4 | ||
|
|
3f2c1f8ff7 | ||
|
|
7310d70b93 | ||
|
|
ae73840d40 | ||
|
|
a0195b499c | ||
|
|
0372a74ae9 | ||
|
|
dbcc55351c | ||
|
|
f02d2f0239 | ||
|
|
2617175158 | ||
|
|
362d24b89a | ||
|
|
459f233b57 | ||
|
|
1368c8e5b7 | ||
|
|
662d22c533 | ||
|
|
f9188ac5db | ||
|
|
5aab3e52ed | ||
|
|
6bd14d2b9b | ||
|
|
a63d5fe3c3 | ||
|
|
84456de512 |
No files matched your search
@@ -0,0 +1,154 @@
|
|||||||
|
<?php
|
||||||
|
if (!defined('PHPWG_ROOT_PATH'))
|
||||||
|
{
|
||||||
|
die('Hacking attempt!');
|
||||||
|
}
|
||||||
|
|
||||||
|
function bratonien_tools_atomic_cache_remove_tree($root, array &$failed)
|
||||||
|
{
|
||||||
|
if (!file_exists($root) && !is_link($root)) return;
|
||||||
|
|
||||||
|
$iterator = new RecursiveIteratorIterator(
|
||||||
|
new RecursiveDirectoryIterator($root, FilesystemIterator::SKIP_DOTS),
|
||||||
|
RecursiveIteratorIterator::CHILD_FIRST
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($iterator as $item)
|
||||||
|
{
|
||||||
|
$path = $item->getPathname();
|
||||||
|
if ($item->isLink() || $item->isFile())
|
||||||
|
{
|
||||||
|
if (!@unlink($path)) $failed[] = $path;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($item->isDir() && !@rmdir($path))
|
||||||
|
{
|
||||||
|
$failed[] = $path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!@rmdir($root) && is_dir($root)) $failed[] = $root;
|
||||||
|
}
|
||||||
|
|
||||||
|
function bratonien_tools_clear_image_cache_atomic()
|
||||||
|
{
|
||||||
|
global $conf;
|
||||||
|
|
||||||
|
if (!defined('PWG_DERIVATIVE_DIR'))
|
||||||
|
{
|
||||||
|
throw new RuntimeException('PWG_DERIVATIVE_DIR ist nicht definiert.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bratonien_tools_main_cache_process_active() || bratonien_tools_main_cache_is_running())
|
||||||
|
{
|
||||||
|
bratonien_tools_request_main_cache_cancel();
|
||||||
|
if (!bratonien_tools_wait_main_cache_stopped(10.0))
|
||||||
|
{
|
||||||
|
throw new RuntimeException('Der laufende Cache-Aufbau konnte noch nicht beendet werden. Bitte den Abbruch kurz abschließen lassen und erneut leeren.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@unlink(bratonien_tools_main_cache_cancel_file());
|
||||||
|
|
||||||
|
$piwigo_root = realpath(PHPWG_ROOT_PATH);
|
||||||
|
if ($piwigo_root === false)
|
||||||
|
{
|
||||||
|
throw new RuntimeException('Piwigo-Root konnte für die Cache-Sicherheitsprüfung nicht aufgelöst werden.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$cache_root = rtrim(PHPWG_ROOT_PATH, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.trim(PWG_DERIVATIVE_DIR, '/\\');
|
||||||
|
$real_cache_root = realpath($cache_root);
|
||||||
|
if ($real_cache_root === false || !is_dir($real_cache_root))
|
||||||
|
{
|
||||||
|
throw new RuntimeException('Bildcache-Verzeichnis wurde nicht gefunden: '.$cache_root);
|
||||||
|
}
|
||||||
|
|
||||||
|
$root_prefix = rtrim($piwigo_root, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
|
||||||
|
if (strpos(rtrim($real_cache_root, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR, $root_prefix) !== 0)
|
||||||
|
{
|
||||||
|
throw new RuntimeException('Bildcache liegt außerhalb der Piwigo-Installation. Abbruch.');
|
||||||
|
}
|
||||||
|
if (rtrim($real_cache_root, DIRECTORY_SEPARATOR) === rtrim($piwigo_root, DIRECTORY_SEPARATOR))
|
||||||
|
{
|
||||||
|
throw new RuntimeException('Bildcache-Pfad entspricht dem Piwigo-Root. Sicherheitsabbruch.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$before = bratonien_tools_scan_image_cache($real_cache_root);
|
||||||
|
$parent = dirname($real_cache_root);
|
||||||
|
if (!is_dir($parent) || !is_writable($parent))
|
||||||
|
{
|
||||||
|
throw new RuntimeException('Übergeordnetes Bildcache-Verzeichnis ist nicht beschreibbar: '.$parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
$detached = $parent.'/.'.basename($real_cache_root).'.bratonien-clear-'.date('YmdHis').'-'.bin2hex(random_bytes(4));
|
||||||
|
if (file_exists($detached) || is_link($detached))
|
||||||
|
{
|
||||||
|
throw new RuntimeException('Temporäres Cache-Auslagerungsverzeichnis existiert bereits. Abbruch.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Der gesamte bisherige Cache wird in einem einzigen Rename aus dem aktiven
|
||||||
|
// Piwigo-Pfad entfernt. Neue Requests schreiben danach nur noch in den neu
|
||||||
|
// angelegten Cachebaum und können nicht mit dem Löschen des Altbestands
|
||||||
|
// konkurrieren.
|
||||||
|
if (!@rename($real_cache_root, $detached))
|
||||||
|
{
|
||||||
|
throw new RuntimeException('Bildcache konnte nicht atomar aus dem aktiven Pfad ausgelagert werden.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$mode = isset($conf['chmod_value']) ? (int)$conf['chmod_value'] : 0755;
|
||||||
|
$umask = umask(0);
|
||||||
|
$created = @mkdir($real_cache_root, $mode, true);
|
||||||
|
umask($umask);
|
||||||
|
if (!$created && !is_dir($real_cache_root))
|
||||||
|
{
|
||||||
|
// Der aktive Pfad muss in diesem Fehlerfall wiederhergestellt werden.
|
||||||
|
if (!file_exists($real_cache_root) && @rename($detached, $real_cache_root))
|
||||||
|
{
|
||||||
|
throw new RuntimeException('Neuer Bildcache konnte nicht angelegt werden; der bisherige Cache wurde vollständig wiederhergestellt.');
|
||||||
|
}
|
||||||
|
throw new RuntimeException('Neuer Bildcache konnte nicht angelegt und der bisherige Cache nicht automatisch wiederhergestellt werden. Manueller Eingriff erforderlich.');
|
||||||
|
}
|
||||||
|
|
||||||
|
@chmod($real_cache_root, $mode);
|
||||||
|
@file_put_contents($real_cache_root.'/index.htm', 'Not allowed!');
|
||||||
|
|
||||||
|
$failed = array();
|
||||||
|
bratonien_tools_atomic_cache_remove_tree($detached, $failed);
|
||||||
|
|
||||||
|
$active = bratonien_tools_scan_image_cache($real_cache_root);
|
||||||
|
|
||||||
|
bratonien_tools_write_main_cache_status(array(
|
||||||
|
'state'=>'idle',
|
||||||
|
'message'=>'Bildcache wurde atomar geleert. Kein manueller Cache-Aufbau aktiv.',
|
||||||
|
));
|
||||||
|
|
||||||
|
if ($failed)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(sprintf(
|
||||||
|
'Der aktive Bildcache wurde erfolgreich geleert und neu angelegt, aber %d Datei(en)/Verzeichnis(se) des ausgelagerten Altbestands konnten nicht entfernt werden. Erste problematische Stelle: %s',
|
||||||
|
count($failed),
|
||||||
|
$failed[0]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$message = sprintf(
|
||||||
|
'Bildcache atomar geleert: %d alte Datei(en) (%s) entfernt, davon %d Custom-Derivate.',
|
||||||
|
$before['files'],
|
||||||
|
bratonien_tools_format_bytes($before['bytes']),
|
||||||
|
$before['custom']
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($active['files'] > 0)
|
||||||
|
{
|
||||||
|
$message .= sprintf(
|
||||||
|
' Während bzw. unmittelbar nach dem Umschalten wurden bereits %d neue Derivatdatei(en) durch laufende Anfragen erzeugt; diese gehören zum neuen Cache und sind kein Rest des gelöschten Bestands.',
|
||||||
|
$active['files']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$message .= ' Der neu aktive Cache ist zum Abschluss der Prüfung leer.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return array('message'=>$message);
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ if (!defined('PHPWG_ROOT_PATH'))
|
|||||||
}
|
}
|
||||||
|
|
||||||
require_once(BRATONIEN_TOOLS_PATH . 'tools/image_cache.inc.php');
|
require_once(BRATONIEN_TOOLS_PATH . 'tools/image_cache.inc.php');
|
||||||
|
require_once(BRATONIEN_TOOLS_PATH . 'include/cache_clear_atomic.inc.php');
|
||||||
require_once(BRATONIEN_TOOLS_PATH . 'tools/watermark.inc.php');
|
require_once(BRATONIEN_TOOLS_PATH . 'tools/watermark.inc.php');
|
||||||
require_once(BRATONIEN_TOOLS_PATH . 'tools/watermark_profiles.inc.php');
|
require_once(BRATONIEN_TOOLS_PATH . 'tools/watermark_profiles.inc.php');
|
||||||
require_once(BRATONIEN_TOOLS_PATH . 'tools/watermark_settings.inc.php');
|
require_once(BRATONIEN_TOOLS_PATH . 'tools/watermark_settings.inc.php');
|
||||||
@@ -28,7 +29,7 @@ require_once(BRATONIEN_TOOLS_PATH . 'include/webdav_warmup_settings.inc.php');
|
|||||||
function bratonien_tools_get_tools()
|
function bratonien_tools_get_tools()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'image_cache_clear' => array('handler' => 'bratonien_tools_clear_image_cache'),
|
'image_cache_clear' => array('handler' => 'bratonien_tools_clear_image_cache_atomic'),
|
||||||
'image_cache_build' => array('handler' => 'bratonien_tools_start_main_cache_build'),
|
'image_cache_build' => array('handler' => 'bratonien_tools_start_main_cache_build'),
|
||||||
'image_cache_cancel' => array('handler' => 'bratonien_tools_cancel_main_cache_build'),
|
'image_cache_cancel' => array('handler' => 'bratonien_tools_cancel_main_cache_build'),
|
||||||
'image_cache_worker_settings' => array('handler' => 'bratonien_tools_save_cache_worker_settings'),
|
'image_cache_worker_settings' => array('handler' => 'bratonien_tools_save_cache_worker_settings'),
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
if (!defined('PHPWG_ROOT_PATH'))
|
||||||
|
{
|
||||||
|
die('Hacking attempt!');
|
||||||
|
}
|
||||||
|
|
||||||
|
function bratonien_tools_webdav_derivative_cache_valid($target_path, $derivative, $params=null, &$reason=null)
|
||||||
|
{
|
||||||
|
$reason = '';
|
||||||
|
$target_path = (string)$target_path;
|
||||||
|
if ($target_path === '' || !is_file($target_path) || !is_readable($target_path))
|
||||||
|
{
|
||||||
|
$reason = 'missing';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cache_root = PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR;
|
||||||
|
if (strpos($target_path, $cache_root) !== 0)
|
||||||
|
{
|
||||||
|
$reason = 'outside-cache';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearstatcache(true, $target_path);
|
||||||
|
$bytes = @filesize($target_path);
|
||||||
|
if ($bytes === false || $bytes < 1)
|
||||||
|
{
|
||||||
|
$reason = 'empty';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$actual = @getimagesize($target_path);
|
||||||
|
if (!is_array($actual) || (int)($actual[0] ?? 0) < 1 || (int)($actual[1] ?? 0) < 1)
|
||||||
|
{
|
||||||
|
$reason = 'not-image';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_object($derivative) && method_exists($derivative, 'get_size'))
|
||||||
|
{
|
||||||
|
$expected = $derivative->get_size();
|
||||||
|
$expected_width = (int)($expected[0] ?? 0);
|
||||||
|
$expected_height = (int)($expected[1] ?? 0);
|
||||||
|
if ($expected_width > 0 && $expected_height > 0)
|
||||||
|
{
|
||||||
|
if ((int)$actual[0] !== $expected_width || (int)$actual[1] !== $expected_height)
|
||||||
|
{
|
||||||
|
$reason = 'dimension-mismatch:'.(int)$actual[0].'x'.(int)$actual[1].'!='.$expected_width.'x'.$expected_height;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_object($params) && isset($params->last_mod_time))
|
||||||
|
{
|
||||||
|
$mtime = @filemtime($target_path);
|
||||||
|
if ($mtime === false || (int)$mtime < (int)$params->last_mod_time)
|
||||||
|
{
|
||||||
|
$reason = 'stale-params';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$reason = 'valid';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -10,7 +10,9 @@ function bratonien_tools_webdav_materialize_source_info($image_id)
|
|||||||
|
|
||||||
$image_id = (int)$image_id;
|
$image_id = (int)$image_id;
|
||||||
if ($image_id < 1) return null;
|
if ($image_id < 1) return null;
|
||||||
if (array_key_exists($image_id, $cache)) return $cache[$image_id];
|
$warmup_cli = PHP_SAPI === 'cli'
|
||||||
|
&& strpos((string)($_SERVER['HTTP_USER_AGENT'] ?? ''), 'Bratonien-WebDAV-Cache-Warmup/') === 0;
|
||||||
|
if (!$warmup_cli && array_key_exists($image_id, $cache)) return $cache[$image_id];
|
||||||
|
|
||||||
$result = pwg_query('SELECT path, coi FROM '.IMAGES_TABLE.' WHERE id='.$image_id.' LIMIT 1');
|
$result = pwg_query('SELECT path, coi FROM '.IMAGES_TABLE.' WHERE id='.$image_id.' LIMIT 1');
|
||||||
if (!pwg_db_num_rows($result)) return $cache[$image_id] = null;
|
if (!pwg_db_num_rows($result)) return $cache[$image_id] = null;
|
||||||
@@ -126,6 +128,7 @@ function bratonien_tools_webdav_materialize_source_info($image_id)
|
|||||||
'fileid'=>$fileid,
|
'fileid'=>$fileid,
|
||||||
'width'=>$width,
|
'width'=>$width,
|
||||||
'height'=>$height,
|
'height'=>$height,
|
||||||
|
'state_dir'=>$state_dir,
|
||||||
'coi'=>$row['coi'] ?? null,
|
'coi'=>$row['coi'] ?? null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -244,7 +247,7 @@ function bratonien_tools_webdav_materialize_after_signature($image_id, $variant,
|
|||||||
|
|
||||||
function bratonien_tools_webdav_materialize_derivative_url($image_id, $variant, array $info, $after_url='')
|
function bratonien_tools_webdav_materialize_derivative_url($image_id, $variant, array $info, $after_url='')
|
||||||
{
|
{
|
||||||
$url = get_root_url().'plugins/'.BRATONIEN_TOOLS_ID.'/webdav-derivative.php?id='.(int)$image_id.'&variant='.rawurlencode($variant);
|
$url = get_root_url().'plugins/'.BRATONIEN_TOOLS_ID.'/webdav-derivative-guard.php?id='.(int)$image_id.'&variant='.rawurlencode($variant);
|
||||||
if ($after_url !== '')
|
if ($after_url !== '')
|
||||||
{
|
{
|
||||||
$url .= '&after='.rawurlencode(bratonien_tools_webdav_materialize_b64url_encode($after_url));
|
$url .= '&after='.rawurlencode(bratonien_tools_webdav_materialize_b64url_encode($after_url));
|
||||||
|
|||||||
@@ -32,6 +32,25 @@ function bratonien_tools_get_webdav_warmup_settings()
|
|||||||
return $settings;
|
return $settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function bratonien_tools_webdav_warmup_missing_baselines()
|
||||||
|
{
|
||||||
|
if (!function_exists('bratonien_tools_nc_connector_connections') || !function_exists('bratonien_tools_nc_connector_is_webdav'))
|
||||||
|
{
|
||||||
|
return array('Connector-Verbindungen konnten nicht geprüft werden.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$missing = array();
|
||||||
|
foreach (bratonien_tools_nc_connector_connections() as $connection)
|
||||||
|
{
|
||||||
|
if (empty($connection['enabled']) || !bratonien_tools_nc_connector_is_webdav($connection)) continue;
|
||||||
|
$connection_id = (int)($connection['id'] ?? 0);
|
||||||
|
if ($connection_id < 1) continue;
|
||||||
|
$state_file = PHPWG_ROOT_PATH.PWG_LOCAL_DIR.'bratonien-webdav-warmup.connection-'.$connection_id.'.json';
|
||||||
|
if (!is_file($state_file) || !is_readable($state_file)) $missing[] = '#'.$connection_id;
|
||||||
|
}
|
||||||
|
return $missing;
|
||||||
|
}
|
||||||
|
|
||||||
function bratonien_tools_save_webdav_warmup_settings()
|
function bratonien_tools_save_webdav_warmup_settings()
|
||||||
{
|
{
|
||||||
$current = bratonien_tools_get_webdav_warmup_settings();
|
$current = bratonien_tools_get_webdav_warmup_settings();
|
||||||
@@ -41,6 +60,17 @@ function bratonien_tools_save_webdav_warmup_settings()
|
|||||||
$batch_size = max(1, min(50, $batch_size));
|
$batch_size = max(1, min(50, $batch_size));
|
||||||
$periodic_hours = max(1, min(168, $periodic_hours));
|
$periodic_hours = max(1, min(168, $periodic_hours));
|
||||||
|
|
||||||
|
if ($enabled && empty($current['enabled']))
|
||||||
|
{
|
||||||
|
$missing = bratonien_tools_webdav_warmup_missing_baselines();
|
||||||
|
if ($missing)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(
|
||||||
|
'WebDAV-Cache-Warmup bleibt deaktiviert. Bitte zuerst „Jetzt prüfen“ ausführen, damit der bestehende produktive Bestand nur als Ausgangszustand erfasst wird. Fehlende Baseline: '.implode(', ', $missing)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$payload = array(
|
$payload = array(
|
||||||
'enabled'=>$enabled,
|
'enabled'=>$enabled,
|
||||||
'batch_size'=>$batch_size,
|
'batch_size'=>$batch_size,
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ if (!defined('BRATONIEN_TOOLS_PATH'))
|
|||||||
|
|
||||||
require_once(BRATONIEN_TOOLS_PATH.'tools/image_cache.inc.php');
|
require_once(BRATONIEN_TOOLS_PATH.'tools/image_cache.inc.php');
|
||||||
require_once(BRATONIEN_TOOLS_PATH.'include/watermark_engine.inc.php');
|
require_once(BRATONIEN_TOOLS_PATH.'include/watermark_engine.inc.php');
|
||||||
|
require_once(BRATONIEN_TOOLS_PATH.'include/webdav_materialize_runtime.inc.php');
|
||||||
require_once(PHPWG_ROOT_PATH.'include/derivative.inc.php');
|
require_once(PHPWG_ROOT_PATH.'include/derivative.inc.php');
|
||||||
require_once(PHPWG_ROOT_PATH.'admin/include/image.class.php');
|
require_once(PHPWG_ROOT_PATH.'admin/include/image.class.php');
|
||||||
|
|
||||||
@@ -229,6 +230,7 @@ function bratonien_tools_cache_builder_worker($worker_index, $worker_count, $run
|
|||||||
$source_path = $src->get_path();
|
$source_path = $src->get_path();
|
||||||
$image_id = (int)$image_row['id'];
|
$image_id = (int)$image_row['id'];
|
||||||
$metadata = null;
|
$metadata = null;
|
||||||
|
$webdav_source = bratonien_tools_webdav_materialize_source_info($image_id);
|
||||||
|
|
||||||
foreach ($variants as $variant_name => $requested_params)
|
foreach ($variants as $variant_name => $requested_params)
|
||||||
{
|
{
|
||||||
@@ -248,6 +250,28 @@ function bratonien_tools_cache_builder_worker($worker_index, $worker_count, $run
|
|||||||
{
|
{
|
||||||
$derivative = new DerivativeImage($requested_params, $src);
|
$derivative = new DerivativeImage($requested_params, $src);
|
||||||
$target_path = $derivative->get_path();
|
$target_path = $derivative->get_path();
|
||||||
|
|
||||||
|
// WebDAV-Connector-Bilder besitzen absichtlich nur einen Placeholder als
|
||||||
|
// lokale Quelle. Der alte Full-Cache-Builder darf diesen niemals direkt
|
||||||
|
// rendern. Fehlende Connector-Derivate gehören ausschließlich in den
|
||||||
|
// materialisierenden WebDAV-Warmup-/On-Demand-Pfad.
|
||||||
|
if ($webdav_source)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
strpos($target_path, PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR) === 0
|
||||||
|
&& is_file($target_path)
|
||||||
|
&& is_readable($target_path)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
$cached++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$skipped++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (strpos($target_path, PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR) !== 0)
|
if (strpos($target_path, PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR) !== 0)
|
||||||
{
|
{
|
||||||
$skipped++;
|
$skipped++;
|
||||||
|
|||||||
+2
-1
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
Plugin Name: Bratonien Tools
|
Plugin Name: Bratonien Tools
|
||||||
Version: 0.9.7.1.8
|
Version: 0.9.7.1.11
|
||||||
Description: Erweiterbare Administrationswerkzeuge fuer die Bratonien-Piwigo-Installation.
|
Description: Erweiterbare Administrationswerkzeuge fuer die Bratonien-Piwigo-Installation.
|
||||||
Plugin URI: https://github.com/Terranom674/Piwigo_Bratonien_Tools
|
Plugin URI: https://github.com/Terranom674/Piwigo_Bratonien_Tools
|
||||||
Author: Bratonien
|
Author: Bratonien
|
||||||
@@ -17,6 +17,7 @@ define('BRATONIEN_TOOLS_PATH', PHPWG_PLUGINS_PATH . BRATONIEN_TOOLS_ID . '/');
|
|||||||
|
|
||||||
require_once(BRATONIEN_TOOLS_PATH . 'include/watermark_runtime.inc.php');
|
require_once(BRATONIEN_TOOLS_PATH . 'include/watermark_runtime.inc.php');
|
||||||
require_once(BRATONIEN_TOOLS_PATH . 'include/webdav_image_runtime.inc.php');
|
require_once(BRATONIEN_TOOLS_PATH . 'include/webdav_image_runtime.inc.php');
|
||||||
|
require_once(BRATONIEN_TOOLS_PATH . 'include/webdav_cache_validation.inc.php');
|
||||||
require_once(BRATONIEN_TOOLS_PATH . 'include/webdav_materialize_runtime.inc.php');
|
require_once(BRATONIEN_TOOLS_PATH . 'include/webdav_materialize_runtime.inc.php');
|
||||||
require_once(BRATONIEN_TOOLS_PATH . 'include/public_selection.inc.php');
|
require_once(BRATONIEN_TOOLS_PATH . 'include/public_selection.inc.php');
|
||||||
require_once(BRATONIEN_TOOLS_PATH . 'include/picture_navigation.inc.php');
|
require_once(BRATONIEN_TOOLS_PATH . 'include/picture_navigation.inc.php');
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ if ($request === '' || strpos($request, '/i.php?/') !== 0)
|
|||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
$piwigo_root = realpath(dirname(__DIR__, 3));
|
$piwigo_root = realpath(dirname(__DIR__, 4));
|
||||||
if ($piwigo_root === false || !is_file($piwigo_root.'/i.php'))
|
if ($piwigo_root === false || !is_file($piwigo_root.'/i.php'))
|
||||||
{
|
{
|
||||||
fwrite(STDERR, "Piwigo i.php wurde nicht gefunden.\n");
|
fwrite(STDERR, "Piwigo i.php wurde nicht gefunden.\n");
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -Eeuo pipefail
|
|
||||||
|
|
||||||
STATE_DIR="${1:-}"
|
|
||||||
shift || true
|
|
||||||
|
|
||||||
[[ -n "$STATE_DIR" ]] || { echo "Connector-State-Verzeichnis fehlt." >&2; exit 2; }
|
|
||||||
[[ $# -gt 0 ]] || { echo "Warmup-Kommando fehlt." >&2; exit 2; }
|
|
||||||
|
|
||||||
mkdir -p -- "$STATE_DIR"
|
|
||||||
LOCK_FILE="$STATE_DIR/webdav-sync.lock"
|
|
||||||
PRIORITY_FILE="$STATE_DIR/webdav-cache-warmup-priority-sync"
|
|
||||||
|
|
||||||
# Der Connector-Sync nutzt denselben Lock exklusiv. Der Warmup hält ihn für
|
|
||||||
# seinen gesamten Lauf nur lesend/geteilt. Dadurch kann der Placeholder- und
|
|
||||||
# Shadow-Tree während Batch-Download, Piwigo-Aufruf und Restore nicht atomar
|
|
||||||
# unter dem Warmup ausgetauscht werden.
|
|
||||||
exec 9>"$LOCK_FILE"
|
|
||||||
flock -s 9
|
|
||||||
|
|
||||||
COMMAND=("$@")
|
|
||||||
|
|
||||||
set +e
|
|
||||||
"${COMMAND[@]}"
|
|
||||||
result=$?
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Ein Connector-Sync kann während eines bereits laufenden Warmups neue Alben
|
|
||||||
# melden. Der Dispatcher legt dafür nur eine Prioritätsmarke an; er startet
|
|
||||||
# keinen zweiten konkurrierenden Worker. Falls der aktive Lauf die Marke noch
|
|
||||||
# nicht selbst übernehmen konnte, wird sie hier nach seinem sauberen Ende
|
|
||||||
# garantiert nachgeholt. Dadurch geht ein Sofort-Warmup nie verloren.
|
|
||||||
if [[ -f "$PRIORITY_FILE" ]]; then
|
|
||||||
rm -f -- "$PRIORITY_FILE"
|
|
||||||
SYNC_COMMAND=()
|
|
||||||
replaced=0
|
|
||||||
for arg in "${COMMAND[@]}"; do
|
|
||||||
if [[ "$arg" == --mode=* ]]; then
|
|
||||||
SYNC_COMMAND+=("--mode=sync")
|
|
||||||
replaced=1
|
|
||||||
else
|
|
||||||
SYNC_COMMAND+=("$arg")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [[ "$replaced" -eq 0 ]]; then
|
|
||||||
SYNC_COMMAND+=("--mode=sync")
|
|
||||||
fi
|
|
||||||
|
|
||||||
set +e
|
|
||||||
"${SYNC_COMMAND[@]}"
|
|
||||||
sync_result=$?
|
|
||||||
set -e
|
|
||||||
if [[ "$sync_result" -ne 0 ]]; then
|
|
||||||
result="$sync_result"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit "$result"
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
STATE_DIR="${1:-}"
|
||||||
|
shift || true
|
||||||
|
|
||||||
|
[[ -n "$STATE_DIR" ]] || { echo "Connector-State-Verzeichnis fehlt." >&2; exit 2; }
|
||||||
|
[[ $# -gt 0 ]] || { echo "Warmup-Kommando fehlt." >&2; exit 2; }
|
||||||
|
|
||||||
|
PRIORITY_FILE="$STATE_DIR/webdav-cache-warmup-priority-sync"
|
||||||
|
ATTEMPTS=0
|
||||||
|
MAX_ATTEMPTS=3600
|
||||||
|
|
||||||
|
# Der Dispatcher setzt die Prioritätsmarke vor dem Start. Falls bereits ein
|
||||||
|
# Warmup läuft, beendet der zusätzliche Worker sich wegen seines Prozess-Locks
|
||||||
|
# sofort und lässt die Marke unangetastet. Wir probieren deshalb erst dann
|
||||||
|
# erneut, wenn die Marke noch vorhanden ist. Sobald ein Sync-Worker den Lock
|
||||||
|
# tatsächlich übernimmt, entfernt er die Marke selbst und arbeitet den neuen
|
||||||
|
# Bestand ab. Dadurch geht die Sofort-Priorität nicht verloren und es gibt nie
|
||||||
|
# zwei gleichzeitig arbeitende Warmup-Worker derselben Verbindung.
|
||||||
|
while [[ -f "$PRIORITY_FILE" ]]; do
|
||||||
|
ATTEMPTS=$((ATTEMPTS + 1))
|
||||||
|
if [[ "$ATTEMPTS" -gt "$MAX_ATTEMPTS" ]]; then
|
||||||
|
echo "Priorisierter WebDAV-Warmup wartet seit zu langer Zeit auf den aktiven Worker." >&2
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
set +e
|
||||||
|
"$@"
|
||||||
|
result=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [[ "$result" -ne 0 ]]; then
|
||||||
|
exit "$result"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ -f "$PRIORITY_FILE" ]] || exit 0
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -61,6 +61,16 @@ function bratonien_tools_cache_warmup_status_file($connection_id)
|
|||||||
return PHPWG_ROOT_PATH.PWG_LOCAL_DIR.'bratonien-webdav-warmup.status-'.(int)$connection_id.'.json';
|
return PHPWG_ROOT_PATH.PWG_LOCAL_DIR.'bratonien-webdav-warmup.status-'.(int)$connection_id.'.json';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function bratonien_tools_cache_warmup_priority_file($state_dir)
|
||||||
|
{
|
||||||
|
return rtrim((string)$state_dir, '/').'/webdav-cache-warmup-priority-sync';
|
||||||
|
}
|
||||||
|
|
||||||
|
function bratonien_tools_cache_warmup_priority_pending($priority_file)
|
||||||
|
{
|
||||||
|
return is_string($priority_file) && $priority_file !== '' && is_file($priority_file);
|
||||||
|
}
|
||||||
|
|
||||||
function bratonien_tools_cache_warmup_write_json($file, array $payload)
|
function bratonien_tools_cache_warmup_write_json($file, array $payload)
|
||||||
{
|
{
|
||||||
$directory = dirname($file);
|
$directory = dirname($file);
|
||||||
@@ -575,10 +585,16 @@ function bratonien_tools_cache_warmup_stage_pending(array $selected, array $stat
|
|||||||
return $pending;
|
return $pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
function bratonien_tools_cache_warmup_run_stage($connection_id, $stage, array $selected, array &$state, array $credentials, $batch_size)
|
function bratonien_tools_cache_warmup_run_stage($connection_id, $stage, array $selected, array &$state, array $credentials, $batch_size, $priority_file='')
|
||||||
{
|
{
|
||||||
$pending = bratonien_tools_cache_warmup_stage_pending($selected, $state, $stage);
|
$pending = bratonien_tools_cache_warmup_stage_pending($selected, $state, $stage);
|
||||||
if (!$pending) return array('ok'=>true, 'success'=>array(), 'failed'=>0);
|
if (!$pending) return array('ok'=>true, 'success'=>array(), 'failed'=>0, 'preempted'=>false);
|
||||||
|
|
||||||
|
if ($stage === 2 && bratonien_tools_cache_warmup_priority_pending($priority_file))
|
||||||
|
{
|
||||||
|
bratonien_tools_cache_warmup_log('stage2_preempted', array('connection_id'=>$connection_id, 'point'=>'before_first_batch'));
|
||||||
|
return array('ok'=>true, 'success'=>array(), 'failed'=>0, 'preempted'=>true);
|
||||||
|
}
|
||||||
|
|
||||||
$temp_root = PHPWG_ROOT_PATH.'upload/bratonien-webdav-warmup';
|
$temp_root = PHPWG_ROOT_PATH.'upload/bratonien-webdav-warmup';
|
||||||
if (!is_dir($temp_root) && !@mkdir($temp_root, 0775, true) && !is_dir($temp_root)) throw new RuntimeException('Warmup-Temp-Verzeichnis konnte nicht angelegt werden.');
|
if (!is_dir($temp_root) && !@mkdir($temp_root, 0775, true) && !is_dir($temp_root)) throw new RuntimeException('Warmup-Temp-Verzeichnis konnte nicht angelegt werden.');
|
||||||
@@ -652,8 +668,14 @@ function bratonien_tools_cache_warmup_run_stage($connection_id, $stage, array $s
|
|||||||
|
|
||||||
foreach ($downloads as $file) @unlink($file);
|
foreach ($downloads as $file) @unlink($file);
|
||||||
@rmdir($dir);
|
@rmdir($dir);
|
||||||
|
|
||||||
|
if ($stage === 2 && bratonien_tools_cache_warmup_priority_pending($priority_file))
|
||||||
|
{
|
||||||
|
bratonien_tools_cache_warmup_log('stage2_preempted', array('connection_id'=>$connection_id, 'point'=>'after_batch', 'batch'=>$batch_number));
|
||||||
|
return array('ok'=>$failed === 0, 'success'=>$success, 'failed'=>$failed, 'preempted'=>true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return array('ok'=>$failed === 0, 'success'=>$success, 'failed'=>$failed);
|
return array('ok'=>$failed === 0, 'success'=>$success, 'failed'=>$failed, 'preempted'=>false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function bratonien_tools_cache_warmup_run($connection_id, $mode)
|
function bratonien_tools_cache_warmup_run($connection_id, $mode)
|
||||||
@@ -670,6 +692,7 @@ function bratonien_tools_cache_warmup_run($connection_id, $mode)
|
|||||||
$state_dir = rtrim((string)($credentials['config']['state_dir'] ?? ''), '/');
|
$state_dir = rtrim((string)($credentials['config']['state_dir'] ?? ''), '/');
|
||||||
if ($state_dir === '') throw new RuntimeException('Connector-State-Verzeichnis fehlt.');
|
if ($state_dir === '') throw new RuntimeException('Connector-State-Verzeichnis fehlt.');
|
||||||
if (!is_dir($state_dir) && !@mkdir($state_dir, 0750, true) && !is_dir($state_dir)) throw new RuntimeException('Connector-State-Verzeichnis konnte nicht angelegt werden.');
|
if (!is_dir($state_dir) && !@mkdir($state_dir, 0750, true) && !is_dir($state_dir)) throw new RuntimeException('Connector-State-Verzeichnis konnte nicht angelegt werden.');
|
||||||
|
$priority_file = bratonien_tools_cache_warmup_priority_file($state_dir);
|
||||||
|
|
||||||
$process_lock = @fopen($state_dir.'/webdav-cache-warmup.lock', 'c');
|
$process_lock = @fopen($state_dir.'/webdav-cache-warmup.lock', 'c');
|
||||||
if (!$process_lock || !@flock($process_lock, LOCK_EX | LOCK_NB))
|
if (!$process_lock || !@flock($process_lock, LOCK_EX | LOCK_NB))
|
||||||
@@ -681,6 +704,12 @@ function bratonien_tools_cache_warmup_run($connection_id, $mode)
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// Nur der Sync-Worker, der den Prozess-Lock tatsächlich erhalten hat,
|
||||||
|
// konsumiert seine eigene Prioritätsmarke. Ein zweiter Sync-Aufruf während
|
||||||
|
// eines laufenden Workers lässt die Marke stehen, damit der aktive Lauf
|
||||||
|
// Stufe 2 sicher zwischen zwei vollständigen Batches unterbrechen kann.
|
||||||
|
if ($mode === 'sync' && is_file($priority_file)) @unlink($priority_file);
|
||||||
|
|
||||||
$scan = bratonien_tools_cache_warmup_scan($connection_id);
|
$scan = bratonien_tools_cache_warmup_scan($connection_id);
|
||||||
$state = bratonien_tools_cache_warmup_load_state($connection_id);
|
$state = bratonien_tools_cache_warmup_load_state($connection_id);
|
||||||
if ($state === null)
|
if ($state === null)
|
||||||
@@ -723,14 +752,24 @@ function bratonien_tools_cache_warmup_run($connection_id, $mode)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$stage1 = bratonien_tools_cache_warmup_run_stage($connection_id, 1, $selected, $state, $credentials, $settings['batch_size']);
|
$stage1 = bratonien_tools_cache_warmup_run_stage($connection_id, 1, $selected, $state, $credentials, $settings['batch_size'], $priority_file);
|
||||||
$stage2_candidates = array();
|
$stage2_candidates = array();
|
||||||
foreach ($selected as $image_id=>$image)
|
foreach ($selected as $image_id=>$image)
|
||||||
{
|
{
|
||||||
$saved = isset($state['images'][(string)$image_id]) && is_array($state['images'][(string)$image_id]) ? $state['images'][(string)$image_id] : array();
|
$saved = isset($state['images'][(string)$image_id]) && is_array($state['images'][(string)$image_id]) ? $state['images'][(string)$image_id] : array();
|
||||||
if (isset($saved['stage1_signature']) && hash_equals((string)$saved['stage1_signature'], $image['signature'])) $stage2_candidates[$image_id] = $image;
|
if (isset($saved['stage1_signature']) && hash_equals((string)$saved['stage1_signature'], $image['signature'])) $stage2_candidates[$image_id] = $image;
|
||||||
}
|
}
|
||||||
$stage2 = bratonien_tools_cache_warmup_run_stage($connection_id, 2, $stage2_candidates, $state, $credentials, $settings['batch_size']);
|
$stage2 = bratonien_tools_cache_warmup_run_stage($connection_id, 2, $stage2_candidates, $state, $credentials, $settings['batch_size'], $priority_file);
|
||||||
|
|
||||||
|
if (!empty($stage2['preempted']))
|
||||||
|
{
|
||||||
|
bratonien_tools_cache_warmup_status($connection_id, 'preempted', 'Warmup Stufe 2 wurde nach einem vollständigen Batch für neue Sync-Priorität freigegeben.', array(
|
||||||
|
'mode'=>$mode,
|
||||||
|
'stage1_failed'=>(int)$stage1['failed'],
|
||||||
|
'stage2_failed'=>(int)$stage2['failed'],
|
||||||
|
));
|
||||||
|
return ((int)$stage1['failed'] + (int)$stage2['failed']) > 0 ? 2 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($scan['albums'] as $album_id) $state['albums'][(string)$album_id] = array('seen_at'=>time());
|
foreach ($scan['albums'] as $album_id) $state['albums'][(string)$album_id] = array('seen_at'=>time());
|
||||||
if ($mode === 'periodic' || $mode === 'manual') $state['last_periodic_at'] = time();
|
if ($mode === 'periodic' || $mode === 'manual') $state['last_periodic_at'] = time();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ if (PHP_SAPI !== 'cli')
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$piwigo_root = realpath(dirname(__DIR__, 3));
|
$piwigo_root = realpath(dirname(__DIR__, 4));
|
||||||
if ($piwigo_root === false)
|
if ($piwigo_root === false)
|
||||||
{
|
{
|
||||||
fwrite(STDERR, "Piwigo-Root wurde nicht gefunden.\n");
|
fwrite(STDERR, "Piwigo-Root wurde nicht gefunden.\n");
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ if (PHP_SAPI !== 'cli')
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$piwigo_root = realpath(dirname(__DIR__, 2));
|
$piwigo_root = realpath(dirname(__DIR__, 3));
|
||||||
if ($piwigo_root === false)
|
if ($piwigo_root === false)
|
||||||
{
|
{
|
||||||
fwrite(STDERR, "Piwigo-Root wurde nicht gefunden.\n");
|
fwrite(STDERR, "Piwigo-Root wurde nicht gefunden.\n");
|
||||||
@@ -58,15 +58,15 @@ if (!function_exists('exec'))
|
|||||||
}
|
}
|
||||||
|
|
||||||
$worker = realpath(BRATONIEN_TOOLS_PATH.'runtime/lib/webdav-cache-warmup.php');
|
$worker = realpath(BRATONIEN_TOOLS_PATH.'runtime/lib/webdav-cache-warmup.php');
|
||||||
$guard = realpath(BRATONIEN_TOOLS_PATH.'runtime/lib/run-webdav-cache-warmup.sh');
|
$priority_waiter = realpath(BRATONIEN_TOOLS_PATH.'runtime/lib/run-webdav-priority-wait.sh');
|
||||||
if (!$worker || !is_file($worker))
|
if (!$worker || !is_file($worker))
|
||||||
{
|
{
|
||||||
fwrite(STDERR, "WebDAV-Cache-Warmup-Worker wurde nicht gefunden.\n");
|
fwrite(STDERR, "WebDAV-Cache-Warmup-Worker wurde nicht gefunden.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (!$guard || !is_file($guard))
|
if (!$priority_waiter || !is_file($priority_waiter))
|
||||||
{
|
{
|
||||||
fwrite(STDERR, "WebDAV-Cache-Warmup-Schutzskript wurde nicht gefunden.\n");
|
fwrite(STDERR, "WebDAV-Prioritäts-Warter wurde nicht gefunden.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,14 +135,22 @@ foreach (bratonien_tools_nc_connector_connections() as $connection)
|
|||||||
@chmod($priority_file, 0664);
|
@chmod($priority_file, 0664);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Der Guard hält webdav-sync.lock für den gesamten Worker-Lauf geteilt.
|
$worker_command = escapeshellarg(PHP_BINARY).' '.escapeshellarg($worker)
|
||||||
// Dadurch kann der produktive Source-/Shadow-Tree während Download, Swap,
|
|
||||||
// Piwigo-Aufruf und Restore nicht von einem Connector-Sync ersetzt werden.
|
|
||||||
$base = escapeshellarg('/bin/bash').' '.escapeshellarg($guard).' '.escapeshellarg($state_dir)
|
|
||||||
.' '.escapeshellarg(PHP_BINARY).' '.escapeshellarg($worker)
|
|
||||||
.' --connection-id='.$connection_id
|
.' --connection-id='.$connection_id
|
||||||
.' --mode='.escapeshellarg($mode);
|
.' --mode='.escapeshellarg($mode);
|
||||||
|
|
||||||
|
if ($mode === 'sync')
|
||||||
|
{
|
||||||
|
// Ein bereits laufender Worker darf seinen aktuellen Bild-/Batchvorgang
|
||||||
|
// vollständig restaurieren. Der Waiter startet den priorisierten Sync-Lauf
|
||||||
|
// danach automatisch, statt die Prioritätsmarke verloren gehen zu lassen.
|
||||||
|
$base = escapeshellarg('/bin/bash').' '.escapeshellarg($priority_waiter).' '.escapeshellarg($state_dir).' '.$worker_command;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$base = $worker_command;
|
||||||
|
}
|
||||||
|
|
||||||
if ($wait)
|
if ($wait)
|
||||||
{
|
{
|
||||||
$output = array();
|
$output = array();
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
define('PHPWG_ROOT_PATH', '../../');
|
||||||
|
include_once(PHPWG_ROOT_PATH.'include/common.inc.php');
|
||||||
|
require_once(PHPWG_ROOT_PATH.'include/derivative.inc.php');
|
||||||
|
|
||||||
|
if (!defined('BRATONIEN_TOOLS_PATH'))
|
||||||
|
{
|
||||||
|
define('BRATONIEN_TOOLS_ID', basename(__DIR__));
|
||||||
|
define('BRATONIEN_TOOLS_PATH', PHPWG_ROOT_PATH.'plugins/'.BRATONIEN_TOOLS_ID.'/');
|
||||||
|
}
|
||||||
|
require_once(BRATONIEN_TOOLS_PATH.'include/webdav_materialize_runtime.inc.php');
|
||||||
|
|
||||||
|
$image_id = (int)($_GET['id'] ?? 0);
|
||||||
|
if ($image_id < 1)
|
||||||
|
{
|
||||||
|
http_response_code(400);
|
||||||
|
header('Content-Type: text/plain; charset=utf-8');
|
||||||
|
echo 'Ungueltige Derivatanforderung.';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$source = bratonien_tools_webdav_materialize_source_info($image_id);
|
||||||
|
if (!$source)
|
||||||
|
{
|
||||||
|
http_response_code(404);
|
||||||
|
header('Content-Type: text/plain; charset=utf-8');
|
||||||
|
echo 'WebDAV-Bildquelle nicht gefunden.';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$state_dir = rtrim((string)($source['state_dir'] ?? ''), '/');
|
||||||
|
if ($state_dir === '')
|
||||||
|
{
|
||||||
|
http_response_code(503);
|
||||||
|
header('Content-Type: text/plain; charset=utf-8');
|
||||||
|
echo 'Connector-State-Verzeichnis fehlt.';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$lock = @fopen($state_dir.'/webdav-sync.lock', 'c');
|
||||||
|
if (!$lock)
|
||||||
|
{
|
||||||
|
http_response_code(503);
|
||||||
|
header('Content-Type: text/plain; charset=utf-8');
|
||||||
|
echo 'Connector-Sync-Lock konnte nicht geoeffnet werden.';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// On-Demand bleibt parallel zu anderen Bildabrufen moeglich, verhindert aber
|
||||||
|
// fuer die Dauer dieses einzelnen Derivataufrufs einen exklusiven Connector-
|
||||||
|
// Tree-Swap. Der bestehende Bild-Lock im eigentlichen Endpoint koordiniert
|
||||||
|
// weiterhin On-Demand und Warmup fuer dieselbe Bild-ID.
|
||||||
|
if (!@flock($lock, LOCK_SH))
|
||||||
|
{
|
||||||
|
fclose($lock);
|
||||||
|
http_response_code(503);
|
||||||
|
header('Content-Type: text/plain; charset=utf-8');
|
||||||
|
echo 'Connector-Sync-Schutz konnte nicht gesetzt werden.';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
include BRATONIEN_TOOLS_PATH.'webdav-derivative.php';
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
@flock($lock, LOCK_UN);
|
||||||
|
fclose($lock);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user