mirror of
https://github.com/unraid/webgui.git
synced 2026-01-01 15:10:19 -06:00
271 lines
9.0 KiB
PHP
271 lines
9.0 KiB
PHP
<?PHP
|
|
/* Copyright 2005-2025, Lime Technology
|
|
* Copyright 2012-2025, 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.
|
|
*/
|
|
?>
|
|
<?
|
|
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
|
|
|
// pool name ending in any of these => zfs subpool
|
|
$subpools = ['special','logs','dedup','cache','spares'];
|
|
|
|
// ZFS subpool name separator and replacement
|
|
$_tilde_ = '~';
|
|
$_proxy_ = '__';
|
|
$_arrow_ = '»';
|
|
|
|
// Wrapper functions
|
|
function file_put_contents_atomic($filename,$data) {
|
|
while (true) {
|
|
$suffix = rand();
|
|
if ( ! is_file("$filename$suffix") )
|
|
break;
|
|
}
|
|
$renResult = false;
|
|
$writeResult = @file_put_contents("$filename$suffix",$data) === strlen($data);
|
|
if ( $writeResult )
|
|
$renResult = @rename("$filename$suffix",$filename);
|
|
if ( ! $writeResult || ! $renResult ) {
|
|
my_logger("File_put_contents_atomic failed to write / rename $filename");
|
|
@unlink("$filename$suffix");
|
|
return false;
|
|
}
|
|
return strlen($data);
|
|
}
|
|
|
|
// custom parse_ini_file/string functions to deal with '#' comment lines and remove html/php tags
|
|
function my_parse_ini_string($text, $sections=false, $scanner=INI_SCANNER_NORMAL) {
|
|
return parse_ini_string(strip_tags(html_entity_decode(preg_replace('/^#.*$/m','',$text))),$sections,$scanner);
|
|
}
|
|
|
|
function my_parse_ini_file($file, $sections=false, $scanner=INI_SCANNER_NORMAL) {
|
|
return my_parse_ini_string(file_get_contents($file),$sections,$scanner);
|
|
}
|
|
|
|
function parse_plugin_cfg($plugin, $sections=false, $scanner=INI_SCANNER_NORMAL) {
|
|
global $docroot;
|
|
$ram = "$docroot/plugins/$plugin/default.cfg";
|
|
$rom = "/boot/config/plugins/$plugin/$plugin.cfg";
|
|
$cfg = file_exists($ram) ? my_parse_ini_file($ram, $sections, $scanner) : [];
|
|
return file_exists($rom) ? array_replace_recursive($cfg, my_parse_ini_file($rom, $sections, $scanner)) : $cfg;
|
|
}
|
|
|
|
function parse_cron_cfg($plugin, $job, $text = "") {
|
|
$cron = "/boot/config/plugins/$plugin/$job.cron";
|
|
if ($text) file_put_contents($cron, $text); else @unlink($cron);
|
|
exec("/usr/local/sbin/update_cron");
|
|
}
|
|
|
|
function agent_fullname($agent, $state) {
|
|
switch ($state) {
|
|
case 'enabled' : return "/boot/config/plugins/dynamix/notifications/agents/$agent";
|
|
case 'disabled': return "/boot/config/plugins/dynamix/notifications/agents-disabled/$agent";
|
|
default : return $agent;
|
|
}
|
|
}
|
|
|
|
function get_plugin_attr($attr, $file) {
|
|
global $docroot;
|
|
exec("$docroot/plugins/dynamix.plugin.manager/scripts/plugin ".escapeshellarg($attr)." ".escapeshellarg($file), $result, $error);
|
|
if ($error===0) return $result[0];
|
|
}
|
|
|
|
function plugin_update_available($plugin, $os=false) {
|
|
$local = get_plugin_attr('version', "/var/log/plugins/$plugin.plg");
|
|
$remote = get_plugin_attr('version', "/tmp/plugins/$plugin.plg");
|
|
if ($remote && strcmp($remote,$local)>0) {
|
|
if ($os) return $remote;
|
|
if (!$unraid = get_plugin_attr('Unraid', "/tmp/plugins/$plugin.plg")) return $remote;
|
|
$server = get_plugin_attr('version', "/var/log/plugins/unRAIDServer.plg");
|
|
if (version_compare($server, $unraid, '>=')) return $remote;
|
|
}
|
|
}
|
|
|
|
function _var(&$name, $key=null, $default='') {
|
|
return is_null($key) ? ($name ?? $default) : ($name[$key] ?? $default);
|
|
}
|
|
|
|
function celsius($temp) {
|
|
return round(($temp-32)*5/9);
|
|
}
|
|
|
|
function fahrenheit($temp) {
|
|
return round(9/5*$temp)+32;
|
|
}
|
|
|
|
function displayTemp($temp) {
|
|
global $display;
|
|
return (is_numeric($temp) && _var($display,'unit')=='F') ? fahrenheit($temp) : $temp;
|
|
}
|
|
|
|
function get_value(&$name, $key, $default) {
|
|
global $var;
|
|
$value = $name[$key] ?? -1;
|
|
return $value!==-1 ? $value : ($var[$key] ?? $default);
|
|
}
|
|
|
|
function get_ctlr_options(&$type, &$disk) {
|
|
if (!$type) return;
|
|
$ports = [];
|
|
if (isset($disk['smPort1'])) $ports[] = $disk['smPort1'];
|
|
if (isset($disk['smPort2'])) $ports[] = $disk['smPort2'];
|
|
if (isset($disk['smPort3'])) $ports[] = $disk['smPort3'];
|
|
$type .= ($ports ? ','.implode($disk['smGlue'] ?? ',',$ports) : '');
|
|
}
|
|
|
|
function port_name($port) {
|
|
return substr($port,-2)!='n1' ? $port : substr($port,0,-2);
|
|
}
|
|
|
|
function exceed($value, $limit, $top=100) {
|
|
return is_numeric($value) && $limit>0 ? ($value>$limit && $value<=$top) : false;
|
|
}
|
|
|
|
function ipaddr($ethX='eth0', $prot=4) {
|
|
global $$ethX;
|
|
switch (_var($$ethX,'PROTOCOL:0')) {
|
|
case 'ipv4':
|
|
return _var($$ethX,'IPADDR:0');
|
|
case 'ipv6':
|
|
return _var($$ethX,'IPADDR6:0');
|
|
case 'ipv4+ipv6':
|
|
switch ($prot) {
|
|
case 4: return _var($$ethX,'IPADDR:0');
|
|
case 6: return _var($$ethX,'IPADDR6:0');
|
|
default:return [_var($$ethX,'IPADDR:0'),_var($$ethX,'IPADDR6:0')];}
|
|
default:
|
|
return _var($$ethX,'IPADDR:0');
|
|
}
|
|
}
|
|
|
|
function no_tilde($name) {
|
|
global $_tilde_ ,$_proxy_;
|
|
return str_replace($_tilde_,$_proxy_,$name);
|
|
}
|
|
|
|
function prefix($key) {
|
|
return preg_replace('/\d+$/','',$key);
|
|
}
|
|
|
|
function pool_name($key) {
|
|
return preg_replace('/(\d+$|~.*$)/', '', $key);
|
|
}
|
|
|
|
function native($name, $full=0) {
|
|
global $_tilde_, $_arrow_;
|
|
switch ($full) {
|
|
case 0: return str_replace($_tilde_," $_arrow_ ",$name);
|
|
case 1: return strpos($name,$_tilde_)!==false ? "$_arrow_ ".explode($_tilde_,$name)[1] : $name;
|
|
}
|
|
}
|
|
|
|
function isSubpool($name) {
|
|
global $subpools, $_tilde_;
|
|
$subpool = my_explode($_tilde_,$name)[1];
|
|
return in_array($subpool,$subpools) ? $subpool : false;
|
|
}
|
|
|
|
function get_nvme_info($device, $info) {
|
|
switch ($info) {
|
|
case 'temp':
|
|
exec("nvme id-ctrl /dev/$device 2>/dev/null | grep -Pom2 '^[wc]ctemp +: \K\d+'",$temp);
|
|
return [$temp[0]-273, $temp[1]-273];
|
|
case 'cctemp':
|
|
return exec("nvme id-ctrl /dev/$device 2>/dev/null | grep -Pom1 '^cctemp +: \K\d+'")-273;
|
|
case 'wctemp':
|
|
return exec("nvme id-ctrl /dev/$device 2>/dev/null | grep -Pom1 '^wctemp +: \K\d+'")-273;
|
|
case 'state':
|
|
$state = exec("nvme get-feature /dev/$device -f2 2>/dev/null | grep -Pom1 'value:.+\K.$'");
|
|
return exec("nvme id-ctrl /dev/$device 2>/dev/null | grep -Pom1 '^ps +$state : mp:\K\S+ \S+'");
|
|
case 'power':
|
|
$state = exec("nvme get-feature /dev/$device -f2 2>/dev/null | grep -Pom1 'value:.+\K.$'");
|
|
return exec("smartctl -c /dev/$device 2>/dev/null | grep -Pom1 '^ *$state [+-] +\K[^W]+'");
|
|
}
|
|
}
|
|
|
|
// convert strftime to date format
|
|
function my_date($fmt, $time) {
|
|
$legacy = ['%c' => 'D j M Y h:i A','%A' => 'l','%Y' => 'Y','%B' => 'F','%e' => 'j','%d' => 'd','%m' => 'm','%I' => 'h','%H' => 'H','%M' => 'i','%S' => 's','%p' => 'a','%R' => 'H:i', '%F' => 'Y-m-d', '%T' => 'H:i:s'];
|
|
return date(strtr($fmt,$legacy), $time);
|
|
}
|
|
|
|
// ensure params passed to logger are properly escaped
|
|
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);
|
|
curl_setopt($ch, CURLOPT_USERAGENT, 'Unraid');
|
|
if(is_array($opts) && $opts) {
|
|
foreach($opts as $key => $val) {
|
|
curl_setopt($ch, $key, $val);
|
|
}
|
|
}
|
|
$out = curl_exec($ch);
|
|
if (curl_errno($ch) == 23) {
|
|
// error 23 detected, try CURLOPT_ENCODING = "deflate"
|
|
curl_setopt($ch, CURLOPT_ENCODING, "deflate");
|
|
$out = curl_exec($ch);
|
|
}
|
|
if (isset($getinfo)) {
|
|
$getinfo = curl_getinfo($ch);
|
|
}
|
|
if ($errno = curl_errno($ch)) {
|
|
$msg = "Curl error $errno: " . (curl_error($ch) ?: curl_strerror($errno)) . ". Requested url: '$url'";
|
|
if(isset($getinfo)) {
|
|
$getinfo['error'] = $msg;
|
|
}
|
|
my_logger($msg, "http_get_contents");
|
|
}
|
|
curl_close($ch);
|
|
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");
|
|
}
|
|
|
|
function lan_port($port, $state=false) {
|
|
$system = '/sys/class/net';
|
|
$exist = file_exists("$system/$port");
|
|
return !$state ? $exist : ($exist ? file_get_contents("$system/$port/carrier") : false);
|
|
}
|
|
?>
|