mirror of
https://github.com/unraid/webgui.git
synced 2026-01-15 14:09:54 -06:00
Docker: added container vpn network support
-allow extra parameters using --net=<network> to overrule default network assignment - add vpn containers are referenced by name in network assignment - add update containers reference when vpn container is updated
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2019, Lime Technology
|
||||
* Copyright 2015-2019, Guilherme Jardim, Eric Schultz, Jon Panozzo.
|
||||
* Copyright 2012-2019, Bergware International.
|
||||
/* Copyright 2005-2020, Lime Technology
|
||||
* Copyright 2015-2020, Guilherme Jardim, Eric Schultz, Jon Panozzo.
|
||||
* Copyright 2012-2020, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -15,7 +15,6 @@
|
||||
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
|
||||
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
|
||||
require_once "$docroot/plugins/dynamix.docker.manager/include/Helpers.php";
|
||||
require_once "$docroot/webGui/include/Helpers.php";
|
||||
|
||||
libxml_use_internal_errors(false); # Enable xml errors
|
||||
|
||||
@@ -35,7 +34,7 @@ $DockerTemplates = new DockerTemplates();
|
||||
|
||||
$custom = DockerUtil::custom();
|
||||
$subnet = DockerUtil::network($custom);
|
||||
$cpus = cpu_list();
|
||||
$cpus = DockerUtil::cpus();
|
||||
|
||||
function cpu_pinning() {
|
||||
global $xml,$cpus;
|
||||
@@ -84,10 +83,10 @@ if (isset($_POST['contName'])) {
|
||||
if (!is_dir($userTmplDir)) mkdir($userTmplDir, 0777, true);
|
||||
if ($Name) {
|
||||
$filename = sprintf('%s/my-%s.xml', $userTmplDir, $Name);
|
||||
if ( is_file($filename) ) {
|
||||
if (is_file($filename)) {
|
||||
$oldXML = simplexml_load_file($filename);
|
||||
if ($oldXML->Icon != $_POST['contIcon']) {
|
||||
if (! strpos($Repository,":")) {
|
||||
if (!strpos($Repository,":")) {
|
||||
$Repository .= ":latest";
|
||||
}
|
||||
$iconPath = $DockerTemplates->getIcon($Repository);
|
||||
@@ -176,12 +175,12 @@ if ($_GET['updateContainer']){
|
||||
// determine if the container is still running
|
||||
if (!empty($oldContainerInfo) && !empty($oldContainerInfo['State']) && !empty($oldContainerInfo['State']['Running'])) {
|
||||
// since container was already running, put it back it to a running state after update
|
||||
$cmd = str_replace('/plugins/dynamix.docker.manager/scripts/docker create ', '/plugins/dynamix.docker.manager/scripts/docker run -d ', $cmd);
|
||||
$cmd = str_replace('/docker create ', '/docker run -d ', $cmd);
|
||||
// attempt graceful stop of container first
|
||||
stopContainer($Name);
|
||||
}
|
||||
// force kill container if still running after 10 seconds
|
||||
if ( ! $_GET['communityApplications'] ) {
|
||||
if (!$_GET['communityApplications']) {
|
||||
removeContainer($Name);
|
||||
}
|
||||
execCommand($cmd);
|
||||
@@ -399,7 +398,7 @@ button[type=button]{margin:0 20px 0 0}
|
||||
function getVal(el, name) {
|
||||
var el = $(el).find("*[name="+name+"]");
|
||||
if (el.length) {
|
||||
return ( $(el).attr('type') == 'checkbox' ) ? ($(el).is(':checked') ? "on" : "off") : $(el).val();
|
||||
return ($(el).attr('type') == 'checkbox') ? ($(el).is(':checked') ? "on" : "off") : $(el).val();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
@@ -407,7 +406,7 @@ button[type=button]{margin:0 20px 0 0}
|
||||
|
||||
function addConfigPopup() {
|
||||
var title = 'Add Configuration';
|
||||
var popup = $( "#dialogAddConfig" );
|
||||
var popup = $("#dialogAddConfig");
|
||||
|
||||
// Load popup the popup with the template info
|
||||
popup.html($("#templatePopupConfig").html());
|
||||
@@ -436,10 +435,10 @@ button[type=button]{margin:0 20px 0 0}
|
||||
["Name","Target","Default","Mode","Description","Type","Display","Required","Mask","Value"].forEach(function(e){
|
||||
Opts[e] = getVal(Element, e);
|
||||
});
|
||||
if (! Opts.Name ){
|
||||
if (!Opts.Name){
|
||||
Opts.Name = makeName(Opts.Type);
|
||||
}
|
||||
if (! Opts.Description ) {
|
||||
if (!Opts.Description) {
|
||||
Opts.Description = "Container "+Opts.Type+": "+Opts.Target;
|
||||
}
|
||||
if (Opts.Required == "true") {
|
||||
@@ -461,7 +460,7 @@ button[type=button]{margin:0 20px 0 0}
|
||||
}
|
||||
});
|
||||
$(".ui-dialog .ui-dialog-titlebar").addClass('menu');
|
||||
$(".ui-dialog .ui-dialog-title").css('text-align','center').css( 'width', "100%");
|
||||
$(".ui-dialog .ui-dialog-title").css('text-align','center').css('width', "100%");
|
||||
$(".ui-dialog .ui-dialog-content").css('padding-top','15px').css('vertical-align','bottom');
|
||||
$(".ui-button-text").css('padding','0px 5px');
|
||||
}
|
||||
@@ -517,10 +516,10 @@ button[type=button]{margin:0 20px 0 0}
|
||||
Opts.Buttons = "<button type='button' onclick='editConfigPopup("+num+",<?=$disableEdit?>)'>Edit</button>";
|
||||
Opts.Buttons += "<button type='button' onclick='removeConfig("+num+")'>Remove</button>";
|
||||
}
|
||||
if (! Opts.Name ){
|
||||
if (!Opts.Name){
|
||||
Opts.Name = makeName(Opts.Type);
|
||||
}
|
||||
if (! Opts.Description ) {
|
||||
if (!Opts.Description) {
|
||||
Opts.Description = "Container "+Opts.Type+": "+Opts.Target;
|
||||
}
|
||||
Opts.Number = num;
|
||||
@@ -545,7 +544,7 @@ button[type=button]{margin:0 20px 0 0}
|
||||
}
|
||||
});
|
||||
$(".ui-dialog .ui-dialog-titlebar").addClass('menu');
|
||||
$(".ui-dialog .ui-dialog-title").css('text-align','center').css( 'width', "100%");
|
||||
$(".ui-dialog .ui-dialog-title").css('text-align','center').css('width', "100%");
|
||||
$(".ui-dialog .ui-dialog-content").css('padding-top','15px').css('vertical-align','bottom');
|
||||
$(".ui-button-text").css('padding','0px 5px');
|
||||
$('.desc_readmore').readmore({maxHeight:10});
|
||||
@@ -668,8 +667,7 @@ button[type=button]{margin:0 20px 0 0}
|
||||
allowBrowsing: true
|
||||
},
|
||||
function(file){if(on_files){p.val(file);p.trigger('change');if(close_on_select){ft.slideUp('fast',function(){ft.remove();});}}},
|
||||
function(folder){if(on_folders){p.val(folder);p.trigger('change');if(close_on_select){$(ft).slideUp('fast',function (){$(ft).remove();});}}}
|
||||
);
|
||||
function(folder){if(on_folders){p.val(folder);p.trigger('change');if(close_on_select){$(ft).slideUp('fast',function (){$(ft).remove();});}}});
|
||||
// Format fileTree according to parent position, height and width
|
||||
ft.css({'left':p.position().left,'top':(p.position().top+p.outerHeight()),'width':(p.width())});
|
||||
// close if click elsewhere
|
||||
@@ -1181,7 +1179,7 @@ button[type=button]{margin:0 20px 0 0}
|
||||
}
|
||||
function toggleReadmore() {
|
||||
var readm = $('#readmore_toggle');
|
||||
if ( readm.hasClass('readmore_collapsed') ) {
|
||||
if (readm.hasClass('readmore_collapsed')) {
|
||||
readm.removeClass('readmore_collapsed').addClass('readmore_expanded');
|
||||
$('#configLocationAdvanced').slideDown('fast');
|
||||
readm.find('a').html('<i class="fa fa-chevron-up"></i> Hide more settings ...');
|
||||
@@ -1193,7 +1191,7 @@ button[type=button]{margin:0 20px 0 0}
|
||||
}
|
||||
function toggleAllocations() {
|
||||
var readm = $('#allocations_toggle');
|
||||
if ( readm.hasClass('readmore_collapsed') ) {
|
||||
if (readm.hasClass('readmore_collapsed')) {
|
||||
readm.removeClass('readmore_collapsed').addClass('readmore_expanded');
|
||||
$('#dockerAllocations').slideDown('fast');
|
||||
readm.find('a').html('<i class="fa fa-chevron-up"></i> Hide docker allocations ...');
|
||||
@@ -1272,7 +1270,7 @@ button[type=button]{margin:0 20px 0 0}
|
||||
echo "$('.advanced-switch').siblings('.switch-button-background').click();";
|
||||
}?>
|
||||
});
|
||||
if ( window.location.href.indexOf("/Apps/") > 0 ) {
|
||||
if (window.location.href.indexOf("/Apps/") > 0) {
|
||||
$(".TemplateDropDown").hide();
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2019, Lime Technology
|
||||
* Copyright 2014-2019, Guilherme Jardim, Eric Schultz, Jon Panozzo.
|
||||
* Copyright 2012-2019, Bergware International.
|
||||
/* Copyright 2005-2020, Lime Technology
|
||||
* Copyright 2014-2020, Guilherme Jardim, Eric Schultz, Jon Panozzo.
|
||||
* Copyright 2012-2020, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -312,7 +312,7 @@ class DockerTemplates {
|
||||
if (!is_file($icon)) $this->download_url($imgUrl, $icon);
|
||||
@copy($icon, $iconRAM);
|
||||
}
|
||||
if ( !is_file($icon) && is_file($iconRAM) ) {
|
||||
if (!is_file($icon) && is_file($iconRAM)) {
|
||||
@copy($iconRAM,$icon);
|
||||
}
|
||||
return (is_file($iconRAM)) ? str_replace($docroot, '', $iconRAM) : '';
|
||||
@@ -368,21 +368,21 @@ class DockerUpdate{
|
||||
* Step 1: Check whether or not the image is in a private registry, get corresponding auth data and generate manifest url
|
||||
*/
|
||||
$DockerClient = new DockerClient();
|
||||
$registryAuth = $DockerClient->getRegistryAuth( $image );
|
||||
if ( $registryAuth ) {
|
||||
$manifestURL = sprintf( '%s%s/manifests/%s', $registryAuth['apiUrl'], $registryAuth['imageName'], $registryAuth['imageTag'] );
|
||||
$registryAuth = $DockerClient->getRegistryAuth($image);
|
||||
if ($registryAuth) {
|
||||
$manifestURL = sprintf('%s%s/manifests/%s', $registryAuth['apiUrl'], $registryAuth['imageName'], $registryAuth['imageTag']);
|
||||
} else {
|
||||
$manifestURL = sprintf( 'https://registry-1.docker.io/v2/%s/manifests/%s', $strRepo, $strTag );
|
||||
$manifestURL = sprintf('https://registry-1.docker.io/v2/%s/manifests/%s', $strRepo, $strTag);
|
||||
}
|
||||
//$this->debug('Manifest URL: ' . $manifestURL);
|
||||
//$this->debug('Manifest URL: '.$manifestURL);
|
||||
|
||||
/*
|
||||
* Step 2: Get www-authenticate header from manifest url to generate token url
|
||||
*/
|
||||
$ch = getCurlHandle($manifestURL, 'HEAD');
|
||||
$response = curl_exec( $ch );
|
||||
$response = curl_exec($ch);
|
||||
if (curl_errno($ch) !== 0) {
|
||||
//$this->debug('Error: curl error getting manifest: ' . curl_error($ch));
|
||||
//$this->debug('Error: curl error getting manifest: '.curl_error($ch));
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -402,19 +402,19 @@ class DockerUpdate{
|
||||
if (empty($args['realm']) || empty($args['service']) || empty($args['scope'])) {
|
||||
return null;
|
||||
}
|
||||
$url = $args['realm'] . '?service=' . urlencode($args['service']) . '&scope=' . urlencode($args['scope']);
|
||||
//$this->debug('Token URL: ' . $url);
|
||||
$url = $args['realm'].'?service='.urlencode($args['service']).'&scope='.urlencode($args['scope']);
|
||||
//$this->debug('Token URL: '.$url);
|
||||
|
||||
/**
|
||||
* Step 3: Get token from API and authenticate via username / password if in private registry and auth data was found
|
||||
*/
|
||||
$ch = getCurlHandle($url);
|
||||
if ($registryAuth) {
|
||||
curl_setopt( $ch, CURLOPT_USERPWD, $registryAuth['username'] . ':' . $registryAuth['password'] );
|
||||
curl_setopt($ch, CURLOPT_USERPWD, $registryAuth['username'].':'.$registryAuth['password']);
|
||||
}
|
||||
$response = curl_exec( $ch );
|
||||
$response = curl_exec($ch);
|
||||
if (curl_errno($ch) !== 0) {
|
||||
//$this->debug('Error: curl error getting token: ' . curl_error($ch));
|
||||
//$this->debug('Error: curl error getting token: '.curl_error($ch));
|
||||
return null;
|
||||
}
|
||||
$response = json_decode($response, true);
|
||||
@@ -428,14 +428,14 @@ class DockerUpdate{
|
||||
* Step 4: Get Docker-Content-Digest header from manifest file
|
||||
*/
|
||||
$ch = getCurlHandle($manifestURL, 'HEAD');
|
||||
curl_setopt( $ch, CURLOPT_HTTPHEADER, [
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Accept: application/vnd.docker.distribution.manifest.list.v2+json,application/vnd.docker.distribution.manifest.v2+json',
|
||||
'Authorization: Bearer ' . $token
|
||||
'Authorization: Bearer '.$token
|
||||
]);
|
||||
|
||||
$response = curl_exec( $ch );
|
||||
$response = curl_exec($ch);
|
||||
if (curl_errno($ch) !== 0) {
|
||||
//$this->debug('Error: curl error getting manifest: ' . curl_error($ch));
|
||||
//$this->debug('Error: curl error getting manifest: '.curl_error($ch));
|
||||
return null;
|
||||
}
|
||||
preg_match('@Docker-Content-Digest:\s*(.*)@', $response, $matches);
|
||||
@@ -444,7 +444,7 @@ class DockerUpdate{
|
||||
return null;
|
||||
}
|
||||
$digest = trim($matches[1]);
|
||||
//$this->debug('Remote Digest: ' . $digest);
|
||||
//$this->debug('Remote Digest: '.$digest);
|
||||
return $digest;
|
||||
}
|
||||
|
||||
@@ -486,19 +486,19 @@ class DockerUpdate{
|
||||
DockerUtil::saveJSON($dockerManPaths['update-status'], $updateStatus);
|
||||
}
|
||||
|
||||
public function inspectLocalVersion( $image ) {
|
||||
public function inspectLocalVersion($image) {
|
||||
$DockerClient = new DockerClient();
|
||||
$inspect = $DockerClient->getDockerJSON( '/images/' . $image . '/json' );
|
||||
if ( empty( $inspect['RepoDigests'] ) ) {
|
||||
$inspect = $DockerClient->getDockerJSON('/images/'.$image.'/json');
|
||||
if (empty($inspect['RepoDigests'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$shaPos = strpos( $inspect['RepoDigests'][0], '@sha256:' );
|
||||
if ( $shaPos === false ) {
|
||||
$shaPos = strpos($inspect['RepoDigests'][0], '@sha256:');
|
||||
if ($shaPos === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return substr( $inspect['RepoDigests'][0], $shaPos + 1 );
|
||||
return substr($inspect['RepoDigests'][0], $shaPos + 1);
|
||||
}
|
||||
|
||||
public function setUpdateStatus($image, $version) {
|
||||
@@ -563,7 +563,7 @@ class DockerUpdate{
|
||||
$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)) {
|
||||
if (!empty($local_element)) {
|
||||
foreach ($remote_element->attributes() as $key => $value) {
|
||||
$rvalue = $this->xml_decode($value);
|
||||
$value = $this->xml_decode($local_element[$key]);
|
||||
@@ -763,13 +763,13 @@ class DockerClient {
|
||||
|
||||
public function pullImage($image, $callback=null) {
|
||||
$header = null;
|
||||
$registryAuth = $this->getRegistryAuth( $image );
|
||||
if ( $registryAuth ) {
|
||||
$header = 'X-Registry-Auth: ' . base64_encode( json_encode( [
|
||||
$registryAuth = $this->getRegistryAuth($image);
|
||||
if ($registryAuth) {
|
||||
$header = 'X-Registry-Auth: '.base64_encode(json_encode([
|
||||
'username' => $registryAuth['username'],
|
||||
'password' => $registryAuth['password'],
|
||||
'serveraddress' => $registryAuth['apiUrl'],
|
||||
] ) ) . "\r\n";
|
||||
]))."\r\n";
|
||||
}
|
||||
|
||||
$ret = $this->getDockerJSON("/images/create?fromImage=".urlencode($image), 'POST', $code, $callback, false, $header);
|
||||
@@ -789,7 +789,7 @@ class DockerClient {
|
||||
return false;
|
||||
}
|
||||
$dockerConfig = json_decode(file_get_contents($dockerConfig), true);
|
||||
if ( empty( $dockerConfig['auths'] ) || empty( $dockerConfig['auths'][ $matches[1] ] ) ) {
|
||||
if (empty($dockerConfig['auths']) || empty($dockerConfig['auths'][ $matches[1] ])) {
|
||||
return false;
|
||||
}
|
||||
list($user, $password) = explode(':', base64_decode($dockerConfig['auths'][ $matches[1] ]['auth']));
|
||||
@@ -800,7 +800,7 @@ class DockerClient {
|
||||
'registryName' => $matches[1],
|
||||
'imageName' => $matches[2],
|
||||
'imageTag' => $matches[3],
|
||||
'apiUrl' => 'https://' . $matches[1] . '/v2/',
|
||||
'apiUrl' => 'https://'.$matches[1].'/v2/',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -841,9 +841,11 @@ class DockerClient {
|
||||
$c['Volumes'] = $info['HostConfig']['Binds'];
|
||||
$c['Created'] = $this->humanTiming($ct['Created']);
|
||||
$c['NetworkMode'] = $ct['HostConfig']['NetworkMode'];
|
||||
[$net, $id] = explode(':',$c['NetworkMode']);
|
||||
$c['CPUset'] = $info['HostConfig']['CpusetCpus'];
|
||||
$c['BaseImage'] = $ct['Labels']['BASEIMAGE'] ?? false;
|
||||
$c['Ports'] = [];
|
||||
if ($id) $c['NetworkMode'] = $net.str_replace('/',':',DockerUtil::docker("inspect --format='{{.Name}}' $id")?:'/???');
|
||||
if ($driver[$c['NetworkMode']]=='bridge') {
|
||||
$ports = &$info['HostConfig']['PortBindings'];
|
||||
$nat = true;
|
||||
@@ -949,7 +951,7 @@ class DockerUtil {
|
||||
|
||||
public static function driver() {
|
||||
$list = [];
|
||||
foreach (static::docker("network ls --format='{{.Name}}={{.Driver}}'",true) as $network) {list($name,$driver) = explode('=',$network); $list[$name] = $driver;}
|
||||
foreach (static::docker("network ls --format='{{.Name}}={{.Driver}}'",true) as $network) {list($net,$driver) = explode('=',$network); $list[$net] = $driver;}
|
||||
return $list;
|
||||
}
|
||||
|
||||
@@ -957,10 +959,15 @@ class DockerUtil {
|
||||
return static::docker("network ls --filter driver='bridge' --filter driver='macvlan' --format='{{.Name}}'|grep -v '^bridge$'",true);
|
||||
}
|
||||
|
||||
public static function network($more) {
|
||||
public static function network($custom) {
|
||||
$list = ['bridge'=>'', 'host'=>'', 'none'=>''];
|
||||
foreach ($more as $net) $list[$net] = substr(static::docker("network inspect --format='{{range .IPAM.Config}}{{.Subnet}}, {{end}}' $net"),0,-1);
|
||||
foreach ($custom as $net) $list[$net] = implode(', ',array_filter(static::docker("network inspect --format='{{range .IPAM.Config}}{{println .Subnet}}{{end}}' $net",true)));
|
||||
return $list;
|
||||
}
|
||||
|
||||
public static function cpus() {
|
||||
exec('cat /sys/devices/system/cpu/*/topology/thread_siblings_list|sort -nu', $cpus);
|
||||
return $cpus;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2018, Lime Technology
|
||||
* Copyright 2014-2018, Guilherme Jardim, Eric Schultz, Jon Panozzo.
|
||||
* Copyright 2012-2018, Bergware International.
|
||||
/* Copyright 2005-2020, Lime Technology
|
||||
* Copyright 2014-2020, Guilherme Jardim, Eric Schultz, Jon Panozzo.
|
||||
* Copyright 2012-2020, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -51,7 +51,7 @@ foreach ($containers as $ct) {
|
||||
$running = $info['running'] ? 1 : 0;
|
||||
$paused = $info['paused'] ? 1 : 0;
|
||||
$is_autostart = $info['autostart'] ? 'true':'false';
|
||||
$updateStatus = $info['updated']=='true'||$info['updated']=='undef' ? 'true':'false';
|
||||
$updateStatus = ($info['updated']=='true'||$info['updated']=='undef') && strpos($ct['NetworkMode'],':???')===false ? 'true':'false';
|
||||
$template = $info['template'];
|
||||
$shell = $info['shell'];
|
||||
$webGui = html_entity_decode($info['url']);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2018, Lime Technology
|
||||
* Copyright 2014-2018, Guilherme Jardim, Eric Schultz, Jon Panozzo.
|
||||
* Copyright 2012-2018, Bergware International.
|
||||
/* Copyright 2005-2020, Lime Technology
|
||||
* Copyright 2014-2020, Guilherme Jardim, Eric Schultz, Jon Panozzo.
|
||||
* Copyright 2012-2020, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -238,14 +238,14 @@ function xmlToVar($xml) {
|
||||
|
||||
function xmlSecurity(&$template) {
|
||||
foreach ($template as &$element) {
|
||||
if ( is_array($element) ) {
|
||||
if (is_array($element)) {
|
||||
xmlSecurity($element);
|
||||
} else {
|
||||
if ( is_string($element) ) {
|
||||
if (is_string($element)) {
|
||||
$tempElement = htmlspecialchars_decode($element);
|
||||
$tempElement = str_replace("[","<",$tempElement);
|
||||
$tempElement = str_replace("]",">",$tempElement);
|
||||
if ( preg_match('#<script(.*?)>(.*?)</script>#is',$tempElement) || preg_match('#<iframe(.*?)>(.*?)</iframe>#is',$tempElement) ) {
|
||||
if (preg_match('#<script(.*?)>(.*?)</script>#is',$tempElement) || preg_match('#<iframe(.*?)>(.*?)</iframe>#is',$tempElement)) {
|
||||
$element = "REMOVED";
|
||||
}
|
||||
}
|
||||
@@ -258,7 +258,7 @@ function xmlToCommand($xml, $create_paths=false) {
|
||||
$xml = xmlToVar($xml);
|
||||
$cmdName = strlen($xml['Name']) ? '--name='.escapeshellarg($xml['Name']) : '';
|
||||
$cmdPrivileged = strtolower($xml['Privileged'])=='true' ? '--privileged=true' : '';
|
||||
$cmdNetwork = '--net='.escapeshellarg(strtolower($xml['Network']));
|
||||
$cmdNetwork = preg_match('/\-\-net(work)?=/',$xml['ExtraParams']) ? "" : '--net='.escapeshellarg(strtolower($xml['Network']));
|
||||
$cmdMyIP = '';
|
||||
foreach (explode(' ',str_replace(',',' ',$xml['MyIP'])) as $myIP) if ($myIP) $cmdMyIP .= (strpos($myIP,':')?'--ip6=':'--ip=').escapeshellarg($myIP).' ';
|
||||
$cmdCPUset = strlen($xml['CPUset']) ? '--cpuset-cpus='.escapeshellarg($xml['CPUset']) : '';
|
||||
@@ -268,7 +268,7 @@ function xmlToCommand($xml, $create_paths=false) {
|
||||
$Labels = [''];
|
||||
$Devices = [''];
|
||||
// Bind Time
|
||||
$Variables[] = 'TZ="' . $var['timeZone'] . '"';
|
||||
$Variables[] = 'TZ="'.$var['timeZone'].'"';
|
||||
// Add HOST_OS variable
|
||||
$Variables[] = 'HOST_OS="Unraid"';
|
||||
|
||||
@@ -280,7 +280,7 @@ function xmlToCommand($xml, $create_paths=false) {
|
||||
if ($confType != "device" && !strlen($containerConfig)) continue;
|
||||
if ($confType == "path") {
|
||||
$Volumes[] = escapeshellarg($hostConfig).':'.escapeshellarg($containerConfig).':'.escapeshellarg($Mode);
|
||||
if ( ! file_exists($hostConfig) && $create_paths ) {
|
||||
if (!file_exists($hostConfig) && $create_paths) {
|
||||
@mkdir($hostConfig, 0777, true);
|
||||
@chown($hostConfig, 99);
|
||||
@chgrp($hostConfig, 100);
|
||||
@@ -439,7 +439,7 @@ function pullImage($name, $image, $echo=true) {
|
||||
if ($echo) @flush();
|
||||
});
|
||||
if ($echo) {
|
||||
echo "<script>addLog('<br><b>TOTAL DATA PULLED:</b> " . $DockerClient->formatBytes(array_sum($alltotals)) . "');</script>\n";
|
||||
echo "<script>addLog('<br><b>TOTAL DATA PULLED:</b> ".$DockerClient->formatBytes(array_sum($alltotals))."');</script>\n";
|
||||
@flush();
|
||||
}
|
||||
if (!empty($strError)) {
|
||||
@@ -469,7 +469,7 @@ function execCommand($command, $echo=true) {
|
||||
@flush();
|
||||
}
|
||||
$proc = proc_open($command." 2>&1", $descriptorspec, $pipes, '/', []);
|
||||
while ($out = fgets( $pipes[1] )) {
|
||||
while ($out = fgets($pipes[1])) {
|
||||
$out = preg_replace("%[\t\n\x0B\f\r]+%", '', $out);
|
||||
if ($echo) {
|
||||
echo '<script>addLog("'.htmlspecialchars($out).'");</script>';
|
||||
@@ -524,16 +524,15 @@ function getAllocations() {
|
||||
return $ports;
|
||||
}
|
||||
|
||||
function getCurlHandle($url, $method = 'GET') {
|
||||
$ch = curl_init();
|
||||
curl_setopt( $ch, CURLOPT_URL, $url );
|
||||
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
|
||||
if ($method === 'HEAD') {
|
||||
curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, 'HEAD' );
|
||||
curl_setopt( $ch, CURLOPT_HEADER, 1 );
|
||||
curl_setopt( $ch, CURLOPT_NOBODY, true );
|
||||
}
|
||||
|
||||
return $ch;
|
||||
function getCurlHandle($url, $method='GET') {
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
if ($method === 'HEAD') {
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD');
|
||||
curl_setopt($ch, CURLOPT_HEADER, 1);
|
||||
curl_setopt($ch, CURLOPT_NOBODY, true);
|
||||
}
|
||||
return $ch;
|
||||
}
|
||||
?>
|
||||
|
||||
Reference in New Issue
Block a user