Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions IOBrowser.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
054776F6268A85B6005864F8 /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 054776F5268A85B6005864F8 /* Icon.icns */; };
0552FE472948FC7300DAA87A /* PropertyValueTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0552FE462948FC7300DAA87A /* PropertyValueTransformer.swift */; };
0552FE482948FC7300DAA87A /* PropertyValueTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0552FE462948FC7300DAA87A /* PropertyValueTransformer.swift */; };
0552FE4A294907FE00DAA87A /* Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0552FE49294907FE00DAA87A /* Data.swift */; };
0552FE4B294907FE00DAA87A /* Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0552FE49294907FE00DAA87A /* Data.swift */; };
05646BB42685020A00707676 /* ApplicationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05646BAF2685020A00707676 /* ApplicationDelegate.swift */; };
05646BB52685020A00707676 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 05646BB12685020A00707676 /* MainMenu.xib */; };
05646BEF2685055F00707676 /* AboutWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05646BEE2685055F00707676 /* AboutWindowController.swift */; };
Expand Down Expand Up @@ -98,7 +96,6 @@
054776F3268A7BFA005864F8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PropertyListFormatViewController.xib; sourceTree = "<group>"; };
054776F5268A85B6005864F8 /* Icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Icon.icns; sourceTree = "<group>"; };
0552FE462948FC7300DAA87A /* PropertyValueTransformer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PropertyValueTransformer.swift; sourceTree = "<group>"; };
0552FE49294907FE00DAA87A /* Data.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Data.swift; sourceTree = "<group>"; };
05646B9A268501B300707676 /* IOBrowser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IOBrowser.app; sourceTree = BUILT_PRODUCTS_DIR; };
05646BA4268501B400707676 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
05646BA5268501B400707676 /* IOBrowser.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = IOBrowser.entitlements; sourceTree = "<group>"; };
Expand Down Expand Up @@ -232,7 +229,6 @@
05B886BF2689C64F00E8A413 /* PropertyListNode.swift */,
054776F0268A7BED005864F8 /* PropertyListFormatViewController.swift */,
0552FE462948FC7300DAA87A /* PropertyValueTransformer.swift */,
0552FE49294907FE00DAA87A /* Data.swift */,
050087D62949CEE400882DD8 /* PasteboardWriter.swift */,
050087DB2949D17E00882DD8 /* Either.swift */,
);
Expand Down Expand Up @@ -573,7 +569,6 @@
05646BEF2685055F00707676 /* AboutWindowController.swift in Sources */,
0552FE472948FC7300DAA87A /* PropertyValueTransformer.swift in Sources */,
05B886BB2688F44E00E8A413 /* PropertiesViewController.swift in Sources */,
0552FE4A294907FE00DAA87A /* Data.swift in Sources */,
05B886B62688BE2E00E8A413 /* Preferences.swift in Sources */,
05646BF72685064C00707676 /* MainWindowController.swift in Sources */,
054776F1268A7BED005864F8 /* PropertyListFormatViewController.swift in Sources */,
Expand All @@ -595,7 +590,6 @@
059861D0292B9B7000B20BBD /* AboutWindowController.swift in Sources */,
0552FE482948FC7300DAA87A /* PropertyValueTransformer.swift in Sources */,
059861D1292B9B7000B20BBD /* PropertiesViewController.swift in Sources */,
0552FE4B294907FE00DAA87A /* Data.swift in Sources */,
059861D2292B9B7000B20BBD /* Preferences.swift in Sources */,
059861D3292B9B7000B20BBD /* MainWindowController.swift in Sources */,
059861D4292B9B7000B20BBD /* PropertyListFormatViewController.swift in Sources */,
Expand Down Expand Up @@ -674,6 +668,7 @@
DEVELOPMENT_TEAM = 326Y53CJMD;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = IOBrowser/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
Expand All @@ -695,6 +690,7 @@
DEVELOPMENT_TEAM = 326Y53CJMD;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = IOBrowser/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
Expand Down
75 changes: 0 additions & 75 deletions IOBrowser/Classes/Data.swift

This file was deleted.

16 changes: 8 additions & 8 deletions IOBrowser/Classes/Preferences.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ public class Preferences: NSObject

set( value )
{
self.willChangeValue( for: \.lastStart )
self.willChangeValue( for: \.numberDisplayMode )
UserDefaults.standard.set( value, forKey: "numberDisplayMode" )
self.didChangeValue( for: \.lastStart )
self.didChangeValue( for: \.numberDisplayMode )
}
}

Expand All @@ -65,24 +65,24 @@ public class Preferences: NSObject

set( value )
{
self.willChangeValue( for: \.lastStart )
self.willChangeValue( for: \.dataDisplayMode )
UserDefaults.standard.set( value, forKey: "dataDisplayMode" )
self.didChangeValue( for: \.lastStart )
self.didChangeValue( for: \.dataDisplayMode )
}
}

@objc public dynamic var detectNumbersInData: Bool
@objc public dynamic var detectNumbersInData: Int
{
get
{
UserDefaults.standard.bool( forKey: "detectNumbersInData" )
UserDefaults.standard.integer( forKey: "detectNumbersInData" )
}

set( value )
{
self.willChangeValue( for: \.lastStart )
self.willChangeValue( for: \.detectNumbersInData )
UserDefaults.standard.set( value, forKey: "detectNumbersInData" )
self.didChangeValue( for: \.lastStart )
self.didChangeValue( for: \.detectNumbersInData )
}
}

Expand Down
68 changes: 57 additions & 11 deletions IOBrowser/Classes/PropertyValueTransformer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,29 +42,75 @@ public class PropertyValueTransformer: ValueTransformer

if let number = value.propertyList as? NSNumber
{
if Preferences.shared.numberDisplayMode == 0
if CFGetTypeID(number) == CFBooleanGetTypeID()
{
return number.boolValue ? "true" : "false"
}
else if Preferences.shared.numberDisplayMode == 0
{
return number.description
}
else if Preferences.shared.numberDisplayMode == 1
else
{
return String( format: "0x%llX", number.int64Value )
switch CFNumberGetType(number)
{
case .sInt8Type, .sInt16Type, .sInt32Type, .sInt64Type, .charType, .shortType, .intType, .longType, .longLongType:
return String(format: "0x%0*llX", CFNumberGetByteSize(number) * 2, number.uint64Value)

case .float32Type, .float64Type, .floatType, .doubleType, .cgFloatType:
return String(format: "0x%a", number.doubleValue)

default:
return number.description
}
}
}

if let data = value.propertyList as? Data, data.count > 0
{
if Preferences.shared.detectNumbersInData, let number = data.number()
if Preferences.shared.detectNumbersInData != 0, [1, 2, 4, 8].contains(data.count)
{
return PropertyValueTransformer().transformedValue( PropertyListNode( key: value.key, propertyList: NSNumber( value: number ) ) )
}
else if Preferences.shared.dataDisplayMode == 0
{
return data.base64EncodedString()
var number: UInt64 = 0

switch (Preferences.shared.detectNumbersInData)
{
case 1: // big-endian
for byte in data
{
number = (number << 8) | UInt64(byte)
}
case 2: // little-endian
for ( i, byte ) in data.enumerated()
{
number |= UInt64( byte ) << ( i * 8 )
}
default:
break
}

if Preferences.shared.numberDisplayMode == 0
{
return number.description
}
else
{
let width = data.count * 2
return String(format: "0x%0*llX", width, number)
}
Comment on lines +71 to +99
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the big-endian case, when the switch statement's default case is reached (line 88), the number variable remains 0. This means if detectNumbersInData has a value other than 1 or 2 (which shouldn't happen based on the UI, but could happen if the preference is corrupted or set programmatically), the code will continue to format and return "0" or "0x00" instead of falling through to the data display logic. Consider returning early or handling this case explicitly to avoid displaying misleading values.

Copilot uses AI. Check for mistakes.
}
else if Preferences.shared.dataDisplayMode == 1
else
{
return data.hexadecimalString()
switch Preferences.shared.dataDisplayMode
{
case 1:
return data.base64EncodedString()
case 2:
return "0x" + data.map { String(format: "%02X", $0) }.joined()
case 3:
return String(data: data, encoding: .utf8) ?? "<invalid UTF-8 data>"
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The UTF-8 string conversion at line 110 attempts to decode binary data as UTF-8, which could fail for arbitrary binary data. While the nil-coalescing operator provides a fallback, the String initializer may still perform unnecessary decoding work for data that is clearly not UTF-8 text (e.g., starts with null bytes or contains invalid UTF-8 sequences). Consider adding a quick validation check for common UTF-8 patterns before attempting full decoding to improve performance when displaying large amounts of binary data.

Copilot uses AI. Check for mistakes.
default:
return data.description
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions IOBrowser/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.2.1</string>
<string>1.2.2</string>
<key>CFBundleVersion</key>
<string>46</string>
<string>54</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
Expand Down
Loading