Merge branch 'master' into master

This commit is contained in:
dlandon
2024-04-12 08:04:31 -05:00
committed by GitHub
76 changed files with 877 additions and 1279 deletions
@@ -545,6 +545,9 @@ window.onunload = function(){
<? elseif (_var($var,'configValid')=="invalid"):?>
<tr><td><?status_indicator()?>**_(Stopped)_.**</td><td><input type="submit" name="cmdStart" value="_(Start)_" disabled></td>
<td>_(Too many attached devices. Please consider upgrading your)_ <a href="/Tools/Registration">_(registration key)_</a>.</td></tr>
<? elseif (_var($var,'configValid')=="ineligible"):?>
<tr><td><?status_indicator()?>**_(Stopped)_.**</td><td><input type="submit" name="cmdStart" value="_(Start)_" disabled></td>
<td>_(Ineligible to run this version of Unraid OS. Please consider extending your)_ <a href="/Tools/Registration">_(registration key)_</a>.</td></tr>
<? elseif (_var($var,'configValid')=="nokeyserver"):?>
<tr><td><?status_indicator()?>**_(Stopped)_.**</td><td><input type="submit" name="cmdStart" value="_(Start)_" disabled></td>
<td>_(Cannot contact key-server. Please check your)_ <a href="/Settings/NetworkSettings">_(network settings)_</a>.</td></tr>
+57 -10
View File
@@ -1,5 +1,5 @@
Menu="Dashboard"
Nchan="wg_poller,update_1,update_2,update_3,ups_status:stop"
Nchan="wg_poller,update_1,update_2,update_3,ups_status:stop,vm_dashusage:stop"
---
<?PHP
/* Copyright 2005-2023, Lime Technology * Copyright 2012-2023, Bergware International.
@@ -73,6 +73,10 @@ $vdisk = exec("grep -Pom1 '^DOCKER_IMAGE_TYPE=\"\\K[^\"]+' /boot/config/docker.c
$dot = _var($display,'number','.,')[0];
$zfs = count(array_filter(array_column($disks,'fsType'),function($fs){return str_replace('luks:','',$fs??'')=='zfs';}));
$domain_cfgfile = "/boot/config/domain.cfg";
$domain_cfg = parse_ini_file($domain_cfgfile);
if (!isset($domain_cfg['USAGE'])) $vmusage = "N" ; else $vmusage = $domain_cfg['USAGE'];
// enable/disable graph elements by making hook script executable or not
chmod("$docroot/webGui/system/VM_usage",$libvirtd ? 0755 : 0644);
chmod("$docroot/webGui/system/ZFS_cache",$zfs ? 0755 : 0644);
@@ -275,10 +279,10 @@ foreach ($cpus as $pair) {
<a href='/Dashboard/Tools/Processes' title="_(View Running Processes)_"><i class='fa fa-fw fa-info-circle control'></i></a>
</td></tr><tr><td>
<span class='w26'><i class='ups fa fa-compress'></i>_(Usable size)_: <?=$ramsize?><br><i class='ups fa fa-expand'></i>_(Maximum size)_: <?="$memory_maximum $unit"?><?=$low?'*':''?></span>
<span class='w18 center'><a class='info hand none'>_(RAM usage)_<span>_(Percent of total used memory)_ (<?=$ramsize?>)</span></a></span>
<span class='w18 center'><a class='info hand none'>_(Flash device)_<span>_(Percent usage of flash usb device)_ (<?=$flashsize?>)</span></a></span>
<span class='w18 center'><a class='info hand none'>_(Log filesystem)_<span>_(Percent usage of LOG file system)_ (<?=$logsize?>)</span></a></span>
<span class='w18 center'><a class='info hand none'><?=$vdisk?><span><?=_("Percent usage of $vdisk")?> (<?=$dockersize?>)</span></a></span>
<span class='w18 center static'><a class='info hand none'>_(RAM usage)_<span>_(Percent of total used memory)_ (<?=$ramsize?>)</span></a></span>
<span class='w18 center static'><a class='info hand none'>_(Flash device)_<span>_(Percent usage of flash usb device)_ (<?=$flashsize?>)</span></a></span>
<span class='w18 center static'><a class='info hand none'>_(Log filesystem)_<span>_(Percent usage of LOG file system)_ (<?=$logsize?>)</span></a></span>
<span class='w18 center static'><a class='info hand none'><?=$vdisk?><span><?=_("Percent usage of $vdisk")?> (<?=$dockersize?>)</span></a></span>
</td></tr><tr><td>
<span class='w26'><legend>_(Legend)_</legend><span id='dynamic'></span></span>
<span class='w18 center'><div class='pie' id='sys0'><span class='sys0'></span><span class='var0'></span></div></span>
@@ -424,6 +428,13 @@ echo "</td></tr>";
<a href='/Dashboard/Settings/VMSettings' title="_(Go to VM settings)_"><i class='fa fa-fw fa-cog control'></i></a>
</td></tr>
</tbody>
<?if ($vmusage == "Y"):?>
<tbody id='vm_view_usage' title="_(Virtual Machines Usage)_" >
<tr><td><i class='icon-virtualization f32'></i><div class='section'>_(Virtual Machines Usage)_</div>
<a href='/Dashboard/Settings/VMSettings' title="_(Go to VM settings)_"><i class='fa fa-fw fa-cog control'></i></a>
</td></tr>
</tbody>
<?endif;?>
<?endif;?>
<tbody title="_(Shares Information)_"<?if ($group):?> class="mixed"<?endif;?>>
@@ -685,7 +696,8 @@ function hideShow() {
<tr><td>_(VM Name)_:</td><td><label id="VMName"></label></td></tr>
<tr><td>_(Snapshot Name)_:</td><td><input type="text" id="targetsnap" autocomplete="off" spellcheck="false" value="--generate" onclick="this.select()">_(Check free space)_:<input type="checkbox" id="targetsnapfspc" checked></td></tr>
<tr><td>_(Description)_:</td><td><input type="text" id="targetsnapdesc" autocomplete="off" spellcheck="false" value="" onclick="this.select()"></td></tr>
<tr id="fstypeline"><td>_(FS Native Snapshot )_:</td><td><label id="fstype"></label><input type="checkbox" id="targetsnapfstype" checked>_(Unchecked will use QEMU External Snapshot)_</td></tr>
<tr id="memoryline"><td>_(Memory dump )_:</td><td><input type="checkbox" id="targetsnapmem" checked></td></tr>
<tr id="fstypeline"><td>_(FS Native Snapshot )_:</td><td><label id="fstype"></label><input type="checkbox" id="targetsnapfstype" >_(Unchecked will use QEMU External Snapshot)_</td></tr>
</table>
</div>
@@ -932,7 +944,7 @@ function loadlist(init) {
$('#vms').is(':checked') ? $.cookie('my_vms','startedOnly',{expires:3650}) : $.removeCookie('my_vms');
});
}
$.post('/webGui/include/DashboardApps.php',{docker:'<?=$dockerd?>',vms:'<?=$libvirtd?>'},function(d) {
$.post('/webGui/include/DashboardApps.php',{docker:'<?=$dockerd?>',vms:'<?=$libvirtd?>',vmusage:'<?=$vmusage?>'},function(d) {
var data = d.split('\0');
$('#docker_view tr.updated').remove();
$('#docker_view').append(data[0]).hideMe();
@@ -944,6 +956,8 @@ function loadlist(init) {
var started_vms = $('#vm_view').find('span.outer.vms.started').length;
var stopped_vms = $('#vm_view').find('span.outer.vms.stopped').length;
var paused_vms = $('#vm_view').find('span.outer.vms.paused').length;
$('#vm_view_usage tr.useupdated').remove();
$('#vm_view_usage').append(data[2]).hideMe();
$('.apps.switch').html("_(Containers)_ -- _(Started)_: "+started_apps+", _(Stopped)_: "+stopped_apps+", _(Paused)_: "+paused_apps);
$('.vms.switch').html("_(VMs)_ -- _(Started)_: "+started_vms+", _(Stopped)_: "+stopped_vms+", _(Paused)_: "+paused_vms);
if ($.cookie('my_apps')!=null) $('span.apps.stopped').hide(0,noApps());
@@ -1209,7 +1223,7 @@ function addProperties() {
$('div#sys3').hover(function(){$('.sys3').hide();$('.var3').show();},function(){$('.sys3').show();$('.var3').hide();});
$('#current_time').hover(function(){$.post('/webGui/include/DashboardApps.php',{ntp:'ntp'},function(ntp){$('#current_time').prop('title',ntp+"\n_(Go to date and time settings)_");});});
// make truncated descriptions fully visible when hovering over them
$('span.w18').hover(
$('span.w18').not('.static').hover(
function(){if ($(this)[0].offsetWidth < $(this)[0].scrollWidth) {recall = $(this).next(); recover=recall.html(); recall.html('&nbsp;');}},
function(){if ($(this)[0].offsetWidth < $(this)[0].scrollWidth) {recall.html(recover); recall=null;}}
);
@@ -1380,7 +1394,7 @@ function VMClone(uuid, name){
});
dialogStyle();
}
function selectsnapshot(uuid, name ,snaps, opt, getlist, status,fstype){
function selectsnapshot(uuid, name ,snaps, opt, getlist, state,fstype){
box = $("#iframe-popup");
box.html($("#templatesnapshot"+opt).html());
const capopt = opt.charAt(0).toUpperCase() + opt.slice(1);
@@ -1394,7 +1408,21 @@ function selectsnapshot(uuid, name ,snaps, opt, getlist, status,fstype){
var only = (opt == "remove") ? 0 : 1;
$.post("/plugins/dynamix.vm.manager/include/VMajax.php",{action:"snap-images",uuid:uuid,snapshotname:snaps,only:only},function(data){if (data.html) box.find('#targetsnapimages').html(data.html);},'json');
}
var memorydump = "no";
document.getElementById("targetsnapfspc").checked = true;
if (fstype == "ZFS") {
box.find('#targetsnaprmv').prop('disabled',true);
box.find('#targetsnaprmvmeta').prop('disabled',true);
}
if (state != "running") {
box.find('#memoryline').prop('hidden',true);
box.find('#targetsnapmem').prop('hidden',true);
box.find('#targetsnapmem').prop('checked',false);
} else {
box.find('#memoryline').prop('hidden',false);
box.find('#targetsnapmem').prop('hidden',false);
box.find('#targetsnapmem').prop('checked',true);
}
box.dialog({
title: optiontext,
height: 'auto',
@@ -1422,10 +1450,11 @@ function selectsnapshot(uuid, name ,snaps, opt, getlist, status,fstype){
if (opt == "create") {
free = box.find('#targetsnapfspc').prop('checked') ? 'yes' : 'no';
desc = box.find("#targetsnapdesc").prop('value');
memorydump = box.find('#targetsnapmem').prop('checked') ? 'yes' : 'no';
fstypeuse = box.find('#targetsnapfstype').prop('checked') ? 'yes' : 'no';
if (fstypeuse == "no") fstype ="QEMU";
}
ajaxVMDispatch({action:"snap-" + opt +'-external', uuid:uuid, snapshotname:target, remove:remove, free:free, desc:desc, fstype:fstype}, "loadlist");
ajaxVMDispatch({action:"snap-" + opt +'-external', uuid:uuid, snapshotname:target, remove:remove, free:free, desc:desc, fstype:fstype,memorydump:memorydump}, "loadlist");
box.dialog('close');
},
"_(Cancel)_": function(){
@@ -1501,6 +1530,18 @@ function cpu_parse(msg) {
return parse;
}
<?if ($vmusage == "Y"):?>
var vmdashusage = new NchanSubscriber('/sub/vm_dashusage',{subscriber:'websocket'});
vmdashusage.on('message', function(msg){
var data = JSON.parse(msg);
for (const [vm, vmdata] of Object.entries(data)) {
for (const [displayitem, value] of Object.entries(vmdata)) {
$('#vmmetrics-'+displayitem + '-' + vm ).html(value);
}
}
});
<?endif;?>
var dashboard = new NchanSubscriber('/sub/cpuload,update1,update2,update3<?=$wireguard?",wireguard":""?>',{subscriber:'websocket'});
dashboard.on('message',function(msg,meta) {
switch (meta.id.channel()) {
@@ -1667,6 +1708,9 @@ $(function() {
dropdown('enter_view');
startup = false;
dashboard.start();
<?if ($vmusage == "Y"):?>
vmdashusage.start();
<?endif;?>
<?if ($apcupsd):?>
apcups.start();
<?endif;?>
@@ -1692,6 +1736,9 @@ $(function() {
window.onunload = function(){
dashboard.stop();
<?if ($vmusage == "Y"):?>
vmdashusage.stop();
<?endif;?>
<?if ($apcupsd):?>
apcups.stop();
<?endif;?>
+16 -2
View File
@@ -313,7 +313,14 @@ function setGlue(form,reset) {
{glue:'/',more:3,dev:1,type:'',min1:1,max1:4,min2:1,max2:128,min3:1,max3:4}, // highpoint
{glue:'' ,more:1,dev:1,type:'',min1:0,max1:15}, // hp cciss
{glue:'' ,more:0,dev:0,type:''}, // marvell
{glue:',',more:1,dev:1,type:'',min1:0,max1:127} // megaraid
{glue:',',more:1,dev:1,type:'',min1:0,max1:127}, // megaraid
{glue:',',more:1,dev:0,type:'input',min1:'',max1:'0xffffffff'}, // cypress
{glue:',',more:3,dev:0,type:'select',min1:'',max1:'p',min2:'',max2:'x',min3:1,max3:128},// jmicron ata
{glue:'' ,more:0,dev:0,type:''}, // prolific
{glue:'' ,more:0,dev:0,type:''}, // sunplus
{glue:'' ,more:0,dev:0,type:''}, // asmedia
{glue:'' ,more:0,dev:0,type:''}, // jmicron nvme
{glue:'' ,more:0,dev:0,type:''}, // realtek
];
var n = form.smType.selectedIndex>0 ? form.smType.selectedIndex-1 : <?=_var($var,'smIndex',0)?>;
var x = data[n]['more'];
@@ -603,7 +610,7 @@ _(Spin down delay)_:
_(File system status)_:
: <?=_(_var($disk,'fsStatus'))?>&nbsp;
<?$disabled = (_var($var,'fsState')=="Stopped" && !empty(_var($disk,'uuid'))) || (_var($var,'fsState')=="Started" && _var($disk,'fsStatus')=='Mounted') ? "disabled" : ""?>
<?$disabled = (_var($var,'fsState')=="Stopped" && !empty(_var($disk,'uuid'))) || (_var($var,'fsState')=="Started" && _var($disk,'fsType')!='auto') ? "disabled" : ""?>
<?if (diskType('Data') || (!isSubpool($name) && _var($disk,'slots',0)==1)):?>
_(File system type)_:
: <select id="diskFsType" name="diskFsType.<?=_var($disk,'idx',0)?>" onchange="changeFsType()" <?=$disabled?>>
@@ -1246,6 +1253,13 @@ _(SMART controller type)_:
<?=mk_option(_var($disk,'smType'), "-d cciss", "HP cciss")?>
<?=mk_option(_var($disk,'smType'), "-d marvell", "Marvell")?>
<?=mk_option(_var($disk,'smType'), "-d megaraid", "MegaRAID")?>
<?=mk_option(_var($disk,'smType'), "-d usbcypress", "Cypress ATACB")?>
<?=mk_option(_var($disk,'smType'), "-d usbjmicron", "JMicron ATA pass-through")?>
<?=mk_option(_var($disk,'smType'), "-d usbprolific", "Prolific ATA pass-through")?>
<?=mk_option(_var($disk,'smType'), "-d usbsunplus", "Sunplus ATA pass-through")?>
<?=mk_option(_var($disk,'smType'), "-d sntasmedia", "ASMedia NVMe pass-through")?>
<?=mk_option(_var($disk,'smType'), "-d sntjmicron", "JMicron NVMe pass-through")?>
<?=mk_option(_var($disk,'smType'), "-d sntrealtek", "Realtek NVMe pass-through")?>
</select>
<input type="text" name="smPort1" value="<?=_var($disk,'smPort1')?>" class="option"><select name="smPort1" class="narrow option" disabled></select>
<input type="text" name="smPort2" value="<?=_var($disk,'smPort2')?>" class="option"><select name="smPort2" class="narrow option" disabled></select>
+7
View File
@@ -364,6 +364,13 @@ _(Default SMART controller type)_:
<?=mk_option(_var($var,'smType'), "-d cciss", "HP cciss")?>
<?=mk_option(_var($var,'smType'), "-d marvell", "Marvell")?>
<?=mk_option(_var($var,'smType'), "-d megaraid", "MegaRAID")?>
<?=mk_option(_var($var,'smType'), "-d usbcypress", "Cypress ATACB")?>
<?=mk_option(_var($var,'smType'), "-d usbjmicron", "JMicron ATA pass-through")?>
<?=mk_option(_var($var,'smType'), "-d usbprolific", "Prolific ATA pass-through")?>
<?=mk_option(_var($var,'smType'), "-d usbsunplus", "Sunplus ATA pass-through")?>
<?=mk_option(_var($var,'smType'), "-d sntasmedia", "ASMedia NVMe pass-through")?>
<?=mk_option(_var($var,'smType'), "-d sntjmicron", "JMicron NVMe pass-through")?>
<?=mk_option(_var($var,'smType'), "-d sntrealtek", "Realtek NVMe pass-through")?>
</select>
:disk_default_smart_controller_help:
+10 -28
View File
@@ -5,8 +5,8 @@ Icon="icon-key"
Tag="expeditedssl"
---
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
/* Copyright 2005-2024, Lime Technology
* Copyright 2012-2024, 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,
@@ -75,7 +75,7 @@ if ($cert1Present) {
$cert1SelfSigned = ($cert1Subject == $cert1Issuer);
}
// unraid.net, myunraid.net LE cert. could potentially be user provided as well
// myunraid.net LE cert. could potentially be user provided as well
$cert2File = "/boot/config/ssl/certs/certificate_bundle.pem";
$cert2Present = file_exists("$cert2File");
if ($cert2Present) {
@@ -84,6 +84,8 @@ if ($cert2Present) {
$cert2Expires = exec("/usr/bin/openssl x509 -in $cert2File -noout -text | sed -n -e 's/^.*Not After : //p'");
$isWildcardCert = preg_match('/.*\.myunraid\.net$/', $cert2Subject);
$subject2URL = $cert2Subject;
$dnsValid = false;
$dnsRebindingProtection = false;
if ($isWildcardCert) {
exec("openssl x509 -checkend 2592000 -noout -in $cert2File 2>/dev/null", $arrout, $retval_expired);
if (!$addr) {
@@ -119,8 +121,8 @@ $http_port = _var($var,'PORT','80') != '80' ? ":{$var['PORT']}" : '';
$https_port = _var($var,'PORTSSL','443') != '443' ? ":{$var['PORTSSL']}" : '';
$http_ip_url = "http://"._var($nginx,'NGINX_LANIP')."{$http_port}/";
$https_ip_url = "https://"._var($nginx,'NGINX_LANIP')."{$https_port}/";
$http_ip6_url = "http://"._var($nginx,'NGINX_LANIP6')."{$http_port}/";
$https_ip6_url = "https://"._var($nginx,'NGINX_LANIP6')."{$https_port}/";
$http_ip6_url = "http://["._var($nginx,'NGINX_LANIP6')."]{$http_port}/";
$https_ip6_url = "https://["._var($nginx,'NGINX_LANIP6')."]{$https_port}/";
$http_mdns_url = "http://"._var($nginx,'NGINX_LANMDNS')."{$http_port}/";
$https_mdns_url = "https://"._var($nginx,'NGINX_LANMDNS')."{$https_port}/";
$https_fqdn_url = "https://"._var($nginx,'NGINX_LANFQDN')."{$https_port}/";
@@ -164,7 +166,6 @@ $cert_time_format = $display['date'].($display['date']!='%c' ? ', '.str_replac
$provisionlabel = $isWildcardCert ? _('Renew') : _('Provision');
$disabled_provision = $keyfile===false || ($isWildcardCert && $retval_expired===0) || !$addr ? 'disabled' : '';
$disabled_provision_msg = !$addr ? _('Ensure the primary network card eth0 has an IP address.') : '';
$disabled_updatedns = $keyfile!==false && $isWildcardCert ? '' : 'disabled';
$disabled_delete = $cert2Present && $var['USE_SSL']!='auto' ? '' : 'disabled';
$disabled_auto = $isWildcardCert && !$dnsRebindingProtection && $dnsValid ? '' : 'disabled';
@@ -189,23 +190,6 @@ function provisionHandler(event, form) { // provisions and renewals require bein
if (event.submitter.value === 'Renew') return true; // always allow renewals
};
function updateDNS(button) {
$(button).prop("disabled", true).html("<i class='fa fa-circle-o-notch fa-spin fa-fw'></i>_(Update DNS)_");
var failure = function(data) {
var status = data.status;
var obj = data.responseJSON;
var msg = "_(Sorry, an error occurred updating unraid.net DNS records)_. _(The error is)_: "+obj.error+".";
$(button).prop("disabled", false).html("_(Update DNS)_");
swal({title:"_(Oops)_",text:msg,type:"error",html:true,confirmButtonText:"_(Ok)_"});
};
var success = function(data) {
$(button).prop("disabled", false).html("_(Update DNS)_");
<?$text = _('Your local IP address %s has been updated for unraid.net')?>
swal({title:"",text:"<?=sprintf($text,$addr)?>",type:"success",html:true,confirmButtonText:"_(Ok)_"});
};
$.post("/webGui/include/UpdateDNS.php",success).fail(failure);
}
function checkPorts(form) {
var portsInUse = [<?=implode(',',$portsInUse)?>];
var range = [], list = [], duplicates = [];
@@ -359,12 +343,10 @@ _(Local access URLs)_:
$n = 0;
foreach($urls as $url) {
$msg = "";
$url0 = substr_count($url[0]??'',':')>3 ? preg_replace('#(://)(.+?)(:?\d*)/$#','$1[$2]$3/',$url[0]) : $url[0]; // IPv6 - IPv4 notation
$url1 = substr_count($url[1]??'',':')>3 ? preg_replace('#(://)(.+?)(:?\d*)/$#','$1[$2]$3/',$url[1]) : $url[1]; // IPv6 - IPv4 notation
if ($url[1]) $msg .= " "._("redirects to")." <a href='$url1'>$url1</a>";
if ($url[1]) $msg .= " "._("redirects to")." <a href='$url[1]'>$url[1]</a>";
if ($url[2]) $msg .= " "._("uses")." ".$url[2];
if ($url[3]) $msg .= "<span class='warning'> <i class='fa fa-warning fa-fw'></i> "._("is a self-signed certificate, ignore the browser's warning and proceed to the GUI")."</span>";
echo ($n ? "<dt>&nbsp;</dt><dd>" : ""),"<a href='$url0'>$url0</a>$msg",($n++ ? "</dd>" : "");
echo ($n ? "<dt>&nbsp;</dt><dd>" : ""),"<a href='$url[0]'>$url[0]</a>$msg",($n++ ? "</dd>" : "");
}?>
:mgmt_local_access_urls_help:
@@ -431,7 +413,7 @@ _(CA-signed certificate file)_:
<?endif;?>
&nbsp;
: <button type="submit" name="changePorts" value="Provision" <?=$disabled_provision?>><?=$provisionlabel?></button><button type="submit" name="changePorts" value="Delete" <?=$disabled_delete?> >_(Delete)_</button><!-- <button type="button" onclick="updateDNS(this)" <?=$disabled_updatedns?>>_(Update DNS)_</button> --><?=$disabled_provision_msg?>
: <button type="submit" name="changePorts" value="Provision" <?=$disabled_provision?>><?=$provisionlabel?></button><button type="submit" name="changePorts" value="Delete" <?=$disabled_delete?> >_(Delete)_</button><?=$disabled_provision_msg?>
:mgmt_certificate_expiration_help:
+1 -2
View File
@@ -18,8 +18,7 @@ Tag="folder-o"
<?
$width = [166,300];
function data_disks($disk) {
global $pools;
return (_var($disk,'type')=="Data" || (_var($disk,'type')=="Cache" && in_array(_var($disk,'name'),$pools))) && _var($disk,'status')=='DISK_OK';
return in_array(_var($disk,'type'),['Data','Cache']) && array_key_exists('exportable',$disk) && _var($disk,'fsStatus')=='Mounted';
}
?>
<script>
+1 -1
View File
@@ -101,7 +101,7 @@ function textsave(module,remove = false) {
if (data.modprobe == "") $('#text'+module).attr('hidden', true); else $('#text'+module).attr('rows', 3);
if (data.supportpage == true) {
if (data.support == true) {
document.getElementById("link" + module).innerHTML = "<a href='" + data.supporturl + "'target='_blank'><i title='"+_("Support page")_+"' class='fa fa-phone-square'></i></a>";
document.getElementById("link" + module).innerHTML = "<a href='" + data.supporturl + "'target='_blank'><i title='"+"_(Support page)_"+"' class='fa fa-phone-square'></i></a>";
}
}
}
+10 -1
View File
@@ -108,6 +108,15 @@ _(Local syslog folder)_:
:syslog_local_folder_help:
_(System identifier for logfile name)_:
: <select name="server_filename">
<?=mk_option($syslog['server_filename'], "syslog-%FROMHOST-IP%.log", _("IP Address"))?>
<?=mk_option($syslog['server_filename'], "syslog-%HOSTNAME%.log", _("Hostname (from syslog message)"))?>
<?=mk_option($syslog['server_filename'], "syslog-%FROMHOST%.log", _("Hostname (from DNS reverse lookup)"))?>
</select>
:syslog_remote_system_identifier_help:
_(Local syslog rotation)_:
: <select name="log_rotation" onchange="logOptions(this.value,'slow')">
<?=mk_option(_var($syslog,'log_rotation'), "", _("Disabled"))?>
@@ -146,7 +155,7 @@ _(Local syslog number of files)_:
</div>
_(Remote syslog server)_:
: <span class="span"><input type="text" name="remote_server" class="narrow" value="<?=_var($syslog,'remote_server')?>" maxlength="23" placeholder="_(name or ip address)_"></span>
: <span class="span"><input type="text" name="remote_server" class="narrow" value="<?=_var($syslog,'remote_server')?>" maxlength="50" placeholder="_(name or ip address)_"></span>
<select name="remote_protocol" class="narrow">
<?=mk_option(_var($syslog,'remote_protocol'), "udp", _("UDP"))?>
<?=mk_option(_var($syslog,'remote_protocol'), "tcp", _("TCP"))?>
+2
View File
@@ -30,6 +30,8 @@ $(function() {
$globals = [];
$names = ['_SERVER','devs','disks','sec','sec_nfs','shares','users','var'];
foreach ($names as $name) $globals[$name] = $$name;
// show outgoing proxy information, is in the environment but not a superglobal
$globals['environment'] = ['http_proxy' => getenv('http_proxy'), 'no_proxy' => getenv('no_proxy')];
echo "<pre class='up'>",htmlspecialchars(print_r($globals,true)),"</pre>";
?>
<input type="button" value="_(Done)_" onclick="done()">
-121
View File
@@ -1,121 +0,0 @@
Menu="UNRAID-OS"
Title="Wake On LAN"
Icon="fa-bell"
Tag="server"
---
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, 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,
* as published by the Free Software Foundation.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
if (count($_POST)) {
$cfg = NULL ;
if ($_POST['#apply'] == "_(Save)_") {
foreach($_POST as $postkey=>$data) {
if ($postkey=="#apply") continue;
$keys = explode(";",$postkey);
if (count($keys) >1) $update_file[$keys[1]][$keys[2]][$keys[0]]=$data;
}
foreach($update_file as $type => $types) {
foreach($types as $name => $details) {
if ($details['user_mac'] == "") $details['user_mac'] = "None Defined";
if ($details['user_mac'] == "None Defined" && ($details['enable'] == "enable" || $details['enable'] == "shutdown")) unset($update_file[$type][$name]) ;
}
}
}
unset($_POST) ;
file_put_contents("/boot/config/wol.json",json_encode($update_file));
#echo '<meta http-equiv="refresh" content="0;url=/Tools">';
echo '<meta http-equiv="refresh" content="0">';
#unset($_SESSION['csrf_token']);
}
?>
<script src="/webGui/javascript/jquery.tablesorter.widgets.js"></script>
<script>
function showWOL(options, init = false) {
option = options;
if (init) {
$('#wolsearch').prop('disabled', true);
$.post('/webGui/include/WOL.php',{table:'t1load',option:"all"},function(data){
clearTimeout(timers.refresh);
filter = [];
$("#t1").trigger("destroy");
$('#t1').html(data.html);
$('#t1').tablesorter({
sortList: [[0,0]],
sortAppend: [[0,0]],
widgets: ['stickyHeaders','filter','zebra'],
widgetOptions: {
// on black and white, offset is height of #menu
// on azure and gray, offset is height of #header
stickyHeaders_offset: ($('#menu').height() < 50) ? $('#menu').height() : $('#header').height(),
filter_columnFilters: false,
zebra: ["normal-row","alt-row"]
}
});
$('div.spinner.fixed').hide('slow');
$('#wolsearch').prop('disabled', false);
$('#select').prop('disabled', false);
$('#rebuild').prop('disabled', data.init);
},"json");
} else {
filter = [];
filterWOL();
}
}
function filterWOL() {
var totalColumns = $('#t1')[0].config.columns;
var filter = [];
filter[totalColumns] = $('#wolsearch').val(); // this searches all columns
$('#t1').trigger('search', [filter]);
}
function showWOLupdate() {
$('#rebuild').prop('disabled', true);
$('#t1').html("");
$('#wolsearch').prop('disabled', true);
$('#select').prop('disabled', true);
$('div.spinner.fixed').show('slow');
$.post('/webGui/include/WOL.php',{table:'t1create',option:"all"},function(data){
$('#rebuild').prop('disabled', false);
showWOL("all",true);
$('div.spinner.fixed').hide('slow');
});
}
function maccreate(name) {
$.post('/webGui/include/WOL.php',{table:'macaddress'}, function( data ) {
if (data.mac) {
$('#'+name).val(data.mac);
}
},'json');
}
showWOL("all",true);
</script>
:WOL_intro_help:
<form autocomplete="off" onsubmit="return false;"><span><input class="t1 search" id="wolsearch" type="search" placeholder="Search..." onchange="filterWOL();"></span></form>
<pre><form name="WOL" id="WOL" method="POST" class="js-confirm-leave" >
<table name="t1"id='t1' class="t1 unraid tablesorter" >
<tr><td><div class="spinner"></div></td></tr></table></pre><br>
<input type="button" value="_(Done)_" onclick="done()">
<input type="submit" name="#apply" id='#apply' value="_(Save)_" >
</form>
-102
View File
@@ -1,102 +0,0 @@
Menu="OtherSettings"
Type="xmenu"
Title="Wake on Lan Settings"
Icon="fa-bell"
Tag="share-alt"
---
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, 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,
* as published by the Free Software Foundation.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
?>
<?
exec("ls --indicator-style=none /sys/class/net|grep -P '^eth[1-9][0-9]*$'",$ports);
$disabled = _var($var,'fsState')!='Stopped' ? 'disabled' : '';
$width = [166,300];
$file = '/boot/config/wol.cfg';
$current = parse_ini_file($file);
if (!isset($current['LOGFILE'])) $current['LOGFILE'] = "syslog"
?>
<script>
showStatus('pid','unraidwold');
</script>
<form markdown="1" name="WOLsettings" method="POST" action="/update.php" target="progressFrame" >
<input type="hidden" name="#file" value="<?=$file;?>">
<input type="hidden" name="#command" value="/webGui/scripts/WOL_action">
<input type="hidden" name="#arg[1]" value="load">
_(Enable Wake on Lan)_:
: <select name="WOLENABLED" >
<?=mk_option($current['WOLENABLED'], "no", _('No'))?>
<?=mk_option($current['WOLENABLED'], "yes", _('Yes'))?>
</select>
:WOL_enable_help:
_(Enable Docker actions)_:
: <select name="RUNDOCKER" >
<?=mk_option($current['RUNDOCKER'], "y", _('Yes'))?>
<?=mk_option($current['RUNDOCKER'], "n", _('No'))?>
</select>
:WOL_run_docker_help:
_(Enable LXC actions)_:
: <select name="RUNLXC" >
<?=mk_option($current['RUNLXC'], "y", _('Yes'))?>
<?=mk_option($current['RUNLXC'], "n", _('No'))?>
</select>
:WOL_run_LXC_help:
_(Enable VM actions)_:
: <select name="RUNVM" >
<?=mk_option($current['RUNVM'], "y", _('Yes'))?>
<?=mk_option($current['RUNVM'], "n", _('No'))?>
</select>
:WOL_run_VM_help:
_(Enable Shutdown actions)_:
: <select name="RUNSHUT" >
<?=mk_option($current['RUNSHUT'], "n", _('No'))?>
<?=mk_option($current['RUNSHUT'], "y", _('Yes'))?>
</select>
:WOL_run_shutdown_help:
_(Interface to listern on)_:
: <select id="INTERFACE" name="INTERFACE" >
<?=mk_option(_var($eth0,'INTERFACE'),'eth0','eth0','selected')?>
<?foreach ($ports as $port):?>
<?if (!locked('eth0',$port)) echo mk_option_check($current['INTERFACE'],$port,$port)?>
<?endforeach;?>
</select>
:WOL_interface_help:
_(Interface promiscuous mode)_:
: <select id="IFMODE" name="IFMODE" >
<?=mk_option($current['IFMODE'], "n", _('No'))?>
<?=mk_option($current['IFMODE'], "y", _('Yes'))?>
</select>
:WOL_promiscuous_mode_help:
_(Log file)_:
: <input name="LOGFILE" class="narrow"type="text" value=<?=$current['LOGFILE']?>>
:WOL_log_file_help:
&nbsp;
: <input type="submit" value="_(Apply)_" disabled><input type="button" value="_(Done)_" onclick="done()">
</form>
@@ -1,3 +0,0 @@
#!/bin/bash
/usr/local/emhttp/plugins/dynamix/scripts/WOL_action load &
@@ -1,3 +0,0 @@
#!/bin/bash
/usr/local/emhttp/plugins/dynamix/include/script/WOL_action stop &
@@ -68,6 +68,8 @@ if ($_POST['docker']) {
}
echo "\0";
if ($_POST['vms']) {
$vmusage = $_POST['vmusage'];
$vmusagehtml = [];
$user_prefs = '/boot/config/plugins/dynamix.vm.manager/userprefs.cfg';
$vms = $lv->get_domains() ?: [];
if (file_exists($user_prefs)) {
@@ -78,6 +80,7 @@ if ($_POST['vms']) {
natcasesort($vms);
}
echo "<tr title='' class='updated'><td>";
$running = 0;
foreach ($vms as $vm) {
$res = $lv->get_domain_by_name($vm);
$uuid = libvirt_domain_get_uuid_string($res);
@@ -123,6 +126,7 @@ if ($_POST['vms']) {
$shape = 'play';
$status = 'started';
$color = 'green-text';
$running++;
break;
case 'paused':
case 'pmsuspended':
@@ -138,8 +142,30 @@ if ($_POST['vms']) {
}
$image = substr($icon,-4)=='.png' ? "<img src='$icon' class='img'>" : (substr($icon,0,5)=='icon-' ? "<i class='$icon img'></i>" : "<i class='fa fa-$icon img'></i>");
echo "<span class='outer solid vms $status'><span id='vm-$uuid' $menu class='hand'>$image</span><span class='inner'>$vm<br><i class='fa fa-$shape $status $color'></i><span class='state'>"._($status)."</span></span></span>";
if ($state == "running") {
#Build VM Usage array.
$menuusage = sprintf("onclick=\"addVMContext('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')\"", addslashes($vm), addslashes($uuid), addslashes($template), $state, addslashes($vmrcurl), strtoupper($vmrcprotocol), addslashes($log),addslashes($fstype), $vmrcconsole,true);
$vmusagehtml[] = "<span class='outer solid vmsuse $status'><span id='vmusage-$uuid' $menuusage class='hand'>$image</span><span class='inner'>$vm<br><i class='fa fa-$shape $status $color'></i><span class='state'>"._($status)."</span></span>";
$vmusagehtml[] = "<br><br><span id='vmmetrics-gcpu-".$uuid."'>"._("Loading")."....</span>";
$vmusagehtml[] = "<br><span id='vmmetrics-hcpu-".$uuid."'>"._("Loading")."....</span>";
$vmusagehtml[] = "<br><span id='vmmetrics-mem-".$uuid."'>"._("Loading")."....</span>";
$vmusagehtml[] = "<br><span id='vmmetrics-disk-".$uuid."'>"._("Loading")."....</span>";
$vmusagehtml[] = "<br><span id='vmmetrics-net-".$uuid."'>"._("Loading")."....</span>";
$vmusagehtml[] = "</span>";
}
}
$none = count($vms) ? _('No running virtual machines') : _('No virtual machines defined');
echo "<span id='no_vms' style='display:none'>$none<br><br></span>";
echo "</td></tr>";
echo "\0";
echo "<tr title='' class='useupdated'><td>";
if ($vmusage == "Y") {
foreach ($vmusagehtml as $vmhtml) {
echo $vmhtml;
}
if (!count($vmusagehtml)) echo "<span id='no_usagevms'><br> "._('No running virtual machines')."<br></span>";
if ($running < 1 && count($vmusagehtml)) echo "<span id='no_usagevms'><br>". _('No running virtual machines')."<br></span>";
echo "</td></tr>";
}
}
@@ -291,4 +291,13 @@ function my_mkdir($dirname,$permissions = 0777,$recursive = false) {
break;
}
}
function get_realvolume($path) {
if (strpos($path,"/mnt/user/",0) === 0)
$reallocation = trim(shell_exec("getfattr --absolute-names --only-values -n system.LOCATION ".escapeshellarg($path)." 2>/dev/null"));
else {
$realexplode = explode("/",str_replace("/mnt/","",$path));
$reallocation = $realexplode[0];
}
return $reallocation;
}
?>
@@ -39,13 +39,13 @@ foreach ($files as $file) {
$c = 0;
foreach ($fields as $field) {
if ($c==5) break;
$text = $field ? explode('=',$field,2)[1] : "-";
$text = $field ? (explode('=',$field,2)[1]??"") : "-";
$tag = ($c<4) ? "" : " data='".str_replace(['alert','warning','normal'],['0','1','2'],$text)."'";
echo (!$c++) ? "<tr>".str_replace('*',$text,$td_).date($dynamix['notify']['date'].' '.$dynamix['notify']['time'],$text)."$_td" : "<td$tag>"._($text)."</td>";
}
echo "<td><a href='#' onclick='$(this).hide();$.post(\"/webGui/include/DeleteLogFile.php\",{log:\"$archive\"},function(){archiveList();});return false' title=\""._('Delete notification')."\"><i class='fa fa-trash-o'></i></a></td></tr>";
if ($extra) {
$text = explode('=',$field,2)[1];
$text = explode('=',$field,2)[1]??"";
echo "<tr class='tablesorter-childRow row$row'><td colspan='4'>$text</td><td></td></tr><tr class='tablesorter-childRow row$row'><td colspan='5'></td></tr>";
$row++;
}
@@ -73,7 +73,7 @@ case 't1load':
} else {
$supporturl = $module['supporturl'];
$pluginname = $module['plugin'];
$supporthtml = "<span id='link$modname'><a href='$supporturl' target='_blank'><i title='"._("Support page $pluginname")."' class='fa fa-phone-square'></i></a></span>";
$supporthtml = "<span id='link$modname'><a href='$supporturl' target='_blank'><i title='"._("Support page")." $pluginname' class='fa fa-phone-square'></i></a></span>";
}
}
if (!empty($module["version"])) $version = " (".$module["version"].")"; else $version = "";
+9 -347
View File
@@ -1,6 +1,6 @@
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
/* Copyright 2005-2024, Lime Technology
* Copyright 2012-2024, 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,
@@ -12,353 +12,15 @@
?>
<?
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Helpers.php";
// add translations
$_SERVER['REQUEST_URI'] = 'settings';
require_once "$docroot/webGui/include/Translations.php";
function host_lookup_ip($host) {
$result = @dns_get_record($host, DNS_A);
$ip = $result ? _var($result[0],'ip') : '';
return($ip);
}
function rebindDisabled() {
global $isLegacyCert;
$rebindtesturl = $isLegacyCert ? "rebindtest.unraid.net" : "rebindtest.myunraid.net";
// DNS Rebind Protection - this checks the server but clients could still have issues
$validResponse = ["192.168.42.42", "fd42"];
$response = host_lookup_ip($rebindtesturl);
return in_array(explode('::',$response)[0], $validResponse);
}
function format_port($port) {
return ($port != 80 && $port != 443) ? ':'.$port : '';
}
function anonymize_host($host) {
global $anon;
if ($anon) {
$host = preg_replace('/.*\.myunraid\.net/', '*.hash.myunraid.net', $host);
$host = preg_replace('/.*\.unraid\.net/', 'hash.unraid.net', $host);
}
return $host;
}
function anonymize_ip($ip) {
global $anon;
if ($anon && filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
$ip = "[redacted]";
}
return $ip;
}
function generate_internal_host($host, $ip) {
if (strpos($host,'.myunraid.net') !== false) {
$host = str_replace('*', str_replace('.', '-', $ip), $host);
}
return $host;
}
function generate_external_host($host, $ip) {
if (strpos($host,'.myunraid.net') !== false) {
$host = str_replace('*', str_replace('.', '-', $ip), $host);
} elseif (strpos($host,'.unraid.net') !== false) {
$host = "www.".$host;
}
return $host;
}
function verbose_output($httpcode, $result) {
global $cli, $verbose, $anon, $plgversion, $post, $var, $isRegistered, $myservers, $reloadNginx, $nginx, $isLegacyCert;
global $remoteaccess;
global $icon_warn, $icon_ok;
if (!$cli || !$verbose) return;
if ($anon) echo "(Output is anonymized, use '-vv' to see full details)".PHP_EOL;
echo "Unraid OS "._var($var,'version','???').((strpos($plgversion, "base-") === false) ? " with My Servers plugin version {$plgversion}" : '').PHP_EOL;
echo ($isRegistered) ? "{$icon_ok}Signed in to Unraid.net as {$myservers['remote']['username']}".PHP_EOL : "{$icon_warn}Not signed in to Unraid.net".PHP_EOL ;
echo "Use SSL is "._var($nginx,'NGINX_USESSL','No').PHP_EOL;
echo (rebindDisabled()) ? "{$icon_ok}Rebind protection is disabled" : "{$icon_warn}Rebind protection is enabled";
echo " for ".($isLegacyCert ? "unraid.net" : "myunraid.net").PHP_EOL;
if ($post) {
$wanip = trim(@file_get_contents("https://wanip4.unraid.net/"));
// check the data
$certhostname = _var($nginx,'NGINX_CERTNAME');
if ($certhostname) {
// $certhostname is $nginx['NGINX_CERTNAME'] (certificate_bundle.pem)
$certhostip = host_lookup_ip(generate_internal_host($certhostname, _var($post,'internalip')));
$certhosterr = ($certhostip != _var($post,'internalip'));
}
if (_var($post,'internalhostname') != $certhostname) {
// $post['internalhostname'] is $nginx['NGINX_LANMDNS'] (no cert, or Server_unraid_bundle.pem) || $nginx['NGINX_CERTNAME'] (certificate_bundle.pem)
$internalhostip = host_lookup_ip(generate_internal_host(_var($post,'internalhostname'), _var($post,'internalip')));
$internalhosterr = ($internalhostip != _var($post,'internalip'));
}
if (!empty($post['externalhostname'])) {
// $post['externalhostname'] is $nginx['NGINX_CERTNAME'] (certificate_bundle.pem)
$externalhostip = host_lookup_ip(generate_external_host($post['externalhostname'], $wanip));
$externalhosterr = ($externalhostip != $wanip);
}
// anonymize data. no caclulations can be done with this data beyond this point.
if ($anon) {
if (!empty($certhostip)) $certhostip = anonymize_ip($certhostip);
if (!empty($certhostname)) $certhostname = anonymize_host($certhostname);
if (!empty($internalhostip)) $internalhostip = anonymize_ip($internalhostip);
if (!empty($externalhostip)) $externalhostip = anonymize_ip($externalhostip);
if (!empty($wanip)) $wanip = anonymize_ip($wanip);
if (!empty($post['internalip'])) $post['internalip'] = anonymize_ip($post['internalip']);
if (!empty($post['internalhostname'])) $post['internalhostname'] = anonymize_host($post['internalhostname']);
if (!empty($post['externalhostname'])) $post['externalhostname'] = anonymize_host($post['externalhostname']);
if (!empty($post['externalport'])) $post['externalport'] = "[redacted]";
}
// always anonymize the keyfile
if (!empty($post['keyfile'])) $post['keyfile'] = "[redacted]";
// output notes
if (!empty($post['internalprotocol']) && !empty($post['internalhostname']) && !empty($post['internalport'])) {
$localurl = $post['internalprotocol']."://".generate_internal_host($post['internalhostname'], _var($post,'internalip')).format_port($post['internalport']);
echo 'Local Access url: '.$localurl.PHP_EOL;
if ($internalhostip) {
// $internalhostip will not be defined for .local domains, ok to skip
echo ($internalhosterr) ? $icon_warn : $icon_ok;
echo generate_internal_host($post['internalhostname'], _var($post,'internalip'))." resolves to {$internalhostip}";
echo ($internalhosterr) ? ", it should resolve to "._var($post,'internalip') : "";
echo PHP_EOL;
}
if ($certhostname) {
echo ($certhosterr) ? $icon_warn : $icon_ok;
echo generate_internal_host($certhostname, _var($post,'internalip')).' ';
echo ($certhostip) ? "resolves to {$certhostip}" : "does not resolve to an IP address";
echo ($certhosterr) ? ", it should resolve to "._var($post,'internalip') : "";
echo PHP_EOL;
}
if ($remoteaccess == 'yes' && !empty($post['externalprotocol']) && !empty($post['externalhostname']) && !empty($post['externalport'])) {
$remoteurl = $post['externalprotocol']."://".generate_external_host($post['externalhostname'], $wanip).format_port($post['externalport']);
echo 'Remote Access url: '.$remoteurl.PHP_EOL;
echo ($externalhosterr) ? $icon_warn : $icon_ok;
echo generate_external_host($post['externalhostname'], $wanip).' ';
echo ($externalhosterr) ? "does not resolve to an IP address" : "resolves to ".($externalhostip??'');
echo PHP_EOL;
}
if ($reloadNginx) {
echo "IP address changes were detected, nginx was reloaded".PHP_EOL;
}
}
// output post data
echo PHP_EOL.'Request:'.PHP_EOL;
echo @json_encode($post, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . PHP_EOL;
}
if ($result) {
echo "Response (HTTP $httpcode):".PHP_EOL;
$mutatedResult = is_array($result) ? json_encode($result) : $result;
echo @json_encode(@json_decode($mutatedResult, true), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . PHP_EOL;
}
}
/**
* @name response_complete
* @param {HTTP Response Status Code} $httpcode https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
* @param {String|Array} $result - strings are assumed to be encoded JSON. Arrays will be encoded to JSON.
* @param {String} $cli_success_msg
*/
function response_complete($httpcode, $result, $cli_success_msg='') {
global $cli, $verbose;
$mutatedResult = is_array($result) ? json_encode($result) : $result;
if ($cli) {
if ($verbose) verbose_output($httpcode, $result);
$json = @json_decode($mutatedResult,true);
if (!empty($json['error'])) {
echo 'Error: '.$json['error'].PHP_EOL;
exit(1);
}
exit($cli_success_msg.PHP_EOL);
}
header('Content-Type: application/json');
http_response_code($httpcode);
exit((string)$mutatedResult);
}
require_once "$docroot/webGui/include/Wrappers.php";
// This is a stub, does nothing but return success
my_logger("This is a stub and should not be called", "UpdateDNS");
$cli = php_sapi_name()=='cli';
$verbose = $anon = false;
if ($cli && ($argc > 1) && $argv[1] == "-v") {
$verbose = true;
$anon = true;
}
if ($cli && ($argc > 1) && $argv[1] == "-vv") {
$verbose = true;
}
$var = (array)@parse_ini_file('/var/local/emhttp/var.ini');
$nginx = (array)@parse_ini_file('/var/local/emhttp/nginx.ini');
$is69 = version_compare(_var($var,'version'),"6.9.9","<");
$reloadNginx = false;
$dnserr = false;
$icon_warn = "⚠️ ";
$icon_ok = "✅ ";
$myservers_flash_cfg_path='/boot/config/plugins/dynamix.my.servers/myservers.cfg';
$myservers = (array)@parse_ini_file($myservers_flash_cfg_path,true);
// ensure some vars are defined here so we don't have to test them later
if (empty($myservers['remote']['apikey'])) {
$myservers['remote']['apikey'] = "";
}
if (empty($myservers['remote']['wanaccess'])) {
$myservers['remote']['wanaccess'] = "no";
}
if (empty($myservers['remote']['wanport'])) {
$myservers['remote']['wanport'] = 443;
}
// remoteaccess, externalport
if ($cli) {
$remoteaccess = empty($nginx['NGINX_WANFQDN']) ? 'no' : 'yes';
$externalport = $myservers['remote']['wanport'];
} else {
$remoteaccess = _var($_POST,'remoteaccess','no');
$externalport = intval(_var($_POST,'externalport',443));
if ($remoteaccess != 'yes') {
$remoteaccess = 'no';
}
if ($externalport < 1 || $externalport > 65535) {
$externalport = 443;
}
if ($myservers['remote']['wanaccess'] != $remoteaccess) {
// update the wanaccess ini value
$orig = file_exists($myservers_flash_cfg_path) ? parse_ini_file($myservers_flash_cfg_path,true) : [];
if (!$orig) {
$orig = ['remote' => $myservers['remote']];
}
$orig['remote']['wanaccess'] = $remoteaccess;
$text = '';
foreach ($orig as $section => $block) {
$pairs = "";
foreach ($block as $key => $value) if (strlen($value)) $pairs .= "$key=\"$value\"\n";
if ($pairs) $text .= "[$section]\n".$pairs;
}
if ($text) file_put_contents($myservers_flash_cfg_path, $text);
// need nginx reload
$reloadNginx = true;
}
exit("success".PHP_EOL);
}
$isRegistered = !empty($myservers['remote']['username']);
// protocols, hostnames, ports
$internalprotocol = 'http';
$internalport = _var($nginx,'NGINX_PORT');
$internalhostname = _var($nginx,'NGINX_LANMDNS');
$externalprotocol = 'https';
// keyserver will expand *.hash.myunraid.net or add www to hash.unraid.net as needed
$externalhostname = _var($nginx,'NGINX_CERTNAME');
$isLegacyCert = preg_match('/.*\.unraid\.net$/', _var($nginx,'NGINX_CERTNAME'));
$isWildcardCert = preg_match('/.*\.myunraid\.net$/', _var($nginx,'NGINX_CERTNAME'));
$internalip = _var($nginx,'NGINX_LANIP');
if (_var($nginx,'NGINX_USESSL')=='yes') {
// When NGINX_USESSL is 'yes' in 6.9, it could be using either Server_unraid_bundle.pem or certificate_bundle.pem
// When NGINX_USESSL is 'yes' in 6.10, it is is using Server_unraid_bundle.pem
$internalprotocol = 'https';
$internalport = _var($nginx,'NGINX_PORTSSL');
if ($is69 && _var($nginx,'NGINX_CERTNAME')) {
// this is from certificate_bundle.pem
$internalhostname = _var($nginx,'NGINX_CERTNAME');
}
}
if (_var($nginx,'NGINX_USESSL')=='auto') {
// NGINX_USESSL cannot be 'auto' in 6.9, it is either 'yes' or 'no'
// When NGINX_USESSL is 'auto' in 6.10, it is using certificate_bundle.pem
$internalprotocol = 'https';
$internalport = _var($nginx,'NGINX_PORTSSL');
// keyserver will expand *.hash.myunraid.net as needed
$internalhostname = _var($nginx,'NGINX_CERTNAME');
}
// My Servers version
$plgversion = file_exists("/var/log/plugins/dynamix.unraid.net.plg") ? trim(exec('/usr/local/sbin/plugin version /var/log/plugins/dynamix.unraid.net.plg 2>/dev/null'))
: (file_exists("/var/log/plugins/dynamix.unraid.net.staging.plg") ? trim(exec('/usr/local/sbin/plugin version /var/log/plugins/dynamix.unraid.net.staging.plg 2>/dev/null'))
: 'base-'._var($var,'version'));
// only proceed when when signed in or when legacy unraid.net SSL certificate exists
if (!$isRegistered && !$isLegacyCert) {
response_complete(406, ['error' => _('Nothing to do')]);
}
// keyfile
$keyfile = empty($var['regFILE']) ? false : @file_get_contents($var['regFILE']);
if ($keyfile === false) {
response_complete(406, ['error' => _('Registration key required')]);
}
$keyfile = @base64_encode($keyfile);
// build post array
$post = [
'keyfile' => $keyfile,
'plgversion' => $plgversion
];
if ($isLegacyCert) {
// sign in not required to maintain local ddns for unraid.net cert
// enable local ddns regardless of use_ssl value
$post['internalip'] = $internalip;
// if host.unraid.net does not resolve to the internalip and DNS Rebind Protection is disabled, disable caching
if (host_lookup_ip(generate_internal_host(_var($nginx,'NGINX_CERTNAME'), $post['internalip'])) != $post['internalip'] && rebindDisabled()) $dnserr = true;
}
if ($isRegistered) {
// if signed in, send data needed to maintain My Servers Dashboard
$post['internalhostname'] = $internalhostname;
$post['internalport'] = $internalport;
$post['internalprotocol'] = $internalprotocol;
$post['remoteaccess'] = $remoteaccess;
$post['servercomment'] = _var($var,'COMMENT');
$post['servername'] = _var($var,'NAME');
if ($isWildcardCert) {
// keyserver needs the internalip to generate the local access url
$post['internalip'] = $internalip;
}
if ($remoteaccess == 'yes') {
// include wanip in the cache file so we can track if it changes
$post['_wanip'] = trim(@file_get_contents("https://wanip4.unraid.net/"));
$post['externalhostname'] = $externalhostname;
$post['externalport'] = $externalport;
$post['externalprotocol'] = $externalprotocol;
// if wanip.hash.myunraid.net or www.hash.unraid.net does not resolve to the wanip, disable caching
if (host_lookup_ip(generate_external_host($post['externalhostname'], $post['_wanip'])) != $post['_wanip']) $dnserr = true;
}
}
// if remoteaccess is enabled in 6.10.0-rc3+ and WANIP has changed since nginx started, reload nginx
if (_var($post,'_wanip') != _var($nginx,'NGINX_WANIP') && version_compare(_var($var,'version'),"6.10.0-rc2",">")) $reloadNginx = true;
// if remoteaccess is currently disabled (perhaps because a wanip was not available when nginx was started)
// BUT the system is configured to have it enabled AND a wanip is now available
// then reload nginx
if ($remoteaccess == 'no' && _var($nginx,'NGINX_WANACCESS') == 'yes' && !empty(trim(@file_get_contents("https://wanip4.unraid.net/")))) $reloadNginx = true;
if ($reloadNginx) {
exec("/etc/rc.d/rc.nginx reload &>/dev/null");
}
// maxage is 36 hours
$maxage = 36*60*60;
if ($dnserr || $verbose) $maxage = 0;
$datafile = "/tmp/UpdateDNS.txt";
$datafiletmp = "/tmp/UpdateDNS.txt.new";
$dataprev = @file_get_contents($datafile) ?: '';
$datanew = implode("\n",$post)."\n";
if ($datanew == $dataprev && (time()-filemtime($datafile) < $maxage)) {
response_complete(204, null, _('No change to report'));
}
file_put_contents($datafiletmp,$datanew);
rename($datafiletmp, $datafile);
// do not submit the wanip, it will be captured from the submission if needed for remote access
unset($post['_wanip']);
// report necessary server details to limetech for DNS updates
$ch = curl_init('https://keys.lime-technology.com/account/server/register');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ( ($result === false) || ($httpcode != "200") ) {
// delete cache file to retry submission on next run
@unlink($datafile);
response_complete($httpcode ?? "500", ['error' => $error]);
}
response_complete($httpcode, $result, _('success'));
header('Content-Type: application/json');
http_response_code(204);
exit(0);
?>
-125
View File
@@ -1,125 +0,0 @@
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, 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,
* as published by the Free Software Foundation.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
?>
<?
global $lv;
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Helpers.php";
require_once "$docroot/webGui/include/SysDriversHelpers.php";
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
// add translations
$_SERVER['REQUEST_URI'] = 'tools';
require_once "$docroot/webGui/include/Translations.php";
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt.php";
function macbyte($val) {
if ($val < 16)
return '0'.dechex($val);
return dechex($val);
}
$arrEntries = [];
$vms = $lv->get_domains() ?:[];
sort($vms,SORT_NATURAL);
foreach($vms as $vm){
$arrEntries['VM'][$vm]['interfaces'] = $lv->get_nic_info($vm);
$arrEntries['VM'][$vm]['name'] = $vm;
}
$DockerClient = new DockerClient();
$containers = $DockerClient->getDockerJSON("/containers/json?all=1");
foreach($containers as $ct)
$arrEntries['Docker'][substr($ct["Names"][0],1)] = [
'interfaces' => ['0 '=> ['mac' => isset($ct["NetworkSettings"]["Networks"]["bridge"]["MacAddress"]) ? $ct["NetworkSettings"]["Networks"]["bridge"]["MacAddress"] : ""]],
'name' => substr($ct["Names"][0],1),
];
$lxc = explode("\n",shell_exec("lxc-ls -1")) ;
$lxcpath = trim(shell_exec("lxc-config lxc.lxcpath"));
foreach ($lxc as $lxcname) {
if ($lxcname == "") continue;
$value = explode("=",shell_exec("cat $lxcpath/$lxcname/config | grep 'hwaddr'"));
$arrEntries['LXC'][$lxcname]['interfaces'][0]['mac'] = trim($value[1]);
$arrEntries['LXC'][$lxcname]['name'] = $lxcname;
}
if (is_file("/boot/config/wol.json")) $user_mac = json_decode(file_get_contents("/boot/config/wol.json"),true); else $user_mac = [];
foreach($arrEntries as $key => $data) {
$type=$key;
foreach($data as $data2){
$name=$data2['name'];
if (isset($user_mac[$type][$name])) {
$name=$name;
$arrEntries[$type][$name]['enable'] = $user_mac[$type][$name]['enable'];
$arrEntries[$type][$name]['user_mac'] = strtolower($user_mac[$type][$name]['user_mac']);
} else {
$arrEntries[$type][$name]['enable'] = 'enable';
$arrEntries[$type][$name]['user_mac'] = 'None Defined';
}
}
}
switch ($_POST['table']) {
case 't1load':
$arrMacs = $arrEntries;
$html = "<thead><tr><th>"._('Service')."</th><th>"._('Name')."</th><th>"._('Mac Address')."</th><th>"._('Enabled')."</th><th>"._('User Mac Address')."</th></tr></thead>";
$html .= "<tbody>";
ksort($arrMacs);
foreach($arrMacs as $systype => $m) {
foreach($m as $macaddr) {
if ($systype == "") continue;
$html .= "<tr id='row$systype'>";
$macs = "";
foreach($macaddr['interfaces'] as $intdetail)
{
$macs .= " {$intdetail['mac']}" ;
}
$html .= "<td>$systype</td>";
$selecttypename="enable;".$systype.";".$macaddr['name'];
$mactypename=htmlspecialchars("user_mac;".$systype.";".$macaddr['name']);
$mactypeid=htmlspecialchars("user_mac".$systype."".$macaddr['name']);
$user_mac_str = '<input type="text" name="'.$mactypename.'" id="'.$mactypeid.'" class="narrow" value="'.htmlspecialchars($macaddr['user_mac']).'" title="'._("random mac, you can supply your own").'" /><a><i onclick="maccreate(\''.$mactypeid.'\')" class="fa fa-refresh mac_generate" title="re-generate random mac address"></i></a>';
$html .= "<td>{$macaddr['name']}</td><td id=\"status$systype\">$macs</td><td>";
$html .="<select name='$selecttypename' class='audio narrow'>";
$html .= mk_option($macaddr["enable"] , "disable", _("Disabled"));
$html .= mk_option($macaddr["enable"] , "enable", _("Enabled"));
$html .= mk_option($macaddr["enable"] , "shutdown", _("Enabled and Shutdown"));
$html .= "</select></td><td>".$user_mac_str."</td></tr>";
$text = "";
}
}
if (count($arrMacs) < 1) {
$html .= "<tr id='row'>";
$html .= "<td></td><td></td><td>"._("No Entries")."</td><td></td><td></td></tr>";
}
$html .= "</tbody>";
$rtn = array();
$rtn['html'] = $html;
echo json_encode($rtn);
break;
case "macaddress":
$seed = 1;
$prefix = '62:00:00';
$prefix .=':'.macbyte(($seed * rand()) % 256).':'.macbyte(($seed * rand()) % 256).':'.macbyte(($seed * rand()) % 256);
echo json_encode(['mac' => $prefix]);
break;
}
?>
-180
View File
@@ -1,180 +0,0 @@
#!/usr/bin/php
<?php
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
require_once "$docroot/webGui/include/Helpers.php";
require_once "$docroot/webGui/include/Custom.php";
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt.php";
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
function getContainerStats($container, $option) {
exec("lxc-info " . $container, $content);
foreach($content as $index => $string) {
if (strpos($string, $option) !== FALSE)
return trim(explode(':', $string)[1]);
}
}
$mac = strtolower($argv[1]);
$libvirtd_running = is_file('/var/run/libvirt/libvirtd.pid') ;
$dockerd_running = is_file('/var/run/dockerd.pid');
$lxc_ls_exist = is_file('/usr/bin/lxc-ls');
#$RUNDOCKER = $RUNLXC = $RUNVM = true;
extract(parse_ini_file("/boot/config/wol.cfg")) ;
if (!isset($RUNLXC)) $RUNLXC = "y";
if (!isset($RUNVM)) $RUNVM = "y";
if (!isset($RUNDocker)) $RUNDocker = "y";
if (!isset($RUNSHUT)) $RUNSHUT = "n";
$arrEntries = [] ;
if ($libvirtd_running && $RUNVM == "y") {
$vms = $lv->get_domains();
sort($vms,SORT_NATURAL);
foreach($vms as $vm){
$arrEntries['VM'][$vm]['interfaces'] = $lv->get_nic_info($vm);
$arrEntries['VM'][$vm]['name'] = $vm;
}
}
if ($dockerd_running && $RUNDOCKER == "y") {
$DockerClient = new DockerClient();
$containers = $DockerClient->getDockerJSON("/containers/json?all=1");
foreach($containers as $container)
$arrEntries['Docker'][ substr($container["Names"][0],1) ] = [
'interfaces' => ['0' => ['mac' => isset($container["NetworkSettings"]["Networks"]["bridge"]["MacAddress"]) ? $container["NetworkSettings"]["Networks"]["bridge"]["MacAddress"]:""]],
'name' => substr($container["Names"][0],1),
'state' => $container["State"],
];
}
if ($lxc_ls_exist && $RUNLXC == "y") {
$lxc = explode("\n",shell_exec("lxc-ls -1")) ;
$lxcpath = trim(shell_exec("lxc-config lxc.lxcpath"));
foreach ($lxc as $lxcname) {
if ($lxcname == "") continue;
$values = explode("=",shell_exec("cat $lxcpath/$lxcname/config | grep 'hwaddr'"));
$arrEntries['LXC'][$lxcname]['interfaces'][0]['mac'] = trim($values[1]);
$arrEntries['LXC'][$lxcname]['name'] = $lxcname;
}
}
if (is_file("/boot/config/wol.json")) $user_mac = json_decode(file_get_contents("/boot/config/wol.json"),true); else $user_mac = [];
foreach($arrEntries as $typekey => $typedata)
{
foreach($typedata as $typeEntry){
$name=$typeEntry['name'];
if (isset($user_mac[$typekey][$name])) {
$name=$name;
$arrEntries[$typekey][$name]['enable'] = $user_mac[$typekey][$name]['enable'];
$arrEntries[$typekey][$name]['user_mac'] = strtolower($user_mac[$typekey][$name]['user_mac']);
} else {
$arrEntries[$typekey][$name]['enable'] = "enable";
$arrEntries[$typekey][$name]['user_mac'] = 'None Defined';
}
}
}
$mac_list=[];
foreach($arrEntries as $type => $detail)
{
foreach($detail as $name => $entryDetail)
{
foreach($entryDetail['interfaces'] as $interfaces)
{
$interfaces['mac'] = strtolower($interfaces['mac']);
if($interfaces['mac'] == "" && $entryDetail['user_mac'] == "None Defined") continue;
if (isset($entryDetail['state'])) $state = $entryDetail['state']; else $state = "";
if (isset($entryDetail['enable']) && !$entryDetail['enable'] ) $enable = false; else $enable = true;
if ($entryDetail['user_mac'] != "None Defined") {
$mac_list[$entryDetail['user_mac']] = [
'type' => $type,
'name' => $name,
'state' => $state,
'enable' => $entryDetail['enable'],
];
}
if ($interfaces['mac'] != "") {
$mac_list[$interfaces['mac']] = [
'type' => $type,
'name' => $name,
'state' => $state,
'enable' => $entryDetail['enable'],
];
}
}
}
}
$found = array_key_exists($mac,$mac_list);
if ($found && $mac_list[$mac]['enable'] != "disable") {
echo _("Found"). " " . $mac . " " .$mac_list[$mac]['type'] . " " . $mac_list[$mac]['name'];
switch ($mac_list[$mac]['type']) {
case "VM":
if ($libvirtd_running && $RUNVM == "y") {
$res = $lv->get_domain_by_name($mac_list[$mac]['name']);
$dom = $lv->domain_get_info($res);
$state = $lv->domain_state_translate($dom['state']);
switch ($state) {
case 'running':
if ($RUNSHUT == "y" && $mac_list[$mac]['enable'] == "shutdown") $lv->domain_shutdown("{$mac_list[$mac]['name']}");
break;
case 'paused':
case 'pmsuspended':
$lv->domain_resume("{$mac_list[$mac]['name']}");
break;
default:
$lv->domain_start("{$mac_list[$mac]['name']}");
}
}
break;
case "LXC":
if ($lxc_ls_exist && $RUNLXC == "y") {
$state = getContainerStats($mac_list[$mac]['name'], "State");
switch ($state) {
case 'RUNNING':
if ($RUNSHUT == "y" && $mac_list[$mac]['enable'] == "shutdown") shell_exec("lxc-stop {$mac_list[$mac]['name']}");
break;
case 'FROZEN':
shell_exec("lxc-unfreeze {$mac_list[$mac]['name']}");
break;
default:
shell_exec("lxc-start {$mac_list[$mac]['name']}");
}
}
break;
case "Docker":
if ($dockerd_running && $RUNDOCKER == "y") {
switch ($mac_list[$mac]['state']) {
case "running":
if ($RUNSHUT == "y" && $mac_list[$mac]['enable'] == "shutdown") shell_exec("docker stop {$mac_list[$mac]['name']}");
break;
case "exited":
case "created":
shell_exec("docker start {$mac_list[$mac]['name']}");
break;
case "paused":
shell_exec("docker unpause {$mac_list[$mac]['name']}");
}
}
break;
}
} else {
if ($mac_list[$mac]['enable'] == "disable") echo $mac . " " . _(" has not been actioned as set to disabled");
else echo _("Not Found"). " " . $mac . " " . _("ignoring or Maybe actions disabled for type(Docker/VM/LXC)");
}
?>
@@ -149,4 +149,56 @@ function my_date($fmt, $time) {
function my_logger($message, $logger='webgui') {
exec('logger -t '.escapeshellarg($logger).' -- '.escapeshellarg($message));
}
// Original PHP code by Chirp Internet: www.chirpinternet.eu
// Please acknowledge use of this code by including this header.
// https://www.the-art-of-web.com/php/http-get-contents/
// Modified for Unraid
/**
* Fetches URL and returns content
* @param string $url The URL to fetch
* @param array $opts Array of options to pass to curl_setopt()
* @param array $getinfo Empty array passed by reference, will contain results of curl_getinfo and curl_error
* @return string|false $out The fetched content
*/
function http_get_contents(string $url, array $opts = [], array &$getinfo = NULL) {
$ch = curl_init();
if(isset($getinfo)) {
curl_setopt($ch, CURLINFO_HEADER_OUT, TRUE);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
curl_setopt($ch, CURLOPT_TIMEOUT, 45);
curl_setopt($ch, CURLOPT_ENCODING, "");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_REFERER, "");
curl_setopt($ch, CURLOPT_FAILONERROR, true);
if(is_array($opts) && $opts) {
foreach($opts as $key => $val) {
curl_setopt($ch, $key, $val);
}
}
$out = curl_exec($ch);
if(isset($getinfo)) {
$getinfo = curl_getinfo($ch);
}
if (curl_errno($ch)) {
$msg = curl_error($ch) . " {$url}";
if(isset($getinfo)) {
$getinfo['error'] = $msg;
}
my_logger($msg, "http_get_contents");
}
return $out;
}
/**
* Detect network connectivity via Network Connectivity Status Indicator
* @return bool
*/
function check_network_connectivity(): bool {
$url = 'http://www.msftncsi.com/ncsi.txt';
$out = http_get_contents($url);
return ($out=="Microsoft NCSI");
}
?>
@@ -39,4 +39,8 @@ if ($_SERVER['SCRIPT_NAME'] != '/login.php' && $_SERVER['SCRIPT_NAME'] != '/auth
if ($var['csrf_token'] != $_POST['csrf_token']) csrf_terminate("wrong");
unset($_POST['csrf_token']);
}
$proxy_cfg = (array)@parse_ini_file('/var/local/emhttp/proxy.ini',true);
putenv('http_proxy='.((array_key_exists('http_proxy', $proxy_cfg)) ? $proxy_cfg['http_proxy'] : ''));
putenv('https_proxy='.((array_key_exists('https_proxy', $proxy_cfg)) ? $proxy_cfg['https_proxy'] : ''));
putenv('no_proxy='.((array_key_exists('http_proxy', $proxy_cfg)) ? $proxy_cfg['no_proxy'] : ''));
?>
@@ -13,6 +13,7 @@
<?
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Helpers.php";
require_once "$docroot/webGui/include/Wrappers.php";
// add translations
$_SERVER['REQUEST_URI'] = 'settings';
@@ -425,11 +426,10 @@ case 'public':
$ip = _var($_POST,'#ip');
$v4 = _var($_POST,'#prot')!='6';
$v6 = _var($_POST,'#prot')!='';
$context = stream_context_create(['https'=>['timeout'=>12]]);
$int_ipv4 = $v4 ? (preg_match("/^$validIP4$/",$ip) ? $ip : (@dns_get_record($ip,DNS_A)[0]['ip'] ?: '')) : '';
$ext_ipv4 = $v4 ? (@file_get_contents('https://wanip4.unraid.net',false,$context) ?: '') : '';
$ext_ipv4 = $v4 ? (http_get_contents('https://wanip4.unraid.net') ?: '') : '';
$int_ipv6 = $v6 ? (preg_match("/^$validIP6$/",$ip) ? $ip : (@dns_get_record($ip,DNS_AAAA)[0]['ipv6'] ?: '')) : '';
$ext_ipv6 = $v6 ? (@file_get_contents('https://wanip6.unraid.net',false,$context) ?: '') : '';
$ext_ipv6 = $v6 ? (http_get_contents('https://wanip6.unraid.net') ?: '') : '';
echo "$int_ipv4;$ext_ipv4;$int_ipv6;$ext_ipv6";
break;
case 'addtunnel':
+1 -1
View File
@@ -78,7 +78,7 @@ function device_info(&$disk,$online) {
$help .= "<br>"._("Click to spin $action device");
}
$status = "<a class='info'><i ".($ctrl?"id='dev-$named' ":"")."class='fa fa-$orb orb $color-orb'$ctrl></i><span>$help</span></a>";
$link = (($parity || $data || $pool) && !str_contains($disk_status,'_NP')) || $name=='flash' || in_array($name,$pools) || $type=='New'
$link = (($parity || $data || $pool) && $disk_status!='DISK_NP') || $name=='flash' || in_array($name,$pools) || $type=='New'
? "<a href=\"".htmlspecialchars("/Main/Settings/$source?name=$name")."\">$fancy</a>"
: $fancy;
return $view.$status.$link;
+6 -4
View File
@@ -20,10 +20,12 @@ require_once "$docroot/webGui/include/publish.php";
while (true) {
$echo = shell_exec("$notify get");
$md5_new = md5($echo,true);
if ($md5_new !== $md5_old) {
publish('notify', $echo);
$md5_old = $md5_new;
if ( $echo ) {
$md5_new = md5($echo,true);
if ($md5_new !== $md5_old) {
publish('notify', $echo);
$md5_old = $md5_new;
}
}
sleep(3);
}
+91
View File
@@ -0,0 +1,91 @@
#!/usr/bin/php -q
<?PHP
/* Copyright 2005-2024, Lime Technology
* Copyright 2024-2024, Simon Fairweather.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
?>
<?
$docroot = '/usr/local/emhttp';
$varroot = '/var/local/emhttp';
$md5_old = -1;
require_once "$docroot/webGui/include/Helpers.php";
require_once "$docroot/webGui/include/publish.php";
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
global $vmusagestats;
exec("/etc/rc.d/rc.libvirt status >/dev/null",$dummy,$libvirtd);
$libvirtd = $libvirtd==0;
if (!$libvirtd) return;
extract(parse_plugin_cfg('dynamix',true));
get_vm_usage_stats();
sleep(1);
// add translations
$_SERVER['REQUEST_URI'] = 'dashboard';
$login_locale = _var($display,'locale');
require_once "$docroot/webGui/include/Translations.php";
// remember current language
$locale_init = $locale;
function update_translation($locale) {
global $docroot,$language;
$language = [];
if ($locale) {
$text = "$docroot/languages/$locale/translations.txt";
if (file_exists($text)) {
$store = "$docroot/languages/$locale/translations.dot";
if (!file_exists($store)) file_put_contents($store,serialize(parse_lang_file($text)));
$language = unserialize(file_get_contents($store));
}
$text = "$docroot/languages/$locale/dashboard.txt";
if (file_exists($text)) {
$store = "$docroot/languages/$locale/dashboard.dot";
if (!file_exists($store)) file_put_contents($store,serialize(parse_lang_file($text)));
$language = array_merge($language,unserialize(file_get_contents($store)));
}
}
}
$domain_cfgfile = "/boot/config/domain.cfg";
$domain_cfg = parse_ini_file($domain_cfgfile);
if (isset($domain_cfg['USAGE']) && $domain_cfg['USAGE'] != 'Y' ) return;
if (!isset($domain_cfg['USAGETIMER'])) $timer = 3 ; else $timer = $domain_cfg['USAGETIMER'];
while (true) {
extract(parse_plugin_cfg('dynamix',true));
if (_var($display,'locale') != $locale_init) {
$locale_init = _var($display,'locale');
update_translation($locale_init);
}
get_vm_usage_stats();
$echo = [];
foreach ($vmusagestats as $vm => $vmdata) {
if ($vmdata['state'] == 1) {
$vmencode = str_replace(" "," ",$vm);
$vmencode = $lv->domain_get_uuid($vm);
$echo[$vmencode ]['gcpu'] = "<span class='advanced'>"._("Guest CPU").": <span class='cpug-".$vm."'>".$vmdata['cpuguest']."%</span><div class='usage-disk mm'><span id='cpug-".$vm."' style='width:".$vmdata['cpuguest']."%;'></span><span></span></div></span>";
$echo[$vmencode ]['hcpu'] = "<span class='advanced'>"._("Host CPU").": <span class='cpug-".$vm."'>".$vmdata['cpuhost']."%</span><div class='usage-disk mm'><span id='cpug-".$vm."' style='width:".$vmdata['cpuhost']."%;'></span><span></span></div></span>";
$echo[$vmencode ]['mem'] .= "<span>Mem: ".my_scale($vmdata['mem'],$unit)."$unit / ".my_scale($vmdata['maxmem'],$unit)."$unit</span>";
$echo[$vmencode ]['disk'] .= "<span>Disk: "._("Rd").": ".my_scale($vmdata['rdrate'],$unit)."$unit/s "._("Wr").": ".my_scale($vmdata['wrrate'],$unit)."$unit/s</span>";
$echo[$vmencode ]['net'] .= "<span>Net: "._("RX").": ".my_scale($vmdata['rxrate'],$unit)."$unit/s "._("TX").": ".my_scale($vmdata['txrate'],$unit)."$unit/s</span>";
}
}
$echo = json_encode($echo);
$md5_new = md5($echo,true);
if ($md5_new !== $md5_old) {
$md5_old = publish('vm_dashusage',$echo)!==false ? $md5_new : -1;
}
sleep($timer);
}
?>
-93
View File
@@ -1,93 +0,0 @@
#!/bin/bash
#
# script: WOL_action
#
# Startup script for unraidwold
#
# Simon Fairweather - Initial Script October 2023
DAEMON="unraidwold"
BINARY="/usr/local/bin/unraidwold"
# run & log functions
. /etc/rc.d/rc.runlog
. /boot/config/wol.cfg
unraidwold_running(){
sleep 0.1
ps axc | grep -q ' unraidwold'
}
unraidwold_start(){
log "Starting $DAEMON..."
local REPLY
if unraidwold_running; then
REPLY="Already started"
else
nohup $BINARY $1 $2 $3 $4 $5 $6 > /dev/null &
fi
log "$DAEMON... $REPLY."
}
unraidwold_stop(){
log "Stopping $DAEMON..."
local REPLY
if ! unraidwold_running; then
REPLY="Already stopped"
else
killall -TERM $DAEMON
if ! unraidwold_running; then REPLY="Stopped"; else REPLY="Failed"; fi
fi
log "$DAEMON... $REPLY."
}
unraidwold_status(){
if unraidwold_running; then
echo "$DAEMON is currently running."
else
echo "$DAEMON is not running."
exit 1
fi
}
unraidwold_load()
{
if unraidwold_running; then
unraidwold_stop
fi
sleep 1
if [ "$WOLENABLED" == "yes" ]; then
interfacemode=""
logoptions=""
if [ "$IFMODE" == "y" ]; then
interfacemode="--promiscuous"
fi
if [ "$LOGFILE" != "syslog" ]; then
logoptions="--log $LOGFILE"
fi
unraidwold_start --interface $INTERFACE $interfacemode $logoptions
fi
}
case "$1" in
'start')
unraidwold_start $2 $3 $4 $5 $6
;;
'stop')
unraidwold_stop
;;
'status')
unraidwold_status
;;
'load')
unraidwold_load
;;
*)
echo "Usage: $BDAEMON start|stop|restart|status"
exit 1
esac
exit 0
+8 -10
View File
@@ -25,6 +25,7 @@ $zip = $all ? ($argv[2]??'') : ($argv[1]??'');
$cli = empty($zip);
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Helpers.php";
require_once "$docroot/webGui/include/Wrappers.php";
$folders = ['/boot','/boot/config','/boot/config/plugins','/boot/syslinux','/var/log','/var/log/plugins','/boot/extra','/var/log/packages','/var/lib/pkgtools/packages','/tmp'];
@@ -115,16 +116,6 @@ function maskIP($file) {
// anonymize full IPv6 addresses
run("sed -ri 's/([\"\[ ]([0-9a-f]{1,4}:){4})(([0-9a-f]{1,4}:){3}|:)([0-9a-f]{1,4})([/\" .]|$)/\\1XXXX:XXXX:XXXX:\\5\\6/g' ".escapeshellarg($file)." 2>/dev/null");
}
function cache_only($disk) {
return _var($disk,'type')=='Cache';
}
function cache_filter($disks) {
return array_filter($disks,'cache_only');
}
function pools_filter($disks) {
return array_unique(array_map('prefix',array_keys(cache_filter($disks))));
}
function download_url($url, $path="", $bg=false, $timeout=15) {
$ch = curl_init();
curl_setopt_array($ch,[
@@ -661,6 +652,13 @@ if (file_exists($dhcplog)) {
if (!$all) maskIP($log);
}
// copy phplog
$phplog = "/var/log/phplog";
if (file_exists($phplog)) {
$log = "/$diag/logs/phplog.txt";
run("todos <$phplog >".escapeshellarg($log));
}
// copy graphql-api.log
$graphql = "/var/log/graphql-api.log";
if (file_exists($graphql)) {
@@ -35,7 +35,7 @@ if [[ -n $local_server ]]; then
sed -ri "\$a\\\$InputUDPServerBindRuleset remote\n\\\$UDPServerRun ${server_port:-514}" $ETC
[[ $server_protocol == udp ]] && sed -ri 's/^(\$ModLoad imtcp)/#\1/;/^\$InputTCPServerBindRuleset remote$/d;/^\$InputTCPServerRun [0-9]+$/d' $ETC
fi
sed -ri "/^\\\$template remote,.*$/d;/^#\\\$UDPServerRun [0-9]+.*$/a\\\$template remote,\"${server_folder:-/mnt/user/system}/syslog-%FROMHOST-IP%.log\"" $ETC
sed -ri "/^\\\$template remote,.*$/d;/^#\\\$UDPServerRun [0-9]+.*$/a\\\$template remote,\"${server_folder:-/mnt/user/system}/${server_filename:-syslog-%FROMHOST-IP%.log}\"" $ETC
else
sed -ri '/^\$RuleSet remote$/d;/^\$FileOwner nobody$/d;/^\$FileGroup users$/d;/^\$FileCreateMode 06[46][46]$/d;/^\$IncludeConfig \/etc\/rsyslog\.d\/\*\.conf # remote$/d;/^\*\.\* \?remote$/d;/^\$template remote,".*"$/d;/^\$Input(TCP|UDP)ServerBindRuleset remote$/d;/^\$(InputTCP|UDP)ServerRun [0-9]+$/d;s/^#?\$(ModLoad imtcp|ModLoad imudp)/#\$\1/' $ETC
fi
+5 -3
View File
@@ -1,7 +1,7 @@
#!/usr/bin/php -q
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
/* Copyright 2005-2024, Lime Technology
* Copyright 2012-2024, 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,
@@ -21,6 +21,7 @@ $disks = (array)@parse_ini_file("/var/local/emhttp/disks.ini",true);
require_once "$docroot/webGui/include/CustomMerge.php";
$script = "$docroot/webGui/scripts/notify";
// this command will set the $notify array
extract(parse_plugin_cfg("dynamix",true));
$output = _var($notify,'report');
$server = strtoupper(_var($var,'NAME','tower'));
@@ -178,7 +179,8 @@ $warn = ($error0 || $error3) ? "alert" : (($error1 || $error2) ? "warning" : "no
$stat = $warn=="normal" ? "[PASS]" : "[FAIL]";
$info = "Array has $size disk".($size==1 ? "" : "s").($parity ? " ({$word}parity".($pools ? " & pools)" : ")") : ($pools ? " ({$word}pools)" : ""));
$message = implode('\n', $data);
exec("$script -s ".escapeshellarg("Notice [$server] - array health report $stat")." -d ".escapeshellarg("$info")." -m ".escapeshellarg("$message")." -i ".escapeshellarg("$warn $output")." -l '/Main'");
$subject = "Notice [$server] - array health report $stat";
exec("$script -s ".escapeshellarg($subject)." -d ".escapeshellarg("$info")." -m ".escapeshellarg("$message")." -i ".escapeshellarg("$warn $output")." -l '/Main'");
exit(0);
?>
-11
View File
@@ -1,11 +0,0 @@
table#t1{margin-top:0;font-family:clear-sans}
table#t1 thead tr th{font-weight:bold}
table#t1 tbody tr td{padding:4px 20px 4px 0;margin:0;text-align:left;white-space:normal}
table#t1 tbody tr td:nth-child(1){width:10%}
table#t1 tbody tr td:nth-child(2){width:30%}
table#t1 tbody tr td:nth-child(3){width:15%}
table#t1 tbody tr td:nth-child(4){width:20%}
table#t1 tbody tr td:nth-child(5){width:25%;padding-right:0}
table.t1.tablesorter .filtered{display:none}
.tablesorter-header-inner{font-family:clear-sans;font-weight:bold}
#macform .mac_generate{cursor:pointer;margin-left:-5px;color:#08C;font-size:1.3rem;transform:translate(0px, 2px)}
@@ -122,7 +122,9 @@ table.unraid thead tr:first-child>td{font-size:1.2rem;text-transform:uppercase;l
table.unraid tbody tr:not(.tr_last):hover>td{background-color:rgba(0,0,0,0.05)}
table.unraid tr>td{overflow:hidden;text-overflow:ellipsis;padding-left:8px}
table.unraid tr>td:hover{overflow:visible}
table.legacy{table-layout:auto}
table.legacy{table-layout:auto!important}
table.legacy thead td{line-height:normal;height:auto;padding:7px 0}
table.legacy tbody td{line-height:normal;height:auto;padding:5px 0}
table.disk_status{table-layout:fixed}
table.disk_status tr>td:last-child{padding-right:8px}
table.disk_status tr>td:nth-child(1){width:13%}
@@ -120,7 +120,9 @@ table.unraid tbody tr:nth-child(even){background-color:#212121}
table.unraid tbody tr:not(.tr_last):hover>td{background-color:rgba(255,255,255,0.1)}
table.unraid tr>td{overflow:hidden;text-overflow:ellipsis;padding-left:8px}
table.unraid tr>td:hover{overflow:visible}
table.legacy{table-layout:auto}
table.legacy{table-layout:auto!important}
table.legacy thead td{line-height:normal;height:auto;padding:7px 0}
table.legacy tbody td{line-height:normal;height:auto;padding:5px 0}
table.disk_status{table-layout:fixed}
table.disk_status tr>td:last-child{padding-right:8px}
table.disk_status tr>td:nth-child(1){width:13%}
@@ -122,7 +122,9 @@ table.unraid thead tr:first-child>td{font-size:1.2rem;text-transform:uppercase;l
table.unraid tbody tr:not(.tr_last):hover>td{background-color:rgba(255,255,255,0.05)}
table.unraid tr>td{overflow:hidden;text-overflow:ellipsis;padding-left:8px}
table.unraid tr>td:hover{overflow:visible}
table.legacy{table-layout:auto}
table.legacy{table-layout:auto!important}
table.legacy thead td{line-height:normal;height:auto;padding:7px 0}
table.legacy tbody td{line-height:normal;height:auto;padding:5px 0}
table.disk_status{table-layout:fixed}
table.disk_status tr>td:last-child{padding-right:8px}
table.disk_status tr>td:nth-child(1){width:13%}
@@ -120,7 +120,9 @@ table.unraid tbody tr:nth-child(even){background-color:#ededed}
table.unraid tbody tr:not(.tr_last):hover>td{background-color:rgba(0,0,0,0.1)}
table.unraid tr>td{overflow:hidden;text-overflow:ellipsis;padding-left:8px}
table.unraid tr>td:hover{overflow:visible}
table.legacy{table-layout:auto}
table.legacy{table-layout:auto!important}
table.legacy thead td{line-height:normal;height:auto;padding:7px 0}
table.legacy tbody td{line-height:normal;height:auto;padding:5px 0}
table.disk_status{table-layout:fixed}
table.disk_status tr>td:last-child{padding-right:8px}
table.disk_status tr>td:nth-child(1){width:13%}
@@ -1,4 +1,4 @@
.jGrowl{position:fixed;font-size:1.3rem}
.jGrowl{position:fixed;font-size:1.3rem;z-index:10001}
.jGrowl.top-left{left:10px;top:90px}
.jGrowl.top-right{right:10px;top:90px}
.jGrowl.bottom-left{left:10px;bottom:24px}
@@ -1,4 +1,4 @@
.jGrowl{position:fixed;font-size:1.3rem}
.jGrowl{position:fixed;font-size:1.3rem;z-index:10001}
.jGrowl.top-left{left:10px;top:130px}
.jGrowl.top-right{right:10px;top:130px}
.jGrowl.bottom-left{left:10px;bottom:24px}
@@ -1,4 +1,4 @@
.jGrowl{position:fixed;font-size:1.3rem}
.jGrowl{position:fixed;font-size:1.3rem;z-index:10001}
.jGrowl.top-left{left:10px;top:90px}
.jGrowl.top-right{right:10px;top:90px}
.jGrowl.bottom-left{left:10px;bottom:24px}
@@ -1,4 +1,4 @@
.jGrowl{position:fixed;font-size:1.3rem}
.jGrowl{position:fixed;font-size:1.3rem;z-index:10001}
.jGrowl.top-left{left:10px;top:130px}
.jGrowl.top-right{right:10px;top:130px}
.jGrowl.bottom-left{left:10px;bottom:24px}