source: trunk/Sparkle/SUPipedUnarchiver.m @ 1046

Revision 128, 3.2 KB checked in by speck, 4 years ago (diff)

Fixed missing display of update notes in Sparkle. Embedded Sparkle so subversion has the proper version instead of having to download Sparkle and apply several patches.

Line 
1//
2//  SUPipedUnarchiver.m
3//  Sparkle
4//
5//  Created by Andy Matuschak on 6/16/08.
6//  Copyright 2008 Andy Matuschak. All rights reserved.
7//
8
9#import "SUPipedUnarchiver.h"
10#import "SUUnarchiver_Private.h"
11
12@implementation SUPipedUnarchiver
13
14+ (SEL)_selectorConformingToTypeOfPath:(NSString *)path
15{
16    static NSDictionary *typeSelectorDictionary;
17    if (!typeSelectorDictionary)
18        typeSelectorDictionary = [[NSDictionary dictionaryWithObjectsAndKeys:@"_extractZIP", @".zip", @"_extractTAR", @".tar",
19                                   @"_extractTGZ", @".tar.gz", @"_extractTGZ", @".tgz",
20                                   @"_extractTBZ", @".tar.bz2", @"_extractTBZ", @".tbz", nil] retain];
21
22    NSString *lastPathComponent = [path lastPathComponent];
23    NSEnumerator *typeEnumerator = [typeSelectorDictionary keyEnumerator];
24    id currentType;
25    while ((currentType = [typeEnumerator nextObject]))
26    {
27        if ([currentType length] > [lastPathComponent length]) continue;
28        if ([[lastPathComponent substringFromIndex:[lastPathComponent length] - [currentType length]] isEqualToString:currentType])
29            return NSSelectorFromString([typeSelectorDictionary objectForKey:currentType]);
30    }
31    return NULL;
32}
33
34- (void)start
35{
36    [NSThread detachNewThreadSelector:[[self class] _selectorConformingToTypeOfPath:archivePath] toTarget:self withObject:nil];
37}
38
39+ (BOOL)_canUnarchivePath:(NSString *)path
40{
41    return ([self _selectorConformingToTypeOfPath:path] != nil);
42}
43
44// This method abstracts the types that use a command line tool piping data from stdin.
45- (void)_extractArchivePipingDataToCommand:(NSString *)command
46{
47    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
48    FILE *fp = NULL, *cmdFP = NULL;
49   
50    // Get the file size.
51    NSNumber *fs = [[[NSFileManager defaultManager] fileAttributesAtPath:archivePath traverseLink:NO] objectForKey:NSFileSize];
52    if (fs == nil) goto reportError;
53   
54    // Thank you, Allan Odgaard!
55    // (who wrote the following extraction alg.)
56    fp = fopen([archivePath fileSystemRepresentation], "r");
57    if (!fp) goto reportError;
58   
59    setenv("DESTINATION", [[archivePath stringByDeletingLastPathComponent] fileSystemRepresentation], 1);
60    cmdFP = popen([command fileSystemRepresentation], "w");
61    if (!cmdFP) goto reportError;
62   
63    char buf[32*1024];
64    long len;
65    while((len = fread(buf, 1, 32*1024, fp)))
66    {               
67        fwrite(buf, 1, len, cmdFP);
68        [self performSelectorOnMainThread:@selector(_notifyDelegateOfExtractedLength:) withObject:[NSNumber numberWithLong:len] waitUntilDone:NO];
69    }
70    pclose(cmdFP);
71   
72    [self performSelectorOnMainThread:@selector(_notifyDelegateOfSuccess) withObject:nil waitUntilDone:NO];
73    goto finally;
74   
75reportError:
76    [self performSelectorOnMainThread:@selector(_notifyDelegateOfFailure) withObject:nil waitUntilDone:NO];
77   
78finally:
79    if (fp)
80        fclose(fp);
81    [pool drain];
82}
83
84- (void)_extractTAR
85{
86    return [self _extractArchivePipingDataToCommand:@"tar -xC \"$DESTINATION\""];
87}
88
89- (void)_extractTGZ
90{
91    return [self _extractArchivePipingDataToCommand:@"tar -zxC \"$DESTINATION\""];
92}
93
94- (void)_extractTBZ
95{
96    return [self _extractArchivePipingDataToCommand:@"tar -jxC \"$DESTINATION\""];
97}
98
99- (void)_extractZIP
100{
101    return [self _extractArchivePipingDataToCommand:@"ditto -x -k - \"$DESTINATION\""];
102}
103
104+ (void)load
105{
106    [self _registerImplementation:self];
107}
108
109@end
Note: See TracBrowser for help on using the repository browser.