From 91e73b1f1db57e1ea4be34cd678441c6d3f65312 Mon Sep 17 00:00:00 2001 From: R0GGER Date: Sat, 11 Oct 2025 16:36:53 +0200 Subject: [PATCH] Apple icon --- include/header.php | 5 ++ settings.php | 130 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 131 insertions(+), 4 deletions(-) diff --git a/include/header.php b/include/header.php index 04c6646..6fdfde5 100644 --- a/include/header.php +++ b/include/header.php @@ -57,6 +57,11 @@ if ($theme === 'dark' || in_array('dark-background-active', $body_classes)) { <?php echo htmlspecialchars($settings['site_title'] ?? 'Bookmarkly'); ?> + + + + + diff --git a/settings.php b/settings.php index edf41c4..77637ad 100644 --- a/settings.php +++ b/settings.php @@ -6,6 +6,86 @@ $GLOBALS['body_class'] = 'settings-page'; require_once 'include/auth.php'; +/** + * Resize an image while maintaining aspect ratio and transparency + * @param string $source_path Path to source image + * @param string $destination_path Path to save resized image + * @param int $max_width Maximum width + * @param int $max_height Maximum height + * @param string $extension File extension + * @return bool Success status + */ +function resizeImage($source_path, $destination_path, $max_width, $max_height, $extension) { + // Get original image dimensions + $image_info = getimagesize($source_path); + if ($image_info === false) { + return false; + } + + $original_width = $image_info[0]; + $original_height = $image_info[1]; + + // Calculate new dimensions maintaining aspect ratio + $ratio = min($max_width / $original_width, $max_height / $original_height); + $new_width = round($original_width * $ratio); + $new_height = round($original_height * $ratio); + + // Create image resource based on file type + switch (strtolower($extension)) { + case 'jpg': + case 'jpeg': + $source_image = imagecreatefromjpeg($source_path); + break; + case 'png': + $source_image = imagecreatefrompng($source_path); + break; + case 'gif': + $source_image = imagecreatefromgif($source_path); + break; + default: + return false; + } + + if ($source_image === false) { + return false; + } + + // Create new image with transparency support + $new_image = imagecreatetruecolor($new_width, $new_height); + + // Preserve transparency for PNG and GIF + if ($extension === 'png' || $extension === 'gif') { + imagealphablending($new_image, false); + imagesavealpha($new_image, true); + $transparent = imagecolorallocatealpha($new_image, 255, 255, 255, 127); + imagefilledrectangle($new_image, 0, 0, $new_width, $new_height, $transparent); + } + + // Resize the image + imagecopyresampled($new_image, $source_image, 0, 0, 0, 0, $new_width, $new_height, $original_width, $original_height); + + // Save the resized image + $result = false; + switch (strtolower($extension)) { + case 'jpg': + case 'jpeg': + $result = imagejpeg($new_image, $destination_path, 90); + break; + case 'png': + $result = imagepng($new_image, $destination_path, 9); + break; + case 'gif': + $result = imagegif($new_image, $destination_path); + break; + } + + // Clean up memory + imagedestroy($source_image); + imagedestroy($new_image); + + return $result; +} + // Flash messages for feedback $message = ''; $message_type = ''; @@ -68,10 +148,44 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (in_array($favicon_ext, $allowed_favicon_ext)) { $favicon_filename = 'favicon.' . $favicon_ext; $favicon_path = $uploadDir . $favicon_filename; - if (move_uploaded_file($_FILES['site_favicon']['tmp_name'], $favicon_path)) { - $upsert_stmt->execute(['site_favicon', $favicon_path . '?v=' . time()]); + + // Check if it's an image file (not SVG or ICO) + if (in_array($favicon_ext, ['png', 'jpg', 'jpeg', 'gif'])) { + // Get image dimensions + $image_info = getimagesize($_FILES['site_favicon']['tmp_name']); + if ($image_info === false) { + $_SESSION['flash_message'] = ['text' => 'Invalid image file for favicon.', 'type' => 'danger']; + } else { + $width = $image_info[0]; + $height = $image_info[1]; + + // Validate dimensions (minimum 180x180, maximum 256x256) + if ($width < 180 || $height < 180) { + $_SESSION['flash_message'] = ['text' => 'Favicon must be at least 180x180 pixels for Apple Touch Icon compatibility.', 'type' => 'danger']; + } elseif ($width > 256 || $height > 256) { + // Resize if too large + if (resizeImage($_FILES['site_favicon']['tmp_name'], $favicon_path, 256, 256, $favicon_ext)) { + $upsert_stmt->execute(['site_favicon', $favicon_path . '?v=' . time()]); + $_SESSION['flash_message'] = ['text' => 'Favicon uploaded and resized to 256x256 pixels for optimal Apple Touch Icon compatibility.', 'type' => 'success']; + } else { + $_SESSION['flash_message'] = ['text' => 'Failed to resize favicon.', 'type' => 'danger']; + } + } else { + // Size is acceptable, just move the file + if (move_uploaded_file($_FILES['site_favicon']['tmp_name'], $favicon_path)) { + $upsert_stmt->execute(['site_favicon', $favicon_path . '?v=' . time()]); + } else { + $_SESSION['flash_message'] = ['text' => 'Failed to move uploaded favicon.', 'type' => 'danger']; + } + } + } } else { - $_SESSION['flash_message'] = ['text' => 'Failed to move uploaded favicon.', 'type' => 'danger']; + // For SVG and ICO files, just move them without resizing + if (move_uploaded_file($_FILES['site_favicon']['tmp_name'], $favicon_path)) { + $upsert_stmt->execute(['site_favicon', $favicon_path . '?v=' . time()]); + } else { + $_SESSION['flash_message'] = ['text' => 'Failed to move uploaded favicon.', 'type' => 'danger']; + } } } else { $_SESSION['flash_message'] = ['text' => 'Invalid file type for favicon.', 'type' => 'danger']; @@ -277,7 +391,15 @@ require_once 'include/header.php';
- + +
+ Apple Touch Icon Requirements:
+ • Minimum size: 180x180 pixels
+ • Maximum size: 256x256 pixels
+ • Supported formats: PNG, JPG, GIF, SVG, ICO
+ • Images larger than 256x256 will be automatically resized
+ • Images smaller than 180x180 will be rejected +
Current favicon: Current Favicon