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/get_artist_tracks.php
<?php
session_start();
header('Content-Type: application/json');

require_once '../config/database.php';
require_once '../utils/audio_token.php';

try {
    $pdo = getDBConnection();
    
    // SECURITY: Validate and sanitize parameters
    $artist_id_raw = $_GET['artist_id'] ?? null;
    $type = $_GET['type'] ?? 'all';
    $offset = (int)($_GET['offset'] ?? 0);
    $limit = (int)($_GET['limit'] ?? 20);
    
    if (!$artist_id_raw) {
        throw new Exception('Artist ID is required');
    }
    
    // SECURITY: Validate that artist_id is a positive integer
    if (!is_numeric($artist_id_raw) || (int)$artist_id_raw <= 0) {
        error_log("SECURITY: Invalid artist_id attempt: " . htmlspecialchars($artist_id_raw, ENT_QUOTES, 'UTF-8'));
        throw new Exception('Invalid artist ID');
    }
    
    $artist_id = (int)$artist_id_raw;
    
    // Build query based on type
    $where_clause = "WHERE mt.user_id = ? AND mt.is_public = 1";
    if ($type === 'completed') {
        $where_clause .= " AND mt.status = 'complete'";
    } elseif ($type === 'tracks') {
        // All tracks (including processing, failed, etc.)
    }
    
    // Get current user ID for variation preferences (if logged in)
    $current_user_id = $_SESSION['user_id'] ?? 0;
    
    // OPTIMIZED: Using JOINs instead of correlated subqueries for better performance
    $stmt = $pdo->prepare("
        SELECT 
            mt.id,
            mt.title,
            mt.prompt,
            mt.duration,
            mt.audio_url,
            mt.image_url,
            mt.price,
            mt.status,
            mt.created_at,
            mt.music_type,
            mt.metadata,
            mt.user_id,
            mt.task_id,
            u.name as artist_name,
            COALESCE(like_stats.like_count, 0) as like_count,
            COALESCE(comment_stats.comment_count, 0) as comment_count,
            COALESCE(play_stats.play_count, 0) as play_count,
            COALESCE(share_stats.share_count, 0) as share_count,
            COALESCE(purchase_stats.purchase_count, 0) as purchase_count,
            COALESCE(rating_stats.average_rating, 0) as average_rating,
            COALESCE(rating_stats.rating_count, 0) as rating_count,
            CASE WHEN user_like_stats.track_id IS NOT NULL THEN 1 ELSE 0 END as user_liked,
            CASE WHEN wishlist_stats.track_id IS NOT NULL THEN 1 ELSE 0 END as is_in_wishlist,
            CASE WHEN purchase_user_stats.track_id IS NOT NULL THEN 1 ELSE 0 END as user_purchased,
            MAX(uvp.variation_id) as preferred_variation_id
        FROM music_tracks mt
        JOIN users u ON mt.user_id = u.id
        LEFT JOIN user_variation_preferences uvp ON mt.id = uvp.track_id AND uvp.user_id = ? AND uvp.is_main_track = TRUE
        LEFT JOIN (SELECT track_id, COUNT(*) as like_count FROM track_likes GROUP BY track_id) like_stats ON mt.id = like_stats.track_id
        LEFT JOIN (SELECT track_id, COUNT(*) as comment_count FROM track_comments GROUP BY track_id) comment_stats ON mt.id = comment_stats.track_id
        LEFT JOIN (SELECT track_id, COUNT(*) as play_count FROM track_plays GROUP BY track_id) play_stats ON mt.id = play_stats.track_id
        LEFT JOIN (SELECT track_id, COUNT(*) as share_count FROM track_shares GROUP BY track_id) share_stats ON mt.id = share_stats.track_id
        LEFT JOIN (SELECT track_id, COUNT(*) as purchase_count FROM track_purchases GROUP BY track_id) purchase_stats ON mt.id = purchase_stats.track_id
        LEFT JOIN (SELECT track_id, AVG(rating) as average_rating, COUNT(*) as rating_count FROM track_ratings GROUP BY track_id) rating_stats ON mt.id = rating_stats.track_id
        LEFT JOIN (SELECT track_id FROM track_likes WHERE user_id = ?) user_like_stats ON mt.id = user_like_stats.track_id
        LEFT JOIN (SELECT track_id FROM user_wishlist WHERE user_id = ?) wishlist_stats ON mt.id = wishlist_stats.track_id
        LEFT JOIN (SELECT track_id FROM track_purchases WHERE user_id = ?) purchase_user_stats ON mt.id = purchase_user_stats.track_id
        $where_clause
        GROUP BY mt.id, mt.title, mt.prompt, mt.duration, mt.audio_url, mt.image_url, mt.price, mt.status, mt.created_at, mt.music_type, mt.metadata, mt.user_id, mt.task_id, u.name, like_stats.like_count, comment_stats.comment_count, play_stats.play_count, share_stats.share_count, purchase_stats.purchase_count, rating_stats.average_rating, rating_stats.rating_count, user_like_stats.track_id, wishlist_stats.track_id, purchase_user_stats.track_id
        ORDER BY mt.created_at DESC
        LIMIT ? OFFSET ?
    ");
    
    $stmt->execute([$current_user_id, $current_user_id, $current_user_id, $current_user_id, $artist_id, $limit, $offset]);
    $tracks = $stmt->fetchAll(PDO::FETCH_ASSOC);
    
    // Process tracks for display with variation selection logic
    // Priority: 1) Track metadata selected_variation, 2) user_variation_preferences, 3) default track audio
    $processed_tracks = [];
    $sessionId = session_id();
    
    foreach ($tracks as $track) {
        // Determine preferred audio URL based on variation selection
        $preferred_audio_url = $track['audio_url']; // Default to original track
        $preferred_duration = $track['duration']; // Default to original track duration
        
        // First, check track metadata for selected_variation (set by track owner in library.php)
        $trackMetadata = json_decode($track['metadata'] ?? '{}', true) ?: [];
        $selectedVariationIndex = $trackMetadata['selected_variation'] ?? null;
        
        if ($selectedVariationIndex !== null) {
            // Get the selected variation from audio_variations table (including duration)
            $var_stmt = $pdo->prepare("SELECT audio_url, duration FROM audio_variations WHERE track_id = ? AND variation_index = ?");
            $var_stmt->execute([$track['id'], $selectedVariationIndex]);
            $variation = $var_stmt->fetch(PDO::FETCH_ASSOC);
            
            if ($variation && $variation['audio_url']) {
                $preferred_audio_url = $variation['audio_url'];
                // Use variation duration if available, otherwise keep main track duration
                if (!empty($variation['duration'])) {
                    $preferred_duration = $variation['duration'];
                }
            }
        } elseif ($track['preferred_variation_id']) {
            // Fallback to user_variation_preferences if no metadata selection
            $var_stmt = $pdo->prepare("SELECT audio_url, duration FROM audio_variations WHERE id = ?");
            $var_stmt->execute([$track['preferred_variation_id']]);
            $variation = $var_stmt->fetch(PDO::FETCH_ASSOC);
            
            if ($variation && $variation['audio_url']) {
                $preferred_audio_url = $variation['audio_url'];
                // Use variation duration if available, otherwise keep main track duration
                if (!empty($variation['duration'])) {
                    $preferred_duration = $variation['duration'];
                }
            }
        }
        
        // Get all variations for this track with signed URLs
        $variations = [];
        $var_all_stmt = $pdo->prepare("
            SELECT variation_index, audio_url, duration, title, tags, image_url
            FROM audio_variations 
            WHERE track_id = ? 
            ORDER BY variation_index ASC
        ");
        $var_all_stmt->execute([$track['id']]);
        $track_variations = $var_all_stmt->fetchAll(PDO::FETCH_ASSOC);
        
        foreach ($track_variations as $var) {
            $variationIndex = isset($var['variation_index']) ? (int)$var['variation_index'] : null;
            $signedVarUrl = getSignedAudioUrl($track['id'], $variationIndex, null, $current_user_id, $sessionId);
            $variations[] = [
                'variation_index' => $variationIndex,
                'audio_url' => $signedVarUrl, // Use signed URL for playback
                'duration' => $var['duration'],
                'title' => $var['title'],
                'tags' => $var['tags'],
                'image_url' => $var['image_url']
            ];
        }
        
        // Only include tracks with audio URLs (either original or variation)
        if ($preferred_audio_url) {
            // Parse metadata for additional info
            $metadata = json_decode($track['metadata'] ?: '{}', true);
            
            // Generate signed audio URL that respects variation selection
            // This ensures autoplay uses the same variation as the selected track
            $signed_audio_url = getSignedAudioUrl($track['id'], $selectedVariationIndex);
            
            // IMPORTANT: Use main track audio_url, NOT preferred_audio_url
            // preferred_audio_url might be a preview variation (44 seconds)
            // We want the full track for playlist playback
            // But use signed_audio_url which will route through play_audio.php and respect variation selection
            $processed_tracks[] = [
                'id' => $track['id'],
                'title' => $track['title'] ?: 'Untitled Track',
                'duration' => $track['duration'], // Use main track duration
                'audio_url' => $track['audio_url'], // Use main track audio_url, not preferred
                'signed_audio_url' => $signed_audio_url, // Signed URL that respects variation selection
                'selected_variation_index' => $selectedVariationIndex, // Include variation index for reference
                'variations' => $variations, // Include variations with signed URLs
                'variations_count' => count($variations), // Include count for UI
                'image_url' => $track['image_url'] ?? null,
                'price' => $track['price'] ?? 0,
                'status' => $track['status'],
                'created_at' => $track['created_at'],
                'task_id' => $track['task_id'] ?? null,
                'music_type' => $track['music_type'] ?: 'music',
                'genre' => $metadata['genre'] ?? 'Unknown',
                'description' => $track['prompt'] ?: '',
                'artist_name' => $track['artist_name'] ?: 'Unknown Artist',
                'user_id' => $track['user_id'],
                'like_count' => $track['like_count'] ?? 0,
                'comment_count' => $track['comment_count'] ?? 0,
                'play_count' => $track['play_count'] ?? 0,
                'share_count' => $track['share_count'] ?? 0,
                'purchase_count' => $track['purchase_count'] ?? 0,
                'average_rating' => $track['average_rating'] ?? 0,
                'rating_count' => $track['rating_count'] ?? 0,
                'user_liked' => $track['user_liked'] ?? 0,
                'is_in_wishlist' => $track['is_in_wishlist'] ?? 0,
                'user_purchased' => $track['user_purchased'] ?? 0,
                'metadata' => $track['metadata'] ?? null
            ];
        }
    }
    
    echo json_encode([
        'success' => true,
        'tracks' => $processed_tracks,
        'count' => count($processed_tracks)
    ]);
    
} catch (Exception $e) {
    http_response_code(500);
    echo json_encode([
        'success' => false,
        'error' => $e->getMessage()
    ]);
}
?> 

CasperSecurity Mini