Skip to content

Commit

Permalink
Merge pull request #231 from lbr38/devel
Browse files Browse the repository at this point in the history
4.16.2
  • Loading branch information
lbr38 authored Jan 21, 2025
2 parents e1951fd + e30e4c0 commit d17e4d9
Show file tree
Hide file tree
Showing 11 changed files with 251 additions and 109 deletions.
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ ARG max_upload_size

# Install dependencies
RUN apt-get update -y
RUN apt-get install findutils iputils-ping git gnupg2 rpm librpmsign9 createrepo-c apt-utils curl ca-certificates apt-transport-https dnsutils xz-utils bzip2 vim -y
RUN apt-get install findutils iputils-ping git gnupg2 rpm librpmsign9 createrepo-c apt-utils curl ca-certificates apt-transport-https dnsutils xz-utils bzip2 zstd vim -y

# Install postfix
RUN apt-get install postfix -y
Expand Down
17 changes: 17 additions & 0 deletions www/controllers/Common.php
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,23 @@ public static function xzUncompress(string $filename, string $outputFilename = n
unset($myprocess, $content);
}

/**
* Uncompress specified zstd file 'file.zst' to 'file'
*/
public static function zstdUncompress(string $filename)
{
$myprocess = new \Controllers\Process('/usr/bin/unzstd ' . $filename);
$myprocess->execute();
$content = $myprocess->getOutput();
$myprocess->close();

if ($myprocess->getExitCode() != 0) {
throw new Exception('Error while uncompressing zstd file ' . $filename . ': ' . $content);
}

unset($myprocess, $content);
}

/**
* Return true if distant URL is reachable
* The target URL can be a file or a directory
Expand Down
185 changes: 90 additions & 95 deletions www/controllers/Gpg.php
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,13 @@ public function import(string $gpgKeyUrl, string $gpgKeyFingerprint, string $gpg
throw new Exception('Invalid URL');
}

/**
* If the user specified a URL in the fingerprint field, quit
*/
if (!empty($gpgKeyFingerprint) and preg_match('#^http(s)?://#', $gpgKeyFingerprint)) {
throw new Exception('Invalid fingerprint');
}

try {
/**
* Import GPG key from URL
Expand Down Expand Up @@ -339,76 +346,88 @@ public function import(string $gpgKeyUrl, string $gpgKeyFingerprint, string $gpg
}

/**
* Import a plain text GPG key
* Import a file-based GPG key
*/
public function importPlainText(string $gpgKey)
private function importRawContent(string $fileContent) : array
{
$gpgKey = \Controllers\Common::validateData($gpgKey);
$gpgTempFile = TEMP_DIR . '/.repomanager-newgpgkey.tmp';

/**
* Check if the ASCII text contains invalid characters
*/
if (!\Controllers\Common::isAlphanum($gpgKey, array('-', '=', '+', '/', ' ', ':', '.', '(', ')', "\n", "\r"))) {
throw new Exception('ASCII GPG key contains invalid characters');
}

/**
* Quit if user tries to import a GPG from url
*/
if (preg_match('#http(s)?://#', $gpgKey)) {
if (preg_match('#http(s)?://#', $fileContent)) {
throw new Exception('GPG key must be specified in ASCII text format');
}

/**
* Quit if the user tries to import a file on the system
*/
if (file_exists($gpgKey)) {
if (file_exists($fileContent)) {
throw new Exception('GPG key must be specified in ASCII text format');
}

/**
* Create a temporary file with the ASCII text
*/
if (!file_put_contents($gpgTempFile, $gpgKey)) {
$gpgTempFile = TEMP_DIR . '/.repomanager-newgpgkey.tmp';
if (!file_put_contents($gpgTempFile, $fileContent)) {
throw new Exception('could not initialize GPG import');
}

/**
* First, extract the fingerprints from the GPG key (there could be one or multiple)
*/
$myprocess = new Process("/usr/bin/gpg --homedir " . GPGHOME . " --no-default-keyring --keyring " . GPGHOME . "/trustedkeys.gpg --show-keys --with-fingerprint --with-colons " . $gpgTempFile . " | grep '^fpr' | cut -d: -f10");
$myprocess->execute();
$content = $myprocess->getOutput();
$myprocess->close();
try {
/**
* First, extract the fingerprints from the GPG key (there could be one or multiple)
*/
$myprocess = new Process("/usr/bin/gpg --homedir " . GPGHOME . " --no-default-keyring --keyring " . GPGHOME . "/trustedkeys.gpg --show-keys --with-fingerprint --with-colons " . $gpgTempFile . " | grep '^fpr' | cut -d: -f10");
$myprocess->execute();
$content = $myprocess->getOutput();
$myprocess->close();

if ($myprocess->getExitCode() != 0) {
throw new Exception('could not retrieve fingerprint(s) from GPG key: <br><br><pre class="codeblock">"' . $content . '</pre>');
}
if ($myprocess->getExitCode() != 0) {
throw new Exception('could not retrieve fingerprint(s) from GPG key: <br><br><pre class="codeblock">"' . $content . '</pre>');
}

/**
* Output will print all fingerprints on multiple lines (one per fingerprint)
*/
$fingerprints = explode(PHP_EOL, $content);
/**
* Output will print all fingerprints on multiple lines (one per fingerprint)
*/
$fingerprints = explode(PHP_EOL, $content);

/**
* Import file into the repomanager trusted keyring
*/
$myprocess = new \Controllers\Process('/usr/bin/gpg --no-default-keyring --keyring ' . GPGHOME . '/trustedkeys.gpg --import ' . $gpgTempFile);
$myprocess->execute();
$content = $myprocess->getOutput();
$myprocess->close();
/**
* Import file into the repomanager trusted keyring
*/
$myprocess = new \Controllers\Process('/usr/bin/gpg --no-default-keyring --keyring ' . GPGHOME . '/trustedkeys.gpg --import ' . $gpgTempFile);
$myprocess->execute();
$content = $myprocess->getOutput();
$myprocess->close();

if ($myprocess->getExitCode() != 0) {
throw new Exception('<pre class="codeblock margin-top-5">' . $content . '</pre>');
}

return $fingerprints;
} finally {
/**
* Delete temp file
*/
if (!unlink($gpgTempFile)) {
throw new Exception('cannot delete temporary file: ' . $tempFile);
}
}
}

/**
* Import a plain text GPG key
*/
public function importPlainText(string $gpgKey) : array
{
$gpgKey = \Controllers\Common::validateData($gpgKey);

/**
* Delete temp file
* Check if the ASCII text contains invalid characters
*/
unlink($gpgTempFile);

if ($myprocess->getExitCode() != 0) {
throw new Exception('<pre class="codeblock margin-top-5">' . $content . '</pre>');
if (!\Controllers\Common::isAlphanum($gpgKey, array('-', '=', '+', '/', ' ', ':', '.', '(', ')', "\n", "\r"))) {
throw new Exception('ASCII GPG key contains invalid characters');
}

return $fingerprints;
return $this->importRawContent($gpgKey);
}

/**
Expand All @@ -417,9 +436,6 @@ public function importPlainText(string $gpgKey)
*/
public function importFromUrl(string $url) : array
{
$fingerprints = [];
$tempFile = TEMP_DIR . '/import-gpgkey.asc';

/**
* Quit if the URL is not valid
*/
Expand All @@ -436,16 +452,15 @@ public function importFromUrl(string $url) : array
* Init curl
*/
$ch = curl_init();
$targetFile = fopen($tempFile, 'w');

/**
* Download GPG key from URL
*/
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FILE, $targetFile); // set output file
curl_setopt($ch, CURLOPT_TIMEOUT, 5); // set timeout
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // follow redirect
curl_setopt($ch, CURLOPT_ENCODING, ''); // use compression if any
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // output content to return

/**
* If a proxy has been specified
Expand All @@ -454,66 +469,46 @@ public function importFromUrl(string $url) : array
curl_setopt($ch, CURLOPT_PROXY, PROXY);
}

if (curl_exec($ch) === false) {
/**
* If curl has failed (meaning a curl param might be invalid)
*/
throw new Exception('curl error: ' . curl_error($ch));
$result = curl_exec($ch);

curl_close($ch);
fclose($targetFile);
}
try {
if ($result === false) {
/**
* If curl has failed (meaning a curl param might be invalid)
*/
throw new Exception('curl error: ' . curl_error($ch));
}

/**
* Check that the http return code is 200 (the file has been downloaded)
*/
$status = curl_getinfo($ch);
if (empty($result)) {
/**
* If key is empty, meaning bad key
*/
throw new Exception('empty gpg key response (downloaded file is empty)');
}

if ($status["http_code"] != 200) {
/**
* If return code is 404
* Check that the http return code is 200 (the file has been downloaded)
*/
if ($status["http_code"] == '404') {
throw new Exception('404 file not found');
} else {
throw new Exception('file could not be downloaded (http return code is: ' . $status["http_code"] . ')');
$status = curl_getinfo($ch);

if ($status["http_code"] != 200) {
/**
* If return code is 404
*/
if ($status["http_code"] == '404') {
throw new Exception('404 file not found');
} else {
throw new Exception('file could not be downloaded (http return code is: ' . $status["http_code"] . ')');
}
}

} finally {
curl_close($ch);
fclose($targetFile);

return false;
}

fclose($targetFile);
curl_close($ch);

/**
* Get GPG key content
*/
$gpgKey = file_get_contents($tempFile);

if ($gpgKey === false) {
throw new Exception('error while reading temporary file: ' . $tempFile);
}

if (empty($gpgKey)) {
throw new Exception('empty while reading temporary file: ' . $tempFile . ' (file is empty)');
}

/**
* Import GPG key
*/
$fingerprints = $this->importPlainText($gpgKey);

/**
* Delete temp file
*/
if (!unlink($tempFile)) {
throw new Exception('cannot delete temporary file: ' . $tempFile);
}

return $fingerprints;
return $this->importRawContent($result);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions www/controllers/Repo/Mirror/Deb.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ private function parseReleaseFile()
$splittedLine = explode(' ', trim($line));

/**
* We only need the location with its SHA256 (64 caracters long)
* We only need the location with its SHA256 (64 characters long)
* e.g: bd29d2ec28c10fec66a139d8e9a88ca01ff0f2533ca3fab8dc33c13b533059c1 1279885 main/binary-amd64/Packages
*/
if (strlen($splittedLine[0]) == '64') {
Expand Down Expand Up @@ -181,7 +181,7 @@ private function parseReleaseFile()
$splittedLine = explode(' ', trim($line));

/**
* We only need the location with its md5sum (32 caracters long)
* We only need the location with its md5sum (32 characters long)
* e.g: 35e89f49cdfaa179e552aee1d67c5cdb 2478327 main/i18n/Translation-fr.bz2
*/
if (strlen($splittedLine[0]) == '32') {
Expand Down
7 changes: 6 additions & 1 deletion www/controllers/Repo/Mirror/Rpm.php
Original file line number Diff line number Diff line change
Expand Up @@ -451,14 +451,19 @@ private function parsePrimaryPackagesList(string $primaryFile)
*/
} elseif ($mime == 'application/gzip') {
\Controllers\Common::gunzip($primaryFile);
/**
* Case mime type is application/zstd (.gz file)
*/
} elseif ($mime == 'application/zstd') {
\Controllers\Common::zstdUncompress($primaryFile);
/**
* Case it's another mime type, throw an error
*/
} else {
throw new Exception('MIME type not supported: ' . $mime . '. Please contact the developer to add support for this MIME type.');
}
} catch (Exception $e) {
throw new Exception($e, 'Error while uncompressing <code>'. end(explode('/', $primaryFile)) . '</code>');
throw new Exception('Error while uncompressing <code>'. end(explode('/', $primaryFile)) . '</code>: <pre class="codeblock">' . $e->getMessage() . '</pre>');
}

/**
Expand Down
9 changes: 6 additions & 3 deletions www/controllers/Repo/Source/Deb.php
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,15 @@ public function addGpgKey(int $id, int $distributionId, string $gpgKeyUrl, strin
*/
foreach ($fingerprints as $fingerprint) {
// Ignore fingerprint if already exists
foreach ($currentParams['distributions'][$distributionId]['gpgkeys'] as $gpgKeyDefinition) {
if (isset($gpgKeyDefinition['fingerprint']) and $gpgKeyDefinition['fingerprint'] == $fingerprint) {
continue 2;
if (!empty($currentParams['distributions'][$distributionId]['gpgkeys'])) {
foreach ($currentParams['distributions'][$distributionId]['gpgkeys'] as $gpgKeyDefinition) {
if (isset($gpgKeyDefinition['fingerprint']) and $gpgKeyDefinition['fingerprint'] == $fingerprint) {
continue 2;
}
}
}

// Otherwise add the fingerprint
$currentParams['distributions'][$distributionId]['gpgkeys'][] = array(
'fingerprint' => $fingerprint
);
Expand Down
17 changes: 11 additions & 6 deletions www/controllers/Repo/Source/Rpm.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ public function addReleasever(int $id, string $name)
/**
* Check that a release version with the same name does not already exist
*/
foreach ($currentParams['releasever'] as $releasever) {
if ($releasever['name'] == $name) {
throw new Exception('Release version ' . $name . ' already exists');
if (!empty($currentParams['releasever'])) {
foreach ($currentParams['releasever'] as $releasever) {
if ($releasever['name'] == $name) {
throw new Exception('Release version ' . $name . ' already exists');
}
}
}

Expand Down Expand Up @@ -156,12 +158,15 @@ public function addGpgKey(int $id, int $releaseverId, string $gpgKeyUrl, string
*/
foreach ($fingerprints as $fingerprint) {
// Ignore fingerprint if already exists
foreach ($currentParams['releasever'][$releaseverId]['gpgkeys'] as $gpgKeyDefinition) {
if (isset($gpgKeyDefinition['fingerprint']) and $gpgKeyDefinition['fingerprint'] == $fingerprint) {
continue 2;
if (!empty($currentParams['releasever'][$releaseverId]['gpgkeys'])) {
foreach ($currentParams['releasever'][$releaseverId]['gpgkeys'] as $gpgKeyDefinition) {
if (isset($gpgKeyDefinition['fingerprint']) and $gpgKeyDefinition['fingerprint'] == $fingerprint) {
continue 2;
}
}
}

// Otherwise add the fingerprint
$currentParams['releasever'][$releaseverId]['gpgkeys'][] = array(
'fingerprint' => $fingerprint
);
Expand Down
Loading

0 comments on commit d17e4d9

Please sign in to comment.