1/*
2
3  Preferences.m
4  Zipper
5
6  Copyright (C) 2012 Free Software Foundation, Inc
7
8  Authors: Dirk Olmes <dirk@xanthippe.ping.de>
9           Riccardo Mottola <rm@gnu.org>
10
11  This application is free software; you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by the Free
13  Software Foundation; either version 2 of the License, or (at your option)
14  any later version.
15
16  This program is distributed in the hope that it will be useful, but
17  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18  or FITNESS FOR A PARTICULAR PURPOSE.
19  See the GNU General Public License for more details
20
21 */
22
23#import <Foundation/Foundation.h>
24#import "Preferences.h"
25#import "NSFileManager+Custom.h"
26
27#define X_MISSING_PREF @"MissingPreferenceException"
28#define X_WRONG_PREF @"WrongPreferenceException"
29
30@interface Preferences (PrivateAPI)
31+ (NSString *)stringForKey:(NSString *)key;
32+ (BOOL)boolForKey:(NSString *)key;
33+ (void)checkExecutable:(NSString *)executable withName:(NSString *)name;
34@end
35
36/**
37 * This class encapsulates the access to the app's preferences. It faciliates providing a
38 * Dictionary that will be used instead of NSUserDefaults and searching the PATH environment
39 * variable.
40 */
41@implementation Preferences : NSObject
42
43/**
44 * To faciliate unit testing it's possible to provide the Preferences class with an NSDictionary
45 * that makes up the preferences.
46 */
47static NSDictionary *_replacementPrefs = nil;
48
49/**
50 * Additional Preferences loaded from PropertyList file
51 */
52static NSDictionary *_plistPrefs;
53
54/**
55 * This is the mapping between file extensions and tar's extract option. This option differs
56 * from platform to platform. In order to encapsulate this, Preferences manages this mapping
57 * and clients can ask for a compression argument with <code>compressionArgumentForFile:</code>
58 */
59static NSMutableDictionary *_extensionMapping = nil;
60
61+ (void)initialize
62{
63	NSString *path;
64
65	if (_extensionMapping == nil)
66	{
67		_extensionMapping = [[NSMutableDictionary dictionaryWithObjectsAndKeys:
68			@"", @"tar",
69			@"-z", @"gz",
70			@"-z", @"tgz",
71			@"-j", @"bz2",
72			nil] retain];
73	}
74
75	// see if there's a property list containing preferences to use
76	path = [[NSBundle bundleForClass:self] pathForResource:@"DefaultPreferences" ofType:@"plist"];
77	if (path != nil)
78	{
79		_plistPrefs = [[NSDictionary dictionaryWithContentsOfFile:path] retain];
80	}
81}
82
83+ (void)usePreferences:(NSDictionary *)newPrefs;
84{
85  [_replacementPrefs release];
86  _replacementPrefs = newPrefs;
87  [_replacementPrefs retain];
88}
89
90+ (NSString *)tarExecutable;
91{
92	NSString *tar = [self stringForKey:PREF_KEY_TAR];
93	if (tar == nil)
94	{
95		// search the PATH
96		tar = [[NSFileManager defaultManager] locateExecutable:@"tar"];
97	}
98	return tar;
99}
100
101+ (void)setTarExecutable:(NSString *)newTar
102{
103	if (newTar != nil)
104	{
105		[[NSUserDefaults standardUserDefaults] setObject:newTar forKey:PREF_KEY_TAR];
106	}
107}
108
109+ (BOOL)isBsdTar;
110{
111	return [self boolForKey:PREF_KEY_BSD_TAR];
112}
113
114+ (void)setIsBsdTar:(BOOL)flag
115{
116	[[NSUserDefaults standardUserDefaults] setBool:flag forKey:PREF_KEY_BSD_TAR];
117	if (flag == YES)
118	{
119		// on BSD tar also uses -z for extracting .bz archives
120		[_extensionMapping setObject:@"-z" forKey:@"bz2"];
121	}
122	else
123	{
124		[_extensionMapping setObject:@"-j" forKey:@"bz2"];
125	}
126}
127
128+ (NSString *)zipExecutable;
129{
130	NSString *zip = [self stringForKey:PREF_KEY_ZIP];
131	if (zip == nil)
132	{
133		zip = [[NSFileManager defaultManager] locateExecutable:@"zip"];
134	}
135	return zip;
136}
137+ (void)setZipExecutable:(NSString *)newZip
138{
139	if (newZip != nil)
140	{
141		[[NSUserDefaults standardUserDefaults] setObject:newZip forKey:PREF_KEY_ZIP];
142	}
143}
144
145+ (NSString *)unzipExecutable;
146{
147	NSString *unzip = [self stringForKey:PREF_KEY_UNZIP];
148	if (unzip == nil)
149	{
150		unzip = [[NSFileManager defaultManager] locateExecutable:@"unzip"];
151	}
152	return unzip;
153}
154
155+ (void)setUnzipExecutable:(NSString *)newUnzip
156{
157	if (newUnzip != nil)
158	{
159		[[NSUserDefaults standardUserDefaults] setObject:newUnzip forKey:PREF_KEY_UNZIP];
160	}
161}
162
163+ (NSString *)sevenZipExecutable;
164{
165	NSString *zip = [self stringForKey:PREF_KEY_SEVEN_ZIP];
166	if (zip == nil)
167	{
168		zip = [[NSFileManager defaultManager] locateExecutable:@"7z"];
169
170        // corner case: only 7za may be available on the system
171        if (zip == nil)
172        {
173            zip = [[NSFileManager defaultManager] locateExecutable:@"7za"];
174        }
175	}
176	return zip;
177}
178
179+ (void)setSevenZipExecutable:(NSString *)new7zip
180{
181	if (new7zip != nil)
182	{
183		[[NSUserDefaults standardUserDefaults] setObject:new7zip forKey:PREF_KEY_SEVEN_ZIP];
184	}
185}
186
187+ (NSString *)rarExecutable;
188{
189	NSString *rar = [self stringForKey:PREF_KEY_RAR];
190	if (rar == nil)
191	{
192		rar = [[NSFileManager defaultManager] locateExecutable:@"unrar"];
193	}
194	return rar;
195}
196
197+ (void)setRarExecutable:(NSString *)newRar;
198{
199	if (newRar != nil)
200	{
201		[[NSUserDefaults standardUserDefaults] setObject:newRar forKey:PREF_KEY_RAR];
202	}
203}
204
205+ (NSString *)lhaExecutable
206{
207	NSString *lha = [self stringForKey:PREF_KEY_LHA];
208	if (lha == nil)
209	{
210		lha = [[NSFileManager defaultManager] locateExecutable:@"lha"];
211	}
212	return lha;
213}
214
215+ (void)setLhaExecutable:(NSString *)newLha;
216{
217	if (newLha != nil)
218	{
219		[[NSUserDefaults standardUserDefaults] setObject:newLha forKey:PREF_KEY_LHA];
220	}
221}
222
223+ (NSString *)lzxExecutable
224{
225	NSString *lzx = [self stringForKey:PREF_KEY_LZX];
226	if (lzx == nil)
227	{
228		lzx = [[NSFileManager defaultManager] locateExecutable:@"unlzx"];
229	}
230	return lzx;
231}
232
233+ (void)setLzxExecutable:(NSString *)newLzx;
234{
235	if (newLzx != nil)
236	{
237		[[NSUserDefaults standardUserDefaults] setObject:newLzx forKey:PREF_KEY_LZX];
238	}
239}
240
241+ (NSString *)gzipExecutable
242{
243	NSString *gzip = [self stringForKey:PREF_KEY_GZIP];
244	if (gzip == nil)
245	{
246		gzip = [[NSFileManager defaultManager] locateExecutable:@"gzip"];
247	}
248	return gzip;
249}
250
251+ (void)setGzipExecutable:(NSString *)newGzip
252{
253	if (newGzip != nil)
254	{
255		[[NSUserDefaults standardUserDefaults] setObject:newGzip forKey:PREF_KEY_GZIP];
256	}
257}
258
259+ (NSString *)gunzipExecutable
260{
261	NSString *gunzip = [self stringForKey:PREF_KEY_GUNZIP];
262	if (gunzip == nil)
263	{
264		gunzip = [[NSFileManager defaultManager] locateExecutable:@"gunzip"];
265	}
266	return gunzip;
267}
268
269+ (void)setGunzipExecutable:(NSString *)newGunzip
270{
271	if (newGunzip != nil)
272	{
273		[[NSUserDefaults standardUserDefaults] setObject:newGunzip forKey:PREF_KEY_GUNZIP];
274	}
275}
276
277+ (NSString *)bzip2Executable
278{
279	NSString *bzip2 = [self stringForKey:PREF_KEY_BZIP2];
280	if (bzip2 == nil)
281	{
282		bzip2 = [[NSFileManager defaultManager] locateExecutable:@"bzip2"];
283	}
284	return bzip2;
285}
286
287+ (void)setBzip2Executable:(NSString *)newBzip2
288{
289	if (newBzip2 != nil)
290	{
291		[[NSUserDefaults standardUserDefaults] setObject:newBzip2 forKey:PREF_KEY_BZIP2];
292	}
293}
294
295+ (NSString *)bunzip2Executable
296{
297	NSString *bunzip2 = [self stringForKey:PREF_KEY_BUNZIP2];
298	if (bunzip2 == nil)
299	{
300		bunzip2 = [[NSFileManager defaultManager] locateExecutable:@"bunzip2"];
301	}
302	return bunzip2;
303}
304
305+ (void)setBunzip2Executable:(NSString *)newBunzip2
306{
307	if (newBunzip2 != nil)
308	{
309		[[NSUserDefaults standardUserDefaults] setObject:newBunzip2 forKey:PREF_KEY_BUNZIP2];
310	}
311}
312
313+ (NSString *)unarjExecutable
314{
315	NSString *unarj = [self stringForKey:PREF_KEY_UNARJ];
316	if (unarj == nil)
317	{
318		unarj = [[NSFileManager defaultManager] locateExecutable:@"unarj"];
319	}
320	return unarj;
321}
322
323+ (void)setUnarjExecutable:(NSString *)newUnarj
324{
325	if (newUnarj != nil)
326	{
327		[[NSUserDefaults standardUserDefaults] setObject:newUnarj forKey:PREF_KEY_UNARJ];
328	}
329}
330
331+ (NSString *)unaceExecutable
332{
333	NSString *unace = [self stringForKey:PREF_KEY_UNACE];
334	if (unace == nil)
335	{
336		unace = [[NSFileManager defaultManager] locateExecutable:@"unace"];
337	}
338	return unace;
339}
340
341+ (void)setUnaceExecutable:(NSString *)newUnace
342{
343	if (newUnace != nil)
344	{
345		[[NSUserDefaults standardUserDefaults] setObject:newUnace forKey:PREF_KEY_UNACE];
346	}
347}
348
349+ (NSString *)zooExecutable
350{
351	NSString *zoo = [self stringForKey:PREF_KEY_ZOO];
352	if (zoo == nil)
353	{
354		zoo = [[NSFileManager defaultManager] locateExecutable:@"zoo"];
355	}
356	return zoo;
357}
358
359+ (void)setZooExecutable:(NSString *)newZoo
360{
361	if (newZoo != nil)
362	{
363		[[NSUserDefaults standardUserDefaults] setObject:newZoo forKey:PREF_KEY_ZOO];
364	}
365}
366
367+ (NSString *)xzExecutable
368{
369	NSString *xz = [self stringForKey:PREF_KEY_XZ];
370	if (xz == nil)
371	{
372		xz = [[NSFileManager defaultManager] locateExecutable:@"xz"];
373	}
374	return xz;
375}
376
377+ (void)setXzExecutable:(NSString *)newXz
378{
379	if (newXz != nil)
380	{
381		[[NSUserDefaults standardUserDefaults] setObject:newXz forKey:PREF_KEY_XZ];
382	}
383}
384
385+ (NSString *)lastOpenDirectory
386{
387	return [self stringForKey:PREF_KEY_OPEN_DIR];
388}
389
390+ (void)setLastOpenDirectory:(NSString *)path;
391{
392	[[NSUserDefaults standardUserDefaults] setObject:path forKey:PREF_KEY_OPEN_DIR];
393}
394
395+ (NSString *)lastExtractDirectory;
396{
397	return [self stringForKey:PREF_KEY_EXTRACT_DIR];
398}
399
400+ (void)setLastExtractDirectory:(NSString *)path;
401{
402	[[NSUserDefaults standardUserDefaults] setObject:path forKey:PREF_KEY_EXTRACT_DIR];
403}
404
405+ (NSString *)compressionArgumentForFile:(NSString *)fileName
406{
407	if (fileName != nil)
408	{
409		return [_extensionMapping objectForKey:[fileName pathExtension]];
410	}
411	return nil;
412}
413
414/**
415 * Returns the name of the app that will be used to open files that don't have a
416 * pathExtension.
417 */
418+ (NSString *)defaultOpenApp;
419{
420	return [self stringForKey:PREF_KEY_DEFAULT_OPEN_APP];
421}
422
423+ (void)setDefaultOpenApp:(NSString *)path;
424{
425	[[NSUserDefaults standardUserDefaults] setObject:path forKey:PREF_KEY_DEFAULT_OPEN_APP];
426}
427
428+ (void)save
429{
430	[[NSUserDefaults standardUserDefaults] synchronize];
431}
432
433//------------------------------------------------------------------------------
434// private API
435//------------------------------------------------------------------------------
436+ (NSString *)stringForKey:(NSString *)key;
437{
438	NSString *value;
439
440	if (_replacementPrefs != nil)
441	{
442		return [_replacementPrefs objectForKey:key];
443	}
444
445	value = [[NSUserDefaults standardUserDefaults] stringForKey:key];
446	if ((value == nil) && (_plistPrefs != nil))
447	{
448		value = [_plistPrefs objectForKey:key];
449	}
450	return value;
451}
452
453+ (BOOL)boolForKey:(NSString *)key
454{
455	if (_replacementPrefs != nil)
456	{
457		NSString *value = [_replacementPrefs objectForKey:key];
458		return [value isEqual:@"YES"];
459	}
460	return [[NSUserDefaults standardUserDefaults] boolForKey:key];
461}
462
463@end
464