From 8b65750d389f424675a8c70040058510d8ea9b73 Mon Sep 17 00:00:00 2001
From: Ludovic Brun SQLite
diff --git a/www/controllers/Autoloader.php b/www/controllers/Autoloader.php
index bf1c226c..d2615eef 100644
--- a/www/controllers/Autoloader.php
+++ b/www/controllers/Autoloader.php
@@ -182,6 +182,10 @@ private static function checkPhpModules()
$__LOAD_PHP_MODULES_ERROR++;
$__LOAD_PHP_MODULES_MESSAGES[] = " - xml module for PHP is not installed or disabled.";
}
+ if (!in_array('curl', $modules)) {
+ $__LOAD_PHP_MODULES_ERROR++;
+ $__LOAD_PHP_MODULES_MESSAGES[] = " - curl module for PHP is not installed or disabled.";
+ }
if (!defined('__LOAD_PHP_MODULES_ERROR')) {
define('__LOAD_PHP_MODULES_ERROR', $__LOAD_PHP_MODULES_ERROR);
diff --git a/www/controllers/Common.php b/www/controllers/Common.php
index 07c565fa..aec69d1c 100644
--- a/www/controllers/Common.php
+++ b/www/controllers/Common.php
@@ -683,4 +683,50 @@ public static function gunzip(string $filename)
throw new Exception('Error while closing gziped file: ' . $filename);
}
}
+
+ /**
+ * Uncompress specified xz file 'file.xz' to 'file'
+ */
+ public static function xzUncompress(string $filename)
+ {
+ $myprocess = new Process('/usr/bin/xz --decompress ' . $filename);
+ $myprocess->execute();
+ $content = $myprocess->getOutput();
+ $myprocess->close();
+
+ if ($myprocess->getExitCode() != 0) {
+ throw new Exception('Error while uncompressing xz file ' . $filename . ': ' . $content);
+ }
+ }
+
+ /**
+ * Return true if distant URL file exists
+ */
+ public static function urlFileExists(string $url, string $sslCertificatePath = null, string $sslPrivateKeyPath = null)
+ {
+ $ch = curl_init($url);
+ curl_setopt($ch, CURLOPT_NOBODY, true);
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
+ /**
+ * If a custom SSL certificate and key have been specified
+ */
+ if (!empty($sslCertificatePath)) {
+ curl_setopt($ch, CURLOPT_SSLCERT, $sslCertificatePath);
+ }
+ if (!empty($sslPrivateKeyPath)) {
+ curl_setopt($ch, CURLOPT_SSLKEY, $sslPrivateKeyPath);
+ }
+
+ curl_exec($ch);
+
+ $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+
+ curl_close($ch);
+
+ if ($responseCode != 200) {
+ return false;
+ }
+
+ return true;
+ }
}
diff --git a/www/controllers/Mirror.php b/www/controllers/Mirror.php
index a6d9adc7..309486b3 100644
--- a/www/controllers/Mirror.php
+++ b/www/controllers/Mirror.php
@@ -26,8 +26,8 @@ class Mirror
private $workingDir;
private $outputToFile = false;
private $outputFile;
- private $customCertificate;
- private $customPrivateKey;
+ private $sslCustomCertificate;
+ private $sslCustomPrivateKey;
public function setType(string $type)
{
@@ -79,14 +79,14 @@ public function setSyncSource(string $syncSource)
$this->syncSource = $syncSource;
}
- public function setCustomCertificate(string $path)
+ public function setSslCustomCertificate(string $path)
{
- $this->customCertificate = $path;
+ $this->sslCustomCertificate = $path;
}
- public function setCustomPrivateKey(string $path)
+ public function setSslCustomPrivateKey(string $path)
{
- $this->customPrivateKey = $path;
+ $this->sslCustomPrivateKey = $path;
}
/**
@@ -134,10 +134,22 @@ private function getReleaseFile()
{
$this->logOutput(PHP_EOL . '- Getting Release indices file ... ');
- $this->download($this->url . '/dists/' . $this->dist . '/InRelease', $this->workingDir . '/InRelease');
- $this->download($this->url . '/dists/' . $this->dist . '/Release', $this->workingDir . '/Release');
- $this->download($this->url . '/dists/' . $this->dist . '/Release.gpg', $this->workingDir . '/Release.gpg');
+ /**
+ * Check that Release.xx file exists before downloading it to prevent error message displaying for nothing
+ */
+ if (Common::urlFileExists($this->url . '/dists/' . $this->dist . '/InRelease', $this->sslCustomCertificate, $this->sslCustomPrivateKey)) {
+ $this->download($this->url . '/dists/' . $this->dist . '/InRelease', $this->workingDir . '/InRelease');
+ }
+ if (Common::urlFileExists($this->url . '/dists/' . $this->dist . '/Release', $this->sslCustomCertificate, $this->sslCustomPrivateKey)) {
+ $this->download($this->url . '/dists/' . $this->dist . '/Release', $this->workingDir . '/Release');
+ }
+ if (Common::urlFileExists($this->url . '/dists/' . $this->dist . '/Release.gpg', $this->sslCustomCertificate, $this->sslCustomPrivateKey)) {
+ $this->download($this->url . '/dists/' . $this->dist . '/Release.gpg', $this->workingDir . '/Release.gpg');
+ }
+ /**
+ * Print an error and quit if no Release file has been found
+ */
if (!file_exists($this->workingDir . '/InRelease') and !file_exists($this->workingDir . '/Release') and !file_exists($this->workingDir . '/Release.gpg')) {
$this->logError('Error', 'Could not download Release indices file');
}
@@ -265,7 +277,7 @@ private function parsePrimaryPackagesList(string $primaryFile)
$packageChecksum = $data['checksum'];
/**
- * If path and md5sum have been parsed, had them to the global rpm packages list array
+ * If path and checksum have been parsed, had them to the global rpm packages list array
*/
$this->rpmPackagesLocation[] = array('location' => $packageLocation, 'checksum' => $packageChecksum);
}
@@ -312,24 +324,37 @@ private function parseReleaseIndiceFile()
* Packages pattern to search in the Release file
* e.g: main/binary-amd64/Packages
*/
- $regex = $this->section . '/binary-' . $arch . '/Packages';
+ $regex = $this->section . '/binary-' . $arch . '/Packages($|.gz$|.xz$)';
/**
* Parse the whole file, searching for the desired lines
*/
foreach ($content as $line) {
- if (preg_match("#$regex$#", $line)) {
+ if (preg_match("#$regex#", $line)) {
/**
* Explode the line to separate hashes and location
*/
$splittedLine = explode(' ', trim($line));
/**
- * We only need the location with its md5sum (32 caracters long)
- * e.g: 006b66a6902a5c0ae6a921f7dab4238c 44688496 main/binary-amd64/Packages
+ * We only need the location with its SHA256 (64 caracters long)
+ * e.g: bd29d2ec28c10fec66a139d8e9a88ca01ff0f2533ca3fab8dc33c13b533059c1 1279885 main/binary-amd64/Packages
*/
- if (strlen($splittedLine[0]) == '32') {
- $this->packagesIndicesLocation[] = array('location' => end($splittedLine), 'md5sum' => $splittedLine[0]);
+ if (strlen($splittedLine[0]) == '64') {
+ $location = end($splittedLine);
+ $checksum = $splittedLine[0];
+
+ /**
+ * Include this Package.xx file only if it does really exist on the remote server (sometimes it can be declared in Release but not exists...)
+ */
+ if (Common::urlFileExists($this->url . '/dists/' . $this->dist . '/' . $location, $this->sslCustomCertificate, $this->sslCustomPrivateKey)) {
+ $this->packagesIndicesLocation[] = array('location' => $location, 'checksum' => $checksum);
+
+ /**
+ * Then ignore all next Package.xx indices file from the same arch as at least one has been found
+ */
+ break 1;
+ }
}
}
}
@@ -446,36 +471,47 @@ private function parsePackagesIndiceFile()
*/
foreach ($this->packagesIndicesLocation as $packageIndice) {
$packageIndicesLocation = $packageIndice['location'];
- $packageIndexMd5 = $packageIndice['md5sum'];
+ $packageIndicesChecksum = $packageIndice['checksum'];
+ $packageIndicesName = preg_split('#/#', $packageIndicesLocation);
+ $packageIndicesName = end($packageIndicesName);
/**
- * Download Packages.gz file using its location
+ * Download Packages.xx file using its location
*/
- if (!$this->download($this->url . '/dists/' . $this->dist . '/' . $packageIndicesLocation . '.gz', $this->workingDir . '/Packages.gz')) {
- $this->logError('Error while downloading Packages.gz indices file: ' . $this->url . '/' . $packageIndicesLocation, 'Could not download Packages indices file');
+ if (!$this->download($this->url . '/dists/' . $this->dist . '/' . $packageIndicesLocation, $this->workingDir . '/' . $packageIndicesName)) {
+ $this->logError('Error while downloading ' . $packageIndicesName . ' indices file: ' . $this->url . '/' . $packageIndicesLocation, 'Could not download ' . $packageIndicesName . ' indices file');
}
/**
- * Gunzip Packages.gz
+ * Then check that the Packages.xx file's checksum matches the one that what specified in Release file
*/
- try {
- \Controllers\Common::gunzip($this->workingDir . '/Packages.gz');
- } catch (Exception $e) {
- $this->logError($e, 'Error while uncompressing Packages.gz');
+ if (hash_file('sha256', $this->workingDir . '/' . $packageIndicesName) !== $packageIndicesChecksum) {
+ $this->logError($packageIndicesName . ' indices file\'s SHA256 checksum does not match the SHA256 checksum specified in the Release file ' . $packageIndicesChecksum, 'Could not verify Packages indices file');
}
/**
- * Then check that the gunzip Packages file's md5 is the same as the one that what specified in Release file
+ * Uncompress Packages.xx if it is compressed (.gz or .xz)
*/
- if (md5_file($this->workingDir . '/Packages') !== $packageIndexMd5) {
- $this->logError('Packages indices file\'s md5 (' . md5_file($this->workingDir . '/Packages') . ') does not match the md5 specified in the Release file ' . $packageIndexMd5, 'Could not verify Packages indices file');
+ if (preg_match('/.gz$/i', $packageIndicesName)) {
+ try {
+ Common::gunzip($this->workingDir . '/' . $packageIndicesName);
+ } catch (Exception $e) {
+ $this->logError($e, 'Error while uncompressing ' . $packageIndicesName);
+ }
+ }
+ if (preg_match('/.xz$/i', $packageIndicesName)) {
+ try {
+ Common::xzUncompress($this->workingDir . '/Packages.xz');
+ } catch (Exception $e) {
+ $this->logError($e, 'Error while uncompressing Packages.xz');
+ }
}
/**
* Get all .deb packages location from the uncompressed Packages file
*/
$packageLocation = '';
- $packageMd5 = '';
+ $packageChecksum = '';
$handle = fopen($this->workingDir . '/Packages', 'r');
if ($handle) {
@@ -488,19 +524,19 @@ private function parsePackagesIndiceFile()
}
/**
- * Get deb md5sum
+ * Get deb SHA256
*/
- if (preg_match('/^MD5sum:\s+(.*)/im', $line)) {
- $packageMd5 = trim(str_replace('MD5sum: ', '', $line));
+ if (preg_match('/^SHA256:\s+(.*)/im', $line)) {
+ $packageChecksum = trim(str_replace('SHA256: ', '', $line));
}
/**
- * If location and md5sum have been parsed, had them to the global deb packages list array
+ * If location and checksum have been parsed, had them to the global deb packages list array
*/
- if (!empty($packageLocation) and !empty($packageMd5)) {
- $this->debPackagesLocation[] = array('location' => $packageLocation, 'md5sum' => $packageMd5);
+ if (!empty($packageLocation) and !empty($packageChecksum)) {
+ $this->debPackagesLocation[] = array('location' => $packageLocation, 'checksum' => $packageChecksum);
- unset($packageLocation, $packageMd5);
+ unset($packageLocation, $packageChecksum);
}
}
@@ -690,28 +726,19 @@ private function download(string $url, string $savePath)
$localFile = fopen($savePath, "w");
$ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $url); // set remote file url
- curl_setopt($ch, CURLOPT_FILE, $localFile); // set output file
- curl_setopt($ch, CURLOPT_TIMEOUT, 30); // set timeout
- // curl_setopt($ch, CURLOPT_PORT , 443);
- // curl_setopt($ch, CURLOPT_VERBOSE, 0);
- // curl_setopt($ch, CURLOPT_HEADER, 0);
- // curl_setopt($ch, CURLOPT_SSLCERT, getcwd() . "/public_cert.pem");
- // curl_setopt($ch, CURLOPT_SSLKEY, getcwd() . "/private.pem");
- // curl_setopt($ch, CURLOPT_CAINFO, "/etc/ssl/certs/ca-certificates.crt");
- // curl_setopt($ch, CURLOPT_POST, 1);
- // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
- // curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- // curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
+ curl_setopt($ch, CURLOPT_URL, $url); // set remote file url
+ curl_setopt($ch, CURLOPT_FILE, $localFile); // set output file
+ curl_setopt($ch, CURLOPT_TIMEOUT, 120); // set timeout
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // follow redirect
/**
* If a custom ssl certificate and private key must be used
*/
- if (!empty($this->customCertificate)) {
- curl_setopt($ch, CURLOPT_SSLCERT, $this->customCertificate);
+ if (!empty($this->sslCustomCertificate)) {
+ curl_setopt($ch, CURLOPT_SSLCERT, $this->sslCustomCertificate);
}
- if (!empty($this->customPrivateKey)) {
- curl_setopt($ch, CURLOPT_SSLKEY, $this->customPrivateKey);
+ if (!empty($this->sslCustomPrivateKey)) {
+ curl_setopt($ch, CURLOPT_SSLKEY, $this->sslCustomPrivateKey);
}
/**
@@ -937,7 +964,7 @@ private function downloadDebPackages($url)
*/
foreach ($this->debPackagesLocation as $debPackage) {
$debPackageLocation = $debPackage['location'];
- $debPackageMd5 = $debPackage['md5sum'];
+ $debPackageChecksum = $debPackage['checksum'];
$debPackageName = preg_split('#/#', $debPackageLocation);
$debPackageName = end($debPackageName);
$packageCounter++;
@@ -955,10 +982,10 @@ private function downloadDebPackages($url)
}
/**
- * Check that downloaded deb package's md5 matches the md5sum specified by the Packages file
+ * Check that downloaded deb package's sha256 matches the sha256 specified by the Packages file
*/
- if (md5_file($this->workingDir . '/packages/' . $debPackageName) != $debPackageMd5) {
- $this->logError('md5 does not match', 'Error while retrieving packages');
+ if (hash_file('sha256', $this->workingDir . '/packages/' . $debPackageName) != $debPackageChecksum) {
+ $this->logError('SHA256 does not match', 'Error while retrieving packages');
}
/**
diff --git a/www/controllers/Planification.php b/www/controllers/Planification.php
index d0266b9f..4d5df99b 100644
--- a/www/controllers/Planification.php
+++ b/www/controllers/Planification.php
@@ -684,7 +684,7 @@ public function exec()
/**
* On peut récupérer toutes les informations du repo à partir de l'Id de repo et de l'Id de snapshot
*/
- $this->repo->getAllById($repoId, $mostRecentSnapId);
+ $this->repo->getAllById($repoId, $mostRecentSnapId, '', false);
/**
* Si le snapshot de repo est de type 'local' alors on passe au repo suivant
@@ -1343,7 +1343,7 @@ private function getInfo(string $id)
*/
if (!empty($planInfo['Id_snap'])) {
$this->repo->setSnapId($planInfo['Id_snap']);
- $this->repo->getAllById('', $this->repo->getSnapId());
+ $this->repo->getAllById('', $this->repo->getSnapId(), '', false);
}
if (!empty($planInfo['Id_group'])) {
$this->group->setId($planInfo['Id_group']);
diff --git a/www/controllers/Repo.php b/www/controllers/Repo.php
index 62ca8ba7..4a0ccc87 100644
--- a/www/controllers/Repo.php
+++ b/www/controllers/Repo.php
@@ -1998,11 +1998,6 @@ private function getPackages()
throw new Exception('Local repo snapshot cannot be updated');
}
- /**
- * Get source repo Url
- */
- $this->getFullSource($this->packageType, $this->source);
-
/**
* 2. Si il s'agit d'un nouveau repo, on vérifie qu'un repo du même nom avec un ou plusieurs snapshots actifs n'existe pas déjà.
* Un repo peut exister et n'avoir aucun snapshot / environnement rattachés (il sera invisible dans la liste) mais dans ce cas cela ne doit pas empêcher la création d'un nouveau repo
@@ -2076,15 +2071,6 @@ private function getPackages()
$this->workingDir = REPOS_DIR . '/download-mirror-' . $this->name . '-' . $this->dist . '-' . $this->section . '-' . time();
}
- /**
- * Si le répertoire existe déjà, on le supprime
- */
- if (is_dir($repoPath)) {
- if (!Common::deleteRecursive($repoPath)) {
- throw new Exception('Cannot delete existing directory: ' . $repoPath);
- }
- }
-
/**
* 3. Retrieving packages
*/
@@ -2096,13 +2082,27 @@ private function getPackages()
*/
if ($this->packageType == 'deb') {
try {
+ /**
+ * Get source repo informations
+ */
$mysource = new Source();
$sourceDetails = $mysource->getAll('deb', $this->source);
+
+ /**
+ * Check source repo informations
+ */
+ if (empty($sourceDetails)) {
+ throw new Exception('Could not retrieve source repo informations. Does the source repo still exists?');
+ }
+ if (empty($sourceDetails['Url'])) {
+ throw new Exception('Could not retrieve source repo URL. Check source repo configuration.');
+ }
+
unset($mysource);
$mymirror = new Mirror();
$mymirror->setType('deb');
- $mymirror->setUrl($this->fullUrl);
+ $mymirror->setUrl($sourceDetails['Url']);
$mymirror->setWorkingDir($this->workingDir);
$mymirror->setDist($this->dist);
$mymirror->setSection($this->section);
@@ -2113,10 +2113,10 @@ private function getPackages()
$mymirror->setOutputFile($this->op->log->steplog);
$mymirror->outputToFile(true);
if (!empty($sourceDetails['Ssl_certificate_path'])) {
- $mymirror->setCustomCertificate('/etc/ssl/nginx/nginx-repo.crt');
+ $mymirror->setSslCustomCertificate('/etc/ssl/nginx/nginx-repo.crt');
}
if (!empty($sourceDetails['Ssl_private_key_path'])) {
- $mymirror->setCustomPrivateKey('/etc/ssl/nginx/nginx-repo.key');
+ $mymirror->setSslCustomPrivateKey('/etc/ssl/nginx/nginx-repo.key');
}
$mymirror->mirror();
@@ -2131,8 +2131,14 @@ private function getPackages()
/**
* Renaming working dir name to final name
+ * First delete the target directory if it already exists
*/
- if (!rename($this->workingDir, REPOS_DIR . '/' . $this->name . '/' . $this->dist . '/' . $this->targetDateFormatted . '_' . $this->section)) {
+ if (is_dir($repoPath)) {
+ if (!Common::deleteRecursive($repoPath)) {
+ throw new Exception('Cannot delete existing directory: ' . $repoPath);
+ }
+ }
+ if (!rename($this->workingDir, $repoPath)) {
throw new Exception('Could not rename working directory ' . $this->workingDir);
}
} catch (Exception $e) {
@@ -2143,13 +2149,27 @@ private function getPackages()
if ($this->packageType == 'rpm') {
try {
+ /**
+ * Get source repo informations
+ */
$mysource = new Source();
$sourceDetails = $mysource->getAll('rpm', $this->source);
+
+ /**
+ * Check source repo informations
+ */
+ if (empty($sourceDetails)) {
+ throw new Exception('Could not retrieve source repo informations. Does the source repo still exists?');
+ }
+ if (empty($sourceDetails['Url'])) {
+ throw new Exception('Could not retrieve source repo URL. Check source repo configuration.');
+ }
+
unset($mysource);
$mymirror = new Mirror();
$mymirror->setType('rpm');
- $mymirror->setUrl($this->fullUrl);
+ $mymirror->setUrl($sourceDetails['Url']);
$mymirror->setWorkingDir($this->workingDir);
$mymirror->setArch($this->targetArch);
$mymirror->setSyncSource($this->targetSourcePackage);
@@ -2163,17 +2183,23 @@ private function getPackages()
$mymirror->setGpgKeyUrl($sourceDetails['Gpgkey']);
}
if (!empty($sourceDetails['Ssl_certificate_path'])) {
- $mymirror->setCustomCertificate($sourceDetails['Ssl_certificate_path']);
+ $mymirror->setSslCustomCertificate($sourceDetails['Ssl_certificate_path']);
}
if (!empty($sourceDetails['Ssl_private_key_path'])) {
- $mymirror->setCustomPrivateKey($sourceDetails['Ssl_private_key_path']);
+ $mymirror->setSslCustomPrivateKey($sourceDetails['Ssl_private_key_path']);
}
$mymirror->mirror();
/**
* Renaming working dir name to final name
+ * First delete the target directory if it already exists
*/
- if (!rename($this->workingDir, REPOS_DIR . '/' . $this->targetDateFormatted . '_' . $this->name)) {
+ if (is_dir($repoPath)) {
+ if (!Common::deleteRecursive($repoPath)) {
+ throw new Exception('Cannot delete existing directory: ' . $repoPath);
+ }
+ }
+ if (!rename($this->workingDir, $repoPath)) {
throw new Exception('Could not rename working directory ' . $this->workingDir);
}
} catch (Exception $e) {
@@ -3450,6 +3476,7 @@ public function printRepoList(array $reposList)
$this->time = $repo['Time'];
$this->type = $repo['Type'];
$this->signed = $repo['Signed'];
+ $this->arch = $repo['Arch'];
if (!empty($repo['Description'])) {
$this->description = $repo['Description'];
} else {
@@ -3573,11 +3600,12 @@ private function printRepoLine()
*/
if ($this->snapId != $this->lastSnapId) :
if ($this->snapOpIsRunning($this->snapId) === true) : ?>
-
+
envId) ? 'env-id="' . $this->envId . '"' : ''; ?> repo-type="= $this->type ?>" title="Select and execute an action.">
-
-
+
type == "mirror") {
- echo '
';
+ echo '
';
} elseif ($this->type == "local") {
- echo '
';
+ echo '
';
} else {
echo '
';
}
diff --git a/www/includes/footer.inc.php b/www/includes/footer.inc.php
index bc65722e..6c5beb92 100644
--- a/www/includes/footer.inc.php
+++ b/www/includes/footer.inc.php
@@ -1,10 +1,10 @@
New release available
'; - } - ?> + echo 'New release available: ' .GIT_VERSION. '
'; + } ?>These are the public GPG signing keys you have imported.
- -- = $knownPublicKey['name'] ?> - | -
- |
-
These are the public GPG signing keys you have imported.
+ ++ = $knownPublicKey['name'] ?> + | +
+ |
+