]>
Commit | Line | Data |
---|---|---|
1 | /* patcyh - you should pronounce it like patch | |
2 | * Copyright (C) 2015 Jay Freeman (saurik) | |
3 | */ | |
4 | ||
5 | /* GNU General Public License, Version 3 {{{ */ | |
6 | /* | |
7 | * Cydia is free software: you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published | |
9 | * by the Free Software Foundation, either version 3 of the License, | |
10 | * or (at your option) any later version. | |
11 | * | |
12 | * Cydia is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with Cydia. If not, see <http://www.gnu.org/licenses/>. | |
19 | **/ | |
20 | /* }}} */ | |
21 | ||
22 | #include <objc/runtime.h> | |
23 | #include <Foundation/Foundation.h> | |
24 | ||
25 | @interface MIFileManager | |
26 | + (MIFileManager *) defaultManager; | |
27 | - (NSURL *) destinationOfSymbolicLinkAtURL:(NSURL *)url error:(NSError *)error; | |
28 | @end | |
29 | ||
30 | static Class $MIFileManager; | |
31 | ||
32 | static NSArray *(*_MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$)(MIFileManager *self, SEL _cmd, NSURL *url, BOOL ignoring, NSError *error); | |
33 | ||
34 | static NSArray *$MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$(MIFileManager *self, SEL _cmd, NSURL *url, BOOL ignoring, NSError *error) { | |
35 | MIFileManager *manager(reinterpret_cast<MIFileManager *>([$MIFileManager defaultManager])); | |
36 | NSURL *destiny([manager destinationOfSymbolicLinkAtURL:url error:NULL]); | |
37 | if (destiny == nil) | |
38 | return _MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$(self, _cmd, url, NO, error); | |
39 | ||
40 | NSArray *prefix([url pathComponents]); | |
41 | size_t skip([[destiny pathComponents] count]); | |
42 | NSMutableArray *items([NSMutableArray array]); | |
43 | for (NSURL *item in _MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$(self, _cmd, destiny, NO, error)) { | |
44 | NSArray *components([item pathComponents]); | |
45 | [items addObject:[NSURL fileURLWithPathComponents:[prefix arrayByAddingObjectsFromArray:[components subarrayWithRange:NSMakeRange(skip, [components count] - skip)]]]]; | |
46 | } | |
47 | ||
48 | NSLog(@"items = %@", items); | |
49 | return items; | |
50 | } | |
51 | ||
52 | static NSString *(*_NSURL$path)(NSURL *self, SEL _cmd); | |
53 | ||
54 | static NSString *$NSURL$path(NSURL *self, SEL _cmd) { | |
55 | return [[_NSURL$path(self, _cmd) mutableCopy] autorelease]; | |
56 | } | |
57 | ||
58 | static NSRange (*_NSString$rangeOfString$options$)(NSString *self, SEL _cmd, NSString *value, NSStringCompareOptions options); | |
59 | ||
60 | static NSRange $NSString$rangeOfString$options$(NSString *self, SEL _cmd, NSString *value, NSStringCompareOptions options) { | |
61 | if ([value isEqualToString:@".app/"]) do { | |
62 | char *real(realpath("/Applications", NULL)); | |
63 | NSString *destiny([NSString stringWithUTF8String:real]); | |
64 | free(real); | |
65 | ||
66 | if ([destiny isEqualToString:@"/Applications"]) | |
67 | break; | |
68 | ||
69 | destiny = [destiny stringByAppendingString:@"/"]; | |
70 | if (![self hasPrefix:destiny]) | |
71 | break; | |
72 | ||
73 | if (![self hasSuffix:@".app"]) | |
74 | break; | |
75 | ||
76 | BOOL directory; | |
77 | if (![[NSFileManager defaultManager] fileExistsAtPath:self isDirectory:&directory]) | |
78 | break; | |
79 | if (!directory) | |
80 | break; | |
81 | ||
82 | NSLog(@"path = %@", self); | |
83 | // the trailing / allows lsd to "restart" its verification attempt | |
84 | [(NSMutableString *) self setString:[NSString stringWithFormat:@"/Applications/%@/", [self substringFromIndex:[destiny length]]]]; | |
85 | } while (false); | |
86 | ||
87 | return _NSString$rangeOfString$options$(self, _cmd, value, options); | |
88 | } | |
89 | ||
90 | __attribute__((__constructor__)) | |
91 | static void initialize() { | |
92 | $MIFileManager = objc_getClass("MIFileManager"); | |
93 | ||
94 | if ($MIFileManager != Nil) { | |
95 | SEL sel(@selector(urlsForItemsInDirectoryAtURL:ignoringSymlinks:error:)); | |
96 | if (Method method = class_getInstanceMethod($MIFileManager, sel)) { | |
97 | _MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$ = reinterpret_cast<NSArray *(*)(MIFileManager *, SEL, NSURL *, BOOL, NSError *)>(method_getImplementation(method)); | |
98 | method_setImplementation(method, reinterpret_cast<IMP>(&$MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$)); | |
99 | } | |
100 | } | |
101 | ||
102 | if (Class $NSURL = objc_getClass("NSURL")) { | |
103 | SEL sel(@selector(path)); | |
104 | if (Method method = class_getInstanceMethod($NSURL, sel)) { | |
105 | _NSURL$path = reinterpret_cast<NSString *(*)(NSURL *, SEL)>(method_getImplementation(method)); | |
106 | method_setImplementation(method, reinterpret_cast<IMP>(&$NSURL$path)); | |
107 | } | |
108 | } | |
109 | ||
110 | if (Class $NSString = objc_getClass("NSString")) { | |
111 | SEL sel(@selector(rangeOfString:options:)); | |
112 | if (Method method = class_getInstanceMethod($NSString, sel)) { | |
113 | _NSString$rangeOfString$options$ = reinterpret_cast<NSRange (*)(NSString *, SEL, NSString *, NSStringCompareOptions)>(method_getImplementation(method)); | |
114 | method_setImplementation(method, reinterpret_cast<IMP>(&$NSString$rangeOfString$options$)); | |
115 | } | |
116 | } | |
117 | } |