forked from jerrykrinock/ClassesObjC
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSSYBrowserPaths.m
151 lines (124 loc) · 5.13 KB
/
SSYBrowserPaths.m
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
#import "SSYBrowserPaths.h"
#import "NSString+MorePaths.h"
#import "NSString+Base64.h"
#import "NSData+FileAlias.h"
#import "SSYSuperFileManager.h"
#import "NSFileManager+TempFile.h"
#import "SSYAuthorizedTaskmaster+CopyPaths.h"
#import "NSObject+MoreDescriptions.h"
NSString* const SSYBrowserPathsErrorDomain = @"SSYBrowserPathsErrorDomain" ;
NSString* BrowserSupportPath(NSString* appSupportRelativePath, NSString* homePath) {
return [[NSString applicationSupportPathForHomePath:homePath] stringByAppendingPathComponent:appSupportRelativePath] ;
}
NSString* ProfilesIniPath(NSString* appSupportRelativePath, NSString* homePath) {
return [BrowserSupportPath(appSupportRelativePath, homePath)
stringByAppendingPathComponent:@"profiles.ini"] ;
}
@implementation SSYBrowserPaths
+ (NSArray*)profileNamesForAppSupportRelativePath:(NSString*)appSupportRelativePath
homePath:(NSString*)homePath {
NSString* filepathProfilesIni = ProfilesIniPath(appSupportRelativePath, homePath) ;
NSString* strungFile = [[[NSString alloc] initWithContentsOfFile:filepathProfilesIni] autorelease] ;
NSArray* names = nil ;
if (strungFile) {
// There is a profiles.ini file. Parse it.
// (Browser is Firefox)
NSScanner* scanner = nil ;
NSMutableArray* outbasket = [[NSMutableArray alloc] init] ;
NSString* name ;
if(strungFile) {
scanner = [[NSScanner alloc] initWithString:strungFile] ;
while((![scanner isAtEnd])) {
[scanner scanUpToString:@"Name=" intoString:NULL] ;
if ([scanner scanString:@"Name=" intoString:NULL]) {
[scanner scanUpToString:@"\n" intoString:&name] ;
[outbasket addObject:name] ;
// Without the "if" above, it will add the last name found to outbasket twice
}
}
}
names = [NSArray arrayWithArray:outbasket] ;
[outbasket release] ;
[scanner release] ;
}
return names ;
}
+ (NSString*)profilePathForAppSupportRelativePath:(NSString*)appSupportRelativePath
profileName:(NSString*)profileName
homePath:(NSString*)homePath
error_p:(NSError**)error_p {
NSString* fullPath = nil ;
BOOL ok = YES ;
NSError* error = nil ;
NSString* filepathProfilesIni = ProfilesIniPath(appSupportRelativePath, homePath) ;
NSString* strungFile = [[NSString alloc] initWithContentsOfFile:filepathProfilesIni] ;
if (!strungFile) {
// This may happen if desired profile is on an Other Mac Account,
// where we don't have read permission.
// Try copying the file to a temporary location using
// a privileged-if-necessary Helper tool
NSString* tempPath = [[NSFileManager defaultManager] temporaryFilePath] ;
ok = [[SSYAuthorizedTaskMaster sharedTaskmaster] copyPath:filepathProfilesIni
toPath:tempPath
error_p:&error] ;
if (!ok) {
goto end ;
}
// Now try reading the copied temporary file
strungFile = [[NSString alloc] initWithContentsOfFile:tempPath] ;
// Delete the temporary file
BOOL trivialOk = [[NSFileManager defaultManager] removeItemAtPath:tempPath
error:&error] ;
if (!trivialOk) {
// Unable to delete temporary file. Unimportant error.
// Do not display to user, just log it.
NSLog(@"Internal Error 635-8292 %@", [error longDescription]) ;
}
}
if (strungFile) {
NSScanner* scanner = [[NSScanner alloc] initWithString:strungFile] ;
NSString* nameLine = [[NSString alloc] initWithFormat:@"Name=%@\n", profileName] ;
int isRelative = 1 ; // Try and fail safe; since I have always seen it as = 1.
NSString* pathFromDisk = nil;
[scanner scanUpToString:nameLine intoString:NULL] ;
[scanner scanString:nameLine intoString:NULL] ;
[scanner scanString:@"IsRelative=" intoString:NULL] ;
[scanner scanInt:&isRelative] ;
[scanner scanString:@"Path=" intoString:NULL] ;
[scanner scanUpToString:@"\n" intoString:&pathFromDisk] ;
if (isRelative) {
// In this case, pathFromDisk is a "plain text" path
fullPath = [BrowserSupportPath(appSupportRelativePath, homePath) stringByAppendingPathComponent:pathFromDisk] ;
}
else {
// In this case, pathFromDisk is a base64 encoded alias record
NSData* aliasRecord = [pathFromDisk dataBase64Decoded] ;
fullPath = [aliasRecord pathFromAliasRecordWithTimeout:3.0
error_p:NULL] ;
if (!fullPath) {
NSLog(@"Internal Error 234-5245 Could not get path from alias record in %@ profile %@.\nPossible corruption in %@", appSupportRelativePath, profileName, filepathProfilesIni) ;
}
}
[scanner release] ;
[nameLine release] ;
}
[strungFile release] ;
end:;
if (!ok && !error) {
NSString* msg = [NSString stringWithFormat:
@"%@ cannot access file at path:\n%@",
[[NSProcessInfo processInfo] processName],
filepathProfilesIni] ;
error = [NSError errorWithDomain:SSYBrowserPathsErrorDomain
code:254938
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
msg, NSLocalizedDescriptionKey,
@"The above file is a required piece of Firefox. Make sure it is there. If not, launch Firefox to create a new user profile.", NSLocalizedRecoverySuggestionErrorKey,
nil]] ;
}
if (error_p) {
*error_p = error ;
}
return fullPath ;
}
@end