Dropbox OAuth2 process done (hard work)

This commit is contained in:
Kilian Hofmann 2016-03-30 19:59:42 +02:00
parent 54229c04fc
commit eb9b485d1c
11 changed files with 187 additions and 51 deletions

View File

@ -25,6 +25,7 @@
E28E10731CA0375F006E2C6B /* ROUTE.plist in Resources */ = {isa = PBXBuildFile; fileRef = E28E10721CA0375F006E2C6B /* ROUTE.plist */; };
E29391CE1CA444F4008EB590 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E29391CD1CA444F4008EB590 /* LaunchScreen.storyboard */; };
E2A927161CA30CEE00606E07 /* SharedDeclerations.m in Sources */ = {isa = PBXBuildFile; fileRef = E2A927151CA30CEE00606E07 /* SharedDeclerations.m */; };
E2B694BC1CAC0C56007B28EF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2B694BB1CAC0C56007B28EF /* Security.framework */; };
E2CC73E31CA2B7C7005B786E /* PERF INIT.plist in Resources */ = {isa = PBXBuildFile; fileRef = E2CC73E21CA2B7C7005B786E /* PERF INIT.plist */; };
/* End PBXBuildFile section */
@ -78,6 +79,7 @@
E29391CD1CA444F4008EB590 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
E2A927141CA30CEE00606E07 /* SharedDeclerations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SharedDeclerations.h; sourceTree = "<group>"; };
E2A927151CA30CEE00606E07 /* SharedDeclerations.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SharedDeclerations.m; sourceTree = "<group>"; };
E2B694BB1CAC0C56007B28EF /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
E2CC73E21CA2B7C7005B786E /* PERF INIT.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "PERF INIT.plist"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -86,6 +88,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
E2B694BC1CAC0C56007B28EF /* Security.framework in Frameworks */,
E28E106D1C9FF93D006E2C6B /* QuartzCore.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -110,6 +113,7 @@
E22EE9C31C9DB7B3001F5BC0 = {
isa = PBXGroup;
children = (
E2B694BB1CAC0C56007B28EF /* Security.framework */,
E28E106C1C9FF93D006E2C6B /* QuartzCore.framework */,
E22EE9CE1C9DB7B3001F5BC0 /* FMC Planner 2 */,
E22EE9E81C9DB7B4001F5BC0 /* FMC Planner 2Tests */,
@ -173,8 +177,6 @@
children = (
E2A9270C1CA2FD6D00606E07 /* Implementation */,
E2A9270B1CA2FD6000606E07 /* Header */,
E2549C741CAB2D3F00562602 /* DropboxV2ObjC.h */,
E2549C751CAB2D3F00562602 /* DropboxV2ObjC.m */,
);
name = ViewControllers;
sourceTree = "<group>";
@ -226,8 +228,9 @@
E2A9270E1CA2FE5200606E07 /* Header */ = {
isa = PBXGroup;
children = (
E2A927141CA30CEE00606E07 /* SharedDeclerations.h */,
E22EE9D21C9DB7B3001F5BC0 /* AppDelegate.h */,
E2549C741CAB2D3F00562602 /* DropboxV2ObjC.h */,
E2A927141CA30CEE00606E07 /* SharedDeclerations.h */,
);
name = Header;
sourceTree = "<group>";
@ -235,9 +238,10 @@
E2A9270F1CA2FE5900606E07 /* Implementation */ = {
isa = PBXGroup;
children = (
E2A927151CA30CEE00606E07 /* SharedDeclerations.m */,
E22EE9D31C9DB7B3001F5BC0 /* AppDelegate.m */,
E2549C751CAB2D3F00562602 /* DropboxV2ObjC.m */,
E22EE9D01C9DB7B3001F5BC0 /* main.m */,
E2A927151CA30CEE00606E07 /* SharedDeclerations.m */,
);
name = Implementation;
sourceTree = "<group>";

View File

@ -2,22 +2,4 @@
<Bucket
type = "1"
version = "2.0">
<Breakpoints>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "FMC Planner 2/DropboxV2ObjC.m"
timestampString = "480986473.401724"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "20"
endingLineNumber = "20"
landmarkName = "-authorizeUserWithToke:"
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>

View File

@ -7,11 +7,13 @@
//
#import "DropboxV2ObjC.h"
#import "ViewControllerServiceMenu.h"
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property(strong, nonatomic) UIWindow *window;
@property(strong, nonatomic) DropboxV2ObjC *dbClient;
@property(strong, nonatomic) UIViewController *smWebView;
@end

View File

@ -14,6 +14,11 @@
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
_dbClient = [[DropboxV2ObjC alloc] init];
NSDictionary *credentials =
[[NSURLCredentialStorage sharedCredentialStorage]
credentialsForProtectionSpace:_dbClient.kDropboxProtectionSpace];
NSURLCredential *credential = [credentials.objectEnumerator nextObject];
_dbClient.token = credential.password;
return YES;
}
@ -53,7 +58,11 @@
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
// Display text
[_dbClient authorizeUserWithToke:url];
[_dbClient authorizeUserWithToke:url
completion:^(void) {
[_smWebView.navigationController
popViewControllerAnimated:YES];
}];
return YES;
}

View File

@ -82,17 +82,6 @@
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="MYC-QY-v42">
<rect key="frame" x="87" y="72" width="147" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="2iN-qg-kf5"/>
<constraint firstAttribute="width" constant="147" id="30a-wW-H5A"/>
</constraints>
<state key="normal" title="Connect to Dropbox"/>
<connections>
<action selector="dbConnect:" destination="NBp-hT-qnu" eventType="touchUpInside" id="Sjs-Vk-aFg"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="n9p-C2-IND">
<rect key="frame" x="91" y="110" width="138" height="30"/>
<constraints>
@ -126,15 +115,36 @@
<segue destination="qw7-1R-cA8" kind="push" identifier="Manage" id="Thn-Z7-qri"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="34X-Rk-O8I">
<rect key="frame" x="142" y="224" width="37" height="30"/>
<state key="normal" title="TEST"/>
<connections>
<action selector="testing:" destination="NBp-hT-qnu" eventType="touchUpInside" id="bcp-H9-7iS"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="MYC-QY-v42">
<rect key="frame" x="73" y="72" width="176" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="2iN-qg-kf5"/>
<constraint firstAttribute="width" constant="176" id="30a-wW-H5A"/>
</constraints>
<state key="normal" title="Connect to Dropbox"/>
<connections>
<action selector="dbConnect:" destination="NBp-hT-qnu" eventType="touchUpInside" id="Sjs-Vk-aFg"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="34X-Rk-O8I" firstAttribute="top" secondItem="xba-tH-5D0" secondAttribute="bottom" constant="8" id="0w8-sZ-J4k"/>
<constraint firstItem="n9p-C2-IND" firstAttribute="leading" secondItem="Q1M-LV-Smi" secondAttribute="leading" constant="91" id="3OR-Oa-8cl"/>
<constraint firstAttribute="trailing" secondItem="n9p-C2-IND" secondAttribute="trailing" constant="91" id="6nb-b2-JUb"/>
<constraint firstItem="MYC-QY-v42" firstAttribute="top" secondItem="ggM-lD-yT2" secondAttribute="bottom" constant="8" id="7Aw-oA-8DT"/>
<constraint firstAttribute="trailing" secondItem="MYC-QY-v42" secondAttribute="trailing" constant="86" id="9o7-P0-T70"/>
<constraint firstItem="MYC-QY-v42" firstAttribute="leading" secondItem="Q1M-LV-Smi" secondAttribute="leading" constant="87" id="Clk-jD-xRP"/>
<constraint firstAttribute="trailing" secondItem="MYC-QY-v42" secondAttribute="trailing" constant="71" id="9o7-P0-T70"/>
<constraint firstItem="MYC-QY-v42" firstAttribute="leading" secondItem="Q1M-LV-Smi" secondAttribute="leading" constant="73" id="Clk-jD-xRP"/>
<constraint firstAttribute="trailing" secondItem="34X-Rk-O8I" secondAttribute="trailing" constant="141" id="GPM-3w-OZI"/>
<constraint firstItem="V5o-Hb-Mk0" firstAttribute="leading" secondItem="Q1M-LV-Smi" secondAttribute="leading" constant="73" id="ISQ-lm-JNH"/>
<constraint firstItem="34X-Rk-O8I" firstAttribute="leading" secondItem="Q1M-LV-Smi" secondAttribute="leading" constant="142" id="NW9-dG-lDy"/>
<constraint firstItem="xba-tH-5D0" firstAttribute="top" secondItem="V5o-Hb-Mk0" secondAttribute="bottom" constant="8" id="UcB-x5-idK"/>
<constraint firstItem="n9p-C2-IND" firstAttribute="top" secondItem="MYC-QY-v42" secondAttribute="bottom" constant="8" id="fvc-m1-XMt"/>
<constraint firstItem="xba-tH-5D0" firstAttribute="leading" secondItem="Q1M-LV-Smi" secondAttribute="leading" constant="106" id="gPD-fO-cXe"/>
@ -144,6 +154,9 @@
</constraints>
</view>
<navigationItem key="navigationItem" id="74M-cv-MGw"/>
<connections>
<outlet property="dbConnectButton" destination="MYC-QY-v42" id="SjM-EO-W5v"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="PNG-bU-UDR" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>

View File

@ -6,16 +6,22 @@
// Copyright © 2016 Kilian Hofmann. All rights reserved.
//
#import "SharedDeclerations.h"
#import <Foundation/Foundation.h>
#import <Security/Security.h>
@interface DropboxV2ObjC : NSObject
@property(strong, nonatomic) NSString *token;
@property(strong, nonatomic) NSString *rootDirectory;
@property(strong, nonatomic) NSData *kJSONNullObject;
@property(strong, nonatomic) NSURLProtectionSpace *kDropboxProtectionSpace;
- (BOOL)authorizeUserWithToke:(NSURL *)token;
- (BOOL)authorizeUserWithToke:(NSURL *)token completion:(void (^)(void))handler;
- (NSData *)downloadFromDropbox;
- (void)uploadToDropbox:(NSData *)data;
- (NSArray *)contentsOfPath:(NSString *)path;
- (NSDictionary *)getUserInfo;
- (BOOL)deauthorizeUser;
@end

View File

@ -13,23 +13,100 @@
- (DropboxV2ObjC *)init {
self = [super init];
self.rootDirectory = @"/Apps/FMC Planner 2/";
self.kJSONNullObject = [@"null" dataUsingEncoding:NSASCIIStringEncoding];
self.kDropboxProtectionSpace =
[[NSURLProtectionSpace alloc] initWithHost:@"dropbox"
port:443
protocol:@"HTTP"
realm:nil
authenticationMethod:@"OAuth2"];
return self;
}
- (BOOL)authorizeUserWithToke:(NSURL *)token {
NSScanner *scan = [NSScanner scannerWithString:[token absoluteString]];
#pragma mark - OAuth stuff
- (BOOL)authorizeUserWithToke:(NSURL *)token
completion:(void (^)(void))handler {
NSScanner *scan = [NSScanner scannerWithString:token.absoluteString];
NSString *error = [[NSString alloc] init];
[scan scanUpToString:@"&error=" intoString:&error];
if (![error isEqualToString:[token absoluteString]]) {
if (![error isEqualToString:token.absoluteString]) {
handler();
return false;
}
// No error, refine token
NSString *tokenUnrefined = [[NSString alloc] init];
scan = [NSScanner scannerWithString:token.absoluteString];
[scan scanUpToString:@"&" intoString:&tokenUnrefined];
NSString *tokenRefined = [tokenUnrefined substringFromIndex:21];
_token = tokenRefined;
NSURLCredential *credential = [NSURLCredential
credentialWithUser:@"Dropbox"
password:_token
persistence:NSURLCredentialPersistencePermanent];
[[NSURLCredentialStorage sharedCredentialStorage]
setCredential:credential
forProtectionSpace:_kDropboxProtectionSpace];
handler();
return true;
}
- (BOOL)deauthorizeUser {
NSDictionary *credentials =
[[NSURLCredentialStorage sharedCredentialStorage]
credentialsForProtectionSpace:_kDropboxProtectionSpace];
NSURLCredential *credential = [credentials.objectEnumerator nextObject];
[[NSURLCredentialStorage sharedCredentialStorage]
removeCredential:credential
forProtectionSpace:_kDropboxProtectionSpace];
return true;
}
#pragma mark - File and directory operations
#pragma mark - Other operations
- (NSDictionary *)getUserInfo {
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
request.URL =
[NSURL URLWithString:
@"https://api.dropboxapi.com/2/users/get_current_account"];
[request addValue:[NSString stringWithFormat:@"Bearer %@", _token]
.precomposedStringWithCanonicalMapping
forHTTPHeaderField:(@"Authorization")
.precomposedStringWithCanonicalMapping];
[request addValue:(@"application/json")
.precomposedStringWithCanonicalMapping
forHTTPHeaderField:(@"Content-Type")
.precomposedStringWithCanonicalMapping];
request.HTTPMethod = @"POST";
request.HTTPBody = _kJSONNullObject;
NSURLResponse *response = nil;
NSError *error = nil;
id data = [self parseJSON:[NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error]];
if ([data isKindOfClass:[NSDictionary class]]) {
return data;
} else {
return nil;
}
}
#pragma mark - Helper methods
- (id)parseJSON:(NSData *)data {
NSError *error = nil;
id object =
[NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (error == nil) {
return object;
} else {
return
[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
}
}
@end

View File

@ -52,7 +52,7 @@
+ (NSString *)savePathForFile:(NSString *)file {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *documentsPath = paths[0];
return [documentsPath
stringByAppendingString:[NSString stringWithFormat:@"/%@", file]];
}

View File

@ -109,7 +109,7 @@
.restorationIdentifier isEqualToString:@"LSKR6"]) {
UINavigationController *sm = [self.storyboard
instantiateViewControllerWithIdentifier:@"ServiceMenu"];
((ViewControllerServiceMenu *)[sm.childViewControllers firstObject])
((ViewControllerServiceMenu *)(sm.childViewControllers).firstObject)
.main = _main;
[self presentViewController:sm animated:YES completion:nil];
} else {
@ -135,11 +135,9 @@
(unsigned long)
_maxNumRoutePages]];
}
[_main.save
setObject:((UILabel *)tapReg.view).text
forKey:[NSString stringWithFormat:@"%@@%@", _Header.text,
(_main.save)[[NSString stringWithFormat:@"%@@%@", _Header.text,
((UILabel *)tapReg.view)
.restorationIdentifier]];
.restorationIdentifier]] = ((UILabel *)tapReg.view).text;
_Scratchpad.text = @"";
[_main saveToFile:_main.save];
}
@ -153,7 +151,7 @@
ofType:@"plist"]];
for (UILabel *label in _Desc) {
for (int j = 0; j < screen.count; j++) {
if ([label.restorationIdentifier intValue] == j) {
if ((label.restorationIdentifier).intValue == j) {
label.text = screen[j];
}
if (![screen[j] isEqualToString:@""] ||

View File

@ -16,7 +16,12 @@
@interface ViewControllerServiceMenu : UIViewController
@property(strong, nonatomic) ViewController *main;
@property(strong, nonatomic) IBOutlet UIButton *dbConnectButton;
- (IBAction)dbConnect:(UIButton *)sender;
- (IBAction)dbDisconnect:(UIButton *)sender;
#warning TESTING GROUNDS
- (IBAction)testing:(id)sender;
@end

View File

@ -19,24 +19,43 @@
action:@selector(back)];
}
- (void)viewWillAppear:(BOOL)animated {
DropboxV2ObjC *dbClient =
((AppDelegate *)[UIApplication sharedApplication].delegate).dbClient;
if (dbClient.token != nil) {
[_dbConnectButton setTitle:@"Disconnect from Dropbox"
forState:UIControlStateNormal];
[_dbConnectButton removeTarget:self
action:@selector(dbConnect:)
forControlEvents:UIControlEventTouchUpInside];
[_dbConnectButton addTarget:self
action:@selector(dbDisconnect:)
forControlEvents:UIControlEventTouchUpInside];
}
}
- (void)back {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
((TableViewController *)[segue destinationViewController]).title =
((TableViewController *)segue.destinationViewController).title =
segue.identifier;
((TableViewController *)[segue destinationViewController]).main = _main;
((TableViewController *)segue.destinationViewController).main = _main;
}
#pragma mark - Dropbox Button
- (IBAction)dbConnect:(UIButton *)sender {
DropboxV2ObjC *db_client =
((AppDelegate *)[[UIApplication sharedApplication] delegate]).dbClient;
DropboxV2ObjC *dbClient =
((AppDelegate *)[UIApplication sharedApplication].delegate).dbClient;
UIViewController *webController = [[UIViewController alloc] init];
webController.title = @"Dropbox";
UIWebView *web = [[UIWebView alloc] initWithFrame:webController.view.frame];
[webController.view addSubview:web];
[self.navigationController pushViewController:webController animated:YES];
((AppDelegate *)[UIApplication sharedApplication].delegate).smWebView =
webController;
[web loadRequest:
[NSURLRequest
requestWithURL:
@ -46,4 +65,25 @@
@"uri=x-fmc:/"]]];
}
- (IBAction)dbDisconnect:(UIButton *)sender {
DropboxV2ObjC *dbClient =
((AppDelegate *)[UIApplication sharedApplication].delegate).dbClient;
[dbClient deauthorizeUser];
[_dbConnectButton setTitle:@"Connect to Dropbox"
forState:UIControlStateNormal];
[_dbConnectButton removeTarget:self
action:@selector(dbDisconnect:)
forControlEvents:UIControlEventTouchUpInside];
[_dbConnectButton addTarget:self
action:@selector(dbConnect:)
forControlEvents:UIControlEventTouchUpInside];
}
#warning TESTING GROUNDS
- (IBAction)testing:(id)sender {
DropboxV2ObjC *dbClient =
((AppDelegate *)[UIApplication sharedApplication].delegate).dbClient;
[dbClient getUserInfo];
}
@end