Skip to content

Commit b038af0

Browse files
committed
#6828 Extension installer update.
1 parent 984cf86 commit b038af0

File tree

2 files changed

+121
-18
lines changed

2 files changed

+121
-18
lines changed

server/cli/modules/extension.inc.php

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ public function install($arg) {
9797
// Get extension name
9898
$extension_name = $arg[0];
9999

100+
// Load extension installer
101+
$app->log('Installing extension '.$extension_name, LOGLEVEL_DEBUG);
102+
$app->uses('extension_installer');
103+
$app->load('extension_installer_base');
104+
100105
if(isset($arg[1])) {
101106
$version = $arg[1];
102107
} else {
@@ -108,6 +113,41 @@ public function install($arg) {
108113
die();
109114
}
110115

116+
// check if extension exists in repository
117+
$response = file_get_contents($app->extension_installer->getRepoListUrl());
118+
$repo_extensions = json_decode($response, true);
119+
120+
if(empty($repo_extensions)) {
121+
$this->swriteln();
122+
$this->swriteln('Error: No extensions available in repository.');
123+
$this->swriteln();
124+
die();
125+
}
126+
127+
// Check if the extension exists in the repository
128+
$extension_found = false;
129+
foreach($repo_extensions as $extension) {
130+
if($extension['name'] == $extension_name) {
131+
if($version) {
132+
if($extension['version'] != $version) {
133+
$this->swriteln();
134+
$this->swriteln('Error: Extension version not found in repository.');
135+
$this->swriteln();
136+
die();
137+
}
138+
}
139+
$extension_found = true;
140+
break;
141+
}
142+
}
143+
144+
if(!$extension_found) {
145+
$this->swriteln();
146+
$this->swriteln('Error: Extension not found in repository.');
147+
$this->swriteln();
148+
die();
149+
}
150+
111151
// check version
112152
if(!empty($version) && !preg_match('/^[0-9\.]{1,10}$/',$version)) {
113153
$this->swriteln();
@@ -116,11 +156,6 @@ public function install($arg) {
116156
die();
117157
}
118158

119-
// Load extension installer
120-
$app->log('Installing extension '.$extension_name, LOGLEVEL_DEBUG);
121-
$app->uses('extension_installer');
122-
$app->load('extension_installer_base');
123-
124159
// download extension if not already downloaded
125160
if(!is_dir($app->extension_installer->getExtensionBasedir().'/'.$extension_name)) {
126161
if(!$app->extension_installer->download_extension($extension_name,$version)) {
@@ -493,6 +528,16 @@ public function list($arg) {
493528
$this->swriteln("Time: " . date('Y-m-d H:i:s'));
494529
$this->swriteln();
495530

531+
// Get available extensions form repo API server in json format
532+
$url = 'https://repo.ispconfig.com/api/v1/list/';
533+
$response = file_get_contents($url);
534+
$available_extensions = json_decode($response, true);
535+
536+
if(empty($available_extensions)) {
537+
$this->swriteln('No extensions available.');
538+
return;
539+
}
540+
496541
// Define ANSI color codes
497542
$ansi_reset = "\033[0m";
498543
$bold = "\033[1m";
@@ -518,7 +563,14 @@ public function list($arg) {
518563
}
519564

520565
$status = $extension['active'] ? $green . 'Active' . $ansi_reset : $red . 'Inactive' . $ansi_reset;
521-
$description = isset($extension['description']) ? $extension['description'] : 'No description available';
566+
567+
// get description from available extensions
568+
foreach($available_extensions as $available_extension) {
569+
if($available_extension['name'] == $name) {
570+
$title = $available_extension['title'];
571+
break;
572+
}
573+
}
522574

523575
// Output each row with fixed column positions
524576
$this->swrite($bold . $name . $ansi_reset);
@@ -534,7 +586,7 @@ public function list($arg) {
534586
$status_text = $extension['active'] ? 'Active' : 'Inactive';
535587
$this->swrite(str_repeat(' ', max(0, 12 - strlen($status_text))));
536588

537-
$this->swriteln($description);
589+
$this->swriteln($title);
538590
}
539591

540592
// Display a footer with helpful information
@@ -549,8 +601,11 @@ public function list_available($arg) {
549601

550602
$app->log('Listing available extensions', LOGLEVEL_DEBUG);
551603

604+
$app->uses('extension_installer');
605+
$app->load('extension_installer_base');
606+
552607
// Get available extensions form repo API server in json format
553-
$url = 'https://repo.ispconfig.com/api/v1/list/';
608+
$url = $app->extension_installer->getRepoListUrl();
554609
$response = file_get_contents($url);
555610
$extensions = json_decode($response, true);
556611

@@ -596,7 +651,7 @@ public function list_available($arg) {
596651
$license = substr($license, 0, 7) . '...';
597652
}
598653

599-
$description = isset($extension['description']) ? $extension['description'] : 'No description available';
654+
$title = isset($extension['title']) ? $extension['title'] : 'No title available';
600655

601656
// Output each row with fixed column positions
602657
$this->swrite($bold . $name . $ansi_reset);
@@ -611,7 +666,7 @@ public function list_available($arg) {
611666
// Add padding after license
612667
$this->swrite(str_repeat(' ', max(0, 12 - strlen($license))));
613668

614-
$this->swriteln($description);
669+
$this->swriteln($title);
615670
}
616671

617672
// Display a footer with helpful information

server/lib/classes/extension_installer.inc.php

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ class extension_installer {
55
private $extension_basedir = '/usr/local/ispconfig/extensions';
66
private $ispconfig_dir = '/usr/local/ispconfig';
77
private $download_url = 'https://repo.ispconfig.com/packages/';
8+
private $repo_list_url = 'https://repo.ispconfig.com/api/v1/list/';
89

910
public $errors = [];
1011

@@ -18,6 +19,9 @@ public function getIspconfigDir() {
1819
public function getDownloadUrl() {
1920
return $this->download_url;
2021
}
22+
public function getRepoListUrl() {
23+
return $this->repo_list_url;
24+
}
2125

2226
// get errors
2327
public function getErrors() {
@@ -69,6 +73,8 @@ public function enable_extension($name) {
6973
foreach($files as $file) {
7074
// Skip comment lines
7175
if(substr(trim($file),0,1) == '#') continue;
76+
// skip empty lines
77+
if(empty(trim($file))) continue;
7278

7379
// parse line
7480
list($action,$source,$target) = explode(':',trim($file));
@@ -206,6 +212,8 @@ public function disable_extension($name) {
206212
foreach($files as $file) {
207213
// Skip comment lines
208214
if(substr(trim($file),0,1) == '#') continue;
215+
// skip empty lines
216+
if(empty(trim($file))) continue;
209217

210218
// parse line
211219
list($action,$source,$target) = explode(':',$file);
@@ -219,8 +227,8 @@ public function disable_extension($name) {
219227

220228
// Check target
221229
if(empty($target) || empty($action) || $target == '/' || $target == '.' || $target == '..') {
222-
$app->log('Invalid file list: '.$file_list_path, LOGLEVEL_WARN);
223-
$this->errors[] = 'Invalid file list: '.$file_list_path;
230+
$app->log('Invalid target: '.$target, LOGLEVEL_WARN);
231+
$this->errors[] = 'Invalid target: '.$target;
224232
return false;
225233
}
226234

@@ -229,15 +237,15 @@ public function disable_extension($name) {
229237

230238
// check if empty after realpath
231239
if(empty($target)) {
232-
$app->log('Invalid file list: '.$file_list_path, LOGLEVEL_WARN);
233-
$this->errors[] = 'Invalid file list: '.$file_list_path;
240+
$app->log('Invalid target after realpath: '.$target, LOGLEVEL_WARN);
241+
$this->errors[] = 'Invalid target after realpath: '.$target;
234242
return false;
235243
}
236244

237245
// check if target is within /usr/local/ispconfig and exists
238-
if((!is_file($target) && !is_dir($target)) || !str_starts_with($target, $this->ispconfig_dir)) {
239-
$app->log('Invalid file list: '.$file_list_path, LOGLEVEL_WARN);
240-
$this->errors[] = 'Invalid file list: '.$file_list_path;
246+
if(!str_starts_with($target, $this->ispconfig_dir)) {
247+
$app->log('Target not within /usr/local/ispconfig: '.$target, LOGLEVEL_WARN);
248+
$this->errors[] = 'Target not within /usr/local/ispconfig: '.$target;
241249
return false;
242250
}
243251

@@ -286,6 +294,38 @@ public function download_extension($name, $version = null, $force = false) {
286294
return false;
287295
}
288296

297+
// check if extension exists in repository
298+
$response = file_get_contents($this->getRepoListUrl());
299+
$repo_extensions = json_decode($response, true);
300+
301+
if(empty($repo_extensions)) {
302+
$app->log('No extensions available in repository', LOGLEVEL_WARN);
303+
$this->errors[] = 'No extensions available in repository';
304+
return false;
305+
}
306+
307+
// Check if the extension exists in the repository
308+
$extension_found = false;
309+
foreach($repo_extensions as $extension) {
310+
if($extension['name'] == $name) {
311+
if($version) {
312+
if($extension['version'] != $version) {
313+
$app->log('Extension version not found in repository', LOGLEVEL_WARN);
314+
$this->errors[] = 'Extension version not found in repository';
315+
return false;
316+
}
317+
}
318+
$extension_found = true;
319+
break;
320+
}
321+
}
322+
323+
if(!$extension_found) {
324+
$app->log('Extension not found in repository', LOGLEVEL_WARN);
325+
$this->errors[] = 'Extension not found in repository';
326+
return false;
327+
}
328+
289329
$ext_dir = $this->extension_basedir.'/'.$name;
290330

291331
// Check if the extension has already been downloaded
@@ -514,11 +554,19 @@ public function scan_extensions() {
514554
} else {
515555
$version = 'Unknown';
516556
}
557+
558+
// check license
559+
if(file_exists($extension_directory.'/license')) {
560+
$license = file_get_contents($extension_directory.'/license');
561+
} else {
562+
$license = '';
563+
}
517564

518565
$extensions[] = [
519566
'name' => basename($extension_directory),
520567
'active' => $active,
521-
'version' => $version
568+
'version' => $version,
569+
'license' => $license
522570
];
523571
}
524572
}

0 commit comments

Comments
 (0)