Skip to content

Commit 313ea63

Browse files
skjnldsvclaude
andcommitted
fix: allow file:// URLs with --url option
curl returns HTTP code 0 for file:// (no HTTP involved), causing the download step to incorrectly treat a successful local file copy as a failure. Skip the HTTP code check when the URL uses the file:// scheme. Add Behat scenarios covering the happy path (--no-verify) and the missing-signature error for local file URLs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
1 parent dbd620a commit 313ea63

4 files changed

Lines changed: 100 additions & 2 deletions

File tree

index.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,8 @@ private function downloadArchive(string $fromUrl, string $toLocation): bool {
784784
}
785785

786786
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
787-
if ($httpCode !== 200 && $httpCode !== 206) {
787+
$isFileUrl = str_starts_with($fromUrl, 'file://');
788+
if (!$isFileUrl && $httpCode !== 200 && $httpCode !== 206) {
788789
fclose($fp);
789790
unlink($toLocation);
790791
$this->silentLog('[warn] fail to download archive from ' . $fromUrl . '. Error: ' . $httpCode . ' ' . curl_error($ch));

lib/Updater.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,8 @@ private function downloadArchive(string $fromUrl, string $toLocation): bool {
768768
}
769769

770770
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
771-
if ($httpCode !== 200 && $httpCode !== 206) {
771+
$isFileUrl = str_starts_with($fromUrl, 'file://');
772+
if (!$isFileUrl && $httpCode !== 200 && $httpCode !== 206) {
772773
fclose($fp);
773774
unlink($toLocation);
774775
$this->silentLog('[warn] fail to download archive from ' . $fromUrl . '. Error: ' . $httpCode . ' ' . curl_error($ch));

tests/features/bootstrap/FeatureContext.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,84 @@ public function theCliUpdaterIsRun() {
212212
$this->CLIReturnCode = $returnCode;
213213
}
214214

215+
/**
216+
* @Given the archive for version :version is available locally
217+
*/
218+
public function theArchiveForVersionIsAvailableLocally(string $version): void {
219+
if ($this->skipIt) {
220+
return;
221+
}
222+
223+
$filename = 'nextcloud-' . $version . '.zip';
224+
if (!file_exists($this->tmpDownloadDir . $filename)) {
225+
$fp = fopen($this->tmpDownloadDir . $filename, 'w+');
226+
$url = $this->downloadURL . $filename;
227+
$ch = curl_init($url);
228+
curl_setopt($ch, CURLOPT_FILE, $fp);
229+
curl_setopt($ch, CURLOPT_USERAGENT, 'Nextcloud Updater');
230+
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
231+
if (curl_exec($ch) === false) {
232+
throw new \Exception('Curl error: ' . curl_error($ch));
233+
}
234+
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
235+
if ($httpCode !== 200) {
236+
throw new \Exception('Download failed for ' . $url . ' - HTTP code: ' . $httpCode);
237+
}
238+
curl_close($ch);
239+
fclose($fp);
240+
}
241+
}
242+
243+
/**
244+
* @When the CLI updater is run with local file URL for version :version and --no-verify successfully
245+
*/
246+
public function theCliUpdaterIsRunWithLocalFileUrlAndNoVerifySuccessfully(string $version): void {
247+
if ($this->skipIt) {
248+
return;
249+
}
250+
251+
$this->runUpdaterWithLocalFileUrl($version, noVerify: true);
252+
253+
if ($this->CLIReturnCode !== 0) {
254+
throw new Exception('updater failed' . PHP_EOL . implode(PHP_EOL, $this->CLIOutput));
255+
}
256+
}
257+
258+
/**
259+
* @When the CLI updater is run with local file URL for version :version
260+
*/
261+
public function theCliUpdaterIsRunWithLocalFileUrl(string $version): void {
262+
if ($this->skipIt) {
263+
return;
264+
}
265+
266+
$this->runUpdaterWithLocalFileUrl($version, noVerify: false);
267+
}
268+
269+
private function runUpdaterWithLocalFileUrl(string $version, bool $noVerify): void {
270+
$filename = 'nextcloud-' . $version . '.zip';
271+
$fileUrl = 'file://' . $this->tmpDownloadDir . $filename;
272+
273+
if (!file_exists($this->buildDir . 'updater.phar')) {
274+
throw new Exception('updater.phar not available - please build it in advance via "box build -c box.json"');
275+
}
276+
277+
copy($this->buildDir . 'updater.phar', $this->serverDir . 'nextcloud/updater/updater');
278+
chdir($this->serverDir . 'nextcloud/updater');
279+
chmod($this->serverDir . 'nextcloud/updater/updater', 0755);
280+
281+
$args = '-n --url ' . escapeshellarg($fileUrl);
282+
if ($noVerify) {
283+
$args .= ' --no-verify';
284+
}
285+
exec('./updater ' . $args . ' 2>&1', $output, $returnCode);
286+
287+
// sleep to let the opcache do it's work and invalidate the status.php
288+
sleep(5);
289+
$this->CLIOutput = $output;
290+
$this->CLIReturnCode = $returnCode;
291+
}
292+
215293
/**
216294
* @param $version
217295
*/

tests/features/cli.feature

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,21 @@ Feature: CLI updater
114114
And the installed version should be 26.0.0
115115
And maintenance mode should be off
116116
And upgrade is not required
117+
118+
Scenario: Update via local file URL with --no-verify - 26.0.0 to 26.0.13
119+
Given the current installed version is 26.0.0
120+
And the archive for version 26.0.13 is available locally
121+
When the CLI updater is run with local file URL for version 26.0.13 and --no-verify successfully
122+
Then the installed version should be 26.0.1
123+
And maintenance mode should be off
124+
And upgrade is not required
125+
126+
Scenario: Update via local file URL without --no-verify fails - 26.0.0 to 26.0.13
127+
Given the current installed version is 26.0.0
128+
And the archive for version 26.0.13 is available locally
129+
When the CLI updater is run with local file URL for version 26.0.13
130+
Then the return code should not be 0
131+
And the output should contain "You need to provide a signature with --signature or skip integrity check with --no-verify."
132+
And the installed version should be 26.0.0
133+
And maintenance mode should be off
134+
And upgrade is not required

0 commit comments

Comments
 (0)