Adds SIP002 URL for QR scaner
This commit is contained in:
@ -65,17 +65,40 @@ class ServerProfile: NSObject, NSCopying {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
guard let host = parsedUrl.host, let port = parsedUrl.port,
|
guard let host = parsedUrl.host, let port = parsedUrl.port,
|
||||||
let method = parsedUrl.user, let password = parsedUrl.password else {
|
let user = parsedUrl.user else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
self.serverHost = host
|
self.serverHost = host
|
||||||
self.serverPort = UInt16(port)
|
self.serverPort = UInt16(port)
|
||||||
self.method = method.lowercased()
|
|
||||||
self.password = password
|
|
||||||
|
|
||||||
|
// This can be overriden by the fragment part of SIP002 URL
|
||||||
remark = parsedUrl.queryItems?
|
remark = parsedUrl.queryItems?
|
||||||
.filter({ $0.name == "Remark" }).first?.value ?? ""
|
.filter({ $0.name == "Remark" }).first?.value ?? ""
|
||||||
|
|
||||||
|
if let password = parsedUrl.password {
|
||||||
|
self.method = user.lowercased()
|
||||||
|
self.password = password
|
||||||
|
} else {
|
||||||
|
// SIP002 URL have no password section
|
||||||
|
guard let data = Data(base64Encoded: padBase64(string: user)),
|
||||||
|
let userInfo = String(data: data, encoding: .utf8) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let parts = userInfo.characters.split(separator: ":", maxSplits: 1, omittingEmptySubsequences: false)
|
||||||
|
if parts.count != 2 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
self.method = String(parts[0]).lowercased()
|
||||||
|
self.password = String(parts[1])
|
||||||
|
|
||||||
|
// SIP002 defines where to put the profile name
|
||||||
|
if let profileName = parsedUrl.fragment {
|
||||||
|
self.remark = profileName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let otaStr = parsedUrl.queryItems?
|
if let otaStr = parsedUrl.queryItems?
|
||||||
.filter({ $0.name == "OTA" }).first?.value {
|
.filter({ $0.name == "OTA" }).first?.value {
|
||||||
ota = NSString(string: otaStr).boolValue
|
ota = NSString(string: otaStr).boolValue
|
||||||
|
@ -135,6 +135,40 @@ class ServerProfileTests: XCTestCase {
|
|||||||
XCTAssertNil(profile)
|
XCTAssertNil(profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testInitWithSIP002URL() {
|
||||||
|
// "ss://aes-256-cfb:password@example.com:8388?Remark=Prism&OTA=true"
|
||||||
|
let url = URL(string: "ss://YWVzLTI1Ni1jZmI6cGFzc3dvcmQ=@example.com:8388/?Remark=Prism&OTA=true")!
|
||||||
|
|
||||||
|
let profile = ServerProfile(url: url)
|
||||||
|
|
||||||
|
XCTAssertNotNil(profile)
|
||||||
|
|
||||||
|
XCTAssertEqual(profile?.serverHost, "example.com")
|
||||||
|
XCTAssertEqual(profile?.serverPort, 8388)
|
||||||
|
XCTAssertEqual(profile?.method, "aes-256-cfb")
|
||||||
|
XCTAssertEqual(profile?.password, "password")
|
||||||
|
XCTAssertEqual(profile?.remark, "Prism")
|
||||||
|
XCTAssertEqual(profile?.ota, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testInitWithSIP002URLProfileName() {
|
||||||
|
let url = URL(string: "ss://YWVzLTI1Ni1jZmI6cGFzc3dvcmQ=@example.com:8388/#Name")!
|
||||||
|
|
||||||
|
let profile = ServerProfile(url: url)
|
||||||
|
|
||||||
|
XCTAssertNotNil(profile)
|
||||||
|
XCTAssertEqual(profile?.remark, "Name")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testInitWithSIP002URLProfileNameOverride() {
|
||||||
|
let url = URL(string: "ss://YWVzLTI1Ni1jZmI6cGFzc3dvcmQ=@example.com:8388/?Remark=Name#Overriden")!
|
||||||
|
|
||||||
|
let profile = ServerProfile(url: url)
|
||||||
|
|
||||||
|
XCTAssertNotNil(profile)
|
||||||
|
XCTAssertEqual(profile?.remark, "Overriden")
|
||||||
|
}
|
||||||
|
|
||||||
func testPerformanceExample() {
|
func testPerformanceExample() {
|
||||||
// This is an example of a performance test case.
|
// This is an example of a performance test case.
|
||||||
self.measure {
|
self.measure {
|
||||||
|
Reference in New Issue
Block a user