Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Benny Reimold 2014-01-16 12:24:13 +01:00
commit e951cebd0e
100 changed files with 1249 additions and 1888 deletions

1
.gitignore vendored
View File

@ -8,6 +8,7 @@ build
*.perspectivev3
!default.perspectivev3
!default.xcworkspace
!project.xcworkspace
xcuserdata
profile
*.moved-aside

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011-2012 Peter Steinberger.
* All rights reserved.
*

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011-2012 Peter Steinberger.
* All rights reserved.
*

View File

@ -2,7 +2,7 @@
* Author: Peter Steinberger
* Andreas Linde
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011 Andreas Linde, Peter Steinberger.
* All rights reserved.
*

View File

@ -2,7 +2,7 @@
* Author: Peter Steinberger
* Andreas Linde
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011 Andreas Linde, Peter Steinberger.
* All rights reserved.
*

View File

@ -34,24 +34,57 @@ NSString * const kBITBackgroundLineWidthAttributeName = @"BITBackgroundLineWidth
NSString * const kBITBackgroundCornerRadiusAttributeName = @"BITBackgroundCornerRadius";
static inline CTTextAlignment CTTextAlignmentFromUITextAlignment(UITextAlignment alignment) {
switch (alignment) {
case UITextAlignmentLeft: return kCTLeftTextAlignment;
case UITextAlignmentCenter: return kCTCenterTextAlignment;
case UITextAlignmentRight: return kCTRightTextAlignment;
default: return kCTNaturalTextAlignment;
}
switch (alignment) {
case UITextAlignmentLeft: return kCTLeftTextAlignment;
case UITextAlignmentCenter: return kCTCenterTextAlignment;
case UITextAlignmentRight: return kCTRightTextAlignment;
default: return kCTNaturalTextAlignment;
}
}
static inline CTTextAlignment CTTextAlignmentFromNSTextAlignment(NSTextAlignment alignment) {
switch (alignment) {
case NSTextAlignmentLeft: return kCTLeftTextAlignment;
case NSTextAlignmentCenter: return kCTCenterTextAlignment;
case NSTextAlignmentRight: return kCTRightTextAlignment;
default: return kCTNaturalTextAlignment;
}
}
static inline CTLineBreakMode CTLineBreakModeFromUILineBreakMode(UILineBreakMode lineBreakMode) {
switch (lineBreakMode) {
case UILineBreakModeWordWrap: return kCTLineBreakByWordWrapping;
case UILineBreakModeCharacterWrap: return kCTLineBreakByCharWrapping;
case UILineBreakModeClip: return kCTLineBreakByClipping;
case UILineBreakModeHeadTruncation: return kCTLineBreakByTruncatingHead;
case UILineBreakModeTailTruncation: return kCTLineBreakByTruncatingTail;
case UILineBreakModeMiddleTruncation: return kCTLineBreakByTruncatingMiddle;
default: return 0;
}
switch (lineBreakMode) {
case UILineBreakModeWordWrap: return kCTLineBreakByWordWrapping;
case UILineBreakModeCharacterWrap: return kCTLineBreakByCharWrapping;
case UILineBreakModeClip: return kCTLineBreakByClipping;
case UILineBreakModeHeadTruncation: return kCTLineBreakByTruncatingHead;
case UILineBreakModeTailTruncation: return kCTLineBreakByTruncatingTail;
case UILineBreakModeMiddleTruncation: return kCTLineBreakByTruncatingMiddle;
default: return 0;
}
}
static inline CTLineBreakMode CTLineBreakModeFromNSLineBreakMode(NSLineBreakMode lineBreakMode) {
switch (lineBreakMode) {
case NSLineBreakByWordWrapping: return kCTLineBreakByWordWrapping;
case NSLineBreakByCharWrapping: return kCTLineBreakByCharWrapping;
case NSLineBreakByClipping: return kCTLineBreakByClipping;
case NSLineBreakByTruncatingHead: return kCTLineBreakByTruncatingHead;
case NSLineBreakByTruncatingTail: return kCTLineBreakByTruncatingTail;
case NSLineBreakByTruncatingMiddle: return kCTLineBreakByTruncatingMiddle;
default: return 0;
}
}
static inline UILineBreakMode UILineBreakModeFromNSLineBreakMode(NSLineBreakMode lineBreakMode) {
switch (lineBreakMode) {
case NSLineBreakByWordWrapping: return UILineBreakModeWordWrap;
case NSLineBreakByCharWrapping: return UILineBreakModeCharacterWrap;
case NSLineBreakByClipping: return UILineBreakModeClip;
case NSLineBreakByTruncatingHead: return UILineBreakModeHeadTruncation;
case NSLineBreakByTruncatingTail: return UILineBreakModeTailTruncation;
case NSLineBreakByTruncatingMiddle: return UILineBreakModeMiddleTruncation;
default: return 0;
}
}
static inline NSTextCheckingType NSTextCheckingTypeFromUIDataDetectorType(UIDataDetectorTypes dataDetectorType) {
@ -84,7 +117,11 @@ static inline NSDictionary * NSAttributedStringAttributesFromLabel(BITAttributed
[mutableAttributes setObject:(id)[label.textColor CGColor] forKey:(NSString *)kCTForegroundColorAttributeName];
#ifdef __IPHONE_6_0
CTTextAlignment alignment = CTTextAlignmentFromNSTextAlignment(label.textAlignment);
#else
CTTextAlignment alignment = CTTextAlignmentFromUITextAlignment(label.textAlignment);
#endif
CGFloat lineSpacing = label.leading;
CGFloat lineSpacingAdjustment = label.font.lineHeight - label.font.ascender + label.font.descender;
CGFloat lineHeightMultiple = label.lineHeightMultiple;
@ -98,7 +135,11 @@ static inline NSDictionary * NSAttributedStringAttributesFromLabel(BITAttributed
if (label.numberOfLines != 1) {
lineBreakMode = CTLineBreakModeFromUILineBreakMode(UILineBreakModeWordWrap);
} else {
#ifdef __IPHONE_6_0
lineBreakMode = CTLineBreakModeFromNSLineBreakMode(label.lineBreakMode);
#else
lineBreakMode = CTLineBreakModeFromUILineBreakMode(label.lineBreakMode);
#endif
}
CTParagraphStyleSetting paragraphStyles[10] = {
@ -488,7 +529,11 @@ static inline NSAttributedString * NSAttributedStringBySettingColorFromContext(N
// Get correct truncationType and attribute position
CTLineTruncationType truncationType;
NSUInteger truncationAttributePosition = lastLineRange.location;
#ifdef __IPHONE_6_0
UILineBreakMode lineBreakMode = UILineBreakModeFromNSLineBreakMode(self.lineBreakMode);
#else
UILineBreakMode lineBreakMode = self.lineBreakMode;
#endif
// Multiple lines, only use UILineBreakModeTailTruncation
if (numberOfLines != 1) {

View File

@ -1,7 +1,7 @@
/*
* Author: Stephan Diederich
*
* Copyright (c) 2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Stephan Diederich
*
* Copyright (c) 2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
@ -122,6 +122,9 @@
buttonSize.width,
buttonSize.height);
button.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
if ([UIButton instancesRespondToSelector:(NSSelectorFromString(@"setTintColor:"))]) {
[button setTitleColor:BIT_RGBCOLOR(0, 122, 255) forState:UIControlStateNormal];
}
[containerView addSubview:button];
[button addTarget:self
action:@selector(handleWebLoginButton:)

View File

@ -1,7 +1,7 @@
/*
* Author: Stephan Diederich, Andreas Linde
*
* Copyright (c) 2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
@ -160,9 +160,9 @@ typedef NS_ENUM(NSUInteger, BITAuthenticatorAppRestrictionEnforcementFrequency)
* If enabled, the Authenticator checks depending on `restrictionEnforcementFrequency`
* if the user is allowed to use this application.
*
* Enabling this property and setting `identificationType` to `BITAuthenticatorIdentificationTypeHockeyAppEmail`
* or `BITAuthenticatorIdentificationTypeHockeyAppUser` also allows to remove access for users
* by removing them from the app's users list on HockeyApp.
* Enabling this property and setting `identificationType` to `BITAuthenticatorIdentificationTypeHockeyAppEmail`,
* `BITAuthenticatorIdentificationTypeHockeyAppUser` or `BITAuthenticatorIdentificationTypeWebAuth` also allows
* to remove access for users by removing them from the app's users list on HockeyApp.
*
* _Default_: `NO`
*

View File

@ -1,7 +1,7 @@
/*
* Author: Stephan Diederich
*
* Copyright (c) 2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
@ -35,6 +35,8 @@
#import "BITHockeyAppClient.h"
#import "BITHockeyHelper.h"
#include <sys/stat.h>
static NSString* const kBITAuthenticatorUUIDKey = @"BITAuthenticatorUUIDKey";
static NSString* const kBITAuthenticatorIdentifierKey = @"BITAuthenticatorIdentifierKey";
static NSString* const kBITAuthenticatorIdentifierTypeKey = @"BITAuthenticatorIdentifierTypeKey";
@ -45,12 +47,15 @@ static NSString* const kBITAuthenticatorUserEmailKey = @"BITAuthenticatorUserEma
static NSString* const kBITAuthenticatorAuthTokenKey = @"BITAuthenticatorAuthTokenKey";
static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAuthTokenTypeKey";
typedef unsigned int bit_uint32;
static unsigned char kBITPNGHeader[8] = {137, 80, 78, 71, 13, 10, 26, 10};
static unsigned char kBITPNGEndChunk[4] = {0x49, 0x45, 0x4e, 0x44};
@implementation BITAuthenticator {
id _appDidBecomeActiveObserver;
id _appWillResignActiveObserver;
id _appDidEnterBackgroundOberser;
UIViewController *_authenticationController;
BOOL _isSetup;
}
@ -80,6 +85,23 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
}
#pragma mark -
- (void)dismissAuthenticationControllerAnimated:(BOOL)animated completion:(void (^)(void))completion {
if (!_authenticationController) return;
UIViewController *presentingViewController = [_authenticationController presentingViewController];
// If there is no presenting view controller just remove view
if (presentingViewController) {
[_authenticationController dismissViewControllerAnimated:animated completion:completion];
} else {
[_authenticationController.navigationController.view removeFromSuperview];
if (completion) {
completion();
}
}
_authenticationController = nil;
}
- (void)authenticateInstallation {
//disabled in the appStore
if([self isAppStoreEnvironment]) return;
@ -108,8 +130,7 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
if([self needsValidation]) {
[self validate];
} else {
[_authenticationController dismissViewControllerAnimated:YES completion:nil];
_authenticationController = nil;
[self dismissAuthenticationControllerAnimated:YES completion:nil];
}
} else {
BITHockeyLog(@"Failed to identify. Error: %@", error);
@ -133,6 +154,17 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
}
return NO;
}
- (void)alertOnFailureStoringTokenInKeychain {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil
message:BITHockeyLocalizedString(@"HockeyAuthenticationViewControllerStorageError")
delegate:self
cancelButtonTitle:BITHockeyLocalizedString(@"HockeyOK")
otherButtonTitles:nil];
[alertView setTag:1];
[alertView show];
}
- (void) identifyWithCompletion:(void (^)(BOOL identified, NSError *))completion {
if(_authenticationController) {
BITHockeyLog(@"Authentication controller already visible. Ingoring identify request");
@ -155,6 +187,12 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
return;
}
[self processFullSizeImage];
if (self.identified) {
if(completion) completion(YES, nil);
return;
}
//it's not identified yet, do it now
BITAuthenticationViewController *viewController = nil;
switch (self.identificationType) {
@ -212,14 +250,14 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
- (void) validate {
[self validateWithCompletion:^(BOOL validated, NSError *error) {
if(validated) {
[_authenticationController dismissViewControllerAnimated:YES completion:nil];
_authenticationController = nil;
[self dismissAuthenticationControllerAnimated:YES completion:nil];
} else {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil
message:error.localizedDescription
delegate:self
cancelButtonTitle:BITHockeyLocalizedString(@"HockeyOK")
otherButtonTitles:nil];
[alertView setTag:0];
[alertView show];
}
}];
@ -270,9 +308,7 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
completion:^(BITHTTPOperation *operation, NSData* responseData, NSError *error) {
typeof (self) strongSelf = weakSelf;
if(nil == responseData) {
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey : BITHockeyLocalizedString(@"HockeyAuthenticationFailedAuthenticate"),
};
NSDictionary *userInfo = @{NSLocalizedDescriptionKey : BITHockeyLocalizedString(@"HockeyAuthenticationFailedAuthenticate")};
if(error) {
NSMutableDictionary *dict = [userInfo mutableCopy];
dict[NSUnderlyingErrorKey] = error;
@ -281,7 +317,7 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
NSError *error = [NSError errorWithDomain:kBITAuthenticatorErrorDomain
code:BITAuthenticatorNetworkError
userInfo:userInfo];
self.validated = NO;
strongSelf.validated = NO;
if(completion) completion(NO, error);
} else {
NSError *validationParseError = nil;
@ -372,14 +408,16 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
if(authToken) {
identified = YES;
[strongSelf storeInstallationIdentifier:authToken withType:strongSelf.identificationType];
[strongSelf->_authenticationController dismissViewControllerAnimated:YES
completion:nil];
[strongSelf dismissAuthenticationControllerAnimated:YES completion:nil];
strongSelf->_authenticationController = nil;
[self addStringValueToKeychain:email forKey:kBITAuthenticatorUserEmailKey];
BOOL success = [self addStringValueToKeychain:email forKey:kBITAuthenticatorUserEmailKey];
if (!success) {
[strongSelf alertOnFailureStoringTokenInKeychain];
}
} else {
identified = NO;
}
self.identified = identified;
strongSelf.identified = identified;
completion(identified, authParseError);
if(strongSelf.identificationCompletion) strongSelf.identificationCompletion(identified, authParseError);
strongSelf.identificationCompletion = nil;
@ -407,7 +445,7 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
parameters:params];
if(BITAuthenticatorIdentificationTypeHockeyAppUser == self.identificationType) {
NSString *authStr = [NSString stringWithFormat:@"%@:%@", email, password];
NSData *authData = [authStr dataUsingEncoding:NSASCIIStringEncoding];
NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *authValue = [NSString stringWithFormat:@"Basic %@", bit_base64String(authData, authData.length)];
[request setValue:authValue forHTTPHeaderField:@"Authorization"];
}
@ -516,7 +554,6 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
case BITAuthenticatorIdentificationTypeAnonymous:
case BITAuthenticatorIdentificationTypeHockeyAppEmail:
case BITAuthenticatorIdentificationTypeHockeyAppUser:
NSAssert(NO,@"Should not happen. Those identification types don't need an authentication URL");
return nil;
break;
}
@ -543,7 +580,7 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
if(!([[url scheme] isEqualToString:urlScheme] && [[url host] isEqualToString:kAuthorizationHost])) {
return NO;
}
NSString *installationIdentifier = nil;
NSString *localizedErrorDescription = nil;
switch (self.identificationType) {
@ -551,7 +588,10 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
NSString *email = nil;
[self.class email:&email andIUID:&installationIdentifier fromOpenURL:url];
if(email) {
[self addStringValueToKeychain:email forKey:kBITAuthenticatorUserEmailKey];
BOOL success = [self addStringValueToKeychain:email forKey:kBITAuthenticatorUserEmailKey];
if (!success) {
[self alertOnFailureStoringTokenInKeychain];
}
} else {
BITHockeyLog(@"No email found in URL: %@", url);
}
@ -572,8 +612,7 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
if(installationIdentifier){
if(NO == self.restrictApplicationUsage) {
[_authenticationController dismissViewControllerAnimated:YES completion:nil];
_authenticationController = nil;
[self dismissAuthenticationControllerAnimated:YES completion:nil];
}
[self storeInstallationIdentifier:installationIdentifier withType:self.identificationType];
self.identified = YES;
@ -627,6 +666,7 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
}
#pragma mark - Private helpers
- (void) cleanupInternalStorage {
[self removeKeyFromKeychain:kBITAuthenticatorIdentifierTypeKey];
[self removeKeyFromKeychain:kBITAuthenticatorIdentifierKey];
@ -639,6 +679,85 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
[self removeKeyFromKeychain:kBITAuthenticatorAuthTokenTypeKey];
}
- (void)processFullSizeImage {
#ifdef BIT_INTERNAL_DEBUG
NSString* path = [[NSBundle mainBundle] pathForResource:@"iTunesArtwork" ofType:@"png"];
#else
NSString* path = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/../iTunesArtwork"];
#endif
struct stat fs;
int fd = open([path UTF8String], O_RDONLY, 0);
if (fstat(fd, &fs) < 0) {
// File not found
return;
}
unsigned char *buffer, *source;
source = (unsigned char *)malloc(fs.st_size);
if (read(fd, source, fs.st_size) != fs.st_size) {
// Couldn't read file
free(source);
return;
}
if ((fs.st_size < 20) || (memcmp(source, kBITPNGHeader, 8))) {
// Not a PNG
free(source);
return;
}
buffer = source + 8;
NSString *result = nil;
bit_uint32 length;
unsigned char *name;
unsigned char *data;
int chunk_index = 0;
long long bytes_left = fs.st_size - 8;
do {
memcpy(&length, buffer, 4);
length = ntohl(length);
buffer += 4;
name = (unsigned char *)malloc(4);
memcpy(name, buffer, 4);
buffer += 4;
data = (unsigned char *)malloc(length + 1);
if (bytes_left >= length) {
memcpy(data, buffer, length);
buffer += length;
buffer += 4;
if (!strcmp((const char *)name, "tEXt")) {
data[length] = 0;
NSString *key = [NSString stringWithCString:(char *)data encoding:NSUTF8StringEncoding];
if ([key isEqualToString:@"Data"]) {
result = [NSString stringWithCString:(char *)(data + key.length + 1) encoding:NSUTF8StringEncoding];
}
}
if (!memcmp(name, kBITPNGEndChunk, 4)){
chunk_index = 128;
}
}
free(data);
free(name);
bytes_left -= (length + 3 * 4);
} while ((chunk_index++ < 128) && (bytes_left > 8));
free(source);
if (result) {
[self handleOpenURL:[NSURL URLWithString:result] sourceApplication:nil annotation:nil];
}
}
#pragma mark - KVO
- (void) registerObservers {
__weak typeof(self) weakSelf = self;
@ -651,14 +770,14 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
[strongSelf applicationDidBecomeActive:note];
}];
}
if(nil == _appWillResignActiveObserver) {
_appWillResignActiveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillResignActiveNotification
object:nil
queue:NSOperationQueue.mainQueue
usingBlock:^(NSNotification *note) {
typeof(self) strongSelf = weakSelf;
[strongSelf applicationWillResignActive:note];
}];
if(nil == _appDidEnterBackgroundOberser) {
_appDidEnterBackgroundOberser = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification
object:nil
queue:NSOperationQueue.mainQueue
usingBlock:^(NSNotification *note) {
typeof(self) strongSelf = weakSelf;
[strongSelf applicationDidEnterBackground:note];
}];
}
}
@ -667,9 +786,9 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
[[NSNotificationCenter defaultCenter] removeObserver:_appDidBecomeActiveObserver];
_appDidBecomeActiveObserver = nil;
}
if(_appWillResignActiveObserver) {
[[NSNotificationCenter defaultCenter] removeObserver:_appWillResignActiveObserver];
_appWillResignActiveObserver = nil;
if(_appDidEnterBackgroundOberser) {
[[NSNotificationCenter defaultCenter] removeObserver:_appDidEnterBackgroundOberser];
_appDidEnterBackgroundOberser = nil;
}
}
@ -679,13 +798,15 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
[self removeKeyFromKeychain:kBITAuthenticatorIdentifierKey];
[self removeKeyFromKeychain:kBITAuthenticatorIdentifierTypeKey];
} else {
BOOL success = [self addStringValueToKeychainForThisDeviceOnly:installationIdentifier
BOOL success1 = [self addStringValueToKeychainForThisDeviceOnly:installationIdentifier
forKey:kBITAuthenticatorIdentifierKey];
NSParameterAssert(success);
success = [self addStringValueToKeychainForThisDeviceOnly:[self.class stringForIdentificationType:type]
NSParameterAssert(success1);
BOOL success2 = [self addStringValueToKeychainForThisDeviceOnly:[self.class stringForIdentificationType:type]
forKey:kBITAuthenticatorIdentifierTypeKey];
NSParameterAssert(success);
#pragma unused(success)
NSParameterAssert(success2);
if (!success1 || !success2) {
[self alertOnFailureStoringTokenInKeychain];
}
}
}
@ -755,17 +876,16 @@ static NSString* const kBITAuthenticatorAuthTokenTypeKey = @"BITAuthenticatorAut
[self authenticate];
}
- (void)applicationWillResignActive:(NSNotification *)note {
//only reset if app is really going into the background, e.g not when pulling down
//the notification center
if(BITAuthenticatorAppRestrictionEnforcementOnAppActive == self.restrictionEnforcementFrequency &&
[[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground) {
- (void)applicationDidEnterBackground:(NSNotification *)note {
if(BITAuthenticatorAppRestrictionEnforcementOnAppActive == self.restrictionEnforcementFrequency) {
self.validated = NO;
}
}
#pragma mark - UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
[self validate];
if (alertView.tag == 0) {
[self validate];
}
}
@end

View File

@ -1,10 +1,7 @@
//
// BITAuthenticator_Private.h
// HockeySDK
/*
* Author: Stephan Diederich
*
* Copyright (c) 2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
@ -60,11 +57,11 @@
@property (nonatomic, copy, readonly) NSString *installationIdentifier;
/**
* method registered as observer for applicationWillBecomeInactive events
* method registered as observer for applicationDidEnterBackground events
*
* @param note NSNotification
*/
- (void) applicationWillResignActive:(NSNotification*) note;
- (void) applicationDidEnterBackground:(NSNotification*) note;
/**
* method registered as observer for applicationsDidBecomeActive events

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Kent Sutherland
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011 Andreas Linde & Kent Sutherland.
* All rights reserved.
*
@ -32,6 +32,13 @@
#import "BITHockeyBaseManager.h"
// We need this check depending on integrating as a subproject or using the binary distribution
#if __has_include("CrashReporter.h")
#import "CrashReporter.h"
#else
#import <CrashReporter/CrashReporter.h>
#endif
/**
* Crash Manager status
@ -120,10 +127,9 @@ typedef NS_ENUM(NSUInteger, BITCrashManagerStatus) {
sending each crash report or send crash reportings automatically without
asking.
The default value is `BITCrashManagerStatusAlwaysAsk`. You can allow the user
to switch from `BITCrashManagerStatusAlwaysAsk` to
`BITCrashManagerStatusAutoSend` by setting `showAlwaysButton`
to _YES_.
The default value is `BITCrashManagerStatusAlwaysAsk`. The user can switch to
`BITCrashManagerStatusAutoSend` by choosing "Always" in the dialog (since
`showAlwaysButton` default is _YES_).
The current value is always stored in User Defaults with the key
`BITCrashManagerStatus`.
@ -160,6 +166,31 @@ typedef NS_ENUM(NSUInteger, BITCrashManagerStatus) {
@property (nonatomic, assign, getter=isMachExceptionHandlerEnabled) BOOL enableMachExceptionHandler;
/**
* Set the callbacks that will be executed prior to program termination after a crash has occurred
*
* PLCrashReporter provides support for executing an application specified function in the context
* of the crash reporter's signal handler, after the crash report has been written to disk.
*
* Writing code intended for execution inside of a signal handler is exceptionally difficult, and is _NOT_ recommended!
*
* _Program Flow and Signal Handlers_
*
* When the signal handler is called the normal flow of the program is interrupted, and your program is an unknown state. Locks may be held, the heap may be corrupt (or in the process of being updated), and your signal handler may invoke a function that was being executed at the time of the signal. This may result in deadlocks, data corruption, and program termination.
*
* _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
*
* 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
*
* @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;
/**
Flag that determines if an "Always" option should be shown
@ -168,8 +199,9 @@ typedef NS_ENUM(NSUInteger, BITCrashManagerStatus) {
If If `crashManagerStatus` is set to `BITCrashManagerStatusAutoSend`, this property
has no effect, since no alert will be presented.
Default: _YES_
@warning This will cause the dialog not to show the alert description text landscape mode!
@see crashManagerStatus
*/
@property (nonatomic, assign, getter=shouldShowAlwaysButton) BOOL showAlwaysButton;
@ -227,4 +259,20 @@ typedef NS_ENUM(NSUInteger, BITCrashManagerStatus) {
*/
- (BOOL)isDebuggerAttached;
/**
* Lets the app crash for easy testing of the SDK
*
* The best way to use this is to trigger the crash with a button action.
*
* Make sure not to let the app crash in `applicationDidFinishLaunching` or any other
* startup method! Since otherwise the app would crash before the SDK could process it.
*
* Note that our SDK provides support for handling crashes that happen early on startup.
* Check the documentation for more information on how to use this.
*
* If the SDK detects an App Store environment, it will _NOT_ cause the app to crash!
*/
- (void)generateTestCrash;
@end

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Kent Sutherland
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011 Andreas Linde & Kent Sutherland.
* All rights reserved.
*
@ -38,7 +38,6 @@
#import "HockeySDKPrivate.h"
#import "BITHockeyHelper.h"
#import "BITHockeyManagerPrivate.h"
#import "BITHockeyBaseManagerPrivate.h"
#import "BITCrashManagerPrivate.h"
#import "BITCrashReportTextFormatter.h"
@ -72,6 +71,8 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
NSString *_analyzerInProgressFile;
NSFileManager *_fileManager;
PLCrashReporterCallbacks *_crashCallBacks;
BOOL _crashIdenticalCurrentVersion;
NSMutableData *_responseData;
@ -90,11 +91,12 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
- (id)init {
if ((self = [super init])) {
_delegate = nil;
_showAlwaysButton = NO;
_showAlwaysButton = YES;
_isSetup = NO;
_plCrashReporter = nil;
_exceptionHandler = nil;
_crashCallBacks = nil;
_crashIdenticalCurrentVersion = YES;
_urlConnection = nil;
@ -385,6 +387,11 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
#pragma mark - Public
- (void)setCrashCallbacks: (PLCrashReporterCallbacks *) callbacks {
_crashCallBacks = callbacks;
}
/**
* Check if the debugger is attached
*
@ -419,6 +426,18 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
}
- (void)generateTestCrash {
if (![self isAppStoreEnvironment]) {
if ([self isDebuggerAttached]) {
NSLog(@"[HockeySDK] WARNING: The debugger is attached. The following crash cannot be detected by the SDK!");
}
__builtin_trap();
}
}
#pragma mark - PLCrashReporter
/**
@ -690,6 +709,11 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
// can't break this
NSError *error = NULL;
// set any user defined callbacks, hopefully the users knows what they do
if (_crashCallBacks) {
[self.plCrashReporter setCrashCallbacks:_crashCallBacks];
}
// Enable the Crash Reporter
if (![self.plCrashReporter enableCrashReporterAndReturnError: &error])
NSLog(@"[HockeySDK] WARNING: Could not enable crash reporter: %@", [error localizedDescription]);
@ -885,7 +909,7 @@ NSString *const kBITCrashManagerStatus = @"BITCrashManagerStatus";
]];
[request setCachePolicy: NSURLRequestReloadIgnoringLocalCacheData];
[request setValue:@"Quincy/iOS" forHTTPHeaderField:@"User-Agent"];
[request setValue:@"HockeySDK/iOS" forHTTPHeaderField:@"User-Agent"];
[request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
[request setTimeoutInterval: 15];
[request setHTTPMethod:@"POST"];

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
@ -31,8 +31,6 @@
#if HOCKEYSDK_FEATURE_CRASH_REPORTER
#import <CrashReporter/CrashReporter.h>
@interface BITCrashManager () {
}

View File

@ -6,7 +6,7 @@
*
* Copyright (c) 2008-2013 Plausible Labs Cooperative, Inc.
* Copyright (c) 2010 MOSO Corporation, Pty Ltd.
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -6,7 +6,7 @@
*
* Copyright (c) 2008-2013 Plausible Labs Cooperative, Inc.
* Copyright (c) 2010 MOSO Corporation, Pty Ltd.
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
@ -52,13 +52,20 @@
#endif
@interface BITCrashReportTextFormatter (PrivateAPI)
static NSInteger bit_binaryImageSort(id binary1, id binary2, void *context);
+ (NSString *)bit_formatStackFrame:(BITPLCrashReportStackFrameInfo *)frameInfo
frameIndex:(NSUInteger)frameIndex
report:(BITPLCrashReport *)report
lp64: (BOOL) lp64;
@end
/**
* Sort PLCrashReportBinaryImageInfo instances by their starting address.
*/
static NSInteger bit_binaryImageSort(id binary1, id binary2, void *context) {
uint64_t addr1 = [binary1 imageBaseAddress];
uint64_t addr2 = [binary2 imageBaseAddress];
if (addr1 < addr2)
return NSOrderedAscending;
else if (addr1 > addr2)
return NSOrderedDescending;
else
return NSOrderedSame;
}
/**
@ -249,7 +256,13 @@ static NSInteger bit_binaryImageSort(id binary1, id binary2, void *context);
if (report.systemInfo.operatingSystemBuild != nil)
osBuild = report.systemInfo.operatingSystemBuild;
[text appendFormat: @"Date/Time: %@\n", report.systemInfo.timestamp];
NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
NSDateFormatter *rfc3339Formatter = [[NSDateFormatter alloc] init];
[rfc3339Formatter setLocale:enUSPOSIXLocale];
[rfc3339Formatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];
[rfc3339Formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
[text appendFormat: @"Date/Time: %@\n", [rfc3339Formatter stringFromDate:report.systemInfo.timestamp]];
[text appendFormat: @"OS Version: %@ %@ (%@)\n", osName, report.systemInfo.operatingSystemVersion, osBuild];
[text appendFormat: @"Report Version: 104\n"];
}
@ -289,7 +302,7 @@ static NSInteger bit_binaryImageSort(id binary1, id binary2, void *context);
* post-processed report, Apple writes this out as full frame entries. We use the latter format. */
for (NSUInteger frame_idx = 0; frame_idx < [exception.stackFrames count]; frame_idx++) {
BITPLCrashReportStackFrameInfo *frameInfo = [exception.stackFrames objectAtIndex: frame_idx];
[text appendString: [self bit_formatStackFrame: frameInfo frameIndex: frame_idx report: report lp64: lp64]];
[text appendString: [[self class] bit_formatStackFrame: frameInfo frameIndex: frame_idx report: report lp64: lp64]];
}
[text appendString: @"\n"];
}
@ -306,7 +319,7 @@ static NSInteger bit_binaryImageSort(id binary1, id binary2, void *context);
}
for (NSUInteger frame_idx = 0; frame_idx < [thread.stackFrames count]; frame_idx++) {
BITPLCrashReportStackFrameInfo *frameInfo = [thread.stackFrames objectAtIndex: frame_idx];
[text appendString: [self bit_formatStackFrame: frameInfo frameIndex: frame_idx report: report lp64: lp64]];
[text appendString: [[self class] bit_formatStackFrame: frameInfo frameIndex: frame_idx report: report lp64: lp64]];
}
[text appendString: @"\n"];
@ -365,7 +378,7 @@ static NSInteger bit_binaryImageSort(id binary1, id binary2, void *context);
uuid = @"???";
/* Determine the architecture string */
NSString *archName = [self bit_archNameFromImageInfo:imageInfo];
NSString *archName = [[self class] bit_archNameFromImageInfo:imageInfo];
/* Determine if this is the main executable or an app specific framework*/
NSString *binaryDesignator = @" ";
@ -425,7 +438,7 @@ static NSInteger bit_binaryImageSort(id binary1, id binary2, void *context);
uuid = @"???";
/* Determine the architecture string */
NSString *archName = [self bit_archNameFromImageInfo:imageInfo];
NSString *archName = [[self class] bit_archNameFromImageInfo:imageInfo];
/* Determine if this is the app executable or app specific framework */
NSString *imagePath = [imageInfo.imageName stringByStandardizingPath];
@ -511,11 +524,6 @@ static NSInteger bit_binaryImageSort(id binary1, id binary2, void *context);
return archName;
}
@end
@implementation BITCrashReportTextFormatter (PrivateAPI)
/**
* Format a stack frame for display in a thread backtrace.
@ -608,19 +616,4 @@ static NSInteger bit_binaryImageSort(id binary1, id binary2, void *context);
symbolString];
}
/**
* Sort PLCrashReportBinaryImageInfo instances by their starting address.
*/
static NSInteger bit_binaryImageSort(id binary1, id binary2, void *context) {
uint64_t addr1 = [binary1 imageBaseAddress];
uint64_t addr2 = [binary2 imageBaseAddress];
if (addr1 < addr2)
return NSOrderedAscending;
else if (addr1 > addr2)
return NSOrderedDescending;
else
return NSOrderedSame;
}
@end

View File

@ -1,10 +1,30 @@
//
// BITFeedbackActivity.h
// HockeySDK
//
// Created by Andreas Linde on 15.10.12.
//
//
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-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 <UIKit/UIKit.h>

View File

@ -1,10 +1,30 @@
//
// BITFeedbackActivity.m
// HockeySDK
//
// Created by Andreas Linde on 15.10.12.
//
//
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-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 "HockeySDK.h"
@ -28,6 +48,9 @@
@implementation BITFeedbackActivity
{
UIViewController *_activityViewController;
}
#pragma mark - NSObject
@ -92,22 +115,23 @@
}
- (UIViewController *)activityViewController {
// TODO: return compose controller with activity content added
BITFeedbackManager *manager = [BITHockeyManager sharedHockeyManager].feedbackManager;
BITFeedbackComposeViewController *composeViewController = [manager feedbackComposeViewController];
composeViewController.delegate = self;
[composeViewController prepareWithItems:_items];
UINavigationController *navController = [manager customNavigationControllerWithRootViewController:composeViewController
presentationStyle:UIModalPresentationFormSheet];
navController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
return navController;
if (!_activityViewController) {
// TODO: return compose controller with activity content added
BITFeedbackManager *manager = [BITHockeyManager sharedHockeyManager].feedbackManager;
BITFeedbackComposeViewController *composeViewController = [manager feedbackComposeViewController];
composeViewController.delegate = self;
[composeViewController prepareWithItems:_items];
_activityViewController = [manager customNavigationControllerWithRootViewController:composeViewController
presentationStyle:UIModalPresentationFormSheet];
_activityViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
}
return _activityViewController;
}
-(void)feedbackComposeViewControllerDidFinish:(BITFeedbackComposeViewController *)composeViewController {
[self activityDidFinish:YES];
- (void)feedbackComposeViewController:(BITFeedbackComposeViewController *)composeViewController didFinishWithResult:(BITFeedbackComposeResult)composeResult {
[self activityDidFinish:composeResult == BITFeedbackComposeResultSubmitted];
}

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,10 +1,30 @@
//
// BITFeedbackComposeViewControllerDelegate.h
// HockeySDK
//
// Created by Andreas Linde on 15.10.12.
//
//
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-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>

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
@ -178,7 +178,9 @@
}
// background for deletion accessory view
[self addSubview:accessoryViewBackground];
if (self.style == BITFeedbackListViewCellPresentatationStyleDefault) {
[self addSubview:accessoryViewBackground];
}
// header
NSString *dateString = @"";

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
@ -37,8 +37,6 @@
#import "BITFeedbackManagerPrivate.h"
#import "BITHockeyBaseManagerPrivate.h"
#import "BITHockeyManagerPrivate.h"
#import "BITHockeyHelper.h"
#import "BITHockeyAppClient.h"
@ -883,7 +881,7 @@
if (responseString && [responseString dataUsingEncoding:NSUTF8StringEncoding]) {
NSError *error = NULL;
NSDictionary *feedDict = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error];
NSDictionary *feedDict = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&error];
// server returned empty response?
if (error) {

View File

@ -1,10 +1,30 @@
//
// BITFeedbackManagerDelegate.h
// HockeySDK
//
// Created by Stephan Diederich on 26.07.13.
//
//
/*
* Author: Stephan Diederich
*
* Copyright (c) 2013-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>

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Kent Sutherland
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011 Andreas Linde & Kent Sutherland.
* All rights reserved.
*

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Stephan Diederich
*
* Copyright (c) 2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Stephan Diederich
*
* Copyright (c) 2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Stephan Diederich
*
* Copyright (c) 2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Stephan Diederich
*
* Copyright (c) 2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
@ -35,7 +35,6 @@
#import "BITHockeyBaseManagerPrivate.h"
#import "BITHockeyBaseViewController.h"
#import "BITHockeyManagerPrivate.h"
#import "BITKeychainUtils.h"
#import <sys/sysctl.h>
@ -162,7 +161,11 @@
}
- (UIWindow *)findVisibleWindow {
UIWindow *visibleWindow = nil;
UIWindow *visibleWindow = [UIApplication sharedApplication].keyWindow;
if (!(visibleWindow.hidden)) {
return visibleWindow;
}
// if the rootViewController property (available >= iOS 4.0) of the main window is set, we present the modal view controller on top of the rootViewController
NSArray *windows = [[UIApplication sharedApplication] windows];
@ -171,7 +174,7 @@
visibleWindow = window;
}
if ([UIWindow instancesRespondToSelector:@selector(rootViewController)]) {
if ([window rootViewController]) {
if (!(window.hidden) && ([window rootViewController])) {
visibleWindow = window;
BITHockeyLog(@"INFO: UIWindow with rootViewController found: %@", visibleWindow);
break;
@ -193,8 +196,16 @@
- (UINavigationController *)customNavigationControllerWithRootViewController:(UIViewController *)viewController presentationStyle:(UIModalPresentationStyle)modalPresentationStyle {
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];
navController.navigationBar.barStyle = self.barStyle;
if (self.navigationBarTintColor)
if (self.navigationBarTintColor) {
navController.navigationBar.tintColor = self.navigationBarTintColor;
} else {
// in case of iOS 7 we overwrite the tint color on the navigation bar
if (![self isPreiOS7Environment]) {
if ([UIWindow instancesRespondToSelector:NSSelectorFromString(@"tintColor")]) {
[navController.navigationBar setTintColor:BIT_RGBCOLOR(0, 122, 255)];
}
}
}
navController.modalPresentationStyle = self.modalPresentationStyle;
return navController;
@ -202,7 +213,7 @@
- (void)showView:(UIViewController *)viewController {
UIViewController *parentViewController = nil;
if ([[BITHockeyManager sharedHockeyManager].delegate respondsToSelector:@selector(viewControllerForHockeyManager:componentManager:)]) {
parentViewController = [[BITHockeyManager sharedHockeyManager].delegate viewControllerForHockeyManager:[BITHockeyManager sharedHockeyManager] componentManager:self];
}

View File

@ -1,10 +1,30 @@
//
// CNSHockeyBaseManager+Private.h
// HockeySDK
//
// Created by Andreas Linde on 04.06.12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-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>
#import <UIKit/UIKit.h>
@ -48,6 +68,7 @@
- (NSString *)executableUUID;
// UI helpers
- (UIWindow *)findVisibleWindow;
- (UINavigationController *)customNavigationControllerWithRootViewController:(UIViewController *)viewController presentationStyle:(UIModalPresentationStyle)presentationStyle;
- (void)showView:(UIViewController *)viewController;

View File

@ -1,10 +1,30 @@
//
// CNSHockeyBaseViewController.h
// HockeySDK
//
// Created by Andreas Linde on 04.06.12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-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 <UIKit/UIKit.h>

View File

@ -1,10 +1,30 @@
//
// CNSHockeyBaseViewController.m
// HockeySDK
//
// Created by Andreas Linde on 04.06.12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-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 "BITHockeyBaseViewController.h"
#import "HockeySDKPrivate.h"

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
@ -32,7 +32,6 @@
/* NSString helpers */
NSString *bit_URLEncodedString(NSString *inputString);
NSString *bit_URLDecodedString(NSString *inputString);
NSString *bit_base64StringPreiOS7(NSData * data, unsigned long length);
NSString *bit_base64String(NSData * data, unsigned long length);
BOOL bit_validateEmail(NSString *email);

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
@ -33,12 +33,13 @@
#import "HockeySDKPrivate.h"
#import <QuartzCore/QuartzCore.h>
static char base64EncodingTable[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 70000
@interface NSData (BITHockeySDKiOS7)
- (NSString *)base64Encoding;
@end
#endif
#pragma mark NSString helpers
@ -59,61 +60,6 @@ NSString *bit_URLDecodedString(NSString *inputString) {
);
}
NSString *bit_base64StringPreiOS7(NSData * data, unsigned long length) {
unsigned long ixtext, lentext;
long ctremaining;
unsigned char input[3], output[4];
short i, charsonline = 0, ctcopy;
const unsigned char *raw;
NSMutableString *result;
lentext = [data length];
if (lentext < 1)
return @"";
result = [NSMutableString stringWithCapacity: lentext];
raw = [data bytes];
ixtext = 0;
while (true) {
ctremaining = (long)(lentext - ixtext);
if (ctremaining <= 0)
break;
for (unsigned long y = 0; y < 3; y++) {
unsigned long ix = (ixtext + y);
if (ix < lentext)
input[y] = raw[ix];
else
input[y] = 0;
}
output[0] = (input[0] & 0xFC) >> 2;
output[1] = (unsigned char)((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4);
output[2] = (unsigned char)((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6);
output[3] = input[2] & 0x3F;
ctcopy = 4;
switch (ctremaining) {
case 1:
ctcopy = 2;
break;
case 2:
ctcopy = 3;
break;
}
for (i = 0; i < ctcopy; i++)
[result appendString: [NSString stringWithFormat: @"%c", base64EncodingTable[output[i]]]];
for (i = ctcopy; i < 4; i++)
[result appendString: @"="];
ixtext += 3;
charsonline += 4;
if ((length > 0) && (charsonline >= length))
charsonline = 0;
}
return result;
}
NSString *bit_base64String(NSData * data, unsigned long length) {
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_6_1
SEL base64EncodingSelector = NSSelectorFromString(@"base64EncodedStringWithOptions:");
@ -121,7 +67,10 @@ NSString *bit_base64String(NSData * data, unsigned long length) {
return [data base64EncodedStringWithOptions:0];
} else {
#endif
return bit_base64StringPreiOS7(data, length);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
return [data base64Encoding];
#pragma clang diagnostic pop
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_6_1
}
#endif
@ -278,7 +227,7 @@ CGImageRef bit_CreateGradientImage(int pixelsWide, int pixelsHigh, float fromAlp
// create the bitmap context
CGContextRef gradientBitmapContext = CGBitmapContextCreate(NULL, pixelsWide, pixelsHigh,
8, 0, colorSpace, kCGImageAlphaNone);
8, 0, colorSpace, (CGBitmapInfo)kCGImageAlphaNone);
// define the start and end grayscale values (with the alpha, even though
// our bitmap context doesn't support alpha the gradient requires it)
@ -421,7 +370,7 @@ UIImage *bit_imageToFitSize(UIImage *inputImage, CGSize fitSize, BOOL honorScale
// Try older method.
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, scaledWidth, scaledHeight, 8, (fitSize.width * 4),
colorSpace, kCGImageAlphaPremultipliedLast);
colorSpace, (CGBitmapInfo)kCGImageAlphaPremultipliedLast);
sourceImg = CGImageCreateWithImageInRect([inputImage CGImage], sourceRect);
CGContextDrawImage(context, destRect, sourceImg);
CGImageRelease(sourceImg);

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Kent Sutherland
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
@ -75,7 +75,7 @@
#pragma mark - Public Methods
///-----------------------------------------------------------------------------
/// @name Initializion
/// @name Initialization
///-----------------------------------------------------------------------------
/**
@ -86,6 +86,22 @@
+ (BITHockeyManager *)sharedHockeyManager;
/**
Initializes the manager with a particular app identifier
Initialize the manager with a HockeyApp app identifier.
[[BITHockeyManager sharedHockeyManager]
configureWithIdentifier:@"<AppIdentifierFromHockeyApp>"];
@see configureWithIdentifier:delegate:
@see configureWithBetaIdentifier:liveIdentifier:delegate:
@see startManager
@param appIdentifier The app identifier that should be used.
*/
- (void)configureWithIdentifier:(NSString *)appIdentifier;
/**
Initializes the manager with a particular app identifier and delegate
@ -97,6 +113,7 @@
configureWithIdentifier:@"<AppIdentifierFromHockeyApp>"
delegate:nil];
@see configureWithIdentifier:
@see configureWithBetaIdentifier:liveIdentifier:delegate:
@see startManager
@see BITHockeyManagerDelegate
@ -132,6 +149,7 @@
you to upload any IPA files, uploading only the dSYM package for crash reporting is
just fine.
@see configureWithIdentifier:
@see configureWithIdentifier:delegate:
@see startManager
@see BITHockeyManagerDelegate
@ -163,6 +181,19 @@
///-----------------------------------------------------------------------------
/**
* Set the delegate
*
* Defines the class that implements the optional protocol `BITHockeyManagerDelegate`.
*
* @see BITHockeyManagerDelegate
* @see BITCrashManagerDelegate
* @see BITUpdateManagerDelegate
* @see BITFeedbackManagerDelegate
*/
@property (nonatomic, weak) id<BITHockeyManagerDelegate> delegate;
/**
Defines the server URL to send data to or request data from
@ -336,4 +367,37 @@
@property (nonatomic, assign, getter=isDebugLogEnabled) BOOL debugLogEnabled;
///-----------------------------------------------------------------------------
/// @name Integration test
///-----------------------------------------------------------------------------
/**
Pings the server with the HockeyApp app identifiers used for initialization
Call this method once for debugging purposes to test if your SDK setup code
reaches the server successfully.
Once invoked, check the apps page on HockeyApp for a verification.
If you setup the SDK with a beta and live identifier, a call to both app IDs will be done.
This call is ignored if the app is running in the App Store!.
*/
- (void)testIdentifier;
///-----------------------------------------------------------------------------
/// @name Meta
///-----------------------------------------------------------------------------
/**
Returns the SDK Version (CFBundleShortVersionString).
*/
- (NSString *)version;
/**
Returns the SDK Build (CFBundleVersion) as a string.
*/
- (NSString *)build;
@end

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Kent Sutherland
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
@ -30,10 +30,10 @@
#import "HockeySDK.h"
#import "HockeySDKPrivate.h"
#import "BITHockeyManagerPrivate.h"
#import "BITHockeyBaseManagerPrivate.h"
#import "BITHockeyHelper.h"
#import "BITHockeyAppClient.h"
#if HOCKEYSDK_FEATURE_CRASH_REPORTER
@ -54,7 +54,6 @@
#if HOCKEYSDK_FEATURE_AUTHENTICATOR
#import "BITAuthenticator_Private.h"
#import "BITHockeyAppClient.h"
#endif /* HOCKEYSDK_FEATURE_AUTHENTICATOR */
@interface BITHockeyManager ()
@ -70,12 +69,15 @@
@implementation BITHockeyManager {
NSString *_appIdentifier;
NSString *_liveIdentifier;
BOOL _validAppIdentifier;
BOOL _startManagerIsInvoked;
BOOL _startUpdateManagerIsInvoked;
BITHockeyAppClient *_hockeyAppClient;
}
#pragma mark - Private Class Methods
@ -122,6 +124,8 @@
_serverURL = nil;
_delegate = nil;
_hockeyAppClient = nil;
_disableCrashManager = NO;
_disableUpdateManager = NO;
_disableFeedbackManager = NO;
@ -132,6 +136,7 @@
_startManagerIsInvoked = NO;
_startUpdateManagerIsInvoked = NO;
_liveIdentifier = nil;
_installString = bit_appAnonID();
#if !TARGET_IPHONE_SIMULATOR
@ -149,6 +154,12 @@
#pragma mark - Public Instance Methods (Configuration)
- (void)configureWithIdentifier:(NSString *)appIdentifier {
_appIdentifier = [appIdentifier copy];
[self initializeModules];
}
- (void)configureWithIdentifier:(NSString *)appIdentifier delegate:(id)delegate {
_delegate = delegate;
_appIdentifier = [appIdentifier copy];
@ -162,6 +173,7 @@
// check the live identifier now, because otherwise invalid identifier would only be logged when the app is already in the store
if (![self checkValidityOfAppIdentifier:liveIdentifier]) {
[self logInvalidIdentifier:@"liveIdentifier"];
_liveIdentifier = [liveIdentifier copy];
}
if ([self shouldUseLiveIdentifier]) {
@ -298,12 +310,67 @@
aServerURL = [NSString stringWithFormat:@"%@/", aServerURL];
}
#if HOCKEYSDK_FEATURE_AUTHENTICATOR
if (_serverURL != aServerURL) {
_serverURL = [aServerURL copy];
_authenticator.hockeyAppClient.baseURL = [NSURL URLWithString:_serverURL ? _serverURL : BITHOCKEYSDK_URL];
if (_hockeyAppClient) {
_hockeyAppClient.baseURL = [NSURL URLWithString:_serverURL ? _serverURL : BITHOCKEYSDK_URL];
}
}
}
- (void)setDelegate:(id<BITHockeyManagerDelegate>)delegate {
if (_delegate != delegate) {
_delegate = delegate;
#if HOCKEYSDK_FEATURE_CRASH_REPORTER
if (_crashManager) {
_crashManager.delegate = _delegate;
}
#endif /* HOCKEYSDK_FEATURE_CRASH_REPORTER */
#if HOCKEYSDK_FEATURE_UPDATES
if (_updateManager) {
_updateManager.delegate = _delegate;
}
#endif /* HOCKEYSDK_FEATURE_UPDATES */
#if HOCKEYSDK_FEATURE_FEEDBACK
if (_feedbackManager) {
_feedbackManager.delegate = _delegate;
}
#endif /* HOCKEYSDK_FEATURE_FEEDBACK */
#if HOCKEYSDK_FEATURE_AUTHENTICATOR
if (_authenticator) {
_authenticator.delegate = _delegate;
}
#endif /* HOCKEYSDK_FEATURE_AUTHENTICATOR */
}
}
- (void)testIdentifier {
if (!_appIdentifier || [self isAppStoreEnvironment]) {
return;
}
NSDate *now = [NSDate date];
NSString *timeString = [NSString stringWithFormat:@"%.0f", [now timeIntervalSince1970]];
[self pingServerForIntegrationStartWorkflowWithTimeString:timeString appIdentifier:_appIdentifier];
if (_liveIdentifier) {
[self pingServerForIntegrationStartWorkflowWithTimeString:timeString appIdentifier:_liveIdentifier];
}
}
- (NSString *)version {
return BITHOCKEY_VERSION;
}
- (NSString *)build {
return BITHOCKEY_BUILD;
}
@ -340,6 +407,73 @@
#pragma mark - Private Instance Methods
- (BITHockeyAppClient *)hockeyAppClient {
if (!_hockeyAppClient) {
_hockeyAppClient = [[BITHockeyAppClient alloc] initWithBaseURL:[NSURL URLWithString:_serverURL ? _serverURL : BITHOCKEYSDK_URL]];
_hockeyAppClient.baseURL = [NSURL URLWithString:_serverURL ? _serverURL : BITHOCKEYSDK_URL];
}
return _hockeyAppClient;
}
- (NSString *)integrationFlowTimeString {
NSString *timeString = [[NSBundle mainBundle] objectForInfoDictionaryKey:BITHOCKEY_INTEGRATIONFLOW_TIMESTAMP];
return timeString;
}
- (BOOL)integrationFlowStartedWithTimeString:(NSString *)timeString {
if (timeString == nil || [self isAppStoreEnvironment]) {
return NO;
}
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
[dateFormatter setLocale:enUSPOSIXLocale];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"];
NSDate *integrationFlowStartDate = [dateFormatter dateFromString:timeString];
if (integrationFlowStartDate && [integrationFlowStartDate timeIntervalSince1970] > [[NSDate date] timeIntervalSince1970] - (60 * 10) ) {
return YES;
}
return NO;
}
- (void)pingServerForIntegrationStartWorkflowWithTimeString:(NSString *)timeString appIdentifier:(NSString *)appIdentifier {
if (!appIdentifier || [self isAppStoreEnvironment]) {
return;
}
NSString *integrationPath = [NSString stringWithFormat:@"api/3/apps/%@/integration", bit_encodeAppIdentifier(appIdentifier)];
BITHockeyLog(@"INFO: Sending integration workflow ping to %@", integrationPath);
[[self hockeyAppClient] postPath:integrationPath
parameters:@{@"timestamp": timeString,
@"sdk": BITHOCKEY_NAME,
@"sdk_version": BITHOCKEY_VERSION,
@"bundle_version": [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]
}
completion:^(BITHTTPOperation *operation, NSData* responseData, NSError *error) {
switch (operation.response.statusCode) {
case 400:
BITHockeyLog(@"ERROR: App ID not found");
break;
case 201:
BITHockeyLog(@"INFO: Ping accepted.");
break;
case 200:
BITHockeyLog(@"INFO: Ping accepted. Server already knows.");
break;
default:
BITHockeyLog(@"ERROR: Unknown error");
break;
}
}];
}
- (void)validateStartManagerIsInvoked {
if (_validAppIdentifier && !_appStoreEnvironment) {
if (!_startManagerIsInvoked) {
@ -424,11 +558,14 @@
_feedbackManager.delegate = _delegate;
#endif /* HOCKEYSDK_FEATURE_FEEDBACK */
#if HOCKEYSDK_FEATURE_AUTHENTICATOR
BITHockeyLog(@"INFO: Setup Authenticator");
BITHockeyAppClient *client = [[BITHockeyAppClient alloc] initWithBaseURL:[NSURL URLWithString:_serverURL ? _serverURL : BITHOCKEYSDK_URL]];
_authenticator = [[BITAuthenticator alloc] initWithAppIdentifier:_appIdentifier isAppStoreEnvironment:_appStoreEnvironment];
_authenticator.hockeyAppClient = client;
_authenticator.hockeyAppClient = [self hockeyAppClient];
_authenticator.delegate = _delegate;
#endif /* HOCKEYSDK_FEATURE_AUTHENTICATOR */
#if HOCKEYSDK_FEATURE_UPDATES
#if HOCKEYSDK_FEATURE_JIRA_MOBILE_CONNECT
// Only if JMC is part of the project
@ -440,7 +577,15 @@
[self performSelector:@selector(configureJMC) withObject:nil afterDelay:0];
}
#endif /* HOCKEYSDK_FEATURE_JIRA_MOBILE_CONNECT */
#endif /* HOCKEYSDK_FEATURE_UPDATES */
if (![self isAppStoreEnvironment]) {
NSString *integrationFlowTime = [self integrationFlowTimeString];
if (integrationFlowTime && [self integrationFlowStartedWithTimeString:integrationFlowTime]) {
[self pingServerForIntegrationStartWorkflowWithTimeString:integrationFlowTime appIdentifier:_appIdentifier];
}
}
} else {
[self logInvalidIdentifier:@"app identifier"];
}

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,37 +0,0 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 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>
@interface BITHockeyManager () {
}
@property (nonatomic, weak) id delegate;
@end

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011-2012 Peter Steinberger.
* All rights reserved.
*

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011-2012 Peter Steinberger.
* All rights reserved.
*

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
@ -273,7 +273,7 @@
NSData *data = [responseString dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *json = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSDictionary *json = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (error) {
BITHockeyLog(@"ERROR: Invalid JSON string. %@", [error localizedDescription]);

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011 Andreas Linde.
* All rights reserved.
*

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011 Andreas Linde.
* All rights reserved.
*
@ -200,12 +200,30 @@ typedef NS_ENUM (NSUInteger, BITUpdateSetting) {
When running the app from the App Store, this setting is ignored.
*Default*: nil
@see disableUpdateCheckOptionWhenExpired
@see [BITUpdateManagerDelegate shouldDisplayExpiryAlertForUpdateManager:]
@see [BITUpdateManagerDelegate didDisplayExpiryAlertForUpdateManager:]
@warning This only works when using Ad-Hoc provisioning profiles!
*/
@property (nonatomic, strong) NSDate *expiryDate;
/**
Disable the update check button from expiry screen or alerts
If do not want your users to be able to check for updates once a version is expired,
then enable this property.
If this is not enabled, the users will be able to check for updates and install them
if any is available for the current device.
*Default*: NO
@see expiryDate
@see [BITUpdateManagerDelegate shouldDisplayExpiryAlertForUpdateManager:]
@see [BITUpdateManagerDelegate didDisplayExpiryAlertForUpdateManager:]
@warning This only works when using Ad-Hoc provisioning profiles!
*/
@property (nonatomic) BOOL disableUpdateCheckOptionWhenExpired;
///-----------------------------------------------------------------------------
/// @name User Interface

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011 Andreas Linde.
* All rights reserved.
*
@ -59,6 +59,10 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
BOOL _lastCheckFailed;
BOOL _sendUsageData;
NSFileManager *_fileManager;
NSString *_updateDir;
NSString *_usageDataFile;
id _appDidBecomeActiveObserver;
id _appDidEnterBackgroundObserver;
id _networkDidBecomeReachableObserver;
@ -70,6 +74,9 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
NSNumber *_versionID;
NSString *_versionUUID;
NSString *_uuid;
NSString *_blockingScreenMessage;
NSDate *_lastUpdateCheckFromBlockingScreen;
}
@ -187,7 +194,9 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
if (shouldShowDefaultAlert) {
NSString *appName = bit_appName(BITHockeyLocalizedString(@"HockeyAppNamePlaceholder"));
[self showBlockingScreen:[NSString stringWithFormat:BITHockeyLocalizedString(@"UpdateExpired"), appName] image:@"authorize_denied.png"];
if (!_blockingScreenMessage)
_blockingScreenMessage = [NSString stringWithFormat:BITHockeyLocalizedString(@"UpdateExpired"), appName];
[self showBlockingScreen:_blockingScreenMessage image:@"authorize_denied.png"];
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(didDisplayExpiryAlertForUpdateManager:)]) {
[self.delegate didDisplayExpiryAlertForUpdateManager:self];
@ -200,10 +209,10 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
#pragma mark - Usage
- (void)startUsage {
- (void)loadAppVersionUsageData {
self.currentAppVersionUsageTime = @0;
if ([self expiryDateReached]) return;
self.usageStartTimestamp = [NSDate date];
BOOL newVersion = NO;
@ -219,21 +228,55 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithDouble:[[NSDate date] timeIntervalSinceReferenceDate]] forKey:kBITUpdateDateOfVersionInstallation];
[[NSUserDefaults standardUserDefaults] setObject:_uuid forKey:kBITUpdateUsageTimeForUUID];
[self storeUsageTimeForCurrentVersion:[NSNumber numberWithDouble:0]];
} else {
if (![_fileManager fileExistsAtPath:_usageDataFile])
return;
NSData *codedData = [[NSData alloc] initWithContentsOfFile:_usageDataFile];
if (codedData == nil) return;
NSKeyedUnarchiver *unarchiver = nil;
@try {
unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:codedData];
}
@catch (NSException *exception) {
return;
}
if ([unarchiver containsValueForKey:kBITUpdateUsageTimeOfCurrentVersion]) {
self.currentAppVersionUsageTime = [unarchiver decodeObjectForKey:kBITUpdateUsageTimeOfCurrentVersion];
}
[unarchiver finishDecoding];
}
}
- (void)startUsage {
if ([self expiryDateReached]) return;
self.usageStartTimestamp = [NSDate date];
}
- (void)stopUsage {
if ([self expiryDateReached]) return;
double timeDifference = [[NSDate date] timeIntervalSinceReferenceDate] - [_usageStartTimestamp timeIntervalSinceReferenceDate];
double previousTimeDifference = [(NSNumber *)[[NSUserDefaults standardUserDefaults] valueForKey:kBITUpdateUsageTimeOfCurrentVersion] doubleValue];
double previousTimeDifference = [self.currentAppVersionUsageTime doubleValue];
[self storeUsageTimeForCurrentVersion:[NSNumber numberWithDouble:previousTimeDifference + timeDifference]];
}
- (void) storeUsageTimeForCurrentVersion:(NSNumber *)usageTime {
[[NSUserDefaults standardUserDefaults] setObject:usageTime forKey:kBITUpdateUsageTimeOfCurrentVersion];
[[NSUserDefaults standardUserDefaults] synchronize];
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:usageTime forKey:kBITUpdateUsageTimeOfCurrentVersion];
[archiver finishEncoding];
[data writeToFile:_usageDataFile atomically:YES];
self.currentAppVersionUsageTime = usageTime;
}
- (NSString *)currentUsageString {
@ -339,29 +382,6 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
[[NSUserDefaults standardUserDefaults] synchronize];
}
#pragma mark - Window Helper
- (UIWindow *)findVisibleWindow {
UIWindow *visibleWindow = nil;
// if the rootViewController property (available >= iOS 4.0) of the main window is set, we present the modal view controller on top of the rootViewController
NSArray *windows = [[UIApplication sharedApplication] windows];
for (UIWindow *window in windows) {
if (!window.hidden && !visibleWindow) {
visibleWindow = window;
}
if ([UIWindow instancesRespondToSelector:@selector(rootViewController)]) {
if ([window rootViewController]) {
visibleWindow = window;
BITHockeyLog(@"INFO: UIWindow with rootViewController found: %@", visibleWindow);
break;
}
}
}
return visibleWindow;
}
#pragma mark - Init
@ -384,6 +404,7 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
_checkForTracker = NO;
_firstStartAfterInstall = NO;
_companyName = nil;
_currentAppVersionUsageTime = @0;
// set defaults
self.showDirectInstallOption = NO;
@ -411,10 +432,26 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
NSLog(@"[HockeySDK] WARNING: %@ is missing, make sure it is added!", BITHOCKEYSDK_BUNDLE);
}
_fileManager = [[NSFileManager alloc] init];
// temporary directory for crashes grabbed from PLCrashReporter
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
_updateDir = [[paths objectAtIndex:0] stringByAppendingPathComponent:BITHOCKEY_IDENTIFIER];
if (![_fileManager fileExistsAtPath:_updateDir]) {
NSDictionary *attributes = [NSDictionary dictionaryWithObject: [NSNumber numberWithUnsignedLong: 0755] forKey: NSFilePosixPermissions];
NSError *theError = NULL;
[_fileManager createDirectoryAtPath:_updateDir withIntermediateDirectories: YES attributes: attributes error: &theError];
}
_usageDataFile = [_updateDir stringByAppendingPathComponent:BITHOCKEY_USAGE_DATA];
[self loadAppCache];
_installationIdentification = [self stringValueFromKeychainForKey:kBITUpdateInstallationIdentification];
[self loadAppVersionUsageData];
[self startUsage];
NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter];
@ -458,7 +495,12 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
if ([self isPreiOS7Environment])
self.barStyle = UIBarStyleBlack;
[self showView:[self hockeyViewController:YES]];
BITUpdateViewController *updateViewController = [self hockeyViewController:YES];
if ([self hasNewerMandatoryVersion] || [self expiryDateReached]) {
[updateViewController setMandatoryUpdate: YES];
}
[self showView:updateViewController];
}
@ -472,7 +514,7 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
message:[NSString stringWithFormat:BITHockeyLocalizedString(@"UpdateAlertMandatoryTextWithAppVersion"), [self.newestAppVersion nameAndVersionString]]
delegate:self
cancelButtonTitle:BITHockeyLocalizedString(@"UpdateInstall")
otherButtonTitles:nil
otherButtonTitles:BITHockeyLocalizedString(@"UpdateShow"), nil
];
[alertView setTag:BITUpdateAlertViewTagMandatoryUpdate];
[alertView show];
@ -520,16 +562,27 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
[self.blockingView addSubview:imageView];
}
if (!self.disableUpdateCheckOptionWhenExpired) {
UIButton *checkForUpdateButton = [UIButton buttonWithType:kBITButtonTypeSystem];
checkForUpdateButton.frame = CGRectMake((frame.size.width - 140) / 2.f, frame.size.height - 100, 140, 25);
[checkForUpdateButton setTitle:BITHockeyLocalizedString(@"UpdateButtonCheck") forState:UIControlStateNormal];
[checkForUpdateButton addTarget:self
action:@selector(checkForUpdateForExpiredVersion)
forControlEvents:UIControlEventTouchUpInside];
[self.blockingView addSubview:checkForUpdateButton];
}
if (message != nil) {
frame.origin.x = 20;
frame.origin.y = frame.size.height - 140;
frame.origin.y = frame.size.height - 180;
frame.size.width -= 40;
frame.size.height = 50;
frame.size.height = 70;
UILabel *label = [[UILabel alloc] initWithFrame:frame];
label.text = message;
label.textAlignment = kBITTextLabelAlignmentCenter;
label.numberOfLines = 2;
label.numberOfLines = 3;
label.adjustsFontSizeToFitWidth = YES;
label.backgroundColor = [UIColor clearColor];
[self.blockingView addSubview:label];
@ -538,6 +591,16 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
[visibleWindow addSubview:self.blockingView];
}
- (void)checkForUpdateForExpiredVersion {
if (!self.checkInProgress) {
if (!_lastUpdateCheckFromBlockingScreen ||
abs([NSDate timeIntervalSinceReferenceDate] - [_lastUpdateCheckFromBlockingScreen timeIntervalSinceReferenceDate]) > 60) {
_lastUpdateCheckFromBlockingScreen = [NSDate date];
[self checkForUpdateShowFeedback:NO];
}
}
}
// nag the user with neverending alerts if we cannot find out the window for presenting the covering sheet
- (void)alertFallback:(NSString *)message {
@ -547,6 +610,11 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
cancelButtonTitle:BITHockeyLocalizedString(@"HockeyOK")
otherButtonTitles:nil
];
if (!self.disableUpdateCheckOptionWhenExpired && [message isEqualToString:_blockingScreenMessage]) {
[alertView addButtonWithTitle:BITHockeyLocalizedString(@"UpdateButtonCheck")];
}
[alertView setTag:BITUpdateAlertViewTagNeverEndingAlertView];
[alertView show];
}
@ -752,7 +820,13 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
self.receivedData = nil;
self.urlConnection = nil;
self.checkInProgress = NO;
[self reportError:error];
if ([self expiryDateReached]) {
if (!self.blockingView) {
[self alertFallback:_blockingScreenMessage];
}
} else {
[self reportError:error];
}
}
// api call returned, parsing
@ -770,7 +844,7 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
}
NSError *error = nil;
NSDictionary *json = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:&error];
NSDictionary *json = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&error];
self.trackerConfig = (([self checkForTracker] && [[json valueForKey:@"tracker"] isKindOfClass:[NSDictionary class]]) ? [json valueForKey:@"tracker"] : nil);
self.companyName = (([[json valueForKey:@"company"] isKindOfClass:[NSString class]]) ? [json valueForKey:@"company"] : nil);
@ -849,11 +923,16 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
}
_showFeedback = NO;
}
} else {
} else if (![self expiryDateReached]) {
[self reportError:[NSError errorWithDomain:kBITUpdateErrorDomain
code:BITUpdateAPIServerReturnedEmptyResponse
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Server returned an empty response.", NSLocalizedDescriptionKey, nil]]];
}
if (!_updateAlertShowing && [self expiryDateReached] && !self.blockingView) {
[self alertFallback:_blockingScreenMessage];
}
self.receivedData = nil;
self.urlConnection = nil;
}
@ -959,22 +1038,29 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) {
// invoke the selected action from the action sheet for a location element
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if ([alertView tag] == BITUpdateAlertViewTagMandatoryUpdate) {
(void)[self initiateAppDownload];
_updateAlertShowing = NO;
return;
} else if ([alertView tag] == BITUpdateAlertViewTagNeverEndingAlertView) {
[self alertFallback:[alertView message]];
if ([alertView tag] == BITUpdateAlertViewTagNeverEndingAlertView) {
if (buttonIndex == 1) {
[self checkForUpdateForExpiredVersion];
} else {
[self alertFallback:_blockingScreenMessage];
}
return;
}
_updateAlertShowing = NO;
if (buttonIndex == [alertView firstOtherButtonIndex]) {
// YES button has been clicked
if (self.blockingView) {
[self.blockingView removeFromSuperview];
}
[self showUpdateView];
} else if (buttonIndex == [alertView firstOtherButtonIndex] + 1) {
// YES button has been clicked
(void)[self initiateAppDownload];
} else {
if ([self expiryDateReached] && !self.blockingView) {
[self alertFallback:_blockingScreenMessage];
}
}
}

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011 Andreas Linde.
* All rights reserved.
*
@ -52,6 +52,8 @@
// get array of all available versions
@property (nonatomic, copy) NSArray *appVersions;
@property (nonatomic, strong) NSNumber *currentAppVersionUsageTime;
@property (nonatomic, strong) NSURLConnection *urlConnection;
@property (nonatomic, copy) NSDate *usageStartTimestamp;

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011 Andreas Linde, Peter Steinberger.
* All rights reserved.
*

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011 Andreas Linde, Peter Steinberger.
* All rights reserved.
*
@ -364,8 +364,11 @@
}
- (void)viewWillAppear:(BOOL)animated {
if (_isAppStoreEnvironment)
if (_isAppStoreEnvironment) {
self.appStoreButtonState = AppStoreButtonStateOffline;
} else if (self.mandatoryUpdate) {
self.navigationItem.leftBarButtonItem = nil;
}
_updateManager.currentHockeyViewController = self;
[super viewWillAppear:animated];
[self redrawTableView];

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011 Andreas Linde, Peter Steinberger.
* All rights reserved.
*
@ -69,7 +69,8 @@ typedef NS_ENUM(NSUInteger, AppStoreButtonState) {
}
@property (nonatomic, weak) BITUpdateManager *updateManager;
@property (nonatomic, readwrite) BOOL modal;
@property (nonatomic, readwrite) BOOL mandatoryUpdate;
@property (nonatomic, assign) AppStoreButtonState appStoreButtonState;

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011-2012 Peter Steinberger.
* All rights reserved.
*

View File

@ -2,7 +2,7 @@
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011-2012 Peter Steinberger.
* All rights reserved.
*

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011 Andreas Linde.
* All rights reserved.
*

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2013-2014 HockeyApp, Bit Stadium GmbH.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person

View File

@ -41,6 +41,8 @@
#define BITHOCKEY_FEEDBACK_SETTINGS @"BITFeedbackManager.plist"
#define BITHOCKEY_USAGE_DATA @"BITUpdateManager.plist"
#define kBITUpdateInstalledUUID @"BITUpdateInstalledUUID"
#define kBITUpdateInstalledVersionID @"BITUpdateInstalledVersionID"
#define kBITUpdateCurrentCompanyName @"BITUpdateCurrentCompanyName"
@ -56,6 +58,8 @@
#define kBITStoreUpdateLastUUID @"BITStoreUpdateLastUUID"
#define kBITStoreUpdateIgnoreVersion @"BITStoreUpdateIgnoredVersion"
#define BITHOCKEY_INTEGRATIONFLOW_TIMESTAMP @"BITIntegrationFlowStartTimestamp"
#define BITHOCKEYSDK_BUNDLE @"HockeySDKResources.bundle"
#define BITHOCKEYSDK_URL @"https://sdk.hockeyapp.net/"
@ -67,21 +71,21 @@ NSBundle *BITHockeyBundle(void);
NSString *BITHockeyLocalizedString(NSString *stringToken);
NSString *BITHockeyMD5(NSString *str);
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
#define kBITTextLabelAlignmentCenter UITextAlignmentCenter
#define kBITTextLabelAlignmentLeft UITextAlignmentLeft
#define kBITTextLabelAlignmentRight UITextAlignmentRight
#define kBITLineBreakModeMiddleTruncation UILineBreakModeMiddleTruncation
#else
#ifdef __IPHONE_6_0
#define kBITTextLabelAlignmentCenter NSTextAlignmentCenter
#define kBITTextLabelAlignmentLeft NSTextAlignmentLeft
#define kBITTextLabelAlignmentRight NSTextAlignmentRight
#define kBITLineBreakModeMiddleTruncation NSLineBreakByTruncatingMiddle
#endif /* __IPHONE_OS_VERSION_MIN_REQUIRED */
#else
#define kBITTextLabelAlignmentCenter UITextAlignmentCenter
#define kBITTextLabelAlignmentLeft UITextAlignmentLeft
#define kBITTextLabelAlignmentRight UITextAlignmentRight
#define kBITLineBreakModeMiddleTruncation UILineBreakModeMiddleTruncation
#endif /* __IPHONE_6_0 */
#if __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_6_1

View File

@ -1,7 +1,7 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
*
* Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011 Andreas Linde.
* All rights reserved.
*
@ -50,11 +50,16 @@ NSBundle *BITHockeyBundle(void) {
}
NSString *BITHockeyLocalizedString(NSString *stringToken) {
if (!stringToken) return @"";
NSString *appSpecificLocalizationString = NSLocalizedString(stringToken, @"");
if (appSpecificLocalizationString && ![stringToken isEqualToString:appSpecificLocalizationString]) {
return appSpecificLocalizationString;
} else if (BITHockeyBundle()) {
return NSLocalizedStringFromTableInBundle(stringToken, @"HockeySDK", BITHockeyBundle(), @"");
NSString *bundleSpecificLocalizationString = NSLocalizedStringFromTableInBundle(stringToken, @"HockeySDK", BITHockeyBundle(), @"");
if (bundleSpecificLocalizationString)
return bundleSpecificLocalizationString;
return stringToken;
} else {
return stringToken;
}

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'HockeySDK'
s.version = '3.5.0'
s.version = '3.5.1'
s.license = 'MIT'
s.platform = :ios, '5.0'
s.summary = 'Distribute beta apps and collect crash reports with HockeyApp.'

View File

@ -3,7 +3,7 @@
The Hockey SDK is provided under the following license:
The MIT License
Copyright (c) 2012-2013 HockeyApp, Bit Stadium GmbH.
Copyright (c) 2012-2014 HockeyApp, Bit Stadium GmbH.
All rights reserved.
Permission is hereby granted, free of charge, to any person
@ -30,8 +30,8 @@ The Hockey SDK is provided under the following license:
Except as noted below, PLCrashReporter
is provided under the following license:
Copyright (c) 2008 - 2013 Plausible Labs Cooperative, Inc.
Copyright (c) 2012 - 2013 HockeyApp, Bit Stadium GmbH.
Copyright (c) 2008 - 2014 Plausible Labs Cooperative, Inc.
Copyright (c) 2012 - 2014 HockeyApp, Bit Stadium GmbH.
All rights reserved.
Permission is hereby granted, free of charge, to any person

View File

@ -1,6 +1,6 @@
## Version 3.5.0
## Version 3.5.1
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.0/docs/docs/Changelog.html)
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.1/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.0/docs/docs/Guide-Installation-Setup.html) (Recommended)
- [Installation & Setup Advanced](http://www.hockeyapp.net/help/sdk/ios/3.5.0/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.0rc3/docs/docs/HowTo-Authenticating-Users-on-iOS.html)
- [Migration from previous SDK Versions](http://www.hockeyapp.net/help/sdk/ios/3.5.0/docs/docs/Guide-Migration-Kits.html)
- [Installation & Setup](http://www.hockeyapp.net/help/sdk/ios/3.5.1/docs/docs/Guide-Installation-Setup.html) (Recommended)
- [Installation & Setup Advanced](http://www.hockeyapp.net/help/sdk/ios/3.5.1/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.1/docs/docs/HowTo-Authenticating-Users-on-iOS.html)
- [Migration from previous SDK Versions](http://www.hockeyapp.net/help/sdk/ios/3.5.1/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/DocSet`
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.0/](http://hockeyapp.net/help/sdk/ios/3.5.0/)
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.1/](http://hockeyapp.net/help/sdk/ios/3.5.1/)

View File

@ -231,7 +231,7 @@
"HockeyFeedbackUserDataEmail" = "E-Mail";
/* Email Placeholder */
"HockeyFeedbackUserDataEmailPlaceholder" = "beispiel@email.de";
"HockeyFeedbackUserDataEmailPlaceholder" = "email@beispiel.de";
/* Authenticator */
@ -249,7 +249,7 @@
/* BITAuthenticatorAuthTypeEmail and BITAuthenticatorAuthTypeEmailAndPassword */
"HockeyAuthenticationViewControllerDataEmailAndPasswordDescription" = "Geben Sie die E-Mail-Adresse und das Kennwort Ihres HockeyApp-Accounts ein, um Zugriff auf diese App zu erhalten.";
"HockeyAuthenticationViewControllerDataEmailDescription" = "Geben Sie die E-Mail-Adresse Ihres HockeyApp-Accounts ein, um Zugriff auf diese App zu erhalten.";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "beispiel@email.de";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "email@beispiel.de";
"HockeyAuthenticationViewControllerPasswordPlaceholder" = "Erforderlich";
"HockeyAuthenticationViewControllerEmailDescription" = "E-Mail";
"HockeyAuthenticationViewControllerPasswordDescription" = "Kennwort";
@ -257,6 +257,9 @@
/* Error presented to the user if authentication failed because of networking issues */
"HockeyAuthenticationViewControllerNetworkError" = "Die Autorisierung ist fehlgeschlagen, da Ihr Gerät anscheinend nicht mit dem Internet verbunden ist. Bitte erneut versuchen.";
/* Error presented to the user if authentication could not be stored on the device */
"HockeyAuthenticationViewControllerStorageError" = "Your authentication token could not be stored due to a keychain error. Please contact the developer of the app.";
"HockeyAuthenticationFailedAuthenticate" = "Autorisierung fehlgeschlagen. Bitte erneut versuchen oder an den Entwickler dieser App wenden.";
"HockeyAuthenticationNotMember" = "Sie sind nicht berechtigt, diese App zu nutzen. Bitte wenden Sie sich an den Entwickler dieser App.";

View File

@ -231,7 +231,7 @@
"HockeyFeedbackUserDataEmail" = "Email";
/* Email Placeholder */
"HockeyFeedbackUserDataEmailPlaceholder" = "example@email.com";
"HockeyFeedbackUserDataEmailPlaceholder" = "email@example.com";
/* Authenticator */
@ -249,7 +249,7 @@
/* BITAuthenticatorAuthTypeEmail and BITAuthenticatorAuthTypeEmailAndPassword */
"HockeyAuthenticationViewControllerDataEmailAndPasswordDescription" = "Please enter your HockeyApp account's email address and password to authorize access to this app.";
"HockeyAuthenticationViewControllerDataEmailDescription" = "Please enter your HockeyApp account's email address to authorize access to this app.";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "example@email.com";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "email@example.com";
"HockeyAuthenticationViewControllerPasswordPlaceholder" = "Required";
"HockeyAuthenticationViewControllerEmailDescription" = "Email";
"HockeyAuthenticationViewControllerPasswordDescription" = "Password";
@ -257,6 +257,8 @@
/* Error presented to the user if authentication failed because of networking issues */
"HockeyAuthenticationViewControllerNetworkError" = "Failed to authorize because your device appears to be disconnected from the Internet. Please try again.";
/* Error presented to the user if authentication could not be stored on the device */
"HockeyAuthenticationViewControllerStorageError" = "Your authentication token could not be stored due to a keychain error. Please contact the developer of the app.";
"HockeyAuthenticationFailedAuthenticate" = "Failed to authorize. Please try again or contact the developer of this app.";
"HockeyAuthenticationNotMember" = "You are not authorized to use this app. Please contact the developer of this app.";

View File

@ -231,7 +231,7 @@
"HockeyFeedbackUserDataEmail" = "Correo";
/* Email Placeholder */
"HockeyFeedbackUserDataEmailPlaceholder" = "ejemplo@correo.com";
"HockeyFeedbackUserDataEmailPlaceholder" = "correo@ejemplo.com";
/* Authenticator */
@ -249,7 +249,7 @@
/* BITAuthenticatorAuthTypeEmail and BITAuthenticatorAuthTypeEmailAndPassword */
"HockeyAuthenticationViewControllerDataEmailAndPasswordDescription" = "Escriba el correo y contraseña de su cuenta de HockeyApp para autorizar el acceso a esta app.";
"HockeyAuthenticationViewControllerDataEmailDescription" = "Escriba el correo de su cuenta de HockeyApp para autorizar el acceso a esta app.";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "ejemplo@dominio.com";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "correo@ejemplo.com";
"HockeyAuthenticationViewControllerPasswordPlaceholder" = "Obligatorio";
"HockeyAuthenticationViewControllerEmailDescription" = "Correo";
"HockeyAuthenticationViewControllerPasswordDescription" = "Contraseña";
@ -257,6 +257,9 @@
/* Error presented to the user if authentication failed because of networking issues */
"HockeyAuthenticationViewControllerNetworkError" = "No se ha podido realizar la autorización porque su dispositivo parece no estar conectado a Internet. Vuelva a intentarlo.";
/* Error presented to the user if authentication could not be stored on the device */
"HockeyAuthenticationViewControllerStorageError" = "Your authentication token could not be stored due to a keychain error. Please contact the developer of the app.";
"HockeyAuthenticationFailedAuthenticate" = "Error de autorización. Vuelva a intentarlo o póngase en contacto con el desarrollador de la app.";
"HockeyAuthenticationNotMember" = "No tiene autorización para usar esta app. Póngase en contacto con el desarrollador de la app.";

View File

@ -231,7 +231,7 @@
"HockeyFeedbackUserDataEmail" = "Adresse";
/* Email Placeholder */
"HockeyFeedbackUserDataEmailPlaceholder" = "exemple@email.com";
"HockeyFeedbackUserDataEmailPlaceholder" = "email@exemple.com";
/* Authenticator */
@ -249,7 +249,7 @@
/* BITAuthenticatorAuthTypeEmail and BITAuthenticatorAuthTypeEmailAndPassword */
"HockeyAuthenticationViewControllerDataEmailAndPasswordDescription" = "Saisissez l'adresse électronique et le mot de passe de votre compte HockeyApp pour autoriser l'accès à cette application.";
"HockeyAuthenticationViewControllerDataEmailDescription" = "Saisissez l'adresse électronique de votre compte HockeyApp pour autoriser l'accès à cette application.";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "exemple@email.com";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "email@exemple.com";
"HockeyAuthenticationViewControllerPasswordPlaceholder" = "Requis";
"HockeyAuthenticationViewControllerEmailDescription" = "Adresse";
"HockeyAuthenticationViewControllerPasswordDescription" = "Mot de passe";
@ -257,6 +257,9 @@
/* Error presented to the user if authentication failed because of networking issues */
"HockeyAuthenticationViewControllerNetworkError" = "Échec de l'autorisation. Votre appareil semble déconnecté d'Internet. Réessayez.";
/* Error presented to the user if authentication could not be stored on the device */
"HockeyAuthenticationViewControllerStorageError" = "Your authentication token could not be stored due to a keychain error. Please contact the developer of the app.";
"HockeyAuthenticationFailedAuthenticate" = "Échec de l'autorisation. Réessayez ou contactez le développeur de l'application.";
"HockeyAuthenticationNotMember" = "Vous n'êtes pas autorisé à utiliser cette application. Contactez le développeur de l'application.";

View File

@ -231,7 +231,7 @@
"HockeyFeedbackUserDataEmail" = "E-mail";
/* Email Placeholder */
"HockeyFeedbackUserDataEmailPlaceholder" = "primjer@email.com";
"HockeyFeedbackUserDataEmailPlaceholder" = "email@primjer.com";
/* Authenticator */
@ -249,7 +249,7 @@
/* BITAuthenticatorAuthTypeEmail and BITAuthenticatorAuthTypeEmailAndPassword */
"HockeyAuthenticationViewControllerDataEmailAndPasswordDescription" = "Unesite molimo Vas e-mail adresu i lozinku Vašeg HockeyApp računa kako biste autorizirali pristup ovoj aplikaciji.";
"HockeyAuthenticationViewControllerDataEmailDescription" = "Molimo Vas unesite e-mail adresu Vašeg HockeyApp računa za autorizaciju pristupa aplikaciji.";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "primjer@email.com";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "email@primjer.com";
"HockeyAuthenticationViewControllerPasswordPlaceholder" = "Obavezno";
"HockeyAuthenticationViewControllerEmailDescription" = "E-mail";
"HockeyAuthenticationViewControllerPasswordDescription" = "Lozinka";
@ -257,6 +257,9 @@
/* Error presented to the user if authentication failed because of networking issues */
"HockeyAuthenticationViewControllerNetworkError" = "Autorizacija nije uspjela. Vaš uređaj nema pristup internetu. Molimo Vas pokušajte iznova.";
/* Error presented to the user if authentication could not be stored on the device */
"HockeyAuthenticationViewControllerStorageError" = "Your authentication token could not be stored due to a keychain error. Please contact the developer of the app.";
"HockeyAuthenticationFailedAuthenticate" = "Autorizacija nije uspjela. Molimo Vas pokušajte iznova ili kontaktirajte razvojnog programera ove aplikacije.";
"HockeyAuthenticationNotMember" = "Vi niste autorizirani za korištenje ove aplikacije. Molimo Vas kontaktirajte razvojnog programera ove aplikacije.";

View File

@ -231,7 +231,7 @@
"HockeyFeedbackUserDataEmail" = "E-mail";
/* Email Placeholder */
"HockeyFeedbackUserDataEmailPlaceholder" = "example@email.com";
"HockeyFeedbackUserDataEmailPlaceholder" = "email@example.com";
/* Authenticator */
@ -249,7 +249,7 @@
/* BITAuthenticatorAuthTypeEmail and BITAuthenticatorAuthTypeEmailAndPassword */
"HockeyAuthenticationViewControllerDataEmailAndPasswordDescription" = "Kérjük, adja meg HockeyApp fiókjához tartozó e-mail címét és jelszavát az alkalmazáshoz történő hozzáférés engedélyezéséhez.";
"HockeyAuthenticationViewControllerDataEmailDescription" = "Kérjük, adja meg HockeyApp fiókjához tartozó e-mail címét az alkalmazáshoz történő hozzáférés engedélyezéséhez.";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "example@email.com";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "email@example.com";
"HockeyAuthenticationViewControllerPasswordPlaceholder" = "Szükséges mező";
"HockeyAuthenticationViewControllerEmailDescription" = "E-mail";
"HockeyAuthenticationViewControllerPasswordDescription" = "Jelszó";
@ -257,6 +257,9 @@
/* Error presented to the user if authentication failed because of networking issues */
"HockeyAuthenticationViewControllerNetworkError" = "A hitelesítés sikertelen, mert készüléke nem csatlakozik az internethez. Kérjük, próbálja meg később újra.";
/* Error presented to the user if authentication could not be stored on the device */
"HockeyAuthenticationViewControllerStorageError" = "Your authentication token could not be stored due to a keychain error. Please contact the developer of the app.";
"HockeyAuthenticationFailedAuthenticate" = "A hitelesítés sikertelen. Kérjük, próbálja meg később újra vagy lépjen kapcsolatba az alkalmazás fejlesztőjével.";
"HockeyAuthenticationNotMember" = "Nem jogosult az alkalmazás használatára. Kérjük, lépjen kapcsolatba az alkalmazás fejlesztőjével.";

View File

@ -231,7 +231,7 @@
"HockeyFeedbackUserDataEmail" = "E-mail";
/* Email Placeholder */
"HockeyFeedbackUserDataEmailPlaceholder" = "esempio@email.com";
"HockeyFeedbackUserDataEmailPlaceholder" = "email@esempio.com";
/* Authenticator */
@ -249,7 +249,7 @@
/* BITAuthenticatorAuthTypeEmail and BITAuthenticatorAuthTypeEmailAndPassword */
"HockeyAuthenticationViewControllerDataEmailAndPasswordDescription" = "Inserisci l'indirizzo e-mail e la password del tuo account HockeyApp per autorizzare l'accesso a questa app.";
"HockeyAuthenticationViewControllerDataEmailDescription" = "Inserisci l'indirizzo e-mail del tuo account HockeyApp per autorizzare l'accesso a questa app.";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "esempio@email.com";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "email@esempio.com";
"HockeyAuthenticationViewControllerPasswordPlaceholder" = "Richiesto";
"HockeyAuthenticationViewControllerEmailDescription" = "E-mail";
"HockeyAuthenticationViewControllerPasswordDescription" = "Password";
@ -257,6 +257,9 @@
/* Error presented to the user if authentication failed because of networking issues */
"HockeyAuthenticationViewControllerNetworkError" = "Autorizzazione non riuscita. Pare che il dispositivo non sia connesso a Internet. Riprova.";
/* Error presented to the user if authentication could not be stored on the device */
"HockeyAuthenticationViewControllerStorageError" = "Your authentication token could not be stored due to a keychain error. Please contact the developer of the app.";
"HockeyAuthenticationFailedAuthenticate" = "Autorizzazione non riuscita. Riprova o contatta lo sviluppatore di questa app.";
"HockeyAuthenticationNotMember" = "Non sei autorizzato a usare questa app. Contatta lo sviluppatore di questa app.";

View File

@ -231,7 +231,7 @@
"HockeyFeedbackUserDataEmail" = "メール";
/* Email Placeholder */
"HockeyFeedbackUserDataEmailPlaceholder" = "example@email.com";
"HockeyFeedbackUserDataEmailPlaceholder" = "email@example.com";
/* Authenticator */
@ -249,7 +249,7 @@
/* BITAuthenticatorAuthTypeEmail and BITAuthenticatorAuthTypeEmailAndPassword */
"HockeyAuthenticationViewControllerDataEmailAndPasswordDescription" = "HockeyAppアカウントのメールアドレスとパスワードを入力し、このAppへのアクセスを認証してください。";
"HockeyAuthenticationViewControllerDataEmailDescription" = "HockeyAppアカウントのメールアドレスを入力し、このAppへのアクセスを認証してください。";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "example@email.com";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "email@example.com";
"HockeyAuthenticationViewControllerPasswordPlaceholder" = "必須";
"HockeyAuthenticationViewControllerEmailDescription" = "メール";
"HockeyAuthenticationViewControllerPasswordDescription" = "パスワード";
@ -257,6 +257,9 @@
/* Error presented to the user if authentication failed because of networking issues */
"HockeyAuthenticationViewControllerNetworkError" = "デバイスがインターネットに接続されていないため、認証できません。やり直してください。";
/* Error presented to the user if authentication could not be stored on the device */
"HockeyAuthenticationViewControllerStorageError" = "Your authentication token could not be stored due to a keychain error. Please contact the developer of the app.";
"HockeyAuthenticationFailedAuthenticate" = "認証できませんでした。やり直すか、このAppのデベロッパに連絡してください。";
"HockeyAuthenticationNotMember" = "このAppの使用を認証されていません。このAppのデベロッパに連絡してください。";

View File

@ -231,7 +231,7 @@
"HockeyFeedbackUserDataEmail" = "E-mail";
/* Email Placeholder */
"HockeyFeedbackUserDataEmailPlaceholder" = "voorbeeld@e-mail.com";
"HockeyFeedbackUserDataEmailPlaceholder" = "e-mail@voorbeeld.com";
/* Authenticator */
@ -249,7 +249,7 @@
/* BITAuthenticatorAuthTypeEmail and BITAuthenticatorAuthTypeEmailAndPassword */
"HockeyAuthenticationViewControllerDataEmailAndPasswordDescription" = "Voer het e-mailadres en wachtwoord van uw HockeyApp-account in om toegang tot deze app te verlenen.";
"HockeyAuthenticationViewControllerDataEmailDescription" = "Voer het e-mailadres van uw HockeyApp-account in om toegang tot deze app te verlenen.";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "voorbeeld@e-mail.com";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "mail@voorbeeld.com";
"HockeyAuthenticationViewControllerPasswordPlaceholder" = "Verplicht";
"HockeyAuthenticationViewControllerEmailDescription" = "E-mail";
"HockeyAuthenticationViewControllerPasswordDescription" = "Wachtwoord";
@ -257,6 +257,9 @@
/* Error presented to the user if authentication failed because of networking issues */
"HockeyAuthenticationViewControllerNetworkError" = "Identiteitscontrole mislukt omdat uw apparaat niet is verbonden met het internet. Probeer opnieuw.";
/* Error presented to the user if authentication could not be stored on the device */
"HockeyAuthenticationViewControllerStorageError" = "Your authentication token could not be stored due to a keychain error. Please contact the developer of the app.";
"HockeyAuthenticationFailedAuthenticate" = "Identiteitscontrole mislukt. Probeer opnieuw of neem contact op met de ontwikkelaar van deze app.";
"HockeyAuthenticationNotMember" = "U bent niet gemachtigd om deze app te gebruiken. Neem contact op met de ontwikkelaar van deze app.";

View File

@ -231,7 +231,7 @@
"HockeyFeedbackUserDataEmail" = "E-mail";
/* Email Placeholder */
"HockeyFeedbackUserDataEmailPlaceholder" = "exemplo@email.com";
"HockeyFeedbackUserDataEmailPlaceholder" = "email@exemplo.com";
/* Authenticator */
@ -249,7 +249,7 @@
/* BITAuthenticatorAuthTypeEmail and BITAuthenticatorAuthTypeEmailAndPassword */
"HockeyAuthenticationViewControllerDataEmailAndPasswordDescription" = "Introduza o endereço de e-mail e a palavra-passe da sua conta HockeyApp para autorizar o acesso a esta aplicação.";
"HockeyAuthenticationViewControllerDataEmailDescription" = "Introduza o endereço de e-mail da sua conta HockeyApp para autorizar o acesso a esta aplicação.";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "exemplo@email.com";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "email@exemplo.com";
"HockeyAuthenticationViewControllerPasswordPlaceholder" = "Necessário";
"HockeyAuthenticationViewControllerEmailDescription" = "E-mail";
"HockeyAuthenticationViewControllerPasswordDescription" = "Palavra-passe";
@ -257,6 +257,9 @@
/* Error presented to the user if authentication failed because of networking issues */
"HockeyAuthenticationViewControllerNetworkError" = "Falha ao autorizar porque provavelmente o dispositivo não tem ligação à Internet. Tente novamente.";
/* Error presented to the user if authentication could not be stored on the device */
"HockeyAuthenticationViewControllerStorageError" = "Your authentication token could not be stored due to a keychain error. Please contact the developer of the app.";
"HockeyAuthenticationFailedAuthenticate" = "Falha ao autorizar. Tente novamente ou contacte o programador desta aplicação.";
"HockeyAuthenticationNotMember" = "Não está autorizado a utilizar esta aplicação. Contacte o programador desta aplicação.";

View File

@ -231,7 +231,7 @@
"HockeyFeedbackUserDataEmail" = "E-mail";
/* Email Placeholder */
"HockeyFeedbackUserDataEmailPlaceholder" = "exemplo@email.com";
"HockeyFeedbackUserDataEmailPlaceholder" = "email@exemplo.com";
/* Authenticator */
@ -249,7 +249,7 @@
/* BITAuthenticatorAuthTypeEmail and BITAuthenticatorAuthTypeEmailAndPassword */
"HockeyAuthenticationViewControllerDataEmailAndPasswordDescription" = "Informe seu e-mail e senha da conta do HockeyApp para autorizar o acesso a este aplicativo.";
"HockeyAuthenticationViewControllerDataEmailDescription" = "Informe seu e-mail da conta do HockeyApp para autorizar o acesso a este aplicativo.";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "exemplo@email.com";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "email@exemplo.com";
"HockeyAuthenticationViewControllerPasswordPlaceholder" = "Necessário";
"HockeyAuthenticationViewControllerEmailDescription" = "E-mail";
"HockeyAuthenticationViewControllerPasswordDescription" = "Senha";
@ -257,6 +257,9 @@
/* Error presented to the user if authentication failed because of networking issues */
"HockeyAuthenticationViewControllerNetworkError" = "Não foi possível autorizar porque seu dispositivo parece estar desconectado da Internet. Tente novamente.";
/* Error presented to the user if authentication could not be stored on the device */
"HockeyAuthenticationViewControllerStorageError" = "Your authentication token could not be stored due to a keychain error. Please contact the developer of the app.";
"HockeyAuthenticationFailedAuthenticate" = "Falha ao autorizar. Tente novamente ou contate o desenvolvedor deste aplicativo.";
"HockeyAuthenticationNotMember" = "Você não tem autorização para usar este aplicativo. Contate o desenvolvedor deste aplicativo.";

View File

@ -231,7 +231,7 @@
"HockeyFeedbackUserDataEmail" = "E-mail";
/* Email Placeholder */
"HockeyFeedbackUserDataEmailPlaceholder" = "exemplu@email.ro";
"HockeyFeedbackUserDataEmailPlaceholder" = "email@exemplu.ro";
/* Authenticator */
@ -249,7 +249,7 @@
/* BITAuthenticatorAuthTypeEmail and BITAuthenticatorAuthTypeEmailAndPassword */
"HockeyAuthenticationViewControllerDataEmailAndPasswordDescription" = "Please enter your HockeyApp account's email address and password to authorize access to this app.";
"HockeyAuthenticationViewControllerDataEmailDescription" = "Please enter your HockeyApp account's email address to authorize access to this app.";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "exemplu@email.ro";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "email@exemplu.ro";
"HockeyAuthenticationViewControllerPasswordPlaceholder" = "Required";
"HockeyAuthenticationViewControllerEmailDescription" = "E-mail";
"HockeyAuthenticationViewControllerPasswordDescription" = "Password";
@ -257,6 +257,9 @@
/* Error presented to the user if authentication failed because of networking issues */
"HockeyAuthenticationViewControllerNetworkError" = "Failed to authorize because your device appears to be disconnected from the Internet. Please try again.";
/* Error presented to the user if authentication could not be stored on the device */
"HockeyAuthenticationViewControllerStorageError" = "Your authentication token could not be stored due to a keychain error. Please contact the developer of the app.";
"HockeyAuthenticationFailedAuthenticate" = "Failed to authorize. Please try again or contact the developer of this app.";
"HockeyAuthenticationNotMember" = "You are not authorized to use this app. Please contact the developer of this app.";

View File

@ -231,7 +231,7 @@
"HockeyFeedbackUserDataEmail" = "Email";
/* Email Placeholder */
"HockeyFeedbackUserDataEmailPlaceholder" = "example@email.com";
"HockeyFeedbackUserDataEmailPlaceholder" = "email@example.com";
/* Authenticator */
@ -249,7 +249,7 @@
/* BITAuthenticatorAuthTypeEmail and BITAuthenticatorAuthTypeEmailAndPassword */
"HockeyAuthenticationViewControllerDataEmailAndPasswordDescription" = "Введите email и пароль аккаунта HockeyApp, чтобы авторизовать доступ к этому приложению.";
"HockeyAuthenticationViewControllerDataEmailDescription" = "Введите email аккаунта HockeyApp, чтобы авторизовать доступ к этому приложению.";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "example@email.com";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "email@example.com";
"HockeyAuthenticationViewControllerPasswordPlaceholder" = "Обязательное поле";
"HockeyAuthenticationViewControllerEmailDescription" = "Email";
"HockeyAuthenticationViewControllerPasswordDescription" = "Пароль";
@ -257,6 +257,9 @@
/* Error presented to the user if authentication failed because of networking issues */
"HockeyAuthenticationViewControllerNetworkError" = "Не удалось авторизоваться, так как ваше устройство не подключено к интернету. Попробуйте еще раз ";
/* Error presented to the user if authentication could not be stored on the device */
"HockeyAuthenticationViewControllerStorageError" = "Your authentication token could not be stored due to a keychain error. Please contact the developer of the app.";
"HockeyAuthenticationFailedAuthenticate" = "Авторизация не удалась. Попробуйте еще раз или свяжитесь с разработчиком приложения.";
"HockeyAuthenticationNotMember" = "У вас нет разрешения использовать это приложение. Обратитесь к разработчику приложения.";

View File

@ -231,7 +231,7 @@
"HockeyFeedbackUserDataEmail" = "邮件";
/* Email Placeholder */
"HockeyFeedbackUserDataEmailPlaceholder" = "example@email.com";
"HockeyFeedbackUserDataEmailPlaceholder" = "email@example.com";
/* Authenticator */
@ -249,7 +249,7 @@
/* BITAuthenticatorAuthTypeEmail and BITAuthenticatorAuthTypeEmailAndPassword */
"HockeyAuthenticationViewControllerDataEmailAndPasswordDescription" = "请输入你的 HockeyApp 帐户的电子邮件和密码来授权访问这个 app。";
"HockeyAuthenticationViewControllerDataEmailDescription" = "请输入你的 HockeyApp 帐户的电子邮件来授权访问这个 app。";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "example@email.com";
"HockeyAuthenticationViewControllerEmailPlaceholder" = "email@example.com";
"HockeyAuthenticationViewControllerPasswordPlaceholder" = "必需的";
"HockeyAuthenticationViewControllerEmailDescription" = "邮件";
"HockeyAuthenticationViewControllerPasswordDescription" = "密码";
@ -257,6 +257,9 @@
/* Error presented to the user if authentication failed because of networking issues */
"HockeyAuthenticationViewControllerNetworkError" = "你设备的 Internet 连接似乎已断开,导致授权失败。请再试一次。";
/* Error presented to the user if authentication could not be stored on the device */
"HockeyAuthenticationViewControllerStorageError" = "Your authentication token could not be stored due to a keychain error. Please contact the developer of the app.";
"HockeyAuthenticationFailedAuthenticate" = "授权错误。请再试一次或联系这个 app 的开发人员。";
"HockeyAuthenticationNotMember" = "你未获授权使用这个程序。请联系这个 app 的开发人员。";

View File

@ -127,7 +127,6 @@
1EAF20AA162DC0F600957B1D /* feedbackActiviy.png in Resources */ = {isa = PBXBuildFile; fileRef = 1EAF20A6162DC0F600957B1D /* feedbackActiviy.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 */; };
1EC69F601615001500808FD9 /* BITHockeyManagerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EC69F5D1615001500808FD9 /* BITHockeyManagerPrivate.h */; };
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 */; };
1EF95CAA162CB314000AE3AD /* BITFeedbackComposeViewControllerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF95CA9162CB313000AE3AD /* BITFeedbackComposeViewControllerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -284,7 +283,6 @@
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>"; };
1EB52FC3167B73D400C801D5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/HockeySDK.strings; sourceTree = "<group>"; };
1EC69F5D1615001500808FD9 /* BITHockeyManagerPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITHockeyManagerPrivate.h; 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>"; };
1EF95CA5162CB036000AE3AD /* BITFeedbackActivity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITFeedbackActivity.m; sourceTree = "<group>"; };
@ -544,6 +542,7 @@
indentWidth = 2;
sourceTree = "<group>";
tabWidth = 2;
usesTabs = 0;
};
E400561B148D79B500EB22B9 /* Products */ = {
isa = PBXGroup;
@ -589,7 +588,6 @@
1E94F9DE16E912DD006570AD /* StoreUpdate */,
E41EB465148D7BF50015DEDC /* BITHockeyManager.h */,
E41EB466148D7BF50015DEDC /* BITHockeyManager.m */,
1EC69F5D1615001500808FD9 /* BITHockeyManagerPrivate.h */,
1E5955FA15B7877A00A03429 /* BITHockeyManagerDelegate.h */,
1E71509A15B5C76F004E88FF /* HockeySDK.h */,
1E84DB3317E0977C00AC83FD /* HockeySDKFeatureConfig.h */,
@ -666,7 +664,6 @@
E405266217A2AD300096359C /* BITFeedbackManagerDelegate.h in Headers */,
1E49A4D0161222B900463151 /* BITWebTableViewCell.h in Headers */,
1E49A4D8161222D400463151 /* HockeySDKPrivate.h in Headers */,
1EC69F601615001500808FD9 /* BITHockeyManagerPrivate.h in Headers */,
E48A3DEC17B3ED1C00924C3D /* BITAuthenticator.h in Headers */,
1E754E601621FBB70070AB92 /* BITCrashReportTextFormatter.h in Headers */,
1E84DB3417E099BA00AC83FD /* HockeySDKFeatureConfig.h in Headers */,
@ -836,7 +833,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
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\nTEMP_DIR=${PRODUCTS_DIR}/Temp\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\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\"\ncd \"${TEMP_DIR}\"\nzip -yr \"../${FMK_NAME}-iOS-${VERSION_STRING}.zip\" \"./${FMK_NAME}.embeddedframework\" \"./CHANGELOG\" \"./README.md\" \"./LICENSE\" \"./${HOCKEYSDK_DOCSET_VERSION_NAME}.docset\" -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\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";
};
1E8E66B215BC3D8200632A2E /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
@ -1131,6 +1128,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
@ -1265,6 +1263,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
@ -1299,6 +1298,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0500"
version = "1.3">
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
@ -20,6 +20,20 @@
ReferencedContainer = "container:HockeySDK.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "1E5A458F16F0DFC200B55C04"
BuildableName = "HockeySDKTests.octest"
BlueprintName = "HockeySDKTests"
ReferencedContainer = "container:HockeySDK.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
@ -27,6 +41,24 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "CodeCoverage">
<PostActions>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
<ActionContent
title = "Run Script"
scriptText = "cd ${SRCROOT}/../Vendor/XcodeCoverage&#10;./getcov&#10;">
<EnvironmentBuildable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "1E5A458F16F0DFC200B55C04"
BuildableName = "HockeySDKTests.octest"
BlueprintName = "HockeySDKTests"
ReferencedContainer = "container:HockeySDK.xcodeproj">
</BuildableReference>
</EnvironmentBuildable>
</ActionContent>
</ExecutionAction>
</PostActions>
<Testables>
<TestableReference
skipped = "NO">

View File

@ -77,7 +77,7 @@ static void *kInstallationIdentification = &kInstallationIdentification;
NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *json = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSDictionary *json = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
return json;
}
@ -105,7 +105,6 @@ static void *kInstallationIdentification = &kInstallationIdentification;
#pragma mark - Initial defaults
- (void) testDefaultValues {
assertThatBool(_sut.automaticMode, equalToBool(YES));
assertThatBool(_sut.restrictApplicationUsage, equalToBool(NO));
assertThatBool(_sut.isIdentified, equalToBool(NO));
assertThatBool(_sut.isValidated, equalToBool(NO));
@ -259,7 +258,7 @@ static void *kInstallationIdentification = &kInstallationIdentification;
_sut.identificationType = BITAuthenticatorIdentificationTypeHockeyAppUser;
[_sut validateWithCompletion:^(BOOL validated, NSError *error) {
assertThatBool(validated, equalToBool(NO));
assertThatInt(error.code, equalToInt(BITAuthenticatorNotIdentified));
assertThatLong(error.code, equalToLong(BITAuthenticatorNotIdentified));
}];
}
@ -301,16 +300,6 @@ static void *kInstallationIdentification = &kInstallationIdentification;
}
#pragma mark - Lifetime checks
- (void) testThatAuthenticationTriggersOnStart {
id delegateMock = mockProtocol(@protocol(BITAuthenticatorDelegate));
_sut.delegate = delegateMock;
_sut.identificationType = BITAuthenticatorIdentificationTypeDevice;
[_sut startManager];
[verify(delegateMock) authenticator:_sut willShowAuthenticationController:(id)anything()];
}
- (void) testThatValidationTriggersOnDidBecomeActive {
id delegateMock = mockProtocol(@protocol(BITAuthenticatorDelegate));
_sut.delegate = delegateMock;

View File

@ -20,7 +20,6 @@
#import "BITCrashManagerPrivate.h"
#import "BITHockeyBaseManager.h"
#import "BITHockeyBaseManagerPrivate.h"
#import "BITHockeyManagerPrivate.h"
#import "BITTestHelper.h"

View File

@ -50,7 +50,7 @@
NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *json = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSDictionary *json = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
return json;
}
@ -115,25 +115,25 @@
#pragma mark - Convenience methods
- (void) testThatGetPathCreatesAndEnquesAnOperation {
assertThatUnsignedInt(_sut.operationQueue.operationCount, equalToUnsignedInt(0));
assertThatUnsignedLong(_sut.operationQueue.operationCount, equalToUnsignedLong(0));
[given([_sut operationWithURLRequest:(id)anything()
completion:nil]) willReturn:[NSOperation new]];
[_sut getPath:@"endpoint"
parameters:nil
completion:nil];
assertThatUnsignedInt(_sut.operationQueue.operationCount, equalToUnsignedInt(1));
assertThatUnsignedLong(_sut.operationQueue.operationCount, equalToUnsignedLong(1));
}
- (void) testThatPostPathCreatesAndEnquesAnOperation {
assertThatUnsignedInt(_sut.operationQueue.operationCount, equalToUnsignedInt(0));
assertThatUnsignedLong(_sut.operationQueue.operationCount, equalToUnsignedLong(0));
[given([_sut operationWithURLRequest:nil
completion:nil]) willReturn:[NSOperation new]];
[_sut postPath:@"endpoint"
parameters:nil
completion:nil];
assertThatUnsignedInt(_sut.operationQueue.operationCount, equalToUnsignedInt(1));
assertThatUnsignedLong(_sut.operationQueue.operationCount, equalToUnsignedLong(1));
}
#pragma mark - Completion Tests
@ -143,12 +143,12 @@
#pragma mark - HTTPOperation enqueuing / cancellation
- (void) testThatOperationIsQueued {
assertThatUnsignedInt(_sut.operationQueue.operationCount, equalToUnsignedInt(0));
assertThatUnsignedLong(_sut.operationQueue.operationCount, equalToUnsignedLong(0));
[_sut.operationQueue setSuspended:YES];
BITHTTPOperation *op = [BITHTTPOperation new];
[_sut enqeueHTTPOperation:op];
assertThatUnsignedInt(_sut.operationQueue.operationCount, equalToUnsignedInt(1));
assertThatUnsignedLong(_sut.operationQueue.operationCount, equalToUnsignedLong(1));
}
- (void) testThatOperationCancellingMatchesAllOperationsWithNilMethod {
@ -162,9 +162,9 @@
completion:nil]];
[_sut enqeueHTTPOperation:[_sut operationWithURLRequest:requestPost
completion:nil]];
assertThatUnsignedInt(_sut.operationQueue.operationCount, equalToUnsignedInt(3));
assertThatUnsignedLong(_sut.operationQueue.operationCount, equalToUnsignedLong(3));
NSUInteger numCancelled = [_sut cancelOperationsWithPath:nil method:nil];
assertThatUnsignedInt(numCancelled, equalToUnsignedInt(3));
assertThatUnsignedLong(numCancelled, equalToUnsignedLong(3));
}
- (void) testThatOperationCancellingMatchesAllOperationsWithNilPath {
@ -178,9 +178,9 @@
completion:nil]];
[_sut enqeueHTTPOperation:[_sut operationWithURLRequest:requestPost
completion:nil]];
assertThatUnsignedInt(_sut.operationQueue.operationCount, equalToUnsignedInt(3));
assertThatUnsignedLong(_sut.operationQueue.operationCount, equalToUnsignedLong(3));
NSUInteger numCancelled = [_sut cancelOperationsWithPath:nil method:nil];
assertThatUnsignedInt(numCancelled, equalToUnsignedInt(3));
assertThatUnsignedLong(numCancelled, equalToUnsignedLong(3));
}
@ -196,9 +196,9 @@
completion:nil]];
[_sut enqeueHTTPOperation:[_sut operationWithURLRequest:requestPost
completion:nil]];
assertThatUnsignedInt(_sut.operationQueue.operationCount, equalToUnsignedInt(3));
assertThatUnsignedLong(_sut.operationQueue.operationCount, equalToUnsignedLong(3));
NSUInteger numCancelled = [_sut cancelOperationsWithPath:@"Another/acas" method:nil];
assertThatUnsignedInt(numCancelled, equalToUnsignedInt(1));
assertThatUnsignedLong(numCancelled, equalToUnsignedLong(1));
}
- (void) testThatOperationCancellingMatchesAllOperationsWithSetMethod {
@ -211,9 +211,9 @@
completion:nil]];
[_sut enqeueHTTPOperation:[_sut operationWithURLRequest:requestPost
completion:nil]];
assertThatUnsignedInt(_sut.operationQueue.operationCount, equalToUnsignedInt(3));
assertThatUnsignedLong(_sut.operationQueue.operationCount, equalToUnsignedLong(3));
NSUInteger numCancelled = [_sut cancelOperationsWithPath:nil method:@"POST"];
assertThatUnsignedInt(numCancelled, equalToUnsignedInt(1));
assertThatUnsignedLong(numCancelled, equalToUnsignedLong(1));
}
- (void) testThatOperationCancellingMatchesAllOperationsWithSetMethodAndPath {
@ -226,9 +226,9 @@
completion:nil]];
[_sut enqeueHTTPOperation:[_sut operationWithURLRequest:requestPost
completion:nil]];
assertThatUnsignedInt(_sut.operationQueue.operationCount, equalToUnsignedInt(3));
assertThatUnsignedLong(_sut.operationQueue.operationCount, equalToUnsignedLong(3));
NSUInteger numCancelled = [_sut cancelOperationsWithPath:@"Another/acas" method:@"PUT"];
assertThatUnsignedInt(numCancelled, equalToUnsignedInt(1));
assertThatUnsignedLong(numCancelled, equalToUnsignedLong(1));
}
#pragma mark - Operation Testing

View File

@ -36,46 +36,6 @@
[super tearDown];
}
- (void)testBase64Encoding {
NSString *string = @"Lorem ipsum dolor sit amet.";
NSData *stringData = [string dataUsingEncoding:NSUTF8StringEncoding];
NSString *encodedString = bit_base64String(stringData, stringData.length);
assertThatBool([encodedString isEqualToString:@"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQu"], equalToBool(YES));
}
- (void)testBase64EncodingPreiOS7 {
NSString *string = @"Lorem ipsum dolor sit amet.";
NSData *stringData = [string dataUsingEncoding:NSUTF8StringEncoding];
NSString *encodedString = bit_base64StringPreiOS7(stringData, stringData.length);
assertThatBool([encodedString isEqualToString:@"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQu"], equalToBool(YES));
}
- (void)testBase64EncodingPreiOS7EmptyString {
NSString *string = @"";
NSData *stringData = [string dataUsingEncoding:NSUTF8StringEncoding];
NSString *encodedString = bit_base64StringPreiOS7(stringData, stringData.length);
assertThatBool([encodedString isEqualToString:@""], equalToBool(YES));
}
- (void)testBase64EncodingCompareToiOS7Implementation {
// this requires iOS 7
BOOL result = YES;
SEL base64EncodingSelector = NSSelectorFromString(@"base64EncodedStringWithOptions:");
NSData *dataInstance = [NSData data];
if ([dataInstance respondsToSelector:base64EncodingSelector]) {
NSString *string = @"A dummy whatever strange !* char : test &# more";
NSData *stringData = [string dataUsingEncoding:NSUTF8StringEncoding];
NSString *encodedString = bit_base64String(stringData, stringData.length);
NSString *base64EncodedString = [[string dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];
result = [base64EncodedString isEqualToString:encodedString];
}
assertThatBool(result, equalToBool(YES));
}
- (void)testValidateEmail {
BOOL result = NO;

View File

@ -61,7 +61,7 @@
NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *json = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSDictionary *json = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
return json;
}

View File

@ -1,8 +1,8 @@
#include "HockeySDK.xcconfig"
BUILD_NUMBER = 23
VERSION_STRING = 3.5.0
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) BITHOCKEY_VERSION="@\""$(VERSION_STRING)"\""
BUILD_NUMBER = 24
VERSION_STRING = 3.5.1
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) BITHOCKEY_VERSION="@\""$(VERSION_STRING)"\"" BITHOCKEY_BUILD="@\""$(BUILD_NUMBER)"\""
BIT_ARM_ARCHS = armv7 armv7s arm64
BIT_SIM_ARCHS = x86_64 i386
ARCHS = $(BIT_ARM_ARCHS)

View File

@ -50,11 +50,10 @@
/*
* For release builds, disable unused unwind implementations on targets that do not use them. For non-release
* builds, we include the unwind implementations to allow testing on a broader range of targets; it's possible
* that both compact and/or DWARF unwinding could be implemented by Apple for iOS/ARM in the future.
* builds, we include the unwind implementations to allow testing on a broader range of targets.
*/
#ifdef PLCF_RELEASE_BUILD
# if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
# if defined(__arm__)
# ifndef PLCRASH_FEATURE_UNWIND_DWARF
# define PLCRASH_FEATURE_UNWIND_DWARF 0
# endif
@ -88,13 +87,13 @@
#endif
#ifndef PLCRASH_FEATURE_UNWIND_DWARF
/** If true, enable DWARF unwinding support. DWARF unwinding is currently only used by Mac OS X. */
/** If true, enable DWARF unwinding support. */
# define PLCRASH_FEATURE_UNWIND_DWARF 1
#endif
#ifndef PLCRASH_FEATURE_UNWIND_COMPACT
/** If true, enable compact unwinding support. This is only used by Mac OS X. */
/** If true, enable compact unwinding support. */
# define PLCRASH_FEATURE_UNWIND_COMPACT 1
#endif

View File

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

View File

@ -1,3 +1,55 @@
## Version 3.5.1
- General
- [NEW] Add new initialize to make the configuration easier: `[BITHockeyManager configureWithIdentifier:]`
- [NEW] Add `[BITHockeyManager testIdentifier]` to check if the SDK reaches the server. The result is shown on the HockeyApp website on success.
- [UPDATE] `delegate` can now also be defined using the property directly (instead of using the configureWith methods)
- [UPDATE] Use system provided Base64 encoding implementation
- [UPDATE] Improved logic to choose the right `UIWindow` instance for dialogs
- [BUGFIX] Fix compile issues when excluding all modules but crash reporting
- [BUGFIX] Fix warning on implicit conversion from `CGImageAlphaInfo` to `CGBitmapInfo`
- [BUGFIX] Fix warnings for implicit conversions of `UITextAlignment` and `UILineBreakMode`
- [BUGFIX] Various additional smaller bug fixes
<br /><br/>
- Crash Reporting
- [NEW] Integrated PLCrashReporter 1.2 RC 2
- [NEW] Add `generateTestCrash` method to more quickly test the crash reporting (automatically disabled in App Store environment!)
- [NEW] Add PLCR header files to the public headers in the framework
- [NEW] Add the option to define callbacks that will be executed prior to program termination after a crash has occurred. Callback code has to be async-safe!
- [UPDATE] Change the default of `showAlwaysButton` property to `YES`
- [BUGFIX] Always format date and timestamps in crash report in `en_US_POSIX` locale.
<br /><br/>
- Feedback
- [UPDATE] Use only one activity view controller per UIActivity
- [BUGFIX] Fix delete button appearance in feedback list view on iOS 7 when swiping a feedback message
- [BUGFIX] Comply to -[UIActivity activityDidFinish:] requirements
- [BUGFIX] Use non-deprecated delegate method for `BITFeedbackActivity`
<br /><br/>
- Ad-Hoc/Enterprise Authentication
- [NEW] Automatic authorization when app was installed over the air. This still requires to call `[BITAuthenticator authenticateInstallation];` after calling `startManager`!
- [UPDATE] Set the tintColor in the auth view and modal views navigation controller on iOS 7
- [UPDATE] Show an alert if the authentication token could not be stored into the keychain
- [UPDATE] Use UTF8 encoding for auth data
- [UPDATE] Replace email placeholder texts
- [BUGFIX] Make sure the authentication window is always correctly dismissed
- [BUGFIX] Fixed memory issues
<br /><br/>
- Ad-Hoc/Enterprise Updates
- [NEW] Provide alert option to show mandatory update details
- [NEW] Add button to expired page (and alert) that lets the user check for a new version (can be disabled using `disableUpdateCheckOptionWhenExpired`)
- [UPDATE] Usage metrics are now stored in an independent file instead of using `NSUserDefaults`
<br /><br/>
## Version 3.5.0
- General

View File

@ -1,6 +1,6 @@
## Version 3.5.0
## Version 3.5.1
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.0/docs/docs/Changelog.html)
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.1/docs/docs/Changelog.html)
## Introduction
@ -85,25 +85,17 @@ The SDK runs on devices with iOS 5.0 or higher.
#import "HockeySDK.h"
3. Let the AppDelegate implement the protocols `BITHockeyManagerDelegate`:
3. Search for the method `application:didFinishLaunchingWithOptions:`
<pre><code>@interface AppDelegate(HockeyProtocols) < BITHockeyManagerDelegate > {}
@end</code></pre>
4. Add the following lines:
4. Search for the method `application:didFinishLaunchingWithOptions:`
5. Add the following lines:
[[BITHockeyManager sharedHockeyManager] configureWithBetaIdentifier:@"BETA_IDENTIFIER"
liveIdentifier:@"LIVE_IDENTIFIER"
delegate:self];
[[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_IDENTIFIER"];
[[BITHockeyManager sharedHockeyManager] startManager];
[[BITHockeyManager sharedHockeyManager].authenticator authenticateInstallation];
6. Replace `BETA_IDENTIFIER` with the app identifier of your beta app. If you don't know what the app identifier is or how to find it, please read [this how-to](http://support.hockeyapp.net/kb/how-tos/how-to-find-the-app-identifier).
5. Replace `APP_IDENTIFIER` with the app identifier of your beta app. If you don't know what the app identifier is or how to find it, please read [this how-to](http://support.hockeyapp.net/kb/how-tos/how-to-find-the-app-identifier).
7. Replace `LIVE_IDENTIFIER` with the app identifier of your release app. We suggest to setup different apps on HockeyApp for your test and production builds. You usually will have way more test versions, but your production version usually has way more crash reports. This helps to keep data separated, getting a better overview and less trouble setting the right app versions downloadable for your beta users.
8. If you want to use the beta distribution feature on iOS 7 or later with In-App Updates, restrict versions to specific users or want to know who is actually testing your app, you need to follow the instructions on our guide [Identify and authenticate users of Ad-Hoc or Enterprise builds](HowTo-Authenticating-Users-on-iOS)
6. If you want to see beta analytics, use the beta distribution feature with in-app updates, restrict versions to specific users, or want to know who is actually testing your app, you need to follow the instructions on our guide [Identify and authenticate users of Ad-Hoc or Enterprise builds](HowTo-Authenticating-Users-on-iOS)
*Note:* The SDK is optimized to defer everything possible to a later time while making sure e.g. crashes on startup can also be caught and each module executes other code with a delay some seconds. This ensures that applicationDidFinishLaunching will process as fast as possible and the SDK will not block the startup sequence resulting in a possible kill by the watchdog process.
@ -116,7 +108,7 @@ The Mac Desktop Uploader can provide easy uploading of your app versions to Hock
### Xcode Documentation
This documentation provides integrated help in Xcode for all public APIs and a set of additional tutorials and HowTos.
This documentation provides integrated help in Xcode for all public APIs and a set of additional tutorials and how-tos.
1. Download the [HockeySDK-iOS documentation](http://hockeyapp.net/releases/).
@ -124,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/DocSet`
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.0/](http://hockeyapp.net/help/sdk/ios/3.5.0/)
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.1/](http://hockeyapp.net/help/sdk/ios/3.5.1/)
### Set up with xcconfig

View File

@ -1,6 +1,6 @@
## Version 3.5.0
## Version 3.5.1
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.0/docs/docs/Changelog.html)
- [Changelog](http://www.hockeyapp.net/help/sdk/ios/3.5.1/docs/docs/Changelog.html)
## Introduction
@ -65,25 +65,17 @@ The SDK runs on devices with iOS 5.0 or higher.
#import <HockeySDK/HockeySDK.h>
3. Let the AppDelegate implement the protocols `BITHockeyManagerDelegate`:
3. Search for the method `application:didFinishLaunchingWithOptions:`
<pre><code>@interface AppDelegate(HockeyProtocols) < BITHockeyManagerDelegate > {}
@end</code></pre>
4. Add the following lines:
4. Search for the method `application:didFinishLaunchingWithOptions:`
5. Add the following lines:
[[BITHockeyManager sharedHockeyManager] configureWithBetaIdentifier:@"BETA_IDENTIFIER"
liveIdentifier:@"LIVE_IDENTIFIER"
delegate:self];
[[BITHockeyManager sharedHockeyManager] configureWithIdentifier:@"APP_IDENTIFIER"];
[[BITHockeyManager sharedHockeyManager] startManager];
[[BITHockeyManager sharedHockeyManager].authenticator authenticateInstallation];
6. Replace `BETA_IDENTIFIER` with the app identifier of your beta app. If you don't know what the app identifier is or how to find it, please read [this how-to](http://support.hockeyapp.net/kb/how-tos/how-to-find-the-app-identifier).
5. Replace `APP_IDENTIFIER` with the app identifier of your app. If you don't know what the app identifier is or how to find it, please read [this how-to](http://support.hockeyapp.net/kb/how-tos/how-to-find-the-app-identifier).
7. Replace `LIVE_IDENTIFIER` with the app identifier of your release app. We suggest to setup different apps on HockeyApp for your test and production builds. You usually will have way more test versions, but your production version usually has way more crash reports. This helps to keep data separated, getting a better overview and less trouble setting the right app versions downloadable for your beta users.
8. If you want to use the beta distribution feature on iOS 7 or later with In-App Updates, restrict versions to specific users or want to know who is actually testing your app, you need to follow the instructions on our guide [Identify and authenticate users of Ad-Hoc or Enterprise builds](HowTo-Authenticating-Users-on-iOS)
6. If you want to see beta analytics, use the beta distribution feature with in-app updates, restrict versions to specific users, or want to know who is actually testing your app, you need to follow the instructions on our guide [Identify and authenticate users of Ad-Hoc or Enterprise builds](HowTo-Authenticating-Users-on-iOS)
*Note:* The SDK is optimized to defer everything possible to a later time while making sure e.g. crashes on startup can also be caught and each module executes other code with a delay some seconds. This ensures that applicationDidFinishLaunching will process as fast as possible and the SDK will not block the startup sequence resulting in a possible kill by the watchdog process.
@ -96,11 +88,11 @@ The Mac Desktop Uploader can provide easy uploading of your app versions to Hock
### Xcode Documentation
This documentation provides integrated help in Xcode for all public APIs and a set of additional tutorials and HowTos.
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.0.docset` into ~`/Library/Developer/Shared/Documentation/DocSet`
1. Copy `de.bitstadium.HockeySDK-iOS-3.5.1.docset` into ~`/Library/Developer/Shared/Documentation/DocSet`
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.0/](http://hockeyapp.net/help/sdk/ios/3.5.0/)
The documentation is also available via the following URL: [http://hockeyapp.net/help/sdk/ios/3.5.1/](http://hockeyapp.net/help/sdk/ios/3.5.1/)
### Set up with xcconfig