]>
Commit | Line | Data |
---|---|---|
ec4c25d4 JF |
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 | ||
412e960a | 22 | #include <pthread.h> |
ec4c25d4 JF |
23 | #include <objc/runtime.h> |
24 | #include <Foundation/Foundation.h> | |
25 | ||
412e960a JF |
26 | @class LSDXPCServer; |
27 | ||
ec4c25d4 JF |
28 | @interface MIFileManager |
29 | + (MIFileManager *) defaultManager; | |
30 | - (NSURL *) destinationOfSymbolicLinkAtURL:(NSURL *)url error:(NSError *)error; | |
31 | @end | |
32 | ||
33 | static Class $MIFileManager; | |
34 | ||
412e960a JF |
35 | static pthread_key_t key_; |
36 | ||
ec4c25d4 JF |
37 | static NSArray *(*_MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$)(MIFileManager *self, SEL _cmd, NSURL *url, BOOL ignoring, NSError *error); |
38 | ||
39 | static NSArray *$MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$(MIFileManager *self, SEL _cmd, NSURL *url, BOOL ignoring, NSError *error) { | |
40 | MIFileManager *manager(reinterpret_cast<MIFileManager *>([$MIFileManager defaultManager])); | |
41 | NSURL *destiny([manager destinationOfSymbolicLinkAtURL:url error:NULL]); | |
42 | if (destiny == nil) | |
f44e675d | 43 | return _MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$(self, _cmd, url, NO, error); |
ec4c25d4 JF |
44 | |
45 | NSArray *prefix([url pathComponents]); | |
46 | size_t skip([[destiny pathComponents] count]); | |
47 | NSMutableArray *items([NSMutableArray array]); | |
f44e675d | 48 | for (NSURL *item in _MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$(self, _cmd, destiny, NO, error)) { |
ec4c25d4 JF |
49 | NSArray *components([item pathComponents]); |
50 | [items addObject:[NSURL fileURLWithPathComponents:[prefix arrayByAddingObjectsFromArray:[components subarrayWithRange:NSMakeRange(skip, [components count] - skip)]]]]; | |
51 | } | |
52 | ||
53 | return items; | |
54 | } | |
55 | ||
c3315f13 JF |
56 | static NSString *(*_NSURL$path)(NSURL *self, SEL _cmd); |
57 | ||
58 | static NSString *$NSURL$path(NSURL *self, SEL _cmd) { | |
412e960a JF |
59 | NSString *path(_NSURL$path(self, _cmd)); |
60 | if (pthread_getspecific(key_) != NULL) | |
61 | path = [[path mutableCopy] autorelease]; | |
62 | return path; | |
c3315f13 JF |
63 | } |
64 | ||
65 | static NSRange (*_NSString$rangeOfString$options$)(NSString *self, SEL _cmd, NSString *value, NSStringCompareOptions options); | |
66 | ||
67 | static NSRange $NSString$rangeOfString$options$(NSString *self, SEL _cmd, NSString *value, NSStringCompareOptions options) { | |
412e960a JF |
68 | do { |
69 | if (pthread_getspecific(key_) == NULL) | |
70 | break; | |
71 | if (![value isEqualToString:@".app/"]) | |
72 | break; | |
73 | ||
c3315f13 JF |
74 | char *real(realpath("/Applications", NULL)); |
75 | NSString *destiny([NSString stringWithUTF8String:real]); | |
76 | free(real); | |
77 | ||
78 | if ([destiny isEqualToString:@"/Applications"]) | |
79 | break; | |
80 | ||
81 | destiny = [destiny stringByAppendingString:@"/"]; | |
82 | if (![self hasPrefix:destiny]) | |
83 | break; | |
84 | ||
c3315f13 JF |
85 | BOOL directory; |
86 | if (![[NSFileManager defaultManager] fileExistsAtPath:self isDirectory:&directory]) | |
87 | break; | |
88 | if (!directory) | |
89 | break; | |
90 | ||
c3315f13 JF |
91 | // the trailing / allows lsd to "restart" its verification attempt |
92 | [(NSMutableString *) self setString:[NSString stringWithFormat:@"/Applications/%@/", [self substringFromIndex:[destiny length]]]]; | |
93 | } while (false); | |
94 | ||
95 | return _NSString$rangeOfString$options$(self, _cmd, value, options); | |
96 | } | |
97 | ||
412e960a JF |
98 | static id (*_LSDXPCServer$canOpenURL$connection$)(LSDXPCServer *self, SEL _cmd, id url, id connection); |
99 | ||
100 | static id $LSDXPCServer$canOpenURL$connection$(LSDXPCServer *self, SEL _cmd, id url, id connection) { | |
101 | pthread_setspecific(key_, connection); | |
102 | @try { | |
103 | return _LSDXPCServer$canOpenURL$connection$(self, _cmd, url, connection); | |
104 | } @finally { | |
105 | pthread_setspecific(key_, NULL); | |
106 | } | |
107 | } | |
108 | ||
ec4c25d4 JF |
109 | __attribute__((__constructor__)) |
110 | static void initialize() { | |
412e960a JF |
111 | pthread_key_create(&key_, NULL); |
112 | ||
ec4c25d4 | 113 | $MIFileManager = objc_getClass("MIFileManager"); |
c3315f13 JF |
114 | |
115 | if ($MIFileManager != Nil) { | |
116 | SEL sel(@selector(urlsForItemsInDirectoryAtURL:ignoringSymlinks:error:)); | |
117 | if (Method method = class_getInstanceMethod($MIFileManager, sel)) { | |
118 | _MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$ = reinterpret_cast<NSArray *(*)(MIFileManager *, SEL, NSURL *, BOOL, NSError *)>(method_getImplementation(method)); | |
119 | method_setImplementation(method, reinterpret_cast<IMP>(&$MIFileManager$urlsForItemsInDirectoryAtURL$ignoringSymlinks$error$)); | |
120 | } | |
121 | } | |
122 | ||
123 | if (Class $NSURL = objc_getClass("NSURL")) { | |
124 | SEL sel(@selector(path)); | |
125 | if (Method method = class_getInstanceMethod($NSURL, sel)) { | |
126 | _NSURL$path = reinterpret_cast<NSString *(*)(NSURL *, SEL)>(method_getImplementation(method)); | |
127 | method_setImplementation(method, reinterpret_cast<IMP>(&$NSURL$path)); | |
128 | } | |
129 | } | |
130 | ||
131 | if (Class $NSString = objc_getClass("NSString")) { | |
132 | SEL sel(@selector(rangeOfString:options:)); | |
133 | if (Method method = class_getInstanceMethod($NSString, sel)) { | |
134 | _NSString$rangeOfString$options$ = reinterpret_cast<NSRange (*)(NSString *, SEL, NSString *, NSStringCompareOptions)>(method_getImplementation(method)); | |
135 | method_setImplementation(method, reinterpret_cast<IMP>(&$NSString$rangeOfString$options$)); | |
136 | } | |
137 | } | |
412e960a JF |
138 | |
139 | if (Class $LSDXPCServer = objc_getClass("LSDXPCServer")) { | |
140 | SEL sel(@selector(canOpenURL:connection:)); | |
141 | if (Method method = class_getInstanceMethod($LSDXPCServer, sel)) { | |
142 | _LSDXPCServer$canOpenURL$connection$ = reinterpret_cast<id (*)(LSDXPCServer *, SEL, id, id)>(method_getImplementation(method)); | |
143 | method_setImplementation(method, reinterpret_cast<IMP>(&$LSDXPCServer$canOpenURL$connection$)); | |
144 | } | |
145 | } | |
ec4c25d4 | 146 | } |