diff -Nru mumble-1.3.0/debian/changelog mumble-1.3.1-rc1/debian/changelog --- mumble-1.3.0/debian/changelog 2019-09-14 22:11:37.000000000 +0000 +++ mumble-1.3.1-rc1/debian/changelog 2020-04-11 07:30:46.000000000 +0000 @@ -1,8 +1,8 @@ -mumble (1.3.0-1~ppa1~disco1) disco; urgency=medium +mumble (1.3.1-rc1-1~ppa1~disco1) disco; urgency=medium - * PPA Upload of 1.3.0 for Ubuntu disco + * PPA Upload of 1.3.1-rc1 for Ubuntu disco - -- Mumble PPA Bot Sat, 14 Sep 2019 22:11:37 +0000 + -- Mumble PPA Bot Sat, 11 Apr 2020 07:30:46 +0000 mumble (1.2.4-118-g63e3fd0-0~template2) template; urgency=low diff -Nru mumble-1.3.0/debian/README.md mumble-1.3.1-rc1/debian/README.md --- mumble-1.3.0/debian/README.md 2019-09-14 22:11:37.000000000 +0000 +++ mumble-1.3.1-rc1/debian/README.md 2020-04-11 07:30:46.000000000 +0000 @@ -3,9 +3,34 @@ This git repository contains a template Debian package that we use to generate the Mumble PPAs that live on Launchpad: -* - * - * +| PPA | Description | +| --- | --- | +| [release][ppa-release] | Current stable release of Mumble and Mumble Server | +| [snapshot][ppa-snapshot] | Current development snapshot of Mumble and Mumble Server for testind and bleeding-edge features and fixes | + +The provided packages are the client `mumble` and the server `mumble-server`. + +## Context + +PPA stands for Personal Package Archive. + +While a distribution like Ubuntu prepares and offers official packages (builds) maintained by a dedicated maintainer these packages can become outdated compared to the upstream source project because of the fixed release cycles of the distribution. + +Some distributions offer backports package repositories that backport newer program versions to previous OS distribution versions. But a single backports repository will contain a lot of newer packages instead of just the ones you want to explicitly use newer versions of. Manually managing those (with a lower auto-install priority) is possible, but manual work. + +PPAs allow third parties like upstream official projects to host their own package archives which can be added to an installations package sources. These PPAs are often more focused on single software packages. + +For Mumble we provide a [release][ppa-release] and a [snapshot][ppa-snapshot] repository (under [~mumble][ppa]). The release PPA holds current stable releases for current and older Ubuntu releases. The snapshot PPA holds current development snapshots for testing and bleeding-edge features and fixes. + +### PPA package building + +Ubuntu uses the Debian apt deb package system. + +This repository holds deb package information and scripts for building deb packages, and for uploading them to the PPA. + +### Our infrastructure + +In our internal build system we have a job named 'Mumble Ubuntu PPA Submitter' that prepares a package source tar ball that is uploaded to launchpad, build on the launchpad build system, and published in the PPAs for numerous Ubuntu versions. ## General Idea @@ -75,3 +100,7 @@ a temporary indicator of the fact that a PPA build was performed (oh, and it of course also provides the version number to use for the package and the release to target). + +[ppa]: https://launchpad.net/~mumble +[ppa-release]: https://launchpad.net/~mumble/+archive/ubuntu/release +[ppa-snapshot]: https://launchpad.net/~mumble/+archive/ubuntu/snapshot diff -Nru mumble-1.3.0/g15helper/g15helper.plist mumble-1.3.1-rc1/g15helper/g15helper.plist --- mumble-1.3.0/g15helper/g15helper.plist 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/g15helper/g15helper.plist 2020-04-11 07:27:44.000000000 +0000 @@ -13,7 +13,7 @@ CFBundleSignature G15H CFBundleVersion - 1.3.0 + 1.3.1 NSHumanReadableCopyright Copyright (c) 2005-2019 The Mumble Developers diff -Nru mumble-1.3.0/g15helper/g15helper.rc mumble-1.3.1-rc1/g15helper/g15helper.rc --- mumble-1.3.0/g15helper/g15helper.rc 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/g15helper/g15helper.rc 2020-04-11 07:27:44.000000000 +0000 @@ -20,8 +20,8 @@ #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,0,0 - PRODUCTVERSION 1,3,0,0 + FILEVERSION 1,3,1,0 + PRODUCTVERSION 1,3,1,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS (VER_DEBUG|VER_RELEASE) FILEOS VOS_NT_WINDOWS32 @@ -34,9 +34,9 @@ BEGIN VALUE "CompanyName", "The Mumble Developers" VALUE "FileDescription", "Mumble G15 LCD Helper" - VALUE "FileVersion", "1.3.0" - VALUE "ProductVersion", "1.3.0" - VALUE "LegalCopyright", "Copyright (c) 2005-2019 The Mumble Developers" + VALUE "FileVersion", "1.3.1" + VALUE "ProductVersion", "1.3.1" + VALUE "LegalCopyright", "Copyright (c) 2005-2020 The Mumble Developers" VALUE "OriginalFilename", "mumble-g15-helper.exe" VALUE "ProductName", "Mumble G15 LCD Helper" #ifdef SNAPSHOT_BUILD diff -Nru mumble-1.3.0/installer/Settings.wxi mumble-1.3.1-rc1/installer/Settings.wxi --- mumble-1.3.0/installer/Settings.wxi 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/installer/Settings.wxi 2020-04-11 07:27:44.000000000 +0000 @@ -2,7 +2,7 @@ - + diff -Nru mumble-1.3.0/macx/common.pri mumble-1.3.1-rc1/macx/common.pri --- mumble-1.3.0/macx/common.pri 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/macx/common.pri 2020-04-11 07:27:44.000000000 +0000 @@ -5,7 +5,7 @@ # Common OSX overlay settings. -VERSION = 1.3.0 +VERSION = 1.3.1 DEFINES *= VERSION=\\\"$$VERSION\\\" diff -Nru mumble-1.3.0/macx/osax/osax.plist mumble-1.3.1-rc1/macx/osax/osax.plist --- mumble-1.3.0/macx/osax/osax.plist 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/macx/osax/osax.plist 2020-04-11 07:27:44.000000000 +0000 @@ -13,7 +13,7 @@ CFBundlePackageType osax CFbundleVersion - 1.3.0 + 1.3.1 CFBundleSignature MUOL CSResourcesFileMapped diff -Nru mumble-1.3.0/overlay/mumble_ol.rc mumble-1.3.1-rc1/overlay/mumble_ol.rc --- mumble-1.3.0/overlay/mumble_ol.rc 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/overlay/mumble_ol.rc 2020-04-11 07:27:44.000000000 +0000 @@ -18,8 +18,8 @@ #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,0,0 - PRODUCTVERSION 1,3,0,0 + FILEVERSION 1,3,1,0 + PRODUCTVERSION 1,3,1,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS (VER_DEBUG|VER_RELEASE) FILEOS VOS_NT_WINDOWS32 @@ -32,8 +32,8 @@ BEGIN VALUE "CompanyName", "The Mumble Developers" VALUE "FileDescription", "Mumble - Low-latency VoIP client" - VALUE "FileVersion", "1.3.0" - VALUE "ProductVersion", "1.3.0" + VALUE "FileVersion", "1.3.1" + VALUE "ProductVersion", "1.3.1" VALUE "LegalCopyright", "Copyright (c) 2005-2019 The Mumble Developers" VALUE "OriginalFilename", "mumble_ol.dll" VALUE "ProductName", "Mumble" diff -Nru mumble-1.3.0/overlay/overlay_exe/overlay_exe.rc mumble-1.3.1-rc1/overlay/overlay_exe/overlay_exe.rc --- mumble-1.3.0/overlay/overlay_exe/overlay_exe.rc 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/overlay/overlay_exe/overlay_exe.rc 2020-04-11 07:27:44.000000000 +0000 @@ -18,8 +18,8 @@ #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,0,0 - PRODUCTVERSION 1,3,0,0 + FILEVERSION 1,3,1,0 + PRODUCTVERSION 1,3,1,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS (VER_DEBUG|VER_RELEASE) FILEOS VOS_NT_WINDOWS32 @@ -32,9 +32,9 @@ BEGIN VALUE "CompanyName", "The Mumble Developers" VALUE "FileDescription", "Mumble - Low-latency VoIP client" - VALUE "FileVersion", "1.3.0" - VALUE "ProductVersion", "1.3.0" - VALUE "LegalCopyright", "Copyright (c) 2005-2019 The Mumble Developers" + VALUE "FileVersion", "1.3.1" + VALUE "ProductVersion", "1.3.1" + VALUE "LegalCopyright", "Copyright (c) 2005-2020 The Mumble Developers" VALUE "OriginalFilename", "mumble_ol_helper.exe" VALUE "ProductName", "Mumble" #ifdef SNAPSHOT_BUILD diff -Nru mumble-1.3.0/overlay/overlay-shared.pro mumble-1.3.1-rc1/overlay/overlay-shared.pro --- mumble-1.3.0/overlay/overlay-shared.pro 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/overlay/overlay-shared.pro 2020-04-11 07:27:44.000000000 +0000 @@ -5,7 +5,7 @@ include (../qmake/compiler.pri) -VERSION = 1.3.0 +VERSION = 1.3.1 TARGET_EXT = .dll TEMPLATE = lib CONFIG -= qt diff -Nru mumble-1.3.0/overlay_gl/overlay_gl.pro mumble-1.3.1-rc1/overlay_gl/overlay_gl.pro --- mumble-1.3.0/overlay_gl/overlay_gl.pro 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/overlay_gl/overlay_gl.pro 2020-04-11 07:27:44.000000000 +0000 @@ -10,7 +10,7 @@ TEMPLATE = lib CONFIG -= qt gui CONFIG *= debug_and_release -VERSION = 1.3.0 +VERSION = 1.3.1 SOURCES = overlay.c CONFIG(static) { diff -Nru mumble-1.3.0/overlay_winx64/mumble_ol.rc mumble-1.3.1-rc1/overlay_winx64/mumble_ol.rc --- mumble-1.3.0/overlay_winx64/mumble_ol.rc 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/overlay_winx64/mumble_ol.rc 2020-04-11 07:27:44.000000000 +0000 @@ -18,8 +18,8 @@ #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,0,0 - PRODUCTVERSION 1,3,0,0 + FILEVERSION 1,3,1,0 + PRODUCTVERSION 1,3,1,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS (VER_DEBUG|VER_RELEASE) FILEOS VOS_NT_WINDOWS32 @@ -32,9 +32,9 @@ BEGIN VALUE "CompanyName", "The Mumble Developers" VALUE "FileDescription", "Mumble - Low-latency VoIP client" - VALUE "FileVersion", "1.3.0" - VALUE "ProductVersion", "1.3.0" - VALUE "LegalCopyright", "Copyright (c) 2005-2019 The Mumble Developers" + VALUE "FileVersion", "1.3.1" + VALUE "ProductVersion", "1.3.1" + VALUE "LegalCopyright", "Copyright (c) 2005-2020 The Mumble Developers" VALUE "OriginalFilename", "mumble_ol_x64.dll" VALUE "ProductName", "Mumble" #ifdef SNAPSHOT_BUILD diff -Nru mumble-1.3.0/overlay_winx64/overlay_exe_winx64/overlay_exe.rc mumble-1.3.1-rc1/overlay_winx64/overlay_exe_winx64/overlay_exe.rc --- mumble-1.3.0/overlay_winx64/overlay_exe_winx64/overlay_exe.rc 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/overlay_winx64/overlay_exe_winx64/overlay_exe.rc 2020-04-11 07:27:44.000000000 +0000 @@ -18,8 +18,8 @@ #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,0,0 - PRODUCTVERSION 1,3,0,0 + FILEVERSION 1,3,1,0 + PRODUCTVERSION 1,3,1,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS (VER_DEBUG|VER_RELEASE) FILEOS VOS_NT_WINDOWS32 @@ -32,9 +32,9 @@ BEGIN VALUE "CompanyName", "The Mumble Developers" VALUE "FileDescription", "Mumble - Low-latency VoIP client" - VALUE "FileVersion", "1.3.0" - VALUE "ProductVersion", "1.3.0" - VALUE "LegalCopyright", "Copyright (c) 2005-2019 The Mumble Developers" + VALUE "FileVersion", "1.3.1" + VALUE "ProductVersion", "1.3.1" + VALUE "LegalCopyright", "Copyright (c) 2005-2020 The Mumble Developers" VALUE "OriginalFilename", "mumble_ol_helper_x64.exe" VALUE "ProductName", "Mumble" #ifdef SNAPSHOT_BUILD diff -Nru mumble-1.3.0/plugins/mumble_plugin.h mumble-1.3.1-rc1/plugins/mumble_plugin.h --- mumble-1.3.0/plugins/mumble_plugin.h 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/plugins/mumble_plugin.h 2020-04-11 07:27:44.000000000 +0000 @@ -126,7 +126,7 @@ typedef MumblePluginQt *(MUMBLE_PLUGIN_CALLING_CONVENTION *mumblePluginQtFunc)(); /* - * All plugins must implement one function called mumbleGetPlugin(), which + * All plugins must implement one function called getMumblePlugin(), which * follows the mumblePluginFunc type and returns a MumblePlugin struct. * * magic should be initialized to MUMBLE_PLUGIN_MAGIC. description is the diff -Nru mumble-1.3.0/qmake/toolchain/win32-msvc2015/x64.toolchain mumble-1.3.1-rc1/qmake/toolchain/win32-msvc2015/x64.toolchain --- mumble-1.3.0/qmake/toolchain/win32-msvc2015/x64.toolchain 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/qmake/toolchain/win32-msvc2015/x64.toolchain 2020-04-11 07:27:44.000000000 +0000 @@ -12,29 +12,29 @@ # of the native architecture of the build # environment. -# Use the x86-based amd64 cross compiler by default. +# Use the x86-based amd64 cross compiler by default... QMAKE_CC = "\"$$(VCINSTALLDIR)bin\\x86_amd64\\cl.exe\"" QMAKE_CXX = "\"$$(VCINSTALLDIR)bin\\x86_amd64\\cl.exe\"" -QMAKE_LINK = \""$$(VCINSTALLDIR)\\bin\\x86_amd64\\link.exe\"" -QMAKE_LIB = \""$$(VCINSTALLDIR)\\bin\\x86_amd64\\lib.exe\"" +QMAKE_LINK = \""$$(VCINSTALLDIR)bin\\x86_amd64\\link.exe\"" +QMAKE_LIB = \""$$(VCINSTALLDIR)bin\\x86_amd64\\lib.exe\"" -# ...but use the native amd64 compiler if it is available. +# ... but use the native amd64 compiler if it is available. exists($$(VCINSTALLDIR)\\bin\\amd64) { QMAKE_CC = "\"$$(VCINSTALLDIR)bin\\amd64\\cl.exe\"" QMAKE_CXX = "\"$$(VCINSTALLDIR)bin\\amd64\\cl.exe\"" - QMAKE_LINK = \""$$(VCINSTALLDIR)\\bin\\amd64\\link.exe\"" - QMAKE_LIB = \""$$(VCINSTALLDIR)\\bin\\amd64\\lib.exe\"" + QMAKE_LINK = \""$$(VCINSTALLDIR)bin\\amd64\\link.exe\"" + QMAKE_LIB = \""$$(VCINSTALLDIR)bin\\amd64\\lib.exe\"" } -QMAKE_RC = \""$$(WindowsSdkDir)\\bin\\x64\\rc.exe\"" +QMAKE_RC = \""$$(WindowsSdkDir)bin\\$$(WindowsSDKLibVersion)x64\\rc.exe\"" -INCLUDEPATH *= "$$(VCINSTALLDIR)\\include" -INCLUDEPATH *= "$$(VCINSTALLDIR)\\atlmfc\\include" -INCLUDEPATH *= "$$(WindowsSdkDir)\\include\\shared" -INCLUDEPATH *= "$$(WindowsSdkDir)\\include\\um" -INCLUDEPATH *= "$$(WindowsSdkDir)\\include\\winrt" +INCLUDEPATH *= "$$(VCINSTALLDIR)include" +INCLUDEPATH *= "$$(VCINSTALLDIR)atlmfc\\include" +INCLUDEPATH *= "$$(WindowsSdkDir)include$$(WindowsSDKLibVersion)shared" +INCLUDEPATH *= "$$(WindowsSdkDir)include$$(WindowsSDKLibVersion)um" +INCLUDEPATH *= "$$(WindowsSdkDir)include$$(WindowsSDKLibVersion)winrt" -QMAKE_LFLAGS *= "/LIBPATH:\"$$(VCINSTALLDIR)\\lib\\amd64\"" -QMAKE_LFLAGS *= "/LIBPATH:\"$$(VCINSTALLDIR)\\atlmfc\\lib\\amd64\"" -QMAKE_LFLAGS *= "/LIBPATH:\"$$(WindowsSdkDir)\\lib\\$$(WindowsSDKLibVersion)um\\x64\"" -QMAKE_LFLAGS *= "/LIBPATH:\"$$(WindowsSdkDir)\\lib\\$$(WindowsSDKLibVersion)ucrt\\x64\"" +QMAKE_LFLAGS *= "/LIBPATH:\"$$(VCINSTALLDIR)lib\\amd64\"" +QMAKE_LFLAGS *= "/LIBPATH:\"$$(VCINSTALLDIR)atlmfc\\lib\\amd64\"" +QMAKE_LFLAGS *= "/LIBPATH:\"$$(WindowsSdkDir)lib\\$$(WindowsSDKLibVersion)um\\x64\"" +QMAKE_LFLAGS *= "/LIBPATH:\"$$(WindowsSdkDir)lib\\$$(WindowsSDKLibVersion)ucrt\\x64\"" diff -Nru mumble-1.3.0/qmake/toolchain/win32-msvc2015/x86.toolchain mumble-1.3.1-rc1/qmake/toolchain/win32-msvc2015/x86.toolchain --- mumble-1.3.0/qmake/toolchain/win32-msvc2015/x86.toolchain 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/qmake/toolchain/win32-msvc2015/x86.toolchain 2020-04-11 07:27:44.000000000 +0000 @@ -14,17 +14,17 @@ QMAKE_CC = "\"$$(VCINSTALLDIR)bin\\cl.exe\"" QMAKE_CXX = "\"$$(VCINSTALLDIR)bin\\cl.exe\"" -QMAKE_LINK = \""$$(VCINSTALLDIR)\\bin\\link.exe\"" -QMAKE_LIB = \""$$(VCINSTALLDIR)\\bin\\lib.exe\"" -QMAKE_RC = \""$$(WindowsSdkDir)\\bin\\x86\\rc.exe\"" +QMAKE_LINK = \""$$(VCINSTALLDIR)bin\\link.exe\"" +QMAKE_LIB = \""$$(VCINSTALLDIR)bin\\lib.exe\"" +QMAKE_RC = \""$$(WindowsSdkDir)bin\\$$(WindowsSDKLibVersion)x86\\rc.exe\"" -INCLUDEPATH *= "$$(VCINSTALLDIR)\\include" -INCLUDEPATH *= "$$(VCINSTALLDIR)\\atlmfc\\include" -INCLUDEPATH *= "$$(WindowsSdkDir)\\include\\shared" -INCLUDEPATH *= "$$(WindowsSdkDir)\\include\\um" -INCLUDEPATH *= "$$(WindowsSdkDir)\\include\\winrt" +INCLUDEPATH *= "$$(VCINSTALLDIR)include" +INCLUDEPATH *= "$$(VCINSTALLDIR)atlmfc\\include" +INCLUDEPATH *= "$$(WindowsSdkDir)include$$(WindowsSDKLibVersion)shared" +INCLUDEPATH *= "$$(WindowsSdkDir)include$$(WindowsSDKLibVersion)um" +INCLUDEPATH *= "$$(WindowsSdkDir)include$$(WindowsSDKLibVersion)winrt" -QMAKE_LFLAGS *= "/LIBPATH:\"$$(VCINSTALLDIR)\\lib\"" -QMAKE_LFLAGS *= "/LIBPATH:\"$$(VCINSTALLDIR)\\atlmfc\\lib\"" -QMAKE_LFLAGS *= "/LIBPATH:\"$$(WindowsSdkDir)\\lib\\$$(WindowsSDKLibVersion)um\\x86\"" -QMAKE_LFLAGS *= "/LIBPATH:\"$$(WindowsSdkDir)\\lib\\$$(WindowsSDKLibVersion)ucrt\\x86\"" +QMAKE_LFLAGS *= "/LIBPATH:\"$$(VCINSTALLDIR)lib\"" +QMAKE_LFLAGS *= "/LIBPATH:\"$$(VCINSTALLDIR)atlmfc\\lib\"" +QMAKE_LFLAGS *= "/LIBPATH:\"$$(WindowsSdkDir)lib\\$$(WindowsSDKLibVersion)um\\x86\"" +QMAKE_LFLAGS *= "/LIBPATH:\"$$(WindowsSdkDir)lib\\$$(WindowsSDKLibVersion)ucrt\\x86\"" diff -Nru mumble-1.3.0/qmake/toolchain/win32-msvc2015/x86-xp.toolchain mumble-1.3.1-rc1/qmake/toolchain/win32-msvc2015/x86-xp.toolchain --- mumble-1.3.0/qmake/toolchain/win32-msvc2015/x86-xp.toolchain 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/qmake/toolchain/win32-msvc2015/x86-xp.toolchain 2020-04-11 07:27:44.000000000 +0000 @@ -14,24 +14,24 @@ # Windows XP, regardless of the native # architecture of the build environment. -WIN7_XP_SDK_DIR="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.1A" +WIN7_XP_SDK_DIR="C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.1A\\" QMAKE_CC = "\"$$(VCINSTALLDIR)bin\\cl.exe\" /D_USING_V110_SDK71_" QMAKE_CXX = "\"$$(VCINSTALLDIR)bin\\cl.exe\" /D_USING_V110_SDK71_" -QMAKE_LINK = \""$$(VCINSTALLDIR)\\bin\\link.exe\"" -QMAKE_LIB = \""$$(VCINSTALLDIR)\\bin\\lib.exe\"" -QMAKE_RC = \""$${WIN7_XP_SDK_DIR}\\bin\\rc.exe\" /D_USING_V110_SDK71_" +QMAKE_LINK = \""$$(VCINSTALLDIR)bin\\link.exe\"" +QMAKE_LIB = \""$$(VCINSTALLDIR)bin\\lib.exe\"" +QMAKE_RC = \""$${WIN7_XP_SDK_DIR}bin\\rc.exe\" /D_USING_V110_SDK71_" -INCLUDEPATH *= "$$(DXSDK_DIR)\\include" -INCLUDEPATH *= "$${WIN7_XP_SDK_DIR}\\include" -INCLUDEPATH *= "$$(VCINSTALLDIR)\\include" -INCLUDEPATH *= "$$(VCINSTALLDIR)\\atlmfc\\include" -INCLUDEPATH *= "$$(WindowsSdkDir)\\include\\shared" -INCLUDEPATH *= "$$(WindowsSdkDir)\\include\\um" -INCLUDEPATH *= "$$(WindowsSdkDir)\\include\\winrt" +INCLUDEPATH *= "$$(DXSDK_DIR)include" +INCLUDEPATH *= "$${WIN7_XP_SDK_DIR}include" +INCLUDEPATH *= "$$(VCINSTALLDIR)include" +INCLUDEPATH *= "$$(VCINSTALLDIR)atlmfc\\include" +INCLUDEPATH *= "$$(WindowsSdkDir)include\\$$(WindowsSDKLibVersion)shared" +INCLUDEPATH *= "$$(WindowsSdkDir)include\\$$(WindowsSDKLibVersion)um" +INCLUDEPATH *= "$$(WindowsSdkDir)include\\$$(WindowsSDKLibVersion)winrt" QMAKE_LFLAGS *= "/LIBPATH:\"$$(DXSDK_DIR)\\lib\\x86\"" -QMAKE_LFLAGS *= "/LIBPATH:\"$$(VCINSTALLDIR)\\lib\"" -QMAKE_LFLAGS *= "/LIBPATH:\"$$(VCINSTALLDIR)\\atlmfc\\lib\"" -QMAKE_LFLAGS *= "/LIBPATH:\"$$(WindowsSdkDir)\\lib\\$$(WindowsSDKLibVersion)um\\x86\"" -QMAKE_LFLAGS *= "/LIBPATH:\"$$(WindowsSdkDir)\\lib\\$$(WindowsSDKLibVersion)ucrt\\x86\"" +QMAKE_LFLAGS *= "/LIBPATH:\"$$(VCINSTALLDIR)lib\"" +QMAKE_LFLAGS *= "/LIBPATH:\"$$(VCINSTALLDIR)atlmfc\\lib\"" +QMAKE_LFLAGS *= "/LIBPATH:\"$$(WindowsSdkDir)lib\\$$(WindowsSDKLibVersion)um\\x86\"" +QMAKE_LFLAGS *= "/LIBPATH:\"$$(WindowsSdkDir)lib\\$$(WindowsSDKLibVersion)ucrt\\x86\"" diff -Nru mumble-1.3.0/scripts/azure-pipelines/build_macos.bash mumble-1.3.1-rc1/scripts/azure-pipelines/build_macos.bash --- mumble-1.3.0/scripts/azure-pipelines/build_macos.bash 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/scripts/azure-pipelines/build_macos.bash 2020-04-11 07:27:44.000000000 +0000 @@ -11,4 +11,6 @@ export MUMBLE_PREFIX=/usr/local export MUMBLE_ICE_PREFIX=/usr/local/opt/ice -qmake -recursive CONFIG+="release tests warnings-as-errors" && make -j $(sysctl -n hw.ncpu) && make check +qmake -recursive CONFIG+="release tests warnings-as-errors" +make -j $(sysctl -n hw.ncpu) +make check diff -Nru mumble-1.3.0/scripts/azure-pipelines/install-environment.ps1 mumble-1.3.1-rc1/scripts/azure-pipelines/install-environment.ps1 --- mumble-1.3.0/scripts/azure-pipelines/install-environment.ps1 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/scripts/azure-pipelines/install-environment.ps1 2020-04-11 07:27:44.000000000 +0000 @@ -37,7 +37,19 @@ if (-Not (Test-Path $env_7z)) { Write-Host "Environment not cached. Downloading..." $env_url = "$MUMBLE_ENVIRONMENT_SOURCE/$MUMBLE_ENVIRONMENT_VERSION.7z" - Invoke-WebRequest -Uri $env_url -OutFile $env_7z + try { + # According to https://github.com/PowerShell/PowerShell/issues/2138 disabling the + # progressbar can significantly increase the speed of Invoke-Web-Request. + $ProgressPreference = 'SilentlyContinue' + + Invoke-WebRequest -Uri $env_url -OutFile $env_7z + + # Reset progressbar + $ProgressPreference = 'Continue' + } catch { + Write-Host "Failed at downloading build-environment: $PSItem" + exit 1 + } } if (-Not (Test-Path (Join-Path $MUMBLE_ENVIRONMENT_PATH $MUMBLE_ENVIRONMENT_VERSION))) { diff -Nru mumble-1.3.0/scripts/travis-ci/before_install.bash mumble-1.3.1-rc1/scripts/travis-ci/before_install.bash --- mumble-1.3.0/scripts/travis-ci/before_install.bash 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/scripts/travis-ci/before_install.bash 2020-04-11 07:27:44.000000000 +0000 @@ -76,7 +76,18 @@ # We don’t use the symlinked "python" installed # by default in the image, so we unlink it to allow # the "python@2" package to be installed without conflict. - brew update && brew unlink python && brew install qt5 libogg libvorbis flac libsndfile protobuf openssl ice + brew update && brew unlink python + + # As brew will set a non-zero exit status if one of the packages it is asked to install + # is installed already. Thus we have to iterate through every single one and check if it + # is installed first. + for pkg in qt5 libogg libvorbis flac libsndfile protobuf openssl ice; do + if brew ls --versions "$pkg" > /dev/null; then + echo "Skipping installation of $pkg as it is already installed" + else + brew install "$pkg" + fi + done else exit 1 fi diff -Nru mumble-1.3.0/scripts/travis-ci/script.bash mumble-1.3.1-rc1/scripts/travis-ci/script.bash --- mumble-1.3.0/scripts/travis-ci/script.bash 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/scripts/travis-ci/script.bash 2020-04-11 07:27:44.000000000 +0000 @@ -17,7 +17,9 @@ if [ "${MUMBLE_NO_PCH}" == "1" ]; then EXTRA_CONFIG="no-pch ${EXTRA_CONFIG}" fi - qmake-qt4 CONFIG+="release tests g15-emulator qt4-legacy-compat ${EXTRA_CONFIG}" -recursive && make -j2 && make check + qmake-qt4 CONFIG+="release tests g15-emulator qt4-legacy-compat ${EXTRA_CONFIG}" -recursive + make -j2 + make check elif [ "${MUMBLE_QT}" == "qt5" ] && [ "${MUMBLE_HOST}" == "x86_64-linux-gnu" ]; then EXTRA_CONFIG=PREFIX=/usr if [ "${MUMBLE_NO_PCH}" == "1" ]; then @@ -33,7 +35,8 @@ # Run the SonarQube analysis sonar-scanner else - make -j2 && make check + make -j2 + make check if [ "${MASTER_BRANCH}" = "1" ]; then # The next few lines should really be done by "make install"; https://github.com/mumble-voip/mumble/issues/1029 @@ -61,7 +64,7 @@ if [ "${MUMBLE_NO_PCH}" == "1" ]; then EXTRA_CONFIG="no-pch ${EXTRA_CONFIG}" fi - ${MUMBLE_HOST}.static-qmake-qt5 -recursive -Wall CONFIG+="release tests warnings-as-errors g15-emulator no-overlay no-bonjour no-elevation no-ice ${EXTRA_CONFIG}" + ${MUMBLE_HOST}.static-qmake-qt5 -recursive -Wall CONFIG+="release tests g15-emulator no-overlay no-bonjour no-elevation no-ice ${EXTRA_CONFIG}" make -j2 make check TESTRUNNER="wine" elif [ "${MUMBLE_QT}" == "qt5" ] && [ "${MUMBLE_HOST}" == "x86_64-w64-mingw32" ]; then @@ -74,7 +77,7 @@ if [ "${MUMBLE_NO_PCH}" == "1" ]; then EXTRA_CONFIG="no-pch ${EXTRA_CONFIG}" fi - ${MUMBLE_HOST}.static-qmake-qt5 -recursive -Wall CONFIG+="release tests warnings-as-errors g15-emulator no-overlay no-bonjour no-elevation no-ice ${EXTRA_CONFIG}" + ${MUMBLE_HOST}.static-qmake-qt5 -recursive -Wall CONFIG+="release tests g15-emulator no-overlay no-bonjour no-elevation no-ice ${EXTRA_CONFIG}" make -j2 make check TESTRUNNER="wine" else @@ -86,7 +89,9 @@ export PATH=$PATH:/usr/local/opt/qt5/bin:/usr/local/bin export MUMBLE_PREFIX=/usr/local export MUMBLE_ICE_PREFIX=/usr/local/opt/ice - qmake CONFIG+="release tests warnings-as-errors" && make -j2 && make check + qmake CONFIG+="release tests" + make -j2 + make check ./macx/scripts/osxdist.py --no-compat-warning else exit 1 diff -Nru mumble-1.3.0/src/mumble/AudioInput.cpp mumble-1.3.1-rc1/src/mumble/AudioInput.cpp --- mumble-1.3.0/src/mumble/AudioInput.cpp 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/AudioInput.cpp 2020-04-11 07:27:44.000000000 +0000 @@ -794,6 +794,13 @@ iFrameCounter++; + // As g.iTarget is not protected by any locks, we avoid race-conditions by + // copying it once at this point and stick to whatever value it is here. Thus + // if the value of g.iTarget changes during the execution of this function, + // it won't cause any inconsistencies and the change is reflected once this + // function is called again. + int voiceTargetID = g.iTarget; + if (! bRunning) return; @@ -864,10 +871,13 @@ bool bIsSpeech = false; - if (level > g.s.fVADmax) + if (level > g.s.fVADmax) { + // Voice-activation threshold has been reached bIsSpeech = true; - else if (level > g.s.fVADmin && bPreviousVoice) + } else if (level > g.s.fVADmin && bPreviousVoice) { + // Voice-deactivation threshold has not yet been reached bIsSpeech = true; + } if (! bIsSpeech) { iHoldFrames++; @@ -877,15 +887,20 @@ iHoldFrames = 0; } - if (g.s.atTransmit == Settings::Continuous) + if (g.s.atTransmit == Settings::Continuous) { + // Continous transmission is enabled bIsSpeech = true; - else if (g.s.atTransmit == Settings::PushToTalk) + } else if (g.s.atTransmit == Settings::PushToTalk) { + // PTT is enabled, so check if it is currently active bIsSpeech = g.s.uiDoublePush && ((g.uiDoublePush < g.s.uiDoublePush) || (g.tDoublePush.elapsed() < g.s.uiDoublePush)); + } + // If g.iPushToTalk > 0 that means that we are currently in some sort of PTT action. For + // instance this could mean we're currently whispering bIsSpeech = bIsSpeech || (g.iPushToTalk > 0); ClientUser *p = ClientUser::get(g.uiSession); - if (g.s.bMute || ((g.s.lmLoopMode != Settings::Local) && p && (p->bMute || p->bSuppress)) || g.bPushToMute || (g.iTarget < 0)) { + if (g.s.bMute || ((g.s.lmLoopMode != Settings::Local) && p && (p->bMute || p->bSuppress)) || g.bPushToMute || (voiceTargetID < 0)) { bIsSpeech = false; } @@ -900,7 +915,7 @@ if (p) { if (! bIsSpeech) p->setTalking(Settings::Passive); - else if (g.iTarget == 0) + else if (voiceTargetID == 0) p->setTalking(Settings::Talking); else p->setTalking(Settings::Shouting); @@ -1001,7 +1016,7 @@ } if (encoded) { - flushCheck(QByteArray(reinterpret_cast(&buffer[0]), len), !bIsSpeech); + flushCheck(QByteArray(reinterpret_cast(&buffer[0]), len), !bIsSpeech, voiceTargetID); } if (! bIsSpeech) @@ -1024,18 +1039,28 @@ sh->sendMessage(data, pds.size() + 1); } -void AudioInput::flushCheck(const QByteArray &frame, bool terminator) { +void AudioInput::flushCheck(const QByteArray &frame, bool terminator, int voiceTargetID) { qlFrames << frame; if (! terminator && iBufferedFrames < iAudioFrames) return; int flags = 0; - if (g.iTarget > 0) { - flags = g.iTarget; + if (voiceTargetID > 0) { + flags = voiceTargetID; } if (terminator && g.iPrevTarget > 0) { + // If we have been whispering to some target but have just ended, terminator will be true. However + // in the case of whispering this means that we just released the whisper key so this here is the + // last audio frame that is sent for whispering. The whisper key being released means that g.iTarget + // is reset to 0 by now. In order to send the last whisper frame correctly, we have to use + // g.iPrevTarget which is set to whatever g.iTarget has been before its last change. + flags = g.iPrevTarget; + + // We reset g.iPrevTarget as it has fulfilled its purpose for this whisper-action. It'll be set + // accordingly once the client whispers for the next time. + g.iPrevTarget = 0; } if (g.s.lmLoopMode == Settings::Server) diff -Nru mumble-1.3.0/src/mumble/AudioInput.h mumble-1.3.1-rc1/src/mumble/AudioInput.h --- mumble-1.3.0/src/mumble/AudioInput.h 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/AudioInput.h 2020-04-11 07:27:44.000000000 +0000 @@ -138,7 +138,7 @@ int iBufferedFrames; QList qlFrames; - void flushCheck(const QByteArray &, bool terminator); + void flushCheck(const QByteArray &, bool terminator, int voiceTargetID); void initializeMixer(); diff -Nru mumble-1.3.0/src/mumble/AudioOutput.ui mumble-1.3.1-rc1/src/mumble/AudioOutput.ui --- mumble-1.3.0/src/mumble/AudioOutput.ui 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/AudioOutput.ui 2020-04-11 07:27:44.000000000 +0000 @@ -383,10 +383,10 @@ If checked Mumble lowers the volume of other users while you talk if you have the "Priority Speaker" status. - <b>Attenuate other users while talking as Priority Speaker.</b><br />Mumble supports decreasing the volume of other users while you talk as the <i>Priority Speaker</i> to avoid getting disturbed. Checking this checkbox will enable this feature. + <b>Attenuate other users while talking as Priority Speaker</b><br />Mumble supports decreasing the volume of other users while you talk as the <i>Priority Speaker</i> to avoid getting disturbed. Checking this checkbox will enable this feature. - Attenuate other users while talking as Priority Speaker. + Attenuate other users while talking as Priority Speaker diff -Nru mumble-1.3.0/src/mumble/ConnectDialog.cpp mumble-1.3.1-rc1/src/mumble/ConnectDialog.cpp --- mumble-1.3.0/src/mumble/ConnectDialog.cpp 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/ConnectDialog.cpp 2020-04-11 07:27:44.000000000 +0000 @@ -1155,12 +1155,16 @@ } void ConnectDialog::OnSortChanged(int logicalIndex, Qt::SortOrder) { - if (logicalIndex == 2) - foreach(ServerItem *si, qlItems) - if (si->uiPing && (si->uiPing != si->uiPingSort)) { - si->uiPingSort = si->uiPing; - si->setDatas(); - } + if (logicalIndex != 2) { + return; + } + + foreach(ServerItem *si, qlItems) { + if (si->uiPing && (si->uiPing != si->uiPingSort)) { + si->uiPingSort = si->uiPing; + si->setDatas(); + } + } } void ConnectDialog::on_qaFavoriteAdd_triggered() { diff -Nru mumble-1.3.0/src/mumble/DBus.cpp mumble-1.3.1-rc1/src/mumble/DBus.cpp --- mumble-1.3.0/src/mumble/DBus.cpp 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/DBus.cpp 2020-04-11 07:27:44.000000000 +0000 @@ -58,7 +58,13 @@ path.prepend(c->qsName); c = c->cParent; } - u.setPath(path.join(QLatin1String("/"))); + QString fullpath = path.join(QLatin1String("/")); + // Make sure fullpath starts with a slash for non-empty paths. Setting + // a path without a leading slash clears the whole QUrl. + if (!fullpath.isEmpty()) { + fullpath.prepend(QLatin1String("/")); + } + u.setPath(fullpath); QDBusConnection::sessionBus().send(msg.createReply(QString::fromLatin1(u.toEncoded()))); } diff -Nru mumble-1.3.0/src/mumble/Global.h mumble-1.3.1-rc1/src/mumble/Global.h --- mumble-1.3.0/src/mumble/Global.h 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/Global.h 2020-04-11 07:27:44.000000000 +0000 @@ -61,7 +61,11 @@ int iPushToTalk; Timer tDoublePush; quint64 uiDoublePush; + /// Holds the current VoiceTarget ID to send audio to int iTarget; + /// Holds the value of iTarget before its last change until the current + /// audio-stream ends (and it has a value > 0). See the comment in + /// AudioInput::flushCheck for further details on this. int iPrevTarget; bool bPushToMute; bool bCenterPosition; diff -Nru mumble-1.3.0/src/mumble/main.cpp mumble-1.3.1-rc1/src/mumble/main.cpp --- mumble-1.3.0/src/mumble/main.cpp 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/main.cpp 2020-04-11 07:27:44.000000000 +0000 @@ -373,7 +373,7 @@ #ifdef Q_OS_MAC if (os_lang) { - qWarning("Using Mac OS X system langauge as locale name"); + qWarning("Using Mac OS X system language as locale name"); qsSystemLocale = QLatin1String(os_lang); } #endif @@ -430,9 +430,6 @@ g.bc = new BonjourClient(); #endif - //TODO: This already loads up the DLL and does some initial hooking, even - // when the OL is disabled. This should either not be done (object instantiation) - // or the dll loading and preparation be delayed to first use. g.o = new Overlay(); g.o->setActive(g.s.os.bEnable); diff -Nru mumble-1.3.0/src/mumble/MainWindow.cpp mumble-1.3.1-rc1/src/mumble/MainWindow.cpp --- mumble-1.3.0/src/mumble/MainWindow.cpp 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/MainWindow.cpp 2020-04-11 07:27:44.000000000 +0000 @@ -2783,7 +2783,7 @@ } void MainWindow::on_gsSendClipboardTextMessage_triggered(bool down, QVariant) { - if (!down) { + if (!down || (QApplication::clipboard()->text().isEmpty())) { return; } @@ -3077,24 +3077,26 @@ QDesktopWidget dw; - QRect qr = dw.screenGeometry(p); + if (dw.screenNumber(p) >= 0) { + QRect qr = dw.screenGeometry(p); - if (p.y() < (qr.height() / 2)) - top = true; + if (p.y() < (qr.height() / 2)) + top = true; - qmTray->clear(); - if (top) { - qmTray->addAction(qaQuit); - qmTray->addAction(qaShow); - qmTray->addSeparator(); - qmTray->addAction(qaAudioDeaf); - qmTray->addAction(qaAudioMute); - } else { - qmTray->addAction(qaAudioMute); - qmTray->addAction(qaAudioDeaf); - qmTray->addSeparator(); - qmTray->addAction(qaShow); - qmTray->addAction(qaQuit); + qmTray->clear(); + if (top) { + qmTray->addAction(qaQuit); + qmTray->addAction(qaShow); + qmTray->addSeparator(); + qmTray->addAction(qaAudioDeaf); + qmTray->addAction(qaAudioMute); + } else { + qmTray->addAction(qaAudioMute); + qmTray->addAction(qaAudioDeaf); + qmTray->addSeparator(); + qmTray->addAction(qaShow); + qmTray->addAction(qaQuit); + } } } diff -Nru mumble-1.3.0/src/mumble/ManualPlugin.cpp mumble-1.3.1-rc1/src/mumble/ManualPlugin.cpp --- mumble-1.3.0/src/mumble/ManualPlugin.cpp 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/ManualPlugin.cpp 2020-04-11 07:27:44.000000000 +0000 @@ -25,9 +25,12 @@ static bool bLinkable = false; static bool bActive = true; -static int iAzimuth = 0; +static int iAzimuth = 180; static int iElevation = 0; +static const QString defaultContext = QString::fromLatin1("Mumble"); +static const QString defaultIdentity = QString::fromLatin1("Agent47"); + static struct { float avatar_pos[3]; float avatar_front[3]; @@ -48,7 +51,16 @@ qgvPosition->viewport()->installEventFilter(this); qgvPosition->scale(1.0f, 1.0f); qgsScene = new QGraphicsScene(QRectF(-5.0f, -5.0f, 10.0f, 10.0f), this); - qgiPosition = qgsScene->addEllipse(QRectF(-0.5f, -0.5f, 1.0f, 1.0f), QApplication::palette().text().color(), QBrush(Qt::red)); + + const float indicatorDiameter = 4.0f; + QPainterPath indicator; + // The center of the indicator's circle will represent the current position + indicator.addEllipse(QRectF(-indicatorDiameter / 2, -indicatorDiameter / 2, indicatorDiameter, indicatorDiameter)); + // A line will indicate the indicator's orientation (azimuth) + indicator.moveTo(0, indicatorDiameter / 2); + indicator.lineTo(0, indicatorDiameter); + + qgiPosition = qgsScene->addPath(indicator); qgvPosition->setScene(qgsScene); qgvPosition->fitInView(-5.0f, -5.0f, 10.0f, 10.0f, Qt::KeepAspectRatio); @@ -67,6 +79,14 @@ qsbAzimuth->setValue(iAzimuth); qsbElevation->setValue(iElevation); updateTopAndFront(iAzimuth, iElevation); + + // Set context and identity to default values in order to + // a) make positional audio work out of the box (needs a context) + // b) make the user aware of what each field might contain + qleContext->setText(defaultContext); + qleIdentity->setText(defaultIdentity); + my.context = defaultContext.toStdString(); + my.identity = defaultIdentity.toStdWString(); } bool Manual::eventFilter(QObject *obj, QEvent *evt) { @@ -124,8 +144,8 @@ } void Manual::on_qsbAzimuth_valueChanged(int i) { - if (i > 180) - qdAzimuth->setValue(-360 + i); + if (i > 360) + qdAzimuth->setValue(i % 360); else qdAzimuth->setValue(i); @@ -185,6 +205,8 @@ iAzimuth = azimuth; iElevation = elevation; + qgiPosition->setRotation(azimuth); + double azim = azimuth * M_PI / 180.; double elev = elevation * M_PI / 180.; diff -Nru mumble-1.3.0/src/mumble/ManualPlugin.ui mumble-1.3.1-rc1/src/mumble/ManualPlugin.ui --- mumble-1.3.0/src/mumble/ManualPlugin.ui 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/ManualPlugin.ui 2020-04-11 07:27:44.000000000 +0000 @@ -65,6 +65,9 @@ 100.000000000000000 + + QPainter::Antialiasing|QPainter::TextAntialiasing + @@ -142,6 +145,16 @@ Heading + + + + ° + + + 360 + + + @@ -158,8 +171,8 @@ - - + + -180 @@ -169,6 +182,12 @@ 30 + + 90 + + + 90 + true @@ -180,6 +199,19 @@ + + + + ° + + + -90 + + + 90 + + + @@ -196,23 +228,17 @@ - - + + - -180 + 0 - 180 + 360 30 - - 90 - - - 90 - true @@ -224,29 +250,6 @@ - - - - ° - - - 360 - - - - - - - ° - - - -90 - - - 90 - - - @@ -317,24 +320,27 @@ State - - - + + + + + true + - Linked + Link true - true + false - - + + - Activated + Activate true @@ -344,16 +350,16 @@ - - - - Unhinge - - - + + + + Unhinge + + + @@ -366,6 +372,9 @@ QDialogButtonBox::Close|QDialogButtonBox::Reset + + false + diff -Nru mumble-1.3.0/src/mumble/Messages.cpp mumble-1.3.1-rc1/src/mumble/Messages.cpp --- mumble-1.3.0/src/mumble/Messages.cpp 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/Messages.cpp 2020-04-11 07:27:44.000000000 +0000 @@ -40,14 +40,17 @@ #define VICTIM_INIT \ ClientUser *pDst=ClientUser::get(msg.session()); \ - if (! pDst) { \ + if (!pDst) { \ qWarning("MainWindow: Message for nonexistent victim %d.", msg.session()); \ return; \ } #define SELF_INIT \ - ClientUser *pSelf = ClientUser::get(g.uiSession); - + ClientUser *pSelf = ClientUser::get(g.uiSession); \ + if (!pSelf) { \ + qWarning("MainWindow: Received message outside of session (sid %d).", g.uiSession); \ + return; \ + } void MainWindow::msgAuthenticate(const MumbleProto::Authenticate &) { } @@ -263,8 +266,7 @@ void MainWindow::msgUserState(const MumbleProto::UserState &msg) { ACTOR_INIT; - SELF_INIT; - + ClientUser* pSelf = ClientUser::get(g.uiSession); ClientUser *pDst = ClientUser::get(msg.session()); Channel *channel = NULL; @@ -696,7 +698,11 @@ g.db->setChannelFiltered(sh->qbaDigest, c->iId, false); c->bFiltered = false; } - pmModel->removeChannel(c); + if (!pmModel->removeChannel(c, true)) { + g.l->log(Log::CriticalError, tr("Protocol violation. Server sent remove for occupied channel.")); + g.sh->disconnect(); + return; + } } } diff -Nru mumble-1.3.0/src/mumble/mumble_dll.rc mumble-1.3.1-rc1/src/mumble/mumble_dll.rc --- mumble-1.3.0/src/mumble/mumble_dll.rc 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/mumble_dll.rc 2020-04-11 07:27:44.000000000 +0000 @@ -18,8 +18,8 @@ #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,0,0 - PRODUCTVERSION 1,3,0,0 + FILEVERSION 1,3,1,0 + PRODUCTVERSION 1,3,1,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS (VER_DEBUG|VER_RELEASE) FILEOS VOS_NT_WINDOWS32 @@ -32,9 +32,9 @@ BEGIN VALUE "CompanyName", "The Mumble Developers" VALUE "FileDescription", "Mumble - Low-latency VoIP client" - VALUE "FileVersion", "1.3.0" - VALUE "ProductVersion", "1.3.0" - VALUE "LegalCopyright", "Copyright (c) 2005-2019 The Mumble Developers" + VALUE "FileVersion", "1.3.1" + VALUE "ProductVersion", "1.3.1" + VALUE "LegalCopyright", "Copyright (c) 2005-2020 The Mumble Developers" VALUE "OriginalFilename", "mumble_app.dll" VALUE "ProductName", "Mumble" #ifdef SNAPSHOT_BUILD diff -Nru mumble-1.3.0/src/mumble/mumble_en.ts mumble-1.3.1-rc1/src/mumble/mumble_en.ts --- mumble-1.3.0/src/mumble/mumble_en.ts 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/mumble_en.ts 2020-04-11 07:27:44.000000000 +0000 @@ -6903,18 +6903,15 @@ - - Linked + Unhinge - - Activated + Link - - Unhinge + Activate @@ -7898,8 +7895,7 @@ PortAudioSystem - - Default Device + Default device diff -Nru mumble-1.3.0/src/mumble/mumble.plist mumble-1.3.1-rc1/src/mumble/mumble.plist --- mumble-1.3.0/src/mumble/mumble.plist 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/mumble.plist 2020-04-11 07:27:44.000000000 +0000 @@ -26,7 +26,7 @@ CFBundleVersion - 1.3.0 + 1.3.1 NSHumanReadableCopyright Copyright (c) 2005-2019 The Mumble Developers NSPrincipalClass diff -Nru mumble-1.3.0/src/mumble/mumble.rc mumble-1.3.1-rc1/src/mumble/mumble.rc --- mumble-1.3.0/src/mumble/mumble.rc 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/mumble.rc 2020-04-11 07:27:44.000000000 +0000 @@ -20,8 +20,8 @@ #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,0,0 - PRODUCTVERSION 1,3,0,0 + FILEVERSION 1,3,1,0 + PRODUCTVERSION 1,3,1,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS (VER_DEBUG|VER_RELEASE) FILEOS VOS_NT_WINDOWS32 @@ -34,9 +34,9 @@ BEGIN VALUE "CompanyName", "The Mumble Developers" VALUE "FileDescription", "Mumble - Low-latency VoIP client" - VALUE "FileVersion", "1.3.0" - VALUE "ProductVersion", "1.3.0" - VALUE "LegalCopyright", "Copyright (c) 2005-2019 The Mumble Developers" + VALUE "FileVersion", "1.3.1" + VALUE "ProductVersion", "1.3.1" + VALUE "LegalCopyright", "Copyright (c) 2005-2020 The Mumble Developers" VALUE "OriginalFilename", "mumble.exe" VALUE "ProductName", "Mumble" #ifdef SNAPSHOT_BUILD diff -Nru mumble-1.3.0/src/mumble/Overlay.cpp mumble-1.3.1-rc1/src/mumble/Overlay.cpp --- mumble-1.3.0/src/mumble/Overlay.cpp 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/Overlay.cpp 2020-04-11 07:27:44.000000000 +0000 @@ -175,9 +175,42 @@ Overlay::Overlay() : QObject() { d = NULL; - platformInit(); - forceSettings(); + m_initialized = false; + qlsServer = NULL; + + QMetaObject::connectSlotsByName(this); +} + +Overlay::~Overlay() { + setActive(false); + if (d) { + delete d; + } + + // Need to be deleted first, since destructor references lingering QLocalSockets + foreach(OverlayClient *oc, qlClients) { + // As we're the one closing the connection, we do not need to be + // notified of disconnects. This is important because on disconnect we + // also remove (and 'delete') the overlay client. + disconnect(oc->qlsSocket, SIGNAL(disconnected()), this, SLOT(disconnected())); + disconnect(oc->qlsSocket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(error(QLocalSocket::LocalSocketError))); + delete oc; + } +} + +void Overlay::setActive(bool act) { + if (!m_initialized) { + platformInit(); + forceSettings(); + + m_initialized = true; + } + + setActiveInternal(act); +} + +void Overlay::createPipe() { qlsServer = new QLocalServer(this); QString pipepath; #ifdef Q_OS_WIN @@ -209,31 +242,12 @@ qWarning() << "Overlay: Listening on" << qlsServer->fullServerName(); connect(qlsServer, SIGNAL(newConnection()), this, SLOT(newConnection())); } - - QMetaObject::connectSlotsByName(this); -} - -Overlay::~Overlay() { - setActive(false); - delete d; - - // Need to be deleted first, since destructor references lingering QLocalSockets - foreach(OverlayClient *oc, qlClients) - { - // As we're the one closing the connection, we do not need to be - // notified of disconnects. This is important because on disconnect we - // also remove (and 'delete') the overlay client. - disconnect(oc->qlsSocket, SIGNAL(disconnected()), this, SLOT(disconnected())); - disconnect(oc->qlsSocket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(error(QLocalSocket::LocalSocketError))); - delete oc; - } } void Overlay::newConnection() { - while (true) { + while (qlsServer && qlsServer->hasPendingConnections()) { QLocalSocket *qls = qlsServer->nextPendingConnection(); - if (! qls) - break; + OverlayClient *oc = new OverlayClient(qls, this); qlClients << oc; diff -Nru mumble-1.3.0/src/mumble/Overlay.h mumble-1.3.1-rc1/src/mumble/Overlay.h --- mumble-1.3.0/src/mumble/Overlay.h 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/Overlay.h 2020-04-11 07:27:44.000000000 +0000 @@ -83,8 +83,14 @@ QSet qsQueried; QSet qsQuery; + /// A flag indicating if the platformInit has been called already + bool m_initialized; + // These 2 functions (among others) are implemented by the system-specific backend void platformInit(); + void setActiveInternal(bool act); + + void createPipe(); QMap qmOverlayHash; QLocalServer *qlsServer; diff -Nru mumble-1.3.0/src/mumble/Overlay_macx.mm mumble-1.3.1-rc1/src/mumble/Overlay_macx.mm --- mumble-1.3.0/src/mumble/Overlay_macx.mm 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/Overlay_macx.mm 2020-04-11 07:27:44.000000000 +0000 @@ -163,8 +163,11 @@ d = new OverlayPrivateMac(this); } -void Overlay::setActive(bool act) { - static_cast(d)->setActive(act); +void Overlay::setActiveInternal(bool act) { + if (d) { + /// Only act if the private instance has been created already + static_cast(d)->setActive(act); + } } bool OverlayConfig::supportsInstallableOverlay() { diff -Nru mumble-1.3.0/src/mumble/Overlay_unix.cpp mumble-1.3.1-rc1/src/mumble/Overlay_unix.cpp --- mumble-1.3.0/src/mumble/Overlay_unix.cpp 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/Overlay_unix.cpp 2020-04-11 07:27:44.000000000 +0000 @@ -12,7 +12,7 @@ d = NULL; } -void Overlay::setActive(bool) { +void Overlay::setActiveInternal(bool) { } bool OverlayConfig::supportsInstallableOverlay() { diff -Nru mumble-1.3.0/src/mumble/Overlay_win.cpp mumble-1.3.1-rc1/src/mumble/Overlay_win.cpp --- mumble-1.3.0/src/mumble/Overlay_win.cpp 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/Overlay_win.cpp 2020-04-11 07:27:44.000000000 +0000 @@ -320,8 +320,11 @@ d = new OverlayPrivateWin(this); } -void Overlay::setActive(bool act) { - static_cast(d)->setActive(act); +void Overlay::setActiveInternal(bool act) { + if (d) { + // Only act if the private instance has been created already + static_cast(d)->setActive(act); + } } bool OverlayConfig::supportsInstallableOverlay() { diff -Nru mumble-1.3.0/src/mumble/PulseAudio.cpp mumble-1.3.1-rc1/src/mumble/PulseAudio.cpp --- mumble-1.3.0/src/mumble/PulseAudio.cpp 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/PulseAudio.cpp 2020-04-11 07:27:44.000000000 +0000 @@ -535,13 +535,7 @@ AudioOutputPtr ao = g.ao; PulseAudioOutput *pao = dynamic_cast(ao.get()); - unsigned char buffer[bytes]; - if (! pao) { - // Transitioning, but most likely transitions back, so just zero. - memset(buffer, 0, bytes); - pa_stream_write(s, buffer, bytes, NULL, 0, PA_SEEK_RELATIVE); - pas->wakeup(); return; } @@ -606,6 +600,7 @@ const unsigned int samples = static_cast(bytes) / iSampleSize; bool oldAttenuation = pas->bAttenuating; + unsigned char buffer[bytes]; // do we have some mixed output? if (pao->mix(buffer, samples)) { // attenuate if instructed to or it's in settings diff -Nru mumble-1.3.0/src/mumble/ServerHandler.cpp mumble-1.3.1-rc1/src/mumble/ServerHandler.cpp --- mumble-1.3.0/src/mumble/ServerHandler.cpp 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/ServerHandler.cpp 2020-04-11 07:27:44.000000000 +0000 @@ -155,7 +155,7 @@ quint16 senderPort; qusUdp->readDatagram(encrypted, qMin(2048U, buflen), &senderAddr, &senderPort); - if (!(HostAddress(senderAddr) == HostAddress(qhaRemote)) || (senderPort != usPort)) + if (!(HostAddress(senderAddr) == HostAddress(qhaRemote)) || (senderPort != usResolvedPort)) continue; ConnectionPtr connection(cConnection); @@ -243,7 +243,7 @@ QApplication::postEvent(this, new ServerHandlerMessageEvent(qba, MessageHandler::UDPTunnel, true)); } else { connection->csCrypt.encrypt(reinterpret_cast(data), crypto, len); - qusUdp->writeDatagram(reinterpret_cast(crypto), len + 4, qhaRemote, usPort); + qusUdp->writeDatagram(reinterpret_cast(crypto), len + 4, qhaRemote, usResolvedPort); } } @@ -698,6 +698,7 @@ qhaRemote = connection->peerAddress(); qhaLocal = connection->localAddress(); + usResolvedPort = connection->peerPort(); if (qhaLocal.isNull()) { qFatal("ServerHandler: qhaLocal is unexpectedly a null addr"); } diff -Nru mumble-1.3.0/src/mumble/ServerHandler.h mumble-1.3.1-rc1/src/mumble/ServerHandler.h --- mumble-1.3.0/src/mumble/ServerHandler.h 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/ServerHandler.h 2020-04-11 07:27:44.000000000 +0000 @@ -63,6 +63,7 @@ QString qsUserName; QString qsPassword; unsigned short usPort; + unsigned short usResolvedPort; bool bUdp; bool bStrong; diff -Nru mumble-1.3.0/src/mumble/Settings.cpp mumble-1.3.1-rc1/src/mumble/Settings.cpp --- mumble-1.3.0/src/mumble/Settings.cpp 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/Settings.cpp 2020-04-11 07:27:44.000000000 +0000 @@ -95,7 +95,7 @@ const QString Settings::cqsDefaultPushClickOff = QLatin1String(":/off.ogg"); OverlaySettings::OverlaySettings() { - bEnable = true; + bEnable = false; fX = 1.0f; fY = 0.0f; @@ -318,7 +318,7 @@ qsJackClientName = QLatin1String("mumble"); qsJackAudioOutput = QLatin1String("1"); - bJackStartServer = true; + bJackStartServer = false; bJackAutoConnect = true; bEcho = false; diff -Nru mumble-1.3.0/src/mumble/UserLocalVolumeDialog.ui mumble-1.3.1-rc1/src/mumble/UserLocalVolumeDialog.ui --- mumble-1.3.0/src/mumble/UserLocalVolumeDialog.ui 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/UserLocalVolumeDialog.ui 2020-04-11 07:27:44.000000000 +0000 @@ -2,10 +2,24 @@ UserLocalVolumeDialog + + + 0 + 0 + 500 + 224 + + 500 - 0 + 224 + + + + + 16777215 + 224 diff -Nru mumble-1.3.0/src/mumble/UserModel.cpp mumble-1.3.1-rc1/src/mumble/UserModel.cpp --- mumble-1.3.0/src/mumble/UserModel.cpp 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/UserModel.cpp 2020-04-11 07:27:44.000000000 +0000 @@ -352,6 +352,14 @@ switch (role) { case Qt::DecorationRole: if (idx.column() == 0) { + if (p == pSelf && p->bSelfMute) { + // This is a workaround for a bug that can lead to the user having muted him/herself but + // the talking icon is stuck at qiTalkingOn for some reason. + // Until someone figures out how to fix the root of the problem, we'll have this workaround + // to cure the symptoms of the bug. + return qiTalkingOff; + } + switch (p->tsState) { case Settings::Talking: return qiTalkingOn; @@ -1156,12 +1164,12 @@ return c; } -void UserModel::removeChannel(Channel *c) { - ModelItem *item, *i; +bool UserModel::removeChannel(Channel *c, const bool onlyIfUnoccupied) { + const ModelItem *item = ModelItem::c_qhChannels.value(c); + + if (onlyIfUnoccupied && item->iUsers !=0) return false; // Checks full hierarchy - item=ModelItem::c_qhChannels.value(c); - - foreach(i, item->qlChildren) { + foreach(const ModelItem *i, item->qlChildren) { if (i->pUser) removeUser(i->pUser); else @@ -1171,7 +1179,7 @@ Channel *p = c->cParent; if (! p) - return; + return true; ModelItem *citem = ModelItem::c_qhChannels.value(p); @@ -1187,6 +1195,7 @@ delete item; delete c; + return true; } void UserModel::moveChannel(Channel *c, Channel *p) { diff -Nru mumble-1.3.0/src/mumble/UserModel.h mumble-1.3.1-rc1/src/mumble/UserModel.h --- mumble-1.3.0/src/mumble/UserModel.h 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/UserModel.h 2020-04-11 07:27:44.000000000 +0000 @@ -30,6 +30,7 @@ ModelItem *parent; QList qlChildren; QList qlHiddenChildren; + /// Number of users in this channel (recursive) int iUsers; static QHash c_qhChannels; @@ -126,7 +127,7 @@ void setCommentHash(Channel *c, const QByteArray &hash); void removeUser(ClientUser *p); - void removeChannel(Channel *c); + bool removeChannel(Channel *c, const bool onlyIfUnoccupied = false); void linkChannels(Channel *c, QList links); void unlinkChannels(Channel *c, QList links); diff -Nru mumble-1.3.0/src/mumble/WebFetch.cpp mumble-1.3.1-rc1/src/mumble/WebFetch.cpp --- mumble-1.3.0/src/mumble/WebFetch.cpp 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble/WebFetch.cpp 2020-04-11 07:27:44.000000000 +0000 @@ -79,7 +79,12 @@ emit fetched(a, url, headers); deleteLater(); - } else if (url.host() == prefixedServiceHost()) { + } else if (url.host() == prefixedServiceHost() && url.host() != serviceHost()) { + // We have tried to fetch from a local service domain (e.g. de-update.mumble.info) + // which has failed, so naturally we want to try the non-local one (update.mumble.info) + // as well as maybe that one will work. + // This of course only makes sense, if prefixedServiceHost() and serviceHost() are in fact + // different hosts. url.setHost(serviceHost()); qnr = Network::get(url); diff -Nru mumble-1.3.0/src/mumble.pri mumble-1.3.1-rc1/src/mumble.pri --- mumble-1.3.0/src/mumble.pri 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/mumble.pri 2020-04-11 07:27:44.000000000 +0000 @@ -8,7 +8,7 @@ include(../qmake/rcc.pri) include(../qmake/pkgconfig.pri) -VERSION = 1.3.0 +VERSION = 1.3.1 DIST = mumble.pri Message.h PacketDataStream.h CryptState.h Timer.h Version.h OSInfo.h SSL.h CONFIG += qt thread debug_and_release warn_on DEFINES *= MUMBLE_VERSION_STRING=$$VERSION diff -Nru mumble-1.3.0/src/murmur/Messages.cpp mumble-1.3.1-rc1/src/murmur/Messages.cpp --- mumble-1.3.0/src/murmur/Messages.cpp 2019-09-14 22:10:20.000000000 +0000 +++ mumble-1.3.1-rc1/src/murmur/Messages.cpp 2020-04-11 07:27:45.000000000 +0000 @@ -1325,11 +1325,12 @@ group->add_remove(id); } } - if (pg) + if (pg) { foreach(int id, pg->members()) { qsId.insert(id); group->add_inherited_members(id); } + } } sendMessage(uSource, msg); diff -Nru mumble-1.3.0/src/murmur/MurmurGRPCImpl.cpp mumble-1.3.1-rc1/src/murmur/MurmurGRPCImpl.cpp --- mumble-1.3.0/src/murmur/MurmurGRPCImpl.cpp 2019-09-14 22:10:20.000000000 +0000 +++ mumble-1.3.1-rc1/src/murmur/MurmurGRPCImpl.cpp 2020-04-11 07:27:45.000000000 +0000 @@ -18,6 +18,11 @@ #include "ServerUser.h" #include "Server.h" #include "Channel.h" +#include "Utils.h" + +#include + +#include #include "MurmurRPC.proto.Wrapper.cpp" @@ -139,10 +144,22 @@ m_completionQueue = builder.AddCompletionQueue(); m_server = builder.BuildAndStart(); meta->connectListener(this); + m_isRunning = true; start(); } MurmurRPCImpl::~MurmurRPCImpl() { + void *ignored_tag; + bool ignored_ok; + m_isRunning = false; + m_server->Shutdown(std::chrono::system_clock::now()); + m_completionQueue->Shutdown(); + while (m_completionQueue->Next(&ignored_tag, &ignored_ok)) { + if (ignored_tag) { + auto op = static_cast *>(ignored_tag); + delete op; + } + } } // ToRPC/FromRPC methods convert data to/from grpc protocol buffer messages. @@ -1102,7 +1119,7 @@ void MurmurRPCImpl::run() { MurmurRPC::Wrapper::V1_Init(this, &m_V1Service); - while (true) { + while (m_isRunning) { void *tag; bool ok; if (!m_completionQueue->Next(&tag, &ok)) { diff -Nru mumble-1.3.0/src/murmur/MurmurGRPCImpl.h mumble-1.3.1-rc1/src/murmur/MurmurGRPCImpl.h --- mumble-1.3.0/src/murmur/MurmurGRPCImpl.h 2019-09-14 22:10:20.000000000 +0000 +++ mumble-1.3.1-rc1/src/murmur/MurmurGRPCImpl.h 2020-04-11 07:27:45.000000000 +0000 @@ -36,6 +36,7 @@ class MurmurRPCImpl : public QThread { Q_OBJECT; std::unique_ptr m_server; + volatile bool m_isRunning; protected: void customEvent(QEvent *evt); public: diff -Nru mumble-1.3.0/src/murmur/Murmur.ice mumble-1.3.1-rc1/src/murmur/Murmur.ice --- mumble-1.3.0/src/murmur/Murmur.ice 2019-09-14 22:10:20.000000000 +0000 +++ mumble-1.3.1-rc1/src/murmur/Murmur.ice 2020-04-11 07:27:45.000000000 +0000 @@ -223,7 +223,7 @@ sequence TreeList; enum ChannelInfo { ChannelDescription, ChannelPosition }; - enum UserInfo { UserName, UserEmail, UserComment, UserHash, UserPassword, UserLastActive }; + enum UserInfo { UserName, UserEmail, UserComment, UserHash, UserPassword, UserLastActive, UserKDFIterations }; dictionary UserMap; dictionary ChannelMap; diff -Nru mumble-1.3.0/src/murmur/murmur.plist mumble-1.3.1-rc1/src/murmur/murmur.plist --- mumble-1.3.0/src/murmur/murmur.plist 2019-09-14 22:10:20.000000000 +0000 +++ mumble-1.3.1-rc1/src/murmur/murmur.plist 2020-04-11 07:27:45.000000000 +0000 @@ -13,7 +13,7 @@ CFBundleSignature MMUR CFBundleVersion - 1.3.0 + 1.3.1 NSHumanReadableCopyright Copyright (c) 2005-2019 The Mumble Developers diff -Nru mumble-1.3.0/src/murmur/murmur.rc mumble-1.3.1-rc1/src/murmur/murmur.rc --- mumble-1.3.0/src/murmur/murmur.rc 2019-09-14 22:10:20.000000000 +0000 +++ mumble-1.3.1-rc1/src/murmur/murmur.rc 2020-04-11 07:27:45.000000000 +0000 @@ -20,8 +20,8 @@ #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,0,0 - PRODUCTVERSION 1,3,0,0 + FILEVERSION 1,3,1,0 + PRODUCTVERSION 1,3,1,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS (VER_DEBUG|VER_RELEASE) FILEOS VOS_NT_WINDOWS32 @@ -34,9 +34,9 @@ BEGIN VALUE "CompanyName", "The Mumble Developers" VALUE "FileDescription", "Murmur - Low-latency VoIP server" - VALUE "FileVersion", "1.3.0" - VALUE "ProductVersion", "1.3.0" - VALUE "LegalCopyright", "Copyright (c) 2005-2019 The Mumble Developers" + VALUE "FileVersion", "1.3.1" + VALUE "ProductVersion", "1.3.1" + VALUE "LegalCopyright", "Copyright (c) 2005-2020 The Mumble Developers" VALUE "OriginalFilename", "murmur.exe" VALUE "ProductName", "Mumble" #ifdef SNAPSHOT_BUILD diff -Nru mumble-1.3.0/src/murmur/Server.cpp mumble-1.3.1-rc1/src/murmur/Server.cpp --- mumble-1.3.0/src/murmur/Server.cpp 2019-09-14 22:10:20.000000000 +0000 +++ mumble-1.3.1-rc1/src/murmur/Server.cpp 2020-04-11 07:27:45.000000000 +0000 @@ -1420,6 +1420,19 @@ } void Server::connectionClosed(QAbstractSocket::SocketError err, const QString &reason) { + if (reason.contains(QLatin1String("140E0197"))) { + // A severe bug was introduced in qt/qtbase@93a803a6de27d9eb57931c431b5f3d074914f693. + // q_SSL_shutdown() causes Qt to emit "error()" from unrelated QSslSocket(s), in addition to the correct one. + // The issue causes this function to disconnect random authenticated clients. + // + // The workaround consists in ignoring a specific OpenSSL error: + // "Error while reading: error:140E0197:SSL routines:SSL_shutdown:shutdown while in init [20]" + // + // Definitely not ideal, but it fixes a critical vulnerability. + qWarning("Ignored OpenSSL error 140E0197 for %p", sender()); + return; + } + Connection *c = qobject_cast(sender()); if (! c) return; @@ -1630,7 +1643,7 @@ } Channel *target = dest; - while (target->cParent && ! hasPermission(static_cast(p), target, ChanACL::Enter)) + while (target->cParent && (! hasPermission(static_cast(p), target, ChanACL::Enter) || isChannelFull(target, static_cast(p)))) target = target->cParent; MumbleProto::UserState mpus; diff -Nru mumble-1.3.0/src/murmur/ServerUser.cpp mumble-1.3.1-rc1/src/murmur/ServerUser.cpp --- mumble-1.3.0/src/murmur/ServerUser.cpp 2019-09-14 22:10:20.000000000 +0000 +++ mumble-1.3.1-rc1/src/murmur/ServerUser.cpp 2020-04-11 07:27:45.000000000 +0000 @@ -112,42 +112,80 @@ return static_cast((sum * 1000000ULL) / elapsed); } -inline static QTime now() { - return QTime::currentTime(); -} - -inline static int millisecondsBetween(const QTime &start, const QTime &end) { - return start.msecsTo(end); -} - -// Rate limiting: burst up to 5, 1 message per sec limit over longer time -LeakyBucket::LeakyBucket(unsigned int tokensPerSec, unsigned int maxTokens) : tokensPerSec(tokensPerSec), maxTokens(maxTokens), currentTokens(0) { - lastUpdate = now(); +LeakyBucket::LeakyBucket(unsigned int tokensPerSec, unsigned int maxTokens) + : m_tokensPerSec(tokensPerSec), + m_maxTokens(maxTokens), + m_currentTokens(0), + m_timer() { + m_timer.start(); + + if (!QElapsedTimer::isMonotonic()) { + qFatal("Non-monotonic clocks are not reliable enough and lead to issues as " + "https://github.com/mumble-voip/mumble/issues/3985. " + "This is a serious issue and should be reported!"); + } } bool LeakyBucket::ratelimit(int tokens) { // First remove tokens we leaked over time - const QTime tnow = now(); - const long ms = millisecondsBetween(lastUpdate, tnow); + const qint64 elapsedMillis = m_timer.elapsed(); - const long drainTokens = (ms * tokensPerSec) / 1000; + if (elapsedMillis < 0) { + if (m_timer.isValid()) { + // By definition of a monotinic clock, this shouldn't be possible to happen. + // Thus if it does happen there's somthing going very wrong which is why we + // emit the qFatal which at the state this line here was added, will crash + // the server. But at least that guarantees to give us a report on the crash + // instead of obscure reports about the rate limiter causing all sorts of + // weird issues. + qFatal("ServerUser.cpp: Monotonic timer returned negative elapsed time!"); + + // In case the implementation changes and qFatal no longer crashes the server, + // we'll restart the timer but limit the message. + m_timer.restart(); + return true; + } else { + // For some reason the timer is in an invalid state. This shouldn't happen + // as we start it in the constructor, but in case it does, we log the error + // and reset the timer and the tokens as a fail-safe. We also won't limit + // in this case as a potential limit is based on an invalid timer. That's + // not what we want. + qCritical("ServerUser.cpp: Monotonic timer is invalid!"); + m_timer.restart(); + m_currentTokens = 0; + return false; + } + } + + const qint64 drainTokens = (elapsedMillis * m_tokensPerSec) / 1000; - // Prevent constant starvation due to too many updates + // Only restart the timer if enough time has elapsed so whe drain at least + // a single token. If we were to restart the timer every time, even if the + // interval between the calls to this function is so small that we don't + // drain a token, we can end up in a situation in which we will never drain + // a token even if let's say by the time this function is called the second + // time we would have to drain a single token (over the course of both function + // calls, but each function call individually wouldn't drain a token). if (drainTokens > 0) { - this->lastUpdate = tnow; + m_timer.restart(); + } - this->currentTokens -= drainTokens; - if (this->currentTokens < 0) { - this->currentTokens = 0; - } + // Make sure that m_currentTokens never gets less than 0 by draining + if (static_cast(m_currentTokens) < drainTokens) { + m_currentTokens = 0; + } else { + m_currentTokens -= drainTokens; } - // Then try to add tokens - bool limit = this->currentTokens > ((static_cast(maxTokens)) - tokens); + // Now that the tokens have been updated to reflect the constant drain caused by + // the imaginary leaking bucket, we can check whether the given amount of tokens + // still fit in this imaginary bucket (and thus the corresponding message may pass) + // or if it doesn't (and thus the message will be limited (rejected)) + bool limit = m_currentTokens > ((static_cast(m_maxTokens)) - tokens); // If the bucket is not overflowed, allow message and add tokens if (!limit) { - this->currentTokens += tokens; + m_currentTokens += tokens; } return limit; diff -Nru mumble-1.3.0/src/murmur/ServerUser.h mumble-1.3.1-rc1/src/murmur/ServerUser.h --- mumble-1.3.0/src/murmur/ServerUser.h 2019-09-14 22:10:20.000000000 +0000 +++ mumble-1.3.1-rc1/src/murmur/ServerUser.h 2020-04-11 07:27:45.000000000 +0000 @@ -7,7 +7,7 @@ #define MUMBLE_MURMUR_SERVERUSER_H_ #include -#include +#include #ifdef Q_OS_UNIX #include @@ -56,15 +56,29 @@ class Server; -// Simple algorithm for rate limiting +/// A simple implementation for rate-limiting. +/// See https://en.wikipedia.org/wiki/Leaky_bucket class LeakyBucket { private: - unsigned int tokensPerSec, maxTokens; - long currentTokens; - QTime lastUpdate; + /// The amount of tokens that are drained per second. + /// (The sze of the whole in the bucket) + unsigned int m_tokensPerSec; + /// The maximum amount of tokens that may be encountered. + /// (The capacity of the bucket) + unsigned int m_maxTokens; + /// The amount of tokens currently stored + /// (The amount of whater currently in the bucket) + long m_currentTokens; + /// A timer that is used to measure time intervals. It is essential + /// that this timer uses a monotonic clock (which is why QElapsedTimer is + /// used instead of QTime or QDateTime). + QElapsedTimer m_timer; public: - // Returns true if packets should be dropped + /// @param tokens The amount of tokens that should be added. + /// @returns Whether adding this amount of tokens triggers rate + /// limiting (true means the corresponding packet has to be + /// discared and false means the packet may be processed) bool ratelimit(int tokens); LeakyBucket(unsigned int tokensPerSec, unsigned int maxTokens); diff -Nru mumble-1.3.0/src/SSL.cpp mumble-1.3.1-rc1/src/SSL.cpp --- mumble-1.3.0/src/SSL.cpp 2019-09-14 22:10:19.000000000 +0000 +++ mumble-1.3.1-rc1/src/SSL.cpp 2020-04-11 07:27:44.000000000 +0000 @@ -212,8 +212,10 @@ QSslSocket::setDefaultCaCertificates(ql); #endif // NO_SYSTEM_CA_OVERRIDE -#if QT_VERSION >= 0x040800 // Don't perform on-demand loading of root certificates +#if QT_VERSION >= 0x050500 + QSslSocket::addDefaultCaCertificates(QSslConfiguration::systemCaCertificates()); +#elif QT_VERSION >= 0x040800 QSslSocket::addDefaultCaCertificates(QSslSocket::systemCaCertificates()); #endif diff -Nru mumble-1.3.0/src/Version.h mumble-1.3.1-rc1/src/Version.h --- mumble-1.3.0/src/Version.h 2019-09-14 22:10:59.000000000 +0000 +++ mumble-1.3.1-rc1/src/Version.h 2020-04-11 07:28:53.000000000 +0000 @@ -4,7 +4,7 @@ // Mumble source tree or at . #ifndef MUMBLE_VERSION -#define MUMBLE_VERSION 1.3.0 +#define MUMBLE_VERSION 1.3.1-rc1 #endif #ifndef MUMBLE_VERSION_H_ #define MUMBLE_VERSION_H_ diff -Nru mumble-1.3.0/themes/ClassicTheme.qrc mumble-1.3.1-rc1/themes/ClassicTheme.qrc --- mumble-1.3.0/themes/ClassicTheme.qrc 2019-09-14 22:10:20.000000000 +0000 +++ mumble-1.3.1-rc1/themes/ClassicTheme.qrc 2020-04-11 07:27:45.000000000 +0000 @@ -50,6 +50,7 @@ Classic/tango/actions/format-text-underline.svg Classic/tango/actions/media-record.svg Classic/tango/categories/applications-internet.svg + Classic/tango/places/network-workgroup.svg Classic/tango/emblems/emblem-favorite.svg Classic/tango/mimetypes/image-x-generic.svg Classic/tango/mimetypes/text-html.svg diff -Nru mumble-1.3.0/themes/MumbleTheme.qrc mumble-1.3.1-rc1/themes/MumbleTheme.qrc --- mumble-1.3.0/themes/MumbleTheme.qrc 2019-09-14 22:10:20.000000000 +0000 +++ mumble-1.3.1-rc1/themes/MumbleTheme.qrc 2020-04-11 07:27:45.000000000 +0000 @@ -56,6 +56,7 @@ Mumble/actions/format-text-underline.svg Mumble/actions/media-record.svg Mumble/categories/applications-internet.svg + Classic/tango/places/network-workgroup.svg Mumble/controls/arrow_down.svg Mumble/controls/arrow_down_disabled.svg Mumble/controls/arrow_up.svg