From 5b46cd5a0e2dcf53a8431015c99d3106a4a0528c Mon Sep 17 00:00:00 2001 From: comex Date: Thu, 17 Mar 2011 20:26:34 -0400 Subject: [PATCH] okay --- locutus/locutus.c | 104 +++++++++++---------------------------- locutus/locutus_server.m | 93 ++++++++++++++++------------------ make.py | 20 ++++++-- optparse.py | 11 +++++ 4 files changed, 99 insertions(+), 129 deletions(-) create mode 100644 optparse.py diff --git a/locutus/locutus.c b/locutus/locutus.c index d798216..7f0b832 100644 --- a/locutus/locutus.c +++ b/locutus/locutus.c @@ -9,11 +9,14 @@ #include #include #include "inject.h" -#include "bzlib.h" #include #include #include #include +#include + +// todo: test interrupted downloads +// darken //#define TINY @@ -35,25 +38,28 @@ static size_t downloaded_bytes; static struct request { CFStringRef url; const char *output; - bool is_bz2; + CFStringRef content_type; union { struct {}; struct { CFReadStreamRef read_stream; - bz_stream bz; int out_fd; bool finished; size_t content_length; }; }; } requests[] = { - { CFSTR("http://a.qoid.us/test.bz2"), "/tmp/install", true, {}}, - { CFSTR("http://a.qoid.us/test"), "/tmp/foo", false, {}}, - { CFSTR("http://a.qoid.us/Cydia.png"), "/tmp/Cydia.png", false, {}} + { CFSTR("http://a.qoid.us/test"), "/tmp/foo", CFSTR("application/x-bzip2"), {}}, +#if defined(DEVICE_IPHONE3_1) || defined(DEVICE_IPOD4_1) + { CFSTR("http://a.qoid.us/Cydia@2x.png"), "/tmp/Cydia@2x.png", CFSTR("image/png"), {}} +#else + { CFSTR("http://a.qoid.us/Cydia.png"), "/tmp/Cydia.png", CFSTR("image/png"), {}} +#endif }, *const requests_end = requests + sizeof(requests)/sizeof(*requests); __attribute__((noreturn)) static void leave() { + // maybe remove temp? exit(0); } @@ -90,23 +96,17 @@ static void pause_it(CFStringRef err) { // handle an error or completion static void handle_error(struct request *r, CFStringRef err) { - if(r->is_bz2) { - BZ2_bzDecompressEnd(&r->bz); - } close(r->out_fd); r->out_fd = 0; if(err) { pause_it(err); } else { + rename(basename((char *) r->output), r->output); r->finished = true; CFReadStreamClose(r->read_stream); CFRelease(r->read_stream); r->read_stream = NULL; - static char buf[64] = "locutus.got-"; - strncpy(buf + 12, basename((char *) r->output), sizeof(buf) - 12); - notify_post(buf); - for(struct request *r = requests; r < requests_end; r++) { if(!r->finished) return; } @@ -130,13 +130,7 @@ static void request_callback(CFReadStreamRef stream, CFStreamEventType event_typ } break; case kCFStreamEventEndEncountered: - if(r->is_bz2) { - if(r->read_stream) { // end of the bz2 file but no BZ_STREAM_END - handle_error(r, CFSTR("compressed data was truncated")); - } - } else { - handle_error(r, NULL); - } + handle_error(r, NULL); break; case kCFStreamEventHasBytesAvailable: if(!r->content_length) { @@ -148,14 +142,13 @@ static void request_callback(CFReadStreamRef stream, CFStreamEventType event_typ if(code == 200) { CFStringRef cl = CFHTTPMessageCopyHeaderFieldValue(response, CFSTR("Content-Length")); if(!cl) { - handle_error(r, CFSTR("server fails")); + handle_error(r, CFSTR("Server fails (no length)")); break; } else { r->content_length = CFStringGetIntValue(cl); CFRelease(cl); } } else if(code == 206) { - #ifndef TINY // partial content off_t off = 0; CFStringRef range = CFHTTPMessageCopyHeaderFieldValue(response, CFSTR("Content-Range")); @@ -170,15 +163,20 @@ static void request_callback(CFReadStreamRef stream, CFStreamEventType event_typ } CFRelease(range); } - if(off != lseek(r->out_fd, 0, SEEK_SET)) { - handle_error(r, CFSTR("server fails")); + if(off != lseek(r->out_fd, off, SEEK_SET)) { + handle_error(r, CFSTR("Server fails (206)")); break; } - #endif } else { + fprintf(stderr, ">%s<\n", r->output); handle_error(r, CFStringCreateWithFormat(NULL, NULL, CFSTR("HTTP response code %d"), (int) code)); break; } + CFStringRef content_type = CFHTTPMessageCopyHeaderFieldValue(response, CFSTR("Content-Type")); + if(!content_type || kCFCompareEqualTo != CFStringCompare(content_type, r->content_type, kCFCompareCaseInsensitive)) { + handle_error(r, CFStringCreateWithFormat(NULL, NULL, CFSTR("Wrong Content-Type; are you on a fail Wi-Fi network?"))); + } + } // actually read @@ -193,48 +191,7 @@ static void request_callback(CFReadStreamRef stream, CFStreamEventType event_typ written += (size_t) idx; - if(!r->is_bz2) { - _assert((CFIndex) write(r->out_fd, compressed, idx) == idx); - } else { - r->bz.avail_in = (unsigned int) idx; - r->bz.next_in = compressed; - r->bz.avail_out = sizeof(uncompressed); - r->bz.next_out = uncompressed; - while(r->bz.avail_in > 0) { - int result = BZ2_bzDecompress(&r->bz); - if(result != BZ_STREAM_END && result != BZ_OK) { - CFStringRef error; - switch(result) { - case BZ_CONFIG_ERROR: - case BZ_SEQUENCE_ERROR: - case BZ_PARAM_ERROR: - _assert_zero(result); // I screwed up - case BZ_MEM_ERROR: - error = CFSTR("BZ2 memory error"); - break; - case BZ_DATA_ERROR: - error = CFSTR("BZ2 data error (corrupt file)"); - break; - case BZ_DATA_ERROR_MAGIC: - error = CFSTR("BZ2 data error (corrupt file, you might be behind a crappy transparent proxy)"); - break; - default: - error = CFSTR("unknown BZ2 error"); - break; - } - handle_error(r, error); - goto end; - } - - size_t towrite = sizeof(uncompressed) - r->bz.avail_out; - _assert((size_t) write(r->out_fd, uncompressed, towrite) == towrite); - if(result == BZ_STREAM_END) { - // we're done - handle_error(r, NULL); - goto end; - } - } - } + _assert((CFIndex) write(r->out_fd, compressed, idx) == idx); } end: did_download(written); @@ -248,24 +205,16 @@ static void init_requests() { for(struct request *r = requests; r < requests_end; r++) { if(r->read_stream) continue; - if(r->is_bz2) { - _assert_zero(BZ2_bzDecompressInit(&r->bz, 0, 0)); - } - CFURLRef url = _assert(CFURLCreateWithString(NULL, r->url, NULL)); CFHTTPMessageRef message = _assert(CFHTTPMessageCreateRequest(NULL, CFSTR("GET"), url, kCFHTTPVersion1_1)); CFRelease(url); if(r->out_fd) { - #ifdef TINY - lseek(r->out_fd, 0, SEEK_SET); - #else CFStringRef range = CFStringCreateWithFormat(NULL, NULL, CFSTR("bytes %d-%d"), (int) lseek(r->out_fd, 0, SEEK_CUR), (int) r->content_length - 1); CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Range"), range); CFRelease(range); - #endif } else { - r->out_fd = _assert(open(r->output, O_WRONLY | O_CREAT | O_TRUNC, 0644)); + r->out_fd = _assert(open(basename((char *) r->output), O_WRONLY | O_CREAT | O_TRUNC, 0644)); } r->read_stream = _assert(CFReadStreamCreateForHTTPRequest(NULL, message)); @@ -289,6 +238,7 @@ static void run_install() { progress = 0.0; update_state("INSTALLING_ICON_LABEL", NULL); fprintf(stderr, "installing or something\n"); + notify_post("locutus.installed"); leave(); } @@ -355,6 +305,8 @@ int main() { //syslog(LOG_EMERG, "omg hax\n"); //printf("omg hax\n"); //return 0; + mkdir("/tmp/locutus-temp", 0755); // might fail + _assert_zero(chdir("/tmp/locutus-temp")); uint32_t one = 1; _assert_zero(sysctlbyname("security.mac.vnode_enforce", NULL, NULL, &one, sizeof(one))); diff --git a/locutus/locutus_server.m b/locutus/locutus_server.m index 0fbbe1d..d274167 100644 --- a/locutus/locutus_server.m +++ b/locutus/locutus_server.m @@ -1,7 +1,6 @@ #include #include #include -//#include #include #include #include @@ -10,7 +9,6 @@ #import #include - static NSString *const bundle_identifier = @"com.saurik.Cydia.notreally"; static notify_handler_t sk_handler; @@ -21,10 +19,9 @@ static id icon; static id icon_controller; static id icon_model; - -static NSString *display_name; - +static UIImage *icon_image; static UIAlertView *alert_view; +static NSString *display_name; static inline NSString *_(NSString *key) { NSString *r = [[NSBundle mainBundle] localizedStringForKey:key value:nil table:@"SpringBoard"]; @@ -49,6 +46,8 @@ -(void)remove; -(void)setDelegate:(id)delegate; -(void)setDownload:(id)download; -(void)updateDisplayName; +-(id)darkenedIconImage:(id)image alpha:(float)alpha; +-(id)darkenedIcon:(id)image alpha:(float)alpha; @end @interface SBIconController { @@ -66,21 +65,6 @@ -(void)addIcon:(id)icon; //-(void)removeIcon:(id)icon; @end -@interface MyDelegate : NSObject { -} -@end -@implementation MyDelegate -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { - if(buttonIndex == 0) { - sk_handler(0); - [alert_view release]; - alert_view = nil; - } else { - notify_post("locutus.pause"); - } -} -@end - static notify_handler_t sk_handler = ^(int token) { NSLog(@"s/k"); [alert_view dismissWithClickedButtonIndex:0 animated:YES]; @@ -112,17 +96,23 @@ static void MyIcon_completeUninstall(id self, SEL sel) { sk_handler(0); } + +static void MyIcon_alertView_clickedButtonAtIndex(id self, SEL sel, UIAlertView *alertView, NSInteger buttonIndex) { + if(buttonIndex == 0) { + sk_handler(0); + [alert_view release]; + alert_view = nil; + } else { + notify_post("locutus.pause"); + } +} + static void set_progress(float progress) { id _progress = nil; object_getInstanceVariable(icon, "_progress", (void **) &_progress); [_progress setProgress:progress]; } -static void override(SEL sel, IMP imp) { - method_setImplementation(class_getInstanceMethod(MyIcon, sel), imp); -} -#define OVERRIDE(x) override(@selector(x), (IMP) MyIcon_##x) - __attribute__((constructor)) static void init() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -131,11 +121,13 @@ static void init() { char name[32]; sprintf(name, "MyIcon_%p", &init); MyIcon = objc_allocateClassPair(objc_getClass("SBDownloadingIcon"), name, 0); +#define OVERRIDE(x) class_replaceMethod(MyIcon, @selector(x), (IMP) MyIcon_##x, "") OVERRIDE(displayName); OVERRIDE(applicationBundleID); OVERRIDE(launch); OVERRIDE(allowsUninstall); OVERRIDE(completeUninstall); + class_addMethod(MyIcon, @selector(alertView:clickedButtonAtIndex:), (IMP) MyIcon_alertView_clickedButtonAtIndex, "@:@l"); objc_registerClassPair(MyIcon); icon_controller = [objc_getClass("SBIconController") sharedInstance]; @@ -165,36 +157,37 @@ static void init() { NSLog(@"err = <%@>", err); if(![err isEqualToString:@"ok"]) { [alert_view dismissWithClickedButtonIndex:0 animated:YES]; // shouldn't happen! - alert_view = [[UIAlertView alloc] initWithTitle:@"JailbreakMe" message:err delegate:[[MyDelegate alloc] init] cancelButtonTitle:_(@"DATA_PLAN_FAILED_TRY_LATER") otherButtonTitles:_(@"DATA_PLAN_FAILED_TRY_AGAIN"), nil]; + alert_view = [[UIAlertView alloc] initWithTitle:@"There was a problem downloading the jailbreak files." message:err delegate:icon cancelButtonTitle:@"Cancel" otherButtonTitles:@"Retry", nil]; [alert_view show]; } - }); - - notify_register_dispatch("locutus.got-file", &tokens[2], dispatch_get_main_queue(), ^(int token) { - UIImage *image = [UIImage imageWithContentsOfFile:@"/tmp/Cydia.png"]; - if(image) { - if([icon respondsToSelector:@selector(setDisplayedIconImage:)]) { - [icon setDisplayedIconImage:image]; - } else { - [icon setDisplayedIcon:image]; + + if(!icon_image) { + icon_image = [UIImage imageWithContentsOfFile:@"/tmp/Cydia.png"]; + if(icon_image) { + if([icon respondsToSelector:@selector(setDisplayedIconImage:)]) { + [icon setDisplayedIconImage:[icon darkenedIconImage:icon_image alpha:0.5]]; + } else { + [icon setDisplayedIcon:[icon darkenedIcon:icon_image alpha:0.5]]; + } } - notify_cancel(token); } }); - NSLog(@"done, MyIcon is now %p", MyIcon); - - icon = [MyIcon alloc]; - NSLog(@"omg"); - icon = [icon initWithLeafIdentifier:bundle_identifier]; - [icon setDelegate:icon_controller]; - display_name = _(@"WAITING_ICON_LABEL"); - NSLog(@"%@", icon); - [icon_model addIcon:icon]; - //[icon setDownload:[[NSObject alloc] init]]; - //[icon setDelegate:[[NSObject alloc] init]]; - [icon_controller addNewIconToDesignatedLocation:icon animate:NO scrollToList:NO saveIconState:YES]; - [icon_controller setIconToReveal:icon]; - [icon release]; + notify_register_dispatch("locutus.installed", &tokens[2], dispatch_get_main_queue(), ^(int token) { + + }); + + dispatch_async(dispatch_get_main_queue(), ^{ + NSLog(@"done, MyIcon is now %p", MyIcon); + + icon = [[MyIcon alloc] initWithLeafIdentifier:bundle_identifier]; + [icon setDelegate:icon_controller]; + display_name = _(@"WAITING_ICON_LABEL"); + NSLog(@"%@", icon); + [icon_model addIcon:icon]; + [icon_controller addNewIconToDesignatedLocation:icon animate:NO scrollToList:NO saveIconState:YES]; + [icon_controller setIconToReveal:icon]; + [icon release]; + }); [pool release]; } diff --git a/make.py b/make.py index 7a905a9..ba1a5e0 100755 --- a/make.py +++ b/make.py @@ -3,16 +3,29 @@ from fabricate import * import fabricate fabricate.default_builder.deps # do this before we chdir -import sys, os +import sys, os, re + ROOT = os.path.realpath(os.path.dirname(sys.argv[0])) -os.environ['PYTHONPATH'] = 'ROOT/datautils:ROOT/goo:ROOT/config'.replace('ROOT', ROOT) +os.environ['PYTHONPATH'] = ROOT+'/datautils:'+ROOT+'/goo' + +# configgy + +m = re.search('bs/(i[A-Z][a-z]+[0-9],[0-9])_([0-9A-Z\._]+)', os.readlink(ROOT + '/config/cur')) +device = m.group(1) +version = m.group(2) +platform, version = m.groups() +is_armv7 = device not in ['iPhone1,1', 'iPhone1,2', 'iPod1,1', 'iPod2,1'] + +def cify(x): + return re.sub('[^A-Z0-9]', '_', x.upper()) + GCC_FLAGS = ['-std=gnu99', '-gstabs', '-Werror', '-Wimplicit', '-Wuninitialized', '-Wall', '-Wextra', '-Wreturn-type', '-Wno-unused', '-Os'] SDK = '/var/sdk' BIN = '/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin' GCC_BIN = BIN + '/gcc-4.2' GCC_BASE = [GCC_BIN, GCC_FLAGS, '-isysroot', SDK, '-F'+SDK+'/System/Library/Frameworks', '-F'+SDK+'/System/Library/PrivateFrameworks', '-I', ROOT, '-fno-blocks', '-mapcs-frame', '-fomit-frame-pointer'] -GCC = [GCC_BASE, '-arch', 'armv7', '-mthumb'] +GCC = [GCC_BASE, '-arch', ('armv7' if is_armv7 else 'armv6'), '-mthumb', '-DDEVICE_%s' % cify(device), '-DVERSION_%s' % cify(version)] GCC_UNIVERSAL = [GCC_BASE, '-arch', 'armv6', '-arch', 'armv7', '-mthumb'] GCC_ARMV6 = [GCC_BASE, '-arch', 'armv6', '-mthumb'] GCC_NATIVE = ['gcc', '-arch', 'i386', '-arch', 'x86_64', GCC_FLAGS] @@ -57,6 +70,7 @@ def locutus(): compile_stuff(['locutus_server.m'], 'locutus_server.dylib', cflags=cflags+['-Wno-deprecated-declarations'], ldflags=['-dynamiclib', '-framework', 'Foundation', '-framework', 'UIKit', '-install_name', 'X'*32]+cflags, ldid=False) run('sh', '-c', 'xxd -i locutus_server.dylib | sed "s/locutus_server_//g" > locutus_server_.c') compile_stuff(['locutus.c', 'inject.c', 'baton.S', 'locutus_server_.c'], 'locutus', cflags=cflags, ldflags=['-lbz2', '-framework', 'CoreFoundation', '-framework', 'CFNetwork']+cflags, ldid=True, ent='ent.plist') +build = locutus def goo(): goto('goo') diff --git a/optparse.py b/optparse.py new file mode 100644 index 0000000..36ae00d --- /dev/null +++ b/optparse.py @@ -0,0 +1,11 @@ +import sys +class OptionParser: + def __init__(self, *args, **kwargs): + self.sort = 0 + def add_option(self, *args, **kwargs): + setattr(self, kwargs.get('dest', ''), kwargs.get('default', None)) + def disable_interspersed_args(self): pass + def __getattr__(self, a): + return None + def parse_args(self): + return (self, sys.argv[1:])