v1.0.0.0
StocketBase
- <?php
-
- declare(strict_types=1);
-
- require_once __DIR__ . '/config.php';
- require_once __DIR__ . '/database.php';
- require_once __DIR__ . '/user-auth.php';
- require_once __DIR__ . '/language.php';
- require_once __DIR__ . '/site-front.php';
- require_once __DIR__ . '/digital-files.php';
-
- final class DownloadHandler
- {
- public static function run(int $fileId, string $token): never
- {
- UserAuth::boot();
-
- $settings = SiteFront::settings();
- $token = strtolower(trim($token));
- $loginRequired = ($settings['require_account_to_purchase'] ?? '0') === '1';
-
- $file = DigitalFiles::find($fileId);
- if ($file === null) {
- self::fail($settings, 404, Language::get('download_not_found', 'File not found.'));
- }
-
- $fileProductId = (int) $file['product_id'];
- $productStatement = Database::site()->prepare('SELECT * FROM products WHERE id = :id LIMIT 1');
- $productStatement->execute(['id' => $fileProductId]);
- $product = $productStatement->fetch() ?: null;
-
- $customer = UserAuth::user();
- $grantToConsume = null;
- $allowed = false;
-
- $isFreeDownload = $product !== null
- && ($file['detached_at'] ?? null) === null
- && $product['status'] === 'published'
- && $product['deleted_at'] === null
- && DigitalFiles::isFree($product);
-
- if ($isFreeDownload) {
- if ($loginRequired && $customer === null) {
- self::requireLogin($fileId, '');
- }
- $allowed = true;
- } elseif ($customer !== null && DigitalFiles::customerOwnsProduct((int) $customer['id'], $fileProductId)) {
- $allowed = true;
- } elseif ($token !== '') {
- $grant = DigitalFiles::findValidGrant($token, $fileProductId);
- if ($grant === null) {
- self::fail($settings, 403, Language::get('download_link_expired', 'This download link has expired or reached its download limit.'));
- }
-
- $grantOwner = $grant['user_account_id'] !== null ? (int) $grant['user_account_id'] : null;
- if ($loginRequired && $grantOwner !== null && ($customer === null || (int) $customer['id'] !== $grantOwner)) {
- self::requireLogin($fileId, $token);
- }
-
- $grantToConsume = (int) $grant['id'];
- $allowed = true;
- } elseif ($customer === null) {
- self::requireLogin($fileId, '');
- }
-
- if (!$allowed) {
- self::fail($settings, 403, Language::get('download_access_denied', 'You do not have access to this file.'));
- }
-
- $path = DigitalFiles::resolvePath($file);
- if ($path === null || !is_readable($path)) {
- error_log('StocketBase: product file ' . (int) $file['id'] . ' is missing from storage.');
- self::fail($settings, 404, Language::get('download_not_found', 'File not found.'));
- }
-
- $alreadyCounted = self::countedInSession((int) $file['id']);
-
- if (!$alreadyCounted) {
- if ($grantToConsume !== null && !DigitalFiles::consumeGrant($grantToConsume)) {
- self::fail($settings, 403, Language::get('download_link_expired', 'This download link has expired or reached its download limit.'));
- }
-
- DigitalFiles::recordDownload((int) $file['id']);
- self::markCountedInSession((int) $file['id']);
- }
-
- DigitalFiles::stream($file, $path);
- }
-
- private static function countedInSession(int $fileId): bool
- {
- return session_status() === PHP_SESSION_ACTIVE
- && isset($_SESSION['counted_downloads'][$fileId]);
- }
-
- private static function markCountedInSession(int $fileId): void
- {
- if (session_status() !== PHP_SESSION_ACTIVE) {
- return;
- }
-
- $counted = is_array($_SESSION['counted_downloads'] ?? null) ? $_SESSION['counted_downloads'] : [];
- $counted[$fileId] = time();
- if (count($counted) > 200) {
- asort($counted);
- $counted = array_slice($counted, -200, null, true);
- }
- $_SESSION['counted_downloads'] = $counted;
- }
-
- private static function fail(array $settings, int $status, string $message): never
- {
- http_response_code($status);
- header('X-Robots-Tag: noindex, nofollow');
- $pageTitle = $message . ' - ' . $settings['site_name'];
- $pageDescription = '';
- require __DIR__ . '/front-header.php';
- echo '<h1 class="article-title">' . htmlspecialchars($message) . '</h1>';
- echo '<p><a href="index.php" class="unlock-btn">' . htmlspecialchars(Language::get('order_confirmation_continue_shopping', 'Continue shopping')) . '</a></p>';
- require __DIR__ . '/front-footer.php';
- exit;
- }
-
- private static function requireLogin(int $fileId, string $token): never
- {
- $returnTo = DigitalFiles::downloadUrl($fileId, $token !== '' ? $token : null);
- header('Location: user-login.php?redirect=' . urlencode($returnTo));
- exit;
- }
- }
-