]> err.no Git - sope/blob - sope-core/NGExtensions/NGCustomFileManager.m
Drop apache 1 build-dependency
[sope] / sope-core / NGExtensions / NGCustomFileManager.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with SOPE; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 #include <NGExtensions/NGCustomFileManager.h>
23 #include "common.h"
24
25 typedef struct {
26   NSString                *sourcePath;
27   NSString                *absolutePath;
28   NSString                *path;
29   NGCustomFileManagerInfo *info;
30   id                      fileManager;
31 } NGCustomFMPath;
32
33 @interface NGCustomFileManager(Helpers)
34 - (NGCustomFMPath)_resolvePath:(NSString *)_path;
35 - (BOOL)_boolDo:(SEL)_sel onPath:(NSString *)_path;
36 - (BOOL)_boolDo:(SEL)_sel onPath:(NSString *)_path handler:(id)_handler;
37 - (id)_do:(SEL)_sel onPath:(NSString *)_path;
38 @end
39
40 @implementation NGCustomFileManager
41
42 + (int)version {
43   return [super version] + 0 /* v0 */;
44 }
45 + (void)initialize {
46   NSAssert2([super version] == 0,
47             @"invalid superclass (%@) version %i !",
48             NSStringFromClass([self superclass]), [super version]);
49 }
50
51 /* customization */
52
53 - (NSString *)makeAbsolutePath:(NSString *)_path {
54   if ([_path isAbsolutePath])
55     return _path;
56   
57   return [[self currentDirectoryPath] stringByAppendingPathComponent:_path];
58 }
59
60 - (NGCustomFileManagerInfo *)fileManagerInfoForPath:(NSString *)_path {
61   return nil;
62 }
63
64 /* common ops */
65
66 - (NGCustomFMPath)_resolvePath:(NSString *)_path {
67   NGCustomFMPath p;
68   
69   p.sourcePath   = _path;
70   p.absolutePath = [self makeAbsolutePath:_path];
71   p.info         = [self fileManagerInfoForPath:_path];
72   p.path         = [p.info rewriteAbsolutePath:p.absolutePath];
73   p.fileManager  = [p.info fileManager];
74   return p;
75 }
76
77 - (BOOL)_boolDo:(SEL)_sel onPath:(NSString *)_path {
78   NGCustomFMPath p;
79   BOOL (*op)(id,SEL,NSString *);
80   
81   if (_sel == NULL) return NO;
82   p = [self _resolvePath:_path];
83   if ((_path = p.path) == nil) return NO;
84   if ((op = (void *)[p.fileManager methodForSelector:_sel]) == NULL) return NO;
85   
86   return op(p.fileManager, _sel, _path);
87 }
88 - (BOOL)_boolDo:(SEL)_sel onPath:(NSString *)_path handler:(id)_handler {
89   NGCustomFMPath p;
90   BOOL (*op)(id,SEL,NSString *,id);
91   
92   if (_sel == NULL) return NO;
93   p = [self _resolvePath:_path];
94   if ((_path = p.path) == nil) return NO;
95   if ((op = (void *)[p.fileManager methodForSelector:_sel]) == NULL) return NO;
96   
97   return op(p.fileManager, _sel, _path, _handler);
98 }
99 - (id)_do:(SEL)_sel onPath:(NSString *)_path {
100   NGCustomFMPath p;
101   id (*op)(id,SEL,NSString *);
102   
103   if (_sel == NULL) return NO;
104   p = [self _resolvePath:_path];
105   if ((_path = p.path) == nil) return NO;
106   if ((op = (void *)[p.fileManager methodForSelector:_sel]) == NULL) return NO;
107   
108   return op(p.fileManager, _sel, _path);
109 }
110
111 /* directory operations */
112
113 - (BOOL)changeCurrentDirectoryPath:(NSString *)_path {
114   BOOL isDir = NO;
115   if ((_path = [self makeAbsolutePath:_path]) == nil) return NO;
116   
117   if (![self fileExistsAtPath:_path isDirectory:&isDir]) return NO;
118   if (!isDir) return NO;
119   
120   ASSIGNCOPY(self->cwd, _path);
121   return YES;
122 }
123 - (NSString *)currentDirectoryPath {
124   return self->cwd;
125 }
126
127 - (BOOL)createDirectoryAtPath:(NSString *)_path
128   attributes:(NSDictionary *)_ats
129 {
130   NGCustomFMPath p;
131   p = [self _resolvePath:_path];
132   if (p.path == nil) return NO;
133   
134   return [p.fileManager createDirectoryAtPath:p.path attributes:_ats];
135 }
136
137 /* file operations */
138
139 - (BOOL)copyPath:(NSString *)_s toPath:(NSString *)_d handler:(id)_handler {
140   NGCustomFileManagerInfo *sinfo, *dinfo;
141   
142   if ((_s = [self makeAbsolutePath:_s]) == nil) return NO;
143   if ((_d = [self makeAbsolutePath:_d]) == nil) return NO;
144   if ((sinfo = [self fileManagerInfoForPath:_s]) == nil) return NO;
145   if ((dinfo = [self fileManagerInfoForPath:_d]) == nil) return NO;
146   _s = [sinfo rewriteAbsolutePath:_s];
147   _d = [dinfo rewriteAbsolutePath:_d];
148   
149   if ([sinfo isEqual:dinfo]) /* same filemanager */
150     return [[sinfo fileManager] copyPath:_s toPath:_d handler:_handler];
151   
152   /* operation between different filemanagers ... */
153   return NO;
154 }
155
156 - (BOOL)movePath:(NSString *)_s toPath:(NSString *)_d handler:(id)_handler {
157   NGCustomFileManagerInfo *sinfo, *dinfo;
158   
159   if ((_s = [self makeAbsolutePath:_s]) == nil) return NO;
160   if ((_d = [self makeAbsolutePath:_d]) == nil) return NO;
161   if ((sinfo = [self fileManagerInfoForPath:_s]) == nil) return NO;
162   if ((dinfo = [self fileManagerInfoForPath:_d]) == nil) return NO;
163   _s = [sinfo rewriteAbsolutePath:_s];
164   _d = [dinfo rewriteAbsolutePath:_d];
165   
166   if ([sinfo isEqual:dinfo]) /* same filemanager */
167     return [[sinfo fileManager] movePath:_s toPath:_d handler:_handler];
168     
169   /* operation between different filemanagers ... */
170   return NO;
171 }
172
173 - (BOOL)linkPath:(NSString *)_s toPath:(NSString *)_d handler:(id)_handler {
174   NGCustomFileManagerInfo *sinfo, *dinfo;
175   
176   if ((_s = [self makeAbsolutePath:_s]) == nil) return NO;
177   if ((_d = [self makeAbsolutePath:_d]) == nil) return NO;
178   if ((sinfo = [self fileManagerInfoForPath:_s]) == nil) return NO;
179   if ((dinfo = [self fileManagerInfoForPath:_d]) == nil) return NO;
180   _s = [sinfo rewriteAbsolutePath:_s];
181   _d = [dinfo rewriteAbsolutePath:_d];
182   
183   if ([sinfo isEqual:dinfo]) /* same filemanager */
184     return [[sinfo fileManager] linkPath:_s toPath:_d handler:_handler];
185     
186   /* operation between different filemanagers ... */
187   return NO;
188 }
189
190 - (BOOL)removeFileAtPath:(NSString *)_path handler:(id)_handler {
191   return [self _boolDo:_cmd onPath:_path handler:_handler];
192 }
193
194 - (BOOL)createFileAtPath:(NSString *)_path contents:(NSData *)_contents
195   attributes:(NSDictionary *)_attributes
196 {
197   NGCustomFMPath p;
198   p = [self _resolvePath:_path];
199   if (p.path == nil) return NO;
200   
201   return [p.fileManager
202                 createFileAtPath:p.path
203                 contents:_contents
204                 attributes:_attributes];
205 }
206
207 /* getting and comparing file contents */
208
209 - (NSData *)contentsAtPath:(NSString *)_path {
210   return [self _do:_cmd onPath:_path];
211 }
212
213 - (BOOL)contentsEqualAtPath:(NSString *)_path1 andPath:(NSString *)_path2 {
214   NGCustomFileManagerInfo *info1, *info2;
215   
216   if ((_path1 = [self makeAbsolutePath:_path1]) == nil) return NO;
217   if ((_path2 = [self makeAbsolutePath:_path2]) == nil) return NO;
218   if ((info1 = [self fileManagerInfoForPath:_path1]) == nil) return NO;
219   if ((info2 = [self fileManagerInfoForPath:_path2]) == nil) return NO;
220   _path1 = [info1 rewriteAbsolutePath:_path1];
221   _path2 = [info2 rewriteAbsolutePath:_path2];
222   
223   if ([info1 isEqual:info2]) /* same filemanager */
224     return [[info1 fileManager] contentsEqualAtPath:_path1 andPath:_path2];
225   
226   /* operation between different filemanagers ... */
227   return NO;
228 }
229
230 /* determining access to files */
231
232 - (BOOL)fileExistsAtPath:(NSString *)_path {
233   return [self _boolDo:_cmd onPath:_path];
234 }
235 - (BOOL)fileExistsAtPath:(NSString *)_path isDirectory:(BOOL *)_isDirectory {
236   NGCustomFMPath p;
237   p = [self _resolvePath:_path];
238   if (p.path == nil) return NO;
239   
240   return [p.fileManager fileExistsAtPath:p.path isDirectory:_isDirectory];
241 }
242 - (BOOL)isReadableFileAtPath:(NSString *)_path {
243   return [self _boolDo:_cmd onPath:_path];
244 }
245 - (BOOL)isWritableFileAtPath:(NSString *)_path {
246   return [self _boolDo:_cmd onPath:_path];
247 }
248 - (BOOL)isExecutableFileAtPath:(NSString *)_path {
249   return [self _boolDo:_cmd onPath:_path];
250 }
251 - (BOOL)isDeletableFileAtPath:(NSString *)_path {
252   return [self _boolDo:_cmd onPath:_path];
253 }
254
255 /* Getting and setting attributes */
256
257 - (NSDictionary *)fileAttributesAtPath:(NSString *)_p traverseLink:(BOOL)_flag{
258   NGCustomFMPath p;
259   p = [self _resolvePath:_p];
260   if (p.path == nil) return NO;
261   
262   /* special link handling required ??? */
263   return [p.fileManager fileAttributesAtPath:p.path traverseLink:_flag];
264 }
265
266 - (NSDictionary *)fileSystemAttributesAtPath:(NSString *)_p {
267   return [self _do:_cmd onPath:_p];
268 }
269
270 - (BOOL)changeFileAttributes:(NSDictionary *)_attributes atPath:(NSString *)_p{
271   NGCustomFMPath p;
272   p = [self _resolvePath:_p];
273   if (p.path == nil) return NO;
274   
275   return [p.fileManager changeFileAttributes:_attributes atPath:p.path];
276 }
277
278 /* discovering directory contents */
279
280 - (NSArray *)directoryContentsAtPath:(NSString *)_path {
281   /* this returns relative path's, can be passed back */
282   return [self _do:_cmd onPath:_path];
283 }
284
285 - (NSDirectoryEnumerator *)enumeratorAtPath:(NSString *)_path {
286   /* this needs to be wrapped ! */
287   return nil;
288 }
289
290 - (NSArray *)subpathsAtPath:(NSString *)_path {
291   /* this returns relative path's, can be passed back */
292   return [self _do:_cmd onPath:_path];
293 }
294
295 /* symbolic-link operations */
296
297 - (BOOL)createSymbolicLinkAtPath:(NSString *)_p pathContent:(NSString *)_dpath{
298   /* should that process the link-path somehow ??? */
299   NGCustomFMPath p;
300   p = [self _resolvePath:_p];
301   if (p.path == nil) return NO;
302   
303   return [p.fileManager createSymbolicLinkAtPath:p.path pathContent:_dpath];
304 }
305 - (NSString *)pathContentOfSymbolicLinkAtPath:(NSString *)_path {
306   /* should that process the link-path somehow ??? */
307   return [self _do:_cmd onPath:_path];
308 }
309
310 /* feature check */
311
312 - (BOOL)supportsVersioningAtPath:(NSString *)_path {
313   return [self _boolDo:_cmd onPath:_path];
314 }
315 - (BOOL)supportsLockingAtPath:(NSString *)_path {
316   return [self _boolDo:_cmd onPath:_path];
317 }
318 - (BOOL)supportsFolderDataSourceAtPath:(NSString *)_path {
319   return [self _boolDo:_cmd onPath:_path];
320 }
321
322 - (BOOL)supportsFeature:(NSString *)_featureURI atPath:(NSString *)_path {
323   NGCustomFMPath p;
324   p = [self _resolvePath:_path];
325   if (p.path == nil) return NO;
326   
327   return [p.fileManager supportsFeature:_featureURI atPath:p.path];
328 }
329
330 /* writing */
331
332 - (BOOL)writeContents:(NSData *)_content atPath:(NSString *)_path {
333   NGCustomFMPath p;
334   p = [self _resolvePath:_path];
335   if (p.path == nil) return NO;
336   
337   return [p.fileManager writeContents:_content atPath:p.path];
338 }
339
340 /* global-IDs */
341
342 - (EOGlobalID *)globalIDForPath:(NSString *)_path {
343   NGCustomFileManagerInfo *info;
344   if ((_path = [self makeAbsolutePath:_path])      == nil) return NO;
345   if ((info = [self fileManagerInfoForPath:_path]) == nil) return NO;
346
347   if (![info supportsGlobalIDs])
348     return nil;
349   
350   if ((_path = [info rewriteAbsolutePath:_path]) == nil)
351     return NO;
352   
353   return [[info fileManager] globalIDForPath:_path];
354 }
355
356 - (NSString *)pathForGlobalID:(EOGlobalID *)_gid {
357   return nil;
358 }
359
360 /* trash */
361
362 - (BOOL)supportsTrashFolderAtPath:(NSString *)_path {
363   return [self _boolDo:_cmd onPath:_path];
364 }
365 - (NSString *)trashFolderForPath:(NSString *)_path {
366   return NO;
367 }
368
369 @end /* NGCustomFileManager */
370
371 @implementation NGCustomFileManager(NGFileManagerVersioning)
372
373 /* versioning */
374
375 - (BOOL)checkoutFileAtPath:(NSString *)_path handler:(id)_handler {
376   return [self _boolDo:_cmd onPath:_path handler:_handler];
377 }
378 - (BOOL)releaseFileAtPath:(NSString *)_path handler:(id)_handler {
379   return [self _boolDo:_cmd onPath:_path handler:_handler];
380 }
381 - (BOOL)rejectFileAtPath:(NSString *)_path handler:(id)_handler {
382   return [self _boolDo:_cmd onPath:_path handler:_handler];
383 }
384 - (BOOL)checkoutFileAtPath:(NSString *)_path version:(NSString *)_version
385   handler:(id)_handler
386 {
387   NGCustomFMPath p;
388   p = [self _resolvePath:_path];
389   if (p.path == nil) return NO;
390   
391   return [p.fileManager
392            checkoutFileAtPath:p.path version:_version handler:_handler];
393 }
394
395 /* versioning data */
396
397 - (NSString *)lastVersionAtPath:(NSString *)_path {
398   return [self _do:_cmd onPath:_path];
399 }
400 - (NSArray *)versionsAtPath:(NSString *)_path {
401   return [self _do:_cmd onPath:_path];
402 }
403
404 - (NSData *)contentsAtPath:(NSString *)_path version:(NSString *)_version {
405   NGCustomFMPath p;
406   p = [self _resolvePath:_path];
407   if (p.path == nil) return NO;
408   
409   return [p.fileManager contentsAtPath:p.path version:_version];
410 }
411
412 - (NSDictionary *)fileAttributesAtPath:(NSString *)_path
413   traverseLink:(BOOL)_followLink
414   version:(NSString *)_version
415 {
416   NGCustomFMPath p;
417   p = [self _resolvePath:_path];
418   if (p.path == nil) return NO;
419   
420   /* do something special to symlink ??? */
421   
422   return [p.fileManager
423            fileAttributesAtPath:p.path
424            traverseLink:_followLink
425            version:_version];
426 }
427
428 @end /* NGCustomFileManager(NGFileManagerVersioning) */
429
430 @implementation NGCustomFileManager(NGFileManagerLocking)
431
432 - (BOOL)lockFileAtPath:(NSString *)_path handler:(id)_handler {
433   return [self _boolDo:_cmd onPath:_path handler:_handler];
434 }
435 - (BOOL)unlockFileAtPath:(NSString *)_path handler:(id)_handler {
436   return [self _boolDo:_cmd onPath:_path handler:_handler];
437 }
438 - (BOOL)isFileLockedAtPath:(NSString *)_path {
439   return [self _boolDo:_cmd onPath:_path];
440 }
441
442 /* access rights */
443
444 - (BOOL)isLockableFileAtPath:(NSString *)_path {
445   return [self _boolDo:_cmd onPath:_path];
446 }
447 - (BOOL)isUnlockableFileAtPath:(NSString *)_path {
448   return [self _boolDo:_cmd onPath:_path];
449 }
450
451 @end /* NGCustomFileManager(NGFileManagerLocking) */
452
453 @implementation NGCustomFileManager(NGFileManagerDataSources)
454
455 /* datasources (work on folders) */
456
457 - (EODataSource *)dataSourceAtPath:(NSString *)_path {
458   return [self _do:_cmd onPath:_path];
459 }
460
461 - (EODataSource *)dataSource {
462   return [self dataSourceAtPath:[self currentDirectoryPath]];
463 }
464
465 @end /* NGCustomFileManager(NGFileManagerDataSources) */
466
467 @implementation NGCustomFileManagerInfo
468
469 - (id)initWithCustomFileManager:(NGCustomFileManager *)_master
470   fileManager:(id<NGFileManager,NSObject>)_fm
471 {
472   self->master      = _master;
473   self->fileManager = [_fm retain];
474   return self;
475 }
476 - (id)init {
477   return [self initWithCustomFileManager:nil fileManager:nil];
478 }
479
480 - (void)dealloc {
481   [self->fileManager release];
482   [super dealloc];
483 }
484
485 - (void)resetMaster {
486   self->master = nil;
487 }
488
489 /* accessors */
490
491 - (NGCustomFileManager *)master {
492   return self->master;
493 }
494 - (id<NGFileManager,NSObject>)fileManager {
495   return self->fileManager;
496 }
497
498 /* operations */
499
500 - (NSString *)rewriteAbsolutePath:(NSString *)_path {
501   return _path;
502 }
503
504 /* capabilities */
505
506 - (BOOL)supportsGlobalIDs {
507   return [self->fileManager respondsToSelector:@selector(globalIDForPath:)];
508 }
509
510 @end /* NGCustomFileManagerInfo */