Merge branch 'release/1.2'

This commit is contained in:
Charlie Qiu
2016-08-04 16:48:03 +08:00
27 changed files with 417 additions and 132 deletions

View File

@ -1,12 +1,12 @@
# ShadowsocksX-NG
Current version is 1.1
Current version is 1.2
[![Build Status](https://travis-ci.org/qiuyuzhou/ShadowsocksX-NG.svg?branch=develop)](https://travis-ci.org/qiuyuzhou/ShadowsocksX-NG)
Next Generation of [ShadowsocksX](https://github.com/shadowsocks/shadowsocks-iOS)
## Why Another Implement
## Why?
It's hard to maintaine the original implement. There are too many unused code in it.
It also embed ss-local source. It's crazy to maitaine depandences of ss-local.
@ -42,8 +42,10 @@ Then I rewrite the gui code by swift.
- Local socks5 timeout.
- If enable UDP relay.
- GFW List url.
- Manual spesify network service profiles which would be configure the proxy.
- Could reorder shadowsocks profiles by drag & drop in servers preferences panel.
## Diferences with orignal ShadowsocksX
## Different from orignal ShadowsocksX
Run ss-local as backgroud service through launchd, not in app process.
So after you quit the app, the ss-local maybe is still running.
@ -51,9 +53,15 @@ So after you quit the app, the ss-local maybe is still running.
Add a manual mode which won't configure the system proxy settings.
Then you could configure your apps to use socks5 proxy manual.
## Contributing
Contributions must be available on a separately named branch based on the latest version of the main branch develop.
ref: [GitFlow](http://nvie.com/posts/a-successful-git-branching-model/)
## TODO List
- Embed the http proxy server [privoxy](http://www.privoxy.org/).
- [ ] Embed the http proxy server [privoxy](http://www.privoxy.org/).
## License

View File

@ -18,7 +18,6 @@
9B0BFFEE1D0460A70040E62B /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9B0BFFEC1D0460A70040E62B /* MainMenu.xib */; };
9B0BFFF91D0460A70040E62B /* ShadowsocksX_NGTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B0BFFF81D0460A70040E62B /* ShadowsocksX_NGTests.swift */; };
9B0D55461D2CC85400A4A8E2 /* ProxyPreferencesController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9B0D55481D2CC85400A4A8E2 /* ProxyPreferencesController.xib */; };
9B172A6A1D0ADDDD00B87B9A /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9B172A6C1D0ADDDD00B87B9A /* Localizable.strings */; };
9B2491B41D0ACC3A003BBECC /* PreferencesWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9B2491B61D0ACC3A003BBECC /* PreferencesWindowController.xib */; };
9B2491B71D0ACC3E003BBECC /* AdvPreferencesWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9B2491B91D0ACC3E003BBECC /* AdvPreferencesWindowController.xib */; };
9B3FFF0D1D05FEB30019A709 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B3FFF0C1D05FEB30019A709 /* Utils.swift */; };
@ -42,6 +41,7 @@
9BA04B231D23D5A5005AAD7F /* ProxyConfTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BA04B221D23D5A5005AAD7F /* ProxyConfTool.m */; };
9BA04B261D24044D005AAD7F /* ProxyPreferencesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BA04B241D24044D005AAD7F /* ProxyPreferencesController.swift */; };
9BB706A71D1B982300551F0E /* SWBApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BB706A51D1B982300551F0E /* SWBApplication.m */; };
9BC70EDC1D2E3E3100EDA4CA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9B172A6C1D0ADDDD00B87B9A /* Localizable.strings */; };
9BE8FBBF1D0B211600CAFD01 /* libcrypto.1.0.0.dylib in Resources */ = {isa = PBXBuildFile; fileRef = 9BE8FBBD1D0B1FB900CAFD01 /* libcrypto.1.0.0.dylib */; };
9BEEF0691D04D4D500FC52B3 /* install_ss_local.sh in Resources */ = {isa = PBXBuildFile; fileRef = 9BEEF0651D04CB8500FC52B3 /* install_ss_local.sh */; };
9BEEF06A1D04D4D500FC52B3 /* start_ss_local.sh in Resources */ = {isa = PBXBuildFile; fileRef = 9BEEF0661D04CE8D00FC52B3 /* start_ss_local.sh */; };
@ -52,6 +52,8 @@
9BEEF0751D04EF3E00FC52B3 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BEEF0731D04EF3E00FC52B3 /* PreferencesWindowController.swift */; };
9BEEF0781D04FE8A00FC52B3 /* LaunchAgentUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BEEF0771D04FE8A00FC52B3 /* LaunchAgentUtils.swift */; };
9BEEF07B1D05631500FC52B3 /* AdvPreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BEEF0791D05631500FC52B3 /* AdvPreferencesWindowController.swift */; };
C8E42A6C1D4F270A0074C7EA /* UserRulesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8E42A6A1D4F270A0074C7EA /* UserRulesController.swift */; };
C8E42A6E1D4F2CAF0074C7EA /* UserRulesController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C8E42A701D4F2CAF0074C7EA /* UserRulesController.xib */; };
E0E57CCA7EB34B90F9D340F2 /* Pods_ShadowsocksX_NGTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 388120F062D7EB7DD0D8DDCA /* Pods_ShadowsocksX_NGTests.framework */; };
F0809FF1595BE2966343D3C7 /* libPods-proxy_conf_helper.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E7783AEDB4A3BDDC9FF16AC /* libPods-proxy_conf_helper.a */; };
/* End PBXBuildFile section */
@ -159,6 +161,9 @@
9BEEF0771D04FE8A00FC52B3 /* LaunchAgentUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LaunchAgentUtils.swift; sourceTree = "<group>"; };
9BEEF0791D05631500FC52B3 /* AdvPreferencesWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdvPreferencesWindowController.swift; sourceTree = "<group>"; };
B4E6A97CA843F3943524B686 /* Pods-proxy_conf_helper.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-proxy_conf_helper.debug.xcconfig"; path = "Pods/Target Support Files/Pods-proxy_conf_helper/Pods-proxy_conf_helper.debug.xcconfig"; sourceTree = "<group>"; };
C8E42A6A1D4F270A0074C7EA /* UserRulesController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserRulesController.swift; sourceTree = "<group>"; };
C8E42A6F1D4F2CAF0074C7EA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UserRulesController.xib; sourceTree = "<group>"; };
C8E42A721D4F2CB10074C7EA /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/UserRulesController.strings"; sourceTree = "<group>"; };
E9E9FB3855DA55D0710EE7BD /* Pods-ShadowsocksX-NG.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShadowsocksX-NG.release.xcconfig"; path = "Pods/Target Support Files/Pods-ShadowsocksX-NG/Pods-ShadowsocksX-NG.release.xcconfig"; sourceTree = "<group>"; };
FE3237E9FB24D9B924A0E630 /* Pods-ShadowsocksX-NG.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShadowsocksX-NG.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ShadowsocksX-NG/Pods-ShadowsocksX-NG.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -307,6 +312,8 @@
9B2491B91D0ACC3E003BBECC /* AdvPreferencesWindowController.xib */,
9BA04B241D24044D005AAD7F /* ProxyPreferencesController.swift */,
9B0D55481D2CC85400A4A8E2 /* ProxyPreferencesController.xib */,
C8E42A6A1D4F270A0074C7EA /* UserRulesController.swift */,
C8E42A701D4F2CAF0074C7EA /* UserRulesController.xib */,
);
name = UI;
sourceTree = "<group>";
@ -447,10 +454,10 @@
9BE8FBBF1D0B211600CAFD01 /* libcrypto.1.0.0.dylib in Resources */,
9B3FFF541D09E2D10019A709 /* proxy_conf_helper in Resources */,
9BEEF0691D04D4D500FC52B3 /* install_ss_local.sh in Resources */,
9B172A6A1D0ADDDD00B87B9A /* Localizable.strings in Resources */,
9B0D55461D2CC85400A4A8E2 /* ProxyPreferencesController.xib in Resources */,
9B2491B41D0ACC3A003BBECC /* PreferencesWindowController.xib in Resources */,
9B3FFF291D08A1DF0019A709 /* user-rule.txt in Resources */,
C8E42A6E1D4F2CAF0074C7EA /* UserRulesController.xib in Resources */,
9BEEF06A1D04D4D500FC52B3 /* start_ss_local.sh in Resources */,
9B3FFF391D08CF110019A709 /* qrcode.min.js in Resources */,
9B3FFF3A1D08CF110019A709 /* qrcode.htm in Resources */,
@ -463,6 +470,7 @@
9B2491B71D0ACC3E003BBECC /* AdvPreferencesWindowController.xib in Resources */,
9B3FFF381D08CF110019A709 /* jquery.min.js in Resources */,
9B3FFF271D0898EB0019A709 /* gfwlist.txt in Resources */,
9BC70EDC1D2E3E3100EDA4CA /* Localizable.strings in Resources */,
9B0BFFEE1D0460A70040E62B /* MainMenu.xib in Resources */,
9B3FFF4C1D09D8F70019A709 /* install_helper.sh in Resources */,
9B07EFAC1D048E880052D9DF /* menu_icon@2x.png in Resources */,
@ -625,6 +633,7 @@
9B0BFFE91D0460A70040E62B /* AppDelegate.swift in Sources */,
9BA04B231D23D5A5005AAD7F /* ProxyConfTool.m in Sources */,
9BEEF0781D04FE8A00FC52B3 /* LaunchAgentUtils.swift in Sources */,
C8E42A6C1D4F270A0074C7EA /* UserRulesController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -705,6 +714,15 @@
name = AdvPreferencesWindowController.xib;
sourceTree = "<group>";
};
C8E42A701D4F2CAF0074C7EA /* UserRulesController.xib */ = {
isa = PBXVariantGroup;
children = (
C8E42A6F1D4F2CAF0074C7EA /* Base */,
C8E42A721D4F2CB10074C7EA /* zh-Hans */,
);
name = UserRulesController.xib;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */

View File

@ -16,7 +16,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
var preferencesWinCtrl: PreferencesWindowController!
var advPreferencesWinCtrl: AdvPreferencesWindowController!
var proxyPreferencesWinCtrl: ProxyPreferencesController!
var editUserRulesWinCtrl: UserRulesController!
var launchAtLoginController: LaunchAtLoginController = LaunchAtLoginController()
@IBOutlet weak var window: NSWindow!
@ -24,11 +25,14 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
@IBOutlet weak var runningStatusMenuItem: NSMenuItem!
@IBOutlet weak var toggleRunningMenuItem: NSMenuItem!
@IBOutlet weak var proxyMenuItem: NSMenuItem!
@IBOutlet weak var autoModeMenuItem: NSMenuItem!
@IBOutlet weak var globalModeMenuItem: NSMenuItem!
@IBOutlet weak var manualModeMenuItem: NSMenuItem!
@IBOutlet weak var serversMenuItem: NSMenuItem!
@IBOutlet var showQRCodeMenuItem: NSMenuItem!
@IBOutlet var scanQRCodeMenuItem: NSMenuItem!
@IBOutlet var serversPreferencesMenuItem: NSMenuItem!
@IBOutlet weak var lanchAtLoginMenuItem: NSMenuItem!
@ -178,23 +182,15 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
}
@IBAction func editUserRulesForPAC(sender: NSMenuItem) {
let url = NSURL(fileURLWithPath: PACUserRuleFilePath)
NSWorkspace.sharedWorkspace().openURL(url)
}
@IBAction func applyUserRulesForPAC(sender: NSMenuItem) {
if GeneratePACFile() {
// Popup a user notification
let notification = NSUserNotification()
notification.title = "PAC has been updated by User Rules.".localized
NSUserNotificationCenter.defaultUserNotificationCenter()
.deliverNotification(notification)
} else {
let notification = NSUserNotification()
notification.title = "It's failed to update PAC by User Rules.".localized
NSUserNotificationCenter.defaultUserNotificationCenter()
.deliverNotification(notification)
if editUserRulesWinCtrl != nil {
editUserRulesWinCtrl.close()
}
let ctrl = UserRulesController(windowNibName: "UserRulesController")
editUserRulesWinCtrl = ctrl
ctrl.showWindow(self)
NSApp.activateIgnoringOtherApps(true)
ctrl.window?.makeKeyAndOrderFront(self)
}
@IBAction func showQRCodeForCurrentServer(sender: NSMenuItem) {
@ -331,14 +327,17 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
let defaults = NSUserDefaults.standardUserDefaults()
let mode = defaults.stringForKey("ShadowsocksRunningMode")
if mode == "auto" {
proxyMenuItem.title = "Proxy - Auto By PAC".localized
autoModeMenuItem.state = 1
globalModeMenuItem.state = 0
manualModeMenuItem.state = 0
} else if mode == "global" {
proxyMenuItem.title = "Proxy - Global".localized
autoModeMenuItem.state = 0
globalModeMenuItem.state = 1
manualModeMenuItem.state = 0
} else if mode == "manual" {
proxyMenuItem.title = "Proxy - Manual".localized
autoModeMenuItem.state = 0
globalModeMenuItem.state = 0
manualModeMenuItem.state = 1
@ -364,6 +363,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
func updateServersMenu() {
let mgr = ServerProfileManager.instance
serversMenuItem.submenu?.removeAllItems()
let showQRItem = showQRCodeMenuItem
let scanQRItem = scanQRCodeMenuItem
let preferencesItem = serversPreferencesMenuItem
var i = 0
@ -389,6 +390,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
if !mgr.profiles.isEmpty {
serversMenuItem.submenu?.addItem(NSMenuItem.separatorItem())
}
serversMenuItem.submenu?.addItem(showQRItem)
serversMenuItem.submenu?.addItem(scanQRItem)
serversMenuItem.submenu?.addItem(NSMenuItem.separatorItem())
serversMenuItem.submenu?.addItem(preferencesItem)
}

View File

@ -3,61 +3,61 @@
{
"size" : "16x16",
"idiom" : "mac",
"filename" : "icon_16x16.png",
"filename" : "Icon_16x16.png",
"scale" : "1x"
},
{
"size" : "16x16",
"idiom" : "mac",
"filename" : "icon_16x16@2x.png",
"filename" : "Icon_16x16@2x.png",
"scale" : "2x"
},
{
"size" : "32x32",
"idiom" : "mac",
"filename" : "icon_32x32.png",
"filename" : "Icon_32x32.png",
"scale" : "1x"
},
{
"size" : "32x32",
"idiom" : "mac",
"filename" : "icon_32x32@2x.png",
"filename" : "Icon_32x32@2x.png",
"scale" : "2x"
},
{
"size" : "128x128",
"idiom" : "mac",
"filename" : "icon_128x128.png",
"filename" : "Icon_128x128.png",
"scale" : "1x"
},
{
"size" : "128x128",
"idiom" : "mac",
"filename" : "icon_128x128@2x.png",
"filename" : "Icon_128x128@2x.png",
"scale" : "2x"
},
{
"size" : "256x256",
"idiom" : "mac",
"filename" : "icon_256x256.png",
"filename" : "Icon_256x256.png",
"scale" : "1x"
},
{
"size" : "256x256",
"idiom" : "mac",
"filename" : "icon_256x256@2x.png",
"filename" : "Icon_256x256@2x.png",
"scale" : "2x"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "icon_512x512.png",
"filename" : "Icon_512x512.png",
"scale" : "1x"
},
{
"size" : "512x512",
"idiom" : "mac",
"filename" : "icon_512x512@2x.png",
"filename" : "Icon_512x512@2x.png",
"scale" : "2x"
}
],

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 798 B

After

Width:  |  Height:  |  Size: 798 B

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 87 KiB

View File

Before

Width:  |  Height:  |  Size: 195 KiB

After

Width:  |  Height:  |  Size: 195 KiB

View File

@ -39,3 +39,9 @@
"Shadowsocks: Off" = "Shadowsocks: Off";
"Turn Shadowsocks On" = "Turn Shadowsocks On";
"Proxy - Auto By PAC" = "Proxy - Auto By PAC";
"Proxy - Global" = "Proxy - Global";
"Proxy - Manual" = "Proxy - Manual";

View File

@ -18,9 +18,12 @@
<outlet property="globalModeMenuItem" destination="Mw3-Jm-eXA" id="ar5-Yx-3ze"/>
<outlet property="lanchAtLoginMenuItem" destination="eUq-p7-ICK" id="w4p-0c-DZn"/>
<outlet property="manualModeMenuItem" destination="8PR-gs-c5N" id="9qz-mU-5kt"/>
<outlet property="proxyMenuItem" destination="diI-fB-Rss" id="Qjk-9U-3Qy"/>
<outlet property="runningStatusMenuItem" destination="fzk-mE-CEV" id="Vwm-Rg-Ykn"/>
<outlet property="scanQRCodeMenuItem" destination="Qe6-bF-paT" id="XHa-pa-nCa"/>
<outlet property="serversMenuItem" destination="u5M-hQ-VSc" id="8gp-SY-Y4U"/>
<outlet property="serversPreferencesMenuItem" destination="M5r-E7-44f" id="voe-SX-k6a"/>
<outlet property="showQRCodeMenuItem" destination="R6A-96-Zcb" id="XHz-pz-nCz"/>
<outlet property="statusMenu" destination="Hob-KD-bx9" id="clA-ZW-0pT"/>
<outlet property="toggleRunningMenuItem" destination="GSu-Tf-StS" id="XHw-pU-nCa"/>
</connections>
@ -60,6 +63,19 @@
<action selector="selectManualMode:" target="Voe-Tx-rLC" id="Xxb-28-6fi"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="V92-VH-Agn"/>
<menuItem title="Update PAC from GFW List" id="TFc-Ec-duM">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateGFWList:" target="Voe-Tx-rLC" id="Ztt-PS-F3T"/>
</connections>
</menuItem>
<menuItem title="Edit User Rules For PAC..." id="rms-p0-CvB">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="editUserRulesForPAC:" target="Voe-Tx-rLC" id="ZtK-2d-Pcl"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="bMX-qn-Qwi"/>
<menuItem title="Advance Proxy Preference..." id="sbx-yz-3lO">
<modifierMask key="keyEquivalentModifierMask"/>
@ -70,11 +86,23 @@
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="kkf-gh-O8t"/>
<menuItem title="Servers" id="u5M-hQ-VSc">
<modifierMask key="keyEquivalentModifierMask" shift="YES"/>
<menu key="submenu" title="Servers" id="9Y1-db-3HK">
<items>
<menuItem title="Show QR Code For Current Server..." id="R6A-96-Zcb">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="showQRCodeForCurrentServer:" target="Voe-Tx-rLC" id="t45-Zk-cai"/>
</connections>
</menuItem>
<menuItem title="Scan QR Code From Screen ..." id="Qe6-bF-paT">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="scanQRCodeFromScreen:" target="Voe-Tx-rLC" id="zQZ-IT-H4a"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="6sL-A4-S7N"/>
<menuItem title="Server Preferences..." id="M5r-E7-44f">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
@ -84,46 +112,12 @@
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="eLu-uz-b4H"/>
<menuItem title="Advance Preference ..." id="bZ3-fy-34d">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="editAdvPreferences:" target="Voe-Tx-rLC" id="mEF-XS-HJE"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="V92-VH-Agn"/>
<menuItem title="Update PAC from GFW List" id="TFc-Ec-duM">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateGFWList:" target="Voe-Tx-rLC" id="Ztt-PS-F3T"/>
</connections>
</menuItem>
<menuItem title="Edit User Rules For PAC..." id="rms-p0-CvB">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="editUserRulesForPAC:" target="Voe-Tx-rLC" id="ZtK-2d-Pcl"/>
</connections>
</menuItem>
<menuItem title="Apply User Rules For PAC" id="6qf-cg-HXc">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="applyUserRulesForPAC:" target="Voe-Tx-rLC" id="iAp-Ae-0zV"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="6sL-A4-S7N"/>
<menuItem title="Show QR Code For Current Server..." id="R6A-96-Zcb">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="showQRCodeForCurrentServer:" target="Voe-Tx-rLC" id="t45-Zk-cai"/>
</connections>
</menuItem>
<menuItem title="Scan QR Code From Screen ..." id="Qe6-bF-paT">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="scanQRCodeFromScreen:" target="Voe-Tx-rLC" id="zQZ-IT-H4a"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="wcA-9q-cxa"/>
<menuItem title="Launch At Login" id="eUq-p7-ICK">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15G31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
<capability name="box content view" minToolsVersion="7.0"/>
@ -24,16 +24,16 @@
<window title="Server Preferences" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" oneShot="NO" animationBehavior="default" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="423" y="365" width="544" height="330"/>
<rect key="contentRect" x="423" y="365" width="590" height="330"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="544" height="330"/>
<rect key="frame" x="0.0" y="0.0" width="590" height="330"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView focusRingType="none" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="u4U-Ju-FJV">
<rect key="frame" x="20" y="80" width="165" height="230"/>
<rect key="frame" x="20" y="80" width="223" height="230"/>
<clipView key="contentView" focusRingType="none" id="1oC-7s-16v">
<rect key="frame" x="1" y="1" width="163" height="228"/>
<rect key="frame" x="1" y="1" width="221" height="228"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnSelection="YES" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" id="r91-ho-Lum">
@ -84,7 +84,7 @@
</scroller>
</scrollView>
<box borderType="line" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="oZ5-85-pwY">
<rect key="frame" x="202" y="57" width="325" height="255"/>
<rect key="frame" x="248" y="57" width="325" height="255"/>
<view key="contentView" id="a3z-VL-3xV">
<rect key="frame" x="1" y="1" width="323" height="253"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
@ -241,39 +241,10 @@
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</box>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="yyD-qq-aSk">
<rect key="frame" x="449" y="13" width="81" height="32"/>
<constraints>
<constraint firstAttribute="width" constant="69" id="GvX-GM-8n5"/>
</constraints>
<buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="zPE-oD-PwK">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
DQ
</string>
</buttonCell>
<connections>
<action selector="ok:" target="-2" id="ifI-e4-Htf"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="kGm-Zm-ipY">
<rect key="frame" x="368" y="13" width="81" height="32"/>
<constraints>
<constraint firstAttribute="width" constant="69" id="7s5-Pr-Tlv"/>
</constraints>
<buttonCell key="cell" type="push" title="Cacnel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="j03-9E-uHW">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="cancel:" target="-2" id="514-4D-a6S"/>
</connections>
</button>
<box title="Box" boxType="custom" borderType="none" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="Gqv-5O-Wwf">
<rect key="frame" x="20" y="61" width="165" height="19"/>
<rect key="frame" x="20" y="61" width="223" height="19"/>
<view key="contentView" id="MbP-FS-YEs">
<rect key="frame" x="0.0" y="0.0" width="165" height="19"/>
<rect key="frame" x="0.0" y="0.0" width="223" height="19"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="4ig-lF-m2R">
@ -313,30 +284,59 @@ DQ
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
<color key="fillColor" red="1" green="1" blue="1" alpha="0.59999999999999998" colorSpace="calibratedRGB"/>
</box>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="yyD-qq-aSk">
<rect key="frame" x="495" y="13" width="81" height="32"/>
<constraints>
<constraint firstAttribute="width" constant="69" id="uKT-xu-yvV"/>
</constraints>
<buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="zPE-oD-PwK">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
DQ
</string>
</buttonCell>
<connections>
<action selector="ok:" target="-2" id="ifI-e4-Htf"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="kGm-Zm-ipY">
<rect key="frame" x="414" y="13" width="81" height="32"/>
<constraints>
<constraint firstAttribute="width" constant="69" id="s2I-cF-RJc"/>
</constraints>
<buttonCell key="cell" type="push" title="Cacnel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="j03-9E-uHW">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="cancel:" target="-2" id="514-4D-a6S"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="u4U-Ju-FJV" firstAttribute="leading" secondItem="Gqv-5O-Wwf" secondAttribute="leading" id="00T-SU-dGV"/>
<constraint firstItem="u4U-Ju-FJV" firstAttribute="trailing" secondItem="Gqv-5O-Wwf" secondAttribute="trailing" id="1d8-Yd-ErO"/>
<constraint firstAttribute="trailing" secondItem="oZ5-85-pwY" secondAttribute="trailing" constant="20" symbolic="YES" id="6n4-pw-ssp"/>
<constraint firstItem="oZ5-85-pwY" firstAttribute="trailing" secondItem="yyD-qq-aSk" secondAttribute="trailing" id="9rk-Gp-QMb"/>
<constraint firstItem="kGm-Zm-ipY" firstAttribute="baseline" secondItem="yyD-qq-aSk" secondAttribute="baseline" id="DUP-eE-HPu"/>
<constraint firstItem="yyD-qq-aSk" firstAttribute="leading" secondItem="kGm-Zm-ipY" secondAttribute="trailing" constant="12" symbolic="YES" id="E8m-6c-pKH"/>
<constraint firstItem="Gqv-5O-Wwf" firstAttribute="bottom" secondItem="oZ5-85-pwY" secondAttribute="bottom" id="RCW-Hm-rKr"/>
<constraint firstItem="oZ5-85-pwY" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="205" id="SqM-gs-OUV"/>
<constraint firstItem="oZ5-85-pwY" firstAttribute="leading" secondItem="Gqv-5O-Wwf" secondAttribute="trailing" constant="20" symbolic="YES" id="UMl-Hs-ZsE"/>
<constraint firstItem="u4U-Ju-FJV" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" constant="20" symbolic="YES" id="Uds-5g-kRr"/>
<constraint firstItem="u4U-Ju-FJV" firstAttribute="top" secondItem="oZ5-85-pwY" secondAttribute="top" id="VFr-Bp-q4w"/>
<constraint firstItem="Gqv-5O-Wwf" firstAttribute="top" secondItem="u4U-Ju-FJV" secondAttribute="bottom" id="aVt-un-Nac"/>
<constraint firstItem="kGm-Zm-ipY" firstAttribute="top" secondItem="oZ5-85-pwY" secondAttribute="bottom" constant="20" symbolic="YES" id="fEN-vq-93f"/>
<constraint firstItem="u4U-Ju-FJV" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="20" symbolic="YES" id="mxl-v4-OJS"/>
<constraint firstItem="Gqv-5O-Wwf" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" constant="250" id="xor-Fa-hnd"/>
<constraint firstAttribute="bottom" secondItem="kGm-Zm-ipY" secondAttribute="bottom" constant="20" symbolic="YES" id="xy9-yv-p9u"/>
<constraint firstItem="oZ5-85-pwY" firstAttribute="leading" secondItem="u4U-Ju-FJV" secondAttribute="trailing" constant="8" symbolic="YES" id="C6R-wI-MlZ"/>
<constraint firstItem="kGm-Zm-ipY" firstAttribute="baseline" secondItem="yyD-qq-aSk" secondAttribute="baseline" id="CYq-KM-MIh"/>
<constraint firstItem="yyD-qq-aSk" firstAttribute="leading" secondItem="kGm-Zm-ipY" secondAttribute="trailing" constant="12" symbolic="YES" id="EGq-gP-YUt"/>
<constraint firstAttribute="bottom" secondItem="kGm-Zm-ipY" secondAttribute="bottom" constant="20" symbolic="YES" id="FYH-8M-te7"/>
<constraint firstItem="oZ5-85-pwY" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="251" id="JxK-S6-yOS"/>
<constraint firstItem="Gqv-5O-Wwf" firstAttribute="top" secondItem="u4U-Ju-FJV" secondAttribute="bottom" id="LJq-QU-Vhw"/>
<constraint firstItem="Gqv-5O-Wwf" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" constant="250" id="PxF-wu-Hfs"/>
<constraint firstAttribute="trailing" secondItem="oZ5-85-pwY" secondAttribute="trailing" constant="20" symbolic="YES" id="RnM-Z9-kYW"/>
<constraint firstItem="u4U-Ju-FJV" firstAttribute="top" secondItem="oZ5-85-pwY" secondAttribute="top" id="YHq-MK-f01"/>
<constraint firstItem="Gqv-5O-Wwf" firstAttribute="bottom" secondItem="oZ5-85-pwY" secondAttribute="bottom" id="Z3L-Aj-b7H"/>
<constraint firstItem="u4U-Ju-FJV" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="20" symbolic="YES" id="bVO-t4-Ptw"/>
<constraint firstItem="kGm-Zm-ipY" firstAttribute="top" secondItem="oZ5-85-pwY" secondAttribute="bottom" constant="20" symbolic="YES" id="bxj-ww-w1a"/>
<constraint firstItem="u4U-Ju-FJV" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" constant="20" symbolic="YES" id="f6j-0J-c14"/>
<constraint firstItem="u4U-Ju-FJV" firstAttribute="trailing" secondItem="Gqv-5O-Wwf" secondAttribute="trailing" id="kGk-iB-pW3"/>
<constraint firstItem="yyD-qq-aSk" firstAttribute="trailing" secondItem="oZ5-85-pwY" secondAttribute="trailing" id="nGi-Tj-4Ev"/>
<constraint firstItem="u4U-Ju-FJV" firstAttribute="leading" secondItem="Gqv-5O-Wwf" secondAttribute="leading" id="oo8-zB-YmU"/>
</constraints>
</view>
<connections>
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
</connections>
<point key="canvasLocation" x="391" y="222"/>
<point key="canvasLocation" x="412" y="222"/>
</window>
<numberFormatter formatterBehavior="default10_4" usesGroupingSeparator="NO" groupingSize="0" minimumIntegerDigits="0" maximumIntegerDigits="42" id="QZc-kt-D7Z" userLabel="Port Number Formatter">
<real key="minimum" value="1"/>

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15G31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="UserRulesController" customModule="ShadowsocksX_NG" customModuleProvider="target">
<connections>
<outlet property="didCancel" destination="2bi-hW-nd9" id="wKx-Nb-7Kt"/>
<outlet property="userRulesView" destination="4yV-hS-knY" id="HF3-TH-oBY"/>
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="User Rules" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<rect key="contentRect" x="196" y="240" width="480" height="270"/>
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1057"/>
<view key="contentView" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="N2T-OG-SO9">
<rect key="frame" x="385" y="13" width="81" height="32"/>
<buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="0Sc-cm-Vyu">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
DQ
</string>
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</buttonCell>
<connections>
<action selector="didOK:" target="-2" id="216-18-SFI"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2bi-hW-nd9">
<rect key="frame" x="304" y="13" width="81" height="32"/>
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="QAR-9i-kmv">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
Gw
</string>
</buttonCell>
<connections>
<action selector="didCancel:" target="-2" id="SFh-eD-YLV"/>
</connections>
</button>
<scrollView fixedFrame="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="J3L-MK-p8I">
<rect key="frame" x="20" y="61" width="440" height="189"/>
<clipView key="contentView" ambiguous="YES" id="fO6-Dc-ZUL">
<rect key="frame" x="1" y="1" width="423" height="187"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView ambiguous="YES" importsGraphics="NO" findStyle="panel" continuousSpellChecking="YES" allowsUndo="YES" usesRuler="YES" usesFontPanel="YES" verticallyResizable="YES" allowsNonContiguousLayout="YES" quoteSubstitution="YES" dashSubstitution="YES" spellingCorrection="YES" smartInsertDelete="YES" id="4yV-hS-knY">
<rect key="frame" x="0.0" y="0.0" width="423" height="187"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<size key="minSize" width="423" height="187"/>
<size key="maxSize" width="463" height="10000000"/>
<color key="insertionPointColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<size key="minSize" width="423" height="187"/>
<size key="maxSize" width="463" height="10000000"/>
</textView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="YES" id="z0Z-PW-muW">
<rect key="frame" x="-100" y="-100" width="87" height="18"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" verticalHuggingPriority="750" horizontal="NO" id="Us9-yx-gj4">
<rect key="frame" x="424" y="1" width="15" height="187"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
</subviews>
</view>
<connections>
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
</connections>
<point key="canvasLocation" x="343" y="474"/>
</window>
</objects>
</document>

View File

@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.1</string>
<string>1.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>

View File

@ -26,7 +26,14 @@ func getFileSHA1Sum(filepath: String) -> String {
func generateSSLocalLauchAgentPlist() -> Bool {
let sslocalPath = NSHomeDirectory() + APP_SUPPORT_DIR + "ss-local"
let logFilePath = NSHomeDirectory() + "/Library/Logs/ss-local.log"
let plistFilepath = NSHomeDirectory() + LAUNCH_AGENT_DIR + LAUNCH_AGENT_CONF_NAME
let launchAgentDirPath = NSHomeDirectory() + LAUNCH_AGENT_DIR
let plistFilepath = launchAgentDirPath + LAUNCH_AGENT_CONF_NAME
// Ensure launch agent directory is existed.
let fileMgr = NSFileManager.defaultManager()
if !fileMgr.fileExistsAtPath(launchAgentDirPath) {
try! fileMgr.createDirectoryAtPath(launchAgentDirPath, withIntermediateDirectories: true, attributes: nil)
}
let oldSha1Sum = getFileSHA1Sum(plistFilepath)

View File

@ -26,6 +26,8 @@ class PreferencesWindowController: NSWindowController
@IBOutlet weak var copyURLBtn: NSButton!
let tableViewDragType: String = "ss.server.profile.data"
var defaults: NSUserDefaults!
var profileMgr: ServerProfileManager!
@ -56,6 +58,10 @@ class PreferencesWindowController: NSWindowController
updateProfileBoxVisible()
}
override func awakeFromNib() {
profilesTableView.registerForDraggedTypes([tableViewDragType])
}
@IBAction func addProfile(sender: NSButton) {
if editingProfile != nil && !editingProfile.isValid(){
return
@ -203,6 +209,58 @@ class PreferencesWindowController: NSWindowController
return ""
}
// Drag & Drop reorder rows
func tableView(tableView: NSTableView, pasteboardWriterForRow row: Int) -> NSPasteboardWriting? {
let item = NSPasteboardItem()
item.setString(String(row), forType: tableViewDragType)
return item
}
func tableView(tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int
, proposedDropOperation dropOperation: NSTableViewDropOperation) -> NSDragOperation {
if dropOperation == .Above {
return .Move
}
return .None
}
func tableView(tableView: NSTableView, acceptDrop info: NSDraggingInfo
, row: Int, dropOperation: NSTableViewDropOperation) -> Bool {
if let mgr = profileMgr {
var oldIndexes = [Int]()
info.enumerateDraggingItemsWithOptions([], forView: tableView, classes: [NSPasteboardItem.self], searchOptions: [:]) {
if let str = ($0.0.item as! NSPasteboardItem).stringForType(self.tableViewDragType), index = Int(str) {
oldIndexes.append(index)
}
}
var oldIndexOffset = 0
var newIndexOffset = 0
// For simplicity, the code below uses `tableView.moveRowAtIndex` to move rows around directly.
// You may want to move rows in your content array and then call `tableView.reloadData()` instead.
tableView.beginUpdates()
for oldIndex in oldIndexes {
if oldIndex < row {
let o = mgr.profiles.removeAtIndex(oldIndex + oldIndexOffset)
mgr.profiles.insert(o, atIndex:row - 1)
tableView.moveRowAtIndex(oldIndex + oldIndexOffset, toIndex: row - 1)
oldIndexOffset -= 1
} else {
let o = mgr.profiles.removeAtIndex(oldIndex)
mgr.profiles.insert(o, atIndex:row + newIndexOffset)
tableView.moveRowAtIndex(oldIndex, toIndex: row + newIndexOffset)
newIndexOffset += 1
}
}
tableView.endUpdates()
return true
}
return false
}
//--------------------------------------------------
// For NSTableViewDelegate

View File

@ -136,7 +136,15 @@
}
+ (void)disableProxy {
NSMutableArray* args = [@[@"--mode", @"off"]mutableCopy];
// ssx-ng
NSString* urlString = [NSString stringWithFormat:@"%@/.ShadowsocksX-NG/gfwlist.js", NSHomeDirectory()];
NSURL* url = [NSURL fileURLWithPath:urlString];
NSUInteger port = [[NSUserDefaults standardUserDefaults]integerForKey:@"LocalSocks5.ListenPort"];
NSMutableArray* args = [@[@"--mode", @"off"
, @"--port", [NSString stringWithFormat:@"%lu", (unsigned long)port]
, @"--pac-url", [url absoluteString]
]mutableCopy];
[self addArguments4ManualSpecifyNetworkServices:args];
[self callHelper:args];
}

View File

@ -0,0 +1,53 @@
//
// UserRulesController.swift
// ShadowsocksX-NG
//
// Created by on 16/8/1.
// Copyright © 2016 qiuyuzhou. All rights reserved.
//
import Cocoa
class UserRulesController: NSWindowController {
@IBOutlet var userRulesView: NSTextView!
override func windowDidLoad() {
super.windowDidLoad()
let fileMgr = NSFileManager.defaultManager()
if !fileMgr.fileExistsAtPath(PACUserRuleFilePath) {
let src = NSBundle.mainBundle().pathForResource("user-rule", ofType: "txt")
try! fileMgr.copyItemAtPath(src!, toPath: PACUserRuleFilePath)
}
let str = try? String(contentsOfFile: PACUserRuleFilePath, encoding: NSUTF8StringEncoding)
userRulesView.string = str
}
@IBAction func didCancel(sender: AnyObject) {
window?.performClose(self)
}
@IBAction func didOK(sender: AnyObject) {
if let str = userRulesView.string {
do {
try str.dataUsingEncoding(NSUTF8StringEncoding)?.writeToFile(PACUserRuleFilePath, options: .DataWritingAtomic)
if GeneratePACFile() {
// Popup a user notification
let notification = NSUserNotification()
notification.title = "PAC has been updated by User Rules.".localized
NSUserNotificationCenter.defaultUserNotificationCenter()
.deliverNotification(notification)
} else {
let notification = NSUserNotification()
notification.title = "It's failed to update PAC by User Rules.".localized
NSUserNotificationCenter.defaultUserNotificationCenter()
.deliverNotification(notification)
}
} catch {}
}
window?.performClose(self)
}
}

View File

@ -9,6 +9,6 @@
#ifndef proxy_conf_helper_version_h
#define proxy_conf_helper_version_h
#define kProxyConfHelperVersion @"1.2.0"
#define kProxyConfHelperVersion @"1.3.1"
#endif /* proxy_conf_helper_version_h */

View File

@ -44,3 +44,9 @@
"Turn Shadowsocks On" = "打开 Shadowsocks";
"Proxy - Auto By PAC" = "代理 - PAC自动";
"Proxy - Global" = "代理 - 全局";
"Proxy - Manual" = "代理 - 手动";

View File

@ -0,0 +1,9 @@
/* Class = "NSButtonCell"; title = "OK"; ObjectID = "0Sc-cm-Vyu"; */
"0Sc-cm-Vyu.title" = "确定";
/* Class = "NSWindow"; title = "User Rules"; ObjectID = "F0z-JX-Cv5"; */
"F0z-JX-Cv5.title" = "用户规则";
/* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "QAR-9i-kmv"; */
"QAR-9i-kmv.title" = "取消";

View File

@ -67,10 +67,6 @@ int main(int argc, const char * argv[])
if (!portString) {
return 1;
}
port = [portString integerValue];
if (0 == port) {
return 1;
}
} else if (![@"off" isEqualToString:mode]) {
return 1;
}
@ -79,6 +75,12 @@ int main(int argc, const char * argv[])
return 0;
}
if (portString) {
port = [portString integerValue];
if (0 == port) {
return 1;
}
}
static AuthorizationRef authRef;
static AuthorizationFlags authFlags;
@ -126,11 +128,16 @@ int main(int argc, const char * argv[])
if (modify) {
NSString* prefPath = [NSString stringWithFormat:@"/%@/%@/%@", kSCPrefNetworkServices
, key, kSCEntNetProxies];
if ([mode isEqualToString:@"auto"]) {
[proxies setObject:pacURL forKey:(NSString *)kCFNetworkProxiesProxyAutoConfigURLString];
[proxies setObject:[NSNumber numberWithInt:1] forKey:(NSString *)kCFNetworkProxiesProxyAutoConfigEnable];
SCPreferencesPathSetValue(prefRef, (__bridge CFStringRef)prefPath
, (__bridge CFDictionaryRef)proxies);
} else if ([mode isEqualToString:@"global"]) {
@ -142,9 +149,29 @@ int main(int argc, const char * argv[])
kCFNetworkProxiesSOCKSEnable];
[proxies setObject:@[@"127.0.0.1", @"localhost"] forKey:(NSString *)kCFNetworkProxiesExceptionsList];
SCPreferencesPathSetValue(prefRef, (__bridge CFStringRef)prefPath
, (__bridge CFDictionaryRef)proxies);
} else if ([mode isEqualToString:@"off"]) {
if (pacURL != nil && portString != nil) {
// shadowsocksX-NG
NSDictionary* oldProxies
= (__bridge NSDictionary*)SCPreferencesPathGetValue(prefRef
, (__bridge CFStringRef)prefPath);
if (([oldProxies[(NSString *)kCFNetworkProxiesProxyAutoConfigURLString] isEqualToString:pacURL]
&&[oldProxies[(NSString *)kCFNetworkProxiesProxyAutoConfigEnable] isEqual:[NSNumber numberWithInt:1]])
||([oldProxies[(NSString*)kCFNetworkProxiesSOCKSProxy] isEqualToString:@"127.0.0.1"]
&&[oldProxies[(NSString*)kCFNetworkProxiesSOCKSPort] isEqualTo:[NSNumber numberWithInteger:port]]
&&[oldProxies[(NSString*)kCFNetworkProxiesSOCKSEnable] isEqual:[NSNumber numberWithInt:1]])
) {
SCPreferencesPathSetValue(prefRef, (__bridge CFStringRef)prefPath
, (__bridge CFDictionaryRef)proxies);
}
} else {
SCPreferencesPathSetValue(prefRef, (__bridge CFStringRef)prefPath
, (__bridge CFDictionaryRef)proxies);
}
}
SCPreferencesPathSetValue(prefRef, (__bridge CFStringRef)[NSString stringWithFormat:@"/%@/%@/%@", kSCPrefNetworkServices, key, kSCEntNetProxies], (__bridge CFDictionaryRef)proxies);
}
}