webdav: stop downloading originals for dimension metadata

This commit is contained in:
Terranom674
2026-08-20 18:11:34 +02:00
parent 8cb4abf81d
commit 419fe56cde

View File

@@ -6,7 +6,7 @@ if (PHP_SAPI !== 'cli')
exit(1); exit(1);
} }
const BRATONIEN_WEBDAV_PREVIEW_VERSION = 3; const BRATONIEN_WEBDAV_PREVIEW_VERSION = 2;
const BRATONIEN_WEBDAV_PREVIEW_MAX_EDGE = 4096; const BRATONIEN_WEBDAV_PREVIEW_MAX_EDGE = 4096;
const BRATONIEN_WEBDAV_PREVIEW_JPEG_QUALITY = 88; const BRATONIEN_WEBDAV_PREVIEW_JPEG_QUALITY = 88;
@@ -32,7 +32,7 @@ function fetch_remote_blob($url, $user, $password)
CURLOPT_HTTPAUTH => CURLAUTH_BASIC, CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_USERPWD => $user.':'.$password, CURLOPT_USERPWD => $user.':'.$password,
CURLOPT_FAILONERROR => false, CURLOPT_FAILONERROR => false,
CURLOPT_USERAGENT => 'Bratonien-Tools-WebDAV-Precache/0.9.6.8.20', CURLOPT_USERAGENT => 'Bratonien-Tools-WebDAV-Precache/0.9.6.8.21',
)); ));
$body = curl_exec($ch); $body = curl_exec($ch);
$errno = curl_errno($ch); $errno = curl_errno($ch);
@@ -46,41 +46,14 @@ function fetch_remote_blob($url, $user, $password)
return (string)$body; return (string)$body;
} }
function original_dimensions($blob)
{
if (class_exists('Imagick'))
{
$image = new Imagick();
try
{
$image->readImageBlob($blob);
$image->setIteratorIndex(0);
if (method_exists($image, 'autoOrientImage')) @$image->autoOrientImage();
$width = (int)$image->getImageWidth();
$height = (int)$image->getImageHeight();
if ($width > 0 && $height > 0) return array($width, $height);
}
finally
{
$image->clear();
$image->destroy();
}
}
$size = function_exists('getimagesizefromstring') ? @getimagesizefromstring($blob) : false;
if (is_array($size) && !empty($size[0]) && !empty($size[1]))
{
return array((int)$size[0], (int)$size[1]);
}
fail_preview('Originalabmessungen konnten nicht ermittelt werden.');
}
function preview_extension_for_entry(array $entry) function preview_extension_for_entry(array $entry)
{ {
$content_type = strtolower(trim((string)($entry['content_type'] ?? ''))); $content_type = strtolower(trim((string)($entry['content_type'] ?? '')));
$path = strtolower((string)($entry['webdav_path'] ?? '')); $path = strtolower((string)($entry['webdav_path'] ?? ''));
if ($content_type === 'image/png' || preg_match('/\.png$/', $path)) return 'png'; if ($content_type === 'image/png' || preg_match('/\.png$/', $path))
{
return 'png';
}
return 'jpg'; return 'jpg';
} }
@@ -108,6 +81,7 @@ function write_preview_imagick($blob, $target, $extension)
$image->setIteratorIndex(0); $image->setIteratorIndex(0);
$image->thumbnailImage(BRATONIEN_WEBDAV_PREVIEW_MAX_EDGE, BRATONIEN_WEBDAV_PREVIEW_MAX_EDGE, true, true); $image->thumbnailImage(BRATONIEN_WEBDAV_PREVIEW_MAX_EDGE, BRATONIEN_WEBDAV_PREVIEW_MAX_EDGE, true, true);
$image->stripImage(); $image->stripImage();
if ($extension === 'png') if ($extension === 'png')
{ {
$image->setImageFormat('png'); $image->setImageFormat('png');
@@ -115,12 +89,16 @@ function write_preview_imagick($blob, $target, $extension)
else else
{ {
$image->setImageBackgroundColor('white'); $image->setImageBackgroundColor('white');
if (method_exists($image, 'mergeImageLayers')) $image = $image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN); if (method_exists($image, 'mergeImageLayers'))
{
$image = $image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
}
$image->setImageFormat('jpeg'); $image->setImageFormat('jpeg');
$image->setImageCompression(Imagick::COMPRESSION_JPEG); $image->setImageCompression(Imagick::COMPRESSION_JPEG);
$image->setImageCompressionQuality(BRATONIEN_WEBDAV_PREVIEW_JPEG_QUALITY); $image->setImageCompressionQuality(BRATONIEN_WEBDAV_PREVIEW_JPEG_QUALITY);
$image->setInterlaceScheme(Imagick::INTERLACE_PLANE); $image->setInterlaceScheme(Imagick::INTERLACE_PLANE);
} }
if (!$image->writeImage($target)) fail_preview('Imagick konnte das Preview nicht schreiben.'); if (!$image->writeImage($target)) fail_preview('Imagick konnte das Preview nicht schreiben.');
} }
finally finally
@@ -134,16 +112,19 @@ function write_preview_gd($blob, $target, $extension)
{ {
$source = @imagecreatefromstring($blob); $source = @imagecreatefromstring($blob);
if (!$source) fail_preview('GD konnte das Bild nicht dekodieren.'); if (!$source) fail_preview('GD konnte das Bild nicht dekodieren.');
try try
{ {
$width = imagesx($source); $width = imagesx($source);
$height = imagesy($source); $height = imagesy($source);
if ($width < 1 || $height < 1) fail_preview('Bildabmessungen sind ungültig.'); if ($width < 1 || $height < 1) fail_preview('Bildabmessungen sind ungültig.');
$scale = min(1, BRATONIEN_WEBDAV_PREVIEW_MAX_EDGE / $width, BRATONIEN_WEBDAV_PREVIEW_MAX_EDGE / $height); $scale = min(1, BRATONIEN_WEBDAV_PREVIEW_MAX_EDGE / $width, BRATONIEN_WEBDAV_PREVIEW_MAX_EDGE / $height);
$target_width = max(1, (int)round($width * $scale)); $target_width = max(1, (int)round($width * $scale));
$target_height = max(1, (int)round($height * $scale)); $target_height = max(1, (int)round($height * $scale));
$preview = imagecreatetruecolor($target_width, $target_height); $preview = imagecreatetruecolor($target_width, $target_height);
if (!$preview) fail_preview('GD konnte die Preview-Arbeitsfläche nicht anlegen.'); if (!$preview) fail_preview('GD konnte die Preview-Arbeitsfläche nicht anlegen.');
try try
{ {
if ($extension === 'png') if ($extension === 'png')
@@ -158,8 +139,15 @@ function write_preview_gd($blob, $target, $extension)
$white = imagecolorallocate($preview, 255, 255, 255); $white = imagecolorallocate($preview, 255, 255, 255);
imagefilledrectangle($preview, 0, 0, $target_width, $target_height, $white); imagefilledrectangle($preview, 0, 0, $target_width, $target_height, $white);
} }
if (!imagecopyresampled($preview, $source, 0, 0, 0, 0, $target_width, $target_height, $width, $height)) fail_preview('GD konnte das Preview nicht skalieren.');
$written = $extension === 'png' ? imagepng($preview, $target, 6) : imagejpeg($preview, $target, BRATONIEN_WEBDAV_PREVIEW_JPEG_QUALITY); if (!imagecopyresampled($preview, $source, 0, 0, 0, 0, $target_width, $target_height, $width, $height))
{
fail_preview('GD konnte das Preview nicht skalieren.');
}
$written = $extension === 'png'
? imagepng($preview, $target, 6)
: imagejpeg($preview, $target, BRATONIEN_WEBDAV_PREVIEW_JPEG_QUALITY);
if (!$written) fail_preview('GD konnte das Preview nicht schreiben.'); if (!$written) fail_preview('GD konnte das Preview nicht schreiben.');
} }
finally finally
@@ -177,9 +165,19 @@ function write_preview($blob, $target, $extension)
{ {
$dir = dirname($target); $dir = dirname($target);
if (!is_dir($dir) && !mkdir($dir, 0755, true) && !is_dir($dir)) fail_preview('Preview-Verzeichnis konnte nicht angelegt werden.'); if (!is_dir($dir) && !mkdir($dir, 0755, true) && !is_dir($dir)) fail_preview('Preview-Verzeichnis konnte nicht angelegt werden.');
if (class_exists('Imagick')) write_preview_imagick($blob, $target, $extension);
elseif (function_exists('imagecreatefromstring') && function_exists('imagejpeg') && function_exists('imagepng')) write_preview_gd($blob, $target, $extension); if (class_exists('Imagick'))
else fail_preview('Weder Imagick noch GD ist für die Preview-Erzeugung verfügbar.'); {
write_preview_imagick($blob, $target, $extension);
}
elseif (function_exists('imagecreatefromstring') && function_exists('imagejpeg') && function_exists('imagepng'))
{
write_preview_gd($blob, $target, $extension);
}
else
{
fail_preview('Weder Imagick noch GD ist für die Preview-Erzeugung verfügbar.');
}
clearstatcache(true, $target); clearstatcache(true, $target);
$size = @getimagesize($target); $size = @getimagesize($target);
@@ -226,7 +224,7 @@ try
$cached = 0; $cached = 0;
$errors = 0; $errors = 0;
foreach ($mapping['files'] as &$entry) foreach ($mapping['files'] as $entry)
{ {
if (!is_array($entry) || (string)($entry['kind'] ?? '') !== 'file') continue; if (!is_array($entry) || (string)($entry['kind'] ?? '') !== 'file') continue;
$webdav_path = trim((string)($entry['webdav_path'] ?? ''), '/'); $webdav_path = trim((string)($entry['webdav_path'] ?? ''), '/');
@@ -236,23 +234,22 @@ try
$key = sha1($webdav_path); $key = sha1($webdav_path);
$target = preview_target_for_entry($cache_dir, $key, $entry); $target = preview_target_for_entry($cache_dir, $key, $entry);
$extension = pathinfo($target, PATHINFO_EXTENSION); $extension = pathinfo($target, PATHINFO_EXTENSION);
$old = $old_state[$key] ?? null; $new_state[$key] = array(
'path' => $webdav_path,
'etag' => $etag,
'format' => $extension,
'version' => BRATONIEN_WEBDAV_PREVIEW_VERSION,
);
$old = $old_state[$key] ?? null;
if ( if (
is_file($target) is_file($target)
&& is_array($old) && is_array($old)
&& (string)($old['etag'] ?? '') === $etag && (string)($old['etag'] ?? '') === $etag
&& (string)($old['format'] ?? '') === $extension && (string)($old['format'] ?? '') === $extension
&& (int)($old['version'] ?? 0) === BRATONIEN_WEBDAV_PREVIEW_VERSION && (int)($old['version'] ?? 0) === BRATONIEN_WEBDAV_PREVIEW_VERSION
&& (int)($old['width'] ?? 0) > 0
&& (int)($old['height'] ?? 0) > 0
) )
{ {
$width = (int)$old['width'];
$height = (int)$old['height'];
$entry['width'] = $width;
$entry['height'] = $height;
$new_state[$key] = array('path'=>$webdav_path, 'etag'=>$etag, 'format'=>$extension, 'version'=>BRATONIEN_WEBDAV_PREVIEW_VERSION, 'width'=>$width, 'height'=>$height);
$cached++; $cached++;
continue; continue;
} }
@@ -261,10 +258,6 @@ try
{ {
$url = $base_url.'/remote.php/dav/files/'.rawurlencode($user).'/'.quote_webdav_path($webdav_path); $url = $base_url.'/remote.php/dav/files/'.rawurlencode($user).'/'.quote_webdav_path($webdav_path);
$blob = fetch_remote_blob($url, $user, $password); $blob = fetch_remote_blob($url, $user, $password);
list($width, $height) = original_dimensions($blob);
$entry['width'] = $width;
$entry['height'] = $height;
$new_state[$key] = array('path'=>$webdav_path, 'etag'=>$etag, 'format'=>$extension, 'version'=>BRATONIEN_WEBDAV_PREVIEW_VERSION, 'width'=>$width, 'height'=>$height);
write_preview($blob, $target, $extension); write_preview($blob, $target, $extension);
remove_other_preview_format($cache_dir, $key, $target); remove_other_preview_format($cache_dir, $key, $target);
$generated++; $generated++;
@@ -275,7 +268,6 @@ try
fwrite(STDERR, $webdav_path.': '.$e->getMessage()."\n"); fwrite(STDERR, $webdav_path.': '.$e->getMessage()."\n");
} }
} }
unset($entry);
foreach (glob($cache_dir.'/*') ?: array() as $file) foreach (glob($cache_dir.'/*') ?: array() as $file)
{ {
@@ -285,8 +277,6 @@ try
if (!isset($new_state[$m[1]])) @unlink($file); if (!isset($new_state[$m[1]])) @unlink($file);
} }
file_put_contents($mapping_file, json_encode($mapping, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)."\n", LOCK_EX);
@chmod($mapping_file, 0644);
file_put_contents($state_file, json_encode($new_state, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)."\n", LOCK_EX); file_put_contents($state_file, json_encode($new_state, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)."\n", LOCK_EX);
@chmod($state_file, 0644); @chmod($state_file, 0644);