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/play_audio.php(current)
<?php
// Audio proxy endpoint - hides actual MP3 file paths
// Uses track_id instead of task_id for community pages
// Now includes signed token validation to prevent URL sharing

error_reporting(0);
ini_set('display_errors', 0);
ob_start();

session_start();

// Include token validation
require_once __DIR__ . '/audio_token.php';

// Get track ID and optional variation from URL
$trackId = $_GET['id'] ?? '';
$variationIndex = isset($_GET['variation']) ? (int)$_GET['variation'] : null;
$token = $_GET['token'] ?? '';
$expires = isset($_GET['expires']) ? (int)$_GET['expires'] : 0;

ob_clean();

if (empty($trackId) || !is_numeric($trackId)) {
    http_response_code(400);
    header('Content-Type: text/plain');
    echo "Invalid track ID";
    exit;
}

// Validate signed token
if (empty($token) || empty($expires)) {
    http_response_code(403);
    header('Content-Type: text/plain');
    echo "Access denied - missing token";
    exit;
}

if (!validateAudioToken($trackId, $variationIndex, $token, $expires)) {
    http_response_code(403);
    header('Content-Type: text/plain');
    echo "Access denied - invalid or expired token";
    exit;
}

require_once __DIR__ . '/../config/database.php';
ob_clean();

$pdo = getDBConnection();
if (!$pdo) {
    http_response_code(500);
    header('Content-Type: text/plain');
    echo "Database error";
    exit;
}

// Get track and check if it's public
$stmt = $pdo->prepare("SELECT id, task_id, audio_url, is_public, user_id, status, metadata, selected_variation FROM music_tracks WHERE id = ? AND status = 'complete'");
$stmt->execute([$trackId]);
$track = $stmt->fetch(PDO::FETCH_ASSOC);

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) {
    $hasAccess = true;
} elseif ($track['is_public'] == 1 || $track['is_public'] === null) {
    $hasAccess = true;
} else {
    http_response_code(403);
    header('Content-Type: text/plain');
    echo "Access denied";
    exit;
}

// If no variation parameter provided, check for selected variation in metadata
if ($variationIndex === null) {
    // Check metadata for selected_variation
    if (!empty($track['metadata'])) {
        $metadata = is_string($track['metadata']) ? json_decode($track['metadata'], true) : $track['metadata'];
        if (isset($metadata['selected_variation'])) {
            $variationIndex = (int)$metadata['selected_variation'];
        }
    }
    // Also check selected_variation column if it exists
    if ($variationIndex === null && isset($track['selected_variation']) && $track['selected_variation'] !== null) {
        $variationIndex = (int)$track['selected_variation'];
    }
}

// Get audio URL - check for specific variation first, then main track
$audioUrl = '';

if ($variationIndex !== null) {
    // Get specific variation
    $stmt = $pdo->prepare("SELECT audio_url FROM audio_variations WHERE track_id = ? AND variation_index = ?");
    $stmt->execute([$trackId, $variationIndex]);
    $variation = $stmt->fetch(PDO::FETCH_ASSOC);
    if ($variation) {
        $audioUrl = $variation['audio_url'] ?? '';
    }
}

// If no variation or variation not found, use main track
if (empty($audioUrl)) {
    $audioUrl = $track['audio_url'] ?? '';
    
    // If still empty, try first variation as fallback
    if (empty($audioUrl)) {
        $stmt = $pdo->prepare("SELECT audio_url FROM audio_variations WHERE track_id = ? ORDER BY variation_index ASC LIMIT 1");
        $stmt->execute([$trackId]);
        $variation = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($variation) {
            $audioUrl = $variation['audio_url'] ?? '';
        }
    }
}

if (empty($audioUrl)) {
    http_response_code(404);
    header('Content-Type: text/plain');
    echo "Audio not available";
    exit;
}

// If it's a local file, serve it with Range support for seeking
if (strpos($audioUrl, '/audio_files/') === 0 || strpos($audioUrl, '/uploads/') === 0) {
    $localPath = $_SERVER['DOCUMENT_ROOT'] . $audioUrl;
    if (file_exists($localPath)) {
        $fileSize = filesize($localPath);
        $fileType = mime_content_type($localPath) ?: 'audio/mpeg';
        
        while (ob_get_level()) {
            ob_end_clean();
        }
        
        header('Content-Type: ' . $fileType);
        header('Accept-Ranges: bytes');
        header('Cache-Control: public, max-age=3600');
        
        // Handle Range requests for seeking support
        if (isset($_SERVER['HTTP_RANGE'])) {
            // Parse the Range header
            $range = $_SERVER['HTTP_RANGE'];
            if (preg_match('/bytes=(\d*)-(\d*)/', $range, $matches)) {
                $start = $matches[1] === '' ? 0 : intval($matches[1]);
                $end = $matches[2] === '' ? $fileSize - 1 : intval($matches[2]);
                
                // Validate range
                if ($start > $end || $start >= $fileSize || $end >= $fileSize) {
                    http_response_code(416); // Range Not Satisfiable
                    header("Content-Range: bytes */$fileSize");
                    exit;
                }
                
                $length = $end - $start + 1;
                
                http_response_code(206); // Partial Content
                header("Content-Range: bytes $start-$end/$fileSize");
                header("Content-Length: $length");
                
                // Serve the requested range
                $fp = fopen($localPath, 'rb');
                fseek($fp, $start);
                $remaining = $length;
                while ($remaining > 0 && !feof($fp)) {
                    $chunk = min(8192, $remaining);
                    echo fread($fp, $chunk);
                    $remaining -= $chunk;
                    flush();
                }
                fclose($fp);
                exit;
            }
        }
        
        // No Range header - serve full file
        header('Content-Length: ' . $fileSize);
        readfile($localPath);
        exit;
    }
}

// If it's an external URL, proxy it with Range support
if (strpos($audioUrl, 'http') === 0) {
    while (ob_get_level()) {
        ob_end_clean();
    }
    
    // Build headers to forward to external server
    $requestHeaders = [
        'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
    ];
    
    // Forward Range header if present (for seeking support)
    if (isset($_SERVER['HTTP_RANGE'])) {
        $requestHeaders[] = 'Range: ' . $_SERVER['HTTP_RANGE'];
    }
    
    $ch = curl_init($audioUrl);
    curl_setopt($ch, CURLOPT_TIMEOUT, 60);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $requestHeaders);
    
    // Capture response headers to forward them
    $responseHeaders = [];
    curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $header) use (&$responseHeaders) {
        $len = strlen($header);
        $header = trim($header);
        if (empty($header)) return $len;
        
        // Parse header
        $parts = explode(':', $header, 2);
        if (count($parts) == 2) {
            $name = strtolower(trim($parts[0]));
            $value = trim($parts[1]);
            $responseHeaders[$name] = $value;
        } elseif (strpos($header, 'HTTP/') === 0) {
            // Status line - extract status code
            if (preg_match('/HTTP\/\d\.?\d?\s+(\d+)/', $header, $matches)) {
                $responseHeaders['_status'] = intval($matches[1]);
            }
        }
        return $len;
    });
    
    // Buffer the response to get headers first, then stream
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $body = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    if ($httpCode >= 400) {
        http_response_code(500);
        header('Content-Type: text/plain');
        echo "Failed to stream audio";
        exit;
    }
    
    // Set appropriate status code (206 for partial content, 200 for full)
    if ($httpCode == 206) {
        http_response_code(206);
    }
    
    // Forward relevant headers
    header('Content-Type: ' . ($responseHeaders['content-type'] ?? 'audio/mpeg'));
    header('Accept-Ranges: bytes');
    header('Cache-Control: public, max-age=3600');
    
    if (isset($responseHeaders['content-length'])) {
        header('Content-Length: ' . $responseHeaders['content-length']);
    }
    if (isset($responseHeaders['content-range'])) {
        header('Content-Range: ' . $responseHeaders['content-range']);
    }
    
    // Output the body
    echo $body;
    exit;
}

http_response_code(404);
header('Content-Type: text/plain');
echo "Audio not available";
exit;
?>


CasperSecurity Mini