T.ME/BIBIL_0DAY
CasperSecurity


Server : Apache/2
System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User : gositeme ( 1004)
PHP Version : 8.2.29
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Directory :  /home/gositeme/domains/soundstudiopro.com/private_html/api/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/soundstudiopro.com/private_html/api/download_crate_track.php
<?php
require_once '../config/database.php';
session_start();

// Check if user is logged in
if (!isset($_SESSION['user_id'])) {
    http_response_code(401);
    echo 'Unauthorized';
    exit;
}

// SECURITY: Validate and sanitize parameters
$track_id_raw = $_GET['track_id'] ?? null;
$crate_id_raw = $_GET['crate_id'] ?? null;

if (!$track_id_raw) {
    http_response_code(400);
    echo 'Track ID is required';
    exit;
}

// SECURITY: Validate that track_id is a positive integer
if (!is_numeric($track_id_raw) || (int)$track_id_raw <= 0) {
    error_log("SECURITY: Invalid track_id attempt: " . htmlspecialchars($track_id_raw, ENT_QUOTES, 'UTF-8'));
    http_response_code(400);
    echo 'Invalid track ID';
    exit;
}

$track_id = (int)$track_id_raw;

// Crate ID is optional, but if provided must be valid
$crate_id = null;
if ($crate_id_raw !== null) {
    if (!is_numeric($crate_id_raw) || (int)$crate_id_raw <= 0) {
        error_log("SECURITY: Invalid crate_id attempt: " . htmlspecialchars($crate_id_raw, ENT_QUOTES, 'UTF-8'));
        http_response_code(400);
        echo 'Invalid crate ID';
        exit;
    }
    $crate_id = (int)$crate_id_raw;
}

try {
    $pdo = getDBConnection();
    
    if (!$pdo) {
        throw new Exception('Database connection failed');
    }
    
    // Get track details
    $stmt = $pdo->prepare("
        SELECT 
            mt.id,
            mt.title,
            mt.audio_url,
            mt.user_id,
            u.name as artist_name
        FROM music_tracks mt
        JOIN users u ON mt.user_id = u.id
        WHERE mt.id = ? AND mt.status = 'complete'
    ");
    
    if (!$stmt) {
        throw new Exception('Failed to prepare track query: ' . implode(', ', $pdo->errorInfo()));
    }
    
    $stmt->execute([$track_id]);
    $track = $stmt->fetch(PDO::FETCH_ASSOC);
    
    if (!$track) {
        http_response_code(404);
        echo 'Track not found';
        exit;
    }
    
    // Check if user owns the track or has purchased it
    $user_id = $_SESSION['user_id'];
    $can_download = false;
    
    if ($track['user_id'] == $user_id) {
        // User owns the track
        $can_download = true;
    } else {
        // Check if user has purchased the track
        $stmt = $pdo->prepare("SELECT id FROM track_purchases WHERE user_id = ? AND track_id = ?");
        $stmt->execute([$user_id, $track_id]);
        $purchase = $stmt->fetch();
        $can_download = (bool)$purchase;
    }
    
    if (!$can_download) {
        http_response_code(403);
        echo 'You need to purchase this track to download it';
        exit;
    }
    
    // Validate audio_url exists
    if (empty($track['audio_url'])) {
        http_response_code(404);
        echo 'Audio file URL not found for this track';
        exit;
    }
    
    // Get crate name and track position if crate_id is provided
    $crate_name = '';
    $track_position = '';
    if ($crate_id) {
        $stmt = $pdo->prepare("
            SELECT ap.name, pt.position
            FROM artist_playlists ap
            JOIN playlist_tracks pt ON ap.id = pt.playlist_id
            WHERE ap.id = ? AND ap.user_id = ? AND pt.track_id = ?
        ");
        $stmt->execute([$crate_id, $user_id, $track_id]);
        $crate_info = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if ($crate_info) {
            $crate_name = $crate_info['name'];
            $track_position = $crate_info['position'];
        }
    }
    
    // Record the download (only if table exists - make it optional)
    try {
        // Check if table exists first
        $table_check = $pdo->query("SHOW TABLES LIKE 'track_downloads'");
        if ($table_check && $table_check->rowCount() > 0) {
            $stmt = $pdo->prepare("INSERT INTO track_downloads (track_id, user_id, downloaded_at) VALUES (?, ?, NOW()) ON DUPLICATE KEY UPDATE downloaded_at = NOW()");
            $stmt->execute([$track_id, $user_id]);
        }
    } catch (PDOException $e) {
        // If table doesn't exist or query fails, just log and continue (download should still work)
        error_log("Could not record download (table may not exist): " . $e->getMessage());
    }
    
    // SECURITY: Validate and get the audio file path
    require_once '../includes/file_security.php';
    $audio_validation = validateAudioUrl($track['audio_url']);
    
    if ($audio_validation['type'] === 'invalid') {
        error_log("SECURITY: Invalid audio URL for track $track_id: " . $track['audio_url']);
        http_response_code(404);
        echo 'Audio file not available';
        exit;
    }
    
    // Generate filename
    $track_title = $track['title'] ?: 'Untitled Track';
    
    if ($crate_name && $track_position) {
        $crate_name_clean = sanitizeDownloadFilename($crate_name);
        $filename = $crate_name_clean . ' - Track ' . $track_position . ' - ' . sanitizeDownloadFilename($track_title) . '.mp3';
    } else {
        $filename = sanitizeDownloadFilename($track_title . ' - ' . $track['artist_name']) . '.mp3';
    }
    
    // Handle external URLs
    if ($audio_validation['type'] === 'external') {
        $audio_content = @file_get_contents($audio_validation['url']);
        if ($audio_content === false) {
            http_response_code(404);
            echo 'Audio file not found';
            exit;
        }
        
        header('Content-Type: audio/mpeg');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Content-Length: ' . strlen($audio_content));
        header('Cache-Control: no-cache, must-revalidate');
        header('Pragma: no-cache');
        
        echo $audio_content;
        exit;
    }
    
    // Handle local files
    $file_path = $audio_validation['path'];
    
    if (!$file_path || !file_exists($file_path)) {
        error_log("Download crate track: File not found at: " . ($file_path ?: 'null'));
        error_log("Download crate track: Original audio_url: " . $track['audio_url']);
        http_response_code(404);
        echo 'Audio file not found. Please check that the file exists.';
        exit;
    }
    
    header('Content-Type: audio/mpeg');
    header('Content-Disposition: attachment; filename="' . $filename . '"');
    header('Content-Length: ' . filesize($file_path));
    header('Cache-Control: no-cache, must-revalidate');
    header('Pragma: no-cache');
    
    // Output the file
    readfile($file_path);
    
} catch (Exception $e) {
    $error_message = $e->getMessage();
    $error_trace = $e->getTraceAsString();
    error_log("Error downloading crate track: " . $error_message);
    error_log("Stack trace: " . $error_trace);
    http_response_code(500);
    
    // Show more detailed error in development, generic message in production
    if (isset($_GET['debug']) || (isset($_SERVER['HTTP_HOST']) && strpos($_SERVER['HTTP_HOST'], 'localhost') !== false)) {
        echo 'Internal server error: ' . htmlspecialchars($error_message);
    } else {
        echo 'Internal server error. Please try again or contact support.';
    }
}
?>


CasperSecurity Mini