From 25c8adb737352baeeda772f37b87640de10bfb65 Mon Sep 17 00:00:00 2001 From: "Leon.Schmidt" Date: Fri, 14 Aug 2026 21:24:35 +0200 Subject: [PATCH] FIX - support configurable company service numbers Company service lines were validated as full-length SIM numbers, which rejected short configured numbers such as 911 and stopped dependent server modules from initializing. Accept non-empty service numbers up to the configured SIM length, resolve configured service lines before direct SIM dialing for phone and payphone calls, and load Companies and SIM before Phone. Add focused normalization boundary tests. --- sky_phone/fxmanifest.lua | 4 ++-- sky_phone/source/server/calls.lua | 10 ++++++---- sky_phone/source/server/companies.lua | 10 +++++----- sky_phone/source/shared/sim_number.lua | 11 +++++++++++ tests/sim_number.lua | 4 ++++ 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/sky_phone/fxmanifest.lua b/sky_phone/fxmanifest.lua index e93ca72..c1d31a8 100644 --- a/sky_phone/fxmanifest.lua +++ b/sky_phone/fxmanifest.lua @@ -68,10 +68,10 @@ server_scripts { 'source/server/custom_app_compat.lua', 'source/server/db_migrate.lua', 'source/server/media_metadata.lua', - 'source/server/phone.lua', 'source/server/companies.lua', - 'source/server/custom_app_storage.lua', 'source/server/sim.lua', + 'source/server/phone.lua', + 'source/server/custom_app_storage.lua', 'source/server/payphones.lua', 'source/server/calls.lua', 'source/server/media_import.lua', diff --git a/sky_phone/source/server/calls.lua b/sky_phone/source/server/calls.lua index 9eace16..8291bd5 100644 --- a/sky_phone/source/server/calls.lua +++ b/sky_phone/source/server/calls.lua @@ -946,7 +946,9 @@ Bridge.Callbacks.Register("sky_phone:calls:dial", function(source, data) dial_locks[source] = nil return { success = false, error = "airplane_mode" } end - local number = SkyPhoneSimNumber.Normalize(data.phoneNumber, Config.Sim.NumberLength, Config.Sim.NumberPrefix) + local service_line = SkyPhoneCompanies.GetServiceLine(data.phoneNumber) + local number = service_line and service_line.number + or SkyPhoneSimNumber.Normalize(data.phoneNumber, Config.Sim.NumberLength, Config.Sim.NumberPrefix) if not number then dial_locks[source] = nil return { success = false, error = "invalid_number" } @@ -960,7 +962,6 @@ Bridge.Callbacks.Register("sky_phone:calls:dial", function(source, data) return { success = false, error = "busy" } end dialing_by_sim[scope.device.sim_id] = true - local service_line = SkyPhoneCompanies.GetServiceLine(number) if service_line then if not service_line.canCall then local terminal = create_terminal_call(scope, number, nil, "unavailable") @@ -1109,7 +1110,9 @@ Bridge.Callbacks.Register("sky_phone:payphone:dial", function(source, data) return { success = false, error = "busy" } end - local number = SkyPhoneSimNumber.Normalize(data.phoneNumber, Config.Sim.NumberLength, Config.Sim.NumberPrefix) + local service_line = SkyPhoneCompanies.GetServiceLine(data.phoneNumber) + local number = service_line and service_line.number + or SkyPhoneSimNumber.Normalize(data.phoneNumber, Config.Sim.NumberLength, Config.Sim.NumberPrefix) if not number then return { success = false, error = "invalid_number" } end @@ -1120,7 +1123,6 @@ Bridge.Callbacks.Register("sky_phone:payphone:dial", function(source, data) end dial_locks[source] = true - local service_line = SkyPhoneCompanies.GetServiceLine(number) if service_line then if not service_line.canCall then dial_locks[source] = nil diff --git a/sky_phone/source/server/companies.lua b/sky_phone/source/server/companies.lua index 3a18a55..42d7355 100644 --- a/sky_phone/source/server/companies.lua +++ b/sky_phone/source/server/companies.lua @@ -307,7 +307,7 @@ local function validate_configuration() if type(line) ~= "table" then error(("[sky_phone] Company '%s' has no service line configuration."):format(company_id)) end - local number = SkyPhoneSimNumber.Normalize(line.Number, Config.Sim.NumberLength, Config.Sim.NumberPrefix) + local number = SkyPhoneSimNumber.NormalizeService(line.Number, Config.Sim.NumberLength) if not number then error(("[sky_phone] Company '%s' has an invalid service number."):format(company_id)) end @@ -522,7 +522,7 @@ local function service_line_payload(company_id) end function SkyPhoneCompanies.GetServiceLine(number) - local normalized = SkyPhoneSimNumber.Normalize(number, Config.Sim.NumberLength, Config.Sim.NumberPrefix) + local normalized = SkyPhoneSimNumber.NormalizeService(number, Config.Sim.NumberLength) return normalized and service_line_payload(service_lines_by_number[normalized]) or nil end @@ -531,7 +531,7 @@ function SkyPhoneCompanies.GetServiceLineForCompany(company_id) end function SkyPhoneCompanies.IsServiceNumber(number) - local normalized = SkyPhoneSimNumber.Normalize(number, Config.Sim.NumberLength, Config.Sim.NumberPrefix) + local normalized = SkyPhoneSimNumber.NormalizeService(number, Config.Sim.NumberLength) return normalized ~= nil and service_lines_by_number[normalized] ~= nil end @@ -539,7 +539,7 @@ function SkyPhoneCompanies.IsSystemContactNumber(number) if not Config.Companies.Enabled then return false end - local normalized = SkyPhoneSimNumber.Normalize(number, Config.Sim.NumberLength, Config.Sim.NumberPrefix) + local normalized = SkyPhoneSimNumber.NormalizeService(number, Config.Sim.NumberLength) local company_id = normalized and service_lines_by_number[normalized] or nil local definition = company_id and definitions[company_id] or nil return definition ~= nil and definition.Public == true and definition.ServiceLine.AutoContact == true @@ -2610,7 +2610,7 @@ Bridge.Callbacks.Register("sky_phone:companies:update-profile", function(source, return { success = false, error = "invalid_profile" } end if data.phoneNumber ~= nil then - local number = SkyPhoneSimNumber.Normalize(data.phoneNumber, Config.Sim.NumberLength, Config.Sim.NumberPrefix) + local number = SkyPhoneSimNumber.NormalizeService(data.phoneNumber, Config.Sim.NumberLength) if number ~= member.definition.ServiceLine.Number then return { success = false, error = "invalid_profile" } end diff --git a/sky_phone/source/shared/sim_number.lua b/sky_phone/source/shared/sim_number.lua index 5aeb375..355f15a 100644 --- a/sky_phone/source/shared/sim_number.lua +++ b/sky_phone/source/shared/sim_number.lua @@ -11,6 +11,17 @@ function SkyPhoneSimNumber.Normalize(value, length, prefix) return number end +function SkyPhoneSimNumber.NormalizeService(value, maximum_length) + if type(value) ~= "string" and type(value) ~= "number" then + return nil + end + local number = tostring(value):gsub("%D", "") + if number == "" or #number > maximum_length then + return nil + end + return number +end + function SkyPhoneSimNumber.FromEntropy(entropy, length, prefix) if type(entropy) ~= "string" or entropy == "" then return nil diff --git a/tests/sim_number.lua b/tests/sim_number.lua index 0d03115..1afd8e5 100644 --- a/tests/sim_number.lua +++ b/tests/sim_number.lua @@ -5,6 +5,10 @@ assert(number == "5508400294", "SIM number must be derived deterministically fro assert(SkyPhoneSimNumber.Normalize("550 840 0294", 10, "") == number, "formatted numbers must normalize") assert(SkyPhoneSimNumber.Normalize("123", 10, "") == nil, "short numbers must fail") assert(SkyPhoneSimNumber.Format(number, { 3, 3, 4 }, 10, "") == "550 840 0294", "groups must format") +assert(SkyPhoneSimNumber.NormalizeService("9-1-1", 10) == "911", "formatted service numbers must normalize") +assert(SkyPhoneSimNumber.NormalizeService("0", 10) == "0", "single-digit service numbers must normalize") +assert(SkyPhoneSimNumber.NormalizeService("", 10) == nil, "empty service numbers must fail") +assert(SkyPhoneSimNumber.NormalizeService("12345678901", 10) == nil, "long service numbers must fail") local attempts = 0 local reserved = SkyPhoneSimNumber.Reserve(function()