├── .DS_Store ├── Chrome Extensions ├── apilist ├── apilistasarray ├── apilistasarraybash └── readme.md ├── Extension Manager_Signed.app.zip ├── Extension-Manager-GUI ├── .DS_Store ├── Extension Manager.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── charlesedge.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── charlesedge.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── Extension Manager │ ├── .DS_Store │ ├── App │ │ ├── AppDelegate.swift │ │ └── ExtensionManager.entitlements │ ├── Features │ │ ├── .DS_Store │ │ ├── Base.lproj │ │ │ └── Main.storyboard │ │ └── ViewController.swift │ ├── Models │ │ ├── BrowserExtension.swift │ │ ├── Extension.swift │ │ ├── Filter.swift │ │ ├── Firefox.swift │ │ ├── Parseable.swift │ │ ├── Plugin.swift │ │ ├── Sort.swift │ │ └── SystemExtension.swift │ ├── Resources │ │ ├── .DS_Store │ │ └── Assets.xcassets │ │ │ ├── .DS_Store │ │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ │ ├── AppIcon.appiconset │ │ │ ├── 1024.png │ │ │ ├── 128.png │ │ │ ├── 16.png │ │ │ ├── 256 1.png │ │ │ ├── 256.png │ │ │ ├── 32 1.png │ │ │ ├── 32.png │ │ │ ├── 512 1.png │ │ │ ├── 512.png │ │ │ ├── 64.png │ │ │ ├── Contents.json │ │ │ ├── appstore1024.png │ │ │ ├── ipad152.png │ │ │ ├── ipad76.png │ │ │ ├── ipadNotification20.png │ │ │ ├── ipadNotification40.png │ │ │ ├── ipadPro167.png │ │ │ ├── ipadSettings29.png │ │ │ ├── ipadSettings58.png │ │ │ ├── ipadSpotlight40.png │ │ │ ├── ipadSpotlight80.png │ │ │ ├── iphone120.png │ │ │ ├── iphone180.png │ │ │ ├── mac1024.png │ │ │ ├── mac128.png │ │ │ ├── mac16.png │ │ │ ├── mac256.png │ │ │ ├── mac32.png │ │ │ ├── mac512.png │ │ │ ├── mac64.png │ │ │ ├── notification40.png │ │ │ ├── notification60.png │ │ │ ├── settings58.png │ │ │ ├── settings87.png │ │ │ ├── spotlight120.png │ │ │ └── spotlight80.png │ │ │ ├── Contents.json │ │ │ ├── grey.colorset │ │ │ └── Contents.json │ │ │ └── text.colorset │ │ │ └── Contents.json │ ├── Store │ │ ├── ExtensionStore.swift │ │ └── RequestModel.swift │ └── Utilities │ │ └── Extensions.swift └── README.md ├── Firefox Extensions ├── apis ├── apisaslist └── readme.md ├── Images ├── em3.png ├── em4.png ├── xc1.png └── xc2.png ├── LICENSE ├── Microsoft Edge ├── apis ├── apisasarray └── readme.md ├── README.md ├── extensionsman ├── extensionsman-CLI ├── .DS_Store ├── App │ ├── ConsoleIO.swift │ ├── ExtensionMan.swift │ └── main.swift ├── Models │ ├── BrowserExtension.swift │ ├── Extension.swift │ ├── Filter.swift │ ├── Firefox.swift │ ├── Option.swift │ ├── Parseable.swift │ ├── Plugin.swift │ └── SystemExtension.swift ├── Store │ ├── ExtensionStore.swift │ └── RequestModel.swift ├── Utilitiy │ └── Extensions+extensionman.swift └── extensionsman.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── charlesedge.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ └── xcshareddata │ └── xcschemes │ └── extensionsman.xcscheme └── extensionsmanCLI_Signed.zip /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/.DS_Store -------------------------------------------------------------------------------- /Chrome Extensions/apilist: -------------------------------------------------------------------------------- 1 | chrome.accessibilityFeatures 2 | chrome.action 3 | chrome.alarms 4 | chrome.audio 5 | chrome.bookmarks 6 | chrome.browserAction 7 | chrome.browsingData 8 | chrome.certificateProvider 9 | chrome.commands 10 | chrome.contentSettings 11 | chrome.contextMenus 12 | chrome.cookies 13 | chrome.debugger 14 | chrome.declarativeContent 15 | chrome.declarativeNetRequest 16 | chrome.desktopCapture 17 | chrome.devtools.inspectedWindow 18 | chrome.devtools.network 19 | chrome.devtools.panels 20 | chrome.devtools.recorder 21 | chrome.documentScan 22 | chrome.dom 23 | chrome.downloads 24 | chrome.enterprise.deviceAttributes 25 | chrome.enterprise.hardwarePlatform 26 | chrome.enterprise.networkingAttributes 27 | chrome.enterprise.platformKeys 28 | chrome.events 29 | chrome.extension 30 | chrome.extensionTypes 31 | chrome.fileBrowserHandler 32 | chrome.fileSystemProvider 33 | chrome.fontSettings 34 | chrome.gcm 35 | chrome.history 36 | chrome.i18n 37 | chrome.identity 38 | chrome.idle 39 | chrome.input.ime 40 | chrome.instanceID 41 | chrome.loginState 42 | chrome.management 43 | chrome.notifications 44 | chrome.offscreen 45 | chrome.omnibox 46 | chrome.pageAction 47 | chrome.pageCapture 48 | chrome.permissions 49 | chrome.platformKeys 50 | chrome.power 51 | chrome.printerProvider 52 | chrome.printing 53 | chrome.printingMetrics 54 | chrome.privacy 55 | chrome.proxy 56 | chrome.runtime 57 | chrome.scripting 58 | chrome.search 59 | chrome.sessions 60 | chrome.storage 61 | chrome.system.cpu 62 | chrome.system.display 63 | chrome.system.memory 64 | chrome.system.storage 65 | chrome.tabCapture 66 | chrome.tabGroups 67 | chrome.tabs 68 | chrome.topSites 69 | chrome.tts 70 | chrome.ttsEngine 71 | chrome.types 72 | chrome.vpnProvider 73 | chrome.wallpaper 74 | chrome.wallpaper 75 | chrome.webNavigation 76 | chrome.webRequest 77 | chrome.windows 78 | chrome.automation 79 | chrome.processes 80 | chrome.app.runtime 81 | chrome.app.window 82 | chrome.appviewTag 83 | chrome.bluetooth 84 | chrome.blueetoothLowEnergy 85 | chrome.bluetoothSocket 86 | chrome.browser 87 | chrome.clipboard 88 | chrome.fileSystem 89 | chrome.hid 90 | chrome.mdns 91 | chrome.mediaGalleries 92 | chrome.networking.onc 93 | chrome.serial 94 | chrome.socket 95 | chrome.sockets.tcp 96 | chrome.sockets.tcpServer 97 | chrome.sockets.udp 98 | chrome.syncFileSystem 99 | chrome.system.network 100 | chrome.usb 101 | chrome.virtualKeyboard 102 | chrome.webviewTag 103 | -------------------------------------------------------------------------------- /Chrome Extensions/apilistasarray: -------------------------------------------------------------------------------- 1 | apilist='chrome.accessibilityFeatures|chrome.action|chrome.alarms|chrome.audio|chrome.bookmarks|chrome.browserAction|chrome.browsingData|chrome.certificateProvider|chrome.commands|chrome.contentSettings|chrome.contextMenus|chrome.cookies|chrome.debugger|chrome.declarativeContent|chrome.declarativeNetRequest|chrome.desktopCapture|chrome.devtools.inspectedWindow|chrome.devtools.network|chrome.devtools.panels|chrome.devtools.recorder|chrome.documentScan|chrome.dom|chrome.downloads|chrome.enterprise.deviceAttributes|chrome.enterprise.hardwarePlatform|chrome.enterprise.networkingAttributes|chrome.enterprise.platformKeys|chrome.events|chrome.extension|chrome.extensionTypes|chrome.fileBrowserHandler|chrome.fileSystemProvider|chrome.fontSettings|chrome.gcm|chrome.history|chrome.i18n|chrome.identity|chrome.idle|chrome.input.ime|chrome.instanceID|chrome.loginState|chrome.management|chrome.notifications|chrome.offscreen|chrome.omnibox|chrome.pageAction|chrome.pageCapture|chrome.permissions|chrome.platformKeys|chrome.power|chrome.printerProvider|chrome.printing|chrome.printingMetrics|chrome.privacy|chrome.proxy|chrome.runtime|chrome.scripting|chrome.search|chrome.sessions|chrome.storage|chrome.system.cpu|chrome.system.display|chrome.system.memory|chrome.system.storage|chrome.tabCapture|chrome.tabGroups|chrome.tabs|chrome.topSites|chrome.tts|chrome.ttsEngine|chrome.types|chrome.vpnProvider|chrome.wallpaper|chrome.wallpaper|chrome.webNavigation|chrome.webRequest|chrome.windows|chrome.automation|chrome.processes|chrome.app.runtime|chrome.app.window|chrome.appviewTag|chrome.bluetooth|chrome.blueetoothLowEnergy|chrome.bluetoothSocket|chrome.browser|chrome.clipboard|chrome.fileSystem|chrome.hid|chrome.mdns|chrome.mediaGalleries|chrome.networking.onc|chrome.serial|chrome.socket|chrome.sockets.tcp|chrome.sockets.tcpServer|chrome.sockets.udp|chrome.syncFileSystem|chrome.system.network|chrome.usb|chrome.virtualKeyboard|chrome.webviewTag' 2 | -------------------------------------------------------------------------------- /Chrome Extensions/apilistasarraybash: -------------------------------------------------------------------------------- 1 | apis=("chrome.accessibilityFeatures" "chrome.action" "chrome.alarms" "chrome.audio" "chrome.bookmarks" "chrome.browserAction" "chrome.browsingData" "chrome.certificateProvider" "chrome.commands" "chrome.contentSettings" "chrome.contextMenus" "chrome.cookies" "chrome.debugger" "chrome.declarativeContent" "chrome.declarativeNetRequest" "chrome.desktopCapture" "chrome.devtools.inspectedWindow" "chrome.devtools.network" "chrome.devtools.panels" "chrome.devtools.recorder" "chrome.documentScan" "chrome.dom" "chrome.downloads" "chrome.enterprise.deviceAttributes" "chrome.enterprise.hardwarePlatform" "chrome.enterprise.networkingAttributes" "chrome.enterprise.platformKeys" "chrome.events" "chrome.extension" "chrome.extensionTypes" "chrome.fileBrowserHandler" "chrome.fileSystemProvider" "chrome.fontSettings" "chrome.gcm" "chrome.history" "chrome.i18n" "chrome.identity" "chrome.idle" "chrome.input.ime" "chrome.instanceID" "chrome.loginState" "chrome.management" "chrome.notifications" "chrome.offscreen" "chrome.omnibox" "chrome.pageAction" "chrome.pageCapture" "chrome.permissions" "chrome.platformKeys" "chrome.power" "chrome.printerProvider" "chrome.printing" "chrome.printingMetrics" "chrome.privacy" "chrome.proxy" "chrome.runtime" "chrome.scripting" "chrome.search" "chrome.sessions" "chrome.storage" "chrome.system.cpu" "chrome.system.display" "chrome.system.memory" "chrome.system.storage" "chrome.tabCapture" "chrome.tabGroups" "chrome.tabs" "chrome.topSites" "chrome.tts" "chrome.ttsEngine" "chrome.types" "chrome.vpnProvider" "chrome.wallpaper" "chrome.wallpaper" "chrome.webNavigation" "chrome.webRequest" "chrome.windows" "chrome.automation" "chrome.processes" "chrome.app.runtime" "chrome.app.window" "chrome.appviewTag" "chrome.bluetooth" "chrome.blueetoothLowEnergy" "chrome.bluetoothSocket" "chrome.browser" "chrome.clipboard" "chrome.fileSystem" "chrome.hid" "chrome.mdns" "chrome.mediaGalleries" "chrome.networking.onc" "chrome.serial" "chrome.socket" "chrome.sockets.tcp" "chrome.sockets.tcpServer" "chrome.sockets.udp" "chrome.syncFileSystem" "chrome.system.network" "chrome.usb" "chrome.virtualKeyboard" "chrome.webviewTag") 2 | -------------------------------------------------------------------------------- /Chrome Extensions/readme.md: -------------------------------------------------------------------------------- 1 | # Chrome Extensions 2 | 3 | Browser extensions can perform a number of tasks like access filesystems, gain telemetry on what processes are running on a host, view browsing history, etc. Here is a list of the APIs that Google makes available to Chrome Extension developers https://github.com/krypted/extensionsmanager/blob/main/Chrome%20Extensions/apilist. To see them delimited with a pipe, see: https://github.com/krypted/extensionsmanager/blob/main/Chrome%20Extensions/apilistasarray. Or in a standard shell scripting array form to aid in tool development, see https://github.com/krypted/extensionsmanager/blob/main/Chrome%20Extensions/apilistasarraybash. 4 | 5 | ## Get A List of Extensions 6 | Google Chrome for Mac stores extensions in /Users//Library/Application\ Support/Google/Chrome/Default/Extensions. To see a list of all of the extensions in Google Chrome, the following find command can parse through the directory, read the manifest.json, and find the name field. It’s quoted such that it will skip those that also have short_name defined and given that extensions can have multiple versions on a computer, made to be unique. 7 | 8 | ``` 9 | find ~/Library/Application\ Support/Google/Chrome/Default/Extensions -type f -name "manifest.json" -print0 | xargs -I {} -0 grep '"name":' "{}" | uniq 10 | ``` 11 | 12 | There are other fields that could be parsed out as well, and the xargs could be further refined to only include the quoted name rather than the uglier json, but this satisfies my own need. One of those fields that is important for people concerned about the security of various extensions is permissions, which can grant an extension the ability to access cameras, storage (e.g. through nmp), downloads, interact with a native app, obtain data from pastebin, etc: 13 | 14 | ``` 15 | "permissions": [ "activeTab", "alarms", "scripting", "storage" ], 16 | ``` 17 | ## Find Extensions That Use A Specific Endpoint 18 | Extensions are typically comprised of some javasscript and html files (to render what the javascripts are doing in modals, etc). So it's possible to repeat the above, but search for one of the APIs (for example, if one is deemed dangerous): 19 | 20 | ``` 21 | find ~/Library/Application\ Support/Google/Chrome/Default/Extensions -type f -name "*.js" -print0 | xargs -I {} -0 grep 'chrome.contentSettings' "{}" | uniq 22 | ``` 23 | 24 | To list the Chrome extensions by endpoint used: 25 | ``` 26 | apilist=("chrome.accessibilityFeatures" "chrome.action" 27 | "chrome.alarms" "chrome.audio" "chrome.bookmarks" "chrome.browserAction" 28 | "chrome.browsingData" "chrome.certificateProvider" "chrome.commands" 29 | "chrome.contentSettings" "chrome.contextMenus" "chrome.cookies" 30 | "chrome.debugger" "chrome.declarativeContent" "chrome.declarativeNetRequest" 31 | "chrome.desktopCapture" "chrome.devtools.inspectedWindow" 32 | "chrome.devtools.network" "chrome.devtools.panels" 33 | "chrome.devtools.recorder" "chrome.documentScan" "chrome.dom" 34 | "chrome.downloads" "chrome.enterprise.deviceAttributes" 35 | "chrome.enterprise.hardwarePlatform" 36 | "chrome.enterprise.networkingAttributes" "chrome.enterprise.platformKeys" 37 | "chrome.events" "chrome.extension" "chrome.extensionTypes" 38 | "chrome.fileBrowserHandler" "chrome.fileSystemProvider" 39 | "chrome.fontSettings" "chrome.gcm" "chrome.history" "chrome.i18n" 40 | "chrome.identity" "chrome.idle" "chrome.input.ime" "chrome.instanceID" 41 | "chrome.loginState" "chrome.management" "chrome.notifications" 42 | "chrome.offscreen" "chrome.omnibox" "chrome.pageAction" "chrome.pageCapture" 43 | "chrome.permissions" "chrome.platformKeys" "chrome.power" 44 | "chrome.printerProvider" "chrome.printing" "chrome.printingMetrics" 45 | "chrome.privacy" "chrome.proxy" "chrome.runtime" "chrome.scripting" 46 | "chrome.search" "chrome.sessions" "chrome.storage" "chrome.system.cpu" 47 | "chrome.system.display" "chrome.system.memory" "chrome.system.storage" 48 | "chrome.tabCapture" "chrome.tabGroups" "chrome.tabs" "chrome.topSites" 49 | "chrome.tts" "chrome.ttsEngine" "chrome.types" "chrome.vpnProvider" 50 | "chrome.wallpaper" "chrome.wallpaper" "chrome.webNavigation" 51 | "chrome.webRequest" "chrome.windows" "chrome.automation" "chrome.processes" 52 | "chrome.app.runtime" "chrome.app.window" "chrome.appviewTag" 53 | "chrome.bluetooth" "chrome.blueetoothLowEnergy" "chrome.bluetoothSocket" 54 | "chrome.browser" "chrome.clipboard" "chrome.fileSystem" "chrome.hid" 55 | "chrome.mdns" "chrome.mediaGalleries" "chrome.networking.onc" 56 | "chrome.serial" "chrome.socket" "chrome.sockets.tcp" 57 | "chrome.sockets.tcpServer" "chrome.sockets.udp" "chrome.syncFileSystem" 58 | "chrome.system.network" "chrome.usb" "chrome.virtualKeyboard" 59 | "chrome.webviewTag") 60 | for apis in ${apilist[@]}; do 61 | echo "$apis" 62 | find ~/Library/Application\ Support/Google/Chrome/Default/Extensions -type 63 | f -name "*.js" -print0 | xargs -I {} -0 grep $apis "{}" | 64 | uniq 65 | done 66 | ``` 67 | There are certainly less error prone or more elegant ways to do this, but that's what I've got for now. The array can be reduced to only list apis deemed safe (e.g. chrome.audio). Output can also be parsed to be more appropriate for different processing tools (e.g. in json or yaml). Further, it's also possible to remove the extensions by simply doing an rm of the guid-named directory each is stored in (although a kill on the Chrome process would help reduce any oddities an end user might experience). 68 | ``` 69 | killall "Google Chrome" 70 | ``` 71 | -------------------------------------------------------------------------------- /Extension Manager_Signed.app.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension Manager_Signed.app.zip -------------------------------------------------------------------------------- /Extension-Manager-GUI/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/.DS_Store -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 891D3A87296C1F7700AE3793 /* ExtensionStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 891D3A86296C1F7700AE3793 /* ExtensionStore.swift */; }; 11 | 891D3A8D296C387900AE3793 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 891D3A8C296C387900AE3793 /* Extensions.swift */; }; 12 | 891F262C2A0CF8380061AAFE /* RequestModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 891F262B2A0CF8380061AAFE /* RequestModel.swift */; }; 13 | 891F262E2A0CF90F0061AAFE /* Sort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 891F262D2A0CF90F0061AAFE /* Sort.swift */; }; 14 | 892715D82A1225B400E37F37 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892715D72A1225B400E37F37 /* Filter.swift */; }; 15 | 892715DA2A12260800E37F37 /* Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892715D92A12260800E37F37 /* Extension.swift */; }; 16 | 892715DC2A12263200E37F37 /* Parseable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892715DB2A12263200E37F37 /* Parseable.swift */; }; 17 | 892715DE2A12264700E37F37 /* Plugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892715DD2A12264700E37F37 /* Plugin.swift */; }; 18 | 892715E02A12269C00E37F37 /* SystemExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892715DF2A12269C00E37F37 /* SystemExtension.swift */; }; 19 | 892715E32A1226E700E37F37 /* BrowserExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892715E12A1226E700E37F37 /* BrowserExtension.swift */; }; 20 | 892715E42A1226E700E37F37 /* Firefox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892715E22A1226E700E37F37 /* Firefox.swift */; }; 21 | 89C0C73C296BF75F00C829FD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89C0C73B296BF75F00C829FD /* AppDelegate.swift */; }; 22 | 89C0C73E296BF75F00C829FD /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89C0C73D296BF75F00C829FD /* ViewController.swift */; }; 23 | 89C0C740296BF76100C829FD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 89C0C73F296BF76100C829FD /* Assets.xcassets */; }; 24 | 89C0C743296BF76100C829FD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 89C0C741296BF76100C829FD /* Main.storyboard */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 891D3A86296C1F7700AE3793 /* ExtensionStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtensionStore.swift; sourceTree = ""; }; 29 | 891D3A8C296C387900AE3793 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; }; 30 | 891F262B2A0CF8380061AAFE /* RequestModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestModel.swift; sourceTree = ""; }; 31 | 891F262D2A0CF90F0061AAFE /* Sort.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sort.swift; sourceTree = ""; }; 32 | 892715D72A1225B400E37F37 /* Filter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Filter.swift; sourceTree = ""; }; 33 | 892715D92A12260800E37F37 /* Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extension.swift; sourceTree = ""; }; 34 | 892715DB2A12263200E37F37 /* Parseable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Parseable.swift; sourceTree = ""; }; 35 | 892715DD2A12264700E37F37 /* Plugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Plugin.swift; sourceTree = ""; }; 36 | 892715DF2A12269C00E37F37 /* SystemExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemExtension.swift; sourceTree = ""; }; 37 | 892715E12A1226E700E37F37 /* BrowserExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BrowserExtension.swift; sourceTree = ""; }; 38 | 892715E22A1226E700E37F37 /* Firefox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Firefox.swift; sourceTree = ""; }; 39 | 89C0C738296BF75F00C829FD /* Extension Manager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Extension Manager.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | 89C0C73B296BF75F00C829FD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 41 | 89C0C73D296BF75F00C829FD /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 42 | 89C0C73F296BF76100C829FD /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | 89C0C742296BF76100C829FD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 44 | 89C0C744296BF76100C829FD /* ExtensionManager.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ExtensionManager.entitlements; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | 89C0C735296BF75F00C829FD /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 891D3A82296C1EDE00AE3793 /* App */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 89C0C73B296BF75F00C829FD /* AppDelegate.swift */, 62 | 89C0C744296BF76100C829FD /* ExtensionManager.entitlements */, 63 | ); 64 | path = App; 65 | sourceTree = ""; 66 | }; 67 | 891D3A83296C1EED00AE3793 /* Resources */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | 89C0C73F296BF76100C829FD /* Assets.xcassets */, 71 | ); 72 | path = Resources; 73 | sourceTree = ""; 74 | }; 75 | 891D3A84296C1EFC00AE3793 /* Features */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 89C0C73D296BF75F00C829FD /* ViewController.swift */, 79 | 89C0C741296BF76100C829FD /* Main.storyboard */, 80 | ); 81 | path = Features; 82 | sourceTree = ""; 83 | }; 84 | 891D3A85296C1F6200AE3793 /* Store */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 891D3A86296C1F7700AE3793 /* ExtensionStore.swift */, 88 | 891F262B2A0CF8380061AAFE /* RequestModel.swift */, 89 | ); 90 | path = Store; 91 | sourceTree = ""; 92 | }; 93 | 891D3A8B296C386B00AE3793 /* Utilities */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | 891D3A8C296C387900AE3793 /* Extensions.swift */, 97 | ); 98 | path = Utilities; 99 | sourceTree = ""; 100 | }; 101 | 891F262F2A0CF9180061AAFE /* Models */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 891F262D2A0CF90F0061AAFE /* Sort.swift */, 105 | 892715D72A1225B400E37F37 /* Filter.swift */, 106 | 892715D92A12260800E37F37 /* Extension.swift */, 107 | 892715DB2A12263200E37F37 /* Parseable.swift */, 108 | 892715DD2A12264700E37F37 /* Plugin.swift */, 109 | 892715DF2A12269C00E37F37 /* SystemExtension.swift */, 110 | 892715E12A1226E700E37F37 /* BrowserExtension.swift */, 111 | 892715E22A1226E700E37F37 /* Firefox.swift */, 112 | ); 113 | path = Models; 114 | sourceTree = ""; 115 | }; 116 | 89C0C72F296BF75F00C829FD = { 117 | isa = PBXGroup; 118 | children = ( 119 | 89C0C73A296BF75F00C829FD /* Extension Manager */, 120 | 89C0C739296BF75F00C829FD /* Products */, 121 | ); 122 | sourceTree = ""; 123 | }; 124 | 89C0C739296BF75F00C829FD /* Products */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 89C0C738296BF75F00C829FD /* Extension Manager.app */, 128 | ); 129 | name = Products; 130 | sourceTree = ""; 131 | }; 132 | 89C0C73A296BF75F00C829FD /* Extension Manager */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 891D3A82296C1EDE00AE3793 /* App */, 136 | 891D3A83296C1EED00AE3793 /* Resources */, 137 | 891D3A8B296C386B00AE3793 /* Utilities */, 138 | 891D3A85296C1F6200AE3793 /* Store */, 139 | 891F262F2A0CF9180061AAFE /* Models */, 140 | 891D3A84296C1EFC00AE3793 /* Features */, 141 | ); 142 | path = "Extension Manager"; 143 | sourceTree = ""; 144 | }; 145 | /* End PBXGroup section */ 146 | 147 | /* Begin PBXNativeTarget section */ 148 | 89C0C737296BF75F00C829FD /* Extension Manager */ = { 149 | isa = PBXNativeTarget; 150 | buildConfigurationList = 89C0C747296BF76100C829FD /* Build configuration list for PBXNativeTarget "Extension Manager" */; 151 | buildPhases = ( 152 | 89C0C734296BF75F00C829FD /* Sources */, 153 | 89C0C735296BF75F00C829FD /* Frameworks */, 154 | 89C0C736296BF75F00C829FD /* Resources */, 155 | ); 156 | buildRules = ( 157 | ); 158 | dependencies = ( 159 | ); 160 | name = "Extension Manager"; 161 | productName = extensionsman; 162 | productReference = 89C0C738296BF75F00C829FD /* Extension Manager.app */; 163 | productType = "com.apple.product-type.application"; 164 | }; 165 | /* End PBXNativeTarget section */ 166 | 167 | /* Begin PBXProject section */ 168 | 89C0C730296BF75F00C829FD /* Project object */ = { 169 | isa = PBXProject; 170 | attributes = { 171 | BuildIndependentTargetsInParallel = 1; 172 | LastSwiftUpdateCheck = 1420; 173 | LastUpgradeCheck = 1420; 174 | TargetAttributes = { 175 | 89C0C737296BF75F00C829FD = { 176 | CreatedOnToolsVersion = 14.2; 177 | }; 178 | }; 179 | }; 180 | buildConfigurationList = 89C0C733296BF75F00C829FD /* Build configuration list for PBXProject "Extension Manager" */; 181 | compatibilityVersion = "Xcode 14.0"; 182 | developmentRegion = en; 183 | hasScannedForEncodings = 0; 184 | knownRegions = ( 185 | en, 186 | Base, 187 | ); 188 | mainGroup = 89C0C72F296BF75F00C829FD; 189 | productRefGroup = 89C0C739296BF75F00C829FD /* Products */; 190 | projectDirPath = ""; 191 | projectRoot = ""; 192 | targets = ( 193 | 89C0C737296BF75F00C829FD /* Extension Manager */, 194 | ); 195 | }; 196 | /* End PBXProject section */ 197 | 198 | /* Begin PBXResourcesBuildPhase section */ 199 | 89C0C736296BF75F00C829FD /* Resources */ = { 200 | isa = PBXResourcesBuildPhase; 201 | buildActionMask = 2147483647; 202 | files = ( 203 | 89C0C740296BF76100C829FD /* Assets.xcassets in Resources */, 204 | 89C0C743296BF76100C829FD /* Main.storyboard in Resources */, 205 | ); 206 | runOnlyForDeploymentPostprocessing = 0; 207 | }; 208 | /* End PBXResourcesBuildPhase section */ 209 | 210 | /* Begin PBXSourcesBuildPhase section */ 211 | 89C0C734296BF75F00C829FD /* Sources */ = { 212 | isa = PBXSourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | 892715E42A1226E700E37F37 /* Firefox.swift in Sources */, 216 | 891D3A8D296C387900AE3793 /* Extensions.swift in Sources */, 217 | 892715DA2A12260800E37F37 /* Extension.swift in Sources */, 218 | 892715DE2A12264700E37F37 /* Plugin.swift in Sources */, 219 | 892715D82A1225B400E37F37 /* Filter.swift in Sources */, 220 | 89C0C73E296BF75F00C829FD /* ViewController.swift in Sources */, 221 | 89C0C73C296BF75F00C829FD /* AppDelegate.swift in Sources */, 222 | 892715E02A12269C00E37F37 /* SystemExtension.swift in Sources */, 223 | 891D3A87296C1F7700AE3793 /* ExtensionStore.swift in Sources */, 224 | 891F262E2A0CF90F0061AAFE /* Sort.swift in Sources */, 225 | 891F262C2A0CF8380061AAFE /* RequestModel.swift in Sources */, 226 | 892715E32A1226E700E37F37 /* BrowserExtension.swift in Sources */, 227 | 892715DC2A12263200E37F37 /* Parseable.swift in Sources */, 228 | ); 229 | runOnlyForDeploymentPostprocessing = 0; 230 | }; 231 | /* End PBXSourcesBuildPhase section */ 232 | 233 | /* Begin PBXVariantGroup section */ 234 | 89C0C741296BF76100C829FD /* Main.storyboard */ = { 235 | isa = PBXVariantGroup; 236 | children = ( 237 | 89C0C742296BF76100C829FD /* Base */, 238 | ); 239 | name = Main.storyboard; 240 | sourceTree = ""; 241 | }; 242 | /* End PBXVariantGroup section */ 243 | 244 | /* Begin XCBuildConfiguration section */ 245 | 89C0C745296BF76100C829FD /* Debug */ = { 246 | isa = XCBuildConfiguration; 247 | buildSettings = { 248 | ALWAYS_SEARCH_USER_PATHS = NO; 249 | CLANG_ANALYZER_NONNULL = YES; 250 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 251 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 252 | CLANG_ENABLE_MODULES = YES; 253 | CLANG_ENABLE_OBJC_ARC = YES; 254 | CLANG_ENABLE_OBJC_WEAK = YES; 255 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 256 | CLANG_WARN_BOOL_CONVERSION = YES; 257 | CLANG_WARN_COMMA = YES; 258 | CLANG_WARN_CONSTANT_CONVERSION = YES; 259 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 260 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 261 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 262 | CLANG_WARN_EMPTY_BODY = YES; 263 | CLANG_WARN_ENUM_CONVERSION = YES; 264 | CLANG_WARN_INFINITE_RECURSION = YES; 265 | CLANG_WARN_INT_CONVERSION = YES; 266 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 267 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 268 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 269 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 270 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 271 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 272 | CLANG_WARN_STRICT_PROTOTYPES = YES; 273 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 274 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 275 | CLANG_WARN_UNREACHABLE_CODE = YES; 276 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 277 | COPY_PHASE_STRIP = NO; 278 | DEBUG_INFORMATION_FORMAT = dwarf; 279 | ENABLE_STRICT_OBJC_MSGSEND = YES; 280 | ENABLE_TESTABILITY = YES; 281 | GCC_C_LANGUAGE_STANDARD = gnu11; 282 | GCC_DYNAMIC_NO_PIC = NO; 283 | GCC_NO_COMMON_BLOCKS = YES; 284 | GCC_OPTIMIZATION_LEVEL = 0; 285 | GCC_PREPROCESSOR_DEFINITIONS = ( 286 | "DEBUG=1", 287 | "$(inherited)", 288 | ); 289 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 290 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 291 | GCC_WARN_UNDECLARED_SELECTOR = YES; 292 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 293 | GCC_WARN_UNUSED_FUNCTION = YES; 294 | GCC_WARN_UNUSED_VARIABLE = YES; 295 | MACOSX_DEPLOYMENT_TARGET = 13.0; 296 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 297 | MTL_FAST_MATH = YES; 298 | ONLY_ACTIVE_ARCH = YES; 299 | SDKROOT = macosx; 300 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 301 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 302 | }; 303 | name = Debug; 304 | }; 305 | 89C0C746296BF76100C829FD /* Release */ = { 306 | isa = XCBuildConfiguration; 307 | buildSettings = { 308 | ALWAYS_SEARCH_USER_PATHS = NO; 309 | CLANG_ANALYZER_NONNULL = YES; 310 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 311 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 312 | CLANG_ENABLE_MODULES = YES; 313 | CLANG_ENABLE_OBJC_ARC = YES; 314 | CLANG_ENABLE_OBJC_WEAK = YES; 315 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 316 | CLANG_WARN_BOOL_CONVERSION = YES; 317 | CLANG_WARN_COMMA = YES; 318 | CLANG_WARN_CONSTANT_CONVERSION = YES; 319 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 320 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 321 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 322 | CLANG_WARN_EMPTY_BODY = YES; 323 | CLANG_WARN_ENUM_CONVERSION = YES; 324 | CLANG_WARN_INFINITE_RECURSION = YES; 325 | CLANG_WARN_INT_CONVERSION = YES; 326 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 327 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 328 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 329 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 330 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 331 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 332 | CLANG_WARN_STRICT_PROTOTYPES = YES; 333 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 334 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 335 | CLANG_WARN_UNREACHABLE_CODE = YES; 336 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 337 | COPY_PHASE_STRIP = NO; 338 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 339 | ENABLE_NS_ASSERTIONS = NO; 340 | ENABLE_STRICT_OBJC_MSGSEND = YES; 341 | GCC_C_LANGUAGE_STANDARD = gnu11; 342 | GCC_NO_COMMON_BLOCKS = YES; 343 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 344 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 345 | GCC_WARN_UNDECLARED_SELECTOR = YES; 346 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 347 | GCC_WARN_UNUSED_FUNCTION = YES; 348 | GCC_WARN_UNUSED_VARIABLE = YES; 349 | MACOSX_DEPLOYMENT_TARGET = 13.0; 350 | MTL_ENABLE_DEBUG_INFO = NO; 351 | MTL_FAST_MATH = YES; 352 | SDKROOT = macosx; 353 | SWIFT_COMPILATION_MODE = wholemodule; 354 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 355 | }; 356 | name = Release; 357 | }; 358 | 89C0C748296BF76100C829FD /* Debug */ = { 359 | isa = XCBuildConfiguration; 360 | buildSettings = { 361 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 362 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 363 | CODE_SIGN_ENTITLEMENTS = "Extension Manager/App/ExtensionManager.entitlements"; 364 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; 365 | CODE_SIGN_STYLE = Automatic; 366 | COMBINE_HIDPI_IMAGES = YES; 367 | CURRENT_PROJECT_VERSION = 1; 368 | DEVELOPMENT_TEAM = Z9HV438N39; 369 | GENERATE_INFOPLIST_FILE = YES; 370 | INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; 371 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 372 | INFOPLIST_KEY_NSMainStoryboardFile = Main; 373 | INFOPLIST_KEY_NSPrincipalClass = NSApplication; 374 | LD_RUNPATH_SEARCH_PATHS = ( 375 | "$(inherited)", 376 | "@executable_path/../Frameworks", 377 | ); 378 | MACOSX_DEPLOYMENT_TARGET = 12.0; 379 | MARKETING_VERSION = 0.4; 380 | PRODUCT_BUNDLE_IDENTIFIER = com.krypted.extensionmanager; 381 | PRODUCT_NAME = "$(TARGET_NAME)"; 382 | SWIFT_EMIT_LOC_STRINGS = YES; 383 | SWIFT_VERSION = 5.0; 384 | }; 385 | name = Debug; 386 | }; 387 | 89C0C749296BF76100C829FD /* Release */ = { 388 | isa = XCBuildConfiguration; 389 | buildSettings = { 390 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 391 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 392 | CODE_SIGN_ENTITLEMENTS = "Extension Manager/App/ExtensionManager.entitlements"; 393 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; 394 | CODE_SIGN_STYLE = Automatic; 395 | COMBINE_HIDPI_IMAGES = YES; 396 | CURRENT_PROJECT_VERSION = 1; 397 | DEVELOPMENT_TEAM = Z9HV438N39; 398 | GENERATE_INFOPLIST_FILE = YES; 399 | INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; 400 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 401 | INFOPLIST_KEY_NSMainStoryboardFile = Main; 402 | INFOPLIST_KEY_NSPrincipalClass = NSApplication; 403 | LD_RUNPATH_SEARCH_PATHS = ( 404 | "$(inherited)", 405 | "@executable_path/../Frameworks", 406 | ); 407 | MACOSX_DEPLOYMENT_TARGET = 12.0; 408 | MARKETING_VERSION = 0.4; 409 | PRODUCT_BUNDLE_IDENTIFIER = com.krypted.extensionmanager; 410 | PRODUCT_NAME = "$(TARGET_NAME)"; 411 | SWIFT_EMIT_LOC_STRINGS = YES; 412 | SWIFT_VERSION = 5.0; 413 | }; 414 | name = Release; 415 | }; 416 | /* End XCBuildConfiguration section */ 417 | 418 | /* Begin XCConfigurationList section */ 419 | 89C0C733296BF75F00C829FD /* Build configuration list for PBXProject "Extension Manager" */ = { 420 | isa = XCConfigurationList; 421 | buildConfigurations = ( 422 | 89C0C745296BF76100C829FD /* Debug */, 423 | 89C0C746296BF76100C829FD /* Release */, 424 | ); 425 | defaultConfigurationIsVisible = 0; 426 | defaultConfigurationName = Release; 427 | }; 428 | 89C0C747296BF76100C829FD /* Build configuration list for PBXNativeTarget "Extension Manager" */ = { 429 | isa = XCConfigurationList; 430 | buildConfigurations = ( 431 | 89C0C748296BF76100C829FD /* Debug */, 432 | 89C0C749296BF76100C829FD /* Release */, 433 | ); 434 | defaultConfigurationIsVisible = 0; 435 | defaultConfigurationName = Release; 436 | }; 437 | /* End XCConfigurationList section */ 438 | }; 439 | rootObject = 89C0C730296BF75F00C829FD /* Project object */; 440 | } 441 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager.xcodeproj/project.xcworkspace/xcuserdata/charlesedge.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager.xcodeproj/project.xcworkspace/xcuserdata/charlesedge.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager.xcodeproj/xcuserdata/charlesedge.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Extension Manager.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/.DS_Store -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/App/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // extensionsman 4 | // 5 | // Created by Charles Edge on 09/01/2023. 6 | // 7 | 8 | import Cocoa 9 | 10 | @main 11 | class AppDelegate: NSObject, NSApplicationDelegate { 12 | 13 | 14 | 15 | 16 | func applicationDidFinishLaunching(_ aNotification: Notification) { 17 | // Insert code here to initialize your application 18 | } 19 | 20 | func applicationWillTerminate(_ aNotification: Notification) { 21 | // Insert code here to tear down your application 22 | } 23 | 24 | func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { 25 | return true 26 | } 27 | 28 | 29 | } 30 | 31 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/App/ExtensionManager.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Features/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Features/.DS_Store -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Features/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // extensionsman 4 | // 5 | // Created by Charles Edge on 09/01/2023. 6 | // 7 | 8 | import Cocoa 9 | 10 | extension NSView { 11 | func setSize(greaterThanEqualTo size: CGSize) { 12 | translatesAutoresizingMaskIntoConstraints = false 13 | widthAnchor.constraint(greaterThanOrEqualToConstant: size.width).isActive = true 14 | heightAnchor.constraint(greaterThanOrEqualToConstant: size.height).isActive = true 15 | } 16 | } 17 | 18 | struct R { 19 | struct Dimension { 20 | static var screenSize: CGSize { 21 | let isFullScreen = NSApplication.shared.windows.first?.styleMask.contains(.fullScreen) ?? false 22 | if let size = NSScreen.main?.visibleFrame.size, !isFullScreen { 23 | return CGSize(width: size.width, height: size.height-20) 24 | }else { 25 | return CGSize(width: 970, height: 700) 26 | } 27 | } 28 | static var minimunSize: CGSize { CGSize(width: 1000, height: 550)} 29 | } 30 | 31 | struct Color { 32 | static let grey = NSColor(named: "grey") 33 | static let text = NSColor.black 34 | } 35 | } 36 | 37 | class ViewController: NSViewController { 38 | 39 | @IBOutlet weak var all: NSSwitch! 40 | @IBOutlet weak var thirdparty: NSSwitch! 41 | @IBOutlet weak var network: NSSwitch! 42 | @IBOutlet weak var system: NSSwitch! 43 | @IBOutlet weak var unloaded: NSSwitch! 44 | @IBOutlet weak var googleChrome: NSSwitch! 45 | @IBOutlet weak var microsoftEdge: NSSwitch! 46 | @IBOutlet weak var fireFox: NSSwitch! 47 | @IBOutlet weak var message: NSTextField! 48 | @IBOutlet weak var tableView: NSTableView! 49 | @IBOutlet weak var searchField: NSSearchField! 50 | 51 | private let store = ExtensionStore(requestModel: RequestModel()) 52 | 53 | private var extensionList = [Extension]() { 54 | didSet { 55 | if extensionList.isEmpty { 56 | message.stringValue = "NO ITEMS FOUND. TRY AGIAN WITH DIFFERENT FILTER" 57 | message.isHidden = false 58 | } else { 59 | message.isHidden = true 60 | } 61 | tableView.reloadData() 62 | } 63 | } 64 | 65 | override func viewDidLoad() { 66 | super.viewDidLoad() 67 | 68 | view.appearance = NSAppearance(named: .vibrantLight) 69 | view.wantsLayer = true 70 | view.layer?.backgroundColor = NSColor.white.cgColor 71 | self.view.setSize(greaterThanEqualTo: R.Dimension.minimunSize) 72 | 73 | message.isBordered = false 74 | message.isEditable = false 75 | message.isSelectable = false 76 | 77 | tableView.dataSource = self 78 | tableView.delegate = self 79 | 80 | searchField.delegate = self 81 | 82 | loadData() 83 | } 84 | 85 | @IBAction func valueChanged(_ sender: NSSwitch) { 86 | loadData() 87 | } 88 | 89 | @IBAction func refresh(_ sender: NSButton) { 90 | loadData() 91 | } 92 | 93 | private func loadData() { 94 | switch store.getExtensions(filter: getFilter(), query: getQuery(), sort: getSort()) { 95 | case .success(let items): 96 | extensionList = items 97 | case .failure(let error): 98 | message.stringValue = error.localizedDescription 99 | message.isHidden = false 100 | } 101 | } 102 | 103 | private func getQuery() -> String { 104 | searchField.stringValue 105 | } 106 | 107 | private func getSort() -> Sort { 108 | let column = tableView.sortDescriptors.first 109 | let type = SortType(value: column?.key ?? "") 110 | return Sort(type: type ?? .name, acending: column?.ascending ?? true) 111 | } 112 | 113 | private func getFilter() -> Filter { 114 | return Filter(all: all.state == .on, thirdparty: thirdparty.state == .on, network: network.state == .on, system: system.state == .on, unloaded: unloaded.state == .on, googleChrome: googleChrome.state == .on, microsoftEdge: microsoftEdge.state == .on, fireFox: fireFox.state == .on) 115 | } 116 | } 117 | 118 | extension ViewController: NSTableViewDataSource { 119 | 120 | func numberOfRows(in tableView: NSTableView) -> Int { 121 | return extensionList.count 122 | } 123 | } 124 | 125 | extension ViewController: NSTableViewDelegate { 126 | 127 | func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { 128 | let reuseId = NSUserInterfaceItemIdentifier(rawValue: "NameCell") 129 | let extensionItem = extensionList[row] 130 | 131 | let text: String 132 | if tableColumn == tableView.tableColumns[0] { 133 | text = extensionItem.name 134 | } else if tableColumn == tableView.tableColumns[1] { 135 | text = extensionItem.vendor 136 | } else if tableColumn == tableView.tableColumns[2] { 137 | text = extensionItem.type 138 | } else if tableColumn == tableView.tableColumns[3] { 139 | text = extensionItem.getStatusDescription() 140 | } else if tableColumn == tableView.tableColumns[4] { 141 | text = extensionItem.path 142 | } else if tableColumn == tableView.tableColumns[5] { 143 | text = extensionItem.version 144 | } else if tableColumn == tableView.tableColumns[6] { 145 | text = extensionItem.sdk 146 | } else { 147 | text = "" 148 | } 149 | 150 | if let cell = tableView.makeView(withIdentifier: reuseId, owner: nil) as? NSTableCellView { 151 | cell.textField?.stringValue = text 152 | return cell 153 | }else { 154 | return nil 155 | } 156 | } 157 | 158 | func tableView(_ tableView: NSTableView, sortDescriptorsDidChange oldDescriptors: [NSSortDescriptor]) { 159 | extensionList = store.changeSorting(sort: getSort()) 160 | } 161 | } 162 | 163 | extension ViewController: NSSearchFieldDelegate { 164 | 165 | func controlTextDidChange(_ obj: Notification) { 166 | extensionList = store.changeQuery(query: getQuery()) 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Models/BrowserExtension.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | struct BrowserExtension: Parseable { 4 | 5 | let list: [Extension] 6 | 7 | init(string: String) { 8 | list = BrowserExtensionParser.parse(string: string) 9 | } 10 | } 11 | 12 | class BrowserExtensionParser { 13 | 14 | static func parse(string: String) -> [Extension] { 15 | 16 | let lines = string.replacingOccurrences(of: "\n", with: ",").components(separatedBy: ",").map{$0.trimmingCharacters(in: .whitespacesAndNewlines)}.filter{!$0.isEmpty} 17 | 18 | var items = [Extension]() 19 | var item = Extension() 20 | // status 21 | // path 22 | 23 | for line in lines where !line.isEmpty { 24 | // tells type of extensions 25 | if line.contains("\"name\":") { 26 | if !item.name.isEmpty { 27 | items.append(item) 28 | } 29 | item = Extension() 30 | item.status = true 31 | item.name = getValue(from: line, key: "name") 32 | } else if line.contains("\"author\":") { 33 | item.parentName = getValue(from: line, key: "author") 34 | } else if line.contains("\"version\":") { 35 | item.version = getValue(from: line, key: "version") 36 | } 37 | } 38 | 39 | if !item.name.isEmpty { 40 | items.append(item) 41 | } 42 | 43 | return items 44 | } 45 | 46 | static private func getValue(from string: String, key: String) -> String { 47 | return string.replacingOccurrences(of: "\"\(key)\":", with: "").replacingOccurrences(of: "\"", with: "") 48 | .replacingOccurrences(of: ",", with: "").trimmingCharacters(in: .whitespacesAndNewlines) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Models/Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Extensions.swift 3 | // Extension Manager 4 | // 5 | // Created by Charles Edge on 15/05/2023. 6 | // 7 | 8 | import Foundation 9 | 10 | class Extension { 11 | var name: String 12 | var status: Bool 13 | var path: String 14 | var version: String 15 | var sdk: String 16 | var bundle: String 17 | var parentName: String 18 | var type: String 19 | var vendor: String { 20 | if bundle.contains("com.apple"){ 21 | return "Apple" 22 | } else if !parentName.isEmpty { 23 | return parentName 24 | } else { 25 | return bundle.components(separatedBy: ".").getItemOrEmpty(at: 1) 26 | } 27 | } 28 | 29 | init() { 30 | name = "" 31 | status = false 32 | path = "" 33 | version = "" 34 | sdk = "" 35 | bundle = "" 36 | parentName = "" 37 | type = "" 38 | } 39 | 40 | func getStatusDescription() -> String { 41 | return status ? "Installed" : "Not Installed" 42 | } 43 | 44 | func getVersionNo() -> Double { 45 | let components = version.components(separatedBy: ".") 46 | if components.count > 2 { 47 | return Double("\(components[0]).\(components[1])") ?? 0 48 | }else { 49 | return Double(version) ?? 0 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Models/Filter.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | struct Filter { 4 | let all: Bool 5 | let thirdparty: Bool 6 | let network: Bool 7 | let system: Bool 8 | let unloaded: Bool 9 | let googleChrome: Bool 10 | let microsoftEdge: Bool 11 | let fireFox: Bool 12 | 13 | init(all: Bool, thirdparty: Bool, network: Bool, system: Bool, unloaded: Bool, googleChrome: Bool, microsoftEdge: Bool, fireFox: Bool) { 14 | self.all = all 15 | self.thirdparty = thirdparty 16 | self.network = network 17 | self.system = system 18 | self.unloaded = unloaded 19 | self.googleChrome = googleChrome 20 | self.microsoftEdge = microsoftEdge 21 | self.fireFox = fireFox 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Models/Firefox.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | class Firefox: Decodable { 4 | let addons: [FirefoxItem]? 5 | } 6 | 7 | class FirefoxItem: Decodable { 8 | private let id: String 9 | private let defaultLocale: DefaultLocale? 10 | private let location: String 11 | let version: String 12 | let path: String 13 | let active: Bool 14 | var name: String { defaultLocale?.name ?? "" } 15 | var vendor: String { defaultLocale?.homepageURL ?? id } 16 | 17 | enum CodingKeys: CodingKey { 18 | case id 19 | case defaultLocale 20 | case location 21 | case version 22 | case path 23 | case active 24 | } 25 | 26 | required init(from decoder: Decoder) throws { 27 | let container = try decoder.container(keyedBy: CodingKeys.self) 28 | 29 | self.id = try container.decodeIfPresent(String.self, forKey: .id) ?? "" 30 | self.defaultLocale = try container.decodeIfPresent(DefaultLocale.self, forKey: .defaultLocale) 31 | self.location = try container.decodeIfPresent(String.self, forKey: .location) ?? "" 32 | self.version = try container.decodeIfPresent(String.self, forKey: .version) ?? "" 33 | self.path = try container.decodeIfPresent(String.self, forKey: .path) ?? "" 34 | self.active = try container.decodeIfPresent(Bool.self, forKey: .active) ?? false 35 | } 36 | 37 | } 38 | 39 | class DefaultLocale: Decodable { 40 | let name: String? 41 | let homepageURL: String? 42 | } 43 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Models/Parseable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Parseable.swift 3 | // Extension Manager 4 | // 5 | // Created by Charles Edge on 15/05/2023. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol Parseable { 11 | init( string: String) 12 | } 13 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Models/Plugin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Plugings.swift 3 | // Extension Manager 4 | // 5 | // Created by Charles Edge on 15/05/2023. 6 | // 7 | 8 | import Foundation 9 | 10 | struct Plugins: Parseable { 11 | let list: [Extension] 12 | 13 | init(string: String) { 14 | list = PluginParser.parse(string: string) 15 | } 16 | } 17 | 18 | class PluginParser { 19 | 20 | static func parse(string: String) -> [Extension] { 21 | 22 | let items = string.components(separatedBy: "\n").dropLast() 23 | 24 | var extensionList = [Extension]() 25 | var extensionItem = Extension() 26 | extensionItem.type = "App Extension" 27 | var newItem = true 28 | 29 | for item in items { 30 | if item.isEmpty { 31 | extensionList.append(extensionItem) 32 | extensionItem = Extension() 33 | extensionItem.type = "App Extension" 34 | newItem = true 35 | continue 36 | } 37 | 38 | if newItem { 39 | extensionItem.status = !item.contains("-") 40 | let bundleComponents = item.replacingOccurrences(of: "+", with: "").replacingOccurrences(of: "-", with: "").components(separatedBy: "(") 41 | extensionItem.version = bundleComponents.last?.replacingOccurrences(of: ")", with: "").trimmingCharacters(in: .whitespacesAndNewlines) ?? "" 42 | extensionItem.bundle = bundleComponents.first?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" 43 | 44 | }else if item.contains("Path"){ 45 | extensionItem.path = item.replacingOccurrences(of: "Path = ", with: "").trimmingCharacters(in: .whitespacesAndNewlines) 46 | }else if item.contains("SDK") { 47 | extensionItem.sdk = item.replacingOccurrences(of: "SDK = ", with: "").trimmingCharacters(in: .whitespacesAndNewlines) 48 | }else if item.contains("Display Name") { 49 | extensionItem.name = item.replacingOccurrences(of: "Display Name = ", with: "").trimmingCharacters(in: .whitespacesAndNewlines) 50 | }else if item.contains("Parent Name") { 51 | extensionItem.parentName = item.replacingOccurrences(of: "Parent Name = ", with: "").trimmingCharacters(in: .whitespacesAndNewlines) 52 | } 53 | newItem = false 54 | 55 | } 56 | 57 | return extensionList 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Models/Sort.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | struct Sort { 4 | let type: SortType 5 | let acending: Bool 6 | } 7 | 8 | enum SortType { 9 | case name 10 | case vendor 11 | case type 12 | case path 13 | case status 14 | case version 15 | case sdk 16 | 17 | init?(value: String) { 18 | switch value { 19 | case "name": 20 | self = .name 21 | case "vendor": 22 | self = .vendor 23 | case "type": 24 | self = .type 25 | case "status": 26 | self = .status 27 | case "path": 28 | self = .path 29 | case "version": 30 | self = .version 31 | case "sdk": 32 | self = .sdk 33 | default: 34 | return nil 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Models/SystemExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SystemExtension.swift 3 | // Extension Manager 4 | // 5 | // Created by Charles Edge on 15/05/2023. 6 | // 7 | 8 | import Foundation 9 | 10 | struct SystemExtensions: Parseable { 11 | 12 | let network: [Extension] 13 | let others: [Extension] 14 | 15 | init(string: String) { 16 | let data = SystemExtensionParser.parse(string: string) 17 | network = data.network 18 | others = data.others 19 | } 20 | 21 | init(network: [Extension], others: [Extension]) { 22 | self.network = network 23 | self.others = others 24 | } 25 | } 26 | 27 | class SystemExtensionParser { 28 | 29 | static func parse(string: String) -> SystemExtensions { 30 | 31 | let lines = string.components(separatedBy: "\n").dropFirst().map{$0.trimmingCharacters(in: .whitespacesAndNewlines)} 32 | 33 | var otherItems = [Extension]() 34 | var networkItems = [Extension]() 35 | var isNetworkItems = false 36 | 37 | for line in lines where !line.isEmpty { 38 | // tells type of extensions 39 | if line.starts(with: "---") { 40 | isNetworkItems = line.contains("com.apple.system_extension.network_extension") 41 | } 42 | // tells column names 43 | else if line.contains("bundleID (version)") { 44 | continue 45 | } 46 | // network item 47 | else { 48 | let columns = line.components(separatedBy: "\t") 49 | let extensionItem = Extension() 50 | let bundleInfo = columns.getItemOrEmpty(at: 3) 51 | let bundleComponents = bundleInfo.components(separatedBy: "(") 52 | extensionItem.bundle = bundleComponents.first?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" 53 | let versionInfo = (bundleComponents.last ?? "").trimmingCharacters(in: .whitespacesAndNewlines) 54 | let versionComponents = versionInfo.components(separatedBy: "/") 55 | extensionItem.version = versionComponents.isEmpty ? versionInfo : (versionComponents.first ?? "") 56 | extensionItem.name = columns.getItemOrEmpty(at: 4) 57 | extensionItem.type = isNetworkItems ? "Network Extension" : "System Extension" 58 | extensionItem.status = columns.getItemOrEmpty(at: 5).contains("enabled") 59 | isNetworkItems ? networkItems.append(extensionItem) : otherItems.append(extensionItem) 60 | } 61 | } 62 | 63 | return .init(network: networkItems, others: otherItems) 64 | } 65 | } 66 | 67 | struct SystemExtensionsUnloaded: Parseable { 68 | 69 | let list: [String] 70 | 71 | init(string: String) { 72 | list = string.components(separatedBy: "\n").map{$0.trimmingCharacters(in: .whitespacesAndNewlines)}.filter{!$0.isEmpty} 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/.DS_Store -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/.DS_Store -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/128.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/16.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/256 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/256 1.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/256.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/32 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/32 1.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/32.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/512 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/512 1.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/512.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/64.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "16.png", 5 | "idiom" : "mac", 6 | "scale" : "1x", 7 | "size" : "16x16" 8 | }, 9 | { 10 | "filename" : "32.png", 11 | "idiom" : "mac", 12 | "scale" : "2x", 13 | "size" : "16x16" 14 | }, 15 | { 16 | "filename" : "32 1.png", 17 | "idiom" : "mac", 18 | "scale" : "1x", 19 | "size" : "32x32" 20 | }, 21 | { 22 | "filename" : "64.png", 23 | "idiom" : "mac", 24 | "scale" : "2x", 25 | "size" : "32x32" 26 | }, 27 | { 28 | "filename" : "128.png", 29 | "idiom" : "mac", 30 | "scale" : "1x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "filename" : "256.png", 35 | "idiom" : "mac", 36 | "scale" : "2x", 37 | "size" : "128x128" 38 | }, 39 | { 40 | "filename" : "256 1.png", 41 | "idiom" : "mac", 42 | "scale" : "1x", 43 | "size" : "256x256" 44 | }, 45 | { 46 | "filename" : "512.png", 47 | "idiom" : "mac", 48 | "scale" : "2x", 49 | "size" : "256x256" 50 | }, 51 | { 52 | "filename" : "512 1.png", 53 | "idiom" : "mac", 54 | "scale" : "1x", 55 | "size" : "512x512" 56 | }, 57 | { 58 | "filename" : "1024.png", 59 | "idiom" : "mac", 60 | "scale" : "2x", 61 | "size" : "512x512" 62 | } 63 | ], 64 | "info" : { 65 | "author" : "xcode", 66 | "version" : 1 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/appstore1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/appstore1024.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipad152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipad152.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipad76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipad76.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipadNotification20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipadNotification20.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipadNotification40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipadNotification40.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipadPro167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipadPro167.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipadSettings29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipadSettings29.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipadSettings58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipadSettings58.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipadSpotlight40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipadSpotlight40.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipadSpotlight80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/ipadSpotlight80.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/iphone120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/iphone120.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/iphone180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/iphone180.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/mac1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/mac1024.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/mac128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/mac128.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/mac16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/mac16.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/mac256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/mac256.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/mac32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/mac32.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/mac512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/mac512.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/mac64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/mac64.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/notification40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/notification40.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/notification60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/notification60.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/settings58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/settings58.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/settings87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/settings87.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/spotlight120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/spotlight120.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/spotlight80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/AppIcon.appiconset/spotlight80.png -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/grey.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0x92", 9 | "green" : "0x92", 10 | "red" : "0x92" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Resources/Assets.xcassets/text.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0x00", 9 | "green" : "0x00", 10 | "red" : "0x00" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Store/ExtensionStore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExtensionStore.swift 3 | // Panagram 4 | // 5 | // Created by Charles Edge on 20/12/2022. 6 | // 7 | 8 | import Foundation 9 | 10 | class ExtensionStore { 11 | 12 | private let requestModel: RequestModel 13 | 14 | init(requestModel: RequestModel) { 15 | self.requestModel = requestModel 16 | } 17 | 18 | // MARK: - Type 19 | enum ExtensionType: String { 20 | case network 21 | case system 22 | case thirdparty 23 | case apple 24 | } 25 | 26 | enum Query: String, CaseIterable { 27 | case plugin = "pluginkit -mvv" 28 | case systemExtension = "systemextensionsctl list" 29 | case chrome = "find ~/Library/Application\\ Support/Google/Chrome/Default/Extensions -type f -name \"manifest.json\" -print0 | xargs -I {} -0 grep \'\"name\\|version\\|author\"\' \"{}\" | uniq" 30 | case microsoftEdge = "find ~/Library/Application\\ Support/Microsoft\\ Edge/Default/Extensions -type f -name \"manifest.json\" -print0 | xargs -I {} -0 grep \'\"name\\|version\\|autor\":\' \"{}\" | uniq" 31 | case firefox = "find ~/Library/Application\\ Support/Firefox/Profiles/ -type f -name \"extensions.json\" -print0 | xargs -I {} -0 grep \'\' \"{}\" | uniq" 32 | } 33 | 34 | struct Response { 35 | let query: String 36 | let data: String 37 | } 38 | 39 | // MARK: - Plugins 40 | private func getThirdpartyExtensions() -> Result<[Extension],Error> { 41 | getAllPlugins().map{$0.filter{$0.vendor != "Apple"}} 42 | } 43 | 44 | private func getAllPlugins() -> Result<[Extension],Error> { 45 | let pluginResult: Result = requestModel.runQuery(Query.plugin.rawValue) 46 | return pluginResult.map{$0.list} 47 | } 48 | 49 | // MARK: - System Extensions 50 | private func getAllSystemExtensions() -> Result{ 51 | requestModel.runQuery(Query.systemExtension.rawValue) 52 | } 53 | 54 | private func getNetworkExtensions() -> Result<[Extension],Error> { 55 | getAllSystemExtensions().map{$0.network} 56 | } 57 | 58 | private func getOtherExtensions() -> Result<[Extension],Error> { 59 | getAllSystemExtensions().map{$0.others} 60 | } 61 | 62 | private func getSystemExtensionsUnloaded() -> Result<[Extension],Error> { 63 | getAllSystemExtensions().map{ items in 64 | let all = items.network + items.others 65 | return all.filter{!$0.status} 66 | } 67 | } 68 | 69 | // MARK: Browser Extensions 70 | func getChromeExtensions() -> Result<[Extension],Error> { 71 | let result: Result = requestModel.runQuery(Query.chrome.rawValue) 72 | return result.map{ $0.list.map { item in 73 | item.type = "Google Chrome" 74 | return item 75 | }} 76 | } 77 | 78 | func getMicrosoftEdgeExtensions() -> Result<[Extension],Error> { 79 | let result: Result = requestModel.runQuery(Query.microsoftEdge.rawValue) 80 | return result.map{ $0.list.map { item in 81 | item.type = "MicrosoftEdge Extension" 82 | return item 83 | }} 84 | } 85 | 86 | func getFirefoxExtensions() -> Result<[Extension],Error> { 87 | let result: Result = requestModel.getData(query: Query.firefox.rawValue) 88 | switch result { 89 | case .success(let rawData): 90 | do { 91 | let data = rawData.trimmingCharacters(in: .whitespacesAndNewlines).data(using: .utf8) ?? Data() 92 | let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String:AnyObject] 93 | let jsonData = try JSONSerialization.data(withJSONObject: json ?? [:], options: .prettyPrinted) 94 | let firefoxExtensions = try JSONDecoder().decode(Firefox.self, from: jsonData) 95 | let extensions = (firefoxExtensions.addons ?? []).map { 96 | let item = Extension() 97 | item.name = $0.name 98 | item.parentName = $0.vendor 99 | item.type = "Firefox Extension" 100 | item.status = $0.active 101 | item.path = $0.path 102 | item.version = $0.version 103 | return item 104 | } 105 | return .success(extensions) 106 | } catch { 107 | print(error) 108 | return .success([]) 109 | } 110 | case .failure(let error): 111 | return .failure(error) 112 | } 113 | } 114 | 115 | // MARK: - All 116 | private func getAllExtensions() -> Result<[Extension],Error> { 117 | 118 | var result = [Extension]() 119 | 120 | let systemExtensions = getAllSystemExtensions().map{ $0.network + $0.others } 121 | for extensionsResponse in [getAllPlugins(), systemExtensions, getChromeExtensions(), getMicrosoftEdgeExtensions(), getFirefoxExtensions()] { 122 | switch extensionsResponse { 123 | case.success(let response): 124 | result.append(contentsOf: response) 125 | case .failure(let error): 126 | return .failure(error) 127 | } 128 | } 129 | 130 | return .success(result) 131 | } 132 | 133 | // MARK: Filter Data 134 | private var extensionsList = [Extension]() 135 | private var query = "" 136 | private var sort = Sort(type: .name, acending: true) 137 | 138 | func changeQuery(query: String) -> [Extension] { 139 | self.query = query 140 | return filterExtensions(query: query, sort: sort, extensions: extensionsList) 141 | } 142 | 143 | func changeSorting(sort: Sort) -> [Extension] { 144 | self.sort = sort 145 | return filterExtensions(query: query, sort: sort, extensions: extensionsList) 146 | } 147 | 148 | private func filterExtensions(query: String, sort: Sort, extensions: [Extension]) -> [Extension] { 149 | var list = extensions 150 | if !query.isEmpty { 151 | list = list.filter{$0.name.lowercased().starts(with: query.lowercased())} 152 | } 153 | 154 | list = sortExtensions(sort: sort, extensions: list) 155 | return list 156 | } 157 | 158 | private func sortExtensions(sort: Sort, extensions: [Extension]) -> [Extension] { 159 | var result = extensions 160 | let isSorted: (String,String)->Bool = { value1, value2 -> Bool in 161 | sort.acending ? value1 < value2 : value1 > value2 162 | } 163 | 164 | switch sort.type { 165 | case .name: 166 | result = result.sorted(by: { e1, e2 in 167 | isSorted(e1.name, e2.name) 168 | }) 169 | case .vendor: 170 | result = result.sorted(by: { e1, e2 in 171 | isSorted(e1.vendor, e2.vendor) 172 | }) 173 | case .type: 174 | result = result.sorted(by: { e1, e2 in 175 | isSorted(e1.type, e2.type) 176 | }) 177 | case .status: 178 | result = result.sorted(by: { e1, e2 in 179 | isSorted(e1.getStatusDescription(), e2.getStatusDescription()) 180 | }) 181 | case .path: 182 | result = result.sorted(by: { e1, e2 in 183 | isSorted(e1.path, e2.path) 184 | }) 185 | case .version: 186 | result = result.sorted(by: { e1, e2 in 187 | sort.acending ? e1.getVersionNo() < e2.getVersionNo() : e1.getVersionNo() > e2.getVersionNo() 188 | }) 189 | case .sdk: 190 | result = result.sorted(by: { e1, e2 in 191 | isSorted(e1.sdk, e2.sdk) 192 | }) 193 | } 194 | 195 | return result 196 | } 197 | 198 | func getExtensions(filter: Filter, query: String, sort: Sort) -> Result<[Extension], Error> { 199 | 200 | self.query = query 201 | self.sort = sort 202 | 203 | guard !filter.all else { 204 | let result = getAllExtensions() 205 | 206 | // save for later use when user only change search text 207 | self.extensionsList = (try? result.get()) ?? [] 208 | 209 | return result.map{ filterExtensions(query: query, sort: sort, extensions: $0) } 210 | } 211 | 212 | var extensionList = [Extension]() 213 | let empty = Result<[Extension], Error>.success([]) 214 | let result = [filter.thirdparty ? getThirdpartyExtensions() : empty, 215 | filter.network ? getNetworkExtensions() : empty, 216 | filter.system ? getOtherExtensions() : empty, 217 | filter.unloaded ? getSystemExtensionsUnloaded() : empty, 218 | filter.googleChrome ? getChromeExtensions() : empty, 219 | filter.microsoftEdge ? getMicrosoftEdgeExtensions() : empty, 220 | filter.fireFox ? getFirefoxExtensions() : empty] 221 | 222 | for extensionsResponse in result { 223 | switch extensionsResponse { 224 | case.success(let response): 225 | extensionList.append(contentsOf: response) 226 | case .failure(let error): 227 | return .failure(error) 228 | } 229 | } 230 | 231 | // save for later use when user only change search text 232 | self.extensionsList = extensionList 233 | 234 | return .success(filterExtensions(query: query, sort: sort, extensions: extensionsList)) 235 | } 236 | 237 | // MARK: - Raw 238 | func getRawData() -> Result { 239 | 240 | var result = "" 241 | 242 | for dataResponse in Query.allCases.map({ requestModel.getData(query: $0.rawValue)}) { 243 | switch dataResponse { 244 | case .success(let response): 245 | let prefix = result.isEmpty ? "" : "\n" 246 | result.append("\(prefix)"+response) 247 | case .failure(let error): 248 | return .failure(error) 249 | } 250 | } 251 | 252 | return .success(result) 253 | } 254 | } 255 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Store/RequestModel.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | class RequestModel { 4 | 5 | @discardableResult private func safeShell(_ command: String) throws -> String { 6 | let task = Process() 7 | let pipe = Pipe() 8 | 9 | task.standardOutput = pipe 10 | task.standardError = pipe 11 | // task.arguments = ["-c", command] 12 | task.arguments = ["-c", command] 13 | task.executableURL = URL(fileURLWithPath: "/bin/zsh") //<--updated 14 | // task.executableURL = URL(fileURLWithPath: "/bin/bash") //<--updated 15 | // task.executableURL = URL(fileURLWithPath: "/usr/bin/env") //<--updated 16 | task.standardInput = nil 17 | 18 | try task.run() //<--updated 19 | // task.launch() 20 | 21 | 22 | let data = pipe.fileHandleForReading.readDataToEndOfFile() 23 | let output = String(data: data, encoding: .utf8)! 24 | 25 | return output 26 | } 27 | 28 | func getData(query: String) -> Result { 29 | do { 30 | let data = try safeShell(query) 31 | return .success(data) 32 | }catch { 33 | return .failure(error) 34 | } 35 | } 36 | 37 | func runQuery(_ query: String) -> Result where T: Parseable { 38 | getData(query: query).map{ T(string: $0) } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/Extension Manager/Utilities/Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Extensions.swift 3 | // Extension Manager 4 | // 5 | // Created by Charles Edge on 09/01/2023. 6 | // 7 | 8 | import Foundation 9 | 10 | extension Array where Element == String { 11 | 12 | func getItem(at index: Int) -> String? { 13 | guard index < self.count else {return nil } 14 | return self[index] 15 | } 16 | 17 | func getItemOrEmpty(at index: Int) -> String { 18 | getItem(at: index) ?? "" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Extension-Manager-GUI/README.md: -------------------------------------------------------------------------------- 1 | # Extension-Manager 2 | A ui application for a command line tool I created called "extensionsman" 3 | It provide details about system extensions and application plugins. Allows user to apply different filters and view details abount extensions. 4 | -------------------------------------------------------------------------------- /Firefox Extensions/apis: -------------------------------------------------------------------------------- 1 | action 2 | alarms 3 | bookmarks 4 | browserAction 5 | browserSettings 6 | browsingData 7 | captivePortal 8 | clipboard 9 | commands 10 | contentScripts 11 | contextualIdentities 12 | cookies 13 | devtools 14 | dns 15 | dom 16 | downloads 17 | events 18 | extension 19 | extensionTypes 20 | find 21 | history 22 | i18n 23 | identity 24 | idle 25 | management 26 | menus 27 | notifications 28 | omnibox 29 | pageAction 30 | permissions 31 | pkcs11 32 | privacy 33 | proxy 34 | runtime 35 | scripting 36 | search 37 | sessions 38 | sidebarAction 39 | storage 40 | tabs 41 | theme 42 | topSites 43 | types 44 | userScripts 45 | webNavigation 46 | webRequest 47 | windows 48 | -------------------------------------------------------------------------------- /Firefox Extensions/apisaslist: -------------------------------------------------------------------------------- 1 | APIs = ("action." "alarms." "bookmarks." "browserAction." "browserSettings." "browsingData." "captivePortal." "clipboard." "commands." "contentScripts." "contextualIdentities." "cookies." "devtools." "dns." "dom." "downloads." "events." "extension." "extensionTypes." "find." "history." "i18n." "identity." "idle." "management." "menus." "notifications." "omnibox." "pageAction." "permissions." "pkcs11." "privacy." "proxy." "runtime." "scripting." "search." "sessions." "sidebarAction." "storage." "tabs." "theme." "topSites." "types." "userScripts." "webNavigation." "webRequest." "windows.") 2 | -------------------------------------------------------------------------------- /Firefox Extensions/readme.md: -------------------------------------------------------------------------------- 1 | Browser extensions can perform a number of tasks like access filesystems, gain telemetry on what processes are running on a host, view browsing history, etc. Here is a list of the APIs that Firefox makes available to Extension developers https://github.com/krypted/extensionsmanager/blob/main/Firefox%20Extensions/apisaslist. 2 | 3 | ## Get A List of Extensions 4 | Firefox for Mac stores a list of extensions in /Users/*/Library/Application\ Support/Firefox/Profiles/*/extensions.json (the first * denotes there's a manifest for each user and the second * denotes there are multiple profiles with their own sets of extensions for each Firefox user within that Mac user account). To see a list of all of the extensions in Firefox, the following find command can parse through the directory (or directories), read the extensions.json, and find the name field. 5 | 6 | ``` 7 | cat /Users/*/Library/Application\ Support/Firefox/Profiles/*/extensions.json | sed 's/"name"/\n"name"/g' | grep '"name"' | awk -F',' '{print $2}' 8 | ``` 9 | -------------------------------------------------------------------------------- /Images/em3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Images/em3.png -------------------------------------------------------------------------------- /Images/em4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Images/em4.png -------------------------------------------------------------------------------- /Images/xc1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Images/xc1.png -------------------------------------------------------------------------------- /Images/xc2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/Images/xc2.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /Microsoft Edge/apis: -------------------------------------------------------------------------------- 1 | # APIs Used in Microsoft Edge Extensions 2 | 3 | APIs come in the format of API name followed by the method. Available APIs are as listed below: 4 | 5 | alarms 6 | bookmarks 7 | browserAction 8 | browsingData 9 | commands 10 | contentSettings 11 | contextMenus 12 | cookies 13 | debugger 14 | declarativeContent 15 | declarativeNetRequest Provides 16 | desktopCapture 17 | devtools.network 18 | devtools.panels 19 | downloads 20 | enterprise.hardwarePlatform 21 | events 22 | extension 23 | extensionTypes 24 | fontSettings 25 | history 26 | i18n 27 | idle 28 | management 29 | notifications 30 | omnibox 31 | pageAction 32 | pageCapture 33 | permissions 34 | power 35 | printerProvider 36 | privacy 37 | proxy 38 | runtime 39 | sessions 40 | storage 41 | system.memory 42 | system.storage 43 | tabCapture 44 | tabs Interact 45 | topSites 46 | tts 47 | ttsEngine 48 | types 49 | webNavigation 50 | webRequest 51 | -------------------------------------------------------------------------------- /Microsoft Edge/apisasarray: -------------------------------------------------------------------------------- 1 | apis = (“alarms” “bookmarks” “browserAction” “browsingData” “commands” 2 | “contentSettings” “contextMenus” “cookies” “debugger” “declarativeContent” 3 | “declarativeNetRequest” “desktopCapture” “devtools.network” 4 | “devtools.panels” “downloads” “enterprise.hardwarePlatform” “events” 5 | “extension” “extensionTypes” “fontSettings” “history” “i18n” “idle” 6 | “management” “notifications” “omnibox” “pageAction” “pageCapture” 7 | “permissions” “power” “printerProvider” “privacy” “proxy” “runtime” 8 | “sessions” “storage” “system.memory” “system.storage” “tabCapture” 9 | “tabsInteract” “topSites” “tts” “ttsEngine” “types” “webNavigation” 10 | “webRequest”) 11 | -------------------------------------------------------------------------------- /Microsoft Edge/readme.md: -------------------------------------------------------------------------------- 1 | Browser extensions can perform a number of tasks like access filesystems, gain telemetry on what processes are running on a host, view browsing history, etc. Here is a list of the APIs that Microsoft makes available to Microsoft Edge extension developers https://github.com/krypted/extensionsmanager/blob/main/Microsoft%20Edge/apis. Or in a standard shell scripting array form to aid in tool development, see https://github.com/krypted/extensionsmanager/blob/main/Microsoft%20Edge/apisasarray. 2 | 3 | ## Get A List of Extensions 4 | Edge for Mac stores a list of extensions in ~/Library/Application\ Support/Microsoft\ Edge/Default/Extensions (where the ~ denotes a user's home directory). To see a list of all of the extensions in Chrome on a given machine, the following find command can parse through the directory (or directories if a * is used like in /Users/*/Library/Application\ Support/Microsoft\ Edge/Default/Extensions), read the manifest.json for extensions. 5 | 6 | ``` 7 | find ~/Library/Application\ Support/Microsoft\ Edge/Default/Extensions -type f -name "manifest.json" -print0 | xargs -I {} -0 grep '"name":' "{}" | uniq 8 | ``` 9 | Microsoft Edge exposes a few features in a property list, but none involve extensions (the traditional method for Mac management). 10 | ``` 11 | defaults read ~/Library/Preferences/com.microsoft.edgemac.plist 12 | { 13 | LastRunAppBundlePath = "/Applications/Microsoft Edge.app"; 14 | LoginKeychainEmpty = 1; 15 | OptionalDataCollectionEnabled = 0; 16 | } 17 | ``` 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Extensions Manager and extensionsman 2 | 3 | To just download the graphical interface, click here https://github.com/krypted/extensionsmanager/raw/main/Extension%20Manager%20Executable.zip. 4 | To just download the signed CLI version, click here https://github.com/krypted/extensionsmanager/blob/main/extensionsmanCLI_Signed.zip 5 | 6 | ## Purpose 7 | 8 | This project is to provide single pane of glass telemetry into extensions on macOS. There are a few types of extensions. As such, Extensions Manager (the GUI) and extensionsmman the CLI can be used to see the system extensions, network extensions (which are a class of system extensions), and the app extensions that are on a system. `pluginkit` and `systemextensionsctl` can be used to obtain some of this information if the app has been opened and the extension loaded or known about based on the underlying daemon that manages that type of extension. The goal of this project is to see the extensions that have not been loaded and provide a single interface to see information about the various types of extensions on a system. `extensionsman` is the first of the tools (a CLI version) to aggregate information from the built-in tools from Apple about extensions. Exteensions Manager is a graphical interface that provides much of the same information but in a GUI. 9 | 10 | 11 | 12 | ## Background 13 | 14 | This project is loosely based on the research documented at https://krypted.com/mac-os-x/get-telemetry-on-app-and-system-extensions-in-macos/. This builds on the previous scripts at [https://github.com/krypted/extensionslist](https://github.com/krypted/extensionslist/blob/main/extensionslist.sh) and those can still be used. The new project is compiled in swift so access to the necessary entitlements can be granted via MDM at deployment time and run on client systems (like what was covered in https://krypted.com/mac-security/macos-script-to-list-system-extensions-and-their-state/ but in swift). 15 | 16 | ## Contents of the Project 17 | 18 | This is two projects. The first is a command line interface (`extensionsman` compiled binary, extensionsman-CLI Xcode Project, and extensionsman-CLI zipped up Xcode Project) that provides information about app extensions, system extensions, and network extensions. The second is a shell for a graphical interface. This can be edited and given the open nature of the license, embedded into other products. 19 | 20 | The source of each is posted, so they can be altered and compiled based on further needs. 21 | 22 | ## Command Line Usage 23 | 24 | `extensionsman -all` to show all extensions 25 | 26 | or 27 | 28 | `extensionsman -thirdparty` to show thirdparty extensions 29 | 30 | or 31 | 32 | `extensionsman -n` to show network extensions 33 | 34 | or 35 | 36 | `extensionsman -s` to show system extensions except network extensions 37 | 38 | or 39 | 40 | `extensionsman -raw` to show unformatted result 41 | 42 | or 43 | 44 | `extensionsman -u` to show system extensions that haven't been loaded 45 | 46 | or 47 | 48 | `extensionsman -h` to show usage information 49 | 50 | ## How It Works 51 | 52 | Built-in tools like `pluginkit` and `systemextensionsctl` can be used to see information about extensions once they've been loaded. `pkd` (for app extensions) and one of a few different daemons for system extensions manage them on a Mac. However, it is possible (and likely) that there are .appex and .systemextension bundles on a device that haven't yet been registered. These can live in /Applications, /Applications/Utilities, and /Library/Application Support. Therefore, in order to see which are on a system, these directories need to be searched and compared against the information obtained through pluginkit and systemextensionsctl for a more holistic view of the extensions on a device. Just combing through the directory tree hasn't been added to the project but is planned and is available in a shell script form at https://github.com/krypted/extensionslist/blob/main/systemextensions.sh . 53 | 54 | Extensions have privacy implications. Apple provided the tools mentioned to give system administrators access to information on devices; however, this information is not readily available via API endpoints that can be called via swift. To quote the great Quinn "The Eskimo!" at Apple, "There is no API to get the list of system extensions installed. However, you can tell whether your system extension is installed by calling the -request:foundProperties: method." The goal is not to see if an extension is loaded from within an app but instead to see a digest of extensions. Therefore, while this is a swift project, some of the work being done is accessing shell commands (yes, shelling out to get information is dirty but sometimes it's a thing). 55 | 56 | ## Troubleshoot Build Issues 57 | 58 | The App Sandbox won't allow running command line tools/accessing APIs used in the project. This is why this app hasn't been submitted to the Mac App Store. The following error could appear if App Sandbox is enabled: 59 | 60 | 61 | 62 | To fix, change the "Enable App Sandbox" option to No. 63 | 64 | 65 | 66 | ## Other Types of Extensions 67 | Swift apps aren't the only thing on a Mac that's extensible. For more on telemetry into what Chrome Extensions are doing and to list them, see https://github.com/krypted/extensionsmanager/tree/main/Chrome%20Extensions. Keep in mind that as users use Chrome they grant more and more entitlements to the browser. For a list of Chrome extension APIs that can be consumed by basic javascripts, see https://github.com/krypted/extensionsmanager/blob/main/Chrome%20Extensions/apilist. 68 | 69 | Firefox is similar. Most endpoints are named similarly ( https://github.com/krypted/extensionsmanager/blob/main/Firefox%20Extensions/apisaslist ), but the notation isn't chrome., it's browser... Thefore, the scripts have to be tailored to a different format for expressions. Further, Firefox keeps a simple extensions.json so it's easy to list them https://github.com/krypted/extensionsmanager/tree/main/Firefox%20Extensions. 70 | 71 | Microsoft Edge is also similar, with similarly named endpoints, listed at https://github.com/krypted/extensionsmanager/blob/main/Microsoft%20Edge/apis and a find to locate all the extensions at https://github.com/krypted/extensionsmanager/blob/main/Microsoft%20Edge/readme.md. 72 | 73 | Here, there are three scripts (shell one-liners, really), that can be used to list extensions for each of these browsers (keep in mind that the main project here will list Safari Extensions). The looping and parsing to see which APIs are available is only in the Chrome section from the first paragraph of this section, but the logic and permission structures are similar for the other two, so lists are only a little regex work away. 74 | 75 | ## What's next? 76 | 77 | It would be great to allow for disabling and re-enabling extensions... Given that much wisdom can be found in analyzing the past, maybe it will look something like this (or later versions): 78 | 79 | 80 | 81 | It would be trivial to unload extensions or provide an option to delete an application bundle (or archive to a location an extension can't run at) that is used to load an extension but is currently beyond the scope of what we're trying to accomplish. We also didn't add the ability to see what apps use the extension symbols in compiled form, but instead that's at https://krypted.com/mac-os-x/new-tool-to-recursively-search-all-macos-binaries-for-symbols/ (these can take all night to run). 82 | 83 | Because we're shelling information out it also uses a Refresh button to re-run all the scripts. It would be great to some day be able to get an entitlement that allows objects to natively work with async functions in macOS in such a way that they can be dynamically displayed (or this whole project could get sherlocked, which would be great tbh). Further GUI enhancements should eventually include a search box, the ability to sort for each column, and better dark mode support. 84 | -------------------------------------------------------------------------------- /extensionsman: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/extensionsman -------------------------------------------------------------------------------- /extensionsman-CLI/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/extensionsman-CLI/.DS_Store -------------------------------------------------------------------------------- /extensionsman-CLI/App/ConsoleIO.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ConsoleIO.swift 3 | // 4 | // Created by Charles Edge on 19/12/2022. 5 | // 6 | 7 | import Foundation 8 | class ConsoleIO { 9 | 10 | enum OutputType { 11 | case error 12 | case standard 13 | } 14 | 15 | func writeMessage(_ message: String, to: OutputType = .standard) { 16 | switch to { 17 | case .standard: 18 | print(message) 19 | case .error: 20 | fputs("Error: \(message)\n", stderr) 21 | } 22 | } 23 | 24 | func printUsage() { 25 | let executableName = (CommandLine.arguments[0] as NSString).lastPathComponent 26 | writeMessage("usage:") 27 | writeMessage("\(executableName) -all to show all extensions") 28 | writeMessage("or") 29 | writeMessage("\(executableName) -thirdparty to show thirdparty extensions") 30 | writeMessage("or") 31 | writeMessage("\(executableName) -n to show network extensions") 32 | writeMessage("or") 33 | writeMessage("\(executableName) -s to show system extensions except network extensions") 34 | writeMessage("or") 35 | writeMessage("\(executableName) -u to show unloaded system extensions") 36 | writeMessage("or") 37 | writeMessage("\(executableName) -c to show google chrome extensions") 38 | writeMessage("or") 39 | writeMessage("\(executableName) -e to show microsoft edge extensions") 40 | writeMessage("or") 41 | writeMessage("\(executableName) -f to show firefox extensions") 42 | writeMessage("or") 43 | writeMessage("\(executableName) -raw to show unformatted result") 44 | writeMessage("or") 45 | writeMessage("\(executableName) -h to show usage information") 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /extensionsman-CLI/App/ExtensionMan.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Panagram.swift 3 | // 4 | // Created by Charles Edge on 19/12/2022. 5 | // 6 | 7 | import Foundation 8 | 9 | class ExtensionMan { 10 | 11 | let consoleIO = ConsoleIO() 12 | let store = ExtensionStore(requestModel: RequestModel()) 13 | 14 | func staticMode() { 15 | 16 | guard CommandLine.arguments.count > 1 else { 17 | consoleIO.printUsage() 18 | return 19 | } 20 | 21 | let arguments = CommandLine.arguments[1].components(separatedBy: " ") 22 | let options = arguments.filter{$0.first == "-"}.map{$0.replacingOccurrences(of: "-", with: "")} 23 | 24 | let (option,value) = getOption(options[0]) 25 | 26 | switch option { 27 | case .raw: 28 | let result = store.getRawData().map{ [$0] } 29 | show(result: result) 30 | case .all: 31 | let result = store.getAllExtensions() 32 | show(result: result) 33 | case .thirdparty: 34 | let result = store.getThirdpartyExtensions() 35 | show(result: result) 36 | case .network: 37 | let result = store.getNetworkExtensions() 38 | show(result: result) 39 | case .system: 40 | let result = store.getOtherExtensions() 41 | show(result: result) 42 | case .systemUnloaded: 43 | let result = store.getSystemExtensionsUnloaded() 44 | show(result: result) 45 | case .googleChrome: 46 | show(result: store.getChromeExtensions()) 47 | case .microsoftEdge: 48 | show(result: store.getMicrosoftEdgeExtensions()) 49 | case .firefox: 50 | show(result: store.getFirefoxExtensions()) 51 | case .help: 52 | consoleIO.printUsage() 53 | case .unknown: 54 | consoleIO.writeMessage("Unknown option \(value)") 55 | consoleIO.printUsage() 56 | } 57 | } 58 | 59 | func show(result: Result<[Extension],Error>) { 60 | let strings = result.map{ extensions in 61 | extensions.map { $0.name } 62 | } 63 | show(result: strings) 64 | } 65 | 66 | func show(result: Result<[String],Error>) { 67 | switch result { 68 | case .success(let response): 69 | let message = response.joined(separator: "\n") 70 | consoleIO.writeMessage(message.isEmpty ? "0 Items" : message) 71 | case .failure(let error): 72 | consoleIO.writeMessage(error.localizedDescription, to: .error) 73 | } 74 | } 75 | 76 | func getOption(_ option: String) -> (Option,String) { 77 | return (Option(value: option), option) 78 | } 79 | } 80 | 81 | 82 | -------------------------------------------------------------------------------- /extensionsman-CLI/App/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // 4 | // Created by Charles Edge on 19/12/2022. 5 | // 6 | 7 | import Foundation 8 | 9 | let extensionMan = ExtensionMan() 10 | extensionMan.staticMode() 11 | -------------------------------------------------------------------------------- /extensionsman-CLI/Models/BrowserExtension.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | struct BrowserExtension: Parseable { 4 | 5 | let list: [Extension] 6 | 7 | init(string: String) { 8 | list = BrowserExtensionParser.parse(string: string) 9 | } 10 | } 11 | 12 | class BrowserExtensionParser { 13 | 14 | static func parse(string: String) -> [Extension] { 15 | 16 | let lines = string.replacingOccurrences(of: "\n", with: ",").components(separatedBy: ",").map{$0.trimmingCharacters(in: .whitespacesAndNewlines)}.filter{!$0.isEmpty} 17 | 18 | var items = [Extension]() 19 | var item = Extension() 20 | // status 21 | // path 22 | 23 | for line in lines where !line.isEmpty { 24 | // tells type of extensions 25 | if line.contains("\"name\":") { 26 | if !item.name.isEmpty { 27 | items.append(item) 28 | } 29 | item = Extension() 30 | item.status = true 31 | item.name = getValue(from: line, key: "name") 32 | } else if line.contains("\"author\":") { 33 | item.vendor = getValue(from: line, key: "author") 34 | } else if line.contains("\"version\":") { 35 | item.version = getValue(from: line, key: "version") 36 | } 37 | } 38 | 39 | if !item.name.isEmpty { 40 | items.append(item) 41 | } 42 | 43 | return items 44 | } 45 | 46 | static private func getValue(from string: String, key: String) -> String { 47 | return string.replacingOccurrences(of: "\"\(key)\":", with: "").replacingOccurrences(of: "\"", with: "") 48 | .replacingOccurrences(of: ",", with: "").trimmingCharacters(in: .whitespacesAndNewlines) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /extensionsman-CLI/Models/Extension.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | class Extension { 4 | var name: String 5 | var vendor: String 6 | var status: Bool 7 | var path: String 8 | var version: String 9 | var sdk: String 10 | var bundle: String 11 | var parentName: String 12 | var type: String 13 | 14 | init() { 15 | name = "" 16 | vendor = "" 17 | status = false 18 | path = "" 19 | version = "" 20 | sdk = "" 21 | bundle = "" 22 | parentName = "" 23 | type = "" 24 | } 25 | 26 | convenience init(name: String) { 27 | self.init() 28 | self.name = name 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /extensionsman-CLI/Models/Filter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Filter.swift 3 | // 4 | // Created by Charles Edge on 20/12/2022. 5 | // 6 | 7 | import Foundation 8 | 9 | protocol Filter { 10 | func isValid(_ value: String) -> Bool 11 | } 12 | 13 | class AppleExtensionFilter: Filter { 14 | 15 | func isValid(_ value: String) -> Bool { 16 | value.starts(with: "com.apple") && !value.isEmpty 17 | } 18 | } 19 | 20 | class ThirdPartyExtensionFilter: Filter { 21 | 22 | func isValid(_ value: String) -> Bool { 23 | !value.starts(with: "com.apple") && !value.isEmpty 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /extensionsman-CLI/Models/Firefox.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | class Firefox: Decodable { 4 | let addons: [FirefoxItem]? 5 | } 6 | 7 | class FirefoxItem: Decodable { 8 | private let id: String 9 | private let defaultLocale: DefaultLocale? 10 | private let location: String 11 | let version: String 12 | let path: String 13 | let active: Bool 14 | var name: String { defaultLocale?.name ?? "" } 15 | var vendor: String { defaultLocale?.homepageURL ?? id } 16 | 17 | enum CodingKeys: CodingKey { 18 | case id 19 | case defaultLocale 20 | case location 21 | case version 22 | case path 23 | case active 24 | } 25 | 26 | required init(from decoder: Decoder) throws { 27 | let container = try decoder.container(keyedBy: CodingKeys.self) 28 | 29 | self.id = try container.decodeIfPresent(String.self, forKey: .id) ?? "" 30 | self.defaultLocale = try container.decodeIfPresent(DefaultLocale.self, forKey: .defaultLocale) 31 | self.location = try container.decodeIfPresent(String.self, forKey: .location) ?? "" 32 | self.version = try container.decodeIfPresent(String.self, forKey: .version) ?? "" 33 | self.path = try container.decodeIfPresent(String.self, forKey: .path) ?? "" 34 | self.active = try container.decodeIfPresent(Bool.self, forKey: .active) ?? false 35 | } 36 | 37 | } 38 | 39 | class DefaultLocale: Decodable { 40 | let name: String? 41 | let homepageURL: String? 42 | } 43 | -------------------------------------------------------------------------------- /extensionsman-CLI/Models/Option.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Option.swift 3 | // 4 | // Created by Charles Edge on 20/12/2022. 5 | // 6 | 7 | import Foundation 8 | 9 | enum Option: String { 10 | case raw = "raw" 11 | case all = "all" 12 | case thirdparty = "thirdparty" 13 | case network = "n" 14 | case system = "s" 15 | case systemUnloaded = "u" 16 | case help = "h" 17 | case googleChrome = "c" 18 | case microsoftEdge = "e" 19 | case firefox = "f" 20 | case unknown 21 | 22 | init(value: String) { 23 | switch value { 24 | case "raw": 25 | self = .raw 26 | case "all": 27 | self = .all 28 | case "thirdparty": 29 | self = .thirdparty 30 | case "n": 31 | self = .network 32 | case "s": 33 | self = .system 34 | case "u": 35 | self = .systemUnloaded 36 | case "c": 37 | self = .googleChrome 38 | case "e": 39 | self = .microsoftEdge 40 | case "f": 41 | self = .firefox 42 | case "h": 43 | self = .help 44 | default: 45 | self = .unknown 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /extensionsman-CLI/Models/Parseable.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | protocol Parseable { 4 | init(string: String) 5 | } 6 | -------------------------------------------------------------------------------- /extensionsman-CLI/Models/Plugin.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | struct Plugins: Parseable { 4 | let list: [Extension] 5 | 6 | init(string: String) { 7 | list = PluginParser.parse(string: string) 8 | } 9 | } 10 | 11 | class PluginParser { 12 | 13 | static func parse(string: String) -> [Extension] { 14 | let items = string.components(separatedBy: "\n").dropFirst().dropLast() 15 | 16 | var extensionList = [Extension]() 17 | var extensionItem = Extension() 18 | var newItem = true 19 | 20 | for item in items { 21 | if item.isEmpty { 22 | extensionList.append(extensionItem) 23 | extensionItem = Extension() 24 | extensionItem.type = "App Extension" 25 | newItem = true 26 | continue 27 | } 28 | 29 | if newItem { 30 | extensionItem.status = !item.contains("-") 31 | let bundleComponents = item.replacingOccurrences(of: "+", with: "").replacingOccurrences(of: "-", with: "").components(separatedBy: "(") 32 | extensionItem.version = bundleComponents.last?.replacingOccurrences(of: ")", with: "").trimmingCharacters(in: .whitespacesAndNewlines) ?? "" 33 | extensionItem.bundle = bundleComponents.first?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" 34 | 35 | }else if item.contains("Path"){ 36 | extensionItem.path = item.replacingOccurrences(of: "Path = ", with: "").trimmingCharacters(in: .whitespacesAndNewlines) 37 | }else if item.contains("SDK") { 38 | extensionItem.sdk = item.replacingOccurrences(of: "SDK = ", with: "").trimmingCharacters(in: .whitespacesAndNewlines) 39 | }else if item.contains("Display Name") { 40 | extensionItem.name = item.replacingOccurrences(of: "Display Name = ", with: "").trimmingCharacters(in: .whitespacesAndNewlines) 41 | }else if item.contains("Parent Name") { 42 | extensionItem.parentName = item.replacingOccurrences(of: "Parent Name = ", with: "").trimmingCharacters(in: .whitespacesAndNewlines) 43 | } 44 | newItem = false 45 | 46 | } 47 | return extensionList 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /extensionsman-CLI/Models/SystemExtension.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | struct SystemExtensions: Parseable { 4 | 5 | let network: [Extension] 6 | let others: [Extension] 7 | 8 | init(string: String) { 9 | let data = SystemExtensionParser.parse(string: string) 10 | network = data.network 11 | others = data.others 12 | } 13 | 14 | init(network: [Extension], others: [Extension]) { 15 | self.network = network 16 | self.others = others 17 | } 18 | } 19 | 20 | struct SystemExtensionsUnloaded: Parseable { 21 | 22 | let list: [String] 23 | 24 | init(string: String) { 25 | list = string.components(separatedBy: "\n").map{$0.trimmingCharacters(in: .whitespacesAndNewlines)}.filter{!$0.isEmpty} 26 | } 27 | } 28 | 29 | class SystemExtensionParser { 30 | 31 | static func parse(string: String) -> SystemExtensions { 32 | 33 | let lines = string.components(separatedBy: "\n").dropFirst().map{$0.trimmingCharacters(in: .whitespacesAndNewlines)} 34 | 35 | var otherItems = [Extension]() 36 | var networkItems = [Extension]() 37 | var isNetworkItems = false 38 | 39 | for line in lines where !line.isEmpty { 40 | // tells type of extensions 41 | if line.starts(with: "---") { 42 | isNetworkItems = line.contains("com.apple.system_extension.network_extension") 43 | } 44 | // tells column names 45 | else if line.contains("bundleID (version)") { 46 | continue 47 | } 48 | // network item 49 | else { 50 | let columns = line.components(separatedBy: "\t") 51 | let extensionItem = Extension() 52 | let bundleInfo = columns.getItemOrEmpty(at: 3) 53 | let bundleComponents = bundleInfo.components(separatedBy: "(") 54 | extensionItem.bundle = bundleComponents.first?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" 55 | let versionInfo = (bundleComponents.last ?? "").trimmingCharacters(in: .whitespacesAndNewlines) 56 | let versionComponents = versionInfo.components(separatedBy: "/") 57 | extensionItem.version = versionComponents.isEmpty ? versionInfo : (versionComponents.first ?? "") 58 | extensionItem.name = columns.getItemOrEmpty(at: 4) 59 | extensionItem.type = isNetworkItems ? "Network Extension" : "System Extension" 60 | extensionItem.status = columns.getItemOrEmpty(at: 5).contains("enabled") 61 | isNetworkItems ? networkItems.append(extensionItem) : otherItems.append(extensionItem) 62 | } 63 | } 64 | 65 | return .init(network: networkItems, others: otherItems) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /extensionsman-CLI/Store/ExtensionStore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExtensionStore.swift 3 | // 4 | // Created by Charles Edge on 20/12/2022. 5 | // 6 | 7 | import Foundation 8 | 9 | //kextstat kernal extensions 10 | 11 | class ExtensionStore { 12 | 13 | let requestModel: RequestModel 14 | 15 | init(requestModel: RequestModel) { 16 | self.requestModel = requestModel 17 | } 18 | 19 | enum Query: String, CaseIterable { 20 | case plugin = "pluginkit -mvv" 21 | case systemExtension = "systemextensionsctl list" 22 | case chrome = "find ~/Library/Application\\ Support/Google/Chrome/Default/Extensions -type f -name \"manifest.json\" -print0 | xargs -I {} -0 grep \'\"name\\|version\\|author\"\' \"{}\" | uniq" 23 | case microsoftEdge = "find ~/Library/Application\\ Support/Microsoft\\ Edge/Default/Extensions -type f -name \"manifest.json\" -print0 | xargs -I {} -0 grep \'\"name\\|version\\|autor\":\' \"{}\" | uniq" 24 | // find ~/Library/Application\ Support/Microsoft\ Edge/Default/Extensions -type f -name "manifest.json" -print0 | xargs -I {} -0 grep '"name\|version\|autor":' "{}" | uniq 25 | // case firefox = "cat /Users/*/Library/Application\\ Support/Firefox/Profiles/*/extensions.json" 26 | case firefox = "find ~/Library/Application\\ Support/Firefox/Profiles/ -type f -name \"extensions.json\" -print0 | xargs -I {} -0 grep \'\' \"{}\" | uniq" 27 | //case systemExtensionUnloaded = "systemextensionsctl list | grep 'activated disabled' | awk '{print $4}'" 28 | } 29 | 30 | struct Response { 31 | let query: String 32 | let data: String 33 | } 34 | 35 | // MARK: - Plugins 36 | func getThirdpartyExtensions() -> Result<[Extension],Error> { 37 | getAllPlugins().map{$0.filter{$0.vendor != "Apple"}} 38 | } 39 | 40 | private func getAllPlugins() -> Result<[Extension],Error> { 41 | let pluginResult: Result = requestModel.runQuery(Query.plugin.rawValue) 42 | return pluginResult.map{ $0.list } 43 | } 44 | 45 | // MARK: - System Extensions 46 | 47 | private func getAllSystemExtensions() -> Result{ 48 | requestModel.runQuery(Query.systemExtension.rawValue) 49 | } 50 | 51 | func getNetworkExtensions() -> Result<[Extension],Error> { 52 | getAllSystemExtensions().map{$0.network} 53 | } 54 | 55 | func getSystemExtensionsUnloaded() -> Result<[Extension],Error>{ 56 | getAllSystemExtensions().map{ items in 57 | let all = items.network + items.others 58 | return all.filter{!$0.status} 59 | } 60 | } 61 | 62 | func getOtherExtensions() -> Result<[Extension],Error> { 63 | getAllSystemExtensions().map{$0.others} 64 | } 65 | 66 | // MARK: Browser Extensions 67 | func getChromeExtensions() -> Result<[Extension],Error> { 68 | let result: Result = requestModel.runQuery(Query.chrome.rawValue) 69 | return result.map{ $0.list.map { item in 70 | item.type = "Google Chrome" 71 | return item 72 | }} 73 | } 74 | 75 | func getMicrosoftEdgeExtensions() -> Result<[Extension],Error> { 76 | let result: Result = requestModel.runQuery(Query.microsoftEdge.rawValue) 77 | return result.map{ $0.list.map { item in 78 | item.type = "MicrosoftEdge Extension" 79 | return item 80 | }} 81 | } 82 | 83 | func getFirefoxExtensions() -> Result<[Extension],Error> { 84 | let result: Result = requestModel.getData(query: Query.firefox.rawValue) 85 | switch result { 86 | case .success(let rawData): 87 | do { 88 | let data = rawData.trimmingCharacters(in: .whitespacesAndNewlines).data(using: .utf8) ?? Data() 89 | let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String:AnyObject] 90 | let jsonData = try JSONSerialization.data(withJSONObject: json ?? [:], options: .prettyPrinted) 91 | let firefoxExtensions = try JSONDecoder().decode(Firefox.self, from: jsonData) 92 | let extensions = (firefoxExtensions.addons ?? []).map { 93 | let item = Extension(name: $0.name) 94 | item.vendor = $0.vendor 95 | item.type = "Firefox Extension" 96 | item.status = $0.active 97 | item.path = $0.path 98 | item.version = $0.version 99 | return item 100 | } 101 | return .success(extensions) 102 | } catch { 103 | print(error) 104 | return .success([]) 105 | } 106 | case .failure(let error): 107 | return .failure(error) 108 | } 109 | } 110 | 111 | // MARK: - All 112 | func getAllExtensions() -> Result<[Extension],Error> { 113 | var result = [Extension]() 114 | 115 | let systemExtensions = getAllSystemExtensions().map{ $0.network + $0.others } 116 | for extensionsResponse in [getAllPlugins(), systemExtensions, getChromeExtensions(), getMicrosoftEdgeExtensions(), getFirefoxExtensions()] { 117 | switch extensionsResponse { 118 | case.success(let response): 119 | result.append(contentsOf: response) 120 | case .failure(let error): 121 | return .failure(error) 122 | } 123 | } 124 | 125 | return .success(result) 126 | } 127 | 128 | // MARK: - Raw 129 | func getRawData() -> Result { 130 | var result = "" 131 | 132 | for dataResponse in Query.allCases.map({ requestModel.getData(query: $0.rawValue)}) { 133 | switch dataResponse { 134 | case .success(let response): 135 | let prefix = result.isEmpty ? "" : "\n" 136 | result.append("\(prefix)"+response) 137 | case .failure(let error): 138 | return .failure(error) 139 | } 140 | } 141 | 142 | return .success(result) 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /extensionsman-CLI/Store/RequestModel.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | class RequestModel { 4 | 5 | init() { } 6 | 7 | // MARK: - Data 8 | func getData(query: String) -> Result { 9 | do { 10 | let data = try safeShell(query) 11 | return .success(data) 12 | }catch { 13 | return .failure(error) 14 | } 15 | } 16 | 17 | func runQuery(_ query: String) -> Result where T: Parseable { 18 | getData(query: query).map{ T(string: $0) } 19 | } 20 | 21 | @discardableResult private func safeShell(_ command: String) throws -> String { 22 | let task = Process() 23 | let pipe = Pipe() 24 | 25 | task.standardOutput = pipe 26 | task.standardError = pipe 27 | task.arguments = ["-c", command] 28 | task.executableURL = URL(fileURLWithPath: "/bin/zsh") //<--updated 29 | task.standardInput = nil 30 | 31 | try task.run() //<--updated 32 | 33 | let data = pipe.fileHandleForReading.readDataToEndOfFile() 34 | let output = String(data: data, encoding: .utf8)! 35 | 36 | return output 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /extensionsman-CLI/Utilitiy/Extensions+extensionman.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension Array where Element == String { 4 | 5 | func getItem(at index: Int) -> String? { 6 | guard index < self.count else {return nil } 7 | return self[index] 8 | } 9 | 10 | func getItemOrEmpty(at index: Int) -> String { 11 | getItem(at: index) ?? "" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /extensionsman-CLI/extensionsman.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 891F26322A0CF9E60061AAFE /* Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 891F26312A0CF9E60061AAFE /* Extension.swift */; }; 11 | 891F26342A0CFA100061AAFE /* Parseable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 891F26332A0CFA100061AAFE /* Parseable.swift */; }; 12 | 891F26362A0CFA3F0061AAFE /* Plugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 891F26352A0CFA3F0061AAFE /* Plugin.swift */; }; 13 | 891F26382A0CFAE70061AAFE /* SystemExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 891F26372A0CFAE70061AAFE /* SystemExtension.swift */; }; 14 | 891F263B2A0CFBB80061AAFE /* Extensions+extensionman.swift in Sources */ = {isa = PBXBuildFile; fileRef = 891F263A2A0CFBB80061AAFE /* Extensions+extensionman.swift */; }; 15 | 891F263F2A0D01930061AAFE /* RequestModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 891F263E2A0D01930061AAFE /* RequestModel.swift */; }; 16 | 891F26422A0E235E0061AAFE /* BrowserExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 891F26402A0D05FB0061AAFE /* BrowserExtension.swift */; }; 17 | 891F26462A0E8FA00061AAFE /* Firefox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 891F26452A0E8FA00061AAFE /* Firefox.swift */; }; 18 | 89AC443A2951F56300446515 /* ExtensionMan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89AC44352951F56200446515 /* ExtensionMan.swift */; }; 19 | 89AC443B2951F56300446515 /* ExtensionStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89AC44362951F56300446515 /* ExtensionStore.swift */; }; 20 | 89AC443C2951F56300446515 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89AC44372951F56300446515 /* Filter.swift */; }; 21 | 89AC443D2951F56300446515 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89AC44382951F56300446515 /* main.swift */; }; 22 | 89AC443E2951F56300446515 /* ConsoleIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89AC44392951F56300446515 /* ConsoleIO.swift */; }; 23 | 89AC44402951F6CA00446515 /* Option.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89AC443F2951F6CA00446515 /* Option.swift */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXCopyFilesBuildPhase section */ 27 | 89AC44292951F53200446515 /* CopyFiles */ = { 28 | isa = PBXCopyFilesBuildPhase; 29 | buildActionMask = 2147483647; 30 | dstPath = /usr/share/man/man1/; 31 | dstSubfolderSpec = 0; 32 | files = ( 33 | ); 34 | runOnlyForDeploymentPostprocessing = 1; 35 | }; 36 | /* End PBXCopyFilesBuildPhase section */ 37 | 38 | /* Begin PBXFileReference section */ 39 | 891F26312A0CF9E60061AAFE /* Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extension.swift; sourceTree = ""; }; 40 | 891F26332A0CFA100061AAFE /* Parseable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Parseable.swift; sourceTree = ""; }; 41 | 891F26352A0CFA3F0061AAFE /* Plugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Plugin.swift; sourceTree = ""; }; 42 | 891F26372A0CFAE70061AAFE /* SystemExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemExtension.swift; sourceTree = ""; }; 43 | 891F263A2A0CFBB80061AAFE /* Extensions+extensionman.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Extensions+extensionman.swift"; sourceTree = ""; }; 44 | 891F263E2A0D01930061AAFE /* RequestModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestModel.swift; sourceTree = ""; }; 45 | 891F26402A0D05FB0061AAFE /* BrowserExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserExtension.swift; sourceTree = ""; }; 46 | 891F26452A0E8FA00061AAFE /* Firefox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Firefox.swift; sourceTree = ""; }; 47 | 89AC442B2951F53200446515 /* extensionsman */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = extensionsman; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | 89AC44352951F56200446515 /* ExtensionMan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtensionMan.swift; sourceTree = ""; }; 49 | 89AC44362951F56300446515 /* ExtensionStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtensionStore.swift; sourceTree = ""; }; 50 | 89AC44372951F56300446515 /* Filter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Filter.swift; sourceTree = ""; }; 51 | 89AC44382951F56300446515 /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 52 | 89AC44392951F56300446515 /* ConsoleIO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConsoleIO.swift; sourceTree = ""; }; 53 | 89AC443F2951F6CA00446515 /* Option.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Option.swift; sourceTree = ""; }; 54 | /* End PBXFileReference section */ 55 | 56 | /* Begin PBXFrameworksBuildPhase section */ 57 | 89AC44282951F53200446515 /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | ); 62 | runOnlyForDeploymentPostprocessing = 0; 63 | }; 64 | /* End PBXFrameworksBuildPhase section */ 65 | 66 | /* Begin PBXGroup section */ 67 | 891F26302A0CF9B30061AAFE /* Models */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | 89AC443F2951F6CA00446515 /* Option.swift */, 71 | 89AC44372951F56300446515 /* Filter.swift */, 72 | 891F26312A0CF9E60061AAFE /* Extension.swift */, 73 | 891F26332A0CFA100061AAFE /* Parseable.swift */, 74 | 891F26352A0CFA3F0061AAFE /* Plugin.swift */, 75 | 891F26372A0CFAE70061AAFE /* SystemExtension.swift */, 76 | 891F26402A0D05FB0061AAFE /* BrowserExtension.swift */, 77 | 891F26452A0E8FA00061AAFE /* Firefox.swift */, 78 | ); 79 | path = Models; 80 | sourceTree = ""; 81 | }; 82 | 891F26392A0CFBAD0061AAFE /* Utilitiy */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 891F263A2A0CFBB80061AAFE /* Extensions+extensionman.swift */, 86 | ); 87 | path = Utilitiy; 88 | sourceTree = ""; 89 | }; 90 | 891F263C2A0CFBF10061AAFE /* App */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 89AC44382951F56300446515 /* main.swift */, 94 | 89AC44352951F56200446515 /* ExtensionMan.swift */, 95 | 89AC44392951F56300446515 /* ConsoleIO.swift */, 96 | ); 97 | path = App; 98 | sourceTree = ""; 99 | }; 100 | 891F263D2A0D01850061AAFE /* Store */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 891F263E2A0D01930061AAFE /* RequestModel.swift */, 104 | 89AC44362951F56300446515 /* ExtensionStore.swift */, 105 | ); 106 | path = Store; 107 | sourceTree = ""; 108 | }; 109 | 89AC44222951F53200446515 = { 110 | isa = PBXGroup; 111 | children = ( 112 | 89AC442D2951F53200446515 /* extensionsman */, 113 | 89AC442C2951F53200446515 /* Products */, 114 | ); 115 | sourceTree = ""; 116 | }; 117 | 89AC442C2951F53200446515 /* Products */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 89AC442B2951F53200446515 /* extensionsman */, 121 | ); 122 | name = Products; 123 | sourceTree = ""; 124 | }; 125 | 89AC442D2951F53200446515 /* extensionsman */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 891F263C2A0CFBF10061AAFE /* App */, 129 | 891F263D2A0D01850061AAFE /* Store */, 130 | 891F26392A0CFBAD0061AAFE /* Utilitiy */, 131 | 891F26302A0CF9B30061AAFE /* Models */, 132 | ); 133 | path = extensionsman; 134 | sourceTree = ""; 135 | }; 136 | /* End PBXGroup section */ 137 | 138 | /* Begin PBXNativeTarget section */ 139 | 89AC442A2951F53200446515 /* extensionsman */ = { 140 | isa = PBXNativeTarget; 141 | buildConfigurationList = 89AC44322951F53200446515 /* Build configuration list for PBXNativeTarget "extensionsman" */; 142 | buildPhases = ( 143 | 89AC44272951F53200446515 /* Sources */, 144 | 89AC44282951F53200446515 /* Frameworks */, 145 | 89AC44292951F53200446515 /* CopyFiles */, 146 | ); 147 | buildRules = ( 148 | ); 149 | dependencies = ( 150 | ); 151 | name = extensionsman; 152 | productName = extensionsman; 153 | productReference = 89AC442B2951F53200446515 /* extensionsman */; 154 | productType = "com.apple.product-type.tool"; 155 | }; 156 | /* End PBXNativeTarget section */ 157 | 158 | /* Begin PBXProject section */ 159 | 89AC44232951F53200446515 /* Project object */ = { 160 | isa = PBXProject; 161 | attributes = { 162 | BuildIndependentTargetsInParallel = 1; 163 | LastSwiftUpdateCheck = 1410; 164 | LastUpgradeCheck = 1410; 165 | TargetAttributes = { 166 | 89AC442A2951F53200446515 = { 167 | CreatedOnToolsVersion = 14.1; 168 | LastSwiftMigration = 1410; 169 | }; 170 | }; 171 | }; 172 | buildConfigurationList = 89AC44262951F53200446515 /* Build configuration list for PBXProject "extensionsman" */; 173 | compatibilityVersion = "Xcode 14.0"; 174 | developmentRegion = en; 175 | hasScannedForEncodings = 0; 176 | knownRegions = ( 177 | en, 178 | Base, 179 | ); 180 | mainGroup = 89AC44222951F53200446515; 181 | productRefGroup = 89AC442C2951F53200446515 /* Products */; 182 | projectDirPath = ""; 183 | projectRoot = ""; 184 | targets = ( 185 | 89AC442A2951F53200446515 /* extensionsman */, 186 | ); 187 | }; 188 | /* End PBXProject section */ 189 | 190 | /* Begin PBXSourcesBuildPhase section */ 191 | 89AC44272951F53200446515 /* Sources */ = { 192 | isa = PBXSourcesBuildPhase; 193 | buildActionMask = 2147483647; 194 | files = ( 195 | 89AC443E2951F56300446515 /* ConsoleIO.swift in Sources */, 196 | 89AC443A2951F56300446515 /* ExtensionMan.swift in Sources */, 197 | 891F26382A0CFAE70061AAFE /* SystemExtension.swift in Sources */, 198 | 891F26342A0CFA100061AAFE /* Parseable.swift in Sources */, 199 | 89AC443C2951F56300446515 /* Filter.swift in Sources */, 200 | 89AC443D2951F56300446515 /* main.swift in Sources */, 201 | 891F263B2A0CFBB80061AAFE /* Extensions+extensionman.swift in Sources */, 202 | 89AC44402951F6CA00446515 /* Option.swift in Sources */, 203 | 891F26462A0E8FA00061AAFE /* Firefox.swift in Sources */, 204 | 89AC443B2951F56300446515 /* ExtensionStore.swift in Sources */, 205 | 891F26362A0CFA3F0061AAFE /* Plugin.swift in Sources */, 206 | 891F26322A0CF9E60061AAFE /* Extension.swift in Sources */, 207 | 891F26422A0E235E0061AAFE /* BrowserExtension.swift in Sources */, 208 | 891F263F2A0D01930061AAFE /* RequestModel.swift in Sources */, 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | /* End PBXSourcesBuildPhase section */ 213 | 214 | /* Begin XCBuildConfiguration section */ 215 | 89AC44302951F53200446515 /* Debug */ = { 216 | isa = XCBuildConfiguration; 217 | buildSettings = { 218 | ALWAYS_SEARCH_USER_PATHS = NO; 219 | CLANG_ANALYZER_NONNULL = YES; 220 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 221 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 222 | CLANG_ENABLE_MODULES = YES; 223 | CLANG_ENABLE_OBJC_ARC = YES; 224 | CLANG_ENABLE_OBJC_WEAK = YES; 225 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 226 | CLANG_WARN_BOOL_CONVERSION = YES; 227 | CLANG_WARN_COMMA = YES; 228 | CLANG_WARN_CONSTANT_CONVERSION = YES; 229 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 230 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 231 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 232 | CLANG_WARN_EMPTY_BODY = YES; 233 | CLANG_WARN_ENUM_CONVERSION = YES; 234 | CLANG_WARN_INFINITE_RECURSION = YES; 235 | CLANG_WARN_INT_CONVERSION = YES; 236 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 237 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 238 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 239 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 240 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 241 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 242 | CLANG_WARN_STRICT_PROTOTYPES = YES; 243 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 244 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 245 | CLANG_WARN_UNREACHABLE_CODE = YES; 246 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 247 | COPY_PHASE_STRIP = NO; 248 | DEBUG_INFORMATION_FORMAT = dwarf; 249 | ENABLE_STRICT_OBJC_MSGSEND = YES; 250 | ENABLE_TESTABILITY = YES; 251 | GCC_C_LANGUAGE_STANDARD = gnu11; 252 | GCC_DYNAMIC_NO_PIC = NO; 253 | GCC_NO_COMMON_BLOCKS = YES; 254 | GCC_OPTIMIZATION_LEVEL = 0; 255 | GCC_PREPROCESSOR_DEFINITIONS = ( 256 | "DEBUG=1", 257 | "$(inherited)", 258 | ); 259 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 260 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 261 | GCC_WARN_UNDECLARED_SELECTOR = YES; 262 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 263 | GCC_WARN_UNUSED_FUNCTION = YES; 264 | GCC_WARN_UNUSED_VARIABLE = YES; 265 | MACOSX_DEPLOYMENT_TARGET = 13.0; 266 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 267 | MTL_FAST_MATH = YES; 268 | ONLY_ACTIVE_ARCH = YES; 269 | SDKROOT = macosx; 270 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 271 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 272 | }; 273 | name = Debug; 274 | }; 275 | 89AC44312951F53200446515 /* Release */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | ALWAYS_SEARCH_USER_PATHS = NO; 279 | CLANG_ANALYZER_NONNULL = YES; 280 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 281 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 282 | CLANG_ENABLE_MODULES = YES; 283 | CLANG_ENABLE_OBJC_ARC = YES; 284 | CLANG_ENABLE_OBJC_WEAK = YES; 285 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 286 | CLANG_WARN_BOOL_CONVERSION = YES; 287 | CLANG_WARN_COMMA = YES; 288 | CLANG_WARN_CONSTANT_CONVERSION = YES; 289 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 290 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 291 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 292 | CLANG_WARN_EMPTY_BODY = YES; 293 | CLANG_WARN_ENUM_CONVERSION = YES; 294 | CLANG_WARN_INFINITE_RECURSION = YES; 295 | CLANG_WARN_INT_CONVERSION = YES; 296 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 297 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 298 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 299 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 300 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 301 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 302 | CLANG_WARN_STRICT_PROTOTYPES = YES; 303 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 304 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 305 | CLANG_WARN_UNREACHABLE_CODE = YES; 306 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 307 | COPY_PHASE_STRIP = NO; 308 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 309 | ENABLE_NS_ASSERTIONS = NO; 310 | ENABLE_STRICT_OBJC_MSGSEND = YES; 311 | GCC_C_LANGUAGE_STANDARD = gnu11; 312 | GCC_NO_COMMON_BLOCKS = YES; 313 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 314 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 315 | GCC_WARN_UNDECLARED_SELECTOR = YES; 316 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 317 | GCC_WARN_UNUSED_FUNCTION = YES; 318 | GCC_WARN_UNUSED_VARIABLE = YES; 319 | MACOSX_DEPLOYMENT_TARGET = 13.0; 320 | MTL_ENABLE_DEBUG_INFO = NO; 321 | MTL_FAST_MATH = YES; 322 | SDKROOT = macosx; 323 | SWIFT_COMPILATION_MODE = wholemodule; 324 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 325 | }; 326 | name = Release; 327 | }; 328 | 89AC44332951F53200446515 /* Debug */ = { 329 | isa = XCBuildConfiguration; 330 | buildSettings = { 331 | CLANG_ENABLE_MODULES = YES; 332 | CODE_SIGN_STYLE = Automatic; 333 | DEVELOPMENT_TEAM = Z9HV438N39; 334 | LD_RUNPATH_SEARCH_PATHS = ( 335 | "$(inherited)", 336 | "@executable_path/../Frameworks", 337 | "@loader_path/../Frameworks", 338 | ); 339 | PRODUCT_NAME = "$(TARGET_NAME)"; 340 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 341 | SWIFT_VERSION = 5.0; 342 | }; 343 | name = Debug; 344 | }; 345 | 89AC44342951F53200446515 /* Release */ = { 346 | isa = XCBuildConfiguration; 347 | buildSettings = { 348 | CLANG_ENABLE_MODULES = YES; 349 | CODE_SIGN_STYLE = Automatic; 350 | DEVELOPMENT_TEAM = Z9HV438N39; 351 | LD_RUNPATH_SEARCH_PATHS = ( 352 | "$(inherited)", 353 | "@executable_path/../Frameworks", 354 | "@loader_path/../Frameworks", 355 | ); 356 | PRODUCT_NAME = "$(TARGET_NAME)"; 357 | SWIFT_VERSION = 5.0; 358 | }; 359 | name = Release; 360 | }; 361 | /* End XCBuildConfiguration section */ 362 | 363 | /* Begin XCConfigurationList section */ 364 | 89AC44262951F53200446515 /* Build configuration list for PBXProject "extensionsman" */ = { 365 | isa = XCConfigurationList; 366 | buildConfigurations = ( 367 | 89AC44302951F53200446515 /* Debug */, 368 | 89AC44312951F53200446515 /* Release */, 369 | ); 370 | defaultConfigurationIsVisible = 0; 371 | defaultConfigurationName = Release; 372 | }; 373 | 89AC44322951F53200446515 /* Build configuration list for PBXNativeTarget "extensionsman" */ = { 374 | isa = XCConfigurationList; 375 | buildConfigurations = ( 376 | 89AC44332951F53200446515 /* Debug */, 377 | 89AC44342951F53200446515 /* Release */, 378 | ); 379 | defaultConfigurationIsVisible = 0; 380 | defaultConfigurationName = Release; 381 | }; 382 | /* End XCConfigurationList section */ 383 | }; 384 | rootObject = 89AC44232951F53200446515 /* Project object */; 385 | } 386 | -------------------------------------------------------------------------------- /extensionsman-CLI/extensionsman.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /extensionsman-CLI/extensionsman.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /extensionsman-CLI/extensionsman.xcodeproj/project.xcworkspace/xcuserdata/charlesedge.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/extensionsman-CLI/extensionsman.xcodeproj/project.xcworkspace/xcuserdata/charlesedge.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /extensionsman-CLI/extensionsman.xcodeproj/xcshareddata/xcschemes/extensionsman.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 44 | 46 | 52 | 53 | 54 | 55 | 58 | 59 | 62 | 63 | 66 | 67 | 70 | 71 | 74 | 75 | 78 | 79 | 82 | 83 | 86 | 87 | 90 | 91 | 92 | 93 | 99 | 101 | 107 | 108 | 109 | 110 | 112 | 113 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /extensionsmanCLI_Signed.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krypted/extensionsmanager/6c5b572bf2e2074b5cd5417f4a33e0f2b6f3bbb7/extensionsmanCLI_Signed.zip --------------------------------------------------------------------------------