Logo Search packages:      
Sourcecode: zipper.app version File versions  Download package

Archive.m

#import <Foundation/Foundation.h>
#import "Archive.h"
#import "FileInfo.h"
#import "NSString+Custom.h"
#import "NSObject+Custom.h"
#import "Preferences.h"

#define X_EXE_NOT_FOUND @"ExecutableNotFoundException"

/**
 * This dictionary holds all the file extensions that Archive and its subclasses
 * are able to decompress. Archive subclasses register themselves with 
 * the Archive class.
 */
static NSMutableDictionary *_fileExtMappings = nil;

@interface Archive (PrivateAPI)
- (void)sortElementsBySortOrder:(int) sortOrder selector:(SEL)selector;
@end

@implementation Archive : NSObject

+ (void)initialize
{
      if (_fileExtMappings == nil)
      {
            _fileExtMappings = [[NSMutableDictionary alloc] init];
      }
}

/**
 * All subclasses must register the file extensions they support with the Archive
 * class. This faciliates dynamic addition of Archive subclasses and helps
 * the app discover who's responsible for certain file extensions.
 */
+ (void)registerFileExtension:(NSString *)extension forArchiveClass:(Class)clazz
{
      [_fileExtMappings setObject:clazz forKey:extension];
}

+ (Class)classForFileExtension:(NSString *)fileExtension;
{
      return [_fileExtMappings objectForKey:fileExtension];
}

+ (NSArray *)allFileExtensions;
{
      return [_fileExtMappings allKeys];
}

/**
 * Returns YES if this kind of archives contains information about the compression ratio of
 * the archive, else NO.
 */
+ (BOOL)hasRatio
{
      return NO;
}

/**
 * Returns YES if this kind of archiver can uncopress files 'flat' i.e. without directory
 * information, else NO.
 */
+ (BOOL)canExtractWithoutFullPath
{
      return YES;
}

+ (Archive *)newWithPath:(NSString *)path
{
    NSParameterAssert(path != nil);
    return [[[self alloc] initWithPath:path] autorelease];
}

- (id)initWithPath:(NSString *)path
{
    [super init];
    _path = [path retain];
    _elements = nil;
      _sortOrder = NSOrderedAscending;
      _sortAttribute = NSNotFound;
    return self;
}

- (void)dealloc
{
    [_path release];
    [_elements release];
      [super dealloc];
}

- (NSString *)path
{
      return _path;
}

//------------------------------------------------------------------------------
// managing our elements
//------------------------------------------------------------------------------
- (NSArray *)elements
{
    if (_elements == nil)
    {
        [self setElements:[self listContents]];
    }
    return _elements;
}

- (void)setElements:(NSArray *)elements
{
      ASSIGN(_elements, elements);
}

- (int)elementCount
{
    return [[self elements] count];
}

- (FileInfo *)elementAtIndex:(int)index
{
    return [[self elements] objectAtIndex:index];
}

//------------------------------------------------------------------------------
// sorting our elements
//------------------------------------------------------------------------------
- (void)sortByPath
{
      NSArray * sortedElements = nil;
      
      // make sure we start by ordering in descending order when this column is clicked first
      if (_sortAttribute != SortByPath)
      {
            _sortAttribute = SortByPath;
            _sortOrder = NSOrderedDescending;
      }
      
      if (_sortOrder == NSOrderedAscending)
      {
            sortedElements = [[self elements]
                  sortedArrayUsingSelector:@selector(comparePathDescending:)];
            _sortOrder = NSOrderedDescending;
      }
      else
      {
            sortedElements = [[self elements]
                  sortedArrayUsingSelector:@selector(comparePathAscending:)];
            _sortOrder = NSOrderedAscending;
      }
      [self setElements:sortedElements];
}

- (void)sortBySize
{
      NSArray *sortedElements;

      // make sure we start by ordering in descending order when this column is clicked first
      if (_sortAttribute != SortBySize)
      {
            _sortAttribute = SortBySize;
            _sortOrder = NSOrderedDescending;
      }

      if (_sortOrder == NSOrderedAscending)
      {
            sortedElements = [[self elements]
                  sortedArrayUsingSelector:@selector(compareSizeDescending:)];
            _sortOrder = NSOrderedDescending;
      }
      else
      {
            sortedElements = [[self elements]
                  sortedArrayUsingSelector:@selector(compareSizeAscending:)];
            _sortOrder = NSOrderedAscending;
      }
            
      [self setElements:sortedElements];
}

- (void)sortByFilename
{
      NSArray *sortedElements;
      
      // make sure we start by ordering in descending order when this column is clicked first
      if (_sortAttribute != SortByFilename)
      {
            _sortAttribute = SortByFilename;
            _sortOrder = NSOrderedDescending;
      }

      if (_sortOrder == NSOrderedAscending)
      {
            sortedElements = [[self elements]
                  sortedArrayUsingSelector:@selector(compareFilenameDescending:)];
            _sortOrder = NSOrderedDescending;
      }
      else
      {
            sortedElements = [[self elements]
                  sortedArrayUsingSelector:@selector(compareFilenameAscending:)];
            _sortOrder = NSOrderedAscending;
      }
      [self setElements:sortedElements];
}

- (void)sortByDate
{
      NSArray *sortedElements;
      
      // make sure we start by ordering in descending order when this column is clicked first
      if (_sortAttribute != SortByDate)
      {
            _sortAttribute = SortByDate;
            _sortOrder = NSOrderedDescending;
      }

      if (_sortOrder == NSOrderedAscending)
      {
            sortedElements = [[self elements]
                  sortedArrayUsingSelector:@selector(compareDateDescending:)];
            _sortOrder = NSOrderedDescending;
      }
      else
      {
            sortedElements = [[self elements]
                  sortedArrayUsingSelector:@selector(compareDateAscending:)];
            _sortOrder = NSOrderedAscending;
      }
      [self setElements:sortedElements];
}

- (void)sortByRatio
{
      NSArray *sortedElements;
      
      // make sure we start by ordering in descending order when this column is clicked first
      if (_sortAttribute != SortByRatio)
      {
            _sortAttribute = SortByRatio;
            _sortOrder = NSOrderedDescending;
      }

      if (_sortOrder == NSOrderedAscending)
      {
            sortedElements = [[self elements]
                  sortedArrayUsingSelector:@selector(compareRatioDescending:)];
            _sortOrder = NSOrderedDescending;
      }
      else
      {
            sortedElements = [[self elements]
                  sortedArrayUsingSelector:@selector(compareRatioAscending:)];
            _sortOrder = NSOrderedAscending;
      }
      [self setElements:sortedElements];
}

- (NSComparisonResult)sortOrder
{
      return _sortOrder;
}

//------------------------------------------------------------------------------
// expanding the archive
//------------------------------------------------------------------------------
- (int)expandFiles:(NSArray *)files withPathInfo:(BOOL)usePathInfo toPath:(NSString *)path
{
      [self methodIsAbstract:_cmd];
      // shut up the compiler
      return NSNotFound;
}

- (NSData *)dataByRunningUnachiverWithArguments:(NSArray *)args
{
    NSData *inData;
    NSFileHandle *readHandle;
    NSPipe *pipe;
    NSTask *task;
    NSMutableData *result;
    
      NSParameterAssert(args != nil);
      NSParameterAssert([[self class] executableDoesExist]);

    pipe = [NSPipe pipe];
    readHandle = [pipe fileHandleForReading];

    task = [[NSTask alloc] init];
    [task setLaunchPath:[[self class] unarchiveExecutable]];      
      [task setArguments:args];
    [task setStandardOutput:pipe];
    [task launch];

    result = [NSMutableData dataWithCapacity:1024];
    while ((inData = [readHandle availableData]) && [inData length])
    {
        [result appendData:inData];
    }
    [task release];
    
    return result;
}

- (int)runUnarchiverWithArguments:(NSArray *)args;
{
      return [[self class] runUnarchiverWithArguments:args inDirectory:nil];
}

+ (int)runUnarchiverWithArguments:(NSArray *)args inDirectory:(NSString *)workDir
{
      int result;
      NSTask *task;

      NSParameterAssert([self executableDoesExist]);
      
      task = [[NSTask alloc] init];
      [task setLaunchPath:[self unarchiveExecutable]];
      [task setArguments:args];
      if (workDir != nil)
      {
            [task setCurrentDirectoryPath:workDir];
      }
      [task launch];
      [task waitUntilExit];
      
      result = [task terminationStatus];
      [task release];
      return result;
}

- (NSArray *)listContents
{
      [self methodIsAbstract:_cmd];
      // shut up the compiler
      return nil;
}

+ (BOOL)executableDoesExist
{
      NSString *exePath;
      
      exePath = [self unarchiveExecutable];
      if (exePath == nil) 
      {
            return NO;
      }
      return [[NSFileManager defaultManager] isExecutableFileAtPath:exePath];
}

/**
 * Returns the full path to the executable that's used to extract the archive. This method
 * raises an exception indicating that subclasses have to override it.
 */
+ (NSString *)unarchiveExecutable
{
      [self methodIsAbstract:_cmd];
      // shut up the compiler
      return nil;
}

/**
 * Returns the user presentable name for this kind of archive. This method raises an exception
 * indicating that subclasses have to override it.
 */
+ (NSString *)archiveType
{
      [self methodIsAbstract:_cmd];
      return nil;
}

@end

Generated by  Doxygen 1.6.0   Back to index