From ce768e2efb61880fe2d7c66aa49a779c4221b022 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Mon, 17 Feb 2014 15:06:59 +0800 Subject: [PATCH] support ss:// protocol --- .gitmodules | 3 + NSData-Base64 | 1 + ShadowWeb/ProxySettingsTableViewController.h | 9 +-- ShadowWeb/ProxySettingsTableViewController.m | 60 ++++++++++++++++++-- ShadowWeb/SWBAppDelegate.h | 2 +- ShadowWeb/SWBAppDelegate.m | 22 +++++++ ShadowWeb/shadowsocks-Info.plist | 13 +++++ shadowsocks.xcodeproj/project.pbxproj | 17 +++++- 8 files changed, 115 insertions(+), 12 deletions(-) create mode 160000 NSData-Base64 diff --git a/.gitmodules b/.gitmodules index 49f7ac7..3de5dcc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "iProxy"] path = iProxy url = https://github.com/clowwindy/iProxy.git +[submodule "NSData-Base64"] + path = NSData-Base64 + url = https://github.com/l4u/NSData-Base64.git diff --git a/NSData-Base64 b/NSData-Base64 new file mode 160000 index 0000000..abeb10c --- /dev/null +++ b/NSData-Base64 @@ -0,0 +1 @@ +Subproject commit abeb10cfdbe5c2c3f16ed45f2a7f2b5094f097dd diff --git a/ShadowWeb/ProxySettingsTableViewController.h b/ShadowWeb/ProxySettingsTableViewController.h index 1b9569e..c3787a1 100644 --- a/ShadowWeb/ProxySettingsTableViewController.h +++ b/ShadowWeb/ProxySettingsTableViewController.h @@ -14,9 +14,10 @@ UITextField *passwordField; } -+(BOOL)settingsAreNotComplete; -+(BOOL)runProxy; -+(void)reloadConfig; --(void)saveConfigForKey:(NSString *)key value:(NSString *)value; ++ (void)openSSURL:(NSURL *)url; ++ (BOOL)settingsAreNotComplete; ++ (BOOL)runProxy; ++ (void)reloadConfig; ++ (void)saveConfigForKey:(NSString *)key value:(NSString *)value; @property (nonatomic, weak) UIPopoverController *myPopoverController; @end diff --git a/ShadowWeb/ProxySettingsTableViewController.m b/ShadowWeb/ProxySettingsTableViewController.m index 0ba30c1..eaf6bdb 100644 --- a/ShadowWeb/ProxySettingsTableViewController.m +++ b/ShadowWeb/ProxySettingsTableViewController.m @@ -6,7 +6,7 @@ // Copyright (c) 2012年 clowwindy. All rights reserved. // -#import +#import "NSData+Base64.h" #import "ProxySettingsTableViewController.h" #import "SimpleTableViewSource.h" #import "local.h" @@ -75,7 +75,57 @@ } } -- (void)saveConfigForKey:(NSString *)key value:(NSString *)value { ++ (void)openSSURL:(NSURL *)url { + if (!url.host) { + return; + } + NSString *urlString = [url absoluteString]; + int i = 0; + NSString *errorReason = nil; + while(i < 2) { + if (i == 1) { + NSData *data = [[NSData alloc] initWithBase64Encoding:url.host]; + NSString *decodedString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + urlString = decodedString; + } + i++; + urlString = [urlString stringByReplacingOccurrencesOfString:@"ss://" withString:@"" options:NSAnchoredSearch range:NSMakeRange(0, urlString.length)]; + NSRange firstColonRange = [urlString rangeOfString:@":"]; + NSRange lastColonRange = [urlString rangeOfString:@":" options:NSBackwardsSearch]; + NSRange lastAtRange = [urlString rangeOfString:@"@" options:NSBackwardsSearch]; + if (firstColonRange.length == 0) { + errorReason = @"colon not found"; + continue; + } + if (firstColonRange.location == lastColonRange.location) { + errorReason = @"only one colon"; + continue; + } + if (lastAtRange.length == 0) { + errorReason = @"at not found"; + continue; + } + if (!((firstColonRange.location < lastAtRange.location) && (lastAtRange.location < lastColonRange.location))) { + errorReason = @"wrong position"; + continue; + } + NSString *method = [urlString substringWithRange:NSMakeRange(0, firstColonRange.location)]; + NSString *password = [urlString substringWithRange:NSMakeRange(firstColonRange.location + 1, lastAtRange.location - firstColonRange.location - 1)]; + NSString *IP = [urlString substringWithRange:NSMakeRange(lastAtRange.location + 1, lastColonRange.location - lastAtRange.location - 1)]; + NSString *port = [urlString substringWithRange:NSMakeRange(lastColonRange.location + 1, urlString.length - lastColonRange.location - 1)]; + [ProxySettingsTableViewController saveConfigForKey:kIPKey value:IP]; + [ProxySettingsTableViewController saveConfigForKey:kPortKey value:port]; + [ProxySettingsTableViewController saveConfigForKey:kPasswordKey value:password]; + [ProxySettingsTableViewController saveConfigForKey:kEncryptionKey value:method]; + [[NSUserDefaults standardUserDefaults] setBool:NO forKey:kUsePublicServer]; + [ProxySettingsTableViewController reloadConfig]; + return; + } + + NSLog(@"%@", errorReason); +} + ++ (void)saveConfigForKey:(NSString *)key value:(NSString *)value { [[NSUserDefaults standardUserDefaults] setObject:value forKey:key]; } @@ -146,9 +196,9 @@ if (passwordField.text == nil) { passwordField.text = @""; } - [self saveConfigForKey:kIPKey value:ipField.text]; - [self saveConfigForKey:kPortKey value:portField.text]; - [self saveConfigForKey:kPasswordKey value:passwordField.text]; + [ProxySettingsTableViewController saveConfigForKey:kIPKey value:ipField.text]; + [ProxySettingsTableViewController saveConfigForKey:kPortKey value:portField.text]; + [ProxySettingsTableViewController saveConfigForKey:kPasswordKey value:passwordField.text]; [ProxySettingsTableViewController reloadConfig]; diff --git a/ShadowWeb/SWBAppDelegate.h b/ShadowWeb/SWBAppDelegate.h index 3409c40..498000d 100644 --- a/ShadowWeb/SWBAppDelegate.h +++ b/ShadowWeb/SWBAppDelegate.h @@ -14,7 +14,7 @@ @class SWBViewController; -@interface SWBAppDelegate : UIResponder +@interface SWBAppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; diff --git a/ShadowWeb/SWBAppDelegate.m b/ShadowWeb/SWBAppDelegate.m index dd3fe59..c376b45 100644 --- a/ShadowWeb/SWBAppDelegate.m +++ b/ShadowWeb/SWBAppDelegate.m @@ -22,6 +22,7 @@ void polipo_exit(); @implementation SWBAppDelegate { BOOL polipoRunning; BOOL polipoEnabled; + NSURL *ssURL; } - (void)updateProxyMode { @@ -90,6 +91,27 @@ void polipo_exit(); return YES; } + +- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { + return [self application:application openURL:url sourceApplication:nil annotation:nil]; +} + +- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { + ssURL = url; + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:_L(Use this server?) message:[url absoluteString] delegate:self cancelButtonTitle:_L(Cancel) otherButtonTitles:_L(OK), nil]; + [alertView show]; + return YES; +} + +- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { + if (buttonIndex == 1) { + [ProxySettingsTableViewController openSSURL:ssURL]; + } else { + // Do nothing + } +} + + - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. diff --git a/ShadowWeb/shadowsocks-Info.plist b/ShadowWeb/shadowsocks-Info.plist index f3e02a2..d95464e 100644 --- a/ShadowWeb/shadowsocks-Info.plist +++ b/ShadowWeb/shadowsocks-Info.plist @@ -40,6 +40,19 @@ 2.0 CFBundleSignature ???? + CFBundleURLTypes + + + CFBundleTypeRole + Viewer + CFBundleURLName + ss + CFBundleURLSchemes + + ss + + + CFBundleVersion 2.0 LSRequiresIPhoneOS diff --git a/shadowsocks.xcodeproj/project.pbxproj b/shadowsocks.xcodeproj/project.pbxproj index 23ca20b..f1fe37e 100644 --- a/shadowsocks.xcodeproj/project.pbxproj +++ b/shadowsocks.xcodeproj/project.pbxproj @@ -43,6 +43,7 @@ 623A7EC91795B0D300DF11DF /* local.m in Sources */ = {isa = PBXBuildFile; fileRef = 628693F016DA2816008B1A26 /* local.m */; }; 623A7ECC1795B15500DF11DF /* libcrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 62CD1199175E3BD7008C4D0C /* libcrypto.a */; }; 623A7ECF1795B1D800DF11DF /* libshadowsocks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 623A7EBA1795AE8000DF11DF /* libshadowsocks.a */; }; + 626C4ADB18B1E352003DBE33 /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 626C4ADA18B1E352003DBE33 /* NSData+Base64.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 628693E116DA2578008B1A26 /* AppProxyCap.m in Sources */ = {isa = PBXBuildFile; fileRef = 628693E016DA2578008B1A26 /* AppProxyCap.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 628693E716DA2584008B1A26 /* interpose.c in Sources */ = {isa = PBXBuildFile; fileRef = 628693E416DA2584008B1A26 /* interpose.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 628693EC16DA2706008B1A26 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 628693EA16DA26E2008B1A26 /* SystemConfiguration.framework */; }; @@ -168,6 +169,8 @@ 621FCC081760400800411E5F /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; 623A7EBA1795AE8000DF11DF /* libshadowsocks.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libshadowsocks.a; sourceTree = BUILT_PRODUCTS_DIR; }; 62597BD2175FA1D00090E8A6 /* libssl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libssl.a; path = "OpenSSL-for-iPhone/lib/libssl.a"; sourceTree = ""; }; + 626C4AD918B1E352003DBE33 /* NSData+Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSData+Base64.h"; path = "NSData-Base64/NSData+Base64.h"; sourceTree = SOURCE_ROOT; }; + 626C4ADA18B1E352003DBE33 /* NSData+Base64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSData+Base64.m"; path = "NSData-Base64/NSData+Base64.m"; sourceTree = SOURCE_ROOT; }; 628693DF16DA2578008B1A26 /* AppProxyCap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppProxyCap.h; path = AppProxyCap/lib/AppProxyCap.h; sourceTree = SOURCE_ROOT; }; 628693E016DA2578008B1A26 /* AppProxyCap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppProxyCap.m; path = AppProxyCap/lib/AppProxyCap.m; sourceTree = SOURCE_ROOT; }; 628693E416DA2584008B1A26 /* interpose.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = interpose.c; path = AppProxyCap/lib/inject_and_interpose/interpose.c; sourceTree = SOURCE_ROOT; }; @@ -346,6 +349,7 @@ 621571AE16CF6BCB003D96B4 /* ShadowWeb */ = { isa = PBXGroup; children = ( + 626C4AD818B1E338003DBE33 /* base64 */, 62D85969176DA63C00FE5575 /* polipo */, 621FCBF817603FD600411E5F /* GCDWebServer */, 628693FA16DA2823008B1A26 /* Shadowsocks */, @@ -466,6 +470,15 @@ name = GCDWebServer; sourceTree = ""; }; + 626C4AD818B1E338003DBE33 /* base64 */ = { + isa = PBXGroup; + children = ( + 626C4AD918B1E352003DBE33 /* NSData+Base64.h */, + 626C4ADA18B1E352003DBE33 /* NSData+Base64.m */, + ); + name = base64; + sourceTree = ""; + }; 628693DE16DA2564008B1A26 /* AppProxyCap */ = { isa = PBXGroup; children = ( @@ -735,6 +748,7 @@ 62D85A9D176DA6FC00FE5575 /* http_parse.c in Sources */, 62D85A9F176DA6FC00FE5575 /* io.c in Sources */, 62D85AA0176DA6FC00FE5575 /* local.c in Sources */, + 626C4ADB18B1E352003DBE33 /* NSData+Base64.m in Sources */, 62D85AA2176DA6FC00FE5575 /* log.c in Sources */, 62D85AA3176DA6FC00FE5575 /* main.c in Sources */, 62D85AA4176DA6FC00FE5575 /* Makefile in Sources */, @@ -902,8 +916,7 @@ "\"$(SRCROOT)/OpenSSL-for-iPhone/lib\"", ); PRODUCT_NAME = shadowsocks; - PROVISIONING_PROFILE = ""; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE = "10B86086-082B-4967-8900-EDF458793F84"; WRAPPER_EXTENSION = app; }; name = Release;