mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-08 08:31:13 +00:00
Merge branch 'release/3.5.3'
This commit is contained in:
commit
15d57cce01
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,6 +10,7 @@ build
|
||||
!default.xcworkspace
|
||||
!project.xcworkspace
|
||||
xcuserdata
|
||||
xccheckout
|
||||
profile
|
||||
*.moved-aside
|
||||
|
||||
|
@ -578,6 +578,7 @@ static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44};
|
||||
NSString *const kAuthorizationHost = @"authorize";
|
||||
NSString *urlScheme = _urlScheme ? : [NSString stringWithFormat:@"ha%@", self.appIdentifier];
|
||||
if(!([[url scheme] isEqualToString:urlScheme] && [[url host] isEqualToString:kAuthorizationHost])) {
|
||||
BITHockeyLog(@"URL scheme for authentication doesn't match!");
|
||||
return NO;
|
||||
}
|
||||
|
||||
@ -611,6 +612,7 @@ static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44};
|
||||
}
|
||||
|
||||
if(installationIdentifier){
|
||||
BITHockeyLog(@"Authentication succeeded.");
|
||||
if(NO == self.restrictApplicationUsage) {
|
||||
[self dismissAuthenticationControllerAnimated:YES completion:nil];
|
||||
}
|
||||
@ -622,6 +624,7 @@ static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44};
|
||||
}
|
||||
} else {
|
||||
//reset token
|
||||
BITHockeyLog(@"Resetting authentication token");
|
||||
[self storeInstallationIdentifier:nil withType:self.identificationType];
|
||||
self.identified = NO;
|
||||
if(self.identificationCompletion) {
|
||||
@ -693,6 +696,8 @@ static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44};
|
||||
return;
|
||||
}
|
||||
|
||||
BITHockeyLog(@"Processing full size image for possible authentication");
|
||||
|
||||
unsigned char *buffer, *source;
|
||||
source = (unsigned char *)malloc((unsigned long)fs.st_size);
|
||||
if (read(fd, source, (unsigned long)fs.st_size) != fs.st_size) {
|
||||
@ -720,7 +725,8 @@ static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44};
|
||||
length = ntohl(length);
|
||||
|
||||
buffer += 4;
|
||||
name = (unsigned char *)malloc(4);
|
||||
name = (unsigned char *)malloc(5);
|
||||
name[4] = 0;
|
||||
memcpy(name, buffer, 4);
|
||||
|
||||
buffer += 4;
|
||||
@ -754,7 +760,10 @@ static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44};
|
||||
free(source);
|
||||
|
||||
if (result) {
|
||||
BITHockeyLog(@"Authenticating using full size image information: %@", result);
|
||||
[self handleOpenURL:[NSURL URLWithString:result] sourceApplication:nil annotation:nil];
|
||||
} else {
|
||||
BITHockeyLog(@"No authentication information found");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,6 +166,20 @@ typedef NS_ENUM(NSUInteger, BITCrashManagerStatus) {
|
||||
@property (nonatomic, assign, getter=isMachExceptionHandlerEnabled) BOOL enableMachExceptionHandler;
|
||||
|
||||
|
||||
/**
|
||||
* Enable on device symbolication for system symbols
|
||||
*
|
||||
* By default, the SDK does not symbolicate on the device, since this can
|
||||
* take a few seconds at each crash. Also note that symbolication on the
|
||||
* device might not be able to retrieve all symbols.
|
||||
*
|
||||
* Enable if you want to analyze crashes on unreleased OS versions.
|
||||
*
|
||||
* Default: _NO_
|
||||
*/
|
||||
@property (nonatomic, assign, getter=isOnDeviceSymbolicationEnabled) BOOL enableOnDeviceSymbolication;
|
||||
|
||||
|
||||
/**
|
||||
* Set the callbacks that will be executed prior to program termination after a crash has occurred
|
||||
*
|
||||
|
@ -125,17 +125,7 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:_crashManagerStatus forKey:kBITCrashManagerStatus];
|
||||
}
|
||||
|
||||
// temporary directory for crashes grabbed from PLCrashReporter
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
_crashesDir = [[paths objectAtIndex:0] stringByAppendingPathComponent:BITHOCKEY_IDENTIFIER];
|
||||
|
||||
if (![self.fileManager fileExistsAtPath:_crashesDir]) {
|
||||
NSDictionary *attributes = [NSDictionary dictionaryWithObject: [NSNumber numberWithUnsignedLong: 0755] forKey: NSFilePosixPermissions];
|
||||
NSError *theError = NULL;
|
||||
|
||||
[self.fileManager createDirectoryAtPath:_crashesDir withIntermediateDirectories: YES attributes: attributes error: &theError];
|
||||
}
|
||||
|
||||
_crashesDir = bit_settingsDir();
|
||||
_settingsFile = [_crashesDir stringByAppendingPathComponent:BITHOCKEY_CRASH_SETTINGS];
|
||||
_analyzerInProgressFile = [_crashesDir stringByAppendingPathComponent:BITHOCKEY_CRASH_ANALYZER];
|
||||
|
||||
@ -308,7 +298,8 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
|
||||
* @return The userID value
|
||||
*/
|
||||
- (NSString *)userIDForCrashReport {
|
||||
NSString *userID = @"";
|
||||
// first check the global keychain storage
|
||||
NSString *userID = [self stringValueFromKeychainForKey:kBITHockeyMetaUserID] ?: @"";
|
||||
|
||||
#if HOCKEYSDK_FEATURE_AUTHENTICATOR
|
||||
// if we have an identification from BITAuthenticator, use this as a default.
|
||||
@ -337,7 +328,8 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
|
||||
* @return The userName value
|
||||
*/
|
||||
- (NSString *)userNameForCrashReport {
|
||||
NSString *username = @"";
|
||||
// first check the global keychain storage
|
||||
NSString *username = [self stringValueFromKeychainForKey:kBITHockeyMetaUserName] ?: @"";
|
||||
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(userNameForCrashManager:)]) {
|
||||
username = [self.delegate userNameForCrashManager:self] ?: @"";
|
||||
@ -358,7 +350,8 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
|
||||
* @return The userEmail value
|
||||
*/
|
||||
- (NSString *)userEmailForCrashReport {
|
||||
NSString *useremail = @"";
|
||||
// first check the global keychain storage
|
||||
NSString *useremail = [self stringValueFromKeychainForKey:kBITHockeyMetaUserEmail] ?: @"";
|
||||
|
||||
#if HOCKEYSDK_FEATURE_AUTHENTICATOR
|
||||
// if we have an identification from BITAuthenticator, use this as a default.
|
||||
@ -667,8 +660,14 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
|
||||
if (self.isMachExceptionHandlerEnabled) {
|
||||
signalHandlerType = PLCrashReporterSignalHandlerTypeMach;
|
||||
}
|
||||
|
||||
PLCrashReporterSymbolicationStrategy symbolicationStrategy = PLCrashReporterSymbolicationStrategyNone;
|
||||
if (self.isOnDeviceSymbolicationEnabled) {
|
||||
symbolicationStrategy = PLCrashReporterSymbolicationStrategyAll;
|
||||
}
|
||||
|
||||
BITPLCrashReporterConfig *config = [[BITPLCrashReporterConfig alloc] initWithSignalHandlerType: signalHandlerType
|
||||
symbolicationStrategy: PLCrashReporterSymbolicationStrategyAll];
|
||||
symbolicationStrategy: symbolicationStrategy];
|
||||
self.plCrashReporter = [[BITPLCrashReporter alloc] initWithConfiguration: config];
|
||||
|
||||
// Check if we previously crashed
|
||||
|
@ -33,6 +33,18 @@
|
||||
|
||||
#import <CrashReporter/CrashReporter.h>
|
||||
|
||||
#import <mach-o/dyld.h>
|
||||
#import <mach-o/getsect.h>
|
||||
#import <mach-o/ldsyms.h>
|
||||
#import <dlfcn.h>
|
||||
#import <Availability.h>
|
||||
|
||||
#if defined(__OBJC2__)
|
||||
#define SEL_NAME_SECT "__objc_methname"
|
||||
#else
|
||||
#define SEL_NAME_SECT "__cstring"
|
||||
#endif
|
||||
|
||||
#import "BITCrashReportTextFormatter.h"
|
||||
|
||||
/*
|
||||
@ -67,6 +79,112 @@ static NSInteger bit_binaryImageSort(id binary1, id binary2, void *context) {
|
||||
return NSOrderedSame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the given @a string terminates prior to @a limit.
|
||||
*/
|
||||
static const char *safer_string_read (const char *string, const char *limit) {
|
||||
const char *p = string;
|
||||
do {
|
||||
if (p >= limit || p+1 >= limit) {
|
||||
return NULL;
|
||||
}
|
||||
p++;
|
||||
} while (*p != '\0');
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
/*
|
||||
* The relativeAddress should be `<ecx/rsi/r1/x1 ...> - <image base>`, extracted from the crash report's thread
|
||||
* and binary image list.
|
||||
*
|
||||
* For the (architecture-specific) registers to attempt, see:
|
||||
* http://sealiesoftware.com/blog/archive/2008/09/22/objc_explain_So_you_crashed_in_objc_msgSend.html
|
||||
*/
|
||||
static const char *findSEL (const char *imageName, NSString *imageUUID, uint64_t relativeAddress) {
|
||||
unsigned int images_count = _dyld_image_count();
|
||||
for (unsigned int i = 0; i < images_count; ++i) {
|
||||
intptr_t slide = _dyld_get_image_vmaddr_slide(i);
|
||||
const struct mach_header *header = _dyld_get_image_header(i);
|
||||
const struct mach_header_64 *header64 = (const struct mach_header_64 *) header;
|
||||
const char *name = _dyld_get_image_name(i);
|
||||
|
||||
/* Image disappeared? */
|
||||
if (name == NULL || header == NULL)
|
||||
continue;
|
||||
|
||||
/* Check if this is the correct image. If we were being even more careful, we'd check the LC_UUID */
|
||||
if (strcmp(name, imageName) != 0)
|
||||
continue;
|
||||
|
||||
/* Determine whether this is a 64-bit or 32-bit Mach-O file */
|
||||
BOOL m64 = NO;
|
||||
if (header->magic == MH_MAGIC_64)
|
||||
m64 = YES;
|
||||
|
||||
NSString *uuidString = nil;
|
||||
const uint8_t *command;
|
||||
uint32_t ncmds;
|
||||
|
||||
if (m64) {
|
||||
command = (const uint8_t *)(header64 + 1);
|
||||
ncmds = header64->ncmds;
|
||||
} else {
|
||||
command = (const uint8_t *)(header + 1);
|
||||
ncmds = header->ncmds;
|
||||
}
|
||||
for (uint32_t idx = 0; idx < ncmds; ++idx) {
|
||||
const struct load_command *load_command = (const struct load_command *)command;
|
||||
if (load_command->cmd == LC_UUID) {
|
||||
const struct uuid_command *uuid_command = (const struct uuid_command *)command;
|
||||
const uint8_t *uuid = uuid_command->uuid;
|
||||
uuidString = [[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[4], uuid[5], uuid[6], uuid[7],
|
||||
uuid[8], uuid[9], uuid[10], uuid[11],
|
||||
uuid[12], uuid[13], uuid[14], uuid[15]]
|
||||
lowercaseString];
|
||||
break;
|
||||
} else {
|
||||
command += load_command->cmdsize;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this is the correct image by comparing the UUIDs
|
||||
if (!uuidString || ![uuidString isEqualToString:imageUUID])
|
||||
continue;
|
||||
|
||||
/* Fetch the __objc_methname section */
|
||||
const char *methname_sect;
|
||||
uint64_t methname_sect_size;
|
||||
if (m64) {
|
||||
methname_sect = getsectdatafromheader_64(header64, SEG_TEXT, SEL_NAME_SECT, &methname_sect_size);
|
||||
} else {
|
||||
uint32_t meth_size_32;
|
||||
methname_sect = getsectdatafromheader(header, SEG_TEXT, SEL_NAME_SECT, &meth_size_32);
|
||||
methname_sect_size = meth_size_32;
|
||||
}
|
||||
|
||||
/* Apply the slide, as per getsectdatafromheader(3) */
|
||||
methname_sect += slide;
|
||||
|
||||
if (methname_sect == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Calculate the target address within this image, and verify that it is within __objc_methname */
|
||||
const char *target = ((const char *)header) + relativeAddress;
|
||||
const char *limit = methname_sect + methname_sect_size;
|
||||
if (target < methname_sect || target >= limit) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Read the actual method name */
|
||||
return safer_string_read(target, limit);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats PLCrashReport data as human-readable text.
|
||||
@ -282,6 +400,14 @@ static NSInteger bit_binaryImageSort(id binary1, id binary2, void *context) {
|
||||
|
||||
[text appendString: @"\n"];
|
||||
|
||||
BITPLCrashReportThreadInfo *crashed_thread = nil;
|
||||
for (BITPLCrashReportThreadInfo *thread in report.threads) {
|
||||
if (thread.crashed) {
|
||||
crashed_thread = thread;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Uncaught Exception */
|
||||
if (report.hasExceptionInfo) {
|
||||
[text appendFormat: @"Application Specific Information:\n"];
|
||||
@ -289,6 +415,36 @@ static NSInteger bit_binaryImageSort(id binary1, id binary2, void *context) {
|
||||
report.exceptionInfo.exceptionName, report.exceptionInfo.exceptionReason];
|
||||
|
||||
[text appendString: @"\n"];
|
||||
} else if (crashed_thread != nil) {
|
||||
// try to find the selector in case this was a crash in obj_msgSend
|
||||
// we search this wether the crash happend in obj_msgSend or not since we don't have the symbol!
|
||||
|
||||
NSString *foundSelector = nil;
|
||||
|
||||
// search the registers value for the current arch
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
if (lp64) {
|
||||
foundSelector = [[self class] selectorForRegisterWithName:@"rsi" ofThread:crashed_thread report:report];
|
||||
if (foundSelector == NULL)
|
||||
foundSelector = [[self class] selectorForRegisterWithName:@"rdx" ofThread:crashed_thread report:report];
|
||||
} else {
|
||||
foundSelector = [[self class] selectorForRegisterWithName:@"ecx" ofThread:crashed_thread report:report];
|
||||
}
|
||||
#else
|
||||
if (lp64) {
|
||||
foundSelector = [[self class] selectorForRegisterWithName:@"x1" ofThread:crashed_thread report:report];
|
||||
} else {
|
||||
foundSelector = [[self class] selectorForRegisterWithName:@"r1" ofThread:crashed_thread report:report];
|
||||
if (foundSelector == NULL)
|
||||
foundSelector = [[self class] selectorForRegisterWithName:@"r2" ofThread:crashed_thread report:report];
|
||||
}
|
||||
#endif
|
||||
|
||||
if (foundSelector) {
|
||||
[text appendFormat: @"Application Specific Information:\n"];
|
||||
[text appendFormat: @"Selector name found in current argument registers: %@\n", foundSelector];
|
||||
[text appendString: @"\n"];
|
||||
}
|
||||
}
|
||||
|
||||
/* If an exception stack trace is available, output an Apple-compatible backtrace. */
|
||||
@ -308,12 +464,10 @@ static NSInteger bit_binaryImageSort(id binary1, id binary2, void *context) {
|
||||
}
|
||||
|
||||
/* Threads */
|
||||
BITPLCrashReportThreadInfo *crashed_thread = nil;
|
||||
NSInteger maxThreadNum = 0;
|
||||
for (BITPLCrashReportThreadInfo *thread in report.threads) {
|
||||
if (thread.crashed) {
|
||||
[text appendFormat: @"Thread %ld Crashed:\n", (long) thread.threadNumber];
|
||||
crashed_thread = thread;
|
||||
} else {
|
||||
[text appendFormat: @"Thread %ld:\n", (long) thread.threadNumber];
|
||||
}
|
||||
@ -417,6 +571,41 @@ static NSInteger bit_binaryImageSort(id binary1, id binary2, void *context) {
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the selector string of a given register name
|
||||
*
|
||||
* @param regName The name of the register to use for getting the address
|
||||
* @param thread The crashed thread
|
||||
* @param images NSArray of binary images
|
||||
*
|
||||
* @return The selector as a C string or NULL if no selector was found
|
||||
*/
|
||||
+ (NSString *)selectorForRegisterWithName:(NSString *)regName ofThread:(BITPLCrashReportThreadInfo *)thread report:(BITPLCrashReport *)report {
|
||||
// get the address for the register
|
||||
uint64_t regAddress = 0;
|
||||
|
||||
for (BITPLCrashReportRegisterInfo *reg in thread.registers) {
|
||||
if ([reg.registerName isEqualToString:regName]) {
|
||||
regAddress = reg.registerValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (regAddress == 0)
|
||||
return nil;
|
||||
|
||||
BITPLCrashReportBinaryImageInfo *imageForRegAddress = [report imageForAddress:regAddress];
|
||||
if (imageForRegAddress) {
|
||||
// get the SEL
|
||||
const char *foundSelector = findSEL([imageForRegAddress.imageName UTF8String], imageForRegAddress.imageUUID, regAddress - (uint64_t)imageForRegAddress.imageBaseAddress);
|
||||
|
||||
return [NSString stringWithUTF8String:foundSelector];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of app UUIDs and their architecture
|
||||
* As a dictionary for each element
|
||||
|
@ -255,8 +255,8 @@
|
||||
}
|
||||
|
||||
- (void)newFeedbackAction:(id)sender {
|
||||
BITFeedbackComposeViewController *composeController = [[BITFeedbackComposeViewController alloc] init];
|
||||
|
||||
BITFeedbackComposeViewController *composeController = [self.manager feedbackComposeViewController];
|
||||
|
||||
UINavigationController *navController = [self.manager customNavigationControllerWithRootViewController:composeController
|
||||
presentationStyle:UIModalPresentationFormSheet];
|
||||
|
||||
@ -366,6 +366,16 @@
|
||||
} else {
|
||||
[self dismissViewControllerAnimated:YES completion:^(void){}];
|
||||
}
|
||||
|
||||
if (self.manager.delegate &&
|
||||
[self.manager.delegate respondsToSelector:@selector(feedbackComposeViewController:didFinishWithResult:)]) {
|
||||
[self.manager.delegate feedbackComposeViewController:composeViewController didFinishWithResult:composeResult];
|
||||
} else if (self.manager.delegate && [self.manager.delegate respondsToSelector:@selector(feedbackComposeViewControllerDidFinish:)]) {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
||||
[self.manager.delegate feedbackComposeViewControllerDidFinish:composeViewController];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -87,9 +87,9 @@ typedef NS_ENUM(NSInteger, BITFeedbackUserDataElement) {
|
||||
reload the list content from the server and changing the users name or email if these
|
||||
are allowed to be set.
|
||||
|
||||
It is also possible to invoke the user interface to compose a new message anywhere in your
|
||||
It is also possible to invoke the user interface to compose a new message in your
|
||||
own code, by calling `[BITFeedbackManager showFeedbackComposeView]` modally or adding
|
||||
`[BITFeedackManager feedbackComposeViewController]` to push onto a navigation stack.
|
||||
`[BITFeedbackManager feedbackComposeViewController]` to push onto a navigation stack.
|
||||
|
||||
If new messages are written while the device is offline, the SDK automatically retries to
|
||||
send them once the app starts again or gets active again, or if the notification
|
||||
|
@ -53,7 +53,6 @@
|
||||
|
||||
@implementation BITFeedbackManager {
|
||||
NSFileManager *_fileManager;
|
||||
NSString *_feedbackDir;
|
||||
NSString *_settingsFile;
|
||||
|
||||
id _appDidBecomeActiveObserver;
|
||||
@ -89,18 +88,7 @@
|
||||
|
||||
_fileManager = [[NSFileManager alloc] init];
|
||||
|
||||
// temporary directory for crashes grabbed from PLCrashReporter
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
||||
_feedbackDir = [[paths objectAtIndex:0] stringByAppendingPathComponent:BITHOCKEY_IDENTIFIER];
|
||||
|
||||
if (![_fileManager fileExistsAtPath:_feedbackDir]) {
|
||||
NSDictionary *attributes = [NSDictionary dictionaryWithObject: [NSNumber numberWithUnsignedLong: 0755] forKey: NSFilePosixPermissions];
|
||||
NSError *theError = NULL;
|
||||
|
||||
[_fileManager createDirectoryAtPath:_feedbackDir withIntermediateDirectories: YES attributes: attributes error: &theError];
|
||||
}
|
||||
|
||||
_settingsFile = [_feedbackDir stringByAppendingPathComponent:BITHOCKEY_FEEDBACK_SETTINGS];
|
||||
_settingsFile = [bit_settingsDir() stringByAppendingPathComponent:BITHOCKEY_FEEDBACK_SETTINGS];
|
||||
|
||||
_userID = nil;
|
||||
_userName = nil;
|
||||
@ -218,7 +206,10 @@
|
||||
|
||||
|
||||
- (BITFeedbackComposeViewController *)feedbackComposeViewController {
|
||||
return [[BITFeedbackComposeViewController alloc] init];
|
||||
BITFeedbackComposeViewController *composeViewController = [[BITFeedbackComposeViewController alloc] init];
|
||||
// by default set the delegate to be identical to the one of BITFeedbackManager
|
||||
[composeViewController setDelegate:self.delegate];
|
||||
return composeViewController;
|
||||
}
|
||||
|
||||
- (void)showFeedbackComposeView {
|
||||
@ -271,63 +262,72 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)updateUserIDUsingDelegate {
|
||||
- (BOOL)updateUserIDUsingKeychainAndDelegate {
|
||||
BOOL availableViaDelegate = NO;
|
||||
|
||||
NSString *userID = [self stringValueFromKeychainForKey:kBITHockeyMetaUserID];
|
||||
|
||||
if ([BITHockeyManager sharedHockeyManager].delegate &&
|
||||
[[BITHockeyManager sharedHockeyManager].delegate respondsToSelector:@selector(userIDForHockeyManager:componentManager:)]) {
|
||||
NSString *userID = [[BITHockeyManager sharedHockeyManager].delegate
|
||||
userIDForHockeyManager:[BITHockeyManager sharedHockeyManager]
|
||||
componentManager:self];
|
||||
if (userID) {
|
||||
availableViaDelegate = YES;
|
||||
self.userID = userID;
|
||||
}
|
||||
userID = [[BITHockeyManager sharedHockeyManager].delegate
|
||||
userIDForHockeyManager:[BITHockeyManager sharedHockeyManager]
|
||||
componentManager:self];
|
||||
}
|
||||
|
||||
|
||||
if (userID) {
|
||||
availableViaDelegate = YES;
|
||||
self.userID = userID;
|
||||
}
|
||||
|
||||
return availableViaDelegate;
|
||||
}
|
||||
|
||||
- (BOOL)updateUserNameUsingDelegate {
|
||||
- (BOOL)updateUserNameUsingKeychainAndDelegate {
|
||||
BOOL availableViaDelegate = NO;
|
||||
|
||||
NSString *userName = [self stringValueFromKeychainForKey:kBITHockeyMetaUserName];
|
||||
|
||||
if ([BITHockeyManager sharedHockeyManager].delegate &&
|
||||
[[BITHockeyManager sharedHockeyManager].delegate respondsToSelector:@selector(userNameForHockeyManager:componentManager:)]) {
|
||||
NSString *userName = [[BITHockeyManager sharedHockeyManager].delegate
|
||||
userName = [[BITHockeyManager sharedHockeyManager].delegate
|
||||
userNameForHockeyManager:[BITHockeyManager sharedHockeyManager]
|
||||
componentManager:self];
|
||||
if (userName) {
|
||||
availableViaDelegate = YES;
|
||||
self.userName = userName;
|
||||
self.requireUserName = BITFeedbackUserDataElementDontShow;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (userName) {
|
||||
availableViaDelegate = YES;
|
||||
self.userName = userName;
|
||||
self.requireUserName = BITFeedbackUserDataElementDontShow;
|
||||
}
|
||||
|
||||
return availableViaDelegate;
|
||||
}
|
||||
|
||||
- (BOOL)updateUserEmailUsingDelegate {
|
||||
- (BOOL)updateUserEmailUsingKeychainAndDelegate {
|
||||
BOOL availableViaDelegate = NO;
|
||||
|
||||
NSString *userEmail = [self stringValueFromKeychainForKey:kBITHockeyMetaUserEmail];
|
||||
|
||||
if ([BITHockeyManager sharedHockeyManager].delegate &&
|
||||
[[BITHockeyManager sharedHockeyManager].delegate respondsToSelector:@selector(userEmailForHockeyManager:componentManager:)]) {
|
||||
NSString *userEmail = [[BITHockeyManager sharedHockeyManager].delegate
|
||||
userEmailForHockeyManager:[BITHockeyManager sharedHockeyManager]
|
||||
componentManager:self];
|
||||
if (userEmail) {
|
||||
availableViaDelegate = YES;
|
||||
self.userEmail = userEmail;
|
||||
self.requireUserEmail = BITFeedbackUserDataElementDontShow;
|
||||
}
|
||||
userEmail = [[BITHockeyManager sharedHockeyManager].delegate
|
||||
userEmailForHockeyManager:[BITHockeyManager sharedHockeyManager]
|
||||
componentManager:self];
|
||||
}
|
||||
|
||||
|
||||
if (userEmail) {
|
||||
availableViaDelegate = YES;
|
||||
self.userEmail = userEmail;
|
||||
self.requireUserEmail = BITFeedbackUserDataElementDontShow;
|
||||
}
|
||||
|
||||
return availableViaDelegate;
|
||||
}
|
||||
|
||||
- (void)updateAppDefinedUserData {
|
||||
[self updateUserIDUsingDelegate];
|
||||
[self updateUserNameUsingDelegate];
|
||||
[self updateUserEmailUsingDelegate];
|
||||
[self updateUserIDUsingKeychainAndDelegate];
|
||||
[self updateUserNameUsingKeychainAndDelegate];
|
||||
[self updateUserEmailUsingKeychainAndDelegate];
|
||||
|
||||
// if both values are shown via the delegates, we never ever did ask and will never ever ask for user data
|
||||
if (self.requireUserName == BITFeedbackUserDataElementDontShow &&
|
||||
@ -339,9 +339,9 @@
|
||||
#pragma mark - Local Storage
|
||||
|
||||
- (void)loadMessages {
|
||||
BOOL userIDViaDelegate = [self updateUserIDUsingDelegate];
|
||||
BOOL userNameViaDelegate = [self updateUserNameUsingDelegate];
|
||||
BOOL userEmailViaDelegate = [self updateUserEmailUsingDelegate];
|
||||
BOOL userIDViaDelegate = [self updateUserIDUsingKeychainAndDelegate];
|
||||
BOOL userNameViaDelegate = [self updateUserNameUsingKeychainAndDelegate];
|
||||
BOOL userEmailViaDelegate = [self updateUserEmailUsingKeychainAndDelegate];
|
||||
|
||||
if (![_fileManager fileExistsAtPath:_settingsFile])
|
||||
return;
|
||||
|
@ -29,13 +29,14 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class BITFeedbackManager;
|
||||
@protocol BITFeedbackComposeViewControllerDelegate;
|
||||
|
||||
/**
|
||||
* Delegate protocol which is notified about changes in the feedbackManager
|
||||
* @TODO
|
||||
* * move shouldShowUpdateAlert from feedbackManager here
|
||||
*/
|
||||
@protocol BITFeedbackManagerDelegate <NSObject>
|
||||
@protocol BITFeedbackManagerDelegate <NSObject, BITFeedbackComposeViewControllerDelegate>
|
||||
|
||||
@optional
|
||||
|
||||
|
@ -34,6 +34,8 @@ NSString *bit_URLEncodedString(NSString *inputString);
|
||||
NSString *bit_URLDecodedString(NSString *inputString);
|
||||
NSString *bit_base64String(NSData * data, unsigned long length);
|
||||
|
||||
NSString *bit_settingsDir(void);
|
||||
|
||||
BOOL bit_validateEmail(NSString *email);
|
||||
NSString *bit_keychainHockeySDKServiceName(void);
|
||||
|
||||
|
@ -76,6 +76,28 @@ NSString *bit_base64String(NSData * data, unsigned long length) {
|
||||
#endif
|
||||
}
|
||||
|
||||
NSString *bit_settingsDir(void) {
|
||||
static NSString *settingsDir = nil;
|
||||
static dispatch_once_t predSettingsDir;
|
||||
|
||||
dispatch_once(&predSettingsDir, ^{
|
||||
NSFileManager *fileManager = [[NSFileManager alloc] init];
|
||||
|
||||
// temporary directory for crashes grabbed from PLCrashReporter
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
settingsDir = [[paths objectAtIndex:0] stringByAppendingPathComponent:BITHOCKEY_IDENTIFIER];
|
||||
|
||||
if (![fileManager fileExistsAtPath:settingsDir]) {
|
||||
NSDictionary *attributes = [NSDictionary dictionaryWithObject: [NSNumber numberWithUnsignedLong: 0755] forKey: NSFilePosixPermissions];
|
||||
NSError *theError = NULL;
|
||||
|
||||
[fileManager createDirectoryAtPath:settingsDir withIntermediateDirectories: YES attributes: attributes error: &theError];
|
||||
}
|
||||
});
|
||||
|
||||
return settingsDir;
|
||||
}
|
||||
|
||||
BOOL bit_validateEmail(NSString *email) {
|
||||
NSString *emailRegex =
|
||||
@"(?:[a-z0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[a-z0-9!#$%\\&'*+/=?\\^_`{|}"
|
||||
@ -91,7 +113,13 @@ BOOL bit_validateEmail(NSString *email) {
|
||||
}
|
||||
|
||||
NSString *bit_keychainHockeySDKServiceName(void) {
|
||||
NSString *serviceName = [NSString stringWithFormat:@"%@.HockeySDK", bit_mainBundleIdentifier()];
|
||||
static NSString *serviceName = nil;
|
||||
static dispatch_once_t predServiceName;
|
||||
|
||||
dispatch_once(&predServiceName, ^{
|
||||
serviceName = [NSString stringWithFormat:@"%@.HockeySDK", bit_mainBundleIdentifier()];
|
||||
});
|
||||
|
||||
return serviceName;
|
||||
}
|
||||
|
||||
|
@ -312,9 +312,6 @@
|
||||
/**
|
||||
Reference to the initialized BITAuthenticator module
|
||||
|
||||
The authenticator is disabled by default. To enable it you need to set
|
||||
`[BITAuthenticator authenticationType]` and `[BITAuthenticator validationType]`
|
||||
|
||||
Returns the BITAuthenticator instance initialized by BITHockeyManager
|
||||
|
||||
@see configureWithIdentifier:delegate:
|
||||
@ -387,7 +384,74 @@
|
||||
|
||||
|
||||
///-----------------------------------------------------------------------------
|
||||
/// @name Meta
|
||||
/// @name Additional meta data
|
||||
///-----------------------------------------------------------------------------
|
||||
|
||||
/** Set the userid that should used in the SDK components
|
||||
|
||||
Right now this is used by the `BITCrashManager` to attach to a crash report.
|
||||
`BITFeedbackManager` uses it too for assigning the user to a discussion thread.
|
||||
|
||||
The value can be set at any time and will be stored in the keychain on the current
|
||||
device only! To delete the value from the keychain set the value to `nil`.
|
||||
|
||||
This property is optional and can be used as an alternative to the delegate. If you
|
||||
want to define specific data for each component, use the delegate instead which does
|
||||
overwrite the values set by this property.
|
||||
|
||||
@see userName
|
||||
@see userEmail
|
||||
@see `[BITHockeyManagerDelegate userIDForHockeyManager:componentManager:]`
|
||||
*/
|
||||
@property (nonatomic, retain) NSString *userID;
|
||||
|
||||
|
||||
/** Set the user name that should used in the SDK components
|
||||
|
||||
Right now this is used by the `BITCrashManager` to attach to a crash report.
|
||||
`BITFeedbackManager` uses it too for assigning the user to a discussion thread.
|
||||
|
||||
The value can be set at any time and will be stored in the keychain on the current
|
||||
device only! To delete the value from the keychain set the value to `nil`.
|
||||
|
||||
This property is optional and can be used as an alternative to the delegate. If you
|
||||
want to define specific data for each component, use the delegate instead which does
|
||||
overwrite the values set by this property.
|
||||
|
||||
@warning When returning a non nil value, crash reports are not anonymous any more
|
||||
and the crash alerts will not show the word "anonymous"!
|
||||
|
||||
@see userID
|
||||
@see userEmail
|
||||
@see `[BITHockeyManagerDelegate userNameForHockeyManager:componentManager:]`
|
||||
*/
|
||||
@property (nonatomic, retain) NSString *userName;
|
||||
|
||||
|
||||
/** Set the users email address that should used in the SDK components
|
||||
|
||||
Right now this is used by the `BITCrashManager` to attach to a crash report.
|
||||
`BITFeedbackManager` uses it too for assigning the user to a discussion thread.
|
||||
|
||||
The value can be set at any time and will be stored in the keychain on the current
|
||||
device only! To delete the value from the keychain set the value to `nil`.
|
||||
|
||||
This property is optional and can be used as an alternative to the delegate. If you
|
||||
want to define specific data for each component, use the delegate instead which does
|
||||
overwrite the values set by this property.
|
||||
|
||||
@warning When returning a non nil value, crash reports are not anonymous any more
|
||||
and the crash alerts will not show the word "anonymous"!
|
||||
|
||||
@see userID
|
||||
@see userName
|
||||
@see `[BITHockeyManagerDelegate userEmailForHockeyManager:componentManager:]`
|
||||
*/
|
||||
@property (nonatomic, retain) NSString *userEmail;
|
||||
|
||||
|
||||
///-----------------------------------------------------------------------------
|
||||
/// @name SDK meta data
|
||||
///-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#import "BITHockeyHelper.h"
|
||||
#import "BITHockeyAppClient.h"
|
||||
#import "BITKeychainUtils.h"
|
||||
|
||||
|
||||
#if HOCKEYSDK_FEATURE_CRASH_REPORTER
|
||||
@ -350,6 +351,56 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)modifyKeychainUserValue:(NSString *)value forKey:(NSString *)key {
|
||||
NSError *error = nil;
|
||||
BOOL success = YES;
|
||||
NSString *updateType = @"update";
|
||||
|
||||
if (value) {
|
||||
success = [BITKeychainUtils storeUsername:key
|
||||
andPassword:value
|
||||
forServiceName:bit_keychainHockeySDKServiceName()
|
||||
updateExisting:YES
|
||||
accessibility:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
|
||||
error:&error];
|
||||
} else {
|
||||
updateType = @"delete";
|
||||
if ([BITKeychainUtils getPasswordForUsername:key
|
||||
andServiceName:bit_keychainHockeySDKServiceName()
|
||||
error:&error]) {
|
||||
success = [BITKeychainUtils deleteItemForUsername:key
|
||||
andServiceName:bit_keychainHockeySDKServiceName()
|
||||
error:&error];
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
NSString *errorDescription = [error description] ?: @"";
|
||||
BITHockeyLog(@"ERROR: Couldn't %@ key %@ in the keychain. %@", updateType, key, errorDescription);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setUserID:(NSString *)userID {
|
||||
// always set it, since nil value will trigger removal of the keychain entry
|
||||
_userID = userID;
|
||||
|
||||
[self modifyKeychainUserValue:userID forKey:kBITHockeyMetaUserID];
|
||||
}
|
||||
|
||||
- (void)setUserName:(NSString *)userName {
|
||||
// always set it, since nil value will trigger removal of the keychain entry
|
||||
_userName = userName;
|
||||
|
||||
[self modifyKeychainUserValue:userName forKey:kBITHockeyMetaUserName];
|
||||
}
|
||||
|
||||
- (void)setUserEmail:(NSString *)userEmail {
|
||||
// always set it, since nil value will trigger removal of the keychain entry
|
||||
_userEmail = userEmail;
|
||||
|
||||
[self modifyKeychainUserValue:userEmail forKey:kBITHockeyMetaUserEmail];
|
||||
}
|
||||
|
||||
- (void)testIdentifier {
|
||||
if (!_appIdentifier || [self isAppStoreEnvironment]) {
|
||||
return;
|
||||
|
@ -76,21 +76,22 @@
|
||||
///-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Implement to force the usage of the live identifier
|
||||
*
|
||||
* This is useful if you are e.g. distributing an enterprise app inside your company
|
||||
* and want to use the `liveIdentifier` for that even though it is not running from
|
||||
* the App Store.
|
||||
*
|
||||
* Example:
|
||||
* - (BOOL)shouldUseLiveIdentifierForHockeyManager:(BITHockeyManager *)hockeyManager {
|
||||
* #ifdef (CONFIGURATION_AppStore)
|
||||
* return YES;
|
||||
* #endif
|
||||
* return NO;
|
||||
* }
|
||||
*
|
||||
* @param hockeyManager BITHockeyManager instance
|
||||
Implement to force the usage of the live identifier
|
||||
|
||||
This is useful if you are e.g. distributing an enterprise app inside your company
|
||||
and want to use the `liveIdentifier` for that even though it is not running from
|
||||
the App Store.
|
||||
|
||||
Example:
|
||||
|
||||
- (BOOL)shouldUseLiveIdentifierForHockeyManager:(BITHockeyManager *)hockeyManager {
|
||||
#ifdef (CONFIGURATION_AppStore)
|
||||
return YES;
|
||||
#endif
|
||||
return NO;
|
||||
}
|
||||
|
||||
@param hockeyManager BITHockeyManager instance
|
||||
*/
|
||||
- (BOOL)shouldUseLiveIdentifierForHockeyManager:(BITHockeyManager *)hockeyManager;
|
||||
|
||||
@ -121,13 +122,14 @@
|
||||
|
||||
/** Return the userid that should used in the SDK components
|
||||
|
||||
Right now this is used by the `BITCrashMananger` to attach to a crash report.
|
||||
Right now this is used by the `BITCrashManager` to attach to a crash report.
|
||||
`BITFeedbackManager` uses it too for assigning the user to a discussion thread.
|
||||
|
||||
In addition, if this returns not nil for `BITFeedbackManager` the user will
|
||||
not be asked for any user details by the component, including useerName or userEmail.
|
||||
|
||||
You can find out the component requesting the userID like this:
|
||||
|
||||
- (NSString *)userIDForHockeyManager:(BITHockeyManager *)hockeyManager componentManager:(BITHockeyBaseManager *)componentManager {
|
||||
if (componentManager == hockeyManager.feedbackManager) {
|
||||
return UserIDForFeedback;
|
||||
@ -138,27 +140,32 @@
|
||||
}
|
||||
}
|
||||
|
||||
For crash reports, this delegate is invoked on the startup after the crash!
|
||||
|
||||
Alternatively you can also use `[BITHockeyManager userID]` which will cache the value in the keychain.
|
||||
|
||||
@warning When returning a non nil value for the `BITCrashManager` component, crash reports
|
||||
are not anonymous any more and the crash alerts will not show the word "anonymous"!
|
||||
|
||||
@param hockeyManager The `BITHockeyManager` HockeyManager instance invoking this delegate
|
||||
@param componentManager The `BITHockeyBaseManager` component instance invoking this delegate, can be `BITCrashManager` or `BITFeedbackManager`
|
||||
@see userNameForHockeyManager:componentManager:
|
||||
@see userEmailForHockeyManager:componentManager:
|
||||
@warning When returning a non nil value for the `BITCrashManager` component, crash reports
|
||||
are not anonymous any more and the crash alerts will not show the word "anonymous"!
|
||||
@see [BITHockeyManager userID]
|
||||
*/
|
||||
- (NSString *)userIDForHockeyManager:(BITHockeyManager *)hockeyManager componentManager:(BITHockeyBaseManager *)componentManager;
|
||||
|
||||
|
||||
/** Return the user name that should used in the SDK components
|
||||
|
||||
Right now this is used by the `BITCrashMananger` to attach to a crash report.
|
||||
Right now this is used by the `BITCrashManager` to attach to a crash report.
|
||||
`BITFeedbackManager` uses it too for assigning the user to a discussion thread.
|
||||
|
||||
In addition, if this returns not nil for `BITFeedbackManager` the user will
|
||||
not be asked for any user details by the component, including useerName or userEmail.
|
||||
|
||||
You can find out the component requesting the user name like this:
|
||||
|
||||
- (NSString *)userNameForHockeyManager:(BITHockeyManager *)hockeyManager componentManager:(BITHockeyBaseManager *)componentManager {
|
||||
if (componentManager == hockeyManager.feedbackManager) {
|
||||
return UserNameForFeedback;
|
||||
@ -169,26 +176,32 @@
|
||||
}
|
||||
}
|
||||
|
||||
For crash reports, this delegate is invoked on the startup after the crash!
|
||||
|
||||
Alternatively you can also use `[BITHockeyManager userName]` which will cache the value in the keychain.
|
||||
|
||||
@warning When returning a non nil value for the `BITCrashManager` component, crash reports
|
||||
are not anonymous any more and the crash alerts will not show the word "anonymous"!
|
||||
|
||||
@param hockeyManager The `BITHockeyManager` HockeyManager instance invoking this delegate
|
||||
@param componentManager The `BITHockeyBaseManager` component instance invoking this delegate, can be `BITCrashManager` or `BITFeedbackManager`
|
||||
@see userIDForHockeyManager:componentManager:
|
||||
@see userEmailForHockeyManager:componentManager:
|
||||
@warning When returning a non nil value for the `BITCrashManager` component, crash reports
|
||||
are not anonymous any more and the crash alerts will not show the word "anonymous"!
|
||||
@see [BITHockeyManager userName]
|
||||
*/
|
||||
- (NSString *)userNameForHockeyManager:(BITHockeyManager *)hockeyManager componentManager:(BITHockeyBaseManager *)componentManager;
|
||||
|
||||
|
||||
/** Return the users email address that should used in the SDK components
|
||||
|
||||
Right now this is used by the `BITCrashMananger` to attach to a crash report.
|
||||
Right now this is used by the `BITCrashManager` to attach to a crash report.
|
||||
`BITFeedbackManager` uses it too for assigning the user to a discussion thread.
|
||||
|
||||
In addition, if this returns not nil for `BITFeedbackManager` the user will
|
||||
not be asked for any user details by the component, including useerName or userEmail.
|
||||
|
||||
You can find out the component requesting the user email like this:
|
||||
|
||||
- (NSString *)userEmailForHockeyManager:(BITHockeyManager *)hockeyManager componentManager:(BITHockeyBaseManager *)componentManager {
|
||||
if (componentManager == hockeyManager.feedbackManager) {
|
||||
return UserEmailForFeedback;
|
||||
@ -199,13 +212,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
For crash reports, this delegate is invoked on the startup after the crash!
|
||||
|
||||
Alternatively you can also use `[BITHockeyManager userEmail]` which will cache the value in the keychain.
|
||||
|
||||
@warning When returning a non nil value for the `BITCrashManager` component, crash reports
|
||||
are not anonymous any more and the crash alerts will not show the word "anonymous"!
|
||||
|
||||
@param hockeyManager The `BITHockeyManager` HockeyManager instance invoking this delegate
|
||||
@param componentManager The `BITHockeyBaseManager` component instance invoking this delegate, can be `BITCrashManager` or `BITFeedbackManager`
|
||||
@see userIDForHockeyManager:componentManager:
|
||||
@see userNameForHockeyManager:componentManager:
|
||||
@warning When returning a non nil value for the `BITCrashManager` component, crash reports
|
||||
are not anonymous any more and the crash alerts will not show the word "anonymous"!
|
||||
@see [BITHockeyManager userEmail]
|
||||
*/
|
||||
- (NSString *)userEmailForHockeyManager:(BITHockeyManager *)hockeyManager componentManager:(BITHockeyBaseManager *)componentManager;
|
||||
|
||||
|
@ -43,6 +43,10 @@
|
||||
|
||||
#define BITHOCKEY_USAGE_DATA @"BITUpdateManager.plist"
|
||||
|
||||
#define kBITHockeyMetaUserName @"BITHockeyMetaUserName"
|
||||
#define kBITHockeyMetaUserEmail @"BITHockeyMetaUserEmail"
|
||||
#define kBITHockeyMetaUserID @"BITHockeyMetaUserID"
|
||||
|
||||
#define kBITUpdateInstalledUUID @"BITUpdateInstalledUUID"
|
||||
#define kBITUpdateInstalledVersionID @"BITUpdateInstalledVersionID"
|
||||
#define kBITUpdateCurrentCompanyName @"BITUpdateCurrentCompanyName"
|
||||
|
@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'HockeySDK'
|
||||
s.version = '3.5.2'
|
||||
s.version = '3.5.3'
|
||||
|
||||
s.summary = 'Collect live crash reports, get feedback from your users, distribute your betas, and analyze your test coverage with HockeyApp.'
|
||||
s.description = <<-DESC
|
||||
@ -12,7 +12,7 @@ Pod::Spec.new do |s|
|
||||
DESC
|
||||
|
||||
s.homepage = 'http://hockeyapp.net/'
|
||||
s.documentation_url = 'http://hockeyapp.net/help/sdk/ios/3.5.2/'
|
||||
s.documentation_url = 'http://hockeyapp.net/help/sdk/ios/3.5.3/'
|
||||
|
||||
s.license = 'MIT'
|
||||
s.author = { 'Andreas Linde' => 'mail@andreaslinde.de', 'Thomas Dohmke' => "thomas@dohmke.de" }
|
||||
@ -24,7 +24,7 @@ Pod::Spec.new do |s|
|
||||
|
||||
s.frameworks = 'CoreText', 'QuartzCore', 'SystemConfiguration', 'CoreGraphics', 'UIKit', 'Security'
|
||||
s.ios.vendored_frameworks = 'Vendor/CrashReporter.framework'
|
||||
s.xcconfig = {'GCC_PREPROCESSOR_DEFINITIONS' => %{$(inherited) BITHOCKEY_VERSION="@\\"#{s.version}\\"" BITHOCKEY_BUILD="@\\"25\\""} }
|
||||
s.xcconfig = {'GCC_PREPROCESSOR_DEFINITIONS' => %{$(inherited) BITHOCKEY_VERSION="@\\"#{s.version}\\"" BITHOCKEY_BUILD="@\\"26\\""} }
|
||||
s.resource_bundle = { 'HockeySDKResources' => ['Resources/*.png', 'Resources/*.lproj'] }
|
||||
s.preserve_paths = 'Resources', 'Support'
|
||||
|
||||
|
14
README.md
14
README.md
@ -1,6 +1,6 @@
|
||||
## Version 3.5.2
|
||||
## Version 3.5.3
|
||||
|
||||
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.2/docs/docs/Changelog.html)
|
||||
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.3/docs/docs/Changelog.html)
|
||||
|
||||
|
||||
## Introduction
|
||||
@ -31,10 +31,10 @@ The main SDK class is `BITHockeyManager`. It initializes all modules and provide
|
||||
|
||||
## Installation & Setup
|
||||
|
||||
- [Installation & Setup](http://www.hockeyapp.net/help/sdk/ios/3.5.2/docs/docs/Guide-Installation-Setup.html) (Recommended)
|
||||
- [Installation & Setup Advanced](http://www.hockeyapp.net/help/sdk/ios/3.5.2/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.2/docs/docs/HowTo-Authenticating-Users-on-iOS.html)
|
||||
- [Migration from previous SDK Versions](http://www.hockeyapp.net/help/sdk/ios/3.5.2/docs/docs/Guide-Migration-Kits.html)
|
||||
- [Installation & Setup](http://www.hockeyapp.net/help/sdk/ios/3.5.3/docs/docs/Guide-Installation-Setup.html) (Recommended)
|
||||
- [Installation & Setup Advanced](http://www.hockeyapp.net/help/sdk/ios/3.5.3/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.3/docs/docs/HowTo-Authenticating-Users-on-iOS.html)
|
||||
- [Migration from previous SDK Versions](http://www.hockeyapp.net/help/sdk/ios/3.5.3/docs/docs/Guide-Migration-Kits.html)
|
||||
- [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`
|
||||
|
||||
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.2/](http://hockeyapp.net/help/sdk/ios/3.5.2/)
|
||||
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.3/](http://hockeyapp.net/help/sdk/ios/3.5.3/)
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "HockeySDK.xcconfig"
|
||||
|
||||
BUILD_NUMBER = 25
|
||||
VERSION_STRING = 3.5.2
|
||||
BUILD_NUMBER = 26
|
||||
VERSION_STRING = 3.5.3
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) BITHOCKEY_VERSION="@\""$(VERSION_STRING)"\"" BITHOCKEY_BUILD="@\""$(BUILD_NUMBER)"\""
|
||||
BIT_ARM_ARCHS = armv7 armv7s arm64
|
||||
BIT_SIM_ARCHS = x86_64 i386
|
||||
|
@ -1,3 +1,13 @@
|
||||
## Version 3.5.3
|
||||
|
||||
- [NEW] Crash Reports now provide the selector name e.g. for crashes in `objc_MsgSend`
|
||||
- [NEW] Add setter for global `userID`, `userName`, `userEmail`. Can be used instead of the delegates.
|
||||
- [UPDATE] On device symbolication is now optional, disabled by default
|
||||
- [BUGFIX] Fix for automatic authentication not always working correctly
|
||||
- [BUGFIX] `BITFeedbackComposeViewControllerDelegate` now also works for compose view controller used by the feedback list view
|
||||
- [BUGFIX] Fix typos in documentation
|
||||
<br /><br/>
|
||||
|
||||
## Version 3.5.2
|
||||
|
||||
- [UPDATE] Make sure a log message appears in the console if the SDK is not setup on the main thread
|
||||
|
@ -30,6 +30,8 @@ Previous versions of HockeySDK for iOS used the response of the method `UIDevice
|
||||
|
||||
The app opens Safari and asks the user to log in to his HockeyApp account.
|
||||
|
||||
The strategies **BITAuthenticatorIdentificationTypeDevice** and **BITAuthenticatorIdentificationTypeWebAuth** also allow for automatic authentication as explained [here](http://hockeyapp.net/blog/2014/01/31/automatic-authentication-ios.html).
|
||||
|
||||
After setting up one of those strategies, you need to trigger the authentication process by calling
|
||||
|
||||
[[BITHockeyManager sharedHockeyManager].authenticator authenticateInstallation];
|
||||
|
Loading…
x
Reference in New Issue
Block a user