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/utils/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/soundstudiopro.com/private_html/utils/audiofiles.php
<?php
// Fixed Audio files handler - serves audio files securely
// Disable ALL output before headers - critical for audio streaming
error_reporting(0);
ini_set('display_errors', 0);
ini_set('log_errors', 0);

// CRITICAL: Disable execution time limit for audio streaming
// This prevents the script from timing out during long audio file streaming
// Especially important for logged-out users who might hit default PHP time limits
set_time_limit(0);
ini_set('max_execution_time', 0);

// Start output buffering immediately to catch any warnings/errors
ob_start();

session_start();

// Allow public access for public tracks, but require auth for private tracks
// We'll check this after verifying the track exists

// Get the task ID and variation from the URL
$taskId = $_GET['id'] ?? '';
$variationIndex = $_GET['variation'] ?? null;

// Clear any output buffer before setting headers
ob_clean();

if (empty($taskId)) {
    http_response_code(400);
    header('Content-Type: text/plain');
    header('Content-Length: ' . strlen("Missing id parameter"));
    echo "Missing id parameter";
    exit;
}

// Validate task ID format (alphanumeric)
if (!preg_match('/^[a-zA-Z0-9]+$/', $taskId)) {
    http_response_code(400);
    header('Content-Type: text/plain');
    header('Content-Length: ' . strlen("Invalid id format"));
    echo "Invalid id format";
    exit;
}

// Include database configuration (clear buffer after include in case of warnings)
require_once __DIR__ . '/../config/database.php';
ob_clean(); // Clear any output from database.php (warnings, etc.)

// Verify the track exists and user has access (either owns it or it's public)
$pdo = getDBConnection();
if (!$pdo) {
    http_response_code(500);
    header('Content-Type: text/plain');
    echo "Database error";
    exit;
}

// Check if track exists and is complete
$stmt = $pdo->prepare("SELECT * FROM music_tracks WHERE task_id = ? AND status = 'complete'");
$stmt->execute([$taskId]);
$track = $stmt->fetch();

if (!$track) {
    http_response_code(404);
    header('Content-Type: text/plain');
    echo "Track not found";
    exit;
}

// Check access: user must own the track OR track must be public
$user_id = $_SESSION['user_id'] ?? null;
$hasAccess = false;

if ($user_id && $track['user_id'] == $user_id) {
    // User owns the track - always allow
    $hasAccess = true;
} elseif ($track['is_public'] == 1 || $track['is_public'] === null) {
    // Track is public (is_public = 1 or NULL means public by default) - allow access
    $hasAccess = true;
} else {
    // Track is private and user doesn't own it - require authentication
    if (!isset($_SESSION['user_id'])) {
        http_response_code(401);
        header('Content-Type: text/plain');
        echo "Unauthorized - Please log in to access this track";
        exit;
    }
    http_response_code(403);
    header('Content-Type: text/plain');
    echo "Access denied - track is not public";
    exit;
}

// If variation is requested, get it from audio_variations table
if ($variationIndex !== null) {
    $stmt = $pdo->prepare("SELECT * FROM audio_variations WHERE track_id = ? AND variation_index = ?");
    $stmt->execute([$track['id'], $variationIndex]);
    $variation = $stmt->fetch();
    
    if (!$variation) {
        ob_clean();
        http_response_code(404);
        header('Content-Type: text/plain');
        $errorMsg = "Variation not found";
        header('Content-Length: ' . strlen($errorMsg));
        echo $errorMsg;
        exit;
    }
    
    // Use the source_audio_url (original API.Box URL) for streaming, fallback to audio_url
    $audioUrl = $variation['source_audio_url'] ?? $variation['audio_url'] ?? '';
} else {
    // Use the main track's audio URL
    $audioUrl = $track['audio_url'] ?? '';
    
    // If main audio_url is empty, try to get first variation
    if (empty($audioUrl)) {
        $stmt = $pdo->prepare("SELECT source_audio_url, audio_url FROM audio_variations WHERE track_id = ? ORDER BY variation_index ASC LIMIT 1");
        $stmt->execute([$track['id']]);
        $firstVariation = $stmt->fetch();
        if ($firstVariation) {
            $audioUrl = $firstVariation['source_audio_url'] ?? $firstVariation['audio_url'] ?? '';
        }
    }
}

if (empty($audioUrl)) {
    ob_clean();
    http_response_code(404);
    header('Content-Type: text/plain');
    $errorMsg = "No audio URL found for this track";
    header('Content-Length: ' . strlen($errorMsg));
    echo $errorMsg;
    exit;
}

// SECURITY: If it's a local URL, validate path before serving
if (strpos($audioUrl, '/audio_files/') === 0 || strpos($audioUrl, '/uploads/') === 0) {
    // Use file security utility to validate path
    require_once __DIR__ . '/../includes/file_security.php';
    $audio_validation = validateAudioUrl($audioUrl);
    
    if ($audio_validation['type'] === 'local' && $audio_validation['path']) {
        $localPath = $audio_validation['path'];
        
        if (file_exists($localPath)) {
            $fileSize = filesize($localPath);
            $fileType = mime_content_type($localPath);
            
            // Set proper headers
            header('Content-Type: ' . $fileType);
            header('Content-Length: ' . $fileSize);
            header('Accept-Ranges: bytes');
            header('Cache-Control: no-cache, no-store, must-revalidate');
            header('Content-Disposition: inline; filename="' . basename($localPath) . '"');
            
            // Clear any output buffers
            while (ob_get_level()) {
                ob_end_clean();
            }
            
            readfile($localPath);
            exit;
        } else {
            http_response_code(404);
            header('Content-Type: text/plain');
            echo "Local file not found";
            exit;
        }
    } else {
        // Path validation failed - security violation
        error_log("SECURITY: Invalid audio path in audiofiles.php: " . htmlspecialchars($audioUrl, ENT_QUOTES, 'UTF-8'));
        http_response_code(403);
        header('Content-Type: text/plain');
        echo "Access denied";
        exit;
    }
}

// If it's an API BOX URL, stream it
if (strpos($audioUrl, 'api.box') !== false || strpos($audioUrl, 'apiboxfiles.erweima.ai') !== false) {
    // Set headers for audio streaming
    header('Content-Type: audio/mpeg');
    header('Accept-Ranges: bytes');
    header('Cache-Control: no-cache, no-store, must-revalidate');
    header('Content-Disposition: inline; filename="' . $taskId . '.mp3"');
    
    // Clear any output buffers
    while (ob_get_level()) {
        ob_end_clean();
    }
    
    // Stream the audio from API BOX
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $audioUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); // Stream directly to output
    curl_setopt($ch, CURLOPT_TIMEOUT, 60);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
    curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) {
        echo $data;
        return strlen($data);
    });
    
    $httpCode = curl_exec($ch);
    $curlError = curl_error($ch);
    curl_close($ch);
    
    if ($httpCode === false || !empty($curlError)) {
        http_response_code(500);
        header('Content-Type: text/plain');
        echo "Failed to stream audio: " . $curlError;
    }
    exit;
}

// If it's a cdn1.suno.ai URL or any other HTTP URL, try to stream it
if (strpos($audioUrl, 'http') === 0 || strpos($audioUrl, 'cdn1.suno.ai') !== false) {
    // Clear any output buffers before setting headers
    while (ob_get_level()) {
        ob_end_clean();
    }
    
    // Set headers for audio streaming
    header('Content-Type: audio/mpeg');
    header('Accept-Ranges: bytes');
    header('Cache-Control: no-cache, no-store, must-revalidate');
    header('Content-Disposition: inline; filename="' . $taskId . '.mp3"');
    
    // Stream the audio from external URL
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $audioUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); // Stream directly to output
    curl_setopt($ch, CURLOPT_TIMEOUT, 60);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
    curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) {
        echo $data;
        flush();
        return strlen($data);
    });
    
    $httpCode = curl_exec($ch);
    $curlError = curl_error($ch);
    $httpResponseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    if ($httpCode === false || !empty($curlError) || ($httpResponseCode >= 400)) {
        ob_clean();
        http_response_code(500);
        header('Content-Type: text/plain');
        $errorMsg = "Failed to stream audio: " . ($curlError ?: "HTTP $httpResponseCode");
        header('Content-Length: ' . strlen($errorMsg));
        echo $errorMsg;
        exit;
    }
    exit;
}

// Fallback - try to download and serve
ob_clean();
http_response_code(404);
header('Content-Type: text/plain');
$errorMsg = "Audio not available - unsupported URL format";
header('Content-Length: ' . strlen($errorMsg));
echo $errorMsg;
exit;
?> 

CasperSecurity Mini