diff --git a/.DS_Store b/.DS_Store index 15607a8..ae3def8 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/api/v2/get/download_logs.php b/api/v2/get/download_logs.php new file mode 100644 index 0000000..c9be3d4 --- /dev/null +++ b/api/v2/get/download_logs.php @@ -0,0 +1,100 @@ +soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';} + +//default whereclause +$whereclause = ''; + +//NEW ARRAY +$criterias = []; +$clause = ''; + +//Check for $_GET variables and build up clause +if(isset($get_content) && $get_content!=''){ + //GET VARIABLES FROM URL + $requests = explode("&", $get_content); + //Check for keys and values + foreach ($requests as $y){ + $v = explode("=", $y); + //INCLUDE VARIABLES IN ARRAY + $criterias[$v[0]] = $v[1]; + + if ($v[0] == 'page' || $v[0] =='p' || $v[0] =='totals' || $v[0] =='list' || $v[0] =='history'|| $v[0] =='success_msg'){ + //do nothing + } + elseif ($v[0] == 'user_id') { + $clause .= ' AND dl.user_id = :'.$v[0]; + } + elseif ($v[0] == 'version_id') { + $clause .= ' AND dl.version_id = :'.$v[0]; + } + elseif ($v[0] == 'date_from') { + $clause .= ' AND dl.downloaded_at >= :'.$v[0]; + } + elseif ($v[0] == 'date_to') { + $clause .= ' AND dl.downloaded_at <= :'.$v[0]; + } + elseif ($v[0] == 'search') { + $clause .= ' AND (sv.name LIKE :'.$v[0].' OR u.username LIKE :'.$v[0].' OR dl.ip_address LIKE :'.$v[0].')'; + } + else { + $clause .= ' AND dl.'.$v[0].' = :'.$v[0]; + } + } + if ($whereclause == '' && $clause !=''){ + $whereclause = 'WHERE '.substr($clause, 4); + } else { + $whereclause .= $clause; + } +} + +//Define Query +if(isset($criterias['totals']) && $criterias['totals']==''){ +//Request for total rows + $sql = 'SELECT count(*) as count FROM download_logs dl LEFT JOIN software_versions sv ON dl.version_id = sv.id LEFT JOIN users u ON dl.user_id = u.id '.$whereclause.''; +} +elseif (isset($criterias['list']) && $criterias['list']=='') { + //SQL for Paging + $sql = 'SELECT dl.*, sv.version, sv.name as software_name, u.username FROM download_logs dl LEFT JOIN software_versions sv ON dl.version_id = sv.id LEFT JOIN users u ON dl.user_id = u.id '.$whereclause.' ORDER BY dl.downloaded_at DESC'; +} +else { + $current_page = isset($criterias['p']) && is_numeric($criterias['p']) ? (int)$criterias['p'] : 1; + $sql = 'SELECT dl.*, sv.version, sv.name as software_name, u.username FROM download_logs dl LEFT JOIN software_versions sv ON dl.version_id = sv.id LEFT JOIN users u ON dl.user_id = u.id '.$whereclause.' ORDER BY dl.downloaded_at DESC LIMIT ?, ?'; + $stmt = $pdo->prepare($sql); + $stmt->bindValue(1, ($current_page - 1) * $page_rows_products, PDO::PARAM_INT); + $stmt->bindValue(2, $page_rows_products, PDO::PARAM_INT); + $stmt->execute(); + $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); +} + +//Execute Query for totals/list +if(isset($criterias['totals']) && $criterias['totals']==''){ + $stmt = $pdo->prepare($sql); + $stmt->execute(); + $messages = $stmt->fetch(); + $messages = $messages[0]; +} +elseif(isset($criterias['list'])){ + $stmt = $pdo->prepare($sql); + $stmt->execute(); + $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); +} + +//------------------------------------------ +//JSON_ENCODE +//------------------------------------------ +$messages = json_encode($messages, JSON_UNESCAPED_UNICODE); + +//Send results +echo $messages; + +?> \ No newline at end of file diff --git a/api/v2/get/download_tokens.php b/api/v2/get/download_tokens.php new file mode 100644 index 0000000..36da1a2 --- /dev/null +++ b/api/v2/get/download_tokens.php @@ -0,0 +1,97 @@ +soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';} + +//default whereclause +$whereclause = ''; + +//NEW ARRAY +$criterias = []; +$clause = ''; + +//Check for $_GET variables and build up clause +if(isset($get_content) && $get_content!=''){ + //GET VARIABLES FROM URL + $requests = explode("&", $get_content); + //Check for keys and values + foreach ($requests as $y){ + $v = explode("=", $y); + //INCLUDE VARIABLES IN ARRAY + $criterias[$v[0]] = $v[1]; + + if ($v[0] == 'page' || $v[0] =='p' || $v[0] =='totals' || $v[0] =='list' || $v[0] =='history'|| $v[0] =='success_msg'){ + //do nothing + } + elseif ($v[0] == 'user_id') { + $clause .= ' AND dt.user_id = :'.$v[0]; + } + elseif ($v[0] == 'version_id') { + $clause .= ' AND dt.version_id = :'.$v[0]; + } + elseif ($v[0] == 'used') { + $clause .= ' AND dt.used = :'.$v[0]; + } + elseif ($v[0] == 'token') { + $clause .= ' AND dt.token = :'.$v[0]; + } + else { + $clause .= ' AND dt.'.$v[0].' = :'.$v[0]; + } + } + if ($whereclause == '' && $clause !=''){ + $whereclause = 'WHERE '.substr($clause, 4); + } else { + $whereclause .= $clause; + } +} + +//Define Query +if(isset($criterias['totals']) && $criterias['totals']==''){ +//Request for total rows + $sql = 'SELECT count(*) as count FROM download_tokens dt LEFT JOIN software_versions sv ON dt.version_id = sv.id LEFT JOIN users u ON dt.user_id = u.id '.$whereclause.''; +} +elseif (isset($criterias['list']) && $criterias['list']=='') { + //SQL for Paging + $sql = 'SELECT dt.*, sv.version, sv.name as software_name, u.username FROM download_tokens dt LEFT JOIN software_versions sv ON dt.version_id = sv.id LEFT JOIN users u ON dt.user_id = u.id '.$whereclause.' ORDER BY dt.created_at DESC'; +} +else { + $current_page = isset($criterias['p']) && is_numeric($criterias['p']) ? (int)$criterias['p'] : 1; + $sql = 'SELECT dt.*, sv.version, sv.name as software_name, u.username FROM download_tokens dt LEFT JOIN software_versions sv ON dt.version_id = sv.id LEFT JOIN users u ON dt.user_id = u.id '.$whereclause.' ORDER BY dt.created_at DESC LIMIT ?, ?'; + $stmt = $pdo->prepare($sql); + $stmt->bindValue(1, ($current_page - 1) * $page_rows_products, PDO::PARAM_INT); + $stmt->bindValue(2, $page_rows_products, PDO::PARAM_INT); + $stmt->execute(); + $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); +} + +//Execute Query for totals/list +if(isset($criterias['totals']) && $criterias['totals']==''){ + $stmt = $pdo->prepare($sql); + $stmt->execute(); + $messages = $stmt->fetch(); + $messages = $messages[0]; +} +elseif(isset($criterias['list'])){ + $stmt = $pdo->prepare($sql); + $stmt->execute(); + $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); +} + +//------------------------------------------ +//JSON_ENCODE +//------------------------------------------ +$messages = json_encode($messages, JSON_UNESCAPED_UNICODE); + +//Send results +echo $messages; + +?> \ No newline at end of file diff --git a/api/v2/get/software.php b/api/v2/get/software.php new file mode 100644 index 0000000..af6d1ba --- /dev/null +++ b/api/v2/get/software.php @@ -0,0 +1,170 @@ +soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';} + +//default whereclause +$whereclause = ''; + +//NEW ARRAY +$criterias = []; +$clause = ''; + +//Check for $_GET variables and build up clause +if(isset($get_content) && $get_content!=''){ + //GET VARIABLES FROM URL + $requests = explode("&", $get_content); + //Check for keys and values + foreach ($requests as $y){ + $v = explode("=", $y); + //INCLUDE VARIABLES IN ARRAY + $criterias[$v[0]] = $v[1]; + + if ($v[0] == 'page' || $v[0] =='p' || $v[0] =='totals' || $v[0] =='list' || $v[0] =='history'|| $v[0] =='success_msg'){ + //do nothing + } + elseif ($v[0] == 'available') { + // Special case: get available upgrades for current user + // This will be handled separately below + } + elseif ($v[0] == 'version_id') { + $clause .= ' AND sv.id = :'.$v[0]; + } + elseif ($v[0] == 'version') { + $clause .= ' AND sv.version = :'.$v[0]; + } + elseif ($v[0] == 'search') { + $clause .= ' AND (sv.name LIKE :'.$v[0].' OR sv.description LIKE :'.$v[0].')'; + } + else { + $clause .= ' AND sv.'.$v[0].' = :'.$v[0]; + } + } + if ($whereclause == '' && $clause !=''){ + $whereclause = 'WHERE '.substr($clause, 4); + } else { + $whereclause .= $clause; + } +} + +// Special handling for available upgrades +if (isset($criterias['available'])) { + // Include version access logic + require_once './includes/version_access.php'; + + $userId = $user_data['id']; + + // Get all active versions + $stmt = $pdo->prepare(" + SELECT sv.id, sv.version, sv.major_version, sv.minor_version, sv.patch_version, + sv.name, sv.description, sv.file_size, sv.release_date + FROM software_versions sv + WHERE sv.is_active = TRUE + ORDER BY sv.major_version DESC, sv.minor_version DESC, sv.patch_version DESC + "); + $stmt->execute(); + $versions = $stmt->fetchAll(PDO::FETCH_ASSOC); + + // Get user's current versions + $ownedVersions = getUserOwnedVersions($userId); + $latestOwned = getLatestOwnedVersion($userId); + + $response = [ + 'current_version' => $latestOwned ? $latestOwned['version'] : null, + 'owned_versions' => array_map(function($v) { + return [ + 'version' => $v['version'], + 'name' => $v['name'], + 'purchased_at' => $v['purchased_at'] + ]; + }, $ownedVersions), + 'available_versions' => [] + ]; + + // Check access for each version + foreach ($versions as $version) { + $accessInfo = checkVersionAccess($userId, $version['id']); + + $versionData = [ + 'id' => $version['id'], + 'version' => $version['version'], + 'name' => $version['name'], + 'description' => $version['description'], + 'file_size' => $version['file_size'], + 'release_date' => $version['release_date'], + 'is_accessible' => $accessInfo['accessible'], + 'requires_payment' => $accessInfo['requires_payment'] ?? false, + 'price' => $accessInfo['price'] ?? 0.00, + 'access_reason' => $accessInfo['reason'] + ]; + + // Add additional info based on access type + if (isset($accessInfo['original_price'])) { + $versionData['original_price'] = $accessInfo['original_price']; + } + if (isset($accessInfo['is_upgrade'])) { + $versionData['is_upgrade'] = $accessInfo['is_upgrade']; + } + if (isset($accessInfo['from_version'])) { + $versionData['upgrade_from'] = $accessInfo['from_version']; + } + if (isset($accessInfo['required_version'])) { + $versionData['required_version'] = $accessInfo['required_version']; + } + + $response['available_versions'][] = $versionData; + } + + $messages = $response; +} +else { + // Regular software versions query + if(isset($criterias['totals']) && $criterias['totals']==''){ + //Request for total rows + $sql = 'SELECT count(*) as count FROM software_versions sv '.$whereclause.''; + } + elseif (isset($criterias['list']) && $criterias['list']=='') { + //SQL for Paging + $sql = 'SELECT sv.* FROM software_versions sv '.$whereclause.' ORDER BY sv.major_version DESC, sv.minor_version DESC, sv.patch_version DESC'; + } + else { + $current_page = isset($criterias['p']) && is_numeric($criterias['p']) ? (int)$criterias['p'] : 1; + $sql = 'SELECT sv.* FROM software_versions sv '.$whereclause.' ORDER BY sv.major_version DESC, sv.minor_version DESC, sv.patch_version DESC LIMIT ?, ?'; + $stmt = $pdo->prepare($sql); + $stmt->bindValue(1, ($current_page - 1) * $page_rows_products, PDO::PARAM_INT); + $stmt->bindValue(2, $page_rows_products, PDO::PARAM_INT); + $stmt->execute(); + $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + //Execute Query for totals/list + if(isset($criterias['totals']) && $criterias['totals']==''){ + $stmt = $pdo->prepare($sql); + $stmt->execute(); + $messages = $stmt->fetch(); + $messages = $messages[0]; + } + elseif(isset($criterias['list'])){ + $stmt = $pdo->prepare($sql); + $stmt->execute(); + $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); + } +} + +//------------------------------------------ +//JSON_ENCODE +//------------------------------------------ +$messages = json_encode($messages, JSON_UNESCAPED_UNICODE); + +//Send results +echo $messages; + +?> \ No newline at end of file diff --git a/api/v2/get/software_download.php b/api/v2/get/software_download.php new file mode 100644 index 0000000..7a9229f --- /dev/null +++ b/api/v2/get/software_download.php @@ -0,0 +1,95 @@ +prepare("SELECT * FROM software_versions WHERE id = ?"); +$stmt->execute([$tokenData['version_id']]); +$version = $stmt->fetch(PDO::FETCH_ASSOC); + +if (!$version) { + http_response_code(404); + exit('File not found'); +} + +// Invalidate token after use (one-time use) +invalidateToken($pdo, $token); + +// Stream the file +$filePath = $version['file_path']; // e.g., '/var/www/secure_files/update_v2.0.zip' + +if (!file_exists($filePath)) { + http_response_code(404); + exit('File not found on server'); +} + +// Set headers for file download +header('Content-Type: application/octet-stream'); +header('Content-Disposition: attachment; filename="' . basename($version['filename']) . '"'); +header('Content-Length: ' . filesize($filePath)); +header('Cache-Control: no-cache, must-revalidate'); +header('Pragma: no-cache'); +header('Expires: 0'); + +// Stream file in chunks to handle large files +$handle = fopen($filePath, 'rb'); +while (!feof($handle)) { + echo fread($handle, 8192); + flush(); +} +fclose($handle); +exit; + +// Helper functions for token management +function validateDownloadToken($pdo, $token) { + $stmt = $pdo->prepare( + "SELECT user_id, version_id, expires_at, used + FROM download_tokens + WHERE token = ?" + ); + $stmt->execute([$token]); + $tokenData = $stmt->fetch(PDO::FETCH_ASSOC); + + if (!$tokenData) { + return false; + } + + // Check if expired + if (strtotime($tokenData['expires_at']) < time()) { + return false; + } + + // Check if already used + if ($tokenData['used']) { + return false; + } + + return $tokenData; +} + +function invalidateToken($pdo, $token) { + $stmt = $pdo->prepare("UPDATE download_tokens SET used = 1 WHERE token = ?"); + $stmt->execute([$token]); +} + +?> \ No newline at end of file diff --git a/api/v2/get/upgrade_paths.php b/api/v2/get/upgrade_paths.php new file mode 100644 index 0000000..c730b79 --- /dev/null +++ b/api/v2/get/upgrade_paths.php @@ -0,0 +1,97 @@ +soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';} + +//default whereclause +$whereclause = ''; + +//NEW ARRAY +$criterias = []; +$clause = ''; + +//Check for $_GET variables and build up clause +if(isset($get_content) && $get_content!=''){ + //GET VARIABLES FROM URL + $requests = explode("&", $get_content); + //Check for keys and values + foreach ($requests as $y){ + $v = explode("=", $y); + //INCLUDE VARIABLES IN ARRAY + $criterias[$v[0]] = $v[1]; + + if ($v[0] == 'page' || $v[0] =='p' || $v[0] =='totals' || $v[0] =='list' || $v[0] =='history'|| $v[0] =='success_msg'){ + //do nothing + } + elseif ($v[0] == 'from_version_id') { + $clause .= ' AND up.from_version_id = :'.$v[0]; + } + elseif ($v[0] == 'to_version_id') { + $clause .= ' AND up.to_version_id = :'.$v[0]; + } + elseif ($v[0] == 'is_free') { + $clause .= ' AND up.is_free = :'.$v[0]; + } + elseif ($v[0] == 'search') { + $clause .= ' AND (sv1.name LIKE :'.$v[0].' OR sv2.name LIKE :'.$v[0].' OR up.description LIKE :'.$v[0].')'; + } + else { + $clause .= ' AND up.'.$v[0].' = :'.$v[0]; + } + } + if ($whereclause == '' && $clause !=''){ + $whereclause = 'WHERE '.substr($clause, 4); + } else { + $whereclause .= $clause; + } +} + +//Define Query +if(isset($criterias['totals']) && $criterias['totals']==''){ +//Request for total rows + $sql = 'SELECT count(*) as count FROM upgrade_paths up LEFT JOIN software_versions sv1 ON up.from_version_id = sv1.id LEFT JOIN software_versions sv2 ON up.to_version_id = sv2.id '.$whereclause.''; +} +elseif (isset($criterias['list']) && $criterias['list']=='') { + //SQL for Paging + $sql = 'SELECT up.*, sv1.version as from_version, sv1.name as from_name, sv2.version as to_version, sv2.name as to_name FROM upgrade_paths up LEFT JOIN software_versions sv1 ON up.from_version_id = sv1.id LEFT JOIN software_versions sv2 ON up.to_version_id = sv2.id '.$whereclause.' ORDER BY up.id'; +} +else { + $current_page = isset($criterias['p']) && is_numeric($criterias['p']) ? (int)$criterias['p'] : 1; + $sql = 'SELECT up.*, sv1.version as from_version, sv1.name as from_name, sv2.version as to_version, sv2.name as to_name FROM upgrade_paths up LEFT JOIN software_versions sv1 ON up.from_version_id = sv1.id LEFT JOIN software_versions sv2 ON up.to_version_id = sv2.id '.$whereclause.' ORDER BY up.id LIMIT ?, ?'; + $stmt = $pdo->prepare($sql); + $stmt->bindValue(1, ($current_page - 1) * $page_rows_products, PDO::PARAM_INT); + $stmt->bindValue(2, $page_rows_products, PDO::PARAM_INT); + $stmt->execute(); + $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); +} + +//Execute Query for totals/list +if(isset($criterias['totals']) && $criterias['totals']==''){ + $stmt = $pdo->prepare($sql); + $stmt->execute(); + $messages = $stmt->fetch(); + $messages = $messages[0]; +} +elseif(isset($criterias['list'])){ + $stmt = $pdo->prepare($sql); + $stmt->execute(); + $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); +} + +//------------------------------------------ +//JSON_ENCODE +//------------------------------------------ +$messages = json_encode($messages, JSON_UNESCAPED_UNICODE); + +//Send results +echo $messages; + +?> \ No newline at end of file diff --git a/api/v2/get/user_licenses.php b/api/v2/get/user_licenses.php new file mode 100644 index 0000000..252b99b --- /dev/null +++ b/api/v2/get/user_licenses.php @@ -0,0 +1,97 @@ +soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';} + +//default whereclause +$whereclause = ''; + +//NEW ARRAY +$criterias = []; +$clause = ''; + +//Check for $_GET variables and build up clause +if(isset($get_content) && $get_content!=''){ + //GET VARIABLES FROM URL + $requests = explode("&", $get_content); + //Check for keys and values + foreach ($requests as $y){ + $v = explode("=", $y); + //INCLUDE VARIABLES IN ARRAY + $criterias[$v[0]] = $v[1]; + + if ($v[0] == 'page' || $v[0] =='p' || $v[0] =='totals' || $v[0] =='list' || $v[0] =='history'|| $v[0] =='success_msg'){ + //do nothing + } + elseif ($v[0] == 'user_id') { + $clause .= ' AND ul.user_id = :'.$v[0]; + } + elseif ($v[0] == 'version_id') { + $clause .= ' AND ul.version_id = :'.$v[0]; + } + elseif ($v[0] == 'status') { + $clause .= ' AND ul.status = :'.$v[0]; + } + elseif ($v[0] == 'search') { + $clause .= ' AND (sv.name LIKE :'.$v[0].' OR ul.license_key LIKE :'.$v[0].')'; + } + else { + $clause .= ' AND ul.'.$v[0].' = :'.$v[0]; + } + } + if ($whereclause == '' && $clause !=''){ + $whereclause = 'WHERE '.substr($clause, 4); + } else { + $whereclause .= $clause; + } +} + +//Define Query +if(isset($criterias['totals']) && $criterias['totals']==''){ +//Request for total rows + $sql = 'SELECT count(*) as count FROM user_licenses ul LEFT JOIN software_versions sv ON ul.version_id = sv.id '.$whereclause.''; +} +elseif (isset($criterias['list']) && $criterias['list']=='') { + //SQL for Paging + $sql = 'SELECT ul.*, sv.version, sv.name as software_name FROM user_licenses ul LEFT JOIN software_versions sv ON ul.version_id = sv.id '.$whereclause.' ORDER BY ul.purchased_at DESC'; +} +else { + $current_page = isset($criterias['p']) && is_numeric($criterias['p']) ? (int)$criterias['p'] : 1; + $sql = 'SELECT ul.*, sv.version, sv.name as software_name FROM user_licenses ul LEFT JOIN software_versions sv ON ul.version_id = sv.id '.$whereclause.' ORDER BY ul.purchased_at DESC LIMIT ?, ?'; + $stmt = $pdo->prepare($sql); + $stmt->bindValue(1, ($current_page - 1) * $page_rows_products, PDO::PARAM_INT); + $stmt->bindValue(2, $page_rows_products, PDO::PARAM_INT); + $stmt->execute(); + $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); +} + +//Execute Query for totals/list +if(isset($criterias['totals']) && $criterias['totals']==''){ + $stmt = $pdo->prepare($sql); + $stmt->execute(); + $messages = $stmt->fetch(); + $messages = $messages[0]; +} +elseif(isset($criterias['list'])){ + $stmt = $pdo->prepare($sql); + $stmt->execute(); + $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); +} + +//------------------------------------------ +//JSON_ENCODE +//------------------------------------------ +$messages = json_encode($messages, JSON_UNESCAPED_UNICODE); + +//Send results +echo $messages; + +?> \ No newline at end of file diff --git a/api/v2/get/version_access_rules.php b/api/v2/get/version_access_rules.php new file mode 100644 index 0000000..b824cfa --- /dev/null +++ b/api/v2/get/version_access_rules.php @@ -0,0 +1,94 @@ +soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';} + +//default whereclause +$whereclause = ''; + +//NEW ARRAY +$criterias = []; +$clause = ''; + +//Check for $_GET variables and build up clause +if(isset($get_content) && $get_content!=''){ + //GET VARIABLES FROM URL + $requests = explode("&", $get_content); + //Check for keys and values + foreach ($requests as $y){ + $v = explode("=", $y); + //INCLUDE VARIABLES IN ARRAY + $criterias[$v[0]] = $v[1]; + + if ($v[0] == 'page' || $v[0] =='p' || $v[0] =='totals' || $v[0] =='list' || $v[0] =='history'|| $v[0] =='success_msg'){ + //do nothing + } + elseif ($v[0] == 'version_id') { + $clause .= ' AND var.version_id = :'.$v[0]; + } + elseif ($v[0] == 'access_type') { + $clause .= ' AND var.access_type = :'.$v[0]; + } + elseif ($v[0] == 'search') { + $clause .= ' AND (sv.name LIKE :'.$v[0].' OR var.description LIKE :'.$v[0].')'; + } + else { + $clause .= ' AND var.'.$v[0].' = :'.$v[0]; + } + } + if ($whereclause == '' && $clause !=''){ + $whereclause = 'WHERE '.substr($clause, 4); + } else { + $whereclause .= $clause; + } +} + +//Define Query +if(isset($criterias['totals']) && $criterias['totals']==''){ +//Request for total rows + $sql = 'SELECT count(*) as count FROM version_access_rules var LEFT JOIN software_versions sv ON var.version_id = sv.id '.$whereclause.''; +} +elseif (isset($criterias['list']) && $criterias['list']=='') { + //SQL for Paging + $sql = 'SELECT var.*, sv.version, sv.name as software_name FROM version_access_rules var LEFT JOIN software_versions sv ON var.version_id = sv.id '.$whereclause.' ORDER BY var.id'; +} +else { + $current_page = isset($criterias['p']) && is_numeric($criterias['p']) ? (int)$criterias['p'] : 1; + $sql = 'SELECT var.*, sv.version, sv.name as software_name FROM version_access_rules var LEFT JOIN software_versions sv ON var.version_id = sv.id '.$whereclause.' ORDER BY var.id LIMIT ?, ?'; + $stmt = $pdo->prepare($sql); + $stmt->bindValue(1, ($current_page - 1) * $page_rows_products, PDO::PARAM_INT); + $stmt->bindValue(2, $page_rows_products, PDO::PARAM_INT); + $stmt->execute(); + $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); +} + +//Execute Query for totals/list +if(isset($criterias['totals']) && $criterias['totals']==''){ + $stmt = $pdo->prepare($sql); + $stmt->execute(); + $messages = $stmt->fetch(); + $messages = $messages[0]; +} +elseif(isset($criterias['list'])){ + $stmt = $pdo->prepare($sql); + $stmt->execute(); + $messages = $stmt->fetchAll(PDO::FETCH_ASSOC); +} + +//------------------------------------------ +//JSON_ENCODE +//------------------------------------------ +$messages = json_encode($messages, JSON_UNESCAPED_UNICODE); + +//Send results +echo $messages; + +?> \ No newline at end of file diff --git a/api/v2/post/software.php b/api/v2/post/software.php new file mode 100644 index 0000000..9773300 --- /dev/null +++ b/api/v2/post/software.php @@ -0,0 +1,202 @@ +soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';} + +//default whereclause +list($whereclause,$condition) = getWhereclause('',$permission,$partner,''); + +// Handle different actions +$action = $post_content['action'] ?? ''; + +switch ($action) { + case 'download': + // Handle secure download request + require_once './includes/version_access.php'; + + $versionId = $post_content['version_id'] ?? null; + + if (!$versionId) { + http_response_code(400); + echo json_encode(['error' => 'Missing version_id']); + exit; + } + + $userId = $user_data['id']; + + // Validate user has access to this version + if (!validateUserAccess($userId, $versionId)) { + http_response_code(403); + echo json_encode(['error' => 'Access denied. Payment required or insufficient permissions.']); + exit; + } + + // Get version details + $stmt = $pdo->prepare("SELECT * FROM software_versions WHERE id = ?"); + $stmt->execute([$versionId]); + $version = $stmt->fetch(PDO::FETCH_ASSOC); + + if (!$version) { + http_response_code(404); + echo json_encode(['error' => 'Version not found']); + exit; + } + + // Log the download + logDownload($pdo, $userId, $versionId); + + // Generate temporary signed URL + $downloadToken = generateSecureDownloadToken($pdo, $userId, $versionId); + + echo json_encode([ + 'download_url' => '/api/v2/get/software_download.php?token=' . $downloadToken, + 'expires_in' => 300 // 5 minutes + ]); + break; + + case 'purchase': + // Handle purchase/license grant + require_once './includes/version_access.php'; + + $versionId = $post_content['version_id'] ?? null; + $transactionId = $post_content['transaction_id'] ?? null; + + if (!$versionId) { + http_response_code(400); + echo json_encode(['error' => 'Missing version_id']); + exit; + } + + $userId = $user_data['id']; + + // Verify payment was successful (integrate with your payment processor) + $paymentVerified = true; // For testing - integrate with actual payment verification + + if (!$paymentVerified) { + http_response_code(400); + echo json_encode(['error' => 'Payment verification failed']); + exit; + } + + // Check access requirements + $accessInfo = checkVersionAccess($userId, $versionId); + + if ($accessInfo['accessible']) { + // Already has access + echo json_encode([ + 'success' => true, + 'message' => 'You already have access to this version', + 'license_granted' => false + ]); + exit; + } + + if (!$accessInfo['requires_payment']) { + // Shouldn't need payment + http_response_code(400); + echo json_encode(['error' => 'This version does not require payment']); + exit; + } + + // Grant license + $success = grantLicense($pdo, $userId, $versionId, $transactionId); + + if ($success) { + echo json_encode([ + 'success' => true, + 'message' => 'License granted successfully', + 'license_granted' => true + ]); + } else { + http_response_code(500); + echo json_encode(['error' => 'Failed to grant license']); + } + break; + + default: + // Handle CRUD operations for software versions (admin only) + if (!isAllowed('software', $profile, $permission, 'C') && + !isAllowed('software', $profile, $permission, 'U') && + !isAllowed('software', $profile, $permission, 'D')) { + http_response_code(403); + echo json_encode(['error' => 'Insufficient permissions']); + exit; + } + + //SET PARAMETERS FOR QUERY + $id = $post_content['id'] ?? ''; //check for id + $command = ($id == '')? 'insert' : 'update'; //IF id = empty then INSERT + if (isset($post_content['delete'])){$command = 'delete';} //change command to delete + $date = date('Y-m-d H:i:s'); + + //CREATE EMPTY STRINGS + $clause = ''; + $clause_insert =''; + $input_insert = ''; + + //ADD STANDARD PARAMETERS TO ARRAY BASED ON INSERT OR UPDATE + if ($command == 'update'){ + $post_content['updated'] = $date; + $post_content['updatedby'] = $username; + } + elseif ($command == 'insert'){ + $post_content['created'] = $date; + $post_content['createdby'] = $username; + } + + //BUILD UP CLAUSE + $execute_input = []; + foreach ($post_content as $key => $value) { + if ($key == 'action' || $key == 'id' || $key == 'delete') continue; + + if ($command == 'insert') { + $clause_insert .= $key.','; + $input_insert .= '?,'; + $execute_input[] = $value; + } elseif ($command == 'update') { + $clause .= $key.'=?,'; + $execute_input[] = $value; + } + } + + //CLEAN UP INPUT + $clause = substr($clause, 0, -1); //Clean clause - remove last comma + $clause_insert = substr($clause_insert, 0, -1); //Clean clause - remove last comma + $input_insert = substr($input_insert, 0, -1); //Clean clause - remove last comma + + //QUERY AND VERIFY ALLOWED + if ($command == 'update' && isAllowed('software',$profile,$permission,'U') === 1){ + $sql = 'UPDATE software_versions SET '.$clause.' WHERE id = ?'; + $execute_input[] = $id; + $stmt = $pdo->prepare($sql); + $stmt->execute($execute_input); + } + elseif ($command == 'insert' && isAllowed('software',$profile,$permission,'C') === 1){ + $sql = 'INSERT INTO software_versions ('.$clause_insert.') VALUES ('.$input_insert.')'; + $stmt = $pdo->prepare($sql); + $stmt->execute($execute_input); + } + elseif ($command == 'delete' && isAllowed('software',$profile,$permission,'D') === 1){ + $stmt = $pdo->prepare('DELETE FROM software_versions WHERE id = ?'); + $stmt->execute([$id]); + + //Add deletion to changelog + changelog($dbname,'software_versions',$id,'Delete','Delete',$username); + } else { + http_response_code(403); + echo json_encode(['error' => 'Operation not allowed']); + } + break; +} + +?> \ No newline at end of file diff --git a/api/v2/post/upgrade_paths.php b/api/v2/post/upgrade_paths.php new file mode 100644 index 0000000..32e355c --- /dev/null +++ b/api/v2/post/upgrade_paths.php @@ -0,0 +1,84 @@ +soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';} + +//default whereclause +list($whereclause,$condition) = getWhereclause('',$permission,$partner,''); + +//SET PARAMETERS FOR QUERY +$id = $post_content['id'] ?? ''; //check for id +$command = ($id == '')? 'insert' : 'update'; //IF id = empty then INSERT +if (isset($post_content['delete'])){$command = 'delete';} //change command to delete +$date = date('Y-m-d H:i:s'); + +//CREATE EMPTY STRINGS +$clause = ''; +$clause_insert =''; +$input_insert = ''; + +//ADD STANDARD PARAMETERS TO ARRAY BASED ON INSERT OR UPDATE +if ($command == 'update'){ + $post_content['updated'] = $date; + $post_content['updatedby'] = $username; +} +elseif ($command == 'insert'){ + $post_content['created'] = $date; + $post_content['createdby'] = $username; +} + +//BUILD UP CLAUSE +$execute_input = []; +foreach ($post_content as $key => $value) { + if ($key == 'id' || $key == 'delete') continue; + + if ($command == 'insert') { + $clause_insert .= $key.','; + $input_insert .= '?,'; + $execute_input[] = $value; + } elseif ($command == 'update') { + $clause .= $key.'=?,'; + $execute_input[] = $value; + } +} + +//CLEAN UP INPUT +$clause = substr($clause, 0, -1); //Clean clause - remove last comma +$clause_insert = substr($clause_insert, 0, -1); //Clean clause - remove last comma +$input_insert = substr($input_insert, 0, -1); //Clean clause - remove last comma + +//QUERY AND VERIFY ALLOWED +if ($command == 'update' && isAllowed('upgrade_paths',$profile,$permission,'U') === 1){ + $sql = 'UPDATE upgrade_paths SET '.$clause.' WHERE id = ?'; + $execute_input[] = $id; + $stmt = $pdo->prepare($sql); + $stmt->execute($execute_input); +} +elseif ($command == 'insert' && isAllowed('upgrade_paths',$profile,$permission,'C') === 1){ + $sql = 'INSERT INTO upgrade_paths ('.$clause_insert.') VALUES ('.$input_insert.')'; + $stmt = $pdo->prepare($sql); + $stmt->execute($execute_input); +} +elseif ($command == 'delete' && isAllowed('upgrade_paths',$profile,$permission,'D') === 1){ + $stmt = $pdo->prepare('DELETE FROM upgrade_paths WHERE id = ?'); + $stmt->execute([$id]); + + //Add deletion to changelog + changelog($dbname,'upgrade_paths',$id,'Delete','Delete',$username); +} else { + http_response_code(403); + echo json_encode(['error' => 'Operation not allowed']); +} + +?> \ No newline at end of file diff --git a/api/v2/post/user_licenses.php b/api/v2/post/user_licenses.php new file mode 100644 index 0000000..dbc75c1 --- /dev/null +++ b/api/v2/post/user_licenses.php @@ -0,0 +1,84 @@ +soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';} + +//default whereclause +list($whereclause,$condition) = getWhereclause('',$permission,$partner,''); + +//SET PARAMETERS FOR QUERY +$id = $post_content['id'] ?? ''; //check for id +$command = ($id == '')? 'insert' : 'update'; //IF id = empty then INSERT +if (isset($post_content['delete'])){$command = 'delete';} //change command to delete +$date = date('Y-m-d H:i:s'); + +//CREATE EMPTY STRINGS +$clause = ''; +$clause_insert =''; +$input_insert = ''; + +//ADD STANDARD PARAMETERS TO ARRAY BASED ON INSERT OR UPDATE +if ($command == 'update'){ + $post_content['updated'] = $date; + $post_content['updatedby'] = $username; +} +elseif ($command == 'insert'){ + $post_content['created'] = $date; + $post_content['createdby'] = $username; +} + +//BUILD UP CLAUSE +$execute_input = []; +foreach ($post_content as $key => $value) { + if ($key == 'id' || $key == 'delete') continue; + + if ($command == 'insert') { + $clause_insert .= $key.','; + $input_insert .= '?,'; + $execute_input[] = $value; + } elseif ($command == 'update') { + $clause .= $key.'=?,'; + $execute_input[] = $value; + } +} + +//CLEAN UP INPUT +$clause = substr($clause, 0, -1); //Clean clause - remove last comma +$clause_insert = substr($clause_insert, 0, -1); //Clean clause - remove last comma +$input_insert = substr($input_insert, 0, -1); //Clean clause - remove last comma + +//QUERY AND VERIFY ALLOWED +if ($command == 'update' && isAllowed('user_licenses',$profile,$permission,'U') === 1){ + $sql = 'UPDATE user_licenses SET '.$clause.' WHERE id = ?'; + $execute_input[] = $id; + $stmt = $pdo->prepare($sql); + $stmt->execute($execute_input); +} +elseif ($command == 'insert' && isAllowed('user_licenses',$profile,$permission,'C') === 1){ + $sql = 'INSERT INTO user_licenses ('.$clause_insert.') VALUES ('.$input_insert.')'; + $stmt = $pdo->prepare($sql); + $stmt->execute($execute_input); +} +elseif ($command == 'delete' && isAllowed('user_licenses',$profile,$permission,'D') === 1){ + $stmt = $pdo->prepare('DELETE FROM user_licenses WHERE id = ?'); + $stmt->execute([$id]); + + //Add deletion to changelog + changelog($dbname,'user_licenses',$id,'Delete','Delete',$username); +} else { + http_response_code(403); + echo json_encode(['error' => 'Operation not allowed']); +} + +?> \ No newline at end of file diff --git a/api/v2/post/version_access_rules.php b/api/v2/post/version_access_rules.php new file mode 100644 index 0000000..437b322 --- /dev/null +++ b/api/v2/post/version_access_rules.php @@ -0,0 +1,84 @@ +soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';} + +//default whereclause +list($whereclause,$condition) = getWhereclause('',$permission,$partner,''); + +//SET PARAMETERS FOR QUERY +$id = $post_content['id'] ?? ''; //check for id +$command = ($id == '')? 'insert' : 'update'; //IF id = empty then INSERT +if (isset($post_content['delete'])){$command = 'delete';} //change command to delete +$date = date('Y-m-d H:i:s'); + +//CREATE EMPTY STRINGS +$clause = ''; +$clause_insert =''; +$input_insert = ''; + +//ADD STANDARD PARAMETERS TO ARRAY BASED ON INSERT OR UPDATE +if ($command == 'update'){ + $post_content['updated'] = $date; + $post_content['updatedby'] = $username; +} +elseif ($command == 'insert'){ + $post_content['created'] = $date; + $post_content['createdby'] = $username; +} + +//BUILD UP CLAUSE +$execute_input = []; +foreach ($post_content as $key => $value) { + if ($key == 'id' || $key == 'delete') continue; + + if ($command == 'insert') { + $clause_insert .= $key.','; + $input_insert .= '?,'; + $execute_input[] = $value; + } elseif ($command == 'update') { + $clause .= $key.'=?,'; + $execute_input[] = $value; + } +} + +//CLEAN UP INPUT +$clause = substr($clause, 0, -1); //Clean clause - remove last comma +$clause_insert = substr($clause_insert, 0, -1); //Clean clause - remove last comma +$input_insert = substr($input_insert, 0, -1); //Clean clause - remove last comma + +//QUERY AND VERIFY ALLOWED +if ($command == 'update' && isAllowed('version_access_rules',$profile,$permission,'U') === 1){ + $sql = 'UPDATE version_access_rules SET '.$clause.' WHERE id = ?'; + $execute_input[] = $id; + $stmt = $pdo->prepare($sql); + $stmt->execute($execute_input); +} +elseif ($command == 'insert' && isAllowed('version_access_rules',$profile,$permission,'C') === 1){ + $sql = 'INSERT INTO version_access_rules ('.$clause_insert.') VALUES ('.$input_insert.')'; + $stmt = $pdo->prepare($sql); + $stmt->execute($execute_input); +} +elseif ($command == 'delete' && isAllowed('version_access_rules',$profile,$permission,'D') === 1){ + $stmt = $pdo->prepare('DELETE FROM version_access_rules WHERE id = ?'); + $stmt->execute([$id]); + + //Add deletion to changelog + changelog($dbname,'version_access_rules',$id,'Delete','Delete',$username); +} else { + http_response_code(403); + echo json_encode(['error' => 'Operation not allowed']); +} + +?> \ No newline at end of file diff --git a/assets/functions.js b/assets/functions.js new file mode 100644 index 0000000..3a8de4b --- /dev/null +++ b/assets/functions.js @@ -0,0 +1,350 @@ +// Software Upgrade System - Frontend Functions +// Requires: jQuery or modern fetch API + +class UpgradeManager { + constructor(apiBase = '/api.php') { + this.apiBase = apiBase; + this.serviceToken = ''; + this.init(); + } + + init() { + // Get service token from DOM if available + const tokenElement = document.getElementById('servicetoken'); + if (tokenElement) { + this.serviceToken = tokenElement.innerHTML || ''; + } + } + + async makeAPICall(endpoint, method = 'GET', data = null) { + const url = this.apiBase + endpoint; + const bearer = 'Bearer ' + this.serviceToken; + + const options = { + method: method, + headers: { + 'Authorization': bearer, + 'Content-Type': 'application/json' + }, + credentials: 'include' + }; + + if (data && (method === 'POST' || method === 'PUT')) { + options.body = JSON.stringify(data); + } + + const response = await fetch(url, options); + + if (!response.ok) { + const errorData = await response.json().catch(() => ({ error: 'Network error' })); + throw new Error(errorData.error || `HTTP ${response.status}`); + } + + return await response.json(); + } + + async getAvailableVersions() { + try { + const data = await this.makeAPICall('/v2/get/software?available'); + return data; + } catch (error) { + console.error('Error fetching available versions:', error); + throw error; + } + } + + async downloadVersion(versionId, onProgress = null) { + try { + // Step 1: Request download token + const downloadRequest = await this.makeAPICall('/v2/post/software', 'POST', { + action: 'download', + version_id: parseInt(versionId) + }); + + if (!downloadRequest.download_url) { + throw new Error('No download URL received'); + } + + // Step 2: Download file using temporary URL + await this.downloadFile(downloadRequest.download_url, onProgress); + + } catch (error) { + console.error('Download error:', error); + throw error; + } + } + + async downloadFile(url, onProgress) { + const response = await fetch(url, { + credentials: 'include' + }); + + if (!response.ok) { + throw new Error('Download failed'); + } + + const contentLength = response.headers.get('Content-Length'); + const total = parseInt(contentLength, 10); + let loaded = 0; + + const reader = response.body.getReader(); + const chunks = []; + + while (true) { + const { done, value } = await reader.read(); + + if (done) break; + + chunks.push(value); + loaded += value.length; + + if (onProgress && total) { + onProgress(loaded, total); + } + } + + // Create blob from chunks + const blob = new Blob(chunks); + + // Trigger download + const downloadUrl = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = downloadUrl; + a.download = 'software_upgrade.zip'; // Filename will be set by server + document.body.appendChild(a); + a.click(); + window.URL.revokeObjectURL(downloadUrl); + document.body.removeChild(a); + } + + async purchaseVersion(versionId, transactionId = null) { + try { + const purchaseData = { + action: 'purchase', + version_id: parseInt(versionId) + }; + + if (transactionId) { + purchaseData.transaction_id = transactionId; + } + + const result = await this.makeAPICall('/v2/post/software', 'POST', purchaseData); + return result; + } catch (error) { + console.error('Purchase error:', error); + throw error; + } + } + + formatBytes(bytes) { + if (bytes === 0) return '0 Bytes'; + const k = 1024; + const sizes = ['Bytes', 'KB', 'MB', 'GB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i]; + } + + formatPrice(price, currency = 'USD') { + return new Intl.NumberFormat('en-US', { + style: 'currency', + currency: currency + }).format(price); + } +} + +// Global upgrade manager instance +let upgradeManager; + +// Initialize upgrade system +function initUpgradeSystem() { + upgradeManager = new UpgradeManager(); +} + +// Display upgrade options in UI +async function showUpgradeOptions(containerId = 'upgrade-container') { + const container = document.getElementById(containerId); + if (!container) { + console.error('Container element not found:', containerId); + return; + } + + try { + const data = await upgradeManager.getAvailableVersions(); + + container.innerHTML = ''; + + // Show current version info + if (data.current_version) { + const currentDiv = document.createElement('div'); + currentDiv.className = 'current-version-info'; + currentDiv.innerHTML = ` +
Owned versions: ${data.owned_versions.map(v => v.version).join(', ')}
+ `; + container.appendChild(currentDiv); + } + + // Show available versions + if (data.available_versions && data.available_versions.length > 0) { + const versionsDiv = document.createElement('div'); + versionsDiv.className = 'available-versions'; + + data.available_versions.forEach(version => { + const versionCard = document.createElement('div'); + versionCard.className = 'version-card'; + versionCard.dataset.versionId = version.id; + + let buttonHTML = ''; + let priceHTML = ''; + let statusHTML = ''; + + if (version.is_accessible) { + statusHTML = 'Owned'; + buttonHTML = ``; + } else if (version.requires_payment) { + if (version.is_upgrade) { + priceHTML = ` +No software versions available at this time.
'; + } + + } catch (error) { + container.innerHTML = ``; + console.error('Error showing upgrade options:', error); + } +} + +// Download version with progress +async function downloadVersion(versionId) { + const button = event.target; + const originalText = button.innerHTML; + + try { + button.disabled = true; + button.innerHTML = 'Preparing Download...'; + + // Create progress indicator + const progressContainer = document.createElement('div'); + progressContainer.className = 'download-progress'; + progressContainer.innerHTML = ` + +Loading available upgrades...
+