share qrcode

This commit is contained in:
yuanxue.yang 2018-11-24 18:06:21 +08:00
parent 40cd322ad0
commit b8d2a80eef
10 changed files with 333 additions and 58 deletions

View File

@ -12,6 +12,6 @@ target 'V2rayU' do
pod 'SwiftyJSON'
pod 'Preferences'
pod 'Sparkle'
pod 'EFQRCode'
pod 'QRCoder'
end

View File

@ -1,36 +1,32 @@
PODS:
- Alamofire (4.7.3)
- EFQRCode (4.4.2):
- swift_qrcodejs (~> 1.0.1)
- Preferences (0.2.0)
- QRCoder (1.0.0)
- Sparkle (1.20.0)
- swift_qrcodejs (1.0.1)
- SwiftyJSON (4.2.0)
DEPENDENCIES:
- Alamofire
- EFQRCode
- Preferences
- QRCoder
- Sparkle
- SwiftyJSON
SPEC REPOS:
https://github.com/cocoapods/specs.git:
- Alamofire
- EFQRCode
- Preferences
- QRCoder
- Sparkle
- swift_qrcodejs
- SwiftyJSON
SPEC CHECKSUMS:
Alamofire: c7287b6e5d7da964a70935e5db17046b7fde6568
EFQRCode: e65a9eb6c7137ed6db4cfce37f0cee47938e44f0
Preferences: ebc036a176a298cde835155c73251173768a2f8d
QRCoder: 488f6869fb89ffcc3de3b4de2dabd200a6573f3c
Sparkle: 48999e7ee032f05ca05e28451eadf4af8ede6b44
swift_qrcodejs: c181fe5c849d30c699546a23762d7e3dd143ab37
SwiftyJSON: c4bcba26dd9ec7a027fc8eade48e2c911f229e96
PODFILE CHECKSUM: fde745e82410567a545d4aa0c3f453959d468f5b
PODFILE CHECKSUM: c8bfc44adeae40100cae3f20ce703eaa6666d947
COCOAPODS: 1.6.0.beta.1

View File

@ -15,6 +15,7 @@
6608D9E22182C9C100A0E0DD /* v2rayStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6608D9E12182C9C100A0E0DD /* v2rayStream.swift */; };
660C8CA22181CBAA00896361 /* V2rayUTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 660C8CA12181CBAA00896361 /* V2rayUTests.swift */; };
660D0E5A216E0158000C2922 /* V2rayServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 660D0E59216E0158000C2922 /* V2rayServer.swift */; };
660F9A7521A94C7600AEB4F7 /* QrcodeWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 660F9A7421A94C7600AEB4F7 /* QrcodeWindow.xib */; };
6610ECB721742AFD008FC401 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 664EB378216C9A5F00B6AE0D /* MainMenu.xib */; };
66406AF42183320000B56041 /* Sample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66406AF32183320000B56041 /* Sample.swift */; };
664EB375216C9A5E00B6AE0D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664EB374216C9A5E00B6AE0D /* AppDelegate.swift */; };
@ -30,6 +31,7 @@
66FEAD432179A969009DECF9 /* PreferenceGeneral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66FEAD422179A969009DECF9 /* PreferenceGeneral.swift */; };
66FEAD53217EE14C009DECF9 /* ConfigWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 66FEAD4E217EE14C009DECF9 /* ConfigWindow.xib */; };
66FEAD54217EE14C009DECF9 /* PreferenceGeneral.xib in Resources */ = {isa = PBXBuildFile; fileRef = 66FEAD50217EE14C009DECF9 /* PreferenceGeneral.xib */; };
6D6DF2CF13D9FD3C7C6492A4 /* QrcodeWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6DF12EA09D2D80788666D0 /* QrcodeWindow.swift */; };
6D6DF4711EE7CB7CA552CC89 /* Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6DF04B14482D1536ADDA7D /* Test.swift */; };
6D6DF6AEAA13C0DB0065BE3B /* Authorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6DF821D34F8B06A62F1936 /* Authorization.swift */; };
6D6DF6F065067CD879201FF9 /* Scanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6DF87840CDA04AF0E9D36E /* Scanner.swift */; };
@ -74,6 +76,7 @@
660C8CA12181CBAA00896361 /* V2rayUTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = V2rayUTests.swift; sourceTree = "<group>"; };
660C8CA32181CBAA00896361 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
660D0E59216E0158000C2922 /* V2rayServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = V2rayServer.swift; sourceTree = "<group>"; usesTabs = 0; wrapsLines = 0; };
660F9A7421A94C7600AEB4F7 /* QrcodeWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = QrcodeWindow.xib; sourceTree = "<group>"; };
66406AF32183320000B56041 /* Sample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sample.swift; sourceTree = "<group>"; };
664B95DD217062A500DBC941 /* Alamofire */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Alamofire; path = Pods/Alamofire; sourceTree = "<group>"; };
664EB371216C9A5E00B6AE0D /* V2rayU.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = V2rayU.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -96,6 +99,7 @@
66FEAD4F217EE14C009DECF9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/ConfigWindow.xib; sourceTree = "<group>"; };
66FEAD51217EE14C009DECF9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PreferenceGeneral.xib; sourceTree = "<group>"; };
6D6DF04B14482D1536ADDA7D /* Test.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Test.swift; sourceTree = "<group>"; };
6D6DF12EA09D2D80788666D0 /* QrcodeWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QrcodeWindow.swift; sourceTree = "<group>"; };
6D6DF821D34F8B06A62F1936 /* Authorization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Authorization.swift; sourceTree = "<group>"; };
6D6DF87840CDA04AF0E9D36E /* Scanner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scanner.swift; sourceTree = "<group>"; };
6D6DFD9F5991B38B128888D6 /* V2rayConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = V2rayConfig.swift; sourceTree = "<group>"; };
@ -208,6 +212,8 @@
6D6DF821D34F8B06A62F1936 /* Authorization.swift */,
6D6DF87840CDA04AF0E9D36E /* Scanner.swift */,
664EB37B216C9A5F00B6AE0D /* Info.plist */,
660F9A7421A94C7600AEB4F7 /* QrcodeWindow.xib */,
6D6DF12EA09D2D80788666D0 /* QrcodeWindow.swift */,
);
path = V2rayU;
sourceTree = "<group>";
@ -373,6 +379,7 @@
66FEAD54217EE14C009DECF9 /* PreferenceGeneral.xib in Resources */,
664EB377216C9A5F00B6AE0D /* Assets.xcassets in Resources */,
66FEAD53217EE14C009DECF9 /* ConfigWindow.xib in Resources */,
660F9A7521A94C7600AEB4F7 /* QrcodeWindow.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -389,22 +396,20 @@
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-V2rayU/Pods-V2rayU-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework",
"${BUILT_PRODUCTS_DIR}/EFQRCode/EFQRCode.framework",
"${BUILT_PRODUCTS_DIR}/Preferences/Preferences.framework",
"${BUILT_PRODUCTS_DIR}/QRCoder/QRCoder.framework",
"${PODS_ROOT}/Sparkle/Sparkle.framework",
"${BUILT_PRODUCTS_DIR}/SwiftyJSON/SwiftyJSON.framework",
"${BUILT_PRODUCTS_DIR}/swift_qrcodejs/swift_qrcodejs.framework",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
);
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/EFQRCode.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Preferences.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/QRCoder.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Sparkle.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyJSON.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/swift_qrcodejs.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@ -473,6 +478,7 @@
6D6DF6AEAA13C0DB0065BE3B /* Authorization.swift in Sources */,
6D6DF6F065067CD879201FF9 /* Scanner.swift in Sources */,
6D6DF4711EE7CB7CA552CC89 /* Test.swift in Sources */,
6D6DF2CF13D9FD3C7C6492A4 /* QrcodeWindow.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -7,7 +7,7 @@
<key>Launcher.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>8</integer>
<integer>11</integer>
</dict>
<key>V2rayU.xcscheme</key>
<dict>
@ -17,17 +17,17 @@
<key>V2rayUHelper.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>13</integer>
<integer>17</integer>
</dict>
<key>V2rayULauncher.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>20</integer>
<integer>21</integer>
</dict>
<key>V2rayULauncher.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>17</integer>
<integer>18</integer>
</dict>
<key>V2rayUTests.test.xcscheme</key>
<dict>
@ -39,7 +39,7 @@
<key>isShown</key>
<false />
<key>orderHint</key>
<integer>12</integer>
<integer>13</integer>
</dict>
<key>V2rayUTests.testDecodeVmess.xcscheme</key>
<dict>
@ -60,17 +60,17 @@
<key>isShown</key>
<false />
<key>orderHint</key>
<integer>5</integer>
<integer>7</integer>
</dict>
<key>V2rayuHelper.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>18</integer>
<integer>19</integer>
</dict>
<key>proxyHelper.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>19</integer>
<integer>20</integer>
</dict>
</dict>
</dict>

View File

@ -2,4 +2,22 @@
<Bucket
type = "0"
version = "2.0">
<Breakpoints>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "V2rayUTests/V2rayUTests.swift"
timestampString = "564742299.928"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "23"
endingLineNumber = "23"
landmarkName = "testQrcode()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>

View File

@ -7,7 +7,6 @@
//
import Cocoa
import WebKit
import Alamofire
class ConfigWindowController: NSWindowController, NSWindowDelegate, NSTabViewDelegate {
@ -430,16 +429,20 @@ class ConfigWindowController: NSWindowController, NSWindowDelegate, NSTabViewDel
let errMsg = V2rayServer.save(idx: self.serversTableView.selectedRow, isValid: self.v2rayConfig.isValid, jsonData: text)
self.errTip.stringValue = errMsg
self.refreshServerList(ok: errMsg.count > 0)
}
func refreshServerList(ok: Bool = true) {
// refresh menu
menuController.showServers()
// if server is current
if let curName = UserDefaults.get(forKey: .v2rayCurrentServerName) {
let v2rayItemList = V2rayServer.list()
if curName == v2rayItemList[self.serversTableView.selectedRow].name {
if errMsg != "" {
menuController.stopV2rayCore()
} else {
if ok {
menuController.startV2rayCore()
} else {
menuController.stopV2rayCore()
}
}
}
@ -481,6 +484,20 @@ class ConfigWindowController: NSWindowController, NSWindowDelegate, NSTabViewDel
self.importJson()
}
func saveImport(importUri: ImportUri) {
if importUri.isValid {
self.configText.string = importUri.json
if importUri.remark.count > 0 {
V2rayServer.edit(rowIndex: self.serversTableView.selectedRow, remark: importUri.remark)
}
// refresh
self.refreshServerList(ok: true)
} else {
self.errTip.stringValue = importUri.error
}
}
func importJson() {
let text = self.configText.string
let uri = jsonUrl.stringValue.trimmingCharacters(in: .whitespaces)
@ -489,19 +506,11 @@ class ConfigWindowController: NSWindowController, NSWindowDelegate, NSTabViewDel
if uri.contains("vmess://") {
let importUri = ImportUri()
importUri.importVmessUri(uri: uri)
if importUri.isValid {
self.configText.string = importUri.json
} else {
self.errTip.stringValue = importUri.error
}
self.saveImport(importUri: importUri)
} else if uri.contains("ss://") {
let importUri = ImportUri()
importUri.importSSUri(uri: uri)
if importUri.isValid {
self.configText.string = importUri.json
} else {
self.errTip.stringValue = importUri.error
}
self.saveImport(importUri: importUri)
} else {
// download json file
Alamofire.request(jsonUrl.stringValue).responseString { DataResponse in

View File

@ -56,6 +56,7 @@ class MenuController: NSObject, NSMenuDelegate {
statusItem.menu = statusMenu
configWindow = ConfigWindowController()
if UserDefaults.getBool(forKey: .v2rayTurnOn) {
// start
// on status
@ -291,13 +292,33 @@ class MenuController: NSObject, NSMenuDelegate {
V2rayLaunch.setSystemProxy(enabled: true, httpPort: httpPort, sockPort: sockPort)
}
@IBAction func generateQrcode(_ sender: NSMenuItem) {
guard let v2ray = V2rayServer.loadSelectedItem() else {
NSLog("v2ray config not found")
self.notice(title: "generate Qrcode fail", subtitle: "", informativeText: "no available servers")
return
}
let share = ShareUri()
share.qrcode(item: v2ray)
if share.error.count > 0 {
self.notice(title: "generate Qrcode fail", subtitle: "", informativeText: share.error)
return
}
let qrcodeWindow = QrcodeWindowController()
qrcodeWindow.showWindow(nil)
qrcodeWindow.setShareUri(uri: share.uri)
// bring to front
NSApp.activate(ignoringOtherApps: true)
}
@IBAction func scanQrcode(_ sender: NSMenuItem) {
let uri: String = Scanner.scanQRCodeFromScreen()
print("scanQrcode", uri)
if uri.count > 0 {
self.importUri(url: uri)
} else {
print("not found")
self.notice(title: "import server fail", subtitle: "", informativeText: "no found qrcode")
}
}
@ -305,44 +326,57 @@ class MenuController: NSObject, NSMenuDelegate {
if let uri = NSPasteboard.general.string(forType: .string), uri.count > 0 {
self.importUri(url: uri)
} else {
print("not found")
self.notice(title: "import server fail", subtitle: "", informativeText: "no found ss:// or vmess:// from Pasteboard")
}
}
@IBAction func generateQrcode(_ sender: NSMenuItem) {
print("generateQrcode")
}
func importUri(url: String) {
let uri = url.trimmingCharacters(in: .whitespaces)
if uri.count == 0 {
print("import error: uri not found")
self.notice(title: "import server fail", subtitle: "", informativeText: "import error: uri not found")
return
}
if uri.contains("ss://") && URL(string: uri) != nil {
let importUri = ImportUri()
importUri.importSSUri(uri: uri)
if importUri.isValid {
V2rayServer.add(remark: importUri.remark, json: importUri.json, isValid: true, url: uri)
// todo tip
// todo refresh server list
} else {
print("import error", importUri.error)
}
self.saveServer(importUri: importUri)
return
}
if uri.contains("vmess://") && URL(string: uri) != nil {
let importUri = ImportUri()
importUri.importVmessUri(uri: uri)
if importUri.isValid {
V2rayServer.add(remark: importUri.remark, json: importUri.json, isValid: true, url: uri)
// todo tip
// todo refresh server list
} else {
print("import error", importUri.error)
}
self.saveServer(importUri: importUri)
return
}
self.notice(title: "import server fail", subtitle: "", informativeText: "no found ss:// or vmess://")
}
func notice(title: String = "", subtitle: String = "", informativeText: String = "") {
// NSUserNotification
let userNotification = NSUserNotification()
userNotification.title = title
userNotification.subtitle = subtitle
userNotification.informativeText = informativeText
// 使NSUserNotificationCenterNSUserNotification
let userNotificationCenter = NSUserNotificationCenter.default
userNotificationCenter.scheduleNotification(userNotification)
}
func saveServer(importUri: ImportUri) {
if importUri.isValid {
// add server
V2rayServer.add(remark: importUri.remark, json: importUri.json, isValid: true, url: importUri.uri)
// refresh server
self.showServers()
self.notice(title: "import server success", subtitle: "", informativeText: importUri.remark)
} else {
self.notice(title: "import server fail", subtitle: "", informativeText: importUri.error)
}
}
}

29
V2rayU/QrcodeWindow.swift Normal file
View File

@ -0,0 +1,29 @@
//
// Created by yanue on 2018/11/24.
// Copyright (c) 2018 yanue. All rights reserved.
//
import Foundation
import Cocoa
import QRCoder
class QrcodeWindowController: NSWindowController {
override var windowNibName: String? {
return "QrcodeWindow" // no extension .xib here
}
@IBOutlet weak var shareUri: NSTextField!
@IBOutlet weak var shareQrcode: NSImageView!
override func awakeFromNib() {
}
override func windowDidLoad() {
super.windowDidLoad()
}
func setShareUri(uri: String) {
self.shareUri.stringValue = uri
let generator = QRCodeGenerator()
shareQrcode.image = generator.createImage(value: uri, size: CGSize(width: 256, height: 256))
}
}

45
V2rayU/QrcodeWindow.xib Normal file
View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="QrcodeWindowController" customModule="V2rayU" customModuleProvider="target">
<connections>
<outlet property="shareQrcode" destination="A7n-ua-0nz" id="osg-S9-FM3"/>
<outlet property="shareUri" destination="u9M-IA-5nP" id="jNY-gA-XtE"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Share QRCode" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="415" height="363"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="415" height="363"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="u9M-IA-5nP">
<rect key="frame" x="43" y="287" width="329" height="57"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" toolTip="share server uri" drawsBackground="YES" id="PMU-Ca-6qA">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="A7n-ua-0nz">
<rect key="frame" x="75" y="18" width="256" height="256"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" imageFrameStyle="grayBezel" id="rrw-ad-nML"/>
</imageView>
</subviews>
</view>
<point key="canvasLocation" x="106.5" y="193.5"/>
</window>
</objects>
</document>

View File

@ -8,13 +8,133 @@ import CoreGraphics
import CoreImage
import SwiftyJSON
struct VmessShare: Codable {
var v: String = "2"
var ps: String = ""
var add: String = ""
var port: String = ""
var id: String = ""
var aid: String = ""
var net: String = ""
var type: String = "none"
var host: String = ""
var path: String = ""
var tls: String = "none"
}
class ShareUri {
var error = ""
var remark = ""
var uri: String = ""
var v2ray = V2rayConfig()
var share = VmessShare()
func qrcode(item: V2rayItem) {
v2ray.parseJson(jsonText: item.json)
if !v2ray.isValid {
self.error = v2ray.errors[0]
return
}
self.remark = item.remark
if v2ray.serverProtocol == V2rayProtocolOutbound.vmess.rawValue {
self.genVmessUri()
let encoder = JSONEncoder()
if let data = try? encoder.encode(self.share) {
let uri = String(data: data, encoding: .utf8)!
self.uri = "vmess://" + uri.base64Encoded()!
print("vmess", self.uri)
} else {
self.error = "encode uri error"
}
return
}
if v2ray.serverProtocol == V2rayProtocolOutbound.shadowsocks.rawValue {
print("share shadowsocks")
self.genShadowsocksUri()
return
}
self.error = "not support"
}
/**s
vmess://(Base64json
json数据如下
{
"v": "2",
"ps": "备注别名",
"add": "111.111.111.111",
"port": "32000",
"id": "1386f85e-657b-4d6e-9d56-78badb75e1fd",
"aid": "100",
"net": "tcp",
"type": "none",
"host": "www.bbb.com",
"path": "/",
"tls": "tls"
}
v:,
net tcp\kcp\ws\h2)
type:none\http\srtp\utp\wechat-video
host
1)http host中间逗号(,)
2)ws host
3)h2 host
path:path(ws/h2)
tlstls)
*/
private func genVmessUri() {
self.share.add = self.v2ray.serverVmess.address
self.share.ps = self.remark
self.share.port = String(self.v2ray.serverVmess.port)
self.share.id = self.v2ray.serverVmess.users[0].id
self.share.aid = String(self.v2ray.serverVmess.users[0].alterId)
self.share.net = self.v2ray.streamNetwork
if self.v2ray.streamNetwork == "h2" {
self.share.host = self.v2ray.streamH2.host[0]
self.share.path = self.v2ray.streamH2.path
}
if self.v2ray.streamNetwork == "ws" {
self.share.host = self.v2ray.streamWs.headers.host
self.share.path = self.v2ray.streamWs.path
}
self.share.tls = self.v2ray.streamTlsSecurity
}
// Shadowsocks
func genShadowsocksUri() {
var ss = ShadowsockUri()
ss.host = self.v2ray.serverShadowsocks.address
ss.port = self.v2ray.serverShadowsocks.port
ss.password = self.v2ray.serverShadowsocks.password
ss.method = self.v2ray.serverShadowsocks.method
ss.remark = self.remark
self.uri = ss.encode()
self.error = ss.error
}
}
class ImportUri {
var isValid: Bool = false
var json: String = ""
var remark: String = ""
var error: String = ""
var uri: String = ""
func importSSUri(uri: String) {
if URL(string: uri) == nil {
self.error = "invail ss url"
return
}
self.uri = uri
let ss = ShadowsockUri()
ss.Init(url: URL(string: uri)!)
if ss.error.count > 0 {
@ -44,6 +164,12 @@ class ImportUri {
}
func importVmessUri(uri: String) {
if URL(string: uri) == nil {
self.error = "invail vmess url"
return
}
self.uri = uri
var vmess = VmessUri()
vmess.parseType2(url: URL(string: uri)!)
if vmess.error.count > 0 {
@ -290,6 +416,7 @@ class VmessUri {
self.tls = json["tls"].stringValue
// type:none\http\srtp\utp\wechat-video
self.type = json["type"].stringValue
print("json", json)
}
}
@ -304,6 +431,17 @@ class ShadowsockUri {
var error: String = ""
// ss://bf-cfb:test@192.168.100.1:8888#remark
func encode() -> String {
let base64 = self.method + ":" + self.password + "@" + self.host + ":" + String(self.port)
var ss = base64.base64Encoded()
if ss != nil {
return "ss://" + ss! + "#" + self.remark
}
self.error = "encode base64 fail"
return ""
}
func Init(url: URL) {
let (_decodedUrl, _tag) = self.decodeUrl(url: url)
guard let decodedUrl = _decodedUrl else {