~ubuntu-branches/ubuntu/dapper/pantomime/dapper

« back to all changes in this revision

Viewing changes to Source/LocalStore.m

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2004-11-20 00:25:28 UTC
  • mfrom: (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20041120002528-igjuwyao6gubpig1
Tags: 1.1.2-3
Build depend / depend on libgnustep-base-1.10-dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
**  LocalStore.m
3
3
**
4
 
**  Copyright (c) 2001, 2002
 
4
**  Copyright (c) 2001, 2002, 2003
5
5
**
6
6
**  Author: Ludovic Marcotte <ludovic@Sophos.ca>
7
7
**
20
20
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
21
*/
22
22
 
23
 
#import <Pantomime/LocalStore.h>
24
 
 
25
 
#import <Pantomime/Constants.h>
26
 
#import <Pantomime/LocalFolder.h>
27
 
#import <Pantomime/URLName.h>
 
23
#include <Pantomime/LocalStore.h>
 
24
 
 
25
#include <Pantomime/Constants.h>
 
26
#include <Pantomime/LocalFolder.h>
 
27
#include <Pantomime/URLName.h>
 
28
 
 
29
#include <Foundation/NSAutoreleasePool.h>
 
30
#include <Foundation/NSPathUtilities.h>
 
31
#include <Foundation/NSValue.h>
28
32
 
29
33
@implementation LocalStore
30
34
 
36
40
  RELEASE(path);
37
41
  RELEASE(folders);
38
42
  RELEASE(fileManager);
 
43
  RELEASE(folderArray);
39
44
  
40
45
  [super dealloc];
41
46
}
54
59
  
55
60
  // We initialize our cache of opened folders
56
61
  folders = [[NSMutableDictionary alloc] init];
 
62
  // Create an array to cache our folder structure
 
63
  folderArray = [[NSMutableArray alloc] initWithArray:
 
64
          [[fileManager enumeratorAtPath:
 
65
                  [self path]] allObjects]];
57
66
  
 
67
   
58
68
  fileManager = [NSFileManager defaultManager];
59
69
  RETAIN(fileManager);
60
 
 
61
 
  if ([fileManager fileExistsAtPath: [self path]
62
 
                   isDirectory: &isDirectory])
 
70
  
 
71
  if ( [fileManager fileExistsAtPath: [self path]
 
72
                    isDirectory: &isDirectory] )
63
73
    {
64
 
      if (! isDirectory)
 
74
      if ( !isDirectory )
65
75
        {
66
76
          AUTORELEASE(self);
67
77
          return nil;
73
83
      return nil;
74
84
    }
75
85
 
 
86
  // Just before returning, we finally enforce our file attributes
 
87
  [self _enforceFileAttributes];
 
88
 
76
89
 
77
90
  return self;
78
91
}
83
96
//
84
97
- (id) initWithURL: (NSString *) theURL;
85
98
{
86
 
  URLName *urlName;
87
 
 
88
 
  urlName = [[URLName alloc] initWithString: theURL];
89
 
 
90
 
  self = [self initWithPathToDirectory: [urlName path]];
91
 
 
92
 
  RELEASE(urlName);
 
99
  URLName *aURLName;
 
100
 
 
101
  aURLName = [[URLName alloc] initWithString: theURL];
 
102
  
 
103
  self = [self initWithPathToDirectory: [aURLName path]];
 
104
 
 
105
  RELEASE(aURLName);
93
106
  
94
107
  return self;
95
108
}
96
109
 
 
110
 
97
111
//
98
112
// This method will open automatically Inbox (case-insensitive).
99
113
// It may return nil if the opening failed or Inbox wasn't found.
122
136
      return nil;
123
137
    }
124
138
  
125
 
  if (! cachedFolder )
 
139
  if ( !cachedFolder )
126
140
    {
127
141
      while ( (aString = [anEnumerator nextObject]) )
128
142
        {
129
143
          if ( [aString compare: theName] == NSOrderedSame )
130
144
            {
131
145
              LocalFolder *aFolder;
132
 
              
133
 
              aFolder = [[LocalFolder alloc] initWithPathToFile:
 
146
 
 
147
                  aFolder = [[LocalFolder alloc] initWithPathToFile:
134
148
                                               [NSString stringWithFormat:@"%@/%@",
135
149
                                                         [self path], aString]];
136
 
              
 
150
 
137
151
              if ( aFolder )
138
152
                {
139
153
                  [aFolder setStore: (Store *)self];
144
158
                  [folders setObject: AUTORELEASE(aFolder)
145
159
                           forKey: theName];
146
160
                }
147
 
              
 
161
 
148
162
              return aFolder;
149
163
            }
150
164
        }
151
 
    return nil; // Never reached?
 
165
      
 
166
      return nil; // Never reached?
152
167
    }
153
168
  else
154
169
    {
155
 
      return cachedFolder;
 
170
          return cachedFolder;
156
171
    }
157
172
}
158
173
 
 
174
 
159
175
//
160
176
//
161
177
//
173
189
  return aFolder;
174
190
}
175
191
 
 
192
 
176
193
//
177
194
// This method returns the list of folders contained in 
178
195
// a specific directory. It'll currently ignore some things
181
198
//
182
199
- (NSEnumerator *) folderEnumerator
183
200
{
184
 
  NSDirectoryEnumerator *aDictionaryEnumerator;
185
 
  NSMutableArray *aMutableArray;
186
 
  NSString *aString;
187
 
  
188
 
  aMutableArray = [[NSMutableArray alloc] initWithArray:
189
 
                                            [[fileManager enumeratorAtPath: 
190
 
                                                            [self path]] allObjects]];
191
 
  AUTORELEASE(aMutableArray);
192
 
 
193
 
  aDictionaryEnumerator = [fileManager enumeratorAtPath: [self path]];
194
 
  
195
 
  // We iterate through our array. If mbox A and .A.summary (or .A.cache) exists, we
196
 
  // remove .A.summary (or .A.cache) from our mutable array.
197
 
  while ( (aString = [aDictionaryEnumerator nextObject]) )
198
 
    {     
199
 
      [aMutableArray removeObject: [NSString stringWithFormat: @".%@.summary", aString]];
200
 
      [aMutableArray removeObject: [NSString stringWithFormat: @".%@.cache", aString]];
 
201
  if ( [folderArray count] > 0 )
 
202
    {
 
203
      return [folderArray objectEnumerator];
201
204
    }
202
 
  
203
 
  return [aMutableArray objectEnumerator];
204
 
}
205
 
 
206
 
 
 
205
 
 
206
  return [self _rebuildFolderEnumerator];
 
207
}
 
208
 
 
209
 
 
210
//
 
211
//
 
212
//
 
213
- (NSEnumerator *) subscribedFolderEnumerator
 
214
{
 
215
  return [self folderEnumerator];
 
216
}
 
217
 
 
218
 
 
219
//
 
220
//
 
221
//
207
222
- (NSString *) path
208
223
{
209
224
  return path;
210
225
}
211
226
 
212
227
 
 
228
//
 
229
//
 
230
//
213
231
- (void) setPath: (NSString *) thePath
214
232
{
215
233
  RETAIN(thePath);
217
235
  path = thePath;
218
236
}
219
237
 
 
238
 
 
239
//
 
240
//
 
241
//
220
242
- (void) close
221
243
{
222
244
  NSEnumerator *anEnumerator;
223
 
  NSString *aName;
 
245
  LocalFolder *aFolder;
224
246
 
225
247
  anEnumerator = [self openedFoldersEnumerator];
226
 
 
227
 
  while ( (aName = [anEnumerator nextObject]) )
 
248
  
 
249
  while ( (aFolder = [anEnumerator nextObject]) )
228
250
    {
229
 
      LocalFolder *aFolder;
230
 
 
231
 
      aFolder = (LocalFolder *)[self folderForName: aName];
232
251
      [aFolder close];
233
252
    }
234
253
}
235
254
 
 
255
 
 
256
//
 
257
//
 
258
//
236
259
- (NSEnumerator *) openedFoldersEnumerator
237
260
{
238
 
  return [folders keyEnumerator];
 
261
  return [folders objectEnumerator];
239
262
}
240
263
 
241
 
- (void) removeFolderFromOpenedFolders: (LocalFolder *) theFolder
 
264
 
 
265
//
 
266
//
 
267
//
 
268
- (void) removeFolderFromOpenedFolders: (Folder *) theFolder
242
269
{
243
 
  [folders removeObjectForKey: [theFolder name]];
 
270
  [folders removeObjectForKey: [(LocalFolder *)theFolder name]];
244
271
}
245
272
 
 
273
 
 
274
//
 
275
//
 
276
//
246
277
- (BOOL) folderForNameIsOpen: (NSString *) theName
247
278
{
248
279
  NSEnumerator *anEnumerator;
249
 
  NSString *aName;
 
280
  LocalFolder *aFolder;
250
281
  
251
282
  anEnumerator = [self openedFoldersEnumerator];
252
283
 
253
 
  while ( (aName = [anEnumerator nextObject]) )
 
284
  while ( (aFolder = [anEnumerator nextObject]) )
254
285
    {
255
 
      if ( [aName compare: theName] == NSOrderedSame)
 
286
      if ( [[aFolder name] compare: theName] == NSOrderedSame)
256
287
        {
257
288
          return YES;
258
289
        }
265
296
//
266
297
//
267
298
//
268
 
- (BOOL) createFolderWithName: (NSString *) theName
269
 
{
270
 
  NSString *aName;
271
 
  BOOL aBOOL;
272
 
 
 
299
- (int) folderTypeForFolderName: (NSString *) theName
 
300
{
 
301
  NSString *aString;
 
302
  BOOL isDir;
 
303
 
 
304
  aString = [NSString stringWithFormat: @"%@/%@", [self path], theName];
 
305
  
 
306
  [[NSFileManager defaultManager] fileExistsAtPath: aString
 
307
                                  isDirectory: &isDir];
 
308
  
 
309
  if ( isDir )
 
310
    {
 
311
      // This could be a maildir store. Check for maildir specific subfolders.
 
312
      aString = [NSString stringWithFormat: @"%@/%@/cur", [self path], theName];
 
313
      
 
314
      if ( [[NSFileManager defaultManager] fileExistsAtPath: aString
 
315
                                           isDirectory: &isDir] && isDir )
 
316
        {
 
317
          return PantomimeHoldsMessages;
 
318
        }
 
319
      else
 
320
        {
 
321
          return PantomimeHoldsFolders;
 
322
        }
 
323
    }
 
324
 
 
325
  return PantomimeHoldsMessages;
 
326
}
 
327
 
 
328
 
 
329
//
 
330
//
 
331
//
 
332
- (NSString *) folderSeparator
 
333
{
 
334
  return @"/";
 
335
}
 
336
 
 
337
 
 
338
//
 
339
// theName must be the full path of the mailbox.
 
340
//
 
341
// Returns YES on success. NO otherwise.
 
342
//
 
343
- (BOOL) createFolderWithName: (NSString *) theName 
 
344
                         type: (int) theType
 
345
                     contents: (NSData *) theContents
 
346
{
 
347
  NSString *aName, *pathToFile;
 
348
  BOOL aBOOL, isDir;
 
349
 
 
350
  NSFileManager *aFileManager;
273
351
  NSEnumerator *anEnumerator;
274
352
 
 
353
  aFileManager = [NSFileManager defaultManager];
275
354
  anEnumerator = [self folderEnumerator];
276
 
 
 
355
  
 
356
  pathToFile = [NSString stringWithFormat: @"%@/%@", [self path], theName];
 
357
  pathToFile = [pathToFile substringToIndex: ([pathToFile length] - [[pathToFile lastPathComponent] length] - 1)];
 
358
  
277
359
  // We verify if the folder with that name does already exist
278
360
  while ( (aName = [anEnumerator nextObject]) )
279
361
    {
283
365
          return NO;
284
366
        }
285
367
    }
286
 
 
287
 
  aBOOL = [[NSFileManager defaultManager] createFileAtPath: [NSString stringWithFormat: @"%@/%@",
288
 
                                                                      [self path], theName]
289
 
                                          contents: nil 
290
 
                                          attributes: nil ];
 
368
  
 
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)
 
372
    {
 
373
      NSString *aString;
 
374
 
 
375
      aString = [NSString stringWithFormat: @"%@/%@", [self path], theName];
 
376
      aBOOL = [aFileManager createDirectoryAtPath: aString  attributes: nil];
 
377
      
 
378
      if ( aBOOL )
 
379
        {
 
380
          [self enforceMode: 0700  atPath: aString];
 
381
          
 
382
          // rebuild the folder list
 
383
          [self _rebuildFolderEnumerator];
 
384
        }
 
385
 
 
386
      return aBOOL;
 
387
    }
 
388
  
 
389
  aBOOL = NO;
 
390
 
 
391
  // We want to create a mailbox store; check if it already exists.
 
392
  if ( [aFileManager fileExistsAtPath: pathToFile
 
393
                     isDirectory: &isDir] )
 
394
    {
 
395
      int size;
 
396
      
 
397
      size = [[[aFileManager fileAttributesAtPath: pathToFile
 
398
                             traverseLink: NO] objectForKey: NSFileSize] intValue];
 
399
 
 
400
      // If we got an empty file or simply a directory...
 
401
      if ( size == 0 || isDir )
 
402
        {
 
403
          NSString *aString;
 
404
          
 
405
          // If the size is 0, that means we have an empty file. We first convert this
 
406
          // file to a directory.
 
407
          if ( size == 0 )
 
408
            {
 
409
              [aFileManager removeFileAtPath: pathToFile  handler: nil];
 
410
              [aFileManager createDirectoryAtPath: pathToFile  attributes: nil];
 
411
            }
 
412
          
 
413
          // We can now proceed with the creation of our store.
 
414
          // Check the type of store we want to create
 
415
          switch (theType)
 
416
            {
 
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];
 
422
                                                                    
 
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];
 
427
              
 
428
              // new
 
429
              aString = [NSString stringWithFormat: @"%@/%@/new", [self path], theName];
 
430
              aBOOL = aBOOL & [aFileManager createDirectoryAtPath: aString  attributes: nil];
 
431
              [self enforceMode: 0700  atPath: aString];
 
432
 
 
433
              // tmp
 
434
              aString = [NSString stringWithFormat: @"%@/%@/tmp", [self path], theName];
 
435
              aBOOL = aBOOL & [aFileManager createDirectoryAtPath: aString  attributes: nil];
 
436
              [self enforceMode: 0700  atPath: aString];
 
437
              break;
 
438
              
 
439
            case MAILBOX_FORMAT_MBOX:
 
440
            default:
 
441
              aBOOL = [aFileManager createFileAtPath: [NSString stringWithFormat: @"%@/%@",
 
442
                                                                [self path], theName]
 
443
                                    contents: theContents
 
444
                                    attributes: nil ];
 
445
              
 
446
              // We now enforce the mode (0600) on this new mailbox
 
447
              [self enforceMode: 0600
 
448
                    atPath: [NSString stringWithFormat: @"%@/%@", [self path], theName]];
 
449
              break;                              
 
450
            }
 
451
          
 
452
          // rebuild the folder list
 
453
          [self _rebuildFolderEnumerator];
 
454
        }
 
455
      else
 
456
        {
 
457
          aBOOL = NO;
 
458
        }
 
459
    }
 
460
              
291
461
  return aBOOL;
292
462
}
293
463
 
294
 
//
295
 
//
 
464
 
 
465
//
 
466
// theName must be the full path of the mailbox.
 
467
//
 
468
// Returns YES on success. NO otherwise.
296
469
//
297
470
- (BOOL) deleteFolderWithName: (NSString *) theName
298
471
{
299
 
  BOOL aBOOL;
300
 
  
301
 
  // We remove the mbox
302
 
  aBOOL = [[NSFileManager defaultManager] removeFileAtPath: [NSString stringWithFormat: @"%@/%@",
303
 
                                                                      [self path], theName]
304
 
                                          handler: nil];
305
 
  
306
 
  // We remove the cache
307
 
  [[NSFileManager defaultManager] removeFileAtPath: [NSString stringWithFormat: @"%@/.%@.cache",
308
 
                                                              [self path], theName]
309
 
                                  handler: nil];
310
 
  
311
 
  return aBOOL;
 
472
  NSFileManager *aFileManager;
 
473
  BOOL aBOOL, isDir;
 
474
  
 
475
  aFileManager = [NSFileManager defaultManager];
 
476
  aBOOL = NO;
 
477
 
 
478
  if ( [aFileManager fileExistsAtPath: [NSString stringWithFormat: @"%@/%@", [self path], theName]
 
479
                     isDirectory: &isDir] )
 
480
    {
 
481
      if ( isDir )
 
482
        {
 
483
          NSEnumerator *theEnumerator;
 
484
          NSArray *theEntries, *dirContents;
 
485
          
 
486
          theEnumerator = [aFileManager enumeratorAtPath: [NSString stringWithFormat: @"%@/%@",
 
487
                                                                    [self path], theName]];
 
488
          
 
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 )
 
495
            {
 
496
              aBOOL = [aFileManager removeFileAtPath: [NSString stringWithFormat: @"%@/%@",
 
497
                                                               [self path], theName]
 
498
                                   handler: nil];
 
499
              
 
500
              // Rebuild the folder tree
 
501
              if(aBOOL == YES)
 
502
                  [self _rebuildFolderEnumerator];
 
503
 
 
504
              return (aBOOL);
 
505
 
 
506
            }
 
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])
 
511
            {
 
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] )
 
515
                {
 
516
                  return NO;
 
517
                }
 
518
              if ( ![aFileManager fileExistsAtPath: [NSString stringWithFormat: @"%@/%@/tmp", [self path], theName]
 
519
                                  isDirectory: &isDir] )
 
520
                {
 
521
                  return NO;
 
522
                }
 
523
            }
 
524
          else
 
525
            {
 
526
              return NO;
 
527
            }
 
528
        }
 
529
 
 
530
      // We remove the mbox or maildir store
 
531
      aBOOL = [aFileManager removeFileAtPath: [NSString stringWithFormat: @"%@/%@",
 
532
                                                        [self path], theName]
 
533
                            handler: nil];
 
534
      
 
535
      // We remove the cache, if the store deletion was successful
 
536
      if ( aBOOL )
 
537
        {
 
538
          NSString *aString;
 
539
 
 
540
          aString = [theName lastPathComponent];
 
541
          
 
542
          [[NSFileManager defaultManager] removeFileAtPath: [NSString stringWithFormat: @"%@/%@.%@.cache",
 
543
                                                                      [self path],
 
544
                                                                      [theName substringToIndex:
 
545
                                                                                 ([theName length] - [aString length])],
 
546
                                                                      aString]
 
547
                                          handler: nil];
 
548
        }
 
549
 
 
550
          // Rebuild the folder tree
 
551
          [self _rebuildFolderEnumerator];
 
552
    }
 
553
  
 
554
  return aBOOL;
 
555
}
 
556
 
 
557
 
 
558
//
 
559
// theName and theNewName MUST be the full path of those mailboxes.
 
560
//
 
561
// Returns YES on success. NO otherwise.
 
562
//
 
563
- (BOOL) renameFolderWithName: (NSString *) theName
 
564
                       toName: (NSString *) theNewName
 
565
{
 
566
  NSFileManager *aFileManager;
 
567
  BOOL aBOOL, isDir;
 
568
  
 
569
  aFileManager = [NSFileManager defaultManager];
 
570
  aBOOL = NO;
 
571
 
 
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]] )
 
575
    {
 
576
      return NO;
 
577
    }
 
578
 
 
579
  // We verify if the source path is valid
 
580
  if ( [aFileManager fileExistsAtPath: [NSString stringWithFormat: @"%@/%@", [self path], theName]
 
581
                     isDirectory: &isDir] )
 
582
    {
 
583
      if ( isDir )
 
584
        {
 
585
          NSEnumerator *theEnumerator;
 
586
          NSArray *theEntries;
 
587
          
 
588
          theEnumerator = [aFileManager enumeratorAtPath: [NSString stringWithFormat: @"%@/%@",
 
589
                                                                    [self path], theName]];
 
590
          
 
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];
 
594
          
 
595
          if ( [theEntries count] == 0 )
 
596
            {
 
597
              return [aFileManager movePath: [NSString stringWithFormat: @"%@/%@",[self path], theName]
 
598
                                   toPath:  [NSString stringWithFormat: @"%@/%@",  [self path], theNewName]
 
599
                                   handler: nil];
 
600
            }
 
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])
 
605
            {
 
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] )
 
609
                {
 
610
                  return NO;
 
611
                }
 
612
              if ( ![aFileManager fileExistsAtPath: [NSString stringWithFormat: @"%@/%@/tmp", [self path], theName]
 
613
                                  isDirectory: &isDir] )
 
614
                {
 
615
                  return NO;
 
616
                }
 
617
          }
 
618
          else
 
619
            {
 
620
              return NO;
 
621
            }
 
622
        }
 
623
      
 
624
      // We rename the mail store
 
625
      aBOOL = [aFileManager movePath: [NSString stringWithFormat: @"%@/%@", [self path], theName]
 
626
                            toPath: [NSString stringWithFormat: @"%@/%@", [self path], theNewName]
 
627
                            handler: nil];
 
628
      
 
629
      // We remove the cache, if the store rename was successful
 
630
      if ( aBOOL )
 
631
        {
 
632
          NSString *str1, *str2;
 
633
 
 
634
          str1 = [theName lastPathComponent];
 
635
          str2 = [theNewName lastPathComponent];
 
636
          
 
637
          [[NSFileManager defaultManager] movePath: [NSString stringWithFormat: @"%@/%@.%@.cache",
 
638
                                                              [self path],
 
639
                                                              [theName substringToIndex:
 
640
                                                                         ([theName length] - [str1 length])],
 
641
                                                              str1]
 
642
                                          toPath: [NSString stringWithFormat: @"%@/%@.%@.cache",
 
643
                                                            [self path],
 
644
                                                            [theNewName substringToIndex:
 
645
                                                                          ([theNewName length] - [str2 length])],
 
646
                                                            str2]
 
647
                                          handler: nil];
 
648
        }
 
649
      
 
650
      // Rebuild the folder tree
 
651
      [self _rebuildFolderEnumerator];
 
652
    }
 
653
  
 
654
  return aBOOL;
 
655
}
 
656
 
 
657
 
 
658
//
 
659
//
 
660
//
 
661
- (void) enforceMode: (unsigned long) theMode
 
662
              atPath: (NSString *) thePath
 
663
 
 
664
{
 
665
  NSMutableDictionary *currentFileAttributes;
 
666
  
 
667
  unsigned long current_attributes, desired_attributes;
 
668
  
 
669
  
 
670
  currentFileAttributes = [[NSMutableDictionary alloc] initWithDictionary: [fileManager fileAttributesAtPath: thePath
 
671
                                                                                        traverseLink: YES]];
 
672
  
 
673
  current_attributes = [currentFileAttributes filePosixPermissions];
 
674
  desired_attributes = theMode;
 
675
  
 
676
  if ( current_attributes != desired_attributes )
 
677
    {
 
678
      [currentFileAttributes setObject: [NSNumber numberWithUnsignedLong: desired_attributes]
 
679
                             forKey: NSFilePosixPermissions];
 
680
      
 
681
      [fileManager changeFileAttributes: currentFileAttributes
 
682
                   atPath: thePath];
 
683
    }
 
684
 
 
685
  RELEASE(currentFileAttributes);
 
686
}
 
687
 
 
688
 
 
689
//
 
690
//
 
691
//
 
692
- (BOOL) isConnected
 
693
{
 
694
  return YES;
 
695
}
 
696
 
 
697
@end
 
698
 
 
699
 
 
700
//
 
701
// Private interface
 
702
//
 
703
@implementation LocalStore (Private)
 
704
 
 
705
- (void) _enforceFileAttributes
 
706
{
 
707
  NSEnumerator *anEnumerator;
 
708
  NSAutoreleasePool *pool;
 
709
  NSString *aString;
 
710
 
 
711
  pool = [[NSAutoreleasePool alloc] init];
 
712
 
 
713
  //
 
714
  // We verify if our Store path's mode is 0700
 
715
  //
 
716
  [self enforceMode: 0700  atPath: [self path]];
 
717
  
 
718
  //
 
719
  // We ensure that all subdirectories are using mode 0700 and files are using mode 0600
 
720
  //
 
721
  anEnumerator = [self folderEnumerator];
 
722
 
 
723
  while ( (aString = [anEnumerator nextObject]) )
 
724
    {
 
725
      BOOL isDir;
 
726
      
 
727
      aString = [NSString stringWithFormat: @"%@/%@", [self path], aString];
 
728
      
 
729
      if ( [fileManager fileExistsAtPath: aString
 
730
                        isDirectory: &isDir] )
 
731
        {
 
732
          if ( isDir )
 
733
            {
 
734
              [self enforceMode: 0700
 
735
                    atPath: aString];
 
736
            }
 
737
          else
 
738
            {
 
739
              [self enforceMode: 0600
 
740
                    atPath: aString];
 
741
            }
 
742
        }
 
743
    } 
 
744
 
 
745
  RELEASE(pool);
 
746
}
 
747
 
 
748
 
 
749
//
 
750
// Rebuild the folder hierarchy
 
751
//
 
752
- (NSEnumerator *) _rebuildFolderEnumerator
 
753
{
 
754
  NSString *aString, *lastPathComponent, *pathToFolder; 
 
755
  NSEnumerator *tmpEnumerator;
 
756
  NSArray *tmpArray;
 
757
  int i;
 
758
  
 
759
  // Clear out our cached folder structure and refresh from the file system
 
760
  [folderArray removeAllObjects];
 
761
  [folderArray setArray: [[fileManager enumeratorAtPath: [self path]] allObjects]];
 
762
  
 
763
  //
 
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
 
769
  //
 
770
  for (i = 0; i< [folderArray count]; i++)
 
771
    {
 
772
      BOOL bIsMailDir;
 
773
      
 
774
      aString = [folderArray objectAtIndex: i];
 
775
      
 
776
      lastPathComponent = [aString lastPathComponent];
 
777
      pathToFolder = [aString substringToIndex: ([aString length] - [lastPathComponent length])];
 
778
    
 
779
      //
 
780
      // First run:
 
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.
 
783
      //
 
784
      if ( [[NSFileManager defaultManager] fileExistsAtPath: [NSString stringWithFormat: @"%@/%@/cur", 
 
785
                                                                       [self path], aString] 
 
786
                                           isDirectory: &bIsMailDir] && bIsMailDir )
 
787
        {
 
788
          NSDirectoryEnumerator *maildirEnumerator;
 
789
          NSArray *subpaths;
 
790
        
 
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]];
 
794
 
 
795
          [self enforceMode: 0700
 
796
                atPath: [NSString stringWithFormat: @"%@/%@/new", [self path], aString]];
 
797
          
 
798
          [self enforceMode: 0700
 
799
                atPath: [NSString stringWithFormat: @"%@/%@/tmp", [self path], aString]];
 
800
          
 
801
          
 
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]];
 
806
          
 
807
          subpaths = [[NSFileManager defaultManager] subpathsAtPath: [NSString stringWithFormat: @"%@/%@", 
 
808
                                                                               [self path], aString]];
 
809
          [folderArray removeObjectsInRange: NSMakeRange(i+1,[subpaths count])];
 
810
        }
 
811
    }
 
812
  
 
813
  //
 
814
  // Second Run: Get rid of cache, summary and OS specific stuff
 
815
  //
 
816
  tmpArray = [[NSArray alloc] initWithArray: folderArray];
 
817
  AUTORELEASE(tmpArray);
 
818
  tmpEnumerator = [tmpArray objectEnumerator];
 
819
  
 
820
  while ( (aString = [tmpEnumerator nextObject]) )
 
821
    {
 
822
      lastPathComponent = [aString lastPathComponent];
 
823
      pathToFolder = [aString substringToIndex: ([aString length] - [lastPathComponent length])];
 
824
      
 
825
      // We remove Netscape/Mozilla summary file.
 
826
      [folderArray removeObject: [NSString stringWithFormat: @"%@.%@.summary", pathToFolder, lastPathComponent]];
 
827
      
 
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]];
 
832
 
 
833
      // We also remove Apple Mac OS X .DS_Store directory
 
834
      [folderArray removeObject: [NSString stringWithFormat: @"%@.DS_Store", pathToFolder]];
 
835
    }
 
836
  
 
837
  return [folderArray objectEnumerator];
312
838
}
313
839
 
314
840
@end