10 Commits

Author SHA1 Message Date
100b23793c Merge pull request 'Many changes' (#62) from Kan18/develop-1.8 into develop-1.8
Some checks failed
CI / build (push) Has been cancelled
Reviewed-on: #62
2026-03-22 11:58:40 -04:00
Kan18
9b502553e0 Update json.lua 2023-12-17 10:14:40 -05:00
Kan18
c247097e20 oops 2022-12-28 20:25:52 +04:00
Kan18
2597724dab Fix Util.getVersion 2022-12-28 20:05:16 +04:00
Kan18
5f153721ea oops 2022-12-28 19:26:48 +04:00
Kan18
0a42551ab7 actually set it to 30 2022-12-28 19:22:38 +04:00
Kan18
76b310d873 oops 2022-12-28 19:22:20 +04:00
Kan18
f26f443b9d Increase discovery message interval, distribute messages
Previously on large server(s), there was an issue where because
chunkloaded computers all started up at once, so they all had the same
discovery message sending timer. This prevents that by starting each off
with a random offset. Also increases the interval for sending messages
from 15 s to 30 s, so that messages (which are the same, a lot of the
time) get sent less often.
2022-12-28 18:43:49 +04:00
Kan18
8fbcc7b8bc Sanitize label in samba.lua
Prevent labels from having .., /, *, control characters, or quotes (this
generally messes things up) and limit them to a reasonable length. We
might possibly also want to do this in snmp.lua, I'm not sure if that
will break things though
2022-12-28 18:26:27 +04:00
Kan18
f7ba900930 genotp.lua changes
Make genotp more clearly state that the password can be used once but
allows permanent access (sorry for not making this clear earlier.) Use a
slightly longer password, and allow uppercase characters except for some
that could be ambiguous
2022-12-28 13:22:57 +04:00
17 changed files with 82 additions and 304 deletions

View File

@@ -51,7 +51,7 @@ local config = {
}
Config.load('Overview', config)
local extSupport = Util.getVersion() >= 1.76
local extSupport = Util.supportsExtChars()
local applications = { }
local buttons = { }

View File

@@ -1,14 +1,22 @@
local SHA = require("opus.crypto.sha2")
local acceptableCharacters = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}
local acceptableCharacters = {}
for c = 0, 127 do
local char = string.char(c)
-- exclude potentially ambiguous characters
if char:match("[1-9a-zA-Z]") and char:match("[^OIl]") then
table.insert(acceptableCharacters, char)
end
end
local acceptableCharactersLen = #acceptableCharacters
local password = ""
for _i = 1, 8 do
for i = 1, 10 do
password = password .. acceptableCharacters[math.random(acceptableCharactersLen)]
end
os.queueEvent("set_otp", SHA.compute(password))
print("Your one-time password is: " .. password)
print("This allows one other device to permanently gain access to this device.")
print("Use the trust settings in System to revert this.")
print("Your one-time password is: " .. password)

View File

@@ -1,200 +0,0 @@
-- Memory Profiler for CC:Tweaked / Opus OS
-- Usage: memprofile [--watch] [--interval <seconds>]
--
-- Shows current Lua memory usage with breakdown estimates.
-- Use --watch to continuously monitor.
-- Useful for detecting memory leaks and understanding overhead.
local args = { ... }
local watch = false
local interval = 3
for i, arg in ipairs(args) do
if arg == '--watch' or arg == '-w' then
watch = true
elseif arg == '--interval' or arg == '-i' then
interval = tonumber(args[i + 1]) or 3
elseif arg == '--help' or arg == '-h' then
print('Usage: memprofile [--watch] [--interval <secs>]')
print('')
print('Options:')
print(' --watch, -w Continuously monitor memory')
print(' --interval, -i N Update interval in seconds (default: 3)')
print(' --help, -h Show this help')
return
end
end
local term = _G.term
local os = _G.os
local function formatBytes(bytes)
if bytes < 1024 then
return string.format('%d B', bytes)
elseif bytes < 1024 * 1024 then
return string.format('%.1f KB', bytes / 1024)
else
return string.format('%.2f MB', bytes / (1024 * 1024))
end
end
local function countTable(t, seen)
if type(t) ~= 'table' or seen[t] then return 0, 0 end
seen[t] = true
local entries = 0
local nested = 0
for k, v in pairs(t) do
entries = entries + 1
if type(v) == 'table' then
local e, n = countTable(v, seen)
nested = nested + 1 + e
entries = entries + n
end
if type(k) == 'table' then
local e, n = countTable(k, seen)
nested = nested + 1 + e
entries = entries + n
end
end
return entries, nested
end
local function getSnapshot()
-- Force a full GC cycle to get accurate usage
collectgarbage('collect')
collectgarbage('collect')
local memKB = collectgarbage('count') -- returns KB as float
local snapshot = {
totalKB = memKB,
totalBytes = math.floor(memKB * 1024),
timestamp = os.clock(),
}
-- Count entries in major global tables
local seen = {}
local globals = {}
local interesting = {
{ name = '_G (globals)', tbl = _G },
{ name = 'kernel', tbl = _G.kernel },
{ name = 'network', tbl = _G.network },
{ name = 'device', tbl = _G.device },
}
for _, item in ipairs(interesting) do
if type(item.tbl) == 'table' then
local entries, nested = countTable(item.tbl, seen)
table.insert(globals, {
name = item.name,
entries = entries,
nested = nested,
})
end
end
snapshot.globals = globals
-- Count routines if kernel is available
if _G.kernel and _G.kernel.routines then
snapshot.routines = #_G.kernel.routines
end
-- Count loaded modules
if package and package.loaded then
local count = 0
for _ in pairs(package.loaded) do
count = count + 1
end
snapshot.loadedModules = count
end
return snapshot
end
local function printSnapshot(snap, prev)
term.clear()
term.setCursorPos(1, 1)
local w = term.getSize()
local sep = string.rep('-', w)
term.setTextColor(colors.yellow)
print('=== Memory Profile ===')
term.setTextColor(colors.white)
print('')
-- Total memory
local memStr = formatBytes(snap.totalBytes)
local deltaStr = ''
if prev then
local delta = snap.totalBytes - prev.totalBytes
if delta > 0 then
deltaStr = string.format(' (+%s)', formatBytes(delta))
term.setTextColor(colors.red)
elseif delta < 0 then
deltaStr = string.format(' (-%s)', formatBytes(-delta))
term.setTextColor(colors.green)
end
end
term.setTextColor(colors.white)
print(string.format('Total Memory: %s%s', memStr, deltaStr))
print(string.format('Uptime: %.1fs', snap.timestamp))
print('')
-- Table sizes
term.setTextColor(colors.lightBlue)
print('Global Tables:')
term.setTextColor(colors.white)
print(sep)
print(string.format(' %-20s %8s %8s', 'Name', 'Entries', 'Nested'))
print(sep)
for _, g in ipairs(snap.globals) do
print(string.format(' %-20s %8d %8d', g.name, g.entries, g.nested))
end
print(sep)
print('')
-- Kernel info
if snap.routines then
term.setTextColor(colors.lightBlue)
print('Kernel:')
term.setTextColor(colors.white)
print(string.format(' Active routines: %d', snap.routines))
end
if snap.loadedModules then
print(string.format(' Loaded modules: %d', snap.loadedModules))
end
print('')
-- CC:Tweaked limits
term.setTextColor(colors.gray)
print('Note: CC:Tweaked default memory limit is ~128MB per computer.')
print('High memory usage may cause slowdowns or crashes.')
if watch then
print('')
term.setTextColor(colors.yellow)
print(string.format('Refreshing every %ds... (Ctrl+T to stop)', interval))
end
end
local function run()
local prev = nil
if watch then
while true do
local snap = getSnapshot()
printSnapshot(snap, prev)
prev = snap
os.sleep(interval)
end
else
local snap = getSnapshot()
printSnapshot(snap, nil)
end
end
run()

View File

@@ -59,6 +59,10 @@ local function sambaConnection(socket)
print('samba: Connection closed')
end
local function sanitizeLabel(computer)
return (computer.id.."_"..computer.label:gsub("[%c%.\"'/%*]", "")):sub(1, 40)
end
Event.addRoutine(function()
print('samba: listening on port 139')
@@ -79,10 +83,10 @@ Event.addRoutine(function()
end)
Event.on('network_attach', function(_, computer)
fs.mount(fs.combine('network', computer.label), 'netfs', computer.id)
fs.mount(fs.combine('network', sanitizeLabel(computer)), 'netfs', computer.id)
end)
Event.on('network_detach', function(_, computer)
print('samba: detaching ' .. computer.label)
fs.unmount(fs.combine('network', computer.label))
print('samba: detaching ' .. sanitizeLabel(computer))
fs.unmount(fs.combine('network', sanitizeLabel(computer)))
end)

View File

@@ -152,7 +152,7 @@ local function getSlots()
end
local function sendInfo()
if os.clock() - infoTimer >= 1 then -- don't flood
if os.clock() - infoTimer >= 5 then -- don't flood
infoTimer = os.clock()
info.label = os.getComputerLabel()
info.uptime = math.floor(os.clock())
@@ -194,16 +194,25 @@ local function sendInfo()
end
end
-- every 10 seconds, send out this computer's info
Event.onInterval(10, function()
sendInfo()
local function cleanNetwork()
for _,c in pairs(_G.network) do
local elapsed = os.clock()-c.timestamp
if c.active and elapsed > 15 then
if c.active and elapsed > 50 then
c.active = false
os.queueEvent('network_detach', c)
end
end
end
-- every 30 seconds, send out this computer's info
-- send with offset so that messages are evenly distributed and do not all come at once
Event.onTimeout(math.random() * 30, function()
sendInfo()
cleanNetwork()
Event.onInterval(30, function()
sendInfo()
cleanNetwork()
end)
end)
Event.on('turtle_response', function()
@@ -213,4 +222,5 @@ Event.on('turtle_response', function()
end
end)
Event.onTimeout(1, sendInfo)
-- send info early so that computers show soon after booting
Event.onTimeout(math.random() * 2 + 1, sendInfo)

View File

@@ -1,9 +1,10 @@
local Security = require('opus.security')
local SHA = require('opus.crypto.sha2')
local Terminal = require('opus.terminal')
local password = Terminal.readPassword('Enter new password: ')
if password then
Security.updatePassword(password)
Security.updatePassword(SHA.compute(password))
print('Password updated')
end

View File

@@ -26,12 +26,12 @@ return UI.Tab {
x = 2, y = 5, ex = -2, ey = -2,
values = {
{ name = '', value = '' },
{ name = 'CC version', value = Util.getVersion() },
{ name = 'Lua version', value = _VERSION },
{ name = 'MC version', value = Util.getMinecraftVersion() },
{ name = 'Disk free', value = Util.toBytes(fs.getFreeSpace('/')) },
{ name = 'Computer ID', value = tostring(os.getComputerID()) },
{ name = 'Day', value = tostring(os.day()) },
{ name = 'CC version', value = ("%d.%d"):format(Util.getVersion()) },
{ name = 'Lua version', value = _VERSION },
{ name = 'MC version', value = Util.getMinecraftVersion() },
{ name = 'Disk free', value = Util.toBytes(fs.getFreeSpace('/')) },
{ name = 'Computer ID', value = tostring(os.getComputerID()) },
{ name = 'Day', value = tostring(os.day()) },
},
disableHeader = true,
inactive = true,

View File

@@ -1,5 +1,5 @@
sys/apps/pain.lua urlfs https://github.com/LDDestroier/CC/raw/master/pain.lua
sys/apps/update.lua urlfs https://pastebin.com/raw/UzGHLbNC
sys/apps/update.lua urlfs http://pastebin.com/raw/UzGHLbNC
sys/apps/Enchat.lua urlfs https://raw.githubusercontent.com/LDDestroier/enchat/master/enchat3.lua
sys/apps/cloud.lua urlfs https://cloud-catcher.squiddev.cc/cloud.lua
rom/modules/main/opus linkfs sys/modules/opus

View File

@@ -14,7 +14,7 @@ local parentTerm = _G.device.terminal
local w,h = parentTerm.getSize()
local overviewId
local tabsDirty = false
local closeInd = Util.getVersion() >= 1.76 and '\215' or '*'
local closeInd = Util.supportsExtChars() and '\215' or '*'
local multishell = { }
_ENV.multishell = multishell

View File

@@ -5,7 +5,7 @@ local cbor = require('opus.cbor')
local sha2 = require('opus.crypto.sha2')
local Util = require('opus.util')
local ROUNDS = 20 -- Standard ChaCha20 (was 8, upgraded for security)
local ROUNDS = 8 -- Adjust this for speed tradeoff
local bxor = bit32.bxor
local band = bit32.band

View File

@@ -15,11 +15,7 @@ for _,m in pairs(methods) do
end
function linkfs.resolve(node, dir)
local mp = node.mountPoint
if dir:sub(1, #mp) == mp then
return node.source .. dir:sub(#mp + 1)
end
return dir
return dir:gsub(node.mountPoint, node.source, 1)
end
function linkfs.mount(path, source)
@@ -45,8 +41,8 @@ function linkfs.mount(path, source)
end
function linkfs.copy(node, s, t)
s = linkfs.resolve(node, s)
t = linkfs.resolve(node, t)
s = s:gsub(node.mountPoint, node.source, 1)
t = t:gsub(node.mountPoint, node.source, 1)
return fs.copy(s, t)
end
@@ -54,29 +50,25 @@ function linkfs.delete(node, dir)
if dir == node.mountPoint then
fs.unmount(node.mountPoint)
else
dir = linkfs.resolve(node, dir)
dir = dir:gsub(node.mountPoint, node.source, 1)
return fs.delete(dir)
end
end
function linkfs.find(node, spec)
spec = linkfs.resolve(node, spec)
spec = spec:gsub(node.mountPoint, node.source, 1)
local list = fs.find(spec)
local src = node.source
local mp = node.mountPoint
for k,f in ipairs(list) do
if f:sub(1, #src) == src then
list[k] = mp .. f:sub(#src + 1)
end
list[k] = f:gsub(node.source, node.mountPoint, 1)
end
return list
end
function linkfs.move(node, s, t)
s = linkfs.resolve(node, s)
t = linkfs.resolve(node, t)
s = s:gsub(node.mountPoint, node.source, 1)
t = t:gsub(node.mountPoint, node.source, 1)
return fs.move(s, t)
end

View File

@@ -35,10 +35,8 @@ end
local methods = { 'delete', 'exists', 'getFreeSpace', 'makeDir', 'list', 'listEx', 'attributes' }
local function resolve(node, dir)
local mp = node.mountPoint
if dir:sub(1, #mp) == mp then
dir = dir:sub(#mp + 1)
end
-- TODO: Wrong ! (does not support names with dashes)
dir = dir:gsub(node.mountPoint, '', 1)
return fs.combine(node.source, dir)
end
@@ -55,7 +53,7 @@ end
function netfs.mount(_, id, source)
if not id or not tonumber(id) then
error('netfs syntax: computerId [directory]')
error('ramfs syntax: computerId [directory]')
end
return {
id = tonumber(id),

View File

@@ -15,7 +15,7 @@ function git.list(repository)
local user = table.remove(t, 1)
local repo = table.remove(t, 1)
local branch = table.remove(t, 1) or 'main'
local branch = table.remove(t, 1) or 'master'
local path
if not Util.empty(t) then

View File

@@ -39,7 +39,8 @@ if register_global_module_table then
_G[global_module_name] = json
end
local _ENV = nil -- blocking globals in Lua 5.2
-- this was incompatible because we use fs later
--local _ENV = nil -- blocking globals in Lua 5.2
pcall (function()
-- Enable access to blocked metatables.

View File

@@ -1,38 +1,10 @@
local Config = require('opus.config')
local SHA = require('opus.crypto.sha2')
local Util = require('opus.util')
local PBKDF2_ITERATIONS = 100
local Security = { }
local function generateSalt()
local salt = { }
for _ = 1, 16 do
salt[#salt + 1] = math.random(0, 0xFF)
end
return setmetatable(salt, Util.byteArrayMT):toHex()
end
function Security.verifyPassword(password)
local stored = Security.getPassword()
if not stored then
return false
end
-- New format: { hash = hex, salt = hex, iter = N }
if type(stored) == 'table' and stored.hash and stored.salt then
local iter = stored.iter or PBKDF2_ITERATIONS
local derived = SHA.pbkdf2(password, Util.hexToByteArray(stored.salt), iter)
return derived:toHex() == stored.hash
end
-- Legacy format: plain SHA-256 hex string
if type(stored) == 'string' then
return SHA.compute(password) == stored
end
return false
local current = Security.getPassword()
return current and password == current
end
function Security.hasPassword()
@@ -56,15 +28,8 @@ function Security.getIdentifier()
end
function Security.updatePassword(password)
local salt = generateSalt()
local derived = SHA.pbkdf2(password, Util.hexToByteArray(salt), PBKDF2_ITERATIONS)
local config = Config.load('os')
config.password = {
hash = derived:toHex(),
salt = salt,
iter = PBKDF2_ITERATIONS,
}
config.password = password
Config.update('os', config)
end

View File

@@ -44,7 +44,7 @@ function UI:init()
tertiary = colors.gray,
}
}
self.extChars = Util.getVersion() >= 1.76
self.extChars = Util.supportsExtChars()
local function keyFunction(event, code, held)
local ie = Input:translate(event, code, held)
@@ -115,16 +115,12 @@ function UI:init()
local ie = Input:translate('mouse_up', button, x, y)
local currentPage = self:getActivePage()
if ie.code == 'control-shift-mouse_click' then -- debug inspector
local Config = require('opus.config')
local debugCfg = Config.load('os', { debug_inspector = false })
if debugCfg.debug_inspector then
local event = currentPage:pointToChild(x, y)
_ENV.multishell.openTab(_ENV, {
path = 'sys/apps/Lua.lua',
args = { event.element, self, _ENV },
focused = true })
end
if ie.code == 'control-shift-mouse_click' then -- hack
local event = currentPage:pointToChild(x, y)
_ENV.multishell.openTab(_ENV, {
path = 'sys/apps/Lua.lua',
args = { event.element, self, _ENV },
focused = true })
elseif ie and currentPage and currentPage.parent.device.side == side then
self:click(currentPage, ie)

View File

@@ -170,16 +170,19 @@ function Util.print(pattern, ...)
end
function Util.getVersion()
local version
local versionString = _G._HOST or _G._CC_VERSION
local versionMajor, versionMinor = versionString:match("(%d+)%.(%d+)")
-- ex.: 1.89 would return 1, 89
return tonumber(versionMajor), tonumber(versionMinor)
end
if _G._CC_VERSION then
version = tonumber(_G._CC_VERSION:match('[%d]+%.?[%d][%d]'))
end
if not version and _G._HOST then
version = tonumber(_G._HOST:match('[%d]+%.?[%d][%d]'))
end
function Util.compareVersion(major, minor)
local currentMajor, currentMinor = Util.getVersion()
return currentMajor > major or currentMajor == major and currentMinor >= minor
end
return version or 1.7
function Util.supportsExtChars()
return Util.compareVersion(1, 76)
end
function Util.getMinecraftVersion()