Compare commits

..

97 Commits
1.6.0 ... 1.6.1

Author SHA1 Message Date
Nick Bolton
ddbef300ad ChangeLog for 1.6.1 2014-11-06 18:09:27 +00:00
Xinyu Hou
afa24f4a02 Disable the privilege helper tool #4191 2014-11-06 17:08:58 +00:00
Xinyu Hou
37be6ec45f Merge pull request #4160 from cribe78/cribe-pullrequest#4055
Fixed: Shift keys are not sent to clients #4055
2014-11-06 15:39:30 +00:00
Xinyu Hou
785bf4c01b Merge pull request #4123 from pdecat/master
Fixed: Linux Chrome hover doesn't work
2014-11-05 14:57:10 +00:00
Xinyu Hou
060d8da671 Used move instead of copytree since copy loses symlinks 2014-11-05 14:53:46 +00:00
Xinyu Hou
d347cbd45f Merge branch 'pdecat-master' 2014-11-05 10:25:31 +00:00
chris
65fc59eeae clean up changes for pull request 2014-11-04 12:17:30 -05:00
chris
93d864ad6f clean up changes for pull request 2014-11-04 12:16:58 -05:00
chris
8024aa9ab1 Working fix for #4055 (client shift key problem) in place 2014-11-04 12:06:30 -05:00
Xinyu Hou
3ebd939f32 Made Mac version check before fixing 2014-11-04 16:04:35 +00:00
Xinyu Hou
deed8a28a2 Made Qt frameworks reorganised only once 2014-11-04 15:41:36 +00:00
Xinyu Hou
546a40a653 Checked source and target existence when move #4149 2014-11-04 13:27:47 +00:00
Xinyu Hou
648d9400f3 Reorganize Qt frameworks layout on Mac 10.9 and 10.10#4149 2014-11-04 12:54:45 +00:00
Patrick Decat
fe15c4e928 Merge branch 'master' of https://github.com/pdecat/synergy 2014-10-29 18:43:05 +01:00
Patrick Decat
1f5c18720a Apply patch from https://github.com/synergy/synergy/issues/3749 2014-10-28 16:06:38 +01:00
Xinyu Hou
e98b3678df Merge branch 'jerry-sandbox' 2014-10-28 10:52:47 +00:00
Nick Bolton
6dea28d2a0 Update README 2014-10-27 15:53:53 -07:00
Nick Bolton
8e05604338 Update README 2014-10-27 15:51:36 -07:00
Nick Bolton
5d33d7fa86 Added some simple "getting started" info to the wiki 2014-10-27 15:51:10 -07:00
Xinyu Hou
117208754f Hided elevate checkbox on Unix #4130 2014-10-27 17:15:50 +00:00
Xinyu Hou
23670c5f9b Moved elevate checkbox to settings #4130 2014-10-27 17:10:12 +00:00
Xinyu Hou
d2191b6b93 Auto elevate for Windows UAC and screen lock #4130 2014-10-27 16:39:18 +00:00
Xinyu Hou
4d3fd14ada Merge branch 'caramis-master' 2014-10-27 14:46:54 +00:00
Xinyu Hou
6a5da5aaac Merge branch 'jerry-sandbox' 2014-10-27 14:40:39 +00:00
Xinyu Hou
6756296d85 Made daemon take full responsibility for logging #4128 2014-10-27 14:11:43 +00:00
Xinyu Hou
39b534f3b8 Merge branch 'petroules-mac-fixes' 2014-10-27 13:04:59 +00:00
Xinyu Hou
35e8c88887 Updated ignored list on Mac 2014-10-27 12:00:18 +00:00
Xinyu Hou
de68346874 Fixed hm config error 2014-10-27 11:58:25 +00:00
Xinyu Hou
4f51d5fa50 Used Mac Sdk from config to detect Mac version 2014-10-24 17:22:07 +01:00
Xinyu Hou
df29bf8e54 Merge branch 'helkanen-master' 2014-10-24 15:10:44 +01:00
Jake Petroules
5b4e46f8ea Fix Info.plist for Synergy GUI.
This fixes the blurriness on Retina displays.
2014-10-23 08:29:51 -07:00
Jake Petroules
fed63422a6 Fix typo causing 64-bit binaries to be excluded on OS X 10.6+. 2014-10-23 08:19:00 -07:00
Xinyu Hou
e707b426cf Ignore Qt Creator user's settings file 2014-10-23 13:22:51 +01:00
Xinyu Hou
5c6eba8790 Merged argsParse to master 2014-10-23 13:21:41 +01:00
Xinyu Hou
561d1c6993 Version to 1.6.1 2014-10-23 12:39:28 +01:00
Nick Bolton
c364befde2 Merge branch 'petroules-64bit' 2014-10-23 12:36:32 +01:00
Xinyu Hou
a32cb41342 Parse arg refactoring #4124
Used argParser in DaemonApp.
2014-10-23 12:09:09 +01:00
Xinyu Hou
a71ebc78b3 Parse arg refactoring #4124
Fixed compile error on Linux
2014-10-23 11:37:59 +01:00
Xinyu Hou
943a355359 Parse arg refactoring #4124
Used argParser to parse arguments and removed the old code
2014-10-23 11:30:51 +01:00
Nick Bolton
a7a0b0021d Only build 64-bit for OS X 10.6 and above #4126
@jakepetroules: Looks like we use ScreenSaver.framework which is not
available in 64-bit until OS X 10.6
(https://developer.apple.com/library/mac/documentation/UserExperience/Reference/ScreenSaver/ObjC_classic/index.html#//apple_ref/doc/uid/20001822).
I've changed the CMake configuration to only build 64-bit for OS X 10.6
and above. Hopefully everything should work now - try it out!
2014-10-23 10:00:11 +01:00
Jake Petroules
67f17a0fda Fix SDK detection to work with modern versions of Xcode.
This finds the the OS X SDK directory by using xcrun and known fallbacks; users shouldn't be symlinking /Developer.
2014-10-23 01:13:33 -07:00
Jake Petroules
e3d57af4fd Add support for building with 64-bit architectures on OS X.
This patch brings full 64-bit compatibility to Synergy on OS X by
replacing all obsolete 32-bit only Carbon functions with modern
equivalents. All functions introduced have been available since 10.4 so
this won't affect the minimum deployment target. Specifically:

Creating an empty CGEvent and getting its location is behaviourally
identical to GetGlobalMouse, and yes, both are in flipped coordinates.
This was tested with a multi-monitor configuration as well.

TrackMouseLocationWithOptions is behaviourally identical to
GetGlobalMouse in these cases because the timeout was 0 and none of the
other out params were used, except for the MouseTrackingResult in one
call was checked against kMouseTrackingTimedOut. Since the timeout was 0
and not kEventDurationForever, that value never could have been returned
anyway.

Instead of attempting to define SIntXX and UIntXX manually, MacTypes.h
is included on OS X. These types were wrong in 64-bit mode because of
this, causing type redefinition errors.
2014-10-23 01:13:33 -07:00
Nick Bolton
e786dbd60f fixed code style 2014-10-22 17:04:20 +01:00
Xinyu Hou
e26ccfdce6 Parse arg refactoring #4124
Added unit testing
2014-10-22 16:52:08 +01:00
Xinyu Hou
f9f2d8e8af Parse arg refactoring #4124
Implemented argParser class.
2014-10-22 16:35:28 +01:00
Xinyu Hou
d2814a423c Parse arg refactoring #4124
Extracted platform specific argument parsing code.
2014-10-22 16:27:38 +01:00
Nick Bolton
cfa10d68ca Merge branch 'master' of https://github.com/ali1234/synergy into ali1234-master 2014-10-22 15:52:06 +01:00
Nick Bolton
c09d2ad91e changed @ to - in package name 2014-10-22 15:06:17 +01:00
Nick Bolton
7abcf13317 fixed "hm dist src" command to support branches
also allowed non-unix platforms to run src
2014-10-22 15:06:17 +01:00
Nick Bolton
f3218ff53c added branch name to package names
now that buildbot builds branches, it'll be handy to see that branch
name in the package name.
2014-10-22 15:06:17 +01:00
Nick Bolton
072e03c6ce changed @ to - in package name 2014-10-22 15:05:28 +01:00
Nick Bolton
420ac24b0b fixed "hm dist src" command to support branches
also allowed non-unix platforms to run src
2014-10-22 15:05:28 +01:00
Nick Bolton
c18411b9a4 added branch name to package names
now that buildbot builds branches, it'll be handy to see that branch
name in the package name.
2014-10-22 15:05:27 +01:00
Nick Bolton
74873d763e changed @ to - in package name 2014-10-22 15:05:08 +01:00
Nick Bolton
aa8d6c95c7 fixed "hm dist src" command to support branches
also allowed non-unix platforms to run src
2014-10-22 15:05:08 +01:00
Nick Bolton
e0101b884f added branch name to package names
now that buildbot builds branches, it'll be handy to see that branch
name in the package name.
2014-10-22 15:05:07 +01:00
Nick Bolton
326901ef86 changed @ to - in package name 2014-10-22 14:58:13 +01:00
Nick Bolton
1c1f0e70f2 changed @ to - in package name 2014-10-22 14:56:57 +01:00
Nick Bolton
5a6bdfb5e6 fixed "hm dist src" command to support branches
also allowed non-unix platforms to run src
2014-10-22 14:37:15 +01:00
Nick Bolton
fe95ec5bc8 added branch name to package names
now that buildbot builds branches, it'll be handy to see that branch
name in the package name.
2014-10-22 14:37:15 +01:00
Nick Bolton
90aa90f19f created dist src export path 2014-10-22 14:37:15 +01:00
Nick Bolton
b85432aeee changed svn export to git export 2014-10-22 14:37:15 +01:00
Nick Bolton
0f926658dc added getGitRevision function to get current git revision. 2014-10-22 14:37:15 +01:00
Nick Bolton
5bd0139734 fixed "hm dist src" command to support branches
also allowed non-unix platforms to run src
2014-10-22 14:06:15 +01:00
Nick Bolton
07d56e8e03 added branch name to package names
now that buildbot builds branches, it'll be handy to see that branch
name in the package name.
2014-10-22 13:55:39 +01:00
Alistair Buxton
2709ae48db Implement DMRM message for relative mouse movement. 2014-10-22 13:53:05 +01:00
Alistair Buxton
b52f2e0ca7 Bail out of packet eater if less than 4 bytes available.
Without this, packlen will be initialized with undefined data. This
causes "oversize packet" errors.
2014-10-22 13:31:40 +01:00
Xinyu Hou
d22418606f Merge branch 'caramis-master' of https://github.com/synergy/synergy into caramis-master 2014-10-22 12:54:39 +01:00
Xinyu Hou
bc772f98a6 Unable to start synergy server with "Cannot create a file when that file already exists" message #3752
Go to next iteration as soon as it fails.
2014-10-22 12:53:14 +01:00
Nick Bolton
c2b3f1414b Merge branch 'master' of https://github.com/pdecat/synergy into pdecat-master 2014-10-22 12:49:16 +01:00
Nick Bolton
8e4f8e6b92 Merge branch 'master' of https://github.com/caramis/synergy into caramis-master 2014-10-22 12:34:35 +01:00
Jean-Philippe Andre
9e358233c3 Fix copy&paste for EFL applications
Fixes issue 4021.
2014-10-22 20:32:16 +09:00
Nick Bolton
4a24a2117a Merge branch 'master' of https://github.com/caramis/synergy into caramis-master 2014-10-22 11:59:14 +01:00
Xinyu Hou
4aa43d6995 Merge branch '64bit' of https://github.com/petroules/synergy into petroules-64bit 2014-10-22 11:40:00 +01:00
Nick Bolton
685f53c7fc cleaned up .gitignore (removed old files) 2014-10-21 16:15:57 +01:00
Nick Bolton
972922607b cleaned up .gitignore (removed old files) 2014-10-21 16:14:29 +01:00
Xinyu Hou
a58ca97941 Merge remote-tracking branch 'origin/master' 2014-10-21 16:00:56 +01:00
Xinyu Hou
e746cc401a Merge branch 'master' of https://github.com/synergy/synergy 2014-10-21 15:49:39 +01:00
Xinyu Hou
504e41966e Carbon loop not ready within 5 sec #4002
Port fix from enterprise.
2014-10-21 15:48:04 +01:00
SeokYeon Hwang
3a663092cf Do not throw exception if ProcessIdToSessionId() is failed.
Many security solutions forbid other program from accessing their own process. So if ProcessIdToSessionId() is failed, simply ignore it.

Signed-off-by: SeokYeon Hwang <caramis@gmail.com>
2014-10-21 19:51:28 +09:00
Nick Bolton
8b4a3a8b92 created dist src export path 2014-10-20 19:26:57 +01:00
Nick Bolton
3b3cec4040 changed svn export to git export 2014-10-20 19:06:25 +01:00
Nick Bolton
ec3a9c3f1f added getGitRevision function to get current git revision. 2014-10-20 17:46:11 +01:00
Nick Bolton
91423c9c97 ignored build files. 2014-10-20 17:45:17 +01:00
Nick Bolton
2dd56efa63 Test 3 2014-10-20 16:11:06 +01:00
Jake Petroules
b644b1253d Fix SDK detection to work with modern versions of Xcode.
This finds the the OS X SDK directory by using xcrun and known fallbacks; users shouldn't be symlinking /Developer.
2014-10-15 19:29:49 -07:00
Jake Petroules
7dd2db25ec Add support for building with 64-bit architectures on OS X.
This patch brings full 64-bit compatibility to Synergy on OS X by
replacing all obsolete 32-bit only Carbon functions with modern
equivalents. All functions introduced have been available since 10.4 so
this won't affect the minimum deployment target. Specifically:

Creating an empty CGEvent and getting its location is behaviourally
identical to GetGlobalMouse, and yes, both are in flipped coordinates.
This was tested with a multi-monitor configuration as well.

TrackMouseLocationWithOptions is behaviourally identical to
GetGlobalMouse in these cases because the timeout was 0 and none of the
other out params were used, except for the MouseTrackingResult in one
call was checked against kMouseTrackingTimedOut. Since the timeout was 0
and not kEventDurationForever, that value never could have been returned
anyway.

Instead of attempting to define SIntXX and UIntXX manually, MacTypes.h
is included on OS X. These types were wrong in 64-bit mode because of
this, causing type redefinition errors.
2014-10-15 19:29:49 -07:00
Xinyu Hou
38718a362f Enable drag and drop by default #4122
Remove premium login from GUI
2014-10-15 14:57:28 +01:00
Patrick Decat
aeab72f724 Apply patch from https://github.com/synergy/synergy/issues/3749 2014-10-15 14:51:44 +02:00
Nick Bolton
70c8f98615 Merge pull request #4121 from nbolton/master
test2
2014-10-14 09:10:54 +01:00
Nick Bolton
8daa83dbea test2 2014-10-14 09:09:23 +01:00
Nick Bolton
c3aa1963c9 test1 [no-issue][no-build] 2014-10-12 09:16:23 +00:00
jerry
a5db4dc8c5 removed test.txt [no-issue][no-build] 2014-09-24 13:21:58 +00:00
jerry
2c16180eba test [no-issue] 2014-09-24 13:21:07 +00:00
jerry
6da369b5f2 created a branch for refactoring args parsing [no-issue][no-build] 2014-09-24 13:08:17 +00:00
jerry
7e562273d5 [no-issue]
revert to r2421
2014-09-15 15:17:07 +00:00
jerry
1805dd7900 issue #575 - Cannot build x86_64 or ppc64 on Mac OS X
applied patch by Jake Petroules
2014-09-15 13:04:43 +00:00
78 changed files with 3232 additions and 2128 deletions

29
.gitignore vendored
View File

@@ -1,19 +1,14 @@
#Vim backup files
*~
#Python compiled files
*.pyc
#Git-svn created .gitignore
/Release
/Debug
/vc90.pdb
/synergy.ncb
/synergy.vcproj.ADOBENET.ssbarnea.user
/bin
/tool
/config.h
/tags
#doxygen
/doc/doxygen
/doc/doxygen.cfg
/lib
/build
/ext/cryptopp562
/ext/gmock-1.6.0
/ext/gtest-1.6.0
/src/gui/Makefile*
/src/gui/object_script*
/src/gui/tmp
/src/gui/ui_*
src/gui/gui.pro.user
src/gui/.qmake.stash
config.h

View File

@@ -17,7 +17,7 @@
# Version number for Synergy
set(VERSION_MAJOR 1)
set(VERSION_MINOR 6)
set(VERSION_REV 0)
set(VERSION_REV 1)
set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REV}")
cmake_minimum_required(VERSION 2.6)
@@ -161,17 +161,20 @@ if (UNIX)
endif()
if (APPLE)
exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
message(STATUS "DARWIN_VERSION=${DARWIN_VERSION}")
if (DARWIN_VERSION LESS 9)
# 10.4: universal (32-bit intel and power pc)
message(STATUS "OSX_TARGET_MAJOR=${OSX_TARGET_MAJOR}")
message(STATUS "OSX_TARGET_MINOR=${OSX_TARGET_MINOR}")
if (NOT (OSX_TARGET_MAJOR EQUAL 10))
message(FATAL_ERROR "Mac OS X target must be 10.x")
endif ()
if (OSX_TARGET_MINOR LESS 6)
# <= 10.5: 32-bit Intel and PowerPC
set(CMAKE_OSX_ARCHITECTURES "ppc;i386"
CACHE STRING "" FORCE)
else()
# 10.5+: 32-bit only -- missing funcs in 64-bit os libs
# such as GetGlobalMouse.
set(CMAKE_OSX_ARCHITECTURES "i386"
# >= 10.6: Intel only
set(CMAKE_OSX_ARCHITECTURES "i386;x86_64"
CACHE STRING "" FORCE)
endif()

View File

@@ -1,3 +1,20 @@
1.6.1
=====
Bug #4002 - Carbon loop not ready within 5 sec
Bug #4191 - Accessibility helper tool crashes
Bug #4149 - Mac 10.9.5 or 10.10 gatekeeper blocks Synergy
Bug #4139 - Exception thrown when ProcessIdToSessionId() fails
Bug #4055 - Shift keys are not sent to clients (Win 8.1 server)
Bug #4021 - Copy & paste not working for EFL applications
Bug #3749 - Linux Chrome hover doesn't work
Bug #4128 - Daemon logging not written with "log to file"
Enhancement #4122 - Enable drag and drop by default
Enhancement #4158 - Build for Mac OS X 10.10
Enhancement #4130 - Auto elevate for Windows UAC and screen lock
Enhancement #4126 - 64-bit support for OS X
Enhancement #4141 - DMRM message support for μSynergy
Enhancement #4124 - More robust argument parsing
1.6.0
=====
Feature #65 - Auto config feature using Zeroconf/Bonjour

27
README
View File

@@ -1,2 +1,25 @@
Help: http://synergy-project.org/help/
Wiki: http://synergy-project.org/wiki/
About
=====
Synergy brings your computers together in one cohesive experience; its
software for sharing one mouse and keyboard between multiple computers
on your desk. It works on Windows, Mac OS X and Linux allowing you to
seamlessly move your mouse cursor between all computers on your desk.
Users
=====
Synergy is easy to download and configure.
Get it here: http://synergy-project.org/
Developers
==========
Synergy is free and open source, so you are free to run the program,
change the program, and redistribute the program with or without changes.
Once you've got the source code, just use "hm conf" and "hm build" to
compile (./hm.sh on Linux and Mac).
For detailed compile instructions and a list of dependencies, check
out our wiki: http://synergy-project.org/wiki/Compiling

View File

@@ -451,9 +451,15 @@ class InternalCommands:
cmake_args += ' -DCMAKE_BUILD_TYPE=' + target.capitalize()
elif sys.platform == "darwin":
macSdkMatch = re.match("(\d+)\.(\d+)", self.macSdk)
if not macSdkMatch:
raise Exception("unknown osx version: " + self.macSdk)
sdkDir = self.getMacSdkDir()
cmake_args += " -DCMAKE_OSX_SYSROOT=" + sdkDir
cmake_args += " -DCMAKE_OSX_DEPLOYMENT_TARGET=" + self.macSdk
cmake_args += " -DOSX_TARGET_MAJOR=" + macSdkMatch.group(1)
cmake_args += " -DOSX_TARGET_MINOR=" + macSdkMatch.group(2)
# if not visual studio, use parent dir
sourceDir = generator.getSourceDir()
@@ -554,7 +560,24 @@ class InternalCommands:
return (major, minor, rev)
def getMacSdkDir(self):
return "/Developer/SDKs/MacOSX" + self.macSdk + ".sdk"
sdkName = "macosx" + self.macSdk
# Ideally we'll use xcrun (which is influenced by $DEVELOPER_DIR), then try a couple
# fallbacks to known paths if xcrun is not available
status, sdkPath = commands.getstatusoutput("xcrun --show-sdk-path --sdk " + sdkName)
if status == 0 and sdkPath:
return sdkPath
developerDir = os.getenv("DEVELOPER_DIR")
if not developerDir:
developerDir = "/Applications/Xcode.app/Contents/Developer"
sdkDirName = sdkName.replace("macosx", "MacOSX")
sdkPath = developerDir + "/Platforms/MacOSX.platform/Developer/SDKs/" + sdkDirName + ".sdk"
if os.path.exists(sdkPath):
return sdkPath
return "/Developer/SDKs/" + sdkDirName + ".sdk"
# http://tinyurl.com/cs2rxxb
def fixCmakeEclipseBug(self):
@@ -734,7 +757,13 @@ class InternalCommands:
raise Exception('Build command not supported with generator: ' + generator)
def makeGui(self, targets, args=""):
name = "Synergy.app"
self.try_chdir(self.getGenerator().binDir)
if os.path.exists(name):
print "removing exisiting bundle"
shutil.rmtree(name)
self.restore_chdir()
if sys.platform == 'win32':
gui_make_cmd = self.w32_make_cmd
elif sys.platform in ['linux2', 'sunos5', 'freebsd7', 'darwin']:
@@ -765,7 +794,50 @@ class InternalCommands:
if sys.platform == 'darwin' and not "clean" in args:
for target in targets:
self.macPostMake(target)
self.fixQtFrameworksLayout()
def symlink(self, source, target):
if not os.path.exists(target):
os.symlink(source, target)
def move(self, source, target):
if os.path.exists(source):
shutil.move(source, target)
def fixQtFrameworksLayout(self):
# reorganize Qt frameworks layout on Mac 10.9.5 or later
# http://goo.gl/BFnQ8l
# QtCore example:
# QtCore.framework/
# QtCore -> Versions/Current/QtCore
# Resources -> Versions/Current/Resources
# Versions/
# Current -> 5
# 5/
# QtCore
# Resources/
# Info.plist
dir = self.getGenerator().binDir
target = dir + "/Synergy.app/Contents/Frameworks"
(major, minor) = self.getMacVersion()
if major == 10:
if minor >= 9:
for root, dirs, files in os.walk(target):
for dir in dirs:
if dir.startswith("Qt"):
self.try_chdir(target + "/" + dir +"/Versions")
self.symlink("5", "Current")
self.move("../Resources", "5")
self.restore_chdir()
self.try_chdir(target + "/" + dir)
dot = dir.find('.')
frameworkName = dir[:dot]
self.symlink("Versions/Current/" + frameworkName, frameworkName)
self.symlink("Versions/Current/Resources", "Resources")
self.restore_chdir()
def macPostMake(self, target):
dir = self.getGenerator().binDir
@@ -779,7 +851,7 @@ class InternalCommands:
shutil.copy(targetDir + "/synergyc", bundleBinDir)
shutil.copy(targetDir + "/synergys", bundleBinDir)
shutil.copy(targetDir + "/syntool", bundleBinDir)
if self.macSdk == "10.9":
launchServicesDir = dir + "/Synergy.app/Contents/Library/LaunchServices/"
if not os.path.exists(launchServicesDir):
@@ -805,15 +877,16 @@ class InternalCommands:
# TODO: auto-detect, qt can now be installed anywhere.
frameworkRootDir = "/Developer/Qt5.2.1/5.2.1/clang_64/lib"
# copy the missing Info.plist files for the frameworks.
target = dir + "/Synergy.app/Contents/Frameworks"
# copy the missing Info.plist files for the frameworks.
for root, dirs, files in os.walk(target):
for dir in dirs:
if dir.startswith("Qt"):
shutil.copy(
frameworkRootDir + "/" + dir + "/Contents/Info.plist",
target + "/" + dir + "/Resources/")
def signmac(self):
self.loadConfig()
if not self.macIdentity:
@@ -941,6 +1014,39 @@ class InternalCommands:
print self.find_revision()
def find_revision(self):
return self.getGitRevision()
def getGitRevision(self):
if sys.version_info < (2, 4):
raise Exception("Python 2.4 or greater required.")
p = subprocess.Popen(
["git", "log", "--pretty=format:%h", "-n", "1"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode != 0:
raise Exception('Could not get revision, git error: ' + str(p.returncode))
return stdout.strip()
def getGitBranchName(self):
if sys.version_info < (2, 4):
raise Exception("Python 2.4 or greater required.")
p = subprocess.Popen(
["git", "rev-parse", "--abbrev-ref", "HEAD"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode != 0:
raise Exception('Could not get branch name, git error: ' + str(p.returncode))
return stdout.strip()
def find_revision_svn(self):
if sys.version_info < (2, 4):
stdout = commands.getoutput('svn info')
else:
@@ -986,10 +1092,7 @@ class InternalCommands:
moveExt = ''
if type == 'src':
if sys.platform in ['linux2', 'darwin']:
self.distSrc()
else:
package_unsupported = True
self.distSrc()
elif type == 'rpm':
if sys.platform == 'linux2':
@@ -1173,10 +1276,15 @@ class InternalCommands:
print "Removing existing export..."
shutil.rmtree(exportPath)
os.mkdir(exportPath)
cmd = "git archive %s | tar -x -C %s" % (
self.getGitBranchName(), exportPath)
print 'Exporting repository to: ' + exportPath
err = os.system('svn export . ' + exportPath)
err = os.system(cmd)
if err != 0:
raise Exception('Repository export failed: ' + str(err))
raise Exception('Repository export failed: ' + str(err))
packagePath = '../' + self.getGenerator().binDir + '/' + name + '.tar.gz'
@@ -1206,7 +1314,7 @@ class InternalCommands:
shutil.rmtree(dist)
os.makedirs(dist)
shutil.copytree(dir + "/" + name + ".app", dist + "/" + name + ".app")
shutil.move(dir + "/" + name + ".app", dist + "/" + name + ".app")
self.try_chdir(dist)
err = os.system("ln -s /Applications")
@@ -1403,9 +1511,10 @@ class InternalCommands:
def dist_name_rev(self, type):
# find the version number (we're puting the rev in after this)
pattern = '(.*\d+\.\d+\.\d+)(.*)'
replace = '\g<1>-r' + self.find_revision() + '\g<2>'
replace = "\g<1>-%s-%s\g<2>" % (
self.getGitBranchName(), self.getGitRevision())
return re.sub(pattern, replace, self.dist_name(type))
def dist_usage(self):
print ('Usage: %s package [package-type]\n'
'\n'

View File

@@ -25,7 +25,7 @@ if (WIN32)
endif()
if (APPLE)
if (DARWIN_VERSION GREATER 12)
if (OSX_TARGET_MINOR GREATER 8)
add_subdirectory(synmacph)
endif()
endif()

View File

@@ -1,115 +1,113 @@
QT += widgets network
QT += widgets \
network
TEMPLATE = app
TARGET = synergy
DEPENDPATH += . \
res
res
INCLUDEPATH += . \
src
src
FORMS += res/MainWindowBase.ui \
res/AboutDialogBase.ui \
res/ServerConfigDialogBase.ui \
res/ScreenSettingsDialogBase.ui \
res/ActionDialogBase.ui \
res/HotkeyDialogBase.ui \
res/SettingsDialogBase.ui \
res/SetupWizardBase.ui
res/AboutDialogBase.ui \
res/ServerConfigDialogBase.ui \
res/ScreenSettingsDialogBase.ui \
res/ActionDialogBase.ui \
res/HotkeyDialogBase.ui \
res/SettingsDialogBase.ui \
res/SetupWizardBase.ui
SOURCES += src/main.cpp \
src/MainWindow.cpp \
src/AboutDialog.cpp \
src/ServerConfig.cpp \
src/ServerConfigDialog.cpp \
src/ScreenSetupView.cpp \
src/Screen.cpp \
src/ScreenSetupModel.cpp \
src/NewScreenWidget.cpp \
src/TrashScreenWidget.cpp \
src/ScreenSettingsDialog.cpp \
src/BaseConfig.cpp \
src/HotkeyDialog.cpp \
src/ActionDialog.cpp \
src/Hotkey.cpp \
src/Action.cpp \
src/KeySequence.cpp \
src/KeySequenceWidget.cpp \
src/SettingsDialog.cpp \
src/AppConfig.cpp \
src/QSynergyApplication.cpp \
src/VersionChecker.cpp \
src/SetupWizard.cpp \
src/IpcClient.cpp \
src/IpcReader.cpp \
src/Ipc.cpp \
src/SynergyLocale.cpp \
src/QUtility.cpp \
src/PremiumAuth.cpp \
src/ZeroconfServer.cpp \
src/ZeroconfThread.cpp \
src/ZeroconfRegister.cpp \
src/ZeroconfBrowser.cpp \
src/ZeroconfService.cpp
src/MainWindow.cpp \
src/AboutDialog.cpp \
src/ServerConfig.cpp \
src/ServerConfigDialog.cpp \
src/ScreenSetupView.cpp \
src/Screen.cpp \
src/ScreenSetupModel.cpp \
src/NewScreenWidget.cpp \
src/TrashScreenWidget.cpp \
src/ScreenSettingsDialog.cpp \
src/BaseConfig.cpp \
src/HotkeyDialog.cpp \
src/ActionDialog.cpp \
src/Hotkey.cpp \
src/Action.cpp \
src/KeySequence.cpp \
src/KeySequenceWidget.cpp \
src/SettingsDialog.cpp \
src/AppConfig.cpp \
src/QSynergyApplication.cpp \
src/VersionChecker.cpp \
src/SetupWizard.cpp \
src/IpcClient.cpp \
src/IpcReader.cpp \
src/Ipc.cpp \
src/SynergyLocale.cpp \
src/QUtility.cpp \
src/ZeroconfServer.cpp \
src/ZeroconfThread.cpp \
src/ZeroconfRegister.cpp \
src/ZeroconfBrowser.cpp \
src/ZeroconfService.cpp
HEADERS += src/MainWindow.h \
src/AboutDialog.h \
src/ServerConfig.h \
src/ServerConfigDialog.h \
src/ScreenSetupView.h \
src/Screen.h \
src/ScreenSetupModel.h \
src/NewScreenWidget.h \
src/TrashScreenWidget.h \
src/ScreenSettingsDialog.h \
src/BaseConfig.h \
src/HotkeyDialog.h \
src/ActionDialog.h \
src/Hotkey.h \
src/Action.h \
src/KeySequence.h \
src/KeySequenceWidget.h \
src/SettingsDialog.h \
src/AppConfig.h \
src/QSynergyApplication.h \
src/VersionChecker.h \
src/SetupWizard.h \
src/IpcClient.h \
src/IpcReader.h \
src/Ipc.h \
src/SynergyLocale.h \
src/QUtility.h \
src/PremiumAuth.h \
src/ZeroconfServer.h \
src/ZeroconfThread.h \
src/ZeroconfRegister.h \
src/ZeroconfRecord.h \
src/ZeroconfBrowser.h \
src/ZeroconfService.h
src/AboutDialog.h \
src/ServerConfig.h \
src/ServerConfigDialog.h \
src/ScreenSetupView.h \
src/Screen.h \
src/ScreenSetupModel.h \
src/NewScreenWidget.h \
src/TrashScreenWidget.h \
src/ScreenSettingsDialog.h \
src/BaseConfig.h \
src/HotkeyDialog.h \
src/ActionDialog.h \
src/Hotkey.h \
src/Action.h \
src/KeySequence.h \
src/KeySequenceWidget.h \
src/SettingsDialog.h \
src/AppConfig.h \
src/QSynergyApplication.h \
src/VersionChecker.h \
src/SetupWizard.h \
src/IpcClient.h \
src/IpcReader.h \
src/Ipc.h \
src/SynergyLocale.h \
src/QUtility.h \
src/ZeroconfServer.h \
src/ZeroconfThread.h \
src/ZeroconfRegister.h \
src/ZeroconfRecord.h \
src/ZeroconfBrowser.h \
src/ZeroconfService.h
RESOURCES += res/Synergy.qrc
RC_FILE = res/win/Synergy.rc
macx {
HEADERS += src/AXDatabaseCleaner.h
OBJECTIVE_SOURCES += src/AXDatabaseCleaner.mm
QMAKE_INFO_PLIST = res/mac/Info.plist
TARGET = Synergy
QSYNERGY_ICON.files = res/mac/Synergy.icns
QSYNERGY_ICON.path = Contents/Resources
QMAKE_BUNDLE_DATA += QSYNERGY_ICON
LIBS += $$MACX_LIBS
}
unix:!macx {
LIBS += -ldns_sd
macx {
HEADERS += src/AXDatabaseCleaner.h
OBJECTIVE_SOURCES += src/AXDatabaseCleaner.mm
QMAKE_INFO_PLIST = res/mac/Info.plist
TARGET = Synergy
QSYNERGY_ICON.files = res/mac/Synergy.icns
QSYNERGY_ICON.path = Contents/Resources
QMAKE_BUNDLE_DATA += QSYNERGY_ICON
LIBS += $$MACX_LIBS
}
unix:!macx:LIBS += -ldns_sd
debug {
OBJECTS_DIR = tmp/debug
MOC_DIR = tmp/debug
RCC_DIR = tmp/debug
OBJECTS_DIR = tmp/debug
MOC_DIR = tmp/debug
RCC_DIR = tmp/debug
}
release {
OBJECTS_DIR = tmp/release
MOC_DIR = tmp/release
RCC_DIR = tmp/release
OBJECTS_DIR = tmp/release
MOC_DIR = tmp/release
RCC_DIR = tmp/release
}
win32 {
Debug:DESTDIR = ../../bin/Debug
Release:DESTDIR = ../../bin/Release
LIBS += -L"../../ext/bonjour/x64" -ldnssd
INCLUDEPATH += "$(BONJOUR_SDK_HOME)/Include"
Debug:DESTDIR = ../../bin/Debug
Release:DESTDIR = ../../bin/Release
LIBS += -L"../../ext/bonjour/x64" \
-ldnssd
INCLUDEPATH += "$(BONJOUR_SDK_HOME)/Include"
}
else:DESTDIR = ../../bin

File diff suppressed because it is too large Load Diff

View File

@@ -114,6 +114,13 @@
<item row="0" column="1">
<widget class="QComboBox" name="m_pComboLanguage"/>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="m_pCheckBoxElevateMode">
<property name="text">
<string>Elevate mode</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@@ -1,443 +1,245 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SetupWizardBase</class>
<widget class="QWizard" name="SetupWizardBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>556</width>
<height>464</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>500</width>
<height>390</height>
</size>
</property>
<property name="windowTitle">
<string>Setup Synergy</string>
</property>
<widget class="QWizardPage" name="m_pWelcomePage">
<property name="title">
<string>Welcome</string>
</property>
<property name="subTitle">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Thanks for installing Synergy!</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">&amp;Language:</string>
</property>
<property name="buddy">
<cstring>m_pComboLanguage</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="m_pComboLanguage">
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_7">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="locale">
<locale language="English" country="UnitedKingdom"/>
</property>
<property name="text">
<string>Synergy lets you easily share your mouse and keyboard between multiple computers on your desk, and it's Free and Open Source. Just move your mouse off the edge of one computer's screen on to another. You can even share all of your clipboards. All you need is a network connection. Synergy is cross-platform (works on Windows, Mac OS X and Linux).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWizardPage" name="m_pPremiumUserPage">
<property name="title">
<string>Synergy Premium</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QRadioButton" name="m_pRadioButtonPremiumLogin">
<property name="text">
<string>I donated to Synergy and have a premium login...</string>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_5">
<item row="0" column="0">
<widget class="QLabel" name="m_pLabel_28">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>&amp;Email:</string>
</property>
<property name="indent">
<number>10</number>
</property>
<property name="buddy">
<cstring>m_pLineEditPremiumEmail</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="m_pLineEditPremiumEmail">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="echoMode">
<enum>QLineEdit::Normal</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="m_pLabel_29">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>&amp;Password:</string>
</property>
<property name="indent">
<number>10</number>
</property>
<property name="buddy">
<cstring>m_pLineEditPremiumPassword</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="m_pLineEditPremiumPassword">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="m_pLabelForgotPassword">
<property name="text">
<string>&lt;a href=&quot;http://synergy-project.org/premium/reset/?source=gui&quot;&gt;Forgot password&lt;/a&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_12">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QRadioButton" name="m_pRadioButtonPremiumLater">
<property name="text">
<string>No, I have not donated to Synergy, skip this step</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_9">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>100</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWizardPage" name="m_pNodePage">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Server or Client?</string>
</property>
<property name="subTitle">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QRadioButton" name="m_pServerRadioButton">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>&amp;Server (share this computer's mouse and keyboard)</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_pClientLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;My main mouse and keyboard are connected to this computer. This will allow you to move your mouse over to another computer's screen. There can only be one server in your setup.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QRadioButton" name="m_pClientRadioButton">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>&amp;Client (use another computer's mouse and keyboard)</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_pServerLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;You have already set up a server. This computer will be controlled using the server's mouse and keyboard. There can be many clients in your setup.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
<tabstops>
<tabstop>m_pComboLanguage</tabstop>
<tabstop>m_pRadioButtonPremiumLogin</tabstop>
<tabstop>m_pLineEditPremiumEmail</tabstop>
<tabstop>m_pLineEditPremiumPassword</tabstop>
<tabstop>m_pRadioButtonPremiumLater</tabstop>
<tabstop>m_pServerRadioButton</tabstop>
<tabstop>m_pClientRadioButton</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SetupWizardBase</class>
<widget class="QWizard" name="SetupWizardBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>556</width>
<height>464</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>500</width>
<height>390</height>
</size>
</property>
<property name="windowTitle">
<string>Setup Synergy</string>
</property>
<widget class="QWizardPage" name="m_pWelcomePage">
<property name="title">
<string>Welcome</string>
</property>
<property name="subTitle">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Thanks for installing Synergy!</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">&amp;Language:</string>
</property>
<property name="buddy">
<cstring>m_pComboLanguage</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="m_pComboLanguage">
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_7">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="locale">
<locale language="English" country="UnitedKingdom"/>
</property>
<property name="text">
<string>Synergy lets you easily share your mouse and keyboard between multiple computers on your desk, and it's Free and Open Source. Just move your mouse off the edge of one computer's screen on to another. You can even share all of your clipboards. All you need is a network connection. Synergy is cross-platform (works on Windows, Mac OS X and Linux).</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWizardPage" name="m_pNodePage">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Server or Client?</string>
</property>
<property name="subTitle">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QRadioButton" name="m_pServerRadioButton">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>&amp;Server (share this computer's mouse and keyboard)</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_pClientLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;My main mouse and keyboard are connected to this computer. This will allow you to move your mouse over to another computer's screen. There can only be one server in your setup.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QRadioButton" name="m_pClientRadioButton">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>&amp;Client (use another computer's mouse and keyboard)</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_pServerLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;You have already set up a server. This computer will be controlled using the server's mouse and keyboard. There can be many clients in your setup.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
<tabstops>
<tabstop>m_pComboLanguage</tabstop>
<tabstop>m_pServerRadioButton</tabstop>
<tabstop>m_pClientRadioButton</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@@ -1,7 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>CFBundleIconFile</key>
<string>Synergy.icns</string>
<key>CFBundlePackageType</key>

View File

@@ -54,7 +54,8 @@ AppConfig::AppConfig(QSettings* settings) :
m_WizardLastRun(0),
m_CryptoPass(),
m_ProcessMode(DEFAULT_PROCESS_MODE),
m_AutoConnect(true)
m_AutoConnect(true),
m_ElevateMode(false)
{
Q_ASSERT(m_pSettings);
@@ -121,10 +122,9 @@ void AppConfig::loadSettings()
m_CryptoPass = settings().value("cryptoPass", "").toString();
m_CryptoEnabled = settings().value("cryptoEnabled", false).toBool();
m_Language = settings().value("language", QLocale::system().name()).toString();
m_PremiumEmail = settings().value("premiumEmail", "").toString();
m_PremiumToken = settings().value("premiumToken", "").toString();
m_StartedBefore = settings().value("startedBefore", false).toBool();
m_AutoConnect = settings().value("autoConnect", true).toBool();
m_ElevateMode = settings().value("elevateMode", false).toBool();
}
void AppConfig::saveSettings()
@@ -139,10 +139,9 @@ void AppConfig::saveSettings()
settings().setValue("cryptoPass", m_CryptoPass);
settings().setValue("cryptoEnabled", m_CryptoEnabled);
settings().setValue("language", m_Language);
settings().setValue("premiumEmail", m_PremiumEmail);
settings().setValue("premiumToken", m_PremiumToken);
settings().setValue("startedBefore", m_StartedBefore);
settings().setValue("autoConnect", m_AutoConnect);
settings().setValue("elevateMode", m_ElevateMode);
}
void AppConfig::setCryptoPass(const QString &s)
@@ -161,14 +160,12 @@ void AppConfig::setCryptoPass(const QString &s)
}
}
bool AppConfig::isPremium()
{
QString hashSrc = m_PremiumEmail + getFirstMacAddress();
QString hashResult = hash(hashSrc);
return hashResult == m_PremiumToken;
}
void AppConfig::setAutoConnect(bool autoConnect)
{
m_AutoConnect = autoConnect;
}
bool AppConfig::elevateMode()
{
return m_ElevateMode;
}

View File

@@ -30,7 +30,7 @@
//
// 1: first version
// 2: added language page
// 3: added premium page
// 3: added premium page and removed
//
const int kWizardVersion = 3;
@@ -67,8 +67,6 @@ class AppConfig
ProcessMode processMode() const { return m_ProcessMode; }
bool wizardShouldRun() const { return m_WizardLastRun < kWizardVersion; }
const QString& language() const { return m_Language; }
const QString& premiumEmail() const { return m_PremiumEmail; }
const QString& premiumToken() const { return m_PremiumToken; }
bool startedBefore() const { return m_StartedBefore; }
bool autoConnect() const { return m_AutoConnect; }
void setAutoConnect(bool autoConnect);
@@ -80,7 +78,7 @@ class AppConfig
bool detectPath(const QString& name, QString& path);
void persistLogDir();
bool isPremium();
bool elevateMode();
protected:
QSettings& settings() { return *m_pSettings; }
@@ -93,9 +91,8 @@ class AppConfig
void setCryptoEnabled(bool b) { m_CryptoEnabled = b; }
void setWizardHasRun() { m_WizardLastRun = kWizardVersion; }
void setLanguage(const QString language) { m_Language = language; }
void setPremiumEmail(const QString premiumEmail) { m_PremiumEmail = premiumEmail; }
void setPremiumToken(const QString premiumToken) { m_PremiumToken = premiumToken; }
void setStartedBefore(bool b) { m_StartedBefore = b; }
void setElevateMode(bool b) { m_ElevateMode = b; }
void loadSettings();
void saveSettings();
@@ -115,10 +112,9 @@ class AppConfig
QString m_CryptoPass;
ProcessMode m_ProcessMode;
QString m_Language;
QString m_PremiumEmail;
QString m_PremiumToken;
bool m_StartedBefore;
bool m_AutoConnect;
bool m_ElevateMode;
static const char m_SynergysName[];
static const char m_SynergycName[];

View File

@@ -70,8 +70,6 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
m_pTrayIcon(NULL),
m_pTrayIconMenu(NULL),
m_AlreadyHidden(false),
m_ElevateProcess(false),
m_SuppressElevateWarning(false),
m_pMenuBar(NULL),
m_pMenuFile(NULL),
m_pMenuEdit(NULL),
@@ -96,9 +94,6 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
connect(&m_IpcClient, SIGNAL(errorMessage(const QString&)), this, SLOT(appendLogError(const QString&)));
connect(&m_IpcClient, SIGNAL(infoMessage(const QString&)), this, SLOT(appendLogNote(const QString&)));
m_IpcClient.connectToHost();
#else
// elevate checkbox is only useful on ms windows.
m_pElevateCheckBox->hide();
#endif
// change default size based on os
@@ -128,8 +123,6 @@ MainWindow::~MainWindow()
void MainWindow::open()
{
updatePremiumInfo();
createTrayIcon();
showNormal();
@@ -164,8 +157,6 @@ void MainWindow::onModeChanged(bool startDesktop, bool applyService)
stopService();
startSynergy();
}
m_pElevateCheckBox->setEnabled(appConfig().processMode() == Service);
}
void MainWindow::setStatus(const QString &status)
@@ -247,10 +238,6 @@ void MainWindow::loadSettings()
m_pLineEditConfigFile->setText(settings().value("configFile", QDir::homePath() + "/" + synergyConfigName).toString());
m_pGroupClient->setChecked(settings().value("groupClientChecked", true).toBool());
m_pLineEditHostname->setText(settings().value("serverHostname").toString());
m_SuppressElevateWarning = true;
m_pElevateCheckBox->setChecked(settings().value("elevateChecked", false).toBool());
m_SuppressElevateWarning = false;
}
void MainWindow::initConnections()
@@ -416,10 +403,9 @@ void MainWindow::startSynergy()
}
#ifndef Q_OS_LINUX
if (appConfig().isPremium())
{
args << "--enable-drag-drop";
}
args << "--enable-drag-drop";
#endif
if ((synergyType() == synergyClient && !clientArgs(args, app))
@@ -479,7 +465,7 @@ void MainWindow::startSynergy()
if (serviceMode)
{
QString command(app + " " + args.join(" "));
m_IpcClient.sendCommand(command, m_ElevateProcess);
m_IpcClient.sendCommand(command, appConfig().elevateMode());
}
appConfig().setStartedBefore(true);
@@ -627,7 +613,7 @@ void MainWindow::stopSynergy()
void MainWindow::stopService()
{
// send empty command to stop service from laucning anything.
m_IpcClient.sendCommand("", m_ElevateProcess);
m_IpcClient.sendCommand("", appConfig().elevateMode());
}
void MainWindow::stopDesktop()
@@ -781,7 +767,6 @@ void MainWindow::changeEvent(QEvent* event)
case QEvent::LanguageChange:
retranslateUi(this);
retranslateMenuBar();
updatePremiumInfo();
break;
default:
@@ -790,20 +775,6 @@ void MainWindow::changeEvent(QEvent* event)
}
}
void MainWindow::updatePremiumInfo()
{
if (m_AppConfig.isPremium())
{
m_pWidgetPremium->hide();
setWindowTitle(tr("Synergy Premium"));
}
else
{
m_pWidgetPremium->show();
setWindowTitle(tr("Synergy"));
}
}
void MainWindow::updateZeroconfService()
{
if (!m_AppConfig.wizardShouldRun()) {
@@ -912,29 +883,6 @@ void MainWindow::on_m_pActionWizard_triggered()
{
SetupWizard wizard(*this, false);
wizard.exec();
updatePremiumInfo();
}
void MainWindow::on_m_pElevateCheckBox_toggled(bool checked)
{
if (checked && !m_SuppressElevateWarning) {
int r = QMessageBox::warning(
this, tr("Elevate Synergy"),
tr("Are you sure you want to elevate Synergy?\n\n"
"This allows Synergy to interact with elevated processes "
"and the UAC dialog, but can cause problems with non-elevated "
"processes. Elevate Synergy only if you really need to."),
QMessageBox::Yes | QMessageBox::No);
if (r != QMessageBox::Yes) {
m_pElevateCheckBox->setChecked(false);
return;
}
}
m_ElevateProcess = checked;
settings().setValue("elevateChecked", checked);
settings().sync();
}
void MainWindow::on_m_pButtonApply_clicked()

View File

@@ -114,7 +114,6 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
void on_m_pActionAbout_triggered();
void on_m_pActionSettings_triggered();
void on_m_pActionWizard_triggered();
void on_m_pElevateCheckBox_toggled(bool checked);
void synergyFinished(int exitCode, QProcess::ExitStatus);
void trayActivated(QSystemTrayIcon::ActivationReason reason);
void stopSynergy();
@@ -147,7 +146,6 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
void stopDesktop();
void changeEvent(QEvent* event);
void retranslateMenuBar();
void updatePremiumInfo();
private:
QSettings& m_Settings;
@@ -161,8 +159,6 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
bool m_AlreadyHidden;
VersionChecker m_VersionChecker;
IpcClient m_IpcClient;
bool m_ElevateProcess;
bool m_SuppressElevateWarning;
QMenuBar* m_pMenuBar;
QMenu* m_pMenuFile;
QMenu* m_pMenuEdit;

View File

@@ -1,67 +0,0 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 Bolton Software Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PremiumAuth.h"
#include "QUtility.h"
#include <QProcess>
#include <QCoreApplication>
#include <stdexcept>
// we use syntool to authenticate because Qt's http library is very
// unreliable, and since we're writing platform specific code, use the
// synergy code since there we can use integ tests.
QString PremiumAuth::request(const QString& email, const QString& password)
{
QString program(QCoreApplication::applicationDirPath() + "/syntool");
QStringList args("--premium-auth");
QProcess process;
process.setReadChannel(QProcess::StandardOutput);
process.start(program, args);
bool success = process.waitForStarted();
QString out, error;
if (success)
{
// hash password in case it contains interesting chars.
QString credentials(email + ":" + hash(password) + "\n");
process.write(credentials.toStdString().c_str());
if (process.waitForFinished()) {
out = process.readAllStandardOutput();
error = process.readAllStandardError();
}
}
out = out.trimmed();
error = error.trimmed();
if (out.isEmpty() ||
!error.isEmpty() ||
!success ||
process.exitCode() != 0)
{
throw std::runtime_error(
QString("Code: %1\nError: %2")
.arg(process.exitCode())
.arg(error.isEmpty() ? "Unknown" : error)
.toStdString());
}
return out;
}

View File

@@ -1,26 +0,0 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 Bolton Software Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QString>
class PremiumAuth
{
public:
QString request(const QString& email, const QString& password);
};

View File

@@ -30,7 +30,8 @@
SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) :
QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
Ui::SettingsDialogBase(),
m_AppConfig(config)
m_AppConfig(config),
m_SuppressElevateWarning(false)
{
setupUi(this);
@@ -48,6 +49,15 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) :
{
m_pLineEditCryptoPass->setText(appConfig().cryptoPass());
}
#if defined(Q_OS_WIN)
m_SuppressElevateWarning = true;
m_pCheckBoxElevateMode->setChecked(appConfig().elevateMode());
m_SuppressElevateWarning = false;
#else
// elevate checkbox is only useful on ms windows.
m_pCheckBoxElevateMode->hide();
#endif
}
void SettingsDialog::accept()
@@ -73,6 +83,7 @@ void SettingsDialog::accept()
appConfig().setCryptoEnabled(cryptoEnabled);
appConfig().setCryptoPass(cryptoPass);
appConfig().setLanguage(m_pComboLanguage->itemData(m_pComboLanguage->currentIndex()).toString());
appConfig().setElevateMode(m_pCheckBoxElevateMode->isChecked());
appConfig().saveSettings();
QDialog::accept();
}
@@ -144,3 +155,21 @@ void SettingsDialog::on_m_pComboLanguage_currentIndexChanged(int index)
QString ietfCode = m_pComboLanguage->itemData(index).toString();
QSynergyApplication::getInstance()->switchTranslator(ietfCode);
}
void SettingsDialog::on_m_pCheckBoxElevateMode_toggled(bool checked)
{
if (checked && !m_SuppressElevateWarning) {
int r = QMessageBox::warning(
this, tr("Elevate Synergy"),
tr("Are you sure you want to elevate Synergy?\n\n"
"This allows Synergy to interact with elevated processes "
"and the UAC dialog, but can cause problems with non-elevated "
"processes. Elevate Synergy only if you really need to."),
QMessageBox::Yes | QMessageBox::No);
if (r != QMessageBox::Yes) {
m_pCheckBoxElevateMode->setChecked(false);
return;
}
}
}

View File

@@ -44,8 +44,10 @@ class SettingsDialog : public QDialog, public Ui::SettingsDialogBase
private:
AppConfig& m_AppConfig;
SynergyLocale m_Locale;
bool m_SuppressElevateWarning;
private slots:
void on_m_pCheckBoxElevateMode_toggled(bool checked);
void on_m_pCheckBoxEnableCrypto_stateChanged(int );
void on_m_pComboLanguage_currentIndexChanged(int index);
void on_m_pCheckBoxLogToFile_stateChanged(int );

View File

@@ -19,15 +19,8 @@
#include "MainWindow.h"
#include "QSynergyApplication.h"
#include "QUtility.h"
#include "PremiumAuth.h"
#include <QMessageBox>
#include <QDesktopServices>
#include <QUrl>
#include <QNetworkRequest>
#include <QNetworkReply>
#define PREMIUM_REGISTER_URL "http://synergy-project.org/donate/?source=gui-wizard"
SetupWizard::SetupWizard(MainWindow& mainWindow, bool startMain) :
m_MainWindow(mainWindow),
@@ -58,13 +51,7 @@ SetupWizard::SetupWizard(MainWindow& mainWindow, bool startMain) :
m_Locale.fillLanguageComboBox(m_pComboLanguage);
setIndexFromItemData(m_pComboLanguage, m_MainWindow.appConfig().language());
AppConfig& appConfig = m_MainWindow.appConfig();
QString premiumEmail = appConfig.premiumEmail();
if (!premiumEmail.isEmpty())
{
m_pRadioButtonPremiumLogin->setChecked(true);
m_pLineEditPremiumEmail->setText(premiumEmail);
}
}
SetupWizard::~SetupWizard()
@@ -89,32 +76,6 @@ bool SetupWizard::validateCurrentPage()
return false;
}
}
else if (currentPage() == m_pPremiumUserPage)
{
if (m_pRadioButtonPremiumLogin->isChecked())
{
if (m_pLineEditPremiumEmail->text().isEmpty() ||
m_pLineEditPremiumPassword->text().isEmpty())
{
message.setText(tr("Please enter your email address and password."));
message.exec();
return false;
}
else if (!isPremiumLoginValid(message))
{
return false;
}
}
else if (m_pRadioButtonPremiumLater->isChecked())
{
return true;
}
else {
message.setText(tr("Please select an option."));
message.exec();
return false;
}
}
return true;
}
@@ -144,19 +105,6 @@ void SetupWizard::accept()
AppConfig& appConfig = m_MainWindow.appConfig();
appConfig.setLanguage(m_pComboLanguage->itemData(m_pComboLanguage->currentIndex()).toString());
appConfig.setPremiumEmail(m_pLineEditPremiumEmail->text());
if (!m_pRadioButtonPremiumLogin->isChecked())
{
appConfig.setPremiumToken("");
}
else
{
QString mac = getFirstMacAddress();
QString hashSrc = m_pLineEditPremiumEmail->text() + mac;
QString hashResult = hash(hashSrc);
appConfig.setPremiumToken(hashResult);
}
appConfig.setWizardHasRun();
appConfig.saveSettings();
@@ -205,65 +153,3 @@ void SetupWizard::on_m_pComboLanguage_currentIndexChanged(int index)
QString ietfCode = m_pComboLanguage->itemData(index).toString();
QSynergyApplication::getInstance()->switchTranslator(ietfCode);
}
void SetupWizard::on_m_pRadioButtonPremiumLogin_toggled(bool checked)
{
m_pLineEditPremiumEmail->setEnabled(checked);
m_pLineEditPremiumPassword->setEnabled(checked);
}
bool SetupWizard::isPremiumLoginValid(QMessageBox& message)
{
QString email = m_pLineEditPremiumEmail->text();
QString password = m_pLineEditPremiumPassword->text();
QString responseJson;
try
{
PremiumAuth auth;
responseJson = auth.request(email, password);
}
catch (std::exception& e)
{
message.critical(
this, "Error",
tr("Sorry, an error occured while trying to sign in. "
"Please contact the help desk, and provide the "
"following details.\n\n%1")
.arg(e.what()));
return false;
}
QRegExp resultRegex(".*\"result\".*:.*(true|false).*");
if (resultRegex.exactMatch(responseJson)) {
QString boolString = resultRegex.cap(1);
if (boolString == "true") {
return true;
}
else if (boolString == "false") {
message.critical(
this, "Error",
tr("Login failed, invalid email or password."));
return false;
}
}
else {
QRegExp errorRegex(".*\"error\".*:.*\"(.+)\".*");
if (errorRegex.exactMatch(responseJson)) {
// replace "\n" with real new lines.
QString error = errorRegex.cap(1).replace("\\n", "\n");
message.critical(
this, "Error",
tr("Login failed, an error occurred.\n\n%1").arg(error));
return false;
}
}
message.critical(
this, "Error",
tr("Login failed, an error occurred.\n\nServer response:\n\n%1")
.arg(responseJson));
return false;
}

View File

@@ -39,9 +39,6 @@ protected:
void accept();
void reject();
private:
bool isPremiumLoginValid(QMessageBox& message);
private:
MainWindow& m_MainWindow;
bool m_StartMain;
@@ -50,5 +47,4 @@ private:
private slots:
void on_m_pCheckBoxEnableCrypto_stateChanged(int );
void on_m_pComboLanguage_currentIndexChanged(int index);
void on_m_pRadioButtonPremiumLogin_toggled(bool checked);
};

View File

@@ -130,81 +130,26 @@ int waitForTray()
}
#if defined(Q_OS_MAC)
bool settingsExist()
{
QSettings settings;
//FIXME: check settings existance properly
int port = settings.value("port", -1).toInt();
return port == -1 ? false : true;
}
bool checkMacAssistiveDevices()
{
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 // mavericks
// new in mavericks, applications are trusted individually
// with use of the accessibility api. this call will show a
// prompt which can show the security/privacy/accessibility
// tab, with a list of allowed applications. synergy should
// show up there automatically, but will be unchecked.
const void* keys[] = { kAXTrustedCheckOptionPrompt };
const void* trueValue[] = { kCFBooleanTrue };
const void* falseValue[] = { kCFBooleanFalse };
CFDictionaryRef optionsWithPrompt = CFDictionaryCreate(NULL, keys, trueValue, 1, NULL, NULL);
CFDictionaryRef optionsWithoutPrompt = CFDictionaryCreate(NULL, keys, falseValue, 1, NULL, NULL);
bool result;
result = AXIsProcessTrustedWithOptions(optionsWithoutPrompt);
// Synergy is not checked in accessibility
if (!result) {
// if setting doesn't exist, just skip helper tool
if (!settingsExist()) {
result = AXIsProcessTrustedWithOptions(optionsWithPrompt);
}
else {
int reply;
reply = QMessageBox::question(
NULL,
"Synergy",
"Synergy requires access to Assistive Devices, but was not allowed.\n\nShould Synergy attempt to fix this?",
QMessageBox::Yes|QMessageBox::Default,
QMessageBox::No|QMessageBox::Escape);
if (reply == QMessageBox::Yes) {
// call privilege help tool
AXDatabaseCleaner axdc;
result = axdc.loadPrivilegeHelper();
result = axdc.xpcConnect();
QMessageBox box;
box.setModal(false);
box.setStandardButtons(0);
box.setText("Please wait.");
box.resize(150, 10);
box.show();
const char* command = "sudo sqlite3 /Library/Application\\ Support/com.apple.TCC/TCC.db 'delete from access where client like \"%Synergy.app%\"'";
result = axdc.privilegeCommand(command);
box.hide();
if (result) {
QMessageBox::information(
NULL, "Synergy",
"Synergy helper tool is complete. Please tick the checkbox in Accessibility.");
}
}
result = AXIsProcessTrustedWithOptions(optionsWithPrompt);
}
if (AXIsProcessTrusted()) {
return true;
}
CFRelease(optionsWithoutPrompt);
CFRelease(optionsWithPrompt);
const void* keys[] = { kAXTrustedCheckOptionPrompt };
const void* trueValue[] = { kCFBooleanTrue };
CFDictionaryRef options = CFDictionaryCreate(NULL, keys, trueValue, 1, NULL, NULL);
bool result = AXIsProcessTrustedWithOptions(options);
CFRelease(options);
return result;
#else

View File

@@ -50,6 +50,18 @@ public:
*/
virtual std::string getSystemDirectory() = 0;
//! Get installed directory
/*!
Returns the directory in which Synergy is installed.
*/
virtual std::string getInstalledDirectory() = 0;
//! Get log directory
/*!
Returns the log file directory.
*/
virtual std::string getLogDirectory() = 0;
//! Concatenate path components
/*!
Concatenate pathname components with a directory separator

View File

@@ -88,6 +88,22 @@ CArchFileUnix::getSystemDirectory()
return "/etc";
}
std::string
CArchFileUnix::getInstalledDirectory()
{
#if WINAPI_XWINDOWS
return "/bin";
#else
return "";
#endif
}
std::string
CArchFileUnix::getLogDirectory()
{
return "/var/log";
}
std::string
CArchFileUnix::concatPath(const std::string& prefix,
const std::string& suffix)

View File

@@ -32,6 +32,8 @@ public:
virtual const char* getBasename(const char* pathname);
virtual std::string getUserDirectory();
virtual std::string getSystemDirectory();
virtual std::string getInstalledDirectory();
virtual std::string getLogDirectory();
virtual std::string concatPath(const std::string& prefix,
const std::string& suffix);
};

View File

@@ -121,6 +121,24 @@ CArchFileWindows::getSystemDirectory()
}
}
std::string
CArchFileWindows::getInstalledDirectory()
{
char fileNameBuffer[MAX_PATH];
GetModuleFileName(NULL, fileNameBuffer, MAX_PATH);
std::string fileName(fileNameBuffer);
size_t lastSlash = fileName.find_last_of("\\");
fileName = fileName.substr(0, lastSlash);
return fileName;
}
std::string
CArchFileWindows::getLogDirectory()
{
return getInstalledDirectory();
}
std::string
CArchFileWindows::concatPath(const std::string& prefix,
const std::string& suffix)

View File

@@ -32,6 +32,8 @@ public:
virtual const char* getBasename(const char* pathname);
virtual std::string getUserDirectory();
virtual std::string getSystemDirectory();
virtual std::string getInstalledDirectory();
virtual std::string getLogDirectory();
virtual std::string concatPath(const std::string& prefix,
const std::string& suffix);
};

View File

@@ -26,6 +26,7 @@
#include <stdarg.h>
#define CLOG (CLog::getInstance())
#define BYE "\nTry `%s --help' for more information."
class ILogOutputter;
class CThread;

View File

@@ -235,14 +235,20 @@ CBufferedLogOutputter::write(ELevel, const char* message)
CFileLogOutputter::CFileLogOutputter(const char* logFile)
{
assert(logFile != NULL);
m_fileName = logFile;
setLogFilename(logFile);
}
CFileLogOutputter::~CFileLogOutputter()
{
}
void
CFileLogOutputter::setLogFilename(const char* logFile)
{
assert(logFile != NULL);
m_fileName = logFile;
}
bool
CFileLogOutputter::write(ELevel level, const char *message)
{

View File

@@ -79,8 +79,11 @@ public:
virtual void close();
virtual void show(bool showIfEmpty);
virtual bool write(ELevel level, const char* message);
void setLogFilename(const char* title);
private:
std::string m_fileName;
std::string m_fileName;
};
//! Write log to system log

View File

@@ -72,6 +72,9 @@
// Added this because it doesn't compile on OS X 10.6 because they are already defined in Carbon
#if !defined(__MACTYPES__)
#if defined(__APPLE__)
#include <CoreServices/CoreServices.h>
#else
typedef signed TYPE_OF_SIZE_1 SInt8;
typedef signed TYPE_OF_SIZE_2 SInt16;
typedef signed TYPE_OF_SIZE_4 SInt32;
@@ -79,6 +82,7 @@ typedef unsigned TYPE_OF_SIZE_1 UInt8;
typedef unsigned TYPE_OF_SIZE_2 UInt16;
typedef unsigned TYPE_OF_SIZE_4 UInt32;
#endif
#endif
//
// clean up
//

View File

@@ -141,7 +141,7 @@ CIpcClientProxy::send(const CIpcMessage& message)
// also, don't allow the dtor to destroy the stream while we're using it.
CArchMutexLock lock(m_writeMutex);
LOG((CLOG_DEBUG "ipc write: %d", message.type()));
LOG((CLOG_DEBUG4 "ipc write: %d", message.type()));
switch (message.type()) {
case kIpcLogLine: {

View File

@@ -83,7 +83,7 @@ CIpcServerProxy::handleData(const CEvent&, void*)
void
CIpcServerProxy::send(const CIpcMessage& message)
{
LOG((CLOG_DEBUG "ipc write: %d", message.type()));
LOG((CLOG_DEBUG4 "ipc write: %d", message.type()));
switch (message.type()) {
case kIpcHello: {

View File

@@ -21,7 +21,6 @@
#include "synergy/XSynergy.h"
#include "base/Log.h"
#include <Tlhelp32.h>
#include <Wtsapi32.h>
CMSWindowsSession::CMSWindowsSession() :
@@ -69,34 +68,29 @@ CMSWindowsSession::isProcessInSession(const char* name, PHANDLE process = NULL)
entry.th32ProcessID, &processSessionId);
if (!pidToSidRet) {
// if we can not acquire session associated with a specified process,
// simply ignore it
LOG((CLOG_ERR "could not get session id for process id %i", entry.th32ProcessID));
throw XArch(new XArchEvalWindows());
gotEntry = nextProcessEntry(snapshot, &entry);
continue;
}
else {
// only pay attention to processes in the active session
if (processSessionId == m_activeSessionId) {
// only pay attention to processes in the active session
if (processSessionId == m_activeSessionId) {
// store the names so we can record them for debug
nameList.push_back(entry.szExeFile);
// store the names so we can record them for debug
nameList.push_back(entry.szExeFile);
if (_stricmp(entry.szExeFile, name) == 0) {
pid = entry.th32ProcessID;
if (_stricmp(entry.szExeFile, name) == 0) {
pid = entry.th32ProcessID;
}
}
}
}
// now move on to the next entry (if we're not at the end)
gotEntry = Process32Next(snapshot, &entry);
if (!gotEntry) {
DWORD err = GetLastError();
if (err != ERROR_NO_MORE_FILES) {
// only worry about error if it's not the end of the snapshot
LOG((CLOG_ERR "could not get next process entry"));
throw XArch(new XArchEvalWindows());
}
}
gotEntry = nextProcessEntry(snapshot, &entry);
}
std::string nameListJoin;
@@ -158,3 +152,40 @@ CMSWindowsSession::updateActiveSession()
{
m_activeSessionId = WTSGetActiveConsoleSessionId();
}
BOOL
CMSWindowsSession::nextProcessEntry(HANDLE snapshot, LPPROCESSENTRY32 entry)
{
BOOL gotEntry = Process32Next(snapshot, entry);
if (!gotEntry) {
DWORD err = GetLastError();
if (err != ERROR_NO_MORE_FILES) {
// only worry about error if it's not the end of the snapshot
LOG((CLOG_ERR "could not get next process entry"));
throw XArch(new XArchEvalWindows());
}
}
return gotEntry;
}
CString
CMSWindowsSession::getActiveDesktopName()
{
CString result;
HDESK hd = OpenInputDesktop(0, TRUE, GENERIC_READ);
if (hd != NULL) {
DWORD size;
GetUserObjectInformation(hd, UOI_NAME, NULL, 0, &size);
TCHAR* name = (TCHAR*)alloca(size + sizeof(TCHAR));
GetUserObjectInformation(hd, UOI_NAME, name, size, &size);
result = name;
CloseDesktop(hd);
}
return result;
}

View File

@@ -17,8 +17,11 @@
#pragma once
#include "base/String.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <Tlhelp32.h>
class CMSWindowsSession {
public:
@@ -39,6 +42,11 @@ public:
void updateActiveSession();
CString getActiveDesktopName();
private:
BOOL nextProcessEntry(HANDLE snapshot, LPPROCESSENTRY32 entry);
private:
DWORD m_activeSessionId;
};

View File

@@ -28,6 +28,7 @@
#include "arch/win32/ArchDaemonWindows.h"
#include "arch/win32/XArchWindows.h"
#include "arch/Arch.h"
#include "base/log_outputters.h"
#include "base/TMethodJob.h"
#include "base/Log.h"
#include "common/Version.h"
@@ -42,6 +43,8 @@ enum {
typedef VOID (WINAPI *SendSas)(BOOL asUser);
const char g_activeDesktop[] = {"activeDesktop:"};
CMSWindowsWatchdog::CMSWindowsWatchdog(
bool autoDetectCommand,
CIpcServer& ipcServer,
@@ -56,12 +59,24 @@ CMSWindowsWatchdog::CMSWindowsWatchdog(
m_ipcLogOutputter(ipcLogOutputter),
m_elevateProcess(false),
m_processFailures(0),
m_processRunning(false)
m_processRunning(false),
m_fileLogOutputter(NULL),
m_autoElevated(false),
m_ready(false)
{
m_mutex = ARCH->newMutex();
m_condVar = ARCH->newCondVar();
}
CMSWindowsWatchdog::~CMSWindowsWatchdog()
{
if (m_condVar != NULL) {
ARCH->closeCondVar(m_condVar);
}
if (m_mutex != NULL) {
ARCH->closeMutex(m_mutex);
}
}
void
@@ -124,7 +139,9 @@ CMSWindowsWatchdog::getUserToken(LPSECURITY_ATTRIBUTES security)
// elevate for the uac dialog (consent.exe) but this would be pointless,
// since synergy would re-launch as non-elevated after the desk switch,
// and so would be unusable with the new elevated process taking focus.
if (m_elevateProcess || m_session.isProcessInSession("logonui.exe", NULL)) {
if (m_elevateProcess
|| m_autoElevated
|| m_session.isProcessInSession("logonui.exe", NULL)) {
LOG((CLOG_DEBUG "getting elevated token, %s",
(m_elevateProcess ? "elevation required" : "at login screen")));
@@ -245,6 +262,12 @@ CMSWindowsWatchdog::isProcessActive()
return exitCode == STILL_ACTIVE;
}
void
CMSWindowsWatchdog::setFileLogOutputter(CFileLogOutputter* outputter)
{
m_fileLogOutputter = outputter;
}
void
CMSWindowsWatchdog::startProcess()
{
@@ -265,7 +288,11 @@ CMSWindowsWatchdog::startProcess()
SECURITY_ATTRIBUTES sa;
ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
getActiveDesktop(&sa);
ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
HANDLE userToken = getUserToken(&sa);
m_autoElevated = false;
// patch by Jack Zhou and Henry Tung
// set UIAccess to fix Windows 8 GUI interaction
@@ -273,6 +300,33 @@ CMSWindowsWatchdog::startProcess()
DWORD uiAccess = 1;
SetTokenInformation(userToken, TokenUIAccess, &uiAccess, sizeof(DWORD));
BOOL createRet = doStartProcess(m_command, userToken, &sa);
if (!createRet) {
LOG((CLOG_ERR "could not launch"));
DWORD exitCode = 0;
GetExitCodeProcess(m_processInfo.hProcess, &exitCode);
LOG((CLOG_ERR "exit code: %d", exitCode));
throw XArch(new XArchEvalWindows);
}
else {
// wait for program to fail.
ARCH->sleep(1);
if (!isProcessActive()) {
throw XMSWindowsWatchdogError("process immediately stopped");
}
m_processRunning = true;
m_processFailures = 0;
LOG((CLOG_DEBUG "started process, session=%i, command=%s",
m_session.getActiveSessionId(), m_command.c_str()));
}
}
BOOL
CMSWindowsWatchdog::doStartProcess(CString& command, HANDLE userToken, LPSECURITY_ATTRIBUTES sa)
{
// clear, as we're reusing process info struct
ZeroMemory(&m_processInfo, sizeof(PROCESS_INFORMATION));
@@ -299,30 +353,14 @@ CMSWindowsWatchdog::startProcess()
// re-launch in current active user session
LOG((CLOG_INFO "starting new process"));
BOOL createRet = CreateProcessAsUser(
userToken, NULL, LPSTR(m_command.c_str()),
&sa, NULL, TRUE, creationFlags,
userToken, NULL, LPSTR(command.c_str()),
sa, NULL, TRUE, creationFlags,
environment, NULL, &si, &m_processInfo);
DestroyEnvironmentBlock(environment);
CloseHandle(userToken);
if (!createRet) {
LOG((CLOG_ERR "could not launch"));
throw XArch(new XArchEvalWindows);
}
else {
// wait for program to fail.
ARCH->sleep(1);
if (!isProcessActive()) {
throw XMSWindowsWatchdogError("process immediately stopped");
}
m_processRunning = true;
m_processFailures = 0;
LOG((CLOG_DEBUG "started process, session=%i, command=%s",
m_session.getActiveSessionId(), m_command.c_str()));
}
return createRet;
}
void
@@ -380,11 +418,16 @@ CMSWindowsWatchdog::outputLoop(void*)
else {
buffer[bytesRead] = '\0';
testOutput(buffer);
// send process output over IPC to GUI, and force it to be sent
// which bypasses the ipc logging anti-recursion mechanism.
m_ipcLogOutputter.write(kINFO, buffer, true);
}
if (m_fileLogOutputter != NULL) {
m_fileLogOutputter->write(kINFO, buffer);
}
}
}
}
@@ -481,3 +524,57 @@ CMSWindowsWatchdog::shutdownExistingProcesses()
CloseHandle(snapshot);
m_processRunning = false;
}
void
CMSWindowsWatchdog::getActiveDesktop(LPSECURITY_ATTRIBUTES security)
{
CString installedDir = ARCH->getInstalledDirectory();
if (!installedDir.empty()) {
CString syntoolCommand;
syntoolCommand.append("\"").append(installedDir).append("\\").append("syntool").append("\"");
syntoolCommand.append(" --get-active-desktop");
m_session.updateActiveSession();
bool elevateProcess = m_elevateProcess;
m_elevateProcess = true;
HANDLE userToken = getUserToken(security);
m_elevateProcess = elevateProcess;
BOOL createRet = doStartProcess(syntoolCommand, userToken, security);
if (!createRet) {
DWORD rc = GetLastError();
RevertToSelf();
}
else {
LOG((CLOG_DEBUG "launched syntool to check active desktop"));
}
ARCH->lockMutex(m_mutex);
while (!m_ready) {
ARCH->waitCondVar(m_condVar, m_mutex, 1.0);
}
m_ready = false;
ARCH->unlockMutex(m_mutex);
}
}
void
CMSWindowsWatchdog::testOutput(CString buffer)
{
// HACK: check standard output seems hacky.
size_t i = buffer.find(g_activeDesktop);
if (i != CString::npos) {
size_t s = sizeof(g_activeDesktop);
CString defaultDesktop("Default");
CString sub = buffer.substr(s - 1, defaultDesktop.size());
if (sub != defaultDesktop) {
m_autoElevated = true;
}
ARCH->lockMutex(m_mutex);
m_ready = true;
ARCH->broadcastCondVar(m_condVar);
ARCH->unlockMutex(m_mutex);
}
}

View File

@@ -20,6 +20,7 @@
#include "platform/MSWindowsSession.h"
#include "synergy/XSynergy.h"
#include "arch/IArchMultithread.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
@@ -29,6 +30,7 @@
class CThread;
class CIpcLogOutputter;
class CIpcServer;
class CFileLogOutputter;
class CMSWindowsWatchdog {
public:
@@ -43,6 +45,7 @@ public:
void setCommand(const std::string& command, bool elevate);
void stop();
bool isProcessActive();
void setFileLogOutputter(CFileLogOutputter* outputter);
private:
void mainLoop(void*);
@@ -52,7 +55,10 @@ private:
HANDLE duplicateProcessToken(HANDLE process, LPSECURITY_ATTRIBUTES security);
HANDLE getUserToken(LPSECURITY_ATTRIBUTES security);
void startProcess();
BOOL doStartProcess(CString& command, HANDLE userToken, LPSECURITY_ATTRIBUTES sa);
void sendSas();
void getActiveDesktop(LPSECURITY_ATTRIBUTES security);
void testOutput(CString buffer);
private:
CThread* m_thread;
@@ -70,6 +76,11 @@ private:
PROCESS_INFORMATION m_processInfo;
int m_processFailures;
bool m_processRunning;
CFileLogOutputter* m_fileLogOutputter;
bool m_autoElevated;
CArchMutex m_mutex;
CArchCond m_condVar;
bool m_ready;
};
//! Relauncher error

View File

@@ -62,6 +62,10 @@ enum {
kSynergyMouseScrollAxisY = 'saxy'
};
enum {
kCarbonLoopWaitTimeout = 10
};
// TODO: upgrade deprecated function usage in these functions.
void setZeroSuppressionInterval();
void avoidSupression();
@@ -292,13 +296,14 @@ COSXScreen::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
void
COSXScreen::getCursorPos(SInt32& x, SInt32& y) const
{
Point mouse;
GetGlobalMouse(&mouse);
x = mouse.h;
y = mouse.v;
CGEventRef event = CGEventCreate(NULL);
CGPoint mouse = CGEventGetLocation(event);
x = mouse.x;
y = mouse.y;
m_cursorPosValid = true;
m_xCursor = x;
m_yCursor = y;
CFRelease(event);
}
void
@@ -696,15 +701,16 @@ COSXScreen::fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const
// we can do.
// get current position
Point oldPos;
GetGlobalMouse(&oldPos);
CGEventRef event = CGEventCreate(NULL);
CGPoint oldPos = CGEventGetLocation(event);
CFRelease(event);
// synthesize event
CGPoint pos;
m_xCursor = static_cast<SInt32>(oldPos.h);
m_yCursor = static_cast<SInt32>(oldPos.v);
pos.x = oldPos.h + dx;
pos.y = oldPos.v + dy;
m_xCursor = static_cast<SInt32>(oldPos.x);
m_yCursor = static_cast<SInt32>(oldPos.y);
pos.x = oldPos.x + dx;
pos.y = oldPos.y + dy;
postMouseEvent(pos);
// we now assume we don't know the current cursor position
@@ -1052,7 +1058,7 @@ COSXScreen::handleSystemEvent(const CEvent& event, void*)
// get scroll amount
r = GetEventParameter(*carbonEvent,
kSynergyMouseScrollAxisX,
typeLongInteger,
typeSInt32,
NULL,
sizeof(xScroll),
NULL,
@@ -1062,7 +1068,7 @@ COSXScreen::handleSystemEvent(const CEvent& event, void*)
}
r = GetEventParameter(*carbonEvent,
kSynergyMouseScrollAxisY,
typeLongInteger,
typeSInt32,
NULL,
sizeof(yScroll),
NULL,
@@ -1090,7 +1096,10 @@ COSXScreen::handleSystemEvent(const CEvent& event, void*)
break;
case kEventClassWindow:
SendEventToWindow(*carbonEvent, m_userInputWindow);
// 2nd param was formerly GetWindowEventTarget(m_userInputWindow) which is 32-bit only,
// however as m_userInputWindow is never initialized to anything we can take advantage of
// the fact that GetWindowEventTarget(NULL) == NULL
SendEventToEventTarget(*carbonEvent, NULL);
switch (GetEventKind(*carbonEvent)) {
case kEventWindowActivated:
LOG((CLOG_DEBUG1 "window activated"));
@@ -1514,15 +1523,16 @@ COSXScreen::getScrollSpeedFactor() const
void
COSXScreen::enableDragTimer(bool enable)
{
UInt32 modifiers;
MouseTrackingResult res;
if (enable && m_dragTimer == NULL) {
m_dragTimer = m_events->newTimer(0.01, NULL);
m_events->adoptHandler(CEvent::kTimer, m_dragTimer,
new TMethodEventJob<COSXScreen>(this,
&COSXScreen::handleDrag));
TrackMouseLocationWithOptions(NULL, 0, 0, &m_dragLastPoint, &modifiers, &res);
CGEventRef event = CGEventCreate(NULL);
CGPoint mouse = CGEventGetLocation(event);
m_dragLastPoint.h = (short)mouse.x;
m_dragLastPoint.v = (short)mouse.y;
CFRelease(event);
}
else if (!enable && m_dragTimer != NULL) {
m_events->removeHandler(CEvent::kTimer, m_dragTimer);
@@ -1534,15 +1544,14 @@ COSXScreen::enableDragTimer(bool enable)
void
COSXScreen::handleDrag(const CEvent&, void*)
{
Point p;
UInt32 modifiers;
MouseTrackingResult res;
CGEventRef event = CGEventCreate(NULL);
CGPoint p = CGEventGetLocation(event);
CFRelease(event);
TrackMouseLocationWithOptions(NULL, 0, 0, &p, &modifiers, &res);
if (res != kMouseTrackingTimedOut && (p.h != m_dragLastPoint.h || p.v != m_dragLastPoint.v)) {
m_dragLastPoint = p;
onMouseMove((SInt32)p.h, (SInt32)p.v);
if ((short)p.x != m_dragLastPoint.h || (short)p.y != m_dragLastPoint.v) {
m_dragLastPoint.h = (short)p.x;
m_dragLastPoint.v = (short)p.y;
onMouseMove((SInt32)p.x, (SInt32)p.y);
}
}
@@ -1693,17 +1702,24 @@ COSXScreen::watchSystemPowerThread(void*)
// setting m_pmThreadReady to true otherwise the parent thread will
// block waiting for it.
if (m_pmRootPort == 0) {
LOG((CLOG_WARN "failed to init watchSystemPowerThread"));
return;
}
LOG((CLOG_DEBUG "started watchSystemPowerThread"));
LOG((CLOG_DEBUG "waiting for event loop"));
m_events->waitForReady();
#if defined(MAC_OS_X_VERSION_10_7)
{
CLock lockCarbon(m_carbonLoopMutex);
if (*m_carbonLoopReady == false) {
// we signalling carbon loop ready before starting
// unless we know how to do it within the loop
LOG((CLOG_DEBUG "signalling carbon loop ready"));
*m_carbonLoopReady = true;
m_carbonLoopReady->signal();
}
@@ -1713,6 +1729,7 @@ COSXScreen::watchSystemPowerThread(void*)
// start the run loop
LOG((CLOG_DEBUG "starting carbon loop"));
CFRunLoopRun();
LOG((CLOG_DEBUG "carbon loop has stopped"));
// cleanup
if (notificationPortRef) {
@@ -2126,14 +2143,26 @@ void
COSXScreen::waitForCarbonLoop() const
{
#if defined(MAC_OS_X_VERSION_10_7)
double timeout = ARCH->time() + 10;
if (*m_carbonLoopReady) {
LOG((CLOG_DEBUG "carbon loop already ready"));
return;
}
CLock lock(m_carbonLoopMutex);
LOG((CLOG_DEBUG "waiting for carbon loop"));
double timeout = ARCH->time() + kCarbonLoopWaitTimeout;
while (!m_carbonLoopReady->wait()) {
if(ARCH->time() > timeout) {
throw std::runtime_error("carbon loop is not ready within 5 sec");
LOG((CLOG_DEBUG "carbon loop not ready, waiting again"));
timeout = ARCH->time() + kCarbonLoopWaitTimeout;
}
}
LOG((CLOG_DEBUG "carbon loop ready"));
#endif
}
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

View File

@@ -142,7 +142,7 @@ COSXScreenSaver::launchTerminationCallback(
OSStatus result;
ProcessSerialNumber psn;
EventParamType actualType;
UInt32 actualSize;
ByteCount actualSize;
result = GetEventParameter(theEvent, kEventParamProcessID,
typeProcessSerialNumber, &actualType,

View File

@@ -937,8 +937,14 @@ CXWindowsClipboard::pushReplies()
for (CReplyMap::iterator index = m_replies.begin();
index != m_replies.end(); ) {
assert(!index->second.empty());
if (!index->second.front()->m_replied) {
pushReplies(index, index->second, index->second.begin());
CReplyList::iterator listit = index->second.begin();
while (listit != index->second.end()) {
if (!(*listit)->m_replied)
break;
++listit;
}
if (listit != index->second.end() && !(*listit)->m_replied) {
pushReplies(index, index->second, listit);
}
else {
++index;

View File

@@ -1782,29 +1782,32 @@ CXWindowsScreen::doSelectEvents(Window w) const
// that we select PointerMotionMask on every window. we also select
// SubstructureNotifyMask in order to get CreateNotify events so we
// select events on new windows too.
//
// note that this can break certain clients due a design flaw of X.
// X will deliver a PointerMotion event to the deepest window in the
// hierarchy that contains the pointer and has PointerMotionMask
// selected by *any* client. if another client doesn't select
// motion events in a subwindow so the parent window will get them
// then by selecting for motion events on the subwindow we break
// that client because the parent will no longer get the events.
// FIXME -- should provide some workaround for event selection
// design flaw. perhaps only select for motion events on windows
// that already do or are top-level windows or don't propagate
// pointer events. or maybe an option to simply poll the mouse.
// we don't want to adjust our grab window
if (w == m_window) {
return;
}
// X11 has a design flaw. If *no* client selected PointerMotionMask for
// a window, motion events will be delivered to that window's parent.
// If *any* client, not necessarily the owner, selects PointerMotionMask
// on such a window, X will stop propagating motion events to its
// parent. This breaks applications that rely on event propagation
// behavior.
//
// Avoid selecting PointerMotionMask unless some other client selected
// it already.
long mask = SubstructureNotifyMask;
XWindowAttributes attr;
XGetWindowAttributes(m_display, w, &attr);
if ((attr.all_event_masks & PointerMotionMask) == PointerMotionMask) {
mask |= PointerMotionMask;
}
// select events of interest. do this before querying the tree so
// we'll get notifications of children created after the XQueryTree()
// so we won't miss them.
XSelectInput(m_display, w, PointerMotionMask | SubstructureNotifyMask);
XSelectInput(m_display, w, mask);
// recurse on child windows
Window rw, pw, *cw;

View File

@@ -17,6 +17,7 @@
*/
#include "synergy/App.h"
#include "base/Log.h"
#include "common/Version.h"
#include "synergy/protocol_types.h"
@@ -51,6 +52,10 @@
CApp* CApp::s_instance = nullptr;
//
// CApp
//
CApp::CApp(IEventQueue* events, CreateTaskBarReceiverFunc createTaskBarReceiver, CArgsBase* args) :
m_bye(&exit),
m_taskBarReceiver(NULL),
@@ -67,205 +72,10 @@ CApp::CApp(IEventQueue* events, CreateTaskBarReceiverFunc createTaskBarReceiver,
CApp::~CApp()
{
s_instance = nullptr;
delete m_args;
}
bool
CApp::isArg(
int argi, int argc, const char* const* argv,
const char* name1, const char* name2,
int minRequiredParameters)
{
if ((name1 != NULL && strcmp(argv[argi], name1) == 0) ||
(name2 != NULL && strcmp(argv[argi], name2) == 0)) {
// match. check args left.
if (argi + minRequiredParameters >= argc) {
LOG((CLOG_PRINT "%s: missing arguments for `%s'" BYE,
argsBase().m_pname, argv[argi], argsBase().m_pname));
m_bye(kExitArgs);
}
return true;
}
// no match
return false;
}
bool
CApp::parseArg(const int& argc, const char* const* argv, int& i)
{
if (appUtil().parseArg(argc, argv, i)) {
// handled by platform util
return true;
}
else if (isArg(i, argc, argv, "-d", "--debug", 1)) {
// change logging level
argsBase().m_logFilter = argv[++i];
}
else if (isArg(i, argc, argv, "-l", "--log", 1)) {
argsBase().m_logFile = argv[++i];
}
else if (isArg(i, argc, argv, "-f", "--no-daemon")) {
// not a daemon
argsBase().m_daemon = false;
}
else if (isArg(i, argc, argv, NULL, "--daemon")) {
// daemonize
argsBase().m_daemon = true;
}
else if (isArg(i, argc, argv, "-n", "--name", 1)) {
// save screen name
argsBase().m_name = argv[++i];
}
else if (isArg(i, argc, argv, "-1", "--no-restart")) {
// don't try to restart
argsBase().m_restartable = false;
}
else if (isArg(i, argc, argv, NULL, "--restart")) {
// try to restart
argsBase().m_restartable = true;
}
else if (isArg(i, argc, argv, "-z", NULL)) {
argsBase().m_backend = true;
}
else if (isArg(i, argc, argv, NULL, "--no-hooks")) {
argsBase().m_noHooks = true;
}
else if (isArg(i, argc, argv, "-h", "--help")) {
help();
m_bye(kExitSuccess);
}
else if (isArg(i, argc, argv, NULL, "--version")) {
version();
m_bye(kExitSuccess);
}
else if (isArg(i, argc, argv, NULL, "--no-tray")) {
argsBase().m_disableTray = true;
}
else if (isArg(i, argc, argv, NULL, "--ipc")) {
argsBase().m_enableIpc = true;
}
else if (isArg(i, argc, argv, NULL, "--server")) {
// HACK: stop error happening when using portable (synergyp)
}
else if (isArg(i, argc, argv, NULL, "--client")) {
// HACK: stop error happening when using portable (synergyp)
}
else if (isArg(i, argc, argv, NULL, "--crypto-pass")) {
argsBase().m_crypto.m_pass = argv[++i];
argsBase().m_crypto.setMode("cfb");
}
else if (isArg(i, argc, argv, NULL, "--enable-drag-drop")) {
bool useDragDrop = true;
#ifdef WINAPI_XWINDOWS
useDragDrop = false;
LOG((CLOG_INFO "ignoring --enable-drag-drop, not supported on linux."));
#endif
#ifdef WINAPI_MSWINDOWS
OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
if (osvi.dwMajorVersion < 6) {
useDragDrop = false;
LOG((CLOG_INFO "ignoring --enable-drag-drop, not supported below vista."));
}
#endif
if (useDragDrop) {
argsBase().m_enableDragDrop = true;
}
}
else {
// option not supported here
return false;
}
return true;
}
void
CApp::parseArgs(int argc, const char* const* argv, int& i)
{
// about these use of assert() here:
// previously an /analyze warning was displayed if we only used assert and
// did not return on failure. however, this warning does not appear to show
// any more (could be because new compiler args have been added).
// the asserts are programmer benefit only; the os should never pass 0 args,
// because the first is always the binary name. the only way assert would
// evaluate to true, is if this parse function were implemented incorrectly,
// which is unlikely because it's old code and has a specific use.
// we should avoid using anything other than assert here, because it will
// look like important code, which it's not really.
assert(argsBase().m_pname != NULL);
assert(argv != NULL);
assert(argc >= 1);
// set defaults
argsBase().m_name = ARCH->getHostName();
// parse options
for (i = 1; i < argc; ++i) {
if (parseArg(argc, argv, i)) {
continue;
}
else if (isArg(i, argc, argv, "--", NULL)) {
// remaining arguments are not options
++i;
break;
}
else if (argv[i][0] == '-') {
std::cerr << "Unrecognized option: " << argv[i] << std::endl;
m_bye(kExitArgs);
}
else {
// this and remaining arguments are not options
break;
}
}
#if SYSAPI_WIN32
// suggest that user installs as a windows service. when launched as
// service, process should automatically detect that it should run in
// daemon mode.
if (argsBase().m_daemon) {
LOG((CLOG_ERR
"the --daemon argument is not supported on windows. "
"instead, install %s as a service (--service install)",
argsBase().m_pname));
m_bye(kExitArgs);
}
#endif
}
void
CApp::version()
{
@@ -363,6 +173,18 @@ CApp::initApp(int argc, const char** argv)
// parse command line
parseArgs(argc, argv);
// set log filter
if (!CLOG->setFilter(argsBase().m_logFilter)) {
LOG((CLOG_PRINT "%s: unrecognized log level `%s'" BYE,
argsBase().m_pname, argsBase().m_logFilter, argsBase().m_pname));
m_bye(kExitArgs);
}
loggingFilterWarning();
if (argsBase().m_enableDragDrop) {
LOG((CLOG_INFO "drag and drop enabled"));
}
// setup file logging after parsing args
setupFileLogging();
@@ -422,3 +244,80 @@ CApp::runEventsLoop(void*)
#endif
}
//
// CMinimalApp
//
CMinimalApp::CMinimalApp() :
CApp(NULL, NULL, new CArgsBase())
{
setEvents(m_events);
}
CMinimalApp::~CMinimalApp()
{
}
int
CMinimalApp::standardStartup(int argc, char** argv)
{
return 0;
}
int
CMinimalApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup)
{
return 0;
}
void
CMinimalApp::startNode()
{
}
int
CMinimalApp::mainLoop()
{
return 0;
}
int
CMinimalApp::foregroundStartup(int argc, char** argv)
{
return 0;
}
CScreen*
CMinimalApp::createScreen()
{
return NULL;
}
void
CMinimalApp::loadConfig()
{
}
bool
CMinimalApp::loadConfig(const CString& pathname)
{
return false;
}
const char*
CMinimalApp::daemonInfo() const
{
return "";
}
const char*
CMinimalApp::daemonName() const
{
return "";
}
void
CMinimalApp::parseArgs(int argc, const char* const* argv)
{
}

View File

@@ -18,10 +18,12 @@
#pragma once
#include "common/common.h"
#include "base/String.h"
#include "synergy/IApp.h"
#include "ipc/IpcClient.h"
#include "synergy/IApp.h"
#include "base/String.h"
#include "base/Log.h"
#include "base/EventQueue.h"
#include "common/common.h"
#if SYSAPI_WIN32
#include "synergy/win32/AppUtilWindows.h"
@@ -70,11 +72,6 @@ public:
// TODO: this is old C code - use inheritance to normalize
void (*m_bye)(int);
// Returns true if argv[argi] is equal to name1 or name2.
bool isArg(int argi, int argc, const char* const* argv,
const char* name1, const char* name2,
int minRequiredParameters = 0);
static CApp& instance() { assert(s_instance != nullptr); return *s_instance; }
// If --log was specified in args, then add a file logger.
@@ -101,12 +98,12 @@ public:
void setSocketMultiplexer(CSocketMultiplexer* sm) { m_socketMultiplexer = sm; }
CSocketMultiplexer* getSocketMultiplexer() const { return m_socketMultiplexer; }
void setEvents(CEventQueue& events) { m_events = &events; }
private:
void handleIpcMessage(const CEvent&, void*);
protected:
virtual void parseArgs(int argc, const char* const* argv, int &i);
virtual bool parseArg(const int& argc, const char* const* argv, int& i);
void initIpcClient();
void cleanupIpcClient();
void runEventsLoop(void*);
@@ -125,7 +122,29 @@ private:
CSocketMultiplexer* m_socketMultiplexer;
};
#define BYE "\nTry `%s --help' for more information."
class CMinimalApp : public CApp {
public:
CMinimalApp();
virtual ~CMinimalApp();
// IApp overrides
virtual int standardStartup(int argc, char** argv);
virtual int runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup);
virtual void startNode();
virtual int mainLoop();
virtual int foregroundStartup(int argc, char** argv);
virtual CScreen* createScreen();
virtual void loadConfig();
virtual bool loadConfig(const CString& pathname);
virtual const char* daemonInfo() const;
virtual const char* daemonName() const;
virtual void parseArgs(int argc, const char* const* argv);
private:
CArch m_arch;
CLog m_log;
CEventQueue m_events;
};
#if WINAPI_MSWINDOWS
#define DAEMON_RUNNING(running_) CArchMiscWindows::daemonRunning(running_)

View File

@@ -30,13 +30,6 @@ CAppUtil::~CAppUtil()
{
}
bool
CAppUtil::parseArg(const int& argc, const char* const* argv, int& i)
{
// no common platform args (yet)
return false;
}
void
CAppUtil::adoptApp(IApp* app)
{

View File

@@ -25,8 +25,7 @@ class CAppUtil : public IAppUtil {
public:
CAppUtil();
virtual ~CAppUtil();
virtual bool parseArg(const int& argc, const char* const* argv, int& i);
virtual void adoptApp(IApp* app);
IApp& app() const;
virtual void exitApp(int code) { throw XExitApp(code); }

View File

@@ -0,0 +1,449 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 Synergy Si, inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "synergy/ArgParser.h"
#include "synergy/App.h"
#include "synergy/ServerArgs.h"
#include "synergy/ClientArgs.h"
#include "synergy/ToolArgs.h"
#include "synergy/ArgsBase.h"
#include "base/Log.h"
CArgsBase* CArgParser::m_argsBase = NULL;
CArgParser::CArgParser(CApp* app) :
m_app(app)
{
}
bool
CArgParser::parseServerArgs(CServerArgs& args, int argc, const char* const* argv)
{
setArgsBase(args);
updateCommonArgs(argv);
for (int i = 1; i < argc; ++i) {
if (parsePlatformArg(args, argc, argv, i)) {
continue;
}
else if (parseGenericArgs(argc, argv, i)) {
continue;
}
else if (isArg(i, argc, argv, "-a", "--address", 1)) {
// save listen address
args.m_synergyAddress = argv[++i];
}
else if (isArg(i, argc, argv, "-c", "--config", 1)) {
// save configuration file path
args.m_configFile = argv[++i];
}
else {
LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE, args.m_pname, argv[i], args.m_pname));
return false;
}
}
if (checkUnexpectedArgs()) {
return false;
}
return true;
}
bool
CArgParser::parseClientArgs(CClientArgs& args, int argc, const char* const* argv)
{
setArgsBase(args);
updateCommonArgs(argv);
int i;
for (i = 1; i < argc; ++i) {
if (parsePlatformArg(args, argc, argv, i)) {
continue;
}
else if (parseGenericArgs(argc, argv, i)) {
continue;
}
else if (isArg(i, argc, argv, NULL, "--camp")) {
// ignore -- included for backwards compatibility
}
else if (isArg(i, argc, argv, NULL, "--no-camp")) {
// ignore -- included for backwards compatibility
}
else if (isArg(i, argc, argv, NULL, "--yscroll", 1)) {
// define scroll
args.m_yscroll = atoi(argv[++i]);
}
else {
if (i + 1 == argc) {
args.m_synergyAddress = argv[i];
return true;
}
LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE, args.m_pname, argv[i], args.m_pname));
return false;
}
}
// exactly one non-option argument (server-address)
if (i == argc) {
LOG((CLOG_PRINT "%s: a server address or name is required" BYE,
args.m_pname, args.m_pname));
return false;
}
if (checkUnexpectedArgs()) {
return false;
}
return true;
}
bool
CArgParser::parsePlatformArg(CArgsBase& argsBase, const int& argc, const char* const* argv, int& i)
{
#if WINAPI_MSWINDOWS
if (isArg(i, argc, argv, NULL, "--service")) {
LOG((CLOG_WARN "obsolete argument --service, use synergyd instead."));
argsBase.m_shouldExit = true;
}
else if (isArg(i, argc, argv, NULL, "--exit-pause")) {
argsBase.m_pauseOnExit = true;
}
else if (isArg(i, argc, argv, NULL, "--stop-on-desk-switch")) {
argsBase.m_stopOnDeskSwitch = true;
}
else {
// option not supported here
return false;
}
return true;
#elif WINAPI_XWINDOWS
if (isArg(i, argc, argv, "-display", "--display", 1)) {
// use alternative display
argsBase.m_display = argv[++i];
}
else if (isArg(i, argc, argv, NULL, "--no-xinitthreads")) {
argsBase.m_disableXInitThreads = true;
}
else {
// option not supported here
return false;
}
return true;
#elif WINAPI_CARBON
// no options for carbon
return false;
#endif
}
bool
CArgParser::parseToolArgs(CToolArgs& args, int argc, const char* const* argv)
{
for (int i = 1; i < argc; ++i) {
if (isArg(i, argc, argv, NULL, "--get-active-desktop", 0)) {
args.m_printActiveDesktopName = true;
return true;
}
else {
return false;
}
}
return false;
}
bool
CArgParser::parseGenericArgs(int argc, const char* const* argv, int& i)
{
if (isArg(i, argc, argv, "-d", "--debug", 1)) {
// change logging level
argsBase().m_logFilter = argv[++i];
}
else if (isArg(i, argc, argv, "-l", "--log", 1)) {
argsBase().m_logFile = argv[++i];
}
else if (isArg(i, argc, argv, "-f", "--no-daemon")) {
// not a daemon
argsBase().m_daemon = false;
}
else if (isArg(i, argc, argv, NULL, "--daemon")) {
// daemonize
argsBase().m_daemon = true;
}
else if (isArg(i, argc, argv, "-n", "--name", 1)) {
// save screen name
argsBase().m_name = argv[++i];
}
else if (isArg(i, argc, argv, "-1", "--no-restart")) {
// don't try to restart
argsBase().m_restartable = false;
}
else if (isArg(i, argc, argv, NULL, "--restart")) {
// try to restart
argsBase().m_restartable = true;
}
else if (isArg(i, argc, argv, "-z", NULL)) {
argsBase().m_backend = true;
}
else if (isArg(i, argc, argv, NULL, "--no-hooks")) {
argsBase().m_noHooks = true;
}
else if (isArg(i, argc, argv, "-h", "--help")) {
if (m_app) {
m_app->help();
}
argsBase().m_shouldExit = true;
}
else if (isArg(i, argc, argv, NULL, "--version")) {
if (m_app) {
m_app->version();
}
argsBase().m_shouldExit = true;
}
else if (isArg(i, argc, argv, NULL, "--no-tray")) {
argsBase().m_disableTray = true;
}
else if (isArg(i, argc, argv, NULL, "--ipc")) {
argsBase().m_enableIpc = true;
}
else if (isArg(i, argc, argv, NULL, "--server")) {
// HACK: stop error happening when using portable (synergyp)
}
else if (isArg(i, argc, argv, NULL, "--client")) {
// HACK: stop error happening when using portable (synergyp)
}
else if (isArg(i, argc, argv, NULL, "--crypto-pass")) {
argsBase().m_crypto.m_pass = argv[++i];
argsBase().m_crypto.setMode("cfb");
}
else if (isArg(i, argc, argv, NULL, "--enable-drag-drop")) {
bool useDragDrop = true;
#ifdef WINAPI_XWINDOWS
useDragDrop = false;
LOG((CLOG_INFO "ignoring --enable-drag-drop, not supported on linux."));
#endif
#ifdef WINAPI_MSWINDOWS
OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
if (osvi.dwMajorVersion < 6) {
useDragDrop = false;
LOG((CLOG_INFO "ignoring --enable-drag-drop, not supported below vista."));
}
#endif
if (useDragDrop) {
argsBase().m_enableDragDrop = true;
}
}
else {
// option not supported here
return false;
}
return true;
}
bool
CArgParser::isArg(
int argi, int argc, const char* const* argv,
const char* name1, const char* name2,
int minRequiredParameters)
{
if ((name1 != NULL && strcmp(argv[argi], name1) == 0) ||
(name2 != NULL && strcmp(argv[argi], name2) == 0)) {
// match. check args left.
if (argi + minRequiredParameters >= argc) {
LOG((CLOG_PRINT "%s: missing arguments for `%s'" BYE,
argsBase().m_pname, argv[argi], argsBase().m_pname));
argsBase().m_shouldExit = true;
return false;
}
return true;
}
// no match
return false;
}
void
CArgParser::splitCommandString(CString& command, std::vector<CString>& argv)
{
if (command.empty()) {
return ;
}
size_t leftDoubleQuote = 0;
size_t rightDoubleQuote = 0;
searchDoubleQuotes(command, leftDoubleQuote, rightDoubleQuote);
size_t startPos = 0;
size_t space = command.find(" ", startPos);
while (space != CString::npos) {
bool ignoreThisSpace = false;
// check if the space is between two double quotes
if (space > leftDoubleQuote && space < rightDoubleQuote) {
ignoreThisSpace = true;
}
else if (space > rightDoubleQuote){
searchDoubleQuotes(command, leftDoubleQuote, rightDoubleQuote, rightDoubleQuote + 1);
}
if (!ignoreThisSpace) {
CString subString = command.substr(startPos, space - startPos);
removeDoubleQuotes(subString);
argv.push_back(subString);
}
// find next space
if (ignoreThisSpace) {
space = command.find(" ", rightDoubleQuote + 1);
}
else {
startPos = space + 1;
space = command.find(" ", startPos);
}
}
CString subString = command.substr(startPos, command.size());
removeDoubleQuotes(subString);
argv.push_back(subString);
}
bool
CArgParser::searchDoubleQuotes(CString& command, size_t& left, size_t& right, size_t startPos)
{
bool result = false;
left = CString::npos;
right = CString::npos;
left = command.find("\"", startPos);
if (left != CString::npos) {
right = command.find("\"", left + 1);
if (right != CString::npos) {
result = true;
}
}
if (!result) {
left = 0;
right = 0;
}
return result;
}
void
CArgParser::removeDoubleQuotes(CString& arg)
{
// if string is surrounded by double quotes, remove them
if (arg[0] == '\"' &&
arg[arg.size() - 1] == '\"') {
arg = arg.substr(1, arg.size() - 2);
}
}
const char**
CArgParser::getArgv(std::vector<CString>& argsArray)
{
size_t argc = argsArray.size();
// caller is responsible for deleting the outer array only
// we use the c string pointers from argsArray and assign
// them to the inner array. So caller only need to use
// delete[] to delete the outer array
const char** argv = new const char*[argc];
for (size_t i = 0; i < argc; i++) {
argv[i] = argsArray[i].c_str();
}
return argv;
}
CString
CArgParser::assembleCommand(std::vector<CString>& argsArray, CString ignoreArg, int parametersRequired)
{
CString result;
for (std::vector<CString>::iterator it = argsArray.begin(); it != argsArray.end(); ++it) {
if (it->compare(ignoreArg) == 0) {
it = it + parametersRequired;
continue;
}
// if there is a space in this arg, use double quotes surround it
if ((*it).find(" ") != CString::npos) {
(*it).insert(0, "\"");
(*it).push_back('\"');
}
result.append(*it);
// add space to saperate args
result.append(" ");
}
if (!result.empty()) {
// remove the tail space
result = result.substr(0, result.size() - 1);
}
return result;
}
void
CArgParser::updateCommonArgs(const char* const* argv)
{
argsBase().m_name = ARCH->getHostName();
argsBase().m_pname = ARCH->getBasename(argv[0]);
}
bool
CArgParser::checkUnexpectedArgs()
{
#if SYSAPI_WIN32
// suggest that user installs as a windows service. when launched as
// service, process should automatically detect that it should run in
// daemon mode.
if (argsBase().m_daemon) {
LOG((CLOG_ERR
"the --daemon argument is not supported on windows. "
"instead, install %s as a service (--service install)",
argsBase().m_pname));
return true;
}
#endif
return false;
}

View File

@@ -0,0 +1,62 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 Synergy Si, Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "base/String.h"
#include "common/stdvector.h"
class CServerArgs;
class CClientArgs;
class CToolArgs;
class CArgsBase;
class CApp;
class CArgParser {
public:
CArgParser(CApp* app);
bool parseServerArgs(CServerArgs& args, int argc, const char* const* argv);
bool parseClientArgs(CClientArgs& args, int argc, const char* const* argv);
bool parsePlatformArg(CArgsBase& argsBase, const int& argc, const char* const* argv, int& i);
bool parseToolArgs(CToolArgs& args, int argc, const char* const* argv);
bool parseGenericArgs(int argc, const char* const* argv, int& i);
void setArgsBase(CArgsBase& argsBase) { m_argsBase = &argsBase; }
static bool isArg(int argi, int argc, const char* const* argv,
const char* name1, const char* name2,
int minRequiredParameters = 0);
static void splitCommandString(CString& command, std::vector<CString>& argv);
static bool searchDoubleQuotes(CString& command, size_t& left,
size_t& right, size_t startPos = 0);
static void removeDoubleQuotes(CString& arg);
static const char** getArgv(std::vector<CString>& argsArray);
static CString assembleCommand(std::vector<CString>& argsArray,
CString ignoreArg = "", int parametersRequired = 0);
private:
void updateCommonArgs(const char* const* argv);
bool checkUnexpectedArgs();
static CArgsBase& argsBase() { return *m_argsBase; }
private:
CApp* m_app;
static CArgsBase* m_argsBase;
};

View File

@@ -39,7 +39,9 @@ m_logFile(NULL),
m_display(NULL),
m_disableTray(false),
m_enableIpc(false),
m_enableDragDrop(false)
m_enableDragDrop(false),
m_shouldExit(false),
m_synergyAddress()
{
}

View File

@@ -46,4 +46,6 @@ public:
#if WINAPI_XWINDOWS
bool m_disableXInitThreads;
#endif
bool m_shouldExit;
CString m_synergyAddress;
};

View File

@@ -19,9 +19,11 @@
#include "synergy/ClientApp.h"
#include "client/Client.h"
#include "synergy/ArgParser.h"
#include "synergy/protocol_types.h"
#include "synergy/Screen.h"
#include "synergy/XScreen.h"
#include "synergy/ClientArgs.h"
#include "net/NetworkAddress.h"
#include "net/TCPSocketFactory.h"
#include "net/SocketMultiplexer.h"
@@ -61,9 +63,10 @@
#define RETRY_TIME 1.0
CClientApp::CClientApp(IEventQueue* events, CreateTaskBarReceiverFunc createTaskBarReceiver) :
CApp(events, createTaskBarReceiver, new CArgs()),
CApp(events, createTaskBarReceiver, new CClientArgs()),
m_client(NULL),
m_clientScreen(NULL)
m_clientScreen(NULL),
m_serverAddress(NULL)
{
}
@@ -71,97 +74,35 @@ CClientApp::~CClientApp()
{
}
CClientApp::CArgs::CArgs() :
m_yscroll(0),
m_serverAddress(NULL)
{
}
CClientApp::CArgs::~CArgs()
{
}
bool
CClientApp::parseArg(const int& argc, const char* const* argv, int& i)
{
if (CApp::parseArg(argc, argv, i)) {
// found common arg
return true;
}
else if (isArg(i, argc, argv, NULL, "--camp")) {
// ignore -- included for backwards compatibility
}
else if (isArg(i, argc, argv, NULL, "--no-camp")) {
// ignore -- included for backwards compatibility
}
else if (isArg(i, argc, argv, NULL, "--yscroll", 1)) {
// define scroll
args().m_yscroll = atoi(argv[++i]);
}
else {
// option not supported here
return false;
}
// argument was valid
return true;
}
void
CClientApp::parseArgs(int argc, const char* const* argv)
{
// asserts values, sets defaults, and parses args
int i;
CApp::parseArgs(argc, argv, i);
CArgParser argParser(this);
bool result = argParser.parseClientArgs(args(), argc, argv);
// exactly one non-option argument (server-address)
if (i == argc) {
LOG((CLOG_PRINT "%s: a server address or name is required" BYE,
args().m_pname, args().m_pname));
if (!result || args().m_shouldExit) {
m_bye(kExitArgs);
}
if (i + 1 != argc) {
LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE,
args().m_pname, argv[i], args().m_pname));
m_bye(kExitArgs);
}
// save server address
try {
*args().m_serverAddress = CNetworkAddress(argv[i], kDefaultPort);
args().m_serverAddress->resolve();
}
catch (XSocketAddress& e) {
// allow an address that we can't look up if we're restartable.
// we'll try to resolve the address each time we connect to the
// server. a bad port will never get better. patch by Brent
// Priddy.
if (!args().m_restartable || e.getError() == XSocketAddress::kBadPort) {
LOG((CLOG_PRINT "%s: %s" BYE,
args().m_pname, e.what(), args().m_pname));
m_bye(kExitFailed);
else {
// save server address
if (!args().m_synergyAddress.empty()) {
try {
*m_serverAddress = CNetworkAddress(args().m_synergyAddress, kDefaultPort);
m_serverAddress->resolve();
}
catch (XSocketAddress& e) {
// allow an address that we can't look up if we're restartable.
// we'll try to resolve the address each time we connect to the
// server. a bad port will never get better. patch by Brent
// Priddy.
if (!args().m_restartable || e.getError() == XSocketAddress::kBadPort) {
LOG((CLOG_PRINT "%s: %s" BYE,
args().m_pname, e.what(), args().m_pname));
m_bye(kExitFailed);
}
}
}
}
// set log filter
if (!CLOG->setFilter(args().m_logFilter)) {
LOG((CLOG_PRINT "%s: unrecognized log level `%s'" BYE,
args().m_pname, args().m_logFilter, args().m_pname));
m_bye(kExitArgs);
}
// identify system
LOG((CLOG_INFO "%s Client on %s %s", kAppVersion, ARCH->getOSName().c_str(), ARCH->getPlatformName().c_str()));
if (args().m_enableDragDrop) {
LOG((CLOG_INFO "drag and drop enabled"));
}
loggingFilterWarning();
}
void
@@ -460,7 +401,7 @@ CClientApp::startClient()
if (m_clientScreen == NULL) {
clientScreen = openClientScreen();
m_client = openClient(args().m_name,
*args().m_serverAddress, clientScreen, args().m_crypto);
*m_serverAddress, clientScreen, args().m_crypto);
m_clientScreen = clientScreen;
LOG((CLOG_NOTE "started client"));
}
@@ -590,7 +531,7 @@ int
CClientApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup)
{
// general initialization
args().m_serverAddress = new CNetworkAddress;
m_serverAddress = new CNetworkAddress;
args().m_pname = ARCH->getBasename(argv[0]);
// install caller's output filter
@@ -612,7 +553,7 @@ CClientApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFun
delete m_taskBarReceiver;
}
delete args().m_serverAddress;
delete m_serverAddress;
throw;
}

View File

@@ -19,26 +19,17 @@
#pragma once
#include "synergy/App.h"
#include "synergy/ArgsBase.h"
class CScreen;
class CEvent;
class CClient;
class CNetworkAddress;
class CThread;
class CClientArgs;
class CCryptoOptions;
class CClientApp : public CApp {
public:
class CArgs : public CArgsBase {
public:
CArgs();
~CArgs();
public:
int m_yscroll;
CNetworkAddress* m_serverAddress;
};
CClientApp(IEventQueue* events, CreateTaskBarReceiverFunc createTaskBarReceiver);
virtual ~CClientApp();
@@ -49,7 +40,7 @@ public:
void help();
// Returns arguments that are common and for client.
CArgs& args() const { return (CArgs&)argsBase(); }
CClientArgs& args() const { return (CClientArgs&)argsBase(); }
const char* daemonName() const;
const char* daemonInfo() const;
@@ -84,11 +75,9 @@ public:
static CClientApp& instance() { return (CClientApp&)CApp::instance(); }
CClient* getClientPtr() { return m_client; }
private:
virtual bool parseArg(const int& argc, const char* const* argv, int& i);
private:
CClient* m_client;
CScreen* m_clientScreen;
CNetworkAddress* m_serverAddress;
};

View File

@@ -0,0 +1,23 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 Synergy Si, Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "synergy/ClientArgs.h"
CClientArgs::CClientArgs() :
m_yscroll(0)
{
}

View File

@@ -0,0 +1,30 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 Synergy Si, Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "synergy/ArgsBase.h"
class CNetworkAddress;
class CClientArgs : public CArgsBase {
public:
CClientArgs();
public:
int m_yscroll;
};

View File

@@ -22,6 +22,9 @@
#include "synergy/DaemonApp.h"
#include "synergy/App.h"
#include "synergy/ArgParser.h"
#include "synergy/ServerArgs.h"
#include "synergy/ClientArgs.h"
#include "ipc/IpcClientProxy.h"
#include "ipc/IpcMessage.h"
#include "ipc/IpcLogOutputter.h"
@@ -84,7 +87,8 @@ CDaemonApp::CDaemonApp() :
#if SYSAPI_WIN32
m_watchdog(nullptr),
#endif
m_events(nullptr)
m_events(nullptr),
m_fileLogOutputter(nullptr)
{
s_instance = this;
}
@@ -194,8 +198,10 @@ CDaemonApp::mainLoop(bool logToFile)
{
DAEMON_RUNNING(true);
if (logToFile)
CLOG->insert(new CFileLogOutputter(logPath().c_str()));
if (logToFile) {
m_fileLogOutputter = new CFileLogOutputter(logFilename().c_str());
CLOG->insert(m_fileLogOutputter);
}
// create socket multiplexer. this must happen after daemonization
// on unix because threads evaporate across a fork().
@@ -210,6 +216,7 @@ CDaemonApp::mainLoop(bool logToFile)
#if SYSAPI_WIN32
m_watchdog = new CMSWindowsWatchdog(false, *m_ipcServer, *m_ipcLogOutputter);
m_watchdog->setFileLogOutputter(m_fileLogOutputter);
#endif
m_events->adoptHandler(
@@ -267,21 +274,17 @@ CDaemonApp::foregroundError(const char* message)
}
std::string
CDaemonApp::logPath()
CDaemonApp::logFilename()
{
#ifdef SYSAPI_WIN32
// TODO: move to CArchMiscWindows
// on windows, log to the same dir as the binary.
char fileNameBuffer[MAX_PATH];
GetModuleFileName(NULL, fileNameBuffer, MAX_PATH);
string fileName(fileNameBuffer);
size_t lastSlash = fileName.find_last_of("\\");
string path(fileName.substr(0, lastSlash));
path.append("\\").append(LOG_FILENAME);
return path;
#elif SYSAPI_UNIX
return "/var/log/" LOG_FILENAME;
#endif
string logFilename;
logFilename = ARCH->setting("LogFilename");
if (logFilename.empty()) {
logFilename = ARCH->getLogDirectory();
logFilename.append("/");
logFilename.append(LOG_FILENAME);
}
return logFilename;
}
void
@@ -301,13 +304,29 @@ CDaemonApp::handleIpcMessage(const CEvent& e, void*)
if (!command.empty()) {
LOG((CLOG_DEBUG "new command, elevate=%d command=%s", cm->elevate(), command.c_str()));
CString debugArg("--debug");
UInt32 debugArgPos = static_cast<UInt32>(command.find(debugArg));
if (debugArgPos != CString::npos) {
UInt32 from = debugArgPos + static_cast<UInt32>(debugArg.size()) + 1;
UInt32 nextSpace = static_cast<UInt32>(command.find(" ", from));
CString logLevel(command.substr(from, nextSpace - from));
std::vector<CString> argsArray;
CArgParser::splitCommandString(command, argsArray);
CArgParser argParser(NULL);
const char** argv = argParser.getArgv(argsArray);
CServerArgs serverArgs;
CClientArgs clientArgs;
int argc = static_cast<int>(argsArray.size());
bool server = argsArray[0].find("synergys") != CString::npos ? true : false;
CArgsBase* argBase = NULL;
if (server) {
argParser.parseServerArgs(serverArgs, argc, argv);
argBase = &serverArgs;
}
else {
argParser.parseClientArgs(clientArgs, argc, argv);
argBase = &clientArgs;
}
delete[] argv;
CString logLevel(argBase->m_logFilter);
if (!logLevel.empty()) {
try {
// change log level based on that in the command string
// and change to that log level now.
@@ -318,6 +337,23 @@ CDaemonApp::handleIpcMessage(const CEvent& e, void*)
LOG((CLOG_ERR "failed to save LogLevel setting, %s", e.what()));
}
}
#if SYSAPI_WIN32
CString logFilename;
if (argBase->m_logFile != NULL) {
logFilename = CString(argBase->m_logFile);
ARCH->setting("LogFilename", logFilename);
m_watchdog->setFileLogOutputter(m_fileLogOutputter);
command = CArgParser::assembleCommand(argsArray, "--log", 1);
LOG((CLOG_DEBUG "removed log file argument and filename %s from command ", logFilename.c_str()));
LOG((CLOG_DEBUG "new command, elevate=%d command=%s", cm->elevate(), command.c_str()));
}
else {
m_watchdog->setFileLogOutputter(NULL);
}
m_fileLogOutputter->setLogFilename(logFilename.c_str());
#endif
}
else {
LOG((CLOG_DEBUG "empty command, elevate=%d", cm->elevate()));

View File

@@ -25,6 +25,7 @@
class CEvent;
class CIpcLogOutputter;
class CFileLogOutputter;
#if SYSAPI_WIN32
class CMSWindowsWatchdog;
@@ -41,7 +42,7 @@ public:
private:
void daemonize();
void foregroundError(const char* message);
std::string logPath();
std::string logFilename();
void handleIpcMessage(const CEvent&, void*);
public:
@@ -55,6 +56,7 @@ private:
CIpcServer* m_ipcServer;
CIpcLogOutputter* m_ipcLogOutputter;
IEventQueue* m_events;
CFileLogOutputter* m_fileLogOutputter;
};
#define LOG_FILENAME "synergyd.log"

View File

@@ -32,9 +32,6 @@ class IApp : public IInterface
{
public:
virtual void setByeFunc(void(*bye)(int)) = 0;
virtual bool isArg(int argi, int argc, const char* const* argv,
const char* name1, const char* name2,
int minRequiredParameters = 0) = 0;
virtual CArgsBase& argsBase() const = 0;
virtual int standardStartup(int argc, char** argv) = 0;
virtual int runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup) = 0;

View File

@@ -23,7 +23,6 @@
class IAppUtil : public IInterface {
public:
virtual bool parseArg(const int& argc, const char* const* argv, int& i) = 0;
virtual void adoptApp(IApp* app) = 0;
virtual IApp& app() const = 0;
virtual int run(int argc, char** argv) = 0;

View File

@@ -22,9 +22,11 @@
#include "server/ClientListener.h"
#include "server/ClientProxy.h"
#include "server/PrimaryClient.h"
#include "synergy/ArgParser.h"
#include "synergy/Screen.h"
#include "synergy/XScreen.h"
#include "synergy/ServerTaskBarReceiver.h"
#include "synergy/ServerArgs.h"
#include "net/SocketMultiplexer.h"
#include "net/TCPSocketFactory.h"
#include "net/XSocket.h"
@@ -63,13 +65,14 @@
//
CServerApp::CServerApp(IEventQueue* events, CreateTaskBarReceiverFunc createTaskBarReceiver) :
CApp(events, createTaskBarReceiver, new CArgs()),
CApp(events, createTaskBarReceiver, new CServerArgs()),
m_server(NULL),
m_serverState(kUninitialized),
m_serverScreen(NULL),
m_primaryClient(NULL),
m_listener(NULL),
m_timer(NULL)
m_timer(NULL),
m_synergyAddress(NULL)
{
}
@@ -77,82 +80,29 @@ CServerApp::~CServerApp()
{
}
CServerApp::CArgs::CArgs() :
m_synergyAddress(NULL),
m_config(NULL)
{
}
CServerApp::CArgs::~CArgs()
{
}
bool
CServerApp::parseArg(const int& argc, const char* const* argv, int& i)
{
if (CApp::parseArg(argc, argv, i)) {
// found common arg
return true;
}
else if (isArg(i, argc, argv, "-a", "--address", 1)) {
// save listen address
try {
*args().m_synergyAddress = CNetworkAddress(argv[i + 1],
kDefaultPort);
args().m_synergyAddress->resolve();
}
catch (XSocketAddress& e) {
LOG((CLOG_PRINT "%s: %s" BYE,
args().m_pname, e.what(), args().m_pname));
m_bye(kExitArgs);
}
++i;
}
else if (isArg(i, argc, argv, "-c", "--config", 1)) {
// save configuration file path
args().m_configFile = argv[++i];
}
else {
// option not supported here
return false;
}
// argument was valid
return true;
}
void
CServerApp::parseArgs(int argc, const char* const* argv)
{
// asserts values, sets defaults, and parses args
int i;
CApp::parseArgs(argc, argv, i);
CArgParser argParser(this);
bool result = argParser.parseServerArgs(args(), argc, argv);
// no non-option arguments are allowed
if (i != argc) {
LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE,
args().m_pname, argv[i], args().m_pname));
if (!result || args().m_shouldExit) {
m_bye(kExitArgs);
}
// set log filter
if (!CLOG->setFilter(args().m_logFilter)) {
LOG((CLOG_PRINT "%s: unrecognized log level `%s'" BYE,
args().m_pname, args().m_logFilter, args().m_pname));
m_bye(kExitArgs);
else {
if (!args().m_synergyAddress.empty()) {
try {
*m_synergyAddress = CNetworkAddress(args().m_synergyAddress,
kDefaultPort);
m_synergyAddress->resolve();
}
catch (XSocketAddress& e) {
LOG((CLOG_PRINT "%s: %s" BYE,
args().m_pname, e.what(), args().m_pname));
m_bye(kExitArgs);
}
}
}
// identify system
LOG((CLOG_INFO "%s Server on %s %s", kAppVersion, ARCH->getOSName().c_str(), ARCH->getPlatformName().c_str()));
if (args().m_enableDragDrop) {
LOG((CLOG_INFO "drag and drop enabled"));
}
loggingFilterWarning();
}
void
@@ -742,8 +692,8 @@ CServerApp::mainLoop()
// set the contact address, if provided, in the config.
// otherwise, if the config doesn't have an address, use
// the default.
if (args().m_synergyAddress->isValid()) {
args().m_config->setSynergyAddress(*args().m_synergyAddress);
if (m_synergyAddress->isValid()) {
args().m_config->setSynergyAddress(*m_synergyAddress);
}
else if (!args().m_config->getSynergyAddress().isValid()) {
args().m_config->setSynergyAddress(CNetworkAddress(kDefaultPort));
@@ -839,7 +789,7 @@ int
CServerApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup)
{
// general initialization
args().m_synergyAddress = new CNetworkAddress;
m_synergyAddress = new CNetworkAddress;
args().m_config = new CConfig(m_events);
args().m_pname = ARCH->getBasename(argv[0]);
@@ -858,7 +808,7 @@ CServerApp::runInner(int argc, char** argv, ILogOutputter* outputter, StartupFun
}
delete args().m_config;
delete args().m_synergyAddress;
delete m_synergyAddress;
return result;
}

View File

@@ -18,6 +18,7 @@
#pragma once
#include "synergy/ArgsBase.h"
#include "synergy/App.h"
#include "base/String.h"
#include "server/Config.h"
@@ -44,20 +45,10 @@ class CClientListener;
class CEventQueueTimer;
class ILogOutputter;
class IEventQueue;
class CServerArgs;
class CServerApp : public CApp {
public:
class CArgs : public CArgsBase {
public:
CArgs();
~CArgs();
public:
CString m_configFile;
CNetworkAddress* m_synergyAddress;
CConfig* m_config;
};
CServerApp(IEventQueue* events, CreateTaskBarReceiverFunc createTaskBarReceiver);
virtual ~CServerApp();
@@ -68,7 +59,7 @@ public:
void help();
// Returns arguments that are common and for server.
CArgs& args() const { return (CArgs&)argsBase(); }
CServerArgs& args() const { return (CServerArgs&)argsBase(); }
const char* daemonName() const;
const char* daemonInfo() const;
@@ -120,9 +111,9 @@ public:
CPrimaryClient* m_primaryClient;
CClientListener* m_listener;
CEventQueueTimer* m_timer;
CNetworkAddress* m_synergyAddress;
private:
virtual bool parseArg(const int& argc, const char* const* argv, int& i);
void handleScreenSwitched(const CEvent&, void* data);
};

View File

@@ -0,0 +1,25 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 Synergy Si, Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "synergy/ServerArgs.h"
CServerArgs::CServerArgs() :
m_configFile(),
m_config(NULL)
{
}

View File

@@ -0,0 +1,32 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 Synergy Si, Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "synergy/ArgsBase.h"
class CNetworkAddress;
class CConfig;
class CServerArgs : public CArgsBase {
public:
CServerArgs();
public:
CString m_configFile;
CConfig* m_config;
};

View File

@@ -16,14 +16,18 @@
*/
#include "synergy/ToolApp.h"
#include "synergy/ArgParser.h"
#include "arch/Arch.h"
#include "base/Log.h"
#include "base/String.h"
#include <iostream>
#include <sstream>
//#define PREMIUM_AUTH_URL "http://localhost/synergy/premium/json/auth/"
#define PREMIUM_AUTH_URL "https://synergy-project.org/premium/json/auth/"
#if SYSAPI_WIN32
#include "platform/MSWindowsSession.h"
#endif
enum {
kErrorOk,
@@ -41,43 +45,43 @@ CToolApp::run(int argc, char** argv)
}
try {
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--premium-auth") == 0) {
premiumAuth();
return kErrorOk;
CArgParser argParser(this);
bool result = argParser.parseToolArgs(m_args, argc, argv);
if (!result) {
m_bye(kExitArgs);
}
if (m_args.m_printActiveDesktopName) {
#if SYSAPI_WIN32
CMSWindowsSession session;
CString name = session.getActiveDesktopName();
if (name.empty()) {
LOG((CLOG_CRIT "failed to get active desktop name"));
return kExitFailed;
}
else {
std::cerr << "unknown arg: " << argv[i] << std::endl;
return kErrorArgs;
std::cout << "activeDesktop:" << name.c_str() << std::endl;
}
#endif
}
else {
throw XSynergy("Nothing to do");
}
}
catch (std::exception& e) {
std::cerr << e.what() << std::endl;
return kErrorException;
LOG((CLOG_CRIT "An error occurred: %s\n", e.what()));
return kExitFailed;
}
catch (...) {
std::cerr << "unknown error" << std::endl;
return kErrorUnknown;
LOG((CLOG_CRIT "An unknown error occurred.\n"));
return kExitFailed;
}
return kErrorOk;
}
void
CToolApp::premiumAuth()
CToolApp::help()
{
CString credentials;
std::cin >> credentials;
size_t separator = credentials.find(':');
CString email = credentials.substr(0, separator);
CString password = credentials.substr(separator + 1, credentials.length());
std::stringstream ss;
ss << PREMIUM_AUTH_URL;
ss << "?email=" << ARCH->internet().urlEncode(email);
ss << "&password=" << password;
std::cout << ARCH->internet().get(ss.str()) << std::endl;
}

View File

@@ -17,12 +17,15 @@
#pragma once
#include "synergy/App.h"
#include "synergy/ToolArgs.h"
#include "common/basic_types.h"
class CToolApp {
class CToolApp : public CMinimalApp
{
public:
UInt32 run(int argc, char** argv);
void help();
private:
void premiumAuth();
CToolArgs m_args;
};

View File

@@ -0,0 +1,23 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 Synergy Si, Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "synergy/ToolArgs.h"
CToolArgs::CToolArgs() :
m_printActiveDesktopName(false)
{
}

View File

@@ -0,0 +1,28 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 Synergy Si, Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "base/String.h"
class CToolArgs {
public:
CToolArgs();
public:
bool m_printActiveDesktopName;
};

View File

@@ -27,31 +27,6 @@ CAppUtilUnix::~CAppUtilUnix()
{
}
bool
CAppUtilUnix::parseArg(const int& argc, const char* const* argv, int& i)
{
#if WINAPI_XWINDOWS
if (app().isArg(i, argc, argv, "-display", "--display", 1)) {
// use alternative display
app().argsBase().m_display = argv[++i];
}
else if (app().isArg(i, argc, argv, NULL, "--no-xinitthreads")) {
app().argsBase().m_disableXInitThreads = true;
}
else {
// option not supported here
return false;
}
return true;
#else
// no options for carbon
return false;
#endif
}
int
standardStartupStatic(int argc, char** argv)
{

View File

@@ -29,7 +29,6 @@ public:
CAppUtilUnix(IEventQueue* events);
virtual ~CAppUtilUnix();
bool parseArg(const int& argc, const char* const* argv, int& i);
int run(int argc, char** argv);
void startNode();
};

View File

@@ -58,29 +58,6 @@ BOOL WINAPI CAppUtilWindows::consoleHandler(DWORD)
return TRUE;
}
bool
CAppUtilWindows::parseArg(const int& argc, const char* const* argv, int& i)
{
if (app().isArg(i, argc, argv, NULL, "--service")) {
LOG((CLOG_WARN "obsolete argument --service, use synergyd instead."));
app().bye(kExitFailed);
}
else if (app().isArg(i, argc, argv, NULL, "--exit-pause")) {
app().argsBase().m_pauseOnExit = true;
}
else if (app().isArg(i, argc, argv, NULL, "--stop-on-desk-switch")) {
app().argsBase().m_stopOnDeskSwitch = true;
}
else {
// option not supported here
return false;
}
return true;
}
static
int
mainLoopStatic()

View File

@@ -38,8 +38,6 @@ public:
CAppUtilWindows(IEventQueue* events);
virtual ~CAppUtilWindows();
bool parseArg(const int& argc, const char* const* argv, int& i);
int daemonNTStartup(int, char**);
int daemonNTMainLoop(int argc, const char** argv);

View File

@@ -118,6 +118,7 @@ static WPARAM g_deadVirtKey = 0;
static WPARAM g_deadRelease = 0;
static LPARAM g_deadLParam = 0;
static BYTE g_deadKeyState[256] = { 0 };
static BYTE g_keyState[256] = { 0 };
static DWORD g_hookThread = 0;
static DWORD g_attachedThread = 0;
static bool g_fakeInput = false;
@@ -192,17 +193,41 @@ makeKeyMsg(UINT virtKey, char c, bool noAltGr)
static
void
keyboardGetState(BYTE keys[256])
keyboardGetState(BYTE keys[256], DWORD vkCode, bool kf_up)
{
// we have to use GetAsyncKeyState() rather than GetKeyState() because
// we don't pass through most keys so the event synchronous state
// doesn't get updated. we do that because certain modifier keys have
// side effects, like alt and the windows key.
SHORT key;
for (int i = 0; i < 256; ++i) {
key = GetAsyncKeyState(i);
keys[i] = (BYTE)((key < 0) ? 0x80u : 0);
if (vkCode < 0 || vkCode >= 256) {
return;
}
// Keep track of key state on our own in case GetAsyncKeyState() fails
g_keyState[vkCode] = kf_up ? 0 : 0x80;
g_keyState[VK_SHIFT] = g_keyState[VK_LSHIFT] | g_keyState[VK_RSHIFT];
SHORT key;
// Test whether GetAsyncKeyState() is being honest with us
key = GetAsyncKeyState(vkCode);
if (key & 0x80) {
// The only time we know for sure that GetAsyncKeyState() is working
// is when it tells us that the current key is down.
// In this case, update g_keyState to reflect what GetAsyncKeyState()
// is telling us, just in case we have gotten out of sync
for (int i = 0; i < 256; ++i) {
key = GetAsyncKeyState(i);
g_keyState[i] = (BYTE)((key < 0) ? 0x80u : 0);
}
}
// copy g_keyState to keys
for (int i = 0; i < 256; ++i) {
keys[i] = g_keyState[i];
}
key = GetKeyState(VK_CAPITAL);
keys[VK_CAPITAL] = (BYTE)(((key < 0) ? 0x80 : 0) | (key & 1));
}
@@ -211,6 +236,9 @@ static
bool
doKeyboardHookHandler(WPARAM wParam, LPARAM lParam)
{
DWORD vkCode = wParam;
bool kf_up = (lParam & (KF_UP << 16)) != 0;
// check for special events indicating if we should start or stop
// passing events through and not report them to the server. this
// is used to allow the server to synthesize events locally but
@@ -254,7 +282,7 @@ doKeyboardHookHandler(WPARAM wParam, LPARAM lParam)
// we need the keyboard state for ToAscii()
BYTE keys[256];
keyboardGetState(keys);
keyboardGetState(keys, vkCode, kf_up);
// ToAscii() maps ctrl+letter to the corresponding control code
// and ctrl+backspace to delete. we don't want those translations

View File

@@ -0,0 +1,44 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 Synergy Si, Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#define TEST_ENV
#include "synergy/App.h"
#include "test/global/gmock.h"
class CMockApp : public CApp
{
public:
CMockApp() : CApp(NULL, NULL, NULL) { }
MOCK_METHOD0(help, void());
MOCK_METHOD0(loadConfig, void());
MOCK_METHOD1(loadConfig, bool(const CString&));
MOCK_CONST_METHOD0(daemonInfo, const char*());
MOCK_CONST_METHOD0(daemonName, const char*());
MOCK_METHOD2(parseArgs, void(int, const char* const*));
MOCK_METHOD0(version, void());
MOCK_METHOD2(standardStartup, int(int, char**));
MOCK_METHOD4(runInner, int(int, char**, ILogOutputter*, StartupFunc));
MOCK_METHOD0(startNode, void());
MOCK_METHOD0(mainLoop, int());
MOCK_METHOD2(foregroundStartup, int(int, char**));
MOCK_METHOD0(createScreen, CScreen*());
};

View File

@@ -0,0 +1,33 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 Synergy Si, Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#define TEST_ENV
#include "synergy/ArgParser.h"
#include "test/global/gmock.h"
class CMockArgParser : public CArgParser
{
public:
CMockArgParser() : CArgParser(NULL) { }
MOCK_METHOD3(parseGenericArgs, bool(int, const char* const*, int&));
MOCK_METHOD0(checkUnexpectedArgs, bool());
};

View File

@@ -49,4 +49,4 @@ endif()
add_executable(unittests ${sources})
target_link_libraries(unittests
arch base client server common io net platform server synergy mt gtest gmock cryptopp ${libs})
arch base client server common io net platform server synergy mt ipc gtest gmock cryptopp ${libs})

View File

@@ -0,0 +1,207 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 Synergy Si, Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "synergy/ArgParser.h"
#include "synergy/ArgsBase.h"
#include "test/global/gtest.h"
TEST(CArgParserTests, isArg_abbreviationsArg_returnTrue)
{
int i = 1;
const int argc = 2;
const char* argv[argc] = { "stub", "-t" };
bool result = CArgParser::isArg(i, argc, argv, "-t", NULL);
EXPECT_EQ(true, result);
}
TEST(CArgParserTests, isArg_fullArg_returnTrue)
{
int i = 1;
const int argc = 2;
const char* argv[argc] = { "stub", "--test" };
bool result = CArgParser::isArg(i, argc, argv, NULL, "--test");
EXPECT_EQ(true, result);
}
TEST(CArgParserTests, isArg_missingArgs_returnFalse)
{
int i = 1;
const int argc = 2;
const char* argv[argc] = { "stub", "-t" };
CArgParser argParser(NULL);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
bool result = CArgParser::isArg(i, argc, argv, "-t", NULL, 1);
EXPECT_FALSE(result);
EXPECT_EQ(true, argsBase.m_shouldExit);
}
TEST(CArgParserTests, searchDoubleQuotes_doubleQuotedArg_returnTrue)
{
CString command("\"stub\"");
size_t left = 0;
size_t right = 0;
bool result = CArgParser::searchDoubleQuotes(command, left, right);
EXPECT_EQ(true, result);
EXPECT_EQ(0, left);
EXPECT_EQ(5, right);
}
TEST(CArgParserTests, searchDoubleQuotes_noDoubleQuotedArg_returnfalse)
{
CString command("stub");
size_t left = 0;
size_t right = 0;
bool result = CArgParser::searchDoubleQuotes(command, left, right);
EXPECT_FALSE(result);
EXPECT_EQ(0, left);
EXPECT_EQ(0, right);
}
TEST(CArgParserTests, searchDoubleQuotes_oneDoubleQuoteArg_returnfalse)
{
CString command("\"stub");
size_t left = 0;
size_t right = 0;
bool result = CArgParser::searchDoubleQuotes(command, left, right);
EXPECT_FALSE(result);
EXPECT_EQ(0, left);
EXPECT_EQ(0, right);
}
TEST(CArgParserTests, splitCommandString_oneArg_returnArgv)
{
CString command("stub");
std::vector<CString> argv;
CArgParser::splitCommandString(command, argv);
EXPECT_EQ(1, argv.size());
EXPECT_EQ("stub", argv.at(0));
}
TEST(CArgParserTests, splitCommandString_twoArgs_returnArgv)
{
CString command("stub1 stub2");
std::vector<CString> argv;
CArgParser::splitCommandString(command, argv);
EXPECT_EQ(2, argv.size());
EXPECT_EQ("stub1", argv.at(0));
EXPECT_EQ("stub2", argv.at(1));
}
TEST(CArgParserTests, splitCommandString_doubleQuotedArgs_returnArgv)
{
CString command("\"stub1\" stub2 \"stub3\"");
std::vector<CString> argv;
CArgParser::splitCommandString(command, argv);
EXPECT_EQ(3, argv.size());
EXPECT_EQ("stub1", argv.at(0));
EXPECT_EQ("stub2", argv.at(1));
EXPECT_EQ("stub3", argv.at(2));
}
TEST(CArgParserTests, splitCommandString_spaceDoubleQuotedArgs_returnArgv)
{
CString command("\"stub1\" stub2 \"stub3 space\"");
std::vector<CString> argv;
CArgParser::splitCommandString(command, argv);
EXPECT_EQ(3, argv.size());
EXPECT_EQ("stub1", argv.at(0));
EXPECT_EQ("stub2", argv.at(1));
EXPECT_EQ("stub3 space", argv.at(2));
}
TEST(CArgParserTests, getArgv_stringArray_return2DArray)
{
std::vector<CString> argArray;
argArray.push_back("stub1");
argArray.push_back("stub2");
argArray.push_back("stub3 space");
const char** argv = CArgParser::getArgv(argArray);
CString row1(argv[0]);
CString row2(argv[1]);
CString row3(argv[2]);
EXPECT_EQ("stub1", row1);
EXPECT_EQ("stub2", row2);
EXPECT_EQ("stub3 space", row3);
delete[] argv;
}
TEST(CArgParserTests, assembleCommand_stringArray_returnCommand)
{
std::vector<CString> argArray;
argArray.push_back("stub1");
argArray.push_back("stub2");
CString command = CArgParser::assembleCommand(argArray);
EXPECT_EQ("stub1 stub2", command);
}
TEST(CArgParserTests, assembleCommand_ignoreSecondArg_returnCommand)
{
std::vector<CString> argArray;
argArray.push_back("stub1");
argArray.push_back("stub2");
CString command = CArgParser::assembleCommand(argArray, "stub2");
EXPECT_EQ("stub1", command);
}
TEST(CArgParserTests, assembleCommand_ignoreSecondArgWithOneParameter_returnCommand)
{
std::vector<CString> argArray;
argArray.push_back("stub1");
argArray.push_back("stub2");
argArray.push_back("stub3");
argArray.push_back("stub4");
CString command = CArgParser::assembleCommand(argArray, "stub2", 1);
EXPECT_EQ("stub1 stub4", command);
}
TEST(CArgParserTests, assembleCommand_stringArrayWithSpace_returnCommand)
{
std::vector<CString> argArray;
argArray.push_back("stub1 space");
argArray.push_back("stub2");
argArray.push_back("stub3 space");
CString command = CArgParser::assembleCommand(argArray);
EXPECT_EQ("\"stub1 space\" stub2 \"stub3 space\"", command);
}

View File

@@ -0,0 +1,95 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 Synergy Si, Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "synergy/ArgParser.h"
#include "synergy/ClientArgs.h"
#include "test/mock/synergy/MockArgParser.h"
#include "test/global/gtest.h"
using ::testing::_;
using ::testing::Invoke;
using ::testing::NiceMock;
bool
client_stubParseGenericArgs(int, const char* const*, int&)
{
return false;
}
bool
client_stubCheckUnexpectedArgs()
{
return false;
}
TEST(CClientArgsParsingTests, parseClientArgs_yScrollArg_setYScroll)
{
NiceMock<CMockArgParser> argParser;
ON_CALL(argParser, parseGenericArgs(_, _, _)).WillByDefault(Invoke(client_stubParseGenericArgs));
ON_CALL(argParser, checkUnexpectedArgs()).WillByDefault(Invoke(client_stubCheckUnexpectedArgs));
CClientArgs clientArgs;
const int argc = 3;
const char* kYScrollCmd[argc] = { "stub", "--yscroll", "1" };
argParser.parseClientArgs(clientArgs, argc, kYScrollCmd);
EXPECT_EQ(1, clientArgs.m_yscroll);
}
TEST(CClientArgsParsingTests, parseClientArgs_addressArg_setSynergyAddress)
{
NiceMock<CMockArgParser> argParser;
ON_CALL(argParser, parseGenericArgs(_, _, _)).WillByDefault(Invoke(client_stubParseGenericArgs));
ON_CALL(argParser, checkUnexpectedArgs()).WillByDefault(Invoke(client_stubCheckUnexpectedArgs));
CClientArgs clientArgs;
const int argc = 2;
const char* kAddressCmd[argc] = { "stub", "mock_address" };
bool result = argParser.parseClientArgs(clientArgs, argc, kAddressCmd);
EXPECT_EQ("mock_address", clientArgs.m_synergyAddress);
EXPECT_EQ(true, result);
}
TEST(CClientArgsParsingTests, parseClientArgs_noAddressArg_returnFalse)
{
NiceMock<CMockArgParser> argParser;
ON_CALL(argParser, parseGenericArgs(_, _, _)).WillByDefault(Invoke(client_stubParseGenericArgs));
ON_CALL(argParser, checkUnexpectedArgs()).WillByDefault(Invoke(client_stubCheckUnexpectedArgs));
CClientArgs clientArgs;
const int argc = 1;
const char* kNoAddressCmd[argc] = { "stub" };
bool result = argParser.parseClientArgs(clientArgs, argc, kNoAddressCmd);
EXPECT_FALSE(result);
}
TEST(CClientArgsParsingTests, parseClientArgs_unrecognizedArg_returnFalse)
{
NiceMock<CMockArgParser> argParser;
ON_CALL(argParser, parseGenericArgs(_, _, _)).WillByDefault(Invoke(client_stubParseGenericArgs));
ON_CALL(argParser, checkUnexpectedArgs()).WillByDefault(Invoke(client_stubCheckUnexpectedArgs));
CClientArgs clientArgs;
const int argc = 3;
const char* kUnrecognizedCmd[argc] = { "stub", "mock_arg", "mock_address"};
bool result = argParser.parseClientArgs(clientArgs, argc, kUnrecognizedCmd);
EXPECT_FALSE(result);
}

View File

@@ -0,0 +1,332 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 Synergy Si, Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "synergy/ArgParser.h"
#include "synergy/ArgsBase.h"
#include "test/mock/synergy/MockApp.h"
#include "test/global/gtest.h"
using namespace synergy;
using ::testing::_;
using ::testing::Invoke;
using ::testing::NiceMock;
bool g_helpShowed = false;
bool g_versionShowed = false;
void
showMockHelp()
{
g_helpShowed = true;
}
void
showMockVersion()
{
g_versionShowed = true;
}
TEST(CGenericArgsParsingTests, parseGenericArgs_logLevelCmd_setLogLevel)
{
int i = 1;
const int argc = 3;
const char* kLogLevelCmd[argc] = { "stub", "--debug", "DEBUG" };
CArgParser argParser(NULL);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
argParser.parseGenericArgs(argc, kLogLevelCmd, i);
CString logFilter(argsBase.m_logFilter);
EXPECT_EQ("DEBUG", logFilter);
EXPECT_EQ(2, i);
}
TEST(CGenericArgsParsingTests, parseGenericArgs_logFileCmd_saveLogFilename)
{
int i = 1;
const int argc = 3;
const char* kLogFileCmd[argc] = { "stub", "--log", "mock_filename" };
CArgParser argParser(NULL);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
argParser.parseGenericArgs(argc, kLogFileCmd, i);
CString logFile(argsBase.m_logFile);
EXPECT_EQ("mock_filename", logFile);
EXPECT_EQ(2, i);
}
TEST(CGenericArgsParsingTests, parseGenericArgs_logFileCmdWithSpace_saveLogFilename)
{
int i = 1;
const int argc = 3;
const char* kLogFileCmdWithSpace[argc] = { "stub", "--log", "mo ck_filename" };
CArgParser argParser(NULL);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
argParser.parseGenericArgs(argc, kLogFileCmdWithSpace, i);
CString logFile(argsBase.m_logFile);
EXPECT_EQ("mo ck_filename", logFile);
EXPECT_EQ(2, i);
}
TEST(CGenericArgsParsingTests, parseGenericArgs_noDeamonCmd_daemonFalse)
{
int i = 1;
const int argc = 2;
const char* kNoDeamonCmd[argc] = { "stub", "-f" };
CArgParser argParser(NULL);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
argParser.parseGenericArgs(argc, kNoDeamonCmd, i);
EXPECT_FALSE(argsBase.m_daemon);
EXPECT_EQ(1, i);
}
TEST(CGenericArgsParsingTests, parseGenericArgs_deamonCmd_daemonTrue)
{
int i = 1;
const int argc = 2;
const char* kDeamonCmd[argc] = { "stub", "--daemon" };
CArgParser argParser(NULL);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
argParser.parseGenericArgs(argc, kDeamonCmd, i);
EXPECT_EQ(true, argsBase.m_daemon);
EXPECT_EQ(1, i);
}
TEST(CGenericArgsParsingTests, parseGenericArgs_nameCmd_saveName)
{
int i = 1;
const int argc = 3;
const char* kNameCmd[argc] = { "stub", "--name", "mock" };
CArgParser argParser(NULL);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
argParser.parseGenericArgs(argc, kNameCmd, i);
EXPECT_EQ("mock", argsBase.m_name);
EXPECT_EQ(2, i);
}
TEST(CGenericArgsParsingTests, parseGenericArgs_noRestartCmd_restartFalse)
{
int i = 1;
const int argc = 2;
const char* kNoRestartCmd[argc] = { "stub", "--no-restart" };
CArgParser argParser(NULL);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
argParser.parseGenericArgs(argc, kNoRestartCmd, i);
EXPECT_FALSE(argsBase.m_restartable);
EXPECT_EQ(1, i);
}
TEST(CGenericArgsParsingTests, parseGenericArgs_restartCmd_restartTrue)
{
int i = 1;
const int argc = 2;
const char* kRestartCmd[argc] = { "stub", "--restart" };
CArgParser argParser(NULL);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
argParser.parseGenericArgs(argc, kRestartCmd, i);
EXPECT_EQ(true, argsBase.m_restartable);
EXPECT_EQ(1, i);
}
TEST(CGenericArgsParsingTests, parseGenericArgs_backendCmd_backendTrue)
{
int i = 1;
const int argc = 2;
const char* kBackendCmd[argc] = { "stub", "-z" };
CArgParser argParser(NULL);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
argParser.parseGenericArgs(argc, kBackendCmd, i);
EXPECT_EQ(true, argsBase.m_backend);
EXPECT_EQ(1, i);
}
TEST(CGenericArgsParsingTests, parseGenericArgs_noHookCmd_noHookTrue)
{
int i = 1;
const int argc = 2;
const char* kNoHookCmd[argc] = { "stub", "--no-hooks" };
CArgParser argParser(NULL);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
argParser.parseGenericArgs(argc, kNoHookCmd, i);
EXPECT_EQ(true, argsBase.m_noHooks);
EXPECT_EQ(1, i);
}
TEST(CGenericArgsParsingTests, parseGenericArgs_helpCmd_showHelp)
{
g_helpShowed = false;
int i = 1;
const int argc = 2;
const char* kHelpCmd[argc] = { "stub", "--help" };
NiceMock<CMockApp> app;
CArgParser argParser(&app);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
ON_CALL(app, help()).WillByDefault(Invoke(showMockHelp));
argParser.parseGenericArgs(argc, kHelpCmd, i);
EXPECT_EQ(true, g_helpShowed);
EXPECT_EQ(1, i);
}
TEST(CGenericArgsParsingTests, parseGenericArgs_versionCmd_showVersion)
{
g_versionShowed = false;
int i = 1;
const int argc = 2;
const char* kVersionCmd[argc] = { "stub", "--version" };
NiceMock<CMockApp> app;
CArgParser argParser(&app);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
ON_CALL(app, version()).WillByDefault(Invoke(showMockVersion));
argParser.parseGenericArgs(argc, kVersionCmd, i);
EXPECT_EQ(true, g_versionShowed);
EXPECT_EQ(1, i);
}
TEST(CGenericArgsParsingTests, parseGenericArgs_noTrayCmd_disableTrayTrue)
{
int i = 1;
const int argc = 2;
const char* kNoTrayCmd[argc] = { "stub", "--no-tray" };
CArgParser argParser(NULL);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
argParser.parseGenericArgs(argc, kNoTrayCmd, i);
EXPECT_EQ(true, argsBase.m_disableTray);
EXPECT_EQ(1, i);
}
TEST(CGenericArgsParsingTests, parseGenericArgs_ipcCmd_enableIpcTrue)
{
int i = 1;
const int argc = 2;
const char* kIpcCmd[argc] = { "stub", "--ipc" };
CArgParser argParser(NULL);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
argParser.parseGenericArgs(argc, kIpcCmd, i);
EXPECT_EQ(true, argsBase.m_enableIpc);
EXPECT_EQ(1, i);
}
TEST(CGenericArgsParsingTests, parseGenericArgs_cryptoPassCmd_savePassword)
{
int i = 1;
const int argc = 3;
const char* kCryptoPassCmd[argc] = { "stub", "--crypto-pass", "mock_password" };
CArgParser argParser(NULL);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
argParser.parseGenericArgs(argc, kCryptoPassCmd, i);
EXPECT_EQ("mock_password", argsBase.m_crypto.m_pass);
EXPECT_EQ(1, argsBase.m_crypto.m_mode); // 1 == kCfb
EXPECT_EQ(2, i);
}
#ifndef WINAPI_XWINDOWS
TEST(CGenericArgsParsingTests, parseGenericArgs_dragDropCmdOnNonLinux_enableDragDropTrue)
{
int i = 1;
const int argc = 2;
const char* kDragDropCmd[argc] = { "stub", "--enable-drag-drop" };
CArgParser argParser(NULL);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
argParser.parseGenericArgs(argc, kDragDropCmd, i);
EXPECT_EQ(true, argsBase.m_enableDragDrop);
EXPECT_EQ(1, i);
}
#endif
#ifdef WINAPI_XWINDOWS
TEST(CGenericArgsParsingTests, parseGenericArgs_dragDropCmdOnLinux_enableDragDropFalse)
{
int i = 1;
const int argc = 2;
const char* kDragDropCmd[argc] = { "stub", "--enable-drag-drop" };
CArgParser argParser(NULL);
CArgsBase argsBase;
argParser.setArgsBase(argsBase);
argParser.parseGenericArgs(argc, kDragDropCmd, i);
EXPECT_FALSE(argsBase.m_enableDragDrop);
EXPECT_EQ(1, i);
}
#endif

View File

@@ -0,0 +1,66 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014 Synergy Si, Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file COPYING that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "synergy/ArgParser.h"
#include "synergy/ServerArgs.h"
#include "test/mock/synergy/MockArgParser.h"
#include "test/global/gtest.h"
using ::testing::_;
using ::testing::Invoke;
using ::testing::NiceMock;
bool
server_stubParseGenericArgs(int, const char* const*, int&)
{
return false;
}
bool
server_stubCheckUnexpectedArgs()
{
return false;
}
TEST(CServerArgsParsingTests, parseServerArgs_addressArg_setSynergyAddress)
{
NiceMock<CMockArgParser> argParser;
ON_CALL(argParser, parseGenericArgs(_, _, _)).WillByDefault(Invoke(server_stubParseGenericArgs));
ON_CALL(argParser, checkUnexpectedArgs()).WillByDefault(Invoke(server_stubCheckUnexpectedArgs));
CServerArgs serverArgs;
const int argc = 3;
const char* kAddressCmd[argc] = { "stub", "--address", "mock_address" };
argParser.parseServerArgs(serverArgs, argc, kAddressCmd);
EXPECT_EQ("mock_address", serverArgs.m_synergyAddress);
}
TEST(CServerArgsParsingTests, parseServerArgs_configArg_setConfigFile)
{
NiceMock<CMockArgParser> argParser;
ON_CALL(argParser, parseGenericArgs(_, _, _)).WillByDefault(Invoke(server_stubParseGenericArgs));
ON_CALL(argParser, checkUnexpectedArgs()).WillByDefault(Invoke(server_stubCheckUnexpectedArgs));
CServerArgs serverArgs;
const int argc = 3;
const char* kConfigCmd[argc] = { "stub", "--config", "mock_configFile" };
argParser.parseServerArgs(serverArgs, argc, kConfigCmd);
EXPECT_EQ("mock_configFile", serverArgs.m_configFile);
}

1
test Normal file
View File

@@ -0,0 +1 @@
3