/* Copyright (C) 2000-2005 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ImapListTool.h" #include "common.h" #include #include #include #include @implementation ImapListTool /* output */ - (BOOL)outputResultsAsList:(NSArray *)dirContents fileManager:(NGImap4FileManager *)fm part:(NSString *)_part { unsigned i, count; NSString *path = [fm currentDirectoryPath]; for (i = 0, count = [dirContents count]; i < count; i++) { NSString *cpath, *apath; NSDictionary *info; NSString *mid; if (!self->useDataSource) { cpath = [dirContents objectAtIndex:i]; apath = [path stringByAppendingPathComponent:cpath]; info = [fm fileAttributesAtPath:apath traverseLink:NO]; } else { info = [dirContents objectAtIndex:i]; cpath = [NSString stringWithFormat:@"%u", [(id)info uid]]; apath = [path stringByAppendingPathComponent:cpath]; //cpath = [info valueForKey:@"NSFileName"]; //apath = [info valueForKey:@"NSFilePath"]; } mid = [[info valueForKey:@"NSFileIdentifier"] description]; if ([mid length] > 39) { mid = [mid substringToIndex:37]; mid = [mid stringByAppendingString:@"..."]; } /* id uid date name */ if (_part) { printf("%10d ", [[fm contentsAtPath:[info valueForKey:@"NSFilePath"] part:_part] length]); } printf("%-40s %8s %8i %-32s %s", [mid cString], [[info valueForKey:NSFileOwnerAccountName] cString], [[info valueForKey:NSFileSize] intValue], [[[info valueForKey:NSFileModificationDate] description] cString], [apath cString]); if ([[info valueForKey:NSFileType] isEqualToString:NSFileTypeDirectory]) printf("/\n"); else printf("\n"); } return YES; } - (BOOL)outputResultsAsXML:(NSArray *)_dirContents fileManager:(NGFileManager *)_fm { NSLog(@"XML output not implemented ..."); return NO; } - (BOOL)outputResults:(NSArray *)dirContents fileManager:(NGImap4FileManager *)fm part:(NSString *)_part { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; NSAutoreleasePool *pool; NSString *out; BOOL result; pool = [[NSAutoreleasePool alloc] init]; out = [ud stringForKey:@"out"]; if ([out length] == 0) result = YES; else if ([out isEqualToString:@"xml"]) result = [self outputResultsAsXML:dirContents fileManager:fm]; else if ([out isEqualToString:@"ls"]) result = [self outputResultsAsList:dirContents fileManager:fm part:_part]; else { NSLog(@"unknown output module: %@", out); result = NO; } [pool release]; return result; } /* ops */ - (void)processFile:(NSString *)path fileManager:(NGImap4FileManager *)fm part:(NSString *)_part { /* a file */ NSData *contents; NSString *s; if (_part) { if ((contents = [fm contentsAtPath:path part:_part]) == nil) { NSLog(@"could not get content of message: '%@'", path); } else { s = [[NSString alloc] initWithData:contents encoding:[NSString defaultCStringEncoding]]; printf("%s\n", [s cString]); [s release]; } } else { NGImap4Message *contents; if ((contents = [fm messageAtPath:path]) == nil) { NSLog(@"could not get message at path: '%@'", path); } else { #if 0 s = [[NSString alloc] initWithData:contents encoding:[NSString defaultCStringEncoding]]; printf("%s\n", [s cString]); [s release]; #else printf("%s\n", [[contents description] cString]); printf("%s\n", [[[contents bodyStructure] description] cString]); #endif } } } - (void)processFolder:(NSString *)path fileManager:(NGImap4FileManager *)fm part:(NSString *)_part { NSAutoreleasePool *pool; NSTimeInterval startTime, endTime; unsigned int startSize, endSize; NSProcessInfo *pi = [NSProcessInfo processInfo]; NSArray *dirContents; unsigned i; EODataSource *ds; if (![fm changeCurrentDirectoryPath:path]) { NSLog(@"%s: could not change to directory: '%@'", path); } ds = self->useDataSource ? [(id)fm dataSourceAtPath:path] : nil; /* pre fetches */ for (i = 0; i < self->preloops; i++ ) { NSAutoreleasePool *pool; startTime = [[NSDate date] timeIntervalSince1970]; startSize = [pi virtualMemorySize]; /* fetch */ pool = [[NSAutoreleasePool alloc] init]; { ds = self->useDataSource ? [(id)fm dataSourceAtPath:path] : nil; dirContents = (!self->useDataSource) ? [fm directoryContentsAtPath:path] : [ds fetchObjects]; } [pool release]; /* statistics */ endSize = [pi virtualMemorySize]; endTime = [[NSDate date] timeIntervalSince1970]; if (self->stats) { fprintf(stderr, "parsing time [%2i]: %.3fs, " "vmem-diff: %8i (%4iK,%4iM), vmem: %8i (%4iK,%4iM))\n", i, (endTime-startTime), (endSize - startSize), (endSize - startSize) / 1024, (endSize - startSize) / 1024 / 1024, endSize, endSize/1024, endSize/1024/1024); } } /* actual fetch */ startTime = [[NSDate date] timeIntervalSince1970]; startSize = [pi virtualMemorySize]; pool = [[NSAutoreleasePool alloc] init]; ds = self->useDataSource ? [(id)fm dataSourceAtPath:path] : nil; dirContents = (!self->useDataSource) ? [fm directoryContentsAtPath:path] : [ds fetchObjects]; dirContents = [dirContents retain]; [pool release]; dirContents = [dirContents autorelease]; /* statistics */ endSize = [pi virtualMemorySize]; endTime = [[NSDate date] timeIntervalSince1970]; if (self->stats) { fprintf(stderr, "parsing time: %.3fs, " "vmem-diff: %8i (%4iK,%4iM), vmem: %8i (%4iK,%4iM))\n", (endTime-startTime), (endSize - startSize), (endSize - startSize) / 1024, (endSize - startSize) / 1024 / 1024, endSize, endSize/1024, endSize/1024/1024); } /* output */ [self outputResults:dirContents fileManager:fm part:_part]; } /* path /INBOX/1233?part=1.2 */ - (void)processPath:(NSString *)path fileManager:(NGImap4FileManager *)fm { BOOL isDir; NSArray *array; NSString *part; array = [path componentsSeparatedByString:@"?"]; if ([array count] > 1) { path = [array objectAtIndex:0]; part = [[[array objectAtIndex:1] componentsSeparatedByString:@"="] lastObject]; } else part = nil; if (![fm fileExistsAtPath:path isDirectory:&isDir]) { NSLog(@"file/directory does not exist: %@", path); return; } if (isDir) { [self processFolder:path fileManager:fm part:part]; } else { [self processFile:path fileManager:fm part:part]; } } /* tool operation */ - (int)usage { fprintf(stderr, "usage: imapls ?part=\n"); fprintf(stderr, "usage: imapls \n"); fprintf(stderr, " -url \n"); fprintf(stderr, " -user \n"); fprintf(stderr, " -password \n"); fprintf(stderr, " -host \n"); fprintf(stderr, " -datasource YES|NO\n"); fprintf(stderr, " -out ls|xml\n"); fprintf(stderr, " -statistics YES|NO\n"); fprintf(stderr, " -preloops \n"); return 1; } - (int)runWithArguments:(NSArray *)_args { NGImap4FileManager *fm; NSUserDefaults *ud; int i; _args = [_args subarrayWithRange:NSMakeRange(1, [_args count] - 1)]; if ([_args count] == 0) return [self usage]; ud = [NSUserDefaults standardUserDefaults]; self->useDataSource = [ud boolForKey:@"datasource"]; self->stats = [ud boolForKey:@"statistics"]; self->preloops = [ud integerForKey:@"preloops"]; if ((fm = [self fileManager]) == nil) { NSLog(@"could not open IMAP connection (got no filemanager)"); return 2; } #if 1 NSLog(@"IMAP: %@", fm); #endif for (i = 0; i < [_args count]; i++) { [self processPath:[_args objectAtIndex:i] fileManager:fm]; } return 0; } @end /* ImapListTool */