287
aBOOL = [[NSFileManager defaultManager] createFileAtPath: [NSString stringWithFormat: @"%@/%@",
288
[self path], theName]
369
// Ok, the folder doesn't already exist.
370
// Check if we want to create a simple folder/directory.
371
if (theType == MAILBOX_FORMAT_FOLDER)
375
aString = [NSString stringWithFormat: @"%@/%@", [self path], theName];
376
aBOOL = [aFileManager createDirectoryAtPath: aString attributes: nil];
380
[self enforceMode: 0700 atPath: aString];
382
// rebuild the folder list
383
[self _rebuildFolderEnumerator];
391
// We want to create a mailbox store; check if it already exists.
392
if ( [aFileManager fileExistsAtPath: pathToFile
393
isDirectory: &isDir] )
397
size = [[[aFileManager fileAttributesAtPath: pathToFile
398
traverseLink: NO] objectForKey: NSFileSize] intValue];
400
// If we got an empty file or simply a directory...
401
if ( size == 0 || isDir )
405
// If the size is 0, that means we have an empty file. We first convert this
406
// file to a directory.
409
[aFileManager removeFileAtPath: pathToFile handler: nil];
410
[aFileManager createDirectoryAtPath: pathToFile attributes: nil];
413
// We can now proceed with the creation of our store.
414
// Check the type of store we want to create
417
case MAILBOX_FORMAT_MAILDIR:
418
// Create the main maildir directory
419
aString = [NSString stringWithFormat: @"%@/%@", [self path], theName];
420
aBOOL = [aFileManager createDirectoryAtPath: aString attributes: nil];
421
[self enforceMode: 0700 atPath: aString];
423
// Now create the cur, new, and tmp sub-directories.
424
aString = [NSString stringWithFormat: @"%@/%@/cur", [self path], theName];
425
aBOOL = aBOOL & [aFileManager createDirectoryAtPath: aString attributes: nil];
426
[self enforceMode: 0700 atPath: aString];
429
aString = [NSString stringWithFormat: @"%@/%@/new", [self path], theName];
430
aBOOL = aBOOL & [aFileManager createDirectoryAtPath: aString attributes: nil];
431
[self enforceMode: 0700 atPath: aString];
434
aString = [NSString stringWithFormat: @"%@/%@/tmp", [self path], theName];
435
aBOOL = aBOOL & [aFileManager createDirectoryAtPath: aString attributes: nil];
436
[self enforceMode: 0700 atPath: aString];
439
case MAILBOX_FORMAT_MBOX:
441
aBOOL = [aFileManager createFileAtPath: [NSString stringWithFormat: @"%@/%@",
442
[self path], theName]
443
contents: theContents
446
// We now enforce the mode (0600) on this new mailbox
447
[self enforceMode: 0600
448
atPath: [NSString stringWithFormat: @"%@/%@", [self path], theName]];
452
// rebuild the folder list
453
[self _rebuildFolderEnumerator];
466
// theName must be the full path of the mailbox.
468
// Returns YES on success. NO otherwise.
297
470
- (BOOL) deleteFolderWithName: (NSString *) theName
301
// We remove the mbox
302
aBOOL = [[NSFileManager defaultManager] removeFileAtPath: [NSString stringWithFormat: @"%@/%@",
303
[self path], theName]
306
// We remove the cache
307
[[NSFileManager defaultManager] removeFileAtPath: [NSString stringWithFormat: @"%@/.%@.cache",
308
[self path], theName]
472
NSFileManager *aFileManager;
475
aFileManager = [NSFileManager defaultManager];
478
if ( [aFileManager fileExistsAtPath: [NSString stringWithFormat: @"%@/%@", [self path], theName]
479
isDirectory: &isDir] )
483
NSEnumerator *theEnumerator;
484
NSArray *theEntries, *dirContents;
486
theEnumerator = [aFileManager enumeratorAtPath: [NSString stringWithFormat: @"%@/%@",
487
[self path], theName]];
489
// FIXME - Verify the Store's path.
490
// If it doesn't contain any mailboxes and it's actually not or Store's path, we remove it.
491
theEntries = [theEnumerator allObjects];
492
dirContents = [aFileManager directoryContentsAtPath: [NSString stringWithFormat: @"%@/%@",
493
[self path], theName]];
494
if ( [theEntries count] == 0 )
496
aBOOL = [aFileManager removeFileAtPath: [NSString stringWithFormat: @"%@/%@",
497
[self path], theName]
500
// Rebuild the folder tree
502
[self _rebuildFolderEnumerator];
507
// We could also be trying to delete a maildir mailbox which
508
// has a directory structure with 3 sub-directories: cur, new, tmp
509
else if ( [aFileManager fileExistsAtPath: [NSString stringWithFormat: @"%@/%@/cur", [self path], theName]
510
isDirectory: &isDir])
512
// Make sure that these are the maildir directories and not something else.
513
if ( ![aFileManager fileExistsAtPath: [NSString stringWithFormat: @"%@/%@/new", [self path], theName]
514
isDirectory: &isDir] )
518
if ( ![aFileManager fileExistsAtPath: [NSString stringWithFormat: @"%@/%@/tmp", [self path], theName]
519
isDirectory: &isDir] )
530
// We remove the mbox or maildir store
531
aBOOL = [aFileManager removeFileAtPath: [NSString stringWithFormat: @"%@/%@",
532
[self path], theName]
535
// We remove the cache, if the store deletion was successful
540
aString = [theName lastPathComponent];
542
[[NSFileManager defaultManager] removeFileAtPath: [NSString stringWithFormat: @"%@/%@.%@.cache",
544
[theName substringToIndex:
545
([theName length] - [aString length])],
550
// Rebuild the folder tree
551
[self _rebuildFolderEnumerator];
559
// theName and theNewName MUST be the full path of those mailboxes.
561
// Returns YES on success. NO otherwise.
563
- (BOOL) renameFolderWithName: (NSString *) theName
564
toName: (NSString *) theNewName
566
NSFileManager *aFileManager;
569
aFileManager = [NSFileManager defaultManager];
572
// We verify if the destination path exists. If it does, we abort the rename operation
573
// since we don't want to overwrite the folder.
574
if ( [aFileManager fileExistsAtPath: [NSString stringWithFormat: @"%@/%@", [self path], theNewName]] )
579
// We verify if the source path is valid
580
if ( [aFileManager fileExistsAtPath: [NSString stringWithFormat: @"%@/%@", [self path], theName]
581
isDirectory: &isDir] )
585
NSEnumerator *theEnumerator;
588
theEnumerator = [aFileManager enumeratorAtPath: [NSString stringWithFormat: @"%@/%@",
589
[self path], theName]];
591
// FIXME - Verify the Store's path.
592
// If it doesn't contain any mailboxes and it's actually not or Store's path, we rename it.
593
theEntries = [theEnumerator allObjects];
595
if ( [theEntries count] == 0 )
597
return [aFileManager movePath: [NSString stringWithFormat: @"%@/%@",[self path], theName]
598
toPath: [NSString stringWithFormat: @"%@/%@", [self path], theNewName]
601
// We could also be trying to delete a maildir mailbox which
602
// has a directory structure with 3 sub-directories: cur, new, tmp
603
else if ( [aFileManager fileExistsAtPath: [NSString stringWithFormat: @"%@/%@/cur", [self path], theName]
604
isDirectory: &isDir])
606
// Make sure that these are the maildir directories and not something else.
607
if ( ![aFileManager fileExistsAtPath: [NSString stringWithFormat: @"%@/%@/new", [self path], theName]
608
isDirectory: &isDir] )
612
if ( ![aFileManager fileExistsAtPath: [NSString stringWithFormat: @"%@/%@/tmp", [self path], theName]
613
isDirectory: &isDir] )
624
// We rename the mail store
625
aBOOL = [aFileManager movePath: [NSString stringWithFormat: @"%@/%@", [self path], theName]
626
toPath: [NSString stringWithFormat: @"%@/%@", [self path], theNewName]
629
// We remove the cache, if the store rename was successful
632
NSString *str1, *str2;
634
str1 = [theName lastPathComponent];
635
str2 = [theNewName lastPathComponent];
637
[[NSFileManager defaultManager] movePath: [NSString stringWithFormat: @"%@/%@.%@.cache",
639
[theName substringToIndex:
640
([theName length] - [str1 length])],
642
toPath: [NSString stringWithFormat: @"%@/%@.%@.cache",
644
[theNewName substringToIndex:
645
([theNewName length] - [str2 length])],
650
// Rebuild the folder tree
651
[self _rebuildFolderEnumerator];
661
- (void) enforceMode: (unsigned long) theMode
662
atPath: (NSString *) thePath
665
NSMutableDictionary *currentFileAttributes;
667
unsigned long current_attributes, desired_attributes;
670
currentFileAttributes = [[NSMutableDictionary alloc] initWithDictionary: [fileManager fileAttributesAtPath: thePath
673
current_attributes = [currentFileAttributes filePosixPermissions];
674
desired_attributes = theMode;
676
if ( current_attributes != desired_attributes )
678
[currentFileAttributes setObject: [NSNumber numberWithUnsignedLong: desired_attributes]
679
forKey: NSFilePosixPermissions];
681
[fileManager changeFileAttributes: currentFileAttributes
685
RELEASE(currentFileAttributes);
703
@implementation LocalStore (Private)
705
- (void) _enforceFileAttributes
707
NSEnumerator *anEnumerator;
708
NSAutoreleasePool *pool;
711
pool = [[NSAutoreleasePool alloc] init];
714
// We verify if our Store path's mode is 0700
716
[self enforceMode: 0700 atPath: [self path]];
719
// We ensure that all subdirectories are using mode 0700 and files are using mode 0600
721
anEnumerator = [self folderEnumerator];
723
while ( (aString = [anEnumerator nextObject]) )
727
aString = [NSString stringWithFormat: @"%@/%@", [self path], aString];
729
if ( [fileManager fileExistsAtPath: aString
730
isDirectory: &isDir] )
734
[self enforceMode: 0700
739
[self enforceMode: 0600
750
// Rebuild the folder hierarchy
752
- (NSEnumerator *) _rebuildFolderEnumerator
754
NSString *aString, *lastPathComponent, *pathToFolder;
755
NSEnumerator *tmpEnumerator;
759
// Clear out our cached folder structure and refresh from the file system
760
[folderArray removeAllObjects];
761
[folderArray setArray: [[fileManager enumeratorAtPath: [self path]] allObjects]];
764
// We iterate through our array. If mbox A and .A.summary (or .A.cache) exists, we
765
// remove .A.summary (or .A.cache) from our mutable array.
766
// We do this in two runs:
767
// First run: remove maildir sub-directory structure so that is appears as a regular folder.
768
// Second run: remove other stuff like *.cache, *.summary
770
for (i = 0; i< [folderArray count]; i++)
774
aString = [folderArray objectAtIndex: i];
776
lastPathComponent = [aString lastPathComponent];
777
pathToFolder = [aString substringToIndex: ([aString length] - [lastPathComponent length])];
781
// If this is a maildir directory, remove its sub-directory structure from the list,
782
// so that the maildir store appears just like a regular mail store.
784
if ( [[NSFileManager defaultManager] fileExistsAtPath: [NSString stringWithFormat: @"%@/%@/cur",
785
[self path], aString]
786
isDirectory: &bIsMailDir] && bIsMailDir )
788
NSDirectoryEnumerator *maildirEnumerator;
791
// Wust ensure 700 mode un cur/new/tmp folders and 600 on all files (ie., messages)
792
[self enforceMode: 0700
793
atPath: [NSString stringWithFormat: @"%@/%@/cur", [self path], aString]];
795
[self enforceMode: 0700
796
atPath: [NSString stringWithFormat: @"%@/%@/new", [self path], aString]];
798
[self enforceMode: 0700
799
atPath: [NSString stringWithFormat: @"%@/%@/tmp", [self path], aString]];
802
// Get all the children of this directory an remove them from our mutable array.
803
maildirEnumerator = [[NSFileManager defaultManager] enumeratorAtPath:
804
[NSString stringWithFormat: @"%@/%@",
805
[self path], aString]];
807
subpaths = [[NSFileManager defaultManager] subpathsAtPath: [NSString stringWithFormat: @"%@/%@",
808
[self path], aString]];
809
[folderArray removeObjectsInRange: NSMakeRange(i+1,[subpaths count])];
814
// Second Run: Get rid of cache, summary and OS specific stuff
816
tmpArray = [[NSArray alloc] initWithArray: folderArray];
817
AUTORELEASE(tmpArray);
818
tmpEnumerator = [tmpArray objectEnumerator];
820
while ( (aString = [tmpEnumerator nextObject]) )
822
lastPathComponent = [aString lastPathComponent];
823
pathToFolder = [aString substringToIndex: ([aString length] - [lastPathComponent length])];
825
// We remove Netscape/Mozilla summary file.
826
[folderArray removeObject: [NSString stringWithFormat: @"%@.%@.summary", pathToFolder, lastPathComponent]];
828
// We remove Pantomime's cache file. Before doing so, we ensure it's 600 mode.
829
[folderArray removeObject: [NSString stringWithFormat: @"%@.%@.cache", pathToFolder, lastPathComponent]];
830
[self enforceMode: 0600
831
atPath: [NSString stringWithFormat: @"%@/%@.%@.cache", [self path], pathToFolder, lastPathComponent]];
833
// We also remove Apple Mac OS X .DS_Store directory
834
[folderArray removeObject: [NSString stringWithFormat: @"%@.DS_Store", pathToFolder]];
837
return [folderArray objectEnumerator];