'category_id'), null, true); $access_result = pwg_query('SELECT 1 FROM '.IMAGE_CATEGORY_TABLE.' WHERE image_id='.$image_id.' AND '.$permission_condition.' LIMIT 1'); if (!pwg_db_num_rows($access_result)) bratonien_tools_webdav_image_abort(403, 'Kein Zugriff auf dieses Bild.'); $source = bratonien_tools_webdav_image_source_info($image_id); if (!$source) bratonien_tools_webdav_image_abort(404, 'Keine WebDAV-Quelle für dieses Bild gefunden.'); if (!empty($_GET['preview'])) { $preview = bratonien_tools_webdav_preview_path($source); if ($preview) { $mtime = @filemtime($preview) ?: time(); $etag = sha1($preview.'|'.$mtime.'|'.(@filesize($preview) ?: 0)); header('Content-Type: '.bratonien_tools_webdav_preview_content_type($preview)); header('Content-Length: '.(string)filesize($preview)); header('ETag: "'.$etag.'"'); header('Cache-Control: private, max-age=86400, must-revalidate'); header('X-Content-Type-Options: nosniff'); $client_etag = trim((string)($_SERVER['HTTP_IF_NONE_MATCH'] ?? ''), " \t\r\n\""); if ($client_etag !== '' && hash_equals($etag, $client_etag)) { http_response_code(304); exit; } if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'HEAD') readfile($preview); exit; } } $table = $GLOBALS['prefixeTable'].'bratonien_tools_nc_connections'; $result = pwg_query('SELECT config_json, secret_blob FROM `'.$table.'` WHERE id='.(int)$source['connection_id'].' LIMIT 1'); if (!pwg_db_num_rows($result)) bratonien_tools_webdav_image_abort(404, 'WebDAV-Verbindung nicht gefunden.'); $row = pwg_db_fetch_assoc($result); $config = json_decode((string)$row['config_json'], true); if (!is_array($config)) bratonien_tools_webdav_image_abort(500, 'WebDAV-Konfiguration ist ungültig.'); $key_result = pwg_query("SELECT value FROM ".$GLOBALS['prefixeTable']."config WHERE param='bratonien_nc_connector_secret' LIMIT 1"); if (!pwg_db_num_rows($key_result)) bratonien_tools_webdav_image_abort(500, 'Connector-Schlüssel fehlt.'); $key_row = pwg_db_fetch_assoc($key_result); $credentials = bratonien_tools_webdav_image_decrypt_secret((string)$row['secret_blob'], (string)$key_row['value']); if (!is_array($credentials)) bratonien_tools_webdav_image_abort(500, 'WebDAV-Zugangsdaten konnten nicht gelesen werden.'); $base_url = rtrim((string)($config['nextcloud_url'] ?? ''), '/'); $user = trim((string)($credentials['nextcloud_user'] ?? '')); $password = (string)($credentials['nextcloud_password'] ?? ''); $webdav_path = trim((string)$source['webdav_path'], '/'); if ($base_url === '' || $user === '' || $password === '' || $webdav_path === '') { bratonien_tools_webdav_image_abort(500, 'WebDAV-Bildquelle ist unvollständig.'); } $etag = trim((string)($source['etag'] ?? '')); if ($etag !== '') { header('ETag: "'.str_replace('"', '', $etag).'"'); $client_etag = trim((string)($_SERVER['HTTP_IF_NONE_MATCH'] ?? ''), " \t\r\n\""); if ($client_etag !== '' && hash_equals($etag, $client_etag)) { http_response_code(304); exit; } } header('Cache-Control: private, max-age=300, must-revalidate'); header('X-Content-Type-Options: nosniff'); $url = $base_url.'/remote.php/dav/files/'.rawurlencode($user).'/'.bratonien_tools_webdav_image_quote_path($webdav_path); $ch = curl_init($url); $options = array( CURLOPT_FOLLOWLOCATION => false, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 120, CURLOPT_HTTPAUTH => CURLAUTH_BASIC, CURLOPT_USERPWD => $user.':'.$password, CURLOPT_RETURNTRANSFER => false, CURLOPT_FAILONERROR => false, CURLOPT_USERAGENT => 'Bratonien-Tools-WebDAV-Image/0.9.6.0', CURLOPT_HEADERFUNCTION => function($ch, $line) { $length = strlen($line); $trimmed = trim($line); if ($trimmed === '') return $length; if (preg_match('#^HTTP/\S+\s+([0-9]{3})#i', $trimmed, $m)) { http_response_code((int)$m[1]); return $length; } $colon = strpos($line, ':'); if ($colon === false) return $length; $name = strtolower(trim(substr($line, 0, $colon))); $value = trim(substr($line, $colon + 1)); if (in_array($name, array('content-type','content-length','content-range','accept-ranges','last-modified'), true)) { header($name.': '.$value, true); } return $length; }, CURLOPT_WRITEFUNCTION => function($ch, $data) { echo $data; return strlen($data); }, ); if (!empty($_SERVER['HTTP_RANGE'])) { $range = trim((string)$_SERVER['HTTP_RANGE']); if (preg_match('/^bytes=(.+)$/i', $range, $m)) $options[CURLOPT_RANGE] = $m[1]; } if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'HEAD') { $options[CURLOPT_NOBODY] = true; } curl_setopt_array($ch, $options); $ok = curl_exec($ch); $errno = curl_errno($ch); $http = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($ok === false || $errno !== 0) { if (!headers_sent()) bratonien_tools_webdav_image_abort(502, 'Nextcloud-Bild konnte nicht geladen werden.'); exit; } if ($http < 200 || $http >= 400) { exit; }