Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add network stream support #14

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
.PHONY: all clean test deploy

SRC_FILES = src/aastuff.m src/aea.m src/args.m src/extract.m src/extract_standalone.m src/utils.m
SRC_FILES = src/aastuff.m src/aea.m src/args.m src/extract.m src/extract_standalone.m src/network.m src/utils.m
SRC_FILES_SWIFT =
OBJ_FILES_SWIFT = $(patsubst src/%.swift,obj/%.o,$(SRC_FILES_SWIFT))
HDR_FILES = include/AppleArchivePrivate.h include/OSISAEAExtractor.h \
include/aea.h include/args.h include/extract.h include/extract_standalone.h include/utils.h $(HDR_SWIFT)
include/aea.h include/args.h include/extract.h include/extract_standalone.h include/network.h include/utils.h $(HDR_SWIFT)

CFLAGS = -fmodules -fobjc-arc -Iinclude -Iobj -Wall -Werror -Wunreachable-code
LDLIBS = -framework Foundation -lAppleArchive
Expand Down
2 changes: 2 additions & 0 deletions include/args.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ typedef NS_ENUM(NSInteger, PrivateKeyFormat) {

@property(nonatomic, assign) bool encrypted;
@property(nonatomic, assign) bool list;
@property(nonatomic, assign) bool remote;
@property(nonatomic, strong) NSString* archivePath;
@property(nonatomic, strong) NSString* outputPath;
@property(nonatomic, assign) bool decryptOnly;
@property(nonatomic, assign) bool exitEarly;
@property(nonatomic, strong) NSData* key;
@property(nonatomic, strong) NSString* filter;
@property(nonatomic, strong) NSRegularExpression* regex;
Expand Down
14 changes: 14 additions & 0 deletions include/network.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef NETWORK_H
#define NETWORK_H

#import <AppleArchive/AppleArchive.h>
#import <Foundation/Foundation.h>

bool checkAlive(NSString* url, NSError** error);

AAByteStream remote_archive_open(NSString* url);
int remote_archive_close(void* stream);
ssize_t remote_archive_read(void* stream, void* buf, size_t nbyte);
off_t remote_archive_seek(void* stream, off_t offset, int whence);

#endif /* NETWORK_H */
4 changes: 3 additions & 1 deletion include/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
#define NAME @"aastuff"
#endif

#define VERSION @"2.0.0"
#define VERSION @"2.1.0"

NSData* makeSynchronousRequestWithSession(NSURLSession* session, NSURLRequest* request, NSHTTPURLResponse** response, NSError** error);
NSData* makeSynchronousRequest(NSURLRequest* request, NSHTTPURLResponse** response, NSError** error);
NSData* getRange(NSString* url, NSRange range, NSError** error);

#endif /* UTILS_H */
19 changes: 15 additions & 4 deletions src/aastuff.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#import "args.h"
#import "extract.h"
#import "extract_standalone.h"
#import "network.h"
#import "utils.h"

int main(int argc, char** argv) {
Expand All @@ -19,10 +20,20 @@ int main(int argc, char** argv) {
return 1;
}

AAByteStream stream = AAFileStreamOpenWithPath(config.archivePath.UTF8String, O_RDONLY, 0644);
if (!stream) {
ERRLOG(@"Failed to open archive file stream");
return 1;
AAByteStream stream = NULL;
if (config.remote) {
stream = remote_archive_open(config.archivePath);
if (!stream) {
ERRLOG(@"Failed to open remote archive file stream");
return 1;
}

} else {
stream = AAFileStreamOpenWithPath(config.archivePath.UTF8String, O_RDONLY, 0644);
if (!stream) {
ERRLOG(@"Failed to open archive file stream");
return 1;
}
}

AAByteStream decryptionStream = NULL;
Expand Down
58 changes: 46 additions & 12 deletions src/args.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#import <Foundation/Foundation.h>
#import <getopt.h>

#import "network.h"
#import "utils.h"

#define APPLE_ARCHIVE_MAGIC @"AA01"
Expand Down Expand Up @@ -32,6 +33,8 @@ static void usage(void) {
ERRLOG(@" Filter files by glob pattern");
ERRLOG(@" -r, --regex <pattern>");
ERRLOG(@" Filter files by regex pattern");
ERRLOG(@" -e, --exit-early");
ERRLOG(@" Exit early after extracting the first matching file");
#endif
ERRLOG(@"Key Options:");
ERRLOG(@" -k, --key <base64>");
Expand Down Expand Up @@ -65,6 +68,7 @@ static void usage(void) {
#if AASTUFF_STANDALONE
{"filter", required_argument, 0, 'f'},
{"regex", required_argument, 0, 'r'},
{"exit-early", no_argument, 0, 'e'},
#endif
{"key", required_argument, 0, 'k'},
{"key-file", required_argument, 0, 'K'},
Expand All @@ -82,19 +86,21 @@ static void usage(void) {
int c;

bool list = false;
bool remote = false;
NSString* archivePath = nil;
NSString* outputPath = nil;
bool decryptOnly = false;
NSString* keyBase64 = nil;
NSString* keyPath = nil;
NSString* filter = nil;
NSString* regexString = nil;
bool exitEarly = false;
bool network = false;
NSString* unwrapKeyBase64 = nil;
NSString* unwrapKeyPath = nil;
NSString* unwrapKeyFormatString = nil;

while ((c = getopt_long(argc, argv, "-i:o:ldhvf:r:k:K:u:U:n", long_options, &option_index)) != -1) {
while ((c = getopt_long(argc, argv, "-i:o:ldhvf:r:ek:K:u:U:n", long_options, &option_index)) != -1) {
switch (c) {
case 'i':
archivePath = [NSString stringWithUTF8String:optarg];
Expand Down Expand Up @@ -125,6 +131,9 @@ static void usage(void) {
case 'r':
regexString = [NSString stringWithUTF8String:optarg];
break;
case 'e':
exitEarly = true;
break;
#endif
case 'k':
keyBase64 = [NSString stringWithUTF8String:optarg];
Expand Down Expand Up @@ -161,6 +170,10 @@ static void usage(void) {
return nil;
}

if ([@[@"http", @"https"] containsObject:[NSURL URLWithString:archivePath].scheme]) {
remote = true;
}

if (!list && !outputPath) {
ERRLOG(@"Output %@ is required", decryptOnly ? @"file path" : @"directory");
usage();
Expand Down Expand Up @@ -292,9 +305,11 @@ static void usage(void) {

ExtractionConfiguration* config = [[ExtractionConfiguration alloc] init];
config.list = list;
config.remote = remote;
config.archivePath = archivePath;
config.outputPath = outputPath;
config.decryptOnly = decryptOnly;
config.exitEarly = exitEarly;
config.key = key;
config.filter = filter;
config.regex = regex;
Expand All @@ -309,9 +324,16 @@ int validateArgs(ExtractionConfiguration* config) {
NSError* error = nil;
NSFileManager* fileManager = [NSFileManager defaultManager];

if (![fileManager fileExistsAtPath:config.archivePath]) {
ERRLOG(@"Archive does not exist");
return 1;
if (config.remote) {
if (!checkAlive(config.archivePath, &error)) {
ERRLOG(@"Failed to connect to server: %@", error);
return 1;
}
} else {
if (![fileManager fileExistsAtPath:config.archivePath]) {
ERRLOG(@"Archive does not exist");
return 1;
}
}

if (config.list) {
Expand All @@ -338,15 +360,21 @@ int validateArgs(ExtractionConfiguration* config) {
}
}

NSFileHandle* handle = [NSFileHandle fileHandleForReadingAtPath:config.archivePath];
if (!handle) {
ERRLOG(@"Failed to open archive file");
return 1;
}
NSData* magic = nil;

if (config.remote) {
magic = getRange(config.archivePath, NSMakeRange(0, 4), &error);
} else {
NSFileHandle* handle = [NSFileHandle fileHandleForReadingAtPath:config.archivePath];
if (!handle) {
ERRLOG(@"Failed to open archive file");
return 1;
}

NSData* magic = [handle readDataUpToLength:4 error:&error];
// If this fails, can't do anything about it, so just ignore the error
[handle closeAndReturnError:nil];
magic = [handle readDataUpToLength:4 error:&error];
// If this fails, can't do anything about it, so just ignore the error
[handle closeAndReturnError:nil];
}

if (!magic || magic.length != 4) {
ERRLOG(@"Failed to read magic: %@", error);
Expand Down Expand Up @@ -389,11 +417,17 @@ - (nonnull id)copyWithZone:(nullable NSZone*)zone {
ExtractionConfiguration* copy = [[ExtractionConfiguration alloc] init];
copy.encrypted = self.encrypted;
copy.list = self.list;
copy.remote = self.remote;
copy.archivePath = self.archivePath;
copy.outputPath = self.outputPath;
copy.decryptOnly = self.decryptOnly;
copy.exitEarly = self.exitEarly;
copy.key = self.key;
copy.filter = self.filter;
copy.regex = self.regex;
copy.network = self.network;
copy.unwrapKey = self.unwrapKey;
copy.unwrapKeyFormat = self.unwrapKeyFormat;

copy.function = self.function;
return copy;
Expand Down
20 changes: 18 additions & 2 deletions src/extract_standalone.m
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,18 @@ ssize_t nested_archive_read(void* stream, void* buf, size_t nbyte) {
}
#endif

static bool done = false;

static int aa_callback(void* arg, AAEntryMessage message, const char* path, void* data) {
ExtractionConfiguration* config = (__bridge ExtractionConfiguration*)arg;

DBGLOG(@"[%@] Message: %@ (%d), Path: %s", config.function, messageToString(message), message, path);

if (done) {
DBGLOG(@"[%@] Done", config.function);
return -1;
}

if (config.regex) {
NSUInteger ret = [config.regex numberOfMatchesInString:[NSString stringWithUTF8String:path] options:0
range:NSMakeRange(0, strlen(path))];
Expand Down Expand Up @@ -118,6 +125,11 @@ static int aa_callback(void* arg, AAEntryMessage message, const char* path, void
}
}

if (message == AA_ENTRY_MESSAGE_EXTRACT_END && config.exitEarly) {
DBGLOG(@"[%@] Path: %s finished, exiting early", config.function, path);
done = true;
}

// Continue
return 0;
}
Expand Down Expand Up @@ -192,7 +204,7 @@ int extractAssetStandalone(AAByteStream byteStream, ExtractionConfiguration* con
continue;
}

DBGLOG(@"Processing %c entry", (char)yop);
DBGLOG(@"Processing %c [%s] entry", (char)yop, lbl);

if (yop == AA_YOP_TYPE_EXTRACT || yop == AA_YOP_TYPE_DST_FIXUP) {
if (config.list && yop == AA_YOP_TYPE_DST_FIXUP) {
Expand Down Expand Up @@ -255,7 +267,11 @@ int extractAssetStandalone(AAByteStream byteStream, ExtractionConfiguration* con

if (AAArchiveStreamProcess(innerDecodeStream, extractStream, (void*)CFBridgingRetain([config copyWithFunction:@"PROCESS"]),
aa_callback, 0, 0) < 0) {
ERRLOG(@"Failed to process archive stream");
if (done) {
DBGLOG(@"Done processing");
} else {
ERRLOG(@"Failed to process archive stream");
}
AAArchiveStreamClose(extractStream);
CFRelease(configCopy);
AAArchiveStreamClose(innerDecodeStream);
Expand Down
Loading
Loading