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