Provision device from QRCode.
NEEDS DESIGN - will likely have an intermediate "device manager" screen. * extracted QRCode Scanner into re-usable ViewController // FREEBIE
This commit is contained in:
parent
6545161192
commit
84156698c4
3
Podfile
3
Podfile
|
@ -3,7 +3,8 @@ source 'https://github.com/CocoaPods/Specs.git'
|
|||
|
||||
target 'Signal' do
|
||||
pod 'SocketRocket', :git => 'https://github.com/facebook/SocketRocket.git'
|
||||
pod 'SignalServiceKit', :git => 'https://github.com/WhisperSystems/SignalServiceKit.git'
|
||||
#pod 'SignalServiceKit', :git => 'https://github.com/WhisperSystems/SignalServiceKit.git'
|
||||
pod 'SignalServiceKit', path: '../SignalServiceKit'
|
||||
pod 'OpenSSL', '~> 1.0.208'
|
||||
pod 'PastelogKit', '~> 1.3'
|
||||
pod 'FFCircularProgressView', '~> 0.5'
|
||||
|
|
|
@ -119,19 +119,16 @@ DEPENDENCIES:
|
|||
- OpenSSL (~> 1.0.208)
|
||||
- PastelogKit (~> 1.3)
|
||||
- SCWaveformView (~> 1.0)
|
||||
- SignalServiceKit (from `https://github.com/WhisperSystems/SignalServiceKit.git`)
|
||||
- SignalServiceKit (from `../SignalServiceKit`)
|
||||
- SocketRocket (from `https://github.com/facebook/SocketRocket.git`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
SignalServiceKit:
|
||||
:git: https://github.com/WhisperSystems/SignalServiceKit.git
|
||||
:path: "../SignalServiceKit"
|
||||
SocketRocket:
|
||||
:git: https://github.com/facebook/SocketRocket.git
|
||||
|
||||
CHECKOUT OPTIONS:
|
||||
SignalServiceKit:
|
||||
:commit: 1d0b645fc98545ba09d2828c1908689d3052ca4c
|
||||
:git: https://github.com/WhisperSystems/SignalServiceKit.git
|
||||
SocketRocket:
|
||||
:commit: 8096fef47d582bff8ae3758c9ae7af1d55ea53d6
|
||||
:git: https://github.com/facebook/SocketRocket.git
|
||||
|
@ -161,6 +158,6 @@ SPEC CHECKSUMS:
|
|||
UnionFind: c33be5adb12983981d6e827ea94fc7f9e370f52d
|
||||
YapDatabase: 713d4018cfacbd6e77dd430710ca84730e450980
|
||||
|
||||
PODFILE CHECKSUM: 060ff4edf8b7a110984cb2c1ffef3f6e19a6b8b6
|
||||
PODFILE CHECKSUM: fa9416a71a75bf01fde5554c0505c69f88921ab7
|
||||
|
||||
COCOAPODS: 1.0.1
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
45843D1F1D2236B30013E85A /* OWSContactsSearcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 45843D1E1D2236B30013E85A /* OWSContactsSearcher.m */; };
|
||||
45843D201D2236B30013E85A /* OWSContactsSearcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 45843D1E1D2236B30013E85A /* OWSContactsSearcher.m */; };
|
||||
45843D221D223BA10013E85A /* OWSContactsSearcherTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 45843D211D223BA10013E85A /* OWSContactsSearcherTest.m */; };
|
||||
458E38311D6682450094BD24 /* OWSQRCodeScanningViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 458E38301D6682450094BD24 /* OWSQRCodeScanningViewController.m */; };
|
||||
458E38341D66873D0094BD24 /* OWSLinkDeviceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 458E38331D66873D0094BD24 /* OWSLinkDeviceViewController.m */; };
|
||||
458E38371D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 458E38361D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m */; };
|
||||
458E383A1D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 458E38391D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m */; };
|
||||
459C3F0D1C9B3A1B003ACF51 /* TSMessageAdapterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 459C3F0C1C9B3A1B003ACF51 /* TSMessageAdapterTest.m */; };
|
||||
45C681B71D305A580050903A /* OWSCall.m in Sources */ = {isa = PBXBuildFile; fileRef = 45C681B61D305A580050903A /* OWSCall.m */; };
|
||||
45C681B81D305A580050903A /* OWSCall.m in Sources */ = {isa = PBXBuildFile; fileRef = 45C681B61D305A580050903A /* OWSCall.m */; };
|
||||
|
@ -519,6 +523,13 @@
|
|||
45843D1D1D2236B30013E85A /* OWSContactsSearcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSContactsSearcher.h; sourceTree = "<group>"; };
|
||||
45843D1E1D2236B30013E85A /* OWSContactsSearcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSContactsSearcher.m; sourceTree = "<group>"; };
|
||||
45843D211D223BA10013E85A /* OWSContactsSearcherTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSContactsSearcherTest.m; sourceTree = "<group>"; };
|
||||
458E382F1D6682450094BD24 /* OWSQRCodeScanningViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSQRCodeScanningViewController.h; sourceTree = "<group>"; };
|
||||
458E38301D6682450094BD24 /* OWSQRCodeScanningViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSQRCodeScanningViewController.m; sourceTree = "<group>"; };
|
||||
458E38321D66873D0094BD24 /* OWSLinkDeviceViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSLinkDeviceViewController.h; sourceTree = "<group>"; };
|
||||
458E38331D66873D0094BD24 /* OWSLinkDeviceViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSLinkDeviceViewController.m; sourceTree = "<group>"; };
|
||||
458E38351D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSDeviceProvisioningURLParser.h; sourceTree = "<group>"; };
|
||||
458E38361D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDeviceProvisioningURLParser.m; sourceTree = "<group>"; };
|
||||
458E38391D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OWSDeviceProvisioningURLParserTest.m; path = Models/OWSDeviceProvisioningURLParserTest.m; sourceTree = "<group>"; };
|
||||
459C3F0C1C9B3A1B003ACF51 /* TSMessageAdapterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSMessageAdapterTest.m; path = "view controllers/Signals/TSMessageAdapters/TSMessageAdapterTest.m"; sourceTree = "<group>"; };
|
||||
45C681B51D305A580050903A /* OWSCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSCall.h; sourceTree = "<group>"; };
|
||||
45C681B61D305A580050903A /* OWSCall.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSCall.m; sourceTree = "<group>"; };
|
||||
|
@ -1113,13 +1124,6 @@
|
|||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
457F3AB01D1470CF00C51351 /* view controllers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = "view controllers";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
457F3AC01D14A0F700C51351 /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1134,10 +1138,20 @@
|
|||
45C681B61D305A580050903A /* OWSCall.m */,
|
||||
453D28B81D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.h */,
|
||||
453D28B91D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m */,
|
||||
458E38351D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.h */,
|
||||
458E38361D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
458E38381D6699110094BD24 /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
458E38391D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m */,
|
||||
);
|
||||
name = Models;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
459C3F0E1C9B3A20003ACF51 /* TSMessageAdapters */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1678,6 +1692,8 @@
|
|||
B6BADBE61B88D1AC0086A80D /* LockInteractionController.m */,
|
||||
76EB050B18170B33006006FC /* InCallViewController.h */,
|
||||
76EB050C18170B33006006FC /* InCallViewController.m */,
|
||||
458E382F1D6682450094BD24 /* OWSQRCodeScanningViewController.h */,
|
||||
458E38301D6682450094BD24 /* OWSQRCodeScanningViewController.m */,
|
||||
);
|
||||
name = "View Controllers";
|
||||
path = "view controllers";
|
||||
|
@ -1803,7 +1819,7 @@
|
|||
B660F66C1C29867F00687D6E /* test */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
457F3AB01D1470CF00C51351 /* view controllers */,
|
||||
458E38381D6699110094BD24 /* Models */,
|
||||
459C3F0E1C9B3A20003ACF51 /* TSMessageAdapters */,
|
||||
B660F66D1C29867F00687D6E /* audio */,
|
||||
B660F6731C29867F00687D6E /* call */,
|
||||
|
@ -2220,6 +2236,8 @@
|
|||
B66B9F7C1AEAF40500E2E609 /* NotificationSettingsOptionsViewController.m */,
|
||||
FCD274E91A5AFDDB00202277 /* AboutTableViewController.h */,
|
||||
FCD274EA1A5AFDDB00202277 /* AboutTableViewController.m */,
|
||||
458E38321D66873D0094BD24 /* OWSLinkDeviceViewController.h */,
|
||||
458E38331D66873D0094BD24 /* OWSLinkDeviceViewController.m */,
|
||||
);
|
||||
name = Settings;
|
||||
sourceTree = "<group>";
|
||||
|
@ -2614,6 +2632,7 @@
|
|||
76EB060218170B33006006FC /* InitiatorSessionDescriptor.m in Sources */,
|
||||
76EB05FC18170B33006006FC /* CallConnectUtil_Server.m in Sources */,
|
||||
B6DA6B071B8A2F9A00CA6F98 /* AppStoreRating.m in Sources */,
|
||||
458E38311D6682450094BD24 /* OWSQRCodeScanningViewController.m in Sources */,
|
||||
76EB062418170B33006006FC /* PriorityQueue.m in Sources */,
|
||||
B6BADBE71B88D1AC0086A80D /* LockInteractionController.m in Sources */,
|
||||
76EB061A18170B33006006FC /* DiscardingLog.m in Sources */,
|
||||
|
@ -2698,12 +2717,14 @@
|
|||
E197B61118BBEC1A00F073E5 /* AudioProcessor.m in Sources */,
|
||||
FCAC964019FEF99A0046DFC5 /* InboxTableViewCell.m in Sources */,
|
||||
76EB05EA18170B33006006FC /* CallProgress.m in Sources */,
|
||||
458E38371D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m in Sources */,
|
||||
FCFA64B41A24F3880007FB87 /* UIColor+OWS.m in Sources */,
|
||||
76EB05C218170B33006006FC /* DhPacketSharedSecretHashes.m in Sources */,
|
||||
B6C93C4E199567AD00EDF894 /* DebugLogger.m in Sources */,
|
||||
76EB063218170B33006006FC /* Crc32.m in Sources */,
|
||||
E197B62418BBF5BB00F073E5 /* SoundPlayer.m in Sources */,
|
||||
E197B61018BBEC1A00F073E5 /* EncodedAudioPacket.m in Sources */,
|
||||
458E38341D66873D0094BD24 /* OWSLinkDeviceViewController.m in Sources */,
|
||||
76EB063618170B33006006FC /* DataUtil.m in Sources */,
|
||||
E197B60C18BBEC1A00F073E5 /* AudioPacker.m in Sources */,
|
||||
E197B61218BBEC1A00F073E5 /* AudioStretcher.m in Sources */,
|
||||
|
@ -2840,6 +2861,7 @@
|
|||
B660F72C1C29988E00687D6E /* HttpRequestUtil.m in Sources */,
|
||||
B660F72D1C29988E00687D6E /* HttpResponse.m in Sources */,
|
||||
B660F72E1C29988E00687D6E /* HttpManager.m in Sources */,
|
||||
458E383A1D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m in Sources */,
|
||||
B660F72F1C29988E00687D6E /* HttpSocket.m in Sources */,
|
||||
B660F7301C29988E00687D6E /* IpAddress.m in Sources */,
|
||||
B660F7311C29988E00687D6E /* IpEndPoint.m in Sources */,
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSDeviceProvisioningURLParser : NSObject
|
||||
|
||||
@property (readonly, getter=isValid) BOOL valid;
|
||||
@property (nonatomic, readonly) NSString *ephemeralDeviceId;
|
||||
@property (nonatomic, readonly) NSData *publicKey;
|
||||
|
||||
- (instancetype)initWithProvisioningURL:(NSString *)provisioningURL;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSDeviceProvisioningURLParser.h"
|
||||
#import "NSData+Base64.h"
|
||||
#import <AxolotlKit/NSData+keyVersionByte.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NSString *const OWSQueryItemNameEphemeralDeviceIdKey = @"uuid";
|
||||
NSString *const OWSQueryItemNameEncodedPublicKeyKey = @"pub_key";
|
||||
|
||||
@implementation OWSDeviceProvisioningURLParser
|
||||
|
||||
- (instancetype)initWithProvisioningURL:(NSString *)provisioningURL
|
||||
{
|
||||
self = [super init];
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
NSURLComponents *components = [NSURLComponents componentsWithString:provisioningURL];
|
||||
for (NSURLQueryItem *queryItem in [components queryItems]) {
|
||||
if ([queryItem.name isEqualToString:OWSQueryItemNameEphemeralDeviceIdKey]) {
|
||||
_ephemeralDeviceId = queryItem.value;
|
||||
} else if ([queryItem.name isEqualToString:OWSQueryItemNameEncodedPublicKeyKey]) {
|
||||
NSString *encodedPublicKey = queryItem.value;
|
||||
_publicKey = [[NSData dataFromBase64String:encodedPublicKey] removeKeyType];
|
||||
} else {
|
||||
DDLogWarn(@"Unkown query item in provisioning string: %@", queryItem.name);
|
||||
}
|
||||
}
|
||||
|
||||
_valid = _ephemeralDeviceId && _publicKey;
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -1408,8 +1408,8 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="Network Status" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uNq-FV-lwt">
|
||||
<rect key="frame" x="15" y="11" width="200" height="21"/>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Network Status" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uNq-FV-lwt">
|
||||
<rect key="frame" x="15" y="12" width="200" height="19.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="200" id="q6L-Sa-lrA"/>
|
||||
</constraints>
|
||||
|
@ -1474,9 +1474,29 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="dkL-Nz-E6H" style="IBUITableViewCellStyleDefault" id="Xx7-pz-aLN" userLabel="Advanced Cell">
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="hrc-lZ-NeA" style="IBUITableViewCellStyleDefault" id="wZ8-fs-Ylw" userLabel="Linked Devices Cell">
|
||||
<rect key="frame" x="0.0" y="314" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="wZ8-fs-Ylw" id="Ua5-nw-s2z">
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Linked Devices" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hrc-lZ-NeA">
|
||||
<rect key="frame" x="15" y="0.0" width="270" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<segue destination="tWr-1v-Sq9" kind="push" id="LTQ-a4-Xbb"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="dkL-Nz-E6H" style="IBUITableViewCellStyleDefault" id="Xx7-pz-aLN" userLabel="Advanced Cell">
|
||||
<rect key="frame" x="0.0" y="358" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Xx7-pz-aLN" id="pMA-vR-8Ae">
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
|
@ -1492,7 +1512,7 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="qeN-f1-cIQ" style="IBUITableViewCellStyleDefault" id="EI4-kQ-MMA" userLabel="About Cell">
|
||||
<rect key="frame" x="0.0" y="358" width="320" height="44"/>
|
||||
<rect key="frame" x="0.0" y="402" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="EI4-kQ-MMA" id="czg-5p-aVz">
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="43.5"/>
|
||||
|
@ -1513,7 +1533,7 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<tableViewSection id="FdD-MV-PUQ">
|
||||
<cells>
|
||||
<tableViewCell autoresizesSubviews="NO" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="100" id="R82-FT-SEA" userLabel="Destroy Account Cell">
|
||||
<rect key="frame" x="0.0" y="402" width="320" height="100"/>
|
||||
<rect key="frame" x="0.0" y="446" width="320" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="R82-FT-SEA" id="Ok9-fE-WhB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="99.5"/>
|
||||
|
@ -1564,6 +1584,7 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<outlet property="aboutLabel" destination="qeN-f1-cIQ" id="kmc-iU-NK5"/>
|
||||
<outlet property="advancedLabel" destination="dkL-Nz-E6H" id="HUw-SB-apQ"/>
|
||||
<outlet property="destroyAccountButton" destination="4Mk-ly-6fq" id="6Xj-Rb-kfF"/>
|
||||
<outlet property="linkedDevicesLabel" destination="hrc-lZ-NeA" id="VkD-E5-2kW"/>
|
||||
<outlet property="networkStatusHeader" destination="uNq-FV-lwt" id="vca-cC-nXG"/>
|
||||
<outlet property="networkStatusLabel" destination="tg3-dQ-odw" id="l6J-8y-maW"/>
|
||||
<outlet property="notificationsLabel" destination="tRQ-1p-6aT" id="sbi-Q3-Mge"/>
|
||||
|
@ -1577,6 +1598,25 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
</objects>
|
||||
<point key="canvasLocation" x="-2860" y="-3154"/>
|
||||
</scene>
|
||||
<!--Link Device-->
|
||||
<scene sceneID="all-Be-y2s">
|
||||
<objects>
|
||||
<viewController id="tWr-1v-Sq9" customClass="OWSLinkDeviceViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="HSZ-fb-tHK"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="nre-8Q-MvI"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="XYT-jy-1yR">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" title="Link Device" id="OnR-Ni-zff"/>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="lPR-Bk-TZT" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-2415" y="-3154"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="aWR-d3-s5V">
|
||||
<objects>
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSQRCodeScanningViewController.h"
|
||||
|
||||
@interface OWSLinkDeviceViewController : OWSQRCodeScanningViewController
|
||||
|
||||
@end
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSLinkDeviceViewController.h"
|
||||
#import "OWSDeviceProvisioningURLParser.h"
|
||||
#import <SignalServiceKit/ECKeyPair+OWSPrivateKey.h>
|
||||
#import <SignalServiceKit/OWSDeviceProvisioner.h>
|
||||
#import <SignalServiceKit/TSStorageManager+IdentityKeyStore.h>
|
||||
#import <SignalServiceKit/TSStorageManager+keyingMaterial.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation OWSLinkDeviceViewController
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated
|
||||
{
|
||||
[super viewDidAppear:animated];
|
||||
}
|
||||
|
||||
- (void)didDetectQRCodeWithString:(NSString *)string
|
||||
{
|
||||
OWSDeviceProvisioningURLParser *parser = [[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:string];
|
||||
|
||||
if (!parser.isValid) {
|
||||
DDLogError(@"Unable to parse provisioning params from QRCode: %@", string);
|
||||
return;
|
||||
}
|
||||
|
||||
NSData *myPublicKey = [[TSStorageManager sharedManager] identityKeyPair].publicKey;
|
||||
NSData *myPrivateKey = [[TSStorageManager sharedManager] identityKeyPair].ows_privateKey;
|
||||
NSString *accountIdentifier = [TSStorageManager localNumber];
|
||||
|
||||
OWSDeviceProvisioner *provisioner = [[OWSDeviceProvisioner alloc] initWithMyPublicKey:myPublicKey
|
||||
myPrivateKey:myPrivateKey
|
||||
theirPublicKey:parser.publicKey
|
||||
theirEphemeralDeviceId:parser.ephemeralDeviceId
|
||||
accountIdentifier:accountIdentifier];
|
||||
|
||||
[provisioner provisionWithSuccess:^{
|
||||
DDLogInfo(@"Successfully provisioned device.");
|
||||
}
|
||||
failure:^(NSError *error) {
|
||||
DDLogError(@"Failed to provision device with error: %@", error);
|
||||
}];
|
||||
|
||||
// TODO show progress. Maybe even incremental with progress callback in provisioner.
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface OWSQRCodeScanningViewController : UIViewController <AVCaptureMetadataOutputObjectsDelegate>
|
||||
|
||||
@property (nonatomic, strong) AVCaptureSession *session;
|
||||
@property (nonatomic, strong) AVCaptureDevice *device;
|
||||
@property (nonatomic, strong) AVCaptureDeviceInput *input;
|
||||
@property (nonatomic, strong) AVCaptureMetadataOutput *output;
|
||||
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *prevLayer;
|
||||
|
||||
@property (nonatomic, strong) UIView *highlightView;
|
||||
|
||||
@end
|
|
@ -0,0 +1,85 @@
|
|||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSQRCodeScanningViewController.h"
|
||||
#import "UIColor+OWS.h"
|
||||
|
||||
@implementation OWSQRCodeScanningViewController
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
self.title = NSLocalizedString(@"SCAN_KEY", @"");
|
||||
|
||||
self.highlightView = [[UIView alloc] init];
|
||||
self.highlightView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin
|
||||
| UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
|
||||
self.highlightView.layer.borderColor = [UIColor ows_greenColor].CGColor;
|
||||
self.highlightView.layer.borderWidth = 4;
|
||||
[self.view addSubview:self.highlightView];
|
||||
|
||||
self.session = [[AVCaptureSession alloc] init];
|
||||
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
||||
NSError *error = nil;
|
||||
|
||||
self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:&error];
|
||||
if (self.input) {
|
||||
[self.session addInput:self.input];
|
||||
} else {
|
||||
DDLogDebug(@"Error: %@", error);
|
||||
}
|
||||
|
||||
self.output = [[AVCaptureMetadataOutput alloc] init];
|
||||
[self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
|
||||
[self.session addOutput:self.output];
|
||||
|
||||
self.output.metadataObjectTypes = [self.output availableMetadataObjectTypes];
|
||||
|
||||
self.prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
|
||||
self.prevLayer.frame = self.view.bounds;
|
||||
self.prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
|
||||
[self.view.layer insertSublayer:self.prevLayer atIndex:0];
|
||||
|
||||
[self.session startRunning];
|
||||
|
||||
[self.view bringSubviewToFront:self.highlightView];
|
||||
}
|
||||
|
||||
|
||||
- (void)captureOutput:(AVCaptureOutput *)captureOutput
|
||||
didOutputMetadataObjects:(NSArray *)metadataObjects
|
||||
fromConnection:(AVCaptureConnection *)connection
|
||||
{
|
||||
CGRect highlightViewRect = CGRectZero;
|
||||
AVMetadataMachineReadableCodeObject *barCodeObject;
|
||||
NSString *detectionString = nil;
|
||||
NSArray *barCodeTypes = @[ AVMetadataObjectTypeQRCode ];
|
||||
|
||||
for (AVMetadataObject *metadata in metadataObjects) {
|
||||
for (NSString *type in barCodeTypes) {
|
||||
if ([metadata.type isEqualToString:type]) {
|
||||
barCodeObject = (AVMetadataMachineReadableCodeObject *)[self.prevLayer
|
||||
transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject *)metadata];
|
||||
highlightViewRect = barCodeObject.bounds;
|
||||
detectionString = [(AVMetadataMachineReadableCodeObject *)metadata stringValue];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (detectionString != nil) {
|
||||
[self didDetectQRCodeWithString:detectionString];
|
||||
[self.session stopRunning];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self.highlightView.frame = highlightViewRect;
|
||||
}
|
||||
|
||||
- (void)didDetectQRCodeWithString:(NSString *)string
|
||||
{
|
||||
// Override in subclass. Subclass is responsible for dismissing this view controller.
|
||||
DDLogInfo(@"Scanned QRCode with string value: %@", string);
|
||||
}
|
||||
|
||||
|
||||
@end
|
|
@ -4,18 +4,11 @@
|
|||
//
|
||||
// Created by Christine Corbett Moran on 3/29/14.
|
||||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
@interface ScanIdentityBarcodeViewController : UIViewController <AVCaptureMetadataOutputObjectsDelegate>
|
||||
#import "OWSQRCodeScanningViewController.h"
|
||||
|
||||
@property (nonatomic, strong) AVCaptureSession *session;
|
||||
@property (nonatomic, strong) AVCaptureDevice *device;
|
||||
@property (nonatomic, strong) AVCaptureDeviceInput *input;
|
||||
@property (nonatomic, strong) AVCaptureMetadataOutput *output;
|
||||
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *prevLayer;
|
||||
@interface ScanIdentityBarcodeViewController : OWSQRCodeScanningViewController
|
||||
|
||||
@property (nonatomic, strong) UIView *highlightView;
|
||||
@property (nonatomic, strong) NSData *identityKey;
|
||||
|
||||
@end
|
||||
|
|
|
@ -6,104 +6,35 @@
|
|||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NSData+Base64.h"
|
||||
#import "ScanIdentityBarcodeViewController.h"
|
||||
#import "UIColor+OWS.h"
|
||||
|
||||
#import "ScanIdentityBarcodeViewController.h"
|
||||
#import "NSData+Base64.h"
|
||||
|
||||
@implementation ScanIdentityBarcodeViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
- (void)didDetectQRCodeWithString:(NSString *)string
|
||||
{
|
||||
NSData *data = [NSData dataFromBase64String:string];
|
||||
NSString *dialogTitle;
|
||||
NSString *dialogDescription;
|
||||
|
||||
self.title = NSLocalizedString(@"SCAN_KEY", @"");
|
||||
|
||||
self.highlightView = [[UIView alloc] init];
|
||||
self.highlightView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin |
|
||||
UIViewAutoresizingFlexibleRightMargin |
|
||||
UIViewAutoresizingFlexibleBottomMargin;
|
||||
self.highlightView.layer.borderColor = [UIColor ows_greenColor].CGColor;
|
||||
self.highlightView.layer.borderWidth = 4;
|
||||
[self.view addSubview:self.highlightView];
|
||||
|
||||
self.session = [[AVCaptureSession alloc] init];
|
||||
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
||||
NSError *error = nil;
|
||||
|
||||
self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:&error];
|
||||
if (self.input) {
|
||||
[self.session addInput:self.input];
|
||||
if ([data isEqualToData:self.identityKey]) {
|
||||
dialogTitle = NSLocalizedString(@"SCAN_KEY_VERIFIED_TITLE", @"");
|
||||
dialogDescription = NSLocalizedString(@"SCAN_KEY_VERIFIED_TEXT", @"");
|
||||
} else {
|
||||
DDLogDebug(@"Error: %@", error);
|
||||
dialogTitle = NSLocalizedString(@"SCAN_KEY_CONFLICT_TITLE", @"");
|
||||
dialogDescription = NSLocalizedString(@"SCAN_KEY_CONFLICT_TEXT", @"");
|
||||
}
|
||||
|
||||
self.output = [[AVCaptureMetadataOutput alloc] init];
|
||||
[self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
|
||||
[self.session addOutput:self.output];
|
||||
|
||||
self.output.metadataObjectTypes = [self.output availableMetadataObjectTypes];
|
||||
|
||||
self.prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
|
||||
self.prevLayer.frame = self.view.bounds;
|
||||
self.prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
|
||||
[self.view.layer insertSublayer:self.prevLayer atIndex:0];
|
||||
|
||||
[self.session startRunning];
|
||||
|
||||
[self.view bringSubviewToFront:self.highlightView];
|
||||
}
|
||||
|
||||
|
||||
- (void)captureOutput:(AVCaptureOutput *)captureOutput
|
||||
didOutputMetadataObjects:(NSArray *)metadataObjects
|
||||
fromConnection:(AVCaptureConnection *)connection {
|
||||
CGRect highlightViewRect = CGRectZero;
|
||||
AVMetadataMachineReadableCodeObject *barCodeObject;
|
||||
NSString *detectionString = nil;
|
||||
NSArray *barCodeTypes = @[ AVMetadataObjectTypeQRCode ];
|
||||
|
||||
for (AVMetadataObject *metadata in metadataObjects) {
|
||||
for (NSString *type in barCodeTypes) {
|
||||
if ([metadata.type isEqualToString:type]) {
|
||||
barCodeObject = (AVMetadataMachineReadableCodeObject *)[self.prevLayer
|
||||
transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject *)metadata];
|
||||
highlightViewRect = barCodeObject.bounds;
|
||||
detectionString = [(AVMetadataMachineReadableCodeObject *)metadata stringValue];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (detectionString != nil) {
|
||||
NSData *detectionData = [NSData dataFromBase64String:detectionString];
|
||||
|
||||
NSString *dialogTitle;
|
||||
NSString *dialogDescription;
|
||||
|
||||
if ([detectionData isEqualToData:self.identityKey]) {
|
||||
dialogTitle = NSLocalizedString(@"SCAN_KEY_VERIFIED_TITLE", @"");
|
||||
dialogDescription = NSLocalizedString(@"SCAN_KEY_VERIFIED_TEXT", @"");
|
||||
} else {
|
||||
dialogTitle = NSLocalizedString(@"SCAN_KEY_CONFLICT_TITLE", @"");
|
||||
dialogDescription = NSLocalizedString(@"SCAN_KEY_CONFLICT_TEXT", @"");
|
||||
}
|
||||
|
||||
[self.session stopRunning];
|
||||
UIAlertController *controller = [UIAlertController alertControllerWithTitle:dialogTitle
|
||||
message:dialogDescription
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[self presentViewController:controller
|
||||
animated:YES
|
||||
completion:^{
|
||||
[self performSelector:@selector(dismissScannerAfterSuccesfullScan)
|
||||
withObject:nil
|
||||
afterDelay:5];
|
||||
}];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self.highlightView.frame = highlightViewRect;
|
||||
UIAlertController *controller = [UIAlertController alertControllerWithTitle:dialogTitle
|
||||
message:dialogDescription
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[self
|
||||
presentViewController:controller
|
||||
animated:YES
|
||||
completion:^{
|
||||
[self performSelector:@selector(dismissScannerAfterSuccesfullScan) withObject:nil afterDelay:5];
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Action
|
||||
|
@ -111,7 +42,7 @@
|
|||
- (void)dismissScannerAfterSuccesfullScan {
|
||||
[self dismissViewControllerAnimated:YES
|
||||
completion:^{
|
||||
[self closeButtonAction:nil];
|
||||
[self closeButtonAction:nil];
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
@property (strong, nonatomic) IBOutlet UILabel *networkStatusHeader;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *privacyLabel;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *notificationsLabel;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *linkedDevicesLabel;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *advancedLabel;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *aboutLabel;
|
||||
@property (strong, nonatomic) IBOutlet UIButton *destroyAccountButton;
|
||||
|
|
|
@ -33,16 +33,16 @@
|
|||
#define kRegisteredNumberRow 0
|
||||
#define kPrivacyRow 0
|
||||
#define kNotificationRow 1
|
||||
#define kAdvancedRow 2
|
||||
#define kAboutRow 3
|
||||
#define kAdvancedRow 3
|
||||
#define kAboutRow 4
|
||||
#define kNetworkRow 0
|
||||
#define kUnregisterRow 0
|
||||
|
||||
typedef enum {
|
||||
kRegisteredRows = 1,
|
||||
kGeneralRows = 4,
|
||||
kRegisteredRows = 1,
|
||||
kGeneralRows = 5,
|
||||
kNetworkStatusRows = 1,
|
||||
kUnregisterRows = 1,
|
||||
kUnregisterRows = 1,
|
||||
} kRowsForSection;
|
||||
|
||||
typedef enum {
|
||||
|
@ -79,6 +79,8 @@ typedef enum {
|
|||
self.advancedLabel.text = NSLocalizedString(@"SETTINGS_ADVANCED_TITLE", @"");
|
||||
self.aboutLabel.text = NSLocalizedString(@"SETTINGS_ABOUT", @"");
|
||||
self.notificationsLabel.text = NSLocalizedString(@"SETTINGS_NOTIFICATIONS", nil);
|
||||
self.linkedDevicesLabel.text = NSLocalizedString(
|
||||
@"LINKED_DEVICES_LABEL", @"table cell label, when pressed takes you to manage your linked devices.");
|
||||
[self.destroyAccountButton setTitle:NSLocalizedString(@"SETTINGS_DELETE_ACCOUNT_BUTTON", @"")
|
||||
forState:UIControlStateNormal];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSDeviceProvisioningURLParser.h"
|
||||
#import <SignalServiceKit/NSData+Base64.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
@interface OWSDeviceProvisioningURLParserTest : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation OWSDeviceProvisioningURLParserTest
|
||||
|
||||
- (void)testValid
|
||||
{
|
||||
OWSDeviceProvisioningURLParser *parser = [[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:@""];
|
||||
XCTAssertFalse(parser.isValid);
|
||||
|
||||
parser = [[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:@"ts:/?uuid=MTIz"];
|
||||
XCTAssertFalse(parser.isValid);
|
||||
|
||||
parser = [[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:@"ts:/?pub_key=MTIz"];
|
||||
XCTAssertFalse(parser.isValid);
|
||||
|
||||
parser = [[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:@"ts:/uuid=asd&pub_key=MTIz"];
|
||||
XCTAssertFalse(parser.isValid);
|
||||
|
||||
parser = [[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:@"ts:/?uuid=asd&pub_key=MTIz"];
|
||||
XCTAssert(parser.isValid);
|
||||
}
|
||||
|
||||
- (void)testPublicKey
|
||||
{
|
||||
OWSDeviceProvisioningURLParser *parser =
|
||||
[[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:@"ts:/?uuid=asd&pub_key=MTIz"];
|
||||
|
||||
XCTAssertEqualObjects(@"MTIz", [parser.publicKey base64EncodedString]);
|
||||
}
|
||||
|
||||
- (void)testEphemeralDeviceId
|
||||
{
|
||||
OWSDeviceProvisioningURLParser *parser =
|
||||
[[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:@"ts:/?uuid=asd&pub_key=MTIz"];
|
||||
|
||||
XCTAssertEqualObjects(@"asd", parser.ephemeralDeviceId);
|
||||
}
|
||||
|
||||
@end
|
Binary file not shown.
Loading…
Reference in New Issue