diff --git a/plugins/dynamix.docker.manager/include/CreateDocker.php b/plugins/dynamix.docker.manager/include/CreateDocker.php index edc6b7e13..1c4aa41eb 100644 --- a/plugins/dynamix.docker.manager/include/CreateDocker.php +++ b/plugins/dynamix.docker.manager/include/CreateDocker.php @@ -178,8 +178,10 @@ function postToXML($post, $setOwnership = false) { $xml->Overview = xml_encode($post['contOverview']); $xml->Category = xml_encode($post['contCategory']); $xml->WebUI = xml_encode($post['contWebUI']); + $xml->TemplateURL = xml_encode($post['contTemplateURL']); $xml->Icon = xml_encode($post['contIcon']); $xml->ExtraParams = xml_encode($post['contExtraParams']); + $xml->DateInstalled = xml_encode(strtotime("now")); # V1 compatibility $xml->Description = xml_encode($post['contOverview']); @@ -240,6 +242,7 @@ function xmlToVar($xml) { $out['Overview'] = stripslashes(xml_decode($xml->Overview)); $out['Category'] = xml_decode($xml->Category); $out['WebUI'] = xml_decode($xml->WebUI); + $out['TemplateURL'] = xml_decode($xml->TemplateURL); $out['Icon'] = xml_decode($xml->Icon); $out['ExtraParams'] = xml_decode($xml->ExtraParams); @@ -1203,6 +1206,17 @@ $showAdditionalInfo = ''; + + Template URL: + + + + +
+

This URL is used to keep the template updated.

+
+ + Icon URL: diff --git a/plugins/dynamix.docker.manager/include/DockerClient.php b/plugins/dynamix.docker.manager/include/DockerClient.php index 9f9f8fddc..a323f60ac 100644 --- a/plugins/dynamix.docker.manager/include/DockerClient.php +++ b/plugins/dynamix.docker.manager/include/DockerClient.php @@ -65,11 +65,13 @@ class DockerTemplates { if ($this->verbose) echo $m."\n"; } + public function download_url($url, $path = "", $bg = false) { exec("curl --max-time 60 --silent --insecure --location --fail ".($path ? " -o ".escapeshellarg($path) : "")." ".escapeshellarg($url)." ".($bg ? ">/dev/null 2>&1 &" : "2>/dev/null"), $out, $exit_code); return ($exit_code === 0) ? implode("\n", $out) : false; } + public function listDir($root, $ext = null) { $iter = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($root, @@ -331,6 +333,10 @@ class DockerTemplates { $tmp['template'] = $this->getUserTemplate($name); } + if ($reload) { + $DockerUpdate->updateUserTemplate($ct); + } + $this->debug("\n$name"); foreach ($tmp as $c => $d) $this->debug(sprintf(" %-10s: %s", $c, $d)); $new_info[$name] = $tmp; @@ -379,6 +385,16 @@ class DockerUpdate{ } + private function xml_encode($string) { + return htmlspecialchars($string, ENT_XML1, 'UTF-8'); + } + + + private function xml_decode($string) { + return strval(html_entity_decode($string, ENT_XML1, 'UTF-8')); + } + + public function download_url($url, $path = "", $bg = false) { exec("curl --max-time 30 --silent --insecure --location --fail ".($path ? " -o ".escapeshellarg($path) : "")." ".escapeshellarg($url)." ".($bg ? ">/dev/null 2>&1 &" : "2>/dev/null"), $out, $exit_code); return ($exit_code === 0) ? implode("\n", $out) : false; @@ -503,6 +519,86 @@ class DockerUpdate{ $this->debug("Update status: Image='${image}', Local='${version}', Remote='${version}'"); file_put_contents($update_file, json_encode($updateStatus, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); } + + + public function updateUserTemplate($Container) { + $changed = false; + $DockerTemplates = new DockerTemplates(); + $validElements = array( 0 => "Support", + 1 => "Overview", + 2 => "Category", + 3 => "WebUI", + 4 => "Icon"); + + $validAttributes = array( 0 => "Name", + 1 => "Default", + 2 => "Description", + 3 => "Display", + 4 => "Required", + 5 => "Mask"); + // Get user template file and abort if fail + if ( ! $file = $DockerTemplates->getUserTemplate($Container) ) return null; + // Load user template XML, verify if it's valid and abort if doesn't have TemplateURL element + $template = @simplexml_load_file($file); + if ( $template && ! isset($template->TemplateURL) ) return null; + // Load a user template DOM for import remote template new Config + $dom_local = dom_import_simplexml($template); + // Try to download the remote template and abort if it fail. + if (! $dl = $this->download_url($this->xml_decode($template->TemplateURL))) return null; + // Try to load the downloaded template and abort if fail. + if (! $remote_template = @simplexml_load_string($dl)) return null; + // Loop through remote template elements and compare them to local ones + foreach ($remote_template->children() as $name => $remote_element) { + $name = $this->xml_decode($name); + // Compare through validElements + if ($name != "Config" && in_array($name, $validElements)) { + $local_element = $template->xpath("//$name")[0]; + $rvalue = $this->xml_decode($remote_element); + $value = $this->xml_decode($local_element); + // Values changed, updating. + if ( $value != $rvalue) { + $local_element->{0} = $this->xml_encode($rvalue); + $changed = true; + } + // Compare atributes on Config if they are in the validAttributes list + } else if ($name == "Config"){ + $type = $this->xml_decode($remote_element['Type']); + $target = $this->xml_decode($remote_element['Target']); + if ($type == "Port") { + $mode = $this->xml_decode($remote_element['Mode']); + $local_element = $template->xpath("//Config[@Type='$type'][@Target='$target'][@Mode='$mode']")[0]; + } else { + $local_element = $template->xpath("//Config[@Type='$type'][@Target='$target']")[0]; + } + // If the local template already have the pertinent Config element, loop through it's attributes and update those on validAttributes + if (! empty($local_element)) { + foreach ($remote_element->attributes() as $key => $value) { + $rvalue = $this->xml_decode($value); + $value = $this->xml_decode($local_element[$key]); + // Values changed, updating. + if ($value != $rvalue && in_array($key, $validAttributes)) { + $local_element[$key] = $this->xml_encode($rvalue); + $changed = true; + } + } + // New Config element, add it to the local template + } else { + $dom_remote = dom_import_simplexml($remote_element); + $new_element = $dom_local->ownerDocument->importNode($dom_remote, TRUE); + $dom_local->appendChild($new_element); + $changed = true; + } + } + } + if ($changed) { + // Format output and save to file if there were any commited changes + $dom = new DOMDocument('1.0'); + $dom->preserveWhiteSpace = false; + $dom->formatOutput = true; + $dom->loadXML($template->asXML()); + file_put_contents($file, $dom->saveXML()); + } + } }