class Upgrade
{
public $web_dir;
- public $download_dir;
+ private $temp_dir;
+ private static $temp_extracted_dir;
public static $upgrade_available;
public static $last_check;
public $error;
$tok = split(__DIR__, '/');
unset($tok[count($tok) - 1]);
$this->web_dir = implode('/',$tok).'/';
- $this->download_dir = $this->web_dir.'downloads';
+ /** prepare the temp directory */
+ $temp_dir = $this->web_dir."panel_upgrade";
+ $temp_dir .= ($temp_dir[strlen($temp_dir) - 1] != '/') ? "/" : "";
+ if (file_exists($temp_dir)) {
+ deleteDirectoryContents($temp_dir);
+ rmdir($temp_dir);
+ }
+ $mkdir = mkdir($temp_dir, 0755, true);
+
+ $this->temp_dir = $mkdir ? $temp_dir : NULL;
+ $this->error = $mkdir ? NULL : "Could not create directory: $temp_dir";
Upgrade::$upgrade_available = false;
- $this->checkForNew();
if ($this->error)
error_log($this->error);
- else
- {
- if (Upgrade::$upgrade_available)
- error_log("Upgrade available! Version ".Upgrade::$latest_version);
- else
- error_log("No upgrade available");
- }
}
/** Checks for a new upgrade */
{
global $config;
read_config_db();
- if (time() - $config['upgrade']['last_check'] < 300) // only check every 15 mins
- return $config['upgrade']['latest_version'] > WEBPANEL_VERSION ? true : false;
+ $last_check = &$config['upgrade']['last_check'];
+ if (isset($last_check) && time() - $last_check < 300) // only check every 15 mins
+ {
+ error_log("Skipping upgrade check, checked ".time() - $last_check." seconds ago");
+ return false;
+ }
+ error_log(time()." - ".$last_check." = ".time()-$last_check);
+ $apiUrl = "https://api.github.com/repos/unrealircd/unrealircd-webpanel/releases";
+ $response = file_get_contents($apiUrl, false, stream_context_create(
+ ["http" => ["method" => "GET", "header" => "User-agent: UnrealIRCd Webpanel"]]
+ ));
- // Define the API URL to check for updates
- $apiUrl = "https://api.github.com/repos/unrealircd/unrealircd-webpanel/releases"; // Replace with your API URL
- $response = file_get_contents($apiUrl, false, stream_context_create(["http" => ["method" => "GET", "header" => "User-agent: UnrealIRCd Webpanel"]]));
if ($response === false)
{
$this->error = "Couldn't check github.";
$data = json_decode($response, true);
$latest = $data[count($data) - 1];
$config['upgrade']['latest_version'] = $latest['tag_name'];
- $config['upgrade']['last_check'] = time();
+ $last_check = time();
$config['upgrade']['download_link'] = $latest['zipball_url'];
write_config('upgrade');
Upgrade::$upgrade_available = (float)$latest['tag_name'] > WEBPANEL_VERSION ? true : false;
function downloadUpgradeZip()
{
$ch = curl_init(get_config('upgrade::download_link'));
- $fp = fopen($this->download_dir."/unrealircd-webpanel-upgrade.zip", 'w+');
+ $fp = fopen($this->temp_dir."unrealircd-webpanel-upgrade.zip", 'w+');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
'User-Agent: UnrealIRCd Webpanel',
]);
$success = curl_exec($ch);
-
+ $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+
+ if ($code == "403" || $code == "404")
+ {
+ $this->error ="Unable to download";
+ }
curl_close($ch);
fclose($fp);
return $success;
}
+ function extractZip() {
+ $zip = new ZipArchive;
+ if ($zip->open($this->temp_dir."unrealircd-webpanel-upgrade.zip") === true)
+ {
+ $zip->extractTo("$this->temp_dir");
+ $zip->close();
+ self::$temp_extracted_dir = findOnlyDirectory($this->temp_dir);
+ error_log(self::$temp_extracted_dir);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ function cleanupOldFiles()
+ {
+ foreach ($this->compareAndGetFilesToDelete() as $file)
+ {
+ unlink("$this->web_dir$file");
+ error_log("Deleting: $file");
+ }
+ }
+ function compareAndGetFilesToDelete() : array
+ {
+ $currentFiles = $this->listFiles($this->web_dir);
+ $updateFiles = $this->listFiles(self::$temp_extracted_dir);
+ $filesToDelete = array_diff($currentFiles, $updateFiles);
+ $filesToActuallyDelete = [];
+ error_log("Comparing... Files to delete:");
+ foreach ($filesToDelete as $file)
+ {
+ // skip the relevant directories
+ if (str_starts_with($file, "panel_upgrade/")
+ || str_starts_with($file, "vendor/")
+ || str_starts_with($file, "config/")
+ || str_starts_with($file, "data/")
+ || str_starts_with($file, "plugins/"))
+ continue;
+ $filesToActuallyDelete[] = $file;
+ }
+ return $filesToActuallyDelete;
+ }
+
+ function extractToWebdir()
+ {
+ recurse_copy(self::$temp_extracted_dir, $this->web_dir);
+ }
+
+ /**
+ * Cleans up the extracted update files
+ * @return void
+ */
+ function cleanupDownloadFiles()
+ {
+ $ex_dir = self::$temp_extracted_dir ?? findOnlyDirectory($this->temp_dir);
+ deleteDirectoryContents($ex_dir);
+ rmdir($ex_dir);
+ }
+
+ function listFiles($dir) {
+ $files = [];
+ $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
+ foreach ($iterator as $file)
+ {
+ if ($file->isFile())
+ {
+ $f = substr($file->getPathname(), strlen($dir));
+ if ($f[0] == "/") $f = substr($f,1);
+
+ $files[] = $f;
+ }
+ }
+ return $files;
+ }
}
- // Define the URL to download the update
-$downloadUrl = "https://example.com/api/download_update"; // Replace with your download URL
-
-// Define the URL to download the update
-$downloadUrl = "https://example.com/api/download_update"; // Replace with your download URL
-// Define the directory where the update will be extracted
-$webDir = __DIR__; // Current directory
+function findOnlyDirectory($topDir) {
+ // Ensure the directory exists and is indeed a directory
+ if (!is_dir($topDir)) {
+ die("The specified path is not a directory.");
+ }
-// Function to check for updates
-function checkForUpdate($url) {
- $response = file_get_contents($url);
- if ($response === FALSE) {
- die("Error checking for updates.");
+ // Open the directory
+ $dirHandle = opendir($topDir);
+ if ($dirHandle === false) {
+ die("Unable to open directory.");
}
- $data = json_decode($response, true);
- return $data['update_available'] ?? false;
-}
-// Function to download the update
-function downloadUpdate($url, $savePath) {
- $ch = curl_init($url);
- $fp = fopen($savePath, 'w+');
+ $directories = [];
+
+ // Read through the directory contents
+ while (($entry = readdir($dirHandle)) !== false) {
+ $fullPath = $topDir . DIRECTORY_SEPARATOR . $entry;
+ // Check if the entry is a directory and not . or ..
+ if (is_dir($fullPath) && $entry !== '.' && $entry !== '..') {
+ $directories[] = $fullPath;
+ }
+ }
- curl_setopt($ch, CURLOPT_FILE, $fp);
- curl_setopt($ch, CURLOPT_TIMEOUT, 60);
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
+ // Close the directory handle
+ closedir($dirHandle);
- $success = curl_exec($ch);
+ // Check if there is exactly one directory
+ if (count($directories) === 1) {
+ return $directories[0];
+ } elseif (count($directories) === 0) {
+ return "No directories found after extracting. Possibly missing php-zip extention. Aborting upgrade.";
+ } else {
+ return "Multiple directories found. Previous cleanup was unsuccessful for some reason, maybe a permissions error? Aborting upgrade.";
+ }
+}
- curl_close($ch);
- fclose($fp);
- return $success;
-}
+function deleteDirectoryContents($dir) {
+ error_log("Deleting directory contents at $dir");
+ if (!is_dir($dir)) {
+ echo "The provided path is not a directory.";
+ return false;
+ }
-// Function to extract the zip file
-function extractZip($zipPath, $extractTo) {
- $zip = new ZipArchive;
- if ($zip->open($zipPath) === TRUE) {
- $zip->extractTo($extractTo);
- $zip->close();
- return true;
- } else {
+ // Open the directory
+ $handle = opendir($dir);
+ if ($handle === false) {
+ echo "Failed to open the directory.";
return false;
}
-}
-/**
-// Check for updates
-if (checkForUpdate($apiUrl)) {
- $tempZipFile = $webDir . '/update.zip';
-
- // Download the update
- if (downloadUpdate($downloadUrl, $tempZipFile)) {
- // Extract the update
- if (extractZip($tempZipFile, $webDir)) {
- echo "Update applied successfully.";
+
+ // Loop through the directory contents
+ while (($item = readdir($handle)) !== false) {
+ // Skip the special entries "." and ".."
+ if ($item == "." || $item == "..") {
+ continue;
+ }
+
+ $itemPath = $dir."/".$item;
+
+ // If the item is a directory, recursively delete its contents
+ if (is_dir($itemPath)) {
+ deleteDirectoryContents($itemPath);
+ // Remove the empty directory
+ rmdir($itemPath);
} else {
- echo "Failed to extract the update.";
+ // If the item is a file, delete it
+ unlink($itemPath);
}
- // Clean up the temporary zip file
- unlink($tempZipFile);
- } else {
- echo "Failed to download the update.";
}
-} else {
- echo "No update available.";
+
+ // Close the directory handle
+ closedir($handle);
+
+ return true;
+}
+
+function recurse_copy($src, $dst) {
+ $dir = opendir($src);
+ @mkdir($dst);
+ while(false !== ( $file = readdir($dir)) )
+ if (( $file != '.' ) && ( $file != '..' ))
+ {
+ if ( is_dir($src . '/' . $file) )
+ recurse_copy($src . '/' . $file, $dst . '/' . $file);
+
+ else
+ copy($src . '/' . $file, $dst . '/' . $file);
+ }
+
+
+ closedir($dir);
}
-*/