30 |
31 | #define STPrivilegedTaskDidTerminateNotification @"STPrivilegedTaskDidTerminateNotification"
32 |
33 | // Defines error value for when AuthorizationExecuteWithPrivileges no longer exists
34 | // Rather than defining a new enum, we just create a global constant
35 | extern const OSStatus errAuthorizationFnNoLongerExists;
36 |
37 | @interface STPrivilegedTask : NSObject
38 |
39 | @property (copy) NSArray *arguments;
40 | @property (copy) NSString *currentDirectoryPath;
41 | @property (copy) NSString *launchPath;
42 |
43 | @property (readonly) NSFileHandle *outputFileHandle;
44 | @property (readonly) BOOL isRunning;
45 | @property (readonly) pid_t processIdentifier;
46 | @property (readonly) int terminationStatus;
47 |
48 | @property (copy) void (^terminationHandler)(STPrivilegedTask *);
49 |
50 | - (instancetype)initWithLaunchPath:(NSString *)path;
51 | - (instancetype)initWithLaunchPath:(NSString *)path arguments:(NSArray *)args;
52 | - (instancetype)initWithLaunchPath:(NSString *)path arguments:(NSArray *)args currentDirectory:(NSString *)cwd;
53 |
54 | + (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path;
55 | + (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)args;
56 | + (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)args currentDirectory:(NSString *)cwd;
57 |
58 | - (OSStatus)launch;
59 | - (void)terminate; // doesn't work
60 | - (void)waitUntilExit;
61 |
62 | @end
63 |
64 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at djminikin@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://vshymanskyy.github.io/StandWithUkraine)
2 |
3 |
11 |
12 |
13 | Sketch Cache Cleaner is a macOS app that deletes hidden Sketch history files that can take a lot of space on your hard drive and that you would probably never use.
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 | 1. [Warning](#warning)
47 | 2. [System Requirements](#system-requirements)
48 | 3. [Changelog](https://github.com/yo-op/sketchcachecleaner/blob/master/CHANGELOG.md)
49 | 4. [Tips](#tips)
50 | 5. [Authors](#authors)
51 | 6. [License](#license)
52 |
53 | ---
54 |
55 | ## Warning
56 |
57 | The app idea inspired by two blog posts: [How Sketch took over 200GB of our MacBooks](https://medium.com/@thomasdegry/how-sketch-took-over-200gb-of-our-macbooks-cb7dd10c8163) & [How to recover 50 GB or even more by deleting Sketch caches files](https://medium.com/sketch-app-sources/how-to-recover-50-go-or-even-more-by-deleting-sketch-caches-files-e5829dba20e1)
58 |
59 | Please, read them in case you want to know how it works.
60 |
61 | If your **workflow** relies on **automatic versioning** by macOS
62 | (Time Machine etc.) - **DO NOT USE THIS APP!**
63 |
64 | The app will remove all files in folder: /.DocumentRevisions-V100/
65 |
66 | ---
67 |
68 | ### System Requirements
69 |
70 | - macOS 10.13+
71 | - Xcode 11.4+
72 | - Swift 5.2+
73 |
74 | ---
75 |
76 | ### Authors
77 |
78 | Idea & design: [Yuriy Oparenko](http://oparenko.com/)
79 |
80 | Development: [Sasha Prokhorenko](https://twitter.com/minikin)
81 |
82 | ---
83 |
84 | ### Tips
85 |
86 | - Use this app wisely.
87 | - Reboot your Mac after app use.
88 |
89 | ---
90 |
91 | ### License
92 |
93 | Sketch Cache Cleaner is distributed under the [MIT license](https://github.com/yo-op/sketchcachecleaner/blob/master/LICENSE.md).
94 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### macOS ###
2 | *.DS_Store
3 | .AppleDouble
4 | .LSOverride
5 |
6 | # Icon must end with two \r
7 | Icon
8 |
9 |
10 | # Thumbnails
11 | ._*
12 |
13 | # Files that might appear in the root of a volume
14 | .DocumentRevisions-V100
15 | .fseventsd
16 | .Spotlight-V100
17 | .TemporaryItems
18 | .Trashes
19 | .VolumeIcon.icns
20 | .com.apple.timemachine.donotpresent
21 |
22 | # Directories potentially created on remote AFP share
23 | .AppleDB
24 | .AppleDesktop
25 | Network Trash Folder
26 | Temporary Items
27 | .apdisk
28 |
29 | ### Objective-C ###
30 | # Xcode
31 | #
32 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
33 |
34 | ## Build generated
35 | build/
36 | DerivedData/
37 |
38 | ## Various settings
39 | *.pbxuser
40 | !default.pbxuser
41 | *.mode1v3
42 | !default.mode1v3
43 | *.mode2v3
44 | !default.mode2v3
45 | *.perspectivev3
46 | !default.perspectivev3
47 | xcuserdata/
48 |
49 | ## Other
50 | *.moved-aside
51 | *.xccheckout
52 | *.xcscmblueprint
53 |
54 | ## Obj-C/Swift specific
55 | *.hmap
56 | *.ipa
57 | *.dSYM.zip
58 | *.dSYM
59 |
60 | # CocoaPods
61 | #
62 | # We recommend against adding the Pods directory to your .gitignore. However
63 | # you should judge for yourself, the pros and cons are mentioned at:
64 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
65 | #
66 | # Pods/
67 |
68 | # Carthage
69 | #
70 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
71 | # Carthage/Checkouts
72 |
73 | Carthage/Build
74 |
75 | # fastlane
76 | #
77 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
78 | # screenshots whenever they are needed.
79 | # For more information about the recommended setup visit:
80 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
81 |
82 | fastlane/report.xml
83 | fastlane/Preview.html
84 | fastlane/screenshots
85 | fastlane/test_output
86 |
87 | # Code Injection
88 | #
89 | # After new code Injection tools there's a generated folder /iOSInjectionProject
90 | # https://github.com/johnno1962/injectionforxcode
91 |
92 | iOSInjectionProject/
93 |
94 | ### Objective-C Patch ###
95 |
96 | ### Swift ###
97 | # Xcode
98 | #
99 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
100 |
101 | ## Build generated
102 |
103 | ## Various settings
104 |
105 | ## Other
106 |
107 | ## Obj-C/Swift specific
108 |
109 | ## Playgrounds
110 | timeline.xctimeline
111 | playground.xcworkspace
112 |
113 | # Swift Package Manager
114 | #
115 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
116 | # Packages/
117 | # Package.pins
118 | .build/
119 |
120 | # CocoaPods
121 | #
122 | # We recommend against adding the Pods directory to your .gitignore. However
123 | # you should judge for yourself, the pros and cons are mentioned at:
124 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
125 | #
126 | # Pods/
127 |
128 | # Carthage
129 | #
130 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
131 | # Carthage/Checkouts
132 |
133 |
134 | # fastlane
135 | #
136 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
137 | # screenshots whenever they are needed.
138 | # For more information about the recommended setup visit:
139 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
140 |
141 |
142 | ### Xcode ###
143 | build
144 | *.xcodeproj/*
145 | !*.xcodeproj/project.pbxproj
146 | !*.xcworkspace/contents.xcworkspacedata
147 | /*.gcno
148 |
149 | ### VisualStudioCode ###
150 | .vscode/*
151 | !.vscode/settings.json
152 | !.vscode/tasks.json
153 | !.vscode/launch.json
154 | !.vscode/extensions.json
155 | .history
156 |
--------------------------------------------------------------------------------
/Sketch Cache Cleaner/Controllers/MainViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // Sketch Cache Cleaner
4 | //
5 | // Created by Sasha Prokhorenko on 2/6/17.
6 | // Copyright © 2017 Sasha Prokhorenko. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | final class MainViewController: NSViewController {
12 | // MARK: - IBOutlets
13 |
14 | @IBOutlet private var backgroundView: NSView!
15 | @IBOutlet private var button: NSButton!
16 | @IBOutlet private var shareToTweeterButton: NSButton!
17 | @IBOutlet private var shareToFaceBookButton: NSButton!
18 | @IBOutlet private var mainImage: NSImageView!
19 | @IBOutlet private var backgroundImage: NSImageView!
20 | @IBOutlet private var cacheCleared: NSImageView!
21 | @IBOutlet private var notificationLabel: NSTextField!
22 | @IBOutlet private var sketchLabel: NSTextField!
23 | @IBOutlet private var progress: NSProgressIndicator!
24 |
25 | // MARK: - Instance Properties
26 |
27 | private var permissionGranted = false
28 | private var stringToTest = ""
29 | private let privilegedTask = STPrivilegedTask()
30 | private let bashPath = Environment.bashPath
31 | private let calculateCacheSizeTask = [Environment.calculateCacheScriptPath]
32 | private let clearCacheTask = [Environment.clearCacheScriptPath]
33 |
34 | // MARK: - ViewController lifecycle
35 |
36 | override func viewDidLoad() {
37 | super.viewDidLoad()
38 | configureInitialVCState()
39 | }
40 |
41 | override func viewWillAppear() {
42 | super.viewWillAppear()
43 | additionalVCConfigure()
44 | }
45 |
46 | // MARK: - Initial state
47 |
48 | private func configureInitialVCState() {
49 | backgroundImage.isHidden = true
50 | cacheCleared.isHidden = true
51 | notificationLabel.isHidden = true
52 | shareToTweeterButton.isHidden = true
53 | shareToFaceBookButton.isHidden = true
54 | }
55 |
56 | private func additionalVCConfigure() {
57 | view.window?.titlebarAppearsTransparent = true
58 | view.window?.backgroundColor = Colors.background
59 | view.window?.contentView?.setFrameSize(CGSize(width: (view.window?.contentView?.frame.width)!,
60 | height: (view.window?.contentView?.frame.height)! + 20))
61 | NSButton.setButton(button, title: ButtonText.enableAndScan)
62 | }
63 |
64 | private func appState() {
65 | switch (permissionGranted, button.title) {
66 | case (false, ButtonText.enableAndScan):
67 | button.title = ButtonText.enableAndScan
68 | askPermission()
69 | case (true, ButtonText.scanning):
70 | checkSizeOfCache()
71 | case (true, stringToTest):
72 | clearCache()
73 | default:
74 | break
75 | }
76 | }
77 |
78 | // MARK: - Helpers
79 |
80 | private func askPermission() {
81 | privilegedTask.launchPath = bashPath
82 | privilegedTask.arguments = calculateCacheSizeTask
83 | privilegedTask.currentDirectoryPath = Bundle.main.resourcePath
84 | let err = privilegedTask.launch()
85 | if err != errAuthorizationSuccess {
86 | if err == errAuthorizationCanceled {
87 | permissionGranted = false
88 | return
89 | } else {
90 | print("Something went wrong:", err)
91 | // For error codes, see http://www.opensource.apple.com/source/libsecurity_authorization/libsecurity_authorization-36329/lib/Authorization.h
92 | }
93 | }
94 | privilegedTask.waitUntilExit()
95 | permissionGranted = true
96 | backgroundImage.isHidden = false
97 | progress.startAnimation(self)
98 | button.isEnabled = false
99 | NSButton.setButton(button, title: ButtonText.scanning)
100 | mainImage.cell?.image = #imageLiteral(resourceName: "closedBox")
101 | DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
102 | self.button.isEnabled = true
103 | self.checkSizeOfCache()
104 | }
105 | }
106 |
107 | private func checkSizeOfCache() {
108 | progress.stopAnimation(self)
109 | let readHandle = privilegedTask.outputFileHandle
110 | let outputData = readHandle?.readDataToEndOfFile()
111 | let outputString = String(data: outputData!, encoding: .utf8)
112 | let stringArray = outputString?.components(separatedBy: "/")
113 | guard let stringToDispaly = stringArray?[0] else { return }
114 | if stringToDispaly.trim() == "0B" || stringToDispaly == "" {
115 | finalUIState()
116 | } else {
117 | stringToTest = "Clear \(stringToDispaly.trim())B"
118 | NSButton.setButton(button, title: "Clear \(stringToDispaly.trim())B")
119 | mainImage.cell?.image = #imageLiteral(resourceName: "boxWithSketch")
120 | notificationLabel.isHidden = false
121 | }
122 | }
123 |
124 | private func clearCache() {
125 | privilegedTask.launchPath = bashPath
126 | privilegedTask.arguments = clearCacheTask
127 | privilegedTask.currentDirectoryPath = Bundle.main.resourcePath
128 | let err = privilegedTask.launch()
129 | if err != errAuthorizationSuccess {
130 | if err == errAuthorizationCanceled {
131 | print("User cancelled", permissionGranted)
132 | return
133 | } else {
134 | print("Something went wrong:", err)
135 | }
136 | }
137 | privilegedTask.waitUntilExit()
138 | finalUIState()
139 | }
140 |
141 | private func finalUIState() {
142 | mainImage.cell?.image = #imageLiteral(resourceName: "openBox")
143 | button.isHidden = true
144 | cacheCleared.isHidden = false
145 | notificationLabel.isHidden = true
146 | shareToTweeterButton.isHidden = false
147 | shareToFaceBookButton.isHidden = false
148 | }
149 |
150 | // MARK: - Actions
151 |
152 | @IBAction private func buttonPressed(_: NSButton) {
153 | appState()
154 | }
155 |
156 | @IBAction private func shareToTweeterDidPress(_: NSButton) {
157 | NSWorkspace.shared.open(Share.twitterMessage(stringToTest))
158 | }
159 |
160 | @IBAction private func shareToFacebookrDidPress(_: NSButton) {
161 | NSWorkspace.shared.open(Share.facebookMessage(stringToTest))
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/Sketch Cache Cleaner/Utils/STPrivilegedTask.m:
--------------------------------------------------------------------------------
1 | /*
2 | # STPrivilegedTask - NSTask-like wrapper around AuthorizationExecuteWithPrivileges
3 | # Copyright (C) 2009-2016 Sveinbjorn Thordarson
4 | #
5 | # BSD License
6 | # Redistribution and use in source and binary forms, with or without
7 | # modification, are permitted provided that the following conditions are met:
8 | # * Redistributions of source code must retain the above copyright
9 | # notice, this list of conditions and the following disclaimer.
10 | # * Redistributions in binary form must reproduce the above copyright
11 | # notice, this list of conditions and the following disclaimer in the
12 | # documentation and/or other materials provided with the distribution.
13 | # * Neither the name of Sveinbjorn Thordarson nor that of any other
14 | # contributors may be used to endorse or promote products
15 | # derived from this software without specific prior written permission.
16 | #
17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | # DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
21 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #import "STPrivilegedTask.h"
30 |
31 | #import
32 | #import
33 | #import
34 | #import
35 | #import
36 |
37 | // New error code denoting that AuthorizationExecuteWithPrivileges no longer exists
38 | OSStatus const errAuthorizationFnNoLongerExists = -70001;
39 |
40 | @implementation STPrivilegedTask
41 | {
42 | NSTimer *_checkStatusTimer;
43 | }
44 |
45 | - (instancetype)init
46 | {
47 | self = [super init];
48 | if (self) {
49 | _launchPath = nil;
50 | _arguments = nil;
51 | _isRunning = NO;
52 | _outputFileHandle = nil;
53 | _terminationHandler = nil;
54 | _currentDirectoryPath = [[NSFileManager defaultManager] currentDirectoryPath];
55 | }
56 | return self;
57 | }
58 |
59 | - (instancetype)initWithLaunchPath:(NSString *)path
60 | {
61 | self = [self init];
62 | if (self) {
63 | self.launchPath = path;
64 | }
65 | return self;
66 | }
67 |
68 | - (instancetype)initWithLaunchPath:(NSString *)path arguments:(NSArray *)args
69 | {
70 | self = [self initWithLaunchPath:path];
71 | if (self) {
72 | self.arguments = args;
73 | }
74 | return self;
75 | }
76 |
77 | - (instancetype)initWithLaunchPath:(NSString *)path arguments:(NSArray *)args currentDirectory:(NSString *)cwd
78 | {
79 | self = [self initWithLaunchPath:path arguments:args];
80 | if (self) {
81 | self.currentDirectoryPath = cwd;
82 | }
83 | return self;
84 | }
85 |
86 | #pragma mark -
87 |
88 | + (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path
89 | {
90 | STPrivilegedTask *task = [[STPrivilegedTask alloc] initWithLaunchPath:path];
91 | #if !__has_feature(objc_arc)
92 | [task autorelease];
93 | #endif
94 | [task launch];
95 | [task waitUntilExit];
96 | return task;
97 | }
98 |
99 | + (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)args
100 | {
101 | STPrivilegedTask *task = [[STPrivilegedTask alloc] initWithLaunchPath:path arguments:args];
102 | #if !__has_feature(objc_arc)
103 | [task autorelease];
104 | #endif
105 |
106 | [task launch];
107 | [task waitUntilExit];
108 | return task;
109 | }
110 |
111 | + (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)args currentDirectory:(NSString *)cwd
112 | {
113 | STPrivilegedTask *task = [[STPrivilegedTask alloc] initWithLaunchPath:path arguments:args currentDirectory:cwd];
114 | #if !__has_feature(objc_arc)
115 | [task autorelease];
116 | #endif
117 |
118 | [task launch];
119 | [task waitUntilExit];
120 | return task;
121 | }
122 |
123 | # pragma mark -
124 |
125 | // return 0 for success
126 | - (OSStatus)launch
127 | {
128 | if (_isRunning) {
129 | NSLog(@"Task already running: %@", [self description]);
130 | return 0;
131 | }
132 |
133 | OSStatus err = noErr;
134 | const char *toolPath = [self.launchPath fileSystemRepresentation];
135 |
136 | AuthorizationRef authorizationRef;
137 | AuthorizationItem myItems = { kAuthorizationRightExecute, strlen(toolPath), &toolPath, 0 };
138 | AuthorizationRights myRights = { 1, &myItems };
139 | AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights;
140 |
141 | NSArray *arguments = self.arguments;
142 | NSUInteger numberOfArguments = [arguments count];
143 | char *args[numberOfArguments + 1];
144 | FILE *outputFile;
145 |
146 | // Create fn pointer to AuthorizationExecuteWithPrivileges in case it doesn't exist
147 | // in this version of MacOS
148 | static OSStatus (*_AuthExecuteWithPrivsFn)(
149 | AuthorizationRef authorization, const char *pathToTool, AuthorizationFlags options,
150 | char * const *arguments, FILE **communicationsPipe) = NULL;
151 |
152 | // Check to see if we have the correct function in our loaded libraries
153 | if (!_AuthExecuteWithPrivsFn) {
154 | // On 10.7, AuthorizationExecuteWithPrivileges is deprecated. We want
155 | // to still use it since there's no good alternative (without requiring
156 | // code signing). We'll look up the function through dyld and fail if
157 | // it is no longer accessible. If Apple removes the function entirely
158 | // this will fail gracefully. If they keep the function and throw some
159 | // sort of exception, this won't fail gracefully, but that's a risk
160 | // we'll have to take for now.
161 | // Pattern by Andy Kim from Potion Factory LLC
162 | _AuthExecuteWithPrivsFn = dlsym(RTLD_DEFAULT, "AuthorizationExecuteWithPrivileges");
163 | if (!_AuthExecuteWithPrivsFn) {
164 | // This version of OS X has finally removed this function. Return with an error.
165 | return errAuthorizationFnNoLongerExists;
166 | }
167 | }
168 |
169 | // Use Apple's Authentication Manager APIs to get an Authorization Reference
170 | // These Apple APIs are quite possibly the most horrible of the Mac OS X APIs
171 |
172 | // create authorization reference
173 | err = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef);
174 | if (err != errAuthorizationSuccess) {
175 | return err;
176 | }
177 |
178 | // pre-authorize the privileged operation
179 | err = AuthorizationCopyRights(authorizationRef, &myRights, kAuthorizationEmptyEnvironment, flags, NULL);
180 | if (err != errAuthorizationSuccess) {
181 | return err;
182 | }
183 |
184 | // OK, at this point we have received authorization for the task.
185 | // Let's prepare to launch it
186 |
187 | // first, construct an array of c strings from NSArray w. arguments
188 | for (int i = 0; i < numberOfArguments; i++) {
189 | NSString *argString = arguments[i];
190 | NSUInteger stringLength = [argString length];
191 |
192 | args[i] = malloc((stringLength + 1) * sizeof(char));
193 | snprintf(args[i], stringLength + 1, "%s", [argString fileSystemRepresentation]);
194 | }
195 | args[numberOfArguments] = NULL;
196 |
197 | // change to the current dir specified
198 | char *prevCwd = (char *)getcwd(nil, 0);
199 | chdir([self.currentDirectoryPath fileSystemRepresentation]);
200 |
201 | //use Authorization Reference to execute script with privileges
202 | err = _AuthExecuteWithPrivsFn(authorizationRef, toolPath, kAuthorizationFlagDefaults, args, &outputFile);
203 |
204 | // OK, now we're done executing, let's change back to old dir
205 | chdir(prevCwd);
206 |
207 | // free the malloc'd argument strings
208 | for (int i = 0; i < numberOfArguments; i++) {
209 | free(args[i]);
210 | }
211 |
212 | // free the auth ref
213 | AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);
214 |
215 | // we return err if execution failed
216 | if (err != errAuthorizationSuccess) {
217 | return err;
218 | } else {
219 | _isRunning = YES;
220 | }
221 |
222 | // get file handle for the command output
223 | _outputFileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fileno(outputFile) closeOnDealloc:YES];
224 | _processIdentifier = fcntl(fileno(outputFile), F_GETOWN, 0);
225 |
226 | // start monitoring task
227 | _checkStatusTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(checkTaskStatus) userInfo:nil repeats:YES];
228 |
229 | return err;
230 | }
231 |
232 | - (void)terminate
233 | {
234 | // This doesn't work without a PID, and we can't get one. Stupid Security API
235 | // int ret = kill(pid, SIGKILL);
236 | //
237 | // if (ret != 0) {
238 | // NSLog(@"Error %d", errno);
239 | // }
240 | }
241 |
242 | // hang until task is done
243 | - (void)waitUntilExit
244 | {
245 | if (!_isRunning) {
246 | NSLog(@"Task %@ is not running", [super description]);
247 | return;
248 | }
249 |
250 | [_checkStatusTimer invalidate];
251 |
252 | int status;
253 | pid_t pid = 0;
254 | while ((pid = waitpid(_processIdentifier, &status, WNOHANG)) == 0) {
255 | // do nothing
256 | }
257 | _terminationStatus = WEXITSTATUS(status);
258 | _isRunning = NO;
259 | }
260 |
261 | // check if task has terminated
262 | - (void)checkTaskStatus
263 | {
264 | int status;
265 | pid_t pid = waitpid(_processIdentifier, &status, WNOHANG);
266 | if (pid != 0) {
267 | _isRunning = NO;
268 | _terminationStatus = WEXITSTATUS(status);
269 | [_checkStatusTimer invalidate];
270 | [[NSNotificationCenter defaultCenter] postNotificationName:STPrivilegedTaskDidTerminateNotification object:self];
271 | if (_terminationHandler) {
272 | _terminationHandler(self);
273 | }
274 | }
275 | }
276 |
277 | #pragma mark -
278 |
279 | // Nice description for debugging
280 | - (NSString *)description
281 | {
282 | NSString *commandDescription = [NSString stringWithString:self.launchPath];
283 |
284 | for (NSString *arg in self.arguments) {
285 | commandDescription = [commandDescription stringByAppendingFormat:@" '%@'", arg];
286 | }
287 | [commandDescription stringByAppendingFormat:@" (CWD:%@)", self.currentDirectoryPath];
288 |
289 | return [[super description] stringByAppendingFormat:@" %@", commandDescription];
290 | }
291 |
292 | @end
293 |
--------------------------------------------------------------------------------
/Sketch Cache Cleaner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 54;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 035AF2A11F0585FB003CD85B /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035AF2A01F0585FB003CD85B /* MainViewController.swift */; };
11 | 038FCAE91F058A2100755E96 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 038FCAE81F058A2100755E96 /* Main.storyboard */; };
12 | CE109E5D1F05A01400C4BF25 /* SanFranciscoDisplay-Semibold.otf in Resources */ = {isa = PBXBuildFile; fileRef = CE109E5C1F05A01400C4BF25 /* SanFranciscoDisplay-Semibold.otf */; };
13 | CE25F7D71E490FA00049CF23 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE25F7D61E490FA00049CF23 /* AppDelegate.swift */; };
14 | CE25F7DB1E490FA00049CF23 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CE25F7DA1E490FA00049CF23 /* Assets.xcassets */; };
15 | CE25F7EB1E4914340049CF23 /* calculate_cache_size.sh in Resources */ = {isa = PBXBuildFile; fileRef = CE25F7EA1E4914340049CF23 /* calculate_cache_size.sh */; };
16 | CE25F7ED1E49145A0049CF23 /* clear_cache.sh in Resources */ = {isa = PBXBuildFile; fileRef = CE25F7EC1E49145A0049CF23 /* clear_cache.sh */; };
17 | CE25F7F21E4915190049CF23 /* STPrivilegedTask.m in Sources */ = {isa = PBXBuildFile; fileRef = CE25F7F01E4915190049CF23 /* STPrivilegedTask.m */; };
18 | CE25F7F41E491BE30049CF23 /* stop_cache.sh in Resources */ = {isa = PBXBuildFile; fileRef = CE25F7F31E491BE30049CF23 /* stop_cache.sh */; };
19 | CEA190B11F02FE3B00C9F30A /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA190B01F02FE3B00C9F30A /* Environment.swift */; };
20 | FC4D46CD1FE92BE10012B681 /* NSFont+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC4D46CC1FE92BE10012B681 /* NSFont+Extensions.swift */; };
21 | FC4D46CF1FE92C770012B681 /* NSView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC4D46CE1FE92C770012B681 /* NSView+Extensions.swift */; };
22 | FC4D46D11FE92C940012B681 /* NSButton+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC4D46D01FE92C940012B681 /* NSButton+Extensions.swift */; };
23 | FC4D46D31FE92CBA0012B681 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC4D46D21FE92CBA0012B681 /* String+Extensions.swift */; };
24 | FC4D46D61FE92E7B0012B681 /* MainWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC4D46D51FE92E7B0012B681 /* MainWindow.swift */; };
25 | FC81FE04206A80CB00BA1282 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC81FE03206A80CB00BA1282 /* Colors.swift */; };
26 | FCB22D2C201FC4F40054F43E /* Share.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCB22D2B201FC4F40054F43E /* Share.swift */; };
27 | FCBCBF9D200385B3008CC9CA /* ButtonText.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCBCBF9C200385B3008CC9CA /* ButtonText.swift */; };
28 | /* End PBXBuildFile section */
29 |
30 | /* Begin PBXFileReference section */
31 | 035AF2A01F0585FB003CD85B /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MainViewController.swift; path = "Sketch Cache Cleaner/Controllers/MainViewController.swift"; sourceTree = SOURCE_ROOT; };
32 | 038FCAE81F058A2100755E96 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; };
33 | CE109E5C1F05A01400C4BF25 /* SanFranciscoDisplay-Semibold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SanFranciscoDisplay-Semibold.otf"; sourceTree = ""; };
34 | CE25F7D31E490FA00049CF23 /* Sketch Cache Cleaner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Sketch Cache Cleaner.app"; sourceTree = BUILT_PRODUCTS_DIR; };
35 | CE25F7D61E490FA00049CF23 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
36 | CE25F7DA1E490FA00049CF23 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
37 | CE25F7DF1E490FA00049CF23 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
38 | CE25F7EA1E4914340049CF23 /* calculate_cache_size.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = calculate_cache_size.sh; sourceTree = ""; };
39 | CE25F7EC1E49145A0049CF23 /* clear_cache.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = clear_cache.sh; sourceTree = ""; };
40 | CE25F7EF1E4915190049CF23 /* Sketch Cache Cleaner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Sketch Cache Cleaner-Bridging-Header.h"; sourceTree = ""; };
41 | CE25F7F01E4915190049CF23 /* STPrivilegedTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STPrivilegedTask.m; sourceTree = ""; };
42 | CE25F7F11E4915190049CF23 /* STPrivilegedTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STPrivilegedTask.h; sourceTree = ""; };
43 | CE25F7F31E491BE30049CF23 /* stop_cache.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = stop_cache.sh; sourceTree = ""; };
44 | CEA190B01F02FE3B00C9F30A /* Environment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Environment.swift; sourceTree = ""; };
45 | FC4D46CC1FE92BE10012B681 /* NSFont+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSFont+Extensions.swift"; sourceTree = ""; };
46 | FC4D46CE1FE92C770012B681 /* NSView+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSView+Extensions.swift"; sourceTree = ""; };
47 | FC4D46D01FE92C940012B681 /* NSButton+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSButton+Extensions.swift"; sourceTree = ""; };
48 | FC4D46D21FE92CBA0012B681 /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = ""; };
49 | FC4D46D51FE92E7B0012B681 /* MainWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainWindow.swift; sourceTree = ""; };
50 | FC81FE03206A80CB00BA1282 /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = ""; };
51 | FCB22D2B201FC4F40054F43E /* Share.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Share.swift; sourceTree = ""; };
52 | FCBCBF9C200385B3008CC9CA /* ButtonText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonText.swift; sourceTree = ""; };
53 | /* End PBXFileReference section */
54 |
55 | /* Begin PBXFrameworksBuildPhase section */
56 | CE25F7D01E490FA00049CF23 /* Frameworks */ = {
57 | isa = PBXFrameworksBuildPhase;
58 | buildActionMask = 2147483647;
59 | files = (
60 | );
61 | runOnlyForDeploymentPostprocessing = 0;
62 | };
63 | /* End PBXFrameworksBuildPhase section */
64 |
65 | /* Begin PBXGroup section */
66 | 038FCAEA1F058A5800755E96 /* Storyboards & Xibs */ = {
67 | isa = PBXGroup;
68 | children = (
69 | 038FCAE81F058A2100755E96 /* Main.storyboard */,
70 | );
71 | name = "Storyboards & Xibs";
72 | sourceTree = "";
73 | };
74 | CE25F7CA1E490FA00049CF23 = {
75 | isa = PBXGroup;
76 | children = (
77 | CE25F7D51E490FA00049CF23 /* Sketch Cache Cleaner */,
78 | CE25F7D41E490FA00049CF23 /* Products */,
79 | );
80 | sourceTree = "";
81 | };
82 | CE25F7D41E490FA00049CF23 /* Products */ = {
83 | isa = PBXGroup;
84 | children = (
85 | CE25F7D31E490FA00049CF23 /* Sketch Cache Cleaner.app */,
86 | );
87 | name = Products;
88 | sourceTree = "";
89 | };
90 | CE25F7D51E490FA00049CF23 /* Sketch Cache Cleaner */ = {
91 | isa = PBXGroup;
92 | children = (
93 | CE25F7DA1E490FA00049CF23 /* Assets.xcassets */,
94 | CEE6384A1F78279F00C908C5 /* Controllers */,
95 | CE91327A1EA50C1A007F1ADD /* Extensions */,
96 | CE25F7E91E4913EE0049CF23 /* Scripts */,
97 | 038FCAEA1F058A5800755E96 /* Storyboards & Xibs */,
98 | CE25F7EE1E4914930049CF23 /* Supporting Files */,
99 | CE25F7E71E490FDB0049CF23 /* Utils */,
100 | FC4D46D41FE92CE00012B681 /* Views */,
101 | );
102 | path = "Sketch Cache Cleaner";
103 | sourceTree = "";
104 | };
105 | CE25F7E71E490FDB0049CF23 /* Utils */ = {
106 | isa = PBXGroup;
107 | children = (
108 | FCBCBF9C200385B3008CC9CA /* ButtonText.swift */,
109 | FC81FE03206A80CB00BA1282 /* Colors.swift */,
110 | CEA190B01F02FE3B00C9F30A /* Environment.swift */,
111 | FCB22D2B201FC4F40054F43E /* Share.swift */,
112 | CE25F7EF1E4915190049CF23 /* Sketch Cache Cleaner-Bridging-Header.h */,
113 | CE25F7F11E4915190049CF23 /* STPrivilegedTask.h */,
114 | CE25F7F01E4915190049CF23 /* STPrivilegedTask.m */,
115 | );
116 | path = Utils;
117 | sourceTree = "";
118 | };
119 | CE25F7E91E4913EE0049CF23 /* Scripts */ = {
120 | isa = PBXGroup;
121 | children = (
122 | CE25F7EA1E4914340049CF23 /* calculate_cache_size.sh */,
123 | CE25F7EC1E49145A0049CF23 /* clear_cache.sh */,
124 | CE25F7F31E491BE30049CF23 /* stop_cache.sh */,
125 | );
126 | path = Scripts;
127 | sourceTree = "";
128 | };
129 | CE25F7EE1E4914930049CF23 /* Supporting Files */ = {
130 | isa = PBXGroup;
131 | children = (
132 | CE109E5C1F05A01400C4BF25 /* SanFranciscoDisplay-Semibold.otf */,
133 | CE25F7DF1E490FA00049CF23 /* Info.plist */,
134 | CE25F7D61E490FA00049CF23 /* AppDelegate.swift */,
135 | );
136 | name = "Supporting Files";
137 | sourceTree = "";
138 | };
139 | CE91327A1EA50C1A007F1ADD /* Extensions */ = {
140 | isa = PBXGroup;
141 | children = (
142 | FC4D46D01FE92C940012B681 /* NSButton+Extensions.swift */,
143 | FC4D46CE1FE92C770012B681 /* NSView+Extensions.swift */,
144 | FC4D46D21FE92CBA0012B681 /* String+Extensions.swift */,
145 | FC4D46CC1FE92BE10012B681 /* NSFont+Extensions.swift */,
146 | );
147 | path = Extensions;
148 | sourceTree = "";
149 | };
150 | CEE6384A1F78279F00C908C5 /* Controllers */ = {
151 | isa = PBXGroup;
152 | children = (
153 | 035AF2A01F0585FB003CD85B /* MainViewController.swift */,
154 | );
155 | path = Controllers;
156 | sourceTree = "";
157 | };
158 | FC4D46D41FE92CE00012B681 /* Views */ = {
159 | isa = PBXGroup;
160 | children = (
161 | FC4D46D51FE92E7B0012B681 /* MainWindow.swift */,
162 | );
163 | path = Views;
164 | sourceTree = "";
165 | };
166 | /* End PBXGroup section */
167 |
168 | /* Begin PBXNativeTarget section */
169 | CE25F7D21E490FA00049CF23 /* Sketch Cache Cleaner */ = {
170 | isa = PBXNativeTarget;
171 | buildConfigurationList = CE25F7E21E490FA00049CF23 /* Build configuration list for PBXNativeTarget "Sketch Cache Cleaner" */;
172 | buildPhases = (
173 | CE25F7CF1E490FA00049CF23 /* Sources */,
174 | CE25F7D01E490FA00049CF23 /* Frameworks */,
175 | CE25F7D11E490FA00049CF23 /* Resources */,
176 | FCB22D27201FC2570054F43E /* SwiftLint */,
177 | );
178 | buildRules = (
179 | );
180 | dependencies = (
181 | );
182 | name = "Sketch Cache Cleaner";
183 | packageProductDependencies = (
184 | );
185 | productName = "Sketch Cache Cleaner";
186 | productReference = CE25F7D31E490FA00049CF23 /* Sketch Cache Cleaner.app */;
187 | productType = "com.apple.product-type.application";
188 | };
189 | /* End PBXNativeTarget section */
190 |
191 | /* Begin PBXProject section */
192 | CE25F7CB1E490FA00049CF23 /* Project object */ = {
193 | isa = PBXProject;
194 | attributes = {
195 | LastSwiftUpdateCheck = 0820;
196 | LastUpgradeCheck = 1220;
197 | ORGANIZATIONNAME = "Sasha Prokhorenko";
198 | TargetAttributes = {
199 | CE25F7D21E490FA00049CF23 = {
200 | CreatedOnToolsVersion = 8.2.1;
201 | DevelopmentTeam = GW82A8W73Z;
202 | LastSwiftMigration = 1020;
203 | ProvisioningStyle = Automatic;
204 | };
205 | };
206 | };
207 | buildConfigurationList = CE25F7CE1E490FA00049CF23 /* Build configuration list for PBXProject "Sketch Cache Cleaner" */;
208 | compatibilityVersion = "Xcode 12.0";
209 | developmentRegion = en;
210 | hasScannedForEncodings = 0;
211 | knownRegions = (
212 | en,
213 | Base,
214 | );
215 | mainGroup = CE25F7CA1E490FA00049CF23;
216 | packageReferences = (
217 | );
218 | productRefGroup = CE25F7D41E490FA00049CF23 /* Products */;
219 | projectDirPath = "";
220 | projectRoot = "";
221 | targets = (
222 | CE25F7D21E490FA00049CF23 /* Sketch Cache Cleaner */,
223 | );
224 | };
225 | /* End PBXProject section */
226 |
227 | /* Begin PBXResourcesBuildPhase section */
228 | CE25F7D11E490FA00049CF23 /* Resources */ = {
229 | isa = PBXResourcesBuildPhase;
230 | buildActionMask = 2147483647;
231 | files = (
232 | CE109E5D1F05A01400C4BF25 /* SanFranciscoDisplay-Semibold.otf in Resources */,
233 | CE25F7DB1E490FA00049CF23 /* Assets.xcassets in Resources */,
234 | 038FCAE91F058A2100755E96 /* Main.storyboard in Resources */,
235 | CE25F7ED1E49145A0049CF23 /* clear_cache.sh in Resources */,
236 | CE25F7EB1E4914340049CF23 /* calculate_cache_size.sh in Resources */,
237 | CE25F7F41E491BE30049CF23 /* stop_cache.sh in Resources */,
238 | );
239 | runOnlyForDeploymentPostprocessing = 0;
240 | };
241 | /* End PBXResourcesBuildPhase section */
242 |
243 | /* Begin PBXShellScriptBuildPhase section */
244 | FCB22D27201FC2570054F43E /* SwiftLint */ = {
245 | isa = PBXShellScriptBuildPhase;
246 | buildActionMask = 2147483647;
247 | files = (
248 | );
249 | inputPaths = (
250 | );
251 | name = SwiftLint;
252 | outputPaths = (
253 | );
254 | runOnlyForDeploymentPostprocessing = 0;
255 | shellPath = /bin/sh;
256 | shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
257 | };
258 | /* End PBXShellScriptBuildPhase section */
259 |
260 | /* Begin PBXSourcesBuildPhase section */
261 | CE25F7CF1E490FA00049CF23 /* Sources */ = {
262 | isa = PBXSourcesBuildPhase;
263 | buildActionMask = 2147483647;
264 | files = (
265 | FC4D46D11FE92C940012B681 /* NSButton+Extensions.swift in Sources */,
266 | FC4D46D61FE92E7B0012B681 /* MainWindow.swift in Sources */,
267 | FCB22D2C201FC4F40054F43E /* Share.swift in Sources */,
268 | 035AF2A11F0585FB003CD85B /* MainViewController.swift in Sources */,
269 | CEA190B11F02FE3B00C9F30A /* Environment.swift in Sources */,
270 | FC4D46D31FE92CBA0012B681 /* String+Extensions.swift in Sources */,
271 | FC4D46CF1FE92C770012B681 /* NSView+Extensions.swift in Sources */,
272 | FCBCBF9D200385B3008CC9CA /* ButtonText.swift in Sources */,
273 | FC81FE04206A80CB00BA1282 /* Colors.swift in Sources */,
274 | FC4D46CD1FE92BE10012B681 /* NSFont+Extensions.swift in Sources */,
275 | CE25F7D71E490FA00049CF23 /* AppDelegate.swift in Sources */,
276 | CE25F7F21E4915190049CF23 /* STPrivilegedTask.m in Sources */,
277 | );
278 | runOnlyForDeploymentPostprocessing = 0;
279 | };
280 | /* End PBXSourcesBuildPhase section */
281 |
282 | /* Begin XCBuildConfiguration section */
283 | CE25F7E01E490FA00049CF23 /* Debug */ = {
284 | isa = XCBuildConfiguration;
285 | buildSettings = {
286 | ALWAYS_SEARCH_USER_PATHS = NO;
287 | CLANG_ANALYZER_NONNULL = YES;
288 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
289 | CLANG_CXX_LIBRARY = "libc++";
290 | CLANG_ENABLE_MODULES = YES;
291 | CLANG_ENABLE_OBJC_ARC = YES;
292 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
293 | CLANG_WARN_BOOL_CONVERSION = YES;
294 | CLANG_WARN_COMMA = YES;
295 | CLANG_WARN_CONSTANT_CONVERSION = YES;
296 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
297 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
298 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
299 | CLANG_WARN_EMPTY_BODY = YES;
300 | CLANG_WARN_ENUM_CONVERSION = YES;
301 | CLANG_WARN_INFINITE_RECURSION = YES;
302 | CLANG_WARN_INT_CONVERSION = YES;
303 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
304 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
305 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
306 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
307 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
308 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
309 | CLANG_WARN_STRICT_PROTOTYPES = YES;
310 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
311 | CLANG_WARN_UNREACHABLE_CODE = YES;
312 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
313 | CODE_SIGN_IDENTITY = "-";
314 | COPY_PHASE_STRIP = NO;
315 | DEBUG_INFORMATION_FORMAT = dwarf;
316 | ENABLE_STRICT_OBJC_MSGSEND = YES;
317 | ENABLE_TESTABILITY = YES;
318 | GCC_C_LANGUAGE_STANDARD = gnu99;
319 | GCC_DYNAMIC_NO_PIC = NO;
320 | GCC_NO_COMMON_BLOCKS = YES;
321 | GCC_OPTIMIZATION_LEVEL = 0;
322 | GCC_PREPROCESSOR_DEFINITIONS = (
323 | "DEBUG=1",
324 | "$(inherited)",
325 | );
326 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
327 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
328 | GCC_WARN_UNDECLARED_SELECTOR = YES;
329 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
330 | GCC_WARN_UNUSED_FUNCTION = YES;
331 | GCC_WARN_UNUSED_VARIABLE = YES;
332 | MACOSX_DEPLOYMENT_TARGET = 10.13;
333 | MTL_ENABLE_DEBUG_INFO = YES;
334 | ONLY_ACTIVE_ARCH = YES;
335 | SDKROOT = macosx;
336 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
337 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
338 | };
339 | name = Debug;
340 | };
341 | CE25F7E11E490FA00049CF23 /* Release */ = {
342 | isa = XCBuildConfiguration;
343 | buildSettings = {
344 | ALWAYS_SEARCH_USER_PATHS = NO;
345 | CLANG_ANALYZER_NONNULL = YES;
346 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
347 | CLANG_CXX_LIBRARY = "libc++";
348 | CLANG_ENABLE_MODULES = YES;
349 | CLANG_ENABLE_OBJC_ARC = YES;
350 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
351 | CLANG_WARN_BOOL_CONVERSION = YES;
352 | CLANG_WARN_COMMA = YES;
353 | CLANG_WARN_CONSTANT_CONVERSION = YES;
354 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
355 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
356 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
357 | CLANG_WARN_EMPTY_BODY = YES;
358 | CLANG_WARN_ENUM_CONVERSION = YES;
359 | CLANG_WARN_INFINITE_RECURSION = YES;
360 | CLANG_WARN_INT_CONVERSION = YES;
361 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
362 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
363 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
364 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
365 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
366 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
367 | CLANG_WARN_STRICT_PROTOTYPES = YES;
368 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
369 | CLANG_WARN_UNREACHABLE_CODE = YES;
370 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
371 | CODE_SIGN_IDENTITY = "-";
372 | COPY_PHASE_STRIP = NO;
373 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
374 | ENABLE_NS_ASSERTIONS = NO;
375 | ENABLE_STRICT_OBJC_MSGSEND = YES;
376 | GCC_C_LANGUAGE_STANDARD = gnu99;
377 | GCC_NO_COMMON_BLOCKS = YES;
378 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
379 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
380 | GCC_WARN_UNDECLARED_SELECTOR = YES;
381 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
382 | GCC_WARN_UNUSED_FUNCTION = YES;
383 | GCC_WARN_UNUSED_VARIABLE = YES;
384 | MACOSX_DEPLOYMENT_TARGET = 10.13;
385 | MTL_ENABLE_DEBUG_INFO = NO;
386 | SDKROOT = macosx;
387 | SWIFT_COMPILATION_MODE = wholemodule;
388 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
389 | };
390 | name = Release;
391 | };
392 | CE25F7E31E490FA00049CF23 /* Debug */ = {
393 | isa = XCBuildConfiguration;
394 | buildSettings = {
395 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
396 | CLANG_ENABLE_MODULES = YES;
397 | CLANG_ENABLE_OBJC_WEAK = YES;
398 | CODE_SIGN_IDENTITY = "Apple Development";
399 | COMBINE_HIDPI_IMAGES = YES;
400 | DEVELOPMENT_TEAM = GW82A8W73Z;
401 | ENABLE_HARDENED_RUNTIME = YES;
402 | INFOPLIST_FILE = "Sketch Cache Cleaner/Info.plist";
403 | LD_RUNPATH_SEARCH_PATHS = (
404 | "$(inherited)",
405 | "@executable_path/../Frameworks",
406 | );
407 | MACOSX_DEPLOYMENT_TARGET = 10.13;
408 | MARKETING_VERSION = 1.0.8b;
409 | PRODUCT_BUNDLE_IDENTIFIER = "me.minikin.Sketch-Cache-Cleaner";
410 | PRODUCT_NAME = "$(TARGET_NAME)";
411 | SWIFT_OBJC_BRIDGING_HEADER = "Sketch Cache Cleaner/Utils/Sketch Cache Cleaner-Bridging-Header.h";
412 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
413 | SWIFT_VERSION = 5.0;
414 | };
415 | name = Debug;
416 | };
417 | CE25F7E41E490FA00049CF23 /* Release */ = {
418 | isa = XCBuildConfiguration;
419 | buildSettings = {
420 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
421 | CLANG_ENABLE_MODULES = YES;
422 | CLANG_ENABLE_OBJC_WEAK = YES;
423 | CODE_SIGN_IDENTITY = "Apple Development";
424 | COMBINE_HIDPI_IMAGES = YES;
425 | DEVELOPMENT_TEAM = GW82A8W73Z;
426 | ENABLE_HARDENED_RUNTIME = YES;
427 | INFOPLIST_FILE = "Sketch Cache Cleaner/Info.plist";
428 | LD_RUNPATH_SEARCH_PATHS = (
429 | "$(inherited)",
430 | "@executable_path/../Frameworks",
431 | );
432 | MACOSX_DEPLOYMENT_TARGET = 10.13;
433 | MARKETING_VERSION = 1.0.8b;
434 | PRODUCT_BUNDLE_IDENTIFIER = "me.minikin.Sketch-Cache-Cleaner";
435 | PRODUCT_NAME = "$(TARGET_NAME)";
436 | SWIFT_OBJC_BRIDGING_HEADER = "Sketch Cache Cleaner/Utils/Sketch Cache Cleaner-Bridging-Header.h";
437 | SWIFT_VERSION = 5.0;
438 | };
439 | name = Release;
440 | };
441 | /* End XCBuildConfiguration section */
442 |
443 | /* Begin XCConfigurationList section */
444 | CE25F7CE1E490FA00049CF23 /* Build configuration list for PBXProject "Sketch Cache Cleaner" */ = {
445 | isa = XCConfigurationList;
446 | buildConfigurations = (
447 | CE25F7E01E490FA00049CF23 /* Debug */,
448 | CE25F7E11E490FA00049CF23 /* Release */,
449 | );
450 | defaultConfigurationIsVisible = 0;
451 | defaultConfigurationName = Release;
452 | };
453 | CE25F7E21E490FA00049CF23 /* Build configuration list for PBXNativeTarget "Sketch Cache Cleaner" */ = {
454 | isa = XCConfigurationList;
455 | buildConfigurations = (
456 | CE25F7E31E490FA00049CF23 /* Debug */,
457 | CE25F7E41E490FA00049CF23 /* Release */,
458 | );
459 | defaultConfigurationIsVisible = 0;
460 | defaultConfigurationName = Release;
461 | };
462 | /* End XCConfigurationList section */
463 | };
464 | rootObject = CE25F7CB1E490FA00049CF23 /* Project object */;
465 | }
466 |
--------------------------------------------------------------------------------
/Sketch Cache Cleaner/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 | YnBsaXN0MDDUAQIDBAUGTE1YJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3ASAAGGoK8QEQcI
272 | ERYbHCgpKi41Njs+QUZJVSRudWxs1AkKCwwNDg8QViRjbGFzc1xOU0ltYWdlRmxhZ3NWTlNSZXBzV05T
273 | Q29sb3KAEBIAwAAAgAKADtISCRMVWk5TLm9iamVjdHOhFIADgA3SEgkXGqIYGYAEgAWADBAA1x0JHh8g
274 | ISIjJCUmGxsnVk5TU2l6ZVlOU1BERkRhdGFfEBBOU0NvbG9yU3BhY2VOYW1lXxAZTlNJbnRlcm5hbExh
275 | eW91dERpcmVjdGlvbl8QD05TQml0c1BlclNhbXBsZVxOU0NvbG9yU3BhY2WABoALgAqAB4AIWXsxOTIs
276 | IDE2fV8QGU5TQ2FsaWJyYXRlZFJHQkNvbG9yU3BhY2XSKwksLVROU0lEEAGACdIvMDEyWiRjbGFzc25h
277 | bWVYJGNsYXNzZXNcTlNDb2xvclNwYWNlojM0XE5TQ29sb3JTcGFjZVhOU09iamVjdE8RPmMlUERGLTEu
278 | MwolxOXy5eun86DQxMYKNCAwIG9iago8PCAvTGVuZ3RoIDUgMCBSIC9GaWx0ZXIgL0ZsYXRlRGVjb2Rl
279 | ID4+CnN0cmVhbQp4AY1SwU7DMAy95ysetw6pWeykaXtl4sINUWlCiMMUNm2iBW2D/8fu0k2AkFDTuo6f
280 | X/Js73GPPcoqoOQa3jkEeQ9rLPGG+eJISEfQ+BwTnI3YCZ7g5CkJHEARacBNZ0pnXRvRJVDIcbHWO+LY
281 | ViCPbsC8S8rWbfCE4vF9hjI6FJ/ZHtSSKZD9h2xfxVaEYp39D/VbFCn722ynvEX2VzMjfL9xE8+E3yle
282 | cMcfPBN/P8bN+fxVxut99R4T30vOv5rhGd0dbjsprxa4AWMAkfXkaymbkRIFG5vILWu5GoxVOwMuPxoT
283 | QPoGl5wLlebyJXym5fHUhC2W19LMP3p8aql0mqXT5tzp0kMWsy6Zhk1WIc0e4GUK5MeB2Gqn9QJu3NWI
284 | +g7J5KAAM37UKJmadPpE1SbjI1esVUDmbtCjQiuwXvZrG0wvelWy7pxS3RjTnF4F/lOfjGNoA1WuMs42
285 | HNkHGWVL3DZ17SETXla6OOo66f4CldKfmQplbmRzdHJlYW0KZW5kb2JqCjUgMCBvYmoKMzc0CmVuZG9i
286 | agoyIDAgb2JqCjw8IC9UeXBlIC9QYWdlIC9QYXJlbnQgMyAwIFIgL1Jlc291cmNlcyA2IDAgUiAvQ29u
287 | dGVudHMgNCAwIFIgL01lZGlhQm94IFswIDAgMTkyIDE2XQo+PgplbmRvYmoKNiAwIG9iago8PCAvUHJv
288 | Y1NldCBbIC9QREYgL1RleHQgXSAvQ29sb3JTcGFjZSA8PCAvQ3MxIDcgMCBSIC9DczIgOSAwIFIgPj4g
289 | L0ZvbnQgPDwKL1RjMSA4IDAgUiA+PiA+PgplbmRvYmoKMTAgMCBvYmoKPDwgL0xlbmd0aCAxMSAwIFIg
290 | L04gMyAvQWx0ZXJuYXRlIC9EZXZpY2VSR0IgL0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4Kc3RyZWFtCngB
291 | hVVbiBtVGP6TOckKu87T2tUtpEO9dCm7S7YV3aW0mluTtGsastnVFkGzk5NkzOwkzkzSC30qguKLq75J
292 | Qby9LQiC0nrB1gf7UqlQVnfrIig+tHhBKPRFt/E7k2QmWWqbZc988/3f+W/nnxmigbVCva77FaIlwzZz
293 | yajy3NFjysA6+ekhGqRRGiyoVj2Szc4SfkIrrv2/Wz+QTzBXJ+5s71dvuRsscksl8t0Hvla01CXgE0SB
294 | s2rdtIkGhsFPH7frAoschk0kCPyiwOU2ho2GF9v4NUeTz8WgOQssq5VCEXgFeHyxhy/34HYOUMBPkhvc
295 | 1FRF9CJr1kqazh1De7mHuUd5N7ikN1Cz89uBdciqzh3GdQy1v1IsxAWeBF5RC4k54EeArzW1hUwH367b
296 | 0RzwY0T+nY3qfAR4N3CqZB6cB4Yfv1lppLr4nVOV/LPgt4H/xljMHOnsXVOtGHpJO8HfrvC06G+ISFI0
297 | O50Hhh/pgFnLCT1ykEpFHk8AjwO/Xq0dFjnAp/SZ1ZwTvMhn7VQlJvIU/OWXCoeywKPAv3I9KfSIJf1b
298 | t7OdHFjI0DMiLmKxOLeceuGHhexKPgUecZlum/nOXrZc0g6mO/pPKmZK8GLvtbruzChyC/jNRk7UjliB
299 | yYKZSALDZyDLjXnRT4GbtOArEKcaLWJVyaBNUihHSYriWicTlhJppIPhsHIwHHddzYSzz6IqeI2ajs3C
300 | mnWU7Z1drUJlsAZdd7QqxUIfUQOeKvQH2IrrU6EY7hrgyv/jp53LjY6fGhthYbYX//vYLNvPptkMKewp
301 | 9jQ7wOJgZ9g+13cWe7oViXxuIErbz8uIyB3dAmq/iBptKmD9BYoaWa6Hvq4sjzbGPMsZ8wVNvfLG3z29
302 | 0rCz6iom+jp65F49D/wWuB5Yxboe2HB9KIGfAhv4W0dvvFpqnr3TZXFSGk601qfbehZdVQSV6s7OJXRB
303 | Q828p+aJXh+XTn/5oBdtlZ17/urQpdMlY3nUY0UX+KuZWxk6M+6x4R/Df4ZXw++FPwz/Lr0tfSp9JZ2X
304 | PpcukyJdkC5KX0vfSh9LX7j6u82Qe/YkMhdzJfIW09WtsLfXmFg5Km+XH5bj8g75UXnWVSnyiDwlp+Rd
305 | sGx3z82bb6W3cvTlKKJ1+3PnWOJZ0VxPOAPf/ZgAzYvYNwPzyFij4/Bpot9i3gw6CW3vk9epiIXYFEtv
306 | me5pMfNd38FEMB6MkBLcHZwJTgUPCdx9loO7YJvBmujNDfPhKvoq5TY/Ib4nFKvVT5pauWIre8LhJ5UI
307 | Pn1cSRvq5LhS0HXFMVmKyS1uNnlxksR3U+wjuplzvoe+bVc8zn6GaP9fePd973HHGkQrFtHI4x43hnfl
308 | A+8SnXtCbZjNtj/y+b4jskp79zj3vqEo3l8/t1o38R4beIto881W65/3W63ND+B/g+iC/h+gn3xVCmVu
309 | ZHN0cmVhbQplbmRvYmoKMTEgMCBvYmoKMTA3OQplbmRvYmoKNyAwIG9iagpbIC9JQ0NCYXNlZCAxMCAw
310 | IFIgXQplbmRvYmoKMTIgMCBvYmoKPDwgL0xlbmd0aCAxMyAwIFIgL04gMyAvQWx0ZXJuYXRlIC9EZXZp
311 | Y2VSR0IgL0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4Kc3RyZWFtCngBnZZ3VFPZFofPvTe90BIiICX0GnoJ
312 | INI7SBUEUYlJgFAChoQmdkQFRhQRKVZkVMABR4ciY0UUC4OCYtcJ8hBQxsFRREXl3YxrCe+tNfPemv3H
313 | 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
355 | Jm1m5t/3hPP7CmVuZHN0cmVhbQplbmRvYmoKMTMgMCBvYmoKMjYxMgplbmRvYmoKOSAwIG9iagpbIC9J
356 | Q0NCYXNlZCAxMiAwIFIgXQplbmRvYmoKMyAwIG9iago8PCAvVHlwZSAvUGFnZXMgL01lZGlhQm94IFsw
357 | IDAgMTkyIDE2XSAvQ291bnQgMSAvS2lkcyBbIDIgMCBSIF0gPj4KZW5kb2JqCjE0IDAgb2JqCjw8IC9U
358 | eXBlIC9DYXRhbG9nIC9QYWdlcyAzIDAgUiA+PgplbmRvYmoKOCAwIG9iago8PCAvVHlwZSAvRm9udCAv
359 | U3VidHlwZSAvVHlwZTEgL0Jhc2VGb250IC9CWlZNQk4rU2FuRnJhbmNpc2NvRGlzcGxheS1TZW1pYm9s
360 | ZAovRm9udERlc2NyaXB0b3IgMTUgMCBSIC9FbmNvZGluZyAvTWFjUm9tYW5FbmNvZGluZyAvRmlyc3RD
361 | aGFyIDMyIC9MYXN0Q2hhcgoxMTcgL1dpZHRocyBbIDE5OCAyNjYgMCAwIDAgMCAwIDAgMCAwIDAgMCAw
362 | IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwCjAgMCAwIDAgMCAwIDAgNjIwIDAgMCAwIDAgMCAw
363 | IDAgMCAwIDAgMCAwIDAgMCAwIDU4MiAwIDAgMCAwIDAgNTUzIDAgMCAwIDAKMCAwIDAgNTI4IDAgNTIw
364 | IDU4MyA1MzkgMCAwIDU3OCAyNTkgMCA1MTEgMjU2IDAgMCA1NTcgMCAwIDM2NCA0OTkgMzYxIDU3NApd
365 | ID4+CmVuZG9iagoxNSAwIG9iago8PCAvVHlwZSAvRm9udERlc2NyaXB0b3IgL0ZvbnROYW1lIC9CWlZN
366 | Qk4rU2FuRnJhbmNpc2NvRGlzcGxheS1TZW1pYm9sZCAvRmxhZ3MKMzIgL0ZvbnRCQm94IFstMjM4IC0y
367 | NTIgMTAzNiA5NTBdIC9JdGFsaWNBbmdsZSAwIC9Bc2NlbnQgOTUyIC9EZXNjZW50IC0yNDEKL0NhcEhl
368 | aWdodCA2ODAgL1N0ZW1WIDExNyAvWEhlaWdodCA1MjYgL1N0ZW1IIDk3IC9BdmdXaWR0aCA1MDEgL01h
369 | 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
523 | SI48j3e6QyJbyNvdIYNBPl+Tizc0LWwHWVSmQUywidPovChmErTMMJcWf67qjYkkKX9EQFiphfsskFqT
524 | RWWG5OvjIJheHaAjIfG6GEcvmgNh0g50FQxxVFiHU2uqOBQLs8PHjXpv3mQJO/AzVx6c+aWVdtn3Z5hN
525 | 2fUGG4ZGtibKRYoUfKfZBAw8ZDvyJ+xzqOQUFT0Qkm9HJs9uW6A1oarf0ZUHrvjbNenoKSTiBTkukD+i
526 | qYdqZlz00oyVg76vL+uTVYuWjwyUrlYZ2tBj64lyDhQsSl3IUesqUZinRqlBmKMEqXE0Y/EGHSSzVMKj
527 | j3aQcq6BT7mNZDacIUCA3eqreNAKvMpGQigb0ctqe4FwObFBwkvnADMEpUKpgFy1QolQXkCB8z65DJ5S
528 | rGXBBmGuhHu1Nc7ALX44jzBKO5gg7DCI1dXfXk2sFmKqE69+W26IiU5MpMLKaLq6erL66rdJ1dF0J0bL
529 | 3CdDBL9L0+EoBITSzKCIe0TTJg1vMUf31qnDGLTi1inDmFBqiBaoa5L2qKKXIzqGx+WEF2nmO2rGYjf7
530 | enTQnpYYhOwFr6otqK7plEWQsTmXMWtiRmdrwSABmkrbIa4VGTr60xe/hMcq/TBx/jNNN6VQHoJRklhj
531 | ZZiv2Hlxv0HEAbz4XyZPVB0KZW5kc3RyZWFtCmVuZG9iagoxNyAwIG9iago5NjIyCmVuZG9iagoxOCAw
532 | IG9iagooTWFjIE9TIFggMTAuMTIuNCBRdWFydHogUERGQ29udGV4dCkKZW5kb2JqCjE5IDAgb2JqCihE
533 | OjIwMTcwNTAxMTMyMTM4WjAwJzAwJykKZW5kb2JqCjEgMCBvYmoKPDwgL1Byb2R1Y2VyIDE4IDAgUiAv
534 | Q3JlYXRpb25EYXRlIDE5IDAgUiAvTW9kRGF0ZSAxOSAwIFIgPj4KZW5kb2JqCnhyZWYKMCAyMAowMDAw
535 | MDAwMDAwIDY1NTM1IGYgCjAwMDAwMTUzMzggMDAwMDAgbiAKMDAwMDAwMDQ4OSAwMDAwMCBuIAowMDAw
536 | MDA0NzExIDAwMDAwIG4gCjAwMDAwMDAwMjIgMDAwMDAgbiAKMDAwMDAwMDQ3MCAwMDAwMCBuIAowMDAw
537 | MDAwNTkyIDAwMDAwIG4gCjAwMDAwMDE5MDMgMDAwMDAgbiAKMDAwMDAwNDg0MyAwMDAwMCBuIAowMDAw
538 | MDA0Njc1IDAwMDAwIG4gCjAwMDAwMDA3MDAgMDAwMDAgbiAKMDAwMDAwMTg4MiAwMDAwMCBuIAowMDAw
539 | MDAxOTM5IDAwMDAwIG4gCjAwMDAwMDQ2NTQgMDAwMDAgbiAKMDAwMDAwNDc5MyAwMDAwMCBuIAowMDAw
540 | MDA1MjM4IDAwMDAwIG4gCjAwMDAwMDU1MDcgMDAwMDAgbiAKMDAwMDAxNTIyMiAwMDAwMCBuIAowMDAw
541 | MDE1MjQzIDAwMDAwIG4gCjAwMDAwMTUyOTYgMDAwMDAgbiAKdHJhaWxlcgo8PCAvU2l6ZSAyMCAvUm9v
542 | dCAxNCAwIFIgL0luZm8gMSAwIFIgL0lEIFsgPDE1ZmJhOGYyNzkzZTUxMGRlYjhmZjljNGM1YjkyY2Zl
543 | Pgo8MTVmYmE4ZjI3OTNlNTEwZGViOGZmOWM0YzViOTJjZmU+IF0gPj4Kc3RhcnR4cmVmCjE1NDEzCiUl
544 | RU9GCtIvMDc4XU5TUERGSW1hZ2VSZXCjOTo0XU5TUERGSW1hZ2VSZXBaTlNJbWFnZVJlcNIvMDw9V05T
545 | QXJyYXmiPDTSLzA/QF5OU011dGFibGVBcnJheaM/PDTTQiIJQ0RFV05TV2hpdGVEMCAwABADgA/SLzBH
546 | SFdOU0NvbG9yokc00i8wSktXTlNJbWFnZaJKNF8QD05TS2V5ZWRBcmNoaXZlctFOT1Ryb290gAEACAAR
547 | ABoAIwAtADIANwBLAFEAWgBhAG4AdQB9AH8AhACGAIgAjQCYAJoAnACeAKMApgCoAKoArACuAL0AxADO
548 | AOEA/QEPARwBHgEgASIBJAEmATABTAFRAVYBWAFaAV8BagFzAYABgwGQAZlAAEAFQBNAF0AlQDBANUA9
549 | QEBARUBUQFhAX0BnQGxAbkBwQHVAfUCAQIVAjUCQQKJApUCqAAAAAAAAAgEAAAAAAAAAUAAAAAAAAAAA
550 | AAAAAAAAQKw
551 |
552 |
553 |
554 |
555 |
556 |
557 |
--------------------------------------------------------------------------------