Skip to content

Commit

Permalink
Merge branch 'release/v1.6.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
qiuyuzhou committed Sep 8, 2017
2 parents fd99f16 + 071739d commit 89213c1
Show file tree
Hide file tree
Showing 25 changed files with 309 additions and 126 deletions.
52 changes: 26 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ShadowsocksX-NG

Current version is 1.5
Current version is 1.5.2

[![Build Status](https://travis-ci.org/shadowsocks/ShadowsocksX-NG.svg?branch=develop)](https://travis-ci.org/shadowsocks/ShadowsocksX-NG)

Expand All @@ -9,63 +9,63 @@ Next Generation of [ShadowsocksX](https://github.com/shadowsocks/shadowsocks-iOS
## Why?

It's hard to maintain the original implementation as there is too much unused code in it.
It also embeds the ss-local source. It's crazy to maintain dependencies of ss-local.
So it's hard to update the ss-local version.
It also embeds the `ss-local` source. It's crazy to maintain dependencies of `ss-local`.
So it's hard to update the `ss-local` version.

Now I just copied the ss-local from homebrew. Run ss-local executable as a Launch Agent in the background.
Serve PAC js file as a file URL. So there is only some source code related to GUI left.
Now I just copied the `ss-local` from Homebrew. Run `ss-local` executable as a Launch Agent in the background.
Serve PAC JS file as a file URL. So there is only some source code related to GUI left.
Then I will rewrite the GUI code in Swift.

## Requirements

### Running

- Mac OS X 10.11 +
- macOS 10.11+

### Building

- XCode 8.3+
- cocoapod 1.2+
- Xcode 8.3+
- CocoaPods 1.2+

## Download

From [here](https://github.com/shadowsocks/ShadowsocksX-NG/releases/)

## Features

- Use ss-local from shadowsocks-libev 3.0.5
- Could Update PAC by download GFW List from GitHub.
- Show QRCode for current server profile.
- Scan QRCode from screen.
- Uses `ss-local` from shadowsocks-libev 3.0.5
- Could update PAC by download GFW List from GitHub.
- Shows QRCode for current server profile.
- Scans QRCode from screen.
- Auto launch at login.
- User rules for PAC.
- Support OTA
- Support for [AEAD Ciphers](https://shadowsocks.org/en/spec/AEAD-Ciphers.html)
- HTTP Proxy by [privoxy](http://www.privoxy.org/)
- Over [kcptun](https://github.com/xtaci/kcptun). Version 20170322
- Export/Import configure file.
- An advanced preferences panel to configure:
- Local socks5 listen address.
- Local socks5 listen port.
- Local socks5 timeout.
- An advanced preferences panel for configuring:
- Local SOCKS5 listen address.
- Local SOCKS5 listen port.
- Local SOCKS5 timeout.
- If enable UDP relay.
- GFW List URL.
- Manual specify network service profiles which would be configure the proxy.
- Could reorder shadowsocks profiles by drag & drop in servers preferences panel.
- Manually specify network service profiles which would be used to configure the proxy.
- Could reorder shadowsocks profiles by drag-&-dropping in servers preferences panel.
- Configurable global shortcuts for toggle running and switch proxy mode.

## Different from orignal ShadowsocksX
## Difference from original ShadowsocksX

Run ss-local as a background service through launchd, not as an in-app process.
So after you quit the app, the ss-local maybe be still running.
`ss-local` is run as a background service through launchd, not as an in-app process.
So after you quit the app, the `ss-local` might be still running.

Added a manual mode which won't configure the system proxy settings.
Then you could configure your apps to use socks5 proxy manual.
Added a manual mode which won't configure the system proxy settings,
so that you could configure your apps to use the SOCKS5 proxy manually.

## Contributing
## Contributing

[![gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ShadowsocksX-NG/Lobby)

Contributions must be available on a separately named branch based on the latest version of the main branch develop.
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/)

Expand Down
4 changes: 4 additions & 0 deletions ShadowsocksX-NG.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
9BA04B231D23D5A5005AAD7F /* ProxyConfTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BA04B221D23D5A5005AAD7F /* ProxyConfTool.m */; };
9BAFE2E21E83ED7F00F71CCE /* PreferencesWinController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9BAFE2E41E83ED7F00F71CCE /* PreferencesWinController.xib */; };
9BB706A71D1B982300551F0E /* SWBApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BB706A51D1B982300551F0E /* SWBApplication.m */; };
9BBE7B751F508A0E00E8FFE5 /* fix_dir_owner.sh in Resources */ = {isa = PBXBuildFile; fileRef = 9BBE7B711F50790500E8FFE5 /* fix_dir_owner.sh */; };
9BC70EDC1D2E3E3100EDA4CA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9B172A6C1D0ADDDD00B87B9A /* Localizable.strings */; };
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 */; };
Expand Down Expand Up @@ -216,6 +217,7 @@
9BAFE2EB1E83F91D00F71CCE /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/MainMenu.strings"; sourceTree = "<group>"; };
9BB706A51D1B982300551F0E /* SWBApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SWBApplication.m; sourceTree = "<group>"; };
9BB706A61D1B982300551F0E /* SWBApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWBApplication.h; sourceTree = "<group>"; };
9BBE7B711F50790500E8FFE5 /* fix_dir_owner.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = fix_dir_owner.sh; sourceTree = "<group>"; };
9BE8FBC11D0B71CF00CAFD01 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/PreferencesWindowController.strings"; sourceTree = "<group>"; };
9BEEF0651D04CB8500FC52B3 /* install_ss_local.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = install_ss_local.sh; sourceTree = "<group>"; };
9BEEF0661D04CE8D00FC52B3 /* start_ss_local.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = start_ss_local.sh; sourceTree = "<group>"; };
Expand Down Expand Up @@ -324,6 +326,7 @@
C6D429981DA76FBC002A5711 /* privoxy.config.example */,
9B9CBCB01E2644DC00FC61AA /* start_kcptun.sh */,
9B9CBCB11E26450D00FC61AA /* stop_kcptun.sh */,
9BBE7B711F50790500E8FFE5 /* fix_dir_owner.sh */,
);
name = "Support Files";
sourceTree = "<group>";
Expand Down Expand Up @@ -577,6 +580,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9BBE7B751F508A0E00E8FFE5 /* fix_dir_owner.sh in Resources */,
9B3F7BFF1E82BF5B00C68B75 /* libev.4.dylib in Resources */,
9B3F7C001E82BF5B00C68B75 /* libmbedcrypto.2.4.2.dylib in Resources */,
9B3F7C011E82BF5B00C68B75 /* libsodium.18.dylib in Resources */,
Expand Down
81 changes: 49 additions & 32 deletions ShadowsocksX-NG/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
@IBOutlet weak var serversMenuItem: NSMenuItem!
@IBOutlet var showQRCodeMenuItem: NSMenuItem!
@IBOutlet var scanQRCodeMenuItem: NSMenuItem!
@IBOutlet var showBunchJsonExampleFileItem: NSMenuItem!
@IBOutlet var importBunchJsonFileItem: NSMenuItem!
@IBOutlet var exportAllServerProfileItem: NSMenuItem!
@IBOutlet var serversPreferencesMenuItem: NSMenuItem!
@IBOutlet var serverProfilesBeginSeparatorMenuItem: NSMenuItem!
@IBOutlet var serverProfilesEndSeparatorMenuItem: NSMenuItem!

@IBOutlet weak var copyHttpProxyExportCmdLineMenuItem: NSMenuItem!

Expand All @@ -48,14 +46,38 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
let kProfileMenuItemIndexBase = 100

var statusItem: NSStatusItem!
static let StatusItemIconWidth:CGFloat = 20
static let StatusItemIconWidth: CGFloat = NSVariableStatusItemLength

func ensureLaunchAgentsDirOwner () {
let dirPath = NSHomeDirectory() + "/Library/LaunchAgents"
let fileMgr = FileManager.default
if fileMgr.fileExists(atPath: dirPath) {
do {
let attrs = try fileMgr.attributesOfItem(atPath: dirPath)
if attrs[FileAttributeKey.ownerAccountName] as! String != NSUserName() {
//try fileMgr.setAttributes([FileAttributeKey.ownerAccountName: NSUserName()], ofItemAtPath: dirPath)
let bashFilePath = Bundle.main.path(forResource: "fix_dir_owner.sh", ofType: nil)!
let script = "do shell script \"bash \(bashFilePath) \(NSUserName()) \" with administrator privileges"
if let appleScript = NSAppleScript(source: script) {
var err: NSDictionary? = nil
appleScript.executeAndReturnError(&err)
}
}
}
catch {
NSLog("Error when ensure the owner of $HOME/Library/LaunchAgents, \(error.localizedDescription)")
}
}
}

func applicationDidFinishLaunching(_ aNotification: Notification) {

_ = LaunchAtLoginController()// Ensure set when launch

NSUserNotificationCenter.default.delegate = self

self.ensureLaunchAgentsDirOwner()

// Prepare ss-local
InstallSSLocal()
InstallKcptunClient()
Expand Down Expand Up @@ -241,6 +263,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
}
qrcodeWinCtrl = SWBQRCodeWindowController(windowNibName: "SWBQRCodeWindowController")
qrcodeWinCtrl.qrCode = profile.URL()!.absoluteString
qrcodeWinCtrl.legacyQRCode = profile.URL(legacy: true)!.absoluteString
qrcodeWinCtrl.title = profile.title()
qrcodeWinCtrl.showWindow(self)
NSApp.activate(ignoringOtherApps: true)
Expand Down Expand Up @@ -453,39 +476,33 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
}

func updateServersMenu() {
guard let menu = serversMenuItem.submenu else { return }

let mgr = ServerProfileManager.instance
serversMenuItem.submenu?.removeAllItems()
let preferencesItem = serversPreferencesMenuItem
let showBunch = showBunchJsonExampleFileItem
let importBuntch = importBunchJsonFileItem
let exportAllServer = exportAllServerProfileItem

serversMenuItem.submenu?.addItem(preferencesItem!)
serversMenuItem.submenu?.addItem(NSMenuItem.separator())

var i = 0
for p in mgr.profiles {
let profiles = mgr.profiles

// Remove all profile menu items
let beginIndex = menu.index(of: serverProfilesBeginSeparatorMenuItem) + 1
let endIndex = menu.index(of: serverProfilesEndSeparatorMenuItem)
// Remove from end to begin, so the index won't change :)
for index in (beginIndex..<endIndex).reversed() {
menu.removeItem(at: index)
}

// Insert all profile menu items
for (i, profile) in profiles.enumerated().reversed() {
let item = NSMenuItem()
item.tag = i + kProfileMenuItemIndexBase
item.title = p.title()
if mgr.activeProfileId == p.uuid {
item.state = 1
}
if !p.isValid() {
item.isEnabled = false
}
item.title = profile.title()
item.state = (mgr.activeProfileId == profile.uuid) ? 1 : 0
item.isEnabled = profile.isValid()
item.action = #selector(AppDelegate.selectServer)

serversMenuItem.submenu?.addItem(item)
i += 1
}
if !mgr.profiles.isEmpty {
serversMenuItem.submenu?.addItem(NSMenuItem.separator())
menu.insertItem(item, at: beginIndex)
}

serversMenuItem.submenu?.addItem(showBunch!)
serversMenuItem.submenu?.addItem(importBuntch!)
serversMenuItem.submenu?.addItem(exportAllServer!)

// End separator is redundant if profile section is empty
serverProfilesEndSeparatorMenuItem.isHidden = profiles.isEmpty
}

func handleURLEvent(_ event: NSAppleEventDescriptor, withReplyEvent replyEvent: NSAppleEventDescriptor) {
Expand Down
11 changes: 5 additions & 6 deletions ShadowsocksX-NG/Base.lproj/MainMenu.xib
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11762"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12121"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
Expand All @@ -16,15 +16,13 @@
<connections>
<outlet property="autoModeMenuItem" destination="r07-Gu-aEz" id="9aH-pQ-Rgi"/>
<outlet property="copyHttpProxyExportCmdLineMenuItem" destination="lg6-To-GZA" id="VTb-he-dg4"/>
<outlet property="exportAllServerProfileItem" destination="6k0-gn-DQv" id="W2x-96-ISj"/>
<outlet property="globalModeMenuItem" destination="Mw3-Jm-eXA" id="ar5-Yx-3ze"/>
<outlet property="importBunchJsonFileItem" destination="T9g-gy-gvv" id="vua-jg-YWe"/>
<outlet property="manualModeMenuItem" destination="8PR-gs-c5N" id="9qz-mU-5kt"/>
<outlet property="runningStatusMenuItem" destination="fzk-mE-CEV" id="Vwm-Rg-Ykn"/>
<outlet property="scanQRCodeMenuItem" destination="Qe6-bF-paT" id="XHa-pa-nCa"/>
<outlet property="serverProfilesBeginSeparatorMenuItem" destination="4iN-w2-but" id="Jyu-48-AzD"/>
<outlet property="serverProfilesEndSeparatorMenuItem" destination="3cf-dF-7dx" id="eyc-6W-nWV"/>
<outlet property="serversMenuItem" destination="u5M-hQ-VSc" id="8gp-SY-Y4U"/>
<outlet property="serversPreferencesMenuItem" destination="M5r-E7-44f" id="voe-SX-k6a"/>
<outlet property="showBunchJsonExampleFileItem" destination="pdy-JE-50Q" id="xcZ-ep-mON"/>
<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"/>
Expand Down Expand Up @@ -73,6 +71,7 @@
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="4iN-w2-but"/>
<menuItem isSeparatorItem="YES" id="3cf-dF-7dx"/>
<menuItem title="Show Bunch Json Example File..." id="pdy-JE-50Q">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
Expand Down
4 changes: 2 additions & 2 deletions ShadowsocksX-NG/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.5.1</string>
<string>1.6.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
Expand All @@ -44,7 +44,7 @@
<key>LSUIElement</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2016年 qiuyuzhou. All rights reserved. License GPLv3.</string>
<string>Copyright © 2016-2017 qiuyuzhou. All rights reserved. License GPLv3.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
Expand Down
3 changes: 0 additions & 3 deletions ShadowsocksX-NG/LaunchAgentUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ func generateSSLocalLauchAgentPlist() -> Bool {
let dict: NSMutableDictionary = [
"Label": "com.qiuyuzhou.shadowsocksX-NG.local",
"WorkingDirectory": NSHomeDirectory() + APP_SUPPORT_DIR,
"KeepAlive": true,
"StandardOutPath": logFilePath,
"StandardErrorPath": logFilePath,
"ProgramArguments": arguments,
Expand Down Expand Up @@ -203,7 +202,6 @@ func generatePrivoxyLauchAgentPlist() -> Bool {
let dict: NSMutableDictionary = [
"Label": "com.qiuyuzhou.shadowsocksX-NG.http",
"WorkingDirectory": NSHomeDirectory() + APP_SUPPORT_DIR,
"KeepAlive": true,
"StandardOutPath": logFilePath,
"StandardErrorPath": logFilePath,
"ProgramArguments": arguments
Expand Down Expand Up @@ -358,7 +356,6 @@ func generateKcptunLauchAgentPlist() -> Bool {
let dict: NSMutableDictionary = [
"Label": "com.qiuyuzhou.shadowsocksX-NG.kcptun",
"WorkingDirectory": NSHomeDirectory() + APP_SUPPORT_DIR,
"KeepAlive": true,
"StandardOutPath": logFilePath,
"StandardErrorPath": logFilePath,
"ProgramArguments": arguments,
Expand Down
Loading

0 comments on commit 89213c1

Please sign in to comment.