Merge branch 'refs/heads/feature/CrashReporting' into feature/CrashDetails

Conflicts:
	Classes/BITCrashManager.h
This commit is contained in:
Andreas Linde 2014-04-27 20:04:31 +02:00
commit c4e7754a8b
48 changed files with 966 additions and 183 deletions

0
Classes/BITAttributedLabel.h Executable file → Normal file
View File

0
Classes/BITAttributedLabel.m Executable file → Normal file
View File

View File

@ -108,9 +108,9 @@ static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44};
// make sure this is called after startManager so all modules are fully setup // make sure this is called after startManager so all modules are fully setup
if (!_isSetup) { if (!_isSetup) {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(authenticateInstallation) object:nil];
[self performSelector:@selector(authenticateInstallation) withObject:nil afterDelay:0.1]; [self performSelector:@selector(authenticateInstallation) withObject:nil afterDelay:0.1];
} } else {
switch ([[UIApplication sharedApplication] applicationState]) { switch ([[UIApplication sharedApplication] applicationState]) {
case UIApplicationStateActive: case UIApplicationStateActive:
[self authenticate]; [self authenticate];
@ -120,7 +120,7 @@ static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44};
// do nothing, wait for active state // do nothing, wait for active state
break; break;
} }
}
[self registerObservers]; [self registerObservers];
} }
@ -156,6 +156,10 @@ static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44};
} }
- (void)alertOnFailureStoringTokenInKeychain { - (void)alertOnFailureStoringTokenInKeychain {
if ([[UIApplication sharedApplication] applicationState] != UIApplicationStateActive) {
return;
}
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil
message:BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerStorageError") message:BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerStorageError")
delegate:self delegate:self
@ -607,7 +611,6 @@ static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44};
case BITAuthenticatorIdentificationTypeHockeyAppEmail: case BITAuthenticatorIdentificationTypeHockeyAppEmail:
case BITAuthenticatorIdentificationTypeAnonymous: case BITAuthenticatorIdentificationTypeAnonymous:
case BITAuthenticatorIdentificationTypeHockeyAppUser: case BITAuthenticatorIdentificationTypeHockeyAppUser:
NSAssert(NO, @"Should only be called for Device and WebAuth identificationType");
return NO; return NO;
} }

View File

@ -0,0 +1,66 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
/**
* Provides support to add binary attachments to crash reports
*
* This is used by `[BITCrashManagerDelegate attachmentForCrashManager:]`
*/
@interface BITCrashAttachment : NSObject<NSCoding>
/**
* The filename the attachment should get
*/
@property (nonatomic, readonly, strong) NSString *filename;
/**
* The attachment data as NSData object
*/
@property (nonatomic, readonly, strong) NSData *attachmentData;
/**
* The content type of your data as MIME type
*/
@property (nonatomic, readonly, strong) NSString *contentType;
/**
* Create an BITCrashAttachment instance with a given filename and NSData object
*
* @param filename The filename the attachment should get
* @param attachmentData The attachment data as NSData
* @param contentType The content type of your data as MIME type
*
* @return An instsance of BITCrashAttachment
*/
- (instancetype)initWithFilename:(NSString *)filename
attachmentData:(NSData *)attachmentData
contentType:(NSString *)contentType;
@end

View File

@ -0,0 +1,64 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "BITCrashAttachment.h"
@implementation BITCrashAttachment
- (instancetype)initWithFilename:(NSString *)filename
attachmentData:(NSData *)attachmentData
contentType:(NSString *)contentType
{
if (self = [super init]) {
_filename = filename;
_attachmentData = attachmentData;
_contentType = contentType;
}
return self;
}
#pragma mark - NSCoder
- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:self.filename forKey:@"filename"];
[encoder encodeObject:self.attachmentData forKey:@"data"];
[encoder encodeObject:self.contentType forKey:@"contentType"];
}
- (id)initWithCoder:(NSCoder *)decoder {
if ((self = [super init])) {
_filename = [decoder decodeObjectForKey:@"filename"];
_attachmentData = [decoder decodeObjectForKey:@"data"];
_contentType = [decoder decodeObjectForKey:@"contentType"];
}
return self;
}
@end

View File

@ -34,6 +34,11 @@
@class BITCrashDetails; @class BITCrashDetails;
/**
* Custom block that handles the alert that prompts the user whether he wants to send crash reports
*/
typedef void(^CustomAlertViewHandler)();
/** /**
* Crash Manager status * Crash Manager status
@ -54,6 +59,54 @@ typedef NS_ENUM(NSUInteger, BITCrashManagerStatus) {
}; };
/**
* Prototype of a callback function used to execute additional user code. Called upon completion of crash
* handling, after the crash report has been written to disk.
*
* @param context The API client's supplied context value.
*
* @see `BITCrashManagerCallbacks`
* @see `[BITCrashManager setCrashCallbacks:]`
*/
typedef void (*BITCrashManagerPostCrashSignalCallback)(void *context);
/**
* This structure contains callbacks supported by `BITCrashManager` to allow the host application to perform
* additional tasks prior to program termination after a crash has occured.
*
* @see `BITCrashManagerPostCrashSignalCallback`
* @see `[BITCrashManager setCrashCallbacks:]`
*/
typedef struct BITCrashManagerCallbacks {
/** An arbitrary user-supplied context value. This value may be NULL. */
void *context;
/**
* The callback used to report caught signal information.
*/
BITCrashManagerPostCrashSignalCallback handleSignal;
} BITCrashManagerCallbacks;
/**
* Crash Manager alert user input
*/
typedef NS_ENUM(NSUInteger, BITCrashManagerUserInput) {
/**
* User chose not to send the crash report
*/
BITCrashManagerUserInputDontSend = 0,
/**
* User wants the crash report to be sent
*/
BITCrashManagerUserInputSend = 1,
/**
* User chose to always send crash reports
*/
BITCrashManagerUserInputAlwaysSend = 2
};
@protocol BITCrashManagerDelegate; @protocol BITCrashManagerDelegate;
/** /**
@ -229,15 +282,18 @@ typedef NS_ENUM(NSUInteger, BITCrashManagerStatus) {
* *
* _Async-Safe Functions_ * _Async-Safe Functions_
* *
* A subset of functions are defined to be async-safe by the OS, and are safely callable from within a signal handler. If you do implement a custom post-crash handler, it must be async-safe. A table of POSIX-defined async-safe functions and additional information is available from the CERT programming guide - SIG30-C, see https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers * A subset of functions are defined to be async-safe by the OS, and are safely callable from within a signal handler. If you do implement a custom post-crash handler, it must be async-safe. A table of POSIX-defined async-safe functions and additional information is available from the [CERT programming guide - SIG30-C](https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers).
* *
* Most notably, the Objective-C runtime itself is not async-safe, and Objective-C may not be used within a signal handler. * Most notably, the Objective-C runtime itself is not async-safe, and Objective-C may not be used within a signal handler.
* *
* Documentation taken from PLCrashReporter: https://www.plcrashreporter.org/documentation/api/v1.2-rc2/async_safety.html * Documentation taken from PLCrashReporter: https://www.plcrashreporter.org/documentation/api/v1.2-rc2/async_safety.html
* *
* @see `BITCrashManagerPostCrashSignalCallback`
* @see `BITCrashManagerCallbacks`
*
* @param callbacks A pointer to an initialized PLCrashReporterCallback structure, see https://www.plcrashreporter.org/documentation/api/v1.2-rc2/struct_p_l_crash_reporter_callbacks.html * @param callbacks A pointer to an initialized PLCrashReporterCallback structure, see https://www.plcrashreporter.org/documentation/api/v1.2-rc2/struct_p_l_crash_reporter_callbacks.html
*/ */
- (void)setCrashCallbacks: (PLCrashReporterCallbacks *) callbacks; - (void)setCrashCallbacks: (BITCrashManagerCallbacks *) callbacks;
/** /**
@ -272,6 +328,26 @@ typedef NS_ENUM(NSUInteger, BITCrashManagerStatus) {
*/ */
@property (nonatomic, readonly) BOOL didCrashInLastSession; @property (nonatomic, readonly) BOOL didCrashInLastSession;
/**
Provides an interface to handle user input from a custom alert
@param userInput On this input depends, whether crash reports are sent, always sent or not sent and deleted.
@param userProvidedCrashDescription The content of this optional string will be attached to the crash report as the description and allows to ask the user for e.g. additional comments or info
@return Returns YES if the input is a valid option and successfully triggered further processing of the crash report
@see BITCrashManagerUserInput
*/
- (BOOL)handleUserInput:(BITCrashManagerUserInput)userInput withUserProvidedCrashDescription:(NSString*)userProvidedCrashDescription;
/**
Lets you set a custom block which handles showing a custom UI and asking the user
whether he wants to send the crash report.
@param alertViewHandler A block that is responsible for loading, presenting and and dismissing your custom user interface which prompts the user if he wants to send crash reports. The block is also responsible for triggering further processing of the crash reports.
@warning Block needs to call the `handleUserInput:withUserProvidedCrashDescription` method!
*/
- (void) setAlertViewHandler:(CustomAlertViewHandler)alertViewHandler;
/** /**
Indicates if the app was killed while being in foreground from the iOS Indicates if the app was killed while being in foreground from the iOS

View File

@ -32,12 +32,16 @@
#if HOCKEYSDK_FEATURE_CRASH_REPORTER #if HOCKEYSDK_FEATURE_CRASH_REPORTER
#import <CrashReporter/CrashReporter.h>
#import <SystemConfiguration/SystemConfiguration.h> #import <SystemConfiguration/SystemConfiguration.h>
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import "HockeySDKPrivate.h" #import "HockeySDKPrivate.h"
#import "BITHockeyHelper.h" #import "BITHockeyHelper.h"
#import "BITHockeyAppClient.h"
#import "BITCrashAttachment.h"
#import "BITHockeyBaseManagerPrivate.h" #import "BITHockeyBaseManagerPrivate.h"
#import "BITCrashManagerPrivate.h" #import "BITCrashManagerPrivate.h"
#import "BITCrashReportTextFormatter.h" #import "BITCrashReportTextFormatter.h"
@ -52,6 +56,11 @@
#define kBITCrashMetaUserEmail @"BITCrashMetaUserEmail" #define kBITCrashMetaUserEmail @"BITCrashMetaUserEmail"
#define kBITCrashMetaUserID @"BITCrashMetaUserID" #define kBITCrashMetaUserID @"BITCrashMetaUserID"
#define kBITCrashMetaApplicationLog @"BITCrashMetaApplicationLog" #define kBITCrashMetaApplicationLog @"BITCrashMetaApplicationLog"
#define kBITCrashMetaAttachment @"BITCrashMetaAttachment"
// internal keys
NSString *const KBITAttachmentDictIndex = @"index";
NSString *const KBITAttachmentDictAttachment = @"attachment";
NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus"; NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
@ -69,9 +78,28 @@ NSString *const kBITFakeCrashDeviceModel = @"BITFakeCrashDeviceModel";
NSString *const kBITFakeCrashAppBinaryUUID = @"BITFakeCrashAppBinaryUUID"; NSString *const kBITFakeCrashAppBinaryUUID = @"BITFakeCrashAppBinaryUUID";
NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString"; NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
static BITCrashManagerCallbacks bitCrashCallbacks = {
.context = NULL,
.handleSignal = NULL
};
// proxy implementation for PLCrashReporter to keep our interface stable while this can change
static void plcr_post_crash_callback (siginfo_t *info, ucontext_t *uap, void *context) {
if (bitCrashCallbacks.handleSignal != NULL)
bitCrashCallbacks.handleSignal(context);
}
static PLCrashReporterCallbacks plCrashCallbacks = {
.version = 0,
.context = NULL,
.handleSignal = plcr_post_crash_callback
};
@interface BITCrashManager () @interface BITCrashManager ()
@property (nonatomic, strong) NSFileManager *fileManager; @property (nonatomic, copy, setter = setAlertViewHandler:) CustomAlertViewHandler alertViewHandler;
@end @end
@ -80,6 +108,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
NSMutableArray *_crashFiles; NSMutableArray *_crashFiles;
NSString *_crashesDir; NSString *_crashesDir;
NSString *_lastCrashFilename;
NSString *_settingsFile; NSString *_settingsFile;
NSString *_analyzerInProgressFile; NSString *_analyzerInProgressFile;
NSFileManager *_fileManager; NSFileManager *_fileManager;
@ -127,6 +156,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
_didLogLowMemoryWarning = NO; _didLogLowMemoryWarning = NO;
_approvedCrashReports = [[NSMutableDictionary alloc] init]; _approvedCrashReports = [[NSMutableDictionary alloc] init];
_alertViewHandler = nil;
_fileManager = [[NSFileManager alloc] init]; _fileManager = [[NSFileManager alloc] init];
_crashFiles = [[NSMutableArray alloc] init]; _crashFiles = [[NSMutableArray alloc] init];
@ -187,9 +217,9 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
NSString *errorString = nil; NSString *errorString = nil;
NSMutableDictionary *rootObj = [NSMutableDictionary dictionaryWithCapacity:2]; NSMutableDictionary *rootObj = [NSMutableDictionary dictionaryWithCapacity:2];
if (_approvedCrashReports && [_approvedCrashReports count] > 0) if (_approvedCrashReports && [_approvedCrashReports count] > 0) {
[rootObj setObject:_approvedCrashReports forKey:kBITCrashApprovedReports]; [rootObj setObject:_approvedCrashReports forKey:kBITCrashApprovedReports];
}
NSData *plist = [NSPropertyListSerialization dataFromPropertyList:(id)rootObj NSData *plist = [NSPropertyListSerialization dataFromPropertyList:(id)rootObj
format:NSPropertyListBinaryFormat_v1_0 format:NSPropertyListBinaryFormat_v1_0
errorDescription:&errorString]; errorDescription:&errorString];
@ -234,13 +264,11 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
NSError *error = NULL; NSError *error = NULL;
for (NSUInteger i=0; i < [_crashFiles count]; i++) { for (NSUInteger i=0; i < [_crashFiles count]; i++) {
[_fileManager removeItemAtPath:[_crashFiles objectAtIndex:i] error:&error]; NSString *filename = [_crashFiles objectAtIndex:i];
[_fileManager removeItemAtPath:[[_crashFiles objectAtIndex:i] stringByAppendingString:@".meta"] error:&error];
NSString *cacheFilename = [[_crashFiles objectAtIndex:i] lastPathComponent]; NSString *cacheFilename = [[_crashFiles objectAtIndex:i] lastPathComponent];
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserName]];
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserEmail]]; [self cleanFilesAndKeychainWithFileName:filename CacheFilename:cacheFilename Error:error];
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserID]];
} }
[_crashFiles removeAllObjects]; [_crashFiles removeAllObjects];
[_approvedCrashReports removeAllObjects]; [_approvedCrashReports removeAllObjects];
@ -248,6 +276,71 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
[self saveSettings]; [self saveSettings];
} }
- (void)cleanFilesAndKeychainWithFileName:(NSString *)filename CacheFilename:(NSString *)cacheFilename Error:(NSError *)error{
[_fileManager removeItemAtPath:filename error:&error];
[_fileManager removeItemAtPath:[NSString stringWithFormat:@"%@.data", filename] error:&error];
[_fileManager removeItemAtPath:[NSString stringWithFormat:@"%@.meta", filename] error:&error];
[_fileManager removeItemAtPath:[NSString stringWithFormat:@"%@.desc", filename] error:&error];
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserName]];
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserEmail]];
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserID]];
}
- (void)persistAttachment:(BITCrashAttachment *)attachment withFilename:(NSString *)filename {
NSString *attachmentFilename = [filename stringByAppendingString:@".data"];
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:attachment forKey:kBITCrashMetaAttachment];
[archiver finishEncoding];
[data writeToFile:attachmentFilename atomically:YES];
}
- (void)persistUserProvidedCrashDescription:(NSString *)userProvidedCrashDescription {
if (userProvidedCrashDescription && [userProvidedCrashDescription length] > 0) {
NSError *error;
[userProvidedCrashDescription writeToFile:[NSString stringWithFormat:@"%@.desc", [_crashesDir stringByAppendingPathComponent: _lastCrashFilename]] atomically:YES encoding:NSUTF8StringEncoding error:&error];
}
}
/**
* Read the attachment data from the stored file
*
* @param filename The crash report id
*
* @return an BITCrashAttachment instance or nil
*/
- (BITCrashAttachment *)attachmentForCrashReport:(NSString *)filename {
NSString *attachmentFilename = [filename stringByAppendingString:@".data"];
if (![_fileManager fileExistsAtPath:attachmentFilename])
return nil;
NSData *codedData = [[NSData alloc] initWithContentsOfFile:attachmentFilename];
if (!codedData)
return nil;
NSKeyedUnarchiver *unarchiver = nil;
@try {
unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:codedData];
}
@catch (NSException *exception) {
return nil;
}
if ([unarchiver containsValueForKey:kBITCrashMetaAttachment]) {
BITCrashAttachment *attachment = [unarchiver decodeObjectForKey:kBITCrashMetaAttachment];
return attachment;
}
return nil;
}
/** /**
* Extract all app sepcific UUIDs from the crash reports * Extract all app sepcific UUIDs from the crash reports
* *
@ -474,7 +567,8 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
// if we have an identification from BITAuthenticator, use this as a default. // if we have an identification from BITAuthenticator, use this as a default.
if (( if ((
self.installationIdentificationType == BITAuthenticatorIdentificationTypeHockeyAppEmail || self.installationIdentificationType == BITAuthenticatorIdentificationTypeHockeyAppEmail ||
self.installationIdentificationType == BITAuthenticatorIdentificationTypeHockeyAppUser self.installationIdentificationType == BITAuthenticatorIdentificationTypeHockeyAppUser ||
self.installationIdentificationType == BITAuthenticatorIdentificationTypeWebAuth
) && ) &&
self.installationIdentification) { self.installationIdentification) {
useremail = self.installationIdentification; useremail = self.installationIdentification;
@ -494,12 +588,34 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
return useremail; return useremail;
} }
- (NSString *)getCrashesDir {
return _crashesDir;
}
#pragma mark - Public #pragma mark - Public
- (void)setCrashCallbacks: (PLCrashReporterCallbacks *) callbacks { /**
_crashCallBacks = callbacks; * Set the callback for PLCrashReporter
*
* @param callbacks BITCrashManagerCallbacks instance
*/
- (void)setCrashCallbacks: (BITCrashManagerCallbacks *) callbacks {
if (!callbacks) return;
// set our proxy callback struct
bitCrashCallbacks.context = callbacks->context;
bitCrashCallbacks.handleSignal = callbacks->handleSignal;
// set the PLCrashReporterCallbacks struct
plCrashCallbacks.context = callbacks->context;
_crashCallBacks = &plCrashCallbacks;
}
- (void)setAlertViewHandler:(CustomAlertViewHandler)alertViewHandler{
_alertViewHandler = alertViewHandler;
} }
/** /**
@ -567,6 +683,14 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
} }
[metaDict setObject:applicationLog forKey:kBITCrashMetaApplicationLog]; [metaDict setObject:applicationLog forKey:kBITCrashMetaApplicationLog];
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(attachmentForCrashManager:)]) {
BITCrashAttachment *attachment = [self.delegate attachmentForCrashManager:self];
if (attachment) {
[self persistAttachment:attachment withFilename:[_crashesDir stringByAppendingPathComponent: filename]];
}
}
NSData *plist = [NSPropertyListSerialization dataFromPropertyList:(id)metaDict NSData *plist = [NSPropertyListSerialization dataFromPropertyList:(id)metaDict
format:NSPropertyListBinaryFormat_v1_0 format:NSPropertyListBinaryFormat_v1_0
errorDescription:&errorString]; errorDescription:&errorString];
@ -577,6 +701,41 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
} }
} }
- (BOOL)handleUserInput:(BITCrashManagerUserInput)userInput withUserProvidedCrashDescription:(NSString *)userProvidedCrashDescription{
switch (userInput) {
case BITCrashManagerUserInputDontSend:
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashManagerWillCancelSendingCrashReport:)]) {
[self.delegate crashManagerWillCancelSendingCrashReport:self];
}
[self cleanCrashReports];
return YES;
case BITCrashManagerUserInputSend:
[self persistUserProvidedCrashDescription:userProvidedCrashDescription];
[self sendCrashReports];
return YES;
case BITCrashManagerUserInputAlwaysSend:
_crashManagerStatus = BITCrashManagerStatusAutoSend;
[[NSUserDefaults standardUserDefaults] setInteger:_crashManagerStatus forKey:kBITCrashManagerStatus];
[[NSUserDefaults standardUserDefaults] synchronize];
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashManagerWillSendCrashReportsAlways:)]) {
[self.delegate crashManagerWillSendCrashReportsAlways:self];
}
[self persistUserProvidedCrashDescription:userProvidedCrashDescription];
[self sendCrashReports];
return YES;
default:
return NO;
}
}
#pragma mark - PLCrashReporter #pragma mark - PLCrashReporter
/** /**
@ -602,6 +761,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
NSData *crashData = [[NSData alloc] initWithData:[self.plCrashReporter loadPendingCrashReportDataAndReturnError: &error]]; NSData *crashData = [[NSData alloc] initWithData:[self.plCrashReporter loadPendingCrashReportDataAndReturnError: &error]];
NSString *cacheFilename = [NSString stringWithFormat: @"%.0f", [NSDate timeIntervalSinceReferenceDate]]; NSString *cacheFilename = [NSString stringWithFormat: @"%.0f", [NSDate timeIntervalSinceReferenceDate]];
_lastCrashFilename = cacheFilename;
if (crashData == nil) { if (crashData == nil) {
BITHockeyLog(@"ERROR: Could not load crash report: %@", error); BITHockeyLog(@"ERROR: Could not load crash report: %@", error);
@ -676,7 +836,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
/** /**
* Check if there are any new crash reports that are not yet processed * Check if there are any new crash reports that are not yet processed
* *
* @return `YES` if ther eis at least one new crash report found, `NO` otherwise * @return `YES` if there is at least one new crash report found, `NO` otherwise
*/ */
- (BOOL)hasPendingCrashReport { - (BOOL)hasPendingCrashReport {
if (_crashManagerStatus == BITCrashManagerStatusDisabled) return NO; if (_crashManagerStatus == BITCrashManagerStatusDisabled) return NO;
@ -693,7 +853,9 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
![file hasSuffix:@".DS_Store"] && ![file hasSuffix:@".DS_Store"] &&
![file hasSuffix:@".analyzer"] && ![file hasSuffix:@".analyzer"] &&
![file hasSuffix:@".plist"] && ![file hasSuffix:@".plist"] &&
![file hasSuffix:@".meta"]) { ![file hasSuffix:@".data"] &&
![file hasSuffix:@".meta"] &&
![file hasSuffix:@".desc"]) {
[_crashFiles addObject:[_crashesDir stringByAppendingPathComponent: file]]; [_crashFiles addObject:[_crashesDir stringByAppendingPathComponent: file]];
} }
} }
@ -771,6 +933,9 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
alertDescription = [NSString stringWithFormat:BITHockeyLocalizedString(@"CrashDataFoundDescription"), appName]; alertDescription = [NSString stringWithFormat:BITHockeyLocalizedString(@"CrashDataFoundDescription"), appName];
} }
if (_alertViewHandler) {
_alertViewHandler();
} else {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:BITHockeyLocalizedString(@"CrashDataFoundTitle"), appName] UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:BITHockeyLocalizedString(@"CrashDataFoundTitle"), appName]
message:alertDescription message:alertDescription
delegate:self delegate:self
@ -782,6 +947,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
} }
[alertView show]; [alertView show];
}
} else { } else {
[self sendCrashReports]; [self sendCrashReports];
} }
@ -1004,6 +1170,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
NSError *error = NULL; NSError *error = NULL;
NSMutableString *crashes = nil; NSMutableString *crashes = nil;
NSMutableArray *attachments = [NSMutableArray array];
_crashIdenticalCurrentVersion = NO; _crashIdenticalCurrentVersion = NO;
for (NSUInteger i=0; i < [_crashFiles count]; i++) { for (NSUInteger i=0; i < [_crashFiles count]; i++) {
@ -1053,12 +1220,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
if (report == nil && crashLogString == nil) { if (report == nil && crashLogString == nil) {
BITHockeyLog(@"WARNING: Could not parse crash report"); BITHockeyLog(@"WARNING: Could not parse crash report");
// we cannot do anything with this report, so delete it // we cannot do anything with this report, so delete it
[_fileManager removeItemAtPath:filename error:&error]; [self cleanFilesAndKeychainWithFileName:filename CacheFilename:cacheFilename Error:error];
[_fileManager removeItemAtPath:[NSString stringWithFormat:@"%@.meta", metaFilename] error:&error];
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserName]];
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserEmail]];
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserID]];
continue; continue;
} }
@ -1102,12 +1264,24 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
useremail = [self stringValueFromKeychainForKey:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserEmail]] ?: @""; useremail = [self stringValueFromKeychainForKey:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserEmail]] ?: @"";
userid = [self stringValueFromKeychainForKey:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserID]] ?: @""; userid = [self stringValueFromKeychainForKey:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserID]] ?: @"";
applicationLog = [metaDict objectForKey:kBITCrashMetaApplicationLog] ?: @""; applicationLog = [metaDict objectForKey:kBITCrashMetaApplicationLog] ?: @"";
description = [NSString stringWithContentsOfFile:[NSString stringWithFormat:@"%@.desc", [_crashesDir stringByAppendingPathComponent: cacheFilename]] encoding:NSUTF8StringEncoding error:&error];
BITCrashAttachment *attachment = [self attachmentForCrashReport:filename];
if (attachment) {
NSDictionary *attachmentDict = @{KBITAttachmentDictIndex: @(i),
KBITAttachmentDictAttachment: attachment};
[attachments addObject:attachmentDict];
}
} else { } else {
BITHockeyLog(@"ERROR: Reading crash meta data. %@", error); BITHockeyLog(@"ERROR: Reading crash meta data. %@", error);
} }
if ([applicationLog length] > 0) { if ([applicationLog length] > 0) {
description = [NSString stringWithFormat:@"%@", applicationLog]; if ([description length] > 0) {
description = [NSString stringWithFormat:@"%@\n\nLog:\n%@", description, applicationLog];
} else {
description = [NSString stringWithFormat:@"Log:\n%@", applicationLog];
}
} }
[crashes appendFormat:@"<crash><applicationname>%s</applicationname><uuids>%@</uuids><bundleidentifier>%@</bundleidentifier><systemversion>%@</systemversion><platform>%@</platform><senderversion>%@</senderversion><version>%@</version><uuid>%@</uuid><log><![CDATA[%@]]></log><userid>%@</userid><username>%@</username><contact>%@</contact><installstring>%@</installstring><description><![CDATA[%@]]></description></crash>", [crashes appendFormat:@"<crash><applicationname>%s</applicationname><uuids>%@</uuids><bundleidentifier>%@</bundleidentifier><systemversion>%@</systemversion><platform>%@</platform><senderversion>%@</senderversion><version>%@</version><uuid>%@</uuid><log><![CDATA[%@]]></log><userid>%@</userid><username>%@</username><contact>%@</contact><installstring>%@</installstring><description><![CDATA[%@]]></description></crash>",
@ -1131,12 +1305,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
[_approvedCrashReports setObject:[NSNumber numberWithBool:YES] forKey:filename]; [_approvedCrashReports setObject:[NSNumber numberWithBool:YES] forKey:filename];
} else { } else {
// we cannot do anything with this report, so delete it // we cannot do anything with this report, so delete it
[_fileManager removeItemAtPath:filename error:&error]; [self cleanFilesAndKeychainWithFileName:filename CacheFilename:cacheFilename Error:error];
[_fileManager removeItemAtPath:[NSString stringWithFormat:@"%@.meta", filename] error:&error];
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserName]];
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserEmail]];
[self removeKeyFromKeychain:[NSString stringWithFormat:@"%@.%@", cacheFilename, kBITCrashMetaUserID]];
} }
} }
@ -1144,7 +1313,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
if (crashes != nil) { if (crashes != nil) {
BITHockeyLog(@"INFO: Sending crash reports:\n%@", crashes); BITHockeyLog(@"INFO: Sending crash reports:\n%@", crashes);
[self postXML:[NSString stringWithFormat:@"<crashes>%@</crashes>", crashes]]; [self postXML:[NSString stringWithFormat:@"<crashes>%@</crashes>", crashes] attachments:attachments];
} }
} }
@ -1154,35 +1323,20 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
switch (buttonIndex) { switch (buttonIndex) {
case 0: case 0:
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashManagerWillCancelSendingCrashReport:)]) { [self handleUserInput:BITCrashManagerUserInputDontSend withUserProvidedCrashDescription:nil];
[self.delegate crashManagerWillCancelSendingCrashReport:self];
}
_sendingInProgress = NO;
[self cleanCrashReports];
break; break;
case 1: case 1:
[self sendCrashReports]; [self handleUserInput:BITCrashManagerUserInputSend withUserProvidedCrashDescription:nil];
break; break;
case 2: { case 2:
_crashManagerStatus = BITCrashManagerStatusAutoSend; [self handleUserInput:BITCrashManagerUserInputAlwaysSend withUserProvidedCrashDescription:nil];
[[NSUserDefaults standardUserDefaults] setInteger:_crashManagerStatus forKey:kBITCrashManagerStatus];
[[NSUserDefaults standardUserDefaults] synchronize];
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashManagerWillSendCrashReportsAlways:)]) {
[self.delegate crashManagerWillSendCrashReportsAlways:self];
}
[self sendCrashReports];
break;
}
default:
_sendingInProgress = NO;
[self cleanCrashReports];
break; break;
} }
} }
#pragma mark - Networking #pragma mark - Networking
/** /**
@ -1192,7 +1346,7 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
* *
* @param xml The XML data that needs to be send to the server * @param xml The XML data that needs to be send to the server
*/ */
- (void)postXML:(NSString*)xml { - (void)postXML:(NSString*)xml attachments:(NSArray *)attachments {
NSMutableURLRequest *request = nil; NSMutableURLRequest *request = nil;
NSString *boundary = @"----FOO"; NSString *boundary = @"----FOO";
@ -1214,10 +1368,26 @@ NSString *const kBITFakeCrashReport = @"BITFakeCrashAppString";
[request setValue:contentType forHTTPHeaderField:@"Content-type"]; [request setValue:contentType forHTTPHeaderField:@"Content-type"];
NSMutableData *postBody = [NSMutableData data]; NSMutableData *postBody = [NSMutableData data];
[postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[@"Content-Disposition: form-data; name=\"xml\"; filename=\"crash.xml\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [postBody appendData:[BITHockeyAppClient dataWithPostValue:[xml dataUsingEncoding:NSUTF8StringEncoding]
[postBody appendData:[[NSString stringWithFormat:@"Content-Type: text/xml\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; forKey:@"xml"
[postBody appendData:[xml dataUsingEncoding:NSUTF8StringEncoding]]; contentType:@"text/xml"
boundary:boundary
filename:@"crash.xml"]];
for (NSDictionary *dict in attachments) {
NSInteger index = [(NSNumber *)dict[KBITAttachmentDictIndex] integerValue];
NSString *key = [NSString stringWithFormat:@"attachment%ld", (long)index];
BITCrashAttachment *attachment = (BITCrashAttachment *)dict[KBITAttachmentDictAttachment];
[postBody appendData:[BITHockeyAppClient dataWithPostValue:attachment.attachmentData
forKey:key
contentType:attachment.contentType
boundary:boundary
filename:attachment.filename]];
}
[postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:postBody]; [request setHTTPBody:postBody];

View File

@ -29,6 +29,7 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
@class BITCrashManager; @class BITCrashManager;
@class BITCrashAttachment;
/** /**
The `BITCrashManagerDelegate` formal protocol defines methods further configuring The `BITCrashManagerDelegate` formal protocol defines methods further configuring
@ -47,17 +48,43 @@
/** Return any log string based data the crash report being processed should contain /** Return any log string based data the crash report being processed should contain
@param crashManager The `BITCrashManager` instance invoking this delegate @param crashManager The `BITCrashManager` instance invoking this delegate
@see attachmentForCrashManager:
@see userNameForCrashManager: @see userNameForCrashManager:
@see userEmailForCrashManager: @see userEmailForCrashManager:
*/ */
-(NSString *)applicationLogForCrashManager:(BITCrashManager *)crashManager; -(NSString *)applicationLogForCrashManager:(BITCrashManager *)crashManager;
/** Return a BITCrashAttachment object providing an NSData object the crash report
being processed should contain
Please limit your attachments to reasonable files to avoid high traffic costs for your users.
Example implementation:
- (BITCrashAttachment *)attachmentForCrashManager:(BITCrashManager *)crashManager {
NSData *data = [NSData dataWithContentsOfURL:@"mydatafile"];
BITCrashAttachment *attachment = [[BITCrashAttachment alloc] initWithFilename:@"myfile.data"
attachmentData:data
contentType:@"'application/octet-stream"];
return attachment;
}
@param crashManager The `BITCrashManager` instance invoking this delegate
@see applicationLogForCrashManager:
@see userNameForCrashManager:
@see userEmailForCrashManager:
*/
-(BITCrashAttachment *)attachmentForCrashManager:(BITCrashManager *)crashManager;
/** Return the user name or userid that should be send along each crash report /** Return the user name or userid that should be send along each crash report
@param crashManager The `BITCrashManager` instance invoking this delegate @param crashManager The `BITCrashManager` instance invoking this delegate
@see applicationLogForCrashManager: @see applicationLogForCrashManager:
@see attachmentForCrashManager:
@see userEmailForCrashManager: @see userEmailForCrashManager:
@deprecated Please use `BITHockeyManagerDelegate userNameForHockeyManager:componentManager:` instead @deprecated Please use `BITHockeyManagerDelegate userNameForHockeyManager:componentManager:` instead
@warning When returning a non nil value, crash reports are not anonymous any @warning When returning a non nil value, crash reports are not anonymous any
@ -71,6 +98,7 @@
@param crashManager The `BITCrashManager` instance invoking this delegate @param crashManager The `BITCrashManager` instance invoking this delegate
@see applicationLogForCrashManager: @see applicationLogForCrashManager:
@see attachmentForCrashManager:
@see userNameForCrashManager: @see userNameForCrashManager:
@deprecated Please use `BITHockeyManagerDelegate userEmailForHockeyManager:componentManager:` instead @deprecated Please use `BITHockeyManagerDelegate userEmailForHockeyManager:componentManager:` instead
@warning When returning a non nil value, crash reports are not anonymous any @warning When returning a non nil value, crash reports are not anonymous any

View File

@ -31,13 +31,19 @@
#if HOCKEYSDK_FEATURE_CRASH_REPORTER #if HOCKEYSDK_FEATURE_CRASH_REPORTER
#import <CrashReporter/CrashReporter.h>
@interface BITCrashManager () { @interface BITCrashManager () {
} }
@property (nonatomic) NSUncaughtExceptionHandler *exceptionHandler; @property (nonatomic) NSUncaughtExceptionHandler *exceptionHandler;
@property (nonatomic, strong) NSFileManager *fileManager;
@property (nonatomic, strong) BITPLCrashReporter *plCrashReporter; @property (nonatomic, strong) BITPLCrashReporter *plCrashReporter;
@property (nonatomic) NSString *lastCrashFilename;
#if HOCKEYSDK_FEATURE_AUTHENTICATOR #if HOCKEYSDK_FEATURE_AUTHENTICATOR
// Only set via BITAuthenticator // Only set via BITAuthenticator
@ -61,9 +67,17 @@
- (BOOL)hasPendingCrashReport; - (BOOL)hasPendingCrashReport;
- (BOOL)hasNonApprovedCrashReports; - (BOOL)hasNonApprovedCrashReports;
- (void)persistUserProvidedCrashDescription:(NSString *)userProvidedCrashDescription;
- (void)persistAttachment:(BITCrashAttachment *)attachment withFilename:(NSString *)filename;
- (BITCrashAttachment *)attachmentForCrashReport:(NSString *)filename;
- (void)invokeDelayedProcessing; - (void)invokeDelayedProcessing;
- (void)sendCrashReports; - (void)sendCrashReports;
- (NSString *)getCrashesDir;
- (void)setLastCrashFilename:(NSString *)lastCrashFilename;
@end @end

View File

@ -56,6 +56,11 @@
@property (nonatomic, copy) NSString *userEmail; @property (nonatomic, copy) NSString *userEmail;
// Fetch user meta data
- (BOOL)updateUserIDUsingKeychainAndDelegate;
- (BOOL)updateUserNameUsingKeychainAndDelegate;
- (BOOL)updateUserEmailUsingKeychainAndDelegate;
// load new messages from the server // load new messages from the server
- (void)updateMessagesList; - (void)updateMessagesList;

View File

@ -118,8 +118,8 @@
#pragma mark - Helpers #pragma mark - Helpers
/** /**
* create a post body from the given value, key and boundary * create a post body from the given value, key and boundary. This is a convenience call to
* c/p from HockeyBaseManager * dataWithPostValue:forKey:contentType:boundary and aimed at NSString-content.
* *
* @param value - * @param value -
* @param key - * @param key -
@ -128,4 +128,18 @@
* @return NSData instance configured to be attached on a (post) URLRequest * @return NSData instance configured to be attached on a (post) URLRequest
*/ */
+ (NSData *)dataWithPostValue:(NSString *)value forKey:(NSString *)key boundary:(NSString *) boundary; + (NSData *)dataWithPostValue:(NSString *)value forKey:(NSString *)key boundary:(NSString *) boundary;
/**
* create a post body from the given value, key and boundary and content type.
*
* @param value -
* @param key -
*@param contentType -
* @param boundary -
* @param filename -
*
* @return NSData instance configured to be attached on a (post) URLRequest
*/
+ (NSData *)dataWithPostValue:(NSData *)value forKey:(NSString *)key contentType:(NSString *)contentType boundary:(NSString *) boundary filename:(NSString *)filename;
@end @end

View File

@ -85,12 +85,25 @@
} }
+ (NSData *)dataWithPostValue:(NSString *)value forKey:(NSString *)key boundary:(NSString *) boundary { + (NSData *)dataWithPostValue:(NSString *)value forKey:(NSString *)key boundary:(NSString *) boundary {
return [self dataWithPostValue:[value dataUsingEncoding:NSUTF8StringEncoding] forKey:key contentType:@"text" boundary:boundary filename:nil];
}
+ (NSData *)dataWithPostValue:(NSData *)value forKey:(NSString *)key contentType:(NSString *)contentType boundary:(NSString *) boundary filename:(NSString *)filename {
NSMutableData *postBody = [NSMutableData data]; NSMutableData *postBody = [NSMutableData data];
[postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\";\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithFormat:@"Content-Type: text\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; // There's certainly a better way to check if we are supposed to send binary data here.
[postBody appendData:[value dataUsingEncoding:NSUTF8StringEncoding]]; if (filename){
[postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", key, filename] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n", contentType] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithFormat:@"Content-Transfer-Encoding: binary\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
} else {
[postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", contentType] dataUsingEncoding:NSUTF8StringEncoding]];
}
[postBody appendData:value];
[postBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [postBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
return postBody; return postBody;

View File

@ -38,9 +38,8 @@
#import "BITKeychainUtils.h" #import "BITKeychainUtils.h"
#import <sys/sysctl.h> #import <sys/sysctl.h>
#if !TARGET_IPHONE_SIMULATOR #import <mach-o/dyld.h>
#import <mach-o/ldsyms.h> #import <mach-o/loader.h>
#endif
#ifndef __IPHONE_6_1 #ifndef __IPHONE_6_1
#define __IPHONE_6_1 60100 #define __IPHONE_6_1 60100
@ -134,29 +133,35 @@
} }
- (NSString *)executableUUID { - (NSString *)executableUUID {
// This now requires the testing of this feature to be done on an actual device, since it returns always empty strings on the simulator const struct mach_header *executableHeader = NULL;
// Once there is a better solution to get unit test targets build without problems this should be changed again, so testing of this for (uint32_t i = 0; i < _dyld_image_count(); i++) {
// feature is also possible using the simulator const struct mach_header *header = _dyld_get_image_header(i);
// See: http://support.hockeyapp.net/discussions/problems/2306-integrating-hockeyapp-with-test-bundle-target-i386-issues if (header->filetype == MH_EXECUTE) {
// http://support.hockeyapp.net/discussions/problems/4113-linking-hockeysdk-to-test-bundle-target executableHeader = header;
#if !TARGET_IPHONE_SIMULATOR break;
const uint8_t *command = (const uint8_t *)(&_mh_execute_header + 1); }
for (uint32_t idx = 0; idx < _mh_execute_header.ncmds; ++idx) { }
const struct load_command *load_command = (const struct load_command *)command;
if (load_command->cmd == LC_UUID) { if (!executableHeader)
const struct uuid_command *uuid_command = (const struct uuid_command *)command; return @"";
const uint8_t *uuid = uuid_command->uuid;
BOOL is64bit = executableHeader->magic == MH_MAGIC_64 || executableHeader->magic == MH_CIGAM_64;
uintptr_t cursor = (uintptr_t)executableHeader + (is64bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header));
const struct segment_command *segmentCommand = NULL;
for (uint32_t i = 0; i < executableHeader->ncmds; i++, cursor += segmentCommand->cmdsize) {
segmentCommand = (struct segment_command *)cursor;
if (segmentCommand->cmd == LC_UUID) {
const struct uuid_command *uuidCommand = (const struct uuid_command *)segmentCommand;
const uint8_t *uuid = uuidCommand->uuid;
return [[NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", return [[NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
uuid[0], uuid[1], uuid[2], uuid[3], uuid[0], uuid[1], uuid[2], uuid[3],
uuid[4], uuid[5], uuid[6], uuid[7], uuid[4], uuid[5], uuid[6], uuid[7],
uuid[8], uuid[9], uuid[10], uuid[11], uuid[8], uuid[9], uuid[10], uuid[11],
uuid[12], uuid[13], uuid[14], uuid[15]] uuid[12], uuid[13], uuid[14], uuid[15]]
lowercaseString]; lowercaseString];
} else {
command += load_command->cmdsize;
} }
} }
#endif
return @""; return @"";
} }

View File

@ -458,10 +458,7 @@ UIImage *bit_newWithContentsOfResolutionIndependentFile(NSString * path) {
UIImage *bit_imageWithContentsOfResolutionIndependentFile(NSString *path) { UIImage *bit_imageWithContentsOfResolutionIndependentFile(NSString *path) {
#ifndef __clang_analyzer__
// clang alayzer in 4.2b3 thinks here's a leak, which is not the case.
return bit_newWithContentsOfResolutionIndependentFile(path); return bit_newWithContentsOfResolutionIndependentFile(path);
#endif
} }

View File

@ -36,6 +36,20 @@
#import "BITHockeyAppClient.h" #import "BITHockeyAppClient.h"
#import "BITKeychainUtils.h" #import "BITKeychainUtils.h"
#include <stdint.h>
typedef struct {
uint8_t info_version;
const char hockey_version[16];
const char hockey_build[16];
} bitstadium_info_t;
bitstadium_info_t bitstadium_library_info __attribute__((section("__TEXT,__bit_hockey,regular,no_dead_strip"))) = {
.info_version = 1,
.hockey_version = BITHOCKEY_C_VERSION,
.hockey_build = BITHOCKEY_C_BUILD
};
#if HOCKEYSDK_FEATURE_CRASH_REPORTER #if HOCKEYSDK_FEATURE_CRASH_REPORTER
#import "BITCrashManagerPrivate.h" #import "BITCrashManagerPrivate.h"
@ -417,11 +431,11 @@
- (NSString *)version { - (NSString *)version {
return BITHOCKEY_VERSION; return [NSString stringWithUTF8String:bitstadium_library_info.hockey_version];
} }
- (NSString *)build { - (NSString *)build {
return BITHOCKEY_BUILD; return [NSString stringWithUTF8String:bitstadium_library_info.hockey_build];
} }

View File

@ -155,7 +155,7 @@
if ([self.userDefaults objectForKey:kBITStoreUpdateLastUUID]) { if ([self.userDefaults objectForKey:kBITStoreUpdateLastUUID]) {
lastSavedUUID = [self.userDefaults objectForKey:kBITStoreUpdateLastUUID]; lastSavedUUID = [self.userDefaults objectForKey:kBITStoreUpdateLastUUID];
if (lastSavedUUID && ![lastSavedUUID isEqualToString:_currentUUID]) { if (lastSavedUUID && [lastSavedUUID length] > 0 && ![lastSavedUUID isEqualToString:_currentUUID]) {
// the UUIDs don't match, store the new one // the UUIDs don't match, store the new one
[self.userDefaults setObject:_currentUUID forKey:kBITStoreUpdateLastUUID]; [self.userDefaults setObject:_currentUUID forKey:kBITStoreUpdateLastUUID];

View File

@ -669,7 +669,7 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
self.checkInProgress = YES; self.checkInProgress = YES;
// do we need to update? // do we need to update?
if (![self checkForTracker] && ![self shouldCheckForUpdates] && !_currentHockeyViewController) { if (![self checkForTracker] && !_currentHockeyViewController && ![self shouldCheckForUpdates] && _updateSetting != BITUpdateCheckManually) {
BITHockeyLog(@"INFO: Update not needed right now"); BITHockeyLog(@"INFO: Update not needed right now");
self.checkInProgress = NO; self.checkInProgress = NO;
return; return;

View File

@ -37,6 +37,7 @@
#if HOCKEYSDK_FEATURE_CRASH_REPORTER #if HOCKEYSDK_FEATURE_CRASH_REPORTER
#import "BITCrashManager.h" #import "BITCrashManager.h"
#import "BITCrashAttachment.h"
#import "BITCrashManagerDelegate.h" #import "BITCrashManagerDelegate.h"
#import "BITCrashDetails.h" #import "BITCrashDetails.h"
#endif /* HOCKEYSDK_FEATURE_CRASH_REPORTER */ #endif /* HOCKEYSDK_FEATURE_CRASH_REPORTER */

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'HockeySDK' s.name = 'HockeySDK'
s.version = '3.5.4' s.version = '3.5.5'
s.summary = 'Collect live crash reports, get feedback from your users, distribute your betas, and analyze your test coverage with HockeyApp.' s.summary = 'Collect live crash reports, get feedback from your users, distribute your betas, and analyze your test coverage with HockeyApp.'
s.description = <<-DESC s.description = <<-DESC
@ -12,19 +12,19 @@ Pod::Spec.new do |s|
DESC DESC
s.homepage = 'http://hockeyapp.net/' s.homepage = 'http://hockeyapp.net/'
s.documentation_url = 'http://hockeyapp.net/help/sdk/ios/3.5.4/' s.documentation_url = 'http://hockeyapp.net/help/sdk/ios/3.5.5/'
s.license = 'MIT' s.license = 'MIT'
s.author = { 'Andreas Linde' => 'mail@andreaslinde.de', 'Thomas Dohmke' => "thomas@dohmke.de" } s.author = { 'Andreas Linde' => 'mail@andreaslinde.de', 'Thomas Dohmke' => "thomas@dohmke.de" }
s.source = { :git => 'https://github.com/bitstadium/HockeySDK-iOS.git', :tag => s.version.to_s } s.source = { :git => 'https://github.com/bitstadium/HockeySDK-iOS.git', :tag => s.version.to_s }
s.platform = :ios, '5.0' s.platform = :ios, '5.0'
s.source_files = 'Classes' s.source_files = 'Classes', "Vendor/CrashReporter.framework/Versions/A/Headers/*.h"
s.requires_arc = true s.requires_arc = true
s.frameworks = 'CoreText', 'QuartzCore', 'SystemConfiguration', 'CoreGraphics', 'UIKit', 'Security' s.frameworks = 'CoreText', 'QuartzCore', 'SystemConfiguration', 'CoreGraphics', 'UIKit', 'Security'
s.ios.vendored_frameworks = 'Vendor/CrashReporter.framework' s.ios.vendored_frameworks = 'Vendor/CrashReporter.framework'
s.xcconfig = {'GCC_PREPROCESSOR_DEFINITIONS' => %{$(inherited) BITHOCKEY_VERSION="@\\"#{s.version}\\"" BITHOCKEY_BUILD="@\\"27\\""} } s.xcconfig = {'GCC_PREPROCESSOR_DEFINITIONS' => %{$(inherited) BITHOCKEY_VERSION="@\\"#{s.version}\\"" BITHOCKEY_C_VERSION="\\"#{s.version}\\"" BITHOCKEY_BUILD="@\\"28\\"" BITHOCKEY_C_BUILD="\\"28\\""} }
s.resource_bundle = { 'HockeySDKResources' => ['Resources/*.png', 'Resources/*.lproj'] } s.resource_bundle = { 'HockeySDKResources' => ['Resources/*.png', 'Resources/*.lproj'] }
s.preserve_paths = 'Resources', 'Support' s.preserve_paths = 'Resources', 'Support'

0
LICENSE Executable file → Normal file
View File

View File

@ -1,6 +1,6 @@
## Version 3.5.4 ## Version 3.5.5
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.4/docs/docs/Changelog.html) - [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.5/docs/docs/Changelog.html)
## Introduction ## Introduction
@ -31,10 +31,10 @@ The main SDK class is `BITHockeyManager`. It initializes all modules and provide
## Installation & Setup ## Installation & Setup
- [Installation & Setup](http://www.hockeyapp.net/help/sdk/ios/3.5.4/docs/docs/Guide-Installation-Setup.html) (Recommended) - [Installation & Setup](http://www.hockeyapp.net/help/sdk/ios/3.5.5/docs/docs/Guide-Installation-Setup.html) (Recommended)
- [Installation & Setup Advanced](http://www.hockeyapp.net/help/sdk/ios/3.5.4/docs/docs/Guide-Installation-Setup-Advanced.html) (Using Git submodule and Xcode sub-project) - [Installation & Setup Advanced](http://www.hockeyapp.net/help/sdk/ios/3.5.5/docs/docs/Guide-Installation-Setup-Advanced.html) (Using Git submodule and Xcode sub-project)
- [Identify and authenticate users of Ad-Hoc or Enterprise builds](http://www.hockeyapp.net/help/sdk/ios/3.5.4/docs/docs/HowTo-Authenticating-Users-on-iOS.html) - [Identify and authenticate users of Ad-Hoc or Enterprise builds](http://www.hockeyapp.net/help/sdk/ios/3.5.5/docs/docs/HowTo-Authenticating-Users-on-iOS.html)
- [Migration from previous SDK Versions](http://www.hockeyapp.net/help/sdk/ios/3.5.4/docs/docs/Guide-Migration-Kits.html) - [Migration from previous SDK Versions](http://www.hockeyapp.net/help/sdk/ios/3.5.5/docs/docs/Guide-Migration-Kits.html)
- [Mac Desktop Uploader](http://support.hockeyapp.net/kb/how-tos/how-to-upload-to-hockeyapp-on-a-mac) - [Mac Desktop Uploader](http://support.hockeyapp.net/kb/how-tos/how-to-upload-to-hockeyapp-on-a-mac)
@ -48,4 +48,4 @@ This documentation provides integrated help in Xcode for all public APIs and a s
3. Copy the content into ~`/Library/Developer/Shared/Documentation/DocSets` 3. Copy the content into ~`/Library/Developer/Shared/Documentation/DocSets`
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.4/](http://hockeyapp.net/help/sdk/ios/3.5.4/) The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.5/](http://hockeyapp.net/help/sdk/ios/3.5.5/)

0
Resources/nl.lproj/HockeySDK.strings Executable file → Normal file
View File

0
Resources/ro.lproj/HockeySDK.strings Executable file → Normal file
View File

View File

@ -95,10 +95,10 @@
1E5955D015B71C8600A03429 /* IconGradient@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E5955C515B71C8600A03429 /* IconGradient@2x.png */; }; 1E5955D015B71C8600A03429 /* IconGradient@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E5955C515B71C8600A03429 /* IconGradient@2x.png */; };
1E5955FD15B7877B00A03429 /* BITHockeyManagerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E5955FA15B7877A00A03429 /* BITHockeyManagerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1E5955FD15B7877B00A03429 /* BITHockeyManagerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E5955FA15B7877A00A03429 /* BITHockeyManagerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
1E5A459216F0DFC200B55C04 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E5A459116F0DFC200B55C04 /* SenTestingKit.framework */; }; 1E5A459216F0DFC200B55C04 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E5A459116F0DFC200B55C04 /* SenTestingKit.framework */; };
1E5A459416F0DFC200B55C04 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E5A459316F0DFC200B55C04 /* UIKit.framework */; };
1E5A459516F0DFC200B55C04 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E400561D148D79B500EB22B9 /* Foundation.framework */; }; 1E5A459516F0DFC200B55C04 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E400561D148D79B500EB22B9 /* Foundation.framework */; };
1E5A459B16F0DFC200B55C04 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1E5A459916F0DFC200B55C04 /* InfoPlist.strings */; }; 1E5A459B16F0DFC200B55C04 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1E5A459916F0DFC200B55C04 /* InfoPlist.strings */; };
1E5A459E16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E5A459D16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m */; }; 1E5A459E16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E5A459D16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m */; };
1E61CCAF18E0585A00A5E38E /* BITFeedbackManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E61CCAE18E0585A00A5E38E /* BITFeedbackManagerTests.m */; };
1E70A23217F2F982001BB32D /* live_report_empty.plcrash in Resources */ = {isa = PBXBuildFile; fileRef = 1E70A22F17F2F982001BB32D /* live_report_empty.plcrash */; }; 1E70A23217F2F982001BB32D /* live_report_empty.plcrash in Resources */ = {isa = PBXBuildFile; fileRef = 1E70A22F17F2F982001BB32D /* live_report_empty.plcrash */; };
1E70A23317F2F982001BB32D /* live_report_exception.plcrash in Resources */ = {isa = PBXBuildFile; fileRef = 1E70A23017F2F982001BB32D /* live_report_exception.plcrash */; }; 1E70A23317F2F982001BB32D /* live_report_exception.plcrash in Resources */ = {isa = PBXBuildFile; fileRef = 1E70A23017F2F982001BB32D /* live_report_exception.plcrash */; };
1E70A23417F2F982001BB32D /* live_report_signal.plcrash in Resources */ = {isa = PBXBuildFile; fileRef = 1E70A23117F2F982001BB32D /* live_report_signal.plcrash */; }; 1E70A23417F2F982001BB32D /* live_report_signal.plcrash in Resources */ = {isa = PBXBuildFile; fileRef = 1E70A23117F2F982001BB32D /* live_report_signal.plcrash */; };
@ -129,6 +129,8 @@
1EAF20AA162DC0F600957B1D /* feedbackActiviy.png in Resources */ = {isa = PBXBuildFile; fileRef = 1EAF20A6162DC0F600957B1D /* feedbackActiviy.png */; }; 1EAF20AA162DC0F600957B1D /* feedbackActiviy.png in Resources */ = {isa = PBXBuildFile; fileRef = 1EAF20A6162DC0F600957B1D /* feedbackActiviy.png */; };
1EAF20AB162DC0F600957B1D /* feedbackActiviy@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1EAF20A7162DC0F600957B1D /* feedbackActiviy@2x.png */; }; 1EAF20AB162DC0F600957B1D /* feedbackActiviy@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1EAF20A7162DC0F600957B1D /* feedbackActiviy@2x.png */; };
1EB52FD5167B766100C801D5 /* HockeySDK.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1E59555F15B6F80E00A03429 /* HockeySDK.strings */; }; 1EB52FD5167B766100C801D5 /* HockeySDK.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1E59555F15B6F80E00A03429 /* HockeySDK.strings */; };
1ED570C718BF878C00AB3350 /* BITCrashAttachment.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ED570C518BF878C00AB3350 /* BITCrashAttachment.h */; settings = {ATTRIBUTES = (Public, ); }; };
1ED570C818BF878C00AB3350 /* BITCrashAttachment.m in Sources */ = {isa = PBXBuildFile; fileRef = 1ED570C618BF878C00AB3350 /* BITCrashAttachment.m */; };
1EF95CA6162CB037000AE3AD /* BITFeedbackActivity.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF95CA4162CB036000AE3AD /* BITFeedbackActivity.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1EF95CA6162CB037000AE3AD /* BITFeedbackActivity.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF95CA4162CB036000AE3AD /* BITFeedbackActivity.h */; settings = {ATTRIBUTES = (Public, ); }; };
1EF95CA7162CB037000AE3AD /* BITFeedbackActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EF95CA5162CB036000AE3AD /* BITFeedbackActivity.m */; }; 1EF95CA7162CB037000AE3AD /* BITFeedbackActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EF95CA5162CB036000AE3AD /* BITFeedbackActivity.m */; };
1EF95CAA162CB314000AE3AD /* BITFeedbackComposeViewControllerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF95CA9162CB313000AE3AD /* BITFeedbackComposeViewControllerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1EF95CAA162CB314000AE3AD /* BITFeedbackComposeViewControllerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF95CA9162CB313000AE3AD /* BITFeedbackComposeViewControllerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -248,11 +250,11 @@
1E5955FA15B7877A00A03429 /* BITHockeyManagerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITHockeyManagerDelegate.h; sourceTree = "<group>"; }; 1E5955FA15B7877A00A03429 /* BITHockeyManagerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITHockeyManagerDelegate.h; sourceTree = "<group>"; };
1E5A459016F0DFC200B55C04 /* HockeySDKTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HockeySDKTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; 1E5A459016F0DFC200B55C04 /* HockeySDKTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HockeySDKTests.octest; sourceTree = BUILT_PRODUCTS_DIR; };
1E5A459116F0DFC200B55C04 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 1E5A459116F0DFC200B55C04 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
1E5A459316F0DFC200B55C04 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
1E5A459816F0DFC200B55C04 /* HockeySDKTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HockeySDKTests-Info.plist"; sourceTree = "<group>"; }; 1E5A459816F0DFC200B55C04 /* HockeySDKTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HockeySDKTests-Info.plist"; sourceTree = "<group>"; };
1E5A459A16F0DFC200B55C04 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 1E5A459A16F0DFC200B55C04 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
1E5A459D16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BITStoreUpdateManagerTests.m; sourceTree = "<group>"; }; 1E5A459D16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BITStoreUpdateManagerTests.m; sourceTree = "<group>"; };
1E5A459F16F0DFC200B55C04 /* HockeySDKTests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HockeySDKTests-Prefix.pch"; sourceTree = "<group>"; }; 1E5A459F16F0DFC200B55C04 /* HockeySDKTests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HockeySDKTests-Prefix.pch"; sourceTree = "<group>"; };
1E61CCAE18E0585A00A5E38E /* BITFeedbackManagerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITFeedbackManagerTests.m; sourceTree = "<group>"; };
1E66CA9115D4100500F35BED /* buildnumber.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = buildnumber.xcconfig; sourceTree = "<group>"; }; 1E66CA9115D4100500F35BED /* buildnumber.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = buildnumber.xcconfig; sourceTree = "<group>"; };
1E6DDCEE169E290C0076C65D /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/HockeySDK.strings; sourceTree = "<group>"; }; 1E6DDCEE169E290C0076C65D /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/HockeySDK.strings; sourceTree = "<group>"; };
1E6F0450167B5E5600ED1C86 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/HockeySDK.strings"; sourceTree = "<group>"; }; 1E6F0450167B5E5600ED1C86 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/HockeySDK.strings"; sourceTree = "<group>"; };
@ -287,6 +289,8 @@
1EAF20A6162DC0F600957B1D /* feedbackActiviy.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = feedbackActiviy.png; sourceTree = "<group>"; }; 1EAF20A6162DC0F600957B1D /* feedbackActiviy.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = feedbackActiviy.png; sourceTree = "<group>"; };
1EAF20A7162DC0F600957B1D /* feedbackActiviy@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "feedbackActiviy@2x.png"; sourceTree = "<group>"; }; 1EAF20A7162DC0F600957B1D /* feedbackActiviy@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "feedbackActiviy@2x.png"; sourceTree = "<group>"; };
1EB52FC3167B73D400C801D5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/HockeySDK.strings; sourceTree = "<group>"; }; 1EB52FC3167B73D400C801D5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/HockeySDK.strings; sourceTree = "<group>"; };
1ED570C518BF878C00AB3350 /* BITCrashAttachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITCrashAttachment.h; sourceTree = "<group>"; };
1ED570C618BF878C00AB3350 /* BITCrashAttachment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITCrashAttachment.m; sourceTree = "<group>"; };
1EDA60CF15C2C1450032D10B /* HockeySDK-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HockeySDK-Info.plist"; sourceTree = "<group>"; }; 1EDA60CF15C2C1450032D10B /* HockeySDK-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HockeySDK-Info.plist"; sourceTree = "<group>"; };
1EF95CA4162CB036000AE3AD /* BITFeedbackActivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackActivity.h; sourceTree = "<group>"; }; 1EF95CA4162CB036000AE3AD /* BITFeedbackActivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackActivity.h; sourceTree = "<group>"; };
1EF95CA5162CB036000AE3AD /* BITFeedbackActivity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITFeedbackActivity.m; sourceTree = "<group>"; }; 1EF95CA5162CB036000AE3AD /* BITFeedbackActivity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITFeedbackActivity.m; sourceTree = "<group>"; };
@ -336,7 +340,6 @@
files = ( files = (
1EA1170016F4D32C001C015C /* libHockeySDK.a in Frameworks */, 1EA1170016F4D32C001C015C /* libHockeySDK.a in Frameworks */,
1E5A459216F0DFC200B55C04 /* SenTestingKit.framework in Frameworks */, 1E5A459216F0DFC200B55C04 /* SenTestingKit.framework in Frameworks */,
1E5A459416F0DFC200B55C04 /* UIKit.framework in Frameworks */,
1EA1170116F4D354001C015C /* CrashReporter.framework in Frameworks */, 1EA1170116F4D354001C015C /* CrashReporter.framework in Frameworks */,
1E5A459516F0DFC200B55C04 /* Foundation.framework in Frameworks */, 1E5A459516F0DFC200B55C04 /* Foundation.framework in Frameworks */,
1E7A45FC16F54FB5005B08F1 /* OCHamcrestIOS.framework in Frameworks */, 1E7A45FC16F54FB5005B08F1 /* OCHamcrestIOS.framework in Frameworks */,
@ -381,6 +384,7 @@
1E5A459D16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m */, 1E5A459D16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m */,
E48A3DEE17B3EFF100924C3D /* BITAuthenticatorTests.m */, E48A3DEE17B3EFF100924C3D /* BITAuthenticatorTests.m */,
1EFF03E417F2485500A5F13C /* BITCrashManagerTests.m */, 1EFF03E417F2485500A5F13C /* BITCrashManagerTests.m */,
1E61CCAE18E0585A00A5E38E /* BITFeedbackManagerTests.m */,
E40E0B0817DA19DC005E38C1 /* BITHockeyAppClientTests.m */, E40E0B0817DA19DC005E38C1 /* BITHockeyAppClientTests.m */,
E4507E4217F0658F00171A0D /* BITKeychainUtilsTests.m */, E4507E4217F0658F00171A0D /* BITKeychainUtilsTests.m */,
1E70A23517F31B82001BB32D /* BITHockeyHelperTests.m */, 1E70A23517F31B82001BB32D /* BITHockeyHelperTests.m */,
@ -486,6 +490,8 @@
1E90FD7218EDB86400CF0417 /* BITCrashDetails.m */, 1E90FD7218EDB86400CF0417 /* BITCrashDetails.m */,
1EFF03D717F20F8300A5F13C /* BITCrashManagerPrivate.h */, 1EFF03D717F20F8300A5F13C /* BITCrashManagerPrivate.h */,
1E754E581621FBB70070AB92 /* BITCrashManagerDelegate.h */, 1E754E581621FBB70070AB92 /* BITCrashManagerDelegate.h */,
1ED570C518BF878C00AB3350 /* BITCrashAttachment.h */,
1ED570C618BF878C00AB3350 /* BITCrashAttachment.m */,
1E754E5A1621FBB70070AB92 /* BITCrashReportTextFormatter.h */, 1E754E5A1621FBB70070AB92 /* BITCrashReportTextFormatter.h */,
1E754E5B1621FBB70070AB92 /* BITCrashReportTextFormatter.m */, 1E754E5B1621FBB70070AB92 /* BITCrashReportTextFormatter.m */,
); );
@ -566,7 +572,6 @@
E41EB48B148D7C4E0015DEDC /* CrashReporter.framework */, E41EB48B148D7C4E0015DEDC /* CrashReporter.framework */,
E400561D148D79B500EB22B9 /* Foundation.framework */, E400561D148D79B500EB22B9 /* Foundation.framework */,
1E5A459116F0DFC200B55C04 /* SenTestingKit.framework */, 1E5A459116F0DFC200B55C04 /* SenTestingKit.framework */,
1E5A459316F0DFC200B55C04 /* UIKit.framework */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
@ -655,6 +660,7 @@
1E49A4AF161222B900463151 /* BITHockeyBaseManager.h in Headers */, 1E49A4AF161222B900463151 /* BITHockeyBaseManager.h in Headers */,
1E49A4B8161222B900463151 /* BITHockeyBaseViewController.h in Headers */, 1E49A4B8161222B900463151 /* BITHockeyBaseViewController.h in Headers */,
1E94F9E116E91330006570AD /* BITStoreUpdateManager.h in Headers */, 1E94F9E116E91330006570AD /* BITStoreUpdateManager.h in Headers */,
1ED570C718BF878C00AB3350 /* BITCrashAttachment.h in Headers */,
1E0829001708F69A0073050E /* BITStoreUpdateManagerDelegate.h in Headers */, 1E0829001708F69A0073050E /* BITStoreUpdateManagerDelegate.h in Headers */,
1E49A4421612223B00463151 /* BITFeedbackListViewCell.h in Headers */, 1E49A4421612223B00463151 /* BITFeedbackListViewCell.h in Headers */,
1E49A4541612223B00463151 /* BITFeedbackManagerPrivate.h in Headers */, 1E49A4541612223B00463151 /* BITFeedbackManagerPrivate.h in Headers */,
@ -744,7 +750,7 @@
E4005611148D79B500EB22B9 /* Project object */ = { E4005611148D79B500EB22B9 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 0500; LastUpgradeCheck = 0510;
}; };
buildConfigurationList = E4005614148D79B500EB22B9 /* Build configuration list for PBXProject "HockeySDK" */; buildConfigurationList = E4005614148D79B500EB22B9 /* Build configuration list for PBXProject "HockeySDK" */;
compatibilityVersion = "Xcode 3.2"; compatibilityVersion = "Xcode 3.2";
@ -840,7 +846,7 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "# Sets the target folders and the final framework product.\nFMK_NAME=HockeySDK\nFMK_VERSION=A\nFMK_RESOURCE_BUNDLE=HockeySDKResources\n\n# Documentation\nHOCKEYSDK_DOCSET_VERSION_NAME=\"de.bitstadium.${HOCKEYSDK_DOCSET_NAME}-${VERSION_STRING}\"\n\n# Install dir will be the final output to the framework.\n# The following line create it in the root folder of the current project.\nPRODUCTS_DIR=${SRCROOT}/../Products\nPLCR_DIR=${SRCROOT}/../Vendor/CrashReporter.framework\nZIP_FOLDER=HockeySDK-iOS\nTEMP_DIR=${PRODUCTS_DIR}/${ZIP_FOLDER}\nINSTALL_DIR=${TEMP_DIR}/${FMK_NAME}.framework\n\n# Working dir will be deleted after the framework creation.\nWRK_DIR=build\nDEVICE_DIR=${WRK_DIR}/Release-iphoneos\nSIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator\nHEADERS_DIR=${WRK_DIR}/Release-iphoneos/usr/local/include\n\n# Building both architectures.\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphoneos\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphonesimulator\n\n# Cleaning the oldest.\nif [ -d \"${TEMP_DIR}\" ]\nthen\nrm -rf \"${TEMP_DIR}\"\nfi\n\n# Creates and renews the final product folder.\nmkdir -p \"${INSTALL_DIR}\"\nmkdir -p \"${INSTALL_DIR}/Versions\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers\"\n\n# Creates the internal links.\n# It MUST uses relative path, otherwise will not work when the folder is copied/moved.\nln -s \"${FMK_VERSION}\" \"${INSTALL_DIR}/Versions/Current\"\nln -s \"Versions/Current/Headers\" \"${INSTALL_DIR}/Headers\"\nln -s \"Versions/Current/Resources\" \"${INSTALL_DIR}/Resources\"\nln -s \"Versions/Current/${FMK_NAME}\" \"${INSTALL_DIR}/${FMK_NAME}\"\n\n# Copies the headers and resources files to the final product folder.\ncp -R \"${SRCROOT}/build/Release-iphoneos/include/HockeySDK/\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${PLCR_DIR}/Versions/A/Headers/\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${DEVICE_DIR}/${FMK_RESOURCE_BUNDLE}.bundle\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\ncp -f \"${SRCROOT}/${FMK_NAME}.xcconfig\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\n\n# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.\nlipo -create \"${DEVICE_DIR}/lib${FMK_NAME}.a\" \"${SIMULATOR_DIR}/lib${FMK_NAME}.a\" -output \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\"\n\n# Combine the CrashReporter static library into a new Hockey static library file if they are not already present and copy the public headers too\nif [ -z $(otool -L \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" | grep 'libCrashReporter') ]\nthen\nlibtool -static -o \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${SRCROOT}/../Vendor/CrashReporter.framework/Versions/A/CrashReporter\"\nfi\n\nrm -r \"${WRK_DIR}\"\n\n# build embeddedframework folder and move framework into it\nmkdir \"${INSTALL_DIR}/../${FMK_NAME}.embeddedframework\"\nmv \"${INSTALL_DIR}\" \"${INSTALL_DIR}/../${FMK_NAME}.embeddedframework/${FMK_NAME}.framework\"\n\n# link Resources\nNEW_INSTALL_DIR=${TEMP_DIR}/${FMK_NAME}.embeddedframework\nmkdir \"${NEW_INSTALL_DIR}/Resources\"\nln -s \"../${FMK_NAME}.framework/Resources/${FMK_RESOURCE_BUNDLE}.bundle\" \"${NEW_INSTALL_DIR}/Resources/${FMK_RESOURCE_BUNDLE}.bundle\"\nln -s \"../${FMK_NAME}.framework/Resources/${FMK_NAME}.xcconfig\" \"${NEW_INSTALL_DIR}/Resources/${FMK_NAME}.xcconfig\"\n\n# copy license, changelog, documentation, integration json\ncp -f \"${SRCROOT}/../Docs/Changelog-template.md\" \"${TEMP_DIR}/CHANGELOG\"\ncp -f \"${SRCROOT}/../Docs/Guide-Installation-Setup-template.md\" \"${TEMP_DIR}/README.md\"\ncp -f \"${SRCROOT}/../LICENSE\" \"${TEMP_DIR}\"\nmkdir \"${TEMP_DIR}/${HOCKEYSDK_DOCSET_VERSION_NAME}.docset\"\ncp -R \"${SRCROOT}/../documentation/docset/Contents\" \"${TEMP_DIR}/${HOCKEYSDK_DOCSET_VERSION_NAME}.docset\"\n\n# build zip\ncd \"${PRODUCTS_DIR}\"\nrm -f \"${FMK_NAME}-iOS-${VERSION_STRING}.zip\"\nzip -yr \"${FMK_NAME}-iOS-${VERSION_STRING}.zip\" \"${ZIP_FOLDER}\" -x \\*/.*\n\n#copy to output dir on cisimple\nif [ $CISIMPLE ]; then\n if [ ! -d \"${CONFIGURATION_BUILD_DIR}\" ]; then\n mkdir \"${CONFIGURATION_BUILD_DIR}\"\n fi\n cd \"${PRODUCTS_DIR}\"\n cp \"${FMK_NAME}-iOS-${VERSION_STRING}.zip\" \"${CONFIGURATION_BUILD_DIR}/${FMK_NAME}-iOS-${VERSION_STRING}.zip\"\nfi"; shellScript = "# Sets the target folders and the final framework product.\nFMK_NAME=HockeySDK\nFMK_VERSION=A\nFMK_RESOURCE_BUNDLE=HockeySDKResources\n\n# Documentation\nHOCKEYSDK_DOCSET_VERSION_NAME=\"de.bitstadium.${HOCKEYSDK_DOCSET_NAME}-${VERSION_STRING}\"\n\n# Install dir will be the final output to the framework.\n# The following line create it in the root folder of the current project.\nPRODUCTS_DIR=${SRCROOT}/../Products\nZIP_FOLDER=HockeySDK-iOS\nTEMP_DIR=${PRODUCTS_DIR}/${ZIP_FOLDER}\nINSTALL_DIR=${TEMP_DIR}/${FMK_NAME}.framework\n\n# Working dir will be deleted after the framework creation.\nWRK_DIR=build\nDEVICE_DIR=${WRK_DIR}/Release-iphoneos\nSIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator\nHEADERS_DIR=${WRK_DIR}/Release-iphoneos/usr/local/include\n\n# Building both architectures.\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphoneos\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphonesimulator\n\n# Cleaning the oldest.\nif [ -d \"${TEMP_DIR}\" ]\nthen\nrm -rf \"${TEMP_DIR}\"\nfi\n\n# Creates and renews the final product folder.\nmkdir -p \"${INSTALL_DIR}\"\nmkdir -p \"${INSTALL_DIR}/Versions\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers\"\n\n# Creates the internal links.\n# It MUST uses relative path, otherwise will not work when the folder is copied/moved.\nln -s \"${FMK_VERSION}\" \"${INSTALL_DIR}/Versions/Current\"\nln -s \"Versions/Current/Headers\" \"${INSTALL_DIR}/Headers\"\nln -s \"Versions/Current/Resources\" \"${INSTALL_DIR}/Resources\"\nln -s \"Versions/Current/${FMK_NAME}\" \"${INSTALL_DIR}/${FMK_NAME}\"\n\n# Copies the headers and resources files to the final product folder.\ncp -R \"${SRCROOT}/build/Release-iphoneos/include/HockeySDK/\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${DEVICE_DIR}/${FMK_RESOURCE_BUNDLE}.bundle\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\ncp -f \"${SRCROOT}/${FMK_NAME}.xcconfig\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\n\n# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.\nlipo -create \"${DEVICE_DIR}/lib${FMK_NAME}.a\" \"${SIMULATOR_DIR}/lib${FMK_NAME}.a\" -output \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\"\n\n# Combine the CrashReporter static library into a new Hockey static library file if they are not already present and copy the public headers too\nif [ -z $(otool -L \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" | grep 'libCrashReporter') ]\nthen\nlibtool -static -o \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${SRCROOT}/../Vendor/CrashReporter.framework/Versions/A/CrashReporter\"\nfi\n\nrm -r \"${WRK_DIR}\"\n\n# build embeddedframework folder and move framework into it\nmkdir \"${INSTALL_DIR}/../${FMK_NAME}.embeddedframework\"\nmv \"${INSTALL_DIR}\" \"${INSTALL_DIR}/../${FMK_NAME}.embeddedframework/${FMK_NAME}.framework\"\n\n# link Resources\nNEW_INSTALL_DIR=${TEMP_DIR}/${FMK_NAME}.embeddedframework\nmkdir \"${NEW_INSTALL_DIR}/Resources\"\nln -s \"../${FMK_NAME}.framework/Resources/${FMK_RESOURCE_BUNDLE}.bundle\" \"${NEW_INSTALL_DIR}/Resources/${FMK_RESOURCE_BUNDLE}.bundle\"\nln -s \"../${FMK_NAME}.framework/Resources/${FMK_NAME}.xcconfig\" \"${NEW_INSTALL_DIR}/Resources/${FMK_NAME}.xcconfig\"\n\n# copy license, changelog, documentation, integration json\ncp -f \"${SRCROOT}/../Docs/Changelog-template.md\" \"${TEMP_DIR}/CHANGELOG\"\ncp -f \"${SRCROOT}/../Docs/Guide-Installation-Setup-template.md\" \"${TEMP_DIR}/README.md\"\ncp -f \"${SRCROOT}/../LICENSE\" \"${TEMP_DIR}\"\nmkdir \"${TEMP_DIR}/${HOCKEYSDK_DOCSET_VERSION_NAME}.docset\"\ncp -R \"${SRCROOT}/../documentation/docset/Contents\" \"${TEMP_DIR}/${HOCKEYSDK_DOCSET_VERSION_NAME}.docset\"\n\n# build zip\ncd \"${PRODUCTS_DIR}\"\nrm -f \"${FMK_NAME}-iOS-${VERSION_STRING}.zip\"\nzip -yr \"${FMK_NAME}-iOS-${VERSION_STRING}.zip\" \"${ZIP_FOLDER}\" -x \\*/.*\n";
}; };
1E8E66B215BC3D8200632A2E /* ShellScript */ = { 1E8E66B215BC3D8200632A2E /* ShellScript */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
@ -883,6 +889,7 @@
1E49A4511612223B00463151 /* BITFeedbackManager.m in Sources */, 1E49A4511612223B00463151 /* BITFeedbackManager.m in Sources */,
E4933E8117B66CDA00B11ACC /* BITHTTPOperation.m in Sources */, E4933E8117B66CDA00B11ACC /* BITHTTPOperation.m in Sources */,
1E49A45A1612223B00463151 /* BITFeedbackMessage.m in Sources */, 1E49A45A1612223B00463151 /* BITFeedbackMessage.m in Sources */,
1ED570C818BF878C00AB3350 /* BITCrashAttachment.m in Sources */,
1E49A4601612223B00463151 /* BITFeedbackUserDataViewController.m in Sources */, 1E49A4601612223B00463151 /* BITFeedbackUserDataViewController.m in Sources */,
1E49A4701612226D00463151 /* BITAppVersionMetaInfo.m in Sources */, 1E49A4701612226D00463151 /* BITAppVersionMetaInfo.m in Sources */,
1E49A4761612226D00463151 /* BITUpdateManager.m in Sources */, 1E49A4761612226D00463151 /* BITUpdateManager.m in Sources */,
@ -923,6 +930,7 @@
1E70A23617F31B82001BB32D /* BITHockeyHelperTests.m in Sources */, 1E70A23617F31B82001BB32D /* BITHockeyHelperTests.m in Sources */,
E48A3DEF17B3EFF100924C3D /* BITAuthenticatorTests.m in Sources */, E48A3DEF17B3EFF100924C3D /* BITAuthenticatorTests.m in Sources */,
1EA1170716F53B91001C015C /* BITTestHelper.m in Sources */, 1EA1170716F53B91001C015C /* BITTestHelper.m in Sources */,
1E61CCAF18E0585A00A5E38E /* BITFeedbackManagerTests.m in Sources */,
E4507E4317F0658F00171A0D /* BITKeychainUtilsTests.m in Sources */, E4507E4317F0658F00171A0D /* BITKeychainUtilsTests.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0500" LastUpgradeVersion = "0510"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0500" LastUpgradeVersion = "0510"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0500" LastUpgradeVersion = "0510"
version = "1.7"> version = "1.7">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0500" LastUpgradeVersion = "0510"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -23,6 +23,7 @@
#import "BITTestHelper.h" #import "BITTestHelper.h"
#define kBITCrashMetaAttachment @"BITCrashMetaAttachment"
@interface BITCrashManagerTests : SenTestCase @interface BITCrashManagerTests : SenTestCase
@ -71,7 +72,6 @@
[self startManager]; [self startManager];
} }
#pragma mark - Setup Tests #pragma mark - Setup Tests
- (void)testThatItInstantiates { - (void)testThatItInstantiates {
@ -81,6 +81,32 @@
#pragma mark - Persistence tests #pragma mark - Persistence tests
- (void)testPersistUserProvidedCrashDescription {
NSString *tempCrashName = @"tempCrash";
[_sut setLastCrashFilename:tempCrashName];
[_sut persistUserProvidedCrashDescription:@"Test string"];
NSError *error;
NSString *description = [NSString stringWithContentsOfFile:[NSString stringWithFormat:@"%@.desc", [[_sut getCrashesDir] stringByAppendingPathComponent: tempCrashName]] encoding:NSUTF8StringEncoding error:&error];
assertThat(description, equalTo(@"Test string"));
}
- (void)testPersistAttachment {
NSString *filename = @"TestAttachment";
NSData *data = [[NSData alloc] initWithBase64Encoding:@"TestData"];
NSString* type = @"text/plain";
BITCrashAttachment *originalAttachment = [[BITCrashAttachment alloc] initWithFilename:filename attachmentData:data contentType:type];
NSString *attachmentFilename = [_sut.getCrashesDir stringByAppendingPathComponent:@"testAttachment"];
[_sut persistAttachment:originalAttachment withFilename:attachmentFilename];
BITCrashAttachment *decodedAttachment = [_sut attachmentForCrashReport:attachmentFilename];
assertThat(decodedAttachment.filename, equalTo(filename));
assertThat(decodedAttachment.attachmentData, equalTo(data));
assertThat(decodedAttachment.contentType, equalTo(type));
}
#pragma mark - Helper #pragma mark - Helper
@ -123,6 +149,44 @@
[verifyCount(delegateMock, times(1)) userEmailForHockeyManager:hm componentManager:_sut]; [verifyCount(delegateMock, times(1)) userEmailForHockeyManager:hm componentManager:_sut];
} }
#pragma mark - Handle User Input
- (void)testHandleUserInputDontSend {
id <BITCrashManagerDelegate> delegateMock = mockProtocol(@protocol(BITCrashManagerDelegate));
_sut.delegate = delegateMock;
assertThatBool([_sut handleUserInput:BITCrashManagerUserInputDontSend withUserProvidedCrashDescription:nil], equalToBool(YES));
[verify(delegateMock) crashManagerWillCancelSendingCrashReport:_sut];
}
- (void)testHandleUserInputSend {
assertThatBool([_sut handleUserInput:BITCrashManagerUserInputSend withUserProvidedCrashDescription:nil], equalToBool(YES));
}
- (void)testHandleUserInputAlwaysSend {
id <BITCrashManagerDelegate> delegateMock = mockProtocol(@protocol(BITCrashManagerDelegate));
_sut.delegate = delegateMock;
NSUserDefaults *mockUserDefaults = mock([NSUserDefaults class]);
//Test if CrashManagerStatus is unset
[given([mockUserDefaults integerForKey:@"BITCrashManagerStatus"]) willReturn:nil];
//Test if method runs through
assertThatBool([_sut handleUserInput:BITCrashManagerUserInputAlwaysSend withUserProvidedCrashDescription:nil], equalToBool(YES));
//Test if correct CrashManagerStatus is now set
[given([mockUserDefaults integerForKey:@"BITCrashManagerStauts"]) willReturnInt:BITCrashManagerStatusAutoSend];
//Verify that delegate method has been called
[verify(delegateMock) crashManagerWillSendCrashReportsAlways:_sut];
}
- (void)testHandleUserInputWithInvalidInput {
assertThatBool([_sut handleUserInput:3 withUserProvidedCrashDescription:nil], equalToBool(NO));
}
#pragma mark - Debugger #pragma mark - Debugger
@ -201,6 +265,7 @@
[_sut handleCrashReport]; [_sut handleCrashReport];
[verifyCount(delegateMock, times(1)) applicationLogForCrashManager:_sut]; [verifyCount(delegateMock, times(1)) applicationLogForCrashManager:_sut];
[verifyCount(delegateMock, times(1)) attachmentForCrashManager:_sut];
// we should have now 1 pending crash report // we should have now 1 pending crash report
assertThatBool([_sut hasPendingCrashReport], equalToBool(YES)); assertThatBool([_sut hasPendingCrashReport], equalToBool(YES));

View File

@ -0,0 +1,216 @@
//
// BITFeedbackManagerTests.m
// HockeySDK
//
// Created by Andreas Linde on 24.03.14.
//
//
#import <SenTestingKit/SenTestingKit.h>
#define HC_SHORTHAND
#import <OCHamcrestIOS/OCHamcrestIOS.h>
#define MOCKITO_SHORTHAND
#import <OCMockitoIOS/OCMockitoIOS.h>
#import "HockeySDK.h"
#import "HockeySDKPrivate.h"
#import "BITFeedbackManager.h"
#import "BITFeedbackManagerPrivate.h"
#import "BITHockeyBaseManager.h"
#import "BITHockeyBaseManagerPrivate.h"
#import "BITTestHelper.h"
@interface BITFeedbackManagerTests : SenTestCase
@end
@implementation BITFeedbackManagerTests {
BITFeedbackManager *_sut;
}
- (void)setUp {
[super setUp];
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
hm.delegate = nil;
_sut = [[BITFeedbackManager alloc] initWithAppIdentifier:nil isAppStoreEnvironment:NO];
_sut.delegate = nil;
}
- (void)tearDown {
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wimplicit"
__gcov_flush();
# pragma clang diagnostic pop
[_sut removeKeyFromKeychain:kBITHockeyMetaUserID];
[_sut removeKeyFromKeychain:kBITHockeyMetaUserName];
[_sut removeKeyFromKeychain:kBITHockeyMetaUserEmail];
_sut = nil;
[super tearDown];
}
#pragma mark - Private
- (void)startManager {
[_sut startManager];
}
#pragma mark - Setup Tests
#pragma mark - User Metadata
- (void)testUpdateUserIDWithNoDataPresent {
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
id delegateMock = mockProtocol(@protocol(BITHockeyManagerDelegate));
hm.delegate = delegateMock;
_sut.delegate = delegateMock;
BOOL dataAvailable = [_sut updateUserIDUsingKeychainAndDelegate];
assertThatBool(dataAvailable, equalToBool(NO));
assertThat(_sut.userID, nilValue());
[verifyCount(delegateMock, times(1)) userIDForHockeyManager:hm componentManager:_sut];
}
- (void)testUpdateUserIDWithDelegateReturningData {
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
NSObject <BITHockeyManagerDelegate> *classMock = mockObjectAndProtocol([NSObject class], @protocol(BITHockeyManagerDelegate));
[given([classMock userIDForHockeyManager:hm componentManager:_sut]) willReturn:@"test"];
hm.delegate = classMock;
_sut.delegate = classMock;
BOOL dataAvailable = [_sut updateUserIDUsingKeychainAndDelegate];
assertThatBool(dataAvailable, equalToBool(YES));
assertThat(_sut.userID, equalTo(@"test"));
[verifyCount(classMock, times(1)) userIDForHockeyManager:hm componentManager:_sut];
}
- (void)testUpdateUserIDWithValueInKeychain {
[_sut addStringValueToKeychain:@"test" forKey:kBITHockeyMetaUserID];
BOOL dataAvailable = [_sut updateUserIDUsingKeychainAndDelegate];
assertThatBool(dataAvailable, equalToBool(YES));
assertThat(_sut.userID, equalTo(@"test"));
}
- (void)testUpdateUserIDWithGlobalSetter {
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
[hm setUserID:@"test"];
BOOL dataAvailable = [_sut updateUserIDUsingKeychainAndDelegate];
assertThatBool(dataAvailable, equalToBool(YES));
assertThat(_sut.userID, equalTo(@"test"));
}
- (void)testUpdateUserNameWithNoDataPresent {
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
id delegateMock = mockProtocol(@protocol(BITHockeyManagerDelegate));
hm.delegate = delegateMock;
_sut.delegate = delegateMock;
BOOL dataAvailable = [_sut updateUserNameUsingKeychainAndDelegate];
assertThatBool(dataAvailable, equalToBool(NO));
assertThat(_sut.userName, nilValue());
[verifyCount(delegateMock, times(1)) userNameForHockeyManager:hm componentManager:_sut];
}
- (void)testUpdateUserNameWithDelegateReturningData {
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
NSObject <BITHockeyManagerDelegate> *classMock = mockObjectAndProtocol([NSObject class], @protocol(BITHockeyManagerDelegate));
[given([classMock userNameForHockeyManager:hm componentManager:_sut]) willReturn:@"test"];
hm.delegate = classMock;
_sut.delegate = classMock;
BOOL dataAvailable = [_sut updateUserNameUsingKeychainAndDelegate];
assertThatBool(dataAvailable, equalToBool(YES));
assertThat(_sut.userName, equalTo(@"test"));
[verifyCount(classMock, times(1)) userNameForHockeyManager:hm componentManager:_sut];
}
- (void)testUpdateUserNameWithValueInKeychain {
[_sut addStringValueToKeychain:@"test" forKey:kBITHockeyMetaUserName];
BOOL dataAvailable = [_sut updateUserNameUsingKeychainAndDelegate];
assertThatBool(dataAvailable, equalToBool(YES));
assertThat(_sut.userName, equalTo(@"test"));
}
- (void)testUpdateUserNameWithGlobalSetter {
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
[hm setUserName:@"test"];
BOOL dataAvailable = [_sut updateUserNameUsingKeychainAndDelegate];
assertThatBool(dataAvailable, equalToBool(YES));
assertThat(_sut.userName, equalTo(@"test"));
}
- (void)testUpdateUserEmailWithNoDataPresent {
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
id delegateMock = mockProtocol(@protocol(BITHockeyManagerDelegate));
hm.delegate = delegateMock;
_sut.delegate = delegateMock;
BOOL dataAvailable = [_sut updateUserEmailUsingKeychainAndDelegate];
assertThatBool(dataAvailable, equalToBool(NO));
assertThat(_sut.userEmail, nilValue());
[verifyCount(delegateMock, times(1)) userEmailForHockeyManager:hm componentManager:_sut];
}
- (void)testUpdateUserEmailWithDelegateReturningData {
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
NSObject <BITHockeyManagerDelegate> *classMock = mockObjectAndProtocol([NSObject class], @protocol(BITHockeyManagerDelegate));
[given([classMock userEmailForHockeyManager:hm componentManager:_sut]) willReturn:@"test"];
hm.delegate = classMock;
_sut.delegate = classMock;
BOOL dataAvailable = [_sut updateUserEmailUsingKeychainAndDelegate];
assertThatBool(dataAvailable, equalToBool(YES));
assertThat(_sut.userEmail, equalTo(@"test"));
[verifyCount(classMock, times(1)) userEmailForHockeyManager:hm componentManager:_sut];
}
- (void)testUpdateUserEmailWithValueInKeychain {
[_sut addStringValueToKeychain:@"test" forKey:kBITHockeyMetaUserEmail];
BOOL dataAvailable = [_sut updateUserEmailUsingKeychainAndDelegate];
assertThatBool(dataAvailable, equalToBool(YES));
assertThat(_sut.userEmail, equalTo(@"test"));
}
- (void)testUpdateUserEmailWithGlobalSetter {
BITHockeyManager *hm = [BITHockeyManager sharedHockeyManager];
[hm setUserEmail:@"test"];
BOOL dataAvailable = [_sut updateUserEmailUsingKeychainAndDelegate];
assertThatBool(dataAvailable, equalToBool(YES));
assertThat(_sut.userEmail, equalTo(@"test"));
}
@end

View File

@ -32,7 +32,12 @@
} }
- (void)tearDown { - (void)tearDown {
// Put teardown code here; it will be run once, after the last test case. // Tear-down code here.
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wimplicit"
__gcov_flush();
# pragma clang diagnostic pop
[super tearDown]; [super tearDown];
} }

View File

@ -300,7 +300,7 @@
STAssertFalse(result, @"The newer version is being ignored"); STAssertFalse(result, @"The newer version is being ignored");
} }
- (void)testReportedVersionIsNewerThanTHeIgnoredVersion { - (void)testReportedVersionIsNewerThanTheIgnoredVersion {
NSUserDefaults *mockUserDefaults = mock([NSUserDefaults class]); NSUserDefaults *mockUserDefaults = mock([NSUserDefaults class]);
[given([mockUserDefaults objectForKey:@"BITStoreUpdateLastStoreVersion"]) willReturn:@"4.1.1"]; [given([mockUserDefaults objectForKey:@"BITStoreUpdateLastStoreVersion"]) willReturn:@"4.1.1"];
[given([mockUserDefaults objectForKey:@"BITStoreUpdateLastUUID"]) willReturn:@""]; [given([mockUserDefaults objectForKey:@"BITStoreUpdateLastUUID"]) willReturn:@""];

View File

@ -1,8 +1,8 @@
#include "HockeySDK.xcconfig" #include "HockeySDK.xcconfig"
BUILD_NUMBER = 27 BUILD_NUMBER = 28
VERSION_STRING = 3.5.4 VERSION_STRING = 3.5.5
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) BITHOCKEY_VERSION="@\""$(VERSION_STRING)"\"" BITHOCKEY_BUILD="@\""$(BUILD_NUMBER)"\"" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) BITHOCKEY_VERSION="@\""$(VERSION_STRING)"\"" BITHOCKEY_BUILD="@\""$(BUILD_NUMBER)"\"" BITHOCKEY_C_VERSION="\""$(VERSION_STRING)"\"" BITHOCKEY_C_BUILD="\""$(BUILD_NUMBER)"\""
BIT_ARM_ARCHS = armv7 armv7s arm64 BIT_ARM_ARCHS = armv7 armv7s arm64
BIT_SIM_ARCHS = x86_64 i386 BIT_SIM_ARCHS = x86_64 i386
ARCHS = $(BIT_ARM_ARCHS) ARCHS = $(BIT_ARM_ARCHS)

View File

@ -32,7 +32,7 @@
@interface PLCrashReportProcessInfo : NSObject { @interface PLCrashReportProcessInfo : NSObject {
@private @private
/** Process name */ /** Process name, or nil if unavailable. */
NSString *_processName; NSString *_processName;
/** Process ID */ /** Process ID */
@ -45,7 +45,7 @@
* will be nil. */ * will be nil. */
NSDate *_processStartTime; NSDate *_processStartTime;
/** Parent process name */ /** Parent process name, or nil if unavailable. */
NSString *_parentProcessName; NSString *_parentProcessName;
/** Parent process ID */ /** Parent process ID */

View File

@ -3,7 +3,7 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>BuildMachineOSBuild</key> <key>BuildMachineOSBuild</key>
<string>13B42</string> <string>13C64</string>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>English</string> <string>English</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
@ -23,16 +23,16 @@
<key>DTCompiler</key> <key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string> <string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key> <key>DTPlatformBuild</key>
<string>5A3005</string> <string>5B1008</string>
<key>DTPlatformVersion</key> <key>DTPlatformVersion</key>
<string>GM</string> <string>GM</string>
<key>DTSDKBuild</key> <key>DTSDKBuild</key>
<string>13A595</string> <string>13C64</string>
<key>DTSDKName</key> <key>DTSDKName</key>
<string>macosx10.9</string> <string>macosx10.9</string>
<key>DTXcode</key> <key>DTXcode</key>
<string>0502</string> <string>0511</string>
<key>DTXcodeBuild</key> <key>DTXcodeBuild</key>
<string>5A3005</string> <string>5B1008</string>
</dict> </dict>
</plist> </plist>

0
Vendor/XcodeCoverage/.gitignore vendored Executable file → Normal file
View File

0
Vendor/XcodeCoverage/LICENSE.txt vendored Executable file → Normal file
View File

0
Vendor/XcodeCoverage/README.md vendored Executable file → Normal file
View File

View File

@ -5,6 +5,7 @@
# Source: https://github.com/jonreid/XcodeCoverage # Source: https://github.com/jonreid/XcodeCoverage
# #
source envcov.sh DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source ${DIR}/envcov.sh
"${LCOV}" --zerocounters -d "${OBJ_DIR}" "${LCOV}" --zerocounters -d "${OBJ_DIR}"

View File

@ -4,7 +4,8 @@
# Source: https://github.com/jonreid/XcodeCoverage # Source: https://github.com/jonreid/XcodeCoverage
# #
source env.sh DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source ${DIR}/env.sh
# Change the report name if you like: # Change the report name if you like:
LCOV_INFO=Coverage.info LCOV_INFO=Coverage.info

View File

@ -4,4 +4,5 @@
# Source: https://github.com/jonreid/XcodeCoverage # Source: https://github.com/jonreid/XcodeCoverage
# #
export | egrep '( BUILT_PRODUCTS_DIR)|(CURRENT_ARCH)|(OBJECT_FILE_DIR_normal)|(SRCROOT)|(OBJROOT)' > ../Vendor/XcodeCoverage/env.sh DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
export | egrep '( BUILT_PRODUCTS_DIR)|(CURRENT_ARCH)|(OBJECT_FILE_DIR_normal)|(SRCROOT)|(OBJROOT)' > ${DIR}/env.sh

View File

@ -5,7 +5,8 @@
# Source: https://github.com/jonreid/XcodeCoverage # Source: https://github.com/jonreid/XcodeCoverage
# #
source envcov.sh DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source ${DIR}/envcov.sh
remove_old_report() remove_old_report()
{ {

View File

@ -1017,7 +1017,7 @@ sub process_dafile($$)
warn("WARNING: GCOV failed for $da_filename!\n"); warn("WARNING: GCOV failed for $da_filename!\n");
return; return;
} }
die("ERROR: GCOV failed for $da_filename!\n"); warn("WARNING: GCOV failed for $da_filename!\n");
} }
# Collect data from resulting .gcov files and create .info file # Collect data from resulting .gcov files and create .info file
@ -1865,13 +1865,18 @@ sub get_gcov_version()
my $version_string; my $version_string;
my $result; my $result;
open(GCOV_PIPE, "-|", "$gcov_tool -v") open(GCOV_PIPE, "-|", "$gcov_tool --version")
or die("ERROR: cannot retrieve gcov version!\n"); or die("ERROR: cannot retrieve gcov version!\n");
$version_string = <GCOV_PIPE>; $version_string = <GCOV_PIPE>;
close(GCOV_PIPE); close(GCOV_PIPE);
$result = 0; $result = 0;
if ($version_string =~ /(\d+)\.(\d+)(\.(\d+))?/) if ($version_string =~ m/LLVM/)
{
info("Found llvm-cov\n");
$result = 0x40201;
}
elsif ($version_string =~ /(\d+)\.(\d+)(\.(\d+))?/)
{ {
if (defined($4)) if (defined($4))
{ {
@ -1887,7 +1892,6 @@ sub get_gcov_version()
return ($result, $version_string); return ($result, $version_string);
} }
# #
# info(printf_parameter) # info(printf_parameter)
# #

View File

@ -1,3 +1,14 @@
## Version 3.5.5
- [NEW] `BITCrashManager`: Added support for adding a binary attachment to crash reports
- [NEW] `BITCrashManager`: Integrated PLCrashReporter 1.2 RC5 (with 2 more fixes)
- [BUGFIX] `BITUpdateManager`: Fixed problem with `checkForUpdate` when `updateSetting` is set to `BITUpdateCheckManually`
- [BUGFIX] `BITAuthenticator`: Fixed keychain warning alert showing app on launch if keychain is locked
- [BUGFIX] `BITAuthenticator`: Fixed a possible assertion problem with auto-authentication (when using custom SDK builds without assertions being disabled)
- [BUGFIX] `BITAuthenticator`: Added user email to crash report for beta builds if BITAuthenticator is set to BITAuthenticatorIdentificationTypeWebAuth
- [BUGFIX] Fixed more analyzer warnings
<br /><br/>
## Version 3.5.4 ## Version 3.5.4
- [BUGFIX] Fix a possible crash before sending the crash report when the selector could not be found - [BUGFIX] Fix a possible crash before sending the crash report when the selector could not be found

View File

@ -1,6 +1,6 @@
## Version 3.5.4 ## Version 3.5.5
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.4/docs/docs/Changelog.html) - [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.5/docs/docs/Changelog.html)
## Introduction ## Introduction
@ -116,7 +116,7 @@ This documentation provides integrated help in Xcode for all public APIs and a s
3. Copy the content into ~`/Library/Developer/Shared/Documentation/DocSets` 3. Copy the content into ~`/Library/Developer/Shared/Documentation/DocSets`
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.4/](http://hockeyapp.net/help/sdk/ios/3.5.4/) The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.5/](http://hockeyapp.net/help/sdk/ios/3.5.5/)
### Set up with xcconfig ### Set up with xcconfig

View File

@ -1,6 +1,6 @@
## Version 3.5.4 ## Version 3.5.5
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.4/docs/docs/Changelog.html) - [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.5/docs/docs/Changelog.html)
## Introduction ## Introduction
@ -90,9 +90,9 @@ The Mac Desktop Uploader can provide easy uploading of your app versions to Hock
This documentation provides integrated help in Xcode for all public APIs and a set of additional tutorials and how-tos. This documentation provides integrated help in Xcode for all public APIs and a set of additional tutorials and how-tos.
1. Copy `de.bitstadium.HockeySDK-iOS-3.5.1.docset` into ~`/Library/Developer/Shared/Documentation/DocSets` 1. Copy `de.bitstadium.HockeySDK-iOS-3.5.5.docset` into ~`/Library/Developer/Shared/Documentation/DocSets`
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.4/](http://hockeyapp.net/help/sdk/ios/3.5.4/) The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.5/](http://hockeyapp.net/help/sdk/ios/3.5.5/)
### Set up with xcconfig ### Set up with xcconfig