Files
assetmgt/api/v2/get/software_download.php
“VeLiTi” 653e33d7e9 Add software tool functionality with device connection and upgrade options
- Implemented the software tool page with user interface for connecting devices.
- Added functionality to display connection status and software upgrade options.
- Included a help modal with step-by-step instructions for users.
- Integrated error handling and user permission checks.
- Enhanced user experience with dynamic content updates and visual feedback.
2025-12-21 14:16:55 +01:00

285 lines
9.1 KiB
PHP

<?php
defined($security_key) or exit;
//------------------------------------------
// Secure Software Download API
// Validates time-based URL token and streams firmware files
//------------------------------------------
//Connect to DB
$pdo = dbConnect($dbname);
// STEP 1: Validate token parameter exists
if (!isset($_GET['token']) || $_GET['token'] == '') {
http_response_code(400);
echo json_encode(["error" => "MISSING_TOKEN", "message" => "Download token required"]);
exit;
}
$download_start = microtime(true);
// URL decode the token in case it was encoded during transmission
$url_token = urldecode($_GET['token']);
// STEP 2: Validate and decode URL token using standalone secure function
$token_data = validate_secure_download_token($url_token);
if (isset($token_data['error'])) {
http_response_code(403);
echo json_encode([
"error" => $token_data['error'],
"message" => $token_data['message']
]);
exit;
}
$serial_number = $token_data['sn'];
$version_id = $token_data['version_id'];
// STEP 3: Get equipment data (reuse software_update.php logic)
$sql = 'SELECT
e.rowID as equipment_rowid,
e.productrowid,
e.sw_version as current_sw_version,
e.hw_version,
e.sw_version_license,
e.accounthierarchy,
p.productcode
FROM equipment e
JOIN products p ON e.productrowid = p.rowID
WHERE e.serialnumber = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute([$serial_number]);
$equipment = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$equipment) {
http_response_code(404);
log_download([
'user_id' => $user_data['id'],
'version_id' => $version_id,
'status' => 'failed',
'error_message' => 'Equipment not found',
'createdby' => $username
]);
echo json_encode(["error" => "EQUIPMENT_NOT_FOUND", "message" => "Equipment not found"]);
exit;
}
// STEP 4: Get version data
$sql = 'SELECT
psv.rowID,
psv.version,
psv.name,
psv.file_path,
psv.hw_version,
psv.status
FROM products_software_versions psv
WHERE psv.rowID = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute([$version_id]);
$version = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$version) {
http_response_code(404);
log_download([
'user_id' => $user_data['id'],
'version_id' => $version_id,
'status' => 'failed',
'error_message' => 'Version not found',
'accounthierarchy' => $equipment['accounthierarchy'],
'createdby' => $username
]);
echo json_encode(["error" => "VERSION_NOT_FOUND", "message" => "Version not found"]);
exit;
}
if ($version['status'] != 1) {
http_response_code(403);
log_download([
'user_id' => $user_data['id'],
'version_id' => $version_id,
'status' => 'failed',
'error_message' => 'Version inactive',
'accounthierarchy' => $equipment['accounthierarchy'],
'createdby' => $username
]);
echo json_encode(["error" => "VERSION_INACTIVE", "message" => "Version is not active"]);
exit;
}
// STEP 5: Check version is assigned to product
$sql = 'SELECT COUNT(*) as assigned
FROM products_software_assignment
WHERE product_id = ? AND software_version_id = ? AND status = 1';
$stmt = $pdo->prepare($sql);
$stmt->execute([$equipment['productrowid'], $version_id]);
$assignment = $stmt->fetch(PDO::FETCH_ASSOC);
if ($assignment['assigned'] == 0) {
http_response_code(403);
log_download([
'user_id' => $user_data['id'],
'version_id' => $version_id,
'status' => 'failed',
'error_message' => 'Version not assigned to product',
'accounthierarchy' => $equipment['accounthierarchy'],
'createdby' => $username
]);
echo json_encode(["error" => "VERSION_NOT_ASSIGNED", "message" => "Version not assigned to product"]);
exit;
}
// STEP 6: Hardware version compatibility
// Only check if version has hw_version requirement (not NULL or empty)
// Match logic from software_update.php line 103
if ($version['hw_version'] && $version['hw_version'] != '') {
if ($equipment['hw_version'] && $version['hw_version'] != $equipment['hw_version']) {
http_response_code(403);
log_download([
'user_id' => $user_data['id'],
'version_id' => $version_id,
'status' => 'failed',
'error_message' => 'Hardware version mismatch',
'accounthierarchy' => $equipment['accounthierarchy'],
'createdby' => $username
]);
echo json_encode(["error" => "HW_VERSION_MISMATCH", "message" => "Hardware version incompatible"]);
exit;
}
}
// STEP 7: License validation (reuse software_update.php logic)
$current_sw_version = $equipment['current_sw_version'];
// Get upgrade pricing
$sql = 'SELECT price, currency
FROM products_software_upgrade_paths pup
JOIN products_software_versions from_ver ON pup.from_version_id = from_ver.rowID
WHERE pup.to_version_id = ? AND from_ver.version = ? AND pup.is_active = 1';
$stmt = $pdo->prepare($sql);
$stmt->execute([$version_id, $current_sw_version]);
$upgrade_pricing = $stmt->fetch(PDO::FETCH_ASSOC);
$final_price = $upgrade_pricing['price'] ?? '0.00';
if ($final_price > 0) {
// Paid upgrade - check license
$sw_version_license = $equipment['sw_version_license'];
if (!$sw_version_license) {
http_response_code(402);
log_download([
'user_id' => $user_data['id'],
'version_id' => $version_id,
'status' => 'failed',
'error_message' => 'License required',
'accounthierarchy' => $equipment['accounthierarchy'],
'createdby' => $username
]);
echo json_encode([
"error" => "LICENSE_REQUIRED",
"message" => "Valid license required",
"price" => $final_price,
"currency" => $upgrade_pricing['currency']
]);
exit;
}
// Validate license
$sql = 'SELECT status, starts_at, expires_at
FROM products_software_licenses
WHERE license_key = ? AND equipment_id = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute([$sw_version_license, $equipment['equipment_rowid']]);
$license = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$license || $license['status'] != 1) {
http_response_code(402);
log_download([
'user_id' => $user_data['id'],
'version_id' => $version_id,
'status' => 'failed',
'error_message' => 'Invalid license',
'accounthierarchy' => $equipment['accounthierarchy'],
'createdby' => $username
]);
echo json_encode(["error" => "INVALID_LICENSE", "message" => "License is invalid"]);
exit;
}
// Check license date validity
$now = date('Y-m-d H:i:s');
if (($license['starts_at'] && $license['starts_at'] > $now) ||
($license['expires_at'] && $license['expires_at'] < $now)) {
http_response_code(402);
log_download([
'user_id' => $user_data['id'],
'version_id' => $version_id,
'status' => 'failed',
'error_message' => 'License expired',
'accounthierarchy' => $equipment['accounthierarchy'],
'createdby' => $username
]);
echo json_encode(["error" => "LICENSE_EXPIRED", "message" => "License is expired"]);
exit;
}
}
// STEP 8: Build file path and verify exists
$firmware_path = dirname(__FILE__, 4) . '/firmware/' . $version['file_path'];
if (!file_exists($firmware_path)) {
http_response_code(404);
log_download([
'user_id' => $user_data['id'],
'version_id' => $version_id,
'status' => 'failed',
'error_message' => 'File not found on server',
'accounthierarchy' => $equipment['accounthierarchy'],
'createdby' => $username
]);
echo json_encode(["error" => "FILE_NOT_FOUND", "message" => "Firmware file not available"]);
exit;
}
// STEP 9: Stream file and log
$file_size = filesize($firmware_path);
try {
// Log successful download before streaming
$download_time = round(microtime(true) - $download_start);
log_download([
'user_id' => $user_data['id'],
'version_id' => $version_id,
'file_size' => $file_size,
'download_time_seconds' => $download_time,
'status' => 'success',
'accounthierarchy' => $equipment['accounthierarchy'],
'createdby' => $username
]);
// Stream file (function handles path traversal check and exits after streaming)
stream_file_download($firmware_path, $version['file_path']);
} catch (Exception $e) {
log_download([
'user_id' => $user_data['id'],
'version_id' => $version_id,
'file_size' => $file_size,
'status' => 'failed',
'error_message' => $e->getMessage(),
'accounthierarchy' => $equipment['accounthierarchy'],
'createdby' => $username
]);
http_response_code(500);
echo json_encode(["error" => "DOWNLOAD_FAILED", "message" => "Download failed"]);
}
?>