]> jfr.im git - irc/unrealircd/unrealircd-webpanel.git/blobdiff - Classes/class-upgrade.php
Shut up some errors
[irc/unrealircd/unrealircd-webpanel.git] / Classes / class-upgrade.php
index ea993778cb658ef250ee73156281287258d9ab85..e29f6df847c7ecfd087555cae0c5e42832a0bac2 100644 (file)
@@ -3,7 +3,8 @@
 class Upgrade
 {
     public $web_dir;
 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;
     public static $upgrade_available;
     public static $last_check;
     public $error;
@@ -21,19 +22,21 @@ class Upgrade
         $tok = split(__DIR__, '/');
         unset($tok[count($tok) - 1]);
         $this->web_dir = implode('/',$tok).'/';
         $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;
         Upgrade::$upgrade_available = false;
-        $this->checkForNew();
         if ($this->error)
             error_log($this->error);
         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 */
     }
     
     /** Checks for a new upgrade */
@@ -41,12 +44,18 @@ class Upgrade
     {
         global $config;
         read_config_db();
     {
         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.";
         if ($response === false)
         {
             $this->error = "Couldn't check github.";
@@ -55,7 +64,7 @@ class Upgrade
         $data = json_decode($response, true);
         $latest = $data[count($data) - 1];
         $config['upgrade']['latest_version'] = $latest['tag_name'];
         $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;
         $config['upgrade']['download_link'] = $latest['zipball_url'];
         write_config('upgrade');
         Upgrade::$upgrade_available = (float)$latest['tag_name'] > WEBPANEL_VERSION ? true : false;
@@ -64,7 +73,7 @@ class Upgrade
     function downloadUpgradeZip()
     {
         $ch = curl_init(get_config('upgrade::download_link'));
     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);
     
         curl_setopt($ch, CURLOPT_FILE, $fp);
         curl_setopt($ch, CURLOPT_TIMEOUT, 60);
@@ -73,80 +82,183 @@ class Upgrade
             'User-Agent: UnrealIRCd Webpanel',
         ]);
         $success = curl_exec($ch);
             '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;
     }
         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;
     }
         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 {
         } 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);
 }
 }
-*/