├── .github ├── FUNDING.yml └── workflows │ └── ci-mac.yaml ├── .gitignore ├── .gitmodules ├── Assets ├── Icon.psd ├── Logo.png ├── Logo.psd └── Screenshot.png ├── CODE_OF_CONDUCT.md ├── IOBrowser.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ ├── IOBrowser AppStore.xcscheme │ └── IOBrowser.xcscheme ├── IOBrowser ├── Classes │ ├── AboutWindowController.swift │ ├── ApplicationDelegate.swift │ ├── ArrayIsEmpty.swift │ ├── ArrayIsNotEmpty.swift │ ├── Data.swift │ ├── Either.swift │ ├── IODisplayItem.swift │ ├── IOObject.swift │ ├── MainWindowController.swift │ ├── PasteboardWriter.swift │ ├── Preferences.swift │ ├── PropertiesViewController.swift │ ├── PropertyListFormatViewController.swift │ ├── PropertyListNode.swift │ └── PropertyValueTransformer.swift ├── IOBrowser-AppStore.entitlements ├── IOBrowser-Bridging-Header.h ├── IOBrowser.entitlements ├── Info.plist └── UI │ ├── Base.lproj │ ├── AboutWindowController.xib │ ├── MainMenu.xib │ ├── MainWindowController.xib │ ├── PropertiesViewController.xib │ └── PropertyListFormatViewController.xib │ └── Images │ ├── DocumentTemplate.pdf │ ├── FolderTemplate.pdf │ ├── Icon.icns │ └── StackTemplate.pdf ├── LICENSE └── README.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: macmade 2 | -------------------------------------------------------------------------------- /.github/workflows/ci-mac.yaml: -------------------------------------------------------------------------------- 1 | name: ci-mac 2 | on: [push] 3 | jobs: 4 | ci: 5 | runs-on: macos-latest 6 | strategy: 7 | matrix: 8 | run-config: 9 | - { scheme: 'IOBrowser', configuration: 'Debug', project: 'IOBrowser.xcodeproj', build: 1, analyze: 1, test: 0, info: 1, destination: 'platform=macOS' } 10 | - { scheme: 'IOBrowser', configuration: 'Release', project: 'IOBrowser.xcodeproj', build: 1, analyze: 1, test: 0, info: 1, destination: 'platform=macOS' } 11 | steps: 12 | 13 | - uses: actions/checkout@v1 14 | with: 15 | submodules: 'recursive' 16 | 17 | - uses: macmade/action-xcodebuild@v1.0.0 18 | 19 | - uses: macmade/action-slack@v1.0.0 20 | if: ${{ always() }} 21 | env: 22 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} 23 | with: 24 | channel: '#ci' 25 | status: ${{ job.status }} 26 | title: ${{ matrix.run-config[ 'scheme' ] }} - ${{ matrix.run-config[ 'configuration' ] }} 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac Finder 2 | .DS_Store 3 | .Trashes 4 | Icon? 5 | 6 | # Thumbnails 7 | ._* 8 | 9 | # Files that might appear on external disk 10 | .Spotlight-V100 11 | .Trashes 12 | 13 | # Xcode 14 | *.pbxuser 15 | *.mode1v3 16 | *.mode2v3 17 | *.perspectivev3 18 | *.xccheckout 19 | *.profraw 20 | !default.pbxuser 21 | !default.mode1v3 22 | !default.mode2v3 23 | !default.perspectivev3 24 | xcuserdata 25 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Submodules/xcconfig"] 2 | path = Submodules/xcconfig 3 | url = https://github.com/macmade/xcconfig.git 4 | [submodule "Submodules/GitHubUpdates"] 5 | path = Submodules/GitHubUpdates 6 | url = https://github.com/macmade/GitHubUpdates.git 7 | -------------------------------------------------------------------------------- /Assets/Icon.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macmade/IOBrowser/19d58e63212450ef7a5ff6e11cc10c612028838c/Assets/Icon.psd -------------------------------------------------------------------------------- /Assets/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macmade/IOBrowser/19d58e63212450ef7a5ff6e11cc10c612028838c/Assets/Logo.png -------------------------------------------------------------------------------- /Assets/Logo.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macmade/IOBrowser/19d58e63212450ef7a5ff6e11cc10c612028838c/Assets/Logo.psd -------------------------------------------------------------------------------- /Assets/Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macmade/IOBrowser/19d58e63212450ef7a5ff6e11cc10c612028838c/Assets/Screenshot.png -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | xs-labs.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /IOBrowser.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 050087D72949CEE400882DD8 /* PasteboardWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 050087D62949CEE400882DD8 /* PasteboardWriter.swift */; }; 11 | 050087DC2949D17E00882DD8 /* Either.swift in Sources */ = {isa = PBXBuildFile; fileRef = 050087DB2949D17E00882DD8 /* Either.swift */; }; 12 | 050087E8294A661C00882DD8 /* PasteboardWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 050087D62949CEE400882DD8 /* PasteboardWriter.swift */; }; 13 | 050087E9294A661F00882DD8 /* Either.swift in Sources */ = {isa = PBXBuildFile; fileRef = 050087DB2949D17E00882DD8 /* Either.swift */; }; 14 | 054776E4268A5C87005864F8 /* IODisplayItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 054776E3268A5C87005864F8 /* IODisplayItem.swift */; }; 15 | 054776F1268A7BED005864F8 /* PropertyListFormatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 054776F0268A7BED005864F8 /* PropertyListFormatViewController.swift */; }; 16 | 054776F4268A7BFA005864F8 /* PropertyListFormatViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 054776F2268A7BFA005864F8 /* PropertyListFormatViewController.xib */; }; 17 | 054776F6268A85B6005864F8 /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 054776F5268A85B6005864F8 /* Icon.icns */; }; 18 | 0552FE472948FC7300DAA87A /* PropertyValueTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0552FE462948FC7300DAA87A /* PropertyValueTransformer.swift */; }; 19 | 0552FE482948FC7300DAA87A /* PropertyValueTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0552FE462948FC7300DAA87A /* PropertyValueTransformer.swift */; }; 20 | 0552FE4A294907FE00DAA87A /* Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0552FE49294907FE00DAA87A /* Data.swift */; }; 21 | 0552FE4B294907FE00DAA87A /* Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0552FE49294907FE00DAA87A /* Data.swift */; }; 22 | 05646BB42685020A00707676 /* ApplicationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05646BAF2685020A00707676 /* ApplicationDelegate.swift */; }; 23 | 05646BB52685020A00707676 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 05646BB12685020A00707676 /* MainMenu.xib */; }; 24 | 05646BEF2685055F00707676 /* AboutWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05646BEE2685055F00707676 /* AboutWindowController.swift */; }; 25 | 05646BF22685058700707676 /* AboutWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 05646BF02685058700707676 /* AboutWindowController.xib */; }; 26 | 05646BF72685064C00707676 /* MainWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05646BF62685064C00707676 /* MainWindowController.swift */; }; 27 | 05646BFA2685072900707676 /* MainWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 05646BF82685072900707676 /* MainWindowController.xib */; }; 28 | 0566B96D2686B531006EE45A /* GitHubUpdates.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0566B9692686B526006EE45A /* GitHubUpdates.framework */; }; 29 | 0566B96E2686B531006EE45A /* GitHubUpdates.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0566B9692686B526006EE45A /* GitHubUpdates.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 30 | 059861CB292B9B7000B20BBD /* ArrayIsEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05B88700268A382D00E8A413 /* ArrayIsEmpty.swift */; }; 31 | 059861CC292B9B7000B20BBD /* PropertyListNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05B886BF2689C64F00E8A413 /* PropertyListNode.swift */; }; 32 | 059861CD292B9B7000B20BBD /* IOObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05B886B82688CB1200E8A413 /* IOObject.swift */; }; 33 | 059861CE292B9B7000B20BBD /* IODisplayItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 054776E3268A5C87005864F8 /* IODisplayItem.swift */; }; 34 | 059861CF292B9B7000B20BBD /* ApplicationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05646BAF2685020A00707676 /* ApplicationDelegate.swift */; }; 35 | 059861D0292B9B7000B20BBD /* AboutWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05646BEE2685055F00707676 /* AboutWindowController.swift */; }; 36 | 059861D1292B9B7000B20BBD /* PropertiesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05B886BA2688F44E00E8A413 /* PropertiesViewController.swift */; }; 37 | 059861D2292B9B7000B20BBD /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05B886B52688BE2E00E8A413 /* Preferences.swift */; }; 38 | 059861D3292B9B7000B20BBD /* MainWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05646BF62685064C00707676 /* MainWindowController.swift */; }; 39 | 059861D4292B9B7000B20BBD /* PropertyListFormatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 054776F0268A7BED005864F8 /* PropertyListFormatViewController.swift */; }; 40 | 059861D5292B9B7000B20BBD /* ArrayIsNotEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05B88704268A388700E8A413 /* ArrayIsNotEmpty.swift */; }; 41 | 059861DA292B9B7000B20BBD /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 05646BB12685020A00707676 /* MainMenu.xib */; }; 42 | 059861DB292B9B7000B20BBD /* PropertiesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 05B886BC2688F4AA00E8A413 /* PropertiesViewController.xib */; }; 43 | 059861DC292B9B7000B20BBD /* FolderTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 05B88715268A463800E8A413 /* FolderTemplate.pdf */; }; 44 | 059861DD292B9B7000B20BBD /* MainWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 05646BF82685072900707676 /* MainWindowController.xib */; }; 45 | 059861DE292B9B7000B20BBD /* DocumentTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 05B88716268A463800E8A413 /* DocumentTemplate.pdf */; }; 46 | 059861DF292B9B7000B20BBD /* StackTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 05B88713268A40E300E8A413 /* StackTemplate.pdf */; }; 47 | 059861E0292B9B7000B20BBD /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 054776F5268A85B6005864F8 /* Icon.icns */; }; 48 | 059861E1292B9B7000B20BBD /* PropertyListFormatViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 054776F2268A7BFA005864F8 /* PropertyListFormatViewController.xib */; }; 49 | 059861E2292B9B7000B20BBD /* AboutWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 05646BF02685058700707676 /* AboutWindowController.xib */; }; 50 | 05B886B62688BE2E00E8A413 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05B886B52688BE2E00E8A413 /* Preferences.swift */; }; 51 | 05B886B92688CB1200E8A413 /* IOObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05B886B82688CB1200E8A413 /* IOObject.swift */; }; 52 | 05B886BB2688F44E00E8A413 /* PropertiesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05B886BA2688F44E00E8A413 /* PropertiesViewController.swift */; }; 53 | 05B886BE2688F4AA00E8A413 /* PropertiesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 05B886BC2688F4AA00E8A413 /* PropertiesViewController.xib */; }; 54 | 05B886C02689C64F00E8A413 /* PropertyListNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05B886BF2689C64F00E8A413 /* PropertyListNode.swift */; }; 55 | 05B88701268A382D00E8A413 /* ArrayIsEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05B88700268A382D00E8A413 /* ArrayIsEmpty.swift */; }; 56 | 05B88705268A388700E8A413 /* ArrayIsNotEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05B88704268A388700E8A413 /* ArrayIsNotEmpty.swift */; }; 57 | 05B88714268A40E300E8A413 /* StackTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 05B88713268A40E300E8A413 /* StackTemplate.pdf */; }; 58 | 05B88717268A463800E8A413 /* FolderTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 05B88715268A463800E8A413 /* FolderTemplate.pdf */; }; 59 | 05B88718268A463800E8A413 /* DocumentTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 05B88716268A463800E8A413 /* DocumentTemplate.pdf */; }; 60 | /* End PBXBuildFile section */ 61 | 62 | /* Begin PBXContainerItemProxy section */ 63 | 0566B9682686B526006EE45A /* PBXContainerItemProxy */ = { 64 | isa = PBXContainerItemProxy; 65 | containerPortal = 0566B9632686B526006EE45A /* GitHubUpdates.xcodeproj */; 66 | proxyType = 2; 67 | remoteGlobalIDString = 05F82B251EF32EA700EC8A93; 68 | remoteInfo = GitHubUpdates; 69 | }; 70 | 0566B96A2686B526006EE45A /* PBXContainerItemProxy */ = { 71 | isa = PBXContainerItemProxy; 72 | containerPortal = 0566B9632686B526006EE45A /* GitHubUpdates.xcodeproj */; 73 | proxyType = 2; 74 | remoteGlobalIDString = 0555EBA01EF3DDA10016167F; 75 | remoteInfo = Relauncher; 76 | }; 77 | /* End PBXContainerItemProxy section */ 78 | 79 | /* Begin PBXCopyFilesBuildPhase section */ 80 | 0566B96F2686B531006EE45A /* Embed Frameworks */ = { 81 | isa = PBXCopyFilesBuildPhase; 82 | buildActionMask = 2147483647; 83 | dstPath = ""; 84 | dstSubfolderSpec = 10; 85 | files = ( 86 | 0566B96E2686B531006EE45A /* GitHubUpdates.framework in Embed Frameworks */, 87 | ); 88 | name = "Embed Frameworks"; 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | /* End PBXCopyFilesBuildPhase section */ 92 | 93 | /* Begin PBXFileReference section */ 94 | 050087D62949CEE400882DD8 /* PasteboardWriter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasteboardWriter.swift; sourceTree = ""; }; 95 | 050087DB2949D17E00882DD8 /* Either.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Either.swift; sourceTree = ""; }; 96 | 054776E3268A5C87005864F8 /* IODisplayItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IODisplayItem.swift; sourceTree = ""; }; 97 | 054776F0268A7BED005864F8 /* PropertyListFormatViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PropertyListFormatViewController.swift; sourceTree = ""; }; 98 | 054776F3268A7BFA005864F8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PropertyListFormatViewController.xib; sourceTree = ""; }; 99 | 054776F5268A85B6005864F8 /* Icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Icon.icns; sourceTree = ""; }; 100 | 0552FE462948FC7300DAA87A /* PropertyValueTransformer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PropertyValueTransformer.swift; sourceTree = ""; }; 101 | 0552FE49294907FE00DAA87A /* Data.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Data.swift; sourceTree = ""; }; 102 | 05646B9A268501B300707676 /* IOBrowser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IOBrowser.app; sourceTree = BUILT_PRODUCTS_DIR; }; 103 | 05646BA4268501B400707676 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 104 | 05646BA5268501B400707676 /* IOBrowser.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = IOBrowser.entitlements; sourceTree = ""; }; 105 | 05646BAF2685020A00707676 /* ApplicationDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApplicationDelegate.swift; sourceTree = ""; }; 106 | 05646BB22685020A00707676 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 107 | 05646BB8268503D300707676 /* Release - ccache.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Release - ccache.xcconfig"; sourceTree = ""; }; 108 | 05646BB9268503D300707676 /* Common.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Common.xcconfig; sourceTree = ""; }; 109 | 05646BBA268503D300707676 /* Debug - ccache.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Debug - ccache.xcconfig"; sourceTree = ""; }; 110 | 05646BBB268503D300707676 /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; 111 | 05646BBC268503D300707676 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 112 | 05646BBD268503D300707676 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 113 | 05646BBE268503D300707676 /* Release - Library.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Release - Library.xcconfig"; sourceTree = ""; }; 114 | 05646BC0268503D300707676 /* Signing.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Signing.xcconfig; sourceTree = ""; }; 115 | 05646BC1268503D300707676 /* Architectures.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Architectures.xcconfig; sourceTree = ""; }; 116 | 05646BC3268503D300707676 /* Issues.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Issues.xcconfig; sourceTree = ""; }; 117 | 05646BC5268503D300707676 /* Apple-APIs.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Apple-APIs.xcconfig"; sourceTree = ""; }; 118 | 05646BC6268503D300707676 /* Generic-Issues.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Generic-Issues.xcconfig"; sourceTree = ""; }; 119 | 05646BC7268503D300707676 /* Security.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Security.xcconfig; sourceTree = ""; }; 120 | 05646BC8268503D300707676 /* Objective-C.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Objective-C.xcconfig"; sourceTree = ""; }; 121 | 05646BC9268503D300707676 /* Analysis-Policy.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Analysis-Policy.xcconfig"; sourceTree = ""; }; 122 | 05646BCA268503D300707676 /* Deployment.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Deployment.xcconfig; sourceTree = ""; }; 123 | 05646BCB268503D300707676 /* Build-Options.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Build-Options.xcconfig"; sourceTree = ""; }; 124 | 05646BCC268503D300707676 /* Swift-Compiler.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Swift-Compiler.xcconfig"; sourceTree = ""; }; 125 | 05646BCD268503D300707676 /* Static-Analyzer.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Static-Analyzer.xcconfig"; sourceTree = ""; }; 126 | 05646BCF268503D300707676 /* Warnings-Policies.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Warnings-Policies.xcconfig"; sourceTree = ""; }; 127 | 05646BD0268503D300707676 /* Code-Generation.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Code-Generation.xcconfig"; sourceTree = ""; }; 128 | 05646BD1268503D300707676 /* Language.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Language.xcconfig; sourceTree = ""; }; 129 | 05646BD2268503D300707676 /* General.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = General.xcconfig; sourceTree = ""; }; 130 | 05646BD3268503D300707676 /* Search-Paths.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Search-Paths.xcconfig"; sourceTree = ""; }; 131 | 05646BD4268503D300707676 /* Apple-LLVM.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Apple-LLVM.xcconfig"; sourceTree = ""; }; 132 | 05646BD7268503D300707676 /* Modules.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Modules.xcconfig; sourceTree = ""; }; 133 | 05646BD8268503D300707676 /* Objective-C.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Objective-C.xcconfig"; sourceTree = ""; }; 134 | 05646BD9268503D300707676 /* C++.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "C++.xcconfig"; sourceTree = ""; }; 135 | 05646BDA268503D300707676 /* Code-Generation.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Code-Generation.xcconfig"; sourceTree = ""; }; 136 | 05646BDB268503D300707676 /* Address-Sanitizer.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Address-Sanitizer.xcconfig"; sourceTree = ""; }; 137 | 05646BDC268503D300707676 /* Language.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Language.xcconfig; sourceTree = ""; }; 138 | 05646BDD268503D300707676 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 139 | 05646BDE268503D300707676 /* Undefined-Behavior-Sanitizer.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Undefined-Behavior-Sanitizer.xcconfig"; sourceTree = ""; }; 140 | 05646BDF268503D300707676 /* Warning-Policies.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Warning-Policies.xcconfig"; sourceTree = ""; }; 141 | 05646BE1268503D300707676 /* Objective-C-ARC.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Objective-C-ARC.xcconfig"; sourceTree = ""; }; 142 | 05646BE2268503D300707676 /* Objective-C.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Objective-C.xcconfig"; sourceTree = ""; }; 143 | 05646BE3268503D300707676 /* C++.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "C++.xcconfig"; sourceTree = ""; }; 144 | 05646BE4268503D300707676 /* All-Languages.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "All-Languages.xcconfig"; sourceTree = ""; }; 145 | 05646BE5268503D300707676 /* Preprocessing.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Preprocessing.xcconfig; sourceTree = ""; }; 146 | 05646BE6268503D300707676 /* Debug - Library.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Debug - Library.xcconfig"; sourceTree = ""; }; 147 | 05646BE7268503D300707676 /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitignore; sourceTree = ""; }; 148 | 05646BE9268503D300707676 /* ccache-config.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "ccache-config.sh"; sourceTree = ""; }; 149 | 05646BEA268503D300707676 /* ccache.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = ccache.sh; sourceTree = ""; }; 150 | 05646BEB268503D300707676 /* Debug - zld.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Debug - zld.xcconfig"; sourceTree = ""; }; 151 | 05646BEE2685055F00707676 /* AboutWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutWindowController.swift; sourceTree = ""; }; 152 | 05646BF12685058700707676 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/AboutWindowController.xib; sourceTree = ""; }; 153 | 05646BF62685064C00707676 /* MainWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainWindowController.swift; sourceTree = ""; }; 154 | 05646BF92685072900707676 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainWindowController.xib; sourceTree = ""; }; 155 | 05646C03268527E400707676 /* IOBrowser-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "IOBrowser-Bridging-Header.h"; sourceTree = ""; }; 156 | 0566B9632686B526006EE45A /* GitHubUpdates.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GitHubUpdates.xcodeproj; path = Submodules/GitHubUpdates/GitHubUpdates.xcodeproj; sourceTree = ""; }; 157 | 059861E8292B9B7000B20BBD /* IOBrowser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IOBrowser.app; sourceTree = BUILT_PRODUCTS_DIR; }; 158 | 059861EC292B9BA500B20BBD /* IOBrowser-AppStore.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "IOBrowser-AppStore.entitlements"; sourceTree = ""; }; 159 | 05B886B52688BE2E00E8A413 /* Preferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = ""; }; 160 | 05B886B82688CB1200E8A413 /* IOObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IOObject.swift; sourceTree = ""; }; 161 | 05B886BA2688F44E00E8A413 /* PropertiesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PropertiesViewController.swift; path = IOBrowser/Classes/PropertiesViewController.swift; sourceTree = SOURCE_ROOT; }; 162 | 05B886BD2688F4AA00E8A413 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PropertiesViewController.xib; sourceTree = ""; }; 163 | 05B886BF2689C64F00E8A413 /* PropertyListNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PropertyListNode.swift; sourceTree = ""; }; 164 | 05B88700268A382D00E8A413 /* ArrayIsEmpty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrayIsEmpty.swift; sourceTree = ""; }; 165 | 05B88704268A388700E8A413 /* ArrayIsNotEmpty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrayIsNotEmpty.swift; sourceTree = ""; }; 166 | 05B88713268A40E300E8A413 /* StackTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = StackTemplate.pdf; sourceTree = ""; }; 167 | 05B88715268A463800E8A413 /* FolderTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = FolderTemplate.pdf; sourceTree = ""; }; 168 | 05B88716268A463800E8A413 /* DocumentTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = DocumentTemplate.pdf; sourceTree = ""; }; 169 | /* End PBXFileReference section */ 170 | 171 | /* Begin PBXFrameworksBuildPhase section */ 172 | 05646B97268501B300707676 /* Frameworks */ = { 173 | isa = PBXFrameworksBuildPhase; 174 | buildActionMask = 2147483647; 175 | files = ( 176 | 0566B96D2686B531006EE45A /* GitHubUpdates.framework in Frameworks */, 177 | ); 178 | runOnlyForDeploymentPostprocessing = 0; 179 | }; 180 | 059861D6292B9B7000B20BBD /* Frameworks */ = { 181 | isa = PBXFrameworksBuildPhase; 182 | buildActionMask = 2147483647; 183 | files = ( 184 | ); 185 | runOnlyForDeploymentPostprocessing = 0; 186 | }; 187 | /* End PBXFrameworksBuildPhase section */ 188 | 189 | /* Begin PBXGroup section */ 190 | 05646B91268501B300707676 = { 191 | isa = PBXGroup; 192 | children = ( 193 | 0566B9632686B526006EE45A /* GitHubUpdates.xcodeproj */, 194 | 05646BB7268503D300707676 /* xcconfig */, 195 | 05646B9C268501B300707676 /* IOBrowser */, 196 | 05646B9B268501B300707676 /* Products */, 197 | 0566B96C2686B531006EE45A /* Frameworks */, 198 | ); 199 | sourceTree = ""; 200 | }; 201 | 05646B9B268501B300707676 /* Products */ = { 202 | isa = PBXGroup; 203 | children = ( 204 | 05646B9A268501B300707676 /* IOBrowser.app */, 205 | 059861E8292B9B7000B20BBD /* IOBrowser.app */, 206 | ); 207 | name = Products; 208 | sourceTree = ""; 209 | }; 210 | 05646B9C268501B300707676 /* IOBrowser */ = { 211 | isa = PBXGroup; 212 | children = ( 213 | 05646BAD2685020A00707676 /* Classes */, 214 | 05646BB02685020A00707676 /* UI */, 215 | 05646BB62685021500707676 /* Supporting Files */, 216 | ); 217 | path = IOBrowser; 218 | sourceTree = ""; 219 | }; 220 | 05646BAD2685020A00707676 /* Classes */ = { 221 | isa = PBXGroup; 222 | children = ( 223 | 05646BEE2685055F00707676 /* AboutWindowController.swift */, 224 | 05646BAF2685020A00707676 /* ApplicationDelegate.swift */, 225 | 05B88700268A382D00E8A413 /* ArrayIsEmpty.swift */, 226 | 05B88704268A388700E8A413 /* ArrayIsNotEmpty.swift */, 227 | 05B886B82688CB1200E8A413 /* IOObject.swift */, 228 | 054776E3268A5C87005864F8 /* IODisplayItem.swift */, 229 | 05646BF62685064C00707676 /* MainWindowController.swift */, 230 | 05B886B52688BE2E00E8A413 /* Preferences.swift */, 231 | 05B886BA2688F44E00E8A413 /* PropertiesViewController.swift */, 232 | 05B886BF2689C64F00E8A413 /* PropertyListNode.swift */, 233 | 054776F0268A7BED005864F8 /* PropertyListFormatViewController.swift */, 234 | 0552FE462948FC7300DAA87A /* PropertyValueTransformer.swift */, 235 | 0552FE49294907FE00DAA87A /* Data.swift */, 236 | 050087D62949CEE400882DD8 /* PasteboardWriter.swift */, 237 | 050087DB2949D17E00882DD8 /* Either.swift */, 238 | ); 239 | path = Classes; 240 | sourceTree = ""; 241 | }; 242 | 05646BB02685020A00707676 /* UI */ = { 243 | isa = PBXGroup; 244 | children = ( 245 | 05B88706268A3ECB00E8A413 /* Images */, 246 | 05646BF02685058700707676 /* AboutWindowController.xib */, 247 | 05646BB12685020A00707676 /* MainMenu.xib */, 248 | 05646BF82685072900707676 /* MainWindowController.xib */, 249 | 05B886BC2688F4AA00E8A413 /* PropertiesViewController.xib */, 250 | 054776F2268A7BFA005864F8 /* PropertyListFormatViewController.xib */, 251 | ); 252 | path = UI; 253 | sourceTree = ""; 254 | }; 255 | 05646BB62685021500707676 /* Supporting Files */ = { 256 | isa = PBXGroup; 257 | children = ( 258 | 05646BA4268501B400707676 /* Info.plist */, 259 | 05646C03268527E400707676 /* IOBrowser-Bridging-Header.h */, 260 | 05646BA5268501B400707676 /* IOBrowser.entitlements */, 261 | 059861EC292B9BA500B20BBD /* IOBrowser-AppStore.entitlements */, 262 | ); 263 | name = "Supporting Files"; 264 | sourceTree = ""; 265 | }; 266 | 05646BB7268503D300707676 /* xcconfig */ = { 267 | isa = PBXGroup; 268 | children = ( 269 | 05646BB8268503D300707676 /* Release - ccache.xcconfig */, 270 | 05646BB9268503D300707676 /* Common.xcconfig */, 271 | 05646BBA268503D300707676 /* Debug - ccache.xcconfig */, 272 | 05646BBB268503D300707676 /* Debug.xcconfig */, 273 | 05646BBC268503D300707676 /* Release.xcconfig */, 274 | 05646BBD268503D300707676 /* README.md */, 275 | 05646BBE268503D300707676 /* Release - Library.xcconfig */, 276 | 05646BBF268503D300707676 /* Common */, 277 | 05646BE6268503D300707676 /* Debug - Library.xcconfig */, 278 | 05646BE7268503D300707676 /* .gitignore */, 279 | 05646BE8268503D300707676 /* Scripts */, 280 | 05646BEB268503D300707676 /* Debug - zld.xcconfig */, 281 | ); 282 | name = xcconfig; 283 | path = Submodules/xcconfig; 284 | sourceTree = ""; 285 | }; 286 | 05646BBF268503D300707676 /* Common */ = { 287 | isa = PBXGroup; 288 | children = ( 289 | 05646BC0268503D300707676 /* Signing.xcconfig */, 290 | 05646BC1268503D300707676 /* Architectures.xcconfig */, 291 | 05646BC2268503D300707676 /* Static-Analyzer */, 292 | 05646BCA268503D300707676 /* Deployment.xcconfig */, 293 | 05646BCB268503D300707676 /* Build-Options.xcconfig */, 294 | 05646BCC268503D300707676 /* Swift-Compiler.xcconfig */, 295 | 05646BCD268503D300707676 /* Static-Analyzer.xcconfig */, 296 | 05646BCE268503D300707676 /* Swift-Compiler */, 297 | 05646BD3268503D300707676 /* Search-Paths.xcconfig */, 298 | 05646BD4268503D300707676 /* Apple-LLVM.xcconfig */, 299 | 05646BD5268503D300707676 /* Apple-LLVM */, 300 | ); 301 | path = Common; 302 | sourceTree = ""; 303 | }; 304 | 05646BC2268503D300707676 /* Static-Analyzer */ = { 305 | isa = PBXGroup; 306 | children = ( 307 | 05646BC3268503D300707676 /* Issues.xcconfig */, 308 | 05646BC4268503D300707676 /* Issues */, 309 | ); 310 | path = "Static-Analyzer"; 311 | sourceTree = ""; 312 | }; 313 | 05646BC4268503D300707676 /* Issues */ = { 314 | isa = PBXGroup; 315 | children = ( 316 | 05646BC5268503D300707676 /* Apple-APIs.xcconfig */, 317 | 05646BC6268503D300707676 /* Generic-Issues.xcconfig */, 318 | 05646BC7268503D300707676 /* Security.xcconfig */, 319 | 05646BC8268503D300707676 /* Objective-C.xcconfig */, 320 | 05646BC9268503D300707676 /* Analysis-Policy.xcconfig */, 321 | ); 322 | path = Issues; 323 | sourceTree = ""; 324 | }; 325 | 05646BCE268503D300707676 /* Swift-Compiler */ = { 326 | isa = PBXGroup; 327 | children = ( 328 | 05646BCF268503D300707676 /* Warnings-Policies.xcconfig */, 329 | 05646BD0268503D300707676 /* Code-Generation.xcconfig */, 330 | 05646BD1268503D300707676 /* Language.xcconfig */, 331 | 05646BD2268503D300707676 /* General.xcconfig */, 332 | ); 333 | path = "Swift-Compiler"; 334 | sourceTree = ""; 335 | }; 336 | 05646BD5268503D300707676 /* Apple-LLVM */ = { 337 | isa = PBXGroup; 338 | children = ( 339 | 05646BD6268503D300707676 /* Language */, 340 | 05646BDA268503D300707676 /* Code-Generation.xcconfig */, 341 | 05646BDB268503D300707676 /* Address-Sanitizer.xcconfig */, 342 | 05646BDC268503D300707676 /* Language.xcconfig */, 343 | 05646BDD268503D300707676 /* Warnings.xcconfig */, 344 | 05646BDE268503D300707676 /* Undefined-Behavior-Sanitizer.xcconfig */, 345 | 05646BDF268503D300707676 /* Warning-Policies.xcconfig */, 346 | 05646BE0268503D300707676 /* Warnings */, 347 | 05646BE5268503D300707676 /* Preprocessing.xcconfig */, 348 | ); 349 | path = "Apple-LLVM"; 350 | sourceTree = ""; 351 | }; 352 | 05646BD6268503D300707676 /* Language */ = { 353 | isa = PBXGroup; 354 | children = ( 355 | 05646BD7268503D300707676 /* Modules.xcconfig */, 356 | 05646BD8268503D300707676 /* Objective-C.xcconfig */, 357 | 05646BD9268503D300707676 /* C++.xcconfig */, 358 | ); 359 | path = Language; 360 | sourceTree = ""; 361 | }; 362 | 05646BE0268503D300707676 /* Warnings */ = { 363 | isa = PBXGroup; 364 | children = ( 365 | 05646BE1268503D300707676 /* Objective-C-ARC.xcconfig */, 366 | 05646BE2268503D300707676 /* Objective-C.xcconfig */, 367 | 05646BE3268503D300707676 /* C++.xcconfig */, 368 | 05646BE4268503D300707676 /* All-Languages.xcconfig */, 369 | ); 370 | path = Warnings; 371 | sourceTree = ""; 372 | }; 373 | 05646BE8268503D300707676 /* Scripts */ = { 374 | isa = PBXGroup; 375 | children = ( 376 | 05646BE9268503D300707676 /* ccache-config.sh */, 377 | 05646BEA268503D300707676 /* ccache.sh */, 378 | ); 379 | path = Scripts; 380 | sourceTree = ""; 381 | }; 382 | 0566B9642686B526006EE45A /* Products */ = { 383 | isa = PBXGroup; 384 | children = ( 385 | 0566B9692686B526006EE45A /* GitHubUpdates.framework */, 386 | 0566B96B2686B526006EE45A /* Relauncher */, 387 | ); 388 | name = Products; 389 | sourceTree = ""; 390 | }; 391 | 0566B96C2686B531006EE45A /* Frameworks */ = { 392 | isa = PBXGroup; 393 | children = ( 394 | ); 395 | name = Frameworks; 396 | sourceTree = ""; 397 | }; 398 | 05B88706268A3ECB00E8A413 /* Images */ = { 399 | isa = PBXGroup; 400 | children = ( 401 | 054776F5268A85B6005864F8 /* Icon.icns */, 402 | 05B88716268A463800E8A413 /* DocumentTemplate.pdf */, 403 | 05B88715268A463800E8A413 /* FolderTemplate.pdf */, 404 | 05B88713268A40E300E8A413 /* StackTemplate.pdf */, 405 | ); 406 | path = Images; 407 | sourceTree = ""; 408 | }; 409 | /* End PBXGroup section */ 410 | 411 | /* Begin PBXNativeTarget section */ 412 | 05646B99268501B300707676 /* IOBrowser */ = { 413 | isa = PBXNativeTarget; 414 | buildConfigurationList = 05646BA8268501B400707676 /* Build configuration list for PBXNativeTarget "IOBrowser" */; 415 | buildPhases = ( 416 | 05646B96268501B300707676 /* Sources */, 417 | 05646B97268501B300707676 /* Frameworks */, 418 | 05646BED268503FE00707676 /* ShellScript */, 419 | 05646B98268501B300707676 /* Resources */, 420 | 0566B96F2686B531006EE45A /* Embed Frameworks */, 421 | ); 422 | buildRules = ( 423 | ); 424 | dependencies = ( 425 | ); 426 | name = IOBrowser; 427 | productName = Sensors; 428 | productReference = 05646B9A268501B300707676 /* IOBrowser.app */; 429 | productType = "com.apple.product-type.application"; 430 | }; 431 | 059861C9292B9B7000B20BBD /* IOBrowser AppStore */ = { 432 | isa = PBXNativeTarget; 433 | buildConfigurationList = 059861E5292B9B7000B20BBD /* Build configuration list for PBXNativeTarget "IOBrowser AppStore" */; 434 | buildPhases = ( 435 | 059861CA292B9B7000B20BBD /* Sources */, 436 | 059861D6292B9B7000B20BBD /* Frameworks */, 437 | 059861D9292B9B7000B20BBD /* Resources */, 438 | ); 439 | buildRules = ( 440 | ); 441 | dependencies = ( 442 | ); 443 | name = "IOBrowser AppStore"; 444 | productName = Sensors; 445 | productReference = 059861E8292B9B7000B20BBD /* IOBrowser.app */; 446 | productType = "com.apple.product-type.application"; 447 | }; 448 | /* End PBXNativeTarget section */ 449 | 450 | /* Begin PBXProject section */ 451 | 05646B92268501B300707676 /* Project object */ = { 452 | isa = PBXProject; 453 | attributes = { 454 | LastSwiftUpdateCheck = 1250; 455 | LastUpgradeCheck = 1250; 456 | TargetAttributes = { 457 | 05646B99268501B300707676 = { 458 | CreatedOnToolsVersion = 12.5.1; 459 | LastSwiftMigration = 1250; 460 | }; 461 | }; 462 | }; 463 | buildConfigurationList = 05646B95268501B300707676 /* Build configuration list for PBXProject "IOBrowser" */; 464 | compatibilityVersion = "Xcode 9.3"; 465 | developmentRegion = en; 466 | hasScannedForEncodings = 0; 467 | knownRegions = ( 468 | en, 469 | Base, 470 | ); 471 | mainGroup = 05646B91268501B300707676; 472 | productRefGroup = 05646B9B268501B300707676 /* Products */; 473 | projectDirPath = ""; 474 | projectReferences = ( 475 | { 476 | ProductGroup = 0566B9642686B526006EE45A /* Products */; 477 | ProjectRef = 0566B9632686B526006EE45A /* GitHubUpdates.xcodeproj */; 478 | }, 479 | ); 480 | projectRoot = ""; 481 | targets = ( 482 | 05646B99268501B300707676 /* IOBrowser */, 483 | 059861C9292B9B7000B20BBD /* IOBrowser AppStore */, 484 | ); 485 | }; 486 | /* End PBXProject section */ 487 | 488 | /* Begin PBXReferenceProxy section */ 489 | 0566B9692686B526006EE45A /* GitHubUpdates.framework */ = { 490 | isa = PBXReferenceProxy; 491 | fileType = wrapper.framework; 492 | path = GitHubUpdates.framework; 493 | remoteRef = 0566B9682686B526006EE45A /* PBXContainerItemProxy */; 494 | sourceTree = BUILT_PRODUCTS_DIR; 495 | }; 496 | 0566B96B2686B526006EE45A /* Relauncher */ = { 497 | isa = PBXReferenceProxy; 498 | fileType = "compiled.mach-o.executable"; 499 | path = Relauncher; 500 | remoteRef = 0566B96A2686B526006EE45A /* PBXContainerItemProxy */; 501 | sourceTree = BUILT_PRODUCTS_DIR; 502 | }; 503 | /* End PBXReferenceProxy section */ 504 | 505 | /* Begin PBXResourcesBuildPhase section */ 506 | 05646B98268501B300707676 /* Resources */ = { 507 | isa = PBXResourcesBuildPhase; 508 | buildActionMask = 2147483647; 509 | files = ( 510 | 05646BB52685020A00707676 /* MainMenu.xib in Resources */, 511 | 05B886BE2688F4AA00E8A413 /* PropertiesViewController.xib in Resources */, 512 | 05B88717268A463800E8A413 /* FolderTemplate.pdf in Resources */, 513 | 05646BFA2685072900707676 /* MainWindowController.xib in Resources */, 514 | 05B88718268A463800E8A413 /* DocumentTemplate.pdf in Resources */, 515 | 05B88714268A40E300E8A413 /* StackTemplate.pdf in Resources */, 516 | 054776F6268A85B6005864F8 /* Icon.icns in Resources */, 517 | 054776F4268A7BFA005864F8 /* PropertyListFormatViewController.xib in Resources */, 518 | 05646BF22685058700707676 /* AboutWindowController.xib in Resources */, 519 | ); 520 | runOnlyForDeploymentPostprocessing = 0; 521 | }; 522 | 059861D9292B9B7000B20BBD /* Resources */ = { 523 | isa = PBXResourcesBuildPhase; 524 | buildActionMask = 2147483647; 525 | files = ( 526 | 059861DA292B9B7000B20BBD /* MainMenu.xib in Resources */, 527 | 059861DB292B9B7000B20BBD /* PropertiesViewController.xib in Resources */, 528 | 059861DC292B9B7000B20BBD /* FolderTemplate.pdf in Resources */, 529 | 059861DD292B9B7000B20BBD /* MainWindowController.xib in Resources */, 530 | 059861DE292B9B7000B20BBD /* DocumentTemplate.pdf in Resources */, 531 | 059861DF292B9B7000B20BBD /* StackTemplate.pdf in Resources */, 532 | 059861E0292B9B7000B20BBD /* Icon.icns in Resources */, 533 | 059861E1292B9B7000B20BBD /* PropertyListFormatViewController.xib in Resources */, 534 | 059861E2292B9B7000B20BBD /* AboutWindowController.xib in Resources */, 535 | ); 536 | runOnlyForDeploymentPostprocessing = 0; 537 | }; 538 | /* End PBXResourcesBuildPhase section */ 539 | 540 | /* Begin PBXShellScriptBuildPhase section */ 541 | 05646BED268503FE00707676 /* ShellScript */ = { 542 | isa = PBXShellScriptBuildPhase; 543 | alwaysOutOfDate = 1; 544 | buildActionMask = 2147483647; 545 | files = ( 546 | ); 547 | inputFileListPaths = ( 548 | ); 549 | inputPaths = ( 550 | ); 551 | outputFileListPaths = ( 552 | ); 553 | outputPaths = ( 554 | ); 555 | runOnlyForDeploymentPostprocessing = 0; 556 | shellPath = /bin/sh; 557 | shellScript = "#!/bin/bash\nif [ \"${CONFIGURATION}\" = \"Release\" ]; then\n plist=\"IOBrowser/Info.plist\"\n rev=$(git rev-list `git branch | grep -e \"^*\" | cut -d' ' -f 2` | wc -l)\n /usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $rev\" \"$plist\"\nfi\n"; 558 | }; 559 | /* End PBXShellScriptBuildPhase section */ 560 | 561 | /* Begin PBXSourcesBuildPhase section */ 562 | 05646B96268501B300707676 /* Sources */ = { 563 | isa = PBXSourcesBuildPhase; 564 | buildActionMask = 2147483647; 565 | files = ( 566 | 05B88701268A382D00E8A413 /* ArrayIsEmpty.swift in Sources */, 567 | 050087D72949CEE400882DD8 /* PasteboardWriter.swift in Sources */, 568 | 05B886C02689C64F00E8A413 /* PropertyListNode.swift in Sources */, 569 | 05B886B92688CB1200E8A413 /* IOObject.swift in Sources */, 570 | 050087DC2949D17E00882DD8 /* Either.swift in Sources */, 571 | 054776E4268A5C87005864F8 /* IODisplayItem.swift in Sources */, 572 | 05646BB42685020A00707676 /* ApplicationDelegate.swift in Sources */, 573 | 05646BEF2685055F00707676 /* AboutWindowController.swift in Sources */, 574 | 0552FE472948FC7300DAA87A /* PropertyValueTransformer.swift in Sources */, 575 | 05B886BB2688F44E00E8A413 /* PropertiesViewController.swift in Sources */, 576 | 0552FE4A294907FE00DAA87A /* Data.swift in Sources */, 577 | 05B886B62688BE2E00E8A413 /* Preferences.swift in Sources */, 578 | 05646BF72685064C00707676 /* MainWindowController.swift in Sources */, 579 | 054776F1268A7BED005864F8 /* PropertyListFormatViewController.swift in Sources */, 580 | 05B88705268A388700E8A413 /* ArrayIsNotEmpty.swift in Sources */, 581 | ); 582 | runOnlyForDeploymentPostprocessing = 0; 583 | }; 584 | 059861CA292B9B7000B20BBD /* Sources */ = { 585 | isa = PBXSourcesBuildPhase; 586 | buildActionMask = 2147483647; 587 | files = ( 588 | 059861CB292B9B7000B20BBD /* ArrayIsEmpty.swift in Sources */, 589 | 050087E8294A661C00882DD8 /* PasteboardWriter.swift in Sources */, 590 | 059861CC292B9B7000B20BBD /* PropertyListNode.swift in Sources */, 591 | 059861CD292B9B7000B20BBD /* IOObject.swift in Sources */, 592 | 050087E9294A661F00882DD8 /* Either.swift in Sources */, 593 | 059861CE292B9B7000B20BBD /* IODisplayItem.swift in Sources */, 594 | 059861CF292B9B7000B20BBD /* ApplicationDelegate.swift in Sources */, 595 | 059861D0292B9B7000B20BBD /* AboutWindowController.swift in Sources */, 596 | 0552FE482948FC7300DAA87A /* PropertyValueTransformer.swift in Sources */, 597 | 059861D1292B9B7000B20BBD /* PropertiesViewController.swift in Sources */, 598 | 0552FE4B294907FE00DAA87A /* Data.swift in Sources */, 599 | 059861D2292B9B7000B20BBD /* Preferences.swift in Sources */, 600 | 059861D3292B9B7000B20BBD /* MainWindowController.swift in Sources */, 601 | 059861D4292B9B7000B20BBD /* PropertyListFormatViewController.swift in Sources */, 602 | 059861D5292B9B7000B20BBD /* ArrayIsNotEmpty.swift in Sources */, 603 | ); 604 | runOnlyForDeploymentPostprocessing = 0; 605 | }; 606 | /* End PBXSourcesBuildPhase section */ 607 | 608 | /* Begin PBXVariantGroup section */ 609 | 054776F2268A7BFA005864F8 /* PropertyListFormatViewController.xib */ = { 610 | isa = PBXVariantGroup; 611 | children = ( 612 | 054776F3268A7BFA005864F8 /* Base */, 613 | ); 614 | name = PropertyListFormatViewController.xib; 615 | sourceTree = ""; 616 | }; 617 | 05646BB12685020A00707676 /* MainMenu.xib */ = { 618 | isa = PBXVariantGroup; 619 | children = ( 620 | 05646BB22685020A00707676 /* Base */, 621 | ); 622 | name = MainMenu.xib; 623 | sourceTree = ""; 624 | }; 625 | 05646BF02685058700707676 /* AboutWindowController.xib */ = { 626 | isa = PBXVariantGroup; 627 | children = ( 628 | 05646BF12685058700707676 /* Base */, 629 | ); 630 | name = AboutWindowController.xib; 631 | sourceTree = ""; 632 | }; 633 | 05646BF82685072900707676 /* MainWindowController.xib */ = { 634 | isa = PBXVariantGroup; 635 | children = ( 636 | 05646BF92685072900707676 /* Base */, 637 | ); 638 | name = MainWindowController.xib; 639 | sourceTree = ""; 640 | }; 641 | 05B886BC2688F4AA00E8A413 /* PropertiesViewController.xib */ = { 642 | isa = PBXVariantGroup; 643 | children = ( 644 | 05B886BD2688F4AA00E8A413 /* Base */, 645 | ); 646 | name = PropertiesViewController.xib; 647 | sourceTree = ""; 648 | }; 649 | /* End PBXVariantGroup section */ 650 | 651 | /* Begin XCBuildConfiguration section */ 652 | 05646BA6268501B400707676 /* Debug */ = { 653 | isa = XCBuildConfiguration; 654 | baseConfigurationReference = 05646BBB268503D300707676 /* Debug.xcconfig */; 655 | buildSettings = { 656 | MACOSX_DEPLOYMENT_TARGET = 11.0; 657 | }; 658 | name = Debug; 659 | }; 660 | 05646BA7268501B400707676 /* Release */ = { 661 | isa = XCBuildConfiguration; 662 | baseConfigurationReference = 05646BBC268503D300707676 /* Release.xcconfig */; 663 | buildSettings = { 664 | MACOSX_DEPLOYMENT_TARGET = 11.0; 665 | }; 666 | name = Release; 667 | }; 668 | 05646BA9268501B400707676 /* Debug */ = { 669 | isa = XCBuildConfiguration; 670 | buildSettings = { 671 | CLANG_ENABLE_MODULES = YES; 672 | CODE_SIGN_ENTITLEMENTS = IOBrowser/IOBrowser.entitlements; 673 | CODE_SIGN_STYLE = Automatic; 674 | DEVELOPMENT_TEAM = 326Y53CJMD; 675 | ENABLE_HARDENED_RUNTIME = YES; 676 | INFOPLIST_FILE = IOBrowser/Info.plist; 677 | LD_RUNPATH_SEARCH_PATHS = ( 678 | "$(inherited)", 679 | "@executable_path/../Frameworks", 680 | ); 681 | PRODUCT_BUNDLE_IDENTIFIER = "com.xs-labs.IOBrowser"; 682 | PRODUCT_NAME = IOBrowser; 683 | SWIFT_OBJC_BRIDGING_HEADER = "IOBrowser/IOBrowser-Bridging-Header.h"; 684 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 685 | SWIFT_VERSION = 5.0; 686 | }; 687 | name = Debug; 688 | }; 689 | 05646BAA268501B400707676 /* Release */ = { 690 | isa = XCBuildConfiguration; 691 | buildSettings = { 692 | CLANG_ENABLE_MODULES = YES; 693 | CODE_SIGN_ENTITLEMENTS = IOBrowser/IOBrowser.entitlements; 694 | CODE_SIGN_STYLE = Automatic; 695 | DEVELOPMENT_TEAM = 326Y53CJMD; 696 | ENABLE_HARDENED_RUNTIME = YES; 697 | INFOPLIST_FILE = IOBrowser/Info.plist; 698 | LD_RUNPATH_SEARCH_PATHS = ( 699 | "$(inherited)", 700 | "@executable_path/../Frameworks", 701 | ); 702 | PRODUCT_BUNDLE_IDENTIFIER = "com.xs-labs.IOBrowser"; 703 | PRODUCT_NAME = IOBrowser; 704 | SWIFT_OBJC_BRIDGING_HEADER = "IOBrowser/IOBrowser-Bridging-Header.h"; 705 | SWIFT_VERSION = 5.0; 706 | }; 707 | name = Release; 708 | }; 709 | 059861E6292B9B7000B20BBD /* Debug */ = { 710 | isa = XCBuildConfiguration; 711 | buildSettings = { 712 | CLANG_ENABLE_MODULES = YES; 713 | CODE_SIGN_ENTITLEMENTS = "IOBrowser/IOBrowser-AppStore.entitlements"; 714 | CODE_SIGN_STYLE = Automatic; 715 | DEVELOPMENT_TEAM = 326Y53CJMD; 716 | ENABLE_HARDENED_RUNTIME = YES; 717 | GCC_PREPROCESSOR_DEFINITIONS = ( 718 | "$(inherited)", 719 | "APPSTORE=1", 720 | ); 721 | INFOPLIST_FILE = IOBrowser/Info.plist; 722 | LD_RUNPATH_SEARCH_PATHS = ( 723 | "$(inherited)", 724 | "@executable_path/../Frameworks", 725 | ); 726 | PRODUCT_BUNDLE_IDENTIFIER = "com.xs-labs.IOBrowser"; 727 | PRODUCT_NAME = IOBrowser; 728 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) APPSTORE"; 729 | SWIFT_OBJC_BRIDGING_HEADER = "IOBrowser/IOBrowser-Bridging-Header.h"; 730 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 731 | SWIFT_VERSION = 5.0; 732 | }; 733 | name = Debug; 734 | }; 735 | 059861E7292B9B7000B20BBD /* Release */ = { 736 | isa = XCBuildConfiguration; 737 | buildSettings = { 738 | CLANG_ENABLE_MODULES = YES; 739 | CODE_SIGN_ENTITLEMENTS = "IOBrowser/IOBrowser-AppStore.entitlements"; 740 | CODE_SIGN_STYLE = Automatic; 741 | DEVELOPMENT_TEAM = 326Y53CJMD; 742 | ENABLE_HARDENED_RUNTIME = YES; 743 | GCC_PREPROCESSOR_DEFINITIONS = ( 744 | "$(inherited)", 745 | "APPSTORE=1", 746 | ); 747 | INFOPLIST_FILE = IOBrowser/Info.plist; 748 | LD_RUNPATH_SEARCH_PATHS = ( 749 | "$(inherited)", 750 | "@executable_path/../Frameworks", 751 | ); 752 | PRODUCT_BUNDLE_IDENTIFIER = "com.xs-labs.IOBrowser"; 753 | PRODUCT_NAME = IOBrowser; 754 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) APPSTORE"; 755 | SWIFT_OBJC_BRIDGING_HEADER = "IOBrowser/IOBrowser-Bridging-Header.h"; 756 | SWIFT_VERSION = 5.0; 757 | }; 758 | name = Release; 759 | }; 760 | /* End XCBuildConfiguration section */ 761 | 762 | /* Begin XCConfigurationList section */ 763 | 05646B95268501B300707676 /* Build configuration list for PBXProject "IOBrowser" */ = { 764 | isa = XCConfigurationList; 765 | buildConfigurations = ( 766 | 05646BA6268501B400707676 /* Debug */, 767 | 05646BA7268501B400707676 /* Release */, 768 | ); 769 | defaultConfigurationIsVisible = 0; 770 | defaultConfigurationName = Release; 771 | }; 772 | 05646BA8268501B400707676 /* Build configuration list for PBXNativeTarget "IOBrowser" */ = { 773 | isa = XCConfigurationList; 774 | buildConfigurations = ( 775 | 05646BA9268501B400707676 /* Debug */, 776 | 05646BAA268501B400707676 /* Release */, 777 | ); 778 | defaultConfigurationIsVisible = 0; 779 | defaultConfigurationName = Release; 780 | }; 781 | 059861E5292B9B7000B20BBD /* Build configuration list for PBXNativeTarget "IOBrowser AppStore" */ = { 782 | isa = XCConfigurationList; 783 | buildConfigurations = ( 784 | 059861E6292B9B7000B20BBD /* Debug */, 785 | 059861E7292B9B7000B20BBD /* Release */, 786 | ); 787 | defaultConfigurationIsVisible = 0; 788 | defaultConfigurationName = Release; 789 | }; 790 | /* End XCConfigurationList section */ 791 | }; 792 | rootObject = 05646B92268501B300707676 /* Project object */; 793 | } 794 | -------------------------------------------------------------------------------- /IOBrowser.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /IOBrowser.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /IOBrowser.xcodeproj/xcshareddata/xcschemes/IOBrowser AppStore.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /IOBrowser.xcodeproj/xcshareddata/xcschemes/IOBrowser.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /IOBrowser/Classes/AboutWindowController.swift: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Jean-David Gadina - www.xs-labs.com 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | import Cocoa 26 | 27 | public class AboutWindowController: NSWindowController 28 | { 29 | @objc private dynamic var name: String? 30 | @objc private dynamic var version: String? 31 | @objc private dynamic var copyright: String? 32 | 33 | public override var windowNibName: NSNib.Name? 34 | { 35 | "AboutWindowController" 36 | } 37 | 38 | public override func windowDidLoad() 39 | { 40 | super.windowDidLoad() 41 | 42 | let version = Bundle.main.object( forInfoDictionaryKey: "CFBundleShortVersionString" ) as? String ?? "0.0.0" 43 | 44 | if let build = Bundle.main.object( forInfoDictionaryKey: "CFBundleVersion" ) as? String 45 | { 46 | self.version = "\(version) (\(build))" 47 | } 48 | else 49 | { 50 | self.version = version 51 | } 52 | 53 | self.name = Bundle.main.object( forInfoDictionaryKey: "CFBundleName" ) as? String 54 | self.copyright = Bundle.main.object( forInfoDictionaryKey: "NSHumanReadableCopyright" ) as? String 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /IOBrowser/Classes/ApplicationDelegate.swift: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Jean-David Gadina - www.xs-labs.com 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | import Cocoa 26 | 27 | #if !APPSTORE 28 | import GitHubUpdates 29 | #endif 30 | 31 | @main public class ApplicationDelegate: NSObject, NSApplicationDelegate 32 | { 33 | @objc private dynamic var aboutWindowController = AboutWindowController() 34 | @objc private dynamic var mainWindowController = MainWindowController() 35 | 36 | #if !APPSTORE 37 | private lazy var updater: GitHubUpdater = 38 | { 39 | let updater = GitHubUpdater() 40 | updater.user = "macmade" 41 | updater.repository = "IOBrowser" 42 | 43 | return updater 44 | }() 45 | #endif 46 | 47 | #if APPSTORE 48 | @objc private dynamic var appStore = true 49 | #else 50 | @objc private dynamic var appStore = false 51 | #endif 52 | 53 | public func applicationDidFinishLaunching( _ notification: Notification ) 54 | { 55 | self.showMainWindow( nil ) 56 | 57 | Preferences.shared.lastStart = Date() 58 | 59 | #if !APPSTORE 60 | DispatchQueue.main.asyncAfter( deadline: .now() + .seconds( 5 ) ) 61 | { 62 | self.updater.checkForUpdatesInBackground() 63 | } 64 | #endif 65 | } 66 | 67 | public func applicationWillTerminate( _ notification: Notification ) 68 | {} 69 | 70 | public func applicationShouldTerminateAfterLastWindowClosed( _ sender: NSApplication ) -> Bool 71 | { 72 | true 73 | } 74 | 75 | @IBAction public func showAboutWindow( _ sender: Any? ) 76 | { 77 | if self.aboutWindowController.window?.isVisible == false 78 | { 79 | self.aboutWindowController.window?.layoutIfNeeded() 80 | self.aboutWindowController.window?.center() 81 | } 82 | 83 | self.aboutWindowController.window?.makeKeyAndOrderFront( sender ) 84 | } 85 | 86 | @IBAction public func showMainWindow( _ sender: Any? ) 87 | { 88 | if Preferences.shared.lastStart == nil 89 | { 90 | self.mainWindowController.window?.layoutIfNeeded() 91 | self.mainWindowController.window?.center() 92 | } 93 | 94 | self.mainWindowController.window?.makeKeyAndOrderFront( sender ) 95 | } 96 | 97 | @IBAction public func invertAppearance( _ sender: Any? ) 98 | { 99 | switch NSApp.effectiveAppearance.name 100 | { 101 | case .aqua: NSApp.appearance = NSAppearance( named: .darkAqua ) 102 | case .darkAqua: NSApp.appearance = NSAppearance( named: .aqua ) 103 | case .accessibilityHighContrastAqua: NSApp.appearance = NSAppearance( named: .accessibilityHighContrastDarkAqua ) 104 | case .accessibilityHighContrastDarkAqua: NSApp.appearance = NSAppearance( named: .accessibilityHighContrastAqua ) 105 | case .vibrantLight: NSApp.appearance = NSAppearance( named: .vibrantDark ) 106 | case .vibrantDark: NSApp.appearance = NSAppearance( named: .vibrantLight ) 107 | case .accessibilityHighContrastVibrantLight: NSApp.appearance = NSAppearance( named: .accessibilityHighContrastVibrantDark ) 108 | case .accessibilityHighContrastVibrantDark: NSApp.appearance = NSAppearance( named: .accessibilityHighContrastVibrantLight ) 109 | 110 | default: NSSound.beep() 111 | } 112 | } 113 | 114 | #if APPSTORE 115 | @IBAction public func checkForUpdates( _ sender: Any? ) 116 | {} 117 | #else 118 | @IBAction public func checkForUpdates( _ sender: Any? ) 119 | { 120 | self.updater.checkForUpdates( sender ) 121 | } 122 | #endif 123 | } 124 | -------------------------------------------------------------------------------- /IOBrowser/Classes/ArrayIsEmpty.swift: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Jean-David Gadina - www.xs-labs.com 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | import Foundation 26 | 27 | @objc( ArrayIsEmpty ) 28 | public class ArrayIsEmpty: ValueTransformer 29 | { 30 | public override class func transformedValueClass() -> AnyClass 31 | { 32 | NSNumber.self 33 | } 34 | 35 | public override class func allowsReverseTransformation() -> Bool 36 | { 37 | false 38 | } 39 | 40 | public override func transformedValue( _ value: Any? ) -> Any? 41 | { 42 | guard let array = value as? NSArray else 43 | { 44 | return NSNumber( booleanLiteral: true ) 45 | } 46 | 47 | return NSNumber( booleanLiteral: array.count == 0 ) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /IOBrowser/Classes/ArrayIsNotEmpty.swift: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Jean-David Gadina - www.xs-labs.com 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | import Foundation 26 | 27 | @objc( ArrayIsNotEmpty ) 28 | public class ArrayIsNotEmpty: ValueTransformer 29 | { 30 | public override class func transformedValueClass() -> AnyClass 31 | { 32 | NSNumber.self 33 | } 34 | 35 | public override class func allowsReverseTransformation() -> Bool 36 | { 37 | false 38 | } 39 | 40 | public override func transformedValue( _ value: Any? ) -> Any? 41 | { 42 | guard let array = value as? NSArray else 43 | { 44 | return NSNumber( booleanLiteral: false ) 45 | } 46 | 47 | return NSNumber( booleanLiteral: array.count > 0 ) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /IOBrowser/Classes/Data.swift: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the Software), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | import Foundation 26 | 27 | public extension Data 28 | { 29 | func hexadecimalString() -> String 30 | { 31 | self.reduce( "0x" ) 32 | { 33 | $0.appending( String( format: "%02X", $1 ) ) 34 | } 35 | } 36 | 37 | func number() -> UInt64? 38 | { 39 | if self.count == 1 40 | { 41 | return UInt64( self[ 0 ] ) 42 | } 43 | else if self.count == 2 44 | { 45 | let n1 = UInt64( self[ 0 ] ) << 8 46 | let n2 = UInt64( self[ 1 ] ) 47 | 48 | return n1 | n2 49 | } 50 | else if self.count == 4 51 | { 52 | let n1 = UInt64( self[ 0 ] ) << 24 53 | let n2 = UInt64( self[ 1 ] ) << 16 54 | let n3 = UInt64( self[ 2 ] ) << 8 55 | let n4 = UInt64( self[ 3 ] ) 56 | 57 | return n1 | n2 | n3 | n4 58 | } 59 | else if self.count == 8 60 | { 61 | let n1 = UInt64( self[ 0 ] ) << 56 62 | let n2 = UInt64( self[ 1 ] ) << 48 63 | let n3 = UInt64( self[ 2 ] ) << 40 64 | let n4 = UInt64( self[ 3 ] ) << 32 65 | let n5 = UInt64( self[ 4 ] ) << 24 66 | let n6 = UInt64( self[ 5 ] ) << 16 67 | let n7 = UInt64( self[ 6 ] ) << 8 68 | let n8 = UInt64( self[ 7 ] ) 69 | 70 | return n1 | n2 | n3 | n4 | n5 | n6 | n7 | n8 71 | } 72 | 73 | return nil 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /IOBrowser/Classes/Either.swift: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the Software), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | import Foundation 26 | 27 | @frozen 28 | public enum Either< T1, T2 > 29 | { 30 | case left( T1 ) 31 | case right( T2 ) 32 | } 33 | -------------------------------------------------------------------------------- /IOBrowser/Classes/IODisplayItem.swift: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Jean-David Gadina - www.xs-labs.com 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | import Cocoa 26 | 27 | public class IODisplayItem: NSObject 28 | { 29 | @objc public private( set ) dynamic var object: IOObject 30 | @objc public private( set ) dynamic var name: String 31 | @objc public private( set ) dynamic var index: String 32 | @objc public private( set ) dynamic var icon: NSImage? 33 | @objc public private( set ) dynamic var allChildren: [ IODisplayItem ] 34 | @objc public private( set ) dynamic var children: [ IODisplayItem ] 35 | @objc public private( set ) dynamic var properties: [ PropertyListNode ] 36 | { 37 | didSet 38 | { 39 | self.index = IODisplayItem.index( for: self.properties ) 40 | } 41 | } 42 | 43 | public static var all: [ IODisplayItem ] 44 | { 45 | [ 46 | IODisplayItem( object: IOObject( plane: kIOServicePlane ), name: "Service", icon: NSImage( named: "StackTemplate" ) ), 47 | IODisplayItem( object: IOObject( plane: kIOPowerPlane ), name: "Power", icon: NSImage( named: "StackTemplate" ) ), 48 | IODisplayItem( object: IOObject( plane: kIODeviceTreePlane ), name: "Device Tree", icon: NSImage( named: "StackTemplate" ) ), 49 | IODisplayItem( object: IOObject( plane: kIOAudioPlane ), name: "Audio", icon: NSImage( named: "StackTemplate" ) ), 50 | IODisplayItem( object: IOObject( plane: kIOFireWirePlane ), name: "FireWire", icon: NSImage( named: "StackTemplate" ) ), 51 | IODisplayItem( object: IOObject( plane: kIOUSBPlane ), name: "USB", icon: NSImage( named: "StackTemplate" ) ) 52 | ] 53 | .compactMap { $0 } 54 | } 55 | 56 | public convenience init?( object: IOObject? ) 57 | { 58 | guard let object = object else 59 | { 60 | return nil 61 | } 62 | 63 | self.init( object: object, name: object.name, icon: NSImage( named: object.children.count == 0 ? "DocumentTemplate" : "FolderTemplate" ) ) 64 | } 65 | 66 | public init?( object: IOObject?, name: String, icon: NSImage? ) 67 | { 68 | guard let object = object else 69 | { 70 | return nil 71 | } 72 | 73 | self.object = object 74 | self.name = name 75 | self.icon = icon 76 | self.allChildren = object.children.compactMap { IODisplayItem( object: $0 ) } 77 | self.children = self.allChildren 78 | let properties = object.properties.map { PropertyListNode( key: $0.key, propertyList: $0.value ) } 79 | self.properties = properties 80 | self.index = IODisplayItem.index( for: properties ) 81 | } 82 | 83 | public var predicate: NSPredicate? 84 | { 85 | didSet 86 | { 87 | self.filter( predicate: self.predicate ) 88 | } 89 | } 90 | 91 | private func filter( predicate: NSPredicate? ) 92 | { 93 | self.allChildren.forEach { $0.predicate = predicate } 94 | 95 | guard let predicate = predicate else 96 | { 97 | self.children = self.allChildren 98 | 99 | return 100 | } 101 | 102 | self.children = self.allChildren.compactMap 103 | { 104 | predicate.evaluate( with: $0 ) || $0.children.count > 0 ? $0 : nil 105 | } 106 | } 107 | 108 | private class func index( for properties: [ PropertyListNode ] ) -> String 109 | { 110 | properties.reduce( into: [ String ]() ) 111 | { 112 | $0.append( $1.index ) 113 | } 114 | .joined( separator: " " ) 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /IOBrowser/Classes/IOObject.swift: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Jean-David Gadina - www.xs-labs.com 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | import Cocoa 26 | import CoreFoundation 27 | import IOKit 28 | 29 | @objc public class IOObject: NSObject 30 | { 31 | private static var rootEntry: io_registry_entry_t? 32 | { 33 | var port: mach_port_t = 0 34 | 35 | if IOMasterPort( UInt32( MACH_PORT_NULL ), &port ) != KERN_SUCCESS 36 | { 37 | return nil 38 | } 39 | 40 | let entry = IORegistryGetRootEntry( port ) 41 | 42 | if entry == MACH_PORT_NULL 43 | { 44 | return nil 45 | } 46 | 47 | return entry 48 | } 49 | 50 | @objc public private( set ) dynamic var name: String 51 | @objc public private( set ) dynamic var children: [ IOObject ] = [] 52 | @objc public private( set ) dynamic var properties: [ String : Any ] = [:] 53 | 54 | public convenience init?( plane: String ) 55 | { 56 | guard let entry = IOObject.rootEntry else 57 | { 58 | return nil 59 | } 60 | 61 | self.init( entry: entry, plane: plane ) 62 | } 63 | 64 | private init?( entry: io_registry_entry_t, plane: String ) 65 | { 66 | let name = UnsafeMutablePointer< CChar >.allocate( capacity: 128 ) 67 | 68 | if IORegistryEntryGetNameInPlane( entry, plane, name ) != KERN_SUCCESS 69 | { 70 | return nil 71 | } 72 | 73 | self.name = String( cString: name ) 74 | 75 | var properties: Unmanaged< CFMutableDictionary >? 76 | 77 | if IORegistryEntryCreateCFProperties( entry, &properties, kCFAllocatorDefault, 0 ) == KERN_SUCCESS 78 | { 79 | if let properties = properties?.takeRetainedValue() 80 | { 81 | self.properties = properties as? [ String : Any ] ?? [:] 82 | } 83 | } 84 | 85 | var children: io_iterator_t = 0 86 | 87 | if IORegistryEntryGetChildIterator( entry, plane, &children ) == KERN_SUCCESS 88 | { 89 | var next = IOIteratorNext( children ) 90 | 91 | while next != 0 92 | { 93 | if let child = IOObject( entry: next, plane: plane ) 94 | { 95 | self.children.append( child ) 96 | } 97 | 98 | IOObjectRelease( next ) 99 | 100 | next = IOIteratorNext( children ) 101 | } 102 | 103 | IOObjectRelease( children ) 104 | } 105 | } 106 | 107 | public override var description: String 108 | { 109 | "\( super.description ): \( self.name )" 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /IOBrowser/Classes/MainWindowController.swift: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the Software), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | import Cocoa 26 | 27 | public class MainWindowController: NSWindowController, NSOutlineViewDelegate, NSOutlineViewDataSource 28 | { 29 | @objc private dynamic var loading = true 30 | @objc private dynamic var items = [ IODisplayItem ]() 31 | @objc private dynamic var selectedObject: IODisplayItem? 32 | 33 | @objc private dynamic var searchText: String? 34 | { 35 | didSet 36 | { 37 | self.filter( text: self.searchText ) 38 | } 39 | } 40 | 41 | @objc private dynamic var searchInProperties = true 42 | { 43 | didSet 44 | { 45 | self.filter( text: self.searchText ) 46 | } 47 | } 48 | 49 | @IBOutlet private var treeController: NSTreeController! 50 | @IBOutlet private var outlineView: NSOutlineView! 51 | @IBOutlet private var propertiesView: NSView! 52 | @IBOutlet private var searchField: NSSearchField! 53 | @IBOutlet private var searchOptions: NSMenu! 54 | 55 | private var selectionObserver: NSKeyValueObservation? 56 | private var propertiesViewController: PropertiesViewController? 57 | 58 | public override var windowNibName: NSNib.Name? 59 | { 60 | "MainWindowController" 61 | } 62 | 63 | public override func windowDidLoad() 64 | { 65 | super.windowDidLoad() 66 | 67 | self.outlineView.setDraggingSourceOperationMask( .copy, forLocal: false ) 68 | 69 | self.treeController.sortDescriptors = 70 | [ 71 | NSSortDescriptor( key: "name", ascending: true, selector: #selector( NSString.localizedCaseInsensitiveCompare( _: ) ) ), 72 | ] 73 | 74 | self.selectionObserver = self.treeController.observe( \.selectedObjects ) 75 | { 76 | [ weak self ] o, c in self?.selectionDidChange() 77 | } 78 | 79 | self.load() 80 | } 81 | 82 | private func load() 83 | { 84 | DispatchQueue.global( qos: .userInitiated ).async 85 | { 86 | let items = IODisplayItem.all 87 | 88 | DispatchQueue.main.async 89 | { 90 | self.items = items 91 | 92 | DispatchQueue.main.async 93 | { 94 | self.expandFirstLevel() 95 | 96 | self.loading = false 97 | } 98 | } 99 | } 100 | } 101 | 102 | private func selectionDidChange() 103 | { 104 | self.selectedObject?.properties.forEach { $0.predicate = nil } 105 | 106 | self.selectedObject = self.treeController.selectedObjects.first as? IODisplayItem 107 | 108 | self.propertiesView.subviews.forEach { $0.removeFromSuperview() } 109 | 110 | if let selected = self.selectedObject 111 | { 112 | let controller = PropertiesViewController( item: selected ) 113 | controller.view.translatesAutoresizingMaskIntoConstraints = false 114 | controller.view.frame = self.propertiesView.bounds 115 | self.propertiesViewController = controller 116 | 117 | self.propertiesView.addSubview( controller.view ) 118 | self.propertiesView.addConstraint( NSLayoutConstraint( item: controller.view, attribute: .centerX, relatedBy: .equal, toItem: self.propertiesView, attribute: .centerX, multiplier: 1, constant: 0 ) ) 119 | self.propertiesView.addConstraint( NSLayoutConstraint( item: controller.view, attribute: .centerY, relatedBy: .equal, toItem: self.propertiesView, attribute: .centerY, multiplier: 1, constant: 0 ) ) 120 | self.propertiesView.addConstraint( NSLayoutConstraint( item: controller.view, attribute: .width, relatedBy: .equal, toItem: self.propertiesView, attribute: .width, multiplier: 1, constant: 0 ) ) 121 | self.propertiesView.addConstraint( NSLayoutConstraint( item: controller.view, attribute: .height, relatedBy: .equal, toItem: self.propertiesView, attribute: .height, multiplier: 1, constant: 0 ) ) 122 | 123 | self.searchField.nextKeyView = controller.searchField 124 | controller.searchField.nextKeyView = self.searchField 125 | } 126 | else 127 | { 128 | self.propertiesViewController = nil 129 | self.searchField.nextKeyView = nil 130 | } 131 | } 132 | 133 | private func filter( text: String? ) 134 | { 135 | self.collapseAll() 136 | 137 | let predicate: NSPredicate? = 138 | { 139 | guard let text = text, text.count > 0 140 | else 141 | { 142 | return nil 143 | } 144 | 145 | if self.searchInProperties 146 | { 147 | return NSPredicate( format: "name contains[c] %@ OR index contains[c] %@", text, text ) 148 | } 149 | 150 | return NSPredicate( format: "name contains[c] %@", text ) 151 | }() 152 | 153 | self.items.forEach { $0.predicate = predicate } 154 | 155 | if predicate == nil 156 | { 157 | self.expandFirstLevel() 158 | } 159 | else 160 | { 161 | self.expandAll() 162 | } 163 | } 164 | 165 | @objc 166 | private func expandFirstLevel() 167 | { 168 | self.outlineView.collapseItem( nil, collapseChildren: true ) 169 | 170 | var items = [ Any ]() 171 | 172 | for i in 0 ..< self.items.count 173 | { 174 | if let item = self.outlineView.item( atRow: i ) 175 | { 176 | items.append( item ) 177 | } 178 | } 179 | 180 | items.forEach { self.outlineView.expandItem( $0 ) } 181 | } 182 | 183 | @objc 184 | private func expandAll() 185 | { 186 | self.outlineView.expandItem( nil, expandChildren: true ) 187 | } 188 | 189 | @objc 190 | private func collapseAll() 191 | { 192 | self.outlineView.collapseItem( nil, collapseChildren: true ) 193 | } 194 | 195 | @objc 196 | public func performFindPanelAction( _ sender: Any? ) 197 | { 198 | self.window?.makeFirstResponder( self.searchField ) 199 | } 200 | 201 | @IBAction 202 | private func toggleSearchInProperties( _ sender: Any? ) 203 | { 204 | self.searchInProperties = self.searchInProperties == false 205 | } 206 | 207 | @IBAction 208 | private func showSearchOptions( _ sender: Any? ) 209 | { 210 | guard let view = sender as? NSView, let event = NSApp.currentEvent 211 | else 212 | { 213 | NSSound.beep() 214 | 215 | return 216 | } 217 | 218 | NSMenu.popUpContextMenu( self.searchOptions, with: event, for: view ) 219 | } 220 | 221 | @IBAction 222 | public func copy( _ sender: Any? ) 223 | { 224 | guard let items = self.treeController.selectedObjects as? [ IODisplayItem ], items.isEmpty == false 225 | else 226 | { 227 | NSSound.beep() 228 | 229 | return 230 | } 231 | 232 | NSPasteboard.general.clearContents() 233 | NSPasteboard.general.writeObjects( items.map { PasteboardWriter( item: $0 ) } ) 234 | } 235 | 236 | public func outlineView( _ outlineView: NSOutlineView, pasteboardWriterForItem item: Any ) -> NSPasteboardWriting? 237 | { 238 | guard let item = item as? NSTreeNode, let item = item.representedObject as? IODisplayItem 239 | else 240 | { 241 | return nil 242 | } 243 | 244 | return PasteboardWriter( item: item ) 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /IOBrowser/Classes/PasteboardWriter.swift: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the Software), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | import Cocoa 26 | 27 | public class PasteboardWriter: NSObject, NSPasteboardWriting 28 | { 29 | private var item: Either< PropertyListNode, IODisplayItem > 30 | 31 | public init( item: PropertyListNode ) 32 | { 33 | self.item = .left( item ) 34 | } 35 | 36 | public init( item: IODisplayItem ) 37 | { 38 | self.item = .right( item ) 39 | } 40 | 41 | public func writableTypes( for pasteboard: NSPasteboard ) -> [ NSPasteboard.PasteboardType ] 42 | { 43 | [ .string ] 44 | } 45 | 46 | public func pasteboardPropertyList( forType type: NSPasteboard.PasteboardType ) -> Any? 47 | { 48 | switch self.item 49 | { 50 | case .left( let item ): return self.pasteboardPropertyList( item: item ) 51 | case .right( let item ): return self.pasteboardPropertyList( item: item ) 52 | } 53 | } 54 | 55 | public func pasteboardPropertyList( item: PropertyListNode ) -> Any? 56 | { 57 | guard let value = PropertyValueTransformer().transformedValue( item ) as? String 58 | else 59 | { 60 | return nil 61 | } 62 | 63 | return "\( item.key ): \( value )" 64 | } 65 | 66 | public func pasteboardPropertyList( item: IODisplayItem ) -> Any? 67 | { 68 | item.name 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /IOBrowser/Classes/Preferences.swift: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the Software), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | import Foundation 26 | 27 | public class Preferences: NSObject 28 | { 29 | @objc public dynamic var lastStart: Date? 30 | { 31 | get 32 | { 33 | UserDefaults.standard.object( forKey: "LastStart" ) as? Date 34 | } 35 | 36 | set( value ) 37 | { 38 | self.willChangeValue( for: \.lastStart ) 39 | UserDefaults.standard.set( value, forKey: "LastStart" ) 40 | self.didChangeValue( for: \.lastStart ) 41 | } 42 | } 43 | 44 | @objc public dynamic var numberDisplayMode: Int 45 | { 46 | get 47 | { 48 | UserDefaults.standard.integer( forKey: "numberDisplayMode" ) 49 | } 50 | 51 | set( value ) 52 | { 53 | self.willChangeValue( for: \.lastStart ) 54 | UserDefaults.standard.set( value, forKey: "numberDisplayMode" ) 55 | self.didChangeValue( for: \.lastStart ) 56 | } 57 | } 58 | 59 | @objc public dynamic var dataDisplayMode: Int 60 | { 61 | get 62 | { 63 | UserDefaults.standard.integer( forKey: "dataDisplayMode" ) 64 | } 65 | 66 | set( value ) 67 | { 68 | self.willChangeValue( for: \.lastStart ) 69 | UserDefaults.standard.set( value, forKey: "dataDisplayMode" ) 70 | self.didChangeValue( for: \.lastStart ) 71 | } 72 | } 73 | 74 | @objc public dynamic var detectNumbersInData: Bool 75 | { 76 | get 77 | { 78 | UserDefaults.standard.bool( forKey: "detectNumbersInData" ) 79 | } 80 | 81 | set( value ) 82 | { 83 | self.willChangeValue( for: \.lastStart ) 84 | UserDefaults.standard.set( value, forKey: "detectNumbersInData" ) 85 | self.didChangeValue( for: \.lastStart ) 86 | } 87 | } 88 | 89 | public static let shared = Preferences() 90 | 91 | private override init() 92 | {} 93 | } 94 | -------------------------------------------------------------------------------- /IOBrowser/Classes/PropertiesViewController.swift: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the Software), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | import Cocoa 26 | 27 | public class PropertiesViewController: NSViewController, NSOutlineViewDelegate, NSOutlineViewDataSource 28 | { 29 | @objc private dynamic var item: IODisplayItem 30 | @objc private dynamic var properties: [ PropertyListNode ] 31 | @objc private dynamic var searchText: String? 32 | { 33 | didSet 34 | { 35 | self.filter( text: self.searchText ) 36 | } 37 | } 38 | 39 | @objc private dynamic var preferences = Preferences.shared 40 | 41 | @IBOutlet private var treeController: NSTreeController! 42 | @IBOutlet private var outlineView: NSOutlineView! 43 | @IBOutlet public private( set ) var searchField: NSSearchField! 44 | 45 | private var observers = [ NSKeyValueObservation ]() 46 | 47 | init( item: IODisplayItem ) 48 | { 49 | self.item = item 50 | self.properties = item.properties 51 | 52 | super.init( nibName: nil, bundle: nil ) 53 | } 54 | 55 | required init?( coder: NSCoder ) 56 | { 57 | nil 58 | } 59 | 60 | public override var nibName: NSNib.Name? 61 | { 62 | "PropertiesViewController" 63 | } 64 | 65 | public override func viewDidLoad() 66 | { 67 | super.viewDidLoad() 68 | 69 | self.outlineView.setDraggingSourceOperationMask( .copy, forLocal: false ) 70 | 71 | self.treeController.sortDescriptors = 72 | [ 73 | NSSortDescriptor( key: "key", ascending: true, selector: #selector( NSString.localizedCaseInsensitiveCompare( _: ) ) ), 74 | ] 75 | 76 | let o1 = self.preferences.observe( \.numberDisplayMode ) 77 | { 78 | [ weak self ] _, _ in self?.outlineView.reloadData() 79 | } 80 | 81 | let o2 = self.preferences.observe( \.dataDisplayMode ) 82 | { 83 | [ weak self ] _, _ in self?.outlineView.reloadData() 84 | } 85 | 86 | let o3 = self.preferences.observe( \.detectNumbersInData ) 87 | { 88 | [ weak self ] _, _ in self?.outlineView.reloadData() 89 | } 90 | 91 | self.observers.append( contentsOf: [ o1, o2, o3 ] ) 92 | } 93 | 94 | @objc 95 | public func performFindPanelAction( _ sender: Any? ) 96 | { 97 | self.view.window?.makeFirstResponder( self.searchField ) 98 | } 99 | 100 | @objc 101 | public func saveDocument( _ sender: Any? ) 102 | { 103 | self.saveDocumentAs( sender ) 104 | } 105 | 106 | @objc 107 | public func saveDocumentAs( _ sender: Any? ) 108 | { 109 | if self.item.properties.count == 0 110 | { 111 | NSSound.beep() 112 | 113 | return 114 | } 115 | 116 | guard let window = self.view.window 117 | else 118 | { 119 | NSSound.beep() 120 | 121 | return 122 | } 123 | 124 | let panel = NSSavePanel() 125 | panel.allowedFileTypes = [ "plist" ] 126 | panel.canCreateDirectories = true 127 | let formatController = PropertyListFormatViewController() 128 | panel.accessoryView = formatController.view 129 | 130 | panel.beginSheetModal( for: window ) 131 | { 132 | guard let url = panel.url, $0 == .OK 133 | else 134 | { 135 | return 136 | } 137 | 138 | do 139 | { 140 | let data = try PropertyListSerialization.data( 141 | fromPropertyList: self.item.object.properties, 142 | format: formatController.format, 143 | options: 0 144 | ) 145 | 146 | try data.write( to: url ) 147 | } 148 | catch 149 | { 150 | NSAlert( error: error ).runModal() 151 | } 152 | } 153 | } 154 | 155 | @objc 156 | private func expandAll() 157 | { 158 | self.outlineView.expandItem( nil, expandChildren: true ) 159 | } 160 | 161 | @objc 162 | private func collapseAll() 163 | { 164 | self.outlineView.collapseItem( nil, collapseChildren: true ) 165 | } 166 | 167 | private func filter( text: String? ) 168 | { 169 | self.collapseAll() 170 | 171 | let predicate: NSPredicate? = 172 | { 173 | guard let text = text, text.count > 0 174 | else 175 | { 176 | return nil 177 | } 178 | 179 | return NSPredicate( format: "key contains[c] %@", text ) 180 | }() 181 | 182 | self.item.properties.forEach { $0.predicate = predicate } 183 | 184 | if let predicate = predicate 185 | { 186 | self.properties = self.item.properties.filter 187 | { 188 | $0.children.count > 0 || predicate.evaluate( with: $0 ) 189 | } 190 | 191 | self.expandAll() 192 | } 193 | else 194 | { 195 | self.properties = self.item.properties 196 | 197 | self.collapseAll() 198 | } 199 | } 200 | 201 | @IBAction 202 | public func copy( _ sender: Any? ) 203 | { 204 | guard let items = self.treeController.selectedObjects as? [ PropertyListNode ], items.isEmpty == false 205 | else 206 | { 207 | NSSound.beep() 208 | 209 | return 210 | } 211 | 212 | NSPasteboard.general.clearContents() 213 | NSPasteboard.general.writeObjects( items.map { PasteboardWriter( item: $0 ) } ) 214 | } 215 | 216 | public func outlineView( _ outlineView: NSOutlineView, pasteboardWriterForItem item: Any ) -> NSPasteboardWriting? 217 | { 218 | guard let item = item as? NSTreeNode, let item = item.representedObject as? PropertyListNode 219 | else 220 | { 221 | return nil 222 | } 223 | 224 | return PasteboardWriter( item: item ) 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /IOBrowser/Classes/PropertyListFormatViewController.swift: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Jean-David Gadina - www.xs-labs.com 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | import Cocoa 26 | 27 | public class PropertyListFormatViewController: NSViewController 28 | { 29 | @IBOutlet private var button: NSPopUpButton! 30 | 31 | public override var nibName: NSNib.Name? 32 | { 33 | "PropertyListFormatViewController" 34 | } 35 | 36 | public var format: PropertyListSerialization.PropertyListFormat 37 | { 38 | return self.button.selectedTag() == 0 ? .binary : .xml 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /IOBrowser/Classes/PropertyListNode.swift: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the Software), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | import Cocoa 26 | 27 | public class PropertyListNode: NSObject 28 | { 29 | @objc public private( set ) dynamic var key: String 30 | @objc public private( set ) dynamic var value: String 31 | @objc public private( set ) dynamic var type: String 32 | @objc public private( set ) dynamic var index: String 33 | @objc public private( set ) dynamic var textColor: NSColor 34 | @objc public private( set ) dynamic var allChildren = [ PropertyListNode ]() 35 | @objc public private( set ) dynamic var children = [ PropertyListNode ]() 36 | @objc public private( set ) dynamic var propertyList: Any? 37 | { 38 | didSet 39 | { 40 | self.index = "\( self.key ) \( PropertyListNode.index( for: self.propertyList ) )" 41 | } 42 | } 43 | 44 | private static var dateFormatter: DateFormatter 45 | { 46 | let formatter = DateFormatter() 47 | 48 | formatter.dateStyle = .full 49 | formatter.timeStyle = .medium 50 | formatter.doesRelativeDateFormatting = false 51 | 52 | return formatter 53 | } 54 | 55 | public init( key: String, propertyList: Any? ) 56 | { 57 | let info = PropertyListNode.info( for: propertyList ) 58 | self.key = key 59 | self.type = info.type 60 | self.value = info.value 61 | self.propertyList = propertyList 62 | self.textColor = NSColor.controlTextColor 63 | self.index = "\( key ) \( PropertyListNode.index( for: propertyList ) )" 64 | 65 | super.init() 66 | 67 | if let array = propertyList as? NSArray 68 | { 69 | var i = 0 70 | 71 | array.forEach 72 | { 73 | self.addChild( key: "Item \( i )", propertyList: $0 ) 74 | 75 | i += 1 76 | } 77 | 78 | self.textColor = NSColor.secondaryLabelColor 79 | } 80 | else if let set = propertyList as? NSOrderedSet 81 | { 82 | var i = 0 83 | 84 | set.forEach 85 | { 86 | self.addChild( key: "Item \( i )", propertyList: $0 ) 87 | 88 | i += 1 89 | } 90 | 91 | self.textColor = NSColor.secondaryLabelColor 92 | } 93 | else if let set = propertyList as? NSSet 94 | { 95 | var i = 0 96 | 97 | set.forEach 98 | { 99 | self.addChild( key: "Item \( i )", propertyList: $0 ) 100 | 101 | i += 1 102 | } 103 | 104 | self.textColor = NSColor.secondaryLabelColor 105 | } 106 | else if let dict = propertyList as? NSDictionary 107 | { 108 | dict.forEach { self.addChild( key: "\( $0.key )", propertyList: $0.value ) } 109 | 110 | self.textColor = NSColor.secondaryLabelColor 111 | } 112 | else if let tuple = propertyList as? ( Any, [ AnyHashable: Any ] ) 113 | { 114 | let info = PropertyListNode.info( for: tuple.0 ) 115 | self.type = info.type 116 | self.value = info.value 117 | 118 | tuple.1.forEach { self.addChild( key: "\( $0.key )", propertyList: $0.value ) } 119 | 120 | self.textColor = NSColor.secondaryLabelColor 121 | } 122 | else if let tuple = propertyList as? ( Any, [ Any ] ) 123 | { 124 | let info = PropertyListNode.info( for: tuple.0 ) 125 | self.type = info.type 126 | self.value = info.value 127 | var i = 0 128 | 129 | tuple.1.forEach 130 | { 131 | self.addChild( key: "Item \( i )", propertyList: $0 ) 132 | 133 | i += 1 134 | } 135 | 136 | self.textColor = NSColor.secondaryLabelColor 137 | } 138 | } 139 | 140 | private class func info( for propertyList: Any? ) -> ( type: String, value: String ) 141 | { 142 | if let str = propertyList as? String 143 | { 144 | return ( 145 | type: "String", 146 | value: str 147 | ) 148 | } 149 | else if let num = propertyList as? NSNumber 150 | { 151 | return ( 152 | type: "Number", 153 | value: num.stringValue 154 | ) 155 | } 156 | else if let data = propertyList as? Data 157 | { 158 | return ( 159 | type: "Data", 160 | value: data.base64EncodedString() 161 | ) 162 | } 163 | else if let date = propertyList as? Date 164 | { 165 | return ( 166 | type: "Date", 167 | value: PropertyListNode.dateFormatter.string( from: date ) 168 | ) 169 | } 170 | else if let url = propertyList as? URL 171 | { 172 | return ( 173 | type: "URL", 174 | value: url.absoluteString 175 | ) 176 | } 177 | else if let uuid = propertyList as? UUID 178 | { 179 | return ( 180 | type: "UUID", 181 | value: uuid.uuidString 182 | ) 183 | } 184 | else if let array = propertyList as? NSArray 185 | { 186 | return ( 187 | type: "Array", 188 | value: "\( array.count ) Items" 189 | ) 190 | } 191 | else if let set = propertyList as? NSOrderedSet 192 | { 193 | return ( 194 | type: "Ordered Set", 195 | value: "\( set.count ) Items" 196 | ) 197 | } 198 | else if let set = propertyList as? NSSet 199 | { 200 | return ( 201 | type: "Set", 202 | value: "\( set.count ) Items" 203 | ) 204 | } 205 | else if let dict = propertyList as? NSDictionary 206 | { 207 | return ( 208 | type: "Dictionary", 209 | value: "\( dict.count ) Items" 210 | ) 211 | } 212 | else if let unknown = propertyList 213 | { 214 | return ( 215 | type: "Unknown", 216 | value: "\( unknown )" 217 | ) 218 | } 219 | else 220 | { 221 | return ( 222 | type: "Unknown", 223 | value: "" 224 | ) 225 | } 226 | } 227 | 228 | public var predicate: NSPredicate? 229 | { 230 | didSet 231 | { 232 | self.filter( predicate: self.predicate ) 233 | } 234 | } 235 | 236 | private func filter( predicate: NSPredicate? ) 237 | { 238 | self.allChildren.forEach { $0.predicate = predicate } 239 | 240 | guard let predicate = predicate 241 | else 242 | { 243 | self.children = self.allChildren 244 | 245 | return 246 | } 247 | 248 | self.children = self.allChildren.compactMap 249 | { 250 | predicate.evaluate( with: $0 ) || $0.children.count > 0 ? $0 : nil 251 | } 252 | } 253 | 254 | @discardableResult 255 | private func addChild( key: String, propertyList: Any? ) -> PropertyListNode 256 | { 257 | let child = PropertyListNode( key: key, propertyList: propertyList ) 258 | 259 | self.allChildren.append( child ) 260 | self.children.append( child ) 261 | 262 | return child 263 | } 264 | 265 | private class func index( for plist: Any? ) -> String 266 | { 267 | if let value = plist as? String 268 | { 269 | return value 270 | } 271 | else if let value = plist as? Bool 272 | { 273 | return value ? "true" : "false" 274 | } 275 | else if let value = plist as? NSNumber 276 | { 277 | return value.stringValue 278 | } 279 | else if let value = plist as? URL 280 | { 281 | return value.absoluteString 282 | } 283 | else if let value = plist as? UUID 284 | { 285 | return value.uuidString 286 | } 287 | else if let value = plist as? NSArray 288 | { 289 | return self.index( for: value ) 290 | } 291 | else if let value = plist as? NSOrderedSet 292 | { 293 | return self.index( for: value ) 294 | } 295 | else if let value = plist as? NSSet 296 | { 297 | return self.index( for: value ) 298 | } 299 | else if let value = plist as? NSDictionary 300 | { 301 | return self.index( for: value ) 302 | } 303 | 304 | return "" 305 | } 306 | 307 | private class func index( for value: NSArray ) -> String 308 | { 309 | value.map 310 | { 311 | self.index( for: $0 ) 312 | } 313 | .joined( separator: " " ) 314 | } 315 | 316 | private class func index( for value: NSOrderedSet ) -> String 317 | { 318 | value.map 319 | { 320 | self.index( for: $0 ) 321 | } 322 | .joined( separator: " " ) 323 | } 324 | 325 | private class func index( for value: NSSet ) -> String 326 | { 327 | value.map 328 | { 329 | self.index( for: $0 ) 330 | } 331 | .joined( separator: " " ) 332 | } 333 | 334 | private class func index( for value: NSDictionary ) -> String 335 | { 336 | value.map 337 | { 338 | "\( self.index( for: $0 ) ) \( self.index( for: $1 ) )" 339 | } 340 | .joined( separator: " " ) 341 | } 342 | } 343 | -------------------------------------------------------------------------------- /IOBrowser/Classes/PropertyValueTransformer.swift: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2022, Jean-David Gadina - www.xs-labs.com 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the Software), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | import Foundation 26 | 27 | @objc( PropertyValueTransformer ) 28 | public class PropertyValueTransformer: ValueTransformer 29 | { 30 | public override class func transformedValueClass() -> AnyClass 31 | { 32 | NSString.self 33 | } 34 | 35 | public override func transformedValue( _ value: Any? ) -> Any? 36 | { 37 | guard let value = value as? PropertyListNode 38 | else 39 | { 40 | return nil 41 | } 42 | 43 | if let number = value.propertyList as? NSNumber 44 | { 45 | if Preferences.shared.numberDisplayMode == 0 46 | { 47 | return number.description 48 | } 49 | else if Preferences.shared.numberDisplayMode == 1 50 | { 51 | return String( format: "0x%llX", number.int64Value ) 52 | } 53 | } 54 | 55 | if let data = value.propertyList as? Data, data.count > 0 56 | { 57 | if Preferences.shared.detectNumbersInData, let number = data.number() 58 | { 59 | return PropertyValueTransformer().transformedValue( PropertyListNode( key: value.key, propertyList: NSNumber( value: number ) ) ) 60 | } 61 | else if Preferences.shared.dataDisplayMode == 0 62 | { 63 | return data.base64EncodedString() 64 | } 65 | else if Preferences.shared.dataDisplayMode == 1 66 | { 67 | return data.hexadecimalString() 68 | } 69 | } 70 | 71 | return value.value 72 | } 73 | 74 | public override class func allowsReverseTransformation() -> Bool 75 | { 76 | false 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /IOBrowser/IOBrowser-AppStore.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-write 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /IOBrowser/IOBrowser-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Jean-David Gadina - www.xs-labs.com 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | ******************************************************************************/ 24 | 25 | -------------------------------------------------------------------------------- /IOBrowser/IOBrowser.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /IOBrowser/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | Icon 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | 1.2.1 21 | CFBundleVersion 22 | 46 23 | LSApplicationCategoryType 24 | public.app-category.utilities 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | NSHumanReadableCopyright 28 | Copyright © 2022 XS-Labs. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /IOBrowser/UI/Base.lproj/AboutWindowController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /IOBrowser/UI/Base.lproj/MainWindowController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | NSNegateBoolean 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | ArrayIsNotEmpty 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | NSIsNil 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 202 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | NSIsNil 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | NSIsNotNil 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | NSIsNotNil 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | ArrayIsEmpty 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | NSNegateBoolean 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | -------------------------------------------------------------------------------- /IOBrowser/UI/Base.lproj/PropertiesViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | PropertyValueTransformer 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 179 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | -------------------------------------------------------------------------------- /IOBrowser/UI/Base.lproj/PropertyListFormatViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /IOBrowser/UI/Images/DocumentTemplate.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macmade/IOBrowser/19d58e63212450ef7a5ff6e11cc10c612028838c/IOBrowser/UI/Images/DocumentTemplate.pdf -------------------------------------------------------------------------------- /IOBrowser/UI/Images/FolderTemplate.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macmade/IOBrowser/19d58e63212450ef7a5ff6e11cc10c612028838c/IOBrowser/UI/Images/FolderTemplate.pdf -------------------------------------------------------------------------------- /IOBrowser/UI/Images/Icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macmade/IOBrowser/19d58e63212450ef7a5ff6e11cc10c612028838c/IOBrowser/UI/Images/Icon.icns -------------------------------------------------------------------------------- /IOBrowser/UI/Images/StackTemplate.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/macmade/IOBrowser/19d58e63212450ef7a5ff6e11cc10c612028838c/IOBrowser/UI/Images/StackTemplate.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Jean-David Gadina - www.xs-labs.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | IOBrowser 2 | ========= 3 | 4 | [![Build Status](https://img.shields.io/github/actions/workflow/status/macmade/IOBrowser/ci-mac.yaml?label=macOS&logo=apple)](https://github.com/macmade/IOBrowser/actions/workflows/ci-mac.yaml) 5 | [![Issues](http://img.shields.io/github/issues/macmade/IOBrowser.svg?logo=github)](https://github.com/macmade/IOBrowser/issues) 6 | ![Status](https://img.shields.io/badge/status-active-brightgreen.svg?logo=git) 7 | ![License](https://img.shields.io/badge/license-mit-brightgreen.svg?logo=open-source-initiative) 8 | [![Contact](https://img.shields.io/badge/follow-@macmade-blue.svg?logo=twitter&style=social)](https://twitter.com/macmade) 9 | [![Sponsor](https://img.shields.io/badge/sponsor-macmade-pink.svg?logo=github-sponsors&style=social)](https://github.com/sponsors/macmade) 10 | 11 | ### About 12 | 13 | ![Logo](Assets/Logo.png "Logo") 14 | 15 | A macOS application for browsing the IOKit registry. 16 | 17 | ![Screenshot](Assets/Screenshot.png "Screenshot") 18 | 19 | License 20 | ------- 21 | 22 | Project is released under the terms of the MIT License. 23 | 24 | Repository Infos 25 | ---------------- 26 | 27 | Owner: Jean-David Gadina - XS-Labs 28 | Web: www.xs-labs.com 29 | Blog: www.noxeos.com 30 | Twitter: @macmade 31 | GitHub: github.com/macmade 32 | LinkedIn: ch.linkedin.com/in/macmade/ 33 | StackOverflow: stackoverflow.com/users/182676/macmade 34 | --------------------------------------------------------------------------------