Skip to content
Snippets Groups Projects
welcome-html.lsp 21.3 KiB
Newer Older
Tony Bonnin's avatar
Tony Bonnin committed
<% local view, viewlibrary, page_info, session = ... %>
<% htmlviewfunctions = require("htmlviewfunctions") %>
<% html = require("acf.html") %>
<% json = require("json") %>
<% local sys = viewlibrary.dispatch_component("alpine-baselayout/health/system", nil, true) %>
<% local proc = viewlibrary.dispatch_component("alpine-baselayout/health/proc", nil, true) %>
TEST's avatar
TEST committed
<% local api = viewlibrary.dispatch_component("alpine-baselayout/health/api", nil, true) %>
Tony Bonnin's avatar
Tony Bonnin committed
<% local disk = viewlibrary.dispatch_component("alpine-baselayout/health/storage", nil, true) %>
<% local net = viewlibrary.dispatch_component("alpine-baselayout/health/network", nil, true) %>
<% local netstats = viewlibrary.dispatch_component("alpine-baselayout/health/networkstats", nil, true) %>

<% 
-- PROTECT HOSTNAME WITH SESSION
Tony Bonnin's avatar
Tony Bonnin committed
	local hostname = ""
	if session.userinfo and session.userinfo.userid and viewlibrary and viewlibrary.dispatch_component then
Tony Bonnin's avatar
Tony Bonnin committed
	local result = viewlibrary.dispatch_component("alpine-baselayout/hostname/read", nil, true)
Tony Bonnin's avatar
Tony Bonnin committed
		if result and result.value then
			hostname = result.value
		end
Tony Bonnin's avatar
Tony Bonnin committed
	end

-- CHECK SYS RELEASE VERSION
TEST's avatar
TEST committed
	local check_sysver = string.match(sys.value.version.value, "%d+.%d+.%d+") -- Check Local System Version
Tony Bonnin's avatar
Tony Bonnin committed
	local major_sysver = string.match(check_sysver, "%d+") -- Parse Major for Upgrade
	local minor_sysver = string.gsub(string.match(check_sysver, "%p%d+"), "%D", "") -- Parse Minor for Update
	local patch_sysver = string.gsub(string.match(check_sysver, ".[^.]*$"), "%D", "") -- Parse Patch for Update
	
-- CHECK DIST RELEASE VERSION
	local check_distver = (sys.value.alpinever.value) -- Get All Versions from Alpine Linux Official Website
	local actual_distver = string.match(string.match(check_distver, "version\":\"%d+.%d+.%d+"), "%d+.%d+.%d+") -- Get Last Version
	local major_distver = string.match(actual_distver, "%d+") -- Parse Major for Upgrade
	local minor_distver = string.gsub(string.match(actual_distver, "%p%d+"), "%D", "") -- Parse Minor for Update
	local patch_distver = string.gsub(string.match(actual_distver, ".[^.]*$"), "%D", "") -- Parse Patch for Fix
	if major_sysver == major_distver and minor_sysver == minor_distver and patch_sysver == patch_distver then
	   blockcolor = "<div class='data-block data-system system-uptodate'>"
	   chkres = "<a id='alpine-version-link' class='version-link version-ok' href='https://www.alpinelinux.org/releases/#content' title='🟩 Up to Date' target='_blank'><span class='version-check'>Up To Date | Alpine <span class='version-number-uptodate'>" .. check_sysver .. "</span></span></a>"
Tony Bonnin's avatar
Tony Bonnin committed
	else
TEST's avatar
TEST committed
		blockcolor = "<div class='data-block data-system system-update'>"
		chkres = "<a id='alpine-version-link' class='version-link version-update' href='https://www.alpinelinux.org/releases/#content' title='🟧 Update Needed' target='_blank'><span class='version-check'>Update Needed | Alpine <span class='version-number-update'>" .. check_sysver .. "</span></span></a>"
Tony Bonnin's avatar
Tony Bonnin committed
		kernres = "<i class='fa-solid fa-exclamation icon-kernel-warn'></i>"
Tony Bonnin's avatar
Tony Bonnin committed
	end
	if major_sysver ~= major_distver then
TEST's avatar
TEST committed
		blockcolor = "<div class='data-block data-system system-upgrade'>"
		chkres = "<a id='alpine-version-link' class='version-link version-upgrade' href='https://www.alpinelinux.org/releases/#content' title='🟥 Upgrade Needed' target='_blank'><span class='version-check'>Upgrade Required | Alpine <span class='version-number-upgrade'>" .. check_sysver .. "</span></span></a>"
Tony Bonnin's avatar
Tony Bonnin committed
		kernres = "<i class='fa-solid fa-xmark icon-kernel-err'></i>"
Tony Bonnin's avatar
Tony Bonnin committed
	end
	
-- GET DIST VERSION CHANGES
	local get_verchanges = string.match(sys.value.alpineposts.value, "[%p?%d?.%d?.%d?]+%p?".. actual_distver .."[%p?%d?.%d?.%d?]+")
Tony Bonnin's avatar
Tony Bonnin committed
	
-- FORMAT UPTIME	
	local up_time = math.floor(string.match(sys.value.uptime.value, "[%d]+"))
Tony Bonnin's avatar
Tony Bonnin committed
	local up_centuries = math.floor((up_time / (3600*24) / 365) / 100)
	local up_years = math.floor((up_time / (3600*24) / 365) % 100)
Tony Bonnin's avatar
Tony Bonnin committed
	local up_mounths = math.floor((((up_time / (3600 * 24)) % 365) % 365) / 30)
	local up_days = math.floor((((up_time / (3600 * 24)) % 365) % 365) % 30)
	local up_hours = string.format("%02d", math.floor((up_time % (3600 * 24)) / 3600))
	local up_minutes = string.format("%02d", math.floor(((up_time % (3600 * 24)) % 3600) / 60))
	local up_seconds = string.format("%02d", math.floor(((up_time % (3600 * 24)) % 3600) % 60))
Tony Bonnin's avatar
Tony Bonnin committed
-- CONVERT & DISPLAY UPTIME UP TO CENTURIES
Tony Bonnin's avatar
Tony Bonnin committed
	local uptime = up_centuries .. " Centuries " .. up_years .. " Years " .. up_mounths .. " Mounths " .. up_days .. " Days " .. up_hours .. "h " .. up_minutes .. "m " .. up_seconds .. "s"	
	if up_centuries == 1 then
		uptime = up_centuries .. " Century " .. up_years .. " Year " .. up_mounths .. " Mounths " .. up_days .. " Days " .. up_hours .. "h " .. up_minutes .. "m " .. up_seconds .. "s"
	elseif up_centuries == 0 then
		uptime =  up_years .. " Years " .. up_mounths .. " Mounths " .. up_days .. " Days " .. up_hours .. "h " .. up_minutes .. "m " .. up_seconds .. "s"
	end
Tony Bonnin's avatar
Tony Bonnin committed
	if up_years == 1 then
		uptime = up_years .. " Year " .. up_mounths .. " Mounths " .. up_days .. " Days " .. up_hours .. "h " .. up_minutes .. "m " .. up_seconds .. "s"
	elseif up_years == 0 then
		uptime = up_mounths .. " Mounths " .. up_days .. " Days " .. up_hours .. "h " .. up_minutes .. "m " .. up_seconds .. "s"
	end	
	if up_mounths == 1 then
		uptime = up_mounths .. " Mounth " .. up_days .. " Days " .. up_hours .. "h " .. up_minutes .. "m " .. up_seconds .. "s"
	elseif up_years == 0 and up_mounths == 0 then
		uptime = up_days .. " Days " .. up_hours .. "h " .. up_minutes .. "m " .. up_seconds .. "s"	
	end
	if up_days == 1 then
		uptime = up_days .. " Day " .. up_hours .. "h " .. up_minutes .. "m " .. up_seconds .. "s"
	elseif up_years == 0 and up_mounths == 0 and up_days == 0 then
		uptime = up_hours .. "h " .. up_minutes .. "m " .. up_seconds .. "s"	
	end
	
Tony Bonnin's avatar
Tony Bonnin committed
-- REPLACE O.E.M DEFAULT STRING
Tony Bonnin's avatar
Tony Bonnin committed
	function oem_parse(str)
		return (string.gsub(str, "To be filled by O.E.M." or "Not Specified", "Standard PC")) 
	end		
Tony Bonnin's avatar
Tony Bonnin committed
	function version_parse(str)
Tony Bonnin's avatar
Tony Bonnin committed
		return (string.gsub(str, "To be filled by O.E.M." or "Not Specified", "Unknow")) 
Tony Bonnin's avatar
Tony Bonnin committed
-- GET INTERFACES
Tony Bonnin's avatar
Tony Bonnin committed
	local interfaces = {}
	for intf in pairs(netstats.value) do table.insert(interfaces, intf) end
	table.sort(interfaces)

Tony Bonnin's avatar
Tony Bonnin committed
-- FORMAT BYTES	
function bytesToSize(bytes)
	kilobyte = 1000;
	megabyte = kilobyte * 1000;
	gigabyte = megabyte * 1000;
	terabyte = gigabyte * 1000;
Tony Bonnin's avatar
Tony Bonnin committed
  if((bytes >= 0) and (bytes < kilobyte)) then
    return math.floor(bytes) .. " Bytes";
  elseif((bytes >= kilobyte) and (bytes < megabyte)) then
    return math.floor( bytes / kilobyte) .. ' KB';
  elseif((bytes >= megabyte) and (bytes < gigabyte)) then
    return math.floor( bytes / megabyte) .. ' MB';
  elseif((bytes >= gigabyte) and (bytes < terabyte)) then
    return string.format("%.2f", bytes / gigabyte) .. ' GB';
  elseif(bytes >= terabyte) then
    return string.format("%.2f", bytes / terabyte) .. ' TB';
  else
    return math.floor(bytes) .. ' B';
  end
end

Tony Bonnin's avatar
Tony Bonnin committed
-- FORMAT OCTETS
function blocksToSize(octets)
	kilooctet = 1000;
	megaoctet = kilooctet * 1000;
	gigaoctet = megaoctet * 1000;
	teraoctet = gigaoctet * 1000;
  if((octets >= 0) and (octets < kilooctet)) then
    return math.floor(octets) .. " Octets";
  elseif((octets >= kilooctet) and (octets < megaoctet)) then
    return math.floor( octets / kilooctet) .. ' Ko';
  elseif((octets >= megaoctet) and (octets < gigaoctet)) then
    return math.floor( octets / megaoctet) .. ' Mo';
  elseif((octets >= gigaoctet) and (octets < teraoctet)) then
    return string.format("%.2f", octets / gigaoctet) .. ' Go';
  elseif(octets >= teraoctet) then
    return string.format("%.2f", octets / teraoctet) .. ' To';
Tony Bonnin's avatar
Tony Bonnin committed
  else
Tony Bonnin's avatar
Tony Bonnin committed
    return math.floor(octets) .. ' o';
Tony Bonnin's avatar
Tony Bonnin committed
  end
end
Tony Bonnin's avatar
Tony Bonnin committed
%>

<% local header_level = htmlviewfunctions.displaysectionstart(cfe({label="Dashboard"}), page_info) %>

<!-- Dashboard App Block - LINE 1 -->
<div class="dashboard-main main-block">
TEST's avatar
TEST committed

Tony Bonnin's avatar
Tony Bonnin committed
<!-- Dashboard Version Block - BLOCK 1 -->
Tony Bonnin's avatar
Tony Bonnin committed
	<div class="dashboard-system dashboard-block">
TEST's avatar
TEST committed
		<%= blockcolor %>
Tony Bonnin's avatar
Tony Bonnin committed
			<h4 class="dashboard-block-title dashboard-title-system">System</h4>
TEST's avatar
TEST committed
				<span class="icon-os"></span> 
Tony Bonnin's avatar
Tony Bonnin committed
				<p class="dashboard-infos dash-info-version">
TEST's avatar
TEST committed
					<%= chkres %>
Tony Bonnin's avatar
Tony Bonnin committed
					<span class="check-version">
					 <a class="version-link version-external-link" href="https://www.alpinelinux.org/posts/Alpine<%= get_verchanges %>released.html#content" title="🔗 https://www.alpinelinux.org/posts/Alpine<%= get_verchanges %>released.html#content" target="_blank">Last Release : <%= actual_distver %></a><br>
Tony Bonnin's avatar
Tony Bonnin committed
					 </span>
TEST's avatar
TEST committed
					<span class="kernel-ver">Kernel @ <%= sys.value.kernel.value %> | ACF - <%= sys.value.luaver.value %></span>
Tony Bonnin's avatar
Tony Bonnin committed
				</p>
		</div>
TEST's avatar
TEST committed
		
<!-- Dashboard Hardware Block - 2 -->
		<div class="data-block data-hardware">
Tony Bonnin's avatar
Tony Bonnin committed
			<h4 class="dashboard-block-title dashboard-title-hardware">Hardware</h4>
TEST's avatar
TEST committed
			<span class="icon-cpu">
Tony Bonnin's avatar
Tony Bonnin committed
					<% if string.find((proc.value.model.value), "Intel") then
TEST's avatar
TEST committed
						print ("<canvas class='icon-canvas-dash icon-intel'>''</canvas>")
Tony Bonnin's avatar
Tony Bonnin committed
					elseif string.find((proc.value.model.value), "AMD") then
TEST's avatar
TEST committed
						print ("<canvas class='icon-canvas-dash icon-amd'>''</canvas>")
Tony Bonnin's avatar
Tony Bonnin committed
					else
TEST's avatar
TEST committed
						print ("<canvas class='icon-canvas-dash icon-arm'>''</canvas>")
Tony Bonnin's avatar
Tony Bonnin committed
					end %>
				</span>
TEST's avatar
TEST committed
			<p class="dashboard-infos">
			<span class="data-title">Board</span>
Tony Bonnin's avatar
Tony Bonnin committed
			<%
Tony Bonnin's avatar
Tony Bonnin committed
			-- EXEMPLE TO PARSE KNOW MOBO MODELS OR YOUR OWN ONE
			if string.match(sys.value.boardVendor.value, "ASUSTeK COMPUTER INC.") then
				print ("<span>" .. string.gsub(sys.value.boardVendor.value, "ASUSTeK COMPUTER INC.", "ASUS"))
				print (" | " .. sys.value.boardName.value .. " | ")
				print (version_parse(string.gsub(sys.value.boardVersion.value, "^", "")))
			-- AAEON EMB-H81B
			elseif string.match(sys.value.boardName.value, "EMB%-H81B") then
TEST's avatar
TEST committed
				print ("<span>" .. string.gsub(sys.value.boardVendor.value, "To be filled by O.E.M." or "Not Specified", "AAEON"))
				print (" | " .. sys.value.boardName.value .. " | ")
				print (string.gsub(sys.value.boardVersion.value, "To be filled by O.E.M." or "Not Specified" or "Unknow", "Rev: 2.00") .. "</span>")
			-- AAEON EMB-Q87A
			elseif string.match(sys.value.boardName.value, "EMB%-Q87A") then
				print ("<span>" .. string.gsub(sys.value.boardVendor.value, "To be filled by O.E.M." or "Not Specified" or "Unknow", "AAEON"))
				print (" | " .. sys.value.boardName.value .. " | ")
				print (string.gsub(sys.value.boardVersion.value, "To be filled by O.E.M." or "Not Specified" or "Unknow", "Rev: 2.00") .. "</span>")
Tony Bonnin's avatar
Tony Bonnin committed
			-- ELSE REWRITE ALL OTHERS
			else
				print ("<span>" .. oem_parse(sys.value.boardVendor.value))
				print (" | " .. oem_parse(sys.value.boardName.value) .. " | ")
				print (version_parse(string.gsub(sys.value.boardVersion.value, "^", "Rev : ")))
Tony Bonnin's avatar
Tony Bonnin committed
			end
			%>
Tony Bonnin's avatar
Tony Bonnin committed
			</p>
Tony Bonnin's avatar
Tony Bonnin committed
			<p class="dashboard-infos dash-info-cpu" style="cursor: pointer;" onclick="window.open('/cgi-bin/acf/alpine-baselayout/health/proc', '_blank')" >
TEST's avatar
TEST committed
				<span class="data-title">CPU</span><%= string.sub((proc.value.model.value), 14) %>
Tony Bonnin's avatar
Tony Bonnin committed
			</p>
Tony Bonnin's avatar
Tony Bonnin committed
			<p class="dashboard-infos dash-info-memory" style="cursor: pointer;" onclick="window.open('/cgi-bin/acf/alpine-baselayout/health/proc', '_blank')" >
TEST's avatar
TEST committed
				<span class="data-title">Memory</span>
					<%= string.gsub(bytesToSize(tonumber(sys.value.memory.totalData)), ".%d+%w+", "") %> Total |
					<%= bytesToSize(tonumber(sys.value.memory.freeData)) %> Free | 
					<%= bytesToSize(tonumber(sys.value.memory.usedData)) %> Used 
TEST's avatar
TEST committed
			</p>	
		</div>
		
<!-- Dashboard Monitoring Block - 3 -->
		<div class="data-block data-monitoring">
			<h4 class="dashboard-block-title dashboard-title-system-uptime">Monitoring</h4>
			<span class="icon-trinity"></span>
			<p class="dashboard-infos">
			<span class="data-title">Uptime</span>
				<span id="uptime" class="uptime">
				 <%= uptime %><br>
<script type="application/javascript">
// IMPORT UPTIME FOR JS LIVE TIMER
	if(window.location.href.indexOf("welcome/read") > -1){
	let increment = <%= up_time or "unknow"%>;
	let delay = () => 
	{
	increment += 1;
	// CONVERT JS UPTIME
		var js_uptime = parseInt(increment);
		var js_centuries = Math.floor((js_uptime / (3600*24) / 365) / 100);
		var js_years = Math.floor((js_uptime / (3600*24) / 365) % 100);
		var js_mounths = Math.floor((((js_uptime / (3600 * 24)) % 365) % 365) / 30);
		var js_days = Math.floor((((js_uptime / (3600 * 24)) % 365) % 365) % 30)
		var js_hours = Math.floor(js_uptime % (3600*24) / 3600);
		var js_minutes = Math.floor(js_uptime % 3600 / 60);
		var js_seconds = Math.floor(js_uptime % 60);
	// FORMAT JS UPTIME UP TO CENTURIES
		var centuries_display = js_centuries > 0 ? js_centuries + (js_centuries <= 1 ? " Century " : " Centuries ") : "";
		var years_display = js_years > 0 ? js_years + (js_years <= 1 ? " Year " : " Years ") : "";
		var mounths_display = js_mounths > 0 ? js_mounths + (js_mounths <= 1 ? " Mounth " : " Mounths ") : "";
		var days_display = js_days > 0 ? js_days + (js_days <= 1 ? " Day " : " Days ") : "";
		var hours_display = js_hours < 10 ? "0" + js_hours + "h " : js_hours + "h ";
		var minutes_display = js_minutes < 10 ? "0" + js_minutes + "m " : js_minutes + "m ";
		var secondes_display = js_seconds < 10 ? "0" + js_seconds + "s" : js_seconds + "s";
	// RETURN JS FORMATED TIME
		return centuries_display + years_display + mounths_display + days_display + hours_display + minutes_display + secondes_display;	
	};
	// JS FORMATED TIME LIVE COUNT
		setInterval(() => document.getElementById("uptime").innerHTML = delay(), 1000);
	};
</script>
		</span>
		</p>
		
		<p class="dashboard-infos">
			<span class="data-title">System Temp</span>
			<a href='javascript:void(0);' id='toggle-degree' title='Celsius to Fahrenheit' onclick='toggleDegree()'>
TEST's avatar
TEST committed
				<span id="cpuTemp" class="dash-monitoring-temp">			
				<%
			if ((tonumber(api.value.cpuTemp.value)) ~= nil) and ((tonumber(api.value.cpuTemp.value)) < 50000) then
			print (math.ceil(tonumber(api.value.boardTemp.value / 1000))  .. " °C  &nbsp; | " .. "<span class='normal'>" .. math.floor(tonumber(api.value.cpuTemp.value / 1000)) .. " °C</span>")
TEST's avatar
TEST committed
			elseif ((tonumber(api.value.cpuTemp.value)) ~= nil) and ((tonumber(api.value.cpuTemp.value)) >= 50000) then
			print (math.ceil(tonumber(api.value.boardTemp.value / 1000))  .. " °C  &nbsp; | " .. "<span class='medium'>" .. math.floor(tonumber(api.value.cpuTemp.value / 1000)) .. " °C</span>")
TEST's avatar
TEST committed
			elseif((tonumber(api.value.cpuTemp.value)) ~= nil) and ((tonumber(api.value.cpuTemp.value)) >= 75000) then
			print (math.ceil(tonumber(api.value.boardTemp.value / 1000))  .. " °C  &nbsp; | " .. "<span class='hot'>" .. math.floor(tonumber(api.value.cpuTemp.value / 1000)) .. " °C</span>")
Tony Bonnin's avatar
Tony Bonnin committed
			else
TEST's avatar
TEST committed
			print ("<span class='nan'>N/A<span>")
Tony Bonnin's avatar
Tony Bonnin committed
			end
			%>
			
			<script type="application/javascript" defer>
			// CONVERT TEMP TO FAHRENHEIT
			if (((<%= tonumber(api.value.cpuTemp.value) %>) < 50000) && (window.localStorage.getItem('toggle-degree') === 'fahrenheit')) {
					document.getElementById("cpuTemp").innerHTML = ((Math.ceil(((<%= tonumber(api.value.boardTemp.value) %>) / 1000) * 9 / 5) + 32) + " °F  &nbsp; | <span class='normal'>" + (Math.floor(((<%= tonumber(api.value.cpuTemp.value) %>) / 1000) * 9 / 5) + 32)) + " °F</span>";
				} else if (((<%= tonumber(api.value.cpuTemp.value) %>) >= 50000) && (window.localStorage.getItem('toggle-degree') === 'fahrenheit')) {
					document.getElementById("cpuTemp").innerHTML = ((Math.ceil(((<%= tonumber(api.value.boardTemp.value) %>) / 1000) * 9 / 5) + 32) + " °F  &nbsp; | <span class='medium'>" + (Math.floor(((<%= tonumber(api.value.cpuTemp.value) %>) / 1000) * 9 / 5) + 32)) + " °F</span>";
				} else if (((<%= tonumber(api.value.cpuTemp.value) %>) >= 75000) && (window.localStorage.getItem('toggle-degree') === 'fahrenheit')) {
					document.getElementById("cpuTemp").innerHTML = ((Math.ceil(((<%= tonumber(api.value.boardTemp.value) %>) / 1000) * 9 / 5) + 32) + " °F  &nbsp; | <span class='hot'>" + (Math.floor(((<%= tonumber(api.value.cpuTemp.value) %>) / 1000) * 9 / 5) + 32)) + " °F</span>";
				}
			</script>
			
TEST's avatar
TEST committed
				</span>
TEST's avatar
TEST committed
		</p>
		
		<p class="dashboard-infos">
			<span class="data-title">IP</span>
				<span class="value-title value-net-local"><%= net.value.wanIP.value %>  &nbsp; via &nbsp; <%= netstats.value.br0.ipaddr %></span>
Tony Bonnin's avatar
Tony Bonnin committed
		</div>
	</div>
TEST's avatar
TEST committed
<!-- Dashboard App Block - LINE 1 -->
</div>

<!-- Dashboard App Block - LINE 2 -->
<div class="dashboard-main main-block">

<!-- Dashboard CPU Block - 1 -->
		<div class="data-block data-cpu">
			<h4 class="dashboard-block-title dashboard-title-cpu-stats">CPU Temp</h4>
			<!-- Dashboard Main Block - NETWORK CHART.JS -->	
			<canvas id="chartCpuTemp" class="data-chart block-chart"></canvas>
		</div>
		
<!-- Dashboard Memory Block - 2 -->		
		<div class="data-block data-memory">
			<h4 class="dashboard-block-title dashboard-title-memory-stats">Memory Usage</h4>
			<!-- Dashboard Main Block - NETWORK CHART.JS -->	
			<canvas id="chartMemUsed" class="data-chart block-chart"></canvas>
		</div>
<!-- Dashboard App Block - LINE 2 -->
</div>

<!-- Dashboard App Block - LINE 3 -->
<div class="dashboard-main main-block">
<!-- Dashboard Main Block - SYSTEM - BLOCK 1 -->
	<div class="disk-list">
		<%
				local fdisk_output = sys.value.drivelist.value
-- Function to parse fdisk output and detect disks
function detect_disks(fdisk_output)
    local disks = {}
    for disk_name in fdisk_output:gmatch("Disk /dev/(sd%a):") do
        table.insert(disks, "/dev/" .. disk_name)
    end
    return disks
end
TEST's avatar
TEST committed

-- Function to parse fdisk output
function parse_fdisk_output(output)
    local disk_info = {}
    -- Initialize variables to store disk geometry and partitions
    local geometry = {}
    local partitions = {}
TEST's avatar
TEST committed

    -- Flags to track when to start capturing geometry and partitions
    local capture_geometry = false
    local capture_partitions = false

    -- Split the output into lines
    for line in output:gmatch("[^\r\n]+") do
        -- Start capturing geometry when 'Disk /dev/' is encountered
        if line:match("^Disk%s/dev/(sd%a):") then
            capture_geometry = true
        end

        -- Start capturing partitions when 'Device' is encountered
        if line:match("^Device") then
            capture_partitions = true
        end

        -- Capture disk geometry
        if capture_geometry then
            local disk_size = line:match("Disk /dev/sd%a: (%S+ %a+)")
            if disk_size then
                geometry.disk_size = ("<span class='disk-size'>" .. disk_size .. "</span>")
            end

            local sector_size = line:match("Sector size %(logical/physical%): (%d+)/(%d+)")
            if sector_size then
                geometry.logical_sector_size = tonumber(sector_size)
            end

            local total_sectors = line:match("total (%d+) sectors")
            if total_sectors then
                geometry.total_sectors = tonumber(total_sectors)
            end
TEST's avatar
TEST committed
			
			local disk_model = line:match("Disk model: (.+)")
            if disk_model then
                geometry.disk_model = disk_model
            end

            local heads_cylinders_sectors = line:match("(%d+) heads, (%d+) sectors/track, (%d+) cylinders")
            if heads_cylinders_sectors then
                geometry.heads = tonumber(heads_cylinders_sectors:match("(%d+)"))
                geometry.sectors_per_track = tonumber(heads_cylinders_sectors:match(", (%d+)"))
                geometry.cylinders = tonumber(heads_cylinders_sectors:match(", (%d+)$"))
            end
        end

-- Capture partition information
if capture_partitions then
    -- Extracting information from each line
    local partition_device, start_sector, end_sector, sectors, size, partition_type, name = line:match("^%s*([^%s]+)%s+(%d+)%s+(%d+)%s+(%d+)%s+([%d%.]+%s*[A-Za-z]+)%s+(%w+)%s+(.*)$")

    if partition_device then
        local partition = {
            device = partition_device,
            start_sector = tonumber(start_sector),
            end_sector = tonumber(end_sector),
            size = size,
            type = partition_type,
            name = name
        }
        
        table.insert(partitions, partition)
    else
        -- Print unmatched lines for debugging
        print()
    end
end
end

    -- Store geometry and partitions in disk_info table
    disk_info.geometry = geometry
    disk_info.partitions = partitions

    return disk_info
end
-- Detect disks
local disks = detect_disks(fdisk_output)

-- Iterate over each disk
for _, disk in ipairs(disks) do
    print("<div class='disk-block disk-" .. disk:gsub("/dev/", "") .. "-block'>")
    print("Parsing disk:", disk)
    print("--------------------")
	 
    -- Execute fdisk command for the disk and store the output in a variable
    local fdisk_output_disk = io.popen("fdisk -l " .. disk):read("*a")
	
    -- Parse fdisk output for the disk
    local disk_info = parse_fdisk_output(fdisk_output_disk)
    
    -- Print disk geometry
    --print("Disk Geometry:")
    for key, value in pairs(disk_info.geometry) do
        print(key .. ":", value)
		--print("disk Size":", disk_info.geometry.disk_size)
    end
    print()
    
    -- Print parsed partitions for the disk
    print("Partitions:")
    for _, partition in ipairs(disk_info.partitions) do
        print("Partition Device:", partition.device)
        --print("Start Sector:", partition.start_sector)
        --print("End Sector:", partition.end_sector)
        print("Size:", partition.size)
        --print("Type:", partition.type)
        print("Name:", partition.name)
        print()
    end
    
    print("--------------------")
    print()
	print(disk_info.geometry.disk_size)
    print("</div>")
end
		%>
				</div>
	
<!-- Dashboard Main Block - DISK - BLOCK 2 -->	
</div>
Tony Bonnin's avatar
Tony Bonnin committed

<% htmlviewfunctions.displaysectionend(header_level) %>