![]() 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/ |
<?php
/**
* Share Token System - Generates and validates share tokens for private tracks
* Allows private tracks to be accessed via share links without making them public
*/
// Secret key for signing share tokens
define('SHARE_TOKEN_SECRET', 'ssp_share_2024_' . md5(__DIR__));
// Default expiration time: 1 hour
define('SHARE_TOKEN_DEFAULT_EXPIRY', 3600);
/**
* Generate a share token for a track with expiration
*
* @param int $trackId The track ID
* @param int $userId The user ID who owns the track
* @param int $expiresIn Seconds until expiration (default: 1 hour)
* @return array ['token' => string, 'expires' => int]
*/
function generateShareToken($trackId, $userId, $expiresIn = SHARE_TOKEN_DEFAULT_EXPIRY) {
$expires = time() + $expiresIn;
$timestamp = time();
// Build signature from track ID, user ID, timestamp, expiration, and secret
$data = $trackId . '|' . $userId . '|' . $timestamp . '|' . $expires;
$signature = hash_hmac('sha256', $data, SHARE_TOKEN_SECRET);
// Return token and expiration
return [
'token' => substr($signature, 0, 32),
'expires' => $expires
];
}
/**
* Validate a share token
*
* @param int $trackId The track ID
* @param string $token The token to validate
* @param int $userId The user ID who owns the track
* @return bool True if valid, false otherwise
*/
function validateShareToken($trackId, $token, $userId) {
require_once __DIR__ . '/../config/database.php';
$pdo = getDBConnection();
if (!$pdo) {
return false;
}
// Check if share token exists in database
$stmt = $pdo->prepare("SELECT id FROM music_tracks WHERE id = ? AND user_id = ? AND share_token = ?");
$stmt->execute([$trackId, $userId, $token]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
return $result !== false;
}
/**
* Generate or retrieve existing share token for a track
*
* @param int $trackId The track ID
* @param int $userId The user ID who owns the track
* @param int $expiresIn Seconds until expiration (default: 1 hour)
* @return array ['token' => string, 'expires' => int] or null
*/
function getOrCreateShareToken($trackId, $userId, $expiresIn = SHARE_TOKEN_DEFAULT_EXPIRY) {
require_once __DIR__ . '/../config/database.php';
$pdo = getDBConnection();
if (!$pdo) {
return null;
}
// Check if track exists and user owns it
try {
$stmt = $pdo->prepare("SELECT id, share_token, share_token_expires FROM music_tracks WHERE id = ? AND user_id = ?");
$stmt->execute([$trackId, $userId]);
$track = $stmt->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
// Column might not exist, try to add it
if (strpos($e->getMessage(), 'share_token') !== false || strpos($e->getMessage(), "Unknown column") !== false) {
try {
$pdo->exec("ALTER TABLE music_tracks ADD COLUMN share_token VARCHAR(64), ADD COLUMN share_token_expires INT");
// Try query again
$stmt = $pdo->prepare("SELECT id, share_token, share_token_expires FROM music_tracks WHERE id = ? AND user_id = ?");
$stmt->execute([$trackId, $userId]);
$track = $stmt->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e2) {
error_log("Failed to add share_token columns: " . $e2->getMessage());
return null;
}
} else {
error_log("Error checking track: " . $e->getMessage());
return null;
}
}
if (!$track) {
return null;
}
// If share token already exists and hasn't expired, return it
if (!empty($track['share_token']) && !empty($track['share_token_expires'])) {
if ($track['share_token_expires'] > time()) {
return [
'token' => $track['share_token'],
'expires' => (int)$track['share_token_expires']
];
}
// Token expired, generate new one
}
// Generate new share token
$tokenData = generateShareToken($trackId, $userId, $expiresIn);
// Store in database - first check if column exists, if not add it
try {
$stmt = $pdo->prepare("UPDATE music_tracks SET share_token = ?, share_token_expires = ? WHERE id = ? AND user_id = ?");
$stmt->execute([$tokenData['token'], $tokenData['expires'], $trackId, $userId]);
} catch (PDOException $e) {
// Column might not exist, try to add it
if (strpos($e->getMessage(), 'share_token') !== false || strpos($e->getMessage(), "Unknown column") !== false) {
try {
$pdo->exec("ALTER TABLE music_tracks ADD COLUMN share_token VARCHAR(64), ADD COLUMN share_token_expires INT");
// Try again
$stmt = $pdo->prepare("UPDATE music_tracks SET share_token = ?, share_token_expires = ? WHERE id = ? AND user_id = ?");
$stmt->execute([$tokenData['token'], $tokenData['expires'], $trackId, $userId]);
} catch (PDOException $e2) {
error_log("Failed to add share_token columns: " . $e2->getMessage());
return null;
}
} else {
error_log("Failed to update share_token: " . $e->getMessage());
return null;
}
}
return $tokenData;
}
/**
* Revoke a share token (remove it from database)
*
* @param int $trackId The track ID
* @param int $userId The user ID who owns the track
* @return bool True if successful
*/
function revokeShareToken($trackId, $userId) {
require_once __DIR__ . '/../config/database.php';
$pdo = getDBConnection();
if (!$pdo) {
return false;
}
$stmt = $pdo->prepare("UPDATE music_tracks SET share_token = NULL WHERE id = ? AND user_id = ?");
return $stmt->execute([$trackId, $userId]);
}
/**
* Check if a share token is valid for accessing a track
*
* @param int $trackId The track ID
* @param string $token The share token
* @return bool True if valid and not expired
*/
function isValidShareToken($trackId, $token) {
require_once __DIR__ . '/../config/database.php';
$pdo = getDBConnection();
if (!$pdo) {
return false;
}
// Check if share token exists, matches, and hasn't expired
try {
$stmt = $pdo->prepare("SELECT id, share_token_expires FROM music_tracks WHERE id = ? AND share_token = ?");
$stmt->execute([$trackId, $token]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result === false) {
return false;
}
// Check if token has expired
if (!empty($result['share_token_expires']) && $result['share_token_expires'] < time()) {
return false;
}
return true;
} catch (PDOException $e) {
// Column might not exist
if (strpos($e->getMessage(), 'share_token') !== false || strpos($e->getMessage(), "Unknown column") !== false) {
return false;
}
error_log("Error validating share token: " . $e->getMessage());
return false;
}
}
/**
* Generate a shareable URL with token
*
* @param int $trackId The track ID
* @param string $token The share token
* @return string The shareable URL
*/
function getShareableUrl($trackId, $token) {
// Use the current request's protocol and host, or default to https
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'] ?? 'soundstudiopro.com';
$baseUrl = $protocol . '://' . $host;
return $baseUrl . '/track.php?id=' . $trackId . '&share=' . urlencode($token);
}
/**
* Get expiration options for share tokens
*
* @return array Array of expiration options in seconds
*/
function getShareTokenExpirationOptions() {
return [
'1hour' => 3600, // 1 hour
'6hours' => 21600, // 6 hours
'24hours' => 86400, // 24 hours
'7days' => 604800, // 7 days
'30days' => 2592000 // 30 days
];
}
?>