diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php
index 0007b0d7a..cce7b1bbc 100644
--- a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php
+++ b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php
@@ -428,7 +428,7 @@ class DockerUpdate{
// DEPRECATED: Only used for Docker Index V1 type update checks
public function getRemoteVersion($image) {
- [$strRepo, $strTag] = array_pad(explode(':', DockerUtil::ensureImageTag($image)),2,'');
+ extract(DockerUtil::parseImageTag($image));
$apiUrl = sprintf('http://index.docker.io/v1/repositories/%s/tags/%s', $strRepo, $strTag);
//$this->debug("API URL: $apiUrl");
$apiContent = $this->download_url($apiUrl);
@@ -436,7 +436,7 @@ class DockerUpdate{
}
public function getRemoteVersionV2($image) {
- [$strRepo, $strTag] = array_pad(explode(':', DockerUtil::ensureImageTag($image)),2,'');
+ extract(DockerUtil::parseImageTag($image));
/*
* Step 1: Check whether or not the image is in a private registry, get corresponding auth data and generate manifest url
*/
@@ -980,7 +980,7 @@ class DockerClient {
$c['Size'] = $this->formatBytes($ct['Size']);
$c['VirtualSize'] = $this->formatBytes($ct['VirtualSize']);
$c['Tags'] = array_map('htmlspecialchars', $ct['RepoTags'] ?? []);
- $c['Repository'] = vsprintf('%1$s/%2$s', preg_split("#[:\/]#", DockerUtil::ensureImageTag($ct['RepoTags'][0]??'')));
+ $c['Repository'] = DockerUtil::parseImageTag($ct['RepoTags'][0]??'')['strRepo'];
$c['usedBy'] = $this->usedBy($c['Id']);
$this::$imagesCache[$c['Id']] = $c;
}
@@ -993,18 +993,50 @@ class DockerClient {
##################################
class DockerUtil {
- public static function ensureImageTag($image) {
- [$strRepo, $strTag] = array_map('trim', array_pad(explode(':', $image.':'),2,''));
- if (strpos($strRepo, 'sha256:') === 0) {
+ public static function ensureImageTag($image): string
+ {
+ extract(static::parseImageTag($image));
+
+ return "$strRepo:$strTag";
+ }
+
+ public static function parseImageTag($image): array
+ {
+ if (strpos($image, 'sha256:') === 0) {
// sha256 was provided instead of actual repo name so truncate it for display:
- $strRepo = substr($strRepo, 7, 12);
- } elseif (strpos($strRepo, '/') === false) {
- // Prefix library/ if there's no author (maybe a Docker offical image?)
- $strRepo = "library/$strRepo";
+ $strRepo = substr($image, 7, 12);
+ } elseif (strpos($image, '/') === false) {
+ return static::parseImageTag('library/' . $image);
+ } else {
+ $parsedImage = static::splitImage($image);
+ if (!empty($parsedImage)) {
+ $strRepo = $parsedImage['strRepo'];
+ $strTag = $parsedImage['strTag'];
+ } else {
+ // Unprocessable input
+ $strRepo = $image;
+ }
}
+
// Add :latest tag to image if it's absent
if (empty($strTag)) $strTag = 'latest';
- return "$strRepo:$strTag";
+
+ return array_map('trim', ['strRepo' => $strRepo, 'strTag' => $strTag]);
+ }
+
+ private static function splitImage($image): ?array
+ {
+ if (false === preg_match('@^(.+/)*([^/:]+)(:[^:/]*)*$@', $image, $newSections) || count($newSections) < 3) {
+ return null;
+ } else {
+ [, $strRepo, $image, $strTag] = array_merge($newSections, ['']);
+ $strTag = str_replace(':','',$strTag??'');
+
+ return [
+ 'strRepo' => $strRepo . $image,
+ 'strTag' => $strTag,
+ ];
+ }
}
public static function loadJSON($path) {
diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php
index 400898dd6..9caf1fc20 100644
--- a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php
+++ b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php
@@ -110,7 +110,7 @@ foreach ($containers as $ct) {
if ($ct['BaseImage']) echo "".htmlspecialchars($ct['BaseImage'])."
";
echo _('By').": ";
$registry = $info['registry'];
- [$author,$version] = my_explode(':',$ct['Image']);
+ ['strRepo' => $author, 'strTag' => $version] = DockerUtil::parseImageTag($ct['Image']);
if ($registry) {
echo "".htmlspecialchars(compress($author,24))."";
} else {