Registration refactoring - wip.
This commit is contained in:
parent
9ca1037443
commit
c3dff810ad
@ -442,7 +442,6 @@
|
||||
B6B095E81A1D25C5008BFAA6 /* TSStoragePreKeyStoreTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095E21A1D25C5008BFAA6 /* TSStoragePreKeyStoreTests.m */; };
|
||||
B6B095E91A1D25C5008BFAA6 /* TSStorageSignedPreKeyStore.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095E31A1D25C5008BFAA6 /* TSStorageSignedPreKeyStore.m */; };
|
||||
B6B096611A1D25ED008BFAA6 /* TSAccountManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095ED1A1D25ED008BFAA6 /* TSAccountManager.m */; };
|
||||
B6B096621A1D25ED008BFAA6 /* TSNumberVerifier.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095EF1A1D25ED008BFAA6 /* TSNumberVerifier.m */; };
|
||||
B6B096631A1D25ED008BFAA6 /* TSPreKeyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095F11A1D25ED008BFAA6 /* TSPreKeyManager.m */; };
|
||||
B6B096641A1D25ED008BFAA6 /* TSContactThread.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095F51A1D25ED008BFAA6 /* TSContactThread.m */; };
|
||||
B6B096651A1D25ED008BFAA6 /* TSGroupThread.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095F71A1D25ED008BFAA6 /* TSGroupThread.m */; };
|
||||
@ -472,8 +471,6 @@
|
||||
B6B0967D1A1D25ED008BFAA6 /* TSRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B0962A1A1D25ED008BFAA6 /* TSRequest.m */; };
|
||||
B6B0967E1A1D25ED008BFAA6 /* TSRequestAttachment.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B0962C1A1D25ED008BFAA6 /* TSRequestAttachment.m */; };
|
||||
B6B0967F1A1D25ED008BFAA6 /* TSRequestAttachmentId.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B0962E1A1D25ED008BFAA6 /* TSRequestAttachmentId.m */; };
|
||||
B6B096801A1D25ED008BFAA6 /* TSRequestVerificationCodeRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096301A1D25ED008BFAA6 /* TSRequestVerificationCodeRequest.m */; };
|
||||
B6B096811A1D25ED008BFAA6 /* TSServerCodeVerificationRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096321A1D25ED008BFAA6 /* TSServerCodeVerificationRequest.m */; };
|
||||
B6B096821A1D25ED008BFAA6 /* TSSubmitMessageRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096341A1D25ED008BFAA6 /* TSSubmitMessageRequest.m */; };
|
||||
B6B096831A1D25ED008BFAA6 /* TSUploadAttachment.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096361A1D25ED008BFAA6 /* TSUploadAttachment.m */; };
|
||||
B6B096841A1D25ED008BFAA6 /* TSNetworkManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096381A1D25ED008BFAA6 /* TSNetworkManager.m */; };
|
||||
@ -1183,8 +1180,6 @@
|
||||
B6B095E31A1D25C5008BFAA6 /* TSStorageSignedPreKeyStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSStorageSignedPreKeyStore.m; sourceTree = "<group>"; };
|
||||
B6B095EC1A1D25ED008BFAA6 /* TSAccountManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAccountManager.h; sourceTree = "<group>"; };
|
||||
B6B095ED1A1D25ED008BFAA6 /* TSAccountManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAccountManager.m; sourceTree = "<group>"; };
|
||||
B6B095EE1A1D25ED008BFAA6 /* TSNumberVerifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSNumberVerifier.h; sourceTree = "<group>"; };
|
||||
B6B095EF1A1D25ED008BFAA6 /* TSNumberVerifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSNumberVerifier.m; sourceTree = "<group>"; };
|
||||
B6B095F01A1D25ED008BFAA6 /* TSPreKeyManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSPreKeyManager.h; sourceTree = "<group>"; };
|
||||
B6B095F11A1D25ED008BFAA6 /* TSPreKeyManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSPreKeyManager.m; sourceTree = "<group>"; };
|
||||
B6B095F41A1D25ED008BFAA6 /* TSContactThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSContactThread.h; sourceTree = "<group>"; };
|
||||
@ -1243,10 +1238,6 @@
|
||||
B6B0962C1A1D25ED008BFAA6 /* TSRequestAttachment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSRequestAttachment.m; sourceTree = "<group>"; };
|
||||
B6B0962D1A1D25ED008BFAA6 /* TSRequestAttachmentId.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSRequestAttachmentId.h; sourceTree = "<group>"; };
|
||||
B6B0962E1A1D25ED008BFAA6 /* TSRequestAttachmentId.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSRequestAttachmentId.m; sourceTree = "<group>"; };
|
||||
B6B0962F1A1D25ED008BFAA6 /* TSRequestVerificationCodeRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSRequestVerificationCodeRequest.h; sourceTree = "<group>"; };
|
||||
B6B096301A1D25ED008BFAA6 /* TSRequestVerificationCodeRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSRequestVerificationCodeRequest.m; sourceTree = "<group>"; };
|
||||
B6B096311A1D25ED008BFAA6 /* TSServerCodeVerificationRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSServerCodeVerificationRequest.h; sourceTree = "<group>"; };
|
||||
B6B096321A1D25ED008BFAA6 /* TSServerCodeVerificationRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSServerCodeVerificationRequest.m; sourceTree = "<group>"; };
|
||||
B6B096331A1D25ED008BFAA6 /* TSSubmitMessageRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSSubmitMessageRequest.h; sourceTree = "<group>"; };
|
||||
B6B096341A1D25ED008BFAA6 /* TSSubmitMessageRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSSubmitMessageRequest.m; sourceTree = "<group>"; };
|
||||
B6B096351A1D25ED008BFAA6 /* TSUploadAttachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSUploadAttachment.h; sourceTree = "<group>"; };
|
||||
@ -2871,8 +2862,6 @@
|
||||
children = (
|
||||
B6B095EC1A1D25ED008BFAA6 /* TSAccountManager.h */,
|
||||
B6B095ED1A1D25ED008BFAA6 /* TSAccountManager.m */,
|
||||
B6B095EE1A1D25ED008BFAA6 /* TSNumberVerifier.h */,
|
||||
B6B095EF1A1D25ED008BFAA6 /* TSNumberVerifier.m */,
|
||||
B6B095F01A1D25ED008BFAA6 /* TSPreKeyManager.h */,
|
||||
B6B095F11A1D25ED008BFAA6 /* TSPreKeyManager.m */,
|
||||
);
|
||||
@ -2972,10 +2961,6 @@
|
||||
B6B0962C1A1D25ED008BFAA6 /* TSRequestAttachment.m */,
|
||||
B6B0962D1A1D25ED008BFAA6 /* TSRequestAttachmentId.h */,
|
||||
B6B0962E1A1D25ED008BFAA6 /* TSRequestAttachmentId.m */,
|
||||
B6B0962F1A1D25ED008BFAA6 /* TSRequestVerificationCodeRequest.h */,
|
||||
B6B096301A1D25ED008BFAA6 /* TSRequestVerificationCodeRequest.m */,
|
||||
B6B096311A1D25ED008BFAA6 /* TSServerCodeVerificationRequest.h */,
|
||||
B6B096321A1D25ED008BFAA6 /* TSServerCodeVerificationRequest.m */,
|
||||
B6B096331A1D25ED008BFAA6 /* TSSubmitMessageRequest.h */,
|
||||
B6B096341A1D25ED008BFAA6 /* TSSubmitMessageRequest.m */,
|
||||
B6B096351A1D25ED008BFAA6 /* TSUploadAttachment.h */,
|
||||
@ -3441,7 +3426,7 @@
|
||||
ORGANIZATIONNAME = "Open Whisper Systems";
|
||||
TargetAttributes = {
|
||||
D221A088169C9E5E00537ABF = {
|
||||
DevelopmentTeam = DRXTS3ZU8M;
|
||||
DevelopmentTeam = U68MSDN6DR;
|
||||
SystemCapabilities = {
|
||||
com.apple.DataProtection = {
|
||||
enabled = 1;
|
||||
@ -3843,7 +3828,6 @@
|
||||
76EB062418170B33006006FC /* PriorityQueue.m in Sources */,
|
||||
76EB061A18170B33006006FC /* DiscardingLog.m in Sources */,
|
||||
76EB068418170B34006006FC /* ContactDetailTableViewCell.m in Sources */,
|
||||
B6B096621A1D25ED008BFAA6 /* TSNumberVerifier.m in Sources */,
|
||||
B6B0968B1A1D25ED008BFAA6 /* TSStorageManager+SignedPreKeyStore.m in Sources */,
|
||||
B6B0966E1A1D25ED008BFAA6 /* TSGroupMessageManager.m in Sources */,
|
||||
76EB05AC18170B33006006FC /* SrtpSocket.m in Sources */,
|
||||
@ -3862,7 +3846,6 @@
|
||||
B67ADDC41989FF8700E1A773 /* RPServerRequestsManager.m in Sources */,
|
||||
76EB059418170B33006006FC /* HttpManager.m in Sources */,
|
||||
76EB05EC18170B33006006FC /* CallState.m in Sources */,
|
||||
B6B096811A1D25ED008BFAA6 /* TSServerCodeVerificationRequest.m in Sources */,
|
||||
76EB05D218170B33006006FC /* ZrtpInitiator.m in Sources */,
|
||||
76EB05E018170B33006006FC /* NetworkStream.m in Sources */,
|
||||
B6B0968A1A1D25ED008BFAA6 /* TSStorageManager+SessionStore.m in Sources */,
|
||||
@ -4058,7 +4041,6 @@
|
||||
E197B61318BBEC1A00F073E5 /* DesiredBufferDepthController.m in Sources */,
|
||||
76EB064818170B33006006FC /* Zid.m in Sources */,
|
||||
B6B096741A1D25ED008BFAA6 /* TSMessagesManager.m in Sources */,
|
||||
B6B096801A1D25ED008BFAA6 /* TSRequestVerificationCodeRequest.m in Sources */,
|
||||
B6B096661A1D25ED008BFAA6 /* TSContact.m in Sources */,
|
||||
B6B0967D1A1D25ED008BFAA6 /* TSRequest.m in Sources */,
|
||||
76EB05E218170B33006006FC /* SecureEndPoint.m in Sources */,
|
||||
|
||||
@ -21,11 +21,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.8</string>
|
||||
<string>2.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.8</string>
|
||||
<string>2.0</string>
|
||||
<key>LOGS_EMAIL</key>
|
||||
<string>support@whispersystems.org</string>
|
||||
<key>LOGS_URL</key>
|
||||
|
||||
@ -168,14 +168,9 @@
|
||||
|
||||
UIViewController *viewController;
|
||||
|
||||
if (![TSAccountManager isRegistered]) {
|
||||
viewController = [storyboard instantiateViewControllerWithIdentifier:@"RegisterInitialViewController"];
|
||||
} else{
|
||||
viewController = [storyboard instantiateViewControllerWithIdentifier:@"UserInitialViewController"];
|
||||
}
|
||||
BOOL isNewUser = NO;
|
||||
|
||||
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
self.window.rootViewController = viewController;
|
||||
self.window.rootViewController = isNewUser ? viewControllerForNewUser : viewController;
|
||||
[self.window makeKeyAndVisible];
|
||||
|
||||
return YES;
|
||||
|
||||
@ -35,9 +35,6 @@
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<sections/>
|
||||
<variation key="heightClass=regular-widthClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="0.0" y="-44" width="410" height="844"/>
|
||||
</variation>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="MY2-bB-USa" id="kop-Y6-6DR"/>
|
||||
<outlet property="delegate" destination="MY2-bB-USa" id="vmj-PA-2Od"/>
|
||||
@ -993,7 +990,6 @@ Lorem ipsum : Quick explanation of Fingerprints</string>
|
||||
</variation>
|
||||
<connections>
|
||||
<action selector="sendCodeAction:" destination="sL4-Zw-2Og" eventType="touchUpInside" id="T8X-Mx-4I6"/>
|
||||
<segue destination="3Uo-Ow-qOD" kind="show" identifier="codeSentSegue" id="HE2-Vz-KDj"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qJb-ZJ-J5r">
|
||||
@ -1157,6 +1153,7 @@ Lorem ipsum : Quick explanation of Fingerprints</string>
|
||||
<outlet property="countryCodeLabel" destination="TiF-CF-7WU" id="a8o-pE-QzV"/>
|
||||
<outlet property="countryNameLabel" destination="4o4-Xj-5JG" id="dFh-dM-mgC"/>
|
||||
<outlet property="phoneNumberTextField" destination="tTJ-pq-Z9L" id="gPX-pu-twz"/>
|
||||
<segue destination="3Uo-Ow-qOD" kind="show" identifier="codeSent" id="KhC-MI-Evx"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="rfK-ej-7ve" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
@ -2449,9 +2446,6 @@ Licensed under the GPLv3</string>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
||||
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=regular-widthClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="8" y="8" width="584" height="552"/>
|
||||
</variation>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
|
||||
@ -3341,8 +3335,7 @@ Licensed under the GPLv3</string>
|
||||
<exclude reference="ZIm-Uq-bM8"/>
|
||||
</mask>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="0.0" y="20" width="400" height="100"/>
|
||||
<variation key="heightClass=regular-widthClass=compact">
|
||||
<mask key="subviews">
|
||||
<include reference="Ul8-NY-i4c"/>
|
||||
<include reference="gbm-B5-gCc"/>
|
||||
@ -3396,9 +3389,6 @@ Licensed under the GPLv3</string>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<variation key="heightClass=regular-widthClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="0.0" y="128" width="400" height="672"/>
|
||||
</variation>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="bDi-2Q-XOC" id="VPO-ms-bH1"/>
|
||||
<outlet property="delegate" destination="bDi-2Q-XOC" id="rKM-jX-C39"/>
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
#import <CollapsingFutures.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
#define Signal_Accept_Identifier @"Signal_Call_Accept"
|
||||
#define Signal_Decline_Identifier @"Signal_Call_Decline"
|
||||
|
||||
@ -37,6 +36,15 @@
|
||||
|
||||
- (void)registrationWithSuccess:(void (^)())success failure:(void (^)())failure;
|
||||
|
||||
/**
|
||||
* Registers the push token with the RedPhone server, then returns the push token and a signup token to be used to register with TextSecure.
|
||||
*
|
||||
* @param success Success completion block - registering with TextSecure server
|
||||
* @param failure Failure completion block
|
||||
*/
|
||||
|
||||
- (void)registrationAndRedPhoneTokenRequestWithSuccess:(void (^)(NSData* pushToken, NSString* signupToken))success failure:(void (^)())failure;
|
||||
|
||||
/**
|
||||
* The pushNotification and userNotificationFutureSource are accessed by the App Delegate after requested permissions.
|
||||
*/
|
||||
|
||||
@ -58,7 +58,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
[self registrationForPushWithSuccess:^{
|
||||
[self registrationForPushWithSuccess:^(NSData* pushToken){
|
||||
[self registrationForUserNotificationWithSuccess:success failure:^{
|
||||
[self.missingPermissionsAlertView show];
|
||||
failure();
|
||||
@ -109,7 +109,7 @@
|
||||
return self.userNotificationFutureSource.future;
|
||||
}
|
||||
|
||||
- (void)registrationForPushWithSuccess:(void (^)())success failure:(void (^)())failure{
|
||||
- (void)registrationForPushWithSuccess:(void (^)(NSData* pushToken))success failure:(void (^)())failure{
|
||||
TOCFuture *requestPushTokenFuture = [self registerPushNotificationFuture];
|
||||
|
||||
[requestPushTokenFuture catchDo:^(id failureObj) {
|
||||
@ -132,11 +132,35 @@
|
||||
}];
|
||||
|
||||
[registerPushTokenFuture thenDo:^(id value) {
|
||||
success();
|
||||
success(pushToken);
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
- (void)registrationAndRedPhoneTokenRequestWithSuccess:(void (^)(NSData* pushToken, NSString* signupToken))success failure:(void (^)())failure{
|
||||
[self registrationForPushWithSuccess:^(NSData *pushToken) {
|
||||
[RPServerRequestsManager.sharedInstance performRequest:[RPAPICall requestTextSecureVerificationCode] success:^(NSURLSessionDataTask *task, id responseObject) {
|
||||
NSError *error;
|
||||
|
||||
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:&error];
|
||||
NSString* tsToken = [dictionary objectForKey:@"token"];
|
||||
|
||||
if (!tsToken || !pushToken || error) {
|
||||
failure();
|
||||
return;
|
||||
}
|
||||
|
||||
success(pushToken, tsToken);
|
||||
} failure:^(NSURLSessionDataTask *task, NSError *error) {
|
||||
failure();
|
||||
}];
|
||||
} failure:^{
|
||||
failure();
|
||||
}];
|
||||
|
||||
}
|
||||
|
||||
- (void)registrationForUserNotificationWithSuccess:(void (^)())success failure:(void (^)())failure{
|
||||
TOCFuture *registrerUserNotificationFuture = [self registerForUserNotificationsFuture];
|
||||
|
||||
|
||||
@ -35,6 +35,7 @@ typedef NS_ENUM(NSInteger, HTTPMethod) {
|
||||
+ (RPAPICall*)requestVerificationCodeWithVoice;
|
||||
+ (RPAPICall*)verifyVerificationCode:(NSString*)verificationCode;
|
||||
+ (RPAPICall*)registerPushNotificationWithPushToken:(NSData*)pushToken;
|
||||
+ (RPAPICall*)requestTextSecureVerificationCode;
|
||||
+ (RPAPICall*)unregister;
|
||||
|
||||
+ (RPAPICall*)fetchBloomFilter;
|
||||
|
||||
@ -27,8 +27,8 @@
|
||||
@implementation RPAPICall
|
||||
|
||||
+ (RPAPICall*)defaultAPICall {
|
||||
RPAPICall *apiCall = [[RPAPICall alloc] init];
|
||||
apiCall.parameters = @{};
|
||||
RPAPICall *apiCall = [[RPAPICall alloc] init];
|
||||
apiCall.parameters = @{};
|
||||
apiCall.requestSerializer = [self basicAuthenticationSerializer];
|
||||
apiCall.responseSerializer = [AFHTTPResponseSerializer serializer];
|
||||
return apiCall;
|
||||
@ -45,7 +45,7 @@
|
||||
|
||||
+ (RPAPICall*)requestVerificationCodeWithVoice {
|
||||
RPAPICall *apiCall = [self requestVerificationCode];
|
||||
apiCall.endPoint = [apiCall.endPoint stringByAppendingString:@"/voice"];
|
||||
apiCall.endPoint = [apiCall.endPoint stringByAppendingString:@"/voice"];
|
||||
return apiCall;
|
||||
}
|
||||
|
||||
@ -55,94 +55,102 @@
|
||||
apiCall.method = HTTP_PUT;
|
||||
apiCall.endPoint = [NSString stringWithFormat:@"/users/verification/%@", SGNKeychainUtil.localNumber];
|
||||
|
||||
NSData* signalingCipherKey = SGNKeychainUtil.signalingCipherKey;
|
||||
NSData* signalingMacKey = SGNKeychainUtil.signalingMacKey;
|
||||
NSData* signalingCipherKey = SGNKeychainUtil.signalingCipherKey;
|
||||
NSData* signalingMacKey = SGNKeychainUtil.signalingMacKey;
|
||||
NSData* signalingExtraKeyData = SGNKeychainUtil.signalingCipherKey;
|
||||
|
||||
NSString* encodedSignalingKey = @[signalingCipherKey, signalingMacKey, signalingExtraKeyData].ows_concatDatas.encodedAsBase64;
|
||||
apiCall.parameters = @{@"key" : encodedSignalingKey, @"challenge" : verificationCode};
|
||||
apiCall.parameters = @{@"key" : encodedSignalingKey, @"challenge" : verificationCode};
|
||||
|
||||
return apiCall;
|
||||
}
|
||||
|
||||
+ (RPAPICall*)registerPushNotificationWithPushToken:(NSData*)pushToken {
|
||||
RPAPICall *apiCall = [self defaultAPICall];
|
||||
apiCall.method = HTTP_PUT;
|
||||
apiCall.endPoint = [NSString stringWithFormat:@"/apn/%@", pushToken.encodedAsHexString];
|
||||
apiCall.method = HTTP_PUT;
|
||||
apiCall.endPoint = [NSString stringWithFormat:@"/apn/%@", pushToken.encodedAsHexString];
|
||||
return apiCall;
|
||||
}
|
||||
|
||||
+ (RPAPICall*)requestTextSecureVerificationCode{
|
||||
RPAPICall *apiCall = [self defaultAPICall];
|
||||
apiCall.method = HTTP_GET;
|
||||
apiCall.endPoint = [NSString stringWithFormat:@"/users/verification/textsecure"];
|
||||
return apiCall;
|
||||
}
|
||||
|
||||
+ (RPAPICall*)fetchBloomFilter {
|
||||
RPAPICall *apiCall = [self defaultAPICall];
|
||||
apiCall.method = HTTP_GET;
|
||||
apiCall.endPoint = @"/users/directory";
|
||||
RPAPICall *apiCall = [self defaultAPICall];
|
||||
apiCall.method = HTTP_GET;
|
||||
apiCall.endPoint = @"/users/directory";
|
||||
apiCall.requestSerializer = [self otpAuthenticationSerializer];
|
||||
return apiCall;
|
||||
}
|
||||
|
||||
+ (RPAPICall*)unregister {
|
||||
RPAPICall *apiCall = [self defaultAPICall];
|
||||
apiCall.method = HTTP_GET;
|
||||
apiCall.endPoint = @"/users/directory";
|
||||
apiCall.requestSerializer = [self otpAuthenticationSerializer];
|
||||
RPAPICall *apiCall = [self defaultAPICall];
|
||||
apiCall.method = HTTP_GET;
|
||||
apiCall.endPoint = @"/users/directory";
|
||||
apiCall.requestSerializer = [self otpAuthenticationSerializer];
|
||||
return apiCall;
|
||||
}
|
||||
|
||||
+ (RPAPICall*)requestToOpenPortWithSessionId:(int64_t)sessionId {
|
||||
RPAPICall *apiCall = [self defaultAPICall];
|
||||
apiCall.method = HTTP_GET;
|
||||
apiCall.endPoint = [NSString stringWithFormat:@"/open/%lld", sessionId];
|
||||
apiCall.requestSerializer = [self unauthenticatedSerializer];
|
||||
RPAPICall *apiCall = [self defaultAPICall];
|
||||
apiCall.method = HTTP_GET;
|
||||
apiCall.endPoint = [NSString stringWithFormat:@"/open/%lld", sessionId];
|
||||
apiCall.requestSerializer = [self unauthenticatedSerializer];
|
||||
apiCall.responseSerializer = [AFHTTPResponseSerializer serializer];
|
||||
return apiCall;
|
||||
}
|
||||
|
||||
+ (RPAPICall*)requestToRingWithSessionId:(int64_t)sessionId {
|
||||
RPAPICall *apiCall = [self defaultAPICall];
|
||||
apiCall.method = SIGNAL_RING;
|
||||
apiCall.endPoint = [NSString stringWithFormat:@"/session/%lld", sessionId];
|
||||
apiCall.requestSerializer = [self otpAuthenticationSerializer];
|
||||
RPAPICall *apiCall = [self defaultAPICall];
|
||||
apiCall.method = SIGNAL_RING;
|
||||
apiCall.endPoint = [NSString stringWithFormat:@"/session/%lld", sessionId];
|
||||
apiCall.requestSerializer = [self otpAuthenticationSerializer];
|
||||
return apiCall;
|
||||
}
|
||||
|
||||
+ (RPAPICall*)requestToSignalBusyWithSessionId:(int64_t)sessionId {
|
||||
RPAPICall *apiCall = [self defaultAPICall];
|
||||
apiCall.method = SIGNAL_BUSY;
|
||||
apiCall.endPoint = [NSString stringWithFormat:@"/session/%lld", sessionId];
|
||||
apiCall.requestSerializer = [self otpAuthenticationSerializer];
|
||||
RPAPICall *apiCall = [self defaultAPICall];
|
||||
apiCall.method = SIGNAL_BUSY;
|
||||
apiCall.endPoint = [NSString stringWithFormat:@"/session/%lld", sessionId];
|
||||
apiCall.requestSerializer = [self otpAuthenticationSerializer];
|
||||
return apiCall;
|
||||
}
|
||||
|
||||
+ (RPAPICall*)requestToInitiateToRemoteNumber:(PhoneNumber*)remoteNumber {
|
||||
RPAPICall *apiCall = [self defaultAPICall];
|
||||
|
||||
RPAPICall *apiCall = [self defaultAPICall];
|
||||
|
||||
require(remoteNumber != nil);
|
||||
|
||||
|
||||
NSString* formattedRemoteNumber = remoteNumber.toE164;
|
||||
NSString* interopVersionInsert = (CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL == 0)? @"" : [NSString stringWithFormat:@"/%d", CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL];
|
||||
|
||||
apiCall.method = HTTP_GET;
|
||||
apiCall.endPoint = [NSString stringWithFormat:@"/session%@/%@",
|
||||
interopVersionInsert,
|
||||
formattedRemoteNumber];
|
||||
apiCall.requestSerializer = [self otpAuthenticationSerializer];
|
||||
NSString* interopVersionInsert = (CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL == 0)? @"" : [NSString stringWithFormat:@"/%d", CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL];
|
||||
|
||||
apiCall.method = HTTP_GET;
|
||||
apiCall.endPoint = [NSString stringWithFormat:@"/session%@/%@", interopVersionInsert, formattedRemoteNumber];
|
||||
apiCall.requestSerializer = [self otpAuthenticationSerializer];
|
||||
return apiCall;
|
||||
}
|
||||
|
||||
#pragma mark Authorization Headers
|
||||
|
||||
+ (AFHTTPRequestSerializer*)basicAuthenticationSerializer {
|
||||
AFHTTPRequestSerializer *serializer = [AFJSONRequestSerializer serializer];
|
||||
[serializer setAuthorizationHeaderFieldWithUsername:SGNKeychainUtil.localNumber.toE164 password:SGNKeychainUtil.serverAuthPassword];
|
||||
AFHTTPRequestSerializer *serializer = [AFJSONRequestSerializer serializerWithWritingOptions:0];
|
||||
[serializer setValue:[self computeBasicAuthorizationTokenForLocalNumber:SGNKeychainUtil.localNumber andPassword:SGNKeychainUtil.serverAuthPassword]forHTTPHeaderField:@"Authorization"];
|
||||
return serializer;
|
||||
}
|
||||
|
||||
+ (AFHTTPRequestSerializer*)otpAuthenticationSerializer {
|
||||
AFHTTPRequestSerializer *serializer = [AFJSONRequestSerializer serializer];
|
||||
[serializer setAuthorizationHeaderFieldWithUsername:SGNKeychainUtil.localNumber.toE164 password:SGNKeychainUtil.serverAuthPassword];
|
||||
AFHTTPRequestSerializer *serializer = [AFJSONRequestSerializer serializerWithWritingOptions:0];
|
||||
[serializer setValue:[self computeOtpAuthorizationTokenForLocalNumber:SGNKeychainUtil.localNumber andCounterValue:[SGNKeychainUtil getAndIncrementOneTimeCounter] andPassword:SGNKeychainUtil.serverAuthPassword] forHTTPHeaderField:@"Authorization"];
|
||||
return serializer;
|
||||
}
|
||||
|
||||
+ (AFHTTPRequestSerializer*)unauthenticatedSerializer {
|
||||
return [AFHTTPRequestSerializer serializer];
|
||||
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
|
||||
return serializer;
|
||||
}
|
||||
|
||||
+ (NSString*) computeOtpAuthorizationTokenForLocalNumber:(PhoneNumber*)localNumber
|
||||
|
||||
@ -34,10 +34,9 @@ MacrosSingletonImplemention
|
||||
if (self) {
|
||||
HostNameEndPoint *endpoint = Environment.getCurrent.masterServerSecureEndPoint.hostNameEndPoint;
|
||||
NSURL *endPointURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://%@:%hu", endpoint.hostname, endpoint.port]];
|
||||
NSURLSessionConfiguration *sessionConf = NSURLSessionConfiguration.ephemeralSessionConfiguration;
|
||||
NSURLSessionConfiguration *sessionConf = NSURLSessionConfiguration.defaultSessionConfiguration;
|
||||
self.operationManager = [[AFHTTPSessionManager alloc] initWithBaseURL:endPointURL sessionConfiguration:sessionConf];
|
||||
self.operationManager.responseSerializer = [AFJSONResponseSerializer serializer];
|
||||
self.operationManager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
|
||||
self.operationManager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
|
||||
self.operationManager.securityPolicy.allowInvalidCertificates = YES;
|
||||
NSString *certPath = [NSBundle.mainBundle pathForResource:@"whisperReal" ofType:@"cer"];
|
||||
NSData *certData = [NSData dataWithContentsOfFile:certPath];
|
||||
@ -90,7 +89,6 @@ MacrosSingletonImplemention
|
||||
}];
|
||||
|
||||
return [requestFutureSource future];
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -8,9 +8,19 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "TSConstants.h"
|
||||
#import "TSNumberVerifier.h"
|
||||
|
||||
typedef void(^codeVerifierBlock)(TSNumberVerifier *numberVerifier);
|
||||
typedef NS_ENUM(NSUInteger, TSRegistrationFailure) {
|
||||
kTSRegistrationFailureAuthentication,
|
||||
kTSRegistrationFailureNetwork,
|
||||
kTSRegistrationFailureRateLimit,
|
||||
kTSRegistrationFailureWrongCode,
|
||||
kTSRegistrationFailureAlreadyRegistered,
|
||||
kTSRegistrationFailurePrekeys,
|
||||
kTSRegistrationFailurePushID,
|
||||
kTSRegistrationFailureRequest
|
||||
};
|
||||
|
||||
typedef void(^failedVerificationBlock)(TSRegistrationFailure failureType);
|
||||
|
||||
@interface TSAccountManager : NSObject
|
||||
|
||||
@ -47,16 +57,7 @@ typedef void(^codeVerifierBlock)(TSNumberVerifier *numberVerifier);
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
/**
|
||||
* Request a verification challenge
|
||||
*
|
||||
* @param phoneNumber phone number to send verification challenge to
|
||||
* @param transport sms or voice call
|
||||
* @param successBlock block to execute on success of request
|
||||
* @param failureBlock block to execute on failure of request
|
||||
*/
|
||||
|
||||
+ (void)registerWithPhoneNumber:(NSString*)phoneNumber overTransport:(VerificationTransportType)transport success:(codeVerifierBlock)success failure:(failedRegistrationRequestBlock)failureBlock;
|
||||
+ (void)registerWithRedPhoneToken:(NSString*)tsToken pushToken:(NSData*)pushToken success:(successCompletionBlock)successBlock failure:(failedVerificationBlock)failureBlock;
|
||||
|
||||
/**
|
||||
* Register's the device's push notification token with the server
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Constraints.h"
|
||||
#import "NSData+Base64.h"
|
||||
#import "NSData+hexString.h"
|
||||
#import "NSURLSessionDataTask+StatusCode.h"
|
||||
@ -13,27 +14,17 @@
|
||||
#import "SecurityUtils.h"
|
||||
#import "TSNetworkManager.h"
|
||||
#import "TSAccountManager.h"
|
||||
#import "TSRequestVerificationCodeRequest.h"
|
||||
#import "TSStorageManager+keyingMaterial.h"
|
||||
#import "TSNumberVerifier.h"
|
||||
#import "TSPreKeyManager.h"
|
||||
#import "TSRegisterForPushRequest.h"
|
||||
#import "TSRegisterWithTokenRequest.h"
|
||||
|
||||
typedef void(^succesfullPushRegistrationBlock)(NSData *pushToken);
|
||||
|
||||
|
||||
@interface TSAccountManager ()
|
||||
|
||||
@property (nonatomic, retain) NSString *phoneNumberAwaitingVerification;
|
||||
|
||||
@end
|
||||
|
||||
@interface TSNumberVerifier ()
|
||||
|
||||
+ (instancetype)verifierWithPhoneNumber:(NSString*)phoneNumber;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TSAccountManager
|
||||
|
||||
+ (BOOL)isRegistered {
|
||||
@ -64,8 +55,6 @@ typedef void(^succesfullPushRegistrationBlock)(NSData *pushToken);
|
||||
}];
|
||||
|
||||
if (!registrationID) {
|
||||
YapDatabaseConnection *dbConn = [[TSStorageManager sharedManager] databaseConnection];
|
||||
|
||||
int localIdentifier = random()%16380;
|
||||
|
||||
[dbConn readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
@ -80,24 +69,6 @@ typedef void(^succesfullPushRegistrationBlock)(NSData *pushToken);
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
+ (void)registerWithPhoneNumber:(NSString*)phoneNumber overTransport:(VerificationTransportType)transport success:(codeVerifierBlock)successBlock failure:(failedRegistrationRequestBlock)failureBlock{
|
||||
|
||||
[[TSNetworkManager sharedManager] queueAuthenticatedRequest:[[TSRequestVerificationCodeRequest alloc]
|
||||
initRequestForPhoneNumber:phoneNumber transport:transport]
|
||||
success:^(NSURLSessionDataTask *task, id responseObject) {
|
||||
long statuscode = task.statusCode;
|
||||
|
||||
if (statuscode == 200 || statuscode == 204) {
|
||||
successBlock([TSNumberVerifier verifierWithPhoneNumber:phoneNumber]);
|
||||
} else{
|
||||
failureBlock();
|
||||
}
|
||||
|
||||
} failure:^(NSURLSessionDataTask *task, NSError *error) {
|
||||
failureBlock();
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)registerForPushNotifications:(NSData *)pushToken success:(successCompletionBlock)success failure:(failedVerificationBlock)failureBlock{
|
||||
|
||||
NSString *stringToken = [[pushToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<> "]];
|
||||
@ -119,6 +90,68 @@ typedef void(^succesfullPushRegistrationBlock)(NSData *pushToken);
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)registerWithRedPhoneToken:(NSString*)tsToken pushToken:(NSData*)pushToken success:(successCompletionBlock)successBlock failure:(failedVerificationBlock)failureBlock{
|
||||
NSLog(@"PushToken:%@ TStoken: %@", pushToken, tsToken);
|
||||
|
||||
NSString *authToken = [self generateNewAccountAuthenticationToken];
|
||||
NSString *signalingKey = [self generateNewSignalingKeyToken];
|
||||
NSString *phoneNumber = [[tsToken componentsSeparatedByString:@":"] objectAtIndex:0];
|
||||
NSLog(@"Phone Number %@", phoneNumber);
|
||||
|
||||
require(phoneNumber != nil);
|
||||
require(signalingKey != nil);
|
||||
require(authToken != nil);
|
||||
require(pushToken != nil);
|
||||
|
||||
TSRegisterWithTokenRequest *request = [[TSRegisterWithTokenRequest alloc] initWithVerificationToken:tsToken signalingKey:signalingKey authKey:authToken number:phoneNumber];
|
||||
|
||||
[[TSNetworkManager sharedManager] queueAuthenticatedRequest:request success:^(NSURLSessionDataTask *task, id responseObject) {
|
||||
|
||||
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
|
||||
long statuscode = response.statusCode;
|
||||
|
||||
if (statuscode == 200 || statuscode == 204) {
|
||||
|
||||
[TSStorageManager storeServerToken:authToken signalingKey:signalingKey phoneNumber:phoneNumber];
|
||||
|
||||
[self registerForPushNotifications:pushToken success:^{
|
||||
successBlock();
|
||||
} failure:^(TSRegistrationFailure failureType) {
|
||||
failureBlock(kTSRegistrationFailureNetwork);
|
||||
}];
|
||||
} else{
|
||||
failureBlock(kTSRegistrationFailureNetwork);
|
||||
}
|
||||
|
||||
} failure:^(NSURLSessionDataTask *task, NSError *error) {
|
||||
failureBlock(kTSRegistrationFailureNetwork);
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)registerPreKeys:(successCompletionBlock)successBlock failure:(failedVerificationBlock)failureBlock {
|
||||
[TSPreKeyManager registerPreKeysWithSuccess:^{
|
||||
[TSAccountManager setRegistered:YES];
|
||||
successBlock();
|
||||
} failure:failureBlock];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Server keying material
|
||||
|
||||
+ (NSString*)generateNewAccountAuthenticationToken {
|
||||
NSData *authToken = [SecurityUtils generateRandomBytes:16];
|
||||
NSString *authTokenPrint = [[NSData dataWithData:authToken] hexadecimalString];
|
||||
return authTokenPrint;
|
||||
}
|
||||
|
||||
+ (NSString*)generateNewSignalingKeyToken {
|
||||
/*The signalingKey is 32 bytes of AES material (256bit AES) and 20 bytes of Hmac key material (HmacSHA1) concatenated into a 52 byte slug that is base64 encoded. */
|
||||
NSData *signalingKeyToken = [SecurityUtils generateRandomBytes:52];
|
||||
NSString *signalingKeyTokenPrint = [[NSData dataWithData:signalingKeyToken] base64EncodedString];
|
||||
return signalingKeyTokenPrint;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
//
|
||||
// TSNumberVerifier.h
|
||||
// TextSecureKit
|
||||
//
|
||||
// Created by Frederic Jacobs on 31/10/14.
|
||||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "TSConstants.h"
|
||||
|
||||
typedef NS_ENUM(NSUInteger, TSRegistrationFailure) {
|
||||
kTSRegistrationFailureAuthentication,
|
||||
kTSRegistrationFailureNetwork,
|
||||
kTSRegistrationFailureRateLimit,
|
||||
kTSRegistrationFailureWrongCode,
|
||||
kTSRegistrationFailureAlreadyRegistered,
|
||||
kTSRegistrationFailurePrekeys,
|
||||
kTSRegistrationFailurePushID,
|
||||
kTSRegistrationFailureRequest
|
||||
};
|
||||
|
||||
typedef void(^failedVerificationBlock)(TSRegistrationFailure failureType);
|
||||
|
||||
@interface TSNumberVerifier : NSObject
|
||||
|
||||
/**
|
||||
* Verify verification challenge code. To be called only after registerWithPhoneNumber succeeded
|
||||
*
|
||||
* @param verificationCode the verification code received
|
||||
* @param successBlock block to execute on success of request
|
||||
* @param failureBlock block to execute on failure of request
|
||||
*/
|
||||
|
||||
- (void)verifyCode:(NSString*)verificationCode success:(successCompletionBlock)successBlock failure:(failedVerificationBlock)failureBlock;
|
||||
|
||||
+ (void)registerPhoneNumber:(NSString*)phoneNumber withRedPhoneToken:(NSString*)registrationToken success:(successCompletionBlock)successBlock failure:(failedVerificationBlock)failureBlock;
|
||||
|
||||
@end
|
||||
@ -1,149 +0,0 @@
|
||||
//
|
||||
// TSNumberVerifier.m
|
||||
// TextSecureKit
|
||||
//
|
||||
// Created by Frederic Jacobs on 31/10/14.
|
||||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NSData+Base64.h"
|
||||
#import "NSData+hexString.h"
|
||||
|
||||
#import "SecurityUtils.h"
|
||||
#import "TSAccountManager.h"
|
||||
#import "TSRegisterWithTokenRequest.h"
|
||||
#import "TSServerCodeVerificationRequest.h"
|
||||
#import "TSStorageManager+keyingMaterial.h"
|
||||
#import "TSNetworkManager.h"
|
||||
#import "TSNumberVerifier.h"
|
||||
|
||||
#import "TSPrekeyManager.h"
|
||||
|
||||
@interface TSNumberVerifier ()
|
||||
|
||||
@property (nonatomic, readonly) NSString *phoneNumber;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TSNumberVerifier
|
||||
|
||||
- (instancetype)initWithNumber:(NSString*)string {
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
_phoneNumber = string;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)verifierWithPhoneNumber:(NSString*)phoneNumber {
|
||||
TSNumberVerifier *verifier = [[TSNumberVerifier alloc] initWithNumber:phoneNumber];
|
||||
return verifier;
|
||||
}
|
||||
|
||||
+ (void)registerPhoneNumber:(NSString*)phoneNumber withRedPhoneToken:(NSString*)registrationToken success:(successCompletionBlock)successBlock failure:(failedVerificationBlock)failureBlock{
|
||||
NSString *authToken = [self generateNewAccountAuthenticationToken];
|
||||
NSString *signalingKey = [self generateNewSignalingKeyToken];
|
||||
|
||||
TSRegisterWithTokenRequest *request = [[TSRegisterWithTokenRequest alloc] initWithVerificationToken:registrationToken signalingKey:signalingKey authKey:authToken];
|
||||
|
||||
[[TSNetworkManager sharedManager] queueAuthenticatedRequest:request success:^(NSURLSessionDataTask *task, id responseObject) {
|
||||
|
||||
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
|
||||
long statuscode = response.statusCode;
|
||||
|
||||
if (statuscode == 200 || statuscode == 204) {
|
||||
|
||||
[TSStorageManager storeServerToken:authToken signalingKey:signalingKey phoneNumber:phoneNumber];
|
||||
|
||||
[[self class] registerPushIdWithSuccess:successBlock failure:failureBlock];
|
||||
|
||||
} else{
|
||||
failureBlock(kTSRegistrationFailureNetwork);
|
||||
}
|
||||
|
||||
} failure:^(NSURLSessionDataTask *task, NSError *error) {
|
||||
|
||||
}];
|
||||
|
||||
|
||||
}
|
||||
|
||||
- (void)verifyCode:(NSString*)verificationCode success:(successCompletionBlock)successBlock failure:(failedVerificationBlock)failureBlock {
|
||||
NSString *authToken = [[self class] generateNewAccountAuthenticationToken];
|
||||
NSString *signalingKey = [[self class] generateNewSignalingKeyToken];
|
||||
NSString *phoneNumber = self.phoneNumber;
|
||||
|
||||
TSServerCodeVerificationRequest *request = [[TSServerCodeVerificationRequest alloc] initWithVerificationCode:verificationCode signalingKey:signalingKey authKey:authToken];
|
||||
request.numberToValidate = phoneNumber;
|
||||
|
||||
[[TSNetworkManager sharedManager] queueAuthenticatedRequest:request success:^(NSURLSessionDataTask *task, id responseObject) {
|
||||
|
||||
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
|
||||
long statuscode = response.statusCode;
|
||||
|
||||
if (statuscode == 200 || statuscode == 204) {
|
||||
|
||||
[TSStorageManager storeServerToken:authToken signalingKey:signalingKey phoneNumber:phoneNumber];
|
||||
|
||||
[[self class] registerPushIdWithSuccess:successBlock failure:failureBlock];
|
||||
|
||||
} else{
|
||||
failureBlock(kTSRegistrationFailureNetwork);
|
||||
}
|
||||
|
||||
} failure:^(NSURLSessionDataTask *task, NSError *error) {
|
||||
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
|
||||
long statuscode = response.statusCode;
|
||||
|
||||
switch (statuscode) {
|
||||
case 403: // Wrong verification code
|
||||
failureBlock(kTSRegistrationFailureWrongCode);
|
||||
break;
|
||||
case 413: // Rate limit exceeded
|
||||
failureBlock(kTSRegistrationFailureRateLimit);
|
||||
break;
|
||||
case 417: // Number already registered
|
||||
[[self class] registerPushIdWithSuccess:successBlock failure:failureBlock];
|
||||
break;
|
||||
default:
|
||||
failureBlock(kTSRegistrationFailureNetwork);
|
||||
break;
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
|
||||
+ (void)registerPushIdWithSuccess:(successCompletionBlock)successBlock failure:(failedVerificationBlock)failureBlock {
|
||||
[TSAccountManager registerForPushNotifications:[@"A FAKE TOKEN" dataUsingEncoding:NSUTF8StringEncoding] success:^{
|
||||
[self registerPreKeys:successBlock failure:failureBlock];
|
||||
} failure:failureBlock];;
|
||||
|
||||
}
|
||||
|
||||
+ (void)registerPreKeys:(successCompletionBlock)successBlock failure:(failedVerificationBlock)failureBlock {
|
||||
[TSPreKeyManager registerPreKeysWithSuccess:^{
|
||||
[TSAccountManager setRegistered:YES];
|
||||
successBlock();
|
||||
} failure:failureBlock];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Server keying material
|
||||
|
||||
+ (NSString*)generateNewAccountAuthenticationToken {
|
||||
NSData *authToken = [SecurityUtils generateRandomBytes:16];
|
||||
NSString *authTokenPrint = [[NSData dataWithData:authToken] hexadecimalString];
|
||||
return authTokenPrint;
|
||||
}
|
||||
|
||||
+ (NSString*)generateNewSignalingKeyToken {
|
||||
/*The signalingKey is 32 bytes of AES material (256bit AES) and 20 bytes of Hmac key material (HmacSHA1) concatenated into a 52 byte slug that is base64 encoded. */
|
||||
NSData *signalingKeyToken = [SecurityUtils generateRandomBytes:52];
|
||||
NSString *signalingKeyTokenPrint = [[NSData dataWithData:signalingKeyToken] base64EncodedString];
|
||||
return signalingKeyTokenPrint;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "TSConstants.h"
|
||||
#import "TSNumberVerifier.h"
|
||||
#import "TSAccountManager.h"
|
||||
|
||||
@interface TSPreKeyManager : NSObject
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#import <Mantle/Mantle.h>
|
||||
#import "TSConstants.h"
|
||||
|
||||
@interface TSServerMessage : MTLModel<MTLJSONSerializing>
|
||||
|
||||
|
||||
@ -10,6 +10,8 @@
|
||||
|
||||
@interface TSRegisterWithTokenRequest : TSRequest
|
||||
|
||||
- (TSRequest*) initWithVerificationToken:(NSString*)verificationCode signalingKey:(NSString*)signalingKey authKey:(NSString*)authKey;
|
||||
- (TSRequest*) initWithVerificationToken:(NSString*)verificationCode signalingKey:(NSString*)signalingKey authKey:(NSString*)authKey number:(NSString*)number;
|
||||
|
||||
@property NSString *numberToValidate;
|
||||
|
||||
@end
|
||||
|
||||
@ -12,8 +12,14 @@
|
||||
|
||||
@implementation TSRegisterWithTokenRequest
|
||||
|
||||
- (TSRequest*) initWithVerificationToken:(NSString*)verificationToken signalingKey:(NSString*)signalingKey authKey:(NSString*)authKey{
|
||||
self = [super initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/token/%@", textSecureAccountsAPI, verificationToken]]];
|
||||
- (TSRequest*) initWithVerificationToken:(NSString*)verificationCode
|
||||
signalingKey:(NSString*)signalingKey
|
||||
authKey:(NSString*)authKey
|
||||
number:(NSString*)number
|
||||
{
|
||||
self = [super initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/token/%@", textSecureAccountsAPI, verificationCode]]];
|
||||
|
||||
self.numberToValidate = number;
|
||||
|
||||
[self.parameters addEntriesFromDictionary:@{@"signalingKey": signalingKey, @"AuthKey": authKey, @"supportsSMS": @FALSE, @"registrationId": [NSString stringWithFormat:@"%i",[TSAccountManager getOrGenerateRegistrationId]]}];
|
||||
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
//
|
||||
// TSSendSMSVerificationRequest.h
|
||||
// TextSecureiOS
|
||||
//
|
||||
// Created by Frederic Jacobs on 9/29/13.
|
||||
// Copyright (c) 2013 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TSConstants.h"
|
||||
#import "TSRequest.h"
|
||||
|
||||
@interface TSRequestVerificationCodeRequest : TSRequest
|
||||
|
||||
- (TSRequest*)initRequestForPhoneNumber:(NSString*)phoneNumber transport:(VerificationTransportType)transport;
|
||||
|
||||
@end
|
||||
@ -1,25 +0,0 @@
|
||||
//
|
||||
// TSSendSMSVerificationRequest.m
|
||||
// TextSecureiOS
|
||||
//
|
||||
// Created by Frederic Jacobs on 9/29/13.
|
||||
// Copyright (c) 2013 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TSConstants.h"
|
||||
#import "NSString+escape.h"
|
||||
|
||||
#import "TSRequestVerificationCodeRequest.h"
|
||||
|
||||
@implementation TSRequestVerificationCodeRequest
|
||||
|
||||
- (TSRequest*)initRequestForPhoneNumber:(NSString*)phoneNumber transport:(VerificationTransportType)transport{
|
||||
|
||||
self = [super initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/%@/code/%@", textSecureAccountsAPI, (transport == kSMSVerification)? @"sms" : @"voice", [phoneNumber escape]]]];
|
||||
|
||||
[self setHTTPMethod:@"GET"];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -1,18 +0,0 @@
|
||||
//
|
||||
// TSServerCodeVerificationRequest.h
|
||||
// TextSecureiOS
|
||||
//
|
||||
// Created by Frederic Jacobs on 10/12/13.
|
||||
// Copyright (c) 2013 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TSRequest.h"
|
||||
|
||||
@interface TSServerCodeVerificationRequest : TSRequest
|
||||
|
||||
- (TSRequest*) initWithVerificationCode:(NSString*)verificationCode signalingKey:(NSString*)signalingKey authKey:(NSString*)authKey;
|
||||
|
||||
@property (nonatomic, copy) NSString *numberToValidate;
|
||||
|
||||
@end
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
//
|
||||
// TSServerCodeVerificationRequest.m
|
||||
// TextSecureiOS
|
||||
//
|
||||
// Created by Frederic Jacobs on 10/12/13.
|
||||
// Copyright (c) 2013 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TSConstants.h"
|
||||
#import "TSAccountManager.h"
|
||||
#import "TSServerCodeVerificationRequest.h"
|
||||
|
||||
@implementation TSServerCodeVerificationRequest
|
||||
|
||||
- (TSRequest*) initWithVerificationCode:(NSString*)verificationCode signalingKey:(NSString*)signalingKey authKey:(NSString*)authKey {
|
||||
self = [super initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/%@/%@", textSecureAccountsAPI, @"code", verificationCode]]];
|
||||
|
||||
[self.parameters addEntriesFromDictionary:@{@"signalingKey": signalingKey, @"AuthKey": authKey, @"supportsSMS": @FALSE, @"registrationId": [NSString stringWithFormat:@"%i",[TSAccountManager getOrGenerateRegistrationId]]}];
|
||||
|
||||
[self setHTTPMethod:@"PUT"];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@end
|
||||
@ -9,15 +9,11 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AFNetworking/AFHTTPRequestOperationManager.h>
|
||||
#import "TSRequest.h"
|
||||
#import "TSRequestVerificationCodeRequest.h"
|
||||
|
||||
@interface TSNetworkManager : NSObject
|
||||
|
||||
+ (id)sharedManager;
|
||||
/* requests outside of the TS Server */
|
||||
- (void) queueUnauthenticatedRequest:(TSRequest*) request success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))successCompletionBlock failure: (void (^)(AFHTTPRequestOperation *operation, NSError *error)) failureCompletionBlock;
|
||||
|
||||
/* requests inside the TS Server */
|
||||
- (void) queueAuthenticatedRequest:(TSRequest*) request success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure;
|
||||
|
||||
@end
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
#import "TSConstants.h"
|
||||
#import "TSNetworkManager.h"
|
||||
#import "TSRequest.h"
|
||||
#import "TSServerCodeVerificationRequest.h"
|
||||
#import "TSRegisterWithTokenRequest.h"
|
||||
#import "TSStorageManager+keyingMaterial.h"
|
||||
#import "TSUploadAttachment.h"
|
||||
|
||||
@ -52,23 +52,11 @@
|
||||
|
||||
#pragma mark Manager Methods
|
||||
|
||||
- (void) queueUnauthenticatedRequest:(TSRequest*) request success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))successCompletionBlock failure: (void (^)(AFHTTPRequestOperation *operation, NSError *error)) failureCompletionBlock{
|
||||
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
|
||||
|
||||
[operation setCompletionBlockWithSuccess:successCompletionBlock failure:failureCompletionBlock];
|
||||
[self.operationManager.operationQueue addOperation:operation];
|
||||
}
|
||||
|
||||
- (void) queueAuthenticatedRequest:(TSRequest*) request success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure {
|
||||
if ([request isKindOfClass:[TSRequestVerificationCodeRequest class]]) {
|
||||
// The only unauthenticated request is the initial request for a verification code
|
||||
self.operationManager.requestSerializer = [AFJSONRequestSerializer serializer];
|
||||
[self.operationManager GET:[textSecureServerURL stringByAppendingString:request.URL.absoluteString] parameters:request.parameters success:success failure:failure];
|
||||
|
||||
} else if ([request isKindOfClass:[TSServerCodeVerificationRequest class]]){
|
||||
if ([request isKindOfClass:[TSRegisterWithTokenRequest class]]){
|
||||
// We plant the Authorization parameter ourselves, no need to double add.
|
||||
self.operationManager.requestSerializer = [AFJSONRequestSerializer serializer];
|
||||
[self.operationManager.requestSerializer setAuthorizationHeaderFieldWithUsername:((TSServerCodeVerificationRequest*)request).numberToValidate password:[request.parameters objectForKey:@"AuthKey"]];
|
||||
[self.operationManager.requestSerializer setAuthorizationHeaderFieldWithUsername:((TSRegisterWithTokenRequest*)request).numberToValidate password:[request.parameters objectForKey:@"AuthKey"]];
|
||||
|
||||
[request.parameters removeObjectForKey:@"AuthKey"];
|
||||
|
||||
|
||||
@ -30,7 +30,8 @@ typedef enum {
|
||||
#define textSecureHTTPTimeOut 10
|
||||
|
||||
#define textSecureWebSocketAPI @"wss://textsecure-service.whispersystems.org/v1/websocket/"
|
||||
#define textSecureServerURL @"https://textsecure-service.whispersystems.org/"
|
||||
//#define textSecureServerURL @"https://textsecure-service.whispersystems.org/"
|
||||
#define textSecureServerURL @"https://textsecure-service-staging.whispersystems.org/"
|
||||
|
||||
#define textSecureGeneralAPI @"v1"
|
||||
#define textSecureAccountsAPI @"v1/accounts"
|
||||
|
||||
@ -8,6 +8,12 @@
|
||||
|
||||
#import "CodeVerificationViewController.h"
|
||||
|
||||
#import "RPServerRequestsManager.h"
|
||||
#import "LocalizableText.h"
|
||||
#import "PushManager.h"
|
||||
#import "SGNKeychainUtil.h"
|
||||
#import "TSAccountManager.h"
|
||||
|
||||
@interface CodeVerificationViewController ()
|
||||
|
||||
@end
|
||||
@ -31,9 +37,32 @@
|
||||
|
||||
[_challengeTextField resignFirstResponder];
|
||||
|
||||
//Perform verification
|
||||
//TODO: Lock UI interactions
|
||||
|
||||
[self performSegueWithIdentifier:@"verifiedSegue" sender:self];
|
||||
[[RPServerRequestsManager sharedInstance] performRequest:[RPAPICall verifyVerificationCode:_challengeTextField.text] success:^(NSURLSessionDataTask *task, id responseObject) {
|
||||
|
||||
[PushManager.sharedManager registrationAndRedPhoneTokenRequestWithSuccess:^(NSData *pushToken, NSString *signupToken) {
|
||||
[TSAccountManager registerWithRedPhoneToken:signupToken pushToken:pushToken success:^{
|
||||
[self performSegueWithIdentifier:@"verifiedSegue" sender:self];
|
||||
} failure:^(TSRegistrationFailure failureType) {
|
||||
NSLog(@":(");
|
||||
}];
|
||||
} failure:^{
|
||||
|
||||
}];
|
||||
} failure:^(NSURLSessionDataTask *task, NSError *error) {
|
||||
NSString *alertTitle = NSLocalizedString(@"REGISTRATION_ERROR", @"");
|
||||
|
||||
NSHTTPURLResponse* badResponse = (NSHTTPURLResponse*)task.response;
|
||||
if (badResponse.statusCode == 401) {
|
||||
SignalAlertView(alertTitle, REGISTER_CHALLENGE_ALERT_VIEW_BODY);
|
||||
} else if (badResponse.statusCode == 413){
|
||||
SignalAlertView(alertTitle, NSLocalizedString(@"REGISTER_RATE_LIMITING_BODY", @""));
|
||||
} else {
|
||||
NSString *alertBodyString = [NSString stringWithFormat:@"%@ %lu", NSLocalizedString(@"SERVER_CODE", @""),(unsigned long)badResponse.statusCode];
|
||||
SignalAlertView (alertTitle, alertBodyString);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Keyboard notifications
|
||||
@ -44,11 +73,10 @@
|
||||
|
||||
}
|
||||
|
||||
-(void) dismissKeyboardFromAppropriateSubView {
|
||||
- (void)dismissKeyboardFromAppropriateSubView {
|
||||
[self.view endEditing:NO];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
#pragma mark - Navigation
|
||||
|
||||
|
||||
@ -56,8 +56,7 @@
|
||||
NSNumber *cc = [NBPhoneNumberUtil.sharedInstance getCountryCodeForRegion:countryCode];
|
||||
|
||||
_countryCodeLabel.text = [NSString stringWithFormat:@"%@%@",COUNTRY_CODE_PREFIX, cc];
|
||||
//_countryNameLabel.text = [PhoneNumberUtil countryNameFromCountryCode:countryCode];
|
||||
_countryNameLabel.text = @"United States";
|
||||
_countryNameLabel.text = [PhoneNumberUtil countryNameFromCountryCode:countryCode];
|
||||
}
|
||||
|
||||
|
||||
@ -68,10 +67,27 @@
|
||||
PhoneNumber* localNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:phoneNumber];
|
||||
if(localNumber==nil){ return; }
|
||||
|
||||
//TO:DO Disable button
|
||||
|
||||
[_phoneNumberTextField resignFirstResponder];
|
||||
|
||||
// perform RPServerRequest here
|
||||
|
||||
[SGNKeychainUtil setLocalNumberTo:localNumber];
|
||||
|
||||
[[RPServerRequestsManager sharedInstance]performRequest:[RPAPICall requestVerificationCode] success:^(NSURLSessionDataTask *task, id responseObject) {
|
||||
[self performSegueWithIdentifier:@"codeSent" sender:self];
|
||||
} failure:^(NSURLSessionDataTask *task, NSError *error) {
|
||||
|
||||
//TODO: Re-enable button
|
||||
DDLogError(@"Registration failed with information %@", error.description);
|
||||
|
||||
UIAlertView *registrationErrorAV = [[UIAlertView alloc]initWithTitle:REGISTER_ERROR_ALERT_VIEW_TITLE
|
||||
message:REGISTER_ERROR_ALERT_VIEW_BODY
|
||||
delegate:nil
|
||||
cancelButtonTitle:REGISTER_ERROR_ALERT_VIEW_DISMISS
|
||||
otherButtonTitles:nil, nil];
|
||||
|
||||
[registrationErrorAV show];
|
||||
}];
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6250" systemVersion="14A388a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6250" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
|
||||
</dependencies>
|
||||
@ -82,7 +82,7 @@
|
||||
<constraint firstAttribute="width" constant="40" id="CYQ-6u-lWT"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" clipsSubviews="YES" contentMode="left" verticalHuggingPriority="249" text="888-888-8888" textAlignment="center" lineBreakMode="characterWrap" baselineAdjustment="none" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="18" customClass="InteractiveLabel">
|
||||
<label opaque="NO" clipsSubviews="YES" contentMode="left" verticalHuggingPriority="249" text="" textAlignment="center" lineBreakMode="characterWrap" baselineAdjustment="none" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="18" customClass="InteractiveLabel">
|
||||
<rect key="frame" x="63" y="4" width="218" height="24"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Light" family="Helvetica Neue" pointSize="25"/>
|
||||
<color key="textColor" red="0.1176470588" green="0.1215686275" blue="0.098039215690000001" alpha="1" colorSpace="calibratedRGB"/>
|
||||
@ -109,7 +109,7 @@
|
||||
<constraint firstItem="rKW-B9-eAC" firstAttribute="bottom" secondItem="z0U-dT-qTX" secondAttribute="bottom" constant="-4" id="xru-yK-ID7"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="UNK-zX-eBo" userLabel="Button 1" customClass="DialerButtonView">
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="UNK-zX-eBo" userLabel="Button 1" customClass="DialerButtonView">
|
||||
<rect key="frame" x="33" y="75" width="75" height="77"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LNY-2Q-z2w">
|
||||
@ -164,7 +164,7 @@
|
||||
<outlet property="numberLabel" destination="roV-EL-ndH" id="hVU-9n-kbu"/>
|
||||
</connections>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="nH4-4u-iep" userLabel="Button 3" customClass="DialerButtonView">
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nH4-4u-iep" userLabel="Button 3" customClass="DialerButtonView">
|
||||
<rect key="frame" x="211" y="75" width="76" height="77"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dew-Iu-sVI">
|
||||
@ -219,7 +219,7 @@
|
||||
<outlet property="numberLabel" destination="F6Z-OF-f5h" id="ppZ-dj-PFh"/>
|
||||
</connections>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="82K-Nd-cmI" userLabel="Button 2" customClass="DialerButtonView">
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="82K-Nd-cmI" userLabel="Button 2" customClass="DialerButtonView">
|
||||
<rect key="frame" x="123" y="75" width="74" height="77"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1XT-Tr-yuE">
|
||||
@ -274,8 +274,8 @@
|
||||
<outlet property="numberLabel" destination="3i3-dp-B02" id="ieQ-yz-vHQ"/>
|
||||
</connections>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="jeX-1I-jvh" userLabel="Button 4" customClass="DialerButtonView">
|
||||
<rect key="frame" x="33" y="161.5" width="75" height="77"/>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jeX-1I-jvh" userLabel="Button 4" customClass="DialerButtonView">
|
||||
<rect key="frame" x="33" y="162" width="75" height="77"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="AuY-J1-5vG">
|
||||
<rect key="frame" x="0.0" y="0.0" width="75" height="79"/>
|
||||
@ -329,8 +329,8 @@
|
||||
<outlet property="numberLabel" destination="dFw-RO-jPR" id="cml-9w-BQD"/>
|
||||
</connections>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="J4P-Go-2yG" userLabel="Button 5" customClass="DialerButtonView">
|
||||
<rect key="frame" x="123" y="161.5" width="74" height="77"/>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="J4P-Go-2yG" userLabel="Button 5" customClass="DialerButtonView">
|
||||
<rect key="frame" x="123" y="162" width="74" height="77"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="68R-sE-I0I">
|
||||
<rect key="frame" x="0.0" y="0.0" width="74" height="79"/>
|
||||
@ -384,8 +384,8 @@
|
||||
<outlet property="numberLabel" destination="sFz-u3-Wec" id="2zT-TK-KpV"/>
|
||||
</connections>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="0rE-bh-Z8m" userLabel="Button 6" customClass="DialerButtonView">
|
||||
<rect key="frame" x="211" y="161.5" width="76" height="77"/>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0rE-bh-Z8m" userLabel="Button 6" customClass="DialerButtonView">
|
||||
<rect key="frame" x="211" y="162" width="76" height="77"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Qam-v7-y4Y">
|
||||
<rect key="frame" x="0.0" y="0.0" width="76" height="79"/>
|
||||
@ -604,8 +604,8 @@
|
||||
<outlet property="numberLabel" destination="J3B-Zg-DgR" id="1Tx-cs-Unb"/>
|
||||
</connections>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="T7H-JR-Beb" userLabel="Button *" customClass="DialerButtonView">
|
||||
<rect key="frame" x="33" y="327.5" width="75" height="77"/>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="T7H-JR-Beb" userLabel="Button *" customClass="DialerButtonView">
|
||||
<rect key="frame" x="33" y="328" width="75" height="77"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="jQH-w4-imN">
|
||||
<rect key="frame" x="0.0" y="0.0" width="75" height="79"/>
|
||||
@ -658,8 +658,8 @@
|
||||
<outlet property="numberLabel" destination="325-Sb-hA5" id="gxO-5s-17q"/>
|
||||
</connections>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="97j-3K-zxA" userLabel="Button 0" customClass="DialerButtonView">
|
||||
<rect key="frame" x="123" y="327.5" width="74" height="77"/>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="97j-3K-zxA" userLabel="Button 0" customClass="DialerButtonView">
|
||||
<rect key="frame" x="123" y="328" width="74" height="77"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ynu-j8-rAV">
|
||||
<rect key="frame" x="0.0" y="0.0" width="74" height="79"/>
|
||||
@ -712,8 +712,8 @@
|
||||
<outlet property="numberLabel" destination="hKX-df-8oI" id="qKJ-sl-JSm"/>
|
||||
</connections>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="4UG-he-mMF" userLabel="Button #" customClass="DialerButtonView">
|
||||
<rect key="frame" x="211" y="327.5" width="76" height="77"/>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4UG-he-mMF" userLabel="Button #" customClass="DialerButtonView">
|
||||
<rect key="frame" x="211" y="328" width="76" height="77"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bdz-8Z-3vp">
|
||||
<rect key="frame" x="0.0" y="-7" width="76" height="79"/>
|
||||
@ -764,24 +764,24 @@
|
||||
<outlet property="numberLabel" destination="byT-uY-L8H" id="MLp-Uv-nKS"/>
|
||||
</connections>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1" verticalCompressionResistancePriority="1" translatesAutoresizingMaskIntoConstraints="NO" id="gJH-91-Zx5">
|
||||
<rect key="frame" x="0.0" y="403.5" width="320" height="8.5"/>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1" verticalCompressionResistancePriority="1" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gJH-91-Zx5">
|
||||
<rect key="frame" x="0.0" y="404" width="320" height="9"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1" verticalCompressionResistancePriority="1" translatesAutoresizingMaskIntoConstraints="NO" id="8db-9r-Y2f">
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1" verticalCompressionResistancePriority="1" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8db-9r-Y2f">
|
||||
<rect key="frame" x="0.0" y="320" width="320" height="8"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1" verticalCompressionResistancePriority="1" translatesAutoresizingMaskIntoConstraints="NO" id="DOT-fb-PK3">
|
||||
<rect key="frame" x="0.0" y="237.5" width="320" height="7.5"/>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1" verticalCompressionResistancePriority="1" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DOT-fb-PK3">
|
||||
<rect key="frame" x="0.0" y="238" width="320" height="8"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1" verticalCompressionResistancePriority="1" translatesAutoresizingMaskIntoConstraints="NO" id="m52-xI-oom">
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1" verticalCompressionResistancePriority="1" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="m52-xI-oom">
|
||||
<rect key="frame" x="0.0" y="151" width="320" height="8"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="1" verticalCompressionResistancePriority="1" translatesAutoresizingMaskIntoConstraints="NO" id="dAV-fN-l7c">
|
||||
<rect key="frame" x="0.0" y="67" width="320" height="7.5"/>
|
||||
<rect key="frame" x="0.0" y="67" width="320" height="8"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="lessThanOrEqual" priority="1" constant="19" id="Nr1-Ta-njj"/>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user