diff --git a/ShadowsocksX-NG/Utils.h b/ShadowsocksX-NG/Utils.h index ea24afd..9e9110f 100644 --- a/ShadowsocksX-NG/Utils.h +++ b/ShadowsocksX-NG/Utils.h @@ -11,6 +11,4 @@ void ScanQRCodeOnScreen(); -NSDictionary* ParseSSURL(NSURL* url); - #endif /* QRCodeUtils_h */ diff --git a/ShadowsocksX-NG/Utils.m b/ShadowsocksX-NG/Utils.m index d6f3402..4d34e31 100644 --- a/ShadowsocksX-NG/Utils.m +++ b/ShadowsocksX-NG/Utils.m @@ -71,63 +71,3 @@ void ScanQRCodeOnScreen() { } ]; } - -// 解析SS URL,如果成功则返回一个与ServerProfile类兼容的dict -NSDictionary* ParseSSURL(NSURL* url) { - if (!url.host) { - return nil; - } - - NSString *urlString = [url absoluteString]; - int i = 0; - NSString *errorReason = nil; - while(i < 2) { - if (i == 1) { - NSString* host = url.host; - if ([host length]%4!=0) { - int n = 4 - [host length]%4; - if (1==n) { - host = [host stringByAppendingString:@"="]; - } else if (2==n) { - host = [host stringByAppendingString:@"=="]; - } - } - NSData *data = [[NSData alloc] initWithBase64EncodedString:host options:0]; - 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)]; - - - return @{@"ServerHost": IP, - @"ServerPort": @([port integerValue]), - @"Method": method, - @"Password": password, - }; - } - return nil; -} diff --git a/ShadowsocksX-NG/Utils.swift b/ShadowsocksX-NG/Utils.swift index 74c0f54..509f900 100644 --- a/ShadowsocksX-NG/Utils.swift +++ b/ShadowsocksX-NG/Utils.swift @@ -8,14 +8,12 @@ import Foundation - extension String { var localized: String { return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "") } } - extension Data { func sha1() -> String { let data = self @@ -25,3 +23,36 @@ extension Data { return hexBytes.joined(separator: "") } } + +func ParseSSURL(_ url: URL?) -> [String: Any?]? { + + func padBase64(string: String) -> String { + var length = string.characters.count + length = 4 - length % 4 + length + return string.padding(toLength: length, withPad: "=", startingAt: 0) + } + + if url?.host == nil { + return nil + } + + var plainUrl: URL! = url + + let data = Data(base64Encoded: padBase64(string: url!.host!), + options: Data.Base64DecodingOptions()) + + if data != nil { + let decoded = String(data: data!, encoding: String.Encoding.utf8) + plainUrl = URL(string: "ss://\(decoded!)") + + if plainUrl == nil { + return nil + } + } + + return ["ServerHost": plainUrl.host, + "ServerPort": UInt16(plainUrl.port!), + "Method": plainUrl.user, + "Password": plainUrl.password, + ] +} diff --git a/ShadowsocksX-NGTests/UtilsTests.swift b/ShadowsocksX-NGTests/UtilsTests.swift index 765cd57..2463b89 100644 --- a/ShadowsocksX-NGTests/UtilsTests.swift +++ b/ShadowsocksX-NGTests/UtilsTests.swift @@ -7,6 +7,7 @@ // import XCTest +@testable import ShadowsocksX_NG class UtilsTests: XCTestCase {