├── .gitignore ├── LICENSE ├── PrivacyPolicy.md ├── README.md ├── UTMBeGone.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── UTMBeGone ├── AppDelegate.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── UTMBeGone1024.png │ │ ├── UTMBeGone128.png │ │ ├── UTMBeGone256-1.png │ │ ├── UTMBeGone256.png │ │ ├── UTMBeGone32-1.png │ │ ├── UTMBeGone32.png │ │ ├── UTMBeGone512-1.png │ │ ├── UTMBeGone512.png │ │ └── UTMBeGone64.png │ ├── Contents.json │ └── icon.imageset │ │ ├── Contents.json │ │ └── icon.pdf ├── Base.lproj │ └── MainMenu.xib ├── GarbageRemover │ └── URLGarbageRemover.swift ├── Info.plist ├── Menu │ └── MenuManager.swift ├── PasteboardCore │ ├── PasteboardHandler.swift │ └── PasteboardListener.swift ├── Preferences │ ├── PreferencesViewController.swift │ └── PreferencesViewController.xib ├── Shared │ └── SharedConsts.swift ├── Storage │ ├── QueryItem.swift │ └── QueryItemsManager.swift ├── UTMBeGone.entitlements └── Util │ ├── LaunchAtLoginHelper.swift │ ├── NotificationNames.swift │ ├── OpenWebsiteHelper.swift │ └── UTMBeGone-Bridging-Header.h ├── UTMBeGoneHelper ├── AppDelegate.swift ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ └── Main.storyboard ├── Bundle+MainApp.swift ├── Info.plist └── UTMBeGoneHelper.entitlements ├── UTMBeGoneTests ├── Info.plist └── UTMBeGoneTests.swift └── images ├── icon.png ├── screenshot.png └── screenshot2.png /.gitignore: -------------------------------------------------------------------------------- 1 | UTMBeGone.xcodeproj/xcuserdata 2 | .DS_Store 3 | *.xcuserstate 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2020, Fernando Bunn 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /PrivacyPolicy.md: -------------------------------------------------------------------------------- 1 | # Privacy Policy 2 | 3 | ## What we collect 4 | This app doesn't log any kind of data from you. 5 | 6 | It doesn't have analytics or crash reporting tools (besides the one provided automatically by Apple). 7 | 8 | It is a 100% offline app. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | 6 | # UTMBeGone 7 | 8 | ## Real friends remove UTM tags before sharing links 😊 9 | 10 | Remove UTM tags (and more) when you copy URLs to your pasteboard. 11 | 12 | With UTMBeGone you can prevent people from tracking you and the friends you share links with. The app comes with a pre-set of UTM tags, but you can add/remove as many tags you want. 13 | 14 | # How it works? 15 | Every time you copy a valid URL to your pasteboard UTMBeGone will remove all queries that you configured on UTMBeGone. 16 | 17 | For example, if you copy "http://fakestalkerwebsite.com?randomQuery=123&utm_source=we_are_stalking_you, you will actually paste http://fakestalkerwebsite.com?randomQuery=123 to your friends. 18 | 19 | UTMBeGone comes with a preset of query items to be removed, but you can add or remove anything you like. 20 | 21 | Protect the people you share links with from being tracked :) 22 | 23 | 24 | ## Screenshots 25 | 26 | 27 | 28 | 29 | 30 | 31 | ## Privacy 32 | This project does not track anything you do ( it would be ironic right? 🙃), there are no analytics, no telemetry and it's a 100% offline app. 33 | 34 | ## Download 35 | UTMBeGone is a free and open source hobby project of mine. Feel free to download the project and run it anywhere you like! 36 | If you want to support its development you can buy it on the [App Store](https://apps.apple.com/us/app/utmbegone/id1530867730?mt=12) for those nice automatic updates :) 37 | 38 | ## FAQ 39 | 40 | ### I've removed the icon from the menu bar and now it's gone, how do I add it back? 41 | If you remove/hide the icon from the menu bar the app will keep running, if you want to see it back again just open your Application's folder and double click on the UTMBeGone icon to see it again. 42 | 43 | ### Will this app remove all "utm" tags from all texts I copy? 44 | No, UTMBeGone only removes these tags from valid URLs, which means they need to start with http(s):// . This is intentional because I didn't want to randomly remove tags from texts being copied, it would be very annoying. 45 | -------------------------------------------------------------------------------- /UTMBeGone.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 314FD7D7277A3D0900D16AED /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314FD7D6277A3D0900D16AED /* AppDelegate.swift */; }; 11 | 314FD7DB277A3D0900D16AED /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 314FD7DA277A3D0900D16AED /* Assets.xcassets */; }; 12 | 314FD7DE277A3D0900D16AED /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 314FD7DC277A3D0900D16AED /* Main.storyboard */; }; 13 | 314FD7E4277A3D3B00D16AED /* Bundle+MainApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314FD7E3277A3D3B00D16AED /* Bundle+MainApp.swift */; }; 14 | 314FD7E5277A3D6B00D16AED /* UTMBeGoneHelper.app in CopyFiles */ = {isa = PBXBuildFile; fileRef = 314FD7D4277A3D0800D16AED /* UTMBeGoneHelper.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 15 | 31629499250D180C0015E908 /* NotificationNames.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31629498250D180C0015E908 /* NotificationNames.swift */; }; 16 | 3192B4EF277919E400EFC6FB /* SharedConsts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3192B4EE277919E400EFC6FB /* SharedConsts.swift */; }; 17 | 3192B4F227791B7400EFC6FB /* LaunchAtLoginHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3192B4F127791B7400EFC6FB /* LaunchAtLoginHelper.swift */; }; 18 | 31A1E5F4277E1BFA006079AE /* OpenWebsiteHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A1E5F3277E1BFA006079AE /* OpenWebsiteHelper.swift */; }; 19 | 31A6634924FDAB4400CDD04A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A6634824FDAB4400CDD04A /* AppDelegate.swift */; }; 20 | 31A6634B24FDAB4400CDD04A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 31A6634A24FDAB4400CDD04A /* Assets.xcassets */; }; 21 | 31A6634E24FDAB4400CDD04A /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 31A6634C24FDAB4400CDD04A /* MainMenu.xib */; }; 22 | 31A6635A24FDAB4500CDD04A /* UTMBeGoneTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A6635924FDAB4500CDD04A /* UTMBeGoneTests.swift */; }; 23 | 31A6636524FDAB5900CDD04A /* URLGarbageRemover.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A6636424FDAB5900CDD04A /* URLGarbageRemover.swift */; }; 24 | 31A6636824FDAB5E00CDD04A /* PasteboardHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A6636624FDAB5E00CDD04A /* PasteboardHandler.swift */; }; 25 | 31A6636924FDAB5E00CDD04A /* PasteboardListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A6636724FDAB5E00CDD04A /* PasteboardListener.swift */; }; 26 | 31A6636B24FDAB9C00CDD04A /* MenuManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A6636A24FDAB9C00CDD04A /* MenuManager.swift */; }; 27 | 31D95685250663D100DCD1D1 /* PreferencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31D95683250663D100DCD1D1 /* PreferencesViewController.swift */; }; 28 | 31D95686250663D100DCD1D1 /* PreferencesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 31D95684250663D100DCD1D1 /* PreferencesViewController.xib */; }; 29 | 31D9568925066F2C00DCD1D1 /* QueryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31D9568825066F2C00DCD1D1 /* QueryItem.swift */; }; 30 | 31D9568B2506702F00DCD1D1 /* QueryItemsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31D9568A2506702F00DCD1D1 /* QueryItemsManager.swift */; }; 31 | /* End PBXBuildFile section */ 32 | 33 | /* Begin PBXContainerItemProxy section */ 34 | 31A6635624FDAB4500CDD04A /* PBXContainerItemProxy */ = { 35 | isa = PBXContainerItemProxy; 36 | containerPortal = 31A6633D24FDAB4400CDD04A /* Project object */; 37 | proxyType = 1; 38 | remoteGlobalIDString = 31A6634424FDAB4400CDD04A; 39 | remoteInfo = UTMBeGone; 40 | }; 41 | /* End PBXContainerItemProxy section */ 42 | 43 | /* Begin PBXCopyFilesBuildPhase section */ 44 | 31A42F572779035200A0B82D /* CopyFiles */ = { 45 | isa = PBXCopyFilesBuildPhase; 46 | buildActionMask = 2147483647; 47 | dstPath = Contents/Library/LoginItems; 48 | dstSubfolderSpec = 1; 49 | files = ( 50 | 314FD7E5277A3D6B00D16AED /* UTMBeGoneHelper.app in CopyFiles */, 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | /* End PBXCopyFilesBuildPhase section */ 55 | 56 | /* Begin PBXFileReference section */ 57 | 314FD7D4277A3D0800D16AED /* UTMBeGoneHelper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UTMBeGoneHelper.app; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | 314FD7D6277A3D0900D16AED /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 59 | 314FD7DA277A3D0900D16AED /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 60 | 314FD7DD277A3D0900D16AED /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 61 | 314FD7DF277A3D0900D16AED /* UTMBeGoneHelper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = UTMBeGoneHelper.entitlements; sourceTree = ""; }; 62 | 314FD7E3277A3D3B00D16AED /* Bundle+MainApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+MainApp.swift"; sourceTree = ""; }; 63 | 314FD7E6277A3DAA00D16AED /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 64 | 31629498250D180C0015E908 /* NotificationNames.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationNames.swift; sourceTree = ""; }; 65 | 3192B4EE277919E400EFC6FB /* SharedConsts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedConsts.swift; sourceTree = ""; }; 66 | 3192B4F127791B7400EFC6FB /* LaunchAtLoginHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchAtLoginHelper.swift; sourceTree = ""; }; 67 | 31A1E5F3277E1BFA006079AE /* OpenWebsiteHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenWebsiteHelper.swift; sourceTree = ""; }; 68 | 31A42F5A2779037200A0B82D /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; }; 69 | 31A6634524FDAB4400CDD04A /* UTMBeGone.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UTMBeGone.app; sourceTree = BUILT_PRODUCTS_DIR; }; 70 | 31A6634824FDAB4400CDD04A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 71 | 31A6634A24FDAB4400CDD04A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 72 | 31A6634D24FDAB4400CDD04A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 73 | 31A6634F24FDAB4400CDD04A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 74 | 31A6635024FDAB4400CDD04A /* UTMBeGone.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = UTMBeGone.entitlements; sourceTree = ""; }; 75 | 31A6635524FDAB4500CDD04A /* UTMBeGoneTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UTMBeGoneTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 76 | 31A6635924FDAB4500CDD04A /* UTMBeGoneTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTMBeGoneTests.swift; sourceTree = ""; }; 77 | 31A6635B24FDAB4500CDD04A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 78 | 31A6636424FDAB5900CDD04A /* URLGarbageRemover.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLGarbageRemover.swift; sourceTree = ""; }; 79 | 31A6636624FDAB5E00CDD04A /* PasteboardHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasteboardHandler.swift; sourceTree = ""; }; 80 | 31A6636724FDAB5E00CDD04A /* PasteboardListener.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasteboardListener.swift; sourceTree = ""; }; 81 | 31A6636A24FDAB9C00CDD04A /* MenuManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuManager.swift; sourceTree = ""; }; 82 | 31D95683250663D100DCD1D1 /* PreferencesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesViewController.swift; sourceTree = ""; }; 83 | 31D95684250663D100DCD1D1 /* PreferencesViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PreferencesViewController.xib; sourceTree = ""; }; 84 | 31D9568825066F2C00DCD1D1 /* QueryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryItem.swift; sourceTree = ""; }; 85 | 31D9568A2506702F00DCD1D1 /* QueryItemsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryItemsManager.swift; sourceTree = ""; }; 86 | 31D9568D2506818900DCD1D1 /* UTMBeGone-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UTMBeGone-Bridging-Header.h"; sourceTree = ""; }; 87 | /* End PBXFileReference section */ 88 | 89 | /* Begin PBXFrameworksBuildPhase section */ 90 | 314FD7D1277A3D0800D16AED /* Frameworks */ = { 91 | isa = PBXFrameworksBuildPhase; 92 | buildActionMask = 2147483647; 93 | files = ( 94 | ); 95 | runOnlyForDeploymentPostprocessing = 0; 96 | }; 97 | 31A6634224FDAB4400CDD04A /* Frameworks */ = { 98 | isa = PBXFrameworksBuildPhase; 99 | buildActionMask = 2147483647; 100 | files = ( 101 | ); 102 | runOnlyForDeploymentPostprocessing = 0; 103 | }; 104 | 31A6635224FDAB4500CDD04A /* Frameworks */ = { 105 | isa = PBXFrameworksBuildPhase; 106 | buildActionMask = 2147483647; 107 | files = ( 108 | ); 109 | runOnlyForDeploymentPostprocessing = 0; 110 | }; 111 | /* End PBXFrameworksBuildPhase section */ 112 | 113 | /* Begin PBXGroup section */ 114 | 314FD7D5277A3D0800D16AED /* UTMBeGoneHelper */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | 314FD7E6277A3DAA00D16AED /* Info.plist */, 118 | 314FD7D6277A3D0900D16AED /* AppDelegate.swift */, 119 | 314FD7DA277A3D0900D16AED /* Assets.xcassets */, 120 | 314FD7DC277A3D0900D16AED /* Main.storyboard */, 121 | 314FD7DF277A3D0900D16AED /* UTMBeGoneHelper.entitlements */, 122 | 314FD7E3277A3D3B00D16AED /* Bundle+MainApp.swift */, 123 | ); 124 | path = UTMBeGoneHelper; 125 | sourceTree = ""; 126 | }; 127 | 3192B4ED277919AB00EFC6FB /* Shared */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | 3192B4EE277919E400EFC6FB /* SharedConsts.swift */, 131 | ); 132 | path = Shared; 133 | sourceTree = ""; 134 | }; 135 | 31A42F592779037200A0B82D /* Frameworks */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | 31A42F5A2779037200A0B82D /* ServiceManagement.framework */, 139 | ); 140 | name = Frameworks; 141 | sourceTree = ""; 142 | }; 143 | 31A6633C24FDAB4400CDD04A = { 144 | isa = PBXGroup; 145 | children = ( 146 | 31A6634724FDAB4400CDD04A /* UTMBeGone */, 147 | 31A6635824FDAB4500CDD04A /* UTMBeGoneTests */, 148 | 314FD7D5277A3D0800D16AED /* UTMBeGoneHelper */, 149 | 31A6634624FDAB4400CDD04A /* Products */, 150 | 31A42F592779037200A0B82D /* Frameworks */, 151 | ); 152 | sourceTree = ""; 153 | }; 154 | 31A6634624FDAB4400CDD04A /* Products */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | 31A6634524FDAB4400CDD04A /* UTMBeGone.app */, 158 | 31A6635524FDAB4500CDD04A /* UTMBeGoneTests.xctest */, 159 | 314FD7D4277A3D0800D16AED /* UTMBeGoneHelper.app */, 160 | ); 161 | name = Products; 162 | sourceTree = ""; 163 | }; 164 | 31A6634724FDAB4400CDD04A /* UTMBeGone */ = { 165 | isa = PBXGroup; 166 | children = ( 167 | 3192B4ED277919AB00EFC6FB /* Shared */, 168 | 31D9568725066EFF00DCD1D1 /* Storage */, 169 | 31D95682250663B200DCD1D1 /* Preferences */, 170 | 31A6636E24FDAC8100CDD04A /* Menu */, 171 | 31A6636D24FDAC7800CDD04A /* GarbageRemover */, 172 | 31A6636C24FDAC6E00CDD04A /* PasteboardCore */, 173 | 31D9568C2506817C00DCD1D1 /* Util */, 174 | 31A6634824FDAB4400CDD04A /* AppDelegate.swift */, 175 | 31A6634A24FDAB4400CDD04A /* Assets.xcassets */, 176 | 31A6634C24FDAB4400CDD04A /* MainMenu.xib */, 177 | 31A6634F24FDAB4400CDD04A /* Info.plist */, 178 | 31A6635024FDAB4400CDD04A /* UTMBeGone.entitlements */, 179 | ); 180 | path = UTMBeGone; 181 | sourceTree = ""; 182 | }; 183 | 31A6635824FDAB4500CDD04A /* UTMBeGoneTests */ = { 184 | isa = PBXGroup; 185 | children = ( 186 | 31A6635924FDAB4500CDD04A /* UTMBeGoneTests.swift */, 187 | 31A6635B24FDAB4500CDD04A /* Info.plist */, 188 | ); 189 | path = UTMBeGoneTests; 190 | sourceTree = ""; 191 | }; 192 | 31A6636C24FDAC6E00CDD04A /* PasteboardCore */ = { 193 | isa = PBXGroup; 194 | children = ( 195 | 31A6636724FDAB5E00CDD04A /* PasteboardListener.swift */, 196 | 31A6636624FDAB5E00CDD04A /* PasteboardHandler.swift */, 197 | ); 198 | path = PasteboardCore; 199 | sourceTree = ""; 200 | }; 201 | 31A6636D24FDAC7800CDD04A /* GarbageRemover */ = { 202 | isa = PBXGroup; 203 | children = ( 204 | 31A6636424FDAB5900CDD04A /* URLGarbageRemover.swift */, 205 | ); 206 | path = GarbageRemover; 207 | sourceTree = ""; 208 | }; 209 | 31A6636E24FDAC8100CDD04A /* Menu */ = { 210 | isa = PBXGroup; 211 | children = ( 212 | 31A6636A24FDAB9C00CDD04A /* MenuManager.swift */, 213 | ); 214 | path = Menu; 215 | sourceTree = ""; 216 | }; 217 | 31D95682250663B200DCD1D1 /* Preferences */ = { 218 | isa = PBXGroup; 219 | children = ( 220 | 31D95683250663D100DCD1D1 /* PreferencesViewController.swift */, 221 | 31D95684250663D100DCD1D1 /* PreferencesViewController.xib */, 222 | ); 223 | path = Preferences; 224 | sourceTree = ""; 225 | }; 226 | 31D9568725066EFF00DCD1D1 /* Storage */ = { 227 | isa = PBXGroup; 228 | children = ( 229 | 31D9568825066F2C00DCD1D1 /* QueryItem.swift */, 230 | 31D9568A2506702F00DCD1D1 /* QueryItemsManager.swift */, 231 | ); 232 | path = Storage; 233 | sourceTree = ""; 234 | }; 235 | 31D9568C2506817C00DCD1D1 /* Util */ = { 236 | isa = PBXGroup; 237 | children = ( 238 | 31D9568D2506818900DCD1D1 /* UTMBeGone-Bridging-Header.h */, 239 | 31629498250D180C0015E908 /* NotificationNames.swift */, 240 | 3192B4F127791B7400EFC6FB /* LaunchAtLoginHelper.swift */, 241 | 31A1E5F3277E1BFA006079AE /* OpenWebsiteHelper.swift */, 242 | ); 243 | path = Util; 244 | sourceTree = ""; 245 | }; 246 | /* End PBXGroup section */ 247 | 248 | /* Begin PBXNativeTarget section */ 249 | 314FD7D3277A3D0800D16AED /* UTMBeGoneHelper */ = { 250 | isa = PBXNativeTarget; 251 | buildConfigurationList = 314FD7E0277A3D0900D16AED /* Build configuration list for PBXNativeTarget "UTMBeGoneHelper" */; 252 | buildPhases = ( 253 | 314FD7D0277A3D0800D16AED /* Sources */, 254 | 314FD7D1277A3D0800D16AED /* Frameworks */, 255 | 314FD7D2277A3D0800D16AED /* Resources */, 256 | ); 257 | buildRules = ( 258 | ); 259 | dependencies = ( 260 | ); 261 | name = UTMBeGoneHelper; 262 | productName = UTMBeGoneHelper; 263 | productReference = 314FD7D4277A3D0800D16AED /* UTMBeGoneHelper.app */; 264 | productType = "com.apple.product-type.application"; 265 | }; 266 | 31A6634424FDAB4400CDD04A /* UTMBeGone */ = { 267 | isa = PBXNativeTarget; 268 | buildConfigurationList = 31A6635E24FDAB4500CDD04A /* Build configuration list for PBXNativeTarget "UTMBeGone" */; 269 | buildPhases = ( 270 | 31A6634124FDAB4400CDD04A /* Sources */, 271 | 31A6634224FDAB4400CDD04A /* Frameworks */, 272 | 31A6634324FDAB4400CDD04A /* Resources */, 273 | 31A42F572779035200A0B82D /* CopyFiles */, 274 | ); 275 | buildRules = ( 276 | ); 277 | dependencies = ( 278 | ); 279 | name = UTMBeGone; 280 | productName = UTMBeGone; 281 | productReference = 31A6634524FDAB4400CDD04A /* UTMBeGone.app */; 282 | productType = "com.apple.product-type.application"; 283 | }; 284 | 31A6635424FDAB4500CDD04A /* UTMBeGoneTests */ = { 285 | isa = PBXNativeTarget; 286 | buildConfigurationList = 31A6636124FDAB4500CDD04A /* Build configuration list for PBXNativeTarget "UTMBeGoneTests" */; 287 | buildPhases = ( 288 | 31A6635124FDAB4500CDD04A /* Sources */, 289 | 31A6635224FDAB4500CDD04A /* Frameworks */, 290 | 31A6635324FDAB4500CDD04A /* Resources */, 291 | ); 292 | buildRules = ( 293 | ); 294 | dependencies = ( 295 | 31A6635724FDAB4500CDD04A /* PBXTargetDependency */, 296 | ); 297 | name = UTMBeGoneTests; 298 | productName = UTMBeGoneTests; 299 | productReference = 31A6635524FDAB4500CDD04A /* UTMBeGoneTests.xctest */; 300 | productType = "com.apple.product-type.bundle.unit-test"; 301 | }; 302 | /* End PBXNativeTarget section */ 303 | 304 | /* Begin PBXProject section */ 305 | 31A6633D24FDAB4400CDD04A /* Project object */ = { 306 | isa = PBXProject; 307 | attributes = { 308 | LastSwiftUpdateCheck = 1320; 309 | LastUpgradeCheck = 1200; 310 | ORGANIZATIONNAME = "Fernando Bunn"; 311 | TargetAttributes = { 312 | 314FD7D3277A3D0800D16AED = { 313 | CreatedOnToolsVersion = 13.2; 314 | }; 315 | 31A6634424FDAB4400CDD04A = { 316 | CreatedOnToolsVersion = 11.6; 317 | LastSwiftMigration = 1170; 318 | }; 319 | 31A6635424FDAB4500CDD04A = { 320 | CreatedOnToolsVersion = 11.6; 321 | TestTargetID = 31A6634424FDAB4400CDD04A; 322 | }; 323 | }; 324 | }; 325 | buildConfigurationList = 31A6634024FDAB4400CDD04A /* Build configuration list for PBXProject "UTMBeGone" */; 326 | compatibilityVersion = "Xcode 9.3"; 327 | developmentRegion = en; 328 | hasScannedForEncodings = 0; 329 | knownRegions = ( 330 | en, 331 | Base, 332 | ); 333 | mainGroup = 31A6633C24FDAB4400CDD04A; 334 | productRefGroup = 31A6634624FDAB4400CDD04A /* Products */; 335 | projectDirPath = ""; 336 | projectRoot = ""; 337 | targets = ( 338 | 31A6634424FDAB4400CDD04A /* UTMBeGone */, 339 | 31A6635424FDAB4500CDD04A /* UTMBeGoneTests */, 340 | 314FD7D3277A3D0800D16AED /* UTMBeGoneHelper */, 341 | ); 342 | }; 343 | /* End PBXProject section */ 344 | 345 | /* Begin PBXResourcesBuildPhase section */ 346 | 314FD7D2277A3D0800D16AED /* Resources */ = { 347 | isa = PBXResourcesBuildPhase; 348 | buildActionMask = 2147483647; 349 | files = ( 350 | 314FD7DB277A3D0900D16AED /* Assets.xcassets in Resources */, 351 | 314FD7DE277A3D0900D16AED /* Main.storyboard in Resources */, 352 | ); 353 | runOnlyForDeploymentPostprocessing = 0; 354 | }; 355 | 31A6634324FDAB4400CDD04A /* Resources */ = { 356 | isa = PBXResourcesBuildPhase; 357 | buildActionMask = 2147483647; 358 | files = ( 359 | 31A6634B24FDAB4400CDD04A /* Assets.xcassets in Resources */, 360 | 31A6634E24FDAB4400CDD04A /* MainMenu.xib in Resources */, 361 | 31D95686250663D100DCD1D1 /* PreferencesViewController.xib in Resources */, 362 | ); 363 | runOnlyForDeploymentPostprocessing = 0; 364 | }; 365 | 31A6635324FDAB4500CDD04A /* Resources */ = { 366 | isa = PBXResourcesBuildPhase; 367 | buildActionMask = 2147483647; 368 | files = ( 369 | ); 370 | runOnlyForDeploymentPostprocessing = 0; 371 | }; 372 | /* End PBXResourcesBuildPhase section */ 373 | 374 | /* Begin PBXSourcesBuildPhase section */ 375 | 314FD7D0277A3D0800D16AED /* Sources */ = { 376 | isa = PBXSourcesBuildPhase; 377 | buildActionMask = 2147483647; 378 | files = ( 379 | 314FD7E4277A3D3B00D16AED /* Bundle+MainApp.swift in Sources */, 380 | 314FD7D7277A3D0900D16AED /* AppDelegate.swift in Sources */, 381 | ); 382 | runOnlyForDeploymentPostprocessing = 0; 383 | }; 384 | 31A6634124FDAB4400CDD04A /* Sources */ = { 385 | isa = PBXSourcesBuildPhase; 386 | buildActionMask = 2147483647; 387 | files = ( 388 | 31A6636B24FDAB9C00CDD04A /* MenuManager.swift in Sources */, 389 | 31A6636524FDAB5900CDD04A /* URLGarbageRemover.swift in Sources */, 390 | 31A6634924FDAB4400CDD04A /* AppDelegate.swift in Sources */, 391 | 31A1E5F4277E1BFA006079AE /* OpenWebsiteHelper.swift in Sources */, 392 | 31A6636924FDAB5E00CDD04A /* PasteboardListener.swift in Sources */, 393 | 31A6636824FDAB5E00CDD04A /* PasteboardHandler.swift in Sources */, 394 | 3192B4F227791B7400EFC6FB /* LaunchAtLoginHelper.swift in Sources */, 395 | 31D9568B2506702F00DCD1D1 /* QueryItemsManager.swift in Sources */, 396 | 31629499250D180C0015E908 /* NotificationNames.swift in Sources */, 397 | 3192B4EF277919E400EFC6FB /* SharedConsts.swift in Sources */, 398 | 31D9568925066F2C00DCD1D1 /* QueryItem.swift in Sources */, 399 | 31D95685250663D100DCD1D1 /* PreferencesViewController.swift in Sources */, 400 | ); 401 | runOnlyForDeploymentPostprocessing = 0; 402 | }; 403 | 31A6635124FDAB4500CDD04A /* Sources */ = { 404 | isa = PBXSourcesBuildPhase; 405 | buildActionMask = 2147483647; 406 | files = ( 407 | 31A6635A24FDAB4500CDD04A /* UTMBeGoneTests.swift in Sources */, 408 | ); 409 | runOnlyForDeploymentPostprocessing = 0; 410 | }; 411 | /* End PBXSourcesBuildPhase section */ 412 | 413 | /* Begin PBXTargetDependency section */ 414 | 31A6635724FDAB4500CDD04A /* PBXTargetDependency */ = { 415 | isa = PBXTargetDependency; 416 | target = 31A6634424FDAB4400CDD04A /* UTMBeGone */; 417 | targetProxy = 31A6635624FDAB4500CDD04A /* PBXContainerItemProxy */; 418 | }; 419 | /* End PBXTargetDependency section */ 420 | 421 | /* Begin PBXVariantGroup section */ 422 | 314FD7DC277A3D0900D16AED /* Main.storyboard */ = { 423 | isa = PBXVariantGroup; 424 | children = ( 425 | 314FD7DD277A3D0900D16AED /* Base */, 426 | ); 427 | name = Main.storyboard; 428 | sourceTree = ""; 429 | }; 430 | 31A6634C24FDAB4400CDD04A /* MainMenu.xib */ = { 431 | isa = PBXVariantGroup; 432 | children = ( 433 | 31A6634D24FDAB4400CDD04A /* Base */, 434 | ); 435 | name = MainMenu.xib; 436 | sourceTree = ""; 437 | }; 438 | /* End PBXVariantGroup section */ 439 | 440 | /* Begin XCBuildConfiguration section */ 441 | 314FD7E1277A3D0900D16AED /* Debug */ = { 442 | isa = XCBuildConfiguration; 443 | buildSettings = { 444 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 445 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 446 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 447 | CODE_SIGN_ENTITLEMENTS = UTMBeGoneHelper/UTMBeGoneHelper.entitlements; 448 | CODE_SIGN_STYLE = Automatic; 449 | COMBINE_HIDPI_IMAGES = YES; 450 | CURRENT_PROJECT_VERSION = 14; 451 | DEVELOPMENT_TEAM = B2RUA6XMHC; 452 | ENABLE_HARDENED_RUNTIME = YES; 453 | GENERATE_INFOPLIST_FILE = YES; 454 | INFOPLIST_FILE = UTMBeGoneHelper/Info.plist; 455 | INFOPLIST_KEY_CFBundleDisplayName = ""; 456 | INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; 457 | INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2021 Fernando Bunn. All rights reserved."; 458 | INFOPLIST_KEY_NSMainStoryboardFile = Main; 459 | INFOPLIST_KEY_NSPrincipalClass = NSApplication; 460 | LD_RUNPATH_SEARCH_PATHS = ( 461 | "$(inherited)", 462 | "@executable_path/../Frameworks", 463 | ); 464 | MACOSX_DEPLOYMENT_TARGET = 10.15; 465 | MARKETING_VERSION = 1.3.0; 466 | PRODUCT_BUNDLE_IDENTIFIER = bunn.dev.UTMBeGoneHelper; 467 | PRODUCT_NAME = "$(TARGET_NAME)"; 468 | SKIP_INSTALL = YES; 469 | SWIFT_EMIT_LOC_STRINGS = YES; 470 | SWIFT_VERSION = 5.0; 471 | }; 472 | name = Debug; 473 | }; 474 | 314FD7E2277A3D0900D16AED /* Release */ = { 475 | isa = XCBuildConfiguration; 476 | buildSettings = { 477 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 478 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 479 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 480 | CODE_SIGN_ENTITLEMENTS = UTMBeGoneHelper/UTMBeGoneHelper.entitlements; 481 | CODE_SIGN_STYLE = Automatic; 482 | COMBINE_HIDPI_IMAGES = YES; 483 | CURRENT_PROJECT_VERSION = 14; 484 | DEVELOPMENT_TEAM = B2RUA6XMHC; 485 | ENABLE_HARDENED_RUNTIME = YES; 486 | GENERATE_INFOPLIST_FILE = YES; 487 | INFOPLIST_FILE = UTMBeGoneHelper/Info.plist; 488 | INFOPLIST_KEY_CFBundleDisplayName = ""; 489 | INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; 490 | INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2021 Fernando Bunn. All rights reserved."; 491 | INFOPLIST_KEY_NSMainStoryboardFile = Main; 492 | INFOPLIST_KEY_NSPrincipalClass = NSApplication; 493 | LD_RUNPATH_SEARCH_PATHS = ( 494 | "$(inherited)", 495 | "@executable_path/../Frameworks", 496 | ); 497 | MACOSX_DEPLOYMENT_TARGET = 10.15; 498 | MARKETING_VERSION = 1.3.0; 499 | PRODUCT_BUNDLE_IDENTIFIER = bunn.dev.UTMBeGoneHelper; 500 | PRODUCT_NAME = "$(TARGET_NAME)"; 501 | SKIP_INSTALL = YES; 502 | SWIFT_EMIT_LOC_STRINGS = YES; 503 | SWIFT_VERSION = 5.0; 504 | }; 505 | name = Release; 506 | }; 507 | 31A6635C24FDAB4500CDD04A /* Debug */ = { 508 | isa = XCBuildConfiguration; 509 | buildSettings = { 510 | ALWAYS_SEARCH_USER_PATHS = NO; 511 | CLANG_ANALYZER_NONNULL = YES; 512 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 513 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 514 | CLANG_CXX_LIBRARY = "libc++"; 515 | CLANG_ENABLE_MODULES = YES; 516 | CLANG_ENABLE_OBJC_ARC = YES; 517 | CLANG_ENABLE_OBJC_WEAK = YES; 518 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 519 | CLANG_WARN_BOOL_CONVERSION = YES; 520 | CLANG_WARN_COMMA = YES; 521 | CLANG_WARN_CONSTANT_CONVERSION = YES; 522 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 523 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 524 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 525 | CLANG_WARN_EMPTY_BODY = YES; 526 | CLANG_WARN_ENUM_CONVERSION = YES; 527 | CLANG_WARN_INFINITE_RECURSION = YES; 528 | CLANG_WARN_INT_CONVERSION = YES; 529 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 530 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 531 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 532 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 533 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 534 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 535 | CLANG_WARN_STRICT_PROTOTYPES = YES; 536 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 537 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 538 | CLANG_WARN_UNREACHABLE_CODE = YES; 539 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 540 | COPY_PHASE_STRIP = NO; 541 | DEBUG_INFORMATION_FORMAT = dwarf; 542 | ENABLE_STRICT_OBJC_MSGSEND = YES; 543 | ENABLE_TESTABILITY = YES; 544 | GCC_C_LANGUAGE_STANDARD = gnu11; 545 | GCC_DYNAMIC_NO_PIC = NO; 546 | GCC_NO_COMMON_BLOCKS = YES; 547 | GCC_OPTIMIZATION_LEVEL = 0; 548 | GCC_PREPROCESSOR_DEFINITIONS = ( 549 | "DEBUG=1", 550 | "$(inherited)", 551 | ); 552 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 553 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 554 | GCC_WARN_UNDECLARED_SELECTOR = YES; 555 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 556 | GCC_WARN_UNUSED_FUNCTION = YES; 557 | GCC_WARN_UNUSED_VARIABLE = YES; 558 | MACOSX_DEPLOYMENT_TARGET = 10.15; 559 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 560 | MTL_FAST_MATH = YES; 561 | ONLY_ACTIVE_ARCH = YES; 562 | SDKROOT = macosx; 563 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 564 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 565 | }; 566 | name = Debug; 567 | }; 568 | 31A6635D24FDAB4500CDD04A /* Release */ = { 569 | isa = XCBuildConfiguration; 570 | buildSettings = { 571 | ALWAYS_SEARCH_USER_PATHS = NO; 572 | CLANG_ANALYZER_NONNULL = YES; 573 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 574 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 575 | CLANG_CXX_LIBRARY = "libc++"; 576 | CLANG_ENABLE_MODULES = YES; 577 | CLANG_ENABLE_OBJC_ARC = YES; 578 | CLANG_ENABLE_OBJC_WEAK = YES; 579 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 580 | CLANG_WARN_BOOL_CONVERSION = YES; 581 | CLANG_WARN_COMMA = YES; 582 | CLANG_WARN_CONSTANT_CONVERSION = YES; 583 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 584 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 585 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 586 | CLANG_WARN_EMPTY_BODY = YES; 587 | CLANG_WARN_ENUM_CONVERSION = YES; 588 | CLANG_WARN_INFINITE_RECURSION = YES; 589 | CLANG_WARN_INT_CONVERSION = YES; 590 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 591 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 592 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 593 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 594 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 595 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 596 | CLANG_WARN_STRICT_PROTOTYPES = YES; 597 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 598 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 599 | CLANG_WARN_UNREACHABLE_CODE = YES; 600 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 601 | COPY_PHASE_STRIP = NO; 602 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 603 | ENABLE_NS_ASSERTIONS = NO; 604 | ENABLE_STRICT_OBJC_MSGSEND = YES; 605 | GCC_C_LANGUAGE_STANDARD = gnu11; 606 | GCC_NO_COMMON_BLOCKS = YES; 607 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 608 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 609 | GCC_WARN_UNDECLARED_SELECTOR = YES; 610 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 611 | GCC_WARN_UNUSED_FUNCTION = YES; 612 | GCC_WARN_UNUSED_VARIABLE = YES; 613 | MACOSX_DEPLOYMENT_TARGET = 10.15; 614 | MTL_ENABLE_DEBUG_INFO = NO; 615 | MTL_FAST_MATH = YES; 616 | SDKROOT = macosx; 617 | SWIFT_COMPILATION_MODE = wholemodule; 618 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 619 | }; 620 | name = Release; 621 | }; 622 | 31A6635F24FDAB4500CDD04A /* Debug */ = { 623 | isa = XCBuildConfiguration; 624 | buildSettings = { 625 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 626 | CLANG_ENABLE_MODULES = YES; 627 | CODE_SIGN_ENTITLEMENTS = UTMBeGone/UTMBeGone.entitlements; 628 | CODE_SIGN_IDENTITY = "Apple Development"; 629 | CODE_SIGN_STYLE = Automatic; 630 | COMBINE_HIDPI_IMAGES = YES; 631 | CURRENT_PROJECT_VERSION = 14; 632 | DEVELOPMENT_TEAM = B2RUA6XMHC; 633 | ENABLE_HARDENED_RUNTIME = YES; 634 | INFOPLIST_FILE = UTMBeGone/Info.plist; 635 | LD_RUNPATH_SEARCH_PATHS = ( 636 | "$(inherited)", 637 | "@executable_path/../Frameworks", 638 | ); 639 | MARKETING_VERSION = 1.3.0; 640 | PRODUCT_BUNDLE_IDENTIFIER = bunn.dev.utmbegone; 641 | PRODUCT_NAME = "$(TARGET_NAME)"; 642 | SWIFT_OBJC_BRIDGING_HEADER = "UTMBeGone/Util/UTMBeGone-Bridging-Header.h"; 643 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 644 | SWIFT_VERSION = 5.0; 645 | }; 646 | name = Debug; 647 | }; 648 | 31A6636024FDAB4500CDD04A /* Release */ = { 649 | isa = XCBuildConfiguration; 650 | buildSettings = { 651 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 652 | CLANG_ENABLE_MODULES = YES; 653 | CODE_SIGN_ENTITLEMENTS = UTMBeGone/UTMBeGone.entitlements; 654 | CODE_SIGN_IDENTITY = "Apple Development"; 655 | CODE_SIGN_STYLE = Automatic; 656 | COMBINE_HIDPI_IMAGES = YES; 657 | CURRENT_PROJECT_VERSION = 14; 658 | DEVELOPMENT_TEAM = B2RUA6XMHC; 659 | ENABLE_HARDENED_RUNTIME = YES; 660 | INFOPLIST_FILE = UTMBeGone/Info.plist; 661 | LD_RUNPATH_SEARCH_PATHS = ( 662 | "$(inherited)", 663 | "@executable_path/../Frameworks", 664 | ); 665 | MARKETING_VERSION = 1.3.0; 666 | PRODUCT_BUNDLE_IDENTIFIER = bunn.dev.utmbegone; 667 | PRODUCT_NAME = "$(TARGET_NAME)"; 668 | SWIFT_OBJC_BRIDGING_HEADER = "UTMBeGone/Util/UTMBeGone-Bridging-Header.h"; 669 | SWIFT_VERSION = 5.0; 670 | }; 671 | name = Release; 672 | }; 673 | 31A6636224FDAB4500CDD04A /* Debug */ = { 674 | isa = XCBuildConfiguration; 675 | buildSettings = { 676 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 677 | BUNDLE_LOADER = "$(TEST_HOST)"; 678 | CODE_SIGN_STYLE = Automatic; 679 | COMBINE_HIDPI_IMAGES = YES; 680 | DEVELOPMENT_TEAM = B2RUA6XMHC; 681 | INFOPLIST_FILE = UTMBeGoneTests/Info.plist; 682 | LD_RUNPATH_SEARCH_PATHS = ( 683 | "$(inherited)", 684 | "@executable_path/../Frameworks", 685 | "@loader_path/../Frameworks", 686 | ); 687 | MACOSX_DEPLOYMENT_TARGET = 10.15; 688 | PRODUCT_BUNDLE_IDENTIFIER = bunn.dev.UTMBeGoneTests; 689 | PRODUCT_NAME = "$(TARGET_NAME)"; 690 | SWIFT_VERSION = 5.0; 691 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UTMBeGone.app/Contents/MacOS/UTMBeGone"; 692 | }; 693 | name = Debug; 694 | }; 695 | 31A6636324FDAB4500CDD04A /* Release */ = { 696 | isa = XCBuildConfiguration; 697 | buildSettings = { 698 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 699 | BUNDLE_LOADER = "$(TEST_HOST)"; 700 | CODE_SIGN_STYLE = Automatic; 701 | COMBINE_HIDPI_IMAGES = YES; 702 | DEVELOPMENT_TEAM = B2RUA6XMHC; 703 | INFOPLIST_FILE = UTMBeGoneTests/Info.plist; 704 | LD_RUNPATH_SEARCH_PATHS = ( 705 | "$(inherited)", 706 | "@executable_path/../Frameworks", 707 | "@loader_path/../Frameworks", 708 | ); 709 | MACOSX_DEPLOYMENT_TARGET = 10.15; 710 | PRODUCT_BUNDLE_IDENTIFIER = bunn.dev.UTMBeGoneTests; 711 | PRODUCT_NAME = "$(TARGET_NAME)"; 712 | SWIFT_VERSION = 5.0; 713 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UTMBeGone.app/Contents/MacOS/UTMBeGone"; 714 | }; 715 | name = Release; 716 | }; 717 | /* End XCBuildConfiguration section */ 718 | 719 | /* Begin XCConfigurationList section */ 720 | 314FD7E0277A3D0900D16AED /* Build configuration list for PBXNativeTarget "UTMBeGoneHelper" */ = { 721 | isa = XCConfigurationList; 722 | buildConfigurations = ( 723 | 314FD7E1277A3D0900D16AED /* Debug */, 724 | 314FD7E2277A3D0900D16AED /* Release */, 725 | ); 726 | defaultConfigurationIsVisible = 0; 727 | defaultConfigurationName = Release; 728 | }; 729 | 31A6634024FDAB4400CDD04A /* Build configuration list for PBXProject "UTMBeGone" */ = { 730 | isa = XCConfigurationList; 731 | buildConfigurations = ( 732 | 31A6635C24FDAB4500CDD04A /* Debug */, 733 | 31A6635D24FDAB4500CDD04A /* Release */, 734 | ); 735 | defaultConfigurationIsVisible = 0; 736 | defaultConfigurationName = Release; 737 | }; 738 | 31A6635E24FDAB4500CDD04A /* Build configuration list for PBXNativeTarget "UTMBeGone" */ = { 739 | isa = XCConfigurationList; 740 | buildConfigurations = ( 741 | 31A6635F24FDAB4500CDD04A /* Debug */, 742 | 31A6636024FDAB4500CDD04A /* Release */, 743 | ); 744 | defaultConfigurationIsVisible = 0; 745 | defaultConfigurationName = Release; 746 | }; 747 | 31A6636124FDAB4500CDD04A /* Build configuration list for PBXNativeTarget "UTMBeGoneTests" */ = { 748 | isa = XCConfigurationList; 749 | buildConfigurations = ( 750 | 31A6636224FDAB4500CDD04A /* Debug */, 751 | 31A6636324FDAB4500CDD04A /* Release */, 752 | ); 753 | defaultConfigurationIsVisible = 0; 754 | defaultConfigurationName = Release; 755 | }; 756 | /* End XCConfigurationList section */ 757 | }; 758 | rootObject = 31A6633D24FDAB4400CDD04A /* Project object */; 759 | } 760 | -------------------------------------------------------------------------------- /UTMBeGone.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /UTMBeGone.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /UTMBeGone/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // UTMBeGone 4 | // 5 | // Created by Fernando Bunn on 31/08/2020. 6 | // Copyright © 2020 Fernando Bunn. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | @NSApplicationMain 12 | class AppDelegate: NSObject, NSApplicationDelegate { 13 | let pasteboardHandler = PasteboardHandler() 14 | let menu = MenuManager() 15 | 16 | func applicationDidFinishLaunching(_ aNotification: Notification) { 17 | NSApplication.shared.setActivationPolicy(.accessory) 18 | pasteboardHandler.startListening() 19 | menu.setupMenu() 20 | 21 | LaunchAtLoginHelper().killHelperIfNecessary() 22 | } 23 | 24 | func applicationWillTerminate(_ aNotification: Notification) { 25 | pasteboardHandler.stopListening() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /UTMBeGone/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "scale" : "1x", 6 | "size" : "16x16" 7 | }, 8 | { 9 | "filename" : "UTMBeGone32-1.png", 10 | "idiom" : "mac", 11 | "scale" : "2x", 12 | "size" : "16x16" 13 | }, 14 | { 15 | "filename" : "UTMBeGone32.png", 16 | "idiom" : "mac", 17 | "scale" : "1x", 18 | "size" : "32x32" 19 | }, 20 | { 21 | "filename" : "UTMBeGone64.png", 22 | "idiom" : "mac", 23 | "scale" : "2x", 24 | "size" : "32x32" 25 | }, 26 | { 27 | "filename" : "UTMBeGone128.png", 28 | "idiom" : "mac", 29 | "scale" : "1x", 30 | "size" : "128x128" 31 | }, 32 | { 33 | "filename" : "UTMBeGone256-1.png", 34 | "idiom" : "mac", 35 | "scale" : "2x", 36 | "size" : "128x128" 37 | }, 38 | { 39 | "filename" : "UTMBeGone256.png", 40 | "idiom" : "mac", 41 | "scale" : "1x", 42 | "size" : "256x256" 43 | }, 44 | { 45 | "filename" : "UTMBeGone512-1.png", 46 | "idiom" : "mac", 47 | "scale" : "2x", 48 | "size" : "256x256" 49 | }, 50 | { 51 | "filename" : "UTMBeGone512.png", 52 | "idiom" : "mac", 53 | "scale" : "1x", 54 | "size" : "512x512" 55 | }, 56 | { 57 | "filename" : "UTMBeGone1024.png", 58 | "idiom" : "mac", 59 | "scale" : "2x", 60 | "size" : "512x512" 61 | } 62 | ], 63 | "info" : { 64 | "author" : "xcode", 65 | "version" : 1 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bunn/UTMBeGone/5cfce9911498a836ce92521a21a811b65a21b28b/UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone1024.png -------------------------------------------------------------------------------- /UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bunn/UTMBeGone/5cfce9911498a836ce92521a21a811b65a21b28b/UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone128.png -------------------------------------------------------------------------------- /UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone256-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bunn/UTMBeGone/5cfce9911498a836ce92521a21a811b65a21b28b/UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone256-1.png -------------------------------------------------------------------------------- /UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bunn/UTMBeGone/5cfce9911498a836ce92521a21a811b65a21b28b/UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone256.png -------------------------------------------------------------------------------- /UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone32-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bunn/UTMBeGone/5cfce9911498a836ce92521a21a811b65a21b28b/UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone32-1.png -------------------------------------------------------------------------------- /UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bunn/UTMBeGone/5cfce9911498a836ce92521a21a811b65a21b28b/UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone32.png -------------------------------------------------------------------------------- /UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone512-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bunn/UTMBeGone/5cfce9911498a836ce92521a21a811b65a21b28b/UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone512-1.png -------------------------------------------------------------------------------- /UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bunn/UTMBeGone/5cfce9911498a836ce92521a21a811b65a21b28b/UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone512.png -------------------------------------------------------------------------------- /UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bunn/UTMBeGone/5cfce9911498a836ce92521a21a811b65a21b28b/UTMBeGone/Assets.xcassets/AppIcon.appiconset/UTMBeGone64.png -------------------------------------------------------------------------------- /UTMBeGone/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /UTMBeGone/Assets.xcassets/icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icon.pdf", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /UTMBeGone/Assets.xcassets/icon.imageset/icon.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bunn/UTMBeGone/5cfce9911498a836ce92521a21a811b65a21b28b/UTMBeGone/Assets.xcassets/icon.imageset/icon.pdf -------------------------------------------------------------------------------- /UTMBeGone/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | Default 534 | 535 | 536 | 537 | 538 | 539 | 540 | Left to Right 541 | 542 | 543 | 544 | 545 | 546 | 547 | Right to Left 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | Default 559 | 560 | 561 | 562 | 563 | 564 | 565 | Left to Right 566 | 567 | 568 | 569 | 570 | 571 | 572 | Right to Left 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | -------------------------------------------------------------------------------- /UTMBeGone/GarbageRemover/URLGarbageRemover.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLGarbageRemover.swift 3 | // UTMBeGone 4 | // 5 | // Created by Fernando Bunn on 31/08/2020. 6 | // Copyright © 2020 Fernando Bunn. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct URLGarbageRemover { 12 | static func removeGarbage(_ value: String, itemsToRemove: [String]) -> String { 13 | 14 | let sanitizedString = value.trimmingCharacters(in: .whitespacesAndNewlines) 15 | 16 | guard let url = URL(string: sanitizedString), 17 | var componenets = URLComponents(url: url, resolvingAgainstBaseURL: true), 18 | componenets.scheme != nil else { 19 | return value 20 | } 21 | 22 | componenets.queryItems = componenets.queryItems?.filter { queryItem in 23 | itemsToRemove.map { queryItem.name == $0 }.allSatisfy { $0 == false } 24 | } 25 | 26 | if var newURL = componenets.string { 27 | if newURL.last == "?" { 28 | newURL.removeLast() 29 | } 30 | return newURL 31 | } 32 | return value 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /UTMBeGone/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | ITSAppUsesNonExemptEncryption 24 | 25 | LSApplicationCategoryType 26 | public.app-category.utilities 27 | LSMinimumSystemVersion 28 | $(MACOSX_DEPLOYMENT_TARGET) 29 | LSUIElement 30 | 31 | NSHumanReadableCopyright 32 | Copyright © 2020 Fernando Bunn. All rights reserved. 33 | NSMainNibFile 34 | MainMenu 35 | NSPrincipalClass 36 | NSApplication 37 | NSSupportsAutomaticTermination 38 | 39 | NSSupportsSuddenTermination 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /UTMBeGone/Menu/MenuManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MenuManager.swift 3 | // UTMBeGone 4 | // 5 | // Created by Fernando Bunn on 31/08/2020. 6 | // Copyright © 2020 Fernando Bunn. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class MenuManager: NSObject { 12 | private let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) 13 | private var windowController: NSWindowController? 14 | private var appURL: URL { Bundle.main.bundleURL } 15 | private static let removeItemAlertKey = "UTMBeGone.RemoveItemAlertKey" 16 | private static let stoppedKey = "UTMBeGone.Stopped" 17 | 18 | //Hacky way to figure it out if the user is trying to open the app if it's already running 19 | private var activeCounter = 0 20 | 21 | private var launchAtLoginEnabled: Bool { 22 | get { 23 | LaunchAtLoginHelper().checkEnabled() 24 | } 25 | set { 26 | LaunchAtLoginHelper().setEnabled(newValue) 27 | } 28 | } 29 | 30 | private var stopped: Bool { 31 | get { 32 | UserDefaults.standard.bool(forKey: MenuManager.stoppedKey) 33 | } 34 | set { 35 | UserDefaults.standard.set(newValue, forKey: MenuManager.stoppedKey) 36 | if newValue { 37 | NotificationCenter.default.post(name: .PasteboardShouldStopListening, object: nil) 38 | } else { 39 | NotificationCenter.default.post(name: .PasteboardShouldStartListening, object: nil) 40 | } 41 | setupMenu() 42 | } 43 | } 44 | 45 | @objc private func applicationDidBecomeActive(_ notification: Notification) { 46 | activeCounter += 1 47 | guard activeCounter > 1 else { return } 48 | if item.isVisible == false { 49 | item.isVisible = true 50 | } 51 | } 52 | 53 | public func setupMenu() { 54 | let menu = NSMenu() 55 | 56 | NotificationCenter.default.addObserver(self, selector: #selector(MenuManager.applicationDidBecomeActive), name: NSApplication.didBecomeActiveNotification, object: nil) 57 | 58 | let preferencesItem = NSMenuItem(title: "Preferences", action: #selector(MenuManager.openPreferences), keyEquivalent: "") 59 | preferencesItem.target = self 60 | menu.addItem(preferencesItem) 61 | 62 | if stopped { 63 | let resumeMenuItem = NSMenuItem(title: "Resume ", action: #selector(MenuManager.resume), keyEquivalent: "") 64 | resumeMenuItem.target = self 65 | menu.addItem(resumeMenuItem) 66 | } else { 67 | let stopMenuItem = NSMenuItem(title: "Stop ", action: #selector(MenuManager.stop), keyEquivalent: "") 68 | stopMenuItem.target = self 69 | menu.addItem(stopMenuItem) 70 | } 71 | 72 | let launchAtLoginItem = NSMenuItem(title: "Launch at Login ", action: #selector(MenuManager.toggleLaunchAtLogin), keyEquivalent: "") 73 | launchAtLoginItem.target = self 74 | launchAtLoginItem.state = launchAtLoginEnabled ? .on : .off 75 | menu.addItem(launchAtLoginItem) 76 | 77 | let removeFromMenuItem = NSMenuItem(title: "Hide Icon ", action: #selector(MenuManager.removeFromMenu), keyEquivalent: "") 78 | removeFromMenuItem.target = self 79 | menu.addItem(removeFromMenuItem) 80 | 81 | let websiteItem = NSMenuItem(title: "Project Website", action: #selector(MenuManager.openProjectWebsite), keyEquivalent: "") 82 | websiteItem.target = self 83 | menu.addItem(websiteItem) 84 | 85 | let quitMenuItem = NSMenuItem(title: "Quit", action: #selector(MenuManager.quit), keyEquivalent: "") 86 | quitMenuItem.target = self 87 | menu.addItem(quitMenuItem) 88 | 89 | let image = NSImage(named: .init("icon")) 90 | image?.isTemplate = true 91 | 92 | self.item.button?.image = image 93 | item.menu = menu 94 | item.behavior = .removalAllowed 95 | } 96 | 97 | private func displayRemoveMenuItemAlertIfNecessary() { 98 | if UserDefaults.standard.bool(forKey: MenuManager.removeItemAlertKey) == false { 99 | let alert = NSAlert() 100 | alert.messageText = "UTMBeGone is not gone 😉" 101 | alert.informativeText = "UTMBeGone will keep running in the background. If you wish to see the menu icon again, just double click on the application's icon in your application's folder." 102 | alert.alertStyle = .warning 103 | alert.addButton(withTitle: "Understood!") 104 | alert.runModal() 105 | UserDefaults.standard.set(true, forKey: MenuManager.removeItemAlertKey) 106 | } 107 | } 108 | } 109 | 110 | 111 | //MARK: - Menu Actions 112 | 113 | extension MenuManager { 114 | 115 | @objc private func openPreferences() { 116 | NSApp.activate(ignoringOtherApps: true) 117 | let preferences = PreferencesViewController() 118 | if windowController == nil { 119 | let window = NSWindow(contentViewController: preferences) 120 | window.delegate = self 121 | windowController = NSWindowController(window: window) 122 | } 123 | windowController?.showWindow(self) 124 | windowController?.window?.makeKey() 125 | } 126 | 127 | @objc private func toggleLaunchAtLogin() { 128 | launchAtLoginEnabled.toggle() 129 | setupMenu() 130 | } 131 | 132 | @objc private func openProjectWebsite() { 133 | OpenWebsiteHelper.openWebsite() 134 | } 135 | 136 | @objc private func quit() { 137 | NSApplication.shared.terminate(self) 138 | } 139 | 140 | @objc private func removeFromMenu() { 141 | displayRemoveMenuItemAlertIfNecessary() 142 | item.isVisible = false 143 | } 144 | 145 | @objc private func stop() { 146 | stopped = true 147 | } 148 | 149 | @objc private func resume() { 150 | stopped = false 151 | } 152 | } 153 | 154 | 155 | //MARK: - Window Delegate 156 | 157 | extension MenuManager: NSWindowDelegate { 158 | 159 | func windowWillClose(_ notification: Notification) { 160 | windowController = nil 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /UTMBeGone/PasteboardCore/PasteboardHandler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PasteboardHandler.swift 3 | // UTMBeGone 4 | // 5 | // Created by Fernando Bunn on 31/08/2020. 6 | // Copyright © 2020 Fernando Bunn. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class PasteboardHandler: NSObject { 12 | let listerner = PasteboardListener() 13 | 14 | override init() { 15 | super.init() 16 | setupListeners() 17 | } 18 | 19 | private func setupListeners() { 20 | NotificationCenter.default.addObserver(self, selector: #selector(pasteboardShouldStopListening), name: .PasteboardShouldStopListening, object: nil) 21 | NotificationCenter.default.addObserver(self, selector: #selector(pasteboardShouldStartListening), name: .PasteboardShouldStartListening, object: nil) 22 | } 23 | 24 | func startListening() { 25 | NotificationCenter.default.addObserver(self, selector: #selector(onPasteboardChanged), name: .PasteboardDidChange, object: nil) 26 | listerner.startListening() 27 | } 28 | 29 | func stopListening() { 30 | NotificationCenter.default.removeObserver(self, name: .PasteboardDidChange, object: nil) 31 | listerner.stopListening() 32 | } 33 | 34 | @objc func pasteboardShouldStopListening(_ notification: Notification) { 35 | stopListening() 36 | } 37 | 38 | @objc func pasteboardShouldStartListening(_ notification: Notification) { 39 | startListening() 40 | } 41 | 42 | @objc func onPasteboardChanged(_ notification: Notification) { 43 | guard let pasteboard = notification.object as? NSPasteboard, 44 | let items = pasteboard.pasteboardItems, 45 | let item = items.first?.string(forType: .string) else { return } 46 | 47 | let itemsToRemove = QueryItemsManager().queryList.map { $0.value } 48 | let newItem = URLGarbageRemover.removeGarbage(item, itemsToRemove: itemsToRemove) 49 | 50 | if newItem != item { 51 | listerner.stopListening() 52 | let pasteboard = NSPasteboard.general 53 | pasteboard.clearContents() 54 | pasteboard.setString(newItem, forType: .string) 55 | listerner.startListening() 56 | } 57 | } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /UTMBeGone/PasteboardCore/PasteboardListener.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PasteboardListener.swift 3 | // UTMBeGone 4 | // 5 | // Created by Fernando Bunn on 31/08/2020. 6 | // Copyright © 2020 Fernando Bunn. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class PasteboardListener: NSObject { 12 | var changeCount: Int = 0 13 | var timer: Timer! 14 | 15 | func startListening() { 16 | let pasteboard: NSPasteboard = .general 17 | 18 | timer = Timer.scheduledTimer(withTimeInterval: 0.3, repeats: true) { _ in 19 | if self.changeCount != pasteboard.changeCount { 20 | self.changeCount = pasteboard.changeCount 21 | NotificationCenter.default.post(name: .PasteboardDidChange, object: pasteboard) 22 | } 23 | } 24 | } 25 | 26 | func stopListening() { 27 | timer.invalidate() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /UTMBeGone/Preferences/PreferencesViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PreferencesViewController.swift 3 | // UTMBeGone 4 | // 5 | // Created by Fernando Bunn on 07/09/2020. 6 | // Copyright © 2020 Fernando Bunn. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class PreferencesViewController: NSViewController { 12 | private static let cellIdentifier = "DefaultTableCell" 13 | private let itemsManager = QueryItemsManager() 14 | @IBOutlet weak var tableView: NSTableView! 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | tableView.dataSource = self 19 | tableView.delegate = self 20 | title = "UTMBeGone Preferences" 21 | } 22 | 23 | @objc private func textDidChange(_ sender: NSTextField) { 24 | let row = tableView.row(for: sender) 25 | if row == -1 { 26 | return 27 | } 28 | itemsManager.item(for: row).value = sender.stringValue 29 | itemsManager.save() 30 | } 31 | 32 | @IBAction func addItemButtonClicked(_ sender: NSButton) { 33 | _ = itemsManager.createNewItem() 34 | tableView.reloadData() 35 | } 36 | 37 | @IBAction func removeItemButtonClicked(_ sender: NSButton) { 38 | let selectedRow = tableView.selectedRow 39 | if selectedRow == -1 { 40 | return 41 | } 42 | let item = itemsManager.item(for: selectedRow) 43 | itemsManager.delete(item) 44 | tableView.reloadData() 45 | } 46 | 47 | @IBAction func projectWebsiteButtonClicked(_ sender: NSButton) { 48 | OpenWebsiteHelper.openWebsite() 49 | } 50 | } 51 | 52 | extension PreferencesViewController: NSTableViewDelegate { 53 | 54 | func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { 55 | let cell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: PreferencesViewController.cellIdentifier), owner: self) as? NSTableCellView 56 | cell?.textField?.stringValue = itemsManager.item(for: row).value 57 | cell?.textField?.target = self 58 | cell?.textField?.action = #selector(PreferencesViewController.textDidChange) 59 | return cell 60 | } 61 | } 62 | 63 | extension PreferencesViewController: NSTableViewDataSource { 64 | 65 | func numberOfRows(in tableView: NSTableView) -> Int { 66 | return itemsManager.numberOfItems 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /UTMBeGone/Preferences/PreferencesViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 74 | 78 | 79 | 80 | 81 | 82 | 83 | 93 | 103 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /UTMBeGone/Shared/SharedConsts.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SharedConsts.swift 3 | // UTMBeGone 4 | // 5 | // Created by Fernando Bunn on 26/12/2021. 6 | // Copyright © 2021 Fernando Bunn. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Notification.Name { 12 | static let killLauncher = Notification.Name("killLauncher") 13 | } 14 | 15 | struct SharedConsts { 16 | static let mainAppID = "bunn.dev.utmbegone" 17 | static let launcherAppID = "bunn.dev.UTMBeGoneHelper" 18 | } 19 | -------------------------------------------------------------------------------- /UTMBeGone/Storage/QueryItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // QueryItem.swift 3 | // UTMBeGone 4 | // 5 | // Created by Fernando Bunn on 07/09/2020. 6 | // Copyright © 2020 Fernando Bunn. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class QueryItem: Codable, Equatable { 12 | static func == (lhs: QueryItem, rhs: QueryItem) -> Bool { 13 | lhs.creationDate == rhs.creationDate 14 | } 15 | 16 | var creationDate = Date() 17 | var value: String = "utm" 18 | } 19 | 20 | -------------------------------------------------------------------------------- /UTMBeGone/Storage/QueryItemsManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // QueryItemsManager.swift 3 | // UTMBeGone 4 | // 5 | // Created by Fernando Bunn on 07/09/2020. 6 | // Copyright © 2020 Fernando Bunn. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | class QueryItemsManager { 13 | private static let listKey = "QueryItemListKey" 14 | private(set) var queryList = [QueryItem]() 15 | 16 | init() { 17 | restoreAll() 18 | } 19 | 20 | var numberOfItems: Int { 21 | queryList.count 22 | } 23 | 24 | func item(for index: Int) -> QueryItem { 25 | queryList[index] 26 | } 27 | 28 | func delete(_ item: QueryItem) { 29 | guard let itemIndex = queryList.firstIndex(of: item) else { return } 30 | queryList.remove(at: itemIndex) 31 | save() 32 | } 33 | 34 | private func restoreAll() { 35 | queryList.removeAll() 36 | if let itemsData = UserDefaults.standard.data(forKey: QueryItemsManager.listKey) { 37 | do { 38 | let items = try JSONDecoder().decode([QueryItem].self, from: itemsData) 39 | queryList.append(contentsOf: items) 40 | } catch { 41 | print("Decoding error \(error)") 42 | } 43 | } 44 | 45 | if queryList.count == 0 { 46 | setupDefaultList() 47 | save() 48 | } 49 | } 50 | 51 | func createNewItem() -> QueryItem { 52 | let item = QueryItem() 53 | queryList.append(item) 54 | return item 55 | } 56 | 57 | func save() { 58 | let jsonEncoder = JSONEncoder() 59 | do { 60 | let encoded = try jsonEncoder.encode(queryList) 61 | UserDefaults.standard.set(encoded, forKey: QueryItemsManager.listKey) 62 | } catch { 63 | print("Error encoding \(error)") 64 | } 65 | } 66 | 67 | private func setupDefaultList() { 68 | _ = createNewItem().value = "utm" 69 | _ = createNewItem().value = "utm_source" 70 | _ = createNewItem().value = "utm_media" 71 | _ = createNewItem().value = "utm_campaign" 72 | _ = createNewItem().value = "utm_medium" 73 | _ = createNewItem().value = "utm_term" 74 | _ = createNewItem().value = "utm_content" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /UTMBeGone/UTMBeGone.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 | -------------------------------------------------------------------------------- /UTMBeGone/Util/LaunchAtLoginHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LaunchAtLoginHelper.swift 3 | // UTMBeGone 4 | // 5 | // Created by Fernando Bunn on 26/12/2021. 6 | // Copyright © 2021 Fernando Bunn. All rights reserved. 7 | // 8 | 9 | //Thanks to https://github.com/insidegui/StatusBuddy 10 | 11 | import Cocoa 12 | import ServiceManagement 13 | 14 | struct LaunchAtLoginHelper { 15 | 16 | func killHelperIfNecessary() { 17 | let runningApps = NSWorkspace.shared.runningApplications 18 | let isRunning = !runningApps.filter { $0.bundleIdentifier == SharedConsts.launcherAppID }.isEmpty 19 | 20 | if isRunning { 21 | DistributedNotificationCenter.default().post(name: .killLauncher, object: Bundle.main.bundleIdentifier!) 22 | } 23 | } 24 | 25 | func checkEnabled() -> Bool { 26 | // Not actually deprecated according to the headers. 27 | guard let jobDictsPtr = SMCopyAllJobDictionaries(kSMDomainUserLaunchd) else { return false } 28 | 29 | guard let dicts = jobDictsPtr.takeUnretainedValue() as? [[String: Any]] else { return false } 30 | 31 | return dicts.contains(where: { $0["Label"] as? String == SharedConsts.launcherAppID }) 32 | } 33 | 34 | func setEnabled(_ enabled: Bool) { 35 | SMLoginItemSetEnabled(SharedConsts.launcherAppID as CFString, enabled) 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /UTMBeGone/Util/NotificationNames.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationNames.swift 3 | // UTMBeGone 4 | // 5 | // Created by Fernando Bunn on 12/09/2020. 6 | // Copyright © 2020 Fernando Bunn. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | extension NSNotification.Name { 13 | public static let PasteboardDidChange = NSNotification.Name("pasteboardDidChangeNotification") 14 | public static let PasteboardShouldStopListening = NSNotification.Name("pasteboardShouldStopListening") 15 | public static let PasteboardShouldStartListening = NSNotification.Name("pasteboardShouldStartListening") 16 | } 17 | -------------------------------------------------------------------------------- /UTMBeGone/Util/OpenWebsiteHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OpenWebsiteHelper.swift 3 | // UTMBeGone 4 | // 5 | // Created by Fernando Bunn on 30/12/2021. 6 | // Copyright © 2021 Fernando Bunn. All rights reserved. 7 | // 8 | 9 | 10 | import Cocoa 11 | 12 | struct OpenWebsiteHelper { 13 | 14 | static func openWebsite() { 15 | NSWorkspace.shared.open(URL(string: "https://github.com/Bunn/UTMBeGone")!) 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /UTMBeGone/Util/UTMBeGone-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | -------------------------------------------------------------------------------- /UTMBeGoneHelper/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // UTMBeGoneHelper 4 | // 5 | // Created by Fernando Bunn on 27/12/2021. 6 | // Copyright © 2021 Fernando Bunn. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import os.log 11 | 12 | @NSApplicationMain 13 | class AppDelegate: NSObject, NSApplicationDelegate { 14 | 15 | private let log = OSLog(subsystem: "bunn.dev.UTMBeGoneHelper", category: String(describing: AppDelegate.self)) 16 | 17 | func applicationDidFinishLaunching(_ aNotification: Notification) { 18 | let config = NSWorkspace.OpenConfiguration() 19 | config.activates = false 20 | config.addsToRecentItems = false 21 | config.promptsUserIfNeeded = false 22 | 23 | NSWorkspace.shared.openApplication( 24 | at: Bundle.main.mainAppBundleURL, 25 | configuration: config) { _, error in 26 | if let error = error { 27 | os_log("Failed to launch main app: %{public}@", log: self.log, type: .fault, String(describing: error)) 28 | } else { 29 | os_log("Main app launched successfully", log: self.log, type: .info) 30 | } 31 | 32 | DispatchQueue.main.async { NSApp?.terminate(nil) } 33 | } 34 | } 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /UTMBeGoneHelper/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 | -------------------------------------------------------------------------------- /UTMBeGoneHelper/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "scale" : "1x", 6 | "size" : "16x16" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "scale" : "2x", 11 | "size" : "16x16" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "scale" : "1x", 16 | "size" : "32x32" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "scale" : "2x", 21 | "size" : "32x32" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "scale" : "1x", 26 | "size" : "128x128" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "scale" : "2x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "scale" : "1x", 36 | "size" : "256x256" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "scale" : "2x", 41 | "size" : "256x256" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "scale" : "1x", 46 | "size" : "512x512" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "scale" : "2x", 51 | "size" : "512x512" 52 | } 53 | ], 54 | "info" : { 55 | "author" : "xcode", 56 | "version" : 1 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /UTMBeGoneHelper/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /UTMBeGoneHelper/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | Default 529 | 530 | 531 | 532 | 533 | 534 | 535 | Left to Right 536 | 537 | 538 | 539 | 540 | 541 | 542 | Right to Left 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | Default 554 | 555 | 556 | 557 | 558 | 559 | 560 | Left to Right 561 | 562 | 563 | 564 | 565 | 566 | 567 | Right to Left 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | -------------------------------------------------------------------------------- /UTMBeGoneHelper/Bundle+MainApp.swift: -------------------------------------------------------------------------------- 1 | 2 | //https://github.com/insidegui/StatusBuddy 3 | // 4 | // Bundle+MainApp.swift 5 | // StatusBuddyHelper 6 | // 7 | // Created by Guilherme Rambo on 21/12/21. 8 | // Copyright © 2021 Guilherme Rambo. All rights reserved. 9 | // 10 | 11 | import Foundation 12 | 13 | extension Bundle { 14 | 15 | /// Returns the URL for the app's main bundle. 16 | public var mainAppBundleURL: URL { 17 | #if DEBUG 18 | guard !Bundle.main.bundleURL.path.contains("DerivedData") else { 19 | return derivedDataMainAppBundleURL 20 | } 21 | #endif 22 | 23 | return bundledMainAppBundleURL 24 | } 25 | 26 | /// Returns `true` if the app is running from within the Xcode DerivedData folder. 27 | /// Always returns `false` in release builds. 28 | /// Assumes the path for the folder contains `DerivedData`. 29 | public var isInDerivedDataFolder: Bool { 30 | #if DEBUG 31 | return bundlePath.contains("DerivedData") 32 | #else 33 | return false 34 | #endif 35 | } 36 | 37 | private var bundledMainAppBundleURL: URL { 38 | return bundleURL 39 | .deletingLastPathComponent() // UTMBeGone.app 40 | .deletingLastPathComponent() // LoginItems 41 | .deletingLastPathComponent() // Library 42 | .deletingLastPathComponent() // Contents 43 | } 44 | 45 | #if DEBUG 46 | /// Handles StatusBuddyHelper running directly from within Xcode, in which case it 47 | /// will be outside of the main app bundle. 48 | private var derivedDataMainAppBundleURL: URL { 49 | let mainAppURL = Bundle.main.bundleURL 50 | .deletingLastPathComponent() 51 | .appendingPathComponent("UTMBeGone.app") 52 | 53 | guard FileManager.default.fileExists(atPath: mainAppURL.path) else { 54 | return bundledMainAppBundleURL 55 | } 56 | 57 | return mainAppURL 58 | } 59 | #endif 60 | 61 | } 62 | -------------------------------------------------------------------------------- /UTMBeGoneHelper/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LSBackgroundOnly 6 | 7 | LSUIElement 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /UTMBeGoneHelper/UTMBeGoneHelper.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 | -------------------------------------------------------------------------------- /UTMBeGoneTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /UTMBeGoneTests/UTMBeGoneTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UTMBeGoneTests.swift 3 | // UTMBeGoneTests 4 | // 5 | // Created by Fernando Bunn on 31/08/2020. 6 | // Copyright © 2020 Fernando Bunn. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import UTMBeGone 11 | 12 | class UTMBeGoneTests: XCTestCase { 13 | let defaultItemsToRemove = ["utm", "utm_source", "utm_media", "utm_campaign", "utm_medium", "utm_term"] 14 | 15 | override func setUpWithError() throws { 16 | } 17 | 18 | override func tearDownWithError() throws { 19 | } 20 | 21 | func testQueryWithoutScheme() { 22 | let value = " " 23 | XCTAssertEqual(URLGarbageRemover.removeGarbage(value, itemsToRemove: defaultItemsToRemove), value) 24 | } 25 | 26 | func testURLsWithScheme() throws { 27 | let values = ["https://www.gog.com/news/25th_anniversary_look_back_at_phantasmagoria?utm_medium=social&utm_source=twitter&utm_campaign=20200824_phantasmagoriaeditorial_entw&utm_term=EN" :"https://www.gog.com/news/25th_anniversary_look_back_at_phantasmagoria", 28 | 29 | "https://casa.sapo.pt/detalhes.aspx?UID=9fa85847-82ee-4b0c-a830-44d0b391caf4&utm_medium=email&utm_campaign=alerts&utm_source=details" : "https://casa.sapo.pt/detalhes.aspx?UID=9fa85847-82ee-4b0c-a830-44d0b391caf4", 30 | 31 | "https://www.reddit.com/r/politics/comments/g6wrl2/trump_suggests_injecting_disinfectant_to_treat/?utm_medium=android_app&utm_source=share" : "https://www.reddit.com/r/politics/comments/g6wrl2/trump_suggests_injecting_disinfectant_to_treat/" 32 | ] 33 | 34 | for (badData, goodData) in values { 35 | XCTAssertEqual(URLGarbageRemover.removeGarbage(badData, itemsToRemove: defaultItemsToRemove), goodData) 36 | } 37 | } 38 | 39 | /* 40 | Every browser copies the scheme with the URL. 41 | If the URL doesn't have scheme I'm assuming the user is copying it from another place and we should probably not change it 42 | */ 43 | func testURLsWithoutScheme() throws { 44 | let values = [ 45 | "www.reddit.com/r/portugal/comments/esae9x/informação_útil_para_donos_de_nintendo_switch_e/?utm_medium=android_app&utm_source=share": "www.reddit.com/r/portugal/comments/esae9x/informação_útil_para_donos_de_nintendo_switch_e/?utm_medium=android_app&utm_source=share" 46 | ] 47 | 48 | for (badData, goodData) in values { 49 | XCTAssertEqual(URLGarbageRemover.removeGarbage(badData, itemsToRemove: defaultItemsToRemove), goodData) 50 | } 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bunn/UTMBeGone/5cfce9911498a836ce92521a21a811b65a21b28b/images/icon.png -------------------------------------------------------------------------------- /images/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bunn/UTMBeGone/5cfce9911498a836ce92521a21a811b65a21b28b/images/screenshot.png -------------------------------------------------------------------------------- /images/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bunn/UTMBeGone/5cfce9911498a836ce92521a21a811b65a21b28b/images/screenshot2.png --------------------------------------------------------------------------------