Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

began refactoring for air brake transition and fixed some compiler wa…

…rnings
  • Loading branch information...
commit 18c588ab6ab5d5aef4a31a7464d4eabec2b8d22e 1 parent 5cea069
@calebd calebd authored
View
4 Hoptoad Sample.xcodeproj/project.pbxproj
@@ -273,12 +273,12 @@
isa = PBXGroup;
children = (
3BA58915137C871300D9C544 /* HTNotifier.strings */,
+ 3BA5891E137C871300D9C544 /* HTNotifier.h */,
+ 3BA5891F137C871300D9C544 /* HTNotifier.m */,
3BA5891A137C871300D9C544 /* HTFunctions.h */,
3BA5891B137C871300D9C544 /* HTFunctions.m */,
3BA5891C137C871300D9C544 /* HTNotice.h */,
3BA5891D137C871300D9C544 /* HTNotice.m */,
- 3BA5891E137C871300D9C544 /* HTNotifier.h */,
- 3BA5891F137C871300D9C544 /* HTNotifier.m */,
3BA58924137C871300D9C544 /* HTNotifierDelegate.h */,
);
path = hoptoadnotifier;
View
8 hoptoadnotifier/HTFunctions.h
@@ -29,6 +29,9 @@
#import <Foundation/Foundation.h>
#endif
+// open a new notice file at a path
+int HTOpenFile(int type, const char *path);
+
// start handlers
void HTStartHandlers(void);
void HTStartExceptionHandler(void);
@@ -56,8 +59,9 @@ void HTInitNoticeInfo(void);
void HTReleaseNoticeInfo(void);
// deal with notice information on disk
-NSString * HTNoticesDirectory(void);
-NSArray * HTNotices(void);
+NSString *ABNotifierPathForNewNoticeWithName(NSString *name);
+NSString *ABNotifierPathForNoticesDirectory(void);
+NSArray *ABNotifierAllNotices(void);
// callstack utilities
NSArray *HTCallStackSymbolsFromReturnAddresses(NSArray *);
View
90 hoptoadnotifier/HTFunctions.m
@@ -33,7 +33,7 @@ of this software and associated documentation files (the "Software"), to deal
#import "HTNotifier.h"
#import "HTNotice.h"
-NSString *HTNotifierDirectoryName = @"Hoptoad Notices";
+static NSString * const ABNotifierNoticeDirectoryName = @"Hoptoad Notices";
// handled signals
int ht_signals_count = 6;
@@ -49,12 +49,11 @@ of this software and associated documentation files (the "Software"), to deal
// internal function prototypes
void ht_handle_signal(int, siginfo_t *, void *);
void ht_handle_exception(NSException *);
-int ht_open_file(int);
#pragma mark crash time methods
void ht_handle_signal(int signal, siginfo_t *info, void *context) {
HTStopSignalHandler();
- int fd = ht_open_file(HTSignalNoticeType);
+ int fd = HTOpenFile(HTSignalNoticeType, ht_notice_info.notice_path);
if (fd > -1) {
// signal
@@ -79,53 +78,12 @@ void ht_handle_signal(int signal, siginfo_t *info, void *context) {
}
void ht_handle_exception(NSException *exception) {
HTStopHandlers();
- int fd = ht_open_file(HTExceptionNoticeType);
- if (fd > -1) {
-
- // crash info
- NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:5];
-
- // addresses
- NSArray *addresses = [exception callStackReturnAddresses];
- NSArray *symbols = HTCallStackSymbolsFromReturnAddresses(addresses);
- [dictionary setObject:symbols forKey:@"call stack"];
-
- // exception name and reason
- [dictionary setObject:[exception name] forKey:@"exception name"];
- [dictionary setObject:[exception reason] forKey:@"exception reason"];
-
-#if TARGET_OS_IPHONE
-
- // view controller
- NSString *viewController = HTCurrentViewController();
- if (viewController != nil) {
- [dictionary setObject:viewController forKey:@"view controller"];
- }
-
-#endif
-
- // environment info
- [[HTNotifier sharedNotifier] setEnvironmentValue:[[exception userInfo] description] forKey:@"Exception"];
- NSDictionary *environmentInfo = [[HTNotifier sharedNotifier] environmentInfo];
- [dictionary setObject:environmentInfo forKey:@"environment info"];
-
- // write data
- NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dictionary];
- NSUInteger length = [data length];
- write(fd, &length, sizeof(unsigned long));
- write(fd, [data bytes], length);
-
- // close file
- close(fd);
-
- }
- id<HTNotifierDelegate> delegate = [[HTNotifier sharedNotifier] delegate];
- if ([delegate respondsToSelector:@selector(notifierDidHandleException:)]) {
- [delegate notifierDidHandleException:exception];
- }
+ [[HTNotifier sharedNotifier] logException:exception];
}
-int ht_open_file(int type) {
- int fd = open(ht_notice_info.notice_path, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
+
+#pragma mark - open notice file
+int HTOpenFile(int type, const char *path) {
+ int fd = open(path, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
if (fd > -1) {
write(fd, &HTNoticeFileVersion, sizeof(int));
write(fd, &type, sizeof(int));
@@ -266,9 +224,9 @@ id HTInfoPlistValueForKey(NSString *key) {
else if ([machine isEqualToString:@"iPad2,3"]) { return @"iPad 2 (CDMA)"; }
// ipod
else if ([machine isEqualToString:@"iPod1,1"]) { return @"iPod Touch"; }
- else if ([machine isEqualToString:@"iPod2,1"]) { return @"iPod Touch 2nd Gen"; }
- else if ([machine isEqualToString:@"iPod3,1"]) { return @"iPod Touch 3rd Gen"; }
- else if ([machine isEqualToString:@"iPod4,1"]) { return @"iPod Touch 4th Gen"; }
+ else if ([machine isEqualToString:@"iPod2,1"]) { return @"iPod Touch (2nd generation)"; }
+ else if ([machine isEqualToString:@"iPod3,1"]) { return @"iPod Touch (3rd generation)"; }
+ else if ([machine isEqualToString:@"iPod4,1"]) { return @"iPod Touch (4th generation)"; }
// unknown
else { return machine; }
#else
@@ -286,10 +244,8 @@ void HTInitNoticeInfo(void) {
NSUInteger length;
// exception file name
- NSString *directory = HTNoticesDirectory();
- NSString *fileName = [NSString stringWithFormat:@"%d", time(NULL)];
- value = [directory stringByAppendingPathComponent:fileName];
- value = [value stringByAppendingPathExtension:HTNoticePathExtension];
+ NSString *name = [[NSProcessInfo processInfo] globallyUniqueString];
+ value = ABNotifierPathForNewNoticeWithName(name);
value_str = [value UTF8String];
length = (strlen(value_str) + 1);
ht_notice_info.notice_path = malloc(length);
@@ -375,28 +331,32 @@ void HTReleaseNoticeInfo(void) {
}
#pragma mark - notice information on disk
-NSString * HTNoticesDirectory(void) {
+NSString *ABNotifierPathForNewNoticeWithName(NSString *name) {
+ NSString *path = ABNotifierPathForNoticesDirectory();
+ path = [path stringByAppendingPathComponent:name];
+ return [path stringByAppendingPathExtension:ABNotifierNoticePathExtension];
+}
+NSString *ABNotifierPathForNoticesDirectory() {
#if TARGET_OS_IPHONE
NSArray *folders = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *path = [folders objectAtIndex:0];
if ([folders count] == 0) { path = NSTemporaryDirectory(); }
- return [path stringByAppendingPathComponent:HTNotifierDirectoryName];
+ return [path stringByAppendingPathComponent:ABNotifierNoticePathExtension];
#else
NSArray *folders = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *path = [folders objectAtIndex:0];
if ([folders count] == 0) { path = NSTemporaryDirectory(); }
path = [path stringByAppendingPathComponent:HTApplicationName()];
- return [path stringByAppendingPathComponent:HTNotifierDirectoryName];
+ return [path stringByAppendingPathComponent:ABNotifierNoticePathExtension];
#endif
}
-NSArray * HTNotices(void) {
- NSString *directory = HTNoticesDirectory();
- NSArray *directoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:directory error:nil];
+NSArray *ABNotifierAllNotices(void) {
+ NSString *path = ABNotifierPathForNoticesDirectory();
+ NSArray *directoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
NSMutableArray *crashes = [NSMutableArray arrayWithCapacity:[directoryContents count]];
for (NSString *file in directoryContents) {
- NSString *ext = [file pathExtension];
- if ([ext isEqualToString:HTNoticePathExtension]) {
- NSString *crashPath = [directory stringByAppendingPathComponent:file];
+ if ([[file pathExtension] isEqualToString:ABNotifierNoticePathExtension]) {
+ NSString *crashPath = [path stringByAppendingPathComponent:file];
[crashes addObject:crashPath];
}
}
View
2  hoptoadnotifier/HTNotice.h
@@ -58,7 +58,7 @@ typedef struct ht_notice_info_t {
ht_notice_info_t ht_notice_info;
// file flags
-extern NSString *HTNoticePathExtension;
+extern NSString * const ABNotifierNoticePathExtension;
extern int HTNoticeFileVersion;
extern int HTSignalNoticeType;
extern int HTExceptionNoticeType;
View
291 hoptoadnotifier/HTNotice.m
@@ -31,7 +31,7 @@ of this software and associated documentation files (the "Software"), to deal
#import "DDXML.h"
-NSString *HTNoticePathExtension = @"htnotice";
+NSString * const ABNotifierNoticePathExtension = @"htnotice";
int HTNoticeFileVersion = 4;
int HTSignalNoticeType = 1;
int HTExceptionNoticeType = 2;
@@ -49,171 +49,182 @@ @implementation HTNotice
#pragma mark - factory method to create notice
+ (HTNotice *)noticeWithContentsOfFile:(NSString *)path {
- NSString *extension = [path pathExtension];
- if (![extension isEqualToString:HTNoticePathExtension]) {
- return nil;
- }
-
- // setup
- HTNotice *notice = [[HTNotice alloc] init];
- NSMutableDictionary *info = [NSMutableDictionary dictionaryWithCapacity:3];
- NSData *data = [NSData dataWithContentsOfFile:path];
- NSUInteger location = 0;
- NSUInteger length = 0;
-
- // get version
- int version;
- [data getBytes:&version range:NSMakeRange(location, sizeof(int))];
- location += sizeof(int);
-
- // get type
- int type;
- [data getBytes:&type range:NSMakeRange(location, sizeof(int))];
- location += sizeof(int);
-
- // os version
- [data getBytes:&length range:NSMakeRange(location, sizeof(unsigned long))];
- location += sizeof(unsigned long);
- if (length > 0) {
- char * value_str = malloc(length * sizeof(char));
- [data getBytes:value_str range:NSMakeRange(location, length)];
- location += length;
- [info setObject:[NSString stringWithUTF8String:value_str] forKey:@"Operating System"];
- free(value_str);
- }
-
- // platform
- [data getBytes:&length range:NSMakeRange(location, sizeof(unsigned long))];
- location += sizeof(unsigned long);
- if (length > 0) {
- char * value_str = malloc(length * sizeof(char));
- [data getBytes:value_str range:NSMakeRange(location, length)];
- location += length;
- [info setObject:[NSString stringWithUTF8String:value_str] forKey:@"Device"];
- free(value_str);
- }
- // app version
- [data getBytes:&length range:NSMakeRange(location, sizeof(unsigned long))];
- location += sizeof(unsigned long);
- if (length > 0) {
- char * value_str = malloc(length * sizeof(char));
- [data getBytes:value_str range:NSMakeRange(location, length)];
- location += length;
- [info setObject:[NSString stringWithUTF8String:value_str] forKey:@"App Version"];
- free(value_str);
- }
-
- // environment
- [data getBytes:&length range:NSMakeRange(location, sizeof(unsigned long))];
- location += sizeof(unsigned long);
- if (length > 0) {
- char * value_str = malloc(length * sizeof(char));
- [data getBytes:value_str range:NSMakeRange(location, length)];
- location += length;
- notice.environmentName = [NSString stringWithUTF8String:value_str];
- free(value_str);
- }
-
- // git hash
- if (version >= 2 && version < 4) {
+ @try {
+
+ // check path
+ NSString *extension = [path pathExtension];
+ if (![extension isEqualToString:ABNotifierNoticePathExtension]) {
+ [NSException raise:NSInvalidArgumentException format:@"%@ does is not a notice"];
+ }
+
+ // setup
+ HTNotice *notice = [[HTNotice alloc] init];
+ NSMutableDictionary *info = [NSMutableDictionary dictionaryWithCapacity:3];
+ NSData *data = [NSData dataWithContentsOfFile:path];
+ NSUInteger location = 0;
+ NSUInteger length = 0;
+
+ // get version
+ int version;
+ [data getBytes:&version range:NSMakeRange(location, sizeof(int))];
+ location += sizeof(int);
+
+ // get type
+ int type;
+ [data getBytes:&type range:NSMakeRange(location, sizeof(int))];
+ location += sizeof(int);
+
+ // os version
[data getBytes:&length range:NSMakeRange(location, sizeof(unsigned long))];
location += sizeof(unsigned long);
if (length > 0) {
char * value_str = malloc(length * sizeof(char));
[data getBytes:value_str range:NSMakeRange(location, length)];
location += length;
- [info setObject:[NSString stringWithUTF8String:value_str] forKey:@"Git Commit"];
+ [info setObject:[NSString stringWithUTF8String:value_str] forKey:@"Operating System"];
free(value_str);
}
- }
-
- // bundle version
- if (version >= 3) {
+
+ // platform
[data getBytes:&length range:NSMakeRange(location, sizeof(unsigned long))];
location += sizeof(unsigned long);
if (length > 0) {
char * value_str = malloc(length * sizeof(char));
[data getBytes:value_str range:NSMakeRange(location, length)];
location += length;
- notice.bundleVersion = [NSString stringWithUTF8String:value_str];
+ [info setObject:[NSString stringWithUTF8String:value_str] forKey:@"Device"];
free(value_str);
}
- }
-
-
- // signal notice
- if (type == HTSignalNoticeType) {
-
- // signal
- int signal;
- [data getBytes:&signal range:NSMakeRange(location, sizeof(int))];
- location += sizeof(int);
-
- // exception name and reason
- notice.exceptionName = [NSString stringWithUTF8String:strsignal(signal)];
- notice.exceptionReason = @"Application recieved signal";
- // environment info
- if (version >= 4) {
+ // app version
+ [data getBytes:&length range:NSMakeRange(location, sizeof(unsigned long))];
+ location += sizeof(unsigned long);
+ if (length > 0) {
+ char * value_str = malloc(length * sizeof(char));
+ [data getBytes:value_str range:NSMakeRange(location, length)];
+ location += length;
+ [info setObject:[NSString stringWithUTF8String:value_str] forKey:@"App Version"];
+ free(value_str);
+ }
+
+ // environment
+ [data getBytes:&length range:NSMakeRange(location, sizeof(unsigned long))];
+ location += sizeof(unsigned long);
+ if (length > 0) {
+ char * value_str = malloc(length * sizeof(char));
+ [data getBytes:value_str range:NSMakeRange(location, length)];
+ location += length;
+ notice.environmentName = [NSString stringWithUTF8String:value_str];
+ free(value_str);
+ }
+
+ // git hash
+ if (version >= 2 && version < 4) {
+ [data getBytes:&length range:NSMakeRange(location, sizeof(unsigned long))];
+ location += sizeof(unsigned long);
+ if (length > 0) {
+ char * value_str = malloc(length * sizeof(char));
+ [data getBytes:value_str range:NSMakeRange(location, length)];
+ location += length;
+ [info setObject:[NSString stringWithUTF8String:value_str] forKey:@"Git Commit"];
+ free(value_str);
+ }
+ }
+
+ // bundle version
+ if (version >= 3) {
+ [data getBytes:&length range:NSMakeRange(location, sizeof(unsigned long))];
+ location += sizeof(unsigned long);
+ if (length > 0) {
+ char * value_str = malloc(length * sizeof(char));
+ [data getBytes:value_str range:NSMakeRange(location, length)];
+ location += length;
+ notice.bundleVersion = [NSString stringWithUTF8String:value_str];
+ free(value_str);
+ }
+ }
+
+
+ // signal notice
+ if (type == HTSignalNoticeType) {
+
+ // signal
+ int signal;
+ [data getBytes:&signal range:NSMakeRange(location, sizeof(int))];
+ location += sizeof(int);
+
+ // exception name and reason
+ notice.exceptionName = [NSString stringWithUTF8String:strsignal(signal)];
+ notice.exceptionReason = @"Application recieved signal";
+
+ // environment info
+ if (version >= 4) {
+ [data getBytes:&length range:NSMakeRange(location, sizeof(unsigned long))];
+ location += sizeof(unsigned long);
+ NSData *subdata = [data subdataWithRange:NSMakeRange(location, length)];
+ location += length;
+ NSDictionary *environmentInfo = [NSKeyedUnarchiver unarchiveObjectWithData:subdata];
+ [info addEntriesFromDictionary:environmentInfo];
+ }
+
+ // call stack
+ NSUInteger i = location;
+ length = [data length];
+ const char * bytes = [data bytes];
+ NSMutableArray *array = [NSMutableArray array];
+ while (i < length) {
+ if (bytes[i] == '\0') {
+ NSData *line = [data subdataWithRange:NSMakeRange(location, i - location)];
+ NSString *lineString = [[NSString alloc]
+ initWithBytes:[line bytes]
+ length:[line length]
+ encoding:NSUTF8StringEncoding];
+ [array addObject:lineString];
+ [lineString release];
+ if (i + 1 < length && bytes[i + 1] == '\n') { i += 2; }
+ else { i++; }
+ location = i;
+ }
+ else { i++; }
+ }
+ notice.callStack = array;
+
+ }
+
+ // exception notice
+ else if (type == HTExceptionNoticeType) {
[data getBytes:&length range:NSMakeRange(location, sizeof(unsigned long))];
location += sizeof(unsigned long);
NSData *subdata = [data subdataWithRange:NSMakeRange(location, length)];
location += length;
- NSDictionary *environmentInfo = [NSKeyedUnarchiver unarchiveObjectWithData:subdata];
- [info addEntriesFromDictionary:environmentInfo];
+ NSDictionary *dictionary = [NSKeyedUnarchiver unarchiveObjectWithData:subdata];
+ [info addEntriesFromDictionary:[dictionary objectForKey:@"environment info"]];
+ notice.exceptionName = [dictionary objectForKey:@"exception name"];
+ notice.exceptionReason = [dictionary objectForKey:@"exception reason"];
+ notice.callStack = [dictionary objectForKey:@"call stack"];
+ notice.viewControllerName = [dictionary objectForKey:@"view controller"];
}
-
- // call stack
- NSUInteger i = location;
- length = [data length];
- const char * bytes = [data bytes];
- NSMutableArray *array = [NSMutableArray array];
- while (i < length) {
- if (bytes[i] == '\0') {
- NSData *line = [data subdataWithRange:NSMakeRange(location, i - location)];
- NSString *lineString = [[NSString alloc]
- initWithBytes:[line bytes]
- length:[line length]
- encoding:NSUTF8StringEncoding];
- [array addObject:lineString];
- [lineString release];
- if (i + 1 < length && bytes[i + 1] == '\n') { i += 2; }
- else { i++; }
- location = i;
- }
- else { i++; }
- }
- notice.callStack = array;
-
- }
-
- // exception notice
- else if (type == HTExceptionNoticeType) {
- [data getBytes:&length range:NSMakeRange(location, sizeof(unsigned long))];
- location += sizeof(unsigned long);
- NSData *subdata = [data subdataWithRange:NSMakeRange(location, length)];
- location += length;
- NSDictionary *dictionary = [NSKeyedUnarchiver unarchiveObjectWithData:subdata];
- [info addEntriesFromDictionary:[dictionary objectForKey:@"environment info"]];
- notice.exceptionName = [dictionary objectForKey:@"exception name"];
- notice.exceptionReason = [dictionary objectForKey:@"exception reason"];
- notice.callStack = [dictionary objectForKey:@"call stack"];
- notice.viewControllerName = [dictionary objectForKey:@"view controller"];
+
+ // set action
+ notice.callStack = HTParseCallstack(notice.callStack);
+ notice.action = HTActionFromParsedCallstack(notice.callStack);
+ if (type == HTSignalNoticeType && notice.action != nil) {
+ notice.exceptionReason = notice.action;
+ }
+
+ // set env info
+ notice.environmentInfo = info;
+
+ // return
+ return [notice autorelease];
+
}
-
- // set action
- notice.callStack = HTParseCallstack(notice.callStack);
- notice.action = HTActionFromParsedCallstack(notice.callStack);
- if (type == HTSignalNoticeType && notice.action != nil) {
- notice.exceptionReason = notice.action;
+ @catch (NSException *exception) {
+ HTLog(@"%@", exception);
+ return nil;
}
-
- // set env info
- notice.environmentInfo = info;
- // return
- return [notice autorelease];
}
#pragma mark - object methods
View
23 hoptoadnotifier/HTNotifier.h
@@ -78,11 +78,11 @@ extern NSString * const HTNotifierAutomaticEnvironment;
@interface HTNotifier : NSObject {
#endif
@private
- NSMutableDictionary *_environmentInfo;
- NSString *_environmentName;
- NSString *_apiKey;
- NSObject<HTNotifierDelegate> *_delegate;
- BOOL _useSSL;
+ NSMutableDictionary * __environmentInfo;
+ NSString * __environmentName;
+ NSString * __apiKey;
+ NSObject<HTNotifierDelegate> * __delegate;
+ BOOL __useSSL;
SCNetworkReachabilityRef reachability;
}
@@ -129,11 +129,10 @@ extern NSString * const HTNotifierAutomaticEnvironment;
/*
- writes a test notice if one does not exist already. it
- will be reported just as an actual crash.
+ log an exception in a new notice file
*/
-- (void)writeTestNotice;
+- (void)logException:(NSException *)exception;
/*
@@ -149,6 +148,14 @@ extern NSString * const HTNotifierAutomaticEnvironment;
*/
- (NSString *)environmentValueForKey:(NSString *)key;
+
+/*
+
+ writes a test notice if one does not exist already. it
+ will be reported just as an actual crash.
+
+ */
+- (void)writeTestNotice;
/*
View
147 hoptoadnotifier/HTNotifier.m
@@ -27,7 +27,6 @@ of this software and associated documentation files (the "Software"), to deal
#import "HTFunctions.h"
// internal
-void ht_handle_exception(NSException *);
static HTNotifier *sharedNotifier = nil;
static NSString *HTNotifierHostName = @"airbrakeapp.com";
#define HTNotifierURL [NSURL URLWithString: \
@@ -79,7 +78,7 @@ - (id)initWithAPIKey:(NSString *)key environmentName:(NSString *)name {
if (self) {
// create folder
- NSString *directory = HTNoticesDirectory();
+ NSString *directory = ABNotifierPathForNoticesDirectory();
if (![[NSFileManager defaultManager] fileExistsAtPath:directory]) {
[[NSFileManager defaultManager]
createDirectoryAtPath:directory
@@ -89,9 +88,9 @@ - (id)initWithAPIKey:(NSString *)key environmentName:(NSString *)name {
}
// setup values
- _apiKey = [key copy];
- _environmentName = [name copy];
- _environmentInfo = [[NSMutableDictionary alloc] init];
+ __apiKey = [key copy];
+ __environmentName = [name copy];
+ __environmentInfo = [[NSMutableDictionary alloc] init];
self.useSSL = NO;
#if TARGET_OS_IPHONE && defined(DEBUG)
NSString *UDID = [[UIDevice currentDevice] uniqueIdentifier];
@@ -186,28 +185,19 @@ - (void)postNoticeWithPath:(NSString *)path {
[request setHTTPMethod:@"POST"];
// get notice payload
- @try {
- HTNotice *notice = [HTNotice noticeWithContentsOfFile:path];
- NSData *data = [notice hoptoadXMLData];
- if (data == nil) {
- [NSException
- raise:NSInternalInconsistencyException
- format:@"[Hoptoad] unable to read notice at %@", path];
- }
- else {
- [request setHTTPBody:data];
-#ifdef DEBUG
- HTLog(@"%@", notice);
-#endif
- }
-
- }
- @catch (NSException *exception) {
- HTLog(@"%@", exception);
+ HTNotice *notice = [HTNotice noticeWithContentsOfFile:path];
+ NSData *data = [notice hoptoadXMLData];
+ if (data) {
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
[pool drain];
return;
}
+ else {
+ [request setHTTPBody:data];
+#ifdef DEBUG
+ HTLog(@"%@", notice);
+#endif
+ }
// perform request
NSError *error = nil;
@@ -362,11 +352,11 @@ - (void)showNoticeAlert {
#pragma mark - public methods
@implementation HTNotifier
-@synthesize environmentInfo=_environmentInfo;
-@synthesize environmentName=_environmentName;
-@synthesize apiKey=_apiKey;
-@synthesize useSSL=_useSSL;
-@synthesize delegate=_delegate;
+@synthesize environmentInfo = __environmentInfo;
+@synthesize environmentName = __environmentName;
+@synthesize apiKey = __apiKey;
+@synthesize useSSL = __useSSL;
+@synthesize delegate = __delegate;
#pragma mark - start notifier
+ (void)startNotifierWithAPIKey:(NSString *)key environmentName:(NSString *)name {
@@ -442,9 +432,12 @@ - (void)dealloc {
// release information
HTReleaseNoticeInfo();
if (reachability != NULL) { CFRelease(reachability);reachability = NULL; }
- [_apiKey release];_apiKey = nil;
- [_environmentName release];_environmentName = nil;
- [_environmentInfo release];_environmentInfo = nil;
+ [__apiKey release];
+ __apiKey = nil;
+ [__environmentName release];
+ __environmentName = nil;
+ [__environmentInfo release];
+ __environmentInfo = nil;
// super
[super dealloc];
@@ -453,23 +446,89 @@ - (void)dealloc {
#pragma mark - test mechanism
- (void)writeTestNotice {
- NSString *testPath = [HTNoticesDirectory() stringByAppendingPathComponent:@"TEST"];
- testPath = [testPath stringByAppendingPathExtension:HTNoticePathExtension];
- if ([[NSFileManager defaultManager] fileExistsAtPath:testPath]) { return; }
- @try {
+ @try {
NSArray *array = [NSArray array];
[array objectAtIndex:NSUIntegerMax];
}
- @catch (NSException *e) { ht_handle_exception(e); }
- NSString *noticePath = [NSString stringWithUTF8String:ht_notice_info.notice_path];
- [[NSFileManager defaultManager] moveItemAtPath:noticePath toPath:testPath error:nil];
+ @catch (NSException *e) {
+ [self logException:e];
+ }
+}
+
+#pragma mark - log exception
+- (void)logException:(NSException *)exception {
+ @synchronized(self) {
+
+ // open file
+ NSString *name = [[NSProcessInfo processInfo] globallyUniqueString];
+ NSString *path = ABNotifierPathForNewNoticeWithName(name);
+ int fd = HTOpenFile(HTExceptionNoticeType, [path UTF8String]);
+
+ // write file
+ if (fd > -1) {
+
+ @try {
+
+ // crash info
+ NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:5];
+
+ // addresses
+ NSArray *addresses = [exception callStackReturnAddresses];
+ NSArray *symbols = HTCallStackSymbolsFromReturnAddresses(addresses);
+ [dictionary setObject:symbols forKey:@"call stack"];
+
+ // exception name and reason
+ [dictionary setObject:[exception name] forKey:@"exception name"];
+ [dictionary setObject:[exception reason] forKey:@"exception reason"];
+
+#if TARGET_OS_IPHONE
+
+ // view controller
+ NSString *viewController = HTCurrentViewController();
+ if (viewController != nil) {
+ [dictionary setObject:viewController forKey:@"view controller"];
+ }
+
+#endif
+
+ // environment info
+ [self setEnvironmentValue:[[exception userInfo] description] forKey:@"Exception"];
+ [dictionary setObject:self.environmentInfo forKey:@"environment info"];
+
+ // write data
+ NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dictionary];
+ NSUInteger length = [data length];
+ write(fd, &length, sizeof(unsigned long));
+ write(fd, [data bytes], length);
+
+
+
+ // notify delegate on main thread
+ if ([self.delegate respondsToSelector:@selector(notifierDidLogException:)]) {
+ [self.delegate
+ performSelectorOnMainThread:@selector(notifierDidLogException:)
+ withObject:exception
+ waitUntilDone:YES];
+ }
+
+ }
+ @catch (NSException *exception) {
+ HTLog(@"Encountered an exception while logging an exception");
+ }
+ @finally {
+ close(fd);
+ }
+
+ }
+
+ }
}
#pragma mark - environment information accessors
- (void)setEnvironmentValue:(NSString *)valueOrNil forKey:(NSString *)key {
- if (valueOrNil == nil) { [_environmentInfo removeObjectForKey:key]; }
- else { [_environmentInfo setObject:valueOrNil forKey:key]; }
- NSData *environmentData = [NSKeyedArchiver archivedDataWithRootObject:_environmentInfo];
+ if (valueOrNil == nil) { [__environmentInfo removeObjectForKey:key]; }
+ else { [__environmentInfo setObject:valueOrNil forKey:key]; }
+ NSData *environmentData = [NSKeyedArchiver archivedDataWithRootObject:__environmentInfo];
NSUInteger length = [environmentData length];
free(ht_notice_info.env_info);
ht_notice_info.env_info = malloc(length);
@@ -477,14 +536,14 @@ - (void)setEnvironmentValue:(NSString *)valueOrNil forKey:(NSString *)key {
[environmentData getBytes:ht_notice_info.env_info length:length];
}
- (NSString *)environmentValueForKey:(NSString *)key {
- return [_environmentInfo objectForKey:key];
+ return [__environmentInfo objectForKey:key];
}
#pragma mark - post notices
- (BOOL)postNotices {
BOOL value = [self isHoptoadReachable];
if (value) {
- NSArray *notices = HTNotices();
+ NSArray *notices = ABNotifierAllNotices();
if ([notices count]) {
if ([[NSUserDefaults standardUserDefaults] boolForKey:HTNotifierAlwaysSendKey]) {
[self performSelectorInBackground:@selector(postNoticesWithPaths:) withObject:notices];
@@ -505,7 +564,7 @@ - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
- NSArray *notices = HTNotices();
+ NSArray *notices = ABNotifierAllNotices();
if (buttonIndex == alertView.cancelButtonIndex) {
for (NSString *notice in notices) {
[[NSFileManager defaultManager]
Please sign in to comment.
Something went wrong with that request. Please try again.