diff --git a/.ci/common/finalize-deb.sh b/.ci/common/finalize-deb.sh index 7770cca33..107dfb9a4 100755 --- a/.ci/common/finalize-deb.sh +++ b/.ci/common/finalize-deb.sh @@ -2,16 +2,19 @@ set -e -cd /build - -# add distribution name to file name -rename "s/_amd64/-${1}_amd64/g" *.deb +cd $2 # show content -dpkg -c *.deb +for i in *.deb ; do + echo Contents of $i: + dpkg -c $i +done # show package information and dependencies -dpkg -I *.deb +for i in *.deb ; do + echo Package information for $i: + dpkg -I $i +done # move to Docker volume -mv -v *.deb /veyon +mv -v *.deb $1 diff --git a/.ci/common/finalize-rpm.sh b/.ci/common/finalize-rpm.sh index cf8f570d2..851a8d003 100755 --- a/.ci/common/finalize-rpm.sh +++ b/.ci/common/finalize-rpm.sh @@ -2,16 +2,19 @@ set -e -cd /build - -# add distribution name to file name -rename ".x86_64" ".${1}.x86_64" *.rpm +cd $2 # show files -rpm -qlp *.rpm +for i in *.rpm ; do + echo Contents of $i: + rpm -qlp $i +done # show dependencies -rpm -qpR *.rpm +for i in *.rpm ; do + echo Package information for $i: + rpm -qpR $i +done # move to Docker volume -mv -v *.rpm /veyon +mv -v *.rpm $1 diff --git a/.ci/common/linux-build.sh b/.ci/common/linux-build.sh index 54f71ab48..a8b308a5b 100755 --- a/.ci/common/linux-build.sh +++ b/.ci/common/linux-build.sh @@ -4,19 +4,26 @@ set -e SRC=$1 BUILD=$2 -CPUS=$(nproc) mkdir -p $BUILD cd $BUILD -cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr $SRC +if [ ! -z "$CI_COMMIT_TAG" ] ; then + BUILD_TYPE="RelWithDebInfo" + LTO="ON" + TRANSLATIONS="ON" +else + BUILD_TYPE="Debug" + LTO="OFF" + TRANSLATIONS="OFF" +fi -echo Building on $CPUS CPUs +cmake -G Ninja -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_INSTALL_PREFIX=/usr -DWITH_LTO=$LTO -DWITH_TRANSLATIONS=$TRANSLATIONS $CMAKE_FLAGS $SRC if [ -z "$3" ] ; then - make -j$CPUS + ninja - fakeroot make package + fakeroot ninja package LIBDIR=$(grep VEYON_LIB_DIR CMakeCache.txt |cut -d "=" -f2) BUILD_PWD=$(pwd) @@ -29,6 +36,6 @@ if [ -z "$3" ] ; then ./cli/veyon-cli help ./cli/veyon-cli about else - make ${@:3} -j$CPUS + fakeroot ninja package fi diff --git a/.ci/common/strip-kitemmodels-sources.sh b/.ci/common/strip-kitemmodels-sources.sh deleted file mode 100755 index 1f1fc4f07..000000000 --- a/.ci/common/strip-kitemmodels-sources.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -cd 3rdparty/kitemmodels && \ -rm -rf autotests \ - docs \ - tests - diff --git a/.ci/common/strip-kldap-sources.sh b/.ci/common/strip-kldap-sources.sh index 03d3ef02f..aa005768e 100755 --- a/.ci/common/strip-kldap-sources.sh +++ b/.ci/common/strip-kldap-sources.sh @@ -1,7 +1,12 @@ #!/bin/sh -cd 3rdparty/kldap && \ +(cd 3rdparty/kldap && \ rm -rf \ autotests \ - kioslave - + kioslave \ + src/widgets) +(cd 3rdparty/kldap-qt-compat && \ +rm -rf \ + autotests \ + kioslave \ + src/widgets) diff --git a/.ci/common/strip-ultravnc-sources.sh b/.ci/common/strip-ultravnc-sources.sh index 5c99d3dab..41ea6c23e 100755 --- a/.ci/common/strip-ultravnc-sources.sh +++ b/.ci/common/strip-ultravnc-sources.sh @@ -2,7 +2,7 @@ cd 3rdparty/ultravnc find -name "*.vcproj" -o -name "*.vcxproj" -o -name "*.vdproj" -o -name "*.sln" | xargs rm -rm -rf avilog translations old vncviewer zipunzip_src libjpeg-turbo-win winvnc/winvnc/res setcad setpasswd lzo* xz* zlib* JavaViewer repeater uvnc* *.iss *.zip +rm -rf avilog translations old vncviewer zipunzip_src libjpeg-turbo-win winvnc/winvnc/res setcad setpasswd lzo* xz* zlib* zstd* JavaViewer repeater uvnc* *.iss *.zip cd DSMPlugin rm -rf MSRC4Plugin TestPlugin cd .. diff --git a/.ci/linux.centos.74/Dockerfile b/.ci/linux.centos.74/Dockerfile deleted file mode 100644 index 256842bfe..000000000 --- a/.ci/linux.centos.74/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM centos:7.4.1708 -MAINTAINER Tobias Junghans - -RUN \ - yum --enablerepo=extras install -y epel-release && \ - yum install -y centos-release-scl && \ - yum install -y git devtoolset-7 make cmake3 rpm-build fakeroot \ - qt5-qtbase-devel qt5-qtbase qt5-linguist qt5-qttools \ - libXtst-devel libXrandr-devel libXinerama-devel libXcursor-devel libXrandr-devel libXdamage-devel libXcomposite-devel libXfixes-devel \ - libjpeg-turbo-devel \ - zlib-devel \ - libpng-devel \ - openssl-devel \ - pam-devel \ - procps-devel \ - lzo-devel \ - qca-qt5-devel qca-qt5-ossl \ - cyrus-sasl-devel \ - openldap-devel && \ - ln -s /usr/bin/cmake3 /usr/bin/cmake diff --git a/.ci/linux.centos.74/script.sh b/.ci/linux.centos.74/script.sh deleted file mode 100755 index 3c705cd39..000000000 --- a/.ci/linux.centos.74/script.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -source scl_source enable devtoolset-7 - -set -e - -/veyon/.ci/common/linux-build.sh /veyon /build -/veyon/.ci/common/finalize-rpm.sh "centos-74" diff --git a/.ci/linux.debian.11/Dockerfile b/.ci/linux.debian.11/Dockerfile new file mode 100644 index 000000000..4855dd14f --- /dev/null +++ b/.ci/linux.debian.11/Dockerfile @@ -0,0 +1,23 @@ +FROM debian:bullseye-slim +MAINTAINER Tobias Junghans + +RUN \ + apt-get update && \ + apt-get install --no-install-recommends -y \ + dpkg-dev \ + ca-certificates git binutils gcc g++ ninja-build cmake file fakeroot bzip2 \ + qtbase5-dev qtbase5-private-dev qtbase5-dev-tools qttools5-dev qttools5-dev-tools qtdeclarative5-dev qtquickcontrols2-5-dev \ + xorg-dev \ + libfakekey-dev \ + libpng-dev libjpeg-dev zlib1g-dev liblzo2-dev \ + libvncserver-dev \ + libssl-dev \ + libpam0g-dev \ + libprocps-dev \ + libldap2-dev \ + libsasl2-dev \ + libqca-qt5-2-dev libqca-qt5-2-plugins \ + libavcodec-dev libavformat-dev libavutil-dev libswscale-dev \ + && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* diff --git a/.ci/linux.debian.11/script.sh b/.ci/linux.debian.11/script.sh new file mode 100755 index 000000000..f4f313a6c --- /dev/null +++ b/.ci/linux.debian.11/script.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +export CMAKE_FLAGS="$CMAKE_FLAGS -DWITH_QT6=OFF -DCPACK_DIST=debian.11" + +$1/.ci/common/linux-build.sh $@ +$1/.ci/common/finalize-deb.sh $1 $2 diff --git a/.ci/linux.debian.12/Dockerfile b/.ci/linux.debian.12/Dockerfile new file mode 100644 index 000000000..ed258318d --- /dev/null +++ b/.ci/linux.debian.12/Dockerfile @@ -0,0 +1,23 @@ +FROM debian:bookworm-slim +MAINTAINER Tobias Junghans + +RUN \ + apt-get update && \ + apt-get install --no-install-recommends -y \ + dpkg-dev \ + ca-certificates git binutils gcc g++ ninja-build cmake file fakeroot bzip2 \ + qtbase5-dev qtbase5-private-dev qtbase5-dev-tools qttools5-dev qttools5-dev-tools qtdeclarative5-dev qtquickcontrols2-5-dev \ + xorg-dev \ + libfakekey-dev \ + libpng-dev libjpeg-dev zlib1g-dev liblzo2-dev \ + libvncserver-dev \ + libssl-dev \ + libpam0g-dev \ + libproc2-dev \ + libldap2-dev \ + libsasl2-dev \ + libqca-qt5-2-dev libqca-qt5-2-plugins \ + libavcodec-dev libavformat-dev libavutil-dev libswscale-dev \ + && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* diff --git a/.ci/linux.debian.12/script.sh b/.ci/linux.debian.12/script.sh new file mode 100755 index 000000000..75d84adc9 --- /dev/null +++ b/.ci/linux.debian.12/script.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +set -e + +export CMAKE_FLAGS="$CMAKE_FLAGS -DWITH_QT6=OFF -DCPACK_DIST=debian.12" + +$1/.ci/common/linux-build.sh $@ +$1/.ci/common/finalize-deb.sh $1 $2 + +if [ -z "$3" ] ; then + +# generate source tarball +cd $1 +VERSION=$(git describe --tags --abbrev=0 | sed -e 's/^v//g') +cp $2/CONTRIBUTORS . + +$1/.ci/common/strip-kldap-sources.sh +$1/.ci/common/strip-libvncserver-sources.sh +$1/.ci/common/strip-ultravnc-sources.sh +$1/.ci/common/strip-x11vnc-sources.sh + +cd .. +tar --transform "s,^veyon,veyon-$VERSION," --exclude=".git" --exclude="*.deb" -cjf $2/veyon-$VERSION-src.tar.bz2 veyon + +mv -v $2/*.tar.bz2 $1 + +fi diff --git a/.ci/linux.debian.buster/Dockerfile b/.ci/linux.debian.buster/Dockerfile deleted file mode 100644 index c5b17e1c0..000000000 --- a/.ci/linux.debian.buster/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM debian:buster -MAINTAINER Tobias Junghans - -RUN \ - apt-get update && \ - apt-get install --no-install-recommends -y \ - git binutils gcc g++ make cmake rename file fakeroot bzip2 \ - qtbase5-dev qtbase5-dev-tools qttools5-dev qttools5-dev-tools \ - xorg-dev \ - libjpeg-dev \ - zlib1g-dev \ - libssl-dev \ - libpam0g-dev \ - libprocps-dev \ - libldap2-dev \ - libsasl2-dev \ - libpng-dev \ - liblzo2-dev \ - libqca-qt5-2-dev libqca-qt5-2-plugins \ - && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* diff --git a/.ci/linux.debian.buster/script.sh b/.ci/linux.debian.buster/script.sh deleted file mode 100755 index 9e218d3ad..000000000 --- a/.ci/linux.debian.buster/script.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -set -e - -/veyon/.ci/common/linux-build.sh /veyon /build -/veyon/.ci/common/finalize-deb.sh "debian-buster" diff --git a/.ci/linux.debian.stretch/Dockerfile b/.ci/linux.debian.stretch/Dockerfile deleted file mode 100644 index fc1dd5e5b..000000000 --- a/.ci/linux.debian.stretch/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM debian:stretch -MAINTAINER Tobias Junghans - -RUN \ - apt-get update && \ - apt-get install --no-install-recommends -y \ - git binutils gcc g++ make cmake rename file fakeroot bzip2 \ - qtbase5-dev qtbase5-dev-tools qttools5-dev qttools5-dev-tools \ - xorg-dev \ - libjpeg-dev \ - zlib1g-dev \ - libssl-dev \ - libpam0g-dev \ - libprocps-dev \ - libldap2-dev \ - libsasl2-dev \ - libpng-dev \ - liblzo2-dev \ - libqca-qt5-2-dev libqca-qt5-2-plugins \ - && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* diff --git a/.ci/linux.debian.stretch/script.sh b/.ci/linux.debian.stretch/script.sh deleted file mode 100755 index ef4321b78..000000000 --- a/.ci/linux.debian.stretch/script.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -set -e - -/veyon/.ci/common/linux-build.sh /veyon /build -/veyon/.ci/common/finalize-deb.sh "debian-stretch" - -# generate source tarball -cd /veyon -VERSION=$(git describe --tags --abbrev=0 | sed -e 's/^v//g') -cp /build/CONTRIBUTORS . - -.ci/common/strip-kitemmodels-sources.sh -.ci/common/strip-kldap-sources.sh -.ci/common/strip-libvncserver-sources.sh -.ci/common/strip-ultravnc-sources.sh -.ci/common/strip-x11vnc-sources.sh - -cd / -tar --transform "s,^veyon,veyon-$VERSION," --exclude=".git" --exclude="*.deb" -cjf /build/veyon-$VERSION-src.tar.bz2 veyon - -mv -v /build/*.tar.bz2 /veyon diff --git a/.ci/linux.fedora.29/script.sh b/.ci/linux.fedora.29/script.sh deleted file mode 100755 index c39f8a177..000000000 --- a/.ci/linux.fedora.29/script.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -set -e - -/veyon/.ci/common/linux-build.sh /veyon /build -/veyon/.ci/common/finalize-rpm.sh "fc29" diff --git a/.ci/linux.fedora.41/Dockerfile b/.ci/linux.fedora.41/Dockerfile new file mode 100644 index 000000000..2ce6b7562 --- /dev/null +++ b/.ci/linux.fedora.41/Dockerfile @@ -0,0 +1,19 @@ +FROM fedora:41 +MAINTAINER Tobias Junghans + +RUN \ + dnf install -y https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-41.noarch.rpm && \ + dnf install -y --setopt=install_weak_deps=False \ + git gcc-c++ ninja-build cmake rpm-build fakeroot fakeroot-libs \ + qt6-qtbase-devel qt6-qtbase qt6-qt5compat-devel qt6-linguist qt6-qttools-devel qt6-qtdeclarative-devel qt6-qthttpserver-devel \ + libXtst-devel libXrandr-devel libXinerama-devel libXcursor-devel libXrandr-devel libXdamage-devel libXcomposite-devel libXfixes-devel \ + libfakekey-devel \ + libjpeg-turbo-devel zlib-devel libpng-devel lzo-devel \ + libvncserver-devel \ + openssl-devel \ + pam-devel \ + procps-devel \ + qca-qt6-devel qca-qt6-ossl \ + ffmpeg-devel \ + cyrus-sasl-devel \ + openldap-devel diff --git a/.ci/linux.fedora.41/script.sh b/.ci/linux.fedora.41/script.sh new file mode 100755 index 000000000..b913dc3ee --- /dev/null +++ b/.ci/linux.fedora.41/script.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +export CMAKE_FLAGS="$CMAKE_FLAGS -DWITH_PCH=OFF -DCPACK_DIST=fedora.41 -DCMAKE_CXX_FLAGS=-Wno-template-id-cdtor" + +$1/.ci/common/linux-build.sh $@ +$1/.ci/common/finalize-rpm.sh $1 $2 diff --git a/.ci/linux.fedora.42/Dockerfile b/.ci/linux.fedora.42/Dockerfile new file mode 100644 index 000000000..27275644a --- /dev/null +++ b/.ci/linux.fedora.42/Dockerfile @@ -0,0 +1,19 @@ +FROM fedora:42 +MAINTAINER Tobias Junghans + +RUN \ + dnf install -y https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-42.noarch.rpm && \ + dnf install -y --setopt=install_weak_deps=False \ + git gcc-c++ ninja-build cmake rpm-build fakeroot fakeroot-libs \ + qt6-qtbase-devel qt6-qtbase qt6-qt5compat-devel qt6-linguist qt6-qttools-devel qt6-qtdeclarative-devel qt6-qthttpserver-devel \ + libXtst-devel libXrandr-devel libXinerama-devel libXcursor-devel libXrandr-devel libXdamage-devel libXcomposite-devel libXfixes-devel \ + libfakekey-devel \ + libjpeg-turbo-devel zlib-devel libpng-devel lzo-devel \ + libvncserver-devel \ + openssl-devel \ + pam-devel \ + procps-devel \ + qca-qt6-devel qca-qt6-ossl \ + ffmpeg-devel \ + cyrus-sasl-devel \ + openldap-devel diff --git a/.ci/linux.fedora.42/script.sh b/.ci/linux.fedora.42/script.sh new file mode 100755 index 000000000..35d528dcf --- /dev/null +++ b/.ci/linux.fedora.42/script.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +export CMAKE_FLAGS="$CMAKE_FLAGS -DWITH_PCH=OFF -DCPACK_DIST=fedora.42 -DCMAKE_CXX_FLAGS=-Wno-template-id-cdtor" + +$1/.ci/common/linux-build.sh $@ +$1/.ci/common/finalize-rpm.sh $1 $2 diff --git a/.ci/linux.opensuse.15.0/script.sh b/.ci/linux.opensuse.15.0/script.sh deleted file mode 100755 index 96b5c535b..000000000 --- a/.ci/linux.opensuse.15.0/script.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -set -e - -/veyon/.ci/common/linux-build.sh /veyon /build -/veyon/.ci/common/finalize-rpm.sh "opensuse-15.0" diff --git a/.ci/linux.opensuse.15.1/Dockerfile b/.ci/linux.opensuse.15.1/Dockerfile deleted file mode 100644 index 8026da2d3..000000000 --- a/.ci/linux.opensuse.15.1/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -FROM opensuse/leap:15.1 -MAINTAINER Tobias Junghans - -RUN \ - zypper --gpg-auto-import-keys install -y git gcc-c++ make cmake rpm-build fakeroot \ - libqt5-qtbase-devel libqt5-linguist-devel libqt5-qttools-devel \ - libXtst-devel libXrandr-devel libXinerama-devel libXcursor-devel libXrandr-devel libXdamage-devel libXcomposite-devel libXfixes-devel \ - libjpeg8-devel \ - zlib-devel \ - libpng16-devel libpng16-compat-devel \ - libopenssl-devel \ - procps-devel \ - pam-devel lzo-devel \ - libqca-qt5-devel libqca-qt5-plugins \ - cyrus-sasl-devel \ - openldap2-devel - diff --git a/.ci/linux.opensuse.15.1/script.sh b/.ci/linux.opensuse.15.1/script.sh deleted file mode 100755 index 03cd41d2c..000000000 --- a/.ci/linux.opensuse.15.1/script.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -set -e - -/veyon/.ci/common/linux-build.sh /veyon /build -/veyon/.ci/common/finalize-rpm.sh "opensuse-15.1" diff --git a/.ci/linux.opensuse.15.0/Dockerfile b/.ci/linux.opensuse.15.6/Dockerfile similarity index 53% rename from .ci/linux.opensuse.15.0/Dockerfile rename to .ci/linux.opensuse.15.6/Dockerfile index 8c87fd832..39ceb644d 100644 --- a/.ci/linux.opensuse.15.0/Dockerfile +++ b/.ci/linux.opensuse.15.6/Dockerfile @@ -1,10 +1,11 @@ -FROM opensuse/leap:15.0 +FROM opensuse/leap:15.6 MAINTAINER Tobias Junghans RUN \ - zypper --gpg-auto-import-keys install -y git gcc-c++ make cmake rpm-build fakeroot \ - libqt5-qtbase-devel libqt5-linguist-devel libqt5-qttools-devel \ + zypper --gpg-auto-import-keys install -y git gcc-c++ ninja cmake rpm-build fakeroot \ + libqt5-qtbase-devel libqt5-qtbase-private-headers-devel libqt5-linguist-devel libqt5-qttools-devel libqt5-qtquickcontrols2 libQt5QuickControls2-devel \ libXtst-devel libXrandr-devel libXinerama-devel libXcursor-devel libXrandr-devel libXdamage-devel libXcomposite-devel libXfixes-devel \ + libfakekey-devel \ libjpeg8-devel \ zlib-devel \ libpng16-devel libpng16-compat-devel \ @@ -12,6 +13,7 @@ RUN \ procps-devel \ pam-devel lzo-devel \ libqca-qt5-devel libqca-qt5-plugins \ + libavcodec-devel libavformat-devel libavutil-devel libswscale-devel \ cyrus-sasl-devel \ openldap2-devel diff --git a/.ci/linux.opensuse.15.6/script.sh b/.ci/linux.opensuse.15.6/script.sh new file mode 100755 index 000000000..db0f888f0 --- /dev/null +++ b/.ci/linux.opensuse.15.6/script.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +export CMAKE_FLAGS="$CMAKE_FLAGS -DWITH_QT6=OFF -DCPACK_DIST=opensuse.15.6" + +$1/.ci/common/linux-build.sh $@ +$1/.ci/common/finalize-rpm.sh $1 $2 diff --git a/.ci/linux.opensuse.tumbleweed/Dockerfile b/.ci/linux.opensuse.tumbleweed/Dockerfile new file mode 100644 index 000000000..fa3613b4c --- /dev/null +++ b/.ci/linux.opensuse.tumbleweed/Dockerfile @@ -0,0 +1,19 @@ +FROM opensuse/tumbleweed:latest +MAINTAINER Tobias Junghans + +RUN \ + zypper --gpg-auto-import-keys install -y git gcc-c++ ninja cmake rpm-build fakeroot \ + qt6-widgets-devel qt6-qt5compat-devel qt6-concurrent-devel qt6-linguist-devel qt6-tools-devel qt6-quickcontrols2-devel qt6-httpserver-devel \ + libXtst-devel libXrandr-devel libXinerama-devel libXcursor-devel libXrandr-devel libXdamage-devel libXcomposite-devel libXfixes-devel \ + libfakekey-devel \ + libjpeg8-devel \ + zlib-devel \ + libpng16-devel libpng16-compat-devel \ + libopenssl-devel \ + procps-devel \ + pam-devel lzo-devel \ + qca-qt6-devel qca-qt6-plugins \ + libavcodec-devel libavformat-devel libavutil-devel libswscale-devel \ + cyrus-sasl-devel \ + openldap2-devel + diff --git a/.ci/linux.opensuse.tumbleweed/script.sh b/.ci/linux.opensuse.tumbleweed/script.sh new file mode 100755 index 000000000..ee8f471a8 --- /dev/null +++ b/.ci/linux.opensuse.tumbleweed/script.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +export CMAKE_FLAGS="$CMAKE_FLAGS -DCPACK_DIST=opensuse.tumbleweed" + +$1/.ci/common/linux-build.sh $@ +$1/.ci/common/finalize-rpm.sh $1 $2 diff --git a/.ci/linux.fedora.29/Dockerfile b/.ci/linux.rhel.8/Dockerfile similarity index 52% rename from .ci/linux.fedora.29/Dockerfile rename to .ci/linux.rhel.8/Dockerfile index 8f9516e7e..e33f6ae0e 100644 --- a/.ci/linux.fedora.29/Dockerfile +++ b/.ci/linux.rhel.8/Dockerfile @@ -1,9 +1,11 @@ -FROM fedora:29 +FROM rockylinux:8 MAINTAINER Tobias Junghans RUN \ - yum install -y git gcc-c++ make cmake rpm-build fakeroot \ - qt5-qtbase-devel qt5-qtbase qt5-linguist qt5-qttools \ + dnf -y --enablerepo=extras install epel-release && \ + dnf -y install https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm && \ + dnf -y --enablerepo=devel install git ninja-build cmake rpm-build fakeroot \ + qt5-qtbase-devel qt5-qtbase qt5-linguist qt5-qttools qt5-qtquickcontrols2-devel \ libXtst-devel libXrandr-devel libXinerama-devel libXcursor-devel libXrandr-devel libXdamage-devel libXcomposite-devel libXfixes-devel \ libjpeg-turbo-devel \ zlib-devel \ @@ -13,5 +15,6 @@ RUN \ procps-devel \ lzo-devel \ qca-qt5-devel qca-qt5-ossl \ + ffmpeg-devel \ cyrus-sasl-devel \ openldap-devel diff --git a/.ci/linux.rhel.8/script.sh b/.ci/linux.rhel.8/script.sh new file mode 100755 index 000000000..b2516359e --- /dev/null +++ b/.ci/linux.rhel.8/script.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +export CMAKE_FLAGS="$CMAKE_FLAGS -DWITH_QT6=OFF -DCPACK_DIST=rhel.8" + +$1/.ci/common/linux-build.sh $@ +$1/.ci/common/finalize-rpm.sh $1 $2 diff --git a/.ci/linux.rhel.9/Dockerfile b/.ci/linux.rhel.9/Dockerfile new file mode 100644 index 000000000..e57afa426 --- /dev/null +++ b/.ci/linux.rhel.9/Dockerfile @@ -0,0 +1,21 @@ +FROM rockylinux:9 +MAINTAINER Tobias Junghans + +RUN \ + dnf -y --enablerepo=extras install epel-release && \ + dnf -y install https://download1.rpmfusion.org/free/el/rpmfusion-free-release-9.noarch.rpm && \ + dnf -y --enablerepo=devel install \ + git ninja-build cmake rpm-build fakeroot \ + qt6-qtbase-devel qt6-qtbase qt6-qt5compat-devel qt6-linguist qt6-qttools-devel qt6-qtdeclarative-devel qt6-qthttpserver-devel \ + libXtst-devel libXrandr-devel libXinerama-devel libXcursor-devel libXrandr-devel libXdamage-devel libXcomposite-devel libXfixes-devel \ + libfakekey-devel \ + libjpeg-turbo-devel zlib-devel libpng-devel lzo-devel \ + libvncserver-devel \ + openssl-devel \ + pam-devel \ + procps-devel \ + lzo-devel \ + qca-qt6-devel qca-qt6-ossl \ + ffmpeg-devel \ + cyrus-sasl-devel \ + openldap-devel diff --git a/.ci/linux.rhel.9/script.sh b/.ci/linux.rhel.9/script.sh new file mode 100755 index 000000000..0f9884c1d --- /dev/null +++ b/.ci/linux.rhel.9/script.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +export CMAKE_FLAGS="$CMAKE_FLAGS -DCPACK_DIST=rhel.9" + +$1/.ci/common/linux-build.sh $@ +$1/.ci/common/finalize-rpm.sh $1 $2 diff --git a/.ci/linux.sast/Dockerfile b/.ci/linux.sast/Dockerfile deleted file mode 100755 index 71cab024d..000000000 --- a/.ci/linux.sast/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM debian:stretch -MAINTAINER Tobias Junghans - -RUN \ - apt-get update && \ - apt-get install -y \ - flawfinder \ - && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* diff --git a/.ci/linux.sast/script.sh b/.ci/linux.sast/script.sh deleted file mode 100755 index 8e175ba34..000000000 --- a/.ci/linux.sast/script.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -set -e - -cd /veyon - -flawfinder -Q -c core plugins master server service configurator cli worker - diff --git a/.ci/linux.ubuntu.20.04/Dockerfile b/.ci/linux.ubuntu.20.04/Dockerfile new file mode 100644 index 000000000..206eeb0d3 --- /dev/null +++ b/.ci/linux.ubuntu.20.04/Dockerfile @@ -0,0 +1,25 @@ +FROM ubuntu:focal +MAINTAINER Tobias Junghans + +RUN \ + apt-get update && \ + DEBIAN_FRONTEND="noninteractive" apt-get install --no-install-recommends -y \ + dpkg-dev \ + ca-certificates git binutils gcc g++ ninja-build cmake file fakeroot bzip2 \ + qtbase5-dev qtbase5-private-dev qtbase5-dev-tools qttools5-dev qttools5-dev-tools qtdeclarative5-dev qtquickcontrols2-5-dev \ + xorg-dev \ + libfakekey-dev \ + libjpeg-dev \ + zlib1g-dev \ + libssl-dev \ + libpam0g-dev \ + libprocps-dev \ + libldap2-dev \ + libsasl2-dev \ + libpng-dev \ + liblzo2-dev \ + libqca-qt5-2-dev libqca-qt5-2-plugins \ + libavcodec-dev libavformat-dev libavutil-dev libswscale-dev \ + && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* diff --git a/.ci/linux.ubuntu.20.04/script.sh b/.ci/linux.ubuntu.20.04/script.sh new file mode 100755 index 000000000..4c14dc4a8 --- /dev/null +++ b/.ci/linux.ubuntu.20.04/script.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +export CMAKE_FLAGS="$CMAKE_FLAGS -DWITH_QT6=OFF -DCPACK_DIST=ubuntu.20.04" + +$1/.ci/common/linux-build.sh $@ +$1/.ci/common/finalize-deb.sh $1 $2 diff --git a/.ci/linux.ubuntu.22.04/Dockerfile b/.ci/linux.ubuntu.22.04/Dockerfile new file mode 100644 index 000000000..6ff60f768 --- /dev/null +++ b/.ci/linux.ubuntu.22.04/Dockerfile @@ -0,0 +1,22 @@ +FROM ubuntu:jammy +MAINTAINER Tobias Junghans + +RUN \ + apt-get update && \ + DEBIAN_FRONTEND="noninteractive" apt-get install --no-install-recommends -y \ + dpkg-dev \ + ca-certificates git binutils gcc g++ ninja-build cmake file fakeroot bzip2 \ + qtbase5-dev qtbase5-private-dev qtbase5-dev-tools qttools5-dev qttools5-dev-tools qtdeclarative5-dev qtquickcontrols2-5-dev \ + xorg-dev \ + libfakekey-dev \ + libvncserver-dev \ + libssl-dev \ + libpam0g-dev \ + libprocps-dev \ + libldap2-dev \ + libsasl2-dev \ + libqca-qt5-2-dev libqca-qt5-2-plugins \ + libavcodec-dev libavformat-dev libavutil-dev libswscale-dev \ + && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* diff --git a/.ci/linux.ubuntu.22.04/script.sh b/.ci/linux.ubuntu.22.04/script.sh new file mode 100755 index 000000000..ec867b7de --- /dev/null +++ b/.ci/linux.ubuntu.22.04/script.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +export CMAKE_FLAGS="$CMAKE_FLAGS -DWITH_QT6=OFF -DCPACK_DIST=ubuntu.22.04" + +$1/.ci/common/linux-build.sh $@ +$1/.ci/common/finalize-deb.sh $1 $2 diff --git a/.ci/linux.ubuntu.24.04/Dockerfile b/.ci/linux.ubuntu.24.04/Dockerfile new file mode 100644 index 000000000..c6c0b81c9 --- /dev/null +++ b/.ci/linux.ubuntu.24.04/Dockerfile @@ -0,0 +1,22 @@ +FROM ubuntu:noble +MAINTAINER Tobias Junghans + +RUN \ + apt-get update && \ + apt-get install --no-install-recommends -y \ + dpkg-dev \ + ca-certificates git binutils gcc g++ ninja-build cmake file fakeroot bzip2 \ + qt6-base-dev qt6-5compat-dev qt6-l10n-tools qt6-tools-dev qt6-declarative-dev qt6-httpserver-dev qt6-websockets-dev \ + xorg-dev \ + libfakekey-dev \ + libvncserver-dev \ + libssl-dev \ + libpam0g-dev \ + libproc2-dev \ + libldap2-dev \ + libsasl2-dev \ + libqca-qt6-dev libqca-qt6-plugins \ + libavcodec-dev libavformat-dev libavutil-dev libswscale-dev \ + && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* diff --git a/.ci/linux.ubuntu.24.04/script.sh b/.ci/linux.ubuntu.24.04/script.sh new file mode 100755 index 000000000..d6025bef0 --- /dev/null +++ b/.ci/linux.ubuntu.24.04/script.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +export CMAKE_FLAGS="$CMAKE_FLAGS -DCPACK_DIST=ubuntu.24.04" + +$1/.ci/common/linux-build.sh $@ +$1/.ci/common/finalize-deb.sh $1 $2 diff --git a/.ci/linux.ubuntu.bionic/Dockerfile b/.ci/linux.ubuntu.bionic/Dockerfile deleted file mode 100644 index 5ecf5780f..000000000 --- a/.ci/linux.ubuntu.bionic/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM ubuntu:bionic -MAINTAINER Tobias Junghans - -RUN \ - apt-get update && \ - apt-get install --no-install-recommends -y \ - git binutils gcc g++ make cmake rename file fakeroot bzip2 \ - qtbase5-dev qtbase5-dev-tools qttools5-dev qttools5-dev-tools \ - xorg-dev \ - libjpeg-dev \ - zlib1g-dev \ - libssl-dev \ - libpam0g-dev \ - libprocps-dev \ - libldap2-dev \ - libsasl2-dev \ - libpng-dev \ - liblzo2-dev \ - libqca-qt5-2-dev libqca-qt5-2-plugins \ - && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* diff --git a/.ci/linux.ubuntu.bionic/script.sh b/.ci/linux.ubuntu.bionic/script.sh deleted file mode 100755 index 717e0c91b..000000000 --- a/.ci/linux.ubuntu.bionic/script.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -set -e - -/veyon/.ci/common/linux-build.sh /veyon /build -/veyon/.ci/common/finalize-deb.sh "ubuntu-bionic" diff --git a/.ci/linux.ubuntu.xenial/Dockerfile b/.ci/linux.ubuntu.xenial/Dockerfile deleted file mode 100644 index 5ea3c1cdb..000000000 --- a/.ci/linux.ubuntu.xenial/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM ubuntu:xenial -MAINTAINER Tobias Junghans - -RUN \ - apt-get update && \ - apt-get install --no-install-recommends -y \ - git binutils gcc g++ make cmake rename file fakeroot bzip2 \ - qtbase5-dev qtbase5-dev-tools qttools5-dev qttools5-dev-tools \ - xorg-dev \ - libjpeg-dev \ - zlib1g-dev \ - libssl-dev \ - libpam0g-dev \ - libprocps-dev \ - libldap2-dev \ - libsasl2-dev \ - libpng-dev \ - liblzo2-dev \ - libqca-qt5-2-dev libqca-qt5-2-plugins \ - && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* diff --git a/.ci/linux.ubuntu.xenial/script.sh b/.ci/linux.ubuntu.xenial/script.sh deleted file mode 100755 index 358388e1f..000000000 --- a/.ci/linux.ubuntu.xenial/script.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -set -e - -/veyon/.ci/common/linux-build.sh /veyon /build -/veyon/.ci/common/finalize-deb.sh "ubuntu-xenial" diff --git a/.ci/windows/build.sh b/.ci/windows/build.sh index a12d97e54..326f7229e 100755 --- a/.ci/windows/build.sh +++ b/.ci/windows/build.sh @@ -2,7 +2,6 @@ set -e -CPUS=$(nproc) BASEDIR=$(pwd) BUILDDIR=/tmp/build-$1 @@ -12,16 +11,17 @@ rm -rf $BUILDDIR mkdir $BUILDDIR cd $BUILDDIR -cmake $BASEDIR -DCMAKE_TOOLCHAIN_FILE=$BASEDIR/cmake/modules/Win${1}Toolchain.cmake -DCMAKE_MODULE_PATH=$BASEDIR/cmake/modules/ - -echo Building on $CPUS CPUs +PREFIX=/usr/$1-w64-mingw32 +$PREFIX/bin/qt-cmake $BASEDIR \ + -G Ninja \ + -DQT_TRANSLATIONS_DIR=$PREFIX/translations \ + $CMAKE_FLAGS if [ -z "$2" ] ; then - make -j$CPUS - make win-nsi + ninja windows-binaries else - make ${@:2} -j$CPUS + ninja ${@:2} fi -mv -v veyon*setup.exe $BASEDIR +mv veyon-*win* $BASEDIR diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..386c3bf82 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,18 @@ +name: "CI Builds" +on: [push] +jobs: + build-linux: + strategy: + matrix: + dist: + - debian.12 + - fedora.41 + - opensuse.tumbleweed + - ubuntu.24.04 + runs-on: ubuntu-latest + container: veyon/ci.linux.${{matrix.dist}} + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - run: .ci/linux.${{matrix.dist}}/script.sh $GITHUB_WORKSPACE /tmp diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 000000000..0d734066d --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,60 @@ +name: "CodeQL" + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-24.04 + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'cpp' ] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: true + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + + - name: Install dependencies + run: > + sudo apt-get update && sudo apt-get install --no-install-recommends -y + cmake + ninja-build + qt6-base-dev qt6-5compat-dev qt6-l10n-tools qt6-tools-dev qt6-declarative-dev qt6-httpserver-dev qt6-websockets-dev + xorg-dev + libfakekey-dev + libjpeg-dev + zlib1g-dev + libssl-dev + libpam0g-dev + libproc2-dev + libldap2-dev libsasl2-dev + libpng-dev + liblzo2-dev + libqca-qt6-dev libqca-qt6-plugins + + - name: Build + run: | + mkdir -p $GITHUB_WORKSPACE/build + cd $GITHUB_WORKSPACE/build + cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DWITH_QT6=ON -DWITH_LTO=OFF -DWITH_TRANSLATIONS=OFF .. + ninja + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 diff --git a/.gitignore b/.gitignore index dd70d7eb0..fd29fff6c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ svg Makefile plugins/addons plugins/extra +.vscode/* +veyon-*-setup.exe diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 361a83399..07f73e2ca 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,26 +1,51 @@ -image: docker:latest - stages: - build + - collect -build-win32-installer: +build-linux: stage: build - image: $IMAGE + image: veyon/ci.linux.$DISTRO:latest script: - - .ci/windows/build.sh 32 + - .ci/linux.$DISTRO/script.sh $CI_PROJECT_DIR /tmp + parallel: + matrix: + - DISTRO: + - debian.11 + - debian.12 + - fedora.41 + - fedora.42 + - opensuse.15.6 + - opensuse.tumbleweed + - rhel.8 + - rhel.9 + - ubuntu.20.04 + - ubuntu.22.04 + - ubuntu.24.04 artifacts: - paths: [ "*.exe" ] + paths: [ "veyon*" ] expire_in: 1 day -build-win64-installer: +build-windows: stage: build - image: $IMAGE + image: $CI_REGISTRY/veyon/ci-mingw-w64:5.0 script: - - .ci/windows/build.sh 64 + - .ci/windows/build.sh $ARCH + parallel: + matrix: + - ARCH: [i686, x86_64] artifacts: - paths: [ "*.exe" ] + paths: [ veyon-win* ] expire_in: 1 day +collect-artifacts: + stage: collect + image: veyon/ci.linux.debian.12:latest + dependencies: [ build-linux ] + only: [ tags ] + script: + - ls -la *.deb *.rpm + artifacts: + paths: [ "veyon*" ] + variables: - GIT_SUBMODULE_STRATEGY: normal - IMAGE: $CI_REGISTRY/veyon/ci-mingw-w64:4.2 + GIT_SUBMODULE_STRATEGY: recursive diff --git a/.gitmodules b/.gitmodules index e78d3263f..e3bf84dc0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,14 +3,20 @@ url = https://github.com/veyon/ultravnc.git [submodule "3rdparty/kldap"] path = 3rdparty/kldap - url = https://anongit.kde.org/kldap.git + url = https://invent.kde.org/pim/kldap.git [submodule "3rdparty/libvncserver"] path = 3rdparty/libvncserver url = https://github.com/veyon/libvncserver.git [submodule "3rdparty/x11vnc"] path = 3rdparty/x11vnc url = https://github.com/veyon/x11vnc.git -[submodule "3rdparty/kitemmodels"] - path = 3rdparty/kitemmodels - url = https://anongit.kde.org/kitemmodels.git +[submodule "3rdparty/libfakekey"] + path = 3rdparty/libfakekey + url = https://github.com/veyon/libfakekey.git branch = master +[submodule "3rdparty/qthttpserver"] + path = 3rdparty/qthttpserver + url = https://github.com/veyon/qthttpserver.git +[submodule "3rdparty/kldap-qt-compat"] + path = 3rdparty/kldap-qt-compat + url = https://invent.kde.org/pim/kldap.git diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0d586610b..000000000 --- a/.travis.yml +++ /dev/null @@ -1,33 +0,0 @@ -language: cpp -services: - - docker -git: - depth: false -dist: xenial -sudo: required -matrix: - include: - - env: TARGET_OS=centos.74 - - env: TARGET_OS=debian.stretch - - env: TARGET_OS=debian.buster - - env: TARGET_OS=fedora.29 - - env: TARGET_OS=opensuse.15.0 - - env: TARGET_OS=opensuse.15.1 - - env: TARGET_OS=ubuntu.bionic - - env: TARGET_OS=ubuntu.xenial - - env: TARGET_OS=sast -script: - - wget http://archive.ubuntu.com/ubuntu/pool/main/libs/libseccomp/libseccomp2_2.3.3-3ubuntu1_amd64.deb && sudo dpkg -i libseccomp2*deb - - docker pull veyon/travis.${TRAVIS_OS_NAME}.${TARGET_OS}:latest || docker build -t veyon/travis.${TRAVIS_OS_NAME}.${TARGET_OS} ${TRAVIS_BUILD_DIR}/.ci/${TRAVIS_OS_NAME}.${TARGET_OS}/ - - docker run -v ${TRAVIS_BUILD_DIR}:/veyon:rw veyon/travis.${TRAVIS_OS_NAME}.${TARGET_OS} /bin/sh /veyon/.ci/${TRAVIS_OS_NAME}.${TARGET_OS}/script.sh -deploy: - provider: releases - api_key: - secure: Hvax0pT56HkHHDFhNnCoMIxhTCRZ2eHSK1kf0Lw91pX/UPsexkhtFm9qck2siyyAW5IDaXMWCvbJmD5f8TXNZV5d65NQ9lc0OtUdl/os6Te3LhIbNjdywKQQknWkZxoX+blXr1VCoRUjvruxwt2Q9yIjMJn40cMh8bnQPAx1VNdCAiGNSIb8vFBmTbv9a6GTkQ3xHjlSrtCXoeq3/AZ3OqrRtXLe5uS+TquZBZv4gS908+TaveSfRUBVFB/XPvNKHVdFPYSkQUz3i0k+/ZV+7gWGEHLk2nXcKRe+6tjrsQyhvqTbyOUiQxjsWHHW0dql67ZFmvQR31RM6l/IO3QhBNu1Qotu7IyxKExE7Wn5+RiyLYOA80RoyK09uAJA7T/MyvoY2QH1dWYQEi6kJQdK7A/g51zJJosILaZuokvmF19cjTu7MC0eMkAhhTWB79JRBLg+6DOskCesWfFf7xuCqt4XqONOjWb2N1vSgH0EkkAN4w2jlO/utX9f2bQTC6sOgW57V+/1yD7rKAj0QdI+eJSuuR0azId+UtBEaSefIuGhR7qw+vQ/GZQ27uz4GZ2NalD1mp0wt0wfx+p2TW2XC03uMO1j2ZY3ve8wT+sFlbEMKmwxC3ObRpM14ez2/EIAotauZ0HKDRm/AzvpShz8o9geChxZTuez06frt6Zx7fo= - repo: veyon/veyon - skip_cleanup: true - file_glob: true - file: "veyon*" - on: - tags: true - all_branches: true diff --git a/.tx/config b/.tx/config index ad87236ed..f7022cb79 100644 --- a/.tx/config +++ b/.tx/config @@ -1,9 +1,9 @@ [main] host = https://www.transifex.com -minimum_perc = 5 -[veyon.veyon_42] -file_filter = translations/.ts +[o:veyon-solutions:p:veyon:r:veyon_50] +file_filter = translations/veyon_.ts source_file = translations/veyon.ts source_lang = en +minimum_perc = 5 type = QT diff --git a/3rdparty/ddengine/README.md b/3rdparty/ddengine/README.md index 43eb50f37..89b37e01c 100644 --- a/3rdparty/ddengine/README.md +++ b/3rdparty/ddengine/README.md @@ -1,7 +1,7 @@ DeskDupEngine ------------- -DLL files taken from https://www.uvnc.eu/download/1222/UltraVnc_1_2_24_ALL.zip +DLL files taken from https://www.uvnc.eu/download/132/UltraVnc_1_3_2_ALL.zip and distributed with Veyon as is. Permission has been granted by Rudi De Vos via e-mail on 2018-09-16. diff --git a/3rdparty/ddengine/ddengine.dll b/3rdparty/ddengine/ddengine.dll index afa53e85e..bf666b7eb 100644 Binary files a/3rdparty/ddengine/ddengine.dll and b/3rdparty/ddengine/ddengine.dll differ diff --git a/3rdparty/ddengine/ddengine64.dll b/3rdparty/ddengine/ddengine64.dll index 2e23e1a9e..45121484a 100644 Binary files a/3rdparty/ddengine/ddengine64.dll and b/3rdparty/ddengine/ddengine64.dll differ diff --git a/3rdparty/kitemmodels b/3rdparty/kitemmodels deleted file mode 160000 index 26143d13d..000000000 --- a/3rdparty/kitemmodels +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 26143d13d95864e0e4e17bb55ea83db4af3b179c diff --git a/3rdparty/kldap b/3rdparty/kldap index 87c2b3cfe..ee428f08e 160000 --- a/3rdparty/kldap +++ b/3rdparty/kldap @@ -1 +1 @@ -Subproject commit 87c2b3cfe108d42a7630e4822e29789e852600c1 +Subproject commit ee428f08e48b1b666313b2051d744fcd91799c79 diff --git a/3rdparty/kldap-qt-compat b/3rdparty/kldap-qt-compat new file mode 160000 index 000000000..497435947 --- /dev/null +++ b/3rdparty/kldap-qt-compat @@ -0,0 +1 @@ +Subproject commit 4974359470669f8a2fcb017a2cbc6974aa8e6f3a diff --git a/3rdparty/libfakekey b/3rdparty/libfakekey new file mode 160000 index 000000000..7ad885912 --- /dev/null +++ b/3rdparty/libfakekey @@ -0,0 +1 @@ +Subproject commit 7ad885912efb2131e80914e964d5e635b0d07b40 diff --git a/3rdparty/libvncserver b/3rdparty/libvncserver index 132f321ae..72c2e71bc 160000 --- a/3rdparty/libvncserver +++ b/3rdparty/libvncserver @@ -1 +1 @@ -Subproject commit 132f321ae61d66205b88f224fd1eb07afbdde439 +Subproject commit 72c2e71bc914f0dbbdbd4118a4c65db6c9acc2c9 diff --git a/3rdparty/qthttpserver b/3rdparty/qthttpserver new file mode 160000 index 000000000..52bce5241 --- /dev/null +++ b/3rdparty/qthttpserver @@ -0,0 +1 @@ +Subproject commit 52bce52413763ead7759f8c2e374a40bb82f058f diff --git a/3rdparty/ultravnc b/3rdparty/ultravnc index 8b749632a..493f12135 160000 --- a/3rdparty/ultravnc +++ b/3rdparty/ultravnc @@ -1 +1 @@ -Subproject commit 8b749632a26a3b8d81cb062d43eec980a5b6dca1 +Subproject commit 493f1213556b3aa1589ce0ccc3606172fe24e670 diff --git a/3rdparty/x11vnc b/3rdparty/x11vnc index fd0c86628..2ecb981c9 160000 --- a/3rdparty/x11vnc +++ b/3rdparty/x11vnc @@ -1 +1 @@ -Subproject commit fd0c86628ef9deb46d56b77c521f92b00392c7b6 +Subproject commit 2ecb981c9468b83e4fe3e6cedee2a917155e295d diff --git a/CMakeLists.txt b/CMakeLists.txt index e6a012054..b36a20e73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,334 +1,339 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.1.0) - -PROJECT(veyon) - -SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH}) -IF(CMAKE_BUILD_TYPE STREQUAL "Debug") - SET(VEYON_DEBUG TRUE) -ELSEIF(NOT CMAKE_BUILD_TYPE) - SET(CMAKE_BUILD_TYPE relwithdebinfo) -ENDIF() - -IF(VEYON_DEBUG) - ADD_DEFINITIONS(-DVEYON_DEBUG) -ENDIF() +cmake_minimum_required(VERSION 3.10.0) +message("Using CMake ${CMAKE_VERSION}") + +project(veyon) + +option(WITH_CORE_ONLY "Build core library only" OFF) +option(WITH_ADDONS "Build add-ons" OFF) +option(WITH_TRANSLATIONS "Build translation files" ON) +option(WITH_TESTS "Build tests and integrate runtime test extensions" OFF) +option(WITH_LTO "Build with link-time optimization" ON) +option(WITH_PCH "Reduce compile time by using precompiled headers (requires CMake >= 3.16)" ON) +option(WITH_UNITY_BUILD "Reduce compile time by using cmake unity builds (requires CMake >= 3.16)" ON) +option(WITH_ADDRESS_SANITIZER "Build with address sanitizer" OFF) +option(WITH_THREAD_SANITIZER "Build with thread sanitizer" OFF) +option(WITH_UB_SANITIZER "Build with undefined behavior sanitizer" OFF) +option(WITH_FUZZERS "Build LLVM fuzzer tests (implies WITH_TESTS=ON)" OFF) +option(WITH_BUILTIN_LIBVNC "Build with built-in LibVNCServer/Client" OFF) + +set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH}) +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(VEYON_DEBUG TRUE) +elseif(NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "None") + set(CMAKE_BUILD_TYPE RelWithDebInfo) +endif() + +if(VEYON_DEBUG) + add_definitions(-DVEYON_DEBUG) +endif() set(CMAKE_EXPORT_COMPILE_COMMANDS 1) -IF(COMMAND CMAKE_POLICY) - CMAKE_POLICY(SET CMP0009 NEW) - CMAKE_POLICY(SET CMP0020 NEW) - if(${CMAKE_VERSION} VERSION_GREATER "3.12.0") +if(COMMAND CMAKE_POLICY) + cmake_policy(SET CMP0009 NEW) + cmake_policy(SET CMP0022 NEW) + cmake_policy(SET CMP0058 NEW) + cmake_policy(SET CMP0063 NEW) + cmake_policy(SET CMP0069 NEW) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.12.0") cmake_policy(SET CMP0075 NEW) endif() -ENDIF() - -INCLUDE(AddFileDependencies) -INCLUDE(CheckCSourceCompiles) -INCLUDE(CheckIncludeFiles) -INCLUDE(CheckFunctionExists) -INCLUDE(CheckSymbolExists) -INCLUDE(CheckTypeSize) -INCLUDE(GNUInstallDirs) -INCLUDE(CotireVeyon) -INCLUDE(ConfigureFiles) - -FIND_PACKAGE(Git) - -IF(GIT_FOUND) - EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" describe --tags - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_STRIP_TRAILING_WHITESPACE - OUTPUT_VARIABLE VERSION_STRING) - STRING(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${VERSION_STRING}") - STRING(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${VERSION_STRING}") - STRING(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${VERSION_STRING}") + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14.0") + cmake_policy(SET CMP0083 NEW) + include(CheckPIESupported) + check_pie_supported(LANGUAGES CXX) + if(CMAKE_CXX_LINK_PIE_SUPPORTED) + set(CMAKE_COMPILE_OPTIONS_PIE "-fPIE") + set(CMAKE_LINK_OPTIONS_PIE "-pie;-fPIE;-fPIC") + else() + set(CMAKE_COMPILE_OPTIONS_PIE "-fPIC") + set(CMAKE_LINK_OPTIONS_PIE "-fPIC") + endif() + endif() +endif() + +include(AddFileDependencies) +include(CheckCSourceCompiles) +include(CheckIncludeFiles) +include(CheckFunctionExists) +include(CheckSymbolExists) +include(CheckTypeSize) +include(GNUInstallDirs) +include(ConfigureFiles) +include(PchHelpers) +include(SetDefaultTargetProperties) + +find_package(Git) + +if(GIT_FOUND) + execute_process(COMMAND "${GIT_EXECUTABLE}" describe --tags + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE VERSION_STRING) + string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${VERSION_STRING}") + string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${VERSION_STRING}") + string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${VERSION_STRING}") # determine build number to use in NSIS installer and resource files - EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" describe --tags - COMMAND cut -d "-" -f2 - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_STRIP_TRAILING_WHITESPACE - OUTPUT_VARIABLE VERSION_BUILD) - IF(NOT VERSION_BUILD GREATER 0) - SET(VERSION_BUILD 0) - ENDIF() + execute_process(COMMAND "${GIT_EXECUTABLE}" describe --tags + COMMAND cut -d "-" -f2 + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE VERSION_BUILD) + if(NOT VERSION_BUILD GREATER 0) + set(VERSION_BUILD 0) + endif() # Get list of all committers from git history, ordered by number of commits. # The CONTRIBUTORS file is used by AboutDialog. This information can be provided # with -DCONTRIBUTORS=/path/to/CONTRIBUTORS instead. For instance, to generate # this file for version 3.0.2, the command is: # git shortlog -sne v3.0.2 | cut -c8- - SET(CONTRIBUTORS "${CMAKE_BINARY_DIR}/CONTRIBUTORS") - IF(NOT EXISTS "${CONTRIBUTORS}") - EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" shortlog -s d160d147165271516589c304cb1b8f5e48f8527d..HEAD - COMMAND cut -c8- - COMMAND sort -f - OUTPUT_FILE "${CONTRIBUTORS}" - WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" - TIMEOUT 10) - ENDIF() - -ENDIF() - -# can't retrieve version information as not building from Git repository? -IF(NOT VERSION_STRING) - SET(VERSION_MAJOR 4) - SET(VERSION_MINOR 2) - SET(VERSION_PATCH 3) - SET(VERSION_BUILD 0) - SET(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") -ELSE() - # remove leading character from tag name - STRING(REPLACE "v" "" VERSION_STRING "${VERSION_STRING}") -ENDIF() + set(CONTRIBUTORS "${CMAKE_BINARY_DIR}/CONTRIBUTORS") + if(NOT EXISTS "${CONTRIBUTORS}") + execute_process(COMMAND "${GIT_EXECUTABLE}" shortlog -s d160d147165271516589c304cb1b8f5e48f8527d..HEAD + COMMAND cut -c8- + COMMAND sort -f + OUTPUT_FILE "${CONTRIBUTORS}" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + TIMEOUT 10) + endif() -# set up compiler version variable -STRING(REGEX REPLACE "\\.[0-9]$" "" COMPILER_VERSION_MAJOR_MINOR ${CMAKE_CXX_COMPILER_VERSION}) +endif() +# can't retrieve version information as not building from Git repository? +if(NOT VERSION_STRING) + set(VERSION_MAJOR 4) + set(VERSION_MINOR 99) + set(VERSION_PATCH 0) + set(VERSION_BUILD 0) + set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") +else() + # remove leading character from tag name + string(REPLACE "v" "" VERSION_STRING "${VERSION_STRING}") +endif() # set up basic platform variables -IF(WIN32) - SET(VEYON_BUILD_WIN32 1) -ENDIF() -IF(APPLE) - SET(VEYON_BUILD_APPLE 1) -ENDIF() -IF(UNIX AND NOT ANDROID) - SET(VEYON_BUILD_LINUX 1) -ENDIF() -IF(ANDROID) - SET(VEYON_BUILD_ANDROID 1) -ENDIF() - -IF(WIN64) - SET(VEYON_BUILD_WIN64 TRUE) -ENDIF(WIN64) +if(WIN32) + set(VEYON_BUILD_WINDOWS 1) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + set(VEYON_BUILD_WIN64 1) + set(VEYON_WINDOWS_ARCH "win64") + else() + set(VEYON_BUILD_WIN32 1) + set(VEYON_WINDOWS_ARCH "win32") + endif() + add_definitions(-DUNICODE -D_UNICODE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-attributes") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes") +endif() +if(APPLE) + set(VEYON_BUILD_APPLE 1) +endif() +if(UNIX AND NOT ANDROID) + set(VEYON_BUILD_LINUX 1) +endif() +if(ANDROID) + set(VEYON_BUILD_ANDROID 1) +endif() # set up library and plugin path variables -IF(VEYON_BUILD_ANDROID) - SET(CMAKE_INSTALL_PREFIX "/") - SET(VEYON_LIB_DIR "libs/${ANDROID_ABI}") - SET(VEYON_INSTALL_PLUGIN_DIR "${VEYON_LIB_DIR}/veyon") - SET(VEYON_INSTALL_DATA_DIR "${CMAKE_INSTALL_DATA_DIR}/veyon") - SET(VEYON_PLUGIN_DIR "") - SET(VEYON_TRANSLATIONS_DIR "/translations") -ELSE() - IF(CMAKE_INSTALL_LIBDIR) - SET(VEYON_LIB_DIR "${CMAKE_INSTALL_LIBDIR}/veyon" CACHE INTERNAL "Veyon library directory") - ELSE() - SET(VEYON_LIB_DIR lib/veyon CACHE INTERNAL "Veyon library directory") - ENDIF() - - SET(VEYON_INSTALL_PLUGIN_DIR "${VEYON_LIB_DIR}") - SET(VEYON_INSTALL_DATA_DIR "${CMAKE_INSTALL_DATA_DIR}/veyon") - - IF(WIN32) - SET(VEYON_PLUGIN_DIR "plugins") - SET(VEYON_TRANSLATIONS_DIR "translations") - ELSE() - SET(VEYON_PLUGIN_DIR "../${VEYON_LIB_DIR}") - SET(VEYON_TRANSLATIONS_DIR "../share/veyon/translations") - ENDIF() -ENDIF() - - -SET(VEYON_CORE_INCLUDE_DIR core/include) - -# find required Qt5 modules -FIND_PACKAGE(Qt5Core REQUIRED) -FIND_PACKAGE(Qt5Concurrent REQUIRED) -FIND_PACKAGE(Qt5Gui REQUIRED) -FIND_PACKAGE(Qt5Widgets REQUIRED) -FIND_PACKAGE(Qt5Network REQUIRED) -FIND_PACKAGE(Qt5LinguistTools REQUIRED) -IF(VEYON_DEBUG) -FIND_PACKAGE(Qt5Test REQUIRED) -SET(VEYON_DEBUG_LIBRARIES Qt5::Test) -ENDIF() +if(VEYON_BUILD_ANDROID) + set(CMAKE_INSTALL_PREFIX "/") + set(VEYON_LIB_DIR "lib") + set(VEYON_INSTALL_PLUGIN_DIR "${VEYON_LIB_DIR}/veyon") + set(VEYON_INSTALL_DATA_DIR "${CMAKE_INSTALL_DATADIR}/veyon") + set(VEYON_PLUGIN_DIR "") + set(VEYON_TRANSLATIONS_DIR "/translations") +else() + if(CMAKE_INSTALL_LIBDIR) + set(VEYON_LIB_DIR "${CMAKE_INSTALL_LIBDIR}/veyon" CACHE INTERNAL "Veyon library directory") + else() + set(VEYON_LIB_DIR lib/veyon CACHE INTERNAL "Veyon library directory") + endif() + + set(VEYON_INSTALL_PLUGIN_DIR "${VEYON_LIB_DIR}") + set(VEYON_INSTALL_DATA_DIR "${CMAKE_INSTALL_DATADIR}/veyon") + + if(WIN32) + set(VEYON_PLUGIN_DIR "plugins") + set(VEYON_TRANSLATIONS_DIR "translations") + else() + set(VEYON_PLUGIN_DIR "../${VEYON_LIB_DIR}") + set(VEYON_TRANSLATIONS_DIR "../share/veyon/translations") + endif() +endif() + + +# find required Qt modules +option(WITH_QT6 "Build for Qt 6" ON) +if(WITH_QT6) + set(QT_MAJOR_VERSION 6) + find_package(Qt6 COMPONENTS + Core + Core5Compat + Concurrent + Gui + Widgets + Network + Quick + QuickControls2 + REQUIRED) + if(WITH_TRANSLATIONS) + find_package(Qt6 COMPONENTS LinguistTools REQUIRED) + endif() + if(VEYON_BUILD_ANDROID) + find_package(Qt6 COMPONENTS AndroidExtras REQUIRED) + endif() +else() + set(QT_MAJOR_VERSION 5) + find_package(Qt5Core REQUIRED) + find_package(Qt5Concurrent REQUIRED) + find_package(Qt5Gui REQUIRED) + find_package(Qt5Widgets REQUIRED) + find_package(Qt5Network REQUIRED) + find_package(Qt5Quick REQUIRED) + find_package(Qt5QuickControls2 REQUIRED) + if(WITH_TRANSLATIONS) + find_package(Qt5LinguistTools REQUIRED) + endif() + if(VEYON_BUILD_ANDROID) + find_package(Qt5AndroidExtras REQUIRED) + endif() +endif() # find required libraries -FIND_PACKAGE(ZLIB REQUIRED) -FIND_PACKAGE(PNG REQUIRED) -FIND_PACKAGE(JPEG REQUIRED) -FIND_PACKAGE(LZO REQUIRED) -FIND_PACKAGE(QCA REQUIRED) - -# FindOpenSSL.cmake in recent versions of CMake will only find the DLLs instead -# of the import libraries if CYGWIN is not set -SET(CYGWIN TRUE) -FIND_PACKAGE(OpenSSL REQUIRED) -UNSET(CYGWIN) +find_package(Qca-qt${QT_MAJOR_VERSION} REQUIRED) +find_package(OpenSSL REQUIRED) # find Linux-specific packages -IF(VEYON_BUILD_LINUX) - INCLUDE(XdgInstall) -ENDIF() - - -### BEGIN: libvncclient configuration -CHECK_INCLUDE_FILES(endian.h LIBVNCSERVER_HAVE_ENDIAN_H) -CHECK_INCLUDE_FILES(limits.h LIBVNCSERVER_HAVE_LIMITS_H) -CHECK_INCLUDE_FILES(time.h LIBVNCSERVER_HAVE_TIME_H) -CHECK_INCLUDE_FILES(unistd.h LIBVNCSERVER_HAVE_UNISTD_H) -CHECK_INCLUDE_FILES(ws2tcpip.h LIBVNCSERVER_HAVE_WS2TCPIP_H) -CHECK_INCLUDE_FILES(netinet/in.h LIBVNCSERVER_HAVE_NETINET_IN_H) -CHECK_INCLUDE_FILES(sys/endian.h LIBVNCSERVER_HAVE_SYS_ENDIAN_H) -CHECK_INCLUDE_FILES(sys/socket.h LIBVNCSERVER_HAVE_SYS_SOCKET_H) -CHECK_INCLUDE_FILES(sys/stat.h LIBVNCSERVER_HAVE_SYS_STAT_H) -CHECK_INCLUDE_FILES(sys/time.h LIBVNCSERVER_HAVE_SYS_TIME_H) -CHECK_INCLUDE_FILES(sys/timeb.h LIBVNCSERVER_HAVE_SYS_TIMEB_H) -CHECK_INCLUDE_FILES(sys/types.h LIBVNCSERVER_HAVE_SYS_TYPES_H) - -IF(LIBVNCSERVER_HAVE_SYS_SOCKET_H) - LIST(APPEND CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h") -ENDIF() - -CHECK_TYPE_SIZE("pid_t" LIBVNCSERVER_PID_T) -CHECK_TYPE_SIZE("size_t" LIBVNCSERVER_SIZE_T) -CHECK_TYPE_SIZE("socklen_t" LIBVNCSERVER_SOCKLEN_T) - -SET(_RFB_RFBCONFIG_H TRUE) -SET(LIBVNCSERVER_HAVE_LIBJPEG TRUE) -SET(LIBVNCSERVER_HAVE_LZO TRUE) -SET(LIBVNCSERVER_HAVE_LIBPNG TRUE) -SET(LIBVNCSERVER_HAVE_LIBZ TRUE) -SET(LIBVNCSERVER_HAVE_LIBSSL TRUE) -SET(LIBVNCSERVER_IPv6 TRUE) - -IF(VEYON_BUILD_WIN32) - SET(LIBVNCSERVER_NEED_INADDR_T TRUE) -ENDIF() - -FILE(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/${VEYON_CORE_INCLUDE_DIR}/rfb) -IF(NOT VEYON_BUILD_LINUX OR VEYON_X11VNC_EXTERNAL) - CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/3rdparty/libvncserver/rfb/rfbconfig.h.cmakein ${CMAKE_BINARY_DIR}/${VEYON_CORE_INCLUDE_DIR}/rfb/rfbconfig.h @ONLY) -ENDIF() - -### END: libvncclient configuration - - -IF(SANITIZE) -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread -fsanitize=undefined") -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=thread -fsanitize=undefined") -ENDIF() - -IF(LTO) -SET(LTO_FLAGS "-flto=4") -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LTO_FLAGS}") -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LTO_FLAGS}") -SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LTO_FLAGS}") -SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LTO_FLAGS}") -SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LTO_FLAGS}") -ENDIF() - -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fno-exceptions -std=c++11 -fstack-protector-strong ${CXXFLAGS}") -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fstack-protector-strong ${CFLAGS}") -IF(NOT VEYON_BUILD_WIN32) - SET(SYS_INC SYSTEM) -ENDIF() - -ADD_DEFINITIONS(-DQT_DEPRECATED_WARNINGS -DQT_DISABLE_DEPRECATED_BEFORE=0x050600 -D_FORTIFY_SOURCE=2 -DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII -DQT_NO_CAST_FROM_BYTEARRAY) - -FILE(GLOB_RECURSE IN_FILES RELATIVE ${CMAKE_SOURCE_DIR} "*config.h.in" "*.rc.in" "*.desktop.in" "*.policy.in" "*.service.in" "*.manifest.in" "*.nsi.in") -CONFIGURE_FILES(${IN_FILES}) - -SET(CMAKE_AUTOMOC TRUE) -SET(CMAKE_AUTOUIC TRUE) -SET(CMAKE_AUTORCC TRUE) - -SET(3rdparty_DIR ${CMAKE_SOURCE_DIR}/3rdparty) -SET(ultravnc_DIR ${3rdparty_DIR}/ultravnc) -SET(libvncserver_DIR ${3rdparty_DIR}/libvncserver) -SET(x11vnc_DIR ${3rdparty_DIR}/x11vnc) - -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/${VEYON_CORE_INCLUDE_DIR} ${CMAKE_BINARY_DIR}/${VEYON_CORE_INCLUDE_DIR} ${libvncserver_DIR}) -INCLUDE_DIRECTORIES(${SYS_INC} ${ZLIB_INCLUDE_DIR} ${JPEG_INCLUDE_DIR} ${PNG_INCLUDE_DIR} ${QCA_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${LZO_INCLUDE_DIR}) - -LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/core) - -SET(CMAKE_SKIP_BUILD_RPATH FALSE) -SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) -SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${VEYON_LIB_DIR}") -SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) +if(VEYON_BUILD_LINUX) + include(XdgInstall) +endif() + +if(${CMAKE_VERSION} VERSION_LESS "3.16.0") + set(WITH_PCH OFF) + set(WITH_UNITY_BUILD OFF) +elseif(WITH_UNITY_BUILD) + set(CMAKE_UNITY_BUILD ON) +endif() + +if(VEYON_BUILD_WIN32) + set(WITH_LTO OFF) +endif() + +if(WITH_LTO) + include(ProcessorCount) + ProcessorCount(CPU_COUNT) + set(GCC_LTO_FLAGS "-flto=${CPU_COUNT} -fno-fat-lto-objects") +endif() + +if(WITH_FUZZERS) + set(WITH_TESTS ON) +endif() + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong ${CFLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-strong -fno-exceptions ${CXXFLAGS}") + +if(NOT VEYON_DEBUG AND NOT CMAKE_C_FLAGS MATCHES "FORTIFY_SOURCE" AND NOT CMAKE_CXX_FLAGS MATCHES "FORTIFY_SOURCE") + add_definitions(-D_FORTIFY_SOURCE=2) +endif() + +if(WITH_TESTS) + enable_testing(TRUE) + if(WITH_QT6) + find_package(Qt6 COMPONENTS Test REQUIRED) + else() + find_package(Qt5Test REQUIRED) + endif() + set(VEYON_WITH_TESTS ON) +else() + set(CMAKE_C_VISIBILITY_PRESET hidden) + set(CMAKE_CXX_VISIBILITY_PRESET hidden) + set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) +endif() + +add_definitions( + -DQT_DEPRECATED_WARNINGS + -DQT_DISABLE_DEPRECATED_BEFORE=0x050e00 + -DQT_NO_CAST_FROM_ASCII + -DQT_NO_CAST_TO_ASCII + -DQT_NO_CAST_FROM_BYTEARRAY + -DQT_NO_KEYWORDS + -DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT + -DQT_USE_QSTRINGBUILDER + -DQT_STRICT_ITERATORS + ) + +file(GLOB_RECURSE IN_FILES RELATIVE ${CMAKE_SOURCE_DIR} "veyonconfig.h.in" "*.rc.in" "*.desktop.in" "*.policy.in" "*.service.in" "*.manifest.in" "*.nsi.in") +configure_files(${IN_FILES}) + +set(CMAKE_AUTOMOC TRUE) +set(CMAKE_AUTOUIC TRUE) +set(CMAKE_AUTORCC TRUE) + +set(3rdparty_DIR ${CMAKE_SOURCE_DIR}/3rdparty) +set(ultravnc_DIR ${3rdparty_DIR}/ultravnc) +set(libvncserver_DIR ${3rdparty_DIR}/libvncserver) +set(x11vnc_DIR ${3rdparty_DIR}/x11vnc) +set(libfakekey_DIR ${3rdparty_DIR}/libfakekey) +set(qthttpserver_DIR ${3rdparty_DIR}/qthttpserver) + +set(CMAKE_SKIP_BUILD_RPATH FALSE) +set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) +set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${VEYON_LIB_DIR}") +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + +if(VEYON_BUILD_ANDROID) + include(AndroidDeployQt) + set(_CMAKE_ANDROID_DIR "${CMAKE_SOURCE_DIR}/android") + set(ANDROID_INSTALL_DIR "${CMAKE_BINARY_DIR}/install") + set(ANDROID_EXTRA_PLUGINS ${ANDROID_INSTALL_DIR}/${VEYON_LIB_DIR}/veyon/ ${QT_DIR}/lib/qca-qt5/crypto ${ANDROID_INSTALL_DIR}/jar) + set(ANDROID_EXTRA_LIBS) + list(APPEND ANDROID_EXTRA_LIBS "${ANDROID_SYSROOT_GENERIC}/libc++_shared.so") + list(APPEND ANDROID_EXTRA_LIBS "${QT_DIR}/lib/libldap.so" + "${QT_DIR}/lib/liblber.so" + "${QT_DIR}/lib/libsasl2.so") + + add_custom_target(prepare-apk + COMMAND rm -rf ${ANDROID_INSTALL_DIR} + COMMAND cd ${CMAKE_BINARY_DIR}/core && make DESTDIR=${ANDROID_INSTALL_DIR} install + COMMAND cd ${CMAKE_BINARY_DIR}/plugins && make DESTDIR=${ANDROID_INSTALL_DIR} install + ) +endif() + + +include(cmake/CPackDefinitions.cmake) + # make sub-directories -ADD_SUBDIRECTORY(core) -ADD_SUBDIRECTORY(server) -ADD_SUBDIRECTORY(service) -ADD_SUBDIRECTORY(master) -ADD_SUBDIRECTORY(configurator) -ADD_SUBDIRECTORY(cli) -ADD_SUBDIRECTORY(worker) -ADD_SUBDIRECTORY(plugins) -ADD_SUBDIRECTORY(translations) +add_subdirectory(core) +if(NOT WITH_CORE_ONLY) + add_subdirectory(server) + add_subdirectory(service) + add_subdirectory(master) + add_subdirectory(configurator) + add_subdirectory(cli) + add_subdirectory(worker) + add_subdirectory(plugins) + add_subdirectory(tests) + add_subdirectory(translations) +endif() +if(WITH_ADDONS) + add_subdirectory(addons) +endif() # -# add target for generating Windows installer +# add Windows installer related targets # - -IF(WIN32) - SET(TMP "veyon-${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_BUILD}") - - SET(DLLDIR "${MINGW_PREFIX}/bin") - SET(DLLDIR_LIB "${MINGW_PREFIX}/lib") - SET(DLLDIR_GCC "/usr/lib/gcc/${MINGW_TARGET}/${COMPILER_VERSION_MAJOR_MINOR}-win32") - IF(VEYON_BUILD_WIN64) - SET(DLL_GCC "libgcc_s_seh-1.dll") - SET(DLL_DDENGINE "ddengine64.dll") - ELSE() - SET(DLL_GCC "libgcc_s_sjlj-1.dll") - SET(DLL_DDENGINE "ddengine.dll") - ENDIF() - - ADD_CUSTOM_TARGET(win-nsi - COMMAND make - COMMAND rm -rf ${TMP} - COMMAND mkdir -p ${TMP}/interception - COMMAND cp ${CMAKE_SOURCE_DIR}/3rdparty/interception/* ${TMP}/interception - COMMAND cp ${CMAKE_SOURCE_DIR}/3rdparty/ddengine/${DLL_DDENGINE} ${TMP} - COMMAND cp core/veyon-core.dll server/veyon-server.exe service/veyon-service.exe plugins/vncserver/ultravnc-builtin/vnchooks/vnchooks.dll master/veyon-master.exe configurator/veyon-configurator.exe cli/*.exe worker/veyon-worker.exe ${TMP} - COMMAND mkdir -p ${TMP}/plugins - COMMAND find plugins/ -name '*.dll' -exec cp '{}' ${TMP}/plugins/ '\;' - COMMAND mv ${TMP}/plugins/lib*.dll ${TMP} - COMMAND mkdir -p ${TMP}/translations - COMMAND cp translations/*qm ${TMP}/translations/ - COMMAND cp ${DLLDIR}/libjpeg-62.dll ${TMP} - COMMAND cp ${DLLDIR}/libpng16-16.dll ${TMP} - COMMAND cp ${DLLDIR}/libcrypto-1_1*.dll ${DLLDIR}/libssl-1_1*.dll ${TMP} - COMMAND cp ${DLLDIR}/libqca-qt5.dll ${TMP} - COMMAND cp ${DLLDIR}/libsasl2-3.dll ${TMP} - COMMAND cp ${DLLDIR}/libldap.dll ${DLLDIR}/liblber.dll ${TMP} - COMMAND cp ${DLLDIR}/interception.dll ${TMP} - COMMAND cp ${DLLDIR}/liblzo2-2.dll ${TMP} - COMMAND cp ${DLLDIR_LIB}/zlib1.dll ${TMP} - COMMAND cp ${DLLDIR_LIB}/libwinpthread-1.dll ${TMP} - COMMAND cp ${DLLDIR_GCC}/libstdc++-6.dll ${TMP} - COMMAND cp ${DLLDIR_GCC}/libssp-0.dll ${TMP} - COMMAND cp ${DLLDIR_GCC}/${DLL_GCC} ${TMP} - COMMAND mkdir -p ${TMP}/crypto - COMMAND cp ${DLLDIR_LIB}/qca-qt5/crypto/libqca-ossl.dll ${TMP}/crypto - COMMAND cp ${DLLDIR}/Qt5Core.dll ${DLLDIR}/Qt5Gui.dll ${DLLDIR}/Qt5Widgets.dll ${DLLDIR}/Qt5Network.dll ${DLLDIR}/Qt5Concurrent.dll ${TMP} - COMMAND mkdir -p ${TMP}/platforms - COMMAND cp ${DLLDIR_LIB}/qt5/plugins/platforms/qwindows.dll ${TMP}/platforms - COMMAND mkdir -p ${TMP}/styles - COMMAND cp ${DLLDIR_LIB}/qt5/plugins/styles/*.dll ${TMP}/styles - COMMAND ${STRIP} ${TMP}/*.dll ${TMP}/*.exe ${TMP}/plugins/*.dll ${TMP}/platforms/*.dll ${TMP}/styles/*.dll ${TMP}/crypto/*.dll - COMMAND cp ${CMAKE_SOURCE_DIR}/COPYING ${TMP} - COMMAND cp ${CMAKE_SOURCE_DIR}/COPYING ${TMP}/LICENSE.TXT - COMMAND cp ${CMAKE_SOURCE_DIR}/README.md ${TMP}/README.TXT - COMMAND todos ${TMP}/*.TXT - COMMAND cp nsis/veyon.nsi ${TMP} - COMMAND makensis ${TMP}/veyon.nsi - COMMAND mv ${TMP}/veyon-*setup.exe . - #COMMAND rm -rf ${TMP} - ) -ENDIF() +if(WIN32) + include(WindowsInstaller) +endif() # # package generation # -INCLUDE(cmake/CPackDefinitions.cmake) +include(CPack) @@ -336,37 +341,17 @@ INCLUDE(cmake/CPackDefinitions.cmake) # display configuration information # -MESSAGE("\n" -"Veyon build summary\n" -"--------------------\n" -"* Version : ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_BUILD} (${VERSION_STRING})\n" -"* Install prefix : ${CMAKE_INSTALL_PREFIX}\n" -"* Library directory : ${CMAKE_INSTALL_PREFIX}/${VEYON_LIB_DIR}\n" -"* Plugin directory : ${CMAKE_INSTALL_PREFIX}/${VEYON_INSTALL_PLUGIN_DIR}\n" -"* Build type : ${CMAKE_BUILD_TYPE}\n" -"* Build platform : ${CMAKE_SYSTEM_PROCESSOR}\n" -"* Compile flags : ${CMAKE_C_FLAGS} (CXX: ${CMAKE_CXX_FLAGS})\n" -) - -IF(VEYON_BUILD_ANDROID) - INCLUDE(AndroidDeployQt) - SET(CMAKE_ANDROID_DIR "${CMAKE_SOURCE_DIR}/android") - SET(_CMAKE_ANDROID_DIR "${CMAKE_ANDROID_DIR}") - SET(ANDROID_INSTALL_DIR "${CMAKE_BINARY_DIR}/install") - SET(ANDROID_EXTRA_PLUGINS ${ANDROID_INSTALL_DIR}/${VEYON_LIB_DIR}/veyon/ ${QT_DIR}/lib/qca-qt5/crypto) - FILE(GLOB ANDROID_EXTRA_LIBS ${ANDROID_INSTALL_DIR}/${VEYON_LIB_DIR}/*.so) - LIST(APPEND ANDROID_EXTRA_LIBS "${ANDROID_SYSROOT_GENERIC}/libc++_shared.so") - LIST(APPEND ANDROID_EXTRA_LIBS "${QT_DIR}/lib/libldap.so" - "${QT_DIR}/lib/liblber.so" - "${QT_DIR}/lib/libsasl2.so") - androiddeployqt("veyon-master" "${ANDROID_ADDITIONAL_FIND_ROOT_PATH};${CMAKE_BINARY_DIR}/core") - SET_TARGET_PROPERTIES(create-apk-veyon-master PROPERTIES ANDROID_APK_DIR "${CMAKE_ANDROID_DIR}") - - add_custom_target(prepare-apk - COMMAND rm -rf ${ANDROID_INSTALL_DIR} - COMMAND cd ${CMAKE_BINARY_DIR}/core && make DESTDIR=${ANDROID_INSTALL_DIR} install - COMMAND cd ${CMAKE_BINARY_DIR}/plugins && make DESTDIR=${ANDROID_INSTALL_DIR} install +message("\n" + "Veyon build summary\n" + "--------------------\n" + "* Version : ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_BUILD} (${VERSION_STRING})\n" + "* Install prefix : ${CMAKE_INSTALL_PREFIX}\n" + "* Library directory : ${CMAKE_INSTALL_PREFIX}/${VEYON_LIB_DIR}\n" + "* Plugin directory : ${CMAKE_INSTALL_PREFIX}/${VEYON_INSTALL_PLUGIN_DIR}\n" + "* Build type : ${CMAKE_BUILD_TYPE}\n" + "* Build platform : ${CMAKE_SYSTEM_PROCESSOR}\n" + "* Compile flags : ${CMAKE_C_FLAGS} (CXX: ${CMAKE_CXX_FLAGS})\n" + "* Link-time optimization : ${WITH_LTO}\n" + "* Use precompiled headers : ${WITH_PCH}\n" + "* Use unity build : ${WITH_UNITY_BUILD}\n" ) - - add_dependencies(create-apk-veyon-master prepare-apk) -ENDIF() diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..18c914718 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/README.md b/README.md index 3d068c2a7..21deab64e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Veyon - Virtual Eye On Networks -[![Build status](https://img.shields.io/travis/veyon/veyon.svg)](https://travis-ci.org/veyon/veyon) +[![.github/workflows/build.yml](https://github.com/veyon/veyon/actions/workflows/build.yml/badge.svg)](https://github.com/veyon/veyon/actions/workflows/build.yml) [![Latest stable release](https://img.shields.io/github/release/veyon/veyon.svg?maxAge=3600)](https://github.com/veyon/veyon/releases) [![Overall downloads on Github](https://img.shields.io/github/downloads/veyon/veyon/total.svg?maxAge=3600)](https://github.com/veyon/veyon/releases) [![Documentation Status](https://readthedocs.org/projects/veyon/badge/?version=latest)](https://docs.veyon.io/) @@ -10,27 +10,27 @@ ## What is Veyon? -Veyon is a free and open source software for computer monitoring and classroom -management supporting Windows and Linux. It enables teachers to view and control -computer labs and interact with students. Veyon is available in different -languages and provides lots of useful features: +Veyon is a free and open source software for monitoring and controlling +computers across multiple platforms. Veyon supports you in teaching in digital +learning environments, performing virtual trainings or giving remote support. - * see what's going on in computer labs in overview mode and take screenshots - * remote control computers to support and help users - * broadcast teacher's screen to students in realtime by using demo mode - (either in fullscreen or in a window) - * lock workstations for attracting attention to teacher - * send text messages to students - * powering on/off and rebooting computers remote - * remote logoff and remote execution of arbitrary commands/scripts - * home schooling - Veyon's network technology is not restricted to a subnet - and therefore students at home can join lessons via VPN connections just by - installing the Veyon service +The following features are available in Veyon: + + * Overview: monitor all computers in one or multiple locations or classrooms + * Remote access: view or control computers to watch and support users + * Demo: broadcast the teacher's screen in realtime (fullscreen/window) + * Screen lock: draw attention to what matters right now + * Communication: send text messages to students + * Start and end lessons: log in and log out users all at once + * Screenshots: record learning progress and document infringements + * Programs & websites: launch programs and open website URLs remotely + * Teaching material: distribute and open documents, images and videos easily + * Administration: power on/off and reboot computers remotely ## License -Copyright (c) 2004-2019 Tobias Junghans / Veyon Solutions. +Copyright (c) 2004-2025 Tobias Junghans / Veyon Solutions. See the file COPYING for the GNU GENERAL PUBLIC LICENSE. @@ -60,33 +60,35 @@ First grab the latest sources by cloning the Git repository and fetching all sub Requirements for Debian-based distributions: -- Build tools: g++ make cmake -- Qt5: qtbase5-dev qtbase5-dev-tools qttools5-dev qttools5-dev-tools -- X11: xorg-dev libxtst-dev +- Build tools: g++ libc6-dev make cmake dpkg-dev +- Qt5: qtbase5-dev qtbase5-private-dev qtbase5-dev-tools qttools5-dev qttools5-dev-tools qtdeclarative5-dev qtquickcontrols2-5-dev +- X11: xorg-dev libxtst-dev libfakekey-dev - libjpeg: libjpeg-dev provided by libjpeg-turbo8-dev or libjpeg62-turbo-dev - zlib: zlib1g-dev - OpenSSL: libssl-dev - PAM: libpam0g-dev - procps: libprocps-dev - LZO: liblzo2-dev -- QCA: libqca2-dev libqca-qt5-2-dev +- QCA: libqca-qt5-2-dev - LDAP: libldap2-dev - SASL: libsasl2-dev As root you can run - apt install g++ make cmake qtbase5-dev qtbase5-dev-tools qttools5-dev qttools5-dev-tools \ + apt install g++ libc6-dev make cmake qtbase5-dev qtbase5-private-dev \ + qtbase5-dev-tools qttools5-dev qttools5-dev-tools \ + qtdeclarative5-dev qtquickcontrols2-5-dev libfakekey-dev \ xorg-dev libxtst-dev libjpeg-dev zlib1g-dev libssl-dev libpam0g-dev \ - libprocps-dev liblzo2-dev libqca2-dev libqca-qt5-2-dev libldap2-dev \ - libsasl2-dev + libprocps-dev liblzo2-dev libqca-qt5-2-dev libldap2-dev \ + libsasl2-dev ninja-build Requirements for RedHat-based distributions: - Build tools: gcc-c++ make cmake rpm-build -- Qt5: qt5-devel -- X11: libXtst-devel libXrandr-devel libXinerama-devel libXcursor-devel libXrandr-devel libXdamage-devel libXcomposite-devel libXfixes-devel +- Qt5: qt5-devel qt5-qtbase-private-devel +- X11: libXtst-devel libXrandr-devel libXinerama-devel libXcursor-devel libXrandr-devel libXdamage-devel libXcomposite-devel libXfixes-devel libfakekey-devel - libjpeg: libjpeg-turbo-devel - zlib: zlib-devel - OpenSSL: openssl-devel @@ -100,8 +102,8 @@ Requirements for RedHat-based distributions: As root you can run dnf install gcc-c++ make cmake rpm-build qt5-devel libXtst-devel libXrandr-devel libXinerama-devel libXcursor-devel \ - libXrandr-devel libXdamage-devel libXcomposite-devel libXfixes-devel libjpeg-turbo-devel zlib-devel \ - openssl-devel pam-devel procps-devel lzo-devel qca-devel qca-qt5-devel openldap-devel cyrus-sasl-devel + libXrandr-devel libXdamage-devel libXcomposite-devel libXfixes-devel libfakekey-devel libjpeg-turbo-devel zlib-devel \ + openssl-devel pam-devel procps-devel lzo-devel qca-devel qca-qt5-devel openldap-devel cyrus-sasl-devel ninja-build ### Configuring and building sources @@ -145,6 +147,16 @@ This PPA contains official Veyon packages for Ubuntu suitable for use both on de sudo add-apt-repository ppa:veyon/stable sudo apt-get update + +### openSUSE + +Veyon is available on official openSUSE Tumbleweed repository. + + sudo zypper in veyon + +For openSUSE Leap 15.2, use the unofficial package from Education repository. + + https://software.opensuse.org/package/veyon?search_term=veyon ## Join development @@ -152,6 +164,9 @@ If you are interested in Veyon, its programming, artwork, testing or something l Before starting the implementation of a new feature, please always open an issue at https://github.com/veyon/veyon/issues to start a discussion about your intended implementation. There may be different ideas, improvements, hints or maybe an already ongoing work on this feature. +## Join translation team + +Veyon and its documentation are translated at the Transifex platform. Please go to https://www.transifex.com/veyon-solutions/veyon and join the corresponding translation team. Please DO NOT submit pull requests for modified translation files since this would require manual Transifex synchronizations on our side. ## More information diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..520337358 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,14 @@ +# Security Policy + +## Supported Versions + +Usually, only the latest stable release series is provided with security updates. In addition, customers with maintenance contracts are provided with updates for the respective releases in use. + +| Version | Supported | +| ------- | ------------------ | +| 4.7.x | ✔️ | +| < 4.7.x | ❌ | + +## Reporting a Vulnerability + +If you have found a security-related bug in Veyon, please contact us via email at security@veyon.io to disclose the details about your findings. As soon as we learn about potential security vulnerabilities, we will work together to analyze and fix them as soon as possible. diff --git a/android/build.gradle b/android/build.gradle index 989d0792c..980b1d093 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -18,6 +18,8 @@ apply plugin: 'com.android.application' dependencies { implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) + implementation fileTree(dir: 'assets/jar', include: ['*.jar', '*.aar']) + implementation 'com.android.support:appcompat-v7:28.0.0' } android { diff --git a/android/deployment-file.json.in b/android/deployment-file.json.in index ddccc6f45..67b92ead3 100644 --- a/android/deployment-file.json.in +++ b/android/deployment-file.json.in @@ -10,6 +10,7 @@ "application-binary": "@EXECUTABLE_DESTINATION_PATH@", "stdcpp-path": "@ANDROID_STDCPP@", "sdkBuildToolsRevision": "@ANDROID_SDK_BUILD_TOOLS_REVISION@", + ##EXTRAPREFIXDIRS## ##EXTRALIBS## ##EXTRAPLUGINS## "android-package-source-directory": "@CMAKE_ANDROID_DIR@" diff --git a/android/specifydependencies.cmake b/android/specifydependencies.cmake index b59f6bc51..2bfde779f 100644 --- a/android/specifydependencies.cmake +++ b/android/specifydependencies.cmake @@ -66,6 +66,17 @@ if(extraplugins) set(extraplugins "\"android-extra-plugins\": \"${plugins}\",") endif() +set(extraPrefixDirs "") +foreach(prefix ${ANDROID_ADDITIONAL_FIND_ROOT_PATH}) + if (extraPrefixDirs) + set(extraPrefixDirs "${extraPrefixDirs}, \"${prefix}\"") + else() + set(extraPrefixDirs "\"${prefix}\"") + endif() +endforeach() + +set(extraprefixdirs "\"extraPrefixDirs\": [${extraPrefixDirs}],") + file(READ "${INPUT_FILE}" CONTENTS) #file(READ "stl" stl_contents) @@ -75,6 +86,7 @@ file(READ "${INPUT_FILE}" CONTENTS) string(REPLACE "##ANDROID_TOOL_PREFIX##" "${CMAKE_MATCH_1}" NEWCONTENTS "${CONTENTS}") string(REPLACE "##ANDROID_TOOLCHAIN_VERSION##" "${CMAKE_MATCH_2}" NEWCONTENTS "${NEWCONTENTS}") string(REPLACE "##ANDROID_COMPILER_PREFIX##" "${CMAKE_MATCH_3}" NEWCONTENTS "${NEWCONTENTS}") +string(REPLACE "##EXTRAPREFIXDIRS##" "${extraprefixdirs}" NEWCONTENTS "${NEWCONTENTS}") string(REPLACE "##EXTRALIBS##" "${extralibs}" NEWCONTENTS "${NEWCONTENTS}") string(REPLACE "##EXTRAPLUGINS##" "${extraplugins}" NEWCONTENTS "${NEWCONTENTS}") string(REPLACE "##CMAKE_CXX_STANDARD_LIBRARIES##" "${stl_contents}" NEWCONTENTS "${NEWCONTENTS}") diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index a26ab81aa..1c7254a65 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -1,19 +1,30 @@ -INCLUDE(BuildApplication) -INCLUDE(WindowsBuildHelpers) +include(BuildVeyonApplication) +include(WindowsBuildHelpers) -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src) -SET(cli_SOURCES src/main.cpp) +set(cli_SOURCES + src/main.cpp + src/ConfigCommands.cpp + src/ConfigCommands.h + src/FeatureCommands.cpp + src/FeatureCommands.h + src/PluginCommands.cpp + src/PluginCommands.h + src/ServiceControlCommands.cpp + src/ServiceControlCommands.h + src/ShellCommands.cpp + src/ShellCommands.h + ) -BUILD_APPLICATION(veyon-cli ${cli_SOURCES}) -TARGET_LINK_LIBRARIES(veyon-cli veyon-core Qt5::Network) +build_veyon_application(veyon-cli ${cli_SOURCES}) -ADD_WINDOWS_RESOURCE(veyon-cli ${CMAKE_CURRENT_BINARY_DIR}/veyon-cli.rc) -MAKE_CONSOLE_APP(veyon-cli) +target_compile_options(veyon-cli PRIVATE -Wno-date-time) -IF(VEYON_BUILD_WIN32) -BUILD_APPLICATION(veyon-wcli ${cli_SOURCES}) -TARGET_LINK_LIBRARIES(veyon-wcli veyon-core Qt5::Network) +add_windows_resource(veyon-cli ${CMAKE_CURRENT_BINARY_DIR}/veyon-cli.rc) +make_console_app(veyon-cli) -ADD_WINDOWS_RESOURCE(veyon-wcli ${CMAKE_CURRENT_BINARY_DIR}/veyon-wcli.rc) -MAKE_GRAPHICAL_APP(veyon-wcli) -ENDIF() +if(VEYON_BUILD_WINDOWS) + build_veyon_application(veyon-wcli ${cli_SOURCES}) + + add_windows_resource(veyon-wcli ${CMAKE_CURRENT_BINARY_DIR}/veyon-wcli.rc) + make_graphical_app(veyon-wcli) +endif() diff --git a/plugins/config/ConfigCommandLinePlugin.cpp b/cli/src/ConfigCommands.cpp similarity index 60% rename from plugins/config/ConfigCommandLinePlugin.cpp rename to cli/src/ConfigCommands.cpp index b013a46ca..e013a7100 100644 --- a/plugins/config/ConfigCommandLinePlugin.cpp +++ b/cli/src/ConfigCommands.cpp @@ -1,7 +1,7 @@ /* - * ConfigCommandLinePlugin.cpp - implementation of ConfigCommandLinePlugin class + * ConfigCommands.cpp - implementation of ConfigCommands class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -29,12 +29,12 @@ #include "CommandLineIO.h" #include "Configuration/JsonStore.h" -#include "ConfigCommandLinePlugin.h" +#include "ConfigCommands.h" #include "ConfigurationManager.h" #include "CryptoCore.h" -ConfigCommandLinePlugin::ConfigCommandLinePlugin( QObject* parent ) : +ConfigCommands::ConfigCommands( QObject* parent ) : QObject( parent ), m_commands( { { QStringLiteral("clear"), tr( "Clear system-wide Veyon configuration" ) }, @@ -51,23 +51,23 @@ ConfigCommandLinePlugin::ConfigCommandLinePlugin( QObject* parent ) : -QStringList ConfigCommandLinePlugin::commands() const +QStringList ConfigCommands::commands() const { return m_commands.keys(); } -QString ConfigCommandLinePlugin::commandHelp( const QString& command ) const +QString ConfigCommands::commandHelp( const QString& command ) const { return m_commands.value( command ); } -CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_clear( const QStringList& arguments ) +CommandLinePluginInterface::RunResult ConfigCommands::handle_clear( const QStringList& arguments ) { - Q_UNUSED(arguments); + Q_UNUSED(arguments) if( ConfigurationManager().clearConfiguration() ) { @@ -79,19 +79,27 @@ CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_clear( con -CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_list( const QStringList& arguments ) +CommandLinePluginInterface::RunResult ConfigCommands::handle_list( const QStringList& arguments ) { - Q_UNUSED(arguments); + auto listMode = ListMode::Values; - // clear global configuration - listConfiguration( VeyonCore::config().data(), {} ); + if( arguments.value( 0 ) == QLatin1String("defaults") ) + { + listMode = ListMode::Defaults; + } + else if( arguments.value( 0 ) == QLatin1String("types") ) + { + listMode = ListMode::Types; + } + + listConfiguration( listMode ); return NoResult; } -CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_import( const QStringList& arguments ) +CommandLinePluginInterface::RunResult ConfigCommands::handle_import( const QStringList& arguments ) { QString fileName = arguments.value( 0 ); @@ -105,7 +113,7 @@ CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_import( co return operationError( tr( "Configuration file is not readable!" ) ); } - Configuration::JsonStore xs( Configuration::JsonStore::System, fileName ); + Configuration::JsonStore xs(Configuration::Store::Scope::System, fileName); // merge configuration VeyonCore::config() += VeyonConfiguration( &xs ); @@ -115,7 +123,7 @@ CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_import( co -CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_export( const QStringList& arguments ) +CommandLinePluginInterface::RunResult ConfigCommands::handle_export( const QStringList& arguments ) { QString fileName = arguments.value( 0 ); @@ -136,14 +144,14 @@ CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_export( co } // write current configuration to output file - Configuration::JsonStore( Configuration::JsonStore::System, fileName ).flush( &VeyonCore::config() ); + Configuration::JsonStore(Configuration::Store::Scope::System, fileName).flush( &VeyonCore::config() ); return Successful; } -CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_get( const QStringList& arguments ) +CommandLinePluginInterface::RunResult ConfigCommands::handle_get( const QStringList& arguments ) { QString key = arguments.value( 0 ); @@ -173,7 +181,7 @@ CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_get( const -CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_set( const QStringList& arguments ) +CommandLinePluginInterface::RunResult ConfigCommands::handle_set( const QStringList& arguments ) { auto key = arguments.value( 0 ); auto value = arguments.value( 1 ); @@ -198,7 +206,14 @@ CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_set( const parentKey = keyParts.mid( 0, keyParts.size()-1).join( QLatin1Char('/') ); } - const auto valueType = VeyonCore::config().value( key, parentKey, {} ).userType(); + auto valueType = QMetaType::UnknownType; + const auto property = Configuration::Property::find( &VeyonCore::config(), key, parentKey ); + + if( property ) + { + valueType = static_cast( property->variantValue().userType() ); + } + QVariant configValue = value; if( type == QLatin1String("json") || @@ -209,7 +224,7 @@ CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_set( const else if( key.contains( QStringLiteral("password"), Qt::CaseInsensitive ) || type == QLatin1String("password") ) { - configValue = VeyonCore::cryptoCore().encryptPassword( value ); + configValue = VeyonCore::cryptoCore().encryptPassword( value.toUtf8() ); } else if( type == QLatin1String("list") || valueType == QMetaType::QStringList ) @@ -224,7 +239,7 @@ CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_set( const -CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_unset( const QStringList& arguments ) +CommandLinePluginInterface::RunResult ConfigCommands::handle_unset( const QStringList& arguments ) { QString key = arguments.value( 0 ); @@ -249,9 +264,9 @@ CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_unset( con -CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_upgrade( const QStringList& arguments ) +CommandLinePluginInterface::RunResult ConfigCommands::handle_upgrade( const QStringList& arguments ) { - Q_UNUSED(arguments); + Q_UNUSED(arguments) // upgrade already happened while loading plugins so only save upgraded configuration return applyConfiguration(); @@ -259,40 +274,50 @@ CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::handle_upgrade( c -void ConfigCommandLinePlugin::listConfiguration( const VeyonConfiguration::DataMap &map, - const QString &parentKey ) +void ConfigCommands::listConfiguration( ListMode listMode ) const { - for( auto it = map.begin(); it != map.end(); ++it ) - { - QString curParentKey = parentKey.isEmpty() ? it.key() : parentKey + QLatin1Char('/') + it.key(); + QTextStream stdoutStream( stdout ); + + const auto properties = VeyonCore::config().findChildren(); - if( it.value().type() == QVariant::Map ) + for( auto property : properties ) + { + if( property->flags().testFlag( Configuration::Property::Flag::Legacy ) ) { - listConfiguration( it.value().toMap(), curParentKey ); + continue; } - else + + stdoutStream << property->absoluteKey() << "="; + switch( listMode ) { - QString value = printableConfigurationValue( it.value() ); - if( value.isNull() ) - { - qWarning() << "Key" << it.key() << "has unknown value type:" << it.value(); - } - else - { - QTextStream( stdout ) << curParentKey << "=" << value << endl; - } + case ListMode::Values: + stdoutStream << printableConfigurationValue( property->variantValue() ); + break; + case ListMode::Defaults: + stdoutStream << printableConfigurationValue( property->defaultValue() ); + break; + case ListMode::Types: + stdoutStream << QStringLiteral("[%1]").arg( QString::fromLatin1( + property->defaultValue().typeName() ). + replace( QLatin1Char('Q'), QString() ).toLower() ); + break; } +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + stdoutStream << Qt::endl; +#else + stdoutStream << endl; +#endif } } -CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::applyConfiguration() +CommandLinePluginInterface::RunResult ConfigCommands::applyConfiguration() { ConfigurationManager configurationManager; if( configurationManager.saveConfiguration() == false || - configurationManager.applyConfiguration() == false ) + configurationManager.applyConfiguration() == false ) { return operationError( configurationManager.errorString() ); } @@ -302,30 +327,43 @@ CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::applyConfiguratio -QString ConfigCommandLinePlugin::printableConfigurationValue( const QVariant& value ) +QString ConfigCommands::printableConfigurationValue( const QVariant& value ) { - if( value.type() == QVariant::String || - value.type() == QVariant::Uuid || - value.type() == QVariant::UInt || - value.type() == QVariant::Bool ) + if (value.userType() == QMetaType::QString || + value.userType() == QMetaType::QUuid || + value.userType() == QMetaType::UInt || + value.userType() == QMetaType::Int || + value.userType() == QMetaType::Bool) { return value.toString(); } - else if( value.type() == QVariant::StringList ) + + if (value.userType() == QMetaType::QStringList) { return value.toStringList().join( QLatin1Char(';') ); } - else if( value.userType() == QMetaType::type( "QJsonArray" ) ) + + if( value.userType() == QMetaType::QJsonArray ) { return QString::fromUtf8( QJsonDocument( value.toJsonArray() ).toJson( QJsonDocument::Compact ) ); } + if( value.userType() == QMetaType::QJsonObject ) + { + return QString::fromUtf8( QJsonDocument( value.toJsonObject() ).toJson( QJsonDocument::Compact ) ); + } + + if( QMetaType( value.userType() ).flags().testFlag( QMetaType::IsEnumeration ) ) + { + return QString::number( value.toInt() ); + } + return {}; } -CommandLinePluginInterface::RunResult ConfigCommandLinePlugin::operationError( const QString& message ) +CommandLinePluginInterface::RunResult ConfigCommands::operationError( const QString& message ) { CommandLineIO::error( message ); diff --git a/plugins/config/ConfigCommandLinePlugin.h b/cli/src/ConfigCommands.h similarity index 81% rename from plugins/config/ConfigCommandLinePlugin.h rename to cli/src/ConfigCommands.h index b3cec06b0..d9f6b61ff 100644 --- a/plugins/config/ConfigCommandLinePlugin.h +++ b/cli/src/ConfigCommands.h @@ -1,7 +1,7 @@ /* - * ConfigCommandLinePlugin.h - declaration of ConfigCommandLinePlugin class + * ConfigCommands.h - declaration of ConfigCommands class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,18 +27,17 @@ #include "CommandLinePluginInterface.h" #include "VeyonConfiguration.h" -class ConfigCommandLinePlugin : public QObject, CommandLinePluginInterface, PluginInterface +class ConfigCommands : public QObject, CommandLinePluginInterface, PluginInterface { Q_OBJECT - Q_PLUGIN_METADATA(IID "io.veyon.Veyon.Plugins.ConfigCommandLineInterface") Q_INTERFACES(PluginInterface CommandLinePluginInterface) public: - explicit ConfigCommandLinePlugin( QObject* parent = nullptr ); - ~ConfigCommandLinePlugin() override = default; + explicit ConfigCommands( QObject* parent = nullptr ); + ~ConfigCommands() override = default; Plugin::Uid uid() const override { - return QStringLiteral("1bdb0d1c-f8eb-4d21-a093-d555a10f3975"); + return Plugin::Uid{ QStringLiteral("1bdb0d1c-f8eb-4d21-a093-d555a10f3975") }; } QVersionNumber version() const override @@ -79,7 +78,7 @@ class ConfigCommandLinePlugin : public QObject, CommandLinePluginInterface, Plug QStringList commands() const override; QString commandHelp( const QString& command ) const override; -public slots: +public Q_SLOTS: CommandLinePluginInterface::RunResult handle_clear( const QStringList& arguments ); CommandLinePluginInterface::RunResult handle_list( const QStringList& arguments ); CommandLinePluginInterface::RunResult handle_import( const QStringList& arguments ); @@ -90,8 +89,14 @@ public slots: CommandLinePluginInterface::RunResult handle_upgrade( const QStringList& arguments ); private: - void listConfiguration( const VeyonConfiguration::DataMap &map, - const QString &parentKey ); + enum class ListMode { + Values, + Defaults, + Types + }; + + void listConfiguration( ListMode listMode ) const; + CommandLinePluginInterface::RunResult applyConfiguration(); static QString printableConfigurationValue( const QVariant& value ); diff --git a/cli/src/FeatureCommands.cpp b/cli/src/FeatureCommands.cpp new file mode 100644 index 000000000..0edd1ff56 --- /dev/null +++ b/cli/src/FeatureCommands.cpp @@ -0,0 +1,323 @@ +/* + * FeatureCommands.cpp - implementation of FeatureCommands class + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include +#include +#include + +#include "AuthenticationManager.h" +#include "ComputerControlInterface.h" +#include "FeatureCommands.h" +#include "FeatureManager.h" +#include "PluginManager.h" + + +FeatureCommands::FeatureCommands( QObject* parent ) : + QObject( parent ), + m_commands( { + { listCommand(), tr( "List names of all available features" ) }, + { showCommand(), tr( "Show table with details of all available features" ) }, + { startCommand(), tr( "Start a feature on a remote host" ) }, + { stopCommand(), tr( "Stop a feature on a remote host" ) } + } ) +{ +} + + + +QStringList FeatureCommands::commands() const +{ + return m_commands.keys(); +} + + + +QString FeatureCommands::commandHelp( const QString& command ) const +{ + return m_commands.value( command ); +} + + + +CommandLinePluginInterface::RunResult FeatureCommands::handle_help( const QStringList& arguments ) +{ + const auto command = arguments.value( 0 ); + if( command.isEmpty() ) + { + error( tr("Please specify the command to display help for.") ); + return NoResult; + } + + if( command == listCommand() ) + { + printUsage( commandLineModuleName(), listCommand(), {}, {} ); + printDescription( tr("Displays a list with the names of all available features.") ); + return NoResult; + } + + if( command == showCommand() ) + { + printUsage( commandLineModuleName(), showCommand(), {}, {} ); + printDescription( tr("Displays a table with detailed information about all available features. " + "This information include a description, the UID, the name of the plugin " + "providing the respective feature and some other implementation-related details.") ); + return NoResult; + } + + if( command == startCommand() ) + { + printUsage( commandLineModuleName(), startCommand(), + { { tr("HOST ADDRESS"), {} }, { tr("FEATURE"), {} } }, + { { tr("ARGUMENTS"), {} } } ); + + printDescription( tr("Starts the specified feature on the specified host by connecting to " + "the Veyon Server running remotely. The feature can be specified by name " + "or UID. Use the ``show`` command to see all available features. " + "Depending on the feature, additional arguments (such as the text message to display) " + "encoded as a single JSON string have to be specified. Please refer to " + "the developer documentation for more information") ); + + printExamples( commandLineModuleName(), startCommand(), + { + { tr( "Lock the screen" ), + { QStringLiteral("192.168.1.2"), QStringLiteral("ScreenLock") } + }, + { tr( "Display a text message" ), + { QStringLiteral("192.168.1.2"), QStringLiteral("TextMessage"), + QStringLiteral("\"{\\\"text\\\":\\\"%1\\\"}\"").arg( tr("Test message") ) } + }, + { tr( "Start an application" ), + { QStringLiteral("192.168.1.2"), QStringLiteral("da9ca56a-b2ad-4fff-8f8a-929b2927b442"), + QStringLiteral("\"{\\\"applications\\\":\\\"notepad\\\"}\"") } + } + } ); + + return NoResult; + } + + if( command == stopCommand() ) + { + printUsage( commandLineModuleName(), stopCommand(), + { { tr("HOST ADDRESS"), {} }, { tr("FEATURE"), {} } }, {} ); + + printDescription( tr("Stops the specified feature on the specified host by connecting to " + "the Veyon Server running remotely. The feature can be specified by name " + "or UID. Use the ``show`` command to see all available features.") ); + + printExamples( commandLineModuleName(), stopCommand(), + { + { tr( "Unlock the screen" ), + { QStringLiteral("192.168.1.2"), QStringLiteral("ScreenLock") } + } + } ); + + return NoResult; + } + + error( tr("The specified command does not exist or no help is available for it.") ); + + return NoResult; +} + + +CommandLinePluginInterface::RunResult FeatureCommands::handle_list( const QStringList& arguments ) +{ + Q_UNUSED(arguments) + + FeatureManager featureManager; + for( const auto& feature : std::as_const(featureManager.features()) ) + { + print( feature.name() ); + } + + return NoResult; +} + + + +CommandLinePluginInterface::RunResult FeatureCommands::handle_show( const QStringList& arguments ) +{ + Q_UNUSED(arguments) + + FeatureManager featureManager; + const auto& features = featureManager.features(); + + TableHeader tableHeader( { tr("Name"), tr("Description"), tr("Master"), tr("Service"), tr("Worker"), tr("UID"), tr("Plugin") } ); + TableRows tableRows; + tableRows.reserve( features.count() ); + + for( const auto& feature : features ) + { + if( feature.testFlag( Feature::Flag::Meta) ) + { + continue; + } + + tableRows.append( { + feature.name(), + feature.displayName(), + feature.testFlag(Feature::Flag::Master) ? QLatin1String("x") : QString(), + feature.testFlag(Feature::Flag::Service) ? QLatin1String("x") : QString(), + feature.testFlag(Feature::Flag::Worker) ? QLatin1String("x") : QString(), +#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) + feature.uid().toString( QUuid::WithoutBraces ), +#else + VeyonCore::formattedUuid( feature.uid().toString() ), +#endif + VeyonCore::pluginManager().pluginName( featureManager.pluginUid(feature.uid()) ) + } ); + } + + std::sort( tableRows.begin(), tableRows.end(), []( const TableRow& a, const TableRow& b ) { + return a.first() < b.first(); + }) ; + + printTable( Table( tableHeader, tableRows ) ); + + return NoResult; +} + + + +CommandLinePluginInterface::RunResult FeatureCommands::handle_start( const QStringList& arguments ) +{ + return controlComputer( FeatureProviderInterface::Operation::Start, arguments ); +} + + + +CommandLinePluginInterface::RunResult FeatureCommands::handle_stop( const QStringList& arguments ) +{ + return controlComputer( FeatureProviderInterface::Operation::Stop, arguments ); +} + + + +CommandLinePluginInterface::RunResult FeatureCommands::controlComputer( FeatureProviderInterface::Operation operation, + const QStringList& arguments ) +{ + if( arguments.count() < 2 ) + { + return NotEnoughArguments; + } + + const auto host = arguments[0]; + const auto featureNameOrUid = arguments[1]; + const auto featureArguments = arguments.value(2); + + FeatureManager featureManager; + + Feature::Uid featureUid{featureNameOrUid}; + if( featureUid.isNull() ) + { + for( const auto& feature : featureManager.features() ) + { + if( feature.name() == featureNameOrUid ) + { + featureUid = feature.uid(); + break; + } + } + } + else if( featureManager.feature( featureUid ).isValid() == false ) + { + featureUid = Feature::Uid{}; + } + + if( featureUid.isNull() ) + { + error( tr("Invalid feature name or UID specified") ); + return InvalidArguments; + } + + QJsonParseError parseError; + const auto featureArgsJson = QJsonDocument::fromJson( featureArguments.toUtf8(), &parseError ); + + if( featureArguments.isEmpty() == false && parseError.error != QJsonParseError::NoError ) + { + error( tr("Error parsing the JSON-encoded arguments: %1").arg( parseError.errorString() ) ); + return InvalidArguments; + } + + if( VeyonCore::authenticationManager().initializeCredentials() == false || + VeyonCore::authenticationManager().initializedPlugin()->checkCredentials() == false ) + { + error( tr("Failed to initialize credentials") ); + return Failed; + } + + Computer computer; + computer.setHostAddress(host); + + auto computerControlInterface = ComputerControlInterface::Pointer::create( computer ); + computerControlInterface->start(); + + static constexpr auto ConnectTimeout = 30 * 1000; + QTimer timeoutTimer; + timeoutTimer.start( ConnectTimeout ); + + QEventLoop eventLoop; + connect( &timeoutTimer, &QTimer::timeout, &eventLoop, &QEventLoop::quit ); + connect( computerControlInterface.data(), &ComputerControlInterface::stateChanged, this, + [&]() { + if( computerControlInterface->state() == ComputerControlInterface::State::Connected ) + { + eventLoop.quit(); + } + } ); + + eventLoop.exec(); + + if( computerControlInterface->state() != ComputerControlInterface::State::Connected ) + { + error( tr("Could not establish a connection to host %1").arg( host ) ); + return Failed; + } + + featureManager.controlFeature( featureUid, operation, + featureArgsJson.toVariant().toMap(), + { computerControlInterface } ); + + static constexpr auto MessageQueueWaitTimeout = 10 * 1000; + static constexpr auto MessageQueuePollInterval = 10; + + QElapsedTimer messageQueueWaitTimer; + messageQueueWaitTimer.start(); + + while( computerControlInterface->isMessageQueueEmpty() == false && + messageQueueWaitTimer.elapsed() < MessageQueueWaitTimeout ) + { + QThread::msleep(MessageQueuePollInterval); + } + + if( messageQueueWaitTimer.elapsed() >= MessageQueueWaitTimeout ) + { + error( tr("Failed to send feature control message to host %1").arg( host ) ); + return Failed; + } + + return Successful; +} diff --git a/cli/src/FeatureCommands.h b/cli/src/FeatureCommands.h new file mode 100644 index 000000000..c0c0fe3a0 --- /dev/null +++ b/cli/src/FeatureCommands.h @@ -0,0 +1,114 @@ +/* + * FeatureCommands.h - declaration of FeatureCommands class + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "CommandLinePluginInterface.h" +#include "CommandLineIO.h" +#include "FeatureProviderInterface.h" + +class FeatureCommands : public QObject, CommandLinePluginInterface, PluginInterface, CommandLineIO +{ + Q_OBJECT + Q_INTERFACES(PluginInterface CommandLinePluginInterface) +public: + explicit FeatureCommands( QObject* parent = nullptr ); + ~FeatureCommands() override = default; + + Plugin::Uid uid() const override + { + return Plugin::Uid{ QStringLiteral("2376b972-0bf1-4f50-bcfd-79d4d90730c6") }; + } + + QVersionNumber version() const override + { + return QVersionNumber( 1, 0 ); + } + + QString name() const override + { + return QStringLiteral( "FeatureCommands" ); + } + + QString description() const override + { + return tr( "Feature-related CLI operations" ); + } + + QString vendor() const override + { + return QStringLiteral( "Veyon Community" ); + } + + QString copyright() const override + { + return QStringLiteral( "Tobias Junghans" ); + } + + QString commandLineModuleName() const override + { + return QStringLiteral( "feature" ); + } + + QString commandLineModuleHelp() const override + { + return tr( "Commands for controlling features" ); + } + + QStringList commands() const override; + QString commandHelp( const QString& command ) const override; + +public Q_SLOTS: + CommandLinePluginInterface::RunResult handle_help( const QStringList& arguments ); + CommandLinePluginInterface::RunResult handle_list( const QStringList& arguments ); + CommandLinePluginInterface::RunResult handle_show( const QStringList& arguments ); + CommandLinePluginInterface::RunResult handle_start( const QStringList& arguments ); + CommandLinePluginInterface::RunResult handle_stop( const QStringList& arguments ); + +private: + static QString listCommand() + { + return QStringLiteral("list"); + } + + static QString showCommand() + { + return QStringLiteral("show"); + } + + static QString startCommand() + { + return QStringLiteral("start"); + } + + static QString stopCommand() + { + return QStringLiteral("stop"); + } + + RunResult controlComputer( FeatureProviderInterface::Operation operation, const QStringList& arguments ); + + const QMap m_commands; + +}; diff --git a/cli/src/PluginCommands.cpp b/cli/src/PluginCommands.cpp new file mode 100644 index 000000000..a3ee3ac05 --- /dev/null +++ b/cli/src/PluginCommands.cpp @@ -0,0 +1,100 @@ +/* + * PluginsCommands.cpp - implementation of PluginsCommands class + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "PluginCommands.h" +#include "PluginManager.h" + + +PluginCommands::PluginCommands( QObject* parent ) : + QObject( parent ), + m_commands( { + { QStringLiteral("list"), tr( "List names of all installed plugins" ) }, + { QStringLiteral("show"), tr( "Show table with details of all installed plugins" ) }, + } ) +{ +} + + + +QStringList PluginCommands::commands() const +{ + return m_commands.keys(); +} + + + +QString PluginCommands::commandHelp( const QString& command ) const +{ + return m_commands.value( command ); +} + + + +CommandLinePluginInterface::RunResult PluginCommands::handle_list( const QStringList& arguments ) +{ + Q_UNUSED(arguments) + + const auto plugins = VeyonCore::pluginManager().pluginInterfaces(); + for( auto plugin : plugins ) + { + print( plugin->name() ); + } + + return NoResult; +} + + + +CommandLinePluginInterface::RunResult PluginCommands::handle_show( const QStringList& arguments ) +{ + Q_UNUSED(arguments) + + const auto plugins = VeyonCore::pluginManager().pluginInterfaces(); + + TableHeader tableHeader( { tr("Name"), tr("Description"), tr("Version"), tr("UID") } ); + TableRows tableRows; + tableRows.reserve( plugins.count() ); + + for( auto plugin : plugins ) + { + tableRows.append( { + plugin->name(), + plugin->description(), + plugin->version().toString(), +#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) + plugin->uid().toString( QUuid::WithoutBraces ) +#else + VeyonCore::formattedUuid( plugin->uid().toString() ) +#endif + } ); + } + + std::sort( tableRows.begin(), tableRows.end(), []( const TableRow& a, const TableRow& b ) { + return a.first() < b.first(); + }) ; + + printTable( Table( tableHeader, tableRows ) ); + + return NoResult; +} diff --git a/core/include/MonitoringMode.h b/cli/src/PluginCommands.h similarity index 51% rename from core/include/MonitoringMode.h rename to cli/src/PluginCommands.h index ee064153a..1d8af8317 100644 --- a/core/include/MonitoringMode.h +++ b/cli/src/PluginCommands.h @@ -1,7 +1,7 @@ /* - * MonitoringMode.h - header for the MonitoringMode class + * PluginsCommands.h - declaration of PluginsCommands class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,38 +24,35 @@ #pragma once -#include "SimpleFeatureProvider.h" +#include "CommandLinePluginInterface.h" +#include "CommandLineIO.h" -class MonitoringMode : public QObject, SimpleFeatureProvider, PluginInterface +class PluginCommands : public QObject, CommandLinePluginInterface, PluginInterface, CommandLineIO { Q_OBJECT - Q_INTERFACES(FeatureProviderInterface PluginInterface) + Q_INTERFACES(PluginInterface CommandLinePluginInterface) public: - explicit MonitoringMode( QObject* parent = nullptr ); - - const Feature& feature() const - { - return m_monitoringModeFeature; - } + explicit PluginCommands( QObject* parent = nullptr ); + ~PluginCommands() override = default; Plugin::Uid uid() const override { - return QStringLiteral("1a6a59b1-c7a1-43cc-bcab-c136a4d91be8"); + return Plugin::Uid{ QStringLiteral("cbea24b5-4f6b-446d-8f54-4f98ec796a8c") }; } QVersionNumber version() const override { - return QVersionNumber( 1, 1 ); + return QVersionNumber( 1, 0 ); } QString name() const override { - return QStringLiteral( "MonitoringMode" ); + return QStringLiteral( "Plugin" ); } QString description() const override { - return tr( "Builtin monitoring mode" ); + return tr( "Plugin-related CLI operations" ); } QString vendor() const override @@ -68,13 +65,24 @@ class MonitoringMode : public QObject, SimpleFeatureProvider, PluginInterface return QStringLiteral( "Tobias Junghans" ); } - const FeatureList& featureList() const override + QString commandLineModuleName() const override + { + return QStringLiteral( "plugin" ); + } + + QString commandLineModuleHelp() const override { - return m_features; + return tr( "Commands for managing plugins" ); } + QStringList commands() const override; + QString commandHelp( const QString& command ) const override; + +public Q_SLOTS: + CommandLinePluginInterface::RunResult handle_list( const QStringList& arguments ); + CommandLinePluginInterface::RunResult handle_show( const QStringList& arguments ); + private: - const Feature m_monitoringModeFeature; - const FeatureList m_features; + const QMap m_commands; }; diff --git a/plugins/servicecontrol/ServiceControlPlugin.cpp b/cli/src/ServiceControlCommands.cpp similarity index 71% rename from plugins/servicecontrol/ServiceControlPlugin.cpp rename to cli/src/ServiceControlCommands.cpp index c3cb64ebb..9a4ad1ae9 100644 --- a/plugins/servicecontrol/ServiceControlPlugin.cpp +++ b/cli/src/ServiceControlCommands.cpp @@ -1,7 +1,7 @@ /* - * ServiceControlPlugin.cpp - implementation of ServiceControlPlugin class + * ServiceControlCommands.cpp - implementation of ServiceControlCommands class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,10 +23,10 @@ */ #include "CommandLineIO.h" -#include "ServiceControlPlugin.h" +#include "ServiceControlCommands.h" #include "VeyonServiceControl.h" -ServiceControlPlugin::ServiceControlPlugin( QObject* parent ) : +ServiceControlCommands::ServiceControlCommands( QObject* parent ) : QObject( parent ), m_commands( { { QStringLiteral("register"), tr( "Register Veyon Service" ) }, @@ -41,7 +41,7 @@ ServiceControlPlugin::ServiceControlPlugin( QObject* parent ) : -CommandLinePluginInterface::RunResult ServiceControlPlugin::handle_register( const QStringList& arguments ) +CommandLinePluginInterface::RunResult ServiceControlCommands::handle_register( const QStringList& arguments ) { Q_UNUSED(arguments) @@ -53,7 +53,7 @@ CommandLinePluginInterface::RunResult ServiceControlPlugin::handle_register( con -CommandLinePluginInterface::RunResult ServiceControlPlugin::handle_unregister( const QStringList& arguments ) +CommandLinePluginInterface::RunResult ServiceControlCommands::handle_unregister( const QStringList& arguments ) { Q_UNUSED(arguments) VeyonServiceControl serviceControl; @@ -64,7 +64,7 @@ CommandLinePluginInterface::RunResult ServiceControlPlugin::handle_unregister( c -CommandLinePluginInterface::RunResult ServiceControlPlugin::handle_start( const QStringList& arguments ) +CommandLinePluginInterface::RunResult ServiceControlCommands::handle_start( const QStringList& arguments ) { Q_UNUSED(arguments) @@ -76,7 +76,7 @@ CommandLinePluginInterface::RunResult ServiceControlPlugin::handle_start( const -CommandLinePluginInterface::RunResult ServiceControlPlugin::handle_stop( const QStringList& arguments ) +CommandLinePluginInterface::RunResult ServiceControlCommands::handle_stop( const QStringList& arguments ) { Q_UNUSED(arguments) @@ -88,7 +88,7 @@ CommandLinePluginInterface::RunResult ServiceControlPlugin::handle_stop( const Q -CommandLinePluginInterface::RunResult ServiceControlPlugin::handle_restart( const QStringList& arguments ) +CommandLinePluginInterface::RunResult ServiceControlCommands::handle_restart( const QStringList& arguments ) { handle_stop( arguments ); return handle_start( arguments ); @@ -96,7 +96,7 @@ CommandLinePluginInterface::RunResult ServiceControlPlugin::handle_restart( cons -CommandLinePluginInterface::RunResult ServiceControlPlugin::handle_status( const QStringList& arguments ) +CommandLinePluginInterface::RunResult ServiceControlCommands::handle_status( const QStringList& arguments ) { Q_UNUSED(arguments) diff --git a/plugins/servicecontrol/ServiceControlPlugin.h b/cli/src/ServiceControlCommands.h similarity index 83% rename from plugins/servicecontrol/ServiceControlPlugin.h rename to cli/src/ServiceControlCommands.h index dd4c9bf5f..891186b53 100644 --- a/plugins/servicecontrol/ServiceControlPlugin.h +++ b/cli/src/ServiceControlCommands.h @@ -1,7 +1,7 @@ /* - * ServiceControlPlugin.h - declaration of ServiceControlPlugin class + * ServiceControlCommands.h - declaration of ServiceControlCommands class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,18 +26,17 @@ #include "CommandLinePluginInterface.h" -class ServiceControlPlugin : public QObject, CommandLinePluginInterface, PluginInterface +class ServiceControlCommands : public QObject, CommandLinePluginInterface, PluginInterface { Q_OBJECT - Q_PLUGIN_METADATA(IID "io.veyon.Veyon.Plugins.ServiceControl") Q_INTERFACES(PluginInterface CommandLinePluginInterface) public: - explicit ServiceControlPlugin( QObject* parent = nullptr ); - ~ServiceControlPlugin() override = default; + explicit ServiceControlCommands( QObject* parent = nullptr ); + ~ServiceControlCommands() override = default; Plugin::Uid uid() const override { - return QStringLiteral("b47bcae0-24ff-4bf5-869c-484d64af5c4c"); + return Plugin::Uid{ QStringLiteral("b47bcae0-24ff-4bf5-869c-484d64af5c4c") }; } QVersionNumber version() const override @@ -85,7 +84,7 @@ class ServiceControlPlugin : public QObject, CommandLinePluginInterface, PluginI return m_commands.value( command ); } -public slots: +public Q_SLOTS: CommandLinePluginInterface::RunResult handle_register( const QStringList& arguments ); CommandLinePluginInterface::RunResult handle_unregister( const QStringList& arguments ); CommandLinePluginInterface::RunResult handle_start( const QStringList& arguments ); diff --git a/plugins/shell/ShellCommandLinePlugin.cpp b/cli/src/ShellCommands.cpp similarity index 71% rename from plugins/shell/ShellCommandLinePlugin.cpp rename to cli/src/ShellCommands.cpp index 1ad467860..962d915ab 100644 --- a/plugins/shell/ShellCommandLinePlugin.cpp +++ b/cli/src/ShellCommands.cpp @@ -1,7 +1,7 @@ /* - * ShellCommandLinePlugin.cpp - implementation of ShellCommandLinePlugin class + * ShellCommands.cpp - implementation of ShellCommands class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,34 +27,34 @@ #include #include "CommandLineIO.h" -#include "ShellCommandLinePlugin.h" +#include "ShellCommands.h" -ShellCommandLinePlugin::ShellCommandLinePlugin( QObject* parent ) : +ShellCommands::ShellCommands( QObject* parent ) : QObject( parent ), m_commands( { -{ QStringLiteral("run"), tr( "Run command file" ) }, - } ) + { QStringLiteral("run"), tr( "Run command file" ) }, + } ) { } -QStringList ShellCommandLinePlugin::commands() const +QStringList ShellCommands::commands() const { return m_commands.keys(); } -QString ShellCommandLinePlugin::commandHelp( const QString& command ) const +QString ShellCommands::commandHelp( const QString& command ) const { return m_commands.value( command ); } -CommandLinePluginInterface::RunResult ShellCommandLinePlugin::handle_main() +CommandLinePluginInterface::RunResult ShellCommands::handle_main() { QTextStream stream( stdin ); @@ -78,7 +78,7 @@ CommandLinePluginInterface::RunResult ShellCommandLinePlugin::handle_main() -CommandLinePluginInterface::RunResult ShellCommandLinePlugin::handle_run( const QStringList& arguments ) +CommandLinePluginInterface::RunResult ShellCommands::handle_run( const QStringList& arguments ) { QFile scriptFile( arguments.value( 0 ) ); if( scriptFile.exists() == false ) @@ -97,7 +97,7 @@ CommandLinePluginInterface::RunResult ShellCommandLinePlugin::handle_run( const -void ShellCommandLinePlugin::runCommand( const QString& command ) +void ShellCommands::runCommand( const QString& command ) { // TODO: properly split arguments containing spaces QProcess::execute( QCoreApplication::applicationFilePath(), command.split( QLatin1Char(' ') ) ); diff --git a/plugins/shell/ShellCommandLinePlugin.h b/cli/src/ShellCommands.h similarity index 79% rename from plugins/shell/ShellCommandLinePlugin.h rename to cli/src/ShellCommands.h index d9cd10b2b..63e0c06c6 100644 --- a/plugins/shell/ShellCommandLinePlugin.h +++ b/cli/src/ShellCommands.h @@ -1,7 +1,7 @@ /* - * ShellCommandLinePlugin.h - declaration of ShellCommandLinePlugin class + * ShellCommands.h - declaration of ShellCommands class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,18 +26,17 @@ #include "CommandLinePluginInterface.h" -class ShellCommandLinePlugin : public QObject, CommandLinePluginInterface, PluginInterface +class ShellCommands : public QObject, CommandLinePluginInterface, PluginInterface { Q_OBJECT - Q_PLUGIN_METADATA(IID "io.veyon.Veyon.Plugins.ShellCommandLineInterface") Q_INTERFACES(PluginInterface CommandLinePluginInterface) public: - explicit ShellCommandLinePlugin( QObject* parent = nullptr ); - ~ShellCommandLinePlugin() override = default; + explicit ShellCommands( QObject* parent = nullptr ); + ~ShellCommands() override = default; Plugin::Uid uid() const override { - return QStringLiteral("85f6c631-e75a-4c78-8cb2-a7f3f502015a"); + return Plugin::Uid{ QStringLiteral("85f6c631-e75a-4c78-8cb2-a7f3f502015a") }; } QVersionNumber version() const override @@ -52,7 +51,7 @@ class ShellCommandLinePlugin : public QObject, CommandLinePluginInterface, Plugi QString description() const override { - return tr( "Interactive shell and script execution for Veyon Control" ); + return tr( "Interactive shell and script execution for Veyon CLI" ); } QString vendor() const override @@ -78,7 +77,7 @@ class ShellCommandLinePlugin : public QObject, CommandLinePluginInterface, Plugi QStringList commands() const override; QString commandHelp( const QString& command ) const override; -public slots: +public Q_SLOTS: CommandLinePluginInterface::RunResult handle_main(); CommandLinePluginInterface::RunResult handle_run( const QStringList& arguments ); diff --git a/cli/src/main.cpp b/cli/src/main.cpp index 6356e28e7..057430765 100644 --- a/cli/src/main.cpp +++ b/cli/src/main.cpp @@ -1,7 +1,7 @@ /* * main.cpp - main file for Veyon CLI * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,14 +26,19 @@ #include -#include "CommandLineIO.h" -#include "CommandLinePluginInterface.h" +#include "ConfigCommands.h" +#include "FeatureCommands.h" #include "Logger.h" +#include "PluginCommands.h" #include "PluginManager.h" +#include "ServiceControlCommands.h" +#include "ShellCommands.h" int main( int argc, char **argv ) { + VeyonCore::setupApplicationParameters(); + QCoreApplication* app = nullptr; #ifdef Q_OS_LINUX @@ -50,19 +55,19 @@ int main( int argc, char **argv ) app = new QApplication( argc, argv ); #endif - const auto arguments = app->arguments(); + const auto arguments = QCoreApplication::arguments(); if( arguments.count() == 2 ) { if( arguments.last() == QLatin1String("-v") || arguments.last() == QLatin1String("--version") ) { - CommandLineIO::print( VeyonCore::version() ); + CommandLineIO::print( VeyonCore::versionString() ); delete app; return 0; } - else if( arguments.last() == QLatin1String("about") ) + if( arguments.last() == QLatin1String("about") ) { - CommandLineIO::print( QStringLiteral("Veyon: %1 (%2)").arg( VeyonCore::version() ).arg( QLatin1String(__DATE__) ) ); + CommandLineIO::print( QStringLiteral("Veyon: %1 (%2)").arg( VeyonCore::versionString() ).arg( QLatin1String(__DATE__) ) ); CommandLineIO::print( QStringLiteral("Qt: %1 (built against %2/%3)"). arg( QLatin1String(qVersion() ) ). arg( QLatin1String(QT_VERSION_STR) ). @@ -79,10 +84,15 @@ int main( int argc, char **argv ) qputenv( Logger::logLevelEnvironmentVariable(), QByteArray::number( static_cast(Logger::LogLevel::Nothing) ) ); } - VeyonCore* core = new VeyonCore( app, QStringLiteral("CLI") ); + auto core = new VeyonCore( app, VeyonCore::Component::CLI, QStringLiteral("CLI") ); + VeyonCore::pluginManager().registerExtraPluginInterface( new ConfigCommands( core ) ); + VeyonCore::pluginManager().registerExtraPluginInterface( new FeatureCommands( core ) ); + VeyonCore::pluginManager().registerExtraPluginInterface( new PluginCommands( core ) ); + VeyonCore::pluginManager().registerExtraPluginInterface( new ServiceControlCommands( core ) ); + VeyonCore::pluginManager().registerExtraPluginInterface( new ShellCommands( core ) ); QHash commandLinePluginInterfaces; - const auto pluginObjects = core->pluginManager().pluginObjects(); + const auto pluginObjects = VeyonCore::pluginManager().pluginObjects(); for( auto pluginObject : pluginObjects ) { auto commandLinePluginInterface = qobject_cast( pluginObject ); @@ -128,8 +138,6 @@ int main( int argc, char **argv ) runResult = CommandLinePluginInterface::NotEnoughArguments; } - delete core; - switch( runResult ) { case CommandLinePluginInterface::NoResult: @@ -168,12 +176,13 @@ int main( int argc, char **argv ) { CommandLineIO::print( QStringLiteral(" %1 - %2").arg( command, it.key()->commandHelp( command ) ) ); } + + delete core; + delete app; return -1; } } - delete core; - int rc = -1; if( module == QLatin1String("help") ) @@ -197,6 +206,7 @@ int main( int argc, char **argv ) std::for_each( modulesHelpStrings.begin(), modulesHelpStrings.end(), [](const QString& s) { CommandLineIO::print( QStringLiteral( " " ) + s ); } ); + delete core; delete app; return rc; diff --git a/cli/veyon-cli.rc.in b/cli/veyon-cli.rc.in index 57625d407..aaa5a5028 100644 --- a/cli/veyon-cli.rc.in +++ b/cli/veyon-cli.rc.in @@ -1,10 +1,10 @@ #include -ID_MANIFEST RT_MANIFEST data/veyon-cli.exe.manifest +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST data/veyon-cli.exe.manifest VS_VERSION_INFO VERSIONINFO FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,@VERSION_BUILD@ - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGSMASK 0x0L FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_APP FILESUBTYPE VFT2_UNKNOWN @@ -16,11 +16,16 @@ BEGIN BEGIN VALUE "Comments", "Virtual Eye On Networks (https://veyon.io)\0" VALUE "CompanyName", "Veyon Solutions\0" + VALUE "ProductName", "Veyon\0" + VALUE "ProductVersion", "@VERSION_STRING@\0" VALUE "FileDescription", "Veyon Command Line Interface (console version)\0" VALUE "FileVersion", "@VERSION_STRING@\0" - VALUE "LegalCopyright", "Copyright (c) 2017-2019 Tobias Junghans\0" + VALUE "LegalCopyright", "Copyright (c) 2017-2025 Veyon Solutions / Tobias Junghans\0" VALUE "OriginalFilename", "veyon-cli.exe\0" - VALUE "ProductName", "Veyon\0" END END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04E4 + END END diff --git a/cli/veyon-wcli.rc.in b/cli/veyon-wcli.rc.in index d1a935681..5ba896b39 100644 --- a/cli/veyon-wcli.rc.in +++ b/cli/veyon-wcli.rc.in @@ -1,10 +1,10 @@ #include -ID_MANIFEST RT_MANIFEST data/veyon-wcli.exe.manifest +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST data/veyon-wcli.exe.manifest VS_VERSION_INFO VERSIONINFO FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,@VERSION_BUILD@ - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGSMASK 0x0L FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_APP FILESUBTYPE VFT2_UNKNOWN @@ -16,11 +16,16 @@ BEGIN BEGIN VALUE "Comments", "Virtual Eye On Networks (https://veyon.io)\0" VALUE "CompanyName", "Veyon Solutions\0" + VALUE "ProductName", "Veyon\0" + VALUE "ProductVersion", "@VERSION_STRING@\0" VALUE "FileDescription", "Veyon Command Line Interface (non-console version)\0" VALUE "FileVersion", "@VERSION_STRING@\0" - VALUE "LegalCopyright", "Copyright (c) 2017-2019 Tobias Junghans\0" + VALUE "LegalCopyright", "Copyright (c) 2017-2025 Veyon Solutions / Tobias Junghans\0" VALUE "OriginalFilename", "veyon-wcli.exe\0" - VALUE "ProductName", "Veyon\0" END END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04E4 + END END diff --git a/cmake/CPackDefinitions.cmake b/cmake/CPackDefinitions.cmake index ccc83e340..d9c11b3e8 100644 --- a/cmake/CPackDefinitions.cmake +++ b/cmake/CPackDefinitions.cmake @@ -1,113 +1,107 @@ -# -# generate packages -# -# Environment -if (NOT CPACK_SYSTEM_NAME) - set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_PROCESSOR}") -endif () - - # Basic information -SET(CPACK_PACKAGE_NAME "veyon") -SET(CPACK_PACKAGE_VERSION_MAJOR "${VERSION_MAJOR}") -SET(CPACK_PACKAGE_VERSION_MINOR "${VERSION_MINOR}") -SET(CPACK_PACKAGE_VERSION_PATCH "${VERSION_PATCH}") -set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") +if(NOT CPACK_PACKAGE_NAME) + set(CPACK_PACKAGE_NAME "veyon") +endif() +set(CPACK_PACKAGE_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_BUILD}") -SET(CPACK_PACKAGING_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") -SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}_${CPACK_SYSTEM_NAME}") -SET(CPACK_PACKAGE_CONTACT "Tobias Junghans ") -SET(CPACK_PACKAGE_HOMEPAGE "https://veyon.io") -SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Open source computer monitoring and classroom management") -# SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/DESCRIPTION") -SET(CPACK_PACKAGE_VENDOR "Veyon Solutions") -SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING") -SET(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md") -SET(CPACK_INCLUDE_TOPLEVEL_DIRECTORY TRUE) -SET(CPACK_SOURCE_IGNORE_FILES "${CMAKE_SOURCE_DIR}/build/;${CMAKE_SOURCE_DIR}/.git/;") -SET(CPACK_STRIP_FILES TRUE) +set(CPACK_PACKAGING_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") +set(CPACK_PACKAGE_CONTACT "Tobias Junghans ") +set(CPACK_PACKAGE_HOMEPAGE "https://veyon.io") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Cross-platform computer control and classroom management") +set(CPACK_PACKAGE_VENDOR "Veyon Solutions") +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING") +set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md") +set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY TRUE) +set(CPACK_SOURCE_IGNORE_FILES "${CMAKE_SOURCE_DIR}/build/;${CMAKE_SOURCE_DIR}/.git/;") +set(CPACK_STRIP_FILES TRUE) # DEB package -SET(CPACK_DEBIAN_PACKAGE_DESCRIPTION "Veyon, an open source computer monitoring and classroom management software - Veyon is an open source computer monitoring and classroom management software. - It enables teachers to view and control computer labs and interact with students. - Veyon is available in different languages and provides lots of useful features: - . - * see what's going on in computer labs in overview mode and take screenshots - * remote control computers to support and help users - * broadcast teacher's screen to students in realtime by using demo mode (either in fullscreen or in a window) - * lock workstations for attracting attention to teacher - * send text messages to students - * powering on/off and rebooting computers remote - * remote logoff and remote execution of arbitrary commands/scripts - * home schooling - Veyon's network-technology is not restricted to a subnet and therefore students at home - can join lessons via VPN connections just by installing the Veyon service -") -SET(CPACK_DEBIAN_PACKAGE_SECTION "Education") -SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libqca-qt5-2-plugins") -SET(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) -SET(CPACK_DEBIAN_COMPRESSION_TYPE "xz") +if(${CMAKE_VERSION} VERSION_GREATER "3.15.0") + set(CPACK_DEBIAN_PACKAGE_DESCRIPTION +"Veyon is a free and open source software for monitoring and controlling +computers across multiple platforms. Veyon supports you in teaching in digital +learning environments, performing virtual trainings or giving remote support. -FUNCTION(ReadRelease valuename FROM filename INTO varname) - file (STRINGS ${filename} _distrib - REGEX "^${valuename}=" - ) - string (REGEX REPLACE - "^${valuename}=\"?\(.*\)" "\\1" ${varname} "${_distrib}" - ) - # remove trailing quote that got globbed by the wildcard (greedy match) - string (REGEX REPLACE - "\"$" "" ${varname} "${${varname}}" - ) - set (${varname} "${${varname}}" PARENT_SCOPE) -ENDFUNCTION() +The following features are available in Veyon: -# RPM package -IF(EXISTS /etc/os-release) -ReadRelease("NAME" FROM /etc/os-release INTO OS_NAME) -IF(OS_NAME MATCHES ".*openSUSE.*") - SET(OS_OPENSUSE TRUE) -ENDIF() -ENDIF() +* Overview: monitor all computers in one or multiple locations or classrooms +* Remote access: view or control computers to watch and support users +* Demo: broadcast the teacher's screen in realtime (fullscreen/window) +* Screen lock: draw attention to what matters right now +* Communication: send text messages to students +* Start and end lessons: log in and log out users all at once +* Screenshots: record learning progress and document infringements +* Programs & websites: launch programs and open website URLs remotely +* Teaching material: distribute and open documents, images and videos easily +* Administration: power on/off and reboot computers remotely") +endif() -IF(OS_OPENSUSE) -SET(CPACK_RPM_PACKAGE_REQUIRES ${CPACK_RPM_PACKAGE_REQUIRES} "libqca-qt5-plugins") -ELSE() -SET(CPACK_RPM_PACKAGE_REQUIRES ${CPACK_RPM_PACKAGE_REQUIRES} "qca-qt5-ossl") -ENDIF() -SET(CPACK_RPM_PACKAGE_LICENSE "GPLv2") -SET(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_DEBIAN_PACKAGE_DESCRIPTION}) -SET(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION /lib) +set(CPACK_DEBIAN_PACKAGE_SECTION "Education") +set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqca-qt5-2-plugins, qml-module-qtquick2, qml-module-qtquick-dialogs, qml-module-qtquick-layouts, qml-module-qtqml-models2, qml-module-qtquick-controls2, qml-module-qtquick-window2") +set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) +set(CPACK_DEBIAN_COMPRESSION_TYPE "xz") +function(ReadRelease valuename FROM filename INTO varname) + file (STRINGS ${filename} _distrib + REGEX "^${valuename}=" + ) + string (REGEX REPLACE + "^${valuename}=\"?\(.*\)" "\\1" ${varname} "${_distrib}" + ) + # remove trailing quote that got globbed by the wildcard (greedy match) + string (REGEX REPLACE + "\"$" "" ${varname} "${${varname}}" + ) + set (${varname} "${${varname}}" PARENT_SCOPE) +endfunction() -# Generators -IF (WIN32) # TODO - IF (USE_WIX_TOOLSET) - SET(CPACK_GENERATOR "WIX") # this need WiX Tooset installed and a path to candle.exe - ELSE () - SET(CPACK_GENERATOR "NSIS") # this needs NSIS installed, and available - ENDIF () - SET(CPACK_SOURCE_GENERATOR "ZIP") -ELSEIF ( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # TODO - SET(CPACK_GENERATOR "PackageMake") -ELSE () - IF(EXISTS /etc/redhat-release OR EXISTS /etc/fedora-release OR OS_OPENSUSE) - SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.${CPACK_SYSTEM_NAME}") - SET(CPACK_GENERATOR "RPM") - ENDIF () - IF(EXISTS /etc/debian_version) - if (CPACK_SYSTEM_NAME STREQUAL "x86_64") - set(CPACK_SYSTEM_NAME "amd64") - endif () - SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}_${CPACK_SYSTEM_NAME}") - SET(CPACK_GENERATOR "DEB") - ENDIF () - SET(CPACK_SOURCE_GENERATOR "TGZ") -ENDIF () +# RPM package +if(EXISTS /etc/os-release) + ReadRelease("NAME" FROM /etc/os-release INTO OS_NAME) + if(OS_NAME MATCHES ".*openSUSE.*") + set(OS_OPENSUSE TRUE) + endif() +endif() + +if(OS_OPENSUSE) + if(WITH_QT6) + set(CPACK_RPM_PACKAGE_REQUIRES ${CPACK_RPM_PACKAGE_REQUIRES} "qca-qt6-plugins, libQt6QuickControls2-6") + else() + set(CPACK_RPM_PACKAGE_REQUIRES ${CPACK_RPM_PACKAGE_REQUIRES} "libqca-qt5-plugins, libqt5-qtquickcontrols2") + endif() +else() + if(WITH_QT6) + set(CPACK_RPM_PACKAGE_REQUIRES ${CPACK_RPM_PACKAGE_REQUIRES} "qca-qt6-ossl, qt6-qtdeclarative") + else() + set(CPACK_RPM_PACKAGE_REQUIRES ${CPACK_RPM_PACKAGE_REQUIRES} "qca-qt5-ossl, qt5-qtquickcontrols2") + endif() +endif() +set(CPACK_RPM_PACKAGE_LICENSE "GPLv2") +set(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_DEBIAN_PACKAGE_DESCRIPTION}) +set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION /lib) -INCLUDE(CPack) -# To generate packages use: -# make package -# make package_source +# Generators +if(WIN32) # TODO + if(USE_WIX_TOOLSET) + set(CPACK_GENERATOR "WIX") # this need WiX Tooset installed and a path to candle.exe + else() + set(CPACK_GENERATOR "NSIS") # this needs NSIS installed, and available + endif() + set(CPACK_SOURCE_GENERATOR "ZIP") +elseif( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # TODO + set(CPACK_GENERATOR "PackageMake") +else() + if(EXISTS /etc/redhat-release OR EXISTS /etc/fedora-release OR OS_OPENSUSE) + set(CPACK_RPM_FILE_NAME "RPM-DEFAULT") + set(CPACK_RPM_PACKAGE_RELEASE "${CPACK_DIST}") + set(CPACK_GENERATOR "RPM") + endif() + if(EXISTS /etc/debian_version) + set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT") + set(CPACK_DEBIAN_PACKAGE_RELEASE "${CPACK_DIST}") + set(CPACK_GENERATOR "DEB") + endif() + set(CPACK_SOURCE_GENERATOR "TGZ") +endif() diff --git a/cmake/modules/AndroidDeployQt.cmake b/cmake/modules/AndroidDeployQt.cmake index 1b0fbec61..77a761688 100644 --- a/cmake/modules/AndroidDeployQt.cmake +++ b/cmake/modules/AndroidDeployQt.cmake @@ -1,23 +1,15 @@ find_package(Qt5Core REQUIRED) -function(androiddeployqt QTANDROID_EXPORTED_TARGET ADDITIONAL_FIND_ROOT_PATH) - set(EXPORT_DIR "${CMAKE_BINARY_DIR}/${QTANDROID_EXPORTED_TARGET}_build_apk/") +function(androiddeployqt QTANDROID_EXPORTED_TARGET ANDROID_ADDITIONAL_FIND_ROOT_PATH) + set(EXPORT_DIR "${CMAKE_CURRENT_BINARY_DIR}/${QTANDROID_EXPORTED_TARGET}_build_apk/") set(EXECUTABLE_DESTINATION_PATH "${EXPORT_DIR}/libs/${CMAKE_ANDROID_ARCH_ABI}/lib${QTANDROID_EXPORTED_TARGET}.so") - set(EXTRA_PREFIX_DIRS "") - foreach(prefix ${ADDITIONAL_FIND_ROOT_PATH}) - if (EXTRA_PREFIX_DIRS) - set(EXTRA_PREFIX_DIRS "${EXTRA_PREFIX_DIRS}, \"${prefix}\"") - else() - set(EXTRA_PREFIX_DIRS "\"${prefix}\"") - endif() - endforeach() string(TOLOWER "${CMAKE_HOST_SYSTEM_NAME}" _LOWER_CMAKE_HOST_SYSTEM_NAME) - configure_file("${_CMAKE_ANDROID_DIR}/deployment-file.json.in" "${CMAKE_BINARY_DIR}/${QTANDROID_EXPORTED_TARGET}-deployment.json.in1") - file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/${QTANDROID_EXPORTED_TARGET}-deployment.json.in2" - INPUT "${CMAKE_BINARY_DIR}/${QTANDROID_EXPORTED_TARGET}-deployment.json.in1") + configure_file("${CMAKE_SOURCE_DIR}/android/deployment-file.json.in" "${CMAKE_CURRENT_BINARY_DIR}/${QTANDROID_EXPORTED_TARGET}-deployment.json.in1") + file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${QTANDROID_EXPORTED_TARGET}-deployment.json.in2" + INPUT "${CMAKE_CURRENT_BINARY_DIR}/${QTANDROID_EXPORTED_TARGET}-deployment.json.in1") - if (NOT TARGET create-apk) + if(NOT TARGET create-apk) add_custom_target(create-apk) endif() @@ -27,8 +19,8 @@ function(androiddeployqt QTANDROID_EXPORTED_TARGET ADDITIONAL_FIND_ROOT_PATH) COMMAND cmake -E remove_directory "${EXPORT_DIR}" COMMAND cmake -E copy_directory "$" "${EXPORT_DIR}" COMMAND cmake -E copy "$" "${EXECUTABLE_DESTINATION_PATH}" - COMMAND LANG=C cmake "-DTARGET=$" -P ${_CMAKE_ANDROID_DIR}/hasMainSymbol.cmake - COMMAND LANG=C cmake -DINPUT_FILE="${QTANDROID_EXPORTED_TARGET}-deployment.json.in2" -DOUTPUT_FILE="${QTANDROID_EXPORTED_TARGET}-deployment.json" "-DTARGET=$" "-DOUTPUT_DIR=$" "-DEXPORT_DIR=${CMAKE_INSTALL_PREFIX}" "-DANDROID_ADDITIONAL_FIND_ROOT_PATH=\"${ANDROID_ADDITIONAL_FIND_ROOT_PATH}\"" "-DANDROID_EXTRA_LIBS=\"${ANDROID_EXTRA_LIBS}\"" "-DANDROID_EXTRA_PLUGINS=\"${ANDROID_EXTRA_PLUGINS}\"" -P ${_CMAKE_ANDROID_DIR}/specifydependencies.cmake + COMMAND LANG=C cmake "-DTARGET=$" -P ${CMAKE_SOURCE_DIR}/android/hasMainSymbol.cmake + COMMAND LANG=C cmake -DINPUT_FILE="${QTANDROID_EXPORTED_TARGET}-deployment.json.in2" -DOUTPUT_FILE="${QTANDROID_EXPORTED_TARGET}-deployment.json" "-DTARGET=$" "-DOUTPUT_DIR=$" "-DEXPORT_DIR=${CMAKE_INSTALL_PREFIX}" "-DANDROID_ADDITIONAL_FIND_ROOT_PATH=\"${ANDROID_ADDITIONAL_FIND_ROOT_PATH}\"" "-DANDROID_EXTRA_LIBS=\"${ANDROID_EXTRA_LIBS}\"" "-DANDROID_EXTRA_PLUGINS=\"${ANDROID_EXTRA_PLUGINS}\"" -P ${CMAKE_SOURCE_DIR}/android/specifydependencies.cmake COMMAND $/androiddeployqt --gradle --input "${QTANDROID_EXPORTED_TARGET}-deployment.json" --output "${EXPORT_DIR}" --deployment bundled "\\$(ARGS)" ) diff --git a/cmake/modules/AndroidToolchain.cmake b/cmake/modules/AndroidToolchain.cmake index 3fe33afe6..8666a7916 100644 --- a/cmake/modules/AndroidToolchain.cmake +++ b/cmake/modules/AndroidToolchain.cmake @@ -1,17 +1,17 @@ -SET(ANDROID_STL "c++_shared") -SET(ANDROID_TOOLCHAIN "clang") -SET(ANDROID_API "21") -SET(ANDROID_SDK_BUILD_TOOLS_REVISION "29.0.1") -SET(ANDROID_COMPILER_VERSION "4.9") -SET(ANDROID_SDK_ROOT "/opt/android/sdk") -SET(ANDROID_PLATFORM "android-${ANDROID_API}") -SET(QT_DIR "/usr/${ANDROID_TOOLCHAIN_MACHINE_NAME}") -SET(CMAKE_FIND_ROOT_PATH "${QT_DIR}") -SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ANDROID_NDK}/build/cmake) +set(ANDROID_STL "c++_shared") +set(ANDROID_TOOLCHAIN "clang") +set(ANDROID_API "24") +set(ANDROID_SDK_BUILD_TOOLS_REVISION "29.0.2") +set(ANDROID_COMPILER_VERSION "4.9") +set(ANDROID_SDK_ROOT "/opt/android/sdk") +set(ANDROID_PLATFORM "android-${ANDROID_API}") +set(QT_DIR "/usr/${ANDROID_TOOLCHAIN_MACHINE_NAME}") +set(CMAKE_FIND_ROOT_PATH "${QT_DIR}") +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ANDROID_NDK}/build/cmake) -INCLUDE(android.toolchain) +include(android.toolchain) -SET(ANDROID_SYSROOT_GENERIC "${ANDROID_TOOLCHAIN_ROOT}/sysroot/usr/lib/${ANDROID_TOOLCHAIN_MACHINE_NAME}/") -SET(ANDROID_SYSROOT "${ANDROID_SYSROOT_GENERIC}/${ANDROID_API}") -SET(ANDROID_STDCPP "${ANDROID_SYSROOT}/libstdc++.so") -SET(ANDROID_ADDITIONAL_FIND_ROOT_PATH "${QT_DIR};${ANDROID_SYSROOT}") +set(ANDROID_SYSROOT_GENERIC "${ANDROID_TOOLCHAIN_ROOT}/sysroot/usr/lib/${ANDROID_TOOLCHAIN_MACHINE_NAME}/") +set(ANDROID_SYSROOT "${ANDROID_SYSROOT_GENERIC}/${ANDROID_API}") +set(ANDROID_STDCPP "${ANDROID_SYSROOT}/libstdc++.so") +set(ANDROID_ADDITIONAL_FIND_ROOT_PATH "${QT_DIR};${ANDROID_SYSROOT}") diff --git a/cmake/modules/BuildApplication.cmake b/cmake/modules/BuildApplication.cmake deleted file mode 100644 index 25144ea24..000000000 --- a/cmake/modules/BuildApplication.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# BuildApplication.cmake - Copyright (c) 2019 Tobias Junghans -# -# description: build Veyon application -# usage: BUILD_APPLICATION( ) - -MACRO(BUILD_APPLICATION APPLICATION_NAME) - SET(APPLICATION_SOURCES ${ARGN}) - - IF(VEYON_BUILD_ANDROID) - ADD_LIBRARY(${APPLICATION_NAME} SHARED ${APPLICATION_SOURCES}) - ELSE() - ADD_EXECUTABLE(${APPLICATION_NAME} ${APPLICATION_SOURCES}) - INSTALL(TARGETS ${APPLICATION_NAME} RUNTIME DESTINATION bin) - ENDIF() -ENDMACRO() - diff --git a/cmake/modules/BuildPlugin.cmake b/cmake/modules/BuildPlugin.cmake deleted file mode 100644 index 154560fb1..000000000 --- a/cmake/modules/BuildPlugin.cmake +++ /dev/null @@ -1,20 +0,0 @@ -# BuildPlugin.cmake - Copyright (c) 2017-2019 Tobias Junghans -# -# description: build Veyon plugin -# usage: BUILD_PLUGIN( ) - -MACRO(BUILD_PLUGIN PLUGIN_NAME) - SET(PLUGIN_SOURCES ${ARGN}) - - ADD_LIBRARY(${PLUGIN_NAME} MODULE ${PLUGIN_SOURCES}) - - TARGET_INCLUDE_DIRECTORIES(${PLUGIN_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) - TARGET_LINK_LIBRARIES(${PLUGIN_NAME} veyon-core) - - SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES PREFIX "") - SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES LINK_FLAGS "-Wl,-no-undefined") - INSTALL(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION ${VEYON_INSTALL_PLUGIN_DIR}) - - COTIRE_VEYON(${PLUGIN_NAME}) -ENDMACRO(BUILD_PLUGIN) - diff --git a/cmake/modules/BuildVeyonApplication.cmake b/cmake/modules/BuildVeyonApplication.cmake new file mode 100644 index 000000000..58bf1394d --- /dev/null +++ b/cmake/modules/BuildVeyonApplication.cmake @@ -0,0 +1,22 @@ +# BuildVeyonApplication.cmake - Copyright (c) 2019-2025 Tobias Junghans +# +# description: build Veyon application +# usage: build_veyon_application( ) + +macro(build_veyon_application APPLICATION_NAME) + if(VEYON_BUILD_ANDROID) + add_library(${APPLICATION_NAME} SHARED ${ARGN}) + else() + add_executable(${APPLICATION_NAME} ${ARGN}) + install(TARGETS ${APPLICATION_NAME} RUNTIME DESTINATION bin) + endif() + target_include_directories(${APPLICATION_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src) + set_target_properties(${APPLICATION_NAME} PROPERTIES COMPILE_OPTIONS "${CMAKE_COMPILE_OPTIONS_PIE}") + set_target_properties(${APPLICATION_NAME} PROPERTIES LINK_OPTIONS "${CMAKE_LINK_OPTIONS_PIE}") + target_link_libraries(${APPLICATION_NAME} PRIVATE veyon-core) + set_default_target_properties(${APPLICATION_NAME}) + if(WITH_PCH) + target_precompile_headers(${APPLICATION_NAME} REUSE_FROM veyon-application-pch) + endif() +endmacro() + diff --git a/cmake/modules/BuildVeyonFuzzer.cmake b/cmake/modules/BuildVeyonFuzzer.cmake new file mode 100644 index 000000000..0cfb0f466 --- /dev/null +++ b/cmake/modules/BuildVeyonFuzzer.cmake @@ -0,0 +1,14 @@ +# BuildVeyonFuzzer.cmake - Copyright (c) 2021-2025 Tobias Junghans +# +# description: build fuzzer test for Veyon component +# usage: build_veyon_fuzzer( ) + +macro(build_veyon_fuzzer FUZZER_NAME) + add_executable(${FUZZER_NAME} ${ARGN}) + set_default_target_properties(${FUZZER_NAME}) + target_compile_options(${FUZZER_NAME} PRIVATE "-g;-fsanitize=fuzzer") + target_link_options(${FUZZER_NAME} PRIVATE "-g;-fsanitize=fuzzer") + target_link_libraries(${FUZZER_NAME} veyon-core) + add_test(NAME ${FUZZER_NAME} COMMAND ${FUZZER_NAME} -max_total_time=60) +endmacro() + diff --git a/cmake/modules/BuildVeyonPlugin.cmake b/cmake/modules/BuildVeyonPlugin.cmake new file mode 100644 index 000000000..a1db6aab7 --- /dev/null +++ b/cmake/modules/BuildVeyonPlugin.cmake @@ -0,0 +1,36 @@ +# BuildVeyonPlugin.cmake - Copyright (c) 2017-2025 Tobias Junghans +# +# description: build Veyon plugin +# usage: build_veyon_plugin( ) + +include(SetDefaultTargetProperties) + +macro(build_veyon_plugin PLUGIN_NAME) + set(LIBRARY_TYPE "MODULE") + if(WITH_TESTS) + set(LIBRARY_TYPE "SHARED") + endif() + add_library(${PLUGIN_NAME} ${LIBRARY_TYPE} ${ARGN}) + + target_include_directories(${PLUGIN_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(${PLUGIN_NAME} PRIVATE veyon-core) + + set_default_target_properties(${PLUGIN_NAME}) + set_target_properties(${PLUGIN_NAME} PROPERTIES PREFIX "") + if(${PLUGIN_NAME}_COMPONENT) + install(TARGETS ${PLUGIN_NAME} COMPONENT ${${PLUGIN_NAME}_COMPONENT} LIBRARY DESTINATION ${VEYON_INSTALL_PLUGIN_DIR}) + else() + install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION ${VEYON_INSTALL_PLUGIN_DIR}) + endif() + if(WITH_PCH) + target_precompile_headers(${PLUGIN_NAME} REUSE_FROM veyon-library-pch) + endif() +endmacro() + +macro(test_veyon_plugin PLUGIN_NAME TEST_NAME) + if(WITH_TESTS) + add_executable(${TEST_NAME} ${TEST_NAME}.cpp) + add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME}) + target_link_libraries(${TEST_NAME} PRIVATE veyon-core ${PLUGIN_NAME}) + endif() +endmacro() diff --git a/cmake/modules/ConfigureFiles.cmake b/cmake/modules/ConfigureFiles.cmake index 4757a7984..8d1a8e2bb 100644 --- a/cmake/modules/ConfigureFiles.cmake +++ b/cmake/modules/ConfigureFiles.cmake @@ -1,7 +1,7 @@ -MACRO(CONFIGURE_FILES) - FOREACH(f ${ARGN}) - STRING(REPLACE ".in" "" OUT_FILE "${f}") - CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${f} ${CMAKE_CURRENT_BINARY_DIR}/${OUT_FILE} @ONLY) - ENDFOREACH(f ${IN_FILES}) -ENDMACRO() +macro(configure_files) + foreach(f ${ARGN}) + string(REPLACE ".in" "" OUT_FILE "${f}") + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${f} ${CMAKE_CURRENT_BINARY_DIR}/${OUT_FILE} @ONLY) + endforeach() +endmacro() diff --git a/cmake/modules/CotireVeyon.cmake b/cmake/modules/CotireVeyon.cmake deleted file mode 100644 index 9b6fbe1c4..000000000 --- a/cmake/modules/CotireVeyon.cmake +++ /dev/null @@ -1,10 +0,0 @@ -INCLUDE(cotire) -MACRO(COTIRE_VEYON TARGET_NAME) -get_target_property(_targetType ${TARGET_NAME} TYPE) -if(NOT VEYON_BUILD_ANDROID OR NOT _targetType STREQUAL "EXECUTABLE") -SET_PROPERTY(TARGET ${TARGET_NAME} PROPERTY CXX_STANDARD 11) -SET_PROPERTY(TARGET ${TARGET_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) -SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${PROJECT_SOURCE_DIR}/core/include/Cotire.h") -cotire(${TARGET_NAME}) -endif() -ENDMACRO(COTIRE_VEYON) diff --git a/cmake/modules/CreateTranslations.cmake b/cmake/modules/CreateTranslations.cmake new file mode 100644 index 000000000..a525b64db --- /dev/null +++ b/cmake/modules/CreateTranslations.cmake @@ -0,0 +1,37 @@ +# CreateTranslations.cmake - Copyright (c) 2020-2025 Tobias Junghans +# +# description: create Qt translation files +# usage: create_translations( ) + +function(create_translations name ts_files source_files) + + if(NOT WITH_TRANSLATIONS) + add_custom_target("${name}-translations") + return() + endif() + + set(qm_targets "") + foreach(ts_file ${ts_files}) + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" ts_filename "${ts_file}") + string(REPLACE ".ts" "" basename "${ts_filename}") + set(ts_target "${basename}_ts") + set(qm_target "${basename}_qm") + set(qm_file "${CMAKE_CURRENT_BINARY_DIR}/${basename}.qm") + add_custom_command(OUTPUT ${ts_file} + COMMAND Qt${QT_MAJOR_VERSION}::lupdate -locations none -no-obsolete ${source_files} -ts ${ts_file} + DEPENDS ${source_files}) + add_custom_target(${ts_target} DEPENDS ${ts_file}) + # add command and target for generating/updating QM file if TS file is newer or no QM file exists yet + add_custom_command(OUTPUT ${qm_file} + COMMAND Qt${QT_MAJOR_VERSION}::lrelease ${ts_file} -qm ${qm_file} + DEPENDS ${ts_file}) + add_custom_target(${qm_target} DEPENDS ${qm_file}) + + list(APPEND qm_targets "${qm_target}") + + install(FILES ${qm_file} DESTINATION ${VEYON_INSTALL_DATA_DIR}/translations) + endforeach() + + add_custom_target("${name}-translations" ALL DEPENDS "${qm_targets}") + +endfunction() diff --git a/cmake/modules/FindLZO.cmake b/cmake/modules/FindLZO.cmake index 9a899d81b..806e44fdf 100644 --- a/cmake/modules/FindLZO.cmake +++ b/cmake/modules/FindLZO.cmake @@ -3,27 +3,27 @@ # LZO_INCLUDE_DIR - the LZO include directory # LZO_LIBRARIES - The libraries needed to use LZO -if (LZO_INCLUDE_DIR AND LZO_LIBRARIES) +if(LZO_INCLUDE_DIR AND LZO_LIBRARIES) # in cache already - SET(LZO_FOUND TRUE) -else (LZO_INCLUDE_DIR AND LZO_LIBRARIES) - FIND_PATH(LZO_INCLUDE_DIR NAMES lzo/lzo1x.h) + set(LZO_FOUND TRUE) +else() + find_path(LZO_INCLUDE_DIR NAMES lzo/lzo1x.h) - FIND_LIBRARY(LZO_LIBRARIES NAMES lzo2) + find_library(LZO_LIBRARIES NAMES lzo2) - if (LZO_INCLUDE_DIR AND LZO_LIBRARIES) + if(LZO_INCLUDE_DIR AND LZO_LIBRARIES) set(LZO_FOUND TRUE) - endif (LZO_INCLUDE_DIR AND LZO_LIBRARIES) + endif() - if (LZO_FOUND) - if (NOT LZO_FIND_QUIETLY) + if(LZO_FOUND) + if(NOT LZO_FIND_QUIETLY) message(STATUS "Found LZO: ${LZO_LIBRARIES}") - endif (NOT LZO_FIND_QUIETLY) - else (LZO_FOUND) - if (LZO_FIND_REQUIRED) + endif() + else() + if(LZO_FIND_REQUIRED) message(FATAL_ERROR "Could NOT find LZO") - endif (LZO_FIND_REQUIRED) - endif (LZO_FOUND) + endif() + endif() - MARK_AS_ADVANCED(LZO_INCLUDE_DIR LZO_LIBRARIES) -endif (LZO_INCLUDE_DIR AND LZO_LIBRARIES) + mark_as_advanced(LZO_INCLUDE_DIR LZO_LIBRARIES) +endif() diff --git a/cmake/modules/FindLdap.cmake b/cmake/modules/FindLdap.cmake index 7f8ef0431..5f1880cc1 100644 --- a/cmake/modules/FindLdap.cmake +++ b/cmake/modules/FindLdap.cmake @@ -63,10 +63,10 @@ find_path(Ldap_INCLUDE_DIRS NAMES ldap.h) if(APPLE) - find_library(Ldap_LIBRARIES NAMES LDAP - PATHS - /System/Library/Frameworks - /Library/Frameworks + find_path(Ldap_LIBRARIES NAMES LDAP + PATHS + /System/Library/Frameworks + /Library/Frameworks ) else() find_library(Ldap_LIBRARIES NAMES ldap) @@ -93,9 +93,9 @@ endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Ldap - FOUND_VAR Ldap_FOUND - REQUIRED_VARS Ldap_LIBRARIES Ldap_INCLUDE_DIRS - VERSION_VAR Ldap_VERSION + FOUND_VAR Ldap_FOUND + REQUIRED_VARS Ldap_LIBRARIES Ldap_INCLUDE_DIRS + VERSION_VAR Ldap_VERSION ) if(Ldap_FOUND AND NOT TARGET Ldap::Ldap) diff --git a/cmake/modules/FindLibVNCClient.cmake b/cmake/modules/FindLibVNCClient.cmake new file mode 100644 index 000000000..0e976f44a --- /dev/null +++ b/cmake/modules/FindLibVNCClient.cmake @@ -0,0 +1,61 @@ +#.rst: +# FindLibVNCClient +# -------- +# +# Try to find the LibVNCClient library, once done this will define: +# +# ``LibVNCClient_FOUND`` +# System has LibVNCClient. +# +# ``LibVNCClient_INCLUDE_DIRS`` +# The LibVNCClient include directory. +# +# ``LibVNCClient_LIBRARIES`` +# The LibVNCClient libraries. +# +# ``LibVNCClient_VERSION`` +# The LibVNCClient version. +# +# If ``LibVNCClient_FOUND`` is TRUE, the following imported target +# will be available: +# +# ``LibVNC::LibVNCClient`` +# The LibVNCClient library + +#============================================================================= +# SPDX-FileCopyrightText: 2020-2025 Tobias Junghans +# +# SPDX-License-Identifier: BSD-3-Clause +#============================================================================= + +find_package(PkgConfig QUIET) +pkg_check_modules(PC_LIBVNCCLIENT QUIET libvncclient) + +find_path(LibVNCClient_INCLUDE_DIRS NAMES rfb/rfbclient.h HINTS ${PC_LIBVNCCLIENT_INCLUDE_DIRS}) +find_library(LibVNCClient_LIBRARIES NAMES vncclient HINTS ${PC_LIBVNCCLIENT_LIBRARY_DIRS}) + +set(LibVNCClient_VERSION ${PC_LIBVNCCLIENT_VERSION}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LibVNCClient + FOUND_VAR LibVNCClient_FOUND + REQUIRED_VARS LibVNCClient_INCLUDE_DIRS LibVNCClient_LIBRARIES + VERSION_VAR LibVNCClient_VERSION +) + +mark_as_advanced(LibVNCClient_INCLUDE_DIRS LibVNCClient_LIBRARIES) + +if(LibVNCClient_FOUND AND NOT TARGET LibVNCClient::LibVNCClient) + add_library(LibVNC::LibVNCClient UNKNOWN IMPORTED) + set_target_properties(LibVNC::LibVNCClient PROPERTIES + IMPORTED_LOCATION "${LibVNCClient_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${LibVNCClient_INCLUDE_DIRS}" + INTERFACE_COMPILE_DEFINITIONS "${PC_LIBVNCCLIENT_CFLAGS_OTHER}" + ) +endif() + +include(FeatureSummary) +set_package_properties(LibVNCClient PROPERTIES + DESCRIPTION "cross-platform C library which allows you to easily implement VNC client functionality" + URL "https://libvnc.github.io/" +) diff --git a/cmake/modules/FindLibVNCServer.cmake b/cmake/modules/FindLibVNCServer.cmake new file mode 100644 index 000000000..2900bdb91 --- /dev/null +++ b/cmake/modules/FindLibVNCServer.cmake @@ -0,0 +1,61 @@ +#.rst: +# FindLibVNCServer +# -------- +# +# Try to find the LibVNCServer library, once done this will define: +# +# ``LibVNCServer_FOUND`` +# System has LibVNCServer. +# +# ``LibVNCServer_INCLUDE_DIRS`` +# The LibVNCServer include directory. +# +# ``LibVNCServer_LIBRARIES`` +# The LibVNCServer libraries. +# +# ``LibVNCServer_VERSION`` +# The LibVNCServer version. +# +# If ``LibVNCServer_FOUND`` is TRUE, the following imported target +# will be available: +# +# ``LibVNC::LibVNCServer`` +# The LibVNCServer library + +#============================================================================= +# SPDX-FileCopyrightText: 2020-2025 Tobias Junghans +# +# SPDX-License-Identifier: BSD-3-Clause +#============================================================================= + +find_package(PkgConfig QUIET) +pkg_check_modules(PC_LIBVNCCLIENT QUIET libvncserver) + +find_path(LibVNCServer_INCLUDE_DIRS NAMES rfb/rfb.h HINTS ${PC_LIBVNCCLIENT_INCLUDE_DIRS}) +find_library(LibVNCServer_LIBRARIES NAMES vncserver HINTS ${PC_LIBVNCCLIENT_LIBRARY_DIRS}) + +set(LibVNCServer_VERSION ${PC_LIBVNCCLIENT_VERSION}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LibVNCServer + FOUND_VAR LibVNCServer_FOUND + REQUIRED_VARS LibVNCServer_INCLUDE_DIRS LibVNCServer_LIBRARIES + VERSION_VAR LibVNCServer_VERSION +) + +mark_as_advanced(LibVNCServer_INCLUDE_DIRS LibVNCServer_LIBRARIES) + +if(LibVNCServer_FOUND AND NOT TARGET LibVNCServer::LibVNCServer) + add_library(LibVNC::LibVNCServer UNKNOWN IMPORTED) + set_target_properties(LibVNC::LibVNCServer PROPERTIES + IMPORTED_LOCATION "${LibVNCServer_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${LibVNCServer_INCLUDE_DIRS}" + INTERFACE_COMPILE_DEFINITIONS "${PC_LIBVNCCLIENT_CFLAGS_OTHER}" + ) +endif() + +include(FeatureSummary) +set_package_properties(LibVNCServer PROPERTIES + DESCRIPTION "cross-platform C library which allows you to easily implement VNC server functionality" + URL "https://libvnc.github.io/" +) diff --git a/cmake/modules/FindPAM.cmake b/cmake/modules/FindPAM.cmake index 349983651..cff9db6ce 100644 --- a/cmake/modules/FindPAM.cmake +++ b/cmake/modules/FindPAM.cmake @@ -5,29 +5,29 @@ # PAM_INCLUDE_DIR - the pam include directory # PAM_LIBRARIES - libpam library -if (PAM_INCLUDE_DIR AND PAM_LIBRARY) +if(PAM_INCLUDE_DIR AND PAM_LIBRARY) # Already in cache, be silent set(PAM_FIND_QUIETLY TRUE) -endif (PAM_INCLUDE_DIR AND PAM_LIBRARY) +endif() find_path(PAM_INCLUDE_DIR NAMES security/pam_appl.h pam/pam_appl.h) find_library(PAM_LIBRARY pam) find_library(DL_LIBRARY dl) -if (PAM_INCLUDE_DIR AND PAM_LIBRARY) +if(PAM_INCLUDE_DIR AND PAM_LIBRARY) set(PAM_FOUND TRUE) - if (DL_LIBRARY) + if(DL_LIBRARY) set(PAM_LIBRARIES ${PAM_LIBRARY} ${DL_LIBRARY}) - else (DL_LIBRARY) + else() set(PAM_LIBRARIES ${PAM_LIBRARY}) - endif (DL_LIBRARY) + endif() - if (EXISTS ${PAM_INCLUDE_DIR}/pam/pam_appl.h) + if(EXISTS ${PAM_INCLUDE_DIR}/pam/pam_appl.h) # darwin claims to be something special set(HAVE_PAM_PAM_APPL_H 1) - endif (EXISTS ${PAM_INCLUDE_DIR}/pam/pam_appl.h) + endif() - if (NOT DEFINED PAM_MESSAGE_CONST) + if(NOT DEFINED PAM_MESSAGE_CONST) include(CheckCXXSourceCompiles) # XXX does this work with plain c? check_cxx_source_compiles(" @@ -56,19 +56,19 @@ int main(void) return 0; } " PAM_MESSAGE_CONST) - endif (NOT DEFINED PAM_MESSAGE_CONST) + endif() set(PAM_MESSAGE_CONST ${PAM_MESSAGE_CONST} CACHE BOOL "PAM expects a conversation function with const pam_message") -endif (PAM_INCLUDE_DIR AND PAM_LIBRARY) +endif() -if (PAM_FOUND) - if (NOT PAM_FIND_QUIETLY) +if(PAM_FOUND) + if(NOT PAM_FIND_QUIETLY) message(STATUS "Found PAM: ${PAM_LIBRARIES}") - endif (NOT PAM_FIND_QUIETLY) -else (PAM_FOUND) - if (PAM_FIND_REQUIRED) + endif() +else() + if(PAM_FIND_REQUIRED) message(FATAL_ERROR "PAM was not found") - endif(PAM_FIND_REQUIRED) -endif (PAM_FOUND) + endif() +endif() mark_as_advanced(PAM_INCLUDE_DIR PAM_LIBRARY DL_LIBRARY PAM_MESSAGE_CONST) diff --git a/cmake/modules/FindQCA.cmake b/cmake/modules/FindQCA.cmake deleted file mode 100644 index 5b14af91b..000000000 --- a/cmake/modules/FindQCA.cmake +++ /dev/null @@ -1,99 +0,0 @@ -# Find QCA (Qt Cryptography Architecture 2+) -# ~~~~~~~~~~~~~~~~ -# When run this will define -# -# QCA_FOUND - system has QCA -# QCA_LIBRARY - the QCA library or framework -# QCA_INCLUDE_DIR - the QCA include directory -# QCA_VERSION_STR - e.g. "2.0.3" -# -# Copyright (c) 2006, Michael Larouche, -# Copyright (c) 2014, Larry Shaffer, -# -# Redistribution and use is allowed according to the terms of the BSD license. -# For details see the accompanying COPYING-CMAKE-SCRIPTS file. - - -if(QCA_INCLUDE_DIR AND QCA_LIBRARY) - - set(QCA_FOUND TRUE) - -else(QCA_INCLUDE_DIR AND QCA_LIBRARY) - - set(QCA_LIBRARY_NAMES qca-qt5 qca2-qt5) - - find_library(QCA_LIBRARY - NAMES ${QCA_LIBRARY_NAMES} - PATHS - ${LIB_DIR} - $ENV{LIB} - "$ENV{LIB_DIR}" - /usr/local/lib - ) - - set(_qca_fw) - if(QCA_LIBRARY MATCHES "/qca.*\\.framework") - string(REGEX REPLACE "^(.*/qca.*\\.framework).*$" "\\1" _qca_fw "${QCA_LIBRARY}") - endif() - - find_path(QCA_INCLUDE_DIR - NAMES QtCrypto - PATHS - "${_qca_fw}/Headers" - ${LIB_DIR}/include - "$ENV{LIB_DIR}/include" - $ENV{INCLUDE} - /usr/local/include - PATH_SUFFIXES QtCrypto qt5/QtCrypto Qca-qt5/QtCrypto qt/Qca-qt5/QtCrypto qt5/Qca-qt5/QtCrypto - ) - - if(QCA_LIBRARY AND QCA_INCLUDE_DIR) - set(QCA_FOUND TRUE) - endif() - -endif(QCA_INCLUDE_DIR AND QCA_LIBRARY) - -if(NOT QCA_FOUND) - - if(QCA_FIND_REQUIRED) - message(FATAL_ERROR "Could not find QCA") - else() - message(STATUS "Could not find QCA") - endif() - -else(NOT QCA_FOUND) - - # Check version is valid (>= 2.0.3) - # find_package(QCA 2.0.3) works with 2.1.0+, which has a QcaConfigVersion.cmake, but 2.0.3 does not - - # qca_version.h header only available with 2.1.0+ - set(_qca_version_h "${QCA_INCLUDE_DIR}/qca_version.h") - if(EXISTS "${_qca_version_h}") - file(STRINGS "${_qca_version_h}" _qca_version_str REGEX "^.*QCA_VERSION_STR +\"[^\"]+\".*$") - string(REGEX REPLACE "^.*QCA_VERSION_STR +\"([^\"]+)\".*$" "\\1" QCA_VERSION_STR "${_qca_version_str}") - else() - # qca_core.h contains hexadecimal version in <= 2.0.3 - set(_qca_core_h "${QCA_INCLUDE_DIR}/qca_core.h") - if(EXISTS "${_qca_core_h}") - file(STRINGS "${_qca_core_h}" _qca_version_str REGEX "^#define +QCA_VERSION +0x[0-9a-fA-F]+.*") - string(REGEX REPLACE "^#define +QCA_VERSION +0x([0-9a-fA-F]+)$" "\\1" _qca_version_int "${_qca_version_str}") - if("${_qca_version_int}" STREQUAL "020003") - set(QCA_VERSION_STR "2.0.3") - endif() - endif() - endif() - - if(NOT QCA_VERSION_STR) - set(QCA_FOUND FALSE) - if(QCA_FIND_REQUIRED) - message(FATAL_ERROR "Could not find QCA >= 2.0.3") - else() - message(STATUS "Could not find QCA >= 2.0.3") - endif() - else() - if(NOT QCA_FIND_QUIETLY) - message(STATUS "Found QCA: ${QCA_LIBRARY} (${QCA_VERSION_STR})") - endif() - endif() - -endif(NOT QCA_FOUND) diff --git a/cmake/modules/FindSasl2.cmake b/cmake/modules/FindSasl2.cmake index 95dd8f605..e36c0c2da 100644 --- a/cmake/modules/FindSasl2.cmake +++ b/cmake/modules/FindSasl2.cmake @@ -74,16 +74,16 @@ set(Sasl2_VERSION "${PC_Sasl2_VERSION}") if(NOT Sasl2_VERSION) if(EXISTS "${Sasl2_INCLUDE_DIRS}/sasl/sasl.h") - file(READ "${Sasl2_INCLUDE_DIRS}/sasl/sasl.h" SASL2_H_CONTENT) - string(REGEX MATCH "#define SASL_VERSION_MAJOR[ ]+[0-9]+" SASL2_VERSION_MAJOR_MATCH ${SASL2_H_CONTENT}) - string(REGEX MATCH "#define SASL_VERSION_MINOR[ ]+[0-9]+" SASL2_VERSION_MINOR_MATCH ${SASL2_H_CONTENT}) - string(REGEX MATCH "#define SASL_VERSION_STEP[ ]+[0-9]+" SASL2_VERSION_STEP_MATCH ${SASL2_H_CONTENT}) + file(READ "${Sasl2_INCLUDE_DIRS}/sasl/sasl.h" SASL2_H_CONTENT) + string(REGEX MATCH "#define SASL_VERSION_MAJOR[ ]+[0-9]+" SASL2_VERSION_MAJOR_MATCH ${SASL2_H_CONTENT}) + string(REGEX MATCH "#define SASL_VERSION_MINOR[ ]+[0-9]+" SASL2_VERSION_MINOR_MATCH ${SASL2_H_CONTENT}) + string(REGEX MATCH "#define SASL_VERSION_STEP[ ]+[0-9]+" SASL2_VERSION_STEP_MATCH ${SASL2_H_CONTENT}) - string(REGEX REPLACE ".*_MAJOR[ ]+(.*)" "\\1" SASL2_VERSION_MAJOR ${SASL2_VERSION_MAJOR_MATCH}) - string(REGEX REPLACE ".*_MINOR[ ]+(.*)" "\\1" SASL2_VERSION_MINOR ${SASL2_VERSION_MINOR_MATCH}) - string(REGEX REPLACE ".*_STEP[ ]+(.*)" "\\1" SASL2_VERSION_STEP ${SASL2_VERSION_STEP_MATCH}) + string(REGEX REPLACE ".*_MAJOR[ ]+(.*)" "\\1" SASL2_VERSION_MAJOR ${SASL2_VERSION_MAJOR_MATCH}) + string(REGEX REPLACE ".*_MINOR[ ]+(.*)" "\\1" SASL2_VERSION_MINOR ${SASL2_VERSION_MINOR_MATCH}) + string(REGEX REPLACE ".*_STEP[ ]+(.*)" "\\1" SASL2_VERSION_STEP ${SASL2_VERSION_STEP_MATCH}) - set(Sasl2_VERSION "${SASL2_VERSION_MAJOR}.${SASL2_VERSION_MINOR}.${SASL2_VERSION_STEP}") + set(Sasl2_VERSION "${SASL2_VERSION_MAJOR}.${SASL2_VERSION_MINOR}.${SASL2_VERSION_STEP}") else() # Could not find the version set(Sasl2_VERSION "0.0.0") @@ -93,9 +93,9 @@ endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Sasl2 - FOUND_VAR Sasl2_FOUND - REQUIRED_VARS Sasl2_LIBRARIES Sasl2_INCLUDE_DIRS - VERSION_VAR Sasl2_VERSION + FOUND_VAR Sasl2_FOUND + REQUIRED_VARS Sasl2_LIBRARIES Sasl2_INCLUDE_DIRS + VERSION_VAR Sasl2_VERSION ) if(Sasl2_FOUND AND NOT TARGET Sasl2::Sasl2) add_library(Sasl2::Sasl2 UNKNOWN IMPORTED) diff --git a/cmake/modules/ImportQtTranslations.cmake b/cmake/modules/ImportQtTranslations.cmake new file mode 100644 index 000000000..d189efb2b --- /dev/null +++ b/cmake/modules/ImportQtTranslations.cmake @@ -0,0 +1,30 @@ +# ImportQtTranslations.cmake - Copyright (c) 2020-2025 Tobias Junghans +# +# description: import translation files of Qt into build directory +# usage: import_qt_translations() with QT_TRANSLATIONS_DIR set + + +function(import_qt_translations) + # find Qt's translation files + set(QT_TRANSLATIONS_STAMP ${CMAKE_CURRENT_BINARY_DIR}/qttranslations.stamp) + if(QT_TRANSLATIONS_DIR AND NOT EXISTS "${QT_TRANSLATIONS_STAMP}") + message(STATUS "Processing Qt translation files in ${QT_TRANSLATIONS_DIR}") + file(GLOB QT_TRANSLATIONS "${QT_TRANSLATIONS_DIR}/qt_*.qm") + foreach(QT_TRANSLATION ${QT_TRANSLATIONS}) + if(NOT QT_TRANSLATION MATCHES "help") + string(REPLACE "${QT_TRANSLATIONS_DIR}/" "" QT_TRANSLATION_FILE_NAME "${QT_TRANSLATION}") + string(REPLACE "qt_" "qtbase_" QTBASE_TRANSLATION_FILE_NAME "${QT_TRANSLATION_FILE_NAME}") + # is there qtbase-specific QM file? + if(EXISTS "${QT_TRANSLATIONS_DIR}/${QTBASE_TRANSLATION_FILE_NAME}") + # then use it instead of (deprecated) QM file for all Qt modules + file(COPY "${QT_TRANSLATIONS_DIR}/${QTBASE_TRANSLATION_FILE_NAME}" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + message(STATUS "Imported Qt translation file: ${QT_TRANSLATIONS_DIR}/${QTBASE_TRANSLATION_FILE_NAME}") + else() + file(COPY ${QT_TRANSLATION} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + message(STATUS "Imported Qt translation file: ${QT_TRANSLATION}") + endif() + endif() + endforeach() + file(WRITE "${QT_TRANSLATIONS_STAMP}" "1") + endif() +endfunction() diff --git a/cmake/modules/LibVNCServerIntegration.cmake b/cmake/modules/LibVNCServerIntegration.cmake new file mode 100644 index 000000000..cbecc6629 --- /dev/null +++ b/cmake/modules/LibVNCServerIntegration.cmake @@ -0,0 +1,96 @@ +include(CheckFunctionExists) +include(CheckSymbolExists) +include(CheckIncludeFile) +include(CheckTypeSize) +include(TestBigEndian) +include(CheckCSourceCompiles) +include(CheckCSourceRuns) + +check_include_file("endian.h" LIBVNCSERVER_HAVE_ENDIAN_H) +check_include_file("fcntl.h" LIBVNCSERVER_HAVE_FCNTL_H) +check_include_file("netinet/in.h" LIBVNCSERVER_HAVE_NETINET_IN_H) +check_include_file("sys/endian.h" LIBVNCSERVER_HAVE_SYS_ENDIAN_H) +check_include_file("sys/socket.h" LIBVNCSERVER_HAVE_SYS_SOCKET_H) +check_include_file("sys/stat.h" LIBVNCSERVER_HAVE_SYS_STAT_H) +check_include_file("sys/time.h" LIBVNCSERVER_HAVE_SYS_TIME_H) +check_include_file("sys/types.h" LIBVNCSERVER_HAVE_SYS_TYPES_H) +check_include_file("sys/wait.h" LIBVNCSERVER_HAVE_SYS_WAIT_H) +check_include_file("unistd.h" LIBVNCSERVER_HAVE_UNISTD_H) +check_include_file("sys/uio.h" LIBVNCSERVER_HAVE_SYS_UIO_H) +check_include_file("sys/resource.h" LIBVNCSERVER_HAVE_SYS_RESOURCE_H) + + +# headers needed for check_type_size() +check_include_file("vfork.h" LIBVNCSERVER_HAVE_VFORK_H) +check_include_file("ws2tcpip.h" LIBVNCSERVER_HAVE_WS2TCPIP_H) +check_include_file("arpa/inet.h" HAVE_ARPA_INET_H) +check_include_file("stdint.h" HAVE_STDINT_H) +check_include_file("stddef.h" HAVE_STDDEF_H) +check_include_file("sys/types.h" HAVE_SYS_TYPES_H) + +# error out if required headers not found +if(NOT HAVE_STDINT_H) + message(FATAL_ERROR "Could NOT find required header stdint.h") +endif() + +check_function_exists(gettimeofday LIBVNCSERVER_HAVE_GETTIMEOFDAY) +check_function_exists(vfork LIBVNCSERVER_HAVE_VFORK) +check_function_exists(vprintf LIBVNCSERVER_HAVE_VPRINTF) +check_function_exists(mmap LIBVNCSERVER_HAVE_MMAP) +check_function_exists(fork LIBVNCSERVER_HAVE_FORK) +check_function_exists(ftime LIBVNCSERVER_HAVE_FTIME) +check_function_exists(gethostbyname LIBVNCSERVER_HAVE_GETHOSTBYNAME) +check_function_exists(gethostname LIBVNCSERVER_HAVE_GETHOSTNAME) +check_function_exists(inet_ntoa LIBVNCSERVER_HAVE_INET_NTOA) +check_function_exists(memmove LIBVNCSERVER_HAVE_MEMMOVE) +check_function_exists(memset LIBVNCSERVER_HAVE_MEMSET) +check_function_exists(mkfifo LIBVNCSERVER_HAVE_MKFIFO) +check_function_exists(select LIBVNCSERVER_HAVE_SELECT) +check_function_exists(socket LIBVNCSERVER_HAVE_SOCKET) +check_function_exists(strchr LIBVNCSERVER_HAVE_STRCHR) +check_function_exists(strcspn LIBVNCSERVER_HAVE_STRCSPN) +check_function_exists(strdup LIBVNCSERVER_HAVE_STRDUP) +check_function_exists(strerror LIBVNCSERVER_HAVE_STRERROR) +check_function_exists(strstr LIBVNCSERVER_HAVE_STRSTR) + +check_symbol_exists(htobe64 "endian.h" LIBVNCSERVER_HAVE_HTOBE64) +check_symbol_exists(OSSwapHostToBigInt64 "libkern/OSByteOrder.h" LIBVNCSERVER_HAVE_OSSWAPHOSTTOBIGINT64) + +if(LIBVNCSERVER_HAVE_SYS_SOCKET_H) + # socklen_t + list(APPEND CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h") +endif() +if(HAVE_ARPA_INET_H) + # in_addr_t + list(APPEND CMAKE_EXTRA_INCLUDE_FILES "arpa/inet.h") +endif() + +check_type_size(pid_t LIBVNCSERVER_PID_T) +check_type_size(size_t LIBVNCSERVER_SIZE_T) +check_type_size(socklen_t LIBVNCSERVER_SOCKLEN_T) +check_type_size(in_addr_t LIBVNCSERVER_IN_ADDR_T) +if(NOT HAVE_LIBVNCSERVER_IN_ADDR_T) + set(LIBVNCSERVER_NEED_INADDR_T 1) +endif() + +test_big_endian(LIBVNCSERVER_WORDS_BIGENDIAN) + +find_package(ZLIB REQUIRED) +find_package(PNG REQUIRED) +find_package(JPEG REQUIRED) +find_package(LZO REQUIRED) +set(CMAKE_THREAD_PREFER_PTHREAD TRUE) +find_package(Threads REQUIRED) + +set(_RFB_RFBCONFIG_H TRUE) +set(LIBVNCSERVER_HAVE_LIBJPEG TRUE) +set(LIBVNCSERVER_HAVE_LZO TRUE) +set(LIBVNCSERVER_HAVE_LIBPNG TRUE) +set(LIBVNCSERVER_HAVE_LIBPTHREAD TRUE) +set(LIBVNCSERVER_HAVE_LIBZ TRUE) +set(LIBVNCSERVER_HAVE_LIBSSL TRUE) +set(LIBVNCSERVER_ALLOW24BPP TRUE) +set(LIBVNCSERVER_IPv6 TRUE) + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/rfb) +configure_file(${libvncserver_DIR}/include/rfb/rfbconfig.h.cmakein ${CMAKE_CURRENT_BINARY_DIR}/rfb/rfbconfig.h @ONLY) diff --git a/cmake/modules/MinGWCrossCompile.cmake b/cmake/modules/MinGWCrossCompile.cmake index 02a8a5978..9c4f5b9e0 100644 --- a/cmake/modules/MinGWCrossCompile.cmake +++ b/cmake/modules/MinGWCrossCompile.cmake @@ -1,36 +1,31 @@ # this one is important -SET(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_SYSTEM_NAME Windows) #this one not so much -SET(CMAKE_SYSTEM_VERSION 1) +set(CMAKE_SYSTEM_VERSION 1) -SET(MINGW_PREFIX /usr/${MINGW_TARGET}/) +set(MINGW_PREFIX /usr/${MINGW_TARGET}/) # where is the target environment -SET(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX}) -SET(CMAKE_INSTALL_PREFIX ${MINGW_PREFIX}) +set(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX}) +set(CMAKE_INSTALL_PREFIX ${MINGW_PREFIX}) -SET(MINGW_TOOL_PREFIX /usr/bin/${MINGW_TARGET}-) +set(MINGW_TOOL_PREFIX /usr/bin/${MINGW_TARGET}-) # specify the cross compiler -SET(CMAKE_RC_COMPILER ${MINGW_TOOL_PREFIX}gcc) -SET(CMAKE_C_COMPILER ${MINGW_TOOL_PREFIX}gcc) -SET(CMAKE_CXX_COMPILER ${MINGW_TOOL_PREFIX}g++) +set(CMAKE_RC_COMPILER ${MINGW_TOOL_PREFIX}gcc) +set(CMAKE_C_COMPILER ${MINGW_TOOL_PREFIX}gcc) +set(CMAKE_CXX_COMPILER ${MINGW_TOOL_PREFIX}g++) # specify location of some tools -SET(STRIP ${MINGW_TOOL_PREFIX}strip) -SET(WINDRES ${MINGW_TOOL_PREFIX}windres) +set(STRIP ${MINGW_TOOL_PREFIX}strip) +set(WINDRES ${MINGW_TOOL_PREFIX}windres) -SET(QT_BINARY_DIR ${MINGW_PREFIX}/bin) -SET(QT_QMAKE_EXECUTABLE ${QT_BINARY_DIR}/qmake) +set(QT_BINARY_DIR ${MINGW_PREFIX}/bin) # search for programs in the build host directories -SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # for libraries and headers in the target directories -SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) - -SET(CMAKE_INCLUDE_PATH ${MINGW_PREFIX}/include) - -INCLUDE_DIRECTORIES(${MINGW_PREFIX}/include) -LINK_DIRECTORIES(${MINGW_PREFIX}/lib) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_INCLUDE_PATH ${MINGW_PREFIX}/include) diff --git a/cmake/modules/PchHelpers.cmake b/cmake/modules/PchHelpers.cmake new file mode 100644 index 000000000..c3bbb5c49 --- /dev/null +++ b/cmake/modules/PchHelpers.cmake @@ -0,0 +1,15 @@ + +macro(add_pch_target TARGET_NAME HEADER) + add_library(${TARGET_NAME} STATIC ${HEADER}) + + if(${CMAKE_VERSION} VERSION_GREATER "3.17.5") + file(GENERATE + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}/empty_pch.cxx + CONTENT "/*empty file*/") + set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}/empty_pch.cxx PROPERTIES SKIP_UNITY_BUILD_INCLUSION TRUE SKIP_AUTOGEN TRUE) + target_sources(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}/empty_pch.cxx) + endif() + set_default_target_properties(${TARGET_NAME}) + target_link_libraries(${TARGET_NAME} PUBLIC Qt${QT_MAJOR_VERSION}::Core Qt${QT_MAJOR_VERSION}::Concurrent Qt${QT_MAJOR_VERSION}::Network Qt${QT_MAJOR_VERSION}::Widgets) + target_precompile_headers(${TARGET_NAME} PUBLIC ${HEADER}) +endmacro() diff --git a/cmake/modules/SetDefaultTargetProperties.cmake b/cmake/modules/SetDefaultTargetProperties.cmake new file mode 100644 index 000000000..ec9fd3bba --- /dev/null +++ b/cmake/modules/SetDefaultTargetProperties.cmake @@ -0,0 +1,29 @@ +macro(set_default_target_properties TARGET_NAME) + set_property(TARGET ${TARGET_NAME} PROPERTY NO_SYSTEM_FROM_IMPORTED ON) + set_property(TARGET ${TARGET_NAME} PROPERTY CXX_STANDARD 17) + set_property(TARGET ${TARGET_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) + target_compile_options(${TARGET_NAME} PRIVATE "-Wall;-Werror") + if(WITH_LTO) + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_compile_options(${TARGET_NAME} PRIVATE ${GCC_LTO_FLAGS}) + target_link_options(${TARGET_NAME} PRIVATE ${GCC_LTO_FLAGS}) + else() + set_target_properties(${TARGET_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) + endif() + endif() + if(WITH_ADDRESS_SANITIZER) + target_link_options(${TARGET_NAME} PRIVATE "-static-libsan") + target_compile_options(${TARGET_NAME} PRIVATE "-fsanitize=address") + target_link_options(${TARGET_NAME} PRIVATE "-fsanitize=address") + else() + set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "-Wl,-no-undefined") + endif() + if(WITH_THREAD_SANITIZER) + target_compile_options(${TARGET_NAME} PRIVATE "-fsanitize=thread") + target_link_options(${TARGET_NAME} PRIVATE "-fsanitize=thread") + endif() + if(WITH_UB_SANITIZER) + target_compile_options(${TARGET_NAME} PRIVATE "-fsanitize=undefined") + target_link_options(${TARGET_NAME} PRIVATE "-fsanitize=undefined") + endif() +endmacro() diff --git a/cmake/modules/Win32Toolchain.cmake b/cmake/modules/Win32Toolchain.cmake index de6bd8dba..0df1f60ae 100644 --- a/cmake/modules/Win32Toolchain.cmake +++ b/cmake/modules/Win32Toolchain.cmake @@ -1,6 +1,6 @@ -SET(MINGW_TARGET i686-w64-mingw32) -SET(MINGW_PLATFORM win32) +set(MINGW_TARGET i686-w64-mingw32) +set(MINGW_PLATFORM win32) -SET(CMAKE_SYSTEM_PROCESSOR i686) +set(CMAKE_SYSTEM_PROCESSOR i686) -INCLUDE(MinGWCrossCompile) +include(MinGWCrossCompile) diff --git a/cmake/modules/Win64Toolchain.cmake b/cmake/modules/Win64Toolchain.cmake index c0ebad38b..8fe059105 100644 --- a/cmake/modules/Win64Toolchain.cmake +++ b/cmake/modules/Win64Toolchain.cmake @@ -1,10 +1,10 @@ -SET(MINGW_TARGET x86_64-w64-mingw32) -SET(MINGW_PLATFORM win64) +set(MINGW_TARGET x86_64-w64-mingw32) +set(MINGW_PLATFORM win64) -SET(CMAKE_SYSTEM_PROCESSOR x86_64) +set(CMAKE_SYSTEM_PROCESSOR x86_64) -SET(WIN64 TRUE) +set(WIN64 TRUE) -INCLUDE(MinGWCrossCompile) +include(MinGWCrossCompile) diff --git a/cmake/modules/WindowsBuildHelpers.cmake b/cmake/modules/WindowsBuildHelpers.cmake index 2538fa7a1..641e8f0ca 100644 --- a/cmake/modules/WindowsBuildHelpers.cmake +++ b/cmake/modules/WindowsBuildHelpers.cmake @@ -1,26 +1,18 @@ -MACRO(ADD_WINDOWS_RESOURCE TARGET) - IF(VEYON_BUILD_WIN32) - SET(WINRC "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.rc") - SET(RCOBJ "${CMAKE_CURRENT_BINARY_DIR}/winrc-${TARGET}.obj") - ADD_CUSTOM_COMMAND(OUTPUT ${RCOBJ} - COMMAND ${WINDRES} - -I${CMAKE_CURRENT_SOURCE_DIR} - -o${RCOBJ} - -i${WINRC} - DEPENDS ${WINRC}) - TARGET_SOURCES(${TARGET} PUBLIC ${RCOBJ}) - ENDIF(VEYON_BUILD_WIN32) -ENDMACRO() +macro(add_windows_resource TARGET) + if(VEYON_BUILD_WINDOWS) + set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.rc PROPERTIES INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}) + target_sources(${TARGET} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.rc) + endif() +endmacro() -MACRO(MAKE_GRAPHICAL_APP TARGET) - IF(VEYON_BUILD_WIN32) - SET_TARGET_PROPERTIES(${TARGET} PROPERTIES LINK_FLAGS -mwindows) - ENDIF() -ENDMACRO() - -MACRO(MAKE_CONSOLE_APP TARGET) - IF(VEYON_BUILD_WIN32) - SET_TARGET_PROPERTIES(${TARGET} PROPERTIES LINK_FLAGS -mconsole) - ENDIF() -ENDMACRO() +macro(make_graphical_app TARGET) + if(VEYON_BUILD_WINDOWS) + set_target_properties(${TARGET} PROPERTIES LINK_FLAGS -mwindows) + endif() +endmacro() +macro(make_console_app TARGET) + if(VEYON_BUILD_WINDOWS) + set_target_properties(${TARGET} PROPERTIES LINK_FLAGS -mconsole) + endif() +endmacro() diff --git a/cmake/modules/WindowsInstaller.cmake b/cmake/modules/WindowsInstaller.cmake new file mode 100644 index 000000000..28457dc60 --- /dev/null +++ b/cmake/modules/WindowsInstaller.cmake @@ -0,0 +1,89 @@ +set(WINDOWS_INSTALL_FILES "veyon-${VEYON_WINDOWS_ARCH}-${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_BUILD}") + +set(DLLDIR "${MINGW_PREFIX}/bin") +set(DLLDIR_LIB "${MINGW_PREFIX}/lib") +string(REGEX MATCH "^[^.]+" GCC_VERSION_MAJOR ${CMAKE_CXX_COMPILER_VERSION}) +set(DLLDIR_GCC "/usr/lib/gcc/${MINGW_TARGET}/${GCC_VERSION_MAJOR}-posix") +if(VEYON_BUILD_WIN64) + set(DLL_GCC "libgcc_s_seh-1.dll") + set(DLL_DDENGINE "ddengine64.dll") +else() + set(DLL_GCC "libgcc_s_dw2-1.dll") + set(DLL_DDENGINE "ddengine.dll") +endif() + +add_custom_target(windows-binaries + COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --config $ + COMMAND rm -rf ${WINDOWS_INSTALL_FILES}* + COMMAND mkdir -p ${WINDOWS_INSTALL_FILES}/interception + COMMAND cp ${CMAKE_SOURCE_DIR}/3rdparty/interception/* ${WINDOWS_INSTALL_FILES}/interception + COMMAND cp ${CMAKE_SOURCE_DIR}/3rdparty/ddengine/${DLL_DDENGINE} ${WINDOWS_INSTALL_FILES} + COMMAND cp core/veyon-core.dll ${WINDOWS_INSTALL_FILES} + COMMAND find . -mindepth 2 -name 'veyon-*.exe' -exec cp '{}' ${WINDOWS_INSTALL_FILES}/ '\;' + COMMAND mkdir -p ${WINDOWS_INSTALL_FILES}/plugins + COMMAND find plugins/ -name '*.dll' -exec cp '{}' ${WINDOWS_INSTALL_FILES}/plugins/ '\;' + COMMAND mv ${WINDOWS_INSTALL_FILES}/plugins/lib*.dll ${WINDOWS_INSTALL_FILES} + COMMAND mv ${WINDOWS_INSTALL_FILES}/plugins/vnchooks.dll ${WINDOWS_INSTALL_FILES} + COMMAND mkdir -p ${WINDOWS_INSTALL_FILES}/translations + COMMAND cp translations/*qm ${WINDOWS_INSTALL_FILES}/translations/ + COMMAND cp ${DLLDIR}/libjpeg-62.dll ${WINDOWS_INSTALL_FILES} + COMMAND cp ${DLLDIR}/libpng16-16.dll ${WINDOWS_INSTALL_FILES} + COMMAND cp ${DLLDIR}/libcrypto-3*.dll ${DLLDIR}/libssl-3*.dll ${WINDOWS_INSTALL_FILES} + COMMAND cp ${DLLDIR}/libqca-qt6.dll ${WINDOWS_INSTALL_FILES} + COMMAND cp ${DLLDIR}/libsasl2-3.dll ${WINDOWS_INSTALL_FILES} + COMMAND cp ${DLLDIR}/libldap.dll ${DLLDIR}/liblber.dll ${WINDOWS_INSTALL_FILES} + COMMAND cp ${DLLDIR}/interception.dll ${WINDOWS_INSTALL_FILES} + COMMAND cp ${DLLDIR}/liblzo2-2.dll ${WINDOWS_INSTALL_FILES} + COMMAND cp ${DLLDIR}/libvncclient.dll ${WINDOWS_INSTALL_FILES} + COMMAND cp ${DLLDIR_LIB}/zlib1.dll ${WINDOWS_INSTALL_FILES} + COMMAND cp ${DLLDIR_LIB}/libwinpthread-1.dll ${WINDOWS_INSTALL_FILES} + COMMAND cp ${DLLDIR_GCC}/libstdc++-6.dll ${WINDOWS_INSTALL_FILES} + COMMAND cp ${DLLDIR_GCC}/libssp-0.dll ${WINDOWS_INSTALL_FILES} + COMMAND cp ${DLLDIR_GCC}/${DLL_GCC} ${WINDOWS_INSTALL_FILES} + COMMAND mkdir -p ${WINDOWS_INSTALL_FILES}/crypto + COMMAND cp ${DLLDIR_LIB}/qca-qt6/crypto/libqca-ossl.dll ${WINDOWS_INSTALL_FILES}/crypto + COMMAND cp ${DLLDIR}/Qt6Core.dll + ${DLLDIR}/Qt6Core5Compat.dll + ${DLLDIR}/Qt6Gui.dll + ${DLLDIR}/Qt6Widgets.dll + ${DLLDIR}/Qt6Network.dll + ${DLLDIR}/Qt6Concurrent.dll + ${DLLDIR}/Qt6Qml.dll + ${DLLDIR}/Qt6QmlModels.dll + ${DLLDIR}/Qt6Quick.dll + ${DLLDIR}/Qt6QuickControls2.dll + ${DLLDIR}/Qt6QuickTemplates2.dll + ${WINDOWS_INSTALL_FILES} + COMMAND mkdir -p ${WINDOWS_INSTALL_FILES}/imageformats + COMMAND cp ${MINGW_PREFIX}/plugins/imageformats/qjpeg.dll ${WINDOWS_INSTALL_FILES}/imageformats + COMMAND mkdir -p ${WINDOWS_INSTALL_FILES}/platforms + COMMAND cp ${MINGW_PREFIX}/plugins/platforms/qwindows.dll ${WINDOWS_INSTALL_FILES}/platforms + COMMAND mkdir -p ${WINDOWS_INSTALL_FILES}/styles + COMMAND cp ${MINGW_PREFIX}/plugins/styles/*.dll ${WINDOWS_INSTALL_FILES}/styles + COMMAND mkdir -p ${WINDOWS_INSTALL_FILES}/tls + COMMAND cp ${MINGW_PREFIX}/plugins/tls/qopensslbackend.dll ${WINDOWS_INSTALL_FILES}/tls + COMMAND ${MINGW_TOOL_PREFIX}strip ${WINDOWS_INSTALL_FILES}/*.dll ${WINDOWS_INSTALL_FILES}/*.exe ${WINDOWS_INSTALL_FILES}/plugins/*.dll ${WINDOWS_INSTALL_FILES}/platforms/*.dll ${WINDOWS_INSTALL_FILES}/styles/*.dll ${WINDOWS_INSTALL_FILES}/crypto/*.dll + COMMAND cp ${CMAKE_SOURCE_DIR}/COPYING ${WINDOWS_INSTALL_FILES} + COMMAND cp ${CMAKE_SOURCE_DIR}/COPYING ${WINDOWS_INSTALL_FILES}/LICENSE.TXT + COMMAND cp ${CMAKE_SOURCE_DIR}/README.md ${WINDOWS_INSTALL_FILES}/README.TXT + COMMAND todos ${WINDOWS_INSTALL_FILES}/*.TXT + COMMAND cp -ra ${CMAKE_SOURCE_DIR}/nsis ${WINDOWS_INSTALL_FILES} + COMMAND cp ${CMAKE_BINARY_DIR}/nsis/veyon.nsi ${WINDOWS_INSTALL_FILES} + COMMAND find ${WINDOWS_INSTALL_FILES} -ls +) + +add_custom_target(create-windows-installer + COMMAND makensis ${WINDOWS_INSTALL_FILES}/veyon.nsi + COMMAND mv ${WINDOWS_INSTALL_FILES}/veyon-*setup.exe . + COMMAND rm -rf ${WINDOWS_INSTALL_FILES} + DEPENDS windows-binaries +) + +add_custom_target(prepare-dev-nsi + COMMAND sed -i ${WINDOWS_INSTALL_FILES}/veyon.nsi -e "s,/SOLID lzma,zlib,g" + DEPENDS windows-binaries) + +add_custom_target(dev-nsi + DEPENDS prepare-dev-nsi create-windows-installer +) + diff --git a/cmake/modules/XdgInstall.cmake b/cmake/modules/XdgInstall.cmake index 275ce253a..0f395504b 100644 --- a/cmake/modules/XdgInstall.cmake +++ b/cmake/modules/XdgInstall.cmake @@ -1,12 +1,12 @@ -FIND_PROGRAM(XDG_DESKTOP_MENU_EXECUTABLE xdg-desktop-menu) -SET(XDG_APPS_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/share/applications) +find_program(XDG_DESKTOP_MENU_EXECUTABLE xdg-desktop-menu) +set(XDG_APPS_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/share/applications) -MACRO(XDG_INSTALL DESKTOP_FILE ICON_XPM ICON_PNG ICON_SVG) - INSTALL(FILES ${DESKTOP_FILE} DESTINATION ${XDG_APPS_INSTALL_DIR}) - INSTALL(FILES ${ICON_XPM} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps) - INSTALL(FILES ${ICON_PNG} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps) - INSTALL(FILES ${ICON_SVG} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps) - #IF(XDG_DESKTOP_MENU_EXECUTABLE) - # INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${XDG_DESKTOP_MENU_EXECUTABLE} install --novendor ${XDG_APPS_INSTALL_DIR}/${DESKTOP_FILE})") - #ENDIF() -ENDMACRO() +macro(xdg_install DESKTOP_FILE ICON_XPM ICON_PNG ICON_SVG) + install(FILES ${DESKTOP_FILE} DESTINATION ${XDG_APPS_INSTALL_DIR}) + install(FILES ${ICON_XPM} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps) + install(FILES ${ICON_PNG} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps) + install(FILES ${ICON_SVG} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps) + #if(XDG_DESKTOP_MENU_EXECUTABLE) + # install(CODE "execute_process(COMMAND ${XDG_DESKTOP_MENU_EXECUTABLE} install --novendor ${XDG_APPS_INSTALL_DIR}/${DESKTOP_FILE})") + #endif() +endmacro() diff --git a/cmake/modules/cotire.cmake b/cmake/modules/cotire.cmake deleted file mode 100644 index 97275d649..000000000 --- a/cmake/modules/cotire.cmake +++ /dev/null @@ -1,4190 +0,0 @@ -# - cotire (compile time reducer) -# -# See the cotire manual for usage hints. -# -#============================================================================= -# Copyright 2012-2018 Sascha Kratky -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation -# files (the "Software"), to deal in the Software without -# restriction, including without limitation the rights to use, -# copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following -# conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. -#============================================================================= - -if(__COTIRE_INCLUDED) - return() -endif() -set(__COTIRE_INCLUDED TRUE) - -# call cmake_minimum_required, but prevent modification of the CMake policy stack in include mode -# cmake_minimum_required also sets the policy version as a side effect, which we have to avoid -if (NOT CMAKE_SCRIPT_MODE_FILE) - cmake_policy(PUSH) -endif() -cmake_minimum_required(VERSION 2.8.12) -if (NOT CMAKE_SCRIPT_MODE_FILE) - cmake_policy(POP) -endif() - -set (COTIRE_CMAKE_MODULE_FILE "${CMAKE_CURRENT_LIST_FILE}") -set (COTIRE_CMAKE_MODULE_VERSION "1.8.0") - -# activate select policies -if (POLICY CMP0025) - # Compiler id for Apple Clang is now AppleClang - cmake_policy(SET CMP0025 NEW) -endif() - -if (POLICY CMP0026) - # disallow use of the LOCATION target property - cmake_policy(SET CMP0026 NEW) -endif() - -if (POLICY CMP0038) - # targets may not link directly to themselves - cmake_policy(SET CMP0038 NEW) -endif() - -if (POLICY CMP0039) - # utility targets may not have link dependencies - cmake_policy(SET CMP0039 NEW) -endif() - -if (POLICY CMP0040) - # target in the TARGET signature of add_custom_command() must exist - cmake_policy(SET CMP0040 NEW) -endif() - -if (POLICY CMP0045) - # error on non-existent target in get_target_property - cmake_policy(SET CMP0045 NEW) -endif() - -if (POLICY CMP0046) - # error on non-existent dependency in add_dependencies - cmake_policy(SET CMP0046 NEW) -endif() - -if (POLICY CMP0049) - # do not expand variables in target source entries - cmake_policy(SET CMP0049 NEW) -endif() - -if (POLICY CMP0050) - # disallow add_custom_command SOURCE signatures - cmake_policy(SET CMP0050 NEW) -endif() - -if (POLICY CMP0051) - # include TARGET_OBJECTS expressions in a target's SOURCES property - cmake_policy(SET CMP0051 NEW) -endif() - -if (POLICY CMP0053) - # simplify variable reference and escape sequence evaluation - cmake_policy(SET CMP0053 NEW) -endif() - -if (POLICY CMP0054) - # only interpret if() arguments as variables or keywords when unquoted - cmake_policy(SET CMP0054 NEW) -endif() - -if (POLICY CMP0055) - # strict checking for break() command - cmake_policy(SET CMP0055 NEW) -endif() - -include(CMakeParseArguments) -include(ProcessorCount) - -function (cotire_get_configuration_types _configsVar) - set (_configs "") - if (CMAKE_CONFIGURATION_TYPES) - list (APPEND _configs ${CMAKE_CONFIGURATION_TYPES}) - endif() - if (CMAKE_BUILD_TYPE) - list (APPEND _configs "${CMAKE_BUILD_TYPE}") - endif() - if (_configs) - list (REMOVE_DUPLICATES _configs) - set (${_configsVar} ${_configs} PARENT_SCOPE) - else() - set (${_configsVar} "None" PARENT_SCOPE) - endif() -endfunction() - -function (cotire_get_source_file_extension _sourceFile _extVar) - # get_filename_component returns extension from first occurrence of . in file name - # this function computes the extension from last occurrence of . in file name - string (FIND "${_sourceFile}" "." _index REVERSE) - if (_index GREATER -1) - math (EXPR _index "${_index} + 1") - string (SUBSTRING "${_sourceFile}" ${_index} -1 _sourceExt) - else() - set (_sourceExt "") - endif() - set (${_extVar} "${_sourceExt}" PARENT_SCOPE) -endfunction() - -macro (cotire_check_is_path_relative_to _path _isRelativeVar) - set (${_isRelativeVar} FALSE) - if (IS_ABSOLUTE "${_path}") - foreach (_dir ${ARGN}) - file (RELATIVE_PATH _relPath "${_dir}" "${_path}") - if (NOT _relPath OR (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.")) - set (${_isRelativeVar} TRUE) - break() - endif() - endforeach() - endif() -endmacro() - -function (cotire_filter_language_source_files _language _target _sourceFilesVar _excludedSourceFilesVar _cotiredSourceFilesVar) - if (CMAKE_${_language}_SOURCE_FILE_EXTENSIONS) - set (_languageExtensions "${CMAKE_${_language}_SOURCE_FILE_EXTENSIONS}") - else() - set (_languageExtensions "") - endif() - if (CMAKE_${_language}_IGNORE_EXTENSIONS) - set (_ignoreExtensions "${CMAKE_${_language}_IGNORE_EXTENSIONS}") - else() - set (_ignoreExtensions "") - endif() - if (COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS) - set (_excludeExtensions "${COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS}") - else() - set (_excludeExtensions "") - endif() - if (COTIRE_DEBUG AND _languageExtensions) - message (STATUS "${_language} source file extensions: ${_languageExtensions}") - endif() - if (COTIRE_DEBUG AND _ignoreExtensions) - message (STATUS "${_language} ignore extensions: ${_ignoreExtensions}") - endif() - if (COTIRE_DEBUG AND _excludeExtensions) - message (STATUS "${_language} exclude extensions: ${_excludeExtensions}") - endif() - if (CMAKE_VERSION VERSION_LESS "3.1.0") - set (_allSourceFiles ${ARGN}) - else() - # as of CMake 3.1 target sources may contain generator expressions - # since we cannot obtain required property information about source files added - # through generator expressions at configure time, we filter them out - string (GENEX_STRIP "${ARGN}" _allSourceFiles) - endif() - set (_filteredSourceFiles "") - set (_excludedSourceFiles "") - foreach (_sourceFile ${_allSourceFiles}) - get_source_file_property(_sourceIsHeaderOnly "${_sourceFile}" HEADER_FILE_ONLY) - get_source_file_property(_sourceIsExternal "${_sourceFile}" EXTERNAL_OBJECT) - get_source_file_property(_sourceIsSymbolic "${_sourceFile}" SYMBOLIC) - if (NOT _sourceIsHeaderOnly AND NOT _sourceIsExternal AND NOT _sourceIsSymbolic) - cotire_get_source_file_extension("${_sourceFile}" _sourceExt) - if (_sourceExt) - list (FIND _ignoreExtensions "${_sourceExt}" _ignoreIndex) - if (_ignoreIndex LESS 0) - list (FIND _excludeExtensions "${_sourceExt}" _excludeIndex) - if (_excludeIndex GREATER -1) - list (APPEND _excludedSourceFiles "${_sourceFile}") - else() - list (FIND _languageExtensions "${_sourceExt}" _sourceIndex) - if (_sourceIndex GREATER -1) - # consider source file unless it is excluded explicitly - get_source_file_property(_sourceIsExcluded "${_sourceFile}" COTIRE_EXCLUDED) - if (_sourceIsExcluded) - list (APPEND _excludedSourceFiles "${_sourceFile}") - else() - list (APPEND _filteredSourceFiles "${_sourceFile}") - endif() - else() - get_source_file_property(_sourceLanguage "${_sourceFile}" LANGUAGE) - if ("${_sourceLanguage}" STREQUAL "${_language}") - # add to excluded sources, if file is not ignored and has correct language without having the correct extension - list (APPEND _excludedSourceFiles "${_sourceFile}") - endif() - endif() - endif() - endif() - endif() - endif() - endforeach() - # separate filtered source files from already cotired ones - # the COTIRE_TARGET property of a source file may be set while a target is being processed by cotire - set (_sourceFiles "") - set (_cotiredSourceFiles "") - foreach (_sourceFile ${_filteredSourceFiles}) - get_source_file_property(_sourceIsCotired "${_sourceFile}" COTIRE_TARGET) - if (_sourceIsCotired) - list (APPEND _cotiredSourceFiles "${_sourceFile}") - else() - get_source_file_property(_sourceCompileFlags "${_sourceFile}" COMPILE_FLAGS) - if (_sourceCompileFlags) - # add to excluded sources, if file has custom compile flags - list (APPEND _excludedSourceFiles "${_sourceFile}") - else() - get_source_file_property(_sourceCompileOptions "${_sourceFile}" COMPILE_OPTIONS) - if (_sourceCompileOptions) - # add to excluded sources, if file has list of custom compile options - list (APPEND _excludedSourceFiles "${_sourceFile}") - else() - list (APPEND _sourceFiles "${_sourceFile}") - endif() - endif() - endif() - endforeach() - if (COTIRE_DEBUG) - if (_sourceFiles) - message (STATUS "Filtered ${_target} ${_language} sources: ${_sourceFiles}") - endif() - if (_excludedSourceFiles) - message (STATUS "Excluded ${_target} ${_language} sources: ${_excludedSourceFiles}") - endif() - if (_cotiredSourceFiles) - message (STATUS "Cotired ${_target} ${_language} sources: ${_cotiredSourceFiles}") - endif() - endif() - set (${_sourceFilesVar} ${_sourceFiles} PARENT_SCOPE) - set (${_excludedSourceFilesVar} ${_excludedSourceFiles} PARENT_SCOPE) - set (${_cotiredSourceFilesVar} ${_cotiredSourceFiles} PARENT_SCOPE) -endfunction() - -function (cotire_get_objects_with_property_on _filteredObjectsVar _property _type) - set (_filteredObjects "") - foreach (_object ${ARGN}) - get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET) - if (_isSet) - get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) - if (_propertyValue) - list (APPEND _filteredObjects "${_object}") - endif() - endif() - endforeach() - set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE) -endfunction() - -function (cotire_get_objects_with_property_off _filteredObjectsVar _property _type) - set (_filteredObjects "") - foreach (_object ${ARGN}) - get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET) - if (_isSet) - get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) - if (NOT _propertyValue) - list (APPEND _filteredObjects "${_object}") - endif() - endif() - endforeach() - set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_file_property_values _valuesVar _property) - set (_values "") - foreach (_sourceFile ${ARGN}) - get_source_file_property(_propertyValue "${_sourceFile}" ${_property}) - if (_propertyValue) - list (APPEND _values "${_propertyValue}") - endif() - endforeach() - set (${_valuesVar} ${_values} PARENT_SCOPE) -endfunction() - -function (cotire_resolve_config_properties _configurations _propertiesVar) - set (_properties "") - foreach (_property ${ARGN}) - if ("${_property}" MATCHES "") - foreach (_config ${_configurations}) - string (TOUPPER "${_config}" _upperConfig) - string (REPLACE "" "${_upperConfig}" _configProperty "${_property}") - list (APPEND _properties ${_configProperty}) - endforeach() - else() - list (APPEND _properties ${_property}) - endif() - endforeach() - set (${_propertiesVar} ${_properties} PARENT_SCOPE) -endfunction() - -function (cotire_copy_set_properties _configurations _type _source _target) - cotire_resolve_config_properties("${_configurations}" _properties ${ARGN}) - foreach (_property ${_properties}) - get_property(_isSet ${_type} ${_source} PROPERTY ${_property} SET) - if (_isSet) - get_property(_propertyValue ${_type} ${_source} PROPERTY ${_property}) - set_property(${_type} ${_target} PROPERTY ${_property} "${_propertyValue}") - endif() - endforeach() -endfunction() - -function (cotire_get_target_usage_requirements _target _config _targetRequirementsVar) - set (_targetRequirements "") - get_target_property(_librariesToProcess ${_target} LINK_LIBRARIES) - while (_librariesToProcess) - # remove from head - list (GET _librariesToProcess 0 _library) - list (REMOVE_AT _librariesToProcess 0) - if (_library MATCHES "^\\$<\\$:([A-Za-z0-9_:-]+)>$") - set (_library "${CMAKE_MATCH_1}") - elseif (_config STREQUAL "None" AND _library MATCHES "^\\$<\\$:([A-Za-z0-9_:-]+)>$") - set (_library "${CMAKE_MATCH_1}") - endif() - if (TARGET ${_library}) - list (FIND _targetRequirements ${_library} _index) - if (_index LESS 0) - list (APPEND _targetRequirements ${_library}) - # BFS traversal of transitive libraries - get_target_property(_libraries ${_library} INTERFACE_LINK_LIBRARIES) - if (_libraries) - list (APPEND _librariesToProcess ${_libraries}) - list (REMOVE_DUPLICATES _librariesToProcess) - endif() - endif() - endif() - endwhile() - set (${_targetRequirementsVar} ${_targetRequirements} PARENT_SCOPE) -endfunction() - -function (cotire_filter_compile_flags _language _flagFilter _matchedOptionsVar _unmatchedOptionsVar) - if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - set (_flagPrefix "[/-]") - else() - set (_flagPrefix "--?") - endif() - set (_optionFlag "") - set (_matchedOptions "") - set (_unmatchedOptions "") - foreach (_compileFlag ${ARGN}) - if (_compileFlag) - if (_optionFlag AND NOT "${_compileFlag}" MATCHES "^${_flagPrefix}") - # option with separate argument - list (APPEND _matchedOptions "${_compileFlag}") - set (_optionFlag "") - elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})$") - # remember option - set (_optionFlag "${CMAKE_MATCH_2}") - elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})(.+)$") - # option with joined argument - list (APPEND _matchedOptions "${CMAKE_MATCH_3}") - set (_optionFlag "") - else() - # flush remembered option - if (_optionFlag) - list (APPEND _matchedOptions "${_optionFlag}") - set (_optionFlag "") - endif() - # add to unfiltered options - list (APPEND _unmatchedOptions "${_compileFlag}") - endif() - endif() - endforeach() - if (_optionFlag) - list (APPEND _matchedOptions "${_optionFlag}") - endif() - if (COTIRE_DEBUG AND _matchedOptions) - message (STATUS "Filter ${_flagFilter} matched: ${_matchedOptions}") - endif() - if (COTIRE_DEBUG AND _unmatchedOptions) - message (STATUS "Filter ${_flagFilter} unmatched: ${_unmatchedOptions}") - endif() - set (${_matchedOptionsVar} ${_matchedOptions} PARENT_SCOPE) - set (${_unmatchedOptionsVar} ${_unmatchedOptions} PARENT_SCOPE) -endfunction() - -function (cotire_is_target_supported _target _isSupportedVar) - if (NOT TARGET "${_target}") - set (${_isSupportedVar} FALSE PARENT_SCOPE) - return() - endif() - get_target_property(_imported ${_target} IMPORTED) - if (_imported) - set (${_isSupportedVar} FALSE PARENT_SCOPE) - return() - endif() - get_target_property(_targetType ${_target} TYPE) - if (NOT _targetType MATCHES "EXECUTABLE|(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") - set (${_isSupportedVar} FALSE PARENT_SCOPE) - return() - endif() - set (${_isSupportedVar} TRUE PARENT_SCOPE) -endfunction() - -function (cotire_get_target_compile_flags _config _language _target _flagsVar) - string (TOUPPER "${_config}" _upperConfig) - # collect options from CMake language variables - set (_compileFlags "") - if (CMAKE_${_language}_FLAGS) - set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS}") - endif() - if (CMAKE_${_language}_FLAGS_${_upperConfig}) - set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS_${_upperConfig}}") - endif() - if (_target) - # add target compile flags - get_target_property(_targetflags ${_target} COMPILE_FLAGS) - if (_targetflags) - set (_compileFlags "${_compileFlags} ${_targetflags}") - endif() - endif() - if (UNIX) - separate_arguments(_compileFlags UNIX_COMMAND "${_compileFlags}") - elseif(WIN32) - separate_arguments(_compileFlags WINDOWS_COMMAND "${_compileFlags}") - else() - separate_arguments(_compileFlags) - endif() - # target compile options - if (_target) - get_target_property(_targetOptions ${_target} COMPILE_OPTIONS) - if (_targetOptions) - list (APPEND _compileFlags ${_targetOptions}) - endif() - endif() - # interface compile options from linked library targets - if (_target) - set (_linkedTargets "") - cotire_get_target_usage_requirements(${_target} ${_config} _linkedTargets) - foreach (_linkedTarget ${_linkedTargets}) - get_target_property(_targetOptions ${_linkedTarget} INTERFACE_COMPILE_OPTIONS) - if (_targetOptions) - list (APPEND _compileFlags ${_targetOptions}) - endif() - endforeach() - endif() - # handle language standard properties - if (CMAKE_${_language}_STANDARD_DEFAULT) - # used compiler supports language standard levels - if (_target) - get_target_property(_targetLanguageStandard ${_target} ${_language}_STANDARD) - if (_targetLanguageStandard) - set (_type "EXTENSION") - get_property(_isSet TARGET ${_target} PROPERTY ${_language}_EXTENSIONS SET) - if (_isSet) - get_target_property(_targetUseLanguageExtensions ${_target} ${_language}_EXTENSIONS) - if (NOT _targetUseLanguageExtensions) - set (_type "STANDARD") - endif() - endif() - if (CMAKE_${_language}${_targetLanguageStandard}_${_type}_COMPILE_OPTION) - list (APPEND _compileFlags "${CMAKE_${_language}${_targetLanguageStandard}_${_type}_COMPILE_OPTION}") - endif() - endif() - endif() - endif() - # handle the POSITION_INDEPENDENT_CODE target property - if (_target) - get_target_property(_targetPIC ${_target} POSITION_INDEPENDENT_CODE) - if (_targetPIC) - get_target_property(_targetType ${_target} TYPE) - if (_targetType STREQUAL "EXECUTABLE" AND CMAKE_${_language}_COMPILE_OPTIONS_PIE) - list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_PIE}") - elseif (CMAKE_${_language}_COMPILE_OPTIONS_PIC) - list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_PIC}") - endif() - endif() - endif() - # handle visibility target properties - if (_target) - get_target_property(_targetVisibility ${_target} ${_language}_VISIBILITY_PRESET) - if (_targetVisibility AND CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY) - list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY}${_targetVisibility}") - endif() - get_target_property(_targetVisibilityInlines ${_target} VISIBILITY_INLINES_HIDDEN) - if (_targetVisibilityInlines AND CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN) - list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN}") - endif() - endif() - # platform specific flags - if (APPLE) - get_target_property(_architectures ${_target} OSX_ARCHITECTURES_${_upperConfig}) - if (NOT _architectures) - get_target_property(_architectures ${_target} OSX_ARCHITECTURES) - endif() - if (_architectures) - foreach (_arch ${_architectures}) - list (APPEND _compileFlags "-arch" "${_arch}") - endforeach() - endif() - if (CMAKE_OSX_SYSROOT) - if (CMAKE_${_language}_SYSROOT_FLAG) - list (APPEND _compileFlags "${CMAKE_${_language}_SYSROOT_FLAG}" "${CMAKE_OSX_SYSROOT}") - else() - list (APPEND _compileFlags "-isysroot" "${CMAKE_OSX_SYSROOT}") - endif() - endif() - if (CMAKE_OSX_DEPLOYMENT_TARGET) - if (CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG) - list (APPEND _compileFlags "${CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG}${CMAKE_OSX_DEPLOYMENT_TARGET}") - else() - list (APPEND _compileFlags "-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") - endif() - endif() - endif() - if (COTIRE_DEBUG AND _compileFlags) - message (STATUS "Target ${_target} compile flags: ${_compileFlags}") - endif() - set (${_flagsVar} ${_compileFlags} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_include_directories _config _language _target _includeDirsVar _systemIncludeDirsVar) - set (_includeDirs "") - set (_systemIncludeDirs "") - # default include dirs - if (CMAKE_INCLUDE_CURRENT_DIR) - list (APPEND _includeDirs "${CMAKE_CURRENT_BINARY_DIR}") - list (APPEND _includeDirs "${CMAKE_CURRENT_SOURCE_DIR}") - endif() - set (_targetFlags "") - cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) - # parse additional include directories from target compile flags - if (CMAKE_INCLUDE_FLAG_${_language}) - string (STRIP "${CMAKE_INCLUDE_FLAG_${_language}}" _includeFlag) - string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") - if (_includeFlag) - set (_dirs "") - cotire_filter_compile_flags("${_language}" "${_includeFlag}" _dirs _ignore ${_targetFlags}) - if (_dirs) - list (APPEND _includeDirs ${_dirs}) - endif() - endif() - endif() - # parse additional system include directories from target compile flags - if (CMAKE_INCLUDE_SYSTEM_FLAG_${_language}) - string (STRIP "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" _includeFlag) - string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") - if (_includeFlag) - set (_dirs "") - cotire_filter_compile_flags("${_language}" "${_includeFlag}" _dirs _ignore ${_targetFlags}) - if (_dirs) - list (APPEND _systemIncludeDirs ${_dirs}) - endif() - endif() - endif() - # target include directories - get_directory_property(_dirs DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" INCLUDE_DIRECTORIES) - if (_target) - get_target_property(_targetDirs ${_target} INCLUDE_DIRECTORIES) - if (_targetDirs) - list (APPEND _dirs ${_targetDirs}) - endif() - get_target_property(_targetDirs ${_target} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) - if (_targetDirs) - list (APPEND _systemIncludeDirs ${_targetDirs}) - endif() - endif() - # interface include directories from linked library targets - if (_target) - set (_linkedTargets "") - cotire_get_target_usage_requirements(${_target} ${_config} _linkedTargets) - foreach (_linkedTarget ${_linkedTargets}) - get_target_property(_linkedTargetType ${_linkedTarget} TYPE) - if (CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE AND NOT CMAKE_VERSION VERSION_LESS "3.4.0" AND - _linkedTargetType MATCHES "(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") - # CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE refers to CMAKE_CURRENT_BINARY_DIR and CMAKE_CURRENT_SOURCE_DIR - # at the time, when the target was created. These correspond to the target properties BINARY_DIR and SOURCE_DIR - # which are only available with CMake 3.4 or later. - get_target_property(_targetDirs ${_linkedTarget} BINARY_DIR) - if (_targetDirs) - list (APPEND _dirs ${_targetDirs}) - endif() - get_target_property(_targetDirs ${_linkedTarget} SOURCE_DIR) - if (_targetDirs) - list (APPEND _dirs ${_targetDirs}) - endif() - endif() - get_target_property(_targetDirs ${_linkedTarget} INTERFACE_INCLUDE_DIRECTORIES) - if (_targetDirs) - list (APPEND _dirs ${_targetDirs}) - endif() - get_target_property(_targetDirs ${_linkedTarget} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) - if (_targetDirs) - list (APPEND _systemIncludeDirs ${_targetDirs}) - endif() - endforeach() - endif() - if (dirs) - list (REMOVE_DUPLICATES _dirs) - endif() - list (LENGTH _includeDirs _projectInsertIndex) - foreach (_dir ${_dirs}) - if (CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE) - cotire_check_is_path_relative_to("${_dir}" _isRelative "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}") - if (_isRelative) - list (LENGTH _includeDirs _len) - if (_len EQUAL _projectInsertIndex) - list (APPEND _includeDirs "${_dir}") - else() - list (INSERT _includeDirs _projectInsertIndex "${_dir}") - endif() - math (EXPR _projectInsertIndex "${_projectInsertIndex} + 1") - else() - list (APPEND _includeDirs "${_dir}") - endif() - else() - list (APPEND _includeDirs "${_dir}") - endif() - endforeach() - list (REMOVE_DUPLICATES _includeDirs) - list (REMOVE_DUPLICATES _systemIncludeDirs) - if (CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES) - list (REMOVE_ITEM _includeDirs ${CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES}) - endif() - if (WIN32 AND NOT MINGW) - # convert Windows paths in include directories to CMake paths - if (_includeDirs) - set (_paths "") - foreach (_dir ${_includeDirs}) - file (TO_CMAKE_PATH "${_dir}" _path) - list (APPEND _paths "${_path}") - endforeach() - set (_includeDirs ${_paths}) - endif() - if (_systemIncludeDirs) - set (_paths "") - foreach (_dir ${_systemIncludeDirs}) - file (TO_CMAKE_PATH "${_dir}" _path) - list (APPEND _paths "${_path}") - endforeach() - set (_systemIncludeDirs ${_paths}) - endif() - endif() - if (COTIRE_DEBUG AND _includeDirs) - message (STATUS "Target ${_target} include dirs: ${_includeDirs}") - endif() - set (${_includeDirsVar} ${_includeDirs} PARENT_SCOPE) - if (COTIRE_DEBUG AND _systemIncludeDirs) - message (STATUS "Target ${_target} system include dirs: ${_systemIncludeDirs}") - endif() - set (${_systemIncludeDirsVar} ${_systemIncludeDirs} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_export_symbol _target _exportSymbolVar) - set (_exportSymbol "") - get_target_property(_targetType ${_target} TYPE) - get_target_property(_enableExports ${_target} ENABLE_EXPORTS) - if (_targetType MATCHES "(SHARED|MODULE)_LIBRARY" OR - (_targetType STREQUAL "EXECUTABLE" AND _enableExports)) - get_target_property(_exportSymbol ${_target} DEFINE_SYMBOL) - if (NOT _exportSymbol) - set (_exportSymbol "${_target}_EXPORTS") - endif() - string (MAKE_C_IDENTIFIER "${_exportSymbol}" _exportSymbol) - endif() - set (${_exportSymbolVar} ${_exportSymbol} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_compile_definitions _config _language _target _definitionsVar) - string (TOUPPER "${_config}" _upperConfig) - set (_configDefinitions "") - # CMAKE_INTDIR for multi-configuration build systems - if (NOT "${CMAKE_CFG_INTDIR}" STREQUAL ".") - list (APPEND _configDefinitions "CMAKE_INTDIR=\"${_config}\"") - endif() - # target export define symbol - cotire_get_target_export_symbol("${_target}" _defineSymbol) - if (_defineSymbol) - list (APPEND _configDefinitions "${_defineSymbol}") - endif() - # directory compile definitions - get_directory_property(_definitions DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMPILE_DEFINITIONS) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - get_directory_property(_definitions DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMPILE_DEFINITIONS_${_upperConfig}) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - # target compile definitions - get_target_property(_definitions ${_target} COMPILE_DEFINITIONS) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - get_target_property(_definitions ${_target} COMPILE_DEFINITIONS_${_upperConfig}) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - # interface compile definitions from linked library targets - set (_linkedTargets "") - cotire_get_target_usage_requirements(${_target} ${_config} _linkedTargets) - foreach (_linkedTarget ${_linkedTargets}) - get_target_property(_definitions ${_linkedTarget} INTERFACE_COMPILE_DEFINITIONS) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - endforeach() - # parse additional compile definitions from target compile flags - # and do not look at directory compile definitions, which we already handled - set (_targetFlags "") - cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) - cotire_filter_compile_flags("${_language}" "D" _definitions _ignore ${_targetFlags}) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - list (REMOVE_DUPLICATES _configDefinitions) - if (COTIRE_DEBUG AND _configDefinitions) - message (STATUS "Target ${_target} compile definitions: ${_configDefinitions}") - endif() - set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_compiler_flags _config _language _target _compilerFlagsVar) - # parse target compile flags omitting compile definitions and include directives - set (_targetFlags "") - cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) - set (_flagFilter "D") - if (CMAKE_INCLUDE_FLAG_${_language}) - string (STRIP "${CMAKE_INCLUDE_FLAG_${_language}}" _includeFlag) - string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") - if (_includeFlag) - set (_flagFilter "${_flagFilter}|${_includeFlag}") - endif() - endif() - if (CMAKE_INCLUDE_SYSTEM_FLAG_${_language}) - string (STRIP "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" _includeFlag) - string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") - if (_includeFlag) - set (_flagFilter "${_flagFilter}|${_includeFlag}") - endif() - endif() - set (_compilerFlags "") - cotire_filter_compile_flags("${_language}" "${_flagFilter}" _ignore _compilerFlags ${_targetFlags}) - if (COTIRE_DEBUG AND _compilerFlags) - message (STATUS "Target ${_target} compiler flags: ${_compilerFlags}") - endif() - set (${_compilerFlagsVar} ${_compilerFlags} PARENT_SCOPE) -endfunction() - -function (cotire_add_sys_root_paths _pathsVar) - if (APPLE) - if (CMAKE_OSX_SYSROOT AND CMAKE_${_language}_HAS_ISYSROOT) - foreach (_path IN LISTS ${_pathsVar}) - if (IS_ABSOLUTE "${_path}") - get_filename_component(_path "${CMAKE_OSX_SYSROOT}/${_path}" ABSOLUTE) - if (EXISTS "${_path}") - list (APPEND ${_pathsVar} "${_path}") - endif() - endif() - endforeach() - endif() - endif() - set (${_pathsVar} ${${_pathsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_extra_properties _sourceFile _pattern _resultVar) - set (_extraProperties ${ARGN}) - set (_result "") - if (_extraProperties) - list (FIND _extraProperties "${_sourceFile}" _index) - if (_index GREATER -1) - math (EXPR _index "${_index} + 1") - list (LENGTH _extraProperties _len) - math (EXPR _len "${_len} - 1") - foreach (_index RANGE ${_index} ${_len}) - list (GET _extraProperties ${_index} _value) - if (_value MATCHES "${_pattern}") - list (APPEND _result "${_value}") - else() - break() - endif() - endforeach() - endif() - endif() - set (${_resultVar} ${_result} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_compile_definitions _config _language _sourceFile _definitionsVar) - set (_compileDefinitions "") - if (NOT CMAKE_SCRIPT_MODE_FILE) - string (TOUPPER "${_config}" _upperConfig) - get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS) - if (_definitions) - list (APPEND _compileDefinitions ${_definitions}) - endif() - get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS_${_upperConfig}) - if (_definitions) - list (APPEND _compileDefinitions ${_definitions}) - endif() - endif() - cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+(=.*)?$" _definitions ${ARGN}) - if (_definitions) - list (APPEND _compileDefinitions ${_definitions}) - endif() - if (COTIRE_DEBUG AND _compileDefinitions) - message (STATUS "Source ${_sourceFile} compile definitions: ${_compileDefinitions}") - endif() - set (${_definitionsVar} ${_compileDefinitions} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_files_compile_definitions _config _language _definitionsVar) - set (_configDefinitions "") - foreach (_sourceFile ${ARGN}) - cotire_get_source_compile_definitions("${_config}" "${_language}" "${_sourceFile}" _sourceDefinitions) - if (_sourceDefinitions) - list (APPEND _configDefinitions "${_sourceFile}" ${_sourceDefinitions} "-") - endif() - endforeach() - set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_undefs _sourceFile _property _sourceUndefsVar) - set (_sourceUndefs "") - if (NOT CMAKE_SCRIPT_MODE_FILE) - get_source_file_property(_undefs "${_sourceFile}" ${_property}) - if (_undefs) - list (APPEND _sourceUndefs ${_undefs}) - endif() - endif() - cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+$" _undefs ${ARGN}) - if (_undefs) - list (APPEND _sourceUndefs ${_undefs}) - endif() - if (COTIRE_DEBUG AND _sourceUndefs) - message (STATUS "Source ${_sourceFile} ${_property} undefs: ${_sourceUndefs}") - endif() - set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_files_undefs _property _sourceUndefsVar) - set (_sourceUndefs "") - foreach (_sourceFile ${ARGN}) - cotire_get_source_undefs("${_sourceFile}" ${_property} _undefs) - if (_undefs) - list (APPEND _sourceUndefs "${_sourceFile}" ${_undefs} "-") - endif() - endforeach() - set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE) -endfunction() - -macro (cotire_set_cmd_to_prologue _cmdVar) - set (${_cmdVar} "${CMAKE_COMMAND}") - if (COTIRE_DEBUG) - list (APPEND ${_cmdVar} "--warn-uninitialized") - endif() - list (APPEND ${_cmdVar} "-DCOTIRE_BUILD_TYPE:STRING=$") - if (XCODE) - list (APPEND ${_cmdVar} "-DXCODE:BOOL=TRUE") - endif() - if (COTIRE_VERBOSE) - list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=ON") - elseif("${CMAKE_GENERATOR}" MATCHES "Makefiles") - list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=$(VERBOSE)") - endif() -endmacro() - -function (cotire_init_compile_cmd _cmdVar _language _compilerLauncher _compilerExe _compilerArg1) - if (NOT _compilerLauncher) - set (_compilerLauncher ${CMAKE_${_language}_COMPILER_LAUNCHER}) - endif() - if (NOT _compilerExe) - set (_compilerExe "${CMAKE_${_language}_COMPILER}") - endif() - if (NOT _compilerArg1) - set (_compilerArg1 ${CMAKE_${_language}_COMPILER_ARG1}) - endif() - if (WIN32) - file (TO_NATIVE_PATH "${_compilerExe}" _compilerExe) - endif() - string (STRIP "${_compilerArg1}" _compilerArg1) - if ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") - # compiler launcher is only supported for Makefile and Ninja - set (${_cmdVar} ${_compilerLauncher} "${_compilerExe}" ${_compilerArg1} PARENT_SCOPE) - else() - set (${_cmdVar} "${_compilerExe}" ${_compilerArg1} PARENT_SCOPE) - endif() -endfunction() - -macro (cotire_add_definitions_to_cmd _cmdVar _language) - foreach (_definition ${ARGN}) - if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - list (APPEND ${_cmdVar} "/D${_definition}") - else() - list (APPEND ${_cmdVar} "-D${_definition}") - endif() - endforeach() -endmacro() - -function (cotire_add_includes_to_cmd _cmdVar _language _includesVar _systemIncludesVar) - set (_includeDirs ${${_includesVar}} ${${_systemIncludesVar}}) - if (_includeDirs) - list (REMOVE_DUPLICATES _includeDirs) - foreach (_include ${_includeDirs}) - if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - file (TO_NATIVE_PATH "${_include}" _include) - list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_SEP_${_language}}${_include}") - else() - set (_index -1) - if ("${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" MATCHES ".+") - list (FIND ${_systemIncludesVar} "${_include}" _index) - endif() - if (_index GREATER -1) - list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_SEP_${_language}}${_include}") - else() - list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_SEP_${_language}}${_include}") - endif() - endif() - endforeach() - endif() - set (${_cmdVar} ${${_cmdVar}} PARENT_SCOPE) -endfunction() - -function (cotire_add_frameworks_to_cmd _cmdVar _language _includesVar _systemIncludesVar) - if (APPLE) - set (_frameworkDirs "") - foreach (_include ${${_includesVar}}) - if (IS_ABSOLUTE "${_include}" AND _include MATCHES "\\.framework$") - get_filename_component(_frameworkDir "${_include}" DIRECTORY) - list (APPEND _frameworkDirs "${_frameworkDir}") - endif() - endforeach() - set (_systemFrameworkDirs "") - foreach (_include ${${_systemIncludesVar}}) - if (IS_ABSOLUTE "${_include}" AND _include MATCHES "\\.framework$") - get_filename_component(_frameworkDir "${_include}" DIRECTORY) - list (APPEND _systemFrameworkDirs "${_frameworkDir}") - endif() - endforeach() - if (_systemFrameworkDirs) - list (APPEND _frameworkDirs ${_systemFrameworkDirs}) - endif() - if (_frameworkDirs) - list (REMOVE_DUPLICATES _frameworkDirs) - foreach (_frameworkDir ${_frameworkDirs}) - set (_index -1) - if ("${CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG}" MATCHES ".+") - list (FIND _systemFrameworkDirs "${_frameworkDir}" _index) - endif() - if (_index GREATER -1) - list (APPEND ${_cmdVar} "${CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG}${_frameworkDir}") - else() - list (APPEND ${_cmdVar} "${CMAKE_${_language}_FRAMEWORK_SEARCH_FLAG}${_frameworkDir}") - endif() - endforeach() - endif() - endif() - set (${_cmdVar} ${${_cmdVar}} PARENT_SCOPE) -endfunction() - -macro (cotire_add_compile_flags_to_cmd _cmdVar) - foreach (_flag ${ARGN}) - list (APPEND ${_cmdVar} "${_flag}") - endforeach() -endmacro() - -function (cotire_check_file_up_to_date _fileIsUpToDateVar _file) - if (EXISTS "${_file}") - set (_triggerFile "") - foreach (_dependencyFile ${ARGN}) - if (EXISTS "${_dependencyFile}") - # IS_NEWER_THAN returns TRUE if both files have the same timestamp - # thus we do the comparison in both directions to exclude ties - if ("${_dependencyFile}" IS_NEWER_THAN "${_file}" AND - NOT "${_file}" IS_NEWER_THAN "${_dependencyFile}") - set (_triggerFile "${_dependencyFile}") - break() - endif() - endif() - endforeach() - if (_triggerFile) - if (COTIRE_VERBOSE) - get_filename_component(_fileName "${_file}" NAME) - message (STATUS "${_fileName} update triggered by ${_triggerFile} change.") - endif() - set (${_fileIsUpToDateVar} FALSE PARENT_SCOPE) - else() - if (COTIRE_VERBOSE) - get_filename_component(_fileName "${_file}" NAME) - message (STATUS "${_fileName} is up-to-date.") - endif() - set (${_fileIsUpToDateVar} TRUE PARENT_SCOPE) - endif() - else() - if (COTIRE_VERBOSE) - get_filename_component(_fileName "${_file}" NAME) - message (STATUS "${_fileName} does not exist yet.") - endif() - set (${_fileIsUpToDateVar} FALSE PARENT_SCOPE) - endif() -endfunction() - -macro (cotire_find_closest_relative_path _headerFile _includeDirs _relPathVar) - set (${_relPathVar} "") - foreach (_includeDir ${_includeDirs}) - if (IS_DIRECTORY "${_includeDir}") - file (RELATIVE_PATH _relPath "${_includeDir}" "${_headerFile}") - if (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.") - string (LENGTH "${${_relPathVar}}" _closestLen) - string (LENGTH "${_relPath}" _relLen) - if (_closestLen EQUAL 0 OR _relLen LESS _closestLen) - set (${_relPathVar} "${_relPath}") - endif() - endif() - elseif ("${_includeDir}" STREQUAL "${_headerFile}") - # if path matches exactly, return short non-empty string - set (${_relPathVar} "1") - break() - endif() - endforeach() -endmacro() - -macro (cotire_check_header_file_location _headerFile _insideIncludeDirs _outsideIncludeDirs _headerIsInside) - # check header path against ignored and honored include directories - cotire_find_closest_relative_path("${_headerFile}" "${_insideIncludeDirs}" _insideRelPath) - if (_insideRelPath) - # header is inside, but could be become outside if there is a shorter outside match - cotire_find_closest_relative_path("${_headerFile}" "${_outsideIncludeDirs}" _outsideRelPath) - if (_outsideRelPath) - string (LENGTH "${_insideRelPath}" _insideRelPathLen) - string (LENGTH "${_outsideRelPath}" _outsideRelPathLen) - if (_outsideRelPathLen LESS _insideRelPathLen) - set (${_headerIsInside} FALSE) - else() - set (${_headerIsInside} TRUE) - endif() - else() - set (${_headerIsInside} TRUE) - endif() - else() - # header is outside - set (${_headerIsInside} FALSE) - endif() -endmacro() - -macro (cotire_check_ignore_header_file_path _headerFile _headerIsIgnoredVar) - if (NOT EXISTS "${_headerFile}") - set (${_headerIsIgnoredVar} TRUE) - elseif (IS_DIRECTORY "${_headerFile}") - set (${_headerIsIgnoredVar} TRUE) - elseif ("${_headerFile}" MATCHES "\\.\\.|[_-]fixed" AND "${_headerFile}" MATCHES "\\.h$") - # heuristic: ignore C headers with embedded parent directory references or "-fixed" or "_fixed" in path - # these often stem from using GCC #include_next tricks, which may break the precompiled header compilation - # with the error message "error: no include path in which to search for header.h" - set (${_headerIsIgnoredVar} TRUE) - else() - set (${_headerIsIgnoredVar} FALSE) - endif() -endmacro() - -macro (cotire_check_ignore_header_file_ext _headerFile _ignoreExtensionsVar _headerIsIgnoredVar) - # check header file extension - cotire_get_source_file_extension("${_headerFile}" _headerFileExt) - set (${_headerIsIgnoredVar} FALSE) - if (_headerFileExt) - list (FIND ${_ignoreExtensionsVar} "${_headerFileExt}" _index) - if (_index GREATER -1) - set (${_headerIsIgnoredVar} TRUE) - endif() - endif() -endmacro() - -macro (cotire_parse_line _line _headerFileVar _headerDepthVar) - if (MSVC) - # cl.exe /showIncludes produces different output, depending on the language pack used, e.g.: - # English: "Note: including file: C:\directory\file" - # German: "Hinweis: Einlesen der Datei: C:\directory\file" - # We use a very general regular expression, relying on the presence of the : characters - if (_line MATCHES "( +)([a-zA-Z]:[^:]+)$") - string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) - get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" ABSOLUTE) - else() - set (${_headerFileVar} "") - set (${_headerDepthVar} 0) - endif() - else() - if (_line MATCHES "^(\\.+) (.*)$") - # GCC like output - string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) - if (IS_ABSOLUTE "${CMAKE_MATCH_2}") - set (${_headerFileVar} "${CMAKE_MATCH_2}") - else() - get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" REALPATH) - endif() - else() - set (${_headerFileVar} "") - set (${_headerDepthVar} 0) - endif() - endif() -endmacro() - -function (cotire_parse_includes _language _scanOutput _ignoredIncludeDirs _honoredIncludeDirs _ignoredExtensions _selectedIncludesVar _unparsedLinesVar) - if (WIN32) - # prevent CMake macro invocation errors due to backslash characters in Windows paths - string (REPLACE "\\" "/" _scanOutput "${_scanOutput}") - endif() - # canonize slashes - string (REPLACE "//" "/" _scanOutput "${_scanOutput}") - # prevent semicolon from being interpreted as a line separator - string (REPLACE ";" "\\;" _scanOutput "${_scanOutput}") - # then separate lines - string (REGEX REPLACE "\n" ";" _scanOutput "${_scanOutput}") - list (LENGTH _scanOutput _len) - # remove duplicate lines to speed up parsing - list (REMOVE_DUPLICATES _scanOutput) - list (LENGTH _scanOutput _uniqueLen) - if (COTIRE_VERBOSE OR COTIRE_DEBUG) - message (STATUS "Scanning ${_uniqueLen} unique lines of ${_len} for includes") - if (_ignoredExtensions) - message (STATUS "Ignored extensions: ${_ignoredExtensions}") - endif() - if (_ignoredIncludeDirs) - message (STATUS "Ignored paths: ${_ignoredIncludeDirs}") - endif() - if (_honoredIncludeDirs) - message (STATUS "Included paths: ${_honoredIncludeDirs}") - endif() - endif() - set (_sourceFiles ${ARGN}) - set (_selectedIncludes "") - set (_unparsedLines "") - # stack keeps track of inside/outside project status of processed header files - set (_headerIsInsideStack "") - foreach (_line IN LISTS _scanOutput) - if (_line) - cotire_parse_line("${_line}" _headerFile _headerDepth) - if (_headerFile) - cotire_check_header_file_location("${_headerFile}" "${_ignoredIncludeDirs}" "${_honoredIncludeDirs}" _headerIsInside) - if (COTIRE_DEBUG) - message (STATUS "${_headerDepth}: ${_headerFile} ${_headerIsInside}") - endif() - # update stack - list (LENGTH _headerIsInsideStack _stackLen) - if (_headerDepth GREATER _stackLen) - math (EXPR _stackLen "${_stackLen} + 1") - foreach (_index RANGE ${_stackLen} ${_headerDepth}) - list (APPEND _headerIsInsideStack ${_headerIsInside}) - endforeach() - else() - foreach (_index RANGE ${_headerDepth} ${_stackLen}) - list (REMOVE_AT _headerIsInsideStack -1) - endforeach() - list (APPEND _headerIsInsideStack ${_headerIsInside}) - endif() - if (COTIRE_DEBUG) - message (STATUS "${_headerIsInsideStack}") - endif() - # header is a candidate if it is outside project - if (NOT _headerIsInside) - # get parent header file's inside/outside status - if (_headerDepth GREATER 1) - math (EXPR _index "${_headerDepth} - 2") - list (GET _headerIsInsideStack ${_index} _parentHeaderIsInside) - else() - set (_parentHeaderIsInside TRUE) - endif() - # select header file if parent header file is inside project - # (e.g., a project header file that includes a standard header file) - if (_parentHeaderIsInside) - cotire_check_ignore_header_file_path("${_headerFile}" _headerIsIgnored) - if (NOT _headerIsIgnored) - cotire_check_ignore_header_file_ext("${_headerFile}" _ignoredExtensions _headerIsIgnored) - if (NOT _headerIsIgnored) - list (APPEND _selectedIncludes "${_headerFile}") - else() - # fix header's inside status on stack, it is ignored by extension now - list (REMOVE_AT _headerIsInsideStack -1) - list (APPEND _headerIsInsideStack TRUE) - endif() - endif() - if (COTIRE_DEBUG) - message (STATUS "${_headerFile} ${_ignoredExtensions} ${_headerIsIgnored}") - endif() - endif() - endif() - else() - if (MSVC) - # for cl.exe do not keep unparsed lines which solely consist of a source file name - string (FIND "${_sourceFiles}" "${_line}" _index) - if (_index LESS 0) - list (APPEND _unparsedLines "${_line}") - endif() - else() - list (APPEND _unparsedLines "${_line}") - endif() - endif() - endif() - endforeach() - list (REMOVE_DUPLICATES _selectedIncludes) - set (${_selectedIncludesVar} ${_selectedIncludes} PARENT_SCOPE) - set (${_unparsedLinesVar} ${_unparsedLines} PARENT_SCOPE) -endfunction() - -function (cotire_scan_includes _includesVar) - set(_options "") - set(_oneValueArgs COMPILER_ID COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_VERSION LANGUAGE UNPARSED_LINES SCAN_RESULT) - set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES - IGNORE_PATH INCLUDE_PATH IGNORE_EXTENSIONS INCLUDE_PRIORITY_PATH COMPILER_LAUNCHER) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) - if (NOT _option_LANGUAGE) - set (_option_LANGUAGE "CXX") - endif() - if (NOT _option_COMPILER_ID) - set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") - endif() - if (NOT _option_COMPILER_VERSION) - set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") - endif() - cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_LAUNCHER}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}") - cotire_add_definitions_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_COMPILE_DEFINITIONS}) - cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS}) - cotire_add_includes_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) - cotire_add_frameworks_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) - cotire_add_makedep_flags("${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" _cmd) - # only consider existing source files for scanning - set (_existingSourceFiles "") - foreach (_sourceFile ${_sourceFiles}) - if (EXISTS "${_sourceFile}") - list (APPEND _existingSourceFiles "${_sourceFile}") - endif() - endforeach() - if (NOT _existingSourceFiles) - set (${_includesVar} "" PARENT_SCOPE) - return() - endif() - # add source files to be scanned - if (WIN32) - foreach (_sourceFile ${_existingSourceFiles}) - file (TO_NATIVE_PATH "${_sourceFile}" _sourceFileNative) - list (APPEND _cmd "${_sourceFileNative}") - endforeach() - else() - list (APPEND _cmd ${_existingSourceFiles}) - endif() - if (COTIRE_VERBOSE) - message (STATUS "execute_process: ${_cmd}") - endif() - if (MSVC_IDE OR _option_COMPILER_ID MATCHES "MSVC") - # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared - unset (ENV{VS_UNICODE_OUTPUT}) - endif() - execute_process( - COMMAND ${_cmd} - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - RESULT_VARIABLE _result - OUTPUT_QUIET - ERROR_VARIABLE _output) - if (_result) - message (STATUS "Result ${_result} scanning includes of ${_existingSourceFiles}.") - endif() - cotire_parse_includes( - "${_option_LANGUAGE}" "${_output}" - "${_option_IGNORE_PATH}" "${_option_INCLUDE_PATH}" - "${_option_IGNORE_EXTENSIONS}" - _includes _unparsedLines - ${_sourceFiles}) - if (_option_INCLUDE_PRIORITY_PATH) - set (_sortedIncludes "") - foreach (_priorityPath ${_option_INCLUDE_PRIORITY_PATH}) - foreach (_include ${_includes}) - string (FIND ${_include} ${_priorityPath} _position) - if (_position GREATER -1) - list (APPEND _sortedIncludes ${_include}) - endif() - endforeach() - endforeach() - if (_sortedIncludes) - list (INSERT _includes 0 ${_sortedIncludes}) - list (REMOVE_DUPLICATES _includes) - endif() - endif() - set (${_includesVar} ${_includes} PARENT_SCOPE) - if (_option_UNPARSED_LINES) - set (${_option_UNPARSED_LINES} ${_unparsedLines} PARENT_SCOPE) - endif() - if (_option_SCAN_RESULT) - set (${_option_SCAN_RESULT} ${_result} PARENT_SCOPE) - endif() -endfunction() - -macro (cotire_append_undefs _contentsVar) - set (_undefs ${ARGN}) - if (_undefs) - list (REMOVE_DUPLICATES _undefs) - foreach (_definition ${_undefs}) - list (APPEND ${_contentsVar} "#undef ${_definition}") - endforeach() - endif() -endmacro() - -macro (cotire_comment_str _language _commentText _commentVar) - if ("${_language}" STREQUAL "CMAKE") - set (${_commentVar} "# ${_commentText}") - else() - set (${_commentVar} "/* ${_commentText} */") - endif() -endmacro() - -function (cotire_write_file _language _file _contents _force) - get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) - cotire_comment_str("${_language}" "${_moduleName} ${COTIRE_CMAKE_MODULE_VERSION} generated file" _header1) - cotire_comment_str("${_language}" "${_file}" _header2) - set (_contents "${_header1}\n${_header2}\n${_contents}") - if (COTIRE_DEBUG) - message (STATUS "${_contents}") - endif() - if (_force OR NOT EXISTS "${_file}") - file (WRITE "${_file}" "${_contents}") - else() - file (READ "${_file}" _oldContents) - if (NOT "${_oldContents}" STREQUAL "${_contents}") - file (WRITE "${_file}" "${_contents}") - else() - if (COTIRE_DEBUG) - message (STATUS "${_file} unchanged") - endif() - endif() - endif() -endfunction() - -function (cotire_generate_unity_source _unityFile) - set(_options "") - set(_oneValueArgs LANGUAGE) - set(_multiValueArgs - DEPENDS SOURCES_COMPILE_DEFINITIONS - PRE_UNDEFS SOURCES_PRE_UNDEFS POST_UNDEFS SOURCES_POST_UNDEFS PROLOGUE EPILOGUE) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - if (_option_DEPENDS) - cotire_check_file_up_to_date(_unityFileIsUpToDate "${_unityFile}" ${_option_DEPENDS}) - if (_unityFileIsUpToDate) - return() - endif() - endif() - set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) - if (NOT _option_PRE_UNDEFS) - set (_option_PRE_UNDEFS "") - endif() - if (NOT _option_SOURCES_PRE_UNDEFS) - set (_option_SOURCES_PRE_UNDEFS "") - endif() - if (NOT _option_POST_UNDEFS) - set (_option_POST_UNDEFS "") - endif() - if (NOT _option_SOURCES_POST_UNDEFS) - set (_option_SOURCES_POST_UNDEFS "") - endif() - set (_contents "") - if (_option_PROLOGUE) - list (APPEND _contents ${_option_PROLOGUE}) - endif() - if (_option_LANGUAGE AND _sourceFiles) - if ("${_option_LANGUAGE}" STREQUAL "CXX") - list (APPEND _contents "#ifdef __cplusplus") - elseif ("${_option_LANGUAGE}" STREQUAL "C") - list (APPEND _contents "#ifndef __cplusplus") - endif() - endif() - set (_compileUndefinitions "") - foreach (_sourceFile ${_sourceFiles}) - cotire_get_source_compile_definitions( - "${_option_CONFIGURATION}" "${_option_LANGUAGE}" "${_sourceFile}" _compileDefinitions - ${_option_SOURCES_COMPILE_DEFINITIONS}) - cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_PRE_UNDEFS _sourcePreUndefs ${_option_SOURCES_PRE_UNDEFS}) - cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_POST_UNDEFS _sourcePostUndefs ${_option_SOURCES_POST_UNDEFS}) - if (_option_PRE_UNDEFS) - list (APPEND _compileUndefinitions ${_option_PRE_UNDEFS}) - endif() - if (_sourcePreUndefs) - list (APPEND _compileUndefinitions ${_sourcePreUndefs}) - endif() - if (_compileUndefinitions) - cotire_append_undefs(_contents ${_compileUndefinitions}) - set (_compileUndefinitions "") - endif() - if (_sourcePostUndefs) - list (APPEND _compileUndefinitions ${_sourcePostUndefs}) - endif() - if (_option_POST_UNDEFS) - list (APPEND _compileUndefinitions ${_option_POST_UNDEFS}) - endif() - foreach (_definition ${_compileDefinitions}) - if (_definition MATCHES "^([a-zA-Z0-9_]+)=(.+)$") - list (APPEND _contents "#define ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}") - list (INSERT _compileUndefinitions 0 "${CMAKE_MATCH_1}") - else() - list (APPEND _contents "#define ${_definition}") - list (INSERT _compileUndefinitions 0 "${_definition}") - endif() - endforeach() - # use absolute path as source file location - get_filename_component(_sourceFileLocation "${_sourceFile}" ABSOLUTE) - if (WIN32) - file (TO_NATIVE_PATH "${_sourceFileLocation}" _sourceFileLocation) - endif() - list (APPEND _contents "#include \"${_sourceFileLocation}\"") - endforeach() - if (_compileUndefinitions) - cotire_append_undefs(_contents ${_compileUndefinitions}) - set (_compileUndefinitions "") - endif() - if (_option_LANGUAGE AND _sourceFiles) - list (APPEND _contents "#endif") - endif() - if (_option_EPILOGUE) - list (APPEND _contents ${_option_EPILOGUE}) - endif() - list (APPEND _contents "") - string (REPLACE ";" "\n" _contents "${_contents}") - if (COTIRE_VERBOSE) - message ("${_contents}") - endif() - cotire_write_file("${_option_LANGUAGE}" "${_unityFile}" "${_contents}" TRUE) -endfunction() - -function (cotire_generate_prefix_header _prefixFile) - set(_options "") - set(_oneValueArgs LANGUAGE COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_ID COMPILER_VERSION) - set(_multiValueArgs DEPENDS COMPILE_DEFINITIONS COMPILE_FLAGS - INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES IGNORE_PATH INCLUDE_PATH - IGNORE_EXTENSIONS INCLUDE_PRIORITY_PATH COMPILER_LAUNCHER) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - if (NOT _option_COMPILER_ID) - set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") - endif() - if (NOT _option_COMPILER_VERSION) - set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") - endif() - if (_option_DEPENDS) - cotire_check_file_up_to_date(_prefixFileIsUpToDate "${_prefixFile}" ${_option_DEPENDS}) - if (_prefixFileIsUpToDate) - # create empty log file - set (_unparsedLinesFile "${_prefixFile}.log") - file (WRITE "${_unparsedLinesFile}" "") - return() - endif() - endif() - set (_prologue "") - set (_epilogue "") - if (_option_COMPILER_ID MATCHES "Clang") - set (_prologue "#pragma clang system_header") - elseif (_option_COMPILER_ID MATCHES "GNU") - set (_prologue "#pragma GCC system_header") - elseif (_option_COMPILER_ID MATCHES "MSVC") - set (_prologue "#pragma warning(push, 0)") - set (_epilogue "#pragma warning(pop)") - elseif (_option_COMPILER_ID MATCHES "Intel") - # Intel compiler requires hdrstop pragma to stop generating PCH file - set (_epilogue "#pragma hdrstop") - endif() - set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) - cotire_scan_includes(_selectedHeaders ${_sourceFiles} - LANGUAGE "${_option_LANGUAGE}" - COMPILER_LAUNCHER "${_option_COMPILER_LAUNCHER}" - COMPILER_EXECUTABLE "${_option_COMPILER_EXECUTABLE}" - COMPILER_ARG1 "${_option_COMPILER_ARG1}" - COMPILER_ID "${_option_COMPILER_ID}" - COMPILER_VERSION "${_option_COMPILER_VERSION}" - COMPILE_DEFINITIONS ${_option_COMPILE_DEFINITIONS} - COMPILE_FLAGS ${_option_COMPILE_FLAGS} - INCLUDE_DIRECTORIES ${_option_INCLUDE_DIRECTORIES} - SYSTEM_INCLUDE_DIRECTORIES ${_option_SYSTEM_INCLUDE_DIRECTORIES} - IGNORE_PATH ${_option_IGNORE_PATH} - INCLUDE_PATH ${_option_INCLUDE_PATH} - IGNORE_EXTENSIONS ${_option_IGNORE_EXTENSIONS} - INCLUDE_PRIORITY_PATH ${_option_INCLUDE_PRIORITY_PATH} - UNPARSED_LINES _unparsedLines - SCAN_RESULT _scanResult) - cotire_generate_unity_source("${_prefixFile}" - PROLOGUE ${_prologue} EPILOGUE ${_epilogue} LANGUAGE "${_option_LANGUAGE}" ${_selectedHeaders}) - set (_unparsedLinesFile "${_prefixFile}.log") - if (_unparsedLines) - if (COTIRE_VERBOSE OR _scanResult OR NOT _selectedHeaders) - list (LENGTH _unparsedLines _skippedLineCount) - if (WIN32) - file (TO_NATIVE_PATH "${_unparsedLinesFile}" _unparsedLinesLogPath) - else() - set (_unparsedLinesLogPath "${_unparsedLinesFile}") - endif() - message (STATUS "${_skippedLineCount} line(s) skipped, see ${_unparsedLinesLogPath}") - endif() - string (REPLACE ";" "\n" _unparsedLines "${_unparsedLines}") - endif() - file (WRITE "${_unparsedLinesFile}" "${_unparsedLines}\n") -endfunction() - -function (cotire_add_makedep_flags _language _compilerID _compilerVersion _flagsVar) - set (_flags ${${_flagsVar}}) - if (_compilerID MATCHES "MSVC") - # cl.exe options used - # /nologo suppresses display of sign-on banner - # /TC treat all files named on the command line as C source files - # /TP treat all files named on the command line as C++ source files - # /EP preprocess to stdout without #line directives - # /showIncludes list include files - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /showIncludes) - else() - # return as a flag string - set (_flags "${_sourceFileType${_language}} /EP /showIncludes") - endif() - elseif (_compilerID MATCHES "GNU") - # GCC options used - # -H print the name of each header file used - # -E invoke preprocessor - # -fdirectives-only do not expand macros, requires GCC >= 4.3 - if (_flags) - # append to list - list (APPEND _flags -H -E) - if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0") - list (APPEND _flags -fdirectives-only) - endif() - else() - # return as a flag string - set (_flags "-H -E") - if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0") - set (_flags "${_flags} -fdirectives-only") - endif() - endif() - elseif (_compilerID MATCHES "Clang") - if (UNIX) - # Clang options used - # -H print the name of each header file used - # -E invoke preprocessor - # -fno-color-diagnostics do not print diagnostics in color - # -Eonly just run preprocessor, no output - if (_flags) - # append to list - list (APPEND _flags -H -E -fno-color-diagnostics -Xclang -Eonly) - else() - # return as a flag string - set (_flags "-H -E -fno-color-diagnostics -Xclang -Eonly") - endif() - elseif (WIN32) - # Clang-cl.exe options used - # /TC treat all files named on the command line as C source files - # /TP treat all files named on the command line as C++ source files - # /EP preprocess to stdout without #line directives - # -H print the name of each header file used - # -fno-color-diagnostics do not print diagnostics in color - # -Eonly just run preprocessor, no output - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags "${_sourceFileType${_language}}" /EP -fno-color-diagnostics -Xclang -H -Xclang -Eonly) - else() - # return as a flag string - set (_flags "${_sourceFileType${_language}} /EP -fno-color-diagnostics -Xclang -H -Xclang -Eonly") - endif() - endif() - elseif (_compilerID MATCHES "Intel") - if (WIN32) - # Windows Intel options used - # /nologo do not display compiler version information - # /QH display the include file order - # /EP preprocess to stdout, omitting #line directives - # /TC process all source or unrecognized file types as C source files - # /TP process all source or unrecognized file types as C++ source files - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /QH) - else() - # return as a flag string - set (_flags "${_sourceFileType${_language}} /EP /QH") - endif() - else() - # Linux / Mac OS X Intel options used - # -H print the name of each header file used - # -EP preprocess to stdout, omitting #line directives - # -Kc++ process all source or unrecognized file types as C++ source files - if (_flags) - # append to list - if ("${_language}" STREQUAL "CXX") - list (APPEND _flags -Kc++) - endif() - list (APPEND _flags -H -EP) - else() - # return as a flag string - if ("${_language}" STREQUAL "CXX") - set (_flags "-Kc++ ") - endif() - set (_flags "${_flags}-H -EP") - endif() - endif() - else() - message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") - endif() - set (${_flagsVar} ${_flags} PARENT_SCOPE) -endfunction() - -function (cotire_add_pch_compilation_flags _language _compilerID _compilerVersion _prefixFile _pchFile _hostFile _flagsVar) - set (_flags ${${_flagsVar}}) - if (_compilerID MATCHES "MSVC") - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) - # cl.exe options used - # /Yc creates a precompiled header file - # /Fp specifies precompiled header binary file name - # /FI forces inclusion of file - # /TC treat all files named on the command line as C source files - # /TP treat all files named on the command line as C++ source files - # /Zs syntax check only - # /Zm precompiled header memory allocation scaling factor - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags /nologo "${_sourceFileType${_language}}" - "/Yc${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") - if (COTIRE_PCH_MEMORY_SCALING_FACTOR) - list (APPEND _flags "/Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") - endif() - else() - # return as a flag string - set (_flags "/Yc\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - if (COTIRE_PCH_MEMORY_SCALING_FACTOR) - set (_flags "${_flags} /Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") - endif() - endif() - elseif (_compilerID MATCHES "GNU") - # GCC options used - # -x specify the source language - # -c compile but do not link - # -o place output in file - # note that we cannot use -w to suppress all warnings upon pre-compiling, because turning off a warning may - # alter compile flags as a side effect (e.g., -Wwrite-string implies -fconst-strings) - set (_xLanguage_C "c-header") - set (_xLanguage_CXX "c++-header") - if (_flags) - # append to list - list (APPEND _flags -x "${_xLanguage_${_language}}" -c "${_prefixFile}" -o "${_pchFile}") - else() - # return as a flag string - set (_flags "-x ${_xLanguage_${_language}} -c \"${_prefixFile}\" -o \"${_pchFile}\"") - endif() - elseif (_compilerID MATCHES "Clang") - if (UNIX) - # Clang options used - # -x specify the source language - # -c compile but do not link - # -o place output in file - # -fno-pch-timestamp disable inclusion of timestamp in precompiled headers (clang 4.0.0+) - set (_xLanguage_C "c-header") - set (_xLanguage_CXX "c++-header") - if (_flags) - # append to list - list (APPEND _flags -x "${_xLanguage_${_language}}" -c "${_prefixFile}" -o "${_pchFile}") - if (NOT "${_compilerVersion}" VERSION_LESS "4.0.0") - list (APPEND _flags -Xclang -fno-pch-timestamp) - endif() - else() - # return as a flag string - set (_flags "-x ${_xLanguage_${_language}} -c \"${_prefixFile}\" -o \"${_pchFile}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "4.0.0") - set (_flags "${_flags} -Xclang -fno-pch-timestamp") - endif() - endif() - elseif (WIN32) - # Clang-cl.exe options used - # /Yc creates a precompiled header file - # /Fp specifies precompiled header binary file name - # /FI forces inclusion of file - # /Zs syntax check only - # /TC treat all files named on the command line as C source files - # /TP treat all files named on the command line as C++ source files - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags "${_sourceFileType${_language}}" - "/Yc${_prefixFile}" "/Fp${_pchFile}" "/FI${_prefixFile}" /Zs "${_hostFile}") - else() - # return as a flag string - set (_flags "/Yc\"${_prefixFile}\" /Fp\"${_pchFile}\" /FI\"${_prefixFile}\"") - endif() - endif() - elseif (_compilerID MATCHES "Intel") - if (WIN32) - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) - # Windows Intel options used - # /nologo do not display compiler version information - # /Yc create a precompiled header (PCH) file - # /Fp specify a path or file name for precompiled header files - # /FI tells the preprocessor to include a specified file name as the header file - # /TC process all source or unrecognized file types as C source files - # /TP process all source or unrecognized file types as C++ source files - # /Zs syntax check only - # /Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags /nologo "${_sourceFileType${_language}}" - "/Yc" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - list (APPEND _flags "/Wpch-messages") - endif() - else() - # return as a flag string - set (_flags "/Yc /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - set (_flags "${_flags} /Wpch-messages") - endif() - endif() - else() - # Linux / Mac OS X Intel options used - # -pch-dir location for precompiled header files - # -pch-create name of the precompiled header (PCH) to create - # -Kc++ process all source or unrecognized file types as C++ source files - # -fsyntax-only check only for correct syntax - # -Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) - get_filename_component(_pchDir "${_pchFile}" DIRECTORY) - get_filename_component(_pchName "${_pchFile}" NAME) - set (_xLanguage_C "c-header") - set (_xLanguage_CXX "c++-header") - set (_pchSuppressMessages FALSE) - if ("${CMAKE_${_language}_FLAGS}" MATCHES ".*-Wno-pch-messages.*") - set(_pchSuppressMessages TRUE) - endif() - if (_flags) - # append to list - if ("${_language}" STREQUAL "CXX") - list (APPEND _flags -Kc++) - endif() - list (APPEND _flags -include "${_prefixFile}" -pch-dir "${_pchDir}" -pch-create "${_pchName}" -fsyntax-only "${_hostFile}") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - if (NOT _pchSuppressMessages) - list (APPEND _flags -Wpch-messages) - endif() - endif() - else() - # return as a flag string - set (_flags "-include \"${_prefixFile}\" -pch-dir \"${_pchDir}\" -pch-create \"${_pchName}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - if (NOT _pchSuppressMessages) - set (_flags "${_flags} -Wpch-messages") - endif() - endif() - endif() - endif() - else() - message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") - endif() - set (${_flagsVar} ${_flags} PARENT_SCOPE) -endfunction() - -function (cotire_add_prefix_pch_inclusion_flags _language _compilerID _compilerVersion _prefixFile _pchFile _flagsVar) - set (_flags ${${_flagsVar}}) - if (_compilerID MATCHES "MSVC") - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - # cl.exe options used - # /Yu uses a precompiled header file during build - # /Fp specifies precompiled header binary file name - # /FI forces inclusion of file - # /Zm precompiled header memory allocation scaling factor - if (_pchFile) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - if (_flags) - # append to list - list (APPEND _flags "/Yu${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") - if (COTIRE_PCH_MEMORY_SCALING_FACTOR) - list (APPEND _flags "/Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") - endif() - else() - # return as a flag string - set (_flags "/Yu\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - if (COTIRE_PCH_MEMORY_SCALING_FACTOR) - set (_flags "${_flags} /Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") - endif() - endif() - else() - # no precompiled header, force inclusion of prefix header - if (_flags) - # append to list - list (APPEND _flags "/FI${_prefixFileNative}") - else() - # return as a flag string - set (_flags "/FI\"${_prefixFileNative}\"") - endif() - endif() - elseif (_compilerID MATCHES "GNU") - # GCC options used - # -include process include file as the first line of the primary source file - # -Winvalid-pch warns if precompiled header is found but cannot be used - # note: ccache requires the -include flag to be used in order to process precompiled header correctly - if (_flags) - # append to list - list (APPEND _flags -Winvalid-pch -include "${_prefixFile}") - else() - # return as a flag string - set (_flags "-Winvalid-pch -include \"${_prefixFile}\"") - endif() - elseif (_compilerID MATCHES "Clang") - if (UNIX) - # Clang options used - # -include process include file as the first line of the primary source file - # note: ccache requires the -include flag to be used in order to process precompiled header correctly - if (_flags) - # append to list - list (APPEND _flags -include "${_prefixFile}") - else() - # return as a flag string - set (_flags "-include \"${_prefixFile}\"") - endif() - elseif (WIN32) - # Clang-cl.exe options used - # /Yu uses a precompiled header file during build - # /Fp specifies precompiled header binary file name - # /FI forces inclusion of file - if (_pchFile) - if (_flags) - # append to list - list (APPEND _flags "/Yu${_prefixFile}" "/Fp${_pchFile}" "/FI${_prefixFile}") - else() - # return as a flag string - set (_flags "/Yu\"${_prefixFile}\" /Fp\"${_pchFile}\" /FI\"${_prefixFile}\"") - endif() - else() - # no precompiled header, force inclusion of prefix header - if (_flags) - # append to list - list (APPEND _flags "/FI${_prefixFile}") - else() - # return as a flag string - set (_flags "/FI\"${_prefixFile}\"") - endif() - endif() - endif() - elseif (_compilerID MATCHES "Intel") - if (WIN32) - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - # Windows Intel options used - # /Yu use a precompiled header (PCH) file - # /Fp specify a path or file name for precompiled header files - # /FI tells the preprocessor to include a specified file name as the header file - # /Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) - if (_pchFile) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - if (_flags) - # append to list - list (APPEND _flags "/Yu" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - list (APPEND _flags "/Wpch-messages") - endif() - else() - # return as a flag string - set (_flags "/Yu /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - set (_flags "${_flags} /Wpch-messages") - endif() - endif() - else() - # no precompiled header, force inclusion of prefix header - if (_flags) - # append to list - list (APPEND _flags "/FI${_prefixFileNative}") - else() - # return as a flag string - set (_flags "/FI\"${_prefixFileNative}\"") - endif() - endif() - else() - # Linux / Mac OS X Intel options used - # -pch-dir location for precompiled header files - # -pch-use name of the precompiled header (PCH) to use - # -include process include file as the first line of the primary source file - # -Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) - if (_pchFile) - get_filename_component(_pchDir "${_pchFile}" DIRECTORY) - get_filename_component(_pchName "${_pchFile}" NAME) - set (_pchSuppressMessages FALSE) - if ("${CMAKE_${_language}_FLAGS}" MATCHES ".*-Wno-pch-messages.*") - set(_pchSuppressMessages TRUE) - endif() - if (_flags) - # append to list - list (APPEND _flags -include "${_prefixFile}" -pch-dir "${_pchDir}" -pch-use "${_pchName}") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - if (NOT _pchSuppressMessages) - list (APPEND _flags -Wpch-messages) - endif() - endif() - else() - # return as a flag string - set (_flags "-include \"${_prefixFile}\" -pch-dir \"${_pchDir}\" -pch-use \"${_pchName}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - if (NOT _pchSuppressMessages) - set (_flags "${_flags} -Wpch-messages") - endif() - endif() - endif() - else() - # no precompiled header, force inclusion of prefix header - if (_flags) - # append to list - list (APPEND _flags -include "${_prefixFile}") - else() - # return as a flag string - set (_flags "-include \"${_prefixFile}\"") - endif() - endif() - endif() - else() - message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") - endif() - set (${_flagsVar} ${_flags} PARENT_SCOPE) -endfunction() - -function (cotire_precompile_prefix_header _prefixFile _pchFile _hostFile) - set(_options "") - set(_oneValueArgs COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_ID COMPILER_VERSION LANGUAGE) - set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES SYS COMPILER_LAUNCHER) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - if (NOT _option_LANGUAGE) - set (_option_LANGUAGE "CXX") - endif() - if (NOT _option_COMPILER_ID) - set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") - endif() - if (NOT _option_COMPILER_VERSION) - set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") - endif() - cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_LAUNCHER}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}") - cotire_add_definitions_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_COMPILE_DEFINITIONS}) - cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS}) - cotire_add_includes_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) - cotire_add_frameworks_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) - cotire_add_pch_compilation_flags( - "${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" "${_hostFile}" _cmd) - if (COTIRE_VERBOSE) - message (STATUS "execute_process: ${_cmd}") - endif() - if (MSVC_IDE OR _option_COMPILER_ID MATCHES "MSVC") - # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared - unset (ENV{VS_UNICODE_OUTPUT}) - elseif (_option_COMPILER_ID MATCHES "Clang" AND _option_COMPILER_VERSION VERSION_LESS "4.0.0") - if (_option_COMPILER_LAUNCHER MATCHES "ccache" OR - _option_COMPILER_EXECUTABLE MATCHES "ccache") - # Newer versions of Clang embed a compilation timestamp into the precompiled header binary, - # which results in "file has been modified since the precompiled header was built" errors if ccache is used. - # We work around the problem by disabling ccache upon pre-compiling the prefix header. - set (ENV{CCACHE_DISABLE} "true") - endif() - endif() - execute_process( - COMMAND ${_cmd} - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - RESULT_VARIABLE _result) - if (_result) - message (FATAL_ERROR "cotire: error ${_result} precompiling ${_prefixFile}.") - endif() -endfunction() - -function (cotire_check_precompiled_header_support _language _target _msgVar) - set (_unsupportedCompiler - "Precompiled headers not supported for ${_language} compiler ${CMAKE_${_language}_COMPILER_ID}") - if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC") - # PCH supported since Visual Studio C++ 6.0 - # and CMake does not support an earlier version - set (${_msgVar} "" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "GNU") - # GCC PCH support requires version >= 3.4 - if ("${CMAKE_${_language}_COMPILER_VERSION}" VERSION_LESS "3.4.0") - set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}." PARENT_SCOPE) - else() - set (${_msgVar} "" PARENT_SCOPE) - endif() - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Clang") - if (UNIX) - # all Unix Clang versions have PCH support - set (${_msgVar} "" PARENT_SCOPE) - elseif (WIN32) - # only clang-cl is supported under Windows - get_filename_component(_compilerName "${CMAKE_${_language}_COMPILER}" NAME_WE) - if (NOT _compilerName MATCHES "cl$") - set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}. Use clang-cl instead." PARENT_SCOPE) - endif() - endif() - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Intel") - # Intel PCH support requires version >= 8.0.0 - if ("${CMAKE_${_language}_COMPILER_VERSION}" VERSION_LESS "8.0.0") - set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}." PARENT_SCOPE) - else() - set (${_msgVar} "" PARENT_SCOPE) - endif() - else() - set (${_msgVar} "${_unsupportedCompiler}." PARENT_SCOPE) - endif() - # check if ccache is used as a compiler launcher - get_target_property(_launcher ${_target} ${_language}_COMPILER_LAUNCHER) - get_filename_component(_realCompilerExe "${CMAKE_${_language}_COMPILER}" REALPATH) - if (_realCompilerExe MATCHES "ccache" OR _launcher MATCHES "ccache") - # verify that ccache configuration is compatible with precompiled headers - # always check environment variable CCACHE_SLOPPINESS, because earlier versions of ccache - # do not report the "sloppiness" setting correctly upon printing ccache configuration - if (DEFINED ENV{CCACHE_SLOPPINESS}) - if (NOT "$ENV{CCACHE_SLOPPINESS}" MATCHES "pch_defines" OR - NOT "$ENV{CCACHE_SLOPPINESS}" MATCHES "time_macros") - set (${_msgVar} - "ccache requires the environment variable CCACHE_SLOPPINESS to be set to \"pch_defines,time_macros\"." - PARENT_SCOPE) - endif() - else() - if (_realCompilerExe MATCHES "ccache") - set (_ccacheExe "${_realCompilerExe}") - else() - set (_ccacheExe "${_launcher}") - endif() - execute_process( - COMMAND "${_ccacheExe}" "--print-config" - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" - RESULT_VARIABLE _result - OUTPUT_VARIABLE _ccacheConfig OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_QUIET) - if (_result) - set (${_msgVar} "ccache configuration cannot be determined." PARENT_SCOPE) - elseif (NOT _ccacheConfig MATCHES "sloppiness.*=.*time_macros" OR - NOT _ccacheConfig MATCHES "sloppiness.*=.*pch_defines") - set (${_msgVar} - "ccache requires configuration setting \"sloppiness\" to be set to \"pch_defines,time_macros\"." - PARENT_SCOPE) - endif() - endif() - endif() - if (APPLE) - # PCH compilation not supported by GCC / Clang for multi-architecture builds (e.g., i386, x86_64) - cotire_get_configuration_types(_configs) - foreach (_config ${_configs}) - set (_targetFlags "") - cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) - cotire_filter_compile_flags("${_language}" "arch" _architectures _ignore ${_targetFlags}) - list (LENGTH _architectures _numberOfArchitectures) - if (_numberOfArchitectures GREATER 1) - string (REPLACE ";" ", " _architectureStr "${_architectures}") - set (${_msgVar} - "Precompiled headers not supported on Darwin for multi-architecture builds (${_architectureStr})." - PARENT_SCOPE) - break() - endif() - endforeach() - endif() -endfunction() - -macro (cotire_get_intermediate_dir _cotireDir) - # ${CMAKE_CFG_INTDIR} may reference a build-time variable when using a generator which supports configuration types - get_filename_component(${_cotireDir} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${COTIRE_INTDIR}" ABSOLUTE) -endmacro() - -macro (cotire_setup_file_extension_variables) - set (_unityFileExt_C ".c") - set (_unityFileExt_CXX ".cxx") - set (_prefixFileExt_C ".h") - set (_prefixFileExt_CXX ".hxx") - set (_prefixSourceFileExt_C ".c") - set (_prefixSourceFileExt_CXX ".cxx") -endmacro() - -function (cotire_make_single_unity_source_file_path _language _target _unityFileVar) - cotire_setup_file_extension_variables() - if (NOT DEFINED _unityFileExt_${_language}) - set (${_unityFileVar} "" PARENT_SCOPE) - return() - endif() - set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") - set (_unityFileName "${_unityFileBaseName}${_unityFileExt_${_language}}") - cotire_get_intermediate_dir(_baseDir) - set (_unityFile "${_baseDir}/${_unityFileName}") - set (${_unityFileVar} "${_unityFile}" PARENT_SCOPE) -endfunction() - -function (cotire_make_unity_source_file_paths _language _target _maxIncludes _unityFilesVar) - cotire_setup_file_extension_variables() - if (NOT DEFINED _unityFileExt_${_language}) - set (${_unityFileVar} "" PARENT_SCOPE) - return() - endif() - set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") - cotire_get_intermediate_dir(_baseDir) - set (_startIndex 0) - set (_index 0) - set (_unityFiles "") - set (_sourceFiles ${ARGN}) - foreach (_sourceFile ${_sourceFiles}) - get_source_file_property(_startNew "${_sourceFile}" COTIRE_START_NEW_UNITY_SOURCE) - math (EXPR _unityFileCount "${_index} - ${_startIndex}") - if (_startNew OR (_maxIncludes GREATER 0 AND NOT _unityFileCount LESS _maxIncludes)) - if (_index GREATER 0) - # start new unity file segment - math (EXPR _endIndex "${_index} - 1") - set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}") - list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") - endif() - set (_startIndex ${_index}) - endif() - math (EXPR _index "${_index} + 1") - endforeach() - list (LENGTH _sourceFiles _numberOfSources) - if (_startIndex EQUAL 0) - # there is only a single unity file - cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFiles) - elseif (_startIndex LESS _numberOfSources) - # end with final unity file segment - math (EXPR _endIndex "${_index} - 1") - set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}") - list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") - endif() - set (${_unityFilesVar} ${_unityFiles} PARENT_SCOPE) - if (COTIRE_DEBUG AND _unityFiles) - message (STATUS "unity files: ${_unityFiles}") - endif() -endfunction() - -function (cotire_unity_to_prefix_file_path _language _target _unityFile _prefixFileVar) - cotire_setup_file_extension_variables() - if (NOT DEFINED _unityFileExt_${_language}) - set (${_prefixFileVar} "" PARENT_SCOPE) - return() - endif() - set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") - set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") - string (REPLACE "${_unityFileBaseName}" "${_prefixFileBaseName}" _prefixFile "${_unityFile}") - string (REGEX REPLACE "${_unityFileExt_${_language}}$" "${_prefixFileExt_${_language}}" _prefixFile "${_prefixFile}") - set (${_prefixFileVar} "${_prefixFile}" PARENT_SCOPE) -endfunction() - -function (cotire_prefix_header_to_source_file_path _language _prefixHeaderFile _prefixSourceFileVar) - cotire_setup_file_extension_variables() - if (NOT DEFINED _prefixSourceFileExt_${_language}) - set (${_prefixSourceFileVar} "" PARENT_SCOPE) - return() - endif() - string (REGEX REPLACE "${_prefixFileExt_${_language}}$" "${_prefixSourceFileExt_${_language}}" _prefixSourceFile "${_prefixHeaderFile}") - set (${_prefixSourceFileVar} "${_prefixSourceFile}" PARENT_SCOPE) -endfunction() - -function (cotire_make_prefix_file_name _language _target _prefixFileBaseNameVar _prefixFileNameVar) - cotire_setup_file_extension_variables() - if (NOT _language) - set (_prefixFileBaseName "${_target}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") - set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_C}") - elseif (DEFINED _prefixFileExt_${_language}) - set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") - set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_${_language}}") - else() - set (_prefixFileBaseName "") - set (_prefixFileName "") - endif() - set (${_prefixFileBaseNameVar} "${_prefixFileBaseName}" PARENT_SCOPE) - set (${_prefixFileNameVar} "${_prefixFileName}" PARENT_SCOPE) -endfunction() - -function (cotire_make_prefix_file_path _language _target _prefixFileVar) - cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName) - set (${_prefixFileVar} "" PARENT_SCOPE) - if (_prefixFileName) - if (NOT _language) - set (_language "C") - endif() - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang|Intel|MSVC") - cotire_get_intermediate_dir(_baseDir) - set (${_prefixFileVar} "${_baseDir}/${_prefixFileName}" PARENT_SCOPE) - endif() - endif() -endfunction() - -function (cotire_make_pch_file_path _language _target _pchFileVar) - cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName) - set (${_pchFileVar} "" PARENT_SCOPE) - if (_prefixFileBaseName AND _prefixFileName) - cotire_check_precompiled_header_support("${_language}" "${_target}" _msg) - if (NOT _msg) - if (XCODE) - # For Xcode, we completely hand off the compilation of the prefix header to the IDE - return() - endif() - cotire_get_intermediate_dir(_baseDir) - if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC") - # MSVC uses the extension .pch added to the prefix header base name - set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pch" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Clang") - # Clang looks for a precompiled header corresponding to the prefix header with the extension .pch appended - set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.pch" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "GNU") - # GCC looks for a precompiled header corresponding to the prefix header with the extension .gch appended - set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.gch" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Intel") - # Intel uses the extension .pchi added to the prefix header base name - set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pchi" PARENT_SCOPE) - endif() - endif() - endif() -endfunction() - -function (cotire_select_unity_source_files _unityFile _sourcesVar) - set (_sourceFiles ${ARGN}) - if (_sourceFiles AND "${_unityFile}" MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}_([0-9]+)_([0-9]+)") - set (_startIndex ${CMAKE_MATCH_1}) - set (_endIndex ${CMAKE_MATCH_2}) - list (LENGTH _sourceFiles _numberOfSources) - if (NOT _startIndex LESS _numberOfSources) - math (EXPR _startIndex "${_numberOfSources} - 1") - endif() - if (NOT _endIndex LESS _numberOfSources) - math (EXPR _endIndex "${_numberOfSources} - 1") - endif() - set (_files "") - foreach (_index RANGE ${_startIndex} ${_endIndex}) - list (GET _sourceFiles ${_index} _file) - list (APPEND _files "${_file}") - endforeach() - else() - set (_files ${_sourceFiles}) - endif() - set (${_sourcesVar} ${_files} PARENT_SCOPE) -endfunction() - -function (cotire_get_unity_source_dependencies _language _target _dependencySourcesVar) - set (_dependencySources "") - # depend on target's generated source files - get_target_property(_targetSourceFiles ${_target} SOURCES) - cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${_targetSourceFiles}) - if (_generatedSources) - # but omit all generated source files that have the COTIRE_EXCLUDED property set to true - cotire_get_objects_with_property_on(_excludedGeneratedSources COTIRE_EXCLUDED SOURCE ${_generatedSources}) - if (_excludedGeneratedSources) - list (REMOVE_ITEM _generatedSources ${_excludedGeneratedSources}) - endif() - # and omit all generated source files that have the COTIRE_DEPENDENCY property set to false explicitly - cotire_get_objects_with_property_off(_excludedNonDependencySources COTIRE_DEPENDENCY SOURCE ${_generatedSources}) - if (_excludedNonDependencySources) - list (REMOVE_ITEM _generatedSources ${_excludedNonDependencySources}) - endif() - if (_generatedSources) - list (APPEND _dependencySources ${_generatedSources}) - endif() - endif() - if (COTIRE_DEBUG AND _dependencySources) - message (STATUS "${_language} ${_target} unity source dependencies: ${_dependencySources}") - endif() - set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE) -endfunction() - -function (cotire_get_prefix_header_dependencies _language _target _dependencySourcesVar) - set (_dependencySources "") - # depend on target source files marked with custom COTIRE_DEPENDENCY property - get_target_property(_targetSourceFiles ${_target} SOURCES) - cotire_get_objects_with_property_on(_dependencySources COTIRE_DEPENDENCY SOURCE ${_targetSourceFiles}) - if (COTIRE_DEBUG AND _dependencySources) - message (STATUS "${_language} ${_target} prefix header dependencies: ${_dependencySources}") - endif() - set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE) -endfunction() - -function (cotire_generate_target_script _language _configurations _target _targetScriptVar _targetConfigScriptVar) - set (_targetSources ${ARGN}) - cotire_get_prefix_header_dependencies(${_language} ${_target} COTIRE_TARGET_PREFIX_DEPENDS ${_targetSources}) - cotire_get_unity_source_dependencies(${_language} ${_target} COTIRE_TARGET_UNITY_DEPENDS ${_targetSources}) - # set up variables to be configured - set (COTIRE_TARGET_LANGUAGE "${_language}") - get_target_property(COTIRE_TARGET_IGNORE_PATH ${_target} COTIRE_PREFIX_HEADER_IGNORE_PATH) - cotire_add_sys_root_paths(COTIRE_TARGET_IGNORE_PATH) - get_target_property(COTIRE_TARGET_INCLUDE_PATH ${_target} COTIRE_PREFIX_HEADER_INCLUDE_PATH) - cotire_add_sys_root_paths(COTIRE_TARGET_INCLUDE_PATH) - get_target_property(COTIRE_TARGET_PRE_UNDEFS ${_target} COTIRE_UNITY_SOURCE_PRE_UNDEFS) - get_target_property(COTIRE_TARGET_POST_UNDEFS ${_target} COTIRE_UNITY_SOURCE_POST_UNDEFS) - get_target_property(COTIRE_TARGET_MAXIMUM_NUMBER_OF_INCLUDES ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) - get_target_property(COTIRE_TARGET_INCLUDE_PRIORITY_PATH ${_target} COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH) - cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_PRE_UNDEFS COTIRE_TARGET_SOURCES_PRE_UNDEFS ${_targetSources}) - cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_POST_UNDEFS COTIRE_TARGET_SOURCES_POST_UNDEFS ${_targetSources}) - set (COTIRE_TARGET_CONFIGURATION_TYPES "${_configurations}") - foreach (_config ${_configurations}) - string (TOUPPER "${_config}" _upperConfig) - cotire_get_target_include_directories( - "${_config}" "${_language}" "${_target}" COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig} COTIRE_TARGET_SYSTEM_INCLUDE_DIRECTORIES_${_upperConfig}) - cotire_get_target_compile_definitions( - "${_config}" "${_language}" "${_target}" COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}) - cotire_get_target_compiler_flags( - "${_config}" "${_language}" "${_target}" COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}) - cotire_get_source_files_compile_definitions( - "${_config}" "${_language}" COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig} ${_targetSources}) - endforeach() - get_target_property(COTIRE_TARGET_${_language}_COMPILER_LAUNCHER ${_target} ${_language}_COMPILER_LAUNCHER) - # set up COTIRE_TARGET_SOURCES - set (COTIRE_TARGET_SOURCES "") - foreach (_sourceFile ${_targetSources}) - get_source_file_property(_generated "${_sourceFile}" GENERATED) - if (_generated) - # use absolute paths for generated files only, retrieving the LOCATION property is an expensive operation - get_source_file_property(_sourceLocation "${_sourceFile}" LOCATION) - list (APPEND COTIRE_TARGET_SOURCES "${_sourceLocation}") - else() - list (APPEND COTIRE_TARGET_SOURCES "${_sourceFile}") - endif() - endforeach() - # copy variable definitions to cotire target script - get_cmake_property(_vars VARIABLES) - string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+" _matchVars "${_vars}") - # omit COTIRE_*_INIT variables - string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+_INIT" _initVars "${_matchVars}") - if (_initVars) - list (REMOVE_ITEM _matchVars ${_initVars}) - endif() - # omit COTIRE_VERBOSE which is passed as a CMake define on command line - list (REMOVE_ITEM _matchVars COTIRE_VERBOSE) - set (_contents "") - set (_contentsHasGeneratorExpressions FALSE) - foreach (_var IN LISTS _matchVars ITEMS - XCODE MSVC CMAKE_GENERATOR CMAKE_BUILD_TYPE CMAKE_CONFIGURATION_TYPES - CMAKE_${_language}_COMPILER_ID CMAKE_${_language}_COMPILER_VERSION - CMAKE_${_language}_COMPILER_LAUNCHER CMAKE_${_language}_COMPILER CMAKE_${_language}_COMPILER_ARG1 - CMAKE_INCLUDE_FLAG_${_language} CMAKE_INCLUDE_FLAG_SEP_${_language} - CMAKE_INCLUDE_SYSTEM_FLAG_${_language} - CMAKE_${_language}_FRAMEWORK_SEARCH_FLAG - CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG - CMAKE_${_language}_SOURCE_FILE_EXTENSIONS) - if (DEFINED ${_var}) - string (REPLACE "\"" "\\\"" _value "${${_var}}") - set (_contents "${_contents}set (${_var} \"${_value}\")\n") - if (NOT _contentsHasGeneratorExpressions) - if ("${_value}" MATCHES "\\$<.*>") - set (_contentsHasGeneratorExpressions TRUE) - endif() - endif() - endif() - endforeach() - # generate target script file - get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) - set (_targetCotireScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_moduleName}") - cotire_write_file("CMAKE" "${_targetCotireScript}" "${_contents}" FALSE) - if (_contentsHasGeneratorExpressions) - # use file(GENERATE ...) to expand generator expressions in the target script at CMake generate-time - set (_configNameOrNoneGeneratorExpression "$<$:None>$<$>:$>") - set (_targetCotireConfigScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_configNameOrNoneGeneratorExpression}_${_moduleName}") - file (GENERATE OUTPUT "${_targetCotireConfigScript}" INPUT "${_targetCotireScript}") - else() - set (_targetCotireConfigScript "${_targetCotireScript}") - endif() - set (${_targetScriptVar} "${_targetCotireScript}" PARENT_SCOPE) - set (${_targetConfigScriptVar} "${_targetCotireConfigScript}" PARENT_SCOPE) -endfunction() - -function (cotire_setup_pch_file_compilation _language _target _targetScript _prefixFile _pchFile _hostFile) - set (_sourceFiles ${ARGN}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel" OR - (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "Clang")) - # for MSVC, Intel and Clang-cl, we attach the precompiled header compilation to the host file - # the remaining files include the precompiled header, see cotire_setup_pch_file_inclusion - if (_sourceFiles) - set (_flags "") - cotire_add_pch_compilation_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" "${_hostFile}" _flags) - set_property (SOURCE ${_hostFile} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_OUTPUTS "${_pchFile}") - # make object file generated from host file depend on prefix header - set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}") - # mark host file as cotired to prevent it from being used in another cotired target - set_property (SOURCE ${_hostFile} PROPERTY COTIRE_TARGET "${_target}") - endif() - elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") - # for makefile based generator, we add a custom command to precompile the prefix header - if (_targetScript) - cotire_set_cmd_to_prologue(_cmds) - list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "precompile" "${_targetScript}" "${_prefixFile}" "${_pchFile}" "${_hostFile}") - if (MSVC_IDE) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileLogPath) - else() - file (RELATIVE_PATH _pchFileLogPath "${CMAKE_BINARY_DIR}" "${_pchFile}") - endif() - # make precompiled header compilation depend on the actual compiler executable used to force - # re-compilation when the compiler executable is updated. This prevents "created by a different GCC executable" - # warnings when the precompiled header is included. - get_filename_component(_realCompilerExe "${CMAKE_${_language}_COMPILER}" ABSOLUTE) - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: OUTPUT ${_pchFile} ${_cmds} DEPENDS ${_prefixFile} ${_realCompilerExe} IMPLICIT_DEPENDS ${_language} ${_prefixFile}") - endif() - set_property (SOURCE "${_pchFile}" PROPERTY GENERATED TRUE) - add_custom_command( - OUTPUT "${_pchFile}" - COMMAND ${_cmds} - DEPENDS "${_prefixFile}" "${_realCompilerExe}" - IMPLICIT_DEPENDS ${_language} "${_prefixFile}" - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - COMMENT "Building ${_language} precompiled header ${_pchFileLogPath}" - VERBATIM) - endif() - endif() -endfunction() - -function (cotire_setup_pch_file_inclusion _language _target _wholeTarget _prefixFile _pchFile _hostFile) - if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel" OR - (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "Clang")) - # for MSVC, Intel and clang-cl, we include the precompiled header in all but the host file - # the host file does the precompiled header compilation, see cotire_setup_pch_file_compilation - set (_sourceFiles ${ARGN}) - list (LENGTH _sourceFiles _numberOfSourceFiles) - if (_numberOfSourceFiles GREATER 0) - # mark sources as cotired to prevent them from being used in another cotired target - set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") - set (_flags "") - cotire_add_prefix_pch_inclusion_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" _flags) - set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - # make object files generated from source files depend on precompiled header - set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}") - endif() - elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") - set (_sourceFiles ${_hostFile} ${ARGN}) - if (NOT _wholeTarget) - # for makefile based generator, we force the inclusion of the prefix header for a subset - # of the source files, if this is a multi-language target or has excluded files - set (_flags "") - cotire_add_prefix_pch_inclusion_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" _flags) - set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - # mark sources as cotired to prevent them from being used in another cotired target - set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") - endif() - # make object files generated from source files depend on precompiled header - set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}") - endif() -endfunction() - -function (cotire_setup_prefix_file_inclusion _language _target _prefixFile) - set (_sourceFiles ${ARGN}) - # force the inclusion of the prefix header for the given source files - set (_flags "") - set (_pchFile "") - cotire_add_prefix_pch_inclusion_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" _flags) - set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - # mark sources as cotired to prevent them from being used in another cotired target - set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") - # make object files generated from source files depend on prefix header - set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}") -endfunction() - -function (cotire_get_first_set_property_value _propertyValueVar _type _object) - set (_properties ${ARGN}) - foreach (_property ${_properties}) - get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) - if (_propertyValue) - set (${_propertyValueVar} ${_propertyValue} PARENT_SCOPE) - return() - endif() - endforeach() - set (${_propertyValueVar} "" PARENT_SCOPE) -endfunction() - -function (cotire_setup_combine_command _language _targetScript _joinedFile _cmdsVar) - set (_files ${ARGN}) - set (_filesPaths "") - foreach (_file ${_files}) - get_filename_component(_filePath "${_file}" ABSOLUTE) - list (APPEND _filesPaths "${_filePath}") - endforeach() - cotire_set_cmd_to_prologue(_prefixCmd) - list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "combine") - if (_targetScript) - list (APPEND _prefixCmd "${_targetScript}") - endif() - list (APPEND _prefixCmd "${_joinedFile}" ${_filesPaths}) - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: OUTPUT ${_joinedFile} COMMAND ${_prefixCmd} DEPENDS ${_files}") - endif() - set_property (SOURCE "${_joinedFile}" PROPERTY GENERATED TRUE) - if (MSVC_IDE) - file (TO_NATIVE_PATH "${_joinedFile}" _joinedFileLogPath) - else() - file (RELATIVE_PATH _joinedFileLogPath "${CMAKE_BINARY_DIR}" "${_joinedFile}") - endif() - get_filename_component(_joinedFileBaseName "${_joinedFile}" NAME_WE) - get_filename_component(_joinedFileExt "${_joinedFile}" EXT) - if (_language AND _joinedFileBaseName MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}$") - set (_comment "Generating ${_language} unity source ${_joinedFileLogPath}") - elseif (_language AND _joinedFileBaseName MATCHES "${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}$") - if (_joinedFileExt MATCHES "^\\.c") - set (_comment "Generating ${_language} prefix source ${_joinedFileLogPath}") - else() - set (_comment "Generating ${_language} prefix header ${_joinedFileLogPath}") - endif() - else() - set (_comment "Generating ${_joinedFileLogPath}") - endif() - add_custom_command( - OUTPUT "${_joinedFile}" - COMMAND ${_prefixCmd} - DEPENDS ${_files} - COMMENT "${_comment}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - VERBATIM) - list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd}) - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_setup_target_pch_usage _languages _target _wholeTarget) - if (XCODE) - # for Xcode, we attach a pre-build action to generate the unity sources and prefix headers - set (_prefixFiles "") - foreach (_language ${_languages}) - get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) - if (_prefixFile) - list (APPEND _prefixFiles "${_prefixFile}") - endif() - endforeach() - set (_cmds ${ARGN}) - list (LENGTH _prefixFiles _numberOfPrefixFiles) - if (_numberOfPrefixFiles GREATER 1) - # we also generate a generic, single prefix header which includes all language specific prefix headers - set (_language "") - set (_targetScript "") - cotire_make_prefix_file_path("${_language}" ${_target} _prefixHeader) - cotire_setup_combine_command("${_language}" "${_targetScript}" "${_prefixHeader}" _cmds ${_prefixFiles}) - else() - set (_prefixHeader "${_prefixFiles}") - endif() - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: TARGET ${_target} PRE_BUILD ${_cmds}") - endif() - # because CMake PRE_BUILD command does not support dependencies, - # we check dependencies explicity in cotire script mode when the pre-build action is run - add_custom_command( - TARGET "${_target}" - PRE_BUILD ${_cmds} - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - COMMENT "Updating target ${_target} prefix headers" - VERBATIM) - # make Xcode precompile the generated prefix header with ProcessPCH and ProcessPCH++ - set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES") - set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${_prefixHeader}") - elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") - # for makefile based generator, we force inclusion of the prefix header for all target source files - # if this is a single-language target without any excluded files - if (_wholeTarget) - set (_language "${_languages}") - # for MSVC, Intel and clang-cl, precompiled header inclusion is always done on the source file level - # see cotire_setup_pch_file_inclusion - if (NOT CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel" AND NOT - (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "Clang")) - get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) - if (_prefixFile) - get_property(_pchFile TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER) - set (_options COMPILE_OPTIONS) - cotire_add_prefix_pch_inclusion_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" _options) - set_property(TARGET ${_target} APPEND PROPERTY ${_options}) - endif() - endif() - endif() - endif() -endfunction() - -function (cotire_setup_unity_generation_commands _language _target _targetScript _targetConfigScript _unityFiles _cmdsVar) - set (_dependencySources "") - cotire_get_unity_source_dependencies(${_language} ${_target} _dependencySources ${ARGN}) - foreach (_unityFile ${_unityFiles}) - set_property (SOURCE "${_unityFile}" PROPERTY GENERATED TRUE) - # set up compiled unity source dependencies via OBJECT_DEPENDS - # this ensures that missing source files are generated before the unity file is compiled - if (COTIRE_DEBUG AND _dependencySources) - message (STATUS "${_unityFile} OBJECT_DEPENDS ${_dependencySources}") - endif() - if (_dependencySources) - # the OBJECT_DEPENDS property requires a list of full paths - set (_objectDependsPaths "") - foreach (_sourceFile ${_dependencySources}) - get_source_file_property(_sourceLocation "${_sourceFile}" LOCATION) - list (APPEND _objectDependsPaths "${_sourceLocation}") - endforeach() - set_property (SOURCE "${_unityFile}" PROPERTY OBJECT_DEPENDS ${_objectDependsPaths}) - endif() - if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - # unity file compilation results in potentially huge object file, - # thus use /bigobj by default unter cl.exe and Windows Intel - set_property (SOURCE "${_unityFile}" APPEND_STRING PROPERTY COMPILE_FLAGS "/bigobj") - endif() - cotire_set_cmd_to_prologue(_unityCmd) - list (APPEND _unityCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "unity" "${_targetConfigScript}" "${_unityFile}") - if (CMAKE_VERSION VERSION_LESS "3.1.0") - set (_unityCmdDepends "${_targetScript}") - else() - # CMake 3.1.0 supports generator expressions in arguments to DEPENDS - set (_unityCmdDepends "${_targetConfigScript}") - endif() - if (MSVC_IDE) - file (TO_NATIVE_PATH "${_unityFile}" _unityFileLogPath) - else() - file (RELATIVE_PATH _unityFileLogPath "${CMAKE_BINARY_DIR}" "${_unityFile}") - endif() - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: OUTPUT ${_unityFile} COMMAND ${_unityCmd} DEPENDS ${_unityCmdDepends}") - endif() - add_custom_command( - OUTPUT "${_unityFile}" - COMMAND ${_unityCmd} - DEPENDS ${_unityCmdDepends} - COMMENT "Generating ${_language} unity source ${_unityFileLogPath}" - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - VERBATIM) - list (APPEND ${_cmdsVar} COMMAND ${_unityCmd}) - endforeach() - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_setup_prefix_generation_command _language _target _targetScript _prefixFile _unityFiles _cmdsVar) - set (_sourceFiles ${ARGN}) - set (_dependencySources "") - cotire_get_prefix_header_dependencies(${_language} ${_target} _dependencySources ${_sourceFiles}) - cotire_set_cmd_to_prologue(_prefixCmd) - list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "prefix" "${_targetScript}" "${_prefixFile}" ${_unityFiles}) - set_property (SOURCE "${_prefixFile}" PROPERTY GENERATED TRUE) - # make prefix header generation depend on the actual compiler executable used to force - # re-generation when the compiler executable is updated. This prevents "file not found" - # errors for compiler version specific system header files. - get_filename_component(_realCompilerExe "${CMAKE_${_language}_COMPILER}" ABSOLUTE) - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: OUTPUT ${_prefixFile} COMMAND ${_prefixCmd} DEPENDS ${_unityFile} ${_dependencySources} ${_realCompilerExe}") - endif() - if (MSVC_IDE) - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileLogPath) - else() - file (RELATIVE_PATH _prefixFileLogPath "${CMAKE_BINARY_DIR}" "${_prefixFile}") - endif() - get_filename_component(_prefixFileExt "${_prefixFile}" EXT) - if (_prefixFileExt MATCHES "^\\.c") - set (_comment "Generating ${_language} prefix source ${_prefixFileLogPath}") - else() - set (_comment "Generating ${_language} prefix header ${_prefixFileLogPath}") - endif() - # prevent pre-processing errors upon generating the prefix header when a target's generated include file does not yet exist - # we do not add a file-level dependency for the target's generated files though, because we only want to depend on their existence - # thus we make the prefix header generation depend on a custom helper target which triggers the generation of the files - set (_preTargetName "${_target}${COTIRE_PCH_TARGET_SUFFIX}_pre") - if (TARGET ${_preTargetName}) - # custom helper target has already been generated while processing a different language - list (APPEND _dependencySources ${_preTargetName}) - else() - get_target_property(_targetSourceFiles ${_target} SOURCES) - cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${_targetSourceFiles}) - if (_generatedSources) - add_custom_target("${_preTargetName}" DEPENDS ${_generatedSources}) - cotire_init_target("${_preTargetName}") - list (APPEND _dependencySources ${_preTargetName}) - endif() - endif() - add_custom_command( - OUTPUT "${_prefixFile}" "${_prefixFile}.log" - COMMAND ${_prefixCmd} - DEPENDS ${_unityFiles} ${_dependencySources} "${_realCompilerExe}" - COMMENT "${_comment}" - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - VERBATIM) - list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd}) - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_setup_prefix_generation_from_unity_command _language _target _targetScript _prefixFile _unityFiles _cmdsVar) - set (_sourceFiles ${ARGN}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - # GNU and Clang require indirect compilation of the prefix header to make them honor the system_header pragma - cotire_prefix_header_to_source_file_path(${_language} "${_prefixFile}" _prefixSourceFile) - else() - set (_prefixSourceFile "${_prefixFile}") - endif() - cotire_setup_prefix_generation_command( - ${_language} ${_target} "${_targetScript}" - "${_prefixSourceFile}" "${_unityFiles}" ${_cmdsVar} ${_sourceFiles}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - # set up generation of a prefix source file which includes the prefix header - cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixFile}" _cmds ${_prefixSourceFile}) - endif() - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_setup_prefix_generation_from_provided_command _language _target _targetScript _prefixFile _cmdsVar) - set (_prefixHeaderFiles ${ARGN}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - # GNU and Clang require indirect compilation of the prefix header to make them honor the system_header pragma - cotire_prefix_header_to_source_file_path(${_language} "${_prefixFile}" _prefixSourceFile) - else() - set (_prefixSourceFile "${_prefixFile}") - endif() - cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixSourceFile}" _cmds ${_prefixHeaderFiles}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - # set up generation of a prefix source file which includes the prefix header - cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixFile}" _cmds ${_prefixSourceFile}) - endif() - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_init_cotire_target_properties _target) - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER TRUE) - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD TRUE) - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN FALSE) - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_SOURCE_DIR}") - cotire_check_is_path_relative_to("${CMAKE_BINARY_DIR}" _isRelative "${CMAKE_SOURCE_DIR}") - if (NOT _isRelative) - set_property(TARGET ${_target} APPEND PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_BINARY_DIR}") - endif() - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH "") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH "") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS "") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS "") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT "COPY_UNITY") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES SET) - if (NOT _isSet) - if (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES}") - else() - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "") - endif() - endif() -endfunction() - -function (cotire_make_target_message _target _languages _disableMsg _targetMsgVar) - get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) - get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) - string (REPLACE ";" " " _languagesStr "${_languages}") - math (EXPR _numberOfExcludedFiles "${ARGC} - 4") - if (_numberOfExcludedFiles EQUAL 0) - set (_excludedStr "") - elseif (COTIRE_VERBOSE OR _numberOfExcludedFiles LESS 4) - string (REPLACE ";" ", " _excludedStr "excluding ${ARGN}") - else() - set (_excludedStr "excluding ${_numberOfExcludedFiles} files") - endif() - set (_targetMsg "") - if (NOT _languages) - set (_targetMsg "Target ${_target} cannot be cotired.") - if (_disableMsg) - set (_targetMsg "${_targetMsg} ${_disableMsg}") - endif() - elseif (NOT _targetUsePCH AND NOT _targetAddSCU) - set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build and precompiled header.") - if (_disableMsg) - set (_targetMsg "${_targetMsg} ${_disableMsg}") - endif() - elseif (NOT _targetUsePCH) - if (_excludedStr) - set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header ${_excludedStr}.") - else() - set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header.") - endif() - if (_disableMsg) - set (_targetMsg "${_targetMsg} ${_disableMsg}") - endif() - elseif (NOT _targetAddSCU) - if (_excludedStr) - set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build ${_excludedStr}.") - else() - set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build.") - endif() - if (_disableMsg) - set (_targetMsg "${_targetMsg} ${_disableMsg}") - endif() - else() - if (_excludedStr) - set (_targetMsg "${_languagesStr} target ${_target} cotired ${_excludedStr}.") - else() - set (_targetMsg "${_languagesStr} target ${_target} cotired.") - endif() - endif() - set (${_targetMsgVar} "${_targetMsg}" PARENT_SCOPE) -endfunction() - -function (cotire_choose_target_languages _target _targetLanguagesVar _wholeTargetVar) - set (_languages ${ARGN}) - set (_allSourceFiles "") - set (_allExcludedSourceFiles "") - set (_allCotiredSourceFiles "") - set (_targetLanguages "") - set (_pchEligibleTargetLanguages "") - get_target_property(_targetType ${_target} TYPE) - get_target_property(_targetSourceFiles ${_target} SOURCES) - get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) - get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) - set (_disableMsg "") - foreach (_language ${_languages}) - get_target_property(_prefixHeader ${_target} COTIRE_${_language}_PREFIX_HEADER) - get_target_property(_unityBuildFile ${_target} COTIRE_${_language}_UNITY_SOURCE) - if (_prefixHeader OR _unityBuildFile) - message (STATUS "cotire: target ${_target} has already been cotired.") - set (${_targetLanguagesVar} "" PARENT_SCOPE) - return() - endif() - if (_targetUsePCH AND "${_language}" MATCHES "^C|CXX$" AND DEFINED CMAKE_${_language}_COMPILER_ID) - if (CMAKE_${_language}_COMPILER_ID) - cotire_check_precompiled_header_support("${_language}" "${_target}" _disableMsg) - if (_disableMsg) - set (_targetUsePCH FALSE) - endif() - endif() - endif() - set (_sourceFiles "") - set (_excludedSources "") - set (_cotiredSources "") - cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) - if (_sourceFiles OR _excludedSources OR _cotiredSources) - list (APPEND _targetLanguages ${_language}) - endif() - if (_sourceFiles) - list (APPEND _allSourceFiles ${_sourceFiles}) - endif() - list (LENGTH _sourceFiles _numberOfSources) - if (NOT _numberOfSources LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) - list (APPEND _pchEligibleTargetLanguages ${_language}) - endif() - if (_excludedSources) - list (APPEND _allExcludedSourceFiles ${_excludedSources}) - endif() - if (_cotiredSources) - list (APPEND _allCotiredSourceFiles ${_cotiredSources}) - endif() - endforeach() - set (_targetMsgLevel STATUS) - if (NOT _targetLanguages) - string (REPLACE ";" " or " _languagesStr "${_languages}") - set (_disableMsg "No ${_languagesStr} source files.") - set (_targetUsePCH FALSE) - set (_targetAddSCU FALSE) - endif() - if (_targetUsePCH) - if (_allCotiredSourceFiles) - cotire_get_source_file_property_values(_cotireTargets COTIRE_TARGET ${_allCotiredSourceFiles}) - list (REMOVE_DUPLICATES _cotireTargets) - string (REPLACE ";" ", " _cotireTargetsStr "${_cotireTargets}") - set (_disableMsg "Target sources already include a precompiled header for target(s) ${_cotireTargets}.") - set (_disableMsg "${_disableMsg} Set target property COTIRE_ENABLE_PRECOMPILED_HEADER to FALSE for targets ${_target},") - set (_disableMsg "${_disableMsg} ${_cotireTargetsStr} to get a workable build system.") - set (_targetMsgLevel SEND_ERROR) - set (_targetUsePCH FALSE) - elseif (NOT _pchEligibleTargetLanguages) - set (_disableMsg "Too few applicable sources.") - set (_targetUsePCH FALSE) - elseif (XCODE AND _allExcludedSourceFiles) - # for Xcode, we cannot apply the precompiled header to individual sources, only to the whole target - set (_disableMsg "Exclusion of source files not supported for generator Xcode.") - set (_targetUsePCH FALSE) - elseif (XCODE AND "${_targetType}" STREQUAL "OBJECT_LIBRARY") - # for Xcode, we cannot apply the required PRE_BUILD action to generate the prefix header to an OBJECT_LIBRARY target - set (_disableMsg "Required PRE_BUILD action not supported for OBJECT_LIBRARY targets for generator Xcode.") - set (_targetUsePCH FALSE) - endif() - endif() - if (_targetAddSCU) - # disable unity builds if automatic Qt processing is used - get_target_property(_targetAutoMoc ${_target} AUTOMOC) - get_target_property(_targetAutoUic ${_target} AUTOUIC) - get_target_property(_targetAutoRcc ${_target} AUTORCC) - if (_targetAutoMoc OR _targetAutoUic OR _targetAutoRcc) - if (_disableMsg) - set (_disableMsg "${_disableMsg} Target uses automatic CMake Qt processing.") - else() - set (_disableMsg "Target uses automatic CMake Qt processing.") - endif() - set (_targetAddSCU FALSE) - endif() - endif() - set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER ${_targetUsePCH}) - set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD ${_targetAddSCU}) - cotire_make_target_message(${_target} "${_targetLanguages}" "${_disableMsg}" _targetMsg ${_allExcludedSourceFiles}) - if (_targetMsg) - if (NOT DEFINED COTIREMSG_${_target}) - set (COTIREMSG_${_target} "") - endif() - if (COTIRE_VERBOSE OR NOT "${_targetMsgLevel}" STREQUAL "STATUS" OR - NOT "${COTIREMSG_${_target}}" STREQUAL "${_targetMsg}") - # cache message to avoid redundant messages on re-configure - set (COTIREMSG_${_target} "${_targetMsg}" CACHE INTERNAL "${_target} cotire message.") - message (${_targetMsgLevel} "${_targetMsg}") - endif() - endif() - list (LENGTH _targetLanguages _numberOfLanguages) - if (_numberOfLanguages GREATER 1 OR _allExcludedSourceFiles) - set (${_wholeTargetVar} FALSE PARENT_SCOPE) - else() - set (${_wholeTargetVar} TRUE PARENT_SCOPE) - endif() - set (${_targetLanguagesVar} ${_targetLanguages} PARENT_SCOPE) -endfunction() - -function (cotire_compute_unity_max_number_of_includes _target _maxIncludesVar) - set (_sourceFiles ${ARGN}) - get_target_property(_maxIncludes ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) - if (_maxIncludes MATCHES "(-j|--parallel|--jobs) ?([0-9]*)") - if (DEFINED CMAKE_MATCH_2) - set (_numberOfThreads "${CMAKE_MATCH_2}") - else() - set (_numberOfThreads "") - endif() - if (NOT _numberOfThreads) - # use all available cores - ProcessorCount(_numberOfThreads) - endif() - list (LENGTH _sourceFiles _numberOfSources) - math (EXPR _maxIncludes "(${_numberOfSources} + ${_numberOfThreads} - 1) / ${_numberOfThreads}") - elseif (NOT _maxIncludes MATCHES "[0-9]+") - set (_maxIncludes 0) - endif() - if (COTIRE_DEBUG) - message (STATUS "${_target} unity source max includes: ${_maxIncludes}") - endif() - set (${_maxIncludesVar} ${_maxIncludes} PARENT_SCOPE) -endfunction() - -function (cotire_process_target_language _language _configurations _target _wholeTarget _cmdsVar) - set (${_cmdsVar} "" PARENT_SCOPE) - get_target_property(_targetSourceFiles ${_target} SOURCES) - set (_sourceFiles "") - set (_excludedSources "") - set (_cotiredSources "") - cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) - if (NOT _sourceFiles AND NOT _cotiredSources) - return() - endif() - set (_cmds "") - # check for user provided unity source file list - get_property(_unitySourceFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE_INIT) - if (NOT _unitySourceFiles) - set (_unitySourceFiles ${_sourceFiles} ${_cotiredSources}) - endif() - cotire_generate_target_script( - ${_language} "${_configurations}" ${_target} _targetScript _targetConfigScript ${_unitySourceFiles}) - # set up unity files for parallel compilation - cotire_compute_unity_max_number_of_includes(${_target} _maxIncludes ${_unitySourceFiles}) - cotire_make_unity_source_file_paths(${_language} ${_target} ${_maxIncludes} _unityFiles ${_unitySourceFiles}) - list (LENGTH _unityFiles _numberOfUnityFiles) - if (_numberOfUnityFiles EQUAL 0) - return() - elseif (_numberOfUnityFiles GREATER 1) - cotire_setup_unity_generation_commands( - ${_language} ${_target} "${_targetScript}" "${_targetConfigScript}" "${_unityFiles}" _cmds ${_unitySourceFiles}) - endif() - # set up single unity file for prefix header generation - cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFile) - cotire_setup_unity_generation_commands( - ${_language} ${_target} "${_targetScript}" "${_targetConfigScript}" "${_unityFile}" _cmds ${_unitySourceFiles}) - cotire_make_prefix_file_path(${_language} ${_target} _prefixFile) - # set up prefix header - if (_prefixFile) - # check for user provided prefix header files - get_property(_prefixHeaderFiles TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER_INIT) - if (_prefixHeaderFiles) - cotire_setup_prefix_generation_from_provided_command( - ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" _cmds ${_prefixHeaderFiles}) - else() - cotire_setup_prefix_generation_from_unity_command( - ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" "${_unityFile}" _cmds ${_unitySourceFiles}) - endif() - # check if selected language has enough sources at all - list (LENGTH _sourceFiles _numberOfSources) - if (_numberOfSources LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) - set (_targetUsePCH FALSE) - else() - get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) - endif() - if (_targetUsePCH) - cotire_make_pch_file_path(${_language} ${_target} _pchFile) - if (_pchFile) - # first file in _sourceFiles is passed as the host file - cotire_setup_pch_file_compilation( - ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" "${_pchFile}" ${_sourceFiles}) - cotire_setup_pch_file_inclusion( - ${_language} ${_target} ${_wholeTarget} "${_prefixFile}" "${_pchFile}" ${_sourceFiles}) - endif() - elseif (_prefixHeaderFiles) - # user provided prefix header must be included unconditionally - cotire_setup_prefix_file_inclusion(${_language} ${_target} "${_prefixFile}" ${_sourceFiles}) - endif() - endif() - # mark target as cotired for language - set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE "${_unityFiles}") - if (_prefixFile) - set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER "${_prefixFile}") - if (_targetUsePCH AND _pchFile) - set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER "${_pchFile}") - endif() - endif() - set (${_cmdsVar} ${_cmds} PARENT_SCOPE) -endfunction() - -function (cotire_setup_clean_target _target) - set (_cleanTargetName "${_target}${COTIRE_CLEAN_TARGET_SUFFIX}") - if (NOT TARGET "${_cleanTargetName}") - cotire_set_cmd_to_prologue(_cmds) - get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}" ABSOLUTE) - list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${_outputDir}" "${COTIRE_INTDIR}" "${_target}") - add_custom_target(${_cleanTargetName} - COMMAND ${_cmds} - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - COMMENT "Cleaning up target ${_target} cotire generated files" - VERBATIM) - cotire_init_target("${_cleanTargetName}") - endif() -endfunction() - -function (cotire_setup_pch_target _languages _configurations _target) - if ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") - # for makefile based generators, we add a custom target to trigger the generation of the cotire related files - set (_dependsFiles "") - foreach (_language ${_languages}) - set (_props COTIRE_${_language}_PREFIX_HEADER COTIRE_${_language}_UNITY_SOURCE) - if (NOT CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel" AND NOT - (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "Clang")) - # MSVC, Intel and clang-cl only create precompiled header as a side effect - list (INSERT _props 0 COTIRE_${_language}_PRECOMPILED_HEADER) - endif() - cotire_get_first_set_property_value(_dependsFile TARGET ${_target} ${_props}) - if (_dependsFile) - list (APPEND _dependsFiles "${_dependsFile}") - endif() - endforeach() - if (_dependsFiles) - set (_pchTargetName "${_target}${COTIRE_PCH_TARGET_SUFFIX}") - add_custom_target("${_pchTargetName}" DEPENDS ${_dependsFiles}) - cotire_init_target("${_pchTargetName}") - cotire_add_to_pch_all_target(${_pchTargetName}) - endif() - else() - # for other generators, we add the "clean all" target to clean up the precompiled header - cotire_setup_clean_all_target() - endif() -endfunction() - -function (cotire_filter_object_libraries _target _objectLibrariesVar) - set (_objectLibraries "") - foreach (_source ${ARGN}) - if (_source MATCHES "^\\$$") - list (APPEND _objectLibraries "${_source}") - endif() - endforeach() - set (${_objectLibrariesVar} ${_objectLibraries} PARENT_SCOPE) -endfunction() - -function (cotire_collect_unity_target_sources _target _languages _unityTargetSourcesVar) - get_target_property(_targetSourceFiles ${_target} SOURCES) - set (_unityTargetSources ${_targetSourceFiles}) - foreach (_language ${_languages}) - get_property(_unityFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE) - if (_unityFiles) - # remove source files that are included in the unity source - set (_sourceFiles "") - set (_excludedSources "") - set (_cotiredSources "") - cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) - if (_sourceFiles OR _cotiredSources) - list (REMOVE_ITEM _unityTargetSources ${_sourceFiles} ${_cotiredSources}) - endif() - # add unity source files instead - list (APPEND _unityTargetSources ${_unityFiles}) - endif() - endforeach() - # handle object libraries which are part of the target's sources - get_target_property(_linkLibrariesStrategy ${_target} COTIRE_UNITY_LINK_LIBRARIES_INIT) - if ("${_linkLibrariesStrategy}" MATCHES "^COPY_UNITY$") - cotire_filter_object_libraries(${_target} _objectLibraries ${_targetSourceFiles}) - if (_objectLibraries) - cotire_map_libraries("${_linkLibrariesStrategy}" _unityObjectLibraries ${_objectLibraries}) - list (REMOVE_ITEM _unityTargetSources ${_objectLibraries}) - list (APPEND _unityTargetSources ${_unityObjectLibraries}) - endif() - endif() - set (${_unityTargetSourcesVar} ${_unityTargetSources} PARENT_SCOPE) -endfunction() - -function (cotire_setup_unity_target_pch_usage _languages _target) - foreach (_language ${_languages}) - get_property(_unityFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE) - if (_unityFiles) - get_property(_userPrefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER_INIT) - get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) - if (_userPrefixFile AND _prefixFile) - # user provided prefix header must be included unconditionally by unity sources - cotire_setup_prefix_file_inclusion(${_language} ${_target} "${_prefixFile}" ${_unityFiles}) - endif() - endif() - endforeach() -endfunction() - -function (cotire_setup_unity_build_target _languages _configurations _target) - get_target_property(_unityTargetName ${_target} COTIRE_UNITY_TARGET_NAME) - if (NOT _unityTargetName) - set (_unityTargetName "${_target}${COTIRE_UNITY_BUILD_TARGET_SUFFIX}") - endif() - # determine unity target sub type - get_target_property(_targetType ${_target} TYPE) - if ("${_targetType}" STREQUAL "EXECUTABLE") - set (_unityTargetSubType "") - elseif (_targetType MATCHES "(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") - set (_unityTargetSubType "${CMAKE_MATCH_1}") - else() - message (WARNING "cotire: target ${_target} has unknown target type ${_targetType}.") - return() - endif() - # determine unity target sources - set (_unityTargetSources "") - cotire_collect_unity_target_sources(${_target} "${_languages}" _unityTargetSources) - # prevent AUTOMOC, AUTOUIC and AUTORCC properties from being set when the unity target is created - set (CMAKE_AUTOMOC OFF) - set (CMAKE_AUTOUIC OFF) - set (CMAKE_AUTORCC OFF) - if (COTIRE_DEBUG) - message (STATUS "add target ${_targetType} ${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}") - endif() - # generate unity target - if ("${_targetType}" STREQUAL "EXECUTABLE") - add_executable(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}) - else() - add_library(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}) - endif() - # copy output location properties - set (_outputDirProperties - ARCHIVE_OUTPUT_DIRECTORY ARCHIVE_OUTPUT_DIRECTORY_ - LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY_ - RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_DIRECTORY_) - if (COTIRE_UNITY_OUTPUT_DIRECTORY) - set (_setDefaultOutputDir TRUE) - if (IS_ABSOLUTE "${COTIRE_UNITY_OUTPUT_DIRECTORY}") - set (_outputDir "${COTIRE_UNITY_OUTPUT_DIRECTORY}") - else() - # append relative COTIRE_UNITY_OUTPUT_DIRECTORY to target's actual output directory - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} ${_outputDirProperties}) - cotire_resolve_config_properties("${_configurations}" _properties ${_outputDirProperties}) - foreach (_property ${_properties}) - get_property(_outputDir TARGET ${_target} PROPERTY ${_property}) - if (_outputDir) - get_filename_component(_outputDir "${_outputDir}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE) - set_property(TARGET ${_unityTargetName} PROPERTY ${_property} "${_outputDir}") - set (_setDefaultOutputDir FALSE) - endif() - endforeach() - if (_setDefaultOutputDir) - get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE) - endif() - endif() - if (_setDefaultOutputDir) - set_target_properties(${_unityTargetName} PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY "${_outputDir}" - LIBRARY_OUTPUT_DIRECTORY "${_outputDir}" - RUNTIME_OUTPUT_DIRECTORY "${_outputDir}") - endif() - else() - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - ${_outputDirProperties}) - endif() - # copy output name - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - ARCHIVE_OUTPUT_NAME ARCHIVE_OUTPUT_NAME_ - LIBRARY_OUTPUT_NAME LIBRARY_OUTPUT_NAME_ - OUTPUT_NAME OUTPUT_NAME_ - RUNTIME_OUTPUT_NAME RUNTIME_OUTPUT_NAME_ - PREFIX _POSTFIX SUFFIX - IMPORT_PREFIX IMPORT_SUFFIX) - # copy compile stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - COMPILE_DEFINITIONS COMPILE_DEFINITIONS_ - COMPILE_FLAGS COMPILE_OPTIONS - Fortran_FORMAT Fortran_MODULE_DIRECTORY - INCLUDE_DIRECTORIES - INTERPROCEDURAL_OPTIMIZATION INTERPROCEDURAL_OPTIMIZATION_ - POSITION_INDEPENDENT_CODE - C_COMPILER_LAUNCHER CXX_COMPILER_LAUNCHER - C_INCLUDE_WHAT_YOU_USE CXX_INCLUDE_WHAT_YOU_USE - C_VISIBILITY_PRESET CXX_VISIBILITY_PRESET VISIBILITY_INLINES_HIDDEN - C_CLANG_TIDY CXX_CLANG_TIDY) - # copy compile features - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED - CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED - COMPILE_FEATURES) - # copy interface stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - COMPATIBLE_INTERFACE_BOOL COMPATIBLE_INTERFACE_NUMBER_MAX COMPATIBLE_INTERFACE_NUMBER_MIN - COMPATIBLE_INTERFACE_STRING - INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_FEATURES INTERFACE_COMPILE_OPTIONS - INTERFACE_INCLUDE_DIRECTORIES INTERFACE_SOURCES - INTERFACE_POSITION_INDEPENDENT_CODE INTERFACE_SYSTEM_INCLUDE_DIRECTORIES - INTERFACE_AUTOUIC_OPTIONS NO_SYSTEM_FROM_IMPORTED) - # copy link stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - BUILD_WITH_INSTALL_RPATH BUILD_WITH_INSTALL_NAME_DIR - INSTALL_RPATH INSTALL_RPATH_USE_LINK_PATH SKIP_BUILD_RPATH - LINKER_LANGUAGE LINK_DEPENDS LINK_DEPENDS_NO_SHARED - LINK_FLAGS LINK_FLAGS_ - LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_ - LINK_INTERFACE_MULTIPLICITY LINK_INTERFACE_MULTIPLICITY_ - LINK_SEARCH_START_STATIC LINK_SEARCH_END_STATIC - STATIC_LIBRARY_FLAGS STATIC_LIBRARY_FLAGS_ - NO_SONAME SOVERSION VERSION - LINK_WHAT_YOU_USE BUILD_RPATH) - # copy cmake stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - IMPLICIT_DEPENDS_INCLUDE_TRANSFORM RULE_LAUNCH_COMPILE RULE_LAUNCH_CUSTOM RULE_LAUNCH_LINK) - # copy Apple platform specific stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - BUNDLE BUNDLE_EXTENSION FRAMEWORK FRAMEWORK_VERSION INSTALL_NAME_DIR - MACOSX_BUNDLE MACOSX_BUNDLE_INFO_PLIST MACOSX_FRAMEWORK_INFO_PLIST MACOSX_RPATH - OSX_ARCHITECTURES OSX_ARCHITECTURES_ PRIVATE_HEADER PUBLIC_HEADER RESOURCE XCTEST - IOS_INSTALL_COMBINED XCODE_EXPLICIT_FILE_TYPE XCODE_PRODUCT_TYPE) - # copy Windows platform specific stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - GNUtoMS - COMPILE_PDB_NAME COMPILE_PDB_NAME_ - COMPILE_PDB_OUTPUT_DIRECTORY COMPILE_PDB_OUTPUT_DIRECTORY_ - PDB_NAME PDB_NAME_ PDB_OUTPUT_DIRECTORY PDB_OUTPUT_DIRECTORY_ - VS_DESKTOP_EXTENSIONS_VERSION VS_DOTNET_REFERENCES VS_DOTNET_TARGET_FRAMEWORK_VERSION - VS_GLOBAL_KEYWORD VS_GLOBAL_PROJECT_TYPES VS_GLOBAL_ROOTNAMESPACE - VS_IOT_EXTENSIONS_VERSION VS_IOT_STARTUP_TASK - VS_KEYWORD VS_MOBILE_EXTENSIONS_VERSION - VS_SCC_AUXPATH VS_SCC_LOCALPATH VS_SCC_PROJECTNAME VS_SCC_PROVIDER - VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION - VS_WINRT_COMPONENT VS_WINRT_EXTENSIONS VS_WINRT_REFERENCES - WIN32_EXECUTABLE WINDOWS_EXPORT_ALL_SYMBOLS - DEPLOYMENT_REMOTE_DIRECTORY VS_CONFIGURATION_TYPE - VS_SDK_REFERENCES VS_USER_PROPS VS_DEBUGGER_WORKING_DIRECTORY) - # copy Android platform specific stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - ANDROID_API ANDROID_API_MIN ANDROID_GUI - ANDROID_ANT_ADDITIONAL_OPTIONS ANDROID_ARCH ANDROID_ASSETS_DIRECTORIES - ANDROID_JAR_DEPENDENCIES ANDROID_JAR_DIRECTORIES ANDROID_JAVA_SOURCE_DIR - ANDROID_NATIVE_LIB_DEPENDENCIES ANDROID_NATIVE_LIB_DIRECTORIES - ANDROID_PROCESS_MAX ANDROID_PROGUARD ANDROID_PROGUARD_CONFIG_PATH - ANDROID_SECURE_PROPS_PATH ANDROID_SKIP_ANT_STEP ANDROID_STL_TYPE) - # copy CUDA platform specific stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - CUDA_PTX_COMPILATION CUDA_SEPARABLE_COMPILATION CUDA_RESOLVE_DEVICE_SYMBOLS - CUDA_EXTENSIONS CUDA_STANDARD CUDA_STANDARD_REQUIRED) - # use output name from original target - get_target_property(_targetOutputName ${_unityTargetName} OUTPUT_NAME) - if (NOT _targetOutputName) - set_property(TARGET ${_unityTargetName} PROPERTY OUTPUT_NAME "${_target}") - endif() - # use export symbol from original target - cotire_get_target_export_symbol("${_target}" _defineSymbol) - if (_defineSymbol) - set_property(TARGET ${_unityTargetName} PROPERTY DEFINE_SYMBOL "${_defineSymbol}") - if ("${_targetType}" STREQUAL "EXECUTABLE") - set_property(TARGET ${_unityTargetName} PROPERTY ENABLE_EXPORTS TRUE) - endif() - endif() - # enable parallel compilation for MSVC - if (MSVC AND "${CMAKE_GENERATOR}" MATCHES "Visual Studio") - list (LENGTH _unityTargetSources _numberOfUnityTargetSources) - if (_numberOfUnityTargetSources GREATER 1) - set_property(TARGET ${_unityTargetName} APPEND PROPERTY COMPILE_OPTIONS "/MP") - endif() - endif() - cotire_init_target(${_unityTargetName}) - cotire_add_to_unity_all_target(${_unityTargetName}) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_TARGET_NAME "${_unityTargetName}") -endfunction(cotire_setup_unity_build_target) - -function (cotire_target _target) - set(_options "") - set(_oneValueArgs "") - set(_multiValueArgs LANGUAGES CONFIGURATIONS) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - if (NOT _option_LANGUAGES) - get_property (_option_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) - endif() - if (NOT _option_CONFIGURATIONS) - cotire_get_configuration_types(_option_CONFIGURATIONS) - endif() - # check if cotire can be applied to target at all - cotire_is_target_supported(${_target} _isSupported) - if (NOT _isSupported) - get_target_property(_imported ${_target} IMPORTED) - get_target_property(_targetType ${_target} TYPE) - if (_imported) - message (WARNING "cotire: imported ${_targetType} target ${_target} cannot be cotired.") - else() - message (STATUS "cotire: ${_targetType} target ${_target} cannot be cotired.") - endif() - return() - endif() - # resolve alias - get_target_property(_aliasName ${_target} ALIASED_TARGET) - if (_aliasName) - if (COTIRE_DEBUG) - message (STATUS "${_target} is an alias. Applying cotire to aliased target ${_aliasName} instead.") - endif() - set (_target ${_aliasName}) - endif() - # check if target needs to be cotired for build type - # when using configuration types, the test is performed at build time - cotire_init_cotire_target_properties(${_target}) - if (NOT CMAKE_CONFIGURATION_TYPES) - if (CMAKE_BUILD_TYPE) - list (FIND _option_CONFIGURATIONS "${CMAKE_BUILD_TYPE}" _index) - else() - list (FIND _option_CONFIGURATIONS "None" _index) - endif() - if (_index EQUAL -1) - if (COTIRE_DEBUG) - message (STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} not cotired (${_option_CONFIGURATIONS})") - endif() - return() - endif() - endif() - # when not using configuration types, immediately create cotire intermediate dir - if (NOT CMAKE_CONFIGURATION_TYPES) - cotire_get_intermediate_dir(_baseDir) - file (MAKE_DIRECTORY "${_baseDir}") - endif() - # choose languages that apply to the target - cotire_choose_target_languages("${_target}" _targetLanguages _wholeTarget ${_option_LANGUAGES}) - if (NOT _targetLanguages) - return() - endif() - set (_cmds "") - foreach (_language ${_targetLanguages}) - cotire_process_target_language("${_language}" "${_option_CONFIGURATIONS}" ${_target} ${_wholeTarget} _cmd) - if (_cmd) - list (APPEND _cmds ${_cmd}) - endif() - endforeach() - get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) - if (_targetAddSCU) - cotire_setup_unity_build_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target}) - endif() - get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) - if (_targetUsePCH) - cotire_setup_target_pch_usage("${_targetLanguages}" ${_target} ${_wholeTarget} ${_cmds}) - cotire_setup_pch_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target}) - if (_targetAddSCU) - cotire_setup_unity_target_pch_usage("${_targetLanguages}" ${_target}) - endif() - endif() - get_target_property(_targetAddCleanTarget ${_target} COTIRE_ADD_CLEAN) - if (_targetAddCleanTarget) - cotire_setup_clean_target(${_target}) - endif() -endfunction(cotire_target) - -function (cotire_map_libraries _strategy _mappedLibrariesVar) - set (_mappedLibraries "") - foreach (_library ${ARGN}) - if (_library MATCHES "^\\$$") - set (_libraryName "${CMAKE_MATCH_1}") - set (_linkOnly TRUE) - set (_objectLibrary FALSE) - elseif (_library MATCHES "^\\$$") - set (_libraryName "${CMAKE_MATCH_1}") - set (_linkOnly FALSE) - set (_objectLibrary TRUE) - else() - set (_libraryName "${_library}") - set (_linkOnly FALSE) - set (_objectLibrary FALSE) - endif() - if ("${_strategy}" MATCHES "COPY_UNITY") - cotire_is_target_supported(${_libraryName} _isSupported) - if (_isSupported) - # use target's corresponding unity target, if available - get_target_property(_libraryUnityTargetName ${_libraryName} COTIRE_UNITY_TARGET_NAME) - if (TARGET "${_libraryUnityTargetName}") - if (_linkOnly) - list (APPEND _mappedLibraries "$") - elseif (_objectLibrary) - list (APPEND _mappedLibraries "$") - else() - list (APPEND _mappedLibraries "${_libraryUnityTargetName}") - endif() - else() - list (APPEND _mappedLibraries "${_library}") - endif() - else() - list (APPEND _mappedLibraries "${_library}") - endif() - else() - list (APPEND _mappedLibraries "${_library}") - endif() - endforeach() - list (REMOVE_DUPLICATES _mappedLibraries) - set (${_mappedLibrariesVar} ${_mappedLibraries} PARENT_SCOPE) -endfunction() - -function (cotire_target_link_libraries _target) - cotire_is_target_supported(${_target} _isSupported) - if (NOT _isSupported) - return() - endif() - get_target_property(_unityTargetName ${_target} COTIRE_UNITY_TARGET_NAME) - if (TARGET "${_unityTargetName}") - get_target_property(_linkLibrariesStrategy ${_target} COTIRE_UNITY_LINK_LIBRARIES_INIT) - if (COTIRE_DEBUG) - message (STATUS "unity target ${_unityTargetName} link strategy: ${_linkLibrariesStrategy}") - endif() - if ("${_linkLibrariesStrategy}" MATCHES "^(COPY|COPY_UNITY)$") - get_target_property(_linkLibraries ${_target} LINK_LIBRARIES) - if (_linkLibraries) - cotire_map_libraries("${_linkLibrariesStrategy}" _unityLinkLibraries ${_linkLibraries}) - set_target_properties(${_unityTargetName} PROPERTIES LINK_LIBRARIES "${_unityLinkLibraries}") - if (COTIRE_DEBUG) - message (STATUS "unity target ${_unityTargetName} link libraries: ${_unityLinkLibraries}") - endif() - endif() - get_target_property(_interfaceLinkLibraries ${_target} INTERFACE_LINK_LIBRARIES) - if (_interfaceLinkLibraries) - cotire_map_libraries("${_linkLibrariesStrategy}" _unityLinkInterfaceLibraries ${_interfaceLinkLibraries}) - set_target_properties(${_unityTargetName} PROPERTIES INTERFACE_LINK_LIBRARIES "${_unityLinkInterfaceLibraries}") - if (COTIRE_DEBUG) - message (STATUS "unity target ${_unityTargetName} interface link libraries: ${_unityLinkInterfaceLibraries}") - endif() - endif() - get_target_property(_manualDependencies ${_target} MANUALLY_ADDED_DEPENDENCIES) - if (_manualDependencies) - cotire_map_libraries("${_linkLibrariesStrategy}" _unityManualDependencies ${_manualDependencies}) - if (_unityManualDependencies) - add_dependencies("${_unityTargetName}" ${_unityManualDependencies}) - endif() - endif() - endif() - endif() -endfunction(cotire_target_link_libraries) - -function (cotire_cleanup _binaryDir _cotireIntermediateDirName _targetName) - if (_targetName) - file (GLOB_RECURSE _cotireFiles "${_binaryDir}/${_targetName}*.*") - else() - file (GLOB_RECURSE _cotireFiles "${_binaryDir}/*.*") - endif() - # filter files in intermediate directory - set (_filesToRemove "") - foreach (_file ${_cotireFiles}) - get_filename_component(_dir "${_file}" DIRECTORY) - get_filename_component(_dirName "${_dir}" NAME) - if ("${_dirName}" STREQUAL "${_cotireIntermediateDirName}") - list (APPEND _filesToRemove "${_file}") - endif() - endforeach() - if (_filesToRemove) - if (COTIRE_VERBOSE) - message (STATUS "cleaning up ${_filesToRemove}") - endif() - file (REMOVE ${_filesToRemove}) - endif() -endfunction() - -function (cotire_init_target _targetName) - if (COTIRE_TARGETS_FOLDER) - set_target_properties(${_targetName} PROPERTIES FOLDER "${COTIRE_TARGETS_FOLDER}") - endif() - set_target_properties(${_targetName} PROPERTIES EXCLUDE_FROM_ALL TRUE) - if (MSVC_IDE) - set_target_properties(${_targetName} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD TRUE) - endif() -endfunction() - -function (cotire_add_to_pch_all_target _pchTargetName) - set (_targetName "${COTIRE_PCH_ALL_TARGET_NAME}") - if (NOT TARGET "${_targetName}") - add_custom_target("${_targetName}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - VERBATIM) - cotire_init_target("${_targetName}") - endif() - cotire_setup_clean_all_target() - add_dependencies(${_targetName} ${_pchTargetName}) -endfunction() - -function (cotire_add_to_unity_all_target _unityTargetName) - set (_targetName "${COTIRE_UNITY_BUILD_ALL_TARGET_NAME}") - if (NOT TARGET "${_targetName}") - add_custom_target("${_targetName}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - VERBATIM) - cotire_init_target("${_targetName}") - endif() - cotire_setup_clean_all_target() - add_dependencies(${_targetName} ${_unityTargetName}) -endfunction() - -function (cotire_setup_clean_all_target) - set (_targetName "${COTIRE_CLEAN_ALL_TARGET_NAME}") - if (NOT TARGET "${_targetName}") - cotire_set_cmd_to_prologue(_cmds) - list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${CMAKE_BINARY_DIR}" "${COTIRE_INTDIR}") - add_custom_target(${_targetName} - COMMAND ${_cmds} - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - COMMENT "Cleaning up all cotire generated files" - VERBATIM) - cotire_init_target("${_targetName}") - endif() -endfunction() - -function (cotire) - set(_options "") - set(_oneValueArgs "") - set(_multiValueArgs LANGUAGES CONFIGURATIONS) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - set (_targets ${_option_UNPARSED_ARGUMENTS}) - foreach (_target ${_targets}) - if (TARGET ${_target}) - cotire_target(${_target} LANGUAGES ${_option_LANGUAGES} CONFIGURATIONS ${_option_CONFIGURATIONS}) - else() - message (WARNING "cotire: ${_target} is not a target.") - endif() - endforeach() - foreach (_target ${_targets}) - if (TARGET ${_target}) - cotire_target_link_libraries(${_target}) - endif() - endforeach() -endfunction() - -if (CMAKE_SCRIPT_MODE_FILE) - - # cotire is being run in script mode - # locate -P on command args - set (COTIRE_ARGC -1) - foreach (_index RANGE ${CMAKE_ARGC}) - if (COTIRE_ARGC GREATER -1) - set (COTIRE_ARGV${COTIRE_ARGC} "${CMAKE_ARGV${_index}}") - math (EXPR COTIRE_ARGC "${COTIRE_ARGC} + 1") - elseif ("${CMAKE_ARGV${_index}}" STREQUAL "-P") - set (COTIRE_ARGC 0) - endif() - endforeach() - - # include target script if available - if ("${COTIRE_ARGV2}" MATCHES "\\.cmake$") - # the included target scripts sets up additional variables relating to the target (e.g., COTIRE_TARGET_SOURCES) - include("${COTIRE_ARGV2}") - endif() - - if (COTIRE_DEBUG) - message (STATUS "${COTIRE_ARGV0} ${COTIRE_ARGV1} ${COTIRE_ARGV2} ${COTIRE_ARGV3} ${COTIRE_ARGV4} ${COTIRE_ARGV5}") - endif() - - if (NOT COTIRE_BUILD_TYPE) - set (COTIRE_BUILD_TYPE "None") - endif() - string (TOUPPER "${COTIRE_BUILD_TYPE}" _upperConfig) - set (_includeDirs ${COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig}}) - set (_systemIncludeDirs ${COTIRE_TARGET_SYSTEM_INCLUDE_DIRECTORIES_${_upperConfig}}) - set (_compileDefinitions ${COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}}) - set (_compileFlags ${COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}}) - # check if target has been cotired for actual build type COTIRE_BUILD_TYPE - list (FIND COTIRE_TARGET_CONFIGURATION_TYPES "${COTIRE_BUILD_TYPE}" _index) - if (_index GREATER -1) - set (_sources ${COTIRE_TARGET_SOURCES}) - set (_sourcesDefinitions ${COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig}}) - else() - if (COTIRE_DEBUG) - message (STATUS "COTIRE_BUILD_TYPE=${COTIRE_BUILD_TYPE} not cotired (${COTIRE_TARGET_CONFIGURATION_TYPES})") - endif() - set (_sources "") - set (_sourcesDefinitions "") - endif() - set (_targetPreUndefs ${COTIRE_TARGET_PRE_UNDEFS}) - set (_targetPostUndefs ${COTIRE_TARGET_POST_UNDEFS}) - set (_sourcesPreUndefs ${COTIRE_TARGET_SOURCES_PRE_UNDEFS}) - set (_sourcesPostUndefs ${COTIRE_TARGET_SOURCES_POST_UNDEFS}) - - if ("${COTIRE_ARGV1}" STREQUAL "unity") - - if (XCODE) - # executing pre-build action under Xcode, check dependency on target script - set (_dependsOption DEPENDS "${COTIRE_ARGV2}") - else() - # executing custom command, no need to re-check for dependencies - set (_dependsOption "") - endif() - - cotire_select_unity_source_files("${COTIRE_ARGV3}" _sources ${_sources}) - - cotire_generate_unity_source( - "${COTIRE_ARGV3}" ${_sources} - LANGUAGE "${COTIRE_TARGET_LANGUAGE}" - SOURCES_COMPILE_DEFINITIONS ${_sourcesDefinitions} - PRE_UNDEFS ${_targetPreUndefs} - POST_UNDEFS ${_targetPostUndefs} - SOURCES_PRE_UNDEFS ${_sourcesPreUndefs} - SOURCES_POST_UNDEFS ${_sourcesPostUndefs} - ${_dependsOption}) - - elseif ("${COTIRE_ARGV1}" STREQUAL "prefix") - - if (XCODE) - # executing pre-build action under Xcode, check dependency on unity file and prefix dependencies - set (_dependsOption DEPENDS "${COTIRE_ARGV4}" ${COTIRE_TARGET_PREFIX_DEPENDS}) - else() - # executing custom command, no need to re-check for dependencies - set (_dependsOption "") - endif() - - set (_files "") - foreach (_index RANGE 4 ${COTIRE_ARGC}) - if (COTIRE_ARGV${_index}) - list (APPEND _files "${COTIRE_ARGV${_index}}") - endif() - endforeach() - - cotire_generate_prefix_header( - "${COTIRE_ARGV3}" ${_files} - COMPILER_LAUNCHER "${COTIRE_TARGET_${COTIRE_TARGET_LANGUAGE}_COMPILER_LAUNCHER}" - COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}" - COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1} - COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}" - COMPILER_VERSION "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}" - LANGUAGE "${COTIRE_TARGET_LANGUAGE}" - IGNORE_PATH "${COTIRE_TARGET_IGNORE_PATH};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH}" - INCLUDE_PATH ${COTIRE_TARGET_INCLUDE_PATH} - IGNORE_EXTENSIONS "${CMAKE_${COTIRE_TARGET_LANGUAGE}_SOURCE_FILE_EXTENSIONS};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS}" - INCLUDE_PRIORITY_PATH ${COTIRE_TARGET_INCLUDE_PRIORITY_PATH} - INCLUDE_DIRECTORIES ${_includeDirs} - SYSTEM_INCLUDE_DIRECTORIES ${_systemIncludeDirs} - COMPILE_DEFINITIONS ${_compileDefinitions} - COMPILE_FLAGS ${_compileFlags} - ${_dependsOption}) - - elseif ("${COTIRE_ARGV1}" STREQUAL "precompile") - - set (_files "") - foreach (_index RANGE 5 ${COTIRE_ARGC}) - if (COTIRE_ARGV${_index}) - list (APPEND _files "${COTIRE_ARGV${_index}}") - endif() - endforeach() - - cotire_precompile_prefix_header( - "${COTIRE_ARGV3}" "${COTIRE_ARGV4}" "${COTIRE_ARGV5}" - COMPILER_LAUNCHER "${COTIRE_TARGET_${COTIRE_TARGET_LANGUAGE}_COMPILER_LAUNCHER}" - COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}" - COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1} - COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}" - COMPILER_VERSION "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}" - LANGUAGE "${COTIRE_TARGET_LANGUAGE}" - INCLUDE_DIRECTORIES ${_includeDirs} - SYSTEM_INCLUDE_DIRECTORIES ${_systemIncludeDirs} - COMPILE_DEFINITIONS ${_compileDefinitions} - COMPILE_FLAGS ${_compileFlags}) - - elseif ("${COTIRE_ARGV1}" STREQUAL "combine") - - if (COTIRE_TARGET_LANGUAGE) - set (_combinedFile "${COTIRE_ARGV3}") - set (_startIndex 4) - else() - set (_combinedFile "${COTIRE_ARGV2}") - set (_startIndex 3) - endif() - set (_files "") - foreach (_index RANGE ${_startIndex} ${COTIRE_ARGC}) - if (COTIRE_ARGV${_index}) - list (APPEND _files "${COTIRE_ARGV${_index}}") - endif() - endforeach() - - if (XCODE) - # executing pre-build action under Xcode, check dependency on files to be combined - set (_dependsOption DEPENDS ${_files}) - else() - # executing custom command, no need to re-check for dependencies - set (_dependsOption "") - endif() - - if (COTIRE_TARGET_LANGUAGE) - cotire_generate_unity_source( - "${_combinedFile}" ${_files} - LANGUAGE "${COTIRE_TARGET_LANGUAGE}" - ${_dependsOption}) - else() - cotire_generate_unity_source("${_combinedFile}" ${_files} ${_dependsOption}) - endif() - - elseif ("${COTIRE_ARGV1}" STREQUAL "cleanup") - - cotire_cleanup("${COTIRE_ARGV2}" "${COTIRE_ARGV3}" "${COTIRE_ARGV4}") - - else() - message (FATAL_ERROR "cotire: unknown command \"${COTIRE_ARGV1}\".") - endif() - -else() - - # cotire is being run in include mode - # set up all variable and property definitions - - if (NOT DEFINED COTIRE_DEBUG_INIT) - if (DEFINED COTIRE_DEBUG) - set (COTIRE_DEBUG_INIT ${COTIRE_DEBUG}) - else() - set (COTIRE_DEBUG_INIT FALSE) - endif() - endif() - option (COTIRE_DEBUG "Enable cotire debugging output?" ${COTIRE_DEBUG_INIT}) - - if (NOT DEFINED COTIRE_VERBOSE_INIT) - if (DEFINED COTIRE_VERBOSE) - set (COTIRE_VERBOSE_INIT ${COTIRE_VERBOSE}) - else() - set (COTIRE_VERBOSE_INIT FALSE) - endif() - endif() - option (COTIRE_VERBOSE "Enable cotire verbose output?" ${COTIRE_VERBOSE_INIT}) - - set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS "inc;inl;ipp" CACHE STRING - "Ignore headers with the listed file extensions from the generated prefix header.") - - set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH "" CACHE STRING - "Ignore headers from these directories when generating the prefix header.") - - set (COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS "m;mm" CACHE STRING - "Ignore sources with the listed file extensions from the generated unity source.") - - set (COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES "2" CACHE STRING - "Minimum number of sources in target required to enable use of precompiled header.") - - if (NOT DEFINED COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT) - if (DEFINED COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES) - set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT ${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES}) - elseif ("${CMAKE_GENERATOR}" MATCHES "JOM|Ninja|Visual Studio") - # enable parallelization for generators that run multiple jobs by default - set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT "-j") - else() - set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT "0") - endif() - endif() - set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT}" CACHE STRING - "Maximum number of source files to include in a single unity source file.") - - if (NOT COTIRE_PREFIX_HEADER_FILENAME_SUFFIX) - set (COTIRE_PREFIX_HEADER_FILENAME_SUFFIX "_prefix") - endif() - if (NOT COTIRE_UNITY_SOURCE_FILENAME_SUFFIX) - set (COTIRE_UNITY_SOURCE_FILENAME_SUFFIX "_unity") - endif() - if (NOT COTIRE_INTDIR) - set (COTIRE_INTDIR "cotire") - endif() - if (NOT COTIRE_PCH_ALL_TARGET_NAME) - set (COTIRE_PCH_ALL_TARGET_NAME "all_pch") - endif() - if (NOT COTIRE_UNITY_BUILD_ALL_TARGET_NAME) - set (COTIRE_UNITY_BUILD_ALL_TARGET_NAME "all_unity") - endif() - if (NOT COTIRE_CLEAN_ALL_TARGET_NAME) - set (COTIRE_CLEAN_ALL_TARGET_NAME "clean_cotire") - endif() - if (NOT COTIRE_CLEAN_TARGET_SUFFIX) - set (COTIRE_CLEAN_TARGET_SUFFIX "_clean_cotire") - endif() - if (NOT COTIRE_PCH_TARGET_SUFFIX) - set (COTIRE_PCH_TARGET_SUFFIX "_pch") - endif() - if (MSVC) - # MSVC default PCH memory scaling factor of 100 percent (75 MB) is too small for template heavy C++ code - # use a bigger default factor of 170 percent (128 MB) - if (NOT DEFINED COTIRE_PCH_MEMORY_SCALING_FACTOR) - set (COTIRE_PCH_MEMORY_SCALING_FACTOR "170") - endif() - endif() - if (NOT COTIRE_UNITY_BUILD_TARGET_SUFFIX) - set (COTIRE_UNITY_BUILD_TARGET_SUFFIX "_unity") - endif() - if (NOT DEFINED COTIRE_TARGETS_FOLDER) - set (COTIRE_TARGETS_FOLDER "cotire") - endif() - if (NOT DEFINED COTIRE_UNITY_OUTPUT_DIRECTORY) - if ("${CMAKE_GENERATOR}" MATCHES "Ninja") - # generated Ninja build files do not work if the unity target produces the same output file as the cotired target - set (COTIRE_UNITY_OUTPUT_DIRECTORY "unity") - else() - set (COTIRE_UNITY_OUTPUT_DIRECTORY "") - endif() - endif() - - # define cotire cache variables - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH" - BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." - FULL_DOCS - "The variable can be set to a semicolon separated list of include directories." - "If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header." - "If not defined, defaults to empty list." - ) - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS" - BRIEF_DOCS "Ignore includes with the listed file extensions from the generated prefix header." - FULL_DOCS - "The variable can be set to a semicolon separated list of file extensions." - "If a header file extension matches one in the list, it will be excluded from the generated prefix header." - "Includes with an extension in CMAKE__SOURCE_FILE_EXTENSIONS are always ignored." - "If not defined, defaults to inc;inl;ipp." - ) - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS" - BRIEF_DOCS "Exclude sources with the listed file extensions from the generated unity source." - FULL_DOCS - "The variable can be set to a semicolon separated list of file extensions." - "If a source file extension matches one in the list, it will be excluded from the generated unity source file." - "Source files with an extension in CMAKE__IGNORE_EXTENSIONS are always excluded." - "If not defined, defaults to m;mm." - ) - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES" - BRIEF_DOCS "Minimum number of sources in target required to enable use of precompiled header." - FULL_DOCS - "The variable can be set to an integer > 0." - "If a target contains less than that number of source files, cotire will not enable the use of the precompiled header for the target." - "If not defined, defaults to 2." - ) - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES" - BRIEF_DOCS "Maximum number of source files to include in a single unity source file." - FULL_DOCS - "This may be set to an integer >= 0." - "If 0, cotire will only create a single unity source file." - "If a target contains more than that number of source files, cotire will create multiple unity source files for it." - "Can be set to \"-j\" to optimize the count of unity source files for the number of available processor cores." - "Can be set to \"-j jobs\" to optimize the number of unity source files for the given number of simultaneous jobs." - "Is used to initialize the target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES." - "Defaults to \"-j\" for the generators Visual Studio, JOM or Ninja. Defaults to 0 otherwise." - ) - - # define cotire directory properties - - define_property( - DIRECTORY PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" - BRIEF_DOCS "Modify build command of cotired targets added in this directory to make use of the generated precompiled header." - FULL_DOCS - "See target property COTIRE_ENABLE_PRECOMPILED_HEADER." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_ADD_UNITY_BUILD" - BRIEF_DOCS "Add a new target that performs a unity build for cotired targets added in this directory." - FULL_DOCS - "See target property COTIRE_ADD_UNITY_BUILD." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_ADD_CLEAN" - BRIEF_DOCS "Add a new target that cleans all cotire generated files for cotired targets added in this directory." - FULL_DOCS - "See target property COTIRE_ADD_CLEAN." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" - BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." - FULL_DOCS - "See target property COTIRE_PREFIX_HEADER_IGNORE_PATH." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" - BRIEF_DOCS "Honor headers from these directories when generating the prefix header." - FULL_DOCS - "See target property COTIRE_PREFIX_HEADER_INCLUDE_PATH." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH" - BRIEF_DOCS "Header paths matching one of these directories are put at the top of the prefix header." - FULL_DOCS - "See target property COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each source file." - FULL_DOCS - "See target property COTIRE_UNITY_SOURCE_PRE_UNDEFS." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each source file." - FULL_DOCS - "See target property COTIRE_UNITY_SOURCE_POST_UNDEFS." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" - BRIEF_DOCS "Maximum number of source files to include in a single unity source file." - FULL_DOCS - "See target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_UNITY_LINK_LIBRARIES_INIT" - BRIEF_DOCS "Define strategy for setting up the unity target's link libraries." - FULL_DOCS - "See target property COTIRE_UNITY_LINK_LIBRARIES_INIT." - ) - - # define cotire target properties - - define_property( - TARGET PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" INHERITED - BRIEF_DOCS "Modify this target's build command to make use of the generated precompiled header." - FULL_DOCS - "If this property is set to TRUE, cotire will modify the build command to make use of the generated precompiled header." - "Irrespective of the value of this property, cotire will setup custom commands to generate the unity source and prefix header for the target." - "For makefile based generators cotire will also set up a custom target to manually invoke the generation of the precompiled header." - "The target name will be set to this target's name with the suffix _pch appended." - "Inherited from directory." - "Defaults to TRUE." - ) - - define_property( - TARGET PROPERTY "COTIRE_ADD_UNITY_BUILD" INHERITED - BRIEF_DOCS "Add a new target that performs a unity build for this target." - FULL_DOCS - "If this property is set to TRUE, cotire creates a new target of the same type that uses the generated unity source file instead of the target sources." - "Most of the relevant target properties will be copied from this target to the new unity build target." - "Target dependencies and linked libraries have to be manually set up for the new unity build target." - "The unity target name will be set to this target's name with the suffix _unity appended." - "Inherited from directory." - "Defaults to TRUE." - ) - - define_property( - TARGET PROPERTY "COTIRE_ADD_CLEAN" INHERITED - BRIEF_DOCS "Add a new target that cleans all cotire generated files for this target." - FULL_DOCS - "If this property is set to TRUE, cotire creates a new target that clean all files (unity source, prefix header, precompiled header)." - "The clean target name will be set to this target's name with the suffix _clean_cotire appended." - "Inherited from directory." - "Defaults to FALSE." - ) - - define_property( - TARGET PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" INHERITED - BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." - FULL_DOCS - "The property can be set to a list of directories." - "If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header." - "Inherited from directory." - "If not set, this property is initialized to \${CMAKE_SOURCE_DIR};\${CMAKE_BINARY_DIR}." - ) - - define_property( - TARGET PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" INHERITED - BRIEF_DOCS "Honor headers from these directories when generating the prefix header." - FULL_DOCS - "The property can be set to a list of directories." - "If a header file is found in one of these directories or sub-directories, it will be included in the generated prefix header." - "If a header file is both selected by COTIRE_PREFIX_HEADER_IGNORE_PATH and COTIRE_PREFIX_HEADER_INCLUDE_PATH," - "the option which yields the closer relative path match wins." - "Inherited from directory." - "If not set, this property is initialized to the empty list." - ) - - define_property( - TARGET PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH" INHERITED - BRIEF_DOCS "Header paths matching one of these directories are put at the top of prefix header." - FULL_DOCS - "The property can be set to a list of directories." - "Header file paths matching one of these directories will be inserted at the beginning of the generated prefix header." - "Header files are sorted according to the order of the directories in the property." - "If not set, this property is initialized to the empty list." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" INHERITED - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each target source file." - FULL_DOCS - "This may be set to a semicolon-separated list of preprocessor symbols." - "cotire will add corresponding #undef directives to the generated unit source file before each target source file." - "Inherited from directory." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" INHERITED - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each target source file." - FULL_DOCS - "This may be set to a semicolon-separated list of preprocessor symbols." - "cotire will add corresponding #undef directives to the generated unit source file after each target source file." - "Inherited from directory." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" INHERITED - BRIEF_DOCS "Maximum number of source files to include in a single unity source file." - FULL_DOCS - "This may be set to an integer > 0." - "If a target contains more than that number of source files, cotire will create multiple unity build files for it." - "If not set, cotire will only create a single unity source file." - "Inherited from directory." - "Defaults to empty." - ) - - define_property( - TARGET PROPERTY "COTIRE__UNITY_SOURCE_INIT" - BRIEF_DOCS "User provided unity source file to be used instead of the automatically generated one." - FULL_DOCS - "If set, cotire will only add the given file(s) to the generated unity source file." - "If not set, cotire will add all the target source files to the generated unity source file." - "The property can be set to a user provided unity source file." - "Defaults to empty." - ) - - define_property( - TARGET PROPERTY "COTIRE__PREFIX_HEADER_INIT" - BRIEF_DOCS "User provided prefix header file to be used instead of the automatically generated one." - FULL_DOCS - "If set, cotire will add the given header file(s) to the generated prefix header file." - "If not set, cotire will generate a prefix header by tracking the header files included by the unity source file." - "The property can be set to a user provided prefix header file (e.g., stdafx.h)." - "Defaults to empty." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_LINK_LIBRARIES_INIT" INHERITED - BRIEF_DOCS "Define strategy for setting up unity target's link libraries." - FULL_DOCS - "If this property is empty or set to NONE, the generated unity target's link libraries have to be set up manually." - "If this property is set to COPY, the unity target's link libraries will be copied from this target." - "If this property is set to COPY_UNITY, the unity target's link libraries will be copied from this target with considering existing unity targets." - "Inherited from directory." - "Defaults to empty." - ) - - define_property( - TARGET PROPERTY "COTIRE__UNITY_SOURCE" - BRIEF_DOCS "Read-only property. The generated unity source file(s)." - FULL_DOCS - "cotire sets this property to the path of the generated single computation unit source file for the target." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE__PREFIX_HEADER" - BRIEF_DOCS "Read-only property. The generated prefix header file." - FULL_DOCS - "cotire sets this property to the full path of the generated language prefix header for the target." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE__PRECOMPILED_HEADER" - BRIEF_DOCS "Read-only property. The generated precompiled header file." - FULL_DOCS - "cotire sets this property to the full path of the generated language precompiled header binary for the target." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_TARGET_NAME" - BRIEF_DOCS "The name of the generated unity build target corresponding to this target." - FULL_DOCS - "This property can be set to the desired name of the unity target that will be created by cotire." - "If not set, the unity target name will be set to this target's name with the suffix _unity appended." - "After this target has been processed by cotire, the property is set to the actual name of the generated unity target." - "Defaults to empty string." - ) - - # define cotire source properties - - define_property( - SOURCE PROPERTY "COTIRE_EXCLUDED" - BRIEF_DOCS "Do not modify source file's build command." - FULL_DOCS - "If this property is set to TRUE, the source file's build command will not be modified to make use of the precompiled header." - "The source file will also be excluded from the generated unity source file." - "Source files that have their COMPILE_FLAGS property set will be excluded by default." - "Defaults to FALSE." - ) - - define_property( - SOURCE PROPERTY "COTIRE_DEPENDENCY" - BRIEF_DOCS "Add this source file to dependencies of the automatically generated prefix header file." - FULL_DOCS - "If this property is set to TRUE, the source file is added to dependencies of the generated prefix header file." - "If the file is modified, cotire will re-generate the prefix header source upon build." - "Defaults to FALSE." - ) - - define_property( - SOURCE PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of this source file." - FULL_DOCS - "This may be set to a semicolon-separated list of preprocessor symbols." - "cotire will add corresponding #undef directives to the generated unit source file before this file is included." - "Defaults to empty string." - ) - - define_property( - SOURCE PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of this source file." - FULL_DOCS - "This may be set to a semicolon-separated list of preprocessor symbols." - "cotire will add corresponding #undef directives to the generated unit source file after this file is included." - "Defaults to empty string." - ) - - define_property( - SOURCE PROPERTY "COTIRE_START_NEW_UNITY_SOURCE" - BRIEF_DOCS "Start a new unity source file which includes this source file as the first one." - FULL_DOCS - "If this property is set to TRUE, cotire will complete the current unity file and start a new one." - "The new unity source file will include this source file as the first one." - "This property essentially works as a separator for unity source files." - "Defaults to FALSE." - ) - - define_property( - SOURCE PROPERTY "COTIRE_TARGET" - BRIEF_DOCS "Read-only property. Mark this source file as cotired for the given target." - FULL_DOCS - "cotire sets this property to the name of target, that the source file's build command has been altered for." - "Defaults to empty string." - ) - - message (STATUS "cotire ${COTIRE_CMAKE_MODULE_VERSION} loaded.") - -endif() diff --git a/configurator/CMakeLists.txt b/configurator/CMakeLists.txt index ffdc1d0d9..6c1b4a7fc 100644 --- a/configurator/CMakeLists.txt +++ b/configurator/CMakeLists.txt @@ -1,20 +1,50 @@ -INCLUDE(BuildApplication) -INCLUDE(WindowsBuildHelpers) +include(BuildVeyonApplication) +include(WindowsBuildHelpers) -FILE(GLOB configurator_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h) -FILE(GLOB configurator_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/*.ui) -SET(configurator_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/resources/configurator.qrc) +build_veyon_application(veyon-configurator + src/AccessControlPage.cpp + src/AccessControlPage.h + src/AccessControlPage.ui + src/AccessControlRuleEditDialog.cpp + src/AccessControlRuleEditDialog.h + src/AccessControlRuleEditDialog.ui + src/AccessControlRuleListModel.cpp + src/AccessControlRuleListModel.h + src/AccessControlRulesTestDialog.cpp + src/AccessControlRulesTestDialog.h + src/AccessControlRulesTestDialog.ui + src/AuthenticationPage.cpp + src/AuthenticationPage.h + src/AuthenticationPageTab.cpp + src/AuthenticationPageTab.h + src/AuthenticationPageTab.ui + src/AuthenticationPage.ui + src/GeneralConfigurationPage.cpp + src/GeneralConfigurationPage.h + src/GeneralConfigurationPage.ui + src/main.cpp + src/MainWindow.cpp + src/MainWindow.h + src/MainWindow.ui + src/MasterConfigurationPage.cpp + src/MasterConfigurationPage.h + src/MasterConfigurationPage.ui + src/NetworkObjectDirectoryConfigurationPage.cpp + src/NetworkObjectDirectoryConfigurationPage.h + src/NetworkObjectDirectoryConfigurationPage.ui + src/NetworkObjectDirectoryConfigurationPageTab.cpp + src/NetworkObjectDirectoryConfigurationPageTab.h + src/NetworkObjectDirectoryConfigurationPageTab.ui + src/ServiceConfigurationPage.cpp + src/ServiceConfigurationPage.h + src/ServiceConfigurationPage.ui + resources/configurator.qrc + ) -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src) -BUILD_APPLICATION(veyon-configurator ${configurator_SOURCES} ${configurator_INCLUDES} ${configurator_RESOURCES}) -TARGET_LINK_LIBRARIES(veyon-configurator veyon-core) +add_windows_resource(veyon-configurator) +make_graphical_app(veyon-configurator) -ADD_WINDOWS_RESOURCE(veyon-configurator) -MAKE_GRAPHICAL_APP(veyon-configurator) - -IF(VEYON_BUILD_LINUX) - XDG_INSTALL(${CMAKE_CURRENT_BINARY_DIR}/data/veyon-configurator.desktop ${CMAKE_CURRENT_SOURCE_DIR}/data/veyon-configurator.xpm ${CMAKE_CURRENT_SOURCE_DIR}/data/veyon-configurator.png ${CMAKE_CURRENT_SOURCE_DIR}/data/veyon-configurator.svg) - INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/data/io.veyon.veyon-configurator.policy DESTINATION ${CMAKE_INSTALL_PREFIX}/share/polkit-1/actions) -ENDIF() - -COTIRE_VEYON(veyon-configurator) +if(VEYON_BUILD_LINUX) + xdg_install(${CMAKE_CURRENT_BINARY_DIR}/data/veyon-configurator.desktop ${CMAKE_CURRENT_SOURCE_DIR}/data/veyon-configurator.xpm ${CMAKE_CURRENT_SOURCE_DIR}/data/veyon-configurator.png ${CMAKE_CURRENT_SOURCE_DIR}/data/veyon-configurator.svg) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/data/io.veyon.veyon-configurator.policy DESTINATION ${CMAKE_INSTALL_PREFIX}/share/polkit-1/actions) +endif() diff --git a/configurator/data/io.veyon.veyon-configurator.policy.in b/configurator/data/io.veyon.veyon-configurator.policy.in index 90aeaf953..666777343 100644 --- a/configurator/data/io.veyon.veyon-configurator.policy.in +++ b/configurator/data/io.veyon.veyon-configurator.policy.in @@ -7,6 +7,8 @@ Veyon Configurator Authentication is required to run the Veyon Configurator + Für die Ausführung des Veyon Configurators ist eine Authentifizierung erforderlich + Для запуска Veyon Configurator необходимо выполнить аутентификацию veyon-configurator auth_admin_keep diff --git a/configurator/data/veyon-configurator.desktop.in b/configurator/data/veyon-configurator.desktop.in index 28d9246ba..c830090de 100644 --- a/configurator/data/veyon-configurator.desktop.in +++ b/configurator/data/veyon-configurator.desktop.in @@ -7,5 +7,7 @@ Terminal=false Name=Veyon Configurator Comment=Configuration tool for Veyon (Virtual Eye On Networks) Comment[de]=Einrichtungswerkzeug für Veyon (Virtual Eye On Networks) +Comment[ru]=Конфигуратор программы Veyon (Virtual Eye On Networks) +Comment[pt]=Ferramenta de configuração do Veyon (Virtual Eye On Networks) Categories=Qt;Education;Network;Settings;System;RemoteAccess; Keywords=classroom,control,computer,room,lab,monitoring,teacher,student,settings,configuration diff --git a/configurator/resources/configurator.qrc b/configurator/resources/configurator.qrc index b8952fb1e..0aeb83023 100644 --- a/configurator/resources/configurator.qrc +++ b/configurator/resources/configurator.qrc @@ -2,12 +2,6 @@ veyon-configurator.png help-about.png - media-playback-start.png - media-playback-stop.png - go-up.png - go-down.png - go-next.png - go-previous.png network-vpn.png configure-shortcuts.png application-x-ms-dos-executable.png @@ -16,5 +10,6 @@ vcs-normal.png vcs-removed.png access-rule-ask.png + network-object-directory.png diff --git a/configurator/resources/go-down.png b/configurator/resources/go-down.png deleted file mode 100644 index 669597803..000000000 Binary files a/configurator/resources/go-down.png and /dev/null differ diff --git a/configurator/resources/go-next.png b/configurator/resources/go-next.png deleted file mode 100644 index e129c2ad5..000000000 Binary files a/configurator/resources/go-next.png and /dev/null differ diff --git a/configurator/resources/go-previous.png b/configurator/resources/go-previous.png deleted file mode 100644 index 4e0882a88..000000000 Binary files a/configurator/resources/go-previous.png and /dev/null differ diff --git a/configurator/resources/go-up.png b/configurator/resources/go-up.png deleted file mode 100644 index 60f5c1491..000000000 Binary files a/configurator/resources/go-up.png and /dev/null differ diff --git a/configurator/resources/media-playback-start.png b/configurator/resources/media-playback-start.png deleted file mode 100644 index 1a5aa9e3b..000000000 Binary files a/configurator/resources/media-playback-start.png and /dev/null differ diff --git a/configurator/resources/media-playback-stop.png b/configurator/resources/media-playback-stop.png deleted file mode 100644 index 5d0113ad1..000000000 Binary files a/configurator/resources/media-playback-stop.png and /dev/null differ diff --git a/plugins/builtindirectory/builtindirectory.png b/configurator/resources/network-object-directory.png similarity index 100% rename from plugins/builtindirectory/builtindirectory.png rename to configurator/resources/network-object-directory.png diff --git a/configurator/src/AccessControlPage.cpp b/configurator/src/AccessControlPage.cpp index 80d26a34b..8088977ee 100644 --- a/configurator/src/AccessControlPage.cpp +++ b/configurator/src/AccessControlPage.cpp @@ -1,7 +1,7 @@ /* * AccessControlPage.cpp - implementation of the access control page * - * Copyright (c) 2016-2019 Tobias Junghans + * Copyright (c) 2016-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -36,29 +36,14 @@ #include "ui_AccessControlPage.h" -AccessControlPage::AccessControlPage() : - ConfigurationPage(), +AccessControlPage::AccessControlPage( QWidget* parent ) : + ConfigurationPage( parent ), ui(new Ui::AccessControlPage), m_accessControlRulesModel( this ), m_accessControlRulesTestDialog( this ) { ui->setupUi(this); - if( VeyonCore::userGroupsBackendManager().accessControlBackend() == nullptr ) - { - QMessageBox::critical( this, - tr( "Missing user groups backend" ), - tr( "No default user groups plugin was found. " - "Please check your installation!" ) ); - qFatal( "AccessControlPage: missing default user groups backend" ); - } - - const auto backends = VeyonCore::userGroupsBackendManager().availableBackends(); - for( auto it = backends.constBegin(), end = backends.constEnd(); it != end; ++it ) - { - ui->accessControlUserGroupsBackend->addItem( it.value(), it.key() ); - } - ui->accessControlRulesView->setModel( &m_accessControlRulesModel ); updateAccessGroupsLists(); @@ -78,7 +63,31 @@ void AccessControlPage::resetWidgets() { FOREACH_VEYON_ACCESS_CONTROL_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY); + if (VeyonCore::config().isAccessControlRulesProcessingEnabled() == false && + VeyonCore::config().isAccessRestrictedToUserGroups() == false) + { + ui->skipAccessControl->setChecked(true); + } + m_accessGroups = VeyonCore::config().authorizedUserGroups(); + auto cleanedUpAccessGroups = m_accessGroups; + + const auto availableGroups = VeyonCore::userGroupsBackendManager().configuredBackend()-> + userGroups(VeyonCore::config().useDomainUserGroups()); + + const auto accessGroupNotAvailable = [&availableGroups](const QString& group) { + return availableGroups.contains(group) == false; + }; +#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0) + cleanedUpAccessGroups.removeIf(accessGroupNotAvailable); +#else + cleanedUpAccessGroups.erase(std::remove_if(cleanedUpAccessGroups.begin(), cleanedUpAccessGroups.end(), accessGroupNotAvailable), cleanedUpAccessGroups.end()); +#endif + if (m_accessGroups != cleanedUpAccessGroups) + { + m_accessGroups = cleanedUpAccessGroups; + VeyonCore::config().setAuthorizedUserGroups(m_accessGroups); + } updateAccessGroupsLists(); updateAccessControlRules(); @@ -95,8 +104,6 @@ void AccessControlPage::connectWidgetsToProperties() void AccessControlPage::applyConfiguration() { - VeyonCore::userGroupsBackendManager().reloadConfiguration(); - resetWidgets(); } @@ -142,8 +149,10 @@ void AccessControlPage::updateAccessGroupsLists() ui->allGroupsList->clear(); ui->accessGroupsList->clear(); - const auto backend = VeyonCore::userGroupsBackendManager().accessControlBackend(); - const auto groups = backend->userGroups( VeyonCore::config().domainGroupsForAccessControlEnabled() ); + VeyonCore::userGroupsBackendManager().reloadConfiguration(); + + const auto groups = VeyonCore::userGroupsBackendManager().configuredBackend()-> + userGroups(VeyonCore::config().useDomainUserGroups()); for( const auto& group : groups ) { @@ -252,8 +261,13 @@ void AccessControlPage::moveAccessControlRuleUp() void AccessControlPage::testUserGroupsAccessControl() { - QString username = QInputDialog::getText( this, tr( "Enter username" ), - tr( "Please enter a user login name whose access permissions to test:" ) ); + const auto username = QInputDialog::getText( this, tr( "Enter username" ), + tr( "Please enter a user login name whose access permissions to test:" ) ); + + if (username.isEmpty()) + { + return; + } if( AccessControlProvider().processAuthorizedGroups( username ) ) { diff --git a/configurator/src/AccessControlPage.h b/configurator/src/AccessControlPage.h index 293a6d1b9..2b42c11cb 100644 --- a/configurator/src/AccessControlPage.h +++ b/configurator/src/AccessControlPage.h @@ -1,7 +1,7 @@ /* * AccessControlPage.h - header for the AccessControlPage class * - * Copyright (c) 2016-2019 Tobias Junghans + * Copyright (c) 2016-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -36,14 +36,14 @@ class AccessControlPage : public ConfigurationPage { Q_OBJECT public: - AccessControlPage(); + AccessControlPage( QWidget* parent = nullptr ); ~AccessControlPage() override; void resetWidgets() override; void connectWidgetsToProperties() override; void applyConfiguration() override; -private slots: +private Q_SLOTS: void addAccessGroup(); void removeAccessGroup(); void updateAccessGroupsLists(); diff --git a/configurator/src/AccessControlPage.ui b/configurator/src/AccessControlPage.ui index 693b4cc2d..f3df86097 100644 --- a/configurator/src/AccessControlPage.ui +++ b/configurator/src/AccessControlPage.ui @@ -18,31 +18,17 @@ Computer access control - - + + - Restrict access to members of specific user groups + Process access control rules accessControlModeGroup - - - - - - User groups backend: - - - - - - - - - + false @@ -56,17 +42,7 @@ - - - - Process access control rules - - - accessControlModeGroup - - - - + false @@ -80,7 +56,7 @@ - + Grant access to every authenticated user (default) @@ -93,11 +69,14 @@ - - + + - Enable usage of domain groups + Restrict access to members of specific user groups + + accessControlModeGroup + @@ -108,6 +87,12 @@ false + + + 16777215 + 400 + + User groups authorized for computer access @@ -173,23 +158,17 @@ - - ... - - - :/configurator/go-next.png:/configurator/go-next.png + + :/core/go-next.png:/core/go-next.png - - ... - - - :/configurator/go-previous.png:/configurator/go-previous.png + + :/core/go-previous.png:/core/go-previous.png @@ -220,30 +199,14 @@ Access control rules - - - - Qt::Vertical - - - - 20 - 88 - - - - Move selected rule up - - - - - :/configurator/go-up.png:/configurator/go-up.png + + :/core/go-up.png:/core/go-up.png @@ -304,12 +267,9 @@ Move selected rule down - - - - - :/configurator/go-down.png:/configurator/go-down.png + + :/core/go-down.png:/core/go-down.png @@ -320,6 +280,22 @@ + + + + Qt::Vertical + + + QSizePolicy::MinimumExpanding + + + + 10 + 10 + + + + @@ -344,7 +320,6 @@ - diff --git a/configurator/src/AccessControlRuleEditDialog.cpp b/configurator/src/AccessControlRuleEditDialog.cpp index 9150f0ede..9b1f43f4c 100644 --- a/configurator/src/AccessControlRuleEditDialog.cpp +++ b/configurator/src/AccessControlRuleEditDialog.cpp @@ -1,7 +1,7 @@ /* * AccessControlRuleEditDialog.cpp - dialog for editing an AccessControlRule * - * Copyright (c) 2016-2019 Tobias Junghans + * Copyright (c) 2016-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,6 +24,7 @@ #include "AccessControlRuleEditDialog.h" #include "AccessControlProvider.h" +#include "AuthenticationManager.h" #include "ui_AccessControlRuleEditDialog.h" @@ -34,29 +35,38 @@ AccessControlRuleEditDialog::AccessControlRuleEditDialog(AccessControlRule &rule m_subjectNameMap( { { AccessControlRule::Subject::AccessingUser, tr( "Accessing user" ) }, { AccessControlRule::Subject::AccessingComputer, tr( "Accessing computer" ) }, -{ AccessControlRule::Subject::LocalUser, tr( "Local (logged on) user" ) }, -{ AccessControlRule::Subject::LocalComputer, tr( "Local computer" ) }, +{ AccessControlRule::Subject::LocalUser, tr( "User being accessed" ) }, +{ AccessControlRule::Subject::LocalComputer, tr( "Computer being accessed" ) }, } ) { ui->setupUi(this); AccessControlProvider accessControlProvider; + const auto authenticationMethods = VeyonCore::authenticationManager().availableMethods(); + for( auto it = authenticationMethods.constBegin(), end = authenticationMethods.constEnd(); it != end; ++it ) + { + if( it.value().isEmpty() == false ) + { + ui->authenticationMethods->addItem( it.value(), it.key() ); + } + } + // populate user subject combobox - ui->isMemberOfGroupSubjectComboBox->addItem( m_subjectNameMap[AccessControlRule::Subject::AccessingUser], + ui->isMemberOfGroupSubject->addItem( m_subjectNameMap[AccessControlRule::Subject::AccessingUser], static_cast( AccessControlRule::Subject::AccessingUser ) ); - ui->isMemberOfGroupSubjectComboBox->addItem( m_subjectNameMap[AccessControlRule::Subject::LocalUser], + ui->isMemberOfGroupSubject->addItem( m_subjectNameMap[AccessControlRule::Subject::LocalUser], static_cast( AccessControlRule::Subject::LocalUser ) ); // populate computer subject comboboxes - ui->isAtLocationSubjectComboBox->addItem( m_subjectNameMap[AccessControlRule::Subject::AccessingComputer], + ui->isAtLocationSubject->addItem( m_subjectNameMap[AccessControlRule::Subject::AccessingComputer], static_cast( AccessControlRule::Subject::AccessingComputer ) ); - ui->isAtLocationSubjectComboBox->addItem( m_subjectNameMap[AccessControlRule::Subject::LocalComputer], + ui->isAtLocationSubject->addItem( m_subjectNameMap[AccessControlRule::Subject::LocalComputer], static_cast( AccessControlRule::Subject::LocalComputer ) ); // populate groups and locations comboboxes - ui->groupsComboBox->addItems( accessControlProvider.userGroups() ); - ui->locationsComboBox->addItems( accessControlProvider.locations() ); + ui->groups->addItems( accessControlProvider.userGroups() ); + ui->locations->addItems( accessControlProvider.locations() ); // load general settings ui->ruleNameLineEdit->setText( rule.name() ); @@ -64,25 +74,40 @@ AccessControlRuleEditDialog::AccessControlRuleEditDialog(AccessControlRule &rule // load general condition processing settings ui->ignoreConditionsCheckBox->setChecked( rule.areConditionsIgnored() ); - ui->invertConditionsCheckBox->setChecked( rule.areConditionsInverted() ); // load condition states - ui->isMemberOfGroupCheckBox->setChecked( rule.isConditionEnabled( AccessControlRule::Condition::MemberOfUserGroup ) ); - ui->hasCommonGroupsCheckBox->setChecked( rule.isConditionEnabled( AccessControlRule::Condition::GroupsInCommon ) ); - ui->isAtLocationCheckBox->setChecked( rule.isConditionEnabled( AccessControlRule::Condition::LocatedAt ) ); - ui->hasCommonLocationsCheckBox->setChecked( rule.isConditionEnabled( AccessControlRule::Condition::SameLocation ) ); - ui->isLocalHostAccessCheckBox->setChecked( rule.isConditionEnabled( AccessControlRule::Condition::AccessFromLocalHost ) ); - ui->isLocalUserAccessCheckBox->setChecked( rule.isConditionEnabled( AccessControlRule::Condition::AccessFromLocalUser ) ); - ui->isSameUserAccessCheckBox->setChecked( rule.isConditionEnabled( AccessControlRule::Condition::AccessFromAlreadyConnectedUser ) ); - ui->noUserLoggedOnCheckBox->setChecked( rule.isConditionEnabled( AccessControlRule::Condition::NoUserLoggedOn ) ); + const auto loadCondition = [&rule]( QCheckBox* checkBox, + QComboBox* comboBox, + AccessControlRule::Condition condition ) + { + checkBox->setChecked( rule.isConditionEnabled( condition ) ); + comboBox->setCurrentIndex( rule.isConditionInverted( condition ) ? 1 : 0 ); + }; + + // load condition settings + loadCondition ( ui->isAuthenticatedViaMethod, ui->invertIsAuthenticatedViaMethod, AccessControlRule::Condition::AuthenticationMethod ); + loadCondition ( ui->isMemberOfGroup, ui->invertIsMemberOfGroup, AccessControlRule::Condition::MemberOfGroup ); + loadCondition ( ui->hasCommonGroups, ui->invertHasCommonGroups, AccessControlRule::Condition::GroupsInCommon ); + loadCondition ( ui->isAtLocation, ui->invertIsAtLocation, AccessControlRule::Condition::LocatedAt ); + loadCondition ( ui->hasCommonLocations, ui->invertHasCommonLocations, AccessControlRule::Condition::LocationsInCommon ); + loadCondition ( ui->isLocalHostAccess, ui->invertIsLocalHostAccess, AccessControlRule::Condition::AccessFromLocalHost ); + loadCondition ( ui->isSameUserAccess, ui->invertIsSameUserAccess, AccessControlRule::Condition::AccessFromSameUser ); + loadCondition ( ui->isUserConnected, ui->invertIsUserConnected, AccessControlRule::Condition::AccessFromAlreadyConnectedUser ); + loadCondition ( ui->isAccessedUserLoggedInLocally, ui->invertIsAccessedUserLoggedInLocally, AccessControlRule::Condition::AccessedUserLoggedInLocally ); + loadCondition ( ui->isNoUserLoggedInLocally, ui->invertIsNoUserLoggedInLocally, AccessControlRule::Condition::NoUserLoggedInLocally ); + loadCondition ( ui->isNoUserLoggedInRemotely, ui->invertIsNoUserLoggedInRemotely, AccessControlRule::Condition::NoUserLoggedInRemotely ); + loadCondition ( ui->isUserSession, ui->invertIsUserSession, AccessControlRule::Condition::UserSession ); + loadCondition(ui->computerAlreadyBeingAccessed, ui->invertComputerAlreadyBeingAccessed, AccessControlRule::Condition::ComputerAlreadyBeingAccessed); // load selected condition subjects - ui->isMemberOfGroupSubjectComboBox->setCurrentText( m_subjectNameMap.value( rule.subject( AccessControlRule::Condition::MemberOfUserGroup ) ) ); - ui->isAtLocationSubjectComboBox->setCurrentText( m_subjectNameMap.value( rule.subject( AccessControlRule::Condition::LocatedAt ) ) ); + ui->isMemberOfGroupSubject->setCurrentText( m_subjectNameMap.value( rule.subject( AccessControlRule::Condition::MemberOfGroup ) ) ); + ui->isAtLocationSubject->setCurrentText( m_subjectNameMap.value( rule.subject( AccessControlRule::Condition::LocatedAt ) ) ); // load condition arguments - ui->groupsComboBox->setCurrentText( rule.argument( AccessControlRule::Condition::MemberOfUserGroup ) ); - ui->locationsComboBox->setCurrentText( rule.argument( AccessControlRule::Condition::LocatedAt ) ); + ui->authenticationMethods->setCurrentText( authenticationMethods.value( + Plugin::Uid{ rule.argument( AccessControlRule::Condition::AuthenticationMethod ) } ) ); + ui->groups->setCurrentText( rule.argument( AccessControlRule::Condition::MemberOfGroup ) ); + ui->locations->setCurrentText( rule.argument( AccessControlRule::Condition::LocatedAt ) ); // load action ui->actionNoneRadioButton->setChecked( rule.action() == AccessControlRule::Action::None ); @@ -108,46 +133,51 @@ void AccessControlRuleEditDialog::accept() // save general condition processing settings m_rule.setConditionsIgnored( ui->ignoreConditionsCheckBox->isChecked() ); - m_rule.setConditionsInverted( ui->invertConditionsCheckBox->isChecked() ); // save conditions m_rule.clearParameters(); + const auto saveCondition = [this]( QCheckBox* checkBox, + QComboBox* comboBox, + AccessControlRule::Condition condition ) + { + m_rule.setConditionEnabled( condition, checkBox->isChecked() ); + m_rule.setConditionInverted( condition, comboBox->currentIndex() > 0 ); + }; + + // authentication method + saveCondition( ui->isAuthenticatedViaMethod, ui->invertIsAuthenticatedViaMethod, AccessControlRule::Condition::AuthenticationMethod ); + m_rule.setArgument( AccessControlRule::Condition::AuthenticationMethod, + VeyonCore::formattedUuid( ui->authenticationMethods->currentData().toUuid() ) ); + // member of user group - m_rule.setConditionEnabled( AccessControlRule::Condition::MemberOfUserGroup, - ui->isMemberOfGroupCheckBox->isChecked() ); - m_rule.setSubject( AccessControlRule::Condition::MemberOfUserGroup, - m_subjectNameMap.key( ui->isMemberOfGroupSubjectComboBox->currentText() ) ); - m_rule.setArgument( AccessControlRule::Condition::MemberOfUserGroup, - ui->groupsComboBox->currentText() ); + saveCondition( ui->isMemberOfGroup, ui->invertIsMemberOfGroup, AccessControlRule::Condition::MemberOfGroup ); + m_rule.setSubject( AccessControlRule::Condition::MemberOfGroup, + m_subjectNameMap.key( ui->isMemberOfGroupSubject->currentText() ) ); + m_rule.setArgument( AccessControlRule::Condition::MemberOfGroup, ui->groups->currentText() ); // common groups - m_rule.setConditionEnabled( AccessControlRule::Condition::GroupsInCommon, - ui->hasCommonGroupsCheckBox->isChecked() ); + saveCondition( ui->hasCommonGroups, ui->invertHasCommonGroups, AccessControlRule::Condition::GroupsInCommon ); // located at - m_rule.setConditionEnabled( AccessControlRule::Condition::LocatedAt, - ui->isAtLocationCheckBox->isChecked() ); + saveCondition( ui->isAtLocation, ui->invertIsAtLocation, AccessControlRule::Condition::LocatedAt ); m_rule.setSubject( AccessControlRule::Condition::LocatedAt, - m_subjectNameMap.key( ui->isAtLocationSubjectComboBox->currentText() ) ); - m_rule.setArgument( AccessControlRule::Condition::LocatedAt, - ui->locationsComboBox->currentText() ); + m_subjectNameMap.key( ui->isAtLocationSubject->currentText() ) ); + m_rule.setArgument( AccessControlRule::Condition::LocatedAt, ui->locations->currentText() ); // same location - m_rule.setConditionEnabled( AccessControlRule::Condition::SameLocation, - ui->hasCommonLocationsCheckBox->isChecked() ); - - m_rule.setConditionEnabled( AccessControlRule::Condition::AccessFromLocalHost, - ui->isLocalHostAccessCheckBox->isChecked() ); + saveCondition( ui->hasCommonLocations, ui->invertHasCommonLocations, AccessControlRule::Condition::LocationsInCommon ); - m_rule.setConditionEnabled( AccessControlRule::Condition::AccessFromLocalUser, - ui->isLocalUserAccessCheckBox->isChecked() ); + saveCondition( ui->isLocalHostAccess, ui->invertIsLocalHostAccess, AccessControlRule::Condition::AccessFromLocalHost ); + saveCondition( ui->isSameUserAccess, ui->invertIsSameUserAccess, AccessControlRule::Condition::AccessFromSameUser ); + saveCondition( ui->isUserConnected, ui->invertIsUserConnected, AccessControlRule::Condition::AccessFromAlreadyConnectedUser ); + saveCondition( ui->isAccessedUserLoggedInLocally, ui->invertIsAccessedUserLoggedInLocally, AccessControlRule::Condition::AccessedUserLoggedInLocally ); - m_rule.setConditionEnabled( AccessControlRule::Condition::AccessFromAlreadyConnectedUser, - ui->isSameUserAccessCheckBox->isChecked() ); + saveCondition( ui->isNoUserLoggedInLocally, ui->invertIsNoUserLoggedInLocally, AccessControlRule::Condition::NoUserLoggedInLocally ); + saveCondition( ui->isNoUserLoggedInRemotely, ui->invertIsNoUserLoggedInRemotely, AccessControlRule::Condition::NoUserLoggedInRemotely ); + saveCondition( ui->isUserSession, ui->invertIsUserSession, AccessControlRule::Condition::UserSession ); - m_rule.setConditionEnabled( AccessControlRule::Condition::NoUserLoggedOn, - ui->noUserLoggedOnCheckBox->isChecked() ); + saveCondition(ui->computerAlreadyBeingAccessed, ui->invertComputerAlreadyBeingAccessed, AccessControlRule::Condition::ComputerAlreadyBeingAccessed); // save action if( ui->actionAllowRadioButton->isChecked() ) diff --git a/configurator/src/AccessControlRuleEditDialog.h b/configurator/src/AccessControlRuleEditDialog.h index a0eafc416..86fbe55ce 100644 --- a/configurator/src/AccessControlRuleEditDialog.h +++ b/configurator/src/AccessControlRuleEditDialog.h @@ -1,7 +1,7 @@ /* * AccessControlRuleEditDialog.h - dialog for editing an AccessControlRule * - * Copyright (c) 2016-2019 Tobias Junghans + * Copyright (c) 2016-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/configurator/src/AccessControlRuleEditDialog.ui b/configurator/src/AccessControlRuleEditDialog.ui index 50da4cc22..cd771c877 100644 --- a/configurator/src/AccessControlRuleEditDialog.ui +++ b/configurator/src/AccessControlRuleEditDialog.ui @@ -12,13 +12,6 @@ General - - - - enter a short name for the rule here - - - @@ -26,13 +19,6 @@ - - - - enter a description for the rule here - - - @@ -40,10 +26,17 @@ - - - - Invert all conditions ("is/has" interpreted as "is/has not") + + + + enter a description for the rule here + + + + + + + enter a short name for the rule here @@ -62,141 +55,432 @@ Conditions - - - - - false - - - true - - - QComboBox::AdjustToContents - - + + + + + + + + + + + + + + false + + + QComboBox::AdjustToContents + + + + + + + false + + + + is member of group + + + + + is not member of group + + + + + + + + false + + + true + + + QComboBox::AdjustToContents + + + + - - - - is member of group - - + + + + + + + + + + + + + false + + + QComboBox::AdjustToContents + + + + + + + false + + + + is located at + + + + + is not located at + + + + + + + + false + + + true + + + QComboBox::AdjustToContents + + + + - - - - - - + + + + + + + 0 + 0 + + + + Accessing computer and local computer + + + + + + + false + + + + are located at the same location + + + + + are not located the same location + + + + + - - - - false - - - QComboBox::AdjustToContents - - + + + + + + Accessing computer + + + + + + + false + + + + is local computer + + + + + is not local computer + + + + + - - - - - true - - - - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. - - - true - - + + + + + + Accessing user + + + + + + + false + + + + is authenticated via + + + + + is not authenticated via + + + + + + + + false + + + + - - - - - 0 - 0 - - - - Accessing computer and local computer are at the same location - - + + + + + + Accessing user + + + + + + + false + + + + has one or more groups in common with user being accessed + + + + + has no groups in common with user being accessed + + + + + - - - - No user logged on - - + + + + + + Accessing user + + + + + + + false + + + + 0 + 0 + + + + + equals user being accessed + + + + + is different from user being accessed + + + + + - - - - is located at - - + + + + + + Accessing user + + + + + + + false + + + + is already connected + + + + + is not connected + + + + + - - - - false - - - QComboBox::AdjustToContents - - + + + + + + User being accessed + + + + + + + false + + + + is logged in locally + + + + + is logged in remotely + + + + + - - - - false - - - true - - - QComboBox::AdjustToContents - - + + + + + + + + + false + + + + No user is logged in locally + + + + + One or multiple users are logged in locally + + + + + - - - - - - + + + + + + + + + false + + + + No user is logged in remotely + + + + + One or multiple users are logged in remotely + + + + + - - - - Accessing computer is localhost - - + + + + + + + + + false + + + + Session being accessed is a user session + + + + + Session being accessed is a login screen + + + + + - - - - Accessing user has one or more groups in common with local (logged on) user - - + + + + + + + + + false + + + + Local computer is already being accessed + + + + + Local computer is not yet being accessed + + + + + - - - - Accessing user is logged on user + + + + + true + - - - - - Accessing user is already connected + If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. + + + true @@ -274,19 +558,35 @@ ruleNameLineEdit ruleDescriptionLineEdit ignoreConditionsCheckBox - invertConditionsCheckBox - isMemberOfGroupCheckBox - isMemberOfGroupSubjectComboBox - groupsComboBox - isAtLocationCheckBox - isAtLocationSubjectComboBox - locationsComboBox - hasCommonLocationsCheckBox - isLocalHostAccessCheckBox - hasCommonGroupsCheckBox - isLocalUserAccessCheckBox - isSameUserAccessCheckBox - noUserLoggedOnCheckBox + isMemberOfGroup + isMemberOfGroupSubject + invertIsMemberOfGroup + groups + isAtLocation + isAtLocationSubject + invertIsAtLocation + locations + hasCommonLocations + invertHasCommonLocations + isLocalHostAccess + invertIsLocalHostAccess + isAuthenticatedViaMethod + invertIsAuthenticatedViaMethod + authenticationMethods + hasCommonGroups + invertHasCommonGroups + isSameUserAccess + invertIsSameUserAccess + isUserConnected + invertIsUserConnected + isAccessedUserLoggedInLocally + invertIsAccessedUserLoggedInLocally + isNoUserLoggedInLocally + invertIsNoUserLoggedInLocally + isNoUserLoggedInRemotely + invertIsNoUserLoggedInRemotely + isUserSession + invertIsUserSession actionAllowRadioButton actionDenyRadioButton actionAskForPermissionRadioButton @@ -327,9 +627,9 @@ - isMemberOfGroupCheckBox + isMemberOfGroup toggled(bool) - groupsComboBox + groups setEnabled(bool) @@ -343,9 +643,9 @@ - isAtLocationCheckBox + isAtLocation toggled(bool) - locationsComboBox + locations setEnabled(bool) @@ -359,9 +659,9 @@ - isMemberOfGroupCheckBox + isMemberOfGroup toggled(bool) - isMemberOfGroupSubjectComboBox + isMemberOfGroupSubject setEnabled(bool) @@ -375,9 +675,9 @@ - isAtLocationCheckBox + isAtLocation toggled(bool) - isAtLocationSubjectComboBox + isAtLocationSubject setEnabled(bool) @@ -407,18 +707,226 @@ - ignoreConditionsCheckBox + isAuthenticatedViaMethod toggled(bool) - invertConditionsCheckBox - setDisabled(bool) + authenticationMethods + setEnabled(bool) - 548 - 179 + 212 + 306 - 548 - 225 + 665 + 306 + + + + + isMemberOfGroup + toggled(bool) + invertIsMemberOfGroup + setEnabled(bool) + + + 39 + 307 + + + 408 + 307 + + + + + isAtLocation + toggled(bool) + invertIsAtLocation + setEnabled(bool) + + + 39 + 352 + + + 444 + 352 + + + + + hasCommonLocations + toggled(bool) + invertHasCommonLocations + setEnabled(bool) + + + 224 + 397 + + + 550 + 397 + + + + + isLocalHostAccess + toggled(bool) + invertIsLocalHostAccess + setEnabled(bool) + + + 136 + 442 + + + 417 + 442 + + + + + isAuthenticatedViaMethod + toggled(bool) + invertIsAuthenticatedViaMethod + setEnabled(bool) + + + 112 + 487 + + + 294 + 487 + + + + + hasCommonGroups + toggled(bool) + invertHasCommonGroups + setEnabled(bool) + + + 112 + 532 + + + 381 + 532 + + + + + isSameUserAccess + toggled(bool) + invertIsSameUserAccess + setEnabled(bool) + + + 112 + 577 + + + 381 + 577 + + + + + isUserConnected + toggled(bool) + invertIsUserConnected + setEnabled(bool) + + + 112 + 622 + + + 381 + 622 + + + + + isNoUserLoggedInLocally + toggled(bool) + invertIsNoUserLoggedInLocally + setEnabled(bool) + + + 39 + 667 + + + 492 + 667 + + + + + isNoUserLoggedInRemotely + toggled(bool) + invertIsNoUserLoggedInRemotely + setEnabled(bool) + + + 39 + 712 + + + 492 + 712 + + + + + isAccessedUserLoggedInLocally + toggled(bool) + invertIsAccessedUserLoggedInLocally + setEnabled(bool) + + + 137 + 665 + + + 590 + 665 + + + + + isUserSession + toggled(bool) + invertIsUserSession + setEnabled(bool) + + + 39 + 761 + + + 492 + 761 + + + + + computerAlreadyBeingAccessed + toggled(bool) + invertComputerAlreadyBeingAccessed + setEnabled(bool) + + + 28 + 585 + + + 334 + 585 diff --git a/configurator/src/AccessControlRuleListModel.cpp b/configurator/src/AccessControlRuleListModel.cpp index 53bc9c4a6..3c23d0fe3 100644 --- a/configurator/src/AccessControlRuleListModel.cpp +++ b/configurator/src/AccessControlRuleListModel.cpp @@ -1,7 +1,7 @@ /* * AccessControlRuleListModel.cpp - data model for access control rules * - * Copyright (c) 2016 Tobias Junghans + * Copyright (c) 2016-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -71,9 +71,9 @@ int AccessControlRuleListModel::rowCount(const QModelIndex &parent) const QVariant AccessControlRuleListModel::data(const QModelIndex &index, int role) const { - if (!index.isValid() || index.row() > rowCount() ) + if ( index.isValid() == false || index.row() > rowCount() ) { - return QVariant(); + return {}; } const AccessControlRule& rule = m_accessControlRules[index.row()]; @@ -97,5 +97,5 @@ QVariant AccessControlRuleListModel::data(const QModelIndex &index, int role) co return rule.description(); } - return QVariant(); + return {}; } diff --git a/configurator/src/AccessControlRuleListModel.h b/configurator/src/AccessControlRuleListModel.h index 753a915fc..70eca6d47 100644 --- a/configurator/src/AccessControlRuleListModel.h +++ b/configurator/src/AccessControlRuleListModel.h @@ -1,7 +1,7 @@ /* * AccessControlRuleListModel.h - data model for access control rules * - * Copyright (c) 2016 Tobias Junghans + * Copyright (c) 2016-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/configurator/src/AccessControlRulesTestDialog.cpp b/configurator/src/AccessControlRulesTestDialog.cpp index bdbe2031f..e59cb4c5d 100644 --- a/configurator/src/AccessControlRulesTestDialog.cpp +++ b/configurator/src/AccessControlRulesTestDialog.cpp @@ -1,7 +1,7 @@ /* * AccessControlRulesTestDialog.cpp - dialog for testing access control rules * - * Copyright (c) 2016-2019 Tobias Junghans + * Copyright (c) 2016-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,6 +26,7 @@ #include "AccessControlRulesTestDialog.h" #include "AccessControlProvider.h" +#include "AuthenticationManager.h" #include "HostAddress.h" #include "PlatformUserFunctions.h" @@ -40,6 +41,15 @@ AccessControlRulesTestDialog::AccessControlRulesTestDialog(QWidget *parent) : ui->localUserLineEdit->setText( VeyonCore::platform().userFunctions().currentUser() ); ui->localComputerLineEdit->setText( HostAddress::localFQDN() ); + + const auto authenticationMethods = VeyonCore::authenticationManager().availableMethods(); + for( auto it = authenticationMethods.constBegin(), end = authenticationMethods.constEnd(); it != end; ++it ) + { + if( it.value().isEmpty() == false ) + { + ui->authenticationMethodsComboBox->addItem( it.value(), it.key() ); + } + } } @@ -62,15 +72,19 @@ int AccessControlRulesTestDialog::exec() void AccessControlRulesTestDialog::accept() { - const auto result = - AccessControlProvider().processAccessControlRules( ui->accessingUserLineEdit->text(), - ui->accessingComputerLineEdit->text(), - ui->localUserLineEdit->text(), - ui->localComputerLineEdit->text(), - ui->connectedUsersLineEdit->text().split( QLatin1Char(',') ) ); + const auto result = AccessControlProvider{} + .processAccessControlRules( ui->accessingUserLineEdit->text(), + ui->accessingComputerLineEdit->text(), + ui->localUserLineEdit->text(), + ui->localComputerLineEdit->text(), + ui->connectedUsersLineEdit->text().isEmpty() ? + QStringList() + : + ui->connectedUsersLineEdit->text().split(QLatin1Char(',')), + Plugin::Uid{ui->authenticationMethodsComboBox->currentData().toString()} ); QString resultText; - switch( result ) + switch (result ? result->action() : AccessControlRule::Action::None) { case AccessControlRule::Action::Allow: resultText = tr( "The access in the given scenario is allowed." ); @@ -82,7 +96,7 @@ void AccessControlRulesTestDialog::accept() resultText = tr( "The access in the given scenario needs permission of the logged on user." ); break; default: - resultText = tr( "ERROR: Unknown action" ); + resultText = tr("There is no matching rule with a valid action. The access is therefore denied."); break; } diff --git a/configurator/src/AccessControlRulesTestDialog.h b/configurator/src/AccessControlRulesTestDialog.h index 9ce1718f5..04ac2edc7 100644 --- a/configurator/src/AccessControlRulesTestDialog.h +++ b/configurator/src/AccessControlRulesTestDialog.h @@ -1,7 +1,7 @@ /* * AccessControlRulesTestDialog.h - dialog for testing access control rules * - * Copyright (c) 2016-2019 Tobias Junghans + * Copyright (c) 2016-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/configurator/src/AccessControlRulesTestDialog.ui b/configurator/src/AccessControlRulesTestDialog.ui index 2b72abff8..e5ce866bb 100644 --- a/configurator/src/AccessControlRulesTestDialog.ui +++ b/configurator/src/AccessControlRulesTestDialog.ui @@ -6,26 +6,20 @@ Access control rules test - - - - Qt::Horizontal - - - QDialogButtonBox::Close|QDialogButtonBox::Ok + + + + Local user: - - - - - - - - - - Accessing user: + + + + + 300 + 0 + @@ -43,45 +37,68 @@ - - - - - 0 - 0 - - + + + + + + + + - Please enter the following user and computer information in order to test the configured ruleset. - - - true + Connected users: - - + + + + + - Local user: + Accessing user: - - - - - + + + + Qt::Orientation::Horizontal + + + QDialogButtonBox::StandardButton::Close|QDialogButtonBox::StandardButton::Ok + + - - + + - Connected users: + Please enter the following user and computer information in order to test the configured ruleset. + + + true + + + + Authentication method + + + + + + + + + + + + diff --git a/configurator/src/AuthenticationPage.cpp b/configurator/src/AuthenticationPage.cpp new file mode 100644 index 000000000..cbc2cfef2 --- /dev/null +++ b/configurator/src/AuthenticationPage.cpp @@ -0,0 +1,121 @@ +/* + * AuthenticationPage.cpp - implementation of the AuthenticationPage class + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include + +#include "AuthenticationManager.h" +#include "AuthenticationPage.h" +#include "AuthenticationPageTab.h" +#include "VeyonCore.h" + +#include "ui_AuthenticationPage.h" + +AuthenticationPage::AuthenticationPage( QWidget* parent ) : + ConfigurationPage( parent ), + ui(new Ui::AuthenticationPage) +{ + ui->setupUi(this); + + populateTabs(); +} + + + +AuthenticationPage::~AuthenticationPage() +{ + delete ui; +} + + + +void AuthenticationPage::resetWidgets() +{ + populateTabs(); + connectWidgetsToProperties(); +} + + + +void AuthenticationPage::connectWidgetsToProperties() +{ + for( auto it = m_tabs.constBegin(), end = m_tabs.constEnd(); it != end; ++it ) + { + const auto plugin = it.key(); + const auto checkBox = it.value()->enabledCheckBox(); + + connect( checkBox, &QCheckBox::toggled, this, [plugin, checkBox]() { + VeyonCore::authenticationManager().setEnabled( plugin, checkBox->isChecked() ); + } ); + } +} + + + +void AuthenticationPage::applyConfiguration() +{ +} + + + +void AuthenticationPage::populateTabs() +{ + qDeleteAll(m_tabs); + + const auto plugins = VeyonCore::authenticationManager().plugins(); + for( auto* plugin : plugins ) + { + if( plugin->authenticationMethodName().isEmpty() ) + { + continue; + } + + auto widget = plugin->createAuthenticationConfigurationWidget(); + + auto tab = new AuthenticationPageTab; + + tab->enabledCheckBox()->setChecked( VeyonCore::authenticationManager().isEnabled( plugin ) ); + connect( tab->testButton(), &QPushButton::clicked, this, [this, plugin]() { + if( plugin->initializeCredentials() && plugin->checkCredentials() ) + { + QMessageBox::information( this, AuthenticationPluginInterface::authenticationTestTitle(), + tr( "Authentication is set up properly on this computer." ) ); + } + } ); + + if( widget ) + { + widget->setEnabled( tab->enabledCheckBox()->isChecked() ); + connect( tab->enabledCheckBox(), &QCheckBox::toggled, widget, &QWidget::setEnabled ); + + tab->tabLayout()->insertWidget( 1, widget ); + } + + + ui->tabWidget->addTab( tab, plugin->authenticationMethodName() ); + + m_tabs[plugin] = tab; + } +} diff --git a/configurator/src/AuthenticationPage.h b/configurator/src/AuthenticationPage.h new file mode 100644 index 000000000..47a3ee66a --- /dev/null +++ b/configurator/src/AuthenticationPage.h @@ -0,0 +1,54 @@ +/* + * AuthenticationPage.h - header for the AuthenticationPage class + * + * Copyright (c) 2016-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "ConfigurationPage.h" + +namespace Ui { +class AuthenticationPage; +} + +class AuthenticationPluginInterface; +class AuthenticationPageTab; + +class AuthenticationPage : public ConfigurationPage +{ + Q_OBJECT +public: + AuthenticationPage( QWidget* parent = nullptr ); + ~AuthenticationPage() override; + + void resetWidgets() override; + void connectWidgetsToProperties() override; + void applyConfiguration() override; + +private: + void populateTabs(); + + Ui::AuthenticationPage *ui; + + QMap m_tabs; + +}; diff --git a/configurator/src/AuthenticationPage.ui b/configurator/src/AuthenticationPage.ui new file mode 100644 index 000000000..9ca95cf98 --- /dev/null +++ b/configurator/src/AuthenticationPage.ui @@ -0,0 +1,22 @@ + + + AuthenticationPage + + + Authentication + + + + 0 + + + 0 + + + + + + + + + diff --git a/configurator/src/AuthenticationPageTab.cpp b/configurator/src/AuthenticationPageTab.cpp new file mode 100644 index 000000000..3c619ac96 --- /dev/null +++ b/configurator/src/AuthenticationPageTab.cpp @@ -0,0 +1,62 @@ +/* + * AuthenticationPageTab.cpp - implementation of the AuthenticationPageTab class + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "AuthenticationPageTab.h" + +#include "ui_AuthenticationPageTab.h" + +AuthenticationPageTab::AuthenticationPageTab( QWidget* parent ) : + QWidget( parent ), + ui(new Ui::AuthenticationPageTab) +{ + ui->setupUi(this); +} + + + +AuthenticationPageTab::~AuthenticationPageTab() +{ + delete ui; +} + + + +QBoxLayout* AuthenticationPageTab::tabLayout() const +{ + return ui->tabLayout; +} + + + +QCheckBox* AuthenticationPageTab::enabledCheckBox() const +{ + return ui->enabledCheckBox; +} + + + +QPushButton* AuthenticationPageTab::testButton() const +{ + return ui->testButton; +} diff --git a/configurator/src/AuthenticationPageTab.h b/configurator/src/AuthenticationPageTab.h new file mode 100644 index 000000000..7205ebeca --- /dev/null +++ b/configurator/src/AuthenticationPageTab.h @@ -0,0 +1,51 @@ +/* + * AuthenticationPageTab.h - header for the AuthenticationPageTab class + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +namespace Ui { +class AuthenticationPageTab; +} + +class QBoxLayout; +class QCheckBox; +class QPushButton; + +class AuthenticationPageTab : public QWidget +{ + Q_OBJECT +public: + AuthenticationPageTab( QWidget* parent = nullptr ); + ~AuthenticationPageTab() override; + + QBoxLayout* tabLayout() const; + QCheckBox* enabledCheckBox() const; + QPushButton* testButton() const; + +private: + Ui::AuthenticationPageTab *ui; + +}; diff --git a/configurator/src/AuthenticationPageTab.ui b/configurator/src/AuthenticationPageTab.ui new file mode 100644 index 000000000..3b36099ae --- /dev/null +++ b/configurator/src/AuthenticationPageTab.ui @@ -0,0 +1,89 @@ + + + AuthenticationPageTab + + + Authentication + + + + 16 + + + + + + + Enabled + + + + + + + Qt::Horizontal + + + + 80 + 20 + + + + + + + + false + + + Test + + + + :/core/dialog-ok-apply.png:/core/dialog-ok-apply.png + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 0 + 0 + + + + + + + + + + + + enabledCheckBox + toggled(bool) + testButton + setEnabled(bool) + + + 66 + 31 + + + 254 + 31 + + + + + diff --git a/configurator/src/GeneralConfigurationPage.cpp b/configurator/src/GeneralConfigurationPage.cpp index 5cf5bdf21..0dbe32db0 100644 --- a/configurator/src/GeneralConfigurationPage.cpp +++ b/configurator/src/GeneralConfigurationPage.cpp @@ -1,7 +1,7 @@ /* * GeneralConfigurationPage.cpp - configuration page with general settings * - * Copyright (c) 2016-2019 Tobias Junghans + * Copyright (c) 2016-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,42 +25,50 @@ #include #include +#include "AuthenticationCredentials.h" #include "Configuration/UiMapping.h" #include "GeneralConfigurationPage.h" #include "Filesystem.h" #include "FileSystemBrowser.h" -#include "NetworkObjectDirectoryManager.h" -#include "PasswordDialog.h" #include "PlatformFilesystemFunctions.h" -#include "PlatformUserFunctions.h" #include "PluginManager.h" #include "VeyonServiceControl.h" #include "VeyonCore.h" #include "VeyonConfiguration.h" +#include "UserGroupsBackendManager.h" #include "ui_GeneralConfigurationPage.h" -GeneralConfigurationPage::GeneralConfigurationPage() : - ConfigurationPage(), +GeneralConfigurationPage::GeneralConfigurationPage( QWidget* parent ) : + ConfigurationPage( parent ), ui(new Ui::GeneralConfigurationPage) { ui->setupUi(this); + Configuration::UiMapping::setFlags( ui->tlsConfigGroupBox, Configuration::Property::Flag::Advanced ); + + connect( ui->browseTlsCaCertificateFile, &QAbstractButton::clicked, this, [this]() { + FileSystemBrowser(FileSystemBrowser::ExistingFile, this).exec(ui->tlsCaCertificateFile); + } ); + + connect( ui->browseTlsHostCertificateFile, &QAbstractButton::clicked, this, [this]() { + FileSystemBrowser(FileSystemBrowser::ExistingFile, this).exec(ui->tlsHostCertificateFile); + } ); + + connect( ui->browseTlsHostPrivateKeyFile, &QAbstractButton::clicked, this, [this]() { + FileSystemBrowser(FileSystemBrowser::ExistingFile, this).exec(ui->tlsHostPrivateKeyFile); + } ); + // retrieve list of builtin translations and populate language combobox QStringList languages; - const auto qmFiles = QDir( VeyonCore::translationsDirectory() ).entryList( { QStringLiteral("*.qm") } ); + const auto qmFiles = QDir( VeyonCore::translationsDirectory() ).entryList( { QStringLiteral("veyon*.qm") } ); languages.reserve( qmFiles.count() ); for( const auto& qmFile : qmFiles ) { - // ignore Qt's translation files - if( qmFile.startsWith( QStringLiteral("qt") ) ) - { - continue; - } - QLocale loc( qmFile ); + QLocale loc( qmFile.split( QLatin1Char('_') ).mid( 1 ).join( QLatin1Char('_') ) ); if( loc.language() == QLocale::C ) { loc = QLocale( QLocale::English ); @@ -74,11 +82,32 @@ GeneralConfigurationPage::GeneralConfigurationPage() : ui->uiLanguage->addItems( languages ); - connect( ui->testAuthenticationButton, &QPushButton::clicked, this, &GeneralConfigurationPage::testAuthentication ); + const auto backends = VeyonCore::userGroupsBackendManager().availableBackends(); + if (backends.count() <= 0) + { + QMessageBox::critical(this, + tr("Missing user groups backend"), + tr("No user groups plugin was found. Please check your installation!")); + qFatal("GeneralConfigurationPage: missing user groups backend"); + } + + for (auto it = backends.constBegin(), end = backends.constEnd(); it != end; ++it) + { + ui->userGroupsBackend->addItem(it.value(), it.key()); + } + + connect( ui->userGroupsBackend, QOverload::of(&QComboBox::currentIndexChanged), this, [this]() { + const auto selectedBackend = ui->userGroupsBackend->currentData().toUuid(); + + ui->useDomainUserGroups->setEnabled(VeyonCore::pluginManager().find( + [&selectedBackend](const PluginInterface* plugin) { + return plugin->uid() == selectedBackend && + plugin->flags().testFlag(Plugin::ProvidesDefaultImplementation); + }) != nullptr); + }); + connect( ui->openLogFileDirectory, &QPushButton::clicked, this, &GeneralConfigurationPage::openLogFileDirectory ); connect( ui->clearLogFiles, &QPushButton::clicked, this, &GeneralConfigurationPage::clearLogFiles ); - - populateNetworkObjectDirectories(); } @@ -94,8 +123,8 @@ void GeneralConfigurationPage::resetWidgets() { FOREACH_VEYON_UI_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY); FOREACH_VEYON_LOGGING_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY); - FOREACH_VEYON_NETWORK_OBJECT_DIRECTORY_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY); - FOREACH_VEYON_AUTHENTICATION_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY); + FOREACH_VEYON_USER_GROUPS_BACKEND_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY); + FOREACH_VEYON_TLS_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY); } @@ -104,70 +133,24 @@ void GeneralConfigurationPage::connectWidgetsToProperties() { FOREACH_VEYON_UI_CONFIG_PROPERTY(CONNECT_WIDGET_TO_PROPERTY); FOREACH_VEYON_LOGGING_CONFIG_PROPERTY(CONNECT_WIDGET_TO_PROPERTY); - FOREACH_VEYON_NETWORK_OBJECT_DIRECTORY_CONFIG_PROPERTY(CONNECT_WIDGET_TO_PROPERTY); - FOREACH_VEYON_AUTHENTICATION_CONFIG_PROPERTY(CONNECT_WIDGET_TO_PROPERTY); + FOREACH_VEYON_USER_GROUPS_BACKEND_CONFIG_PROPERTY(CONNECT_WIDGET_TO_PROPERTY); + FOREACH_VEYON_TLS_CONFIG_PROPERTY(CONNECT_WIDGET_TO_PROPERTY); } void GeneralConfigurationPage::applyConfiguration() { + VeyonCore::userGroupsBackendManager().reloadConfiguration(); } -void GeneralConfigurationPage::testAuthentication() -{ - switch( VeyonCore::config().authenticationMethod() ) - { - case VeyonCore::AuthenticationMethod::LogonAuthentication: - if( testLogonAuthentication() == false ) - { - return; - } - break; - case VeyonCore::AuthenticationMethod::KeyFileAuthentication: - if( testKeyFileAuthentication() == false ) - { - return; - } - break; - } - - QMessageBox::information( this, authenticationTestTitle(), - tr( "Authentication is set up properly on this computer." ) ); -} - - - -bool GeneralConfigurationPage::testLogonAuthentication() -{ - return VeyonCore::instance()->initAuthentication() && - VeyonCore::platform().userFunctions().authenticate( VeyonCore::authenticationCredentials().logonUsername(), - VeyonCore::authenticationCredentials().logonPassword() ); -} - - - -bool GeneralConfigurationPage::testKeyFileAuthentication() -{ - if( VeyonCore::instance()->initAuthentication() == false ) - { - QMessageBox::critical( this, authenticationTestTitle(), - tr( "Authentication keys are not set up properly on this computer." ) ); - return false; - } - - return true; -} - - void GeneralConfigurationPage::openLogFileDirectory() { - FileSystemBrowser( FileSystemBrowser::ExistingDirectory ). - exec( ui->logFileDirectory ); + FileSystemBrowser(FileSystemBrowser::ExistingDirectory, this).exec(ui->logFileDirectory); } @@ -204,7 +187,11 @@ void GeneralConfigurationPage::clearLogFiles() for( const auto& f : localLogFiles ) { - if( f != QLatin1String("VeyonConfigurator.log") ) + if( f.startsWith( QLatin1String("VeyonConfigurator") ) ) + { + d.remove( f ); + } + else { success &= d.remove( f ); } @@ -236,15 +223,3 @@ void GeneralConfigurationPage::clearLogFiles() tr( "Could not remove all log files." ) ); } } - - - -void GeneralConfigurationPage::populateNetworkObjectDirectories() -{ - const auto directories = NetworkObjectDirectoryManager().availableDirectories(); - - for( auto it = directories.constBegin(), end = directories.constEnd(); it != end; ++it ) - { - ui->networkObjectDirectoryPlugin->addItem( it.value(), it.key() ); - } -} diff --git a/configurator/src/GeneralConfigurationPage.h b/configurator/src/GeneralConfigurationPage.h index f4147e6bc..93c3dd302 100644 --- a/configurator/src/GeneralConfigurationPage.h +++ b/configurator/src/GeneralConfigurationPage.h @@ -1,7 +1,7 @@ /* * GeneralConfigurationPage.h - configuration page with general settings * - * Copyright (c) 2016-2019 Tobias Junghans + * Copyright (c) 2016-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -32,7 +32,7 @@ class GeneralConfigurationPage : public ConfigurationPage { Q_OBJECT public: - GeneralConfigurationPage(); + GeneralConfigurationPage( QWidget* parent = nullptr ); ~GeneralConfigurationPage() override; void resetWidgets() override; @@ -40,20 +40,9 @@ class GeneralConfigurationPage : public ConfigurationPage void applyConfiguration() override; private: - void testAuthentication(); - bool testLogonAuthentication(); - bool testKeyFileAuthentication(); - void openLogFileDirectory(); void clearLogFiles(); - void populateNetworkObjectDirectories(); - - static QString authenticationTestTitle() - { - return tr( "Authentication test"); - } - Ui::GeneralConfigurationPage* ui; } ; diff --git a/configurator/src/GeneralConfigurationPage.ui b/configurator/src/GeneralConfigurationPage.ui index c68aa5b67..49757a5b1 100644 --- a/configurator/src/GeneralConfigurationPage.ui +++ b/configurator/src/GeneralConfigurationPage.ui @@ -2,7 +2,7 @@ GeneralConfigurationPage - + 0 @@ -15,13 +15,6 @@ User interface - - - - Language: - - - @@ -40,6 +33,13 @@ + + + + Language: + + + @@ -47,86 +47,76 @@ - - - - - - - Authentication - - - - + + - Method: + Style: - - + + - Logon authentication + Fusion - Key file authentication + Native - - + + - Test - - - - :/core/dialog-ok-apply.png:/core/dialog-ok-apply.png + Color scheme: + + + + + System + + + + + Light + + + + + Dark + + + + - + - Network object directory + User groups - + - + Backend: - + - - + + - Update interval: - - - - - - - seconds - - - 10 - - - 3600 - - - 600 + Include user groups from domain @@ -153,9 +143,6 @@ - - ... - :/core/document-open.png:/core/document-open.png @@ -325,6 +312,94 @@ + + + + TLS configuration + + + + + + Use certificate authority for TLS connections + + + + + + + false + + + + + + CA certificate file + + + + + + + + + + ... + + + + :/core/document-open.png:/core/document-open.png + + + + + + + Host certificate file + + + + + + + + + + ... + + + + :/core/document-open.png:/core/document-open.png + + + + + + + Host private key file + + + + + + + + + + ... + + + + :/core/document-open.png:/core/document-open.png + + + + + + + + + @@ -343,10 +418,9 @@ applicationName uiLanguage - authenticationMethod - testAuthenticationButton - networkObjectDirectoryPlugin - networkObjectDirectoryUpdateInterval + uiStyle + uiColorScheme + userGroupsBackend logFileDirectory openLogFileDirectory logLevel @@ -357,6 +431,13 @@ logToStdErr logToSystem clearLogFiles + tlsUseCertificateAuthority + tlsCaCertificateFile + browseTlsCaCertificateFile + tlsHostCertificateFile + browseTlsHostCertificateFile + tlsHostPrivateKeyFile + browseTlsHostPrivateKeyFile @@ -410,5 +491,21 @@ + + tlsUseCertificateAuthority + toggled(bool) + tlsCaFiles + setEnabled(bool) + + + 315 + 581 + + + 315 + 679 + + + diff --git a/configurator/src/MainWindow.cpp b/configurator/src/MainWindow.cpp index 3ce4869be..abbd61853 100644 --- a/configurator/src/MainWindow.cpp +++ b/configurator/src/MainWindow.cpp @@ -1,7 +1,7 @@ /* * MainWindow.cpp - implementation of MainWindow class * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,12 +22,16 @@ * */ +#include #include #include #include #include #include #include +#include +#include +#include #include "Configuration/JsonStore.h" #include "Configuration/UiMapping.h" @@ -49,7 +53,7 @@ MainWindow::MainWindow( QWidget* parent ) : { ui->setupUi( this ); - setWindowTitle( tr( "%1 Configurator %2" ).arg( VeyonCore::applicationName(), VeyonCore::version() ) ); + setWindowTitle( tr( "%1 Configurator %2" ).arg( VeyonCore::applicationName(), VeyonCore::versionString() ) ); loadConfigurationPagePlugins(); @@ -81,12 +85,20 @@ MainWindow::MainWindow( QWidget* parent ) : ui->viewModeStandard->setChecked( true ); connect( viewModeGroup, &QActionGroup::triggered, this, &MainWindow::updateView ); - switchToStandardView(); connect( ui->actionAboutQt, &QAction::triggered, QApplication::instance(), &QApplication::aboutQt ); connect( &VeyonCore::config(), &VeyonConfiguration::configurationChanged, this, &MainWindow::configurationChanged ); + connect( ui->configPages, &QStackedWidget::currentChanged, this, &MainWindow::updateSizes ); + + resize( ui->pageSelector->width() + ui->masterConfigurationPage->minimumSizeHint().width(), + ui->masterConfigurationPage->minimumSizeHint().height() + 100 ); + + restoreGeometry( QSettings{}.value( windowGeometryKey() ).toByteArray() ); + + updateView(); + VeyonCore::enforceBranding( this ); } @@ -122,8 +134,23 @@ void MainWindow::reset( bool onlyUI ) void MainWindow::apply() { - if( applyConfiguration() ) + const auto showError = [this](const ConfigurationManager& configurationManager) { + vCritical() << configurationManager.errorString().toUtf8().constData(); + + QMessageBox::critical(this, + tr("%1 Configurator").arg(VeyonCore::applicationName()), + configurationManager.errorString()); + + }; + + ConfigurationManager configurationManager; + if (configurationManager.saveConfiguration()) { + if (configurationManager.applyConfiguration() == false) + { + showError(configurationManager); + } + const auto pages = findChildren(); for( auto page : pages ) { @@ -133,20 +160,39 @@ void MainWindow::apply() ui->buttonBox->setEnabled( false ); m_configChanged = false; } + else + { + showError(configurationManager); + } } -void MainWindow::updateView() +void MainWindow::closeEvent( QCloseEvent* event ) { - if( ui->viewModeAdvanced->isChecked() ) - { - switchToAdvancedView(); - } - else + if( m_configChanged && + QMessageBox::question( this, tr( "Unsaved settings" ), + tr( "There are unsaved settings. Quit anyway?" ), + QMessageBox::Yes | QMessageBox::No ) != + QMessageBox::Yes ) { - switchToStandardView(); + event->ignore(); + return; } + + QSettings{}.setValue( windowGeometryKey(), saveGeometry() ); + + event->accept(); + QMainWindow::closeEvent( event ); +} + + + +void MainWindow::resizeEvent( QResizeEvent* event ) +{ + QMainWindow::resizeEvent( event ); + + updateSizes(); } @@ -182,7 +228,7 @@ void MainWindow::loadSettingsFromFile() if( !fileName.isEmpty() ) { // write current configuration to output file - Configuration::JsonStore( Configuration::JsonStore::System, fileName ).load( &VeyonCore::config() ); + Configuration::JsonStore(Configuration::JsonStore::Scope::System, fileName).load(&VeyonCore::config()); reset( true ); configurationChanged(); // give user a chance to apply possible changes } @@ -205,7 +251,7 @@ void MainWindow::saveSettingsToFile() bool configChangedPrevious = m_configChanged; // write current configuration to output file - Configuration::JsonStore( Configuration::JsonStore::System, fileName ).flush( &VeyonCore::config() ); + Configuration::JsonStore(Configuration::JsonStore::Scope::System, fileName).flush(&VeyonCore::config()); m_configChanged = configChangedPrevious; ui->buttonBox->setEnabled( m_configChanged ); @@ -235,6 +281,35 @@ void MainWindow::aboutVeyon() +void MainWindow::updateSizes() +{ + ui->configPages->setMinimumSize( ui->scrollArea->width() - ui->scrollArea->verticalScrollBar()->width(), + ui->configPages->currentWidget()->minimumSizeHint().height() ); + + ui->scrollAreaWidgetContents->setFixedSize( + ui->scrollArea->width() - ui->scrollArea->verticalScrollBar()->width(), + qMax( ui->scrollAreaWidgetContents->minimumSizeHint().height(), ui->scrollArea->contentsRect().height() ) + ); +} + + + +void MainWindow::updateView() +{ + if( ui->viewModeAdvanced->isChecked() ) + { + switchToAdvancedView(); + } + else + { + switchToStandardView(); + } + + QTimer::singleShot( 0, this, &MainWindow::updateSizes ); +} + + + void MainWindow::switchToStandardView() { const auto widgets = findChildren(); @@ -247,10 +322,6 @@ void MainWindow::switchToStandardView() { widget->hide(); } - else if( flags & Configuration::Property::Flag::Standard ) - { - widget->show(); - } else if( flags & Configuration::Property::Flag::Advanced ) { widget->hide(); @@ -300,29 +371,9 @@ void MainWindow::switchToAdvancedView() -bool MainWindow::applyConfiguration() -{ - ConfigurationManager configurationManager; - - if( configurationManager.saveConfiguration() == false || - configurationManager.applyConfiguration() == false ) - { - vCritical() << configurationManager.errorString().toUtf8().constData(); - - QMessageBox::critical( nullptr, - tr( "%1 Configurator" ).arg( VeyonCore::applicationName() ), - configurationManager.errorString() ); - return false; - } - - return true; -} - - - void MainWindow::loadConfigurationPagePlugins() { - for( auto pluginObject : qAsConst( VeyonCore::pluginManager().pluginObjects() ) ) + for( auto pluginObject : std::as_const( VeyonCore::pluginManager().pluginObjects() ) ) { auto pluginInterface = qobject_cast( pluginObject ); auto configurationPagePluginInterface = qobject_cast( pluginObject ); @@ -346,22 +397,3 @@ void MainWindow::loadConfigurationPagePlugins() ui->pageSelector->setMinimumSize( ui->pageSelector->sizeHintForColumn(0) + 3 * ui->pageSelector->spacing(), ui->pageSelector->minimumHeight() ); } - - - -void MainWindow::closeEvent( QCloseEvent *closeEvent ) -{ - if( m_configChanged && - QMessageBox::question( this, tr( "Unsaved settings" ), - tr( "There are unsaved settings. " - "Quit anyway?" ), - QMessageBox::Yes | QMessageBox::No ) != - QMessageBox::Yes ) - { - closeEvent->ignore(); - return; - } - - closeEvent->accept(); - QMainWindow::closeEvent( closeEvent ); -} diff --git a/configurator/src/MainWindow.h b/configurator/src/MainWindow.h index 1218f8d72..a0a505e57 100644 --- a/configurator/src/MainWindow.h +++ b/configurator/src/MainWindow.h @@ -1,7 +1,7 @@ /* * MainWindow.h - main window of the Veyon Configurator * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -42,9 +42,11 @@ class MainWindow : public QMainWindow void reset( bool onlyUI = false ); void apply(); - void updateView(); +protected: + void closeEvent( QCloseEvent* event ) override; + void resizeEvent( QResizeEvent* event ) override; -private slots: +private Q_SLOTS: void configurationChanged(); void resetOrApply( QAbstractButton *btn ); void loadSettingsFromFile(); @@ -52,16 +54,20 @@ private slots: void resetConfiguration(); void aboutVeyon(); - private: + static QString windowGeometryKey() + { + return QStringLiteral("Configurator/WindowGeometry"); + } + + void updateSizes(); + void updateView(); + void switchToStandardView(); void switchToAdvancedView(); - bool applyConfiguration(); void loadConfigurationPagePlugins(); - void closeEvent( QCloseEvent *closeEvent ) override; - Ui::MainWindow *ui; bool m_configChanged; diff --git a/configurator/src/MainWindow.ui b/configurator/src/MainWindow.ui index d004a4e5a..5b51924a0 100644 --- a/configurator/src/MainWindow.ui +++ b/configurator/src/MainWindow.ui @@ -10,18 +10,7 @@ :/configurator/veyon-configurator.png:/configurator/veyon-configurator.png - - - - - 0 - - - - - - - + @@ -52,7 +41,7 @@ true - 0 + -1 @@ -78,6 +67,15 @@ ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled + + + Locations & computers + + + + :/configurator/network-object-directory.png:/configurator/network-object-directory.png + + Master @@ -90,6 +88,18 @@ ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled + + + Authentication + + + + :/core/application-x-pem-key.png:/core/application-x-pem-key.png + + + ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled + + Access control @@ -104,14 +114,40 @@ - - - - QDialogButtonBox::Apply|QDialogButtonBox::Reset + + + + Qt::ScrollBarAlwaysOff - + true + + + + 0 + + + 10 + + + 0 + + + 10 + + + + + + + + + + + + + @@ -121,9 +157,27 @@ + + + + QDialogButtonBox::Apply|QDialogButtonBox::Reset + + + true + + + + + + 0 + 0 + 516 + 32 + + &File @@ -235,6 +289,12 @@
AccessControlPage.h
1 + + AuthenticationPage + QWidget +
AuthenticationPage.h
+ 1 +
GeneralConfigurationPage QWidget @@ -253,10 +313,16 @@
ServiceConfigurationPage.h
1
+ + NetworkObjectDirectoryConfigurationPage + QWidget +
NetworkObjectDirectoryConfigurationPage.h
+ 1 +
- + diff --git a/configurator/src/MasterConfigurationPage.cpp b/configurator/src/MasterConfigurationPage.cpp index 5a4e163e4..c3b302f99 100644 --- a/configurator/src/MasterConfigurationPage.cpp +++ b/configurator/src/MasterConfigurationPage.cpp @@ -1,7 +1,7 @@ /* * MasterConfigurationPage.cpp - page for configuring master application * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -35,18 +35,22 @@ #include "ui_MasterConfigurationPage.h" -MasterConfigurationPage::MasterConfigurationPage() : - ConfigurationPage(), - ui(new Ui::MasterConfigurationPage), - m_featureManager() +MasterConfigurationPage::MasterConfigurationPage( QWidget* parent ) : + ConfigurationPage( parent ), + ui(new Ui::MasterConfigurationPage) { ui->setupUi(this); - connect( ui->openUserConfigurationDirectory, &QPushButton::clicked, - this, &MasterConfigurationPage::openUserConfigurationDirectory ); + Configuration::UiMapping::setFlags(ui->advancedSettingsGroupBox, Configuration::Property::Flag::Advanced); - connect( ui->openScreenshotDirectory, &QPushButton::clicked, - this, &MasterConfigurationPage::openScreenshotDirectory ); + connect(ui->openUserConfigurationDirectory, &QPushButton::clicked, + this, &MasterConfigurationPage::openUserConfigurationDirectory); + + connect(ui->openScreenshotDirectory, &QPushButton::clicked, + this, &MasterConfigurationPage::openScreenshotDirectory); + + connect(ui->openConfigurationTemplatesDirectory, &QPushButton::clicked, + this, &MasterConfigurationPage::openConfigurationTemplatesDirectory); populateFeatureComboBox(); } @@ -122,14 +126,21 @@ void MasterConfigurationPage::disableFeature() void MasterConfigurationPage::openUserConfigurationDirectory() { - FileSystemBrowser( FileSystemBrowser::ExistingFile ).exec( ui->userConfigurationDirectory ); + FileSystemBrowser(FileSystemBrowser::ExistingDirectory, this).exec(ui->userConfigurationDirectory); } void MasterConfigurationPage::openScreenshotDirectory() { - FileSystemBrowser( FileSystemBrowser::ExistingDirectory ).exec( ui->screenshotDirectory ); + FileSystemBrowser(FileSystemBrowser::ExistingDirectory, this).exec(ui->screenshotDirectory); +} + + + +void MasterConfigurationPage::openConfigurationTemplatesDirectory() +{ + FileSystemBrowser(FileSystemBrowser::ExistingDirectory, this).exec(ui->configurationTemplatesDirectory); } @@ -139,9 +150,10 @@ void MasterConfigurationPage::populateFeatureComboBox() ui->computerDoubleClickFeature->addItem( QIcon(), tr( "" ), QUuid() ); ui->computerDoubleClickFeature->insertSeparator( ui->computerDoubleClickFeature->count() ); - for( const auto& feature : m_featureManager.features() ) + for( const auto& feature : VeyonCore::featureManager().features() ) { - if( feature.testFlag( Feature::Master ) ) + if( feature.testFlag( Feature::Flag::Master ) && + feature.testFlag( Feature::Flag::Meta ) == false ) { ui->computerDoubleClickFeature->addItem( QIcon( feature.iconUrl() ), feature.displayName(), @@ -160,15 +172,16 @@ void MasterConfigurationPage::updateFeatureLists() ui->allFeaturesListWidget->clear(); ui->disabledFeaturesListWidget->clear(); - for( const auto& feature : qAsConst( m_featureManager.features() ) ) + for( const auto& feature : std::as_const( VeyonCore::featureManager().features() ) ) { - if( feature.testFlag( Feature::Master ) == false || - feature == VeyonCore::builtinFeatures().monitoringMode().feature() ) + if( feature.testFlag( Feature::Flag::Master ) == false || + feature.testFlag( Feature::Flag::Meta ) || + feature == VeyonCore::builtinFeatures().monitoringMode().feature() ) { continue; } - QListWidgetItem* item = new QListWidgetItem( QIcon( feature.iconUrl() ), feature.displayName() ); + auto item = new QListWidgetItem( QIcon( feature.iconUrl() ), feature.displayName() ); item->setData( Qt::UserRole, feature.uid().toString() ); if( m_disabledFeatures.contains( feature.uid().toString() ) ) diff --git a/configurator/src/MasterConfigurationPage.h b/configurator/src/MasterConfigurationPage.h index f361a96ae..a4f2693da 100644 --- a/configurator/src/MasterConfigurationPage.h +++ b/configurator/src/MasterConfigurationPage.h @@ -1,7 +1,7 @@ /* * MasterConfigurationPage.h - header for the MasterConfigurationPage class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,9 +25,6 @@ #pragma once #include "ConfigurationPage.h" -#include "FeatureManager.h" - -class BuiltinFeatures; namespace Ui { class MasterConfigurationPage; @@ -37,26 +34,26 @@ class MasterConfigurationPage : public ConfigurationPage { Q_OBJECT public: - MasterConfigurationPage(); + MasterConfigurationPage( QWidget* parent = nullptr ); ~MasterConfigurationPage() override; void resetWidgets() override; void connectWidgetsToProperties() override; void applyConfiguration() override; -private slots: +private Q_SLOTS: void enableFeature(); void disableFeature(); private: void openUserConfigurationDirectory(); void openScreenshotDirectory(); + void openConfigurationTemplatesDirectory(); void populateFeatureComboBox(); void updateFeatureLists(); Ui::MasterConfigurationPage *ui; - FeatureManager m_featureManager; - QStringList m_disabledFeatures; + QStringList m_disabledFeatures{}; }; diff --git a/configurator/src/MasterConfigurationPage.ui b/configurator/src/MasterConfigurationPage.ui index 94331d68c..ceee96304 100644 --- a/configurator/src/MasterConfigurationPage.ui +++ b/configurator/src/MasterConfigurationPage.ui @@ -31,11 +31,29 @@ 10 - - + + + + + - ... + Screenshots + + + + + + + :/core/document-open.png:/core/document-open.png + + + + + + + + :/core/document-open.png:/core/document-open.png @@ -49,24 +67,18 @@ - - - - - + + - Screenshots + Configuration templates - - + + - - - - ... - + + :/core/document-open.png:/core/document-open.png @@ -82,14 +94,139 @@ User interface - - + + - Text color + Background color - + + + + + + + ms + + + 250 + + + 10000 + + + 250 + + + 1000 + + + + + + + Sort order + + + + + + + Image quality in monitoring mode + + + + + + + px + + + + + + 2 + + + 50 + + + 16 + + + + + + + Thumbnail spacing + + + + + + + Computer thumbnail caption + + + + + + + + + + + Computer and user name + + + + + Only user name + + + + + Only last part of user name + + + + + Only computer name + + + + + + + + + Highest + + + + + High + + + + + Medium + + + + + Low + + + + + Lowest + + + + + @@ -109,73 +246,175 @@ - + - Computer thumbnail caption + Thumbnail aspect ratio - - - - ms - - - 250 - - - 60000 - - - 250 - - - 1000 + + + + Thumbnail update interval - - + + + + Text color + + - - + + + + + Auto + + + + + 16:9 + + + + + 16:10 + + + + + 3:2 + + + + + 4:3 + + + - - + + - Background color + Use modern user interface (experimental) - - + + - Thumbnail update interval + Remote access image quality - - + + + + + Highest + + + + + High + + + + + Medium + + + + + Low + + + + + Lowest + + + + + + + + + + + Advanced + + + + - Sort order + Computer name source - - + + - Computer and user name + Default - Only user name + Host address - Only computer name + Session client address + + + + + Session client name + + + + + Session host name + + + + + Session metadata + + + + + Full name of user + + + + + User login name + + + + + + + + Computer UID role + + + + + + + + Default + + + + + Session meta data hash @@ -186,7 +425,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -224,9 +463,9 @@ - + - Automatically adjust computer thumbnail size + Automatically adjust computer icon size @@ -264,12 +503,19 @@ - + Hide local computer + + + + Hide local session + + + @@ -278,12 +524,19 @@ - + Hide computer filter field + + + + Always expand all locations + + + @@ -310,23 +563,30 @@
- + - + Feature on computer double click: + + + + Open feature windows on the same screen as the main window + + +
- Qt::Vertical + Qt::Orientation::Vertical @@ -367,7 +627,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -379,30 +639,24 @@ - - ... - - - :/configurator/go-next.png:/configurator/go-next.png + + :/core/go-next.png:/core/go-next.png - - ... - - - :/configurator/go-previous.png:/configurator/go-previous.png + + :/core/go-previous.png:/core/go-previous.png - Qt::Vertical + Qt::Orientation::Vertical @@ -429,23 +683,36 @@ tabWidget userConfigurationDirectory screenshotDirectory + configurationTemplatesDirectory openUserConfigurationDirectory openScreenshotDirectory + openConfigurationTemplatesDirectory + computerMonitoringImageQuality + remoteAccessImageQuality computerMonitoringUpdateInterval + computerMonitoringAspectRatio computerMonitoringBackgroundColor computerMonitoringTextColor computerDisplayRoleContent computerMonitoringSortOrder + computerMonitoringThumbnailSpacing + modernUserInterface + computerNameSource + computerUidRoleContent accessControlForMasterEnabled autoSelectCurrentLocation - autoAdjustGridSize + autoAdjustMonitoringIconSize autoOpenComputerSelectPanel showCurrentLocationOnly allowAddingHiddenLocations - localComputerHidden + hideLocalComputer + hideOwnSession hideEmptyLocations - computerFilterHidden + hideComputerFilter + expandLocations enforceSelectedModeForClients + confirmUnsafeActions + showFeatureWindowsOnSameScreen computerDoubleClickFeature allFeaturesListWidget disableFeatureButton @@ -454,7 +721,6 @@ - diff --git a/configurator/src/NetworkObjectDirectoryConfigurationPage.cpp b/configurator/src/NetworkObjectDirectoryConfigurationPage.cpp new file mode 100644 index 000000000..5f596deb1 --- /dev/null +++ b/configurator/src/NetworkObjectDirectoryConfigurationPage.cpp @@ -0,0 +1,108 @@ +/* + * NetworkObjectDirectoryConfigurationPage.cpp - implementation of the NetworkObjectDirectoryConfigurationPage class + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include + +#include "Configuration/UiMapping.h" +#include "NetworkObjectDirectoryConfigurationPage.h" +#include "NetworkObjectDirectoryConfigurationPageTab.h" +#include "NetworkObjectDirectoryManager.h" +#include "NetworkObjectDirectoryPluginInterface.h" +#include "VeyonConfiguration.h" + +#include "ui_NetworkObjectDirectoryConfigurationPage.h" + +NetworkObjectDirectoryConfigurationPage::NetworkObjectDirectoryConfigurationPage( QWidget* parent ) : + ConfigurationPage( parent ), + ui(new Ui::NetworkObjectDirectoryConfigurationPage) +{ + ui->setupUi(this); + + populateTabs(); +} + + + +NetworkObjectDirectoryConfigurationPage::~NetworkObjectDirectoryConfigurationPage() +{ + delete ui; +} + + + +void NetworkObjectDirectoryConfigurationPage::resetWidgets() +{ + FOREACH_VEYON_NETWORK_OBJECT_DIRECTORY_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY); + + for( const auto* tab : std::as_const(m_tabs) ) + { + tab->content()->resetWidgets(); + tab->enabledCheckBox()->setChecked( VeyonCore::networkObjectDirectoryManager().isEnabled( tab->plugin() ) ); + + } +} + + + +void NetworkObjectDirectoryConfigurationPage::connectWidgetsToProperties() +{ + FOREACH_VEYON_NETWORK_OBJECT_DIRECTORY_CONFIG_PROPERTY(CONNECT_WIDGET_TO_PROPERTY); + + for( const auto* tab : std::as_const(m_tabs) ) + { + const auto plugin = tab->plugin(); + const auto checkBox = tab->enabledCheckBox(); + + connect( checkBox, &QCheckBox::toggled, this, [plugin, checkBox]() { + VeyonCore::networkObjectDirectoryManager().setEnabled( plugin, checkBox->isChecked() ); + } ); + } +} + + + +void NetworkObjectDirectoryConfigurationPage::applyConfiguration() +{ + for( const auto* tab : std::as_const(m_tabs) ) + { + tab->content()->applyConfiguration(); + } +} + + + +void NetworkObjectDirectoryConfigurationPage::populateTabs() +{ + const auto plugins = VeyonCore::networkObjectDirectoryManager().plugins(); + for( auto* plugin : plugins ) + { + const auto tab = new NetworkObjectDirectoryConfigurationPageTab( plugin ); + + tab->enabledCheckBox()->setChecked( VeyonCore::networkObjectDirectoryManager().isEnabled( plugin ) ); + + ui->tabWidget->addTab( tab, tab->content()->windowTitle() ); + + m_tabs.append( tab ); + } +} diff --git a/configurator/src/NetworkObjectDirectoryConfigurationPage.h b/configurator/src/NetworkObjectDirectoryConfigurationPage.h new file mode 100644 index 000000000..a594873a6 --- /dev/null +++ b/configurator/src/NetworkObjectDirectoryConfigurationPage.h @@ -0,0 +1,54 @@ +/* + * NetworkObjectDirectoryConfigurationPage.h - header for the NetworkObjectDirectoryConfigurationPage class + * + * Copyright (c) 2016-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "ConfigurationPage.h" + +namespace Ui { +class NetworkObjectDirectoryConfigurationPage; +} + +class NetworkObjectDirectoryPluginInterface; +class NetworkObjectDirectoryConfigurationPageTab; + +class NetworkObjectDirectoryConfigurationPage : public ConfigurationPage +{ + Q_OBJECT +public: + NetworkObjectDirectoryConfigurationPage( QWidget* parent = nullptr ); + ~NetworkObjectDirectoryConfigurationPage() override; + + void resetWidgets() override; + void connectWidgetsToProperties() override; + void applyConfiguration() override; + +private: + void populateTabs(); + + Ui::NetworkObjectDirectoryConfigurationPage *ui; + + QList m_tabs; + +}; diff --git a/configurator/src/NetworkObjectDirectoryConfigurationPage.ui b/configurator/src/NetworkObjectDirectoryConfigurationPage.ui new file mode 100644 index 000000000..3d2e6b391 --- /dev/null +++ b/configurator/src/NetworkObjectDirectoryConfigurationPage.ui @@ -0,0 +1,49 @@ + + + NetworkObjectDirectoryConfigurationPage + + + Locations & computers + + + + 0 + + + 0 + + + + + + + Update interval: + + + + + + + seconds + + + 10 + + + 3600 + + + 600 + + + + + + + + + + + + + diff --git a/configurator/src/NetworkObjectDirectoryConfigurationPageTab.cpp b/configurator/src/NetworkObjectDirectoryConfigurationPageTab.cpp new file mode 100644 index 000000000..a5563310e --- /dev/null +++ b/configurator/src/NetworkObjectDirectoryConfigurationPageTab.cpp @@ -0,0 +1,59 @@ +/* + * NetworkObjectDirectoryConfigurationPageTab.cpp - implementation of the NetworkObjectDirectoryConfigurationPageTab class + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "ConfigurationPage.h" +#include "NetworkObjectDirectoryPluginInterface.h" +#include "NetworkObjectDirectoryConfigurationPageTab.h" + +#include "ui_NetworkObjectDirectoryConfigurationPageTab.h" + +NetworkObjectDirectoryConfigurationPageTab::NetworkObjectDirectoryConfigurationPageTab( + NetworkObjectDirectoryPluginInterface* plugin, QWidget* parent ) : + QWidget( parent ), + ui(new Ui::NetworkObjectDirectoryConfigurationPageTab), + m_plugin( plugin ), + m_content( m_plugin->createNetworkObjectDirectoryConfigurationPage() ) +{ + ui->setupUi(this); + + m_content->setEnabled( false ); + + connect( ui->enabledCheckBox, &QCheckBox::toggled, m_content, &QWidget::setEnabled ); + + ui->tabLayout->insertWidget( 1, m_content ); +} + + + +NetworkObjectDirectoryConfigurationPageTab::~NetworkObjectDirectoryConfigurationPageTab() +{ + delete ui; +} + + + +QCheckBox* NetworkObjectDirectoryConfigurationPageTab::enabledCheckBox() const +{ + return ui->enabledCheckBox; +} diff --git a/configurator/src/NetworkObjectDirectoryConfigurationPageTab.h b/configurator/src/NetworkObjectDirectoryConfigurationPageTab.h new file mode 100644 index 000000000..9531741a1 --- /dev/null +++ b/configurator/src/NetworkObjectDirectoryConfigurationPageTab.h @@ -0,0 +1,62 @@ +/* + * NetworkObjectDirectoryConfigurationPageTab.h - header for the NetworkObjectDirectoryConfigurationPageTab class + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +namespace Ui { +class NetworkObjectDirectoryConfigurationPageTab; +} + +class QBoxLayout; +class QCheckBox; +class QPushButton; +class ConfigurationPage; +class NetworkObjectDirectoryPluginInterface; + +class NetworkObjectDirectoryConfigurationPageTab : public QWidget +{ + Q_OBJECT +public: + NetworkObjectDirectoryConfigurationPageTab( NetworkObjectDirectoryPluginInterface* plugin, QWidget* parent = nullptr ); + ~NetworkObjectDirectoryConfigurationPageTab() override; + + QCheckBox* enabledCheckBox() const; + + NetworkObjectDirectoryPluginInterface* plugin() const + { + return m_plugin; + } + + ConfigurationPage* content() const + { + return m_content; + } + +private: + Ui::NetworkObjectDirectoryConfigurationPageTab *ui; + NetworkObjectDirectoryPluginInterface* m_plugin; + ConfigurationPage* m_content; +}; diff --git a/configurator/src/NetworkObjectDirectoryConfigurationPageTab.ui b/configurator/src/NetworkObjectDirectoryConfigurationPageTab.ui new file mode 100644 index 000000000..1b17ee536 --- /dev/null +++ b/configurator/src/NetworkObjectDirectoryConfigurationPageTab.ui @@ -0,0 +1,20 @@ + + + NetworkObjectDirectoryConfigurationPageTab + + + + 16 + + + + + Enabled + + + + + + + + diff --git a/configurator/src/ServiceConfigurationPage.cpp b/configurator/src/ServiceConfigurationPage.cpp index 175b67735..bfa8fbef7 100644 --- a/configurator/src/ServiceConfigurationPage.cpp +++ b/configurator/src/ServiceConfigurationPage.cpp @@ -1,7 +1,7 @@ /* * ServiceConfigurationPage.cpp - page for configuring service application * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,7 +25,6 @@ #include #include -#include "FileSystemBrowser.h" #include "VeyonConfiguration.h" #include "PluginManager.h" #include "ServiceConfigurationPage.h" @@ -36,14 +35,16 @@ #include "ui_ServiceConfigurationPage.h" -ServiceConfigurationPage::ServiceConfigurationPage() : - ConfigurationPage(), +ServiceConfigurationPage::ServiceConfigurationPage( QWidget* parent ) : + ConfigurationPage( parent ), ui(new Ui::ServiceConfigurationPage), m_vncServerPluginConfigurationWidget( nullptr ) { ui->setupUi(this); - Configuration::UiMapping::setFlags( ui->networkGroupBox, Configuration::Property::Flag::Advanced ); + Configuration::UiMapping::setFlags(ui->networkPortNumbersGroupBox, Configuration::Property::Flag::Advanced); + Configuration::UiMapping::setFlags(ui->miscSettingsGroupBox, Configuration::Property::Flag::Advanced); + Configuration::UiMapping::setFlags(ui->sessionMetaDataGroupBox, Configuration::Property::Flag::Advanced); updateServiceControl(); populateVncServerPluginComboBox(); @@ -82,7 +83,7 @@ void ServiceConfigurationPage::connectWidgetsToProperties() void ServiceConfigurationPage::applyConfiguration() { - VeyonServiceControl serviceControl( this ); + VeyonServiceControl serviceControl(this); if( serviceControl.isServiceRunning() && QMessageBox::question( this, tr( "Restart %1 Service" ).arg( VeyonCore::applicationName() ), @@ -91,8 +92,7 @@ void ServiceConfigurationPage::applyConfiguration() "Restart it now?" ).arg( VeyonCore::applicationName() ), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes ) == QMessageBox::Yes ) { - serviceControl.stopService(); - serviceControl.startService(); + serviceControl.restartService(); } } @@ -100,7 +100,7 @@ void ServiceConfigurationPage::applyConfiguration() void ServiceConfigurationPage::startService() { - VeyonServiceControl( this ).startService(); + VeyonServiceControl(this).startService(); updateServiceControl(); } @@ -109,7 +109,7 @@ void ServiceConfigurationPage::startService() void ServiceConfigurationPage::stopService() { - VeyonServiceControl( this ).stopService(); + VeyonServiceControl(this).stopService(); updateServiceControl(); } @@ -146,14 +146,14 @@ void ServiceConfigurationPage::updateVncServerPluginConfigurationWidget() } } - emit widgetsChanged(); + Q_EMIT widgetsChanged(); } void ServiceConfigurationPage::populateVncServerPluginComboBox() { - for( auto pluginObject : qAsConst( VeyonCore::pluginManager().pluginObjects() ) ) + for( auto pluginObject : std::as_const( VeyonCore::pluginManager().pluginObjects() ) ) { auto pluginInterface = qobject_cast( pluginObject ); auto vncServerPluginInterface = qobject_cast( pluginObject ); diff --git a/configurator/src/ServiceConfigurationPage.h b/configurator/src/ServiceConfigurationPage.h index 5c740479e..841593b4a 100644 --- a/configurator/src/ServiceConfigurationPage.h +++ b/configurator/src/ServiceConfigurationPage.h @@ -1,7 +1,7 @@ /* * ServiceConfigurationPage.h - header for the ServiceConfigurationPage class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -39,19 +39,19 @@ class ServiceConfigurationPage : public ConfigurationPage { Q_OBJECT public: - ServiceConfigurationPage(); + ServiceConfigurationPage( QWidget* parent = nullptr ); ~ServiceConfigurationPage() override; void resetWidgets() override; void connectWidgetsToProperties() override; void applyConfiguration() override; -public slots: +public Q_SLOTS: void startService(); void stopService(); -private slots: +private Q_SLOTS: void updateServiceControl(); void updateVncServerPluginConfigurationWidget(); diff --git a/configurator/src/ServiceConfigurationPage.ui b/configurator/src/ServiceConfigurationPage.ui index 635d64602..dcce5416c 100644 --- a/configurator/src/ServiceConfigurationPage.ui +++ b/configurator/src/ServiceConfigurationPage.ui @@ -5,7 +5,7 @@ Form - + 0 @@ -18,21 +18,21 @@ General - - + + - Show notification on remote connection + Show notification when an unauthorized access is blocked - - + + - Show notification when an unauthorized access is blocked + Show notification on remote connection - + Hide tray icon @@ -40,106 +40,188 @@ - - - State: - - - - - - - Start service - - - - :/configurator/media-playback-start.png:/configurator/media-playback-start.png - - - - Autostart - - + + + + + + State: + + + + + + + + true + + + + Stopped + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + Start service + + + + :/core/media-playback-start.png:/core/media-playback-start.png + + + + + + + Stop service + + + + :/core/media-playback-stop.png:/core/media-playback-stop.png + + + + + + + + + + + + Session mode + + + + - Stop service + Local session mode (single server instance for primary local session) - - - :/configurator/media-playback-stop.png:/configurator/media-playback-stop.png + + true + + sessionModeButtonGroup + - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 75 - true - + + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. - Stopped + Active session mode (single server instance for active local or remote session) + + sessionModeButtonGroup + - - + + Enabling this option will make the service launch a server process for every interactive session on a computer. Typically this is required to support terminal servers. - Multi session mode (for terminal and remote desktop servers) + Multi session mode (distinct server instance for each local and remote desktop session) + + sessionModeButtonGroup + + + + + + + Maximum session count + + + + + + + false + + + 1 + + + 1000 + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + - + - Network + Network port numbers - - - - 1024 + + + + Demo server - - 65535 + + + + + + Internal VNC server - - + + - Demo server port + Veyon server - - + + 1024 @@ -148,29 +230,28 @@ Typically this is required to support terminal servers. - - - - Feature manager port + + + + 1024 - - - - - - Primary service port + + 65535 - - - - Enable firewall exception + + + + 1024 + + + 65535 - - + + 1024 @@ -179,27 +260,40 @@ Typically this is required to support terminal servers. - - + + - Allow connections from localhost only + Feature manager - - + + + + + + + Miscellaneous settings + + + + - Internal VNC server port + Enable firewall exception - - - - 1024 + + + + Allow connections from localhost only - - 65535 + + + + + + Disable clipboard synchronization @@ -236,10 +330,77 @@ Typically this is required to support terminal servers. + + + + Session metadata + + + + + + Content + + + + + + + + 0 + 0 + + + + + None + + + + + Value of an environment variable + + + + + Value of a registry key + + + + + + + + Environment variable name + + + + + + + + + + Registry key name + + + + + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + + + + + + - Qt::Vertical + Qt::Orientation::Vertical @@ -255,20 +416,27 @@ Typically this is required to support terminal servers. isTrayIconHidden failedAuthenticationNotificationsEnabled remoteConnectionNotificationsEnabled - multiSessionModeEnabled autostartService startService stopService - primaryServicePort + localSessionModeEnabled + activeSessionModeEnabled + multiSessionModeEnabled + maximumSessionCount + veyonServerPort vncServerPort featureWorkerManagerPort demoServerPort isFirewallExceptionEnabled localConnectOnly + clipboardSynchronizationDisabled vncServerPlugin + sessionMetaDataContent + sessionMetaDataEnvironmentVariable + sessionMetaDataRegistryKey - + @@ -319,10 +487,29 @@ Typically this is required to support terminal servers. + + multiSessionModeEnabled + toggled(bool) + maximumSessionCount + setEnabled(bool) + + + 320 + 371 + + + 295 + 415 + + + updateVncServerPluginConfigurationWidget() startService() stopService() + + + diff --git a/configurator/src/main.cpp b/configurator/src/main.cpp index 5eb9f13b9..f8a8ee663 100644 --- a/configurator/src/main.cpp +++ b/configurator/src/main.cpp @@ -1,7 +1,7 @@ /* * main.cpp - main file for Veyon Configurator * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -39,12 +39,12 @@ int main( int argc, char **argv ) QApplication app( argc, argv ); - VeyonCore core( &app, QStringLiteral("Configurator") ); + VeyonCore core( &app, VeyonCore::Component::Configurator, QStringLiteral("Configurator") ); // make sure to run as admin if( qEnvironmentVariableIntValue( "VEYON_CONFIGURATOR_NO_ELEVATION" ) == 0 && VeyonCore::platform().coreFunctions().isRunningAsAdmin() == false && - app.arguments().size() <= 1 ) + QCoreApplication::arguments().size() <= 1 ) { if( VeyonCore::platform().coreFunctions().runProgramAsAdmin( QCoreApplication::applicationFilePath(), { QStringLiteral("-elevated") } ) ) diff --git a/configurator/veyon-configurator.rc.in b/configurator/veyon-configurator.rc.in index 643441c79..4128cdaed 100644 --- a/configurator/veyon-configurator.rc.in +++ b/configurator/veyon-configurator.rc.in @@ -1,11 +1,11 @@ veyonconfiguratoricon ICON data/veyon-configurator.ico #include -ID_MANIFEST RT_MANIFEST data/veyon-configurator.exe.manifest +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST data/veyon-configurator.exe.manifest VS_VERSION_INFO VERSIONINFO FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,@VERSION_BUILD@ - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGSMASK 0 FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_APP FILESUBTYPE VFT2_UNKNOWN @@ -17,11 +17,16 @@ BEGIN BEGIN VALUE "Comments", "Virtual Eye On Networks (https://veyon.io)\0" VALUE "CompanyName", "Veyon Solutions\0" + VALUE "ProductName", "Veyon\0" + VALUE "ProductVersion", "@VERSION_STRING@\0" VALUE "FileDescription", "Veyon Configurator\0" VALUE "FileVersion", "@VERSION_STRING@\0" - VALUE "LegalCopyright", "Copyright (c) 2010-2019 Tobias Junghans\0" + VALUE "LegalCopyright", "Copyright (c) 2017-2025 Veyon Solutions / Tobias Junghans\0" VALUE "OriginalFilename", "veyon-configurator.exe\0" - VALUE "ProductName", "Veyon\0" END END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04E4 + END END diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index cfe383559..20ef46e1c 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -1,63 +1,145 @@ -FILE(GLOB veyoncore_INCLUDES - ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/Configuration/*.h -) -FILE(GLOB veyoncore_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/*.ui - ${CMAKE_CURRENT_SOURCE_DIR}/src/Configuration/*.cpp -) - -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/builddata.qrc.in ${CMAKE_CURRENT_BINARY_DIR}/builddata.qrc) -SET(core_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/resources/core.qrc ${CMAKE_CURRENT_BINARY_DIR}/builddata.qrc) - -# find Qt's translation directory -IF(NOT VEYON_BUILD_WIN32) - GET_TARGET_PROPERTY(QT_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION) - EXECUTE_PROCESS(COMMAND "${QT_QMAKE_EXECUTABLE}" -query QT_INSTALL_TRANSLATIONS - OUTPUT_STRIP_TRAILING_WHITESPACE - OUTPUT_VARIABLE QT_TRANSLATIONS_DIR) - ADD_DEFINITIONS(-D'QT_TRANSLATIONS_DIR="${QT_TRANSLATIONS_DIR}"') -ENDIF() - - -SET(libvncclient_SOURCES - ${libvncserver_DIR}/libvncclient/cursor.c - ${libvncserver_DIR}/libvncclient/listen.c - ${libvncserver_DIR}/libvncclient/rfbproto.c - ${libvncserver_DIR}/libvncclient/sockets.c - ${libvncserver_DIR}/libvncclient/tls_none.c - ${libvncserver_DIR}/libvncclient/vncviewer.c - ${libvncserver_DIR}/common/d3des.c - ${libvncserver_DIR}/common/turbojpeg.c) - - -ADD_DEFINITIONS(-DBUILD_VEYON_CORE_LIBRARY) - -INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include ${libvncserver_DIR}/common/) -ADD_LIBRARY(veyon-core SHARED ${veyoncore_SOURCES} ${veyoncore_INCLUDES} ${core_RESOURCES} ${libvncclient_SOURCES}) - -TARGET_LINK_LIBRARIES(veyon-core - Qt5::Concurrent - Qt5::Gui - Qt5::Network - Qt5::Widgets - ${VEYON_DEBUG_LIBRARIES} - ${ZLIB_LIBRARIES} - ${JPEG_LIBRARIES} - ${PNG_LIBRARIES} - ${LZO_LIBRARIES} - ${QCA_LIBRARY} - ${OPENSSL_LIBRARIES} +file(GLOB veyoncore_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/*.ui + ${CMAKE_CURRENT_SOURCE_DIR}/src/Configuration/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/Configuration/*.h ) -IF(VEYON_BUILD_WIN32) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/builddata.qrc.in ${CMAKE_CURRENT_BINARY_DIR}/builddata.qrc) +set(core_RESOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/resources/core.qrc + ${CMAKE_CURRENT_BINARY_DIR}/builddata.qrc + ) + +if(NOT WITH_BUILTIN_LIBVNC) + find_package(LibVNCClient 0.9.14) +endif() + +if(LibVNCClient_FOUND) + include(CheckCSourceCompiles) + set(CMAKE_REQUIRED_LIBRARIES LibVNC::LibVNCClient) + check_c_source_compiles(" + #include + + int main() + { + rfbClient* client = rfbGetClient( 8, 3, 4 ); + client->ReadFromSocket = NULL; + client->WriteToSocket = NULL; + return 0; + } + " + LIBVNCCLIENT_SUPPORTS_CUSTOM_SOCKET_IO) + if(NOT LIBVNCCLIENT_SUPPORTS_CUSTOM_SOCKET_IO) + message(WARNING "Outdated development version of LibVNCClient found") + unset(LibVNCClient_FOUND) + endif() + unset(CMAKE_REQUIRED_LIBRARIES) +endif() + +if(LibVNCClient_FOUND) + set_property(GLOBAL PROPERTY HAVE_LIBVNCCLIENT TRUE) +else() + message(WARNING "Performing internal build of LibVNCClient which requires additional development packages") + include(LibVNCServerIntegration) + set(libvncclient_SOURCES + ${libvncserver_DIR}/src/libvncclient/cursor.c + ${libvncserver_DIR}/src/libvncclient/listen.c + ${libvncserver_DIR}/src/libvncclient/rfbclient.c + ${libvncserver_DIR}/src/libvncclient/sockets.c + ${libvncserver_DIR}/src/libvncclient/tls_openssl.c + ${libvncserver_DIR}/src/libvncclient/vncviewer.c + ${libvncserver_DIR}/src/common/crypto_openssl.c + ${libvncserver_DIR}/src/common/sockets.c + ${libvncserver_DIR}/src/common/turbojpeg.c) + + set_source_files_properties(${libvncclient_SOURCES} PROPERTIES + COMPILE_FLAGS "-Wno-unused-function -Wno-unused-variable -fvisibility=default -Wno-deprecated-declarations" + SKIP_PRECOMPILE_HEADERS TRUE) +endif() + +add_library(veyon-core SHARED ${veyoncore_SOURCES} ${core_RESOURCES} ${libvncclient_SOURCES}) + +target_compile_definitions(veyon-core PRIVATE XK_KOREAN) + +set_default_target_properties(veyon-core) + +target_compile_options(veyon-core PRIVATE -Wno-parentheses) + +target_include_directories(veyon-core PUBLIC + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/src + ${CMAKE_CURRENT_BINARY_DIR}/src + ) + +target_link_libraries(veyon-core PUBLIC + Qt${QT_MAJOR_VERSION}::Concurrent + Qt${QT_MAJOR_VERSION}::Gui + Qt${QT_MAJOR_VERSION}::Network + Qt${QT_MAJOR_VERSION}::Widgets + Qt${QT_MAJOR_VERSION}::QuickControls2 + qca-qt${QT_MAJOR_VERSION} + ) + +if(WITH_QT6) + # required by qca-qt6 + target_link_libraries(veyon-core PUBLIC Qt6::Core5Compat) +endif() + +if(WITH_TESTS) + target_link_libraries(veyon-core PUBLIC Qt${QT_MAJOR_VERSION}::Test) +endif() + +target_link_libraries(veyon-core PUBLIC OpenSSL::SSL) + +if(LibVNCClient_FOUND) + target_link_libraries(veyon-core PRIVATE LibVNC::LibVNCClient) +else() + target_include_directories(veyon-core PRIVATE + ${ZLIB_INCLUDE_DIR} + ${JPEG_INCLUDE_DIR} + ${LZO_INCLUDE_DIR} + ) + target_include_directories(veyon-core PUBLIC + ${libvncserver_DIR}/src/common/ + ${libvncserver_DIR}/include + ) + target_link_libraries(veyon-core PRIVATE + Threads::Threads + PNG::PNG + ${ZLIB_LIBRARIES} + ${JPEG_LIBRARIES} + ${LZO_LIBRARIES} + ) +endif() + +if(VEYON_BUILD_WINDOWS) # add Windows Socket library required by libvncclient - TARGET_LINK_LIBRARIES(veyon-core -lws2_32) - SET_TARGET_PROPERTIES(veyon-core PROPERTIES PREFIX "") - INSTALL(TARGETS veyon-core RUNTIME DESTINATION ${VEYON_LIB_DIR}) -ELSE() - INSTALL(TARGETS veyon-core LIBRARY DESTINATION ${VEYON_LIB_DIR}) -ENDIF(VEYON_BUILD_WIN32) - -COTIRE_VEYON(veyon-core) + target_link_libraries(veyon-core PRIVATE -lws2_32) + set_target_properties(veyon-core PROPERTIES PREFIX "") + if(NOT WITH_CORE_ONLY) + install(TARGETS veyon-core RUNTIME DESTINATION ${VEYON_LIB_DIR}) + endif() +else() + if(NOT WITH_CORE_ONLY) + install(TARGETS veyon-core LIBRARY DESTINATION ${VEYON_LIB_DIR}) + endif() +endif() + +if(VEYON_BUILD_ANDROID) + target_link_libraries(veyon-core PRIVATE Qt${QT_MAJOR_VERSION}::AndroidExtras) +endif() + +if(WITH_PCH) + set(PCH ${CMAKE_CURRENT_SOURCE_DIR}/src/PrecompiledHeader.h) + target_precompile_headers(veyon-core PRIVATE ${PCH}) + + add_pch_target(veyon-application-pch ${PCH}) + set_target_properties(veyon-application-pch PROPERTIES COMPILE_OPTIONS "${CMAKE_COMPILE_OPTIONS_PIE}") + set_target_properties(veyon-application-pch PROPERTIES LINK_OPTIONS "${CMAKE_LINK_OPTIONS_PIE}") + + add_pch_target(veyon-library-pch ${PCH}) + set_target_properties(veyon-library-pch PROPERTIES POSITION_INDEPENDENT_CODE TRUE) +endif() diff --git a/core/include/AccessControlProvider.h b/core/include/AccessControlProvider.h deleted file mode 100644 index a40cfb1b0..000000000 --- a/core/include/AccessControlProvider.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * AccessControlProvider.h - declaration of class AccessControlProvider - * - * Copyright (c) 2016-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#pragma once - -#include "AccessControlRule.h" -#include "NetworkObject.h" - -class UserGroupsBackendInterface; -class NetworkObjectDirectory; - -class VEYON_CORE_EXPORT AccessControlProvider -{ -public: - enum class Access { - Deny, - Allow, - ToBeConfirmed, - } ; - - AccessControlProvider(); - - QStringList userGroups() const; - QStringList locations() const; - QStringList locationsOfComputer( const QString& computer ) const; - - Access checkAccess( const QString& accessingUser, const QString& accessingComputer, - const QStringList& connectedUsers ); - - bool processAuthorizedGroups( const QString& accessingUser ); - - AccessControlRule::Action processAccessControlRules( const QString& accessingUser, - const QString& accessingComputer, - const QString& localUser, - const QString& localComputer, - const QStringList& connectedUsers ); - - bool isAccessToLocalComputerDenied() const; - -private: - bool isMemberOfUserGroup( const QString& user, const QString& groupName ) const; - bool isLocatedAt( const QString& computer, const QString& locationName ) const; - bool haveGroupsInCommon( const QString& userOne, const QString& userTwo ) const; - bool haveSameLocations( const QString& computerOne, const QString& computerTwo ) const; - bool isLocalHost( const QString& accessingComputer ) const; - bool isLocalUser( const QString& accessingUser, const QString& localUser ) const; - bool isNoUserLoggedOn() const; - - QString lookupSubject( AccessControlRule::Subject subject, - const QString& accessingUser, const QString& accessingComputer, - const QString& localUser, const QString& localComputer ) const; - - bool matchConditions( const AccessControlRule& rule, - const QString& accessingUser, const QString& accessingComputer, - const QString& localUser, const QString& localComputer, - const QStringList& connectedUsers ) const; - - static QStringList objectNames( const NetworkObjectList& objects ); - - QList m_accessControlRules; - UserGroupsBackendInterface* m_userGroupsBackend; - NetworkObjectDirectory* m_networkObjectDirectory; - bool m_queryDomainGroups; - -} ; diff --git a/core/include/AuthenticationCredentials.h b/core/include/AuthenticationCredentials.h deleted file mode 100644 index 51097880d..000000000 --- a/core/include/AuthenticationCredentials.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * AuthenticationCredentials.h - class holding credentials for authentication - * - * Copyright (c) 2010-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#pragma once - -#include "CryptoCore.h" -#include "VeyonCore.h" - -// clazy:excludeall=rule-of-three - -class VEYON_CORE_EXPORT AuthenticationCredentials -{ -public: - enum class Type - { - None = 0x00, - PrivateKey = 0x01, - UserLogon = 0x02, - Token = 0x04, - AllTypes = PrivateKey | UserLogon | Token - } ; - - Q_DECLARE_FLAGS(TypeFlags, Type) - - AuthenticationCredentials(); - AuthenticationCredentials( const AuthenticationCredentials &other ); - - bool hasCredentials( Type credentialType ) const; - - // private key auth - bool loadPrivateKey( const QString& privateKeyFile ); - const CryptoCore::PrivateKey& privateKey() const - { - return m_privateKey; - } - - // user logon auth - void setLogonUsername( const QString &username ) - { - m_logonUsername = username; - } - - void setLogonPassword( const QString &password ) - { - m_logonPassword = password; - } - - const QString &logonUsername() const - { - return m_logonUsername; - } - - const QString &logonPassword() const - { - return m_logonPassword; - } - - void setToken( const QString &token ) - { - m_token = token; - } - - const QString &token() const - { - return m_token; - } - - void setInternalVncServerPassword( const QString& password ) - { - m_internalVncServerPassword = password; - } - - const QString& internalVncServerPassword() const - { - return m_internalVncServerPassword; - } - -private: - CryptoCore::PrivateKey m_privateKey; - - QString m_logonUsername; - QString m_logonPassword; - - QString m_token; - - QString m_internalVncServerPassword; - -} ; diff --git a/core/include/ComputerControlInterface.h b/core/include/ComputerControlInterface.h deleted file mode 100644 index 39c1e9c13..000000000 --- a/core/include/ComputerControlInterface.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * ComputerControlInterface.h - interface class for controlling a computer - * - * Copyright (c) 2017-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#pragma once - -#include -#include -#include -#include - -#include "Computer.h" -#include "Feature.h" -#include "VeyonCore.h" -#include "VncConnection.h" - -class QImage; - -class FeatureMessage; -class VncConnection; -class VeyonConnection; - -class VEYON_CORE_EXPORT ComputerControlInterface : public QObject -{ - Q_OBJECT -public: - using Pointer = QSharedPointer; - - using State = VncConnection::State; - - explicit ComputerControlInterface( const Computer& computer, QObject* parent = nullptr ); - ~ComputerControlInterface() override; - - void start( QSize scaledScreenSize ); - void stop(); - - const Computer& computer() const - { - return m_computer; - } - - State state() const - { - return m_state; - } - - const QSize& scaledScreenSize() const - { - return m_scaledScreenSize; - } - - void setScaledScreenSize( QSize size ); - - QImage scaledScreen() const; - - QImage screen() const; - - const QString& userLoginName() const - { - return m_userLoginName; - } - - void setUserLoginName( const QString& userLoginName ); - - const QString& userFullName() const - { - return m_userFullName; - } - - void setUserFullName( const QString& userFullName ); - - const FeatureUidList& activeFeatures() const - { - return m_activeFeatures; - } - - void setActiveFeatures( const FeatureUidList& activeFeatures ); - - Feature::Uid designatedModeFeature() const - { - return m_designatedModeFeature; - } - - void setDesignatedModeFeature( Feature::Uid designatedModeFeature ); - - void sendFeatureMessage( const FeatureMessage& featureMessage, bool wake ); - bool isMessageQueueEmpty(); - - void enableUpdates(); - void disableUpdates(); - - -private: - Pointer weakPointer(); - - void resetWatchdog(); - void restartConnection(); - - void updateState(); - void updateUser(); - void updateActiveFeatures(); - - void handleFeatureMessage( const FeatureMessage& message ); - - static constexpr int ConnectionWatchdogTimeout = 10000; - static constexpr int UpdateIntervalWhenDisabled = 5000; - - Computer m_computer; - - State m_state; - QString m_userLoginName; - QString m_userFullName; - FeatureUidList m_activeFeatures; - Feature::Uid m_designatedModeFeature; - - QSize m_scaledScreenSize; - - VncConnection* m_vncConnection; - VeyonConnection* m_connection; - QTimer m_connectionWatchdogTimer; - QTimer m_userUpdateTimer; - QTimer m_activeFeaturesUpdateTimer; - -signals: - void featureMessageReceived( const FeatureMessage&, ComputerControlInterface::Pointer ); - void screenUpdated(); - void userChanged(); - void stateChanged(); - void activeFeaturesChanged(); - -}; - -using ComputerControlInterfaceList = QVector; diff --git a/core/include/FeatureControl.h b/core/include/FeatureControl.h deleted file mode 100644 index 8fcda8310..000000000 --- a/core/include/FeatureControl.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * FeatureControl.h - declaration of FeatureControl class - * - * Copyright (c) 2017-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#pragma once - -#include "SimpleFeatureProvider.h" - -class VEYON_CORE_EXPORT FeatureControl : public QObject, public SimpleFeatureProvider, public PluginInterface -{ - Q_OBJECT - Q_INTERFACES(FeatureProviderInterface PluginInterface) -public: - explicit FeatureControl( QObject* parent = nullptr ); - ~FeatureControl() override = default; - - bool queryActiveFeatures( const ComputerControlInterfaceList& computerControlInterfaces ); - - Plugin::Uid uid() const override - { - return QStringLiteral("f5ec79e0-186c-4af0-89a2-7e5687cc32b2"); - } - - QVersionNumber version() const override - { - return QVersionNumber( 1, 1 ); - } - - QString name() const override - { - return QStringLiteral( "FeatureControl" ); - } - - QString description() const override - { - return tr( "Feature control" ); - } - - QString vendor() const override - { - return QStringLiteral( "Veyon Community" ); - } - - QString copyright() const override - { - return QStringLiteral( "Tobias Junghans" ); - } - - const FeatureList& featureList() const override - { - return m_features; - } - - bool handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) override; - - bool handleFeatureMessage( VeyonServerInterface& server, - const MessageContext& messageContext, - const FeatureMessage& message ) override; - -private: - enum Commands - { - QueryActiveFeatures, - }; - - enum Arguments - { - ActiveFeatureList, - }; - - const Feature m_featureControlFeature; - const FeatureList m_features; - - FeatureUidList m_activeFeatures; - -}; diff --git a/core/include/QtCompat.h b/core/include/QtCompat.h deleted file mode 100644 index fcc4ce926..000000000 --- a/core/include/QtCompat.h +++ /dev/null @@ -1,373 +0,0 @@ -/* - * QtCompat.h - functions and templates for compatibility with older Qt versions - * - * Copyright (c) 2017-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#pragma once - -#include -#include -#include -#include - -template -static inline bool intersects( const QSet& a, const QSet& b ) -{ -#if QT_VERSION < 0x050600 - return QSet( a ).intersect( b ).isEmpty() == false; -#else - return a.intersects( b ); -#endif -} - -#define Q_DISABLE_MOVE(Class) \ - Class(const Class &&) Q_DECL_EQ_DELETE;\ - Class &operator=(const Class &&) Q_DECL_EQ_DELETE; - -#if QT_VERSION >= 0x050600 -#include -#else - -// taken from qtbase/src/corelib/tools/qversionnumber.h - -class QVersionNumber -{ - /* - * QVersionNumber stores small values inline, without memory allocation. - * We do that by setting the LSB in the pointer that would otherwise hold - * the longer form of the segments. - * The constants below help us deal with the permutations for 32- and 64-bit, - * little- and big-endian architectures. - */ - enum { - // in little-endian, inline_segments[0] is shared with the pointer's LSB, while - // in big-endian, it's inline_segments[7] - InlineSegmentMarker = Q_BYTE_ORDER == Q_LITTLE_ENDIAN ? 0 : sizeof(void*) - 1, - InlineSegmentStartIdx = !InlineSegmentMarker, // 0 for BE, 1 for LE - InlineSegmentCount = sizeof(void*) - 1 - }; - Q_STATIC_ASSERT(InlineSegmentCount >= 3); // at least major, minor, micro - - struct SegmentStorage { - // Note: we alias the use of dummy and inline_segments in the use of the - // union below. This is undefined behavior in C++98, but most compilers implement - // the C++11 behavior. The one known exception is older versions of Sun Studio. - union { - quintptr dummy; - qint8 inline_segments[sizeof(void*)]; - QVector *pointer_segments; - }; - - // set the InlineSegmentMarker and set length to zero - SegmentStorage() Q_DECL_NOTHROW : dummy(1) {} - - SegmentStorage(const QVector &seg) - { - if (dataFitsInline(seg.begin(), seg.size())) - setInlineData(seg.begin(), seg.size()); - else - pointer_segments = new QVector(seg); - } - - SegmentStorage(const SegmentStorage &other) - { - if (other.isUsingPointer()) - pointer_segments = new QVector(*other.pointer_segments); - else - dummy = other.dummy; - } - - SegmentStorage &operator=(const SegmentStorage &other) - { - if (isUsingPointer() && other.isUsingPointer()) { - *pointer_segments = *other.pointer_segments; - } else if (other.isUsingPointer()) { - pointer_segments = new QVector(*other.pointer_segments); - } else { - if (isUsingPointer()) - delete pointer_segments; - dummy = other.dummy; - } - return *this; - } - -#ifdef Q_COMPILER_RVALUE_REFS - SegmentStorage(SegmentStorage &&other) Q_DECL_NOTHROW - : dummy(other.dummy) - { - other.dummy = 1; - } - - SegmentStorage &operator=(SegmentStorage &&other) Q_DECL_NOTHROW - { - qSwap(dummy, other.dummy); - return *this; - } - - explicit SegmentStorage(QVector &&seg) - { - if (dataFitsInline(seg.begin(), seg.size())) - setInlineData(seg.begin(), seg.size()); - else - pointer_segments = new QVector(std::move(seg)); - } -#endif -#ifdef Q_COMPILER_INITIALIZER_LISTS - SegmentStorage(std::initializer_list args) - { - if (dataFitsInline(args.begin(), int(args.size()))) { - setInlineData(args.begin(), int(args.size())); - } else { - pointer_segments = new QVector(args); - } - } -#endif - - ~SegmentStorage() { if (isUsingPointer()) delete pointer_segments; } - - bool isUsingPointer() const Q_DECL_NOTHROW - { return (inline_segments[InlineSegmentMarker] & 1) == 0; } - - int size() const Q_DECL_NOTHROW - { return isUsingPointer() ? pointer_segments->size() : (inline_segments[InlineSegmentMarker] >> 1); } - - void setInlineSize(int len) - { inline_segments[InlineSegmentMarker] = 1 + 2 * len; } - - void resize(int len) - { - if (isUsingPointer()) - pointer_segments->resize(len); - else - setInlineSize(len); - } - - int at(int index) const - { - return isUsingPointer() ? - pointer_segments->at(index) : - inline_segments[InlineSegmentStartIdx + index]; - } - - void setSegments(int len, int maj, int min = 0, int mic = 0) - { - if (maj == qint8(maj) && min == qint8(min) && mic == qint8(mic)) { - int data[] = { maj, min, mic }; - setInlineData(data, len); - } else { - setVector(len, maj, min, mic); - } - } - - private: - static bool dataFitsInline(const int *data, int len) - { - if (len > InlineSegmentCount) - return false; - for (int i = 0; i < len; ++i) - if (data[i] != qint8(data[i])) - return false; - return true; - } - void setInlineData(const int *data, int len) - { - dummy = 1 + len * 2; -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - for (int i = 0; i < len; ++i) - dummy |= quintptr(data[i] & 0xFF) << (8 * (i + 1)); -#elif Q_BYTE_ORDER == Q_BIG_ENDIAN - for (int i = 0; i < len; ++i) - dummy |= quintptr(data[i] & 0xFF) << (8 * (sizeof(void *) - i - 1)); -#else - // the code above is equivalent to: - setInlineSize(len); - for (int i = 0; i < len; ++i) - inline_segments[InlineSegmentStartIdx + i] = data[i] & 0xFF; -#endif - } - - Q_CORE_EXPORT void setVector(int len, int maj, int min, int mic); - } m_segments; - -public: - inline QVersionNumber() Q_DECL_NOTHROW - : m_segments() - {} - inline explicit QVersionNumber(const QVector &seg) - : m_segments(seg) - {} - - // compiler-generated copy/move ctor/assignment operators and the destructor are ok - -#ifdef Q_COMPILER_RVALUE_REFS - explicit QVersionNumber(QVector &&seg) - : m_segments(std::move(seg)) - {} -#endif - -#ifdef Q_COMPILER_INITIALIZER_LISTS - inline QVersionNumber(std::initializer_list args) - : m_segments(args) - {} -#endif - - inline explicit QVersionNumber(int maj) - { m_segments.setSegments(1, maj); } - - inline explicit QVersionNumber(int maj, int min) - { m_segments.setSegments(2, maj, min); } - - inline explicit QVersionNumber(int maj, int min, int mic) - { m_segments.setSegments(3, maj, min, mic); } - - Q_REQUIRED_RESULT inline bool isNull() const Q_DECL_NOTHROW - { return segmentCount() == 0; } - - Q_REQUIRED_RESULT inline bool isNormalized() const Q_DECL_NOTHROW - { return isNull() || segmentAt(segmentCount() - 1) != 0; } - - Q_REQUIRED_RESULT inline int majorVersion() const Q_DECL_NOTHROW - { return segmentAt(0); } - - Q_REQUIRED_RESULT inline int minorVersion() const Q_DECL_NOTHROW - { return segmentAt(1); } - - Q_REQUIRED_RESULT inline int microVersion() const Q_DECL_NOTHROW - { return segmentAt(2); } - - Q_REQUIRED_RESULT Q_CORE_EXPORT QVersionNumber normalized() const; - - Q_REQUIRED_RESULT Q_CORE_EXPORT QVector segments() const; - - Q_REQUIRED_RESULT inline int segmentAt(int index) const Q_DECL_NOTHROW - { return (m_segments.size() > index) ? m_segments.at(index) : 0; } - - Q_REQUIRED_RESULT inline int segmentCount() const Q_DECL_NOTHROW - { return m_segments.size(); } - - Q_REQUIRED_RESULT Q_CORE_EXPORT bool isPrefixOf(const QVersionNumber &other) const Q_DECL_NOTHROW; - - Q_REQUIRED_RESULT Q_CORE_EXPORT static int compare(const QVersionNumber &v1, const QVersionNumber &v2) Q_DECL_NOTHROW; - - Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2); - - Q_REQUIRED_RESULT Q_CORE_EXPORT QString toString() const; - Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(const QString &string, int *suffixIndex = Q_NULLPTR); - -}; - -Q_DECLARE_TYPEINFO(QVersionNumber, Q_MOVABLE_TYPE); - -Q_REQUIRED_RESULT inline bool operator> (const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW -{ return QVersionNumber::compare(lhs, rhs) > 0; } - -Q_REQUIRED_RESULT inline bool operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW -{ return QVersionNumber::compare(lhs, rhs) >= 0; } - -Q_REQUIRED_RESULT inline bool operator< (const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW -{ return QVersionNumber::compare(lhs, rhs) < 0; } - -Q_REQUIRED_RESULT inline bool operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW -{ return QVersionNumber::compare(lhs, rhs) <= 0; } - -Q_REQUIRED_RESULT inline bool operator==(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW -{ return QVersionNumber::compare(lhs, rhs) == 0; } - -Q_REQUIRED_RESULT inline bool operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs) Q_DECL_NOTHROW -{ return QVersionNumber::compare(lhs, rhs) != 0; } - -Q_DECLARE_METATYPE(QVersionNumber) -#endif - -#if QT_VERSION < 0x050700 -template struct QAddConst { using Type = const T; }; -template constexpr typename QAddConst::Type &qAsConst(T &t) { return t; } -template void qAsConst(const T &&) = delete; - -template -struct QNonConstOverload -{ - template - Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr) - { return ptr; } - - template - static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr) - { return ptr; } -}; - -template -struct QConstOverload -{ - template - Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...) const) const Q_DECL_NOTHROW -> decltype(ptr) - { return ptr; } - - template - static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...) const) Q_DECL_NOTHROW -> decltype(ptr) - { return ptr; } -}; - -template -struct QOverload : QConstOverload, QNonConstOverload -{ - using QConstOverload::of; - using QConstOverload::operator(); - using QNonConstOverload::of; - using QNonConstOverload::operator(); - - template - Q_DECL_CONSTEXPR auto operator()(R (*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr) - { return ptr; } - - template - static Q_DECL_CONSTEXPR auto of(R (*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr) - { return ptr; } -}; -#endif - -#if QT_VERSION < 0x051200 -#define QDeadlineTimer(x) static_cast(x) -#else -#include -#endif - - -template -struct QVariantHelper -{ - static T value( const QVariant& variant ) - { - return variant.value(); - } -}; - -#if QT_VERSION < 0x050600 -template -struct QVariantHelper::value >::type> -{ - static T value( const QVariant& variant ) - { - return static_cast( variant.toInt() ); - } -}; -#endif diff --git a/core/include/RfbVeyonAuth.h b/core/include/RfbVeyonAuth.h deleted file mode 100644 index 45509b910..000000000 --- a/core/include/RfbVeyonAuth.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * RfbVeyonAuth.h - types and names related to veyon-specific RFB - * authentication type - * - * Copyright (c) 2017-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#pragma once - -#include "VeyonCore.h" - -static constexpr char rfbSecTypeVeyon = 40; - -class VEYON_CORE_EXPORT RfbVeyonAuth -{ - Q_GADGET -public: - enum Type - { - // invalid/null authentication type - Invalid, - - // no authentication needed - None, - - // only hosts in an internal whitelist list are allowed - HostWhiteListLegacy, // TODO: drop in VEYON5 - - // client has to sign some data to verify it's authority - KeyFile, - - // authentication is performed using given username and password - Logon, - - // client has to prove its authenticity by knowing common token - Token, - - AuthTypeCount - - } ; - - Q_ENUM(Type) - -}; diff --git a/core/include/SimpleFeatureProvider.h b/core/include/SimpleFeatureProvider.h deleted file mode 100644 index 1b4f4194f..000000000 --- a/core/include/SimpleFeatureProvider.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SimpleFeatureProvider.h - interface class for simple feature plugins - * - * Copyright (c) 2018-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#pragma once - -#include "FeatureProviderInterface.h" - -class VEYON_CORE_EXPORT SimpleFeatureProvider : public FeatureProviderInterface -{ -public: - ~SimpleFeatureProvider() override = default; - - bool startFeature( VeyonMasterInterface& master, - const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) override; - - bool stopFeature( VeyonMasterInterface& master, - const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) override; - - bool handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) override; - - bool handleFeatureMessage( VeyonServerInterface& server, - const MessageContext& messageContext, - const FeatureMessage& message ) override; - - bool handleFeatureMessage( VeyonWorkerInterface& worker, const FeatureMessage& message ) override; - -}; diff --git a/core/include/VeyonConfigurationProperties.h b/core/include/VeyonConfigurationProperties.h deleted file mode 100644 index 21afe94b6..000000000 --- a/core/include/VeyonConfigurationProperties.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * VeyonConfigurationProperties.h - definition of every configuration property - * stored in global veyon configuration - * - * Copyright (c) 2016-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING) if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#pragma once - -#include -#include -#include -#include - -#include "Logger.h" -#include "NetworkObjectDirectory.h" - -#define FOREACH_VEYON_CORE_CONFIG_PROPERTIES(OP) \ - OP( VeyonConfiguration, VeyonCore::config(), VeyonCore::ApplicationVersion, applicationVersion, setApplicationVersion, "ApplicationVersion", "Core", QVariant::fromValue(VeyonCore::ApplicationVersion::Version_4_0), Configuration::Property::Flag::Hidden ) \ - OP( VeyonConfiguration, VeyonCore::config(), QJsonObject, pluginVersions, setPluginVersions, "PluginVersions", "Core", QVariant(), Configuration::Property::Flag::Hidden ) \ - OP( VeyonConfiguration, VeyonCore::config(), QString, installationID, setInstallationID, "InstallationID", "Core", QString(), Configuration::Property::Flag::Hidden ) \ - -#define FOREACH_VEYON_UI_CONFIG_PROPERTY(OP) \ - OP( VeyonConfiguration, VeyonCore::config(), QString, applicationName, setApplicationName, "ApplicationName", "UI", QStringLiteral("Veyon"), Configuration::Property::Flag::Hidden ) \ - OP( VeyonConfiguration, VeyonCore::config(), QString, uiLanguage, setUiLanguage, "Language", "UI", QString(), Configuration::Property::Flag::Standard ) - -#define FOREACH_VEYON_SERVICE_CONFIG_PROPERTY(OP) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, isTrayIconHidden, setTrayIconHidden, "HideTrayIcon", "Service", false, Configuration::Property::Flag::Advanced ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, failedAuthenticationNotificationsEnabled, setFailedAuthenticationNotificationsEnabled, "FailedAuthenticationNotifications", "Service", true, Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, remoteConnectionNotificationsEnabled, setRemoteConnectionNotificationsEnabled, "RemoteConnectionNotifications", "Service", false, Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, multiSessionModeEnabled, setMultiSessionModeEnabled, "MultiSession", "Service", false, Configuration::Property::Flag::Advanced ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, autostartService, setServiceAutostart, "Autostart", "Service", true, Configuration::Property::Flag::Advanced ) \ - -#define FOREACH_VEYON_NETWORK_OBJECT_DIRECTORY_CONFIG_PROPERTY(OP) \ - OP( VeyonConfiguration, VeyonCore::config(), QUuid, networkObjectDirectoryPlugin, setNetworkObjectDirectoryPlugin, "Plugin", "NetworkObjectDirectory", QUuid(), Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), int, networkObjectDirectoryUpdateInterval, setNetworkObjectDirectoryUpdateInterval, "UpdateInterval", "NetworkObjectDirectory", NetworkObjectDirectory::DefaultUpdateInterval, Configuration::Property::Flag::Standard ) \ - -#define FOREACH_VEYON_FEATURES_CONFIG_PROPERTY(OP) \ - OP( VeyonConfiguration, VeyonCore::config(), QStringList, disabledFeatures, setDisabledFeatures, "DisabledFeatures", "Features", QStringList(), Configuration::Property::Flag::Standard ) \ - -#define FOREACH_VEYON_LOGGING_CONFIG_PROPERTY(OP) \ - OP( VeyonConfiguration, VeyonCore::config(), Logger::LogLevel, logLevel, setLogLevel, "LogLevel", "Logging", QVariant::fromValue(Logger::LogLevel::Default), Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, logFileSizeLimitEnabled, setLogFileSizeLimitEnabled, "LogFileSizeLimitEnabled", "Logging", false, Configuration::Property::Flag::Advanced ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, logFileRotationEnabled, setLogFileRotationEnabled, "LogFileRotationEnabled", "Logging", false, Configuration::Property::Flag::Advanced ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, logToStdErr, setLogToStdErr, "LogToStdErr", "Logging", true, Configuration::Property::Flag::Advanced ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, logToSystem, setLogToSystem, "LogToSystem", "Logging", false, Configuration::Property::Flag::Advanced ) \ - OP( VeyonConfiguration, VeyonCore::config(), int, logFileSizeLimit, setLogFileSizeLimit, "LogFileSizeLimit", "Logging", Logger::DefaultFileSizeLimit, Configuration::Property::Flag::Advanced ) \ - OP( VeyonConfiguration, VeyonCore::config(), int, logFileRotationCount, setLogFileRotationCount, "LogFileRotationCount", "Logging", Logger::DefaultFileRotationCount, Configuration::Property::Flag::Advanced ) \ - OP( VeyonConfiguration, VeyonCore::config(), QString, logFileDirectory, setLogFileDirectory, "LogFileDirectory", "Logging", QLatin1String(Logger::DefaultLogFileDirectory), Configuration::Property::Flag::Standard ) \ - -#define FOREACH_VEYON_VNC_SERVER_CONFIG_PROPERTY(OP) \ - OP( VeyonConfiguration, VeyonCore::config(), QUuid, vncServerPlugin, setVncServerPlugin, "Plugin", "VncServer", QUuid(), Configuration::Property::Flag::Standard ) \ - -#define FOREACH_VEYON_NETWORK_CONFIG_PROPERTY(OP) \ - OP( VeyonConfiguration, VeyonCore::config(), int, primaryServicePort, setPrimaryServicePort, "PrimaryServicePort", "Network", 11100, Configuration::Property::Flag::Advanced ) \ - OP( VeyonConfiguration, VeyonCore::config(), int, vncServerPort, setVncServerPort, "VncServerPort", "Network", 11200, Configuration::Property::Flag::Advanced ) \ - OP( VeyonConfiguration, VeyonCore::config(), int, featureWorkerManagerPort, setFeatureWorkerManagerPort, "FeatureWorkerManagerPort", "Network", 11300, Configuration::Property::Flag::Advanced ) \ - OP( VeyonConfiguration, VeyonCore::config(), int, demoServerPort, setDemoServerPort, "DemoServerPort", "Network", 11400, Configuration::Property::Flag::Advanced ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, isFirewallExceptionEnabled, setFirewallExceptionEnabled, "FirewallExceptionEnabled", "Network", true, Configuration::Property::Flag::Advanced ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, localConnectOnly, setLocalConnectOnly, "LocalConnectOnly", "Network", false, Configuration::Property::Flag::Advanced ) \ - -#define FOREACH_VEYON_DIRECTORIES_CONFIG_PROPERTY(OP) \ - OP( VeyonConfiguration, VeyonCore::config(), QString, userConfigurationDirectory, setUserConfigurationDirectory, "UserConfiguration", "Directories", QDir::toNativeSeparators( QStringLiteral( "%APPDATA%/Config" ) ), Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), QString, screenshotDirectory, setScreenshotDirectory, "Screenshots", "Directories", QDir::toNativeSeparators( QStringLiteral( "%APPDATA%/Screenshots" ) ), Configuration::Property::Flag::Standard ) \ - -#define FOREACH_VEYON_MASTER_CONFIG_PROPERTY(OP) \ - OP( VeyonConfiguration, VeyonCore::config(), int, computerMonitoringUpdateInterval, setComputerMonitoringUpdateInterval, "ComputerMonitoringUpdateInterval", "Master", 1000, Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), int, computerDisplayRoleContent, setComputerDisplayRoleContent, "ComputerDisplayRoleContent", "Master", QVariant(), Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), int, computerMonitoringSortOrder, setComputerMonitoringSortOrder, "ComputerMonitoringSortOrder", "Master", QVariant(), Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), QColor, computerMonitoringBackgroundColor, setComputerMonitoringBackgroundColor, "ComputerMonitoringBackgroundColor", "Master", QColor(Qt::white), Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), QColor, computerMonitoringTextColor, setComputerMonitoringTextColor, "ComputerMonitoringTextColor", "Master", QColor(Qt::black), Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, accessControlForMasterEnabled, setAccessControlForMasterEnabled, "AccessControlForMasterEnabled", "Master", false, Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, autoAdjustGridSize, setAutoAdjustGridSize, "AutoAdjustGridSize", "Master", false, Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, autoSelectCurrentLocation, setAutoSelectCurrentLocation, "AutoSelectCurrentLocation", "Master", false, Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, showCurrentLocationOnly, setShowCurrentLocationOnly, "ShowCurrentLocationOnly", "Master", false, Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, allowAddingHiddenLocations, setAllowAddingHiddenLocations, "AllowAddingHiddenLocations", "Master", false, Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, localComputerHidden, setLocalComputerHidden, "LocalComputerHidden", "Master", false, Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, hideEmptyLocations, setHideEmptyLocations, "HideEmptyLocations", "Master", false, Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, computerFilterHidden, setComputerFilterHidden, "ComputerFilterHidden", "Master", false, Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), QUuid, computerDoubleClickFeature, setComputerDoubleClickFeature, "ComputerDoubleClickFeature", "Master", QUuid(), Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, enforceSelectedModeForClients, setEnforceSelectedModeForClients, "EnforceSelectedModeForClients", "Master", false, Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, autoOpenComputerSelectPanel, setAutoOpenComputerSelectPanel, "AutoOpenComputerSelectPanel", "Master", false, Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, confirmUnsafeActions, setConfirmUnsafeActions, "ConfirmUnsafeActions", "Master", false, Configuration::Property::Flag::Standard ) \ - -#define FOREACH_VEYON_AUTHENTICATION_CONFIG_PROPERTY(OP) \ - OP( VeyonConfiguration, VeyonCore::config(), VeyonCore::AuthenticationMethod, authenticationMethod, setAuthenticationMethod, "Method", "Authentication", QVariant::fromValue(VeyonCore::AuthenticationMethod::LogonAuthentication), Configuration::Property::Flag::Standard ) \ - -#define FOREACH_VEYON_KEY_AUTHENTICATION_CONFIG_PROPERTY(OP) \ - OP( VeyonConfiguration, VeyonCore::config(), QString, privateKeyBaseDir, setPrivateKeyBaseDir, "PrivateKeyBaseDir", "Authentication", QDir::toNativeSeparators( QStringLiteral( "%GLOBALAPPDATA%/keys/private" ) ), Configuration::Property::Flag::Advanced ) \ - OP( VeyonConfiguration, VeyonCore::config(), QString, publicKeyBaseDir, setPublicKeyBaseDir, "PublicKeyBaseDir", "Authentication", QDir::toNativeSeparators( QStringLiteral( "%GLOBALAPPDATA%/keys/public" ) ), Configuration::Property::Flag::Advanced ) \ - -#define FOREACH_VEYON_ACCESS_CONTROL_CONFIG_PROPERTY(OP) \ - OP( VeyonConfiguration, VeyonCore::config(), QUuid, accessControlUserGroupsBackend, setAccessControlUserGroupsBackend, "UserGroupsBackend", "AccessControl", QUuid(), Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, domainGroupsForAccessControlEnabled, setDomainGroupsForAccessControlEnabled, "DomainGroupsEnabled", "AccessControl", false, Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, isAccessRestrictedToUserGroups, setAccessRestrictedToUserGroups, "AccessRestrictedToUserGroups", "AccessControl", false , Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, isAccessControlRulesProcessingEnabled, setAccessControlRulesProcessingEnabled, "AccessControlRulesProcessingEnabled", "AccessControl", false, Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), QStringList, authorizedUserGroups, setAuthorizedUserGroups, "AuthorizedUserGroups", "AccessControl", QStringList(), Configuration::Property::Flag::Standard ) \ - OP( VeyonConfiguration, VeyonCore::config(), QJsonArray, accessControlRules, setAccessControlRules, "AccessControlRules", "AccessControl", QVariant(), Configuration::Property::Flag::Standard ) \ - -#define FOREACH_VEYON_LEGACY_CONFIG_PROPERTY(OP) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, legacyOpenComputerManagementAtStart, setLegacyOpenComputerManagementAtStart, "OpenComputerManagementAtStart", "Master", false, Configuration::Property::Flag::Legacy ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, legacyAutoSwitchToCurrentRoom, setLegacyAutoSwitchToCurrentRoom, "AutoSwitchToCurrentRoom", "Master", false, Configuration::Property::Flag::Legacy ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, legacyOnlyCurrentRoomVisible, setLegacyOnlyCurrentRoomVisible, "OnlyCurrentRoomVisible", "Master", false, Configuration::Property::Flag::Legacy ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, legacyManualRoomAdditionAllowed, setLegacyManualRoomAdditionAllowed, "ManualRoomAdditionAllowed", "Master", false, Configuration::Property::Flag::Legacy ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, legacyEmptyRoomsHidden, setLegacyEmptyRoomsHidden, "EmptyRoomsHidden", "Master", false, Configuration::Property::Flag::Legacy ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, legacyConfirmDangerousActions, setLegacyConfirmDangerousActions, "ConfirmDangerousActions", "Master", false, Configuration::Property::Flag::Legacy ) \ - OP( VeyonConfiguration, VeyonCore::config(), bool, legacyIsSoftwareSASEnabled, setLegacySoftwareSASEnabled, "SoftwareSASEnabled", "Service", true, Configuration::Property::Flag::Legacy ) \ - -#define FOREACH_VEYON_CONFIG_PROPERTY(OP) \ - FOREACH_VEYON_CORE_CONFIG_PROPERTIES(OP) \ - FOREACH_VEYON_UI_CONFIG_PROPERTY(OP) \ - FOREACH_VEYON_SERVICE_CONFIG_PROPERTY(OP) \ - FOREACH_VEYON_LOGGING_CONFIG_PROPERTY(OP) \ - FOREACH_VEYON_NETWORK_OBJECT_DIRECTORY_CONFIG_PROPERTY(OP)\ - FOREACH_VEYON_FEATURES_CONFIG_PROPERTY(OP)\ - FOREACH_VEYON_VNC_SERVER_CONFIG_PROPERTY(OP) \ - FOREACH_VEYON_NETWORK_CONFIG_PROPERTY(OP) \ - FOREACH_VEYON_DIRECTORIES_CONFIG_PROPERTY(OP) \ - FOREACH_VEYON_MASTER_CONFIG_PROPERTY(OP) \ - FOREACH_VEYON_AUTHENTICATION_CONFIG_PROPERTY(OP) \ - FOREACH_VEYON_KEY_AUTHENTICATION_CONFIG_PROPERTY(OP) \ - FOREACH_VEYON_ACCESS_CONTROL_CONFIG_PROPERTY(OP) \ - FOREACH_VEYON_LEGACY_CONFIG_PROPERTY(OP) diff --git a/core/include/VncView.h b/core/include/VncView.h deleted file mode 100644 index ceb3a68df..000000000 --- a/core/include/VncView.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * VncView.h - VNC viewer widget - * - * Copyright (c) 2006-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#pragma once - -#include -#include -#include -#include - -#include "KeyboardShortcutTrapper.h" -#include "VncConnection.h" - -class ProgressWidget; -class RemoteControlWidget; -class KeyboardShortcutTrapper; -class VeyonConnection; - -class VEYON_CORE_EXPORT VncView : public QWidget -{ - Q_OBJECT -public: - enum Modes - { - RemoteControlMode, - DemoMode, - NumModes - } ; - using Mode = Modes; - - enum Shortcut - { - ShortcutCtrlAltDel, - ShortcutCtrlEscape, - ShortcutAltTab, - ShortcutAltF4, - ShortcutWinTab, - ShortcutWin, - ShortcutMenu, - ShortcutAltCtrlF1, - ShortcutCount - } ; - - VncView( const QString &host, int port, QWidget *parent, Mode mode ); - ~VncView() override; - - bool isViewOnly() const - { - return m_viewOnly; - } - - VncConnection* vncConnection() - { - return m_vncConn; - } - - QSize scaledSize() const; - QSize framebufferSize() const - { - return m_framebufferSize; - } - QSize sizeHint() const override; - - -public slots: - void setViewOnly( bool viewOnly ); - void sendShortcut( Shortcut shortcut ); - - -signals: - void mouseAtBorder(); - void keyEvent( unsigned int, bool ); - void startConnection(); - void connectionEstablished(); - void sizeHintChanged(); - - -private: - void handleShortcut( KeyboardShortcutTrapper::Shortcut shortcut ); - void updateCursorPos( int x, int y ); - void updateCursorShape( const QPixmap& cursorShape, int xh, int yh ); - void updateImage( int x, int y, int w, int h ); - void updateFramebufferSize( int w, int h ); - void updateConnectionState(); - - bool eventFilter( QObject* obj, QEvent* event ) override; - bool event( QEvent* event ) override; - void focusInEvent( QFocusEvent* event ) override; - void focusOutEvent( QFocusEvent* event ) override; - void paintEvent( QPaintEvent* event ) override; - void resizeEvent( QResizeEvent* event ) override; - - void keyEventHandler( QKeyEvent* event ); - void mouseEventHandler( QMouseEvent* event ); - void wheelEventHandler( QWheelEvent* event ); - void unpressModifiers(); - - bool isScaledView() const; - qreal scaleFactor() const; - QPoint mapToFramebuffer( QPoint pos ); - QRect mapFromFramebuffer( QRect rect ); - - void updateLocalCursor(); - void pressKey( unsigned int key ); - void unpressKey( unsigned int key ); - - VncConnection* m_vncConn; - VeyonConnection* m_veyonConnection; - - Mode m_mode; - QPixmap m_cursorShape; - int m_cursorX; - int m_cursorY; - QSize m_framebufferSize; - int m_cursorHotX; - int m_cursorHotY; - bool m_viewOnly; - bool m_viewOnlyFocus; - bool m_initDone; - - int m_buttonMask; - QMap m_mods; - - ProgressWidget* m_establishingConnectionWidget; - - KeyboardShortcutTrapper* m_keyboardShortcutTrapper; - - static constexpr int MouseBorderSignalDelay = 500; - QTimer m_mouseBorderSignalTimer; - -} ; diff --git a/core/resources/core.qrc b/core/resources/core.qrc index 25a553bf3..c1428e7de 100644 --- a/core/resources/core.qrc +++ b/core/resources/core.qrc @@ -5,37 +5,46 @@ application-x-pem-key.png license.png user-group-new.png + user-group-new-dark.png languages.png presentation-none.png - system-suspend-hibernate.png icon16.png icon22.png icon32.png - watch1.png - watch2.png - watch3.png - watch4.png - watch5.png - watch6.png - watch7.png - watch8.png - watch9.png - watch10.png - watch11.png - watch12.png - watch13.png - watch14.png - watch15.png - watch16.png - toolbar-background.png document-open.png + document-open-dark.png document-save.png + document-save-dark.png list-add.png edit-delete.png edit-find.png + edit-find-dark.png help-about.png + help-about-dark.png dialog-ok-apply.png document-edit.png default-pkey.pem + go-up.png + go-up-dark.png + go-down.png + go-down-dark.png + go-previous.png + go-previous-dark.png + go-next.png + go-next-dark.png + media-playback-pause.png + media-playback-pause-dark.png + media-playback-start.png + media-playback-start-dark.png + media-playback-stop.png + media-playback-stop-dark.png + media-record.png + toast-close.png + toast-error.png + toast-information.png + toast-success.png + toast-warning.png + view-fullscreen.png + view-fullscreen-dark.png diff --git a/core/resources/document-open-dark.png b/core/resources/document-open-dark.png new file mode 100644 index 000000000..fa3430cb3 Binary files /dev/null and b/core/resources/document-open-dark.png differ diff --git a/core/resources/document-save-dark.png b/core/resources/document-save-dark.png new file mode 100644 index 000000000..122e9bc2d Binary files /dev/null and b/core/resources/document-save-dark.png differ diff --git a/core/resources/edit-find-dark.png b/core/resources/edit-find-dark.png new file mode 100644 index 000000000..1853cf30a Binary files /dev/null and b/core/resources/edit-find-dark.png differ diff --git a/core/resources/go-down-dark.png b/core/resources/go-down-dark.png new file mode 100644 index 000000000..36bf7a0a2 Binary files /dev/null and b/core/resources/go-down-dark.png differ diff --git a/core/resources/go-down.png b/core/resources/go-down.png new file mode 100644 index 000000000..106738cd7 Binary files /dev/null and b/core/resources/go-down.png differ diff --git a/core/resources/go-next-dark.png b/core/resources/go-next-dark.png new file mode 100644 index 000000000..7a78d72d4 Binary files /dev/null and b/core/resources/go-next-dark.png differ diff --git a/core/resources/go-next.png b/core/resources/go-next.png new file mode 100644 index 000000000..20da882de Binary files /dev/null and b/core/resources/go-next.png differ diff --git a/core/resources/go-previous-dark.png b/core/resources/go-previous-dark.png new file mode 100644 index 000000000..d9b316a2a Binary files /dev/null and b/core/resources/go-previous-dark.png differ diff --git a/core/resources/go-previous.png b/core/resources/go-previous.png new file mode 100644 index 000000000..ee690e3f8 Binary files /dev/null and b/core/resources/go-previous.png differ diff --git a/core/resources/go-up-dark.png b/core/resources/go-up-dark.png new file mode 100644 index 000000000..2697d36f1 Binary files /dev/null and b/core/resources/go-up-dark.png differ diff --git a/core/resources/go-up.png b/core/resources/go-up.png new file mode 100644 index 000000000..be16d90f5 Binary files /dev/null and b/core/resources/go-up.png differ diff --git a/core/resources/help-about-dark.png b/core/resources/help-about-dark.png new file mode 100644 index 000000000..3eafb192a Binary files /dev/null and b/core/resources/help-about-dark.png differ diff --git a/core/resources/media-playback-pause-dark.png b/core/resources/media-playback-pause-dark.png new file mode 100644 index 000000000..ede1b1bdf Binary files /dev/null and b/core/resources/media-playback-pause-dark.png differ diff --git a/core/resources/media-playback-pause.png b/core/resources/media-playback-pause.png new file mode 100644 index 000000000..82dfc9bee Binary files /dev/null and b/core/resources/media-playback-pause.png differ diff --git a/core/resources/media-playback-start-dark.png b/core/resources/media-playback-start-dark.png new file mode 100644 index 000000000..5b22dc132 Binary files /dev/null and b/core/resources/media-playback-start-dark.png differ diff --git a/core/resources/media-playback-start.png b/core/resources/media-playback-start.png new file mode 100644 index 000000000..d144b2675 Binary files /dev/null and b/core/resources/media-playback-start.png differ diff --git a/core/resources/media-playback-stop-dark.png b/core/resources/media-playback-stop-dark.png new file mode 100644 index 000000000..e19b08131 Binary files /dev/null and b/core/resources/media-playback-stop-dark.png differ diff --git a/core/resources/media-playback-stop.png b/core/resources/media-playback-stop.png new file mode 100644 index 000000000..9cd9908b2 Binary files /dev/null and b/core/resources/media-playback-stop.png differ diff --git a/core/resources/media-record.png b/core/resources/media-record.png new file mode 100644 index 000000000..b026c6266 Binary files /dev/null and b/core/resources/media-record.png differ diff --git a/core/resources/system-suspend-hibernate.png b/core/resources/system-suspend-hibernate.png deleted file mode 100644 index 9030012e7..000000000 Binary files a/core/resources/system-suspend-hibernate.png and /dev/null differ diff --git a/core/resources/toast-close.png b/core/resources/toast-close.png new file mode 100644 index 000000000..e0a167888 Binary files /dev/null and b/core/resources/toast-close.png differ diff --git a/core/resources/toast-error.png b/core/resources/toast-error.png new file mode 100644 index 000000000..4c939933f Binary files /dev/null and b/core/resources/toast-error.png differ diff --git a/core/resources/toast-information.png b/core/resources/toast-information.png new file mode 100644 index 000000000..054da26a5 Binary files /dev/null and b/core/resources/toast-information.png differ diff --git a/core/resources/toast-success.png b/core/resources/toast-success.png new file mode 100644 index 000000000..f84f25ce2 Binary files /dev/null and b/core/resources/toast-success.png differ diff --git a/core/resources/toast-warning.png b/core/resources/toast-warning.png new file mode 100644 index 000000000..e152c0eb9 Binary files /dev/null and b/core/resources/toast-warning.png differ diff --git a/core/resources/toolbar-background.png b/core/resources/toolbar-background.png deleted file mode 100644 index c6c5bf518..000000000 Binary files a/core/resources/toolbar-background.png and /dev/null differ diff --git a/core/resources/user-group-new-dark.png b/core/resources/user-group-new-dark.png new file mode 100644 index 000000000..f66e4dd5b Binary files /dev/null and b/core/resources/user-group-new-dark.png differ diff --git a/core/resources/view-fullscreen-dark.png b/core/resources/view-fullscreen-dark.png new file mode 100644 index 000000000..c17070230 Binary files /dev/null and b/core/resources/view-fullscreen-dark.png differ diff --git a/core/resources/view-fullscreen.png b/core/resources/view-fullscreen.png new file mode 100644 index 000000000..a8679f9cb Binary files /dev/null and b/core/resources/view-fullscreen.png differ diff --git a/core/resources/watch1.png b/core/resources/watch1.png deleted file mode 100644 index a3e5fc112..000000000 Binary files a/core/resources/watch1.png and /dev/null differ diff --git a/core/resources/watch10.png b/core/resources/watch10.png deleted file mode 100644 index 28763ea87..000000000 Binary files a/core/resources/watch10.png and /dev/null differ diff --git a/core/resources/watch11.png b/core/resources/watch11.png deleted file mode 100644 index aeda6426f..000000000 Binary files a/core/resources/watch11.png and /dev/null differ diff --git a/core/resources/watch12.png b/core/resources/watch12.png deleted file mode 100644 index d3b37cc42..000000000 Binary files a/core/resources/watch12.png and /dev/null differ diff --git a/core/resources/watch13.png b/core/resources/watch13.png deleted file mode 100644 index 4010c1bb0..000000000 Binary files a/core/resources/watch13.png and /dev/null differ diff --git a/core/resources/watch14.png b/core/resources/watch14.png deleted file mode 100644 index 1b17692ed..000000000 Binary files a/core/resources/watch14.png and /dev/null differ diff --git a/core/resources/watch15.png b/core/resources/watch15.png deleted file mode 100644 index af32f9877..000000000 Binary files a/core/resources/watch15.png and /dev/null differ diff --git a/core/resources/watch16.png b/core/resources/watch16.png deleted file mode 100644 index e8ef8c330..000000000 Binary files a/core/resources/watch16.png and /dev/null differ diff --git a/core/resources/watch2.png b/core/resources/watch2.png deleted file mode 100644 index 51b5fb684..000000000 Binary files a/core/resources/watch2.png and /dev/null differ diff --git a/core/resources/watch3.png b/core/resources/watch3.png deleted file mode 100644 index 989e78222..000000000 Binary files a/core/resources/watch3.png and /dev/null differ diff --git a/core/resources/watch4.png b/core/resources/watch4.png deleted file mode 100644 index 630b1a9fd..000000000 Binary files a/core/resources/watch4.png and /dev/null differ diff --git a/core/resources/watch5.png b/core/resources/watch5.png deleted file mode 100644 index 9ef66cc3b..000000000 Binary files a/core/resources/watch5.png and /dev/null differ diff --git a/core/resources/watch6.png b/core/resources/watch6.png deleted file mode 100644 index f16493053..000000000 Binary files a/core/resources/watch6.png and /dev/null differ diff --git a/core/resources/watch7.png b/core/resources/watch7.png deleted file mode 100644 index add3df317..000000000 Binary files a/core/resources/watch7.png and /dev/null differ diff --git a/core/resources/watch8.png b/core/resources/watch8.png deleted file mode 100644 index 1ed91a272..000000000 Binary files a/core/resources/watch8.png and /dev/null differ diff --git a/core/resources/watch9.png b/core/resources/watch9.png deleted file mode 100644 index b255da8ce..000000000 Binary files a/core/resources/watch9.png and /dev/null differ diff --git a/core/src/AboutDialog.cpp b/core/src/AboutDialog.cpp index fe93c4abc..0753a61cb 100644 --- a/core/src/AboutDialog.cpp +++ b/core/src/AboutDialog.cpp @@ -1,7 +1,7 @@ /* * AboutDialog.cpp - implementation of AboutDialog * - * Copyright (c) 2011-2019 Tobias Junghans + * Copyright (c) 2011-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -37,9 +37,9 @@ AboutDialog::AboutDialog( QWidget *parent ) : { ui->setupUi( this ); - setWindowTitle( tr( "About %1 %2" ).arg( VeyonCore::applicationName(), VeyonCore::version() ) ); + setWindowTitle( tr( "About %1 %2" ).arg( VeyonCore::applicationName(), VeyonCore::versionString() ) ); - ui->versionLabel->setText( VeyonCore::version() ); + ui->versionLabel->setText( VeyonCore::versionString() ); QFile authors( QStringLiteral( ":/CONTRIBUTORS" ) ); authors.open( QFile::ReadOnly ); // Flawfinder: ignore diff --git a/core/include/AboutDialog.h b/core/src/AboutDialog.h similarity index 93% rename from core/include/AboutDialog.h rename to core/src/AboutDialog.h index bc05e1ae7..a9e028e0a 100644 --- a/core/include/AboutDialog.h +++ b/core/src/AboutDialog.h @@ -1,7 +1,7 @@ /* * AboutDialog.h - declaration of AboutDialog class * - * Copyright (c) 2011-2019 Tobias Junghans + * Copyright (c) 2011-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -40,7 +40,7 @@ class VEYON_CORE_EXPORT AboutDialog : public QDialog explicit AboutDialog( QWidget *parent ); ~AboutDialog() override; -private slots: +private Q_SLOTS: void openDonationWebsite(); private: diff --git a/core/src/AboutDialog.ui b/core/src/AboutDialog.ui index 531c07577..ce37d49d4 100644 --- a/core/src/AboutDialog.ui +++ b/core/src/AboutDialog.ui @@ -149,7 +149,7 @@ - Copyright © 2004-2019 Tobias Junghans / Veyon Solutions + Copyright © 2004-2025 Tobias Junghans / Veyon Solutions diff --git a/core/src/AccessControlProvider.cpp b/core/src/AccessControlProvider.cpp index dabd14f4e..ce908f291 100644 --- a/core/src/AccessControlProvider.cpp +++ b/core/src/AccessControlProvider.cpp @@ -1,7 +1,7 @@ /* * AccessControlProvider.cpp - implementation of the AccessControlProvider class * - * Copyright (c) 2016-2019 Tobias Junghans + * Copyright (c) 2016-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -33,22 +33,26 @@ #include "VeyonConfiguration.h" #include "VeyonCore.h" #include "PlatformPluginInterface.h" +#include "PlatformSessionFunctions.h" #include "PlatformUserFunctions.h" AccessControlProvider::AccessControlProvider() : m_accessControlRules(), - m_userGroupsBackend( VeyonCore::userGroupsBackendManager().accessControlBackend() ), - m_networkObjectDirectory( VeyonCore::networkObjectDirectoryManager().configuredDirectory() ), - m_queryDomainGroups( VeyonCore::config().domainGroupsForAccessControlEnabled() ) + m_userGroupsBackend(VeyonCore::userGroupsBackendManager().configuredBackend()), + m_networkObjectDirectory(VeyonCore::networkObjectDirectoryManager().configuredDirectory()), + m_useDomainUserGroups(VeyonCore::config().useDomainUserGroups()), + m_accessControlFeature(QLatin1String(staticMetaObject.className()), + Feature::Flag::Meta | Feature::Flag::Builtin, + Feature::Uid{QStringLiteral("1815941e-eaef-43ab-b9cd-5403dca3f749")}, {}, {}, {}, {}, {}) { const QJsonArray accessControlRules = VeyonCore::config().accessControlRules(); m_accessControlRules.reserve( accessControlRules.size() ); - for( const auto& accessControlRule : accessControlRules ) + for (const auto& accessControlRule : accessControlRules) { - m_accessControlRules.append( AccessControlRule( accessControlRule ) ); + m_accessControlRules.append(AccessControlRule::Pointer::create(accessControlRule)); } } @@ -56,7 +60,7 @@ AccessControlProvider::AccessControlProvider() : QStringList AccessControlProvider::userGroups() const { - auto userGroupList = m_userGroupsBackend->userGroups( m_queryDomainGroups ); + auto userGroupList = m_userGroupsBackend->userGroups(m_useDomainUserGroups); std::sort( userGroupList.begin(), userGroupList.end() ); @@ -68,7 +72,7 @@ QStringList AccessControlProvider::userGroups() const QStringList AccessControlProvider::locations() const { auto locationList = objectNames( m_networkObjectDirectory->queryObjects( NetworkObject::Type::Location, - NetworkObject::Attribute::None, {} ) ); + NetworkObject::Property::None, {} ) ); std::sort( locationList.begin(), locationList.end() ); @@ -90,7 +94,7 @@ QStringList AccessControlProvider::locationsOfComputer( const QString& computer } const auto computers = m_networkObjectDirectory->queryObjects( NetworkObject::Type::Host, - NetworkObject::Attribute::HostAddress, fqdn ); + NetworkObject::Property::HostAddress, fqdn ); if( computers.isEmpty() ) { vWarning() << "Could not query any network objects for host" << fqdn; @@ -118,31 +122,44 @@ QStringList AccessControlProvider::locationsOfComputer( const QString& computer -AccessControlProvider::Access AccessControlProvider::checkAccess( const QString& accessingUser, - const QString& accessingComputer, - const QStringList& connectedUsers ) +AccessControlProvider::CheckResult AccessControlProvider::checkAccess( const QString& accessingUser, + const QString& accessingComputer, + const QStringList& connectedUsers, + Plugin::Uid authMethodUid) { - if( VeyonCore::config().isAccessRestrictedToUserGroups() ) + CheckResult denyAccessCheckResult{Access::Deny}; + if (VeyonCore::config().isAccessRestrictedToUserGroups()) { - if( processAuthorizedGroups( accessingUser ) ) + if (processAuthorizedGroups(accessingUser)) { - return Access::Allow; + return {Access::Allow, Reason::UserInAuthorizedUserGroups}; } + denyAccessCheckResult.reason = Reason::UserNotInAuthorizedUserGroups; } - else if( VeyonCore::config().isAccessControlRulesProcessingEnabled() ) + else if (VeyonCore::config().isAccessControlRulesProcessingEnabled()) { - auto action = processAccessControlRules( accessingUser, - accessingComputer, - VeyonCore::platform().userFunctions().currentUser(), - HostAddress::localFQDN(), - connectedUsers ); - switch( action ) + const auto rule = processAccessControlRules(accessingUser, + accessingComputer, + VeyonCore::platform().userFunctions().currentUser(), + HostAddress::localFQDN(), + connectedUsers, + authMethodUid); + if (rule) { - case AccessControlRule::Action::Allow: - return Access::Allow; - case AccessControlRule::Action::AskForPermission: - return Access::ToBeConfirmed; - default: break; + switch(rule->action()) + { + case AccessControlRule::Action::Allow: + return {Access::Allow, Reason::AccessControlRuleMatched}; + case AccessControlRule::Action::AskForPermission: + return {Access::ToBeConfirmed}; + default: break; + } + denyAccessCheckResult.reason = Reason::AccessControlRuleMatched; + denyAccessCheckResult.matchedRule = rule; + } + else + { + denyAccessCheckResult.reason = Reason::NoAccessControlRuleMatched; } } else @@ -150,13 +167,13 @@ AccessControlProvider::Access AccessControlProvider::checkAccess( const QString& vDebug() << "no access control method configured, allowing access."; // no access control method configured, therefore grant access - return Access::Allow; + return {Access::Allow}; } vDebug() << "configured access control method did not succeed, denying access."; // configured access control method did not succeed, therefore deny access - return Access::Deny; + return denyAccessCheckResult; } @@ -165,40 +182,53 @@ bool AccessControlProvider::processAuthorizedGroups( const QString& accessingUse { vDebug() << "processing for user" << accessingUser; - return intersects( m_userGroupsBackend->groupsOfUser( accessingUser, m_queryDomainGroups ).toSet(), - VeyonCore::config().authorizedUserGroups().toSet() ); + const auto groupsOfAccessingUser = m_userGroupsBackend->groupsOfUser( accessingUser, m_useDomainUserGroups ); + const auto authorizedUserGroups = VeyonCore::config().authorizedUserGroups(); + + vDebug() << groupsOfAccessingUser << authorizedUserGroups; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + const auto groupsOfAccessingUserSet = QSet{ groupsOfAccessingUser.begin(), groupsOfAccessingUser.end() }; + const auto authorizedUserGroupSet = QSet{ authorizedUserGroups.begin(), authorizedUserGroups.end() }; +#else + const auto groupsOfAccessingUserSet = groupsOfAccessingUser.toSet(); + const auto authorizedUserGroupSet = authorizedUserGroups.toSet(); +#endif + + return groupsOfAccessingUserSet.intersects( authorizedUserGroupSet ); } -AccessControlRule::Action AccessControlProvider::processAccessControlRules( const QString& accessingUser, +AccessControlRule::Pointer AccessControlProvider::processAccessControlRules(const QString& accessingUser, const QString& accessingComputer, const QString& localUser, const QString& localComputer, - const QStringList& connectedUsers ) + const QStringList& connectedUsers, + Plugin::Uid authMethodUid) { - vDebug() << "processing rules for" << accessingUser << accessingComputer << localUser << localComputer << connectedUsers; + vDebug() << "processing rules for" << accessingUser << accessingComputer << localUser << localComputer << connectedUsers << authMethodUid; - for( const auto& rule : qAsConst( m_accessControlRules ) ) + for (const auto& rule : std::as_const(m_accessControlRules)) { // rule disabled? - if( rule.action() == AccessControlRule::Action::None ) + if (rule->action() == AccessControlRule::Action::None) { // then continue with next rule continue; } - if( rule.areConditionsIgnored() || - matchConditions( rule, accessingUser, accessingComputer, localUser, localComputer, connectedUsers ) ) + if (rule->areConditionsIgnored() || + matchConditions(*rule, accessingUser, accessingComputer, localUser, localComputer, connectedUsers, authMethodUid)) { - vDebug() << "rule" << rule.name() << "matched with action" << rule.action(); - return rule.action(); + vDebug() << "rule" << rule->name() << "matched with action" << rule->action(); + return rule; } } vDebug() << "no matching rule, denying access"; - return AccessControlRule::Action::Deny; + return nullptr; } @@ -212,12 +242,12 @@ bool AccessControlProvider::isAccessToLocalComputerDenied() const return false; } - for( const auto& rule : qAsConst( m_accessControlRules ) ) + for (const auto& rule : std::as_const(m_accessControlRules)) { - if( matchConditions( rule, {}, {}, - VeyonCore::platform().userFunctions().currentUser(), HostAddress::localFQDN(), {} ) ) + if (matchConditions(*rule, {}, {}, + VeyonCore::platform().userFunctions().currentUser(), HostAddress::localFQDN(), {}, {})) { - switch( rule.action() ) + switch (rule->action()) { case AccessControlRule::Action::Deny: return true; @@ -235,34 +265,57 @@ bool AccessControlProvider::isAccessToLocalComputerDenied() const -bool AccessControlProvider::isMemberOfUserGroup( const QString &user, - const QString &groupName ) const +bool AccessControlProvider::handleFeatureMessage(ComputerControlInterface::Pointer computerControlInterface, const FeatureMessage& message) { - const QRegularExpression groupNameRX( groupName ); - - if( groupNameRX.isValid() ) + if (message.featureUid() == m_accessControlFeature.uid()) { - return m_userGroupsBackend->groupsOfUser( user, m_queryDomainGroups ).indexOf( groupNameRX ) >= 0; + computerControlInterface->setAccessControlFailed(message.argument(Argument::Details).toString()); + return true; } - return m_userGroupsBackend->groupsOfUser( user, m_queryDomainGroups ).contains( groupName ); + return false; +} + + + +void AccessControlProvider::sendDetails(QIODevice* ioDevice, const QString& details) +{ + FeatureMessage{m_accessControlFeature.uid()}.addArgument( + AccessControlProvider::Argument::Details, details) + .sendAsRfbMessage(ioDevice); +} + + + +bool AccessControlProvider::isMemberOfUserGroup( const QString &user, + const QString &groupName ) const +{ + return matchList(m_userGroupsBackend->groupsOfUser(user, m_useDomainUserGroups), groupName); } bool AccessControlProvider::isLocatedAt( const QString &computer, const QString &locationName ) const { - return locationsOfComputer( computer ).contains( locationName ); + return matchList(locationsOfComputer(computer), locationName); } bool AccessControlProvider::haveGroupsInCommon( const QString &userOne, const QString &userTwo ) const { - const auto userOneGroups = m_userGroupsBackend->groupsOfUser( userOne, m_queryDomainGroups ); - const auto userTwoGroups = m_userGroupsBackend->groupsOfUser( userTwo, m_queryDomainGroups ); - - return intersects( userOneGroups.toSet(), userTwoGroups.toSet() ); + const auto userOneGroups = m_userGroupsBackend->groupsOfUser( userOne, m_useDomainUserGroups ); + const auto userTwoGroups = m_userGroupsBackend->groupsOfUser( userTwo, m_useDomainUserGroups ); + +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + const auto userOneGroupSet = QSet{ userOneGroups.begin(), userOneGroups.end() }; + const auto userTwoGroupSet = QSet{ userTwoGroups.begin(), userTwoGroups.end() }; +#else + const auto userOneGroupSet = userOneGroups.toSet(); + const auto userTwoGroupSet = userTwoGroups.toSet(); +#endif + + return userOneGroupSet.intersects( userTwoGroupSet ); } @@ -293,9 +346,16 @@ bool AccessControlProvider::isLocalUser( const QString &accessingUser, const QSt -bool AccessControlProvider::isNoUserLoggedOn() const +bool AccessControlProvider::isNoUserLoggedInLocally() const { - return VeyonCore::platform().userFunctions().isAnyUserLoggedOn() == false; + return VeyonCore::platform().userFunctions().isAnyUserLoggedInLocally() == false; +} + + + +bool AccessControlProvider::isNoUserLoggedInRemotely() const +{ + return VeyonCore::platform().userFunctions().isAnyUserLoggedInRemotely() == false; } @@ -321,27 +381,35 @@ QString AccessControlProvider::lookupSubject( AccessControlRule::Subject subject bool AccessControlProvider::matchConditions( const AccessControlRule &rule, const QString& accessingUser, const QString& accessingComputer, const QString& localUser, const QString& localComputer, - const QStringList& connectedUsers ) const + const QStringList& connectedUsers, Plugin::Uid authMethodUid ) const { - bool hasConditions = false; + vDebug() << rule.toJson(); - // normally all selected conditions have to match in order to make the whole rule match - // if conditions should be inverted (i.e. "is member of" is to be interpreted as "is NOT member of") - // we have to check against the opposite boolean value - bool matchResult = rule.areConditionsInverted() == false; + AccessControlRule::Condition condition{AccessControlRule::Condition::None}; - vDebug() << rule.toJson() << matchResult; + if( rule.isConditionEnabled( AccessControlRule::Condition::AuthenticationMethod ) ) + { + condition = AccessControlRule::Condition::AuthenticationMethod; - if( rule.isConditionEnabled( AccessControlRule::Condition::MemberOfUserGroup ) ) + const auto allowedAuthMethod = Plugin::Uid( rule.argument( AccessControlRule::Condition::AuthenticationMethod ) ); + if( authMethodUid.isNull() || + allowedAuthMethod.isNull() || + ( authMethodUid == allowedAuthMethod ) == rule.isConditionInverted(condition) ) + { + return false; + } + } + + if( rule.isConditionEnabled( AccessControlRule::Condition::MemberOfGroup ) ) { - hasConditions = true; + condition = AccessControlRule::Condition::MemberOfGroup; - const auto condition = AccessControlRule::Condition::MemberOfUserGroup; + const auto condition = AccessControlRule::Condition::MemberOfGroup; const auto user = lookupSubject( rule.subject( condition ), accessingUser, {}, localUser, {} ); const auto group = rule.argument( condition ); if( user.isEmpty() || group.isEmpty() || - isMemberOfUserGroup( user, group ) != matchResult ) + isMemberOfUserGroup( user, group ) == rule.isConditionInverted(condition) ) { return false; } @@ -349,10 +417,10 @@ bool AccessControlProvider::matchConditions( const AccessControlRule &rule, if( rule.isConditionEnabled( AccessControlRule::Condition::GroupsInCommon ) ) { - hasConditions = true; + condition = AccessControlRule::Condition::GroupsInCommon; if( accessingUser.isEmpty() || localUser.isEmpty() || - haveGroupsInCommon( accessingUser, localUser ) != matchResult ) + haveGroupsInCommon( accessingUser, localUser ) == rule.isConditionInverted(condition) ) { return false; } @@ -360,25 +428,24 @@ bool AccessControlProvider::matchConditions( const AccessControlRule &rule, if( rule.isConditionEnabled( AccessControlRule::Condition::LocatedAt ) ) { - hasConditions = true; + condition = AccessControlRule::Condition::LocatedAt; - const auto condition = AccessControlRule::Condition::LocatedAt; const auto computer = lookupSubject( rule.subject( condition ), {}, accessingComputer, {}, localComputer ); const auto location = rule.argument( condition ); if( computer.isEmpty() || location.isEmpty() || - isLocatedAt( computer, location ) != matchResult ) + isLocatedAt( computer, location ) == rule.isConditionInverted(condition) ) { return false; } } - if( rule.isConditionEnabled( AccessControlRule::Condition::SameLocation ) ) + if( rule.isConditionEnabled( AccessControlRule::Condition::LocationsInCommon ) ) { - hasConditions = true; + condition = AccessControlRule::Condition::LocationsInCommon; if( accessingComputer.isEmpty() || localComputer.isEmpty() || - haveSameLocations( accessingComputer, localComputer ) != matchResult ) + haveSameLocations( accessingComputer, localComputer ) == rule.isConditionInverted(condition) ) { return false; } @@ -386,19 +453,19 @@ bool AccessControlProvider::matchConditions( const AccessControlRule &rule, if( rule.isConditionEnabled( AccessControlRule::Condition::AccessFromLocalHost ) ) { - hasConditions = true; + condition = AccessControlRule::Condition::AccessFromLocalHost; - if( isLocalHost( accessingComputer ) != matchResult ) + if( isLocalHost( accessingComputer ) == rule.isConditionInverted(condition) ) { return false; } } - if( rule.isConditionEnabled( AccessControlRule::Condition::AccessFromLocalUser ) ) + if( rule.isConditionEnabled( AccessControlRule::Condition::AccessFromSameUser ) ) { - hasConditions = true; + condition = AccessControlRule::Condition::AccessFromSameUser; - if( isLocalUser( accessingUser, localUser ) != matchResult ) + if( isLocalUser( accessingUser, localUser ) == rule.isConditionInverted(condition) ) { return false; } @@ -406,26 +473,66 @@ bool AccessControlProvider::matchConditions( const AccessControlRule &rule, if( rule.isConditionEnabled( AccessControlRule::Condition::AccessFromAlreadyConnectedUser ) ) { - hasConditions = true; + condition = AccessControlRule::Condition::AccessFromAlreadyConnectedUser; + + if( connectedUsers.contains( accessingUser ) == rule.isConditionInverted(condition) ) + { + return false; + } + } + + if( rule.isConditionEnabled( AccessControlRule::Condition::AccessedUserLoggedInLocally ) ) + { + condition = AccessControlRule::Condition::AccessedUserLoggedInLocally; + + if( VeyonCore::platform().sessionFunctions().currentSessionIsRemote() == rule.isConditionInverted(condition) ) + { + return false; + } + } + + if( rule.isConditionEnabled( AccessControlRule::Condition::NoUserLoggedInLocally ) ) + { + condition = AccessControlRule::Condition::NoUserLoggedInLocally; + + if( isNoUserLoggedInLocally() == rule.isConditionInverted(condition) ) + { + return false; + } + } + + if( rule.isConditionEnabled( AccessControlRule::Condition::NoUserLoggedInRemotely ) ) + { + condition = AccessControlRule::Condition::NoUserLoggedInRemotely; - if( connectedUsers.contains( accessingUser ) != matchResult ) + if( isNoUserLoggedInRemotely() == rule.isConditionInverted(condition) ) { return false; } } - if( rule.isConditionEnabled( AccessControlRule::Condition::NoUserLoggedOn ) ) + if( rule.isConditionEnabled( AccessControlRule::Condition::UserSession ) ) { - hasConditions = true; + condition = AccessControlRule::Condition::UserSession; - if( isNoUserLoggedOn() != matchResult ) + if( VeyonCore::platform().sessionFunctions().currentSessionHasUser() == rule.isConditionInverted(condition) ) + { + return false; + } + } + + if (rule.isConditionEnabled(AccessControlRule::Condition::ComputerAlreadyBeingAccessed)) + { + condition = AccessControlRule::Condition::ComputerAlreadyBeingAccessed; + + if (!connectedUsers.isEmpty() == rule.isConditionInverted(condition)) { return false; } } // do not match the rule if no conditions are set at all - if( hasConditions == false ) + if( condition == AccessControlRule::Condition::None ) { return false; } @@ -447,3 +554,25 @@ QStringList AccessControlProvider::objectNames( const NetworkObjectList& objects return nameList; } + + + +bool AccessControlProvider::matchList(const QStringList& list, const QString& pattern) +{ + if (pattern.startsWith(QLatin1Char('/')) && pattern.endsWith(QLatin1Char('/')) && + pattern.length() > 2) + { + return list.indexOf(QRegularExpression(pattern.mid(1, pattern.length() - 2))) >= 0; + } + + if (pattern.endsWith(QLatin1Char('*'))) + { + const QRegularExpression rx(pattern); + if (rx.isValid()) + { + return list.indexOf(rx) >= 0; + } + } + + return list.contains(pattern); +} diff --git a/core/src/AccessControlProvider.h b/core/src/AccessControlProvider.h new file mode 100644 index 000000000..9c40b520d --- /dev/null +++ b/core/src/AccessControlProvider.h @@ -0,0 +1,174 @@ +/* + * AccessControlProvider.h - declaration of class AccessControlProvider + * + * Copyright (c) 2016-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "AccessControlRule.h" +#include "FeatureProviderInterface.h" +#include "NetworkObject.h" +#include "Plugin.h" + +class UserGroupsBackendInterface; +class NetworkObjectDirectory; + +class VEYON_CORE_EXPORT AccessControlProvider : public QObject, FeatureProviderInterface, PluginInterface +{ + Q_OBJECT + Q_INTERFACES(FeatureProviderInterface PluginInterface) +public: + enum class Access { + Deny, + Allow, + ToBeConfirmed, + } ; + + enum class Reason { + Unknown, + NoAccessControlRuleMatched, + AccessControlRuleMatched, + NotConfirmedByUser, + ConfirmedByUser, + UserNotInAuthorizedUserGroups, + UserInAuthorizedUserGroups, + }; + + enum class Argument + { + Details, + }; + Q_ENUM(Argument) + + struct CheckResult { + Access access = Access::Deny; + Reason reason = Reason::Unknown; + AccessControlRule::Pointer matchedRule = nullptr; + }; + + AccessControlProvider(); + + QStringList userGroups() const; + QStringList locations() const; + QStringList locationsOfComputer( const QString& computer ) const; + + CheckResult checkAccess(const QString& accessingUser, const QString& accessingComputer, + const QStringList& connectedUsers, Plugin::Uid authMethodUid); + + bool processAuthorizedGroups( const QString& accessingUser ); + + AccessControlRule::Pointer processAccessControlRules(const QString& accessingUser, + const QString& accessingComputer, + const QString& localUser, + const QString& localComputer, + const QStringList& connectedUsers, + Plugin::Uid authMethodUid); + + bool isAccessToLocalComputerDenied() const; + + Plugin::Uid uid() const override + { + return Plugin::Uid{QStringLiteral("ef3f61f4-b7fa-41a1-ae09-74e022048617")}; + } + + QVersionNumber version() const override + { + return QVersionNumber(1, 0); + } + + QString name() const override + { + return QStringLiteral("AccessControlProvider"); + } + + QString description() const override + { + return tr( "Provider for access control features" ); + } + + QString vendor() const override + { + return QStringLiteral("Veyon Community"); + } + + QString copyright() const override + { + return QStringLiteral("Tobias Junghans"); + } + + const Feature& feature() const + { + return m_accessControlFeature; + } + + const FeatureList& featureList() const override + { + return m_features; + } + + bool controlFeature(Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces) override + { + Q_UNUSED(featureUid) + Q_UNUSED(operation) + Q_UNUSED(arguments) + Q_UNUSED(computerControlInterfaces) + + return false; + } + + bool handleFeatureMessage(ComputerControlInterface::Pointer computerControlInterface, + const FeatureMessage& message) override; + + void sendDetails(QIODevice* ioDevice, const QString& details); + +private: + bool isMemberOfUserGroup( const QString& user, const QString& groupName ) const; + bool isLocatedAt( const QString& computer, const QString& locationName ) const; + bool haveGroupsInCommon( const QString& userOne, const QString& userTwo ) const; + bool haveSameLocations( const QString& computerOne, const QString& computerTwo ) const; + bool isLocalHost( const QString& accessingComputer ) const; + bool isLocalUser( const QString& accessingUser, const QString& localUser ) const; + bool isNoUserLoggedInLocally() const; + bool isNoUserLoggedInRemotely() const; + + QString lookupSubject( AccessControlRule::Subject subject, + const QString& accessingUser, const QString& accessingComputer, + const QString& localUser, const QString& localComputer ) const; + + bool matchConditions( const AccessControlRule& rule, + const QString& accessingUser, const QString& accessingComputer, + const QString& localUser, const QString& localComputer, + const QStringList& connectedUsers, + Plugin::Uid authMethodUid ) const; + + static QStringList objectNames( const NetworkObjectList& objects ); + static bool matchList(const QStringList& list, const QString& pattern); + + QList m_accessControlRules{}; + UserGroupsBackendInterface* m_userGroupsBackend; + NetworkObjectDirectory* m_networkObjectDirectory; + bool m_useDomainUserGroups; + + Feature m_accessControlFeature; + FeatureList m_features{m_accessControlFeature}; +} ; diff --git a/core/src/AccessControlRule.cpp b/core/src/AccessControlRule.cpp index 41721734e..fd527a0fb 100644 --- a/core/src/AccessControlRule.cpp +++ b/core/src/AccessControlRule.cpp @@ -1,7 +1,7 @@ /* * AccessControlRule.cpp - implementation of the AccessControlRule class * - * Copyright (c) 2016-2019 Tobias Junghans + * Copyright (c) 2016-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,6 +23,7 @@ */ #include +#include #include "AccessControlRule.h" @@ -30,32 +31,16 @@ AccessControlRule::AccessControlRule() : m_name(), m_description(), m_action( Action::None ), - m_parameters(), - m_invertConditions( false ), m_ignoreConditions( false ) { } -AccessControlRule::AccessControlRule(const AccessControlRule &other) : - m_name( other.name() ), - m_description( other.description() ), - m_action( other.action() ), - m_parameters( other.parameters() ), - m_invertConditions( other.areConditionsInverted() ), - m_ignoreConditions( other.areConditionsIgnored() ) -{ -} - - - -AccessControlRule::AccessControlRule(const QJsonValue &jsonValue) : +AccessControlRule::AccessControlRule( const QJsonValue& jsonValue ) : m_name(), m_description(), m_action( Action::None ), - m_parameters(), - m_invertConditions( false ), m_ignoreConditions( false ) { if( jsonValue.isObject() ) @@ -65,20 +50,30 @@ AccessControlRule::AccessControlRule(const QJsonValue &jsonValue) : m_name = json[QStringLiteral("Name")].toString(); m_description = json[QStringLiteral("Description")].toString(); m_action = static_cast( json[QStringLiteral("Action")].toInt() ); - m_invertConditions = json[QStringLiteral("InvertConditions")].toBool(); m_ignoreConditions = json[QStringLiteral("IgnoreConditions")].toBool(); - auto parameters = json[QStringLiteral("Parameters")].toArray(); + const auto parameters = json[QStringLiteral("Parameters")].toArray(); - for( auto parametersValue : parameters ) + for( const auto& parametersValue : parameters ) { QJsonObject parametersObj = parametersValue.toObject(); auto condition = static_cast( parametersObj[QStringLiteral("Condition")].toInt() ); m_parameters[condition].enabled = parametersObj[QStringLiteral("Enabled")].toBool(); + m_parameters[condition].inverted = parametersObj[QStringLiteral("Inverted")].toBool(); m_parameters[condition].subject = static_cast( parametersObj[QStringLiteral("Subject")].toInt() ); m_parameters[condition].argument = parametersObj[QStringLiteral("Argument")].toString(); } + + // migrate global inversion setting from Veyon 4 + if( json[QStringLiteral("InvertConditions")].toBool() ) + { + const auto conditionCount = QMetaEnum::fromType().keyCount(); + for( int i = 0; i < conditionCount; ++i ) + { + m_parameters[Condition(i)].inverted ^= true; + } + } } } @@ -90,7 +85,6 @@ AccessControlRule& AccessControlRule::operator=( const AccessControlRule& other m_description = other.description(); m_action = other.action(); m_parameters = other.parameters(); - m_invertConditions = other.areConditionsInverted(); m_ignoreConditions = other.areConditionsIgnored(); return *this; @@ -105,7 +99,6 @@ QJsonObject AccessControlRule::toJson() const json[QStringLiteral("Name")] = m_name; json[QStringLiteral("Description")] = m_description; json[QStringLiteral("Action")] = static_cast( m_action ); - json[QStringLiteral("InvertConditions")] = m_invertConditions; json[QStringLiteral("IgnoreConditions")] = m_ignoreConditions; QJsonArray parameters; @@ -117,6 +110,7 @@ QJsonObject AccessControlRule::toJson() const QJsonObject parametersObject; parametersObject[QStringLiteral("Condition")] = static_cast( it.key() ); parametersObject[QStringLiteral("Enabled")] = true; + parametersObject[QStringLiteral("Inverted")] = isConditionInverted( it.key() ); parametersObject[QStringLiteral("Subject")] = static_cast( subject( it.key() ) ); parametersObject[QStringLiteral("Argument")] = argument( it.key() ); parameters.append( parametersObject ); diff --git a/core/include/AccessControlRule.h b/core/src/AccessControlRule.h similarity index 83% rename from core/include/AccessControlRule.h rename to core/src/AccessControlRule.h index d36001261..52cf11ba4 100644 --- a/core/include/AccessControlRule.h +++ b/core/src/AccessControlRule.h @@ -1,7 +1,7 @@ /* * AccessControlRule.h - declaration of class AccessControlRule * - * Copyright (c) 2016-2019 Tobias Junghans + * Copyright (c) 2016-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -47,14 +47,19 @@ class VEYON_CORE_EXPORT AccessControlRule enum class Condition { None, - MemberOfUserGroup, + MemberOfGroup, GroupsInCommon, LocatedAt, - SameLocation, + LocationsInCommon, AccessFromLocalHost, - AccessFromLocalUser, + AccessFromSameUser, AccessFromAlreadyConnectedUser, - NoUserLoggedOn, + NoUserLoggedInLocally, + NoUserLoggedInRemotely, + AccessedUserLoggedInLocally, + UserSession, + AuthenticationMethod, + ComputerAlreadyBeingAccessed, } ; Q_ENUM(Condition) @@ -75,16 +80,17 @@ class VEYON_CORE_EXPORT AccessControlRule struct ConditionParameters { bool enabled{false}; + bool inverted{false}; Subject subject{Subject::None}; ConditionArgument argument; }; using ConditionParameterMap = QMap; + using Pointer = QSharedPointer; AccessControlRule(); - AccessControlRule( const AccessControlRule& other ); - explicit AccessControlRule( const QJsonValue& jsonValue ); + explicit AccessControlRule(const QJsonValue& jsonValue); ~AccessControlRule() = default; @@ -145,24 +151,24 @@ class VEYON_CORE_EXPORT AccessControlRule m_ignoreConditions = ignored; } - bool areConditionsInverted() const + bool isConditionEnabled( Condition condition ) const { - return m_invertConditions; + return m_parameters.value( condition ).enabled; } - void setConditionsInverted( bool inverted ) + void setConditionEnabled( Condition condition, bool enabled ) { - m_invertConditions = inverted; + m_parameters[condition].enabled = enabled; } - bool isConditionEnabled( Condition condition ) const + bool isConditionInverted( Condition condition ) const { - return m_parameters.value( condition ).enabled; + return m_parameters.value( condition ).inverted; } - void setConditionEnabled( Condition condition, bool enabled ) + void setConditionInverted( Condition condition, bool inverted ) { - m_parameters[condition].enabled = enabled; + m_parameters[condition].inverted = inverted; } ConditionArgument argument( Condition condition ) const @@ -188,7 +194,6 @@ class VEYON_CORE_EXPORT AccessControlRule QString m_description; Action m_action; ConditionParameterMap m_parameters; - bool m_invertConditions; bool m_ignoreConditions; } ; diff --git a/core/src/AuthenticationCredentials.cpp b/core/src/AuthenticationCredentials.cpp deleted file mode 100644 index fb9720f2d..000000000 --- a/core/src/AuthenticationCredentials.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * AuthenticationCredentials.cpp - class holding credentials for authentication - * - * Copyright (c) 2010-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This software 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 software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "AuthenticationCredentials.h" - - -AuthenticationCredentials::AuthenticationCredentials() : - m_privateKey(), - m_logonUsername(), - m_logonPassword(), - m_token(), - m_internalVncServerPassword() -{ -} - - - -AuthenticationCredentials::AuthenticationCredentials( const AuthenticationCredentials &other ) : - m_privateKey(), - m_logonUsername( other.logonUsername() ), - m_logonPassword( other.logonPassword() ), - m_token( other.token() ), - m_internalVncServerPassword( other.internalVncServerPassword() ) -{ -} - - - -bool AuthenticationCredentials::hasCredentials( Type type ) const -{ - switch( type ) - { - case Type::PrivateKey: - return m_privateKey.isNull() == false; - - case Type::UserLogon: - return m_logonUsername.isEmpty() == false && m_logonPassword.isEmpty() == false; - - case Type::Token: - return m_token.isEmpty() == false && - QByteArray::fromBase64( m_token.toUtf8() ).size() == CryptoCore::ChallengeSize; - - default: - break; - } - - vCritical() << "no valid credential type given:" << TypeFlags( type ); - - return false; -} - - - -bool AuthenticationCredentials::loadPrivateKey( const QString& privateKeyFile ) -{ - vDebug() << privateKeyFile; - - if( privateKeyFile.isEmpty() ) - { - return false; - } - - m_privateKey = CryptoCore::PrivateKey( privateKeyFile ); - - return m_privateKey.isNull() == false && m_privateKey.isPrivate(); -} diff --git a/core/src/AuthenticationCredentials.h b/core/src/AuthenticationCredentials.h new file mode 100644 index 000000000..b497cc7ec --- /dev/null +++ b/core/src/AuthenticationCredentials.h @@ -0,0 +1,49 @@ +/* + * AuthenticationCredentials.h - class holding credentials for authentication + * + * Copyright (c) 2010-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "CryptoCore.h" + +// clazy:excludeall=rule-of-three + +class VEYON_CORE_EXPORT AuthenticationCredentials +{ +public: + using Password = CryptoCore::PlaintextPassword; + + void setInternalVncServerPassword( const Password& password ) + { + m_internalVncServerPassword = password; + } + + const Password& internalVncServerPassword() const + { + return m_internalVncServerPassword; + } + +private: + Password m_internalVncServerPassword; + +} ; diff --git a/core/src/AuthenticationManager.cpp b/core/src/AuthenticationManager.cpp new file mode 100644 index 000000000..9b943fca7 --- /dev/null +++ b/core/src/AuthenticationManager.cpp @@ -0,0 +1,168 @@ +/* + * AuthenticationManager.cpp - implementation of AuthenticationManager + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "PluginManager.h" +#include "AuthenticationManager.h" +#include "VeyonConfiguration.h" + +AuthenticationManager::AuthenticationManager( QObject* parent ) : + QObject( parent ), + m_legacyAuthTypes( { + { LegacyAuthType::Logon, Plugin::Uid{QStringLiteral("63611f7c-b457-42c7-832e-67d0f9281085")} }, + { LegacyAuthType::KeyFile, Plugin::Uid{QStringLiteral("0c69b301-81b4-42d6-8fae-128cdd113314")} } + } ) +{ + for( auto pluginObject : std::as_const( VeyonCore::pluginManager().pluginObjects() ) ) + { + auto pluginInterface = qobject_cast( pluginObject ); + auto authenticationPluginInterface = qobject_cast( pluginObject ); + + if( pluginInterface && authenticationPluginInterface ) + { + m_plugins[pluginInterface->uid()] = authenticationPluginInterface; + } + } + + if( m_plugins.isEmpty() ) + { + qFatal( "AuthenticationManager: no authentication plugins available!" ); + } +} + + + +Plugin::Uid AuthenticationManager::fromLegacyAuthType( LegacyAuthType authType ) const +{ + return m_legacyAuthTypes.value( authType ); +} + + + +AuthenticationManager::LegacyAuthType AuthenticationManager::toLegacyAuthType( Plugin::Uid uid ) const +{ + return m_legacyAuthTypes.key( uid ); +} + + + +Plugin::Uid AuthenticationManager::toUid( AuthenticationPluginInterface* authPlugin ) const +{ + for( auto it = m_plugins.constBegin(), end = m_plugins.constEnd(); it != end; ++it ) + { + if( it.value() == authPlugin ) + { + return it.key(); + } + } + + return {}; +} + + + +AuthenticationManager::Types AuthenticationManager::availableMethods() const +{ + Types types; + for( auto it = m_plugins.constBegin(), end = m_plugins.constEnd(); it != end; ++it ) + { + types[it.key()] = it.value()->authenticationMethodName(); + } + + return types; +} + + + +void AuthenticationManager::setEnabled( Plugin::Uid uid, bool enabled ) +{ + const auto formattedUid = VeyonCore::formattedUuid(uid); + + auto plugins = VeyonCore::config().enabledAuthenticationPlugins(); + + if( enabled ) + { + plugins.append( formattedUid ); + plugins.removeDuplicates(); + } + else + { + plugins.removeAll( formattedUid ); + } + + VeyonCore::config().setEnabledAuthenticationPlugins( plugins ); +} + + + +bool AuthenticationManager::isEnabled( Plugin::Uid uid ) const +{ + return VeyonCore::config().enabledAuthenticationPlugins().contains( VeyonCore::formattedUuid(uid) ); +} + + + +void AuthenticationManager::setEnabled( AuthenticationPluginInterface* authPlugin, bool enabled ) +{ + for( auto it = m_plugins.constBegin(), end = m_plugins.constEnd(); it != end; ++it ) + { + if( it.value() == authPlugin ) + { + setEnabled( it.key(), enabled ); + } + } +} + + + +bool AuthenticationManager::isEnabled( AuthenticationPluginInterface* authPlugin ) const +{ + for( auto it = m_plugins.constBegin(), end = m_plugins.constEnd(); it != end; ++it ) + { + if( it.value() == authPlugin && isEnabled( it.key() ) ) + { + return true; + } + } + + return false; +} + + + +bool AuthenticationManager::initializeCredentials() +{ + for( auto it = m_plugins.constBegin(), end = m_plugins.constEnd(); it != end; ++it ) + { + if( isEnabled( it.key() ) ) + { + if( it.value()->initializeCredentials() ) + { + m_initializedPlugin = it.value(); + return true; + } + } + } + + return false; +} diff --git a/core/src/AuthenticationManager.h b/core/src/AuthenticationManager.h new file mode 100644 index 000000000..8f431052e --- /dev/null +++ b/core/src/AuthenticationManager.h @@ -0,0 +1,76 @@ +/* + * AuthenticationManager.h - header file for AuthenticationManager + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "AuthenticationPluginInterface.h" + +class VEYON_CORE_EXPORT AuthenticationManager : public QObject +{ + Q_OBJECT +public: + enum LegacyAuthType + { + Invalid = 0, + KeyFile = 3, + Logon = 4, + }; + Q_ENUM(LegacyAuthType) + + using Plugins = QMap; + using Types = QMap; + + explicit AuthenticationManager( QObject* parent = nullptr ); + + const Plugins& plugins() const + { + return m_plugins; + } + + Plugin::Uid fromLegacyAuthType( LegacyAuthType authType ) const; + LegacyAuthType toLegacyAuthType( Plugin::Uid uid ) const; + + Plugin::Uid toUid( AuthenticationPluginInterface* authPlugin ) const; + + Types availableMethods() const; + + void setEnabled( Plugin::Uid uid, bool enabled ); + bool isEnabled( Plugin::Uid uid ) const; + + void setEnabled( AuthenticationPluginInterface* authPlugin, bool enabled ); + bool isEnabled( AuthenticationPluginInterface* authPlugin ) const; + + bool initializeCredentials(); + + AuthenticationPluginInterface* initializedPlugin() const + { + return m_initializedPlugin; + } + +private: + const QMap m_legacyAuthTypes; + Plugins m_plugins{}; + AuthenticationPluginInterface* m_initializedPlugin{nullptr}; + +}; diff --git a/plugins/vncserver/ultravnc-builtin/vncntlm.cpp b/core/src/AuthenticationPluginInterface.cpp similarity index 69% rename from plugins/vncserver/ultravnc-builtin/vncntlm.cpp rename to core/src/AuthenticationPluginInterface.cpp index f175f186b..117206b2f 100644 --- a/plugins/vncserver/ultravnc-builtin/vncntlm.cpp +++ b/core/src/AuthenticationPluginInterface.cpp @@ -1,31 +1,32 @@ -/* - * vncntlm.cpp - dummy implementation of vncntlm module - * - * Copyright (c) 2016-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -int CheckUserGroupPasswordUni(char *,char *,const char *) -{ - // never perform logon authentication as we're only using - // simple VNC authentication for internal VNC server - return 0; -} - +/* + * AuthenticationPluginInterface.cpp - interface class for authentication plugins + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "AuthenticationPluginInterface.h" +#include "PlatformUserFunctions.h" + + +QString AuthenticationPluginInterface::accessControlUser() const +{ + return VeyonCore::platform().userFunctions().currentUser(); +} diff --git a/core/src/AuthenticationPluginInterface.h b/core/src/AuthenticationPluginInterface.h new file mode 100644 index 000000000..4a8c51dc5 --- /dev/null +++ b/core/src/AuthenticationPluginInterface.h @@ -0,0 +1,68 @@ +/* + * AuthenticationPluginInterface.h - interface class for authentication plugins + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "PluginInterface.h" +#include "VncServerClient.h" + +// clazy:excludeall=copyable-polymorphic + +class VEYON_CORE_EXPORT AuthenticationPluginInterface +{ + Q_GADGET +public: + virtual ~AuthenticationPluginInterface() = default; + + virtual QString authenticationMethodName() const = 0; + + virtual QWidget* createAuthenticationConfigurationWidget() = 0; + + virtual bool initializeCredentials() = 0; + virtual bool hasCredentials() const = 0; + virtual bool checkCredentials() const = 0; + + // server side authentication + virtual VncServerClient::AuthState performAuthentication( VncServerClient* client, VariantArrayMessage& message ) const = 0; + + // client side authentication + virtual bool authenticate( QIODevice* socket ) const = 0; + + virtual bool requiresAccessControl() const + { + return true; + } + + virtual QString accessControlUser() const; + + static QString authenticationTestTitle() + { + return VeyonCore::tr( "Authentication test"); + } + +}; + +#define AuthenticationPluginInterface_iid "io.veyon.Veyon.Plugins.AuthenticationPluginInterface" + +Q_DECLARE_INTERFACE(AuthenticationPluginInterface, AuthenticationPluginInterface_iid) diff --git a/core/src/BuiltinFeatures.cpp b/core/src/BuiltinFeatures.cpp index 944552382..ef0acccca 100644 --- a/core/src/BuiltinFeatures.cpp +++ b/core/src/BuiltinFeatures.cpp @@ -1,7 +1,7 @@ /* * BuiltinFeatures.cpp - implementation of BuiltinFeatures class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,36 +22,32 @@ * */ +#include "AccessControlProvider.h" #include "BuiltinFeatures.h" -#include "FeatureControl.h" #include "MonitoringMode.h" #include "PluginManager.h" #include "SystemTrayIcon.h" -#include "UserSessionControl.h" #include "DesktopAccessDialog.h" BuiltinFeatures::BuiltinFeatures() : - m_featureControl( new FeatureControl ), m_systemTrayIcon( new SystemTrayIcon ), m_monitoringMode( new MonitoringMode ), m_desktopAccessDialog( new DesktopAccessDialog ), - m_userSessionControl( new UserSessionControl ) + m_accessControlProvider(new AccessControlProvider) { - VeyonCore::pluginManager().registerExtraPluginInterface( m_featureControl ); VeyonCore::pluginManager().registerExtraPluginInterface( m_systemTrayIcon ); VeyonCore::pluginManager().registerExtraPluginInterface( m_monitoringMode ); VeyonCore::pluginManager().registerExtraPluginInterface( m_desktopAccessDialog ); - VeyonCore::pluginManager().registerExtraPluginInterface( m_userSessionControl ); + VeyonCore::pluginManager().registerExtraPluginInterface(m_accessControlProvider); } BuiltinFeatures::~BuiltinFeatures() { - delete m_userSessionControl; delete m_systemTrayIcon; delete m_monitoringMode; delete m_desktopAccessDialog; - delete m_featureControl; + delete m_accessControlProvider; } diff --git a/core/include/BuiltinFeatures.h b/core/src/BuiltinFeatures.h similarity index 81% rename from core/include/BuiltinFeatures.h rename to core/src/BuiltinFeatures.h index 28fe0daa2..9058ce28d 100644 --- a/core/include/BuiltinFeatures.h +++ b/core/src/BuiltinFeatures.h @@ -1,7 +1,7 @@ /* * BuiltinFeatures.h - declaration of BuiltinFeatures class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,11 +26,10 @@ #include "VeyonCore.h" +class AccessControlProvider; class DesktopAccessDialog; -class FeatureControl; class MonitoringMode; class SystemTrayIcon; -class UserSessionControl; // clazy:excludeall=rule-of-three @@ -40,11 +39,6 @@ class VEYON_CORE_EXPORT BuiltinFeatures BuiltinFeatures(); ~BuiltinFeatures(); - FeatureControl& featureControl() - { - return *m_featureControl; - } - SystemTrayIcon& systemTrayIcon() { return *m_systemTrayIcon; @@ -60,15 +54,15 @@ class VEYON_CORE_EXPORT BuiltinFeatures return *m_desktopAccessDialog; } - UserSessionControl& userSessionControl() + AccessControlProvider& accessControlProvider() { - return *m_userSessionControl; + return *m_accessControlProvider; } private: - FeatureControl* m_featureControl; SystemTrayIcon* m_systemTrayIcon; MonitoringMode* m_monitoringMode; DesktopAccessDialog* m_desktopAccessDialog; - UserSessionControl* m_userSessionControl; + AccessControlProvider* m_accessControlProvider; + }; diff --git a/core/src/CommandLineIO.cpp b/core/src/CommandLineIO.cpp index c2cc0573d..a5bf9178a 100644 --- a/core/src/CommandLineIO.cpp +++ b/core/src/CommandLineIO.cpp @@ -1,7 +1,7 @@ /* * CommandLineIO.cpp - text input/output for command line plugins * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,14 +27,15 @@ void CommandLineIO::print( const QString& message ) { - printf( "%s\n", qUtf8Printable( message ) ); + fprintf( stdout, "%s\n", qUtf8Printable( message ) ); + fflush( stdout ); } void CommandLineIO::newline() { - printf( "\n" ); + putc( '\n', stdout ); } @@ -42,6 +43,7 @@ void CommandLineIO::newline() void CommandLineIO::info( const QString &message ) { fprintf( stderr, "[%s] %s\n", qUtf8Printable( VeyonCore::tr( "INFO" ) ), qUtf8Printable( message ) ); + fflush( stderr ); } @@ -49,6 +51,7 @@ void CommandLineIO::info( const QString &message ) void CommandLineIO::warning( const QString &message ) { fprintf( stderr, "[%s] %s\n", qUtf8Printable( VeyonCore::tr( "WARNING" ) ), qUtf8Printable( message ) ); + fflush( stderr ); } @@ -56,6 +59,7 @@ void CommandLineIO::warning( const QString &message ) void CommandLineIO::error( const QString& message ) { fprintf( stderr, "[%s] %s\n", qUtf8Printable( VeyonCore::tr( "ERROR" ) ), qUtf8Printable( message ) ); + fflush( stderr ); } @@ -159,27 +163,28 @@ void CommandLineIO::printExamples( const QString& module, const QString& command void CommandLineIO::printTableRuler( const CommandLineIO::TableColumnWidths& columnWidths, char horizontal, char corner ) { - printf( "%c", corner ); + putc( corner, stdout ); for( const auto& width : columnWidths ) { for( int i = 0; i < width; ++i ) { - printf( "%c", horizontal ); + putc( horizontal, stdout ); } - printf( "%c", corner ); + putc( corner, stdout ); } - printf( "\n" ); + newline(); } void CommandLineIO::printTableRow( const TableColumnWidths& columnWidths, char vertical, const TableRow& row ) { - printf( "%c", vertical ); + putc( vertical, stdout ); for( int col = 0; col < columnWidths.size(); ++col ) { const auto cell = row.value( col ); - printf( " %s%c", qUtf8Printable( cell + QString( columnWidths[col] - cell.size() - 1, QLatin1Char(' ') ) ), vertical ); + fprintf( stdout, " %s%c", qUtf8Printable( cell + QString( columnWidths[col] - cell.size() - 1, QLatin1Char(' ') ) ), vertical ); + fflush( stdout ); } - printf( "\n" ); + newline(); } diff --git a/core/include/CommandLineIO.h b/core/src/CommandLineIO.h similarity index 97% rename from core/include/CommandLineIO.h rename to core/src/CommandLineIO.h index e683d0752..77963d591 100644 --- a/core/include/CommandLineIO.h +++ b/core/src/CommandLineIO.h @@ -1,7 +1,7 @@ /* * CommandLineIO.h - text input/output for command line plugins * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/core/include/CommandLinePluginInterface.h b/core/src/CommandLinePluginInterface.h similarity index 96% rename from core/include/CommandLinePluginInterface.h rename to core/src/CommandLinePluginInterface.h index f3046dfee..a1dd972e7 100644 --- a/core/include/CommandLinePluginInterface.h +++ b/core/src/CommandLinePluginInterface.h @@ -1,7 +1,7 @@ /* * CommandLinePluginInterface.h - interface class for command line plugins * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/core/src/Computer.cpp b/core/src/Computer.cpp index 46706b716..2c1071808 100644 --- a/core/src/Computer.cpp +++ b/core/src/Computer.cpp @@ -1,7 +1,7 @@ /* * Computer.cpp - represents a computer and provides control methods and data * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,13 +25,14 @@ #include "Computer.h" Computer::Computer( NetworkObject::Uid networkObjectUid, - const QString& name, + const QString& displayName, const QString& hostAddress, const QString& macAddress, const QString& location ) : m_networkObjectUid( networkObjectUid ), - m_name( name ), - m_hostAddress( hostAddress ), + m_displayName(displayName), + m_hostName(hostAddress), + m_hostAddress(hostAddress), m_macAddress( macAddress ), m_location( location ) { diff --git a/core/include/Computer.h b/core/src/Computer.h similarity index 71% rename from core/include/Computer.h rename to core/src/Computer.h index 1f77e1f6d..3a1bbfa91 100644 --- a/core/include/Computer.h +++ b/core/src/Computer.h @@ -1,7 +1,7 @@ /* * Computer.h - represents a computer and provides control methods and data * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,7 +24,7 @@ #pragma once -#include +#include #include #include "NetworkObject.h" @@ -33,9 +33,23 @@ class VEYON_CORE_EXPORT Computer { + Q_GADGET public: + enum class NameSource + { + Default, + HostAddress, + SessionClientAddress, + SessionClientName, + SessionHostName, + SessionMetaData, + UserFullName, + UserLoginName, + }; + Q_ENUM(NameSource) + explicit Computer( NetworkObject::Uid networkObjectUid = NetworkObject::Uid(), - const QString& name = {}, + const QString& displayName = {}, const QString& hostAddress = {}, const QString& macAddress = {}, const QString& location = {} ); @@ -55,26 +69,32 @@ class VEYON_CORE_EXPORT Computer return m_networkObjectUid; } - void setName( const QString& name ) + void setDisplayName(const QString& displayName) { - m_name = name; + m_displayName = displayName; } - QString name() const + const QString& displayName() const { - return m_name; + return m_displayName; } - void setHostAddress( const QString& hostAddress ) + void setHostAddress(const QString& hostAddress) { - m_hostAddress = hostAddress; + m_hostName = hostAddress; + m_hostAddress = QHostAddress{hostAddress}; } - QString hostAddress() const + const QHostAddress& hostAddress() const { return m_hostAddress; } + const QString& hostName() const + { + return m_hostName; + } + void setMacAddress( const QString& macAddress ) { m_macAddress = macAddress; @@ -97,11 +117,11 @@ class VEYON_CORE_EXPORT Computer private: NetworkObject::Uid m_networkObjectUid; - QString m_name; - QString m_hostAddress; + QString m_displayName; + QString m_hostName; + QHostAddress m_hostAddress; QString m_macAddress; QString m_location; - }; using ComputerList = QVector; diff --git a/core/src/ComputerControlInterface.cpp b/core/src/ComputerControlInterface.cpp index 999f9d21c..c9fdf38db 100644 --- a/core/src/ComputerControlInterface.cpp +++ b/core/src/ComputerControlInterface.cpp @@ -1,7 +1,7 @@ /* * ComputerControlInterface.cpp - interface class for controlling a computer * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,37 +22,42 @@ * */ +#include "AccessControlProvider.h" #include "BuiltinFeatures.h" #include "ComputerControlInterface.h" #include "Computer.h" -#include "FeatureControl.h" +#include "FeatureManager.h" #include "MonitoringMode.h" -#include "UserSessionControl.h" #include "VeyonConfiguration.h" #include "VeyonConnection.h" #include "VncConnection.h" -ComputerControlInterface::ComputerControlInterface( const Computer& computer, - QObject* parent ) : +ComputerControlInterface::ComputerControlInterface( const Computer& computer, int port, QObject* parent ) : QObject( parent ), m_computer( computer ), - m_state( State::Disconnected ), - m_userLoginName(), - m_userFullName(), - m_scaledScreenSize(), - m_vncConnection( nullptr ), - m_connection( nullptr ), - m_connectionWatchdogTimer( this ), - m_userUpdateTimer( this ), - m_activeFeaturesUpdateTimer( this ) + m_port(port), + m_computerNameSource(VeyonCore::config().computerNameSource()) { + m_pingTimer.setInterval(ConnectionWatchdogPingDelay); + m_pingTimer.setSingleShot(true); + connect(&m_pingTimer, &QTimer::timeout, this, &ComputerControlInterface::ping); + m_connectionWatchdogTimer.setInterval( ConnectionWatchdogTimeout ); m_connectionWatchdogTimer.setSingleShot( true ); connect( &m_connectionWatchdogTimer, &QTimer::timeout, this, &ComputerControlInterface::restartConnection ); - connect( &m_userUpdateTimer, &QTimer::timeout, this, &ComputerControlInterface::updateUser ); - connect( &m_activeFeaturesUpdateTimer, &QTimer::timeout, this, &ComputerControlInterface::updateActiveFeatures ); + m_serverVersionQueryTimer.setInterval(ServerVersionQueryTimeout); + m_serverVersionQueryTimer.setSingleShot(true); + connect( &m_serverVersionQueryTimer, &QTimer::timeout, this, [this]() { + setServerVersion(VeyonCore::ApplicationVersion::Unknown); + }); + + connect(&m_statePollingTimer, &QTimer::timeout, this, [this]() { + updateUser(); + updateSessionInfo(); + updateActiveFeatures(); + }); } @@ -64,36 +69,50 @@ ComputerControlInterface::~ComputerControlInterface() -void ComputerControlInterface::start( QSize scaledScreenSize ) +void ComputerControlInterface::start( QSize scaledFramebufferSize, UpdateMode updateMode ) { // make sure we do not leak stop(); - m_scaledScreenSize = scaledScreenSize; + m_scaledFramebufferSize = scaledFramebufferSize; - if( m_computer.hostAddress().isEmpty() == false ) + if (m_computer.hostName().isEmpty() == false) { - m_vncConnection = new VncConnection(); - m_vncConnection->setHost( m_computer.hostAddress() ); - m_vncConnection->setQuality( VncConnection::Quality::Thumbnail ); - m_vncConnection->setScaledSize( m_scaledScreenSize ); - - enableUpdates(); - - m_connection = new VeyonConnection( m_vncConnection ); + m_connection = new VeyonConnection; - m_vncConnection->start(); - - connect( m_vncConnection, &VncConnection::framebufferUpdateComplete, this, &ComputerControlInterface::resetWatchdog ); - connect( m_vncConnection, &VncConnection::framebufferUpdateComplete, this, &ComputerControlInterface::screenUpdated ); + auto vncConnection = m_connection->vncConnection(); + vncConnection->setHost(m_computer.hostName()); + if( m_port > 0 ) + { + vncConnection->setPort( m_port ); + } + vncConnection->setScaledSize( m_scaledFramebufferSize ); - connect( m_vncConnection, &VncConnection::stateChanged, this, &ComputerControlInterface::updateState ); - connect( m_vncConnection, &VncConnection::stateChanged, this, &ComputerControlInterface::updateUser ); - connect( m_vncConnection, &VncConnection::stateChanged, this, &ComputerControlInterface::updateActiveFeatures ); - connect( m_vncConnection, &VncConnection::stateChanged, this, &ComputerControlInterface::stateChanged ); + connect( vncConnection, &VncConnection::imageUpdated, this, [this]( int x, int y, int w, int h ) + { + Q_EMIT framebufferUpdated( QRect( x, y, w, h ) ); + } ); + connect( vncConnection, &VncConnection::framebufferUpdateComplete, this, [this]() { + resetWatchdog(); + ++m_timestamp; + Q_EMIT scaledFramebufferUpdated(); + } ); + + connect( vncConnection, &VncConnection::stateChanged, this, &ComputerControlInterface::updateState ); + connect(vncConnection, &VncConnection::stateChanged, this, &ComputerControlInterface::setMinimumFramebufferUpdateInterval); + connect(vncConnection, &VncConnection::stateChanged, this, &ComputerControlInterface::updateServerVersion); + connect( vncConnection, &VncConnection::stateChanged, this, &ComputerControlInterface::updateUser ); + connect( vncConnection, &VncConnection::stateChanged, this, &ComputerControlInterface::updateSessionInfo ); + connect( vncConnection, &VncConnection::stateChanged, this, &ComputerControlInterface::updateActiveFeatures ); + connect( vncConnection, &VncConnection::stateChanged, this, &ComputerControlInterface::updateScreens ); + connect( vncConnection, &VncConnection::stateChanged, this, &ComputerControlInterface::stateChanged ); connect( m_connection, &VeyonConnection::featureMessageReceived, this, &ComputerControlInterface::handleFeatureMessage ); connect( m_connection, &VeyonConnection::featureMessageReceived, this, &ComputerControlInterface::resetWatchdog ); + + setUpdateMode( updateMode ); + + vncConnection->start(); } else { @@ -107,114 +126,210 @@ void ComputerControlInterface::stop() { if( m_connection ) { - delete m_connection; + m_connection->stopAndDeleteLater(); m_connection = nullptr; } - if( m_vncConnection ) + m_pingTimer.stop(); + m_connectionWatchdogTimer.stop(); + + m_state = State::Disconnected; +} + + + +QString ComputerControlInterface::computerName() const +{ + const auto propertyOrFallback = [this](const QString& value) { - // do not delete VNC connection but let it delete itself after stopping automatically - m_vncConnection->stopAndDeleteLater(); - m_vncConnection = nullptr; + return value.isEmpty() ? + (computer().displayName().isEmpty() ? computer().hostName() : computer().displayName()) + : + value; + }; + + switch (computerNameSource()) + { + case Computer::NameSource::HostAddress: return propertyOrFallback(computer().hostName()); + case Computer::NameSource::SessionClientName: return propertyOrFallback(sessionInfo().clientName); + case Computer::NameSource::SessionClientAddress: return propertyOrFallback(sessionInfo().clientAddress); + case Computer::NameSource::SessionHostName: return propertyOrFallback(sessionInfo().hostName); + case Computer::NameSource::SessionMetaData: return propertyOrFallback(sessionInfo().metaData); + case Computer::NameSource::UserFullName: return propertyOrFallback(userFullName()); + case Computer::NameSource::UserLoginName: return propertyOrFallback(userLoginName()); + default: + break; } - m_activeFeaturesUpdateTimer.stop(); - m_userUpdateTimer.stop(); - m_connectionWatchdogTimer.stop(); + return propertyOrFallback({}); +} - m_state = State::Disconnected; + + +bool ComputerControlInterface::hasValidFramebuffer() const +{ + return vncConnection() && vncConnection()->hasValidFramebuffer(); +} + + + +QSize ComputerControlInterface::screenSize() const +{ + if( vncConnection() ) + { + return vncConnection()->image().size(); + } + + return {}; } -void ComputerControlInterface::setScaledScreenSize( QSize scaledScreenSize ) +void ComputerControlInterface::setScaledFramebufferSize( QSize scaledFramebufferSize ) { - m_scaledScreenSize = scaledScreenSize; + m_scaledFramebufferSize = scaledFramebufferSize; - if( m_vncConnection ) + if( vncConnection() ) { - m_vncConnection->setScaledSize( m_scaledScreenSize ); + vncConnection()->setScaledSize( m_scaledFramebufferSize ); } - emit screenUpdated(); + ++m_timestamp; + + Q_EMIT scaledFramebufferUpdated(); } -QImage ComputerControlInterface::scaledScreen() const +QImage ComputerControlInterface::scaledFramebuffer() const { - if( m_vncConnection && m_vncConnection->isConnected() ) + if( vncConnection() && vncConnection()->isConnected() ) { - return m_vncConnection->scaledScreen(); + return vncConnection()->scaledFramebuffer(); } - return QImage(); + return {}; } -QImage ComputerControlInterface::screen() const +QImage ComputerControlInterface::framebuffer() const { - if( m_vncConnection && m_vncConnection->isConnected() ) + if( vncConnection() && vncConnection()->isConnected() ) { - return m_vncConnection->image(); + return vncConnection()->image(); } - return QImage(); + return {}; } -void ComputerControlInterface::setUserLoginName( const QString& userLoginName ) +void ComputerControlInterface::setAccessControlFailed(const QString& details) { - if( userLoginName != m_userLoginName ) + lock(); + m_accessControlDetails = details; + m_state = State::AccessControlFailed; + + if (vncConnection()) { - m_userLoginName = userLoginName; + vncConnection()->stop(); + } + unlock(); + + Q_EMIT accessControlDetailsChanged(); + Q_EMIT stateChanged(); +} + + + +void ComputerControlInterface::setServerVersion(VeyonCore::ApplicationVersion version) +{ + m_serverVersionQueryTimer.stop(); + + m_serverVersion = version; - emit userChanged(); + const auto statePollingInterval = VeyonCore::config().computerStatePollingInterval(); + + setQuality(); + + if (m_serverVersion >= VeyonCore::ApplicationVersion::Version_4_7 && + statePollingInterval <= 0) + { + m_statePollingTimer.stop(); + + updateSessionInfo(); + updateScreens(); + setMinimumFramebufferUpdateInterval(); + } + else + { + if (vncConnection()) + { + vncConnection()->setRequiresManualUpdateRateControl(true); + } + + m_statePollingTimer.start(statePollingInterval > 0 ? statePollingInterval : + VeyonCore::config().computerMonitoringUpdateInterval()); } } -void ComputerControlInterface::setUserFullName( const QString& userFullName ) +void ComputerControlInterface::setUserInformation(const QString& userLoginName, const QString& userFullName) { - if( userFullName != m_userFullName ) + if (userLoginName != m_userLoginName || + userFullName != m_userFullName) { + m_userLoginName = userLoginName; m_userFullName = userFullName; - emit userChanged(); + Q_EMIT userChanged(); } } -void ComputerControlInterface::setActiveFeatures( const FeatureUidList& activeFeatures ) +void ComputerControlInterface::setSessionInfo(const PlatformSessionFunctions::SessionInfo& sessionInfo) { - if( activeFeatures != m_activeFeatures ) + if (sessionInfo != m_sessionInfo) { - m_activeFeatures = activeFeatures; + m_sessionInfo = sessionInfo; + Q_EMIT sessionInfoChanged(); + } +} + - emit activeFeaturesChanged(); + +void ComputerControlInterface::setScreens(const ScreenList& screens) +{ + if(screens != m_screens) + { + m_screens = screens; + + Q_EMIT screensChanged(); } } -void ComputerControlInterface::setDesignatedModeFeature( Feature::Uid designatedModeFeature ) +void ComputerControlInterface::setActiveFeatures( const FeatureUidList& activeFeatures ) { - m_designatedModeFeature = designatedModeFeature; + if( activeFeatures != m_activeFeatures ) + { + m_activeFeatures = activeFeatures; - updateActiveFeatures(); + Q_EMIT activeFeaturesChanged(); + } } -void ComputerControlInterface::sendFeatureMessage( const FeatureMessage& featureMessage, bool wake ) +void ComputerControlInterface::sendFeatureMessage(const FeatureMessage& featureMessage) { if( m_connection && m_connection->isConnected() ) { - m_connection->sendFeatureMessage( featureMessage, wake ); + m_connection->sendFeatureMessage(featureMessage); } } @@ -222,9 +337,9 @@ void ComputerControlInterface::sendFeatureMessage( const FeatureMessage& feature bool ComputerControlInterface::isMessageQueueEmpty() { - if( m_vncConnection && m_vncConnection->isConnected() ) + if( vncConnection() && vncConnection()->isConnected() ) { - return m_vncConnection->isEventQueueEmpty(); + return vncConnection()->isEventQueueEmpty(); } return true; @@ -232,30 +347,42 @@ bool ComputerControlInterface::isMessageQueueEmpty() -void ComputerControlInterface::enableUpdates() +void ComputerControlInterface::setUpdateMode( UpdateMode updateMode ) { - const auto updateInterval = VeyonCore::config().computerMonitoringUpdateInterval(); + m_updateMode = updateMode; + + setMinimumFramebufferUpdateInterval(); + setQuality(); - if( m_vncConnection ) + if (vncConnection()) { - m_vncConnection->setFramebufferUpdateInterval( updateInterval ); + vncConnection()->setSkipHostPing(m_updateMode == UpdateMode::Basic || m_updateMode == UpdateMode::FeatureControlOnly); } - - m_userUpdateTimer.start( updateInterval ); - m_activeFeaturesUpdateTimer.start( updateInterval ); } -void ComputerControlInterface::disableUpdates() +void ComputerControlInterface::setProperty(QUuid propertyId, const QVariant& data) { - if( m_vncConnection ) + if (propertyId.isNull() == false) { - m_vncConnection->setFramebufferUpdateInterval( UpdateIntervalWhenDisabled ); + lock(); + m_properties[propertyId] = data; + unlock(); + + Q_EMIT propertyChanged(propertyId); } +} + + + +QVariant ComputerControlInterface::queryProperty(QUuid propertyId) +{ + lock(); + const auto data = m_properties.value(propertyId); + unlock(); - m_userUpdateTimer.stop(); - m_activeFeaturesUpdateTimer.start( UpdateIntervalWhenDisabled ); + return data; } @@ -267,10 +394,92 @@ ComputerControlInterface::Pointer ComputerControlInterface::weakPointer() +void ComputerControlInterface::ping() +{ + if (m_serverVersion >= VeyonCore::ApplicationVersion::Version_4_7) + { + VeyonCore::builtinFeatures().monitoringMode().ping({weakPointer()}); + } +} + + + +void ComputerControlInterface::setMinimumFramebufferUpdateInterval() +{ + auto updateInterval = -1; + + switch (m_updateMode) + { + case UpdateMode::Disabled: + updateInterval = UpdateIntervalDisabled; + break; + + case UpdateMode::Basic: + case UpdateMode::Monitoring: + updateInterval = VeyonCore::config().computerMonitoringUpdateInterval(); + break; + + case UpdateMode::Live: + break; + + case UpdateMode::FeatureControlOnly: + if (vncConnection()) + { + vncConnection()->setSkipFramebufferUpdates(true); + } + break; + } + + if (vncConnection()) + { + vncConnection()->setFramebufferUpdateInterval(updateInterval); + } + + if (m_serverVersion >= VeyonCore::ApplicationVersion::Version_4_7) + { + VeyonCore::builtinFeatures().monitoringMode().setMinimumFramebufferUpdateInterval({weakPointer()}, updateInterval); + } +} + + + +void ComputerControlInterface::setQuality() +{ + auto quality = VncConnectionConfiguration::Quality::Highest; + + if (m_serverVersion >= VeyonCore::ApplicationVersion::Version_4_8) + { + switch (m_updateMode) + { + case UpdateMode::Disabled: + case UpdateMode::FeatureControlOnly: + quality = VncConnectionConfiguration::Quality::Lowest; + break; + + case UpdateMode::Basic: + case UpdateMode::Monitoring: + quality = VeyonCore::config().computerMonitoringImageQuality(); + break; + + case UpdateMode::Live: + quality = VeyonCore::config().remoteAccessImageQuality(); + break; + } + } + + if (vncConnection()) + { + vncConnection()->setQuality(quality); + } +} + + + void ComputerControlInterface::resetWatchdog() { - if( state() == State::Connected ) + if (state() == State::Connected || state() == State::AccessControlFailed) { + m_pingTimer.start(); m_connectionWatchdogTimer.start(); } } @@ -279,10 +488,10 @@ void ComputerControlInterface::resetWatchdog() void ComputerControlInterface::restartConnection() { - if( m_vncConnection ) + if( vncConnection() ) { vDebug(); - m_vncConnection->restart(); + vncConnection()->restart(); m_connectionWatchdogTimer.stop(); } @@ -292,60 +501,150 @@ void ComputerControlInterface::restartConnection() void ComputerControlInterface::updateState() { - if( m_vncConnection ) + lock(); + + if (vncConnection()) { - switch( m_vncConnection->state() ) + if (!(m_state == State::AccessControlFailed && vncConnection()->state() == VncConnection::State::Disconnected)) { - case VncConnection::State::Disconnected: m_state = State::Disconnected; break; - case VncConnection::State::Connecting: m_state = State::Connecting; break; - case VncConnection::State::Connected: m_state = State::Connected; break; - case VncConnection::State::HostOffline: m_state = State::HostOffline; break; - case VncConnection::State::ServiceUnreachable: m_state = State::ServiceUnreachable; break; - case VncConnection::State::AuthenticationFailed: m_state = State::AuthenticationFailed; break; - default: m_state = VncConnection::State::Disconnected; break; + m_state = vncConnection()->state(); } } else { m_state = State::Disconnected; } + + unlock(); +} + + + +void ComputerControlInterface::updateServerVersion() +{ + lock(); + + if (vncConnection()) + { + VeyonCore::builtinFeatures().monitoringMode().queryApplicationVersion({weakPointer()}); + m_serverVersionQueryTimer.start(); + } + + unlock(); +} + + + +void ComputerControlInterface::updateActiveFeatures() +{ + lock(); + + if (vncConnection() && state() == State::Connected) + { + VeyonCore::builtinFeatures().monitoringMode().queryActiveFeatures({weakPointer()}); + } + else + { + setActiveFeatures({}); + } + + unlock(); } void ComputerControlInterface::updateUser() { - if( m_vncConnection && m_connection && state() == State::Connected ) + lock(); + + if( vncConnection() && state() == State::Connected ) { if( userLoginName().isEmpty() ) { - VeyonCore::builtinFeatures().userSessionControl().getUserSessionInfo( { weakPointer() } ); + VeyonCore::builtinFeatures().monitoringMode().queryUserInfo( { weakPointer() } ); } } else { - setUserLoginName( {} ); - setUserFullName( {} ); + setUserInformation({}, {}); } + + unlock(); } -void ComputerControlInterface::updateActiveFeatures() +void ComputerControlInterface::updateSessionInfo() +{ + lock(); + + if (vncConnection() && state() == State::Connected && + m_serverVersion >= VeyonCore::ApplicationVersion::Version_4_8) + { + VeyonCore::builtinFeatures().monitoringMode().querySessionInfo({weakPointer()}); + } + else + { + setSessionInfo({}); + } + + unlock(); +} + + + +void ComputerControlInterface::updateScreens() { - if( m_vncConnection && m_connection && state() == State::Connected ) + lock(); + + if (vncConnection() && state() == State::Connected && + m_serverVersion >= VeyonCore::ApplicationVersion::Version_4_7) { - VeyonCore::builtinFeatures().featureControl().queryActiveFeatures( { weakPointer() } ); + VeyonCore::builtinFeatures().monitoringMode().queryScreens({weakPointer()}); } else { - setActiveFeatures( {} ); + setScreens({}); } + + unlock(); } void ComputerControlInterface::handleFeatureMessage( const FeatureMessage& message ) { - emit featureMessageReceived( message, weakPointer() ); + lock(); + VeyonCore::featureManager().handleFeatureMessage( weakPointer(), message ); + unlock(); +} + + + +QDebug operator<<(QDebug stream, ComputerControlInterface::Pointer computerControlInterface) +{ + if (computerControlInterface.isNull() == false) + { + stream << qUtf8Printable(computerControlInterface->computer().hostName()); + } + return stream; +} + + + +QDebug operator<<(QDebug stream, const ComputerControlInterfaceList& computerControlInterfaces) +{ + QStringList hostAddresses; + hostAddresses.reserve(computerControlInterfaces.size()); + for(const auto& computerControlInterface : computerControlInterfaces) + { + if (computerControlInterface.isNull() == false) + { + hostAddresses.append(computerControlInterface->computer().hostName()); + } + } + + stream << QStringLiteral("[%1]").arg(hostAddresses.join(QLatin1Char(','))).toUtf8().constData(); + + return stream; } diff --git a/core/src/ComputerControlInterface.h b/core/src/ComputerControlInterface.h new file mode 100644 index 000000000..5f0839aa6 --- /dev/null +++ b/core/src/ComputerControlInterface.h @@ -0,0 +1,280 @@ +/* + * ComputerControlInterface.h - interface class for controlling a computer + * + * Copyright (c) 2017-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "Computer.h" +#include "Feature.h" +#include "Lockable.h" +#include "PlatformSessionFunctions.h" +#include "VeyonCore.h" +#include "VeyonConnection.h" + +class VEYON_CORE_EXPORT ComputerControlInterface : public QObject, public Lockable +{ + Q_OBJECT +public: + enum class UpdateMode { + Disabled, + Basic, + Monitoring, + Live, + FeatureControlOnly, + }; + + using Pointer = QSharedPointer; + + using State = VncConnection::State; + + struct ScreenProperties { + int index; + QString name; + QRect geometry; + bool operator==(const ScreenProperties& other) const + { + return other.index == index && + other.name == name && + other.geometry == geometry; + } + }; + using ScreenList = QList; + + explicit ComputerControlInterface( const Computer& computer, int port = -1, QObject* parent = nullptr ); + ~ComputerControlInterface() override; + + VeyonConnection* connection() const + { + return m_connection; + } + + VncConnection* vncConnection() const + { + return m_connection ? m_connection->vncConnection() : nullptr; + } + + void start( QSize scaledFramebufferSize = {}, UpdateMode updateMode = UpdateMode::Monitoring ); + void stop(); + + const Computer& computer() const + { + return m_computer; + } + + QString computerName() const; + + Computer::NameSource computerNameSource() const + { + return m_computerNameSource; + } + + State state() const + { + return m_state; + } + + bool hasValidFramebuffer() const; + + QSize screenSize() const; + + const QSize& scaledFramebufferSize() const + { + return m_scaledFramebufferSize; + } + + void setScaledFramebufferSize( QSize size ); + + QImage scaledFramebuffer() const; + + QImage framebuffer() const; + + int timestamp() const + { + return m_timestamp; + } + + const QString& accessControlDetails() const + { + return m_accessControlDetails; + } + + void setAccessControlFailed(const QString& details); + + VeyonCore::ApplicationVersion serverVersion() const + { + return m_serverVersion; + } + + void setServerVersion(VeyonCore::ApplicationVersion version); + + const QString& userLoginName() const + { + return m_userLoginName; + } + + const QString& userFullName() const + { + return m_userFullName; + } + + void setUserInformation(const QString& userLoginName, const QString& userFullName); + + const PlatformSessionFunctions::SessionInfo& sessionInfo() const + { + return m_sessionInfo; + } + + void setSessionInfo(const PlatformSessionFunctions::SessionInfo& sessionInfo); + + const ScreenList& screens() const + { + return m_screens; + } + + void setScreens(const ScreenList& screens); + + const FeatureUidList& activeFeatures() const + { + return m_activeFeatures; + } + + void setActiveFeatures( const FeatureUidList& activeFeatures ); + + Feature::Uid designatedModeFeature() const + { + return m_designatedModeFeature; + } + + void setDesignatedModeFeature( Feature::Uid designatedModeFeature ) + { + m_designatedModeFeature = designatedModeFeature; + } + + const QStringList& groups() const + { + return m_groups; + } + + void setGroups( const QStringList& groups ) + { + m_groups = groups; + } + + void sendFeatureMessage(const FeatureMessage& featureMessage); + bool isMessageQueueEmpty(); + + void setUpdateMode( UpdateMode updateMode ); + UpdateMode updateMode() const + { + return m_updateMode; + } + + void setProperty(QUuid propertyId, const QVariant& data); + + QVariant queryProperty(QUuid propertyId); + + Pointer weakPointer(); + + template + void executeIfConnected(const T& functor) + { + connect(this, &ComputerControlInterface::stateChanged, this, [this, functor]() { + if (state() == State::Connected) + { + functor(); + } + }); + } + +private: + void ping(); + void setMinimumFramebufferUpdateInterval(); + void setQuality(); + void resetWatchdog(); + void restartConnection(); + + void updateState(); + void updateServerVersion(); + void updateActiveFeatures(); + void updateUser(); + void updateSessionInfo(); + void updateScreens(); + + void handleFeatureMessage( const FeatureMessage& message ); + + static constexpr int ConnectionWatchdogPingDelay = 10000; + static constexpr int ConnectionWatchdogTimeout = ConnectionWatchdogPingDelay*2; + static constexpr int ServerVersionQueryTimeout = 5000; + static constexpr int UpdateIntervalDisabled = 5000; + + const Computer m_computer; + const int m_port; + + UpdateMode m_updateMode{UpdateMode::Disabled}; + Computer::NameSource m_computerNameSource{Computer::NameSource::Default}; + + State m_state{State::Disconnected}; + QString m_userLoginName{}; + QString m_userFullName{}; + PlatformSessionFunctions::SessionInfo m_sessionInfo{}; + ScreenList m_screens; + FeatureUidList m_activeFeatures; + Feature::Uid m_designatedModeFeature; + + QSize m_scaledFramebufferSize{}; + int m_timestamp{0}; + + VeyonConnection* m_connection{nullptr}; + QTimer m_pingTimer{this}; + QTimer m_connectionWatchdogTimer{this}; + + VeyonCore::ApplicationVersion m_serverVersion{VeyonCore::ApplicationVersion::Unknown}; + QTimer m_serverVersionQueryTimer{this}; + + QString m_accessControlDetails{}; + QTimer m_statePollingTimer{this}; + + QStringList m_groups; + + QMap m_properties; + +Q_SIGNALS: + void accessControlDetailsChanged(); + void framebufferSizeChanged(); + void framebufferUpdated( QRect rect ); + void scaledFramebufferUpdated(); + void userChanged(); + void sessionInfoChanged(); + void screensChanged(); + void stateChanged(); + void activeFeaturesChanged(); + void propertyChanged(QUuid propertyId); + +}; + +using ComputerControlInterfaceList = QVector; + +VEYON_CORE_EXPORT QDebug operator<<(QDebug stream, ComputerControlInterface::Pointer computerControlInterface); +VEYON_CORE_EXPORT QDebug operator<<(QDebug stream, const ComputerControlInterfaceList& computerControlInterfaces); + +Q_DECLARE_METATYPE(ComputerControlInterface::Pointer) diff --git a/core/src/ComputerListModel.cpp b/core/src/ComputerListModel.cpp new file mode 100644 index 000000000..f6feab1be --- /dev/null +++ b/core/src/ComputerListModel.cpp @@ -0,0 +1,77 @@ +/* + * ComputerListModel.cpp - data model base class for computer objects + * + * Copyright (c) 2017-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "ComputerListModel.h" +#include "VeyonConfiguration.h" + + +ComputerListModel::ComputerListModel( QObject* parent ) : + QAbstractListModel( parent ), + m_displayRoleContent( VeyonCore::config().computerDisplayRoleContent() ), + m_uidRoleContent(VeyonCore::config().computerUidRoleContent()), + m_sortOrder( VeyonCore::config().computerMonitoringSortOrder() ), + m_aspectRatio( VeyonCore::config().computerMonitoringAspectRatio() ) +{ +} + + + +Qt::ItemFlags ComputerListModel::flags( const QModelIndex& index ) const +{ + auto defaultFlags = QAbstractListModel::flags( index ); + + if( index.isValid() ) + { + return Qt::ItemIsDragEnabled | defaultFlags; + } + + return Qt::ItemIsDropEnabled | defaultFlags; +} + + + +QHash ComputerListModel::roleNames() const +{ + auto roles = QAbstractListModel::roleNames(); + roles[UidRole] = "uid"; + roles[StateRole] = "state"; + roles[UserLoginNameRole] = "userLoginName"; + roles[ImageIdRole] = "imageId"; + roles[GroupsRole] = "groups"; + return roles; +} + + + +Qt::DropActions ComputerListModel::supportedDragActions() const +{ + return Qt::MoveAction; +} + + + +Qt::DropActions ComputerListModel::supportedDropActions() const +{ + return Qt::MoveAction; +} diff --git a/core/src/ComputerListModel.h b/core/src/ComputerListModel.h new file mode 100644 index 000000000..4836c8736 --- /dev/null +++ b/core/src/ComputerListModel.h @@ -0,0 +1,110 @@ +/* + * ComputerListModel.h - data model base class for computer objects + * + * Copyright (c) 2017-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +#include "VeyonCore.h" + +class VEYON_CORE_EXPORT ComputerListModel : public QAbstractListModel +{ + Q_OBJECT +public: + enum { + UidRole = Qt::UserRole, + StateRole, + UserLoginNameRole, + ImageIdRole, + GroupsRole, + FramebufferRole, + ControlInterfaceRole + }; + + enum class DisplayRoleContent { + UserAndComputerName, + UserName, + ComputerName, + }; + Q_ENUM(DisplayRoleContent) + + enum class UidRoleContent { + NetworkObjectUid, + SessionMetaDataHash, + }; + Q_ENUM(UidRoleContent) + + enum class SortOrder { + ComputerAndUserName, + UserName, + LastPartOfUserName, + ComputerName, + }; + Q_ENUM(SortOrder) + + enum class AspectRatio { + Auto, + AR16_9, + AR16_10, + AR3_2, + AR4_3 + }; + Q_ENUM(AspectRatio) + + explicit ComputerListModel( QObject* parent = nullptr ); + + Qt::ItemFlags flags( const QModelIndex& index ) const override; + + QHash roleNames() const override; + + Qt::DropActions supportedDragActions() const override; + Qt::DropActions supportedDropActions() const override; + + DisplayRoleContent displayRoleContent() const + { + return m_displayRoleContent; + } + + UidRoleContent uidRoleContent() const + { + return m_uidRoleContent; + } + + SortOrder sortOrder() const + { + return m_sortOrder; + } + + AspectRatio aspectRatio() const + { + return m_aspectRatio; + } + +private: + DisplayRoleContent m_displayRoleContent; + UidRoleContent m_uidRoleContent; + SortOrder m_sortOrder; + AspectRatio m_aspectRatio; + +}; diff --git a/core/src/Configuration/JsonStore.cpp b/core/src/Configuration/JsonStore.cpp index 25840b722..2da8824e5 100644 --- a/core/src/Configuration/JsonStore.cpp +++ b/core/src/Configuration/JsonStore.cpp @@ -1,7 +1,7 @@ /* * Configuration/JsonStore.cpp - implementation of JsonStore * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -37,8 +37,8 @@ namespace Configuration { -JsonStore::JsonStore( Scope scope, const QString &file ) : - Store( Store::JsonFile, scope ), +JsonStore::JsonStore(Scope scope, const QString &file) : + Store(Store::Backend::JsonFile, scope), m_file( file ) { } @@ -98,23 +98,27 @@ static QJsonObject saveJsonTree( const Object::DataMap& dataMap ) for( auto it = dataMap.begin(); it != dataMap.end(); ++it ) { - if( it.value().type() == QVariant::Map ) + if (it.value().userType() == QMetaType::QVariantMap) { jsonData[it.key()] = saveJsonTree( it.value().toMap() ); } - else if( static_cast( it.value().type() ) == QMetaType::QJsonArray ) + else if (it.value().userType() == QMetaType::QJsonArray) { QJsonObject jsonObj; jsonObj[QStringLiteral("JsonStoreArray")] = it.value().toJsonArray(); jsonData[it.key()] = jsonObj; } - else if( static_cast( it.value().type() ) == QMetaType::QJsonObject ) + else if (it.value().userType() == QMetaType::QJsonObject ) { QJsonObject jsonObj; jsonObj[QStringLiteral("JsonStoreObject")] = it.value().toJsonObject(); jsonData[it.key()] = jsonObj; } - else if( QMetaType( it.value().userType() ).flags().testFlag( QMetaType::IsEnumeration ) ) +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + else if (it.value().metaType().flags().testFlag(QMetaType::IsEnumeration) ) +#else + else if (QMetaType(it.value().userType()).flags().testFlag(QMetaType::IsEnumeration) ) +#endif { jsonData[it.key()] = QJsonValue( it.value().toInt() ); } @@ -166,18 +170,18 @@ void JsonStore::clear() QString JsonStore::configurationFilePath() const { - if( m_file.isEmpty() == false ) + if (m_file.isEmpty() == false) { return m_file; } QString base; - switch( scope() ) + switch (scope()) { - case User: + case Scope::User: base = VeyonCore::config().userConfigurationDirectory(); break; - case System: + case Scope::System: base = VeyonCore::platform().filesystemFunctions().globalAppDataPath(); break; } diff --git a/core/include/Configuration/JsonStore.h b/core/src/Configuration/JsonStore.h similarity index 89% rename from core/include/Configuration/JsonStore.h rename to core/src/Configuration/JsonStore.h index 660ea9111..f5bbbf9bb 100644 --- a/core/include/Configuration/JsonStore.h +++ b/core/src/Configuration/JsonStore.h @@ -1,7 +1,7 @@ /* * Configuration/JsonStore.h - JsonStore class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,6 +25,7 @@ #pragma once #include "Configuration/Store.h" +#include "VeyonCore.h" namespace Configuration { @@ -34,7 +35,7 @@ namespace Configuration class VEYON_CORE_EXPORT JsonStore : public Store { public: - explicit JsonStore( Scope scope, const QString & file = {} ); + explicit JsonStore(Scope scope, const QString & file = {}); void load( Object *obj ) override; void flush( const Object *obj ) override; diff --git a/core/src/Configuration/LocalStore.cpp b/core/src/Configuration/LocalStore.cpp index 32ab493dd..48add5055 100644 --- a/core/src/Configuration/LocalStore.cpp +++ b/core/src/Configuration/LocalStore.cpp @@ -1,7 +1,7 @@ /* * ConfigurationLocalStore.cpp - implementation of LocalStore * - * Copyright (c) 2009-2019 Tobias Junghans + * Copyright (c) 2009-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,9 +22,11 @@ * */ +#include #include #include #include +#include #include #include "Configuration/LocalStore.h" @@ -35,7 +37,7 @@ namespace Configuration { LocalStore::LocalStore( Scope scope ) : - Store( Store::LocalBackend, scope ) + Store(Store::Backend::Local, scope) { } @@ -60,12 +62,13 @@ static void loadSettingsTree( Object *obj, QSettings *s, for( const auto& k : childKeys ) { - QString stringValue = s->value( k ).toString(); - QRegExp jsonValueRX( QStringLiteral("@JsonValue(\\(.*\\))") ); + const auto stringValue = s->value( k ).toString(); + static const QRegularExpression jsonValueRX(QStringLiteral("^@JsonValue(\\(.*\\))$")); + const auto jsonValueMatch = jsonValueRX.match(stringValue); - if( jsonValueRX.indexIn( stringValue ) == 0 ) + if( jsonValueMatch.hasMatch() ) { - auto jsonValue = QJsonDocument::fromJson( QByteArray::fromBase64( jsonValueRX.cap( 1 ).toUtf8() ) ).object(); + auto jsonValue = QJsonDocument::fromJson( QByteArray::fromBase64( jsonValueMatch.captured( 1 ).toUtf8() ) ).object(); if( jsonValue.contains( QStringLiteral( "a" ) ) ) { obj->setValue( k, jsonValue[QStringLiteral("a")].toArray(), parentKey ); @@ -124,21 +127,25 @@ static void saveSettingsTree( const Object::DataMap &dataMap, QSettings *s ) { for( auto it = dataMap.begin(); it != dataMap.end(); ++it ) { - if( it.value().type() == QVariant::Map ) + if (it.value().userType() == QMetaType::QVariantMap) { s->beginGroup( it.key() ); saveSettingsTree( it.value().toMap(), s ); s->endGroup(); } - else if( static_cast( it.value().type() ) == QMetaType::QJsonArray ) + else if (it.value().userType() == QMetaType::QJsonArray) { s->setValue( it.key(), serializeJsonValue( it.value().toJsonArray() ) ); } - else if( static_cast( it.value().type() ) == QMetaType::QJsonObject ) + else if (it.value().userType() == QMetaType::QJsonObject) { s->setValue( it.key(), serializeJsonValue( it.value().toJsonObject() ) ); } - else if( QMetaType( it.value().userType() ).flags().testFlag( QMetaType::IsEnumeration ) ) +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + else if (it.value().metaType().flags().testFlag(QMetaType::IsEnumeration)) +#else + else if( QMetaType(it.value().userType()).flags().testFlag(QMetaType::IsEnumeration)) +#endif { s->setValue( it.key(), it.value().toInt() ); } @@ -186,10 +193,15 @@ void LocalStore::clear() QSettings *LocalStore::createSettingsObject() const { - return new QSettings( scope() == System ? - QSettings::SystemScope : QSettings::UserScope, - QSettings().organizationName(), - QSettings().applicationName() ); + return new QSettings( +#ifdef Q_OS_WIN + QSettings::Registry64Format, +#else + QSettings::NativeFormat, +#endif + scope() == Scope::System ? QSettings::SystemScope : QSettings::UserScope, + QCoreApplication::organizationName(), + QCoreApplication::applicationName()); } diff --git a/core/include/Configuration/LocalStore.h b/core/src/Configuration/LocalStore.h similarity index 93% rename from core/include/Configuration/LocalStore.h rename to core/src/Configuration/LocalStore.h index 97ed9a91a..8abd64614 100644 --- a/core/include/Configuration/LocalStore.h +++ b/core/src/Configuration/LocalStore.h @@ -1,7 +1,7 @@ /* * Configuration/LocalStore.h - LocalStore class * - * Copyright (c) 2009-2019 Tobias Junghans + * Copyright (c) 2009-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,6 +25,7 @@ #pragma once #include "Configuration/Store.h" +#include "VeyonCore.h" class QSettings; diff --git a/core/src/Configuration/Object.cpp b/core/src/Configuration/Object.cpp index 5bb429800..e37586121 100644 --- a/core/src/Configuration/Object.cpp +++ b/core/src/Configuration/Object.cpp @@ -1,7 +1,7 @@ /* * ConfigurationObject.cpp - implementation of ConfigurationObject * - * Copyright (c) 2009-2019 Tobias Junghans + * Copyright (c) 2009-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -30,20 +30,8 @@ namespace Configuration { - -Object::Object() : - m_store( nullptr ), - m_customStore( false ), - m_data() -{ -} - - - Object::Object( Store::Backend backend, Store::Scope scope, const QString& storeName ) : - m_store( createStore( backend, scope ) ), - m_customStore( false ), - m_data() + m_store( createStore( backend, scope ) ) { m_store->setName( storeName ); @@ -54,17 +42,14 @@ Object::Object( Store::Backend backend, Store::Scope scope, const QString& store Object::Object( Store* store ) : m_store( store ), - m_customStore( true ), - m_data() + m_customStore( true ) { reloadFromStore(); } -Object::Object( const Object& obj ) : - m_store( nullptr ), - m_customStore( false ) +Object::Object( const Object& obj ) { *this = obj; } @@ -108,11 +93,11 @@ Object& Object::operator=( const Object& ref ) // allow easy merging of two data maps - source is dominant over destination -static Object::DataMap operator+( Object::DataMap dst, Object::DataMap src ) +static Object::DataMap operator+(Object::DataMap dst, const Object::DataMap& src) { for( auto it = src.begin(), end = src.end(); it != end; ++it ) { - if( it.value().type() == QVariant::Map && dst.contains( it.key() ) ) + if (it.value().userType() == QMetaType::QVariantMap && dst.contains(it.key())) { dst[it.key()] = dst[it.key()].toMap() + it.value().toMap(); } @@ -151,8 +136,8 @@ bool Object::hasValue( const QString& key, const QString& parentKey ) const for( const auto& level : subLevels ) { - if( currentMap.contains( level ) && - currentMap[level].type() == QVariant::Map ) + if (currentMap.contains(level) && + currentMap[level].userType() == QMetaType::QVariantMap) { currentMap = currentMap[level].toMap(); } @@ -188,8 +173,8 @@ QVariant Object::value( const QString& key, const QString& parentKey, const QVar DataMap currentMap = m_data; for( const auto& level : subLevels ) { - if( currentMap.contains( level ) && - currentMap[level].type() == QVariant::Map ) + if (currentMap.contains(level) && + currentMap[level].userType() == QMetaType::QVariantMap) { currentMap = currentMap[level].toMap(); } @@ -218,7 +203,7 @@ static Object::DataMap setValueRecursive( Object::DataMap data, if( subLevels.isEmpty() ) { // search for key in toplevel data map - if( !data.contains( key ) || data[key].type() != QVariant::Map ) + if( !data.contains( key ) || data[key].userType() != QMetaType::QVariantMap) { data[key] = value; } @@ -233,7 +218,7 @@ static Object::DataMap setValueRecursive( Object::DataMap data, const QString level = subLevels.takeFirst(); if( data.contains( level ) ) { - if( data[level].type() != QVariant::Map ) + if( data[level].userType() != QMetaType::QVariantMap) { vWarning() << "parent key points doesn't point to a data map!"; return data; @@ -262,7 +247,7 @@ void Object::setValue( const QString& key, const QVariant& value, const QString& if( data != m_data ) { m_data = data; - emit configurationChanged(); + Q_EMIT configurationChanged(); } } @@ -285,7 +270,7 @@ static Object::DataMap removeValueRecursive( Object::DataMap data, } const QString level = subLevels.takeFirst(); - if( data.contains( level ) && data[level].type() == QVariant::Map ) + if (data.contains(level) && data[level].userType() != QMetaType::QVariantMap) { data[level] = removeValueRecursive( data[level].toMap(), subLevels, key ); } @@ -304,7 +289,7 @@ void Object::removeValue( const QString& key, const QString& parentKey ) if( data != m_data ) { m_data = data; - emit configurationChanged(); + Q_EMIT configurationChanged(); } } @@ -317,7 +302,7 @@ static void addSubObjectRecursive( const Object::DataMap& dataMap, { for( auto it = dataMap.begin(), end = dataMap.end(); it != end; ++it ) { - if( it.value().type() == QVariant::Map ) + if (it.value().userType() != QMetaType::QVariantMap) { auto newParentKey = it.key(); if( parentKey.isEmpty() == false ) @@ -346,9 +331,9 @@ Store* Object::createStore( Store::Backend backend, Store::Scope scope ) { switch( backend ) { - case Store::LocalBackend: return new LocalStore( scope ); - case Store::JsonFile: return new JsonStore( scope ); - case Store::NoBackend: + case Store::Backend::Local: return new LocalStore(scope); + case Store::Backend::JsonFile: return new JsonStore(scope); + case Store::Backend::None: break; default: vCritical() << "invalid store" << backend << "selected"; diff --git a/core/include/Configuration/Object.h b/core/src/Configuration/Object.h similarity index 92% rename from core/include/Configuration/Object.h rename to core/src/Configuration/Object.h index 357ef94c0..b09e7deab 100644 --- a/core/include/Configuration/Object.h +++ b/core/src/Configuration/Object.h @@ -1,7 +1,7 @@ /* * Configuration/Object.h - ConfigurationObject class * - * Copyright (c) 2009-2019 Tobias Junghans + * Copyright (c) 2009-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -38,7 +38,7 @@ class VEYON_CORE_EXPORT Object : public QObject public: using DataMap = QMap; - Object(); + Object() = default; Object( Store::Backend backend, Store::Scope scope, const QString& storeName = {} ); explicit Object( Store* store ); Object( const Object& ); @@ -89,16 +89,16 @@ class VEYON_CORE_EXPORT Object : public QObject } -signals: +Q_SIGNALS: void configurationChanged(); private: static Store* createStore( Store::Backend backend, Store::Scope scope ); - Configuration::Store *m_store; - bool m_customStore; - DataMap m_data; + Configuration::Store* m_store{nullptr}; + bool m_customStore{false}; + DataMap m_data{}; } ; diff --git a/core/src/Configuration/Password.cpp b/core/src/Configuration/Password.cpp index e7613f5e1..5df56acd3 100644 --- a/core/src/Configuration/Password.cpp +++ b/core/src/Configuration/Password.cpp @@ -1,7 +1,7 @@ /* * Password.cpp - implementation of Configuration::Password * - * Copyright (c) 2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -29,14 +29,14 @@ namespace Configuration { -QString Password::plainText() const +CryptoCore::PlaintextPassword Password::plainText() const { return VeyonCore::cryptoCore().decryptPassword( m_encrypted ); } -Password Password::fromPlainText( const QString& plaintext ) +Password Password::fromPlainText( const CryptoCore::PlaintextPassword& plaintext ) { Password password; password.m_encrypted = VeyonCore::cryptoCore().encryptPassword( plaintext ); diff --git a/core/include/Configuration/Password.h b/core/src/Configuration/Password.h similarity index 84% rename from core/include/Configuration/Password.h rename to core/src/Configuration/Password.h index 97d59ae63..9d09a134d 100644 --- a/core/include/Configuration/Password.h +++ b/core/src/Configuration/Password.h @@ -1,7 +1,7 @@ /* * Configuration/Password.h - Configuration::Password class * - * Copyright (c) 2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,7 +24,7 @@ #pragma once -#include "VeyonCore.h" +#include "CryptoCore.h" namespace Configuration { @@ -35,14 +35,14 @@ class VEYON_CORE_EXPORT Password public: Password() = default; - QString plainText() const; + CryptoCore::PlaintextPassword plainText() const; const QString& encrypted() const { return m_encrypted; } - static Password fromPlainText( const QString& plainText ); + static Password fromPlainText( const CryptoCore::PlaintextPassword& plainText ); static Password fromEncrypted( const QString& encrypted ); private: diff --git a/core/src/Configuration/Property.cpp b/core/src/Configuration/Property.cpp index de1ab6dc7..fd33ce4ab 100644 --- a/core/src/Configuration/Property.cpp +++ b/core/src/Configuration/Property.cpp @@ -1,7 +1,7 @@ /* * ConfigurationObject.cpp - implementation of ConfigurationObject * - * Copyright (c) 2009-2019 Tobias Junghans + * Copyright (c) 2009-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -32,6 +32,7 @@ namespace Configuration Configuration::Property::Property( Object* object, const QString& key, const QString& parentKey, const QVariant& defaultValue, Flags flags ) : + QObject( object ), m_object( object ), m_proxy( nullptr ), m_key( key ), @@ -45,6 +46,7 @@ Configuration::Property::Property( Object* object, const QString& key, const QSt Configuration::Property::Property( Proxy* proxy, const QString& key, const QString& parentKey, const QVariant& defaultValue, Flags flags ) : + QObject( proxy->object() ), m_object( nullptr ), m_proxy( proxy ), m_key( key ), @@ -52,6 +54,10 @@ Configuration::Property::Property( Proxy* proxy, const QString& key, const QStri m_defaultValue( defaultValue ), m_flags( flags ) { + connect (proxy, &QObject::destroyed, this, [this]() { + setParent(nullptr); + deleteLater(); + }); } @@ -74,7 +80,8 @@ QVariant Property::variantValue() const { return m_object->value( m_key, m_parentKey, m_defaultValue ); } - else if( m_proxy ) + + if( m_proxy ) { return m_proxy->value( m_key, m_parentKey, m_defaultValue ); } @@ -84,7 +91,7 @@ QVariant Property::variantValue() const -void Property::setVariantValue( const QVariant& value ) +void Property::setVariantValue( const QVariant& value ) const { if( m_object ) { @@ -96,8 +103,24 @@ void Property::setVariantValue( const QVariant& value ) } else { - qFatal(Q_FUNC_INFO); + vCritical(); + } +} + + + +Property* Property::find( QObject* parent, const QString& key, const QString& parentKey ) +{ + const auto properties = parent->findChildren(); + for( auto property : properties ) + { + if( property->m_key == key && property->m_parentKey == parentKey ) + { + return property; + } } + + return nullptr; } @@ -111,7 +134,7 @@ Password Configuration::TypedProperty::value() const template<> -void Configuration::TypedProperty::setValue( const Password& value ) +void Configuration::TypedProperty::setValue( const Password& value ) const { setVariantValue( value.encrypted() ); } diff --git a/core/include/Configuration/Property.h b/core/src/Configuration/Property.h similarity index 77% rename from core/include/Configuration/Property.h rename to core/src/Configuration/Property.h index 0726676cc..0b9f33bf0 100644 --- a/core/include/Configuration/Property.h +++ b/core/src/Configuration/Property.h @@ -1,7 +1,7 @@ /* * Configuration/Property.h - Configuration::Property class * - * Copyright (c) 2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,7 +26,6 @@ #include -#include "QtCompat.h" #include "VeyonCore.h" #include "Configuration/Password.h" @@ -53,8 +52,11 @@ template<> struct CheapestType { using Type = QUuid; }; template struct CheapestType { using Type = T *; }; +// clazy:excludeall=ctor-missing-parent-argument + class VEYON_CORE_EXPORT Property : public QObject { + Q_OBJECT public: enum class Flag { @@ -66,7 +68,7 @@ class VEYON_CORE_EXPORT Property : public QObject Q_DECLARE_FLAGS(Flags, Flag) // work around QTBUG-47652 where Q_FLAG() is broken for enum classes when using Qt < 5.12 -#if QT_VERSION >= 0x051200 +#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) Q_FLAG(Flags) #endif @@ -80,7 +82,39 @@ class VEYON_CORE_EXPORT Property : public QObject QVariant variantValue() const; - void setVariantValue( const QVariant& value ); + void setVariantValue( const QVariant& value ) const; + + static Property* find( QObject* parent, const QString& key, const QString& parentKey ); + + const QString& key() const + { + return m_key; + } + + const QString& parentKey() const + { + return m_parentKey; + } + + QString absoluteKey() const + { + if( m_parentKey.isEmpty() ) + { + return m_key; + } + + return m_parentKey + QLatin1Char('/') + m_key; + } + + const QVariant& defaultValue() const + { + return m_defaultValue; + } + + Flags flags() const + { + return m_flags; + } private: Object* m_object; @@ -94,7 +128,8 @@ class VEYON_CORE_EXPORT Property : public QObject template -class VEYON_CORE_EXPORT TypedProperty : public Property { +class TypedProperty : public Property +{ public: using Type = typename CheapestType::Type; @@ -112,10 +147,10 @@ class VEYON_CORE_EXPORT TypedProperty : public Property { T value() const { - return QVariantHelper::value( variantValue() ); + return variantValue().template value(); } - void setValue( Type value ) + void setValue( Type value ) const { setVariantValue( QVariant::fromValue( value ) ); } @@ -125,28 +160,24 @@ template<> VEYON_CORE_EXPORT Password TypedProperty::value() const; template<> -VEYON_CORE_EXPORT void TypedProperty::setValue( const Password& value ); +VEYON_CORE_EXPORT void TypedProperty::setValue( const Password& value ) const; #define DECLARE_CONFIG_PROPERTY(className,config,type, name, setter, key, parentKey, defaultValue, flags) \ private: \ - Configuration::TypedProperty m_##name{this, QStringLiteral(key), QStringLiteral(parentKey), defaultValue, flags}; \ + const Configuration::TypedProperty* m_##name{ new Configuration::TypedProperty( this, QStringLiteral(key), QStringLiteral(parentKey), defaultValue, flags ) }; \ public: \ type name() const \ { \ - return m_##name.value(); \ + return m_##name->value(); \ } \ const Configuration::TypedProperty& name##Property() const \ { \ - return m_##name; \ - } \ - Configuration::TypedProperty& name##Property() \ - { \ - return m_##name; \ + return *m_##name; \ } \ - void setter( Configuration::TypedProperty::Type value ) \ + void setter( Configuration::TypedProperty::Type value ) const \ { \ - m_##name.setValue( value ); \ + m_##name->setValue( value ); \ } } diff --git a/core/src/Configuration/Proxy.cpp b/core/src/Configuration/Proxy.cpp index 0ce7284e6..d39659f63 100644 --- a/core/src/Configuration/Proxy.cpp +++ b/core/src/Configuration/Proxy.cpp @@ -1,7 +1,7 @@ /* * Proxy.cpp - implementation of Configuration::Proxy * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -28,8 +28,7 @@ namespace Configuration { -Proxy::Proxy(Object *object, QObject *parent) : - QObject( parent ), +Proxy::Proxy( Object* object ) : m_object( object ), m_instanceId() { diff --git a/core/include/Configuration/Proxy.h b/core/src/Configuration/Proxy.h similarity index 86% rename from core/include/Configuration/Proxy.h rename to core/src/Configuration/Proxy.h index 8f2d9527b..4c2d2682d 100644 --- a/core/include/Configuration/Proxy.h +++ b/core/src/Configuration/Proxy.h @@ -1,7 +1,7 @@ /* * Configuration/Proxy.h - ConfigurationProxy class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -34,7 +34,7 @@ class VEYON_CORE_EXPORT Proxy : public QObject { Q_OBJECT public: - explicit Proxy( Object* object, QObject* parent = nullptr ); + explicit Proxy( Object* object ); ~Proxy() override = default; bool hasValue( const QString& key, const QString& parentKey ) const; @@ -48,6 +48,11 @@ class VEYON_CORE_EXPORT Proxy : public QObject void reloadFromStore(); void flushStore(); + QObject* object() const + { + return m_object; + } + const QString& instanceId() const { return m_instanceId; @@ -71,11 +76,11 @@ class VEYON_CORE_EXPORT Proxy : public QObject #define DECLARE_CONFIG_PROXY(name, ops) \ class name : public Configuration::Proxy { \ public: \ - explicit name( Configuration::Object* object, QObject* parent = nullptr ); \ + explicit name( Configuration::Object* object ); \ ops(DECLARE_CONFIG_PROPERTY) \ }; #define IMPLEMENT_CONFIG_PROXY(name) \ - name::name( Configuration::Object* object, QObject* parent ) : Configuration::Proxy( object, parent ) { } + name::name( Configuration::Object* object ) : Configuration::Proxy( object ) { } } diff --git a/core/include/Configuration/Store.h b/core/src/Configuration/Store.h similarity index 79% rename from core/include/Configuration/Store.h rename to core/src/Configuration/Store.h index 00940e3e0..994e9a504 100644 --- a/core/include/Configuration/Store.h +++ b/core/src/Configuration/Store.h @@ -1,7 +1,7 @@ /* * Configuration/Store.h - ConfigurationStore class * - * Copyright (c) 2009-2019 Tobias Junghans + * Copyright (c) 2009-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -28,8 +28,6 @@ #include #include -#include "VeyonCore.h" - namespace Configuration { @@ -39,26 +37,25 @@ class Object; class Store { + Q_GADGET public: - enum Backends + enum class Backend { - LocalBackend, // registry or similiar + Local, // registry or similar JsonFile, - NoBackend - } ; - using Backend = Backends; + None + }; + Q_ENUM(Backend) - enum Scopes + enum class Scope { User, // for current user System, // system-wide (service settings etc.) - } ; - using Scope = Scopes; - + }; - Store( Backend backend, Scope scope ) : - m_backend( backend ), - m_scope( scope ) + Store(Backend backend, Scope scope) : + m_backend(backend), + m_scope(scope) { } @@ -76,10 +73,10 @@ class Store QString configurationNameFromScope() const { - switch( scope() ) + switch (scope()) { - case User: return QStringLiteral( "UserConfig" ); - case System: return QStringLiteral( "SystemConfig" ); + case Scope::User: return QStringLiteral("UserConfig"); + case Scope::System: return QStringLiteral("SystemConfig"); } return {}; diff --git a/core/src/Configuration/UiMapping.cpp b/core/src/Configuration/UiMapping.cpp index 0010465e9..b89ae6d7e 100644 --- a/core/src/Configuration/UiMapping.cpp +++ b/core/src/Configuration/UiMapping.cpp @@ -1,7 +1,7 @@ /* * ConfigurationObject.cpp - implementation of ConfigurationObject * - * Copyright (c) 2009-2019 Tobias Junghans + * Copyright (c) 2009-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -75,7 +75,7 @@ void UiMapping::initWidgetFromProperty( const Configuration::TypedProperty& property, QLineEdit* widget ) { - widget->setText( property.value().plainText() ); + widget->setText( QString::fromUtf8( property.value().plainText().toByteArray() ) ); } @@ -112,7 +112,7 @@ void UiMapping::initWidgetFromProperty( const Configuration::TypedProperty= 0x051200 +#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) object->setProperty( WidgetConfigPropertyFlags, QVariant::fromValue( flags ) ); #else object->setProperty( WidgetConfigPropertyFlags, static_cast( flags ) ); @@ -124,8 +124,8 @@ void UiMapping::setFlags( QObject* object, Property::Flags flags ) Property::Flags UiMapping::flags( QObject* object ) { const auto flagsData = object->property( WidgetConfigPropertyFlags ); -#if QT_VERSION >= 0x051200 - return flagsData.value(); +#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) + return flagsData.value(); #else return static_cast( flagsData.toUInt() ); #endif @@ -133,7 +133,7 @@ Property::Flags UiMapping::flags( QObject* object ) -void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& property, QCheckBox* widget ) +void UiMapping::connectWidgetToProperty( const Configuration::TypedProperty& property, QCheckBox* widget ) { QObject::connect( widget, &QCheckBox::toggled, property.lambdaContext(), [&property]( bool value ) { property.setValue( value ); } ); @@ -141,7 +141,7 @@ void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& pro -void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& property, QGroupBox* widget ) +void UiMapping::connectWidgetToProperty( const Configuration::TypedProperty& property, QGroupBox* widget ) { QObject::connect( widget, &QGroupBox::toggled, property.lambdaContext(), [&property]( bool value ) { property.setValue( value ); } ); @@ -149,7 +149,7 @@ void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& pro -void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& property, QRadioButton* widget ) +void UiMapping::connectWidgetToProperty( const Configuration::TypedProperty& property, QRadioButton* widget ) { QObject::connect( widget, &QCheckBox::toggled, property.lambdaContext(), [&property]( bool value ) { property.setValue( value ); } ); @@ -157,7 +157,7 @@ void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& pro -void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& property, QComboBox* widget ) +void UiMapping::connectWidgetToProperty( const Configuration::TypedProperty& property, QComboBox* widget ) { QObject::connect( widget, &QComboBox::currentTextChanged, property.lambdaContext(), [&property]( const QString& value ) { property.setValue( value ); } ); @@ -165,7 +165,7 @@ void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& -void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& property, QLineEdit* widget ) +void UiMapping::connectWidgetToProperty( const Configuration::TypedProperty& property, QLineEdit* widget ) { QObject::connect( widget, &QLineEdit::textChanged, property.lambdaContext(), [&property]( const QString& value ) { property.setValue( value ); } ); @@ -173,15 +173,15 @@ void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& -void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& property, QLineEdit* widget ) +void UiMapping::connectWidgetToProperty( const Configuration::TypedProperty& property, QLineEdit* widget ) { QObject::connect( widget, &QLineEdit::textChanged, property.lambdaContext(), - [&property]( const QString& plainText ) { property.setValue( Password::fromPlainText( plainText ) ); } ); + [&property]( const QString& plainText ) { property.setValue( Password::fromPlainText( plainText.toUtf8() ) ); } ); } -void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& property, QPushButton* widget ) +void UiMapping::connectWidgetToProperty( const Configuration::TypedProperty& property, QPushButton* widget ) { QObject::connect( widget, &QAbstractButton::clicked, property.lambdaContext(), [&property, widget]() { auto palette = widget->palette(); @@ -197,7 +197,7 @@ void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& p -void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& property, QComboBox* widget ) +void UiMapping::connectWidgetToProperty( const Configuration::TypedProperty& property, QComboBox* widget ) { QObject::connect( widget, QOverload::of(&QComboBox::currentIndexChanged), property.lambdaContext(), [&property]( int index ) { property.setValue( index ); } ); @@ -205,7 +205,7 @@ void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& prop -void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& property, QSpinBox* widget ) +void UiMapping::connectWidgetToProperty( const Configuration::TypedProperty& property, QSpinBox* widget ) { QObject::connect( widget, QOverload::of(&QSpinBox::valueChanged), property.lambdaContext(), [&property]( int index ) { property.setValue( index ); } ); @@ -213,7 +213,7 @@ void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& prop -void UiMapping::connectWidgetToProperty( Configuration::TypedProperty& property, QComboBox* widget ) +void UiMapping::connectWidgetToProperty( const Configuration::TypedProperty& property, QComboBox* widget ) { QObject::connect( widget, QOverload::of(&QComboBox::currentIndexChanged), property.lambdaContext(), [widget, &property]( int index ) { property.setValue( widget->itemData( index ).toUuid() ); } ); diff --git a/core/include/Configuration/UiMapping.h b/core/src/Configuration/UiMapping.h similarity index 73% rename from core/include/Configuration/UiMapping.h rename to core/src/Configuration/UiMapping.h index 10231c048..94e2e1e37 100644 --- a/core/include/Configuration/UiMapping.h +++ b/core/src/Configuration/UiMapping.h @@ -1,7 +1,7 @@ /* * Configuration/UiMapping.h - helper macros and functions for connecting config with UI * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -86,21 +86,21 @@ class VEYON_CORE_EXPORT UiMapping // connect widget signals to configuration property write methods - static void connectWidgetToProperty( Configuration::TypedProperty& property, QCheckBox* widget ); - static void connectWidgetToProperty( Configuration::TypedProperty& property, QGroupBox* widget ); - static void connectWidgetToProperty( Configuration::TypedProperty& property, QRadioButton* widget ); - static void connectWidgetToProperty( Configuration::TypedProperty& property, QComboBox* widget ); - static void connectWidgetToProperty( Configuration::TypedProperty& property, QLineEdit* widget ); - static void connectWidgetToProperty( Configuration::TypedProperty& property, QLineEdit* widget ); - static void connectWidgetToProperty( Configuration::TypedProperty& property, QPushButton* widget ); - static void connectWidgetToProperty( Configuration::TypedProperty& property, QComboBox* widget ); - static void connectWidgetToProperty( Configuration::TypedProperty& property, QSpinBox* widget ); - static void connectWidgetToProperty( Configuration::TypedProperty& property, QComboBox* widget ); + static void connectWidgetToProperty( const Configuration::TypedProperty& property, QCheckBox* widget ); + static void connectWidgetToProperty( const Configuration::TypedProperty& property, QGroupBox* widget ); + static void connectWidgetToProperty( const Configuration::TypedProperty& property, QRadioButton* widget ); + static void connectWidgetToProperty( const Configuration::TypedProperty& property, QComboBox* widget ); + static void connectWidgetToProperty( const Configuration::TypedProperty& property, QLineEdit* widget ); + static void connectWidgetToProperty( const Configuration::TypedProperty& property, QLineEdit* widget ); + static void connectWidgetToProperty( const Configuration::TypedProperty& property, QPushButton* widget ); + static void connectWidgetToProperty( const Configuration::TypedProperty& property, QComboBox* widget ); + static void connectWidgetToProperty( const Configuration::TypedProperty& property, QSpinBox* widget ); + static void connectWidgetToProperty( const Configuration::TypedProperty& property, QComboBox* widget ); // SFINAE overload for enum classes template static typename std::enable_if::value, void>::type - connectWidgetToProperty( Configuration::TypedProperty& property, QComboBox* widget ) + connectWidgetToProperty( const Configuration::TypedProperty& property, QComboBox* widget ) { QObject::connect( widget, QOverload::of(&QComboBox::currentIndexChanged), property.lambdaContext(), [&property]( int index ) { property.setValue( static_cast( index ) ); } ); @@ -108,13 +108,13 @@ class VEYON_CORE_EXPORT UiMapping // overloads for special properties which can't be connected to widgets - static void connectWidgetToProperty( Configuration::TypedProperty& property, QLabel* widget ) + static void connectWidgetToProperty( const Configuration::TypedProperty& property, QLabel* widget ) { Q_UNUSED(property) Q_UNUSED(widget) } - static void connectWidgetToProperty( Configuration::TypedProperty& property, QLabel* widget ) + static void connectWidgetToProperty( const Configuration::TypedProperty& property, QLabel* widget ) { Q_UNUSED(property) Q_UNUSED(widget) diff --git a/core/src/ConfigurationManager.cpp b/core/src/ConfigurationManager.cpp index 4a3ca30a7..b40dd9179 100644 --- a/core/src/ConfigurationManager.cpp +++ b/core/src/ConfigurationManager.cpp @@ -1,7 +1,7 @@ /* * ConfigurationManager.cpp - class for managing Veyon's configuration * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,7 +26,6 @@ #include "ConfigurationManager.h" #include "Filesystem.h" #include "PlatformCoreFunctions.h" -#include "PlatformInputDeviceFunctions.h" #include "PlatformNetworkFunctions.h" #include "VeyonConfiguration.h" #include "VeyonServiceControl.h" @@ -43,7 +42,7 @@ ConfigurationManager::ConfigurationManager( QObject* parent ) : bool ConfigurationManager::clearConfiguration() { - Configuration::LocalStore( Configuration::LocalStore::System ).clear(); + Configuration::LocalStore(Configuration::LocalStore::Scope::System).clear(); return true; } @@ -61,6 +60,14 @@ bool ConfigurationManager::applyConfiguration() auto& network = VeyonCore::platform().networkFunctions(); + if( network.configureFirewallException( VeyonCore::filesystem().serviceFilePath(), + QStringLiteral("Veyon Service"), + m_configuration.isFirewallExceptionEnabled() ) == false ) + { + m_errorString = tr( "Could not configure the firewall configuration for the %1 Service." ).arg( VeyonCore::applicationName() ); + return false; + } + if( network.configureFirewallException( VeyonCore::filesystem().serverFilePath(), QStringLiteral("Veyon Server"), m_configuration.isFirewallExceptionEnabled() ) == false ) @@ -91,7 +98,7 @@ bool ConfigurationManager::applyConfiguration() bool ConfigurationManager::saveConfiguration() { // write global configuration - Configuration::LocalStore localStore( Configuration::LocalStore::System ); + Configuration::LocalStore localStore(Configuration::LocalStore::Scope::System); if( localStore.isWritable() == false ) { m_errorString = tr( "Configuration is not writable. Please check your permissions!" ); diff --git a/core/include/ConfigurationManager.h b/core/src/ConfigurationManager.h similarity index 95% rename from core/include/ConfigurationManager.h rename to core/src/ConfigurationManager.h index 61390ca4d..ae9377863 100644 --- a/core/include/ConfigurationManager.h +++ b/core/src/ConfigurationManager.h @@ -1,7 +1,7 @@ /* * ConfigurationManager.h - class for managing Veyon's configuration * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/core/src/ConfigurationPage.cpp b/core/src/ConfigurationPage.cpp index 7729f8c07..0d8ef0a81 100644 --- a/core/src/ConfigurationPage.cpp +++ b/core/src/ConfigurationPage.cpp @@ -1,7 +1,7 @@ /* * ConfigurationPage.cpp - implementation of configuration page base class * - * Copyright (c) 2016-2019 Tobias Junghans + * Copyright (c) 2016-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/core/include/ConfigurationPage.h b/core/src/ConfigurationPage.h similarity index 94% rename from core/include/ConfigurationPage.h rename to core/src/ConfigurationPage.h index 1624f90a5..beead8013 100644 --- a/core/include/ConfigurationPage.h +++ b/core/src/ConfigurationPage.h @@ -1,7 +1,7 @@ /* * ConfigurationPage.h - base class for all configuration pages * - * Copyright (c) 2016-2019 Tobias Junghans + * Copyright (c) 2016-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -39,7 +39,7 @@ class VEYON_CORE_EXPORT ConfigurationPage : public QWidget virtual void connectWidgetsToProperties() = 0; virtual void applyConfiguration() = 0; -signals: +Q_SIGNALS: void widgetsChanged(); }; diff --git a/core/include/ConfigurationPagePluginInterface.h b/core/src/ConfigurationPagePluginInterface.h similarity index 95% rename from core/include/ConfigurationPagePluginInterface.h rename to core/src/ConfigurationPagePluginInterface.h index 80da8425a..9336d8ab0 100644 --- a/core/include/ConfigurationPagePluginInterface.h +++ b/core/src/ConfigurationPagePluginInterface.h @@ -1,7 +1,7 @@ /* * ConfigurationPagePluginInterface.h - interface class for configuration pages * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/core/src/CryptoCore.cpp b/core/src/CryptoCore.cpp index 098a0ffc0..7e9173848 100644 --- a/core/src/CryptoCore.cpp +++ b/core/src/CryptoCore.cpp @@ -1,7 +1,7 @@ /* * CryptoCore.cpp - core functions for crypto features * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,11 +24,12 @@ #include +#include + #include "CryptoCore.h" +#include "HostAddress.h" -CryptoCore::CryptoCore() : - m_qcaInitializer(), - m_defaultPrivateKey() +CryptoCore::CryptoCore() { const auto features = QCA::supportedFeatures(); @@ -54,7 +55,7 @@ CryptoCore::~CryptoCore() QByteArray CryptoCore::generateChallenge() { - BIGNUM * challengeBigNum = BN_new(); + const auto challengeBigNum = BN_new(); if( challengeBigNum == nullptr ) { @@ -63,7 +64,7 @@ QByteArray CryptoCore::generateChallenge() } // generate a random challenge - BN_rand( challengeBigNum, ChallengeSize * 8, 0, 0 ); + BN_rand( challengeBigNum, ChallengeSize * BitsPerByte, 0, 0 ); QByteArray chall( BN_num_bytes( challengeBigNum ), 0 ); BN_bn2bin( challengeBigNum, reinterpret_cast( chall.data() ) ); BN_free( challengeBigNum ); @@ -73,25 +74,60 @@ QByteArray CryptoCore::generateChallenge() -QString CryptoCore::encryptPassword( const QString& password ) const +QString CryptoCore::encryptPassword( const PlaintextPassword& password ) const { return QString::fromLatin1( m_defaultPrivateKey.toPublicKey(). - encrypt( password.toUtf8(), DefaultEncryptionAlgorithm ).toByteArray().toHex() ); + encrypt( password, DefaultEncryptionAlgorithm ).toByteArray().toHex() ); } -QString CryptoCore::decryptPassword( const QString& encryptedPassword ) const +CryptoCore::PlaintextPassword CryptoCore::decryptPassword( const QString& encryptedPassword ) const { - SecureArray decryptedPassword; + PlaintextPassword decryptedPassword; if( PrivateKey( m_defaultPrivateKey ).decrypt( QByteArray::fromHex( encryptedPassword.toUtf8() ), &decryptedPassword, DefaultEncryptionAlgorithm ) ) { - return QString::fromUtf8( decryptedPassword.toByteArray() ); + return decryptedPassword; } vCritical() << "failed to decrypt password!"; return {}; } + + + +CryptoCore::PrivateKey CryptoCore::createPrivateKey() +{ + return m_keyGenerator.createRSA( CryptoCore::RsaKeySize ); +} + + + +CryptoCore::Certificate CryptoCore::createSelfSignedHostCertificate( const PrivateKey& privateKey ) +{ + QCA::CertificateInfo certInfo{ + { QCA::CertificateInfoTypeKnown::CommonName, HostAddress::localFQDN() }, + { QCA::CertificateInfoTypeKnown::DNS, HostAddress::localFQDN() } + }; + + const auto allAddresses = QNetworkInterface::allAddresses(); + for( const auto& address : allAddresses ) + { + certInfo.insert( QCA::CertificateInfoTypeKnown::IPAddress, address.toString() ); + } + + QCA::CertificateOptions certOpts; + certOpts.setInfo( certInfo ); + certOpts.setConstraints( { QCA::ConstraintTypeKnown::DigitalSignature, + QCA::ConstraintTypeKnown::KeyCertificateSign, + QCA::ConstraintTypeKnown::KeyEncipherment, + QCA::ConstraintTypeKnown::ServerAuth } ); + + certOpts.setValidityPeriod( QDateTime::currentDateTime(), + QDateTime::currentDateTime().addDays(DefaultCertificateValidity) ); + + return QCA::Certificate{certOpts, privateKey}; +} diff --git a/core/include/CryptoCore.h b/core/src/CryptoCore.h similarity index 58% rename from core/include/CryptoCore.h rename to core/src/CryptoCore.h index 77e1c0a39..cd0d8aaf0 100644 --- a/core/include/CryptoCore.h +++ b/core/src/CryptoCore.h @@ -1,7 +1,7 @@ /* * CryptoCore.h - core functions for crypto features * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -33,29 +33,36 @@ class VEYON_CORE_EXPORT CryptoCore { public: - using KeyGenerator = QCA::KeyGenerator; + using Certificate = QCA::Certificate; using PrivateKey = QCA::PrivateKey; using PublicKey = QCA::PublicKey; using SecureArray = QCA::SecureArray; + using PlaintextPassword = SecureArray; - enum { - RsaKeySize = 4096, - ChallengeSize = 128, - }; + static constexpr auto ChallengeSize = 128; + static constexpr auto BitsPerByte = 8; - static constexpr QCA::EncryptionAlgorithm DefaultEncryptionAlgorithm = QCA::EME_PKCS1_OAEP; - static constexpr QCA::SignatureAlgorithm DefaultSignatureAlgorithm = QCA::EMSA3_SHA512; + static constexpr auto DefaultEncryptionAlgorithm = QCA::EME_PKCS1_OAEP; + static constexpr auto DefaultSignatureAlgorithm = QCA::EMSA3_SHA512; + + static constexpr auto DefaultCertificateValidity = 30; CryptoCore(); ~CryptoCore(); static QByteArray generateChallenge(); - QString encryptPassword( const QString& password ) const; - QString decryptPassword( const QString& encryptedPassword ) const; + QString encryptPassword( const PlaintextPassword& password ) const; + PlaintextPassword decryptPassword( const QString& encryptedPassword ) const; + + PrivateKey createPrivateKey(); + Certificate createSelfSignedHostCertificate( const PrivateKey& privateKey ); private: - QCA::Initializer m_qcaInitializer; - PrivateKey m_defaultPrivateKey; + static constexpr auto RsaKeySize = 4096; + + QCA::Initializer m_qcaInitializer{}; + QCA::KeyGenerator m_keyGenerator{}; + PrivateKey m_defaultPrivateKey{}; }; diff --git a/core/src/DesktopAccessDialog.cpp b/core/src/DesktopAccessDialog.cpp index abd1342de..3d3c09ae8 100644 --- a/core/src/DesktopAccessDialog.cpp +++ b/core/src/DesktopAccessDialog.cpp @@ -1,7 +1,7 @@ /* * DesktopAccessDialog.cpp - implementation of DesktopAccessDialog class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,6 +22,7 @@ * */ +#include #include #include #include @@ -38,7 +39,7 @@ DesktopAccessDialog::DesktopAccessDialog( QObject* parent ) : QObject( parent ), m_desktopAccessDialogFeature( Feature( QLatin1String( staticMetaObject.className() ), - Feature::Dialog | Feature::Service | Feature::Worker | Feature::Builtin, + Feature::Flag::Service | Feature::Flag::Worker | Feature::Flag::Builtin, Feature::Uid( "3dd8ec3e-7004-4936-8f2a-70699b9819be" ), Feature::Uid(), tr( "Desktop access dialog" ), {}, {} ) ), @@ -53,20 +54,19 @@ DesktopAccessDialog::DesktopAccessDialog( QObject* parent ) : bool DesktopAccessDialog::isBusy( FeatureWorkerManager* featureWorkerManager ) const { - return featureWorkerManager->isWorkerRunning( m_desktopAccessDialogFeature ); + return featureWorkerManager->isWorkerRunning( m_desktopAccessDialogFeature.uid() ); } void DesktopAccessDialog::exec( FeatureWorkerManager* featureWorkerManager, const QString& user, const QString& host ) { - featureWorkerManager->startWorker( m_desktopAccessDialogFeature, FeatureWorkerManager::ManagedSystemProcess ); - m_choice = ChoiceNone; - featureWorkerManager->sendMessage( FeatureMessage( m_desktopAccessDialogFeature.uid(), RequestDesktopAccess ). - addArgument( UserArgument, user ). - addArgument( HostArgument, host ) ); + featureWorkerManager->sendMessageToManagedSystemWorker( + FeatureMessage( m_desktopAccessDialogFeature.uid(), RequestDesktopAccess ) + .addArgument( Argument::User, user ) + .addArgument( Argument::Host, host ) ); connect( &m_abortTimer, &QTimer::timeout, this, [=]() { abort( featureWorkerManager ); } ); m_abortTimer.start( DialogTimeout ); @@ -76,31 +76,28 @@ void DesktopAccessDialog::exec( FeatureWorkerManager* featureWorkerManager, cons void DesktopAccessDialog::abort( FeatureWorkerManager* featureWorkerManager ) { - featureWorkerManager->stopWorker( m_desktopAccessDialogFeature ); + featureWorkerManager->stopWorker( m_desktopAccessDialogFeature.uid() ); m_choice = ChoiceNone; - emit finished(); + Q_EMIT finished(); } -bool DesktopAccessDialog::handleFeatureMessage( VeyonServerInterface& server, - const MessageContext& messageContext, - const FeatureMessage& message ) +bool DesktopAccessDialog::handleFeatureMessageFromWorker(VeyonServerInterface& server, + const FeatureMessage& message) { - Q_UNUSED(messageContext) - if( m_desktopAccessDialogFeature.uid() == message.featureUid() && message.command() == ReportDesktopAccessChoice ) { - m_choice = QVariantHelper::value( message.argument( ChoiceArgument ) ); + m_choice = message.argument( Argument::Choice ).value(); - server.featureWorkerManager().stopWorker( m_desktopAccessDialogFeature ); + server.featureWorkerManager().stopWorker(m_desktopAccessDialogFeature.uid()); m_abortTimer.stop(); - emit finished(); + Q_EMIT finished(); return true; } @@ -118,11 +115,11 @@ bool DesktopAccessDialog::handleFeatureMessage( VeyonWorkerInterface& worker, co return false; } - const auto result = requestDesktopAccess( message.argument( UserArgument ).toString(), - message.argument( HostArgument ).toString() ); + const auto result = requestDesktopAccess( message.argument( Argument::User ).toString(), + message.argument( Argument::Host ).toString() ); FeatureMessage reply( m_desktopAccessDialogFeature.uid(), ReportDesktopAccessChoice ); - reply.addArgument( ChoiceArgument, result ); + reply.addArgument( Argument::Choice, result ); return worker.sendFeatureMessageReply( reply ); } @@ -144,13 +141,15 @@ DesktopAccessDialog::Choice DesktopAccessDialog::requestDesktopAccess( const QSt tr( "The user %1 at computer %2 wants to access your desktop. Do you want to grant access?" ). arg( user, hostName ), QMessageBox::Yes | QMessageBox::No ); + m.setStyleSheet( QStringLiteral("button-layout:%1").arg(QDialogButtonBox::WinLayout) ); + auto neverBtn = m.addButton( tr( "Never for this session" ), QMessageBox::NoRole ); auto alwaysBtn = m.addButton( tr( "Always for this session" ), QMessageBox::YesRole ); m.setEscapeButton( m.button( QMessageBox::No ) ); m.setDefaultButton( neverBtn ); - VeyonCore::platform().coreFunctions().raiseWindow( &m ); + VeyonCore::platform().coreFunctions().raiseWindow( &m, true ); const auto result = m.exec(); @@ -158,11 +157,13 @@ DesktopAccessDialog::Choice DesktopAccessDialog::requestDesktopAccess( const QSt { return ChoiceNever; } - else if( m.clickedButton() == alwaysBtn ) + + if( m.clickedButton() == alwaysBtn ) { return ChoiceAlways; } - else if( result == QMessageBox::Yes ) + + if( result == QMessageBox::Yes ) { return ChoiceYes; } diff --git a/core/include/DesktopAccessDialog.h b/core/src/DesktopAccessDialog.h similarity index 78% rename from core/include/DesktopAccessDialog.h rename to core/src/DesktopAccessDialog.h index 5f7eeed0d..19012cc5f 100644 --- a/core/include/DesktopAccessDialog.h +++ b/core/src/DesktopAccessDialog.h @@ -1,7 +1,7 @@ /* * DesktopAccessDialog.h - declaration of DesktopAccessDialog class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,15 +26,23 @@ #include -#include "SimpleFeatureProvider.h" +#include "FeatureProviderInterface.h" class FeatureWorkerManager; -class VEYON_CORE_EXPORT DesktopAccessDialog : public QObject, public SimpleFeatureProvider, public PluginInterface +class VEYON_CORE_EXPORT DesktopAccessDialog : public QObject, public FeatureProviderInterface, public PluginInterface { Q_OBJECT Q_INTERFACES(FeatureProviderInterface PluginInterface) public: + enum class Argument + { + User, + Host, + Choice + }; + Q_ENUM(Argument) + enum Choice { ChoiceNone, @@ -61,7 +69,7 @@ class VEYON_CORE_EXPORT DesktopAccessDialog : public QObject, public SimpleFeatu Plugin::Uid uid() const override { - return QStringLiteral("13fb9ce8-afbc-4397-93e3-e01c4d8288c9"); + return Plugin::Uid{ QStringLiteral("13fb9ce8-afbc-4397-93e3-e01c4d8288c9") }; } QVersionNumber version() const override @@ -94,9 +102,19 @@ class VEYON_CORE_EXPORT DesktopAccessDialog : public QObject, public SimpleFeatu return m_features; } - bool handleFeatureMessage( VeyonServerInterface& server, - const MessageContext& messageContext, - const FeatureMessage& message ) override; + bool controlFeature( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) override + { + Q_UNUSED(featureUid) + Q_UNUSED(operation) + Q_UNUSED(arguments) + Q_UNUSED(computerControlInterfaces) + + return false; + } + + bool handleFeatureMessageFromWorker(VeyonServerInterface& server, + const FeatureMessage& message) override; bool handleFeatureMessage( VeyonWorkerInterface& worker, const FeatureMessage& message ) override; @@ -115,13 +133,6 @@ class VEYON_CORE_EXPORT DesktopAccessDialog : public QObject, public SimpleFeatu ReportDesktopAccessChoice }; - enum Arguments - { - UserArgument, - HostArgument, - ChoiceArgument - }; - const Feature m_desktopAccessDialogFeature; const FeatureList m_features; @@ -129,7 +140,7 @@ class VEYON_CORE_EXPORT DesktopAccessDialog : public QObject, public SimpleFeatu QTimer m_abortTimer; -signals: +Q_SIGNALS: void finished(); }; diff --git a/core/src/EnumHelper.h b/core/src/EnumHelper.h new file mode 100644 index 000000000..06f027adf --- /dev/null +++ b/core/src/EnumHelper.h @@ -0,0 +1,47 @@ +/* + * EnumHelper.h - helper functions for enumerations + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +// clazy:excludeall=rule-of-three + +class EnumHelper +{ +public: + template + static QString toString( T item ) + { + return QLatin1String(QMetaEnum::fromType().valueToKey(int(item))); + } + + template + static QString toCamelCaseString( T item ) + { + const auto name = toString( item ); + return name.mid( 0, 1 ).toLower() + name.mid( 1 ); + } + +} ; diff --git a/core/include/Feature.h b/core/src/Feature.h similarity index 89% rename from core/include/Feature.h rename to core/src/Feature.h index c90675dc4..f84388443 100644 --- a/core/include/Feature.h +++ b/core/src/Feature.h @@ -1,7 +1,7 @@ /* * Feature.h - declaration of the Feature class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -37,14 +37,15 @@ class VEYON_CORE_EXPORT Feature public: using Uid = QUuid; - enum FeatureFlag + enum class Flag { - NoFlags, + None = 0x0000, Mode = 0x0001, Action = 0x0002, Session = 0x0004, - Operation = 0x0008, - Dialog = 0x0010, + Meta = 0x0008, + Option = 0x0010, + Checked = 0x0020, Master = 0x0100, Service = 0x0200, Worker = 0x0400, @@ -52,8 +53,11 @@ class VEYON_CORE_EXPORT Feature AllComponents = Master | Service | Worker } ; - Q_DECLARE_FLAGS(Flags, FeatureFlag) + Q_DECLARE_FLAGS(Flags, Flag) + // work around QTBUG-47652 where Q_FLAG() is broken for enum classes when using Qt < 5.12 +#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) Q_FLAG(Flags) +#endif explicit Feature( const QString& name, Flags flags, @@ -78,7 +82,7 @@ class VEYON_CORE_EXPORT Feature explicit Feature( Uid uid = Uid() ) : m_name(), - m_flags( NoFlags ), + m_flags( Flag::None ), m_uid( uid ), m_parentUid( QUuid() ), m_displayName(), @@ -131,10 +135,10 @@ class VEYON_CORE_EXPORT Feature bool isValid() const { - return m_flags != NoFlags; + return m_flags != QFlags::Int(Flag::None); } - bool testFlag( FeatureFlag flag ) const + bool testFlag( Flag flag ) const { return m_flags.testFlag( flag ); } @@ -215,4 +219,4 @@ class VEYON_CORE_EXPORT Feature Q_DECLARE_OPERATORS_FOR_FLAGS(Feature::Flags) using FeatureList = QList; -using FeatureUidList = QStringList; +using FeatureUidList = QList; diff --git a/core/src/FeatureControl.cpp b/core/src/FeatureControl.cpp deleted file mode 100644 index 67b55a6ef..000000000 --- a/core/src/FeatureControl.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * FeatureControl.cpp - implementation of FeatureControl class - * - * Copyright (c) 2017-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#include "FeatureControl.h" -#include "FeatureWorkerManager.h" -#include "VeyonCore.h" -#include "VeyonServerInterface.h" - - -FeatureControl::FeatureControl( QObject* parent ) : - QObject( parent ), - m_featureControlFeature( Feature( QLatin1String( staticMetaObject.className() ), - Feature::Service | Feature::Worker | Feature::Builtin, - Feature::Uid( "a0a96fba-425d-414a-aaf4-352b76d7c4f3" ), - Feature::Uid(), - tr( "Feature control" ), {}, {}, {}, {} ) ), - m_features( { m_featureControlFeature } ) -{ -} - - - -bool FeatureControl::queryActiveFeatures( const ComputerControlInterfaceList& computerControlInterfaces ) -{ - return sendFeatureMessage( FeatureMessage( m_featureControlFeature.uid(), QueryActiveFeatures ), - computerControlInterfaces, false ); -} - - - -bool FeatureControl::handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) -{ - Q_UNUSED(master); - - if( message.featureUid() == m_featureControlFeature.uid() ) - { - computerControlInterface->setActiveFeatures( message.argument( ActiveFeatureList ).toStringList() ); - - return true; - } - - return false; -} - - - -bool FeatureControl::handleFeatureMessage( VeyonServerInterface& server, - const MessageContext& messageContext, - const FeatureMessage& message ) -{ - if( m_featureControlFeature.uid() == message.featureUid() ) - { - FeatureMessage reply( message.featureUid(), message.command() ); - reply.addArgument( ActiveFeatureList, server.featureWorkerManager().runningWorkers() ); - - return server.sendFeatureMessageReply( messageContext, reply ); - } - - return false; -} diff --git a/core/src/FeatureManager.cpp b/core/src/FeatureManager.cpp index 7726080fc..cd696656b 100644 --- a/core/src/FeatureManager.cpp +++ b/core/src/FeatureManager.cpp @@ -1,7 +1,7 @@ /* * FeatureManager.cpp - implementation of the FeatureManager class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,9 +24,11 @@ #include "FeatureManager.h" #include "FeatureMessage.h" +#include "FeatureWorkerManager.h" #include "PluginInterface.h" #include "PluginManager.h" #include "VeyonConfiguration.h" +#include "VeyonServerInterface.h" Q_DECLARE_METATYPE(Feature) Q_DECLARE_METATYPE(FeatureMessage) @@ -34,16 +36,12 @@ Q_DECLARE_METATYPE(FeatureMessage) // clazy:excludeall=reserve-candidates FeatureManager::FeatureManager( QObject* parent ) : - QObject( parent ), - m_features(), - m_emptyFeatureList(), - m_pluginObjects(), - m_dummyFeature() + QObject( parent ) { qRegisterMetaType(); qRegisterMetaType(); - for( const auto& pluginObject : qAsConst( VeyonCore::pluginManager().pluginObjects() ) ) + for( const auto& pluginObject : std::as_const( VeyonCore::pluginManager().pluginObjects() ) ) { auto featurePluginInterface = qobject_cast( pluginObject ); @@ -56,6 +54,12 @@ FeatureManager::FeatureManager( QObject* parent ) : } } + const auto disabledFeatures = VeyonCore::config().disabledFeatures(); + m_disabledFeaturesUids.reserve(disabledFeatures.count()); + for (const auto& disabledFeature : disabledFeatures) + { + m_disabledFeaturesUids.append(Plugin::Uid{disabledFeature}); + } } @@ -96,7 +100,32 @@ const Feature& FeatureManager::feature( Feature::Uid featureUid ) const -Plugin::Uid FeatureManager::pluginUid( const Feature& feature ) const +const FeatureList& FeatureManager::relatedFeatures( Feature::Uid featureUid ) const +{ + return features( pluginUid( featureUid ) ); +} + + + +Feature::Uid FeatureManager::metaFeatureUid( Feature::Uid featureUid ) const +{ + for( const auto& featureInterface : m_featurePluginInterfaces ) + { + for( const auto& feature : featureInterface->featureList() ) + { + if( feature.uid() == featureUid ) + { + return featureInterface->metaFeature( featureUid ); + } + } + } + + return {}; +} + + + +Plugin::Uid FeatureManager::pluginUid( Feature::Uid featureUid ) const { for( auto pluginObject : m_pluginObjects ) { @@ -104,7 +133,10 @@ Plugin::Uid FeatureManager::pluginUid( const Feature& feature ) const auto featurePluginInterface = qobject_cast( pluginObject ); if( pluginInterface && featurePluginInterface && - featurePluginInterface->featureList().contains( feature ) ) + std::find_if( featurePluginInterface->featureList().begin(), + featurePluginInterface->featureList().end(), + [&featureUid]( const Feature& feature ) { return feature.uid() == featureUid; } ) + != featurePluginInterface->featureList().end() ) { return pluginInterface->uid(); } @@ -115,18 +147,31 @@ Plugin::Uid FeatureManager::pluginUid( const Feature& feature ) const +void FeatureManager::controlFeature( Feature::Uid featureUid, + FeatureProviderInterface::Operation operation, + const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) const +{ + for( auto featureInterface : std::as_const( m_featurePluginInterfaces ) ) + { + featureInterface->controlFeature( featureUid, operation, arguments, computerControlInterfaces ); + } +} + + + void FeatureManager::startFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) + const ComputerControlInterfaceList& computerControlInterfaces ) const { - vDebug() << "feature" << feature.name() << feature.uid() << computerControlInterfaces; + vDebug() << computerControlInterfaces << feature.name(); - for( auto featureInterface : qAsConst( m_featurePluginInterfaces ) ) + for( auto featureInterface : std::as_const( m_featurePluginInterfaces ) ) { featureInterface->startFeature( master, feature, computerControlInterfaces ); } - if( feature.testFlag( Feature::Mode ) ) + if( feature.testFlag( Feature::Flag::Mode ) ) { for( const auto& controlInterface : computerControlInterfaces ) { @@ -139,11 +184,11 @@ void FeatureManager::startFeature( VeyonMasterInterface& master, void FeatureManager::stopFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) + const ComputerControlInterfaceList& computerControlInterfaces ) const { - vDebug() << "feature" << feature.name() << feature.uid() << computerControlInterfaces; + vDebug() << computerControlInterfaces << feature.name(); - for( const auto& featureInterface : qAsConst( m_featurePluginInterfaces ) ) + for( const auto& featureInterface : std::as_const( m_featurePluginInterfaces ) ) { featureInterface->stopFeature( master, feature, computerControlInterfaces ); } @@ -159,72 +204,98 @@ void FeatureManager::stopFeature( VeyonMasterInterface& master, -bool FeatureManager::handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - const ComputerControlInterface::Pointer& computerControlInterface ) +void FeatureManager::handleFeatureMessage(ComputerControlInterface::Pointer computerControlInterface, + const FeatureMessage& message) const { - vDebug() << "feature" << message.featureUid() - << "command" << message.command() - << "arguments" << message.arguments(); + vDebug() << computerControlInterface << message; - bool handled = false; + for( const auto& featureInterface : std::as_const( m_featurePluginInterfaces ) ) + { + featureInterface->handleFeatureMessage(computerControlInterface, message); + } +} + + + +void FeatureManager::handleFeatureMessage(VeyonServerInterface& server, + const MessageContext& messageContext, + const FeatureMessage& message) const +{ + vDebug() << "[SERVER]" << message; - for( const auto& featureInterface : qAsConst( m_featurePluginInterfaces ) ) + if (m_disabledFeaturesUids.contains(message.featureUid())) { - if( featureInterface->handleFeatureMessage( master, message, computerControlInterface ) ) - { - handled = true; - } + vWarning() << "ignoring message as feature" << message.featureUid() << "is disabled by configuration!"; + return; } - return handled; + for( const auto& featureInterface : std::as_const( m_featurePluginInterfaces ) ) + { + featureInterface->handleFeatureMessage(server, messageContext, message); + } } -bool FeatureManager::handleFeatureMessage( VeyonServerInterface& server, - const MessageContext& messageContext, - const FeatureMessage& message ) +void FeatureManager::handleFeatureMessageFromWorker(VeyonServerInterface& server, + const FeatureMessage& message) const { - vDebug() << "feature" << message.featureUid() - << "command" << message.command() - << "arguments" << message.arguments(); + vDebug() << "[FROM WORKER]" << message; - if( VeyonCore::config().disabledFeatures().contains( message.featureUid().toString() ) ) + if (m_disabledFeaturesUids.contains(message.featureUid())) { vWarning() << "ignoring message as feature" << message.featureUid() << "is disabled by configuration!"; - return false; + return; } - bool handled = false; - - for( const auto& featureInterface : qAsConst( m_featurePluginInterfaces ) ) + for (const auto& featureInterface : std::as_const(m_featurePluginInterfaces)) { - if( featureInterface->handleFeatureMessage( server, messageContext, message ) ) - { - handled = true; - } + featureInterface->handleFeatureMessageFromWorker(server, message); } +} + + - return handled; + +void FeatureManager::handleFeatureMessage(VeyonWorkerInterface& worker, const FeatureMessage& message) const +{ + vDebug() << "[WORKER]" << message; + + for( const auto& featureInterface : std::as_const( m_featurePluginInterfaces ) ) + { + featureInterface->handleFeatureMessage(worker, message); + } } -bool FeatureManager::handleFeatureMessage( VeyonWorkerInterface& worker, const FeatureMessage& message ) +void FeatureManager::sendAsyncFeatureMessages(VeyonServerInterface& server, + const MessageContext& messageContext) const { - vDebug() << "feature" << message.featureUid() - << "command" << message.command() - << "arguments" << message.arguments(); - bool handled = false; + for (const auto& featureInterface : std::as_const(m_featurePluginInterfaces)) + { + featureInterface->sendAsyncFeatureMessages(server, messageContext); + } +} - for( const auto& featureInterface : qAsConst( m_featurePluginInterfaces ) ) + + +FeatureUidList FeatureManager::activeFeatures( VeyonServerInterface& server ) const +{ + FeatureUidList features; + + for( const auto& featureInterface : std::as_const( m_featurePluginInterfaces ) ) { - if( featureInterface->handleFeatureMessage( worker, message ) ) + for( const auto& feature : featureInterface->featureList() ) { - handled = true; + if( featureInterface->isFeatureActive( server, feature.uid() ) || + server.featureWorkerManager().isWorkerRunning( feature.uid() ) ) + { + features.append( feature.uid() ); + } } } - return handled; + return features; } diff --git a/core/include/FeatureManager.h b/core/src/FeatureManager.h similarity index 54% rename from core/include/FeatureManager.h rename to core/src/FeatureManager.h index b5028dd26..cf65acdba 100644 --- a/core/include/FeatureManager.h +++ b/core/src/FeatureManager.h @@ -1,7 +1,7 @@ /* * FeatureManager.h - header for the FeatureManager class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -50,28 +50,44 @@ class VEYON_CORE_EXPORT FeatureManager : public QObject const Feature& feature( Feature::Uid featureUid ) const; - Plugin::Uid pluginUid( const Feature& feature ) const; + const FeatureList& relatedFeatures( Feature::Uid featureUid ) const; + + Feature::Uid metaFeatureUid( Feature::Uid featureUid ) const; + + Plugin::Uid pluginUid( Feature::Uid featureUid ) const; + + + void controlFeature( Feature::Uid featureUid, + FeatureProviderInterface::Operation operation, + const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) const; void startFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ); + const ComputerControlInterfaceList& computerControlInterfaces ) const; void stopFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ); + const ComputerControlInterfaceList& computerControlInterfaces ) const; + + void handleFeatureMessage(ComputerControlInterface::Pointer computerControlInterface, + const FeatureMessage& message) const; + void handleFeatureMessage(VeyonServerInterface& server, + const MessageContext& messageContext, + const FeatureMessage& message) const; + void handleFeatureMessageFromWorker(VeyonServerInterface& server, + const FeatureMessage& message) const; + void handleFeatureMessage(VeyonWorkerInterface& worker, const FeatureMessage& message) const; + + void sendAsyncFeatureMessages(VeyonServerInterface& server, const MessageContext& messageContext) const; -public slots: - bool handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - const ComputerControlInterface::Pointer& computerControlInterface ); - bool handleFeatureMessage( VeyonServerInterface& server, - const MessageContext& messageContext, - const FeatureMessage& message ); - bool handleFeatureMessage( VeyonWorkerInterface& worker, const FeatureMessage& message ); + FeatureUidList activeFeatures( VeyonServerInterface& server ) const; private: - FeatureList m_features; - const FeatureList m_emptyFeatureList; - QObjectList m_pluginObjects; - FeatureProviderInterfaceList m_featurePluginInterfaces; - const Feature m_dummyFeature; + FeatureList m_features{}; + FeatureUidList m_disabledFeaturesUids{}; + const FeatureList m_emptyFeatureList{}; + QObjectList m_pluginObjects{}; + FeatureProviderInterfaceList m_featurePluginInterfaces{}; + const Feature m_dummyFeature{}; }; diff --git a/core/src/FeatureMessage.cpp b/core/src/FeatureMessage.cpp index 21d3fec18..e57c4a9d2 100644 --- a/core/src/FeatureMessage.cpp +++ b/core/src/FeatureMessage.cpp @@ -1,7 +1,7 @@ /* * FeatureMessage.cpp - implementation of a message encapsulation class for features * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,15 +22,16 @@ * */ +#include "FeatureManager.h" #include "FeatureMessage.h" #include "VariantArrayMessage.h" -bool FeatureMessage::send( QIODevice* ioDevice ) const +bool FeatureMessage::sendPlain(QIODevice* ioDevice) const { - if( ioDevice ) + if (ioDevice) { - VariantArrayMessage message( ioDevice ); + VariantArrayMessage message(ioDevice); message.write( m_featureUid ); message.write( m_command ); @@ -46,6 +47,23 @@ bool FeatureMessage::send( QIODevice* ioDevice ) const +bool FeatureMessage::sendAsRfbMessage(QIODevice* ioDevice) const +{ + if (ioDevice) + { + const char rfbMessageType = FeatureMessage::RfbMessageType; + ioDevice->write(&rfbMessageType, sizeof(rfbMessageType)); + + return sendPlain(ioDevice); + } + + vCritical() << "no IO device!"; + + return false; +} + + + bool FeatureMessage::isReadyForReceive( QIODevice* ioDevice ) { return ioDevice != nullptr && @@ -63,7 +81,7 @@ bool FeatureMessage::receive( QIODevice* ioDevice ) if( message.receive() ) { m_featureUid = message.read().toUuid(); // Flawfinder: ignore - m_command = QVariantHelper::value( message.read() ); // Flawfinder: ignore + m_command = message.read().value(); // Flawfinder: ignore m_arguments = message.read().toMap(); // Flawfinder: ignore return true; } @@ -77,3 +95,14 @@ bool FeatureMessage::receive( QIODevice* ioDevice ) return false; } + + + +QDebug operator<<(QDebug stream, const FeatureMessage& message) +{ + stream << QStringLiteral("FeatureMessage(%1,%2,%3)") + .arg(VeyonCore::featureManager().feature(message.featureUid()).name()) + .arg(message.command()) + .arg(VeyonCore::stringify(message.arguments())).toUtf8().constData(); + return stream; +} diff --git a/core/include/FeatureMessage.h b/core/src/FeatureMessage.h similarity index 72% rename from core/include/FeatureMessage.h rename to core/src/FeatureMessage.h index c6647a53a..2e5321d31 100644 --- a/core/include/FeatureMessage.h +++ b/core/src/FeatureMessage.h @@ -1,7 +1,7 @@ /* * FeatureMessage.h - header for a message encapsulation class for features * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,18 +26,17 @@ #include +#include "EnumHelper.h" #include "Feature.h" -#include "MessageContext.h" class QIODevice; class VEYON_CORE_EXPORT FeatureMessage { public: - using MessageSize = quint32; using FeatureUid = Feature::Uid; using Command = qint32; - using Arguments = QMap; + using Arguments = QVariantMap; static constexpr unsigned char RfbMessageType = 41; @@ -48,14 +47,9 @@ class VEYON_CORE_EXPORT FeatureMessage InitCommand = -2, }; - explicit FeatureMessage() : - m_featureUid(), - m_command( InvalidCommand ), - m_arguments() - { - } + FeatureMessage() = default; - explicit FeatureMessage( FeatureUid featureUid, Command command ) : + explicit FeatureMessage( FeatureUid featureUid, Command command = DefaultCommand ) : m_featureUid( featureUid ), m_command( command ), m_arguments() @@ -95,31 +89,35 @@ class VEYON_CORE_EXPORT FeatureMessage return m_arguments; } - FeatureMessage &addArgument( int index, const QVariant& value ) + template + FeatureMessage& addArgument(T index, const QVariant& value) { - m_arguments[QString::number(index)] = value; + const auto indexString = EnumHelper::toString(index); + if (indexString.isEmpty() == false) + { + m_arguments[indexString] = value; + } return *this; } - QVariant argument( int index ) const + template + QVariant argument(T index) const { - return m_arguments[QString::number(index)]; + return m_arguments[EnumHelper::toString(index)]; } - bool hasArgument( int index ) const - { - return m_arguments.contains( QString::number( index ) ); - } - - bool send( QIODevice* ioDevice ) const; + bool sendPlain(QIODevice* ioDevice) const; + bool sendAsRfbMessage(QIODevice* ioDevice) const; bool isReadyForReceive( QIODevice* ioDevice ); bool receive( QIODevice* ioDevice ); private: - FeatureUid m_featureUid; - Command m_command; - Arguments m_arguments; + FeatureUid m_featureUid{}; + Command m_command{InvalidCommand}; + Arguments m_arguments{}; } ; + +VEYON_CORE_EXPORT QDebug operator<<(QDebug stream, const FeatureMessage& message); diff --git a/core/include/FeatureProviderInterface.h b/core/src/FeatureProviderInterface.h similarity index 55% rename from core/include/FeatureProviderInterface.h rename to core/src/FeatureProviderInterface.h index e61c21c04..a5c2da98f 100644 --- a/core/include/FeatureProviderInterface.h +++ b/core/src/FeatureProviderInterface.h @@ -1,7 +1,7 @@ /* * FeatureProviderInterface.h - interface class for feature plugins * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,6 +25,7 @@ #pragma once #include "ComputerControlInterface.h" +#include "EnumHelper.h" #include "FeatureMessage.h" #include "Feature.h" #include "MessageContext.h" @@ -38,7 +39,16 @@ class VeyonWorkerInterface; class VEYON_CORE_EXPORT FeatureProviderInterface { + Q_GADGET public: + enum class Operation + { + Initialize, + Start, + Stop + }; + Q_ENUM(Operation) + virtual ~FeatureProviderInterface() = default; /*! @@ -46,6 +56,41 @@ class VEYON_CORE_EXPORT FeatureProviderInterface */ virtual const FeatureList& featureList() const = 0; + virtual bool hasFeature( Feature::Uid featureUid ) const + { + for( const auto& feature : featureList() ) + { + if( feature.uid() == featureUid ) + { + return true; + } + } + + return false; + } + + virtual Feature::Uid metaFeature( Feature::Uid ) const + { + return {}; + } + + template + static QString argToString( T item ) + { + return EnumHelper::toCamelCaseString( item ); + } + + /*! + * \brief Control feature in a generic way based on passed arguments + * \param featureUid the UID of the feature to control + * \param operation the operation to perform for the feature + * \param arguments the arguments specifying what and how to control + * \param computerControlInterfaces a list of ComputerControlInterfaces to operate on + */ + virtual bool controlFeature( Feature::Uid featureUid, + Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) = 0; + /*! * \brief Start a feature on master side for given computer control interfaces * \param master a reference to a master instance implementing the VeyonMasterInterface @@ -54,7 +99,12 @@ class VEYON_CORE_EXPORT FeatureProviderInterface */ virtual bool startFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) = 0; + const ComputerControlInterfaceList& computerControlInterfaces ) + { + Q_UNUSED(master) + + return controlFeature( feature.uid(), Operation::Start, {}, computerControlInterfaces ); + } /*! * \brief Stops a feature on master side for given computer control interfaces @@ -64,17 +114,26 @@ class VEYON_CORE_EXPORT FeatureProviderInterface */ virtual bool stopFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) = 0; + const ComputerControlInterfaceList& computerControlInterfaces ) + { + Q_UNUSED(master) + + return controlFeature( feature.uid(), Operation::Stop, {}, computerControlInterfaces ); + } /*! - * \brief Handles a received feature message inside master - * \param master a reference to a master instance implementing the VeyonMasterInterface + * \brief Handles a received feature message received on a certain ComputerControlInterface * \param message the message which has been received and needs to be handled * \param computerControlInterfaces the interface over which the message has been received */ - virtual bool handleFeatureMessage( VeyonMasterInterface& master, - const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) = 0; + virtual bool handleFeatureMessage( ComputerControlInterface::Pointer computerControlInterface , + const FeatureMessage& message ) + { + Q_UNUSED(computerControlInterface) + Q_UNUSED(message) + + return false; + } /*! * \brief Handles a received feature message inside server @@ -83,26 +142,61 @@ class VEYON_CORE_EXPORT FeatureProviderInterface */ virtual bool handleFeatureMessage( VeyonServerInterface& server, const MessageContext& messageContext, - const FeatureMessage& message ) = 0; + const FeatureMessage& message ) + { + Q_UNUSED(server) + Q_UNUSED(messageContext) + Q_UNUSED(message) + + return false; + } + + virtual bool handleFeatureMessageFromWorker(VeyonServerInterface& server, + const FeatureMessage& message) + { + Q_UNUSED(server) + Q_UNUSED(message) + + return false; + } + + /*! + * \brief Send asynchronous messages (e.g. notifications or state updates) to client + */ + virtual void sendAsyncFeatureMessages(VeyonServerInterface& server, const MessageContext& messageContext) + { + Q_UNUSED(server) + Q_UNUSED(messageContext) + } /*! * \brief Handles a received feature message inside worker * \param worker a reference to a worker instance implementing the VeyonWorkerInterface * \param message the message which has been received and needs to be handled */ - virtual bool handleFeatureMessage( VeyonWorkerInterface& worker, const FeatureMessage& message ) = 0; + virtual bool handleFeatureMessage( VeyonWorkerInterface& worker, const FeatureMessage& message ) + { + Q_UNUSED(worker) + Q_UNUSED(message) + + return false; + } + + virtual bool isFeatureActive( VeyonServerInterface& server, Feature::Uid featureUid ) const + { + Q_UNUSED(featureUid) + Q_UNUSED(server) + + return false; + } protected: - bool sendFeatureMessage( const FeatureMessage& message, - const ComputerControlInterfaceList& computerControlInterfaces, - bool wake = true ) + void sendFeatureMessage(const FeatureMessage& message, const ComputerControlInterfaceList& computerControlInterfaces) { - for( const auto& controlInterface : computerControlInterfaces ) + for (const auto& controlInterface : computerControlInterfaces) { - controlInterface->sendFeatureMessage( message, wake ); + controlInterface->sendFeatureMessage(message); } - - return true; } }; diff --git a/core/src/FeatureWorkerManager.cpp b/core/src/FeatureWorkerManager.cpp index 8e49d5afd..ec84ff88d 100644 --- a/core/src/FeatureWorkerManager.cpp +++ b/core/src/FeatureWorkerManager.cpp @@ -1,7 +1,7 @@ /* * FeatureWorkerManager.cpp - class for managing feature worker instances * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -37,10 +37,9 @@ // clazy:excludeall=detaching-member -FeatureWorkerManager::FeatureWorkerManager( VeyonServerInterface& server, FeatureManager& featureManager, QObject* parent ) : +FeatureWorkerManager::FeatureWorkerManager( VeyonServerInterface& server, QObject* parent ) : QObject( parent ), m_server( server ), - m_featureManager( featureManager ), m_tcpServer( this ) { connect( &m_tcpServer, &QTcpServer::newConnection, @@ -67,86 +66,109 @@ FeatureWorkerManager::~FeatureWorkerManager() // properly shutdown all worker processes while( m_workers.isEmpty() == false ) { - stopWorker( Feature( m_workers.firstKey() ) ); + stopWorker( m_workers.firstKey() ); } } -void FeatureWorkerManager::startWorker( const Feature& feature, WorkerProcessMode workerProcessMode ) +bool FeatureWorkerManager::startManagedSystemWorker( Feature::Uid featureUid ) { if( thread() != QThread::currentThread() ) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) - QMetaObject::invokeMethod( this, [=]() { startWorker( feature, workerProcessMode ); }, Qt::BlockingQueuedConnection ); -#else - QMetaObject::invokeMethod( this, "startWorker", Qt::BlockingQueuedConnection, - Q_ARG( Feature, feature ), - Q_ARG( WorkerProcessMode, workerProcessMode ) ); -#endif - return; + vCritical() << "thread mismatch for feature" << featureUid; + return false; } - stopWorker( feature ); - - const auto featureUid = feature.uid().toString(); + stopWorker( featureUid ); Worker worker; - if( workerProcessMode == ManagedSystemProcess ) - { - worker.process = new QProcess; - worker.process->setProcessChannelMode( QProcess::ForwardedChannels ); + worker.process = new QProcess; + worker.process->setProcessChannelMode( QProcess::ForwardedChannels ); - connect( worker.process, static_cast(&QProcess::finished), - worker.process, &QProcess::deleteLater ); + connect( worker.process, static_cast(&QProcess::finished), + worker.process, &QProcess::deleteLater ); - vDebug() << "Starting worker (managed system process) for feature" << feature.name() << featureUid; - worker.process->start( VeyonCore::filesystem().workerFilePath(), { featureUid } ); + vDebug() << "Starting managed system worker for feature" << VeyonCore::featureManager().feature(featureUid).name(); + if( qEnvironmentVariableIsSet("VEYON_VALGRIND_WORKERS") ) + { + worker.process->start( QStringLiteral("valgrind"), + { QStringLiteral("--error-limit=no"), + QStringLiteral("--leak-check=full"), + QStringLiteral("--show-leak-kinds=all"), + QStringLiteral("--log-file=valgrind-%1.log").arg(VeyonCore::formattedUuid(featureUid)), + VeyonCore::filesystem().workerFilePath(), featureUid.toString() } ); } else { - vDebug() << "Starting worker (unmanaged session process) for feature" << feature.name() << featureUid; - const auto ret = VeyonCore::platform().coreFunctions(). - runProgramAsUser( VeyonCore::filesystem().workerFilePath(), { featureUid }, - VeyonCore::platform().userFunctions().currentUser(), - VeyonCore::platform().coreFunctions().activeDesktopName() ); - if( ret == false ) - { - vDebug() << "User session likely not yet available - retrying worker start"; - QTimer::singleShot( UnmanagedSessionProcessRetryInterval, this, - [=]() { startWorker( feature, workerProcessMode ); } ); - return; - } + worker.process->start( VeyonCore::filesystem().workerFilePath(), { featureUid.toString() } ); } m_workersMutex.lock(); - m_workers[feature.uid()] = worker; + m_workers[featureUid] = worker; m_workersMutex.unlock(); + + return true; } -void FeatureWorkerManager::stopWorker( const Feature &feature ) +bool FeatureWorkerManager::startUnmanagedSessionWorker( Feature::Uid featureUid ) { if( thread() != QThread::currentThread() ) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) - QMetaObject::invokeMethod( this, [=]() { stopWorker( feature ); }, Qt::BlockingQueuedConnection ); -#else - QMetaObject::invokeMethod( this, "stopWorker", Qt::BlockingQueuedConnection, - Q_ARG( Feature, feature ) ); -#endif - return; + vCritical() << "thread mismatch for feature" << featureUid; + return false; + } + + stopWorker( featureUid ); + + Worker worker; + + vDebug() << "Starting worker (unmanaged session process) for feature" << featureUid; + + const auto currentUser = VeyonCore::platform().userFunctions().currentUser(); + if( currentUser.isEmpty() ) + { + vDebug() << "could not determine current user - probably a console session with logon screen"; + return false; + } + + const auto ret = VeyonCore::platform().coreFunctions(). + runProgramAsUser( VeyonCore::filesystem().workerFilePath(), { featureUid.toString() }, + currentUser, + VeyonCore::platform().coreFunctions().activeDesktopName() ); + if( ret == false ) + { + vWarning() << "failed to start worker for feature" << featureUid; + return false; } m_workersMutex.lock(); + m_workers[featureUid] = worker; + m_workersMutex.unlock(); + + return true; +} + + + +bool FeatureWorkerManager::stopWorker( Feature::Uid featureUid ) +{ + if( thread() != QThread::currentThread() ) + { + vCritical() << "thread mismatch for feature" << featureUid; + return false; + } + + QMutexLocker locker( &m_workersMutex ); - if( m_workers.contains( feature.uid() ) ) + if( m_workers.contains( featureUid ) ) { - vDebug() << "Stopping worker for feature" << feature.name() << feature.uid(); + vDebug() << "Stopping worker for feature" << featureUid; - auto& worker = m_workers[feature.uid()]; + auto& worker = m_workers[featureUid]; if( worker.socket ) { @@ -166,49 +188,56 @@ void FeatureWorkerManager::stopWorker( const Feature &feature ) killTimer->start( 5000 ); } - m_workers.remove( feature.uid() ); + m_workers.remove( featureUid ); } - m_workersMutex.unlock(); + return false; } -void FeatureWorkerManager::sendMessage( const FeatureMessage& message ) +void FeatureWorkerManager::sendMessageToManagedSystemWorker( const FeatureMessage& message ) { - m_workersMutex.lock(); - - if( m_workers.contains( message.featureUid() ) ) + if( isWorkerRunning( message.featureUid() ) == false && + startManagedSystemWorker( message.featureUid() ) == false ) { - m_workers[message.featureUid()].pendingMessages.append( message ); + vCritical() << "could not start managed system worker"; + return; } - m_workersMutex.unlock(); + sendMessage( message ); + } -bool FeatureWorkerManager::isWorkerRunning( const Feature& feature ) +void FeatureWorkerManager::sendMessageToUnmanagedSessionWorker( const FeatureMessage& message ) { - QMutexLocker locker( &m_workersMutex ); - return m_workers.contains( feature.uid() ); + // don't start worker for logon screen sessions + if( VeyonCore::platform().userFunctions().isAnyUserLoggedInLocally() == false || + VeyonCore::platform().coreFunctions().activeDesktopName().contains( QStringLiteral("winlogon"), Qt::CaseInsensitive ) ) + { + return; + } + + if( isWorkerRunning( message.featureUid() ) == false && + startUnmanagedSessionWorker( message.featureUid() ) == false ) + { + vDebug() << "User session likely not yet available - retrying worker start"; + QTimer::singleShot( UnmanagedSessionProcessRetryInterval, this, + [=]() { sendMessageToUnmanagedSessionWorker( message ); } ); + return; + } + + sendMessage( message ); } -FeatureUidList FeatureWorkerManager::runningWorkers() +bool FeatureWorkerManager::isWorkerRunning( Feature::Uid featureUid ) { QMutexLocker locker( &m_workersMutex ); - - FeatureUidList featureUidList; - featureUidList.reserve( m_workers.size() ); - - for( auto it = m_workers.begin(); it != m_workers.end(); ++it ) - { - featureUidList.append( it.key().toString() ); - } - - return featureUidList; + return m_workers.contains( featureUid ); } @@ -242,15 +271,15 @@ void FeatureWorkerManager::processConnection( QTcpSocket* socket ) if( m_workers[message.featureUid()].socket.isNull() ) { m_workers[message.featureUid()].socket = socket; + sendPendingMessages(); } m_workersMutex.unlock(); if( message.command() >= 0 ) { - m_featureManager.handleFeatureMessage( m_server, MessageContext( socket ), message ); + VeyonCore::featureManager().handleFeatureMessageFromWorker(m_server, message); } - } else { @@ -286,6 +315,24 @@ void FeatureWorkerManager::closeConnection( QTcpSocket* socket ) +void FeatureWorkerManager::sendMessage( const FeatureMessage& message ) +{ + m_workersMutex.lock(); + + if( m_workers.contains( message.featureUid() ) ) + { + m_workers[message.featureUid()].pendingMessages.append( message ); + } + else + { + vWarning() << "worker does not exist for feature" << message.featureUid(); + } + + m_workersMutex.unlock(); +} + + + void FeatureWorkerManager::sendPendingMessages() { m_workersMutex.lock(); @@ -296,7 +343,7 @@ void FeatureWorkerManager::sendPendingMessages() while( worker.socket && worker.pendingMessages.isEmpty() == false ) { - worker.pendingMessages.first().send( worker.socket ); + worker.pendingMessages.first().sendPlain(worker.socket); worker.pendingMessages.removeFirst(); } } diff --git a/core/include/FeatureWorkerManager.h b/core/src/FeatureWorkerManager.h similarity index 70% rename from core/include/FeatureWorkerManager.h rename to core/src/FeatureWorkerManager.h index ffd954b6a..509ef3650 100644 --- a/core/include/FeatureWorkerManager.h +++ b/core/src/FeatureWorkerManager.h @@ -1,7 +1,7 @@ /* * FeatureWorkerManager.h - class for managing feature worker instances * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,12 +24,17 @@ #pragma once -#include #include #include #include #include +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) +#include +#else +#include +#endif + #include "FeatureMessage.h" class FeatureManager; @@ -39,34 +44,31 @@ class VEYON_CORE_EXPORT FeatureWorkerManager : public QObject { Q_OBJECT public: - enum WorkerProcessMode { - ManagedSystemProcess, - UnmanagedSessionProcess, - WorkerProcessModeCount - } ; - - FeatureWorkerManager( VeyonServerInterface& server, FeatureManager& featureManager, QObject* parent = nullptr ); + FeatureWorkerManager( VeyonServerInterface& server, QObject* parent = nullptr ); ~FeatureWorkerManager() override; - Q_INVOKABLE void startWorker( const Feature& feature, WorkerProcessMode workerProcessMode ); - Q_INVOKABLE void stopWorker( const Feature& feature ); + bool startManagedSystemWorker( Feature::Uid featureUid ); + bool startUnmanagedSessionWorker( Feature::Uid featureUid ); - void sendMessage( const FeatureMessage& message ); + bool stopWorker( Feature::Uid featureUid ); + + void sendMessageToManagedSystemWorker( const FeatureMessage& message ); + void sendMessageToUnmanagedSessionWorker( const FeatureMessage& message ); - bool isWorkerRunning( const Feature& feature ); - FeatureUidList runningWorkers(); + bool isWorkerRunning( Feature::Uid featureUid ); private: void acceptConnection(); void processConnection( QTcpSocket* socket ); void closeConnection( QTcpSocket* socket ); + void sendMessage( const FeatureMessage& message ); + void sendPendingMessages(); static constexpr auto UnmanagedSessionProcessRetryInterval = 5000; VeyonServerInterface& m_server; - FeatureManager& m_featureManager; QTcpServer m_tcpServer; struct Worker @@ -79,6 +81,10 @@ class VEYON_CORE_EXPORT FeatureWorkerManager : public QObject using WorkerMap = QMap; WorkerMap m_workers; - QMutex m_workersMutex; +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QRecursiveMutex m_workersMutex; +#else + QMutex m_workersMutex{QMutex::Recursive}; +#endif } ; diff --git a/core/src/FileSystemBrowser.cpp b/core/src/FileSystemBrowser.cpp index 01e390086..bf128440f 100644 --- a/core/src/FileSystemBrowser.cpp +++ b/core/src/FileSystemBrowser.cpp @@ -1,7 +1,7 @@ /* * FileSystemBrowser.cpp - a wrapper class for easily browsing the file system * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -66,18 +66,16 @@ QString FileSystemBrowser::exec( const QString &path, switch( m_browseMode ) { case ExistingDirectory: - chosenPath = QFileDialog::getExistingDirectory( nullptr, title, + chosenPath = QFileDialog::getExistingDirectory(m_parent, title, browsePath, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks ); break; case ExistingFile: - chosenPath = QFileDialog::getOpenFileName( nullptr, title, - browsePath, filter ); + chosenPath = QFileDialog::getOpenFileName(m_parent, title, browsePath, filter); break; case SaveFile: - chosenPath = QFileDialog::getSaveFileName( nullptr, title, - browsePath, filter ); + chosenPath = QFileDialog::getSaveFileName(m_parent, title, browsePath, filter); break; default: break; diff --git a/core/include/FileSystemBrowser.h b/core/src/FileSystemBrowser.h similarity index 90% rename from core/include/FileSystemBrowser.h rename to core/src/FileSystemBrowser.h index 49e88b169..28a359df7 100644 --- a/core/include/FileSystemBrowser.h +++ b/core/src/FileSystemBrowser.h @@ -1,7 +1,7 @@ /* * FileSystemBrowser.h - a wrapper class for easily browsing the file system * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -40,7 +40,8 @@ class VEYON_CORE_EXPORT FileSystemBrowser } ; using BrowseMode = BrowseModes; - explicit FileSystemBrowser( BrowseMode m ) : + explicit FileSystemBrowser(BrowseMode m, QWidget* parent) : + m_parent(parent), m_browseMode( m ), m_expandPath( true ), m_shrinkPath( true ) @@ -64,6 +65,7 @@ class VEYON_CORE_EXPORT FileSystemBrowser private: + QWidget* m_parent; BrowseMode m_browseMode; bool m_expandPath; bool m_shrinkPath; diff --git a/core/src/Filesystem.cpp b/core/src/Filesystem.cpp index f628c60c1..096acf0e9 100644 --- a/core/src/Filesystem.cpp +++ b/core/src/Filesystem.cpp @@ -1,7 +1,7 @@ /* * Filesystem.cpp - filesystem related query and manipulation functions * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,26 +24,29 @@ #include #include +#include +#include #include "VeyonConfiguration.h" #include "Filesystem.h" #include "PlatformFilesystemFunctions.h" +#include "PlatformUserFunctions.h" QString Filesystem::expandPath( QString path ) const { const auto p = QDir::toNativeSeparators( path.replace( QStringLiteral( "%HOME%" ), QDir::homePath() ). - replace( QStringLiteral( "$HOME" ), QDir::homePath() ). + replace( QStringLiteral( "%HOSTNAME%" ), QHostInfo::localHostName() ). replace( QStringLiteral( "%PROFILE%" ), QDir::homePath() ). - replace( QStringLiteral( "$PROFILE" ), QDir::homePath() ). + replace(QStringLiteral( "%USER%" ), VeyonCore::platform().userFunctions().currentUser()). + replace(QStringLiteral("%DESKTOP%"), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)). + replace(QStringLiteral("%DOCUMENTS%"), QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)). + replace(QStringLiteral("%DOWNLOADS%"), QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)). + replace(QStringLiteral("%PICTURES%"), QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)). + replace(QStringLiteral("%VIDEOS%"), QStandardPaths::writableLocation(QStandardPaths::MoviesLocation)). replace( QStringLiteral( "%APPDATA%" ), VeyonCore::platform().filesystemFunctions().personalAppDataPath() ). - replace( QStringLiteral( "$APPDATA" ), VeyonCore::platform().filesystemFunctions().personalAppDataPath() ). replace( QStringLiteral( "%GLOBALAPPDATA%" ), VeyonCore::platform().filesystemFunctions().globalAppDataPath() ). - replace( QStringLiteral( "$GLOBALAPPDATA" ), VeyonCore::platform().filesystemFunctions().globalAppDataPath() ). - replace( QStringLiteral( "%TMP%" ), QDir::tempPath() ). - replace( QStringLiteral( "$TMP" ), QDir::tempPath() ). - replace( QStringLiteral( "%TEMP%" ), QDir::tempPath() ). - replace( QStringLiteral( "$TEMP" ), QDir::tempPath() ) ); + replace(QStringLiteral("%TEMP%"), QDir::tempPath())); // remove duplicate directory separators - however skip the first two chars // as they might specify an UNC path on Windows @@ -63,25 +66,33 @@ QString Filesystem::shrinkPath( QString path ) const { path = QDir::toNativeSeparators( path ); - const QString envVar( QStringLiteral( "%%1%" ) ); + const auto tempPath = QDir::toNativeSeparators(QDir::tempPath()); const auto personalAppDataPath = VeyonCore::platform().filesystemFunctions().personalAppDataPath(); const auto globalAppDataPath = VeyonCore::platform().filesystemFunctions().globalAppDataPath(); - - if( path.startsWith( QDir::toNativeSeparators( QDir::tempPath() ) ) ) - { - path.replace( QDir::toNativeSeparators( QDir::tempPath() ), envVar.arg( QStringLiteral( "TEMP" ) ) ); - } - else if( path.startsWith( personalAppDataPath ) ) - { - path.replace( personalAppDataPath, envVar.arg( QStringLiteral( "APPDATA" ) ) ); - } - else if( path.startsWith( globalAppDataPath ) ) + const auto desktopPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); + const auto documentsPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); + const auto downloadsPath = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation); + const auto picturesPath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); + const auto videosPath = QStandardPaths::writableLocation(QStandardPaths::MoviesLocation); + const auto homePath = QDir::toNativeSeparators(QDir::homePath()); + + for (const auto& mapping : { + qMakePair(tempPath, QStringLiteral("TEMP")), + qMakePair(personalAppDataPath, QStringLiteral("APPDATA")), + qMakePair(globalAppDataPath, QStringLiteral("GLOBALAPPDATA")), + qMakePair(desktopPath, QStringLiteral("DESKTOP")), + qMakePair(documentsPath, QStringLiteral("DOCUMENTS")), + qMakePair(downloadsPath, QStringLiteral("DOWNLOADS")), + qMakePair(picturesPath, QStringLiteral("PICTURES")), + qMakePair(videosPath, QStringLiteral("VIDEOS")), + qMakePair(homePath, QStringLiteral("HOME")), + }) { - path.replace( globalAppDataPath, envVar.arg( QStringLiteral( "GLOBALAPPDATA" ) ) ); - } - else if( path.startsWith( QDir::toNativeSeparators( QDir::homePath() ) ) ) - { - path.replace( QDir::toNativeSeparators( QDir::homePath() ), envVar.arg( QStringLiteral( "HOME" ) ) ); + if (path.startsWith(mapping.first)) + { + path.replace(mapping.first, QStringLiteral("%%1%").arg(mapping.second)); + break; + } } // remove duplicate directory separators - however skip the first two chars @@ -128,22 +139,17 @@ bool Filesystem::ensurePathExists( const QString &path ) const -QString Filesystem::privateKeyPath( const QString& name ) const +QString Filesystem::screenshotDirectoryPath() const { - const auto d = VeyonCore::filesystem().expandPath( VeyonCore::config().privateKeyBaseDir() ) + - QDir::separator() + name + QDir::separator() + QStringLiteral( "key" ); - - return QDir::toNativeSeparators( d ); + return expandPath( VeyonCore::config().screenshotDirectory() ); } -QString Filesystem::publicKeyPath( const QString& name ) const +QString Filesystem::serviceFilePath() const { - const auto d = VeyonCore::filesystem().expandPath( VeyonCore::config().publicKeyBaseDir() ) + - QDir::separator() + name + QDir::separator() + QStringLiteral( "key" ); - - return QDir::toNativeSeparators( d ); + return QDir::toNativeSeparators( QCoreApplication::applicationDirPath() + QDir::separator() + + QStringLiteral("veyon-service" ) + VeyonCore::executableSuffix() ); } diff --git a/core/include/Filesystem.h b/core/src/Filesystem.h similarity index 79% rename from core/include/Filesystem.h rename to core/src/Filesystem.h index 60097cc15..1c8c8742c 100644 --- a/core/include/Filesystem.h +++ b/core/src/Filesystem.h @@ -1,7 +1,7 @@ /* * Filesystem.h - filesystem related query and manipulation functions * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -28,17 +28,22 @@ // clazy:excludeall=rule-of-three -class VEYON_CORE_EXPORT Filesystem +// clazy:excludeall=ctor-missing-parent-argument +class VEYON_CORE_EXPORT Filesystem : public QObject { + Q_OBJECT public: QString expandPath( QString path ) const; QString shrinkPath( QString path ) const; bool ensurePathExists( const QString &path ) const; - QString privateKeyPath( const QString& name ) const; - QString publicKeyPath( const QString& name ) const; + QString screenshotDirectoryPath() const; + QString serviceFilePath() const; QString serverFilePath() const; QString workerFilePath() const; +Q_SIGNALS: + void screenshotDirectoryModified(); + }; diff --git a/core/include/HashList.h b/core/src/HashList.h similarity index 94% rename from core/include/HashList.h rename to core/src/HashList.h index e7869421b..b1a6aa35c 100644 --- a/core/include/HashList.h +++ b/core/src/HashList.h @@ -1,7 +1,7 @@ /* * HashList.h - extended QHash acting like a list * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/core/src/HostAddress.cpp b/core/src/HostAddress.cpp index 9287c60a6..e969c3e24 100644 --- a/core/src/HostAddress.cpp +++ b/core/src/HostAddress.cpp @@ -1,7 +1,7 @@ /* * HostAddress.cpp - implementation of HostAddress class * - * Copyright (c) 2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,10 +24,13 @@ #include #include +#include #include "HostAddress.h" +QString HostAddress::s_cachedLocalFQDN; + HostAddress::HostAddress( const QString& address ) : m_type( determineType( address ) ), m_address( address ) @@ -99,26 +102,67 @@ QString HostAddress::tryConvert( HostAddress::Type targetType ) const -QString HostAddress::localFQDN() +QStringList HostAddress::lookupIpAddresses() const { - const auto localHostName = QHostInfo::localHostName(); - const auto type = determineType( localHostName ); + const auto hostName = convert( Type::FullyQualifiedDomainName ); + const auto hostInfo = QHostInfo::fromName( hostName ); + if( hostInfo.error() != QHostInfo::NoError || hostInfo.addresses().isEmpty() ) + { + vWarning() << "could not lookup IP addresses of host" << hostName << "error:" << hostInfo.errorString(); + return {}; + } - switch( type ) + QStringList ipAddresses; + + const auto addresses = hostInfo.addresses(); + ipAddresses.reserve( addresses.size() ); + + for( const auto& address : addresses ) { - case Type::HostName: - return localHostName + QStringLiteral( "." ) + QHostInfo::localDomainName(); + ipAddresses.append( address.toString() ); + } - case Type::FullyQualifiedDomainName: - return localHostName; + return ipAddresses; +} - default: - break; + +static QUrl parseAddressToUrl( const QString& address ) +{ + const auto colonCount = address.count( QLatin1Char(':') ); + if( colonCount > 1 ) + { + const auto parts = address.split( QLatin1Char(':') ); + return QUrl( QStringLiteral("scheme://[%1]:%2").arg( parts.mid( 0, colonCount ).join( QLatin1Char(':') ), + parts.last() ) ); } - vWarning() << "Could not determine local host name:" << localHostName; + return QUrl( QStringLiteral("scheme://%1").arg( address ) ); +} + + + +QString HostAddress::parseHost( const QString& address ) +{ + return parseAddressToUrl( address ).host(); +} + + + +int HostAddress::parsePortNumber( const QString& address ) +{ + return parseAddressToUrl( address ).port(); +} + + - return HostAddress( localHostName ).convert( Type::FullyQualifiedDomainName ); +QString HostAddress::localFQDN() +{ + if( s_cachedLocalFQDN.isEmpty() ) + { + s_cachedLocalFQDN = resolveLocalFQDN(); + } + + return s_cachedLocalFQDN; } @@ -164,11 +208,7 @@ QString HostAddress::toIpAddress( const QString& hostName ) return {}; } -#if QT_VERSION < 0x050600 - const auto ipAddress = hostInfo.addresses().value( 0 ).toString(); -#else const auto ipAddress = hostInfo.addresses().constFirst().toString(); -#endif vDebug() << "Resolved IP address of host" << hostName << "to" << ipAddress; return ipAddress; @@ -201,8 +241,10 @@ QString HostAddress::toHostName( HostAddress::Type type, const QString& address return fqdnToHostName( hostInfo.hostName() ); } - case Type::Invalid: case Type::HostName: + return address; + + case Type::Invalid: break; } @@ -235,8 +277,10 @@ QString HostAddress::toFQDN( HostAddress::Type type, const QString& address ) return hostInfo.hostName(); } - case Type::Invalid: case Type::FullyQualifiedDomainName: + return address; + + case Type::Invalid: break; } @@ -247,9 +291,31 @@ QString HostAddress::toFQDN( HostAddress::Type type, const QString& address ) QString HostAddress::fqdnToHostName( const QString& fqdn ) { -#if QT_VERSION < 0x050600 - return fqdn.split( QLatin1Char( '.' ) ).value( 0 ); -#else - return fqdn.split( QLatin1Char( '.' ) ).constFirst(); -#endif + return fqdn.split( QLatin1Char( '.' ) ).constFirst(); +} + + + +QString HostAddress::resolveLocalFQDN() +{ + const auto localHostName = QHostInfo::localHostName(); + const auto type = determineType( localHostName ); + + switch( type ) + { + case Type::HostName: + if( QHostInfo::localDomainName().isEmpty() == false ) + { + return localHostName + QStringLiteral( "." ) + QHostInfo::localDomainName(); + } + + case Type::FullyQualifiedDomainName: + return localHostName; + + default: + vWarning() << "Could not determine local host name:" << localHostName; + break; + } + + return HostAddress( localHostName ).tryConvert( Type::FullyQualifiedDomainName ); } diff --git a/core/include/HostAddress.h b/core/src/HostAddress.h similarity index 85% rename from core/include/HostAddress.h rename to core/src/HostAddress.h index f6ff1e0d4..372927c29 100644 --- a/core/include/HostAddress.h +++ b/core/src/HostAddress.h @@ -1,7 +1,7 @@ /* * HostAddress.h - header for HostAddress class * - * Copyright (c) 2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -51,6 +51,11 @@ class VEYON_CORE_EXPORT HostAddress QString convert( Type targetType ) const; QString tryConvert( Type targetType ) const; + QStringList lookupIpAddresses() const; + + static QString parseHost( const QString& address ); + static int parsePortNumber( const QString& address ); + static QString localFQDN(); private: @@ -59,6 +64,9 @@ class VEYON_CORE_EXPORT HostAddress static QString toHostName( Type type, const QString& address ); static QString toFQDN( Type type, const QString& address ); static QString fqdnToHostName( const QString& fqdn ); + static QString resolveLocalFQDN(); + + static QString s_cachedLocalFQDN; Type m_type; QString m_address; diff --git a/core/include/KeyboardShortcutTrapper.h b/core/src/KeyboardShortcutTrapper.h similarity index 90% rename from core/include/KeyboardShortcutTrapper.h rename to core/src/KeyboardShortcutTrapper.h index d87a65fa0..fd8403426 100644 --- a/core/include/KeyboardShortcutTrapper.h +++ b/core/src/KeyboardShortcutTrapper.h @@ -1,7 +1,7 @@ /* * KeyboardShortcutTrapper.h - class for trapping system-wide keyboard shortcuts * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -50,7 +50,7 @@ class VEYON_CORE_EXPORT KeyboardShortcutTrapper : public QObject virtual void setEnabled( bool on ) = 0; -signals: - void shortcutTrapped( Shortcut ); +Q_SIGNALS: + void shortcutTrapped( KeyboardShortcutTrapper::Shortcut ); } ; diff --git a/core/src/LockWidget.cpp b/core/src/LockWidget.cpp index d9753511e..405958fe7 100644 --- a/core/src/LockWidget.cpp +++ b/core/src/LockWidget.cpp @@ -1,7 +1,7 @@ /* * LockWidget.cpp - widget for locking a client * - * Copyright (c) 2006-2016 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,8 +26,9 @@ #include "PlatformInputDeviceFunctions.h" #include -#include #include +#include +#include LockWidget::LockWidget( Mode mode, const QPixmap& background, QWidget* parent ) : @@ -35,19 +36,43 @@ LockWidget::LockWidget( Mode mode, const QPixmap& background, QWidget* parent ) m_background( background ), m_mode( mode ) { - VeyonCore::platform().coreFunctions().setSystemUiState( false ); - VeyonCore::platform().inputDeviceFunctions().disableInputDevices(); + auto leftMostScreen = QGuiApplication::primaryScreen(); + int minimumX = 0; + const auto screens = QGuiApplication::screens(); + for (auto* screen : screens) + { + if (screen->geometry().x() < minimumX) + { + minimumX = screen->geometry().x(); + leftMostScreen = screen; + } + } - if( mode == DesktopVisible ) + if (mode == DesktopVisible) { - m_background = QPixmap::grabWindow( qApp->desktop()->winId() ); + m_background = leftMostScreen->grabWindow(0); } + VeyonCore::platform().coreFunctions().setSystemUiState( false ); + VeyonCore::platform().inputDeviceFunctions().disableInputDevices(); + setWindowTitle( {} ); + +#ifdef Q_OS_LINUX + show(); +#endif + move(leftMostScreen->geometry().topLeft()); +#ifndef Q_OS_LINUX showFullScreen(); - move( 0, 0 ); - setFixedSize( qApp->desktop()->size() ); - VeyonCore::platform().coreFunctions().raiseWindow( this ); +#endif + windowHandle()->setScreen(leftMostScreen); + setFixedSize(leftMostScreen->virtualSize()); + + VeyonCore::platform().coreFunctions().raiseWindow(this, true); +#ifdef Q_OS_LINUX + showFullScreen(); +#endif + setFocusPolicy( Qt::StrongFocus ); setFocus(); grabMouse(); @@ -72,7 +97,7 @@ LockWidget::~LockWidget() void LockWidget::paintEvent( QPaintEvent* event ) { - Q_UNUSED(event); + Q_UNUSED(event) QPainter p( this ); switch( m_mode ) diff --git a/core/include/LockWidget.h b/core/src/LockWidget.h similarity index 95% rename from core/include/LockWidget.h rename to core/src/LockWidget.h index 20b40db06..dee359d0d 100644 --- a/core/include/LockWidget.h +++ b/core/src/LockWidget.h @@ -1,7 +1,7 @@ /* * LockWidget.h - widget for locking a client * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/core/src/Lockable.h b/core/src/Lockable.h new file mode 100644 index 000000000..7f478e0e5 --- /dev/null +++ b/core/src/Lockable.h @@ -0,0 +1,52 @@ +/* + * Lockable.h - header file for Lockable + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#pragma once + +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) +#include +#else +#include +#endif + +class Lockable +{ +public: + virtual void lock() + { + m_mutex.lock(); + } + + virtual void unlock() + { + m_mutex.unlock(); + } + +private: +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QRecursiveMutex m_mutex{}; +#else + QMutex m_mutex{QMutex::Recursive}; +#endif + +}; diff --git a/core/src/LockingPointer.h b/core/src/LockingPointer.h new file mode 100644 index 000000000..30955a13a --- /dev/null +++ b/core/src/LockingPointer.h @@ -0,0 +1,62 @@ +/* + * LockingPointer.h - smart pointer for lockables + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#pragma once + +template +class LockingPointer +{ +public: + LockingPointer( T lockable ) : m_lockable( lockable ) + { + if( m_lockable ) + { + m_lockable->lock(); + } + } + + ~LockingPointer() + { + if( m_lockable ) + { + m_lockable->unlock(); + } + } + + LockingPointer( LockingPointer&& lockingPointer ) : m_lockable( lockingPointer.m_lockable ) + { + lockingPointer.m_lockable = nullptr; + } + + LockingPointer( LockingPointer const& ) = delete; + LockingPointer& operator=( LockingPointer const& ) = delete; + + T operator->() const + { + return m_lockable; + } + +private: + T m_lockable; +}; + diff --git a/core/src/Logger.cpp b/core/src/Logger.cpp index 19ddc98e4..ef3607ea4 100644 --- a/core/src/Logger.cpp +++ b/core/src/Logger.cpp @@ -1,7 +1,7 @@ /* * Logger.cpp - a global clas for easily logging messages to log files * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,22 +31,14 @@ #include "Filesystem.h" #include "Logger.h" #include "PlatformCoreFunctions.h" +#include "PlatformFilesystemFunctions.h" QAtomicPointer Logger::s_instance = nullptr; QMutex Logger::s_instanceMutex; Logger::Logger( const QString &appName ) : - m_logLevel( LogLevel::Default ), - m_logMutex(), - m_lastMessageLevel( LogLevel::Nothing ), - m_lastMessage(), - m_lastMessageCount( 0 ), - m_logToSystem( false ), - m_appName( QStringLiteral( "Veyon" ) + appName ), - m_logFile( nullptr ), - m_logFileSizeLimit( -1 ), - m_logFileRotationCount( -1 ) + m_appName( QStringLiteral( "Veyon" ) + appName ) { s_instanceMutex.lock(); @@ -55,16 +47,27 @@ Logger::Logger( const QString &appName ) : s_instance = this; s_instanceMutex.unlock(); + m_logToSystem = VeyonCore::config().logToSystem(); + m_logToStdErr = VeyonCore::config().logToStdErr(); + auto configuredLogLevel = VeyonCore::config().logLevel(); if( qEnvironmentVariableIsSet( logLevelEnvironmentVariable() ) ) { - configuredLogLevel = static_cast( qEnvironmentVariableIntValue( logLevelEnvironmentVariable() ) ); + configuredLogLevel = logLevelFromString( +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) + qEnvironmentVariable(logLevelEnvironmentVariable()) +#else + QLatin1String(qgetenv(logLevelEnvironmentVariable())) +#endif + ); } m_logLevel = qBound( LogLevel::Min, configuredLogLevel, LogLevel::Max ); - m_logToSystem = VeyonCore::config().logToSystem(); - initLogFile(); + if( m_logLevel > LogLevel::Nothing ) + { + initLogFile(); + } qInstallMessageHandler( qtMsgHandler ); @@ -101,6 +104,38 @@ Logger::~Logger() +Logger::LogLevel Logger::logLevelFromString(const QString& logLevelString) +{ + if (logLevelString.startsWith(QLatin1String("debug"))) + { + return LogLevel::Debug; + } + + if (logLevelString.startsWith(QLatin1String("info"))) + { + return LogLevel::Info; + } + + if (logLevelString.startsWith(QLatin1String("warn"))) + { + return LogLevel::Warning; + } + + if (logLevelString.startsWith(QLatin1String("err"))) + { + return LogLevel::Error; + } + + if (logLevelString.startsWith(QLatin1String("crit"))) + { + return LogLevel::Critical; + } + + return LogLevel(logLevelString.toUInt()); +} + + + void Logger::initLogFile() { @@ -125,7 +160,8 @@ void Logger::initLogFile() if( VeyonCore::config().logFileSizeLimitEnabled() ) { - m_logFileSizeLimit = VeyonCore::config().logFileSizeLimit() * 1024 * 1024; + static constexpr auto BytesPerKB = 1024; + m_logFileSizeLimit = VeyonCore::config().logFileSizeLimit() * BytesPerKB * BytesPerKB; } if( VeyonCore::config().logFileRotationEnabled() ) @@ -138,15 +174,26 @@ void Logger::initLogFile() void Logger::openLogFile() { - m_logFile->open( QFile::WriteOnly | QFile::Append | QFile::Unbuffered | QFile::Text ); - m_logFile->setPermissions( QFile::ReadOwner | QFile::WriteOwner ); + if( VeyonCore::platform().filesystemFunctions().openFileSafely( + m_logFile, + QFile::WriteOnly | QFile::Append | QFile::Unbuffered | QFile::Text, + QFile::ReadOwner | QFile::WriteOwner ) == false ) + { + vCritical() << m_logFile->fileName() << "is a symlink and will not be written to for security reasons"; + m_logFile->close(); + delete m_logFile; + m_logFile = nullptr; + } } void Logger::closeLogFile() { - m_logFile->close(); + if( m_logFile ) + { + m_logFile->close(); + } } @@ -154,7 +201,10 @@ void Logger::closeLogFile() void Logger::clearLogFile() { closeLogFile(); - m_logFile->remove(); + if( m_logFile ) + { + m_logFile->remove(); + } openLogFile(); } @@ -162,7 +212,7 @@ void Logger::clearLogFile() void Logger::rotateLogFile() { - if( m_logFileRotationCount < 1 ) + if( m_logFileRotationCount < 1 || m_logFile == nullptr ) { return; } @@ -180,14 +230,7 @@ void Logger::rotateLogFile() logFileInfo.dir().remove( rotatedLogFiles.takeLast() ); } -#if QT_VERSION < 0x050600 -#warning Building compat code for unsupported version of Qt - using QStringListReverseIterator = std::reverse_iterator; - for( auto it = QStringListReverseIterator(rotatedLogFiles.cend()), - end = QStringListReverseIterator(rotatedLogFiles.cbegin()); it != end; ++it ) -#else for( auto it = rotatedLogFiles.crbegin(), end = rotatedLogFiles.crend(); it != end; ++it ) -#endif { bool numberOk = false; int logFileIndex = it->section( QLatin1Char('.'), -1 ).toInt( &numberOk ); @@ -225,9 +268,10 @@ QString Logger::formatMessage( LogLevel ll, const QString& message ) default: break; } - return QStringLiteral( "%1.%2: [%3] %4\n" ).arg( + return QStringLiteral( "%1.%2: [%3] [%4] %5\n" ).arg( QDateTime::currentDateTime().toString( Qt::ISODate ), QDateTime::currentDateTime().toString( QStringLiteral( "zzz" ) ), + QString::number( VeyonCore::instance()->sessionId() ), messageType, message.trimmed() ); } @@ -239,7 +283,9 @@ void Logger::qtMsgHandler( QtMsgType messageType, const QMessageLogContext& cont { QMutexLocker instanceLocker( &s_instanceMutex ); - if( s_instance.load() == nullptr ) + const auto instance = s_instance.loadAcquire(); + + if( instance == nullptr || message.size() > MaximumMessageSize ) { return; } @@ -257,11 +303,11 @@ void Logger::qtMsgHandler( QtMsgType messageType, const QMessageLogContext& cont if( context.category && strcmp(context.category, "default") != 0 ) { - s_instance.load()->log( logLevel, QStringLiteral( "[%1] " ).arg(QLatin1String(context.category)) + message ); + instance->log( logLevel, QStringLiteral( "[%1] " ).arg(QLatin1String(context.category)) + message ); } else { - s_instance.load()->log( logLevel, message ); + instance->log( logLevel, message ); } } @@ -322,7 +368,7 @@ void Logger::outputMessage( const QString& message ) } } - if( VeyonCore::config().logToStdErr() ) + if (m_logToStdErr) { fprintf( stderr, "%s", message.toUtf8().constData() ); fflush( stderr ); diff --git a/core/include/Logger.h b/core/src/Logger.h similarity index 78% rename from core/include/Logger.h rename to core/src/Logger.h index 4244331d7..9c5b46281 100644 --- a/core/include/Logger.h +++ b/core/src/Logger.h @@ -1,7 +1,7 @@ /* * Logger.h - a global clas for easily logging messages to log files * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -54,7 +54,8 @@ class VEYON_CORE_EXPORT Logger static constexpr int DefaultFileSizeLimit = 100; static constexpr int DefaultFileRotationCount = 10; - static constexpr const char* DefaultLogFileDirectory = "$TEMP"; + static constexpr int MaximumMessageSize = 16384; + static constexpr const char* DefaultLogFileDirectory = "%TEMP%"; explicit Logger( const QString &appName ); ~Logger(); @@ -69,6 +70,7 @@ class VEYON_CORE_EXPORT Logger return m_logLevel; } + static LogLevel logLevelFromString(const QString& logLevelString); private: void initLogFile(); @@ -86,18 +88,19 @@ class VEYON_CORE_EXPORT Logger static QAtomicPointer s_instance; static QMutex s_instanceMutex; - LogLevel m_logLevel; - QMutex m_logMutex; + LogLevel m_logLevel{LogLevel::Default}; + QMutex m_logMutex{}; - LogLevel m_lastMessageLevel; - QString m_lastMessage; - int m_lastMessageCount; - bool m_logToSystem; + LogLevel m_lastMessageLevel{LogLevel::Nothing}; + QString m_lastMessage{}; + int m_lastMessageCount{0}; + bool m_logToStdErr{false}; + bool m_logToSystem{false}; QString m_appName; - QFile *m_logFile; - int m_logFileSizeLimit; - int m_logFileRotationCount; + QFile* m_logFile{nullptr}; + int m_logFileSizeLimit{-1}; + int m_logFileRotationCount{-1}; } ; diff --git a/core/include/MessageContext.h b/core/src/MessageContext.h similarity index 78% rename from core/include/MessageContext.h rename to core/src/MessageContext.h index 484c5276a..85f3fe6ff 100644 --- a/core/include/MessageContext.h +++ b/core/src/MessageContext.h @@ -1,7 +1,7 @@ /* * MessageContext.h - header for transporting context for message I/O * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -34,9 +34,11 @@ class VEYON_CORE_EXPORT MessageContext { public: using IODevice = QPointer; + using Connection = QPointer; - explicit MessageContext( QIODevice* ioDevice ) : - m_ioDevice( ioDevice ) + explicit MessageContext(QIODevice* ioDevice = nullptr, QObject* connection = nullptr) : + m_ioDevice( ioDevice ), + m_connection(connection) { } @@ -47,7 +49,13 @@ class VEYON_CORE_EXPORT MessageContext return m_ioDevice; } + QObject* connection() const + { + return m_connection; + } + private: IODevice m_ioDevice; + Connection m_connection; } ; diff --git a/core/src/MonitoringMode.cpp b/core/src/MonitoringMode.cpp index 068cff355..0cb3056b3 100644 --- a/core/src/MonitoringMode.cpp +++ b/core/src/MonitoringMode.cpp @@ -1,7 +1,7 @@ /* * MonitoringMode.cpp - implementation of MonitoringMode class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,17 +22,471 @@ * */ +#include +#include +#include + +#include "FeatureManager.h" #include "MonitoringMode.h" +#include "PlatformUserFunctions.h" +#include "VeyonConfiguration.h" +#include "VeyonServerInterface.h" + MonitoringMode::MonitoringMode( QObject* parent ) : QObject( parent ), m_monitoringModeFeature( QLatin1String( staticMetaObject.className() ), - Feature::Mode | Feature::Master | Feature::Builtin, + Feature::Flag::Mode | Feature::Flag::Master | Feature::Flag::Builtin, Feature::Uid( "edad8259-b4ef-4ca5-90e6-f238d0fda694" ), Feature::Uid(), tr( "Monitoring" ), tr( "Monitoring" ), tr( "This mode allows you to monitor all computers at one or more locations." ), QStringLiteral( ":/core/presentation-none.png" ) ), - m_features( { m_monitoringModeFeature } ) + m_queryApplicationVersionFeature( QStringLiteral("QueryApplicationVersion"), + Feature::Flag::Service | Feature::Flag::Builtin, + Feature::Uid{"58f5d5d5-9929-48f4-a995-f221c150ae26"}, {}, + tr("Query application version of the server"), {}, {} ), + m_queryActiveFeatures( QStringLiteral("QueryActiveFeatures"), + Feature::Flag::Service | Feature::Flag::Builtin, + Feature::Uid{"a0a96fba-425d-414a-aaf4-352b76d7c4f3"}, {}, + tr("Query active features"), {}, {} ), + m_queryUserInfoFeature(QStringLiteral("UserInfo"), + Feature::Flag::Session | Feature::Flag::Service | Feature::Flag::Builtin, + Feature::Uid("79a5e74d-50bd-4aab-8012-0e70dc08cc72"), + Feature::Uid(), {}, {}, {} ), + m_querySessionInfoFeature(QStringLiteral("SessionInfo"), + Feature::Flag::Session | Feature::Flag::Service | Feature::Flag::Builtin, + Feature::Uid("699ed9dd-f58b-477b-a0af-df8105571b3c"), + Feature::Uid(), {}, {}, {}), + m_queryScreensFeature( QStringLiteral("QueryScreens"), + Feature::Flag::Meta, + Feature::Uid("d5bbc486-7bc5-4c36-a9a8-1566c8b0091a"), + Feature::Uid(), tr("Query properties of remotely available screens"), {}, {} ), + m_features({ m_monitoringModeFeature, m_queryApplicationVersionFeature, m_queryActiveFeatures, + m_queryUserInfoFeature, m_querySessionInfoFeature, m_queryScreensFeature}), + m_sessionMetaDataContent(VeyonCore::config().sessionMetaDataContent()), + m_sessionMetaDataEnvironmentVariable(VeyonCore::config().sessionMetaDataEnvironmentVariable()), + m_sessionMetaDataRegistryKey(VeyonCore::config().sessionMetaDataRegistryKey()) +{ + if(VeyonCore::component() == VeyonCore::Component::Server) + { + connect(&m_activeFeaturesUpdateTimer, &QTimer::timeout, this, &MonitoringMode::updateActiveFeatures); + m_activeFeaturesUpdateTimer.start(ActiveFeaturesUpdateInterval); + + connect(&m_sessionInfoUpdateTimer, &QTimer::timeout, this, &MonitoringMode::updateSessionInfo); + m_sessionInfoUpdateTimer.start(SessionInfoUpdateInterval); + + updateUserInfo(); + updateSessionInfo(); + updateScreenInfoList(); + + connect(qGuiApp, &QGuiApplication::screenAdded, this, &MonitoringMode::updateScreenInfoList); + connect(qGuiApp, &QGuiApplication::screenRemoved, this, &MonitoringMode::updateScreenInfoList); + } +} + + + +void MonitoringMode::ping(const ComputerControlInterfaceList& computerControlInterfaces) +{ + sendFeatureMessage(FeatureMessage{m_monitoringModeFeature.uid(), Command::Ping}, computerControlInterfaces); +} + + + +void MonitoringMode::setMinimumFramebufferUpdateInterval(const ComputerControlInterfaceList& computerControlInterfaces, + int interval) +{ + sendFeatureMessage(FeatureMessage{m_monitoringModeFeature.uid(), Command::SetMinimumFramebufferUpdateInterval} + .addArgument(Argument::MinimumFramebufferUpdateInterval, interval), + computerControlInterfaces); +} + + + +void MonitoringMode::queryApplicationVersion(const ComputerControlInterfaceList& computerControlInterfaces) +{ + sendFeatureMessage(FeatureMessage{m_queryApplicationVersionFeature.uid()}, computerControlInterfaces); +} + + + +void MonitoringMode::queryActiveFeatures(const ComputerControlInterfaceList& computerControlInterfaces) +{ + sendFeatureMessage(FeatureMessage{m_queryActiveFeatures.uid()}, computerControlInterfaces); +} + + + +void MonitoringMode::queryUserInfo(const ComputerControlInterfaceList& computerControlInterfaces) +{ + sendFeatureMessage(FeatureMessage{m_queryUserInfoFeature.uid()}, computerControlInterfaces); +} + + + +void MonitoringMode::querySessionInfo(const ComputerControlInterfaceList& computerControlInterfaces) { + sendFeatureMessage(FeatureMessage{m_querySessionInfoFeature.uid()}, computerControlInterfaces); +} + + + +void MonitoringMode::queryScreens(const ComputerControlInterfaceList& computerControlInterfaces) +{ + sendFeatureMessage(FeatureMessage{m_queryScreensFeature.uid()}, computerControlInterfaces); +} + + + +bool MonitoringMode::handleFeatureMessage( ComputerControlInterface::Pointer computerControlInterface, + const FeatureMessage& message ) +{ + if (message.featureUid() == m_monitoringModeFeature.uid()) + { + if (message.command() == Command::Ping) + { + // successful ping reply implicitly handled through the featureMessageReceived() signal + return true; + } + } + + if (message.featureUid() == m_queryApplicationVersionFeature.uid()) + { + computerControlInterface->setServerVersion(message.argument(Argument::ApplicationVersion) + .value()); + return true; + } + + if( message.featureUid() == m_queryActiveFeatures.uid() ) + { + const auto featureUidStrings = message.argument(Argument::ActiveFeaturesList).toStringList(); + + FeatureUidList activeFeatures{}; + activeFeatures.reserve(featureUidStrings.size()); + + for(const auto& featureUidString : featureUidStrings) + { + activeFeatures.append(Feature::Uid{featureUidString}); + } + + computerControlInterface->setActiveFeatures(activeFeatures); + + return true; + } + + if( message.featureUid() == m_queryUserInfoFeature.uid() ) + { + computerControlInterface->setUserInformation(message.argument( Argument::UserLoginName ).toString(), + message.argument( Argument::UserFullName ).toString()); + + return true; + } + + if (message.featureUid() == m_querySessionInfoFeature.uid()) + { + computerControlInterface->setSessionInfo(PlatformSessionFunctions::SessionInfo{ + message.argument(Argument::SessionId).toInt(), + message.argument(Argument::SessionUptime).toInt(), + message.argument(Argument::SessionClientAddress).toString(), + message.argument(Argument::SessionClientName).toString(), + message.argument(Argument::SessionHostName).toString(), + message.argument(Argument::SessionMetaData).toString(), + }); + + return true; + } + + if( message.featureUid() == m_queryScreensFeature.uid() ) + { + const auto screenInfoList = message.argument(Argument::ScreenInfoList).toList(); + + ComputerControlInterface::ScreenList screens; + screens.reserve(screenInfoList.size()); + + for(int i = 0; i < screenInfoList.size(); ++i) + { + const auto screenInfo = screenInfoList.at(i).toMap(); + ComputerControlInterface::ScreenProperties screenProperties; + screenProperties.index = i + 1; + screenProperties.name = screenInfo.value(QStringLiteral("name")).toString(); + screenProperties.geometry = screenInfo.value(QStringLiteral("geometry")).toRect(); + screens.append(screenProperties); + } + + computerControlInterface->setScreens(screens); + } + + return false; +} + + + +bool MonitoringMode::handleFeatureMessage(VeyonServerInterface& server, + const MessageContext& messageContext, + const FeatureMessage& message) +{ + if (message.featureUid() == m_monitoringModeFeature.uid()) + { + if (message.command() == Command::Ping) + { + return server.sendFeatureMessageReply(messageContext, message); + } + + if (message.command() == Command::SetMinimumFramebufferUpdateInterval) + { + server.setMinimumFramebufferUpdateInterval(messageContext, + message.argument(Argument::MinimumFramebufferUpdateInterval).toInt()); + return true; + } + } + + if (message.featureUid() == m_queryApplicationVersionFeature.uid()) + { + server.sendFeatureMessageReply(messageContext, + FeatureMessage{m_queryApplicationVersionFeature.uid()} + .addArgument(Argument::ApplicationVersion, int(VeyonCore::config().applicationVersion()))); + } + + if (m_queryActiveFeatures.uid() == message.featureUid()) + { + return sendActiveFeatures(server, messageContext); + } + + if (message.featureUid() == m_queryUserInfoFeature.uid()) + { + return sendUserInformation(server, messageContext); + } + + if (message.featureUid() == m_querySessionInfoFeature.uid()) + { + return sendSessionInfo(server, messageContext); + } + + if (message.featureUid() == m_queryScreensFeature.uid()) + { + return sendScreenInfoList(server, messageContext); + } + + return false; +} + + + +void MonitoringMode::sendAsyncFeatureMessages(VeyonServerInterface& server, const MessageContext& messageContext) +{ + const auto activeFeaturesVersion = messageContext.ioDevice()->property(activeFeaturesVersionProperty()).toInt(); + + if (activeFeaturesVersion != m_activeFeaturesVersion) + { + sendActiveFeatures(server, messageContext); + messageContext.ioDevice()->setProperty(activeFeaturesVersionProperty(), m_activeFeaturesVersion); + } + + const auto currentUserInfoVersion = m_userInfoVersion.loadAcquire(); + const auto contextUserInfoVersion = messageContext.ioDevice()->property(userInfoVersionProperty()).toInt(); + + if(contextUserInfoVersion != currentUserInfoVersion) + { + sendUserInformation(server, messageContext); + messageContext.ioDevice()->setProperty(userInfoVersionProperty(), currentUserInfoVersion); + } + + const auto currentSessionInfoVersion = m_sessionInfoVersion.loadAcquire(); + const auto sessionInfoVersion = messageContext.ioDevice()->property(sessionInfoVersionProperty()).toInt(); + + if (sessionInfoVersion != currentSessionInfoVersion) + { + sendSessionInfo(server, messageContext); + messageContext.ioDevice()->setProperty(sessionInfoVersionProperty(), currentSessionInfoVersion); + } + + const auto screenInfoVersion = messageContext.ioDevice()->property(screenInfoListVersionProperty()).toInt(); + + if (screenInfoVersion != m_screenInfoListVersion) + { + sendScreenInfoList(server, messageContext); + messageContext.ioDevice()->setProperty(screenInfoListVersionProperty(), m_screenInfoListVersion); + } +} + + + +bool MonitoringMode::sendActiveFeatures(VeyonServerInterface& server, const MessageContext& messageContext) +{ + return server.sendFeatureMessageReply(messageContext, + FeatureMessage{m_queryActiveFeatures.uid()} + .addArgument(Argument::ActiveFeaturesList, m_activeFeatures)); +} + + + +bool MonitoringMode::sendUserInformation(VeyonServerInterface& server, const MessageContext& messageContext) +{ + FeatureMessage message{m_queryUserInfoFeature.uid()}; + + m_userDataLock.lockForRead(); + if (m_userLoginName.isEmpty()) + { + updateUserInfo(); + message.addArgument(Argument::UserLoginName, QString{}); + message.addArgument(Argument::UserFullName, QString{}); + } + else + { + message.addArgument(Argument::UserLoginName, m_userLoginName); + message.addArgument(Argument::UserFullName, m_userFullName); + } + m_userDataLock.unlock(); + + return server.sendFeatureMessageReply(messageContext, message); +} + + + +bool MonitoringMode::sendSessionInfo(VeyonServerInterface& server, const MessageContext& messageContext) +{ + FeatureMessage message{m_querySessionInfoFeature.uid()}; + + m_sessionInfoLock.lockForRead(); + message.addArgument(Argument::SessionId, m_sessionInfo.id); + message.addArgument(Argument::SessionUptime, m_sessionInfo.uptime); + message.addArgument(Argument::SessionClientAddress, m_sessionInfo.clientAddress); + message.addArgument(Argument::SessionClientName, m_sessionInfo.clientName); + message.addArgument(Argument::SessionHostName, m_sessionInfo.hostName); + message.addArgument(Argument::SessionMetaData, m_sessionInfo.metaData); + m_sessionInfoLock.unlock(); + + return server.sendFeatureMessageReply(messageContext,message); +} + + + +bool MonitoringMode::sendScreenInfoList(VeyonServerInterface& server, const MessageContext& messageContext) +{ + return server.sendFeatureMessageReply(messageContext, + FeatureMessage{m_queryScreensFeature.uid()} + .addArgument(Argument::ScreenInfoList, m_screenInfoList)); +} + + + +void MonitoringMode::updateActiveFeatures() +{ + const auto server = VeyonCore::instance()->findChild(); + if (server) + { + const auto activeFeaturesUids = VeyonCore::featureManager().activeFeatures(*server); + + QStringList activeFeatures; + activeFeatures.reserve(activeFeaturesUids.size()); + + for (const auto& activeFeatureUid : activeFeaturesUids) + { + activeFeatures.append(activeFeatureUid.toString()); + } + + if (activeFeatures != m_activeFeatures) + { + m_activeFeatures = activeFeatures; + m_activeFeaturesVersion++; + } + } +} + + + +void MonitoringMode::updateUserInfo() +{ + // asynchronously query information about logged on user (which might block + // due to domain controller queries and timeouts etc.) + (void) QtConcurrent::run( [=]() { + if( VeyonCore::platform().sessionFunctions().currentSessionHasUser() ) + { + const auto userLoginName = VeyonCore::platform().userFunctions().currentUser(); + const auto userFullName = VeyonCore::platform().userFunctions().fullName( userLoginName ); + m_userDataLock.lockForWrite(); + if(m_userLoginName != userLoginName || + m_userFullName != userFullName) + { + m_userLoginName = userLoginName; + m_userFullName = userFullName; + ++m_userInfoVersion; + } + m_userDataLock.unlock(); + } + + m_userDataLock.lockForRead(); + if (m_userLoginName.isEmpty() && m_userFullName.isEmpty()) + { + QTimer::singleShot(UserInfoUpdateRetryInterval, this, &MonitoringMode::updateUserInfo); + } + m_userDataLock.unlock(); + } ); +} + + + +void MonitoringMode::updateSessionInfo() +{ + (void) QtConcurrent::run([=]() { + QString sessionMetaData; + switch (m_sessionMetaDataContent) + { + case PlatformSessionFunctions::SessionMetaDataContent::EnvironmentVariable: + sessionMetaData = VeyonCore::platform().sessionFunctions().currentSessionEnvironmentVariables().value(m_sessionMetaDataEnvironmentVariable); + break; + case PlatformSessionFunctions::SessionMetaDataContent::RegistryKey: + sessionMetaData = VeyonCore::platform().sessionFunctions().querySettingsValueInCurrentSession(m_sessionMetaDataRegistryKey).toString(); + break; + case PlatformSessionFunctions::SessionMetaDataContent::None: + break; + } + + const PlatformSessionFunctions::SessionInfo currentSessionInfo{ + VeyonCore::sessionId(), + VeyonCore::platform().sessionFunctions().currentSessionUptime(), + VeyonCore::platform().sessionFunctions().currentSessionClientAddress(), + VeyonCore::platform().sessionFunctions().currentSessionClientName(), + VeyonCore::platform().sessionFunctions().currentSessionHostName(), + sessionMetaData + }; + + m_sessionInfoLock.lockForWrite(); + if (currentSessionInfo != m_sessionInfo) + { + m_sessionInfo = currentSessionInfo; + ++m_sessionInfoVersion; + } + m_sessionInfoLock.unlock(); + }); +} + + + + +void MonitoringMode::updateScreenInfoList() +{ + const auto screens = QGuiApplication::screens(); + + QVariantList screenInfoList; + screenInfoList.reserve(screens.size()); + + int index = 1; + for(const auto* screen : screens) + { + QVariantMap screenInfo; + screenInfo[QStringLiteral("name")] = VeyonCore::screenName(*screen, index); + screenInfo[QStringLiteral("geometry")] = screen->geometry(); + screenInfoList.append(screenInfo); + ++index; + + connect(screen, &QScreen::geometryChanged, this, &MonitoringMode::updateScreenInfoList, Qt::UniqueConnection); + } + + if(screenInfoList != m_screenInfoList) + { + m_screenInfoList = screenInfoList; + ++m_screenInfoListVersion; + } } diff --git a/core/src/MonitoringMode.h b/core/src/MonitoringMode.h new file mode 100644 index 000000000..131d7a31b --- /dev/null +++ b/core/src/MonitoringMode.h @@ -0,0 +1,201 @@ +/* + * MonitoringMode.h - header for the MonitoringMode class + * + * Copyright (c) 2017-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +#include "FeatureProviderInterface.h" +#include "PlatformSessionFunctions.h" + +class VEYON_CORE_EXPORT MonitoringMode : public QObject, FeatureProviderInterface, PluginInterface +{ + Q_OBJECT + Q_INTERFACES(FeatureProviderInterface PluginInterface) +public: + enum class Argument + { + UserLoginName, + UserFullName, + SessionId, + ScreenInfoList, + MinimumFramebufferUpdateInterval, + ApplicationVersion, + SessionUptime, + SessionHostName, + SessionClientAddress, + SessionClientName, + SessionMetaData, + ActiveFeaturesList = 0 // for compatibility after migration from FeatureControl + }; + Q_ENUM(Argument) + + explicit MonitoringMode( QObject* parent = nullptr ); + + const Feature& feature() const + { + return m_monitoringModeFeature; + } + + Plugin::Uid uid() const override + { + return Plugin::Uid{ QStringLiteral("1a6a59b1-c7a1-43cc-bcab-c136a4d91be8") }; + } + + QVersionNumber version() const override + { + return QVersionNumber( 1, 2 ); + } + + QString name() const override + { + return QStringLiteral( "MonitoringMode" ); + } + + QString description() const override + { + return tr( "Builtin monitoring mode" ); + } + + QString vendor() const override + { + return QStringLiteral( "Veyon Community" ); + } + + QString copyright() const override + { + return QStringLiteral( "Tobias Junghans" ); + } + + const FeatureList& featureList() const override + { + return m_features; + } + + void ping(const ComputerControlInterfaceList& computerControlInterfaces); + + void setMinimumFramebufferUpdateInterval(const ComputerControlInterfaceList& computerControlInterfaces, + int interval); + + void queryApplicationVersion(const ComputerControlInterfaceList& computerControlInterfaces); + + void queryActiveFeatures(const ComputerControlInterfaceList& computerControlInterfaces); + + void queryUserInfo(const ComputerControlInterfaceList& computerControlInterfaces); + + void querySessionInfo(const ComputerControlInterfaceList& computerControlInterfaces); + + void queryScreens( const ComputerControlInterfaceList& computerControlInterfaces ); + + bool controlFeature( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) override + { + Q_UNUSED(featureUid) + Q_UNUSED(operation) + Q_UNUSED(arguments) + Q_UNUSED(computerControlInterfaces) + + return false; + } + + bool handleFeatureMessage( ComputerControlInterface::Pointer computerControlInterface, + const FeatureMessage& message ) override; + + bool handleFeatureMessage( VeyonServerInterface& server, + const MessageContext& messageContext, + const FeatureMessage& message ) override; + + void sendAsyncFeatureMessages(VeyonServerInterface& server, const MessageContext& messageContext) override; + +private: + bool sendActiveFeatures(VeyonServerInterface& server, const MessageContext& messageContext); + bool sendUserInformation(VeyonServerInterface& server, const MessageContext& messageContext); + bool sendSessionInfo(VeyonServerInterface& server, const MessageContext& messageContext); + bool sendScreenInfoList(VeyonServerInterface& server, const MessageContext& messageContext); + + static const char* activeFeaturesVersionProperty() + { + return "activeFeaturesListVersion"; + } + + static const char* userInfoVersionProperty() + { + return "userInfoVersion"; + } + + static const char* sessionInfoVersionProperty() + { + return "sessionInfoVersion"; + } + + static const char* screenInfoListVersionProperty() + { + return "screenInfoListVersion"; + } + + void updateActiveFeatures(); + void updateUserInfo(); + void updateSessionInfo(); + void updateScreenInfoList(); + + enum Command + { + Ping, + SetMinimumFramebufferUpdateInterval + }; + + static constexpr int ActiveFeaturesUpdateInterval = 250; + static constexpr int SessionInfoUpdateInterval = 1000; + static constexpr int UserInfoUpdateRetryInterval = 1000; + + const Feature m_monitoringModeFeature; + const Feature m_queryApplicationVersionFeature; + const Feature m_queryActiveFeatures; + const Feature m_queryUserInfoFeature; + const Feature m_querySessionInfoFeature; + const Feature m_queryScreensFeature; + const FeatureList m_features; + + int m_activeFeaturesVersion{0}; + QStringList m_activeFeatures; + QTimer m_activeFeaturesUpdateTimer; + + QReadWriteLock m_userDataLock; + QString m_userLoginName; + QString m_userFullName; + QAtomicInt m_userInfoVersion{0}; + + QVariantList m_screenInfoList; + int m_screenInfoListVersion{0}; + + PlatformSessionFunctions::SessionMetaDataContent m_sessionMetaDataContent; + QString m_sessionMetaDataEnvironmentVariable; + QString m_sessionMetaDataRegistryKey; + + QReadWriteLock m_sessionInfoLock; + PlatformSessionFunctions::SessionInfo m_sessionInfo{}; + QAtomicInt m_sessionInfoVersion = 0; + QTimer m_sessionInfoUpdateTimer; + +}; diff --git a/core/src/NestedNetworkObjectDirectory.cpp b/core/src/NestedNetworkObjectDirectory.cpp new file mode 100644 index 000000000..8559b0411 --- /dev/null +++ b/core/src/NestedNetworkObjectDirectory.cpp @@ -0,0 +1,122 @@ +/* + * NestedNetworkObjectDirectory.cpp - implementation of NestedNetworkObjectDirectory + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "NestedNetworkObjectDirectory.h" + + +NestedNetworkObjectDirectory::NestedNetworkObjectDirectory( QObject* parent ) : + NetworkObjectDirectory( tr("All directories"), parent ) +{ +} + + + +void NestedNetworkObjectDirectory::addSubDirectory( NetworkObjectDirectory* subDirectory ) +{ + m_subDirectories.append( subDirectory ); +} + + + +NetworkObjectList NestedNetworkObjectDirectory::queryObjects( NetworkObject::Type type, + NetworkObject::Property property, const QVariant& value ) +{ + NetworkObjectList objects; + + for( auto* subDirectory : std::as_const(m_subDirectories) ) + { + objects += subDirectory->queryObjects( type, property, value ); + } + + return objects; +} + + + +NetworkObjectList NestedNetworkObjectDirectory::queryParents( const NetworkObject& object ) +{ + if( object.directory() && object.directory() != this ) + { + return object.directory()->queryParents( object ); + } + + return {}; +} + + + +void NestedNetworkObjectDirectory::update() +{ + QStringList subDirectoryNames; + subDirectoryNames.reserve( m_subDirectories.count() ); + + for( auto* subDirectory : std::as_const(m_subDirectories) ) + { + subDirectoryNames.append( subDirectory->name() ); + NetworkObject subDirectoryObject{this, NetworkObject::Type::SubDirectory, subDirectory->name(), {}, + {}, rootObject().uid() }; + addOrUpdateObject( subDirectoryObject, rootObject() ); + + subDirectory->update(); + + replaceObjectsRecursively( subDirectory, subDirectoryObject ); + } + + removeObjects( rootObject(), [subDirectoryNames]( const NetworkObject& object ) { + return object.type() == NetworkObject::Type::SubDirectory && + subDirectoryNames.contains( object.name() ) == false; + } ); + + setObjectPopulated( rootObject() ); +} + + + +void NestedNetworkObjectDirectory::fetchObjects( const NetworkObject& parent ) +{ + if( parent.directory() && parent.directory() != this ) + { + parent.directory()->fetchObjects( parent ); + replaceObjects( parent.directory()->objects(parent), parent ); + } + + setObjectPopulated( parent ); +} + + + +void NestedNetworkObjectDirectory::replaceObjectsRecursively( NetworkObjectDirectory* directory, + const NetworkObject& parent ) +{ + const auto objects = directory->objects( parent.type() == NetworkObject::Type::SubDirectory + ? directory->rootObject() : parent ); + for( const auto& object : objects ) + { + if( object.isPopulated() && object.isContainer() ) + { + replaceObjectsRecursively( directory, object ); + } + } + replaceObjects( objects, parent ); +} diff --git a/core/src/NestedNetworkObjectDirectory.h b/core/src/NestedNetworkObjectDirectory.h new file mode 100644 index 000000000..112cd1cdd --- /dev/null +++ b/core/src/NestedNetworkObjectDirectory.h @@ -0,0 +1,50 @@ +/* + * NestedNetworkObjectDirectory.cpp - header file for NestedNetworkObjectDirectory + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "NetworkObjectDirectory.h" + +class NestedNetworkObjectDirectory : public NetworkObjectDirectory +{ + Q_OBJECT +public: + NestedNetworkObjectDirectory( QObject* parent ); + + void addSubDirectory( NetworkObjectDirectory* subDirectory ); + + NetworkObjectList queryObjects( NetworkObject::Type type, + NetworkObject::Property property, const QVariant& value ) override; + NetworkObjectList queryParents( const NetworkObject& childId ) override; + + void update() override; + void fetchObjects( const NetworkObject& parent ) override; + +private: + void replaceObjectsRecursively( NetworkObjectDirectory* directory, + const NetworkObject& parent ); + + QList m_subDirectories; + +}; diff --git a/core/src/NetworkObject.cpp b/core/src/NetworkObject.cpp index 053c9de1d..5ee584290 100644 --- a/core/src/NetworkObject.cpp +++ b/core/src/NetworkObject.cpp @@ -1,7 +1,7 @@ /* * NetworkObject.cpp - data class representing a network object * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,8 +22,10 @@ * */ +#include #include +#include "EnumHelper.h" #include "NetworkObject.h" #include "HostAddress.h" @@ -32,11 +34,10 @@ const QUuid NetworkObject::networkObjectNamespace( QStringLiteral( "8a6c479e-243 NetworkObject::NetworkObject( const NetworkObject& other ) : + m_directory( other.directory() ), + m_properties( other.properties() ), m_type( other.type() ), m_name( other.name() ), - m_hostAddress( other.hostAddress() ), - m_macAddress( other.macAddress() ), - m_directoryAddress( other.directoryAddress() ), m_uid( other.uid() ), m_parentUid( other.parentUid() ), m_populated( other.isPopulated() ) @@ -45,18 +46,16 @@ NetworkObject::NetworkObject( const NetworkObject& other ) : -NetworkObject::NetworkObject( NetworkObject::Type type, +NetworkObject::NetworkObject( NetworkObjectDirectory* directory, + NetworkObject::Type type, const Name& name, - const QString& hostAddress, - const QString& macAddress, - const QString& directoryAddress, + const QVariantMap& properties, Uid uid, Uid parentUid ) : + m_directory( directory ), + m_properties( properties ), m_type( type ), m_name( name ), - m_hostAddress( hostAddress ), - m_macAddress( macAddress ), - m_directoryAddress( directoryAddress ), m_uid( uid ), m_parentUid( parentUid ), m_populated( false ) @@ -64,19 +63,19 @@ NetworkObject::NetworkObject( NetworkObject::Type type, if( m_uid.isNull() ) { m_uid = calculateUid(); + m_calculatedUid = true; } } -NetworkObject::NetworkObject( const QJsonObject& jsonObject ) : - m_type( static_cast( jsonObject.value( QStringLiteral( "Type" ) ).toInt() ) ), - m_name( jsonObject.value( QStringLiteral( "Name" ) ).toString() ), - m_hostAddress( jsonObject.value( QStringLiteral( "HostAddress" ) ).toString() ), - m_macAddress( jsonObject.value( QStringLiteral( "MacAddress" ) ).toString() ), - m_directoryAddress( jsonObject.value( QStringLiteral( "DirectoryAddress" ) ).toString() ), - m_uid( jsonObject.value( QStringLiteral( "Uid" ) ).toString() ), - m_parentUid( jsonObject.value( QStringLiteral( "ParentUid" ) ).toString() ), +NetworkObject::NetworkObject( const QJsonObject& jsonObject, NetworkObjectDirectory* directory ) : + m_directory( directory ), + m_properties( jsonObject.toVariantMap() ), + m_type( Type( jsonObject.value( propertyKey( Property::Type ) ).toInt() ) ), + m_name( jsonObject.value( propertyKey( Property::Name ) ).toString() ), + m_uid( jsonObject.value( propertyKey( Property::Uid ) ).toString() ), + m_parentUid( jsonObject.value( propertyKey( Property::ParentUid ) ).toString() ), m_populated( false ) { } @@ -85,13 +84,17 @@ NetworkObject::NetworkObject( const QJsonObject& jsonObject ) : NetworkObject& NetworkObject::operator=( const NetworkObject& other ) { + if( this == &other ) + { + return *this; + } + + m_directory = other.directory(); m_type = other.type(); m_name = other.name(); - m_hostAddress = other.hostAddress(); - m_macAddress = other.macAddress(); - m_directoryAddress = other.directoryAddress(); m_uid = other.uid(); m_parentUid = other.parentUid(); + m_properties = other.properties(); return *this; } @@ -107,17 +110,28 @@ bool NetworkObject::operator==( const NetworkObject& other ) const bool NetworkObject::exactMatch( const NetworkObject& other ) const { - return uid() == other.uid() && + return directory() == other.directory() && + uid() == other.uid() && type() == other.type() && name() == other.name() && - hostAddress() == other.hostAddress() && - macAddress() == other.macAddress() && - directoryAddress() == other.directoryAddress() && + properties() == other.properties() && parentUid() == other.parentUid(); } +void NetworkObject::setParentUid( Uid parentUid ) +{ + m_parentUid = parentUid; + + if( m_calculatedUid ) + { + m_uid = calculateUid(); + } +} + + + NetworkObject::ModelId NetworkObject::modelId() const { if( type() == Type::Root ) @@ -125,86 +139,74 @@ NetworkObject::ModelId NetworkObject::modelId() const return 0; } - auto id = - ( static_cast( uid().data1 ) << 0u ) + - ( static_cast( uid().data2 ) << 32u ) + - ( static_cast( uid().data3 ) << 48u ) + - ( static_cast( uid().data4[0] ) << 0u ) + - ( static_cast( uid().data4[1] ) << 8u ) + - ( static_cast( uid().data4[2] ) << 16u ) + - ( static_cast( uid().data4[3] ) << 24u ) + - ( static_cast( uid().data4[4] ) << 32u ) + - ( static_cast( uid().data4[5] ) << 40u ) + - ( static_cast( uid().data4[6] ) << 48u ) + - ( static_cast( uid().data4[7] ) << 56u ); - - return static_cast( id ); + return ModelId( + ( quint64( uid().data1 ) << 0U ) + + ( quint64( uid().data2 ) << 32U ) + + ( quint64( uid().data3 ) << 48U ) + + ( quint64( uid().data4[0] ) << 0U ) + + ( quint64( uid().data4[1] ) << 8U ) + + ( quint64( uid().data4[2] ) << 16U ) + + ( quint64( uid().data4[3] ) << 24U ) + + ( quint64( uid().data4[4] ) << 32U ) + + ( quint64( uid().data4[5] ) << 40U ) + + ( quint64( uid().data4[6] ) << 48U ) + + ( quint64( uid().data4[7] ) << 56U ) + ); } -QJsonObject NetworkObject::toJson() const +QVariant NetworkObject::property( Property property ) const { - QJsonObject json; - json[QStringLiteral("Type")] = static_cast( type() ); - json[QStringLiteral("Uid")] = uid().toString(); - json[QStringLiteral("Name")] = name(); - - if( hostAddress().isEmpty() == false ) + switch( property ) { - json[QStringLiteral("HostAddress")] = hostAddress(); + case Property::Type: return QVariant::fromValue(m_type); + case Property::Name: return m_name; + case Property::Uid: return m_uid; + case Property::ParentUid: return m_parentUid; + default: break; } - if( macAddress().isEmpty() == false ) - { - json[QStringLiteral("MacAddress")] = macAddress(); - } + return m_properties.value( propertyKey(property) ); +} - if( directoryAddress().isEmpty() == false ) - { - json[QStringLiteral("DirectoryAddress")] = directoryAddress(); - } - if( parentUid().isNull() == false ) - { - json[QStringLiteral("ParentUid")] = parentUid().toString(); - } - return json; +QString NetworkObject::propertyKey( Property property ) +{ + return EnumHelper::toString(property); } -QVariant NetworkObject::attributeValue( NetworkObject::Attribute attribute ) const +QJsonObject NetworkObject::toJson() const { - switch( attribute ) + auto json = QJsonObject::fromVariantMap( properties() ); + json[propertyKey(Property::Type)] = static_cast( type() ); + json[propertyKey(Property::Uid)] = uid().toString(); + json[propertyKey(Property::Name)] = name(); + + if( parentUid().isNull() == false ) { - case Attribute::None: return {}; - case Attribute::Type: return QVariant::fromValue( type() ); - case Attribute::Name: return name(); - case Attribute::HostAddress: return hostAddress(); - case Attribute::MacAddress: return macAddress(); - case Attribute::DirectoryAddress: return directoryAddress(); - case Attribute::Uid: return uid(); - case Attribute::ParentUid: return parentUid(); + json[propertyKey(Property::ParentUid)] = parentUid().toString(); } - return {}; + return json; } -bool NetworkObject::isAttributeValueEqual( NetworkObject::Attribute attribute, +bool NetworkObject::isPropertyValueEqual( NetworkObject::Property property, const QVariant& value, Qt::CaseSensitivity cs ) const { - const auto myValue = attributeValue( attribute ); + const auto myValue = NetworkObject::property( property ); const auto myValueType = myValue.userType(); if( myValueType == value.userType() && myValueType == QMetaType::QString ) { // make sure to compare host addresses in the same format - if( attribute == NetworkObject::Attribute::HostAddress ) + if( property == NetworkObject::Property::HostAddress ) { const HostAddress myHostAddress( myValue.toString() ); const auto otherHost = HostAddress( value.toString() ).convert( myHostAddress.type() ); @@ -224,14 +226,21 @@ NetworkObject::Uid NetworkObject::calculateUid() const { // if a directory address is set (e.g. full DN in LDAP) it should be unique and can be // used for hashing - if( directoryAddress().isEmpty() == false ) + const auto directoryAddress = property( Property::DirectoryAddress ).toString(); + if( directoryAddress.isEmpty() == false ) { - return QUuid::createUuidV5( networkObjectNamespace, directoryAddress() ); + return QUuid::createUuidV5( networkObjectNamespace, directoryAddress ); } - else if( type() == Type::Root ) + + if( type() == Type::Root ) { return QUuid::createUuidV5( networkObjectNamespace, QByteArrayLiteral("Root") ); } - return QUuid::createUuidV5( networkObjectNamespace, name() + hostAddress() + macAddress() + parentUid().toString() ); + auto jsonProperties = QJsonObject::fromVariantMap(properties()); + jsonProperties.remove( propertyKey( Property::Uid ) ); + + return QUuid::createUuidV5( networkObjectNamespace, + name() + parentUid().toString() + + QString::fromUtf8( QJsonDocument( jsonProperties ).toJson() ) ); } diff --git a/core/include/NetworkObject.h b/core/src/NetworkObject.h similarity index 65% rename from core/include/NetworkObject.h rename to core/src/NetworkObject.h index e3af13154..a569c5a19 100644 --- a/core/include/NetworkObject.h +++ b/core/src/NetworkObject.h @@ -1,7 +1,7 @@ /* * NetworkObject.h - data class representing a network object * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,12 +24,15 @@ #pragma once +#include #include #include #include "HashList.h" #include "VeyonCore.h" +class NetworkObjectDirectory; + class VEYON_CORE_EXPORT NetworkObject { Q_GADGET @@ -37,6 +40,7 @@ class VEYON_CORE_EXPORT NetworkObject using Uid = QUuid; using Name = QString; using ModelId = quintptr; + using Properties = QVariantMap; enum class Type { @@ -45,32 +49,32 @@ class VEYON_CORE_EXPORT NetworkObject Location, Host, Label, - TypeCount + SubDirectory, + DesktopGroup } ; Q_ENUM(Type) - enum class Attribute + enum class Property { None, Type, Name, + Uid, + ParentUid, HostAddress, MacAddress, - DirectoryAddress, - Uid, - ParentUid + DirectoryAddress }; - Q_ENUM(Attribute) + Q_ENUM(Property) NetworkObject( const NetworkObject& other ); - explicit NetworkObject( Type type = Type::None, + explicit NetworkObject( NetworkObjectDirectory* directory = nullptr, + Type type = Type::None, const Name& name = {}, - const QString& hostAddress = {}, - const QString& macAddress = {}, - const QString& directoryAddress = {}, + const Properties& properties = {}, Uid uid = {}, Uid parentUid = {} ); - explicit NetworkObject( const QJsonObject& jsonObject ); + explicit NetworkObject( const QJsonObject& jsonObject, NetworkObjectDirectory* directory = nullptr ); ~NetworkObject() = default; NetworkObject& operator=( const NetworkObject& other ); @@ -78,6 +82,11 @@ class VEYON_CORE_EXPORT NetworkObject bool operator==( const NetworkObject& other ) const; bool exactMatch( const NetworkObject& other ) const; + NetworkObjectDirectory* directory() const + { + return m_directory; + } + bool isValid() const { return type() != Type::None; @@ -103,10 +112,7 @@ class VEYON_CORE_EXPORT NetworkObject return m_parentUid; } - void setParentUid( const Uid& parentUid ) - { - m_parentUid = parentUid; - } + void setParentUid( Uid parentUid ); ModelId modelId() const; @@ -115,44 +121,46 @@ class VEYON_CORE_EXPORT NetworkObject return m_type; } - const Name& name() const + bool isContainer() const { - return m_name; + return isContainer( type() ); } - const QString& hostAddress() const + static bool isContainer( Type type ) { - return m_hostAddress; + return type == Type::Location || + type == Type::SubDirectory || + type == Type::DesktopGroup; } - const QString& macAddress() const + const Name& name() const { - return m_macAddress; + return m_name; } - const QString& directoryAddress() const + const Properties& properties() const { - return m_directoryAddress; + return m_properties; } - QJsonObject toJson() const; + QVariant property( Property property ) const; + static QString propertyKey( Property property ); - QVariant attributeValue( Attribute attribute ) const; + QJsonObject toJson() const; - bool isAttributeValueEqual( Attribute attribute, const QVariant& value, Qt::CaseSensitivity cs ) const; + bool isPropertyValueEqual( Property property, const QVariant& value, Qt::CaseSensitivity cs ) const; private: Uid calculateUid() const; - static ModelId calculateModelId( Uid uid ); + NetworkObjectDirectory* m_directory; + Properties m_properties; Type m_type; QString m_name; - QString m_hostAddress; - QString m_macAddress; - QString m_directoryAddress; Uid m_uid; Uid m_parentUid; bool m_populated; + bool m_calculatedUid{false}; static const QUuid networkObjectNamespace; @@ -160,5 +168,5 @@ class VEYON_CORE_EXPORT NetworkObject Q_DECLARE_METATYPE(NetworkObject::Type) -using NetworkObjectList = QList; +using NetworkObjectList = QVector; using NetworkObjectUidList = HashList; diff --git a/core/src/NetworkObjectDirectory.cpp b/core/src/NetworkObjectDirectory.cpp index 9af328b3c..be2c43a53 100644 --- a/core/src/NetworkObjectDirectory.cpp +++ b/core/src/NetworkObjectDirectory.cpp @@ -1,7 +1,7 @@ /* * NetworkObjectDirectory.cpp - base class for network object directory implementations * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,21 +24,22 @@ #include -#include "VeyonConfiguration.h" -#include "VeyonCore.h" #include "NetworkObjectDirectory.h" -NetworkObjectDirectory::NetworkObjectDirectory( QObject* parent ) : +NetworkObjectDirectory::NetworkObjectDirectory( const QString& name, QObject* parent ) : QObject( parent ), - m_updateTimer( new QTimer( this ) ), - m_objects(), - m_invalidObject( NetworkObject::Type::None ), - m_rootObject( NetworkObject::Type::Root ), - m_defaultObjectList() + m_name( name ), + m_updateTimer(new QTimer(this)), + m_propagateChangedObjectsTimer(new QTimer(this)) { connect( m_updateTimer, &QTimer::timeout, this, &NetworkObjectDirectory::update ); + connect(m_propagateChangedObjectsTimer, &QTimer::timeout, + this, &NetworkObjectDirectory::propagateChildObjectChanges); + m_propagateChangedObjectsTimer->setInterval(ObjectChangePropagationTimeout); + m_propagateChangedObjectsTimer->setSingleShot(true); + // insert root item m_objects[rootId()] = {}; } @@ -62,8 +63,7 @@ void NetworkObjectDirectory::setUpdateInterval( int interval ) const NetworkObjectList& NetworkObjectDirectory::objects( const NetworkObject& parent ) const { - if( parent.type() == NetworkObject::Type::Root || - parent.type() == NetworkObject::Type::Location ) + if( parent.type() == NetworkObject::Type::Root || parent.isContainer() ) { const auto it = m_objects.constFind( parent.modelId() ); if( it != m_objects.end() ) @@ -87,14 +87,12 @@ const NetworkObject& NetworkObjectDirectory::object( NetworkObject::ModelId pare const auto it = m_objects.constFind( parent ); if( it != m_objects.end() ) { - int index = 0; for( const auto& entry : *it ) { if( entry.modelId() == object ) { return entry; } - ++index; } } @@ -186,7 +184,7 @@ NetworkObject::ModelId NetworkObjectDirectory::rootId() const NetworkObjectList NetworkObjectDirectory::queryObjects( NetworkObject::Type type, - NetworkObject::Attribute attribute, + NetworkObject::Property property, const QVariant& value ) { if( hasObjects() == false ) @@ -203,8 +201,8 @@ NetworkObjectList NetworkObjectDirectory::queryObjects( NetworkObject::Type type for( const auto& object : objectList ) { if( ( type == NetworkObject::Type::None || object.type() == type ) && - ( attribute == NetworkObject::Attribute::None || - object.isAttributeValueEqual( attribute, value, Qt::CaseInsensitive ) ) ) + ( property == NetworkObject::Property::None || + object.isPropertyValueEqual( property, value, Qt::CaseInsensitive ) ) ) { objects.append( object ); } @@ -251,6 +249,7 @@ void NetworkObjectDirectory::fetchObjects( const NetworkObject& object ) if( object.type() == NetworkObject::Type::Root ) { update(); + m_rootObject.setPopulated(); } setObjectPopulated( object ); @@ -284,20 +283,22 @@ void NetworkObjectDirectory::addOrUpdateObject( const NetworkObject& networkObje if( index < 0 ) { - emit objectsAboutToBeInserted( parent, objectList.count(), 1 ); + Q_EMIT objectsAboutToBeInserted(parent.modelId(), objectList.count(), 1); objectList.append( completeNetworkObject ); - if( completeNetworkObject.type() == NetworkObject::Type::Location ) + if( completeNetworkObject.isContainer() ) { m_objects[completeNetworkObject.modelId()] = {}; } - emit objectsInserted(); + Q_EMIT objectsInserted(); + + propagateChildObjectChange(parent.modelId()); } else if( objectList[index].exactMatch( completeNetworkObject ) == false ) { objectList.replace( index, completeNetworkObject ); - emit objectChanged( parent, index ); + propagateChildObjectChange(parent.modelId()); } } @@ -312,20 +313,21 @@ void NetworkObjectDirectory::removeObjects( const NetworkObject& parent, const N auto& objectList = m_objects[parent.modelId()]; // clazy:exclude=detaching-member int index = 0; - QList groupsToRemove; + QList objectsToRemove; for( auto it = objectList.begin(); it != objectList.end(); ) { if( removeObjectFilter( *it ) ) { - if( it->type() == NetworkObject::Type::Location ) + if( it->isContainer() ) { - groupsToRemove.append( it->modelId() ); + objectsToRemove.append( it->modelId() ); } - emit objectsAboutToBeRemoved( parent, index, 1 ); + Q_EMIT objectsAboutToBeRemoved(parent.modelId(), index, 1); it = objectList.erase( it ); - emit objectsRemoved(); + Q_EMIT objectsRemoved(); + propagateChildObjectChange(parent.modelId()); } else { @@ -334,7 +336,7 @@ void NetworkObjectDirectory::removeObjects( const NetworkObject& parent, const N } } - for( const auto& groupId : groupsToRemove ) + for( const auto& groupId : objectsToRemove ) { m_objects.remove( groupId ); } @@ -342,6 +344,18 @@ void NetworkObjectDirectory::removeObjects( const NetworkObject& parent, const N +void NetworkObjectDirectory::replaceObjects( const NetworkObjectList& objects, const NetworkObject& parent ) +{ + for( const auto& object : objects ) + { + addOrUpdateObject( object, parent ); + } + + removeObjects( parent, [&objects]( const NetworkObject& object ) { return objects.contains( object ) == false; } ); +} + + + void NetworkObjectDirectory::setObjectPopulated( const NetworkObject& networkObject ) { const auto objectModelId = networkObject.modelId(); @@ -359,3 +373,42 @@ void NetworkObjectDirectory::setObjectPopulated( const NetworkObject& networkObj } } } + + + +void NetworkObjectDirectory::propagateChildObjectChange(NetworkObject::ModelId objectId, int depth) +{ + if (objectId != 0) + { + if (m_changedObjectIds.contains(objectId)) + { + m_changedObjectIds.removeAll(objectId); + } + + m_changedObjectIds.append(objectId); + + propagateChildObjectChange(parentId(objectId), depth+1); + + if (depth == 0) + { + m_propagateChangedObjectsTimer->stop(); + m_propagateChangedObjectsTimer->start(); + } + } +} + + + +void NetworkObjectDirectory::propagateChildObjectChanges() +{ + for (auto it = m_changedObjectIds.constBegin(), end = m_changedObjectIds.constEnd(); + it != end; ++it) + { + const auto parentObjectId = parentId(*it); + const auto childIndex = index(parentObjectId, *it); + + Q_EMIT objectChanged(parentObjectId, childIndex); + } + + m_changedObjectIds.clear(); +} diff --git a/core/include/NetworkObjectDirectory.h b/core/src/NetworkObjectDirectory.h similarity index 65% rename from core/include/NetworkObjectDirectory.h rename to core/src/NetworkObjectDirectory.h index 28fa822f1..99620e091 100644 --- a/core/include/NetworkObjectDirectory.h +++ b/core/src/NetworkObjectDirectory.h @@ -1,7 +1,7 @@ /* * NetworkObjectDirectory.h - base class for network object directory implementations * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -41,7 +41,12 @@ class VEYON_CORE_EXPORT NetworkObjectDirectory : public QObject MaximumUpdateInterval = 3600 }; - explicit NetworkObjectDirectory( QObject* parent ); + explicit NetworkObjectDirectory( const QString& name, QObject* parent ); + + const QString& name() const + { + return m_name; + } void setUpdateInterval( int interval ); @@ -53,10 +58,15 @@ class VEYON_CORE_EXPORT NetworkObjectDirectory : public QObject NetworkObject::ModelId childId( NetworkObject::ModelId parent, int index ) const; NetworkObject::ModelId parentId( NetworkObject::ModelId child ) const; + const NetworkObject& rootObject() const + { + return m_rootObject; + } + NetworkObject::ModelId rootId() const; virtual NetworkObjectList queryObjects( NetworkObject::Type type, - NetworkObject::Attribute attribute, const QVariant& value ); + NetworkObject::Property property, const QVariant& value ); virtual NetworkObjectList queryParents( const NetworkObject& child ); virtual void update() = 0; @@ -68,20 +78,28 @@ class VEYON_CORE_EXPORT NetworkObjectDirectory : public QObject bool hasObjects() const; void addOrUpdateObject( const NetworkObject& networkObject, const NetworkObject& parent ); void removeObjects( const NetworkObject& parent, const NetworkObjectFilter& removeObjectFilter ); + void replaceObjects( const NetworkObjectList& objects, const NetworkObject& parent ); void setObjectPopulated( const NetworkObject& networkObject ); + void propagateChildObjectChange(NetworkObject::ModelId objectId, int depth = 0); + void propagateChildObjectChanges(); private: - QTimer* m_updateTimer; - QHash m_objects; - NetworkObject m_invalidObject; - NetworkObject m_rootObject; - NetworkObjectList m_defaultObjectList; - -signals: - void objectsAboutToBeInserted( const NetworkObject& parent, int index, int count ); + static constexpr auto ObjectChangePropagationTimeout = 100; + + const QString m_name; + QTimer* m_updateTimer = nullptr; + QTimer* m_propagateChangedObjectsTimer = nullptr; + QHash m_objects{}; + NetworkObject m_invalidObject{this, NetworkObject::Type::None}; + NetworkObject m_rootObject{this, NetworkObject::Type::Root}; + NetworkObjectList m_defaultObjectList{}; + QList m_changedObjectIds; + +Q_SIGNALS: + void objectsAboutToBeInserted(NetworkObject::ModelId parentId, int index, int count); void objectsInserted(); - void objectsAboutToBeRemoved( const NetworkObject& parent, int index, int count ); + void objectsAboutToBeRemoved(NetworkObject::ModelId parentId, int index, int count); void objectsRemoved(); - void objectChanged( const NetworkObject& parent, int index ); + void objectChanged(NetworkObject::ModelId parentId, int index); }; diff --git a/core/src/NetworkObjectDirectoryManager.cpp b/core/src/NetworkObjectDirectoryManager.cpp index ef9431eb0..e38439a1f 100644 --- a/core/src/NetworkObjectDirectoryManager.cpp +++ b/core/src/NetworkObjectDirectoryManager.cpp @@ -1,7 +1,7 @@ /* * NetworkObjectDirectoryManager.cpp - implementation of NetworkObjectDirectoryManager * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,81 +26,133 @@ #include "NetworkObjectDirectoryManager.h" #include "NetworkObjectDirectoryPluginInterface.h" #include "PluginManager.h" +#include "NestedNetworkObjectDirectory.h" NetworkObjectDirectoryManager::NetworkObjectDirectoryManager( QObject* parent ) : - QObject( parent ), - m_directoryPluginInterfaces(), - m_configuredDirectory( nullptr ) + QObject( parent ) { - for( auto pluginObject : qAsConst( VeyonCore::pluginManager().pluginObjects() ) ) + for( auto pluginObject : std::as_const( VeyonCore::pluginManager().pluginObjects() ) ) { auto pluginInterface = qobject_cast( pluginObject ); auto directoryPluginInterface = qobject_cast( pluginObject ); if( pluginInterface && directoryPluginInterface ) { - m_directoryPluginInterfaces[pluginInterface] = directoryPluginInterface; + m_plugins[pluginInterface->uid()] = directoryPluginInterface; } } } -QMap NetworkObjectDirectoryManager::availableDirectories() +NetworkObjectDirectory* NetworkObjectDirectoryManager::configuredDirectory() { - QMap items; + if( m_configuredDirectory == nullptr ) + { + const auto enabledDirectories = VeyonCore::config().enabledNetworkObjectDirectoryPlugins(); + if( enabledDirectories.count() == 1 ) + { + m_configuredDirectory = createDirectory( Plugin::Uid{enabledDirectories.constFirst()}, this ); + } + else if( enabledDirectories.count() > 1 ) + { + const auto nestedDirectory = new NestedNetworkObjectDirectory( this ); + for( const auto& directoryUid : enabledDirectories ) + { + nestedDirectory->addSubDirectory( createDirectory( Plugin::Uid{directoryUid}, this ) ); + } + m_configuredDirectory = nestedDirectory; + } + } - for( auto it = m_directoryPluginInterfaces.constBegin(), end = m_directoryPluginInterfaces.constEnd(); it != end; ++it ) + return m_configuredDirectory; +} + + + +NetworkObjectDirectory* NetworkObjectDirectoryManager::createDirectory( Plugin::Uid uid, QObject* parent ) +{ + const auto plugin = m_plugins.value( uid ); + if( plugin ) { - items[it.key()->uid()] = it.value()->directoryName(); + auto directory = plugin->createNetworkObjectDirectory( parent ); + if( directory ) + { + return directory; + } } - return items; + const auto defaultPlugin = VeyonCore::pluginManager().find( + []( const PluginInterface* plugin ) { + return plugin->flags().testFlag( Plugin::ProvidesDefaultImplementation ); + } ); + + if( defaultPlugin ) + { + const auto defaultDirectory = defaultPlugin->createNetworkObjectDirectory( parent ); + if( defaultDirectory ) + { + return defaultDirectory; + } + } + + vCritical() << "no default plugin available! requested plugin:" << uid; + return nullptr; } -NetworkObjectDirectory* NetworkObjectDirectoryManager::configuredDirectory() +void NetworkObjectDirectoryManager::setEnabled( Plugin::Uid uid, bool enabled ) { - if( m_configuredDirectory == nullptr ) + const auto formattedUid = VeyonCore::formattedUuid(uid); + + auto plugins = VeyonCore::config().enabledNetworkObjectDirectoryPlugins(); + + if( enabled ) { - m_configuredDirectory = createDirectory(); + plugins.append( formattedUid ); + plugins.removeDuplicates(); + } + else + { + plugins.removeAll( formattedUid ); } - return m_configuredDirectory; + VeyonCore::config().setEnabledNetworkObjectDirectoryPlugins( plugins ); } -NetworkObjectDirectory* NetworkObjectDirectoryManager::createDirectory() +bool NetworkObjectDirectoryManager::isEnabled( Plugin::Uid uid ) const { - const auto configuredPluginUuid = VeyonCore::config().networkObjectDirectoryPlugin(); + return VeyonCore::config().enabledNetworkObjectDirectoryPlugins().contains( VeyonCore::formattedUuid(uid) ); +} + - for( auto it = m_directoryPluginInterfaces.constBegin(), end = m_directoryPluginInterfaces.constEnd(); it != end; ++it ) + +void NetworkObjectDirectoryManager::setEnabled( NetworkObjectDirectoryPluginInterface* plugin, bool enabled ) +{ + for( auto it = m_plugins.constBegin(), end = m_plugins.constEnd(); it != end; ++it ) { - if( it.key()->uid() == configuredPluginUuid ) + if( it.value() == plugin ) { - auto directory = it.value()->createNetworkObjectDirectory( this ); - if( directory ) - { - return directory; - } + setEnabled( it.key(), enabled ); } } +} + - for( auto it = m_directoryPluginInterfaces.constBegin(), end = m_directoryPluginInterfaces.constEnd(); it != end; ++it ) + +bool NetworkObjectDirectoryManager::isEnabled( NetworkObjectDirectoryPluginInterface* plugin ) const +{ + for( auto it = m_plugins.constBegin(), end = m_plugins.constEnd(); it != end; ++it ) { - if( it.key()->flags().testFlag( Plugin::ProvidesDefaultImplementation ) ) + if( it.value() == plugin && isEnabled( it.key() ) ) { - auto defaultDirectory = it.value()->createNetworkObjectDirectory( this ); - if( defaultDirectory ) - { - return defaultDirectory; - } + return true; } } - vCritical() << "no default plugin available! configured plugin:" << configuredPluginUuid; - return nullptr; + return false; } diff --git a/core/include/NetworkObjectDirectoryManager.h b/core/src/NetworkObjectDirectoryManager.h similarity index 67% rename from core/include/NetworkObjectDirectoryManager.h rename to core/src/NetworkObjectDirectoryManager.h index 184a9f9a9..d356979e4 100644 --- a/core/include/NetworkObjectDirectoryManager.h +++ b/core/src/NetworkObjectDirectoryManager.h @@ -1,7 +1,7 @@ /* * NetworkObjectDirectoryManager.h - header file for NetworkObjectDirectoryManager * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -35,16 +35,27 @@ class VEYON_CORE_EXPORT NetworkObjectDirectoryManager : public QObject { Q_OBJECT public: + using Plugins = QMap; + explicit NetworkObjectDirectoryManager( QObject* parent = nullptr ); - QMap availableDirectories(); + const Plugins& plugins() const + { + return m_plugins; + } NetworkObjectDirectory* configuredDirectory(); -private: - NetworkObjectDirectory* createDirectory(); + NetworkObjectDirectory* createDirectory( Plugin::Uid uid, QObject* parent ); + + void setEnabled( Plugin::Uid uid, bool enabled ); + bool isEnabled( Plugin::Uid uid ) const; - QMap m_directoryPluginInterfaces; - NetworkObjectDirectory* m_configuredDirectory; + void setEnabled( NetworkObjectDirectoryPluginInterface* plugin, bool enabled ); + bool isEnabled( NetworkObjectDirectoryPluginInterface* plugin ) const; + +private: + Plugins m_plugins{}; + NetworkObjectDirectory* m_configuredDirectory{nullptr}; }; diff --git a/core/include/NetworkObjectDirectoryPluginInterface.h b/core/src/NetworkObjectDirectoryPluginInterface.h similarity index 90% rename from core/include/NetworkObjectDirectoryPluginInterface.h rename to core/src/NetworkObjectDirectoryPluginInterface.h index 33630fc2c..846f8c301 100644 --- a/core/include/NetworkObjectDirectoryPluginInterface.h +++ b/core/src/NetworkObjectDirectoryPluginInterface.h @@ -2,7 +2,7 @@ * NetworkObjectDirectoryPluginInterface.h - plugin interface for network * object directory implementations * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,6 +27,7 @@ #include "PluginInterface.h" +class ConfigurationPage; class NetworkObjectDirectory; // clazy:excludeall=copyable-polymorphic @@ -36,6 +37,7 @@ class NetworkObjectDirectoryPluginInterface public: virtual QString directoryName() const = 0; virtual NetworkObjectDirectory* createNetworkObjectDirectory( QObject* parent ) = 0; + virtual ConfigurationPage* createNetworkObjectDirectoryConfigurationPage() = 0; }; diff --git a/core/include/NetworkObjectModel.h b/core/src/NetworkObjectModel.h similarity index 74% rename from core/include/NetworkObjectModel.h rename to core/src/NetworkObjectModel.h index c78d6222f..cf34d3a7c 100644 --- a/core/include/NetworkObjectModel.h +++ b/core/src/NetworkObjectModel.h @@ -1,7 +1,7 @@ /* * NetworkObjectModel.h - base class for data models providing grouped network objects * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -49,4 +49,19 @@ class VEYON_CORE_EXPORT NetworkObjectModel : public QAbstractItemModel ParentUidRole } ; + QHash roleNames() const + { + auto roles = QAbstractItemModel::roleNames(); + roles[CheckStateRole] = "checkState"; + roles[NameRole] = "name"; + roles[UidRole] = "uid"; + roles[TypeRole] = "type"; + roles[HostAddressRole] = "hostAddress"; + roles[MacAddressRole] = "macAddress"; + roles[DirectoryAddressRole] = "directoryAddress"; + roles[ParentUidRole] = "parentUid"; + return roles; + } + + }; diff --git a/core/include/ObjectManager.h b/core/src/ObjectManager.h similarity index 92% rename from core/include/ObjectManager.h rename to core/src/ObjectManager.h index af41e8119..2389911ac 100644 --- a/core/include/ObjectManager.h +++ b/core/src/ObjectManager.h @@ -1,7 +1,7 @@ /* * ObjectManager.h - header file for ObjectManager * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -49,18 +49,26 @@ class ObjectManager return m_objects; } - const QJsonArray& update( const T& object ) + const QJsonArray& update( const T& object, bool addIfNotFound = false ) { + bool found = false; + for( auto it = m_objects.begin(); it != m_objects.end(); ++it ) { T currentObject( it->toObject() ); if( currentObject.uid() == object.uid() ) { *it = object.toJson(); + found = true; break; } } + if( !found ) + { + add( object ); + } + return m_objects; } diff --git a/core/include/PlatformCoreFunctions.h b/core/src/PlatformCoreFunctions.h similarity index 89% rename from core/include/PlatformCoreFunctions.h rename to core/src/PlatformCoreFunctions.h index b77b33e2c..94ab9c266 100644 --- a/core/include/PlatformCoreFunctions.h +++ b/core/src/PlatformCoreFunctions.h @@ -1,7 +1,7 @@ /* * PlatformCoreFunctions.h - interface class for platform plugins * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,6 +31,8 @@ // clazy:excludeall=copyable-polymorphic +class QScreen; + class PlatformCoreFunctions { public: @@ -44,7 +46,7 @@ class PlatformCoreFunctions virtual void reboot() = 0; virtual void powerDown( bool installUpdates ) = 0; - virtual void raiseWindow( QWidget* widget ) = 0; + virtual void raiseWindow( QWidget* widget, bool stayOnTop ) = 0; virtual void disableScreenSaver() = 0; virtual void restoreScreenSaverSettings() = 0; @@ -63,4 +65,6 @@ class PlatformCoreFunctions virtual QString genericUrlHandler() const = 0; + virtual QString queryDisplayDeviceName(const QScreen& screen) const = 0; + }; diff --git a/core/include/PlatformFilesystemFunctions.h b/core/src/PlatformFilesystemFunctions.h similarity index 89% rename from core/include/PlatformFilesystemFunctions.h rename to core/src/PlatformFilesystemFunctions.h index 04926ae25..7dd38744f 100644 --- a/core/include/PlatformFilesystemFunctions.h +++ b/core/src/PlatformFilesystemFunctions.h @@ -1,7 +1,7 @@ /* * PlatformFilesystemFunctions.h - interface class for platform filesystem * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -41,5 +41,6 @@ class PlatformFilesystemFunctions virtual bool setFileOwnerGroup( const QString& filePath, const QString& ownerGroup ) = 0; virtual bool setFileOwnerGroupPermissions( const QString& filePath, QFile::Permissions permissions ) = 0; + virtual bool openFileSafely( QFile* file, QFile::OpenMode openMode, QFile::Permissions permissions ) = 0; }; diff --git a/core/include/PlatformInputDeviceFunctions.h b/core/src/PlatformInputDeviceFunctions.h similarity index 91% rename from core/include/PlatformInputDeviceFunctions.h rename to core/src/PlatformInputDeviceFunctions.h index aeb6bb252..ef67eb68d 100644 --- a/core/include/PlatformInputDeviceFunctions.h +++ b/core/src/PlatformInputDeviceFunctions.h @@ -1,7 +1,7 @@ /* * PlatformInputDeviceFunctions.h - interface class for platform plugins * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -33,6 +33,8 @@ class KeyboardShortcutTrapper; class PlatformInputDeviceFunctions { public: + virtual ~PlatformInputDeviceFunctions() = default; + virtual void enableInputDevices() = 0; virtual void disableInputDevices() = 0; diff --git a/core/include/PlatformNetworkFunctions.h b/core/src/PlatformNetworkFunctions.h similarity index 81% rename from core/include/PlatformNetworkFunctions.h rename to core/src/PlatformNetworkFunctions.h index f840bebaf..b92f9531f 100644 --- a/core/include/PlatformNetworkFunctions.h +++ b/core/src/PlatformNetworkFunctions.h @@ -1,7 +1,7 @@ /* * PlatformNetworkFunctions.h - interface class for platform plugins * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -33,14 +33,19 @@ class PlatformNetworkFunctions public: using Socket = uintptr_t; - enum { - PingTimeout = 1000, - PingProcessTimeout = PingTimeout*2 + static constexpr int PingTimeout = 1000; + static constexpr int PingProcessTimeout = 5000; + + enum class PingResult { + Unknown, + ReplyReceived, + TimedOut, + NameResolutionFailed }; virtual ~PlatformNetworkFunctions() = default; - virtual bool ping( const QString& hostAddress ) = 0; + virtual PingResult ping(const QString& hostAddress) = 0; virtual bool configureFirewallException( const QString& applicationPath, const QString& description, bool enabled ) = 0; virtual bool configureSocketKeepalive( Socket socket, bool enabled, int idleTime, int interval, int probes ) = 0; diff --git a/core/include/PlatformPluginInterface.h b/core/src/PlatformPluginInterface.h similarity index 89% rename from core/include/PlatformPluginInterface.h rename to core/src/PlatformPluginInterface.h index f9654cc81..9886ca5c0 100644 --- a/core/include/PlatformPluginInterface.h +++ b/core/src/PlatformPluginInterface.h @@ -1,7 +1,7 @@ /* * PlatformPluginInterface.h - interface class for platform plugins * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,6 +31,7 @@ class PlatformFilesystemFunctions; class PlatformInputDeviceFunctions; class PlatformNetworkFunctions; class PlatformServiceFunctions; +class PlatformSessionFunctions; class PlatformUserFunctions; // clazy:excludeall=copyable-polymorphic @@ -38,11 +39,14 @@ class PlatformUserFunctions; class PlatformPluginInterface { public: + virtual ~PlatformPluginInterface() = default; + virtual PlatformCoreFunctions& coreFunctions() = 0; virtual PlatformFilesystemFunctions& filesystemFunctions() = 0; virtual PlatformInputDeviceFunctions& inputDeviceFunctions() = 0; virtual PlatformNetworkFunctions& networkFunctions() = 0; virtual PlatformServiceFunctions& serviceFunctions() = 0; + virtual PlatformSessionFunctions& sessionFunctions() = 0; virtual PlatformUserFunctions& userFunctions() = 0; }; diff --git a/core/src/PlatformPluginManager.cpp b/core/src/PlatformPluginManager.cpp index ebef092ec..22861e820 100644 --- a/core/src/PlatformPluginManager.cpp +++ b/core/src/PlatformPluginManager.cpp @@ -1,7 +1,7 @@ /* * PlatformPluginManager.cpp - implementation of PlatformPluginManager * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -30,7 +30,7 @@ PlatformPluginManager::PlatformPluginManager( PluginManager& pluginManager, QObj QObject( parent ), m_platformPlugin( nullptr ) { - for( auto pluginObject : qAsConst( pluginManager.pluginObjects() ) ) + for( auto pluginObject : std::as_const( pluginManager.pluginObjects() ) ) { auto pluginInterface = qobject_cast( pluginObject ); auto platformPluginInterface = qobject_cast( pluginObject ); diff --git a/core/include/PlatformPluginManager.h b/core/src/PlatformPluginManager.h similarity index 95% rename from core/include/PlatformPluginManager.h rename to core/src/PlatformPluginManager.h index 3f1faf0cb..40cf54f26 100644 --- a/core/include/PlatformPluginManager.h +++ b/core/src/PlatformPluginManager.h @@ -1,7 +1,7 @@ /* * PlatformPluginManager.h - header file for PlatformPluginManager * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/core/src/PlatformServiceCore.cpp b/core/src/PlatformServiceCore.cpp deleted file mode 100644 index 40189d99d..000000000 --- a/core/src/PlatformServiceCore.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * PlatformServiceFunctions.cpp - implementation of PlatformServiceFunctions class - * - * Copyright (c) 2018-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#include "PlatformServiceCore.h" -#include "VeyonConfiguration.h" - - - -PlatformServiceCore::PlatformServiceCore() : - m_multiSession( VeyonCore::config().multiSessionModeEnabled() ) -{ -} - - - -PlatformServiceCore::SessionId PlatformServiceCore::openSession( const QVariant& sessionData ) -{ - for( SessionId i = 0; i <= SessionIdMax; ++i ) - { - if( m_sessions.contains( i ) == false ) - { - m_sessions[i] = sessionData; - return i; - } - } - - return SessionIdInvalid; -} - - - -void PlatformServiceCore::closeSession( SessionId sessionId ) -{ - m_sessions.remove( sessionId ); -} - - - -QVariant PlatformServiceCore::sessionDataFromId( PlatformServiceCore::SessionId sessionId ) const -{ - return m_sessions.value( sessionId ); -} - - - -PlatformServiceCore::SessionId PlatformServiceCore::sessionIdFromData( const QVariant& data ) const -{ - return m_sessions.key( data, static_cast( SessionIdInvalid ) ); -} diff --git a/core/include/PlatformServiceFunctions.h b/core/src/PlatformServiceFunctions.h similarity index 88% rename from core/include/PlatformServiceFunctions.h rename to core/src/PlatformServiceFunctions.h index 43f4596f4..592631a2e 100644 --- a/core/include/PlatformServiceFunctions.h +++ b/core/src/PlatformServiceFunctions.h @@ -1,7 +1,7 @@ /* * PlatformServiceFunctions.h - interface class for platform plugins * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,6 +31,8 @@ class PlatformServiceFunctions { public: + using ServiceEntryPoint = std::function; + enum class StartMode { Disabled, Manual, @@ -49,7 +51,7 @@ class PlatformServiceFunctions StartMode startMode, const QString& displayName ) = 0; virtual bool uninstall( const QString& name ) = 0; virtual bool setStartMode( const QString& name, StartMode startMode ) = 0; - virtual bool runAsService( const QString& name, const std::function& serviceMain ) = 0; + virtual bool runAsService( const QString& name, const ServiceEntryPoint& serviceEntryPoint ) = 0; virtual void manageServerInstances() = 0; }; diff --git a/core/src/PlatformSessionFunctions.h b/core/src/PlatformSessionFunctions.h new file mode 100644 index 000000000..35ac17e8d --- /dev/null +++ b/core/src/PlatformSessionFunctions.h @@ -0,0 +1,89 @@ +/* + * PlatformSessionsFunctions.h - interface class for platform session functions + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "VeyonCore.h" + +// clazy:excludeall=copyable-polymorphic + +class VEYON_CORE_EXPORT PlatformSessionFunctions +{ + Q_GADGET +public: + using SessionId = int; + using SessionUptime = int; + using EnvironmentVariables = QMap; + + struct SessionInfo { + SessionId id = InvalidSessionId; + SessionUptime uptime = 0; + QString clientAddress; + QString clientName; + QString hostName; + QString metaData; + bool operator==(const SessionInfo& other) const + { + return other.id == id && + other.uptime == uptime && + other.clientAddress == clientAddress && + other.clientName == clientName && + other.hostName == hostName && + other.metaData == metaData; + } + bool operator!=(const SessionInfo& other) const + { + return !(other == *this); + } + }; + + static constexpr SessionId DefaultSessionId = 0; + static constexpr SessionId InvalidSessionId = -1; + static constexpr SessionUptime InvalidSessionUptime = -1; + + enum class SessionMetaDataContent + { + None, + EnvironmentVariable, + RegistryKey, + }; + Q_ENUM(SessionMetaDataContent) + + virtual ~PlatformSessionFunctions() = default; + + virtual SessionId currentSessionId() = 0; + + virtual PlatformSessionFunctions::SessionUptime currentSessionUptime() const = 0; + virtual QString currentSessionClientAddress() const = 0; + virtual QString currentSessionClientName() const = 0; + virtual QString currentSessionHostName() const = 0; + + virtual QString currentSessionType() const = 0; + virtual bool currentSessionHasUser() const = 0; + virtual bool currentSessionIsRemote() const = 0; + + virtual EnvironmentVariables currentSessionEnvironmentVariables() const = 0; + virtual QVariant querySettingsValueInCurrentSession(const QString& key) const = 0; + +}; diff --git a/core/include/PlatformUserFunctions.h b/core/src/PlatformUserFunctions.h similarity index 73% rename from core/include/PlatformUserFunctions.h rename to core/src/PlatformUserFunctions.h index f7898fc5e..63e2f5a6b 100644 --- a/core/include/PlatformUserFunctions.h +++ b/core/src/PlatformUserFunctions.h @@ -1,7 +1,7 @@ /* * PlatformUserFunctions.h - interface class for platform plugins * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,6 +24,7 @@ #pragma once +#include "CryptoCore.h" #include "PlatformPluginInterface.h" // clazy:excludeall=copyable-polymorphic @@ -31,6 +32,8 @@ class PlatformUserFunctions { public: + using Password = CryptoCore::PlaintextPassword; + virtual ~PlatformUserFunctions() = default; virtual QString fullName( const QString& username ) = 0; @@ -38,12 +41,14 @@ class PlatformUserFunctions virtual QStringList userGroups( bool queryDomainGroups ) = 0; virtual QStringList groupsOfUser( const QString& username, bool queryDomainGroups ) = 0; - virtual bool isAnyUserLoggedOn() = 0; + virtual bool isAnyUserLoggedInLocally() = 0; + virtual bool isAnyUserLoggedInRemotely() = 0; virtual QString currentUser() = 0; - virtual void logon( const QString& username, const QString& password ) = 0; + virtual bool prepareLogon( const QString& username, const Password& password ) = 0; + virtual bool performLogon( const QString& username, const Password& password ) = 0; virtual void logoff() = 0; - virtual bool authenticate( const QString& username, const QString& password ) = 0; + virtual bool authenticate( const QString& username, const Password& password ) = 0; }; diff --git a/core/include/Plugin.h b/core/src/Plugin.h similarity index 91% rename from core/include/Plugin.h rename to core/src/Plugin.h index e8227b834..bb797ac2b 100644 --- a/core/include/Plugin.h +++ b/core/src/Plugin.h @@ -1,7 +1,7 @@ /* * Plugin.h - generic abstraction of a plugin * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -46,4 +46,4 @@ class Plugin }; -using PluginUidList = QList; +using PluginUidList = QVector; diff --git a/core/include/PluginInterface.h b/core/src/PluginInterface.h similarity index 94% rename from core/include/PluginInterface.h rename to core/src/PluginInterface.h index 07d6534e2..5de8060c1 100644 --- a/core/include/PluginInterface.h +++ b/core/src/PluginInterface.h @@ -1,7 +1,7 @@ /* * PluginInterface.h - interface class for plugins * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,6 +25,7 @@ #pragma once #include +#include #include "VeyonCore.h" #include "Plugin.h" diff --git a/core/src/PluginManager.cpp b/core/src/PluginManager.cpp index 12c4b51c3..94e0463a0 100644 --- a/core/src/PluginManager.cpp +++ b/core/src/PluginManager.cpp @@ -1,7 +1,7 @@ /* * PluginManager.cpp - implementation of the PluginManager class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,6 +22,8 @@ * */ +#include + #include #include #include @@ -33,8 +35,6 @@ PluginManager::PluginManager( QObject* parent ) : QObject( parent ), - m_pluginInterfaces(), - m_pluginObjects(), m_noDebugMessages( qEnvironmentVariableIsSet( Logger::logLevelEnvironmentVariable() ) ) { initPluginSearchPath(); @@ -42,6 +42,21 @@ PluginManager::PluginManager( QObject* parent ) : +PluginManager::~PluginManager() +{ + vDebug(); + + for( auto pluginLoader : std::as_const(m_pluginLoaders) ) + { + pluginLoader->unload(); + } + + m_pluginInterfaces.clear(); + m_pluginObjects.clear(); +} + + + void PluginManager::loadPlatformPlugins() { loadPlugins( QStringLiteral("*-platform") + VeyonCore::sharedLibrarySuffix() ); @@ -52,8 +67,6 @@ void PluginManager::loadPlatformPlugins() void PluginManager::loadPlugins() { loadPlugins( QStringLiteral("*") + VeyonCore::sharedLibrarySuffix() ); - - emit pluginsLoaded(); } @@ -62,7 +75,7 @@ void PluginManager::upgradePlugins() { auto versions = VeyonCore::config().pluginVersions(); - for( auto pluginInterface : qAsConst( m_pluginInterfaces ) ) + for( auto pluginInterface : std::as_const( m_pluginInterfaces ) ) { const auto pluginUid = pluginInterface->uid().toString(); auto previousPluginVersion = QVersionNumber::fromString( versions.value( pluginUid ).toString() ); @@ -105,33 +118,16 @@ PluginUidList PluginManager::pluginUids() const pluginUidList.reserve( m_pluginInterfaces.size() ); - for( auto pluginInterface : qAsConst( m_pluginInterfaces ) ) + for( auto pluginInterface : std::as_const( m_pluginInterfaces ) ) { pluginUidList += pluginInterface->uid(); } - std::sort( pluginUidList.begin(), pluginUidList.end() ); - return pluginUidList; } -PluginInterface* PluginManager::pluginInterface( Plugin::Uid pluginUid ) -{ - for( auto pluginInterface : qAsConst( m_pluginInterfaces ) ) - { - if( pluginInterface->uid() == pluginUid ) - { - return pluginInterface; - } - } - - return nullptr; -} - - - QString PluginManager::pluginName( Plugin::Uid pluginUid ) const { for( auto pluginInterface : m_pluginInterfaces ) @@ -157,16 +153,33 @@ void PluginManager::initPluginSearchPath() { vDebug() << "Adding plugin search path" << pluginSearchPath; } - QDir::addSearchPath( QStringLiteral( "plugins" ), pluginSearchPath ); + m_pluginSearchPaths.append(pluginSearchPath); QCoreApplication::addLibraryPath( pluginSearchPath ); } +#if defined(VEYON_WITH_TESTS) + for (const auto& baseDir : {QStringLiteral(CMAKE_BINARY_DIR "/plugins/platform"), + QStringLiteral(CMAKE_BINARY_DIR "/plugins/vncserver"), + QStringLiteral(CMAKE_BINARY_DIR "/plugins/")}) + { + const auto pluginDirs = QDir(baseDir).entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot); + for (const auto& pluginDir : pluginDirs) + { + m_pluginSearchPaths.append(pluginDir.absoluteFilePath()); + } + } +#endif } void PluginManager::loadPlugins( const QString& nameFilter ) { - const auto plugins = QDir( QStringLiteral( "plugins:" ) ).entryInfoList( { nameFilter } ); + QFileInfoList plugins; + for (const auto& pluginSearchPath : std::as_const(m_pluginSearchPaths)) + { + plugins.append(QDir(pluginSearchPath).entryInfoList({nameFilter})); + } + for( const auto& fileInfo : plugins ) { const auto fileName = fileInfo.fileName(); @@ -178,7 +191,8 @@ void PluginManager::loadPlugins( const QString& nameFilter ) continue; } - auto pluginObject = QPluginLoader( fileInfo.filePath() ).instance(); + auto pluginLoader = new QPluginLoader( fileInfo.filePath(), this ); + auto pluginObject = pluginLoader->instance(); auto pluginInterface = qobject_cast( pluginObject ); if( pluginObject && pluginInterface && @@ -190,6 +204,11 @@ void PluginManager::loadPlugins( const QString& nameFilter ) } m_pluginInterfaces += pluginInterface; // clazy:exclude=reserve-candidates m_pluginObjects += pluginObject; // clazy:exclude=reserve-candidates + m_pluginLoaders += pluginLoader; // clazy:exclude=reserve-candidates + } + else + { + delete pluginLoader; } } } diff --git a/core/include/PluginManager.h b/core/src/PluginManager.h similarity index 66% rename from core/include/PluginManager.h rename to core/src/PluginManager.h index 71ad2faf9..40907abb4 100644 --- a/core/include/PluginManager.h +++ b/core/src/PluginManager.h @@ -1,7 +1,7 @@ /* * PluginManager.h - header for the PluginManager class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -29,11 +29,14 @@ #include "Plugin.h" #include "PluginInterface.h" +class QPluginLoader; + class VEYON_CORE_EXPORT PluginManager : public QObject { Q_OBJECT public: explicit PluginManager( QObject* parent = nullptr ); + ~PluginManager(); void loadPlatformPlugins(); void loadPlugins(); @@ -44,12 +47,7 @@ class VEYON_CORE_EXPORT PluginManager : public QObject return m_pluginInterfaces; } - PluginInterfaceList& pluginInterfaces() - { - return m_pluginInterfaces; - } - - QObjectList& pluginObjects() + const QObjectList& pluginObjects() const { return m_pluginObjects; } @@ -58,7 +56,20 @@ class VEYON_CORE_EXPORT PluginManager : public QObject PluginUidList pluginUids() const; - PluginInterface* pluginInterface( Plugin::Uid pluginUid ); + template + InterfaceType* find( const std::function& filter = []() { return true; } ) + { + for( auto object : std::as_const(m_pluginObjects) ) + { + auto pluginInterface = qobject_cast( object ); + if( pluginInterface && filter( qobject_cast( object ) ) ) + { + return pluginInterface; + } + } + + return nullptr; + } QString pluginName( Plugin::Uid pluginUid ) const; @@ -66,11 +77,10 @@ class VEYON_CORE_EXPORT PluginManager : public QObject void initPluginSearchPath(); void loadPlugins( const QString& nameFilter ); - PluginInterfaceList m_pluginInterfaces; - QObjectList m_pluginObjects; - bool m_noDebugMessages; - -signals: - void pluginsLoaded(); + QStringList m_pluginSearchPaths; + PluginInterfaceList m_pluginInterfaces{}; + QObjectList m_pluginObjects{}; + QList m_pluginLoaders{}; + bool m_noDebugMessages{false}; }; diff --git a/core/include/Cotire.h b/core/src/PrecompiledHeader.h similarity index 79% rename from core/include/Cotire.h rename to core/src/PrecompiledHeader.h index c0ccb3af9..232142a82 100644 --- a/core/include/Cotire.h +++ b/core/src/PrecompiledHeader.h @@ -1,11 +1,17 @@ #pragma once +#ifdef __MINGW32__ +#include +#endif + +#ifdef __cplusplus #ifdef QT_WIDGETS_LIB #include #include #include #include #endif +#include #include #include #include @@ -19,3 +25,4 @@ #ifdef QT_NETWORK_LIB #include #endif +#endif diff --git a/core/src/ProcessHelper.cpp b/core/src/ProcessHelper.cpp index b189de77e..ac1dd8d91 100644 --- a/core/src/ProcessHelper.cpp +++ b/core/src/ProcessHelper.cpp @@ -1,7 +1,7 @@ /* * ProcessHelper.cpp - implementation of ProcessHelper * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,14 +22,10 @@ * */ -#include -#include - #include "ProcessHelper.h" -ProcessHelper::ProcessHelper( const QString& program, const QStringList& arguments ) : - m_process() +ProcessHelper::ProcessHelper( const QString& program, const QStringList& arguments ) { m_process.start( program, arguments ); } @@ -59,23 +55,3 @@ QByteArray ProcessHelper::runAndReadAll() return QByteArray(); } - - - -bool ProcessHelper::waitForProcess( QProcess* process, int timeout, int sleepInterval ) -{ - QElapsedTimer timeoutTimer; - timeoutTimer.start(); - - while( process->state() != QProcess::NotRunning ) - { - if( timeoutTimer.elapsed() >= timeout ) - { - return false; - } - - QThread::msleep( static_cast( sleepInterval ) ); - } - - return true; -} diff --git a/core/include/ProcessHelper.h b/core/src/ProcessHelper.h similarity index 86% rename from core/include/ProcessHelper.h rename to core/src/ProcessHelper.h index 1dce69097..2553b57d5 100644 --- a/core/include/ProcessHelper.h +++ b/core/src/ProcessHelper.h @@ -1,7 +1,7 @@ /* * ProcessHelper.h - header file for ProcessHelper * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -35,9 +35,7 @@ class VEYON_CORE_EXPORT ProcessHelper { int run(); QByteArray runAndReadAll(); - static bool waitForProcess( QProcess* process, int timeout, int sleepInterval ); - private: - QProcess m_process; + QProcess m_process{}; }; diff --git a/core/src/ProgressWidget.cpp b/core/src/ProgressWidget.cpp deleted file mode 100644 index 4f0c384e0..000000000 --- a/core/src/ProgressWidget.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * ProgressWidget.cpp - widget with animated progress indicator - * - * Copyright (c) 2006-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This software 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 software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "ProgressWidget.h" - -#include -#include - -// clazy:excludeall=detaching-member - -ProgressWidget::ProgressWidget( const QString& text, const QString& animationPixmapBase, int frames, QWidget* parent ) : - QWidget( parent ), - m_text( text ), - m_frames( frames ), - m_curFrame( 0 ) -{ - m_pixmaps.reserve( m_frames ); - - for( int i = 0; i < m_frames; ++i ) - { - m_pixmaps.push_back( QPixmap( animationPixmapBase.arg( QString::number( i+1 ) ) ) ); - } - - QFont f = font(); - f.setPointSize( 12 ); - setFont( f ); - - setFixedSize( 30 + m_pixmaps[0].width() + fontMetrics().width( m_text ), - m_pixmaps[0].height() * 5 / 4 ); - - auto t = new QTimer( this ); - connect( t, &QTimer::timeout, this, &ProgressWidget::nextFrame ); - t->start( 150 ); -} - - - -void ProgressWidget::nextFrame() -{ - m_curFrame = ( m_curFrame+1 ) % m_frames; - - update(); -} - - - -void ProgressWidget::paintEvent( QPaintEvent* event ) -{ - Q_UNUSED(event); - - QPainter p( this ); - p.setRenderHint( QPainter::Antialiasing ); - p.setPen( QColor( 0x55, 0x55, 0x55 ) ); - - p.setBrush( Qt::white ); - p.drawRect( 0, 0, width() - 1, height() - 1 ); - p.drawPixmap( 6, ( height() - m_pixmaps[m_curFrame].height() ) / 2 - 1, m_pixmaps[m_curFrame] ); - - p.drawText( 14 + m_pixmaps[m_curFrame].width(), 25, m_text ); -} diff --git a/core/src/QSGImageTexture.cpp b/core/src/QSGImageTexture.cpp new file mode 100644 index 000000000..fb5861552 --- /dev/null +++ b/core/src/QSGImageTexture.cpp @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "QSGImageTexture.h" +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#include +#include + +#ifndef GL_BGRA +#define GL_BGRA 0x80E1 +#endif + +QSGImageTexture::QSGImageTexture() + : m_texture_id(0) + , m_has_alpha(false) + , m_dirty_texture(false) + , m_dirty_bind_options(false) + , m_owns_texture(true) +{ +} + + +QSGImageTexture::~QSGImageTexture() +{ + if (m_texture_id && m_owns_texture && QOpenGLContext::currentContext()) + QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &m_texture_id); +} + +void QSGImageTexture::setImage(const QImage &image) +{ + m_image = image; + m_texture_size = image.size(); + m_has_alpha = image.hasAlphaChannel(); + m_dirty_texture = true; + m_dirty_bind_options = true; + } + +int QSGImageTexture::textureId() const +{ + if (m_dirty_texture) { + if (m_image.isNull()) { + // The actual texture and id will be updated/deleted in a later bind() + // or ~QSGImageTexture so just keep it minimal here. + return 0; + } + if (m_texture_id == 0){ + // Generate a texture id for use later and return it. + QOpenGLContext::currentContext()->functions()->glGenTextures(1, &const_cast(this)->m_texture_id); + return int(m_texture_id); + } + } + return int(m_texture_id); +} + +void QSGImageTexture::bind() +{ + QOpenGLContext *context = QOpenGLContext::currentContext(); + QOpenGLFunctions *funcs = context->functions(); + if (!m_dirty_texture) { + funcs->glBindTexture(GL_TEXTURE_2D, m_texture_id); + updateBindOptions(m_dirty_bind_options); + m_dirty_bind_options = false; + return; + } + + m_dirty_texture = false; + + if (m_image.isNull()) { + if (m_texture_id && m_owns_texture) { + funcs->glDeleteTextures(1, &m_texture_id); + } + m_texture_id = 0; + m_texture_size = QSize(); + m_has_alpha = false; + + return; + } + + if (m_texture_id == 0) + funcs->glGenTextures(1, &m_texture_id); + funcs->glBindTexture(GL_TEXTURE_2D, m_texture_id); + + QImage tmp = m_image/*(m_image.format() == QImage::Format_RGB32 || m_image.format() == QImage::Format_ARGB32_Premultiplied) + ? m_image + : m_image.convertToFormat(QImage::Format_ARGB32_Premultiplied);*/; + + int max; + funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max); + if (tmp.width() > max || tmp.height() > max) { + tmp = tmp.scaled(qMin(max, tmp.width()), qMin(max, tmp.height()), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + m_texture_size = tmp.size(); + } + + if (tmp.width() * 4 != tmp.bytesPerLine()) + tmp = tmp.copy(); + + updateBindOptions(m_dirty_bind_options); + + GLenum externalFormat = GL_RGBA; + GLenum internalFormat = GL_RGBA; + +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) + QString *deviceName = + static_cast(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("AndroidDeviceName")); + static bool wrongfullyReportsBgra8888Support = deviceName != 0 + && (deviceName->compare(QLatin1String("samsung SM-T211"), Qt::CaseInsensitive) == 0 + || deviceName->compare(QLatin1String("samsung SM-T210"), Qt::CaseInsensitive) == 0 + || deviceName->compare(QLatin1String("samsung SM-T215"), Qt::CaseInsensitive) == 0); +#else + static bool wrongfullyReportsBgra8888Support = false; +#endif + + if (context->hasExtension(QByteArrayLiteral("GL_EXT_bgra"))) { + externalFormat = GL_BGRA; +#ifdef QT_OPENGL_ES + internalFormat = GL_BGRA; +#else + if (context->isOpenGLES()) + internalFormat = GL_BGRA; +#endif // QT_OPENGL_ES + } else if (!wrongfullyReportsBgra8888Support + && (context->hasExtension(QByteArrayLiteral("GL_EXT_texture_format_BGRA8888")) + || context->hasExtension(QByteArrayLiteral("GL_IMG_texture_format_BGRA8888")))) { + externalFormat = GL_BGRA; + internalFormat = GL_BGRA; +#if defined(Q_OS_DARWIN) && !defined(Q_OS_OSX) + } else if (context->hasExtension(QByteArrayLiteral("GL_APPLE_texture_format_BGRA8888"))) { + externalFormat = GL_BGRA; + internalFormat = GL_RGBA; +#endif + } else { + tmp = std::move(tmp).convertToFormat(QImage::Format_RGBA8888_Premultiplied); + } + + funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_texture_size.width(), m_texture_size.height(), 0, externalFormat, GL_UNSIGNED_BYTE, tmp.constBits()); + + m_dirty_bind_options = false; + m_image = {}; +} +#endif diff --git a/core/src/QSGImageTexture.h b/core/src/QSGImageTexture.h new file mode 100644 index 000000000..04ed2b708 --- /dev/null +++ b/core/src/QSGImageTexture.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma once + +#include +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#include + +class QSGImageTexture : public QSGTexture +{ + Q_OBJECT +public: + QSGImageTexture(); + ~QSGImageTexture() override; + + void setOwnsTexture(bool owns) { m_owns_texture = owns; } + bool ownsTexture() const { return m_owns_texture; } + + int textureId() const override; + void setTextureSize(QSize size) { m_texture_size = size; } + QSize textureSize() const override { return m_texture_size; } + + void setHasAlphaChannel(bool alpha) { m_has_alpha = alpha; } + bool hasAlphaChannel() const override { return m_has_alpha; } + + bool hasMipmaps() const override { return false; } + + void setImage(const QImage &image); + const QImage &image() { return m_image; } + + void bind() override; + + static QSGImageTexture *fromImage(const QImage &image) { + QSGImageTexture *t = new QSGImageTexture(); + t->setImage(image); + return t; + } + +protected: + QImage m_image; + + uint m_texture_id; + QSize m_texture_size; + + uint m_has_alpha : 1; + uint m_dirty_texture : 1; + uint m_dirty_bind_options : 1; + uint m_owns_texture : 1; +}; + +#endif diff --git a/core/src/QmlCore.cpp b/core/src/QmlCore.cpp new file mode 100644 index 000000000..69f8a6c28 --- /dev/null +++ b/core/src/QmlCore.cpp @@ -0,0 +1,84 @@ +/* + * QmlCore.cpp - QML-related core functions + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include +#include +#include + +#include "QmlCore.h" + +QmlCore::QmlCore( QObject* parent ) : + QObject( parent ) +{ +} + + + +QObject* QmlCore::createObjectFromFile( const QString& qmlFile, QObject* parent, QObject* context ) +{ + QQmlComponent component( qmlEngine(parent), qmlFile ); + + auto object = component.beginCreate( qmlContext(parent) ); + object->setParent( parent ); + + qmlEngine(object)->rootContext()->setContextProperty( QStringLiteral("qmlCore"), this ); + + if( context ) + { + qmlEngine(object)->rootContext()->setContextProperty( QStringLiteral("context"), context ); + } + + component.completeCreate(); + + return object; +} + + + +QQuickItem* QmlCore::createItemFromFile( const QString& qmlFile, QQuickItem* parent, QObject* context ) +{ + QQmlComponent component( qmlEngine(parent), qmlFile ); + + auto item = qobject_cast( component.beginCreate( qmlContext(parent) ) ); + item->setParent( parent ); + item->setParentItem( parent ); + + qmlEngine(item)->rootContext()->setContextProperty( QStringLiteral("qmlCore"), this ); + + if( context ) + { + qmlEngine(item)->rootContext()->setContextProperty( QStringLiteral("context"), context ); + } + + component.completeCreate(); + + return item; +} + + + +void QmlCore::deleteLater( QObject* object ) +{ + object->deleteLater(); +} diff --git a/core/include/ProgressWidget.h b/core/src/QmlCore.h similarity index 60% rename from core/include/ProgressWidget.h rename to core/src/QmlCore.h index 6d676ec0b..fceb752fc 100644 --- a/core/include/ProgressWidget.h +++ b/core/src/QmlCore.h @@ -1,7 +1,7 @@ /* - * ProgressWidget.h - widget with animated progress indicator + * QmlCore.h - QML-related core functions * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,27 +23,19 @@ #pragma once -#include -#include -#include +#include "VeyonCore.h" -class ProgressWidget : public QWidget +class QQuickItem; + +class VEYON_CORE_EXPORT QmlCore : public QObject { Q_OBJECT public: - ProgressWidget( const QString& text, const QString& animationPixmapBase, int frames, QWidget* parent = nullptr ); - ~ProgressWidget() override = default; - -protected: - void paintEvent( QPaintEvent* event ) override; - -private: - void nextFrame(); + explicit QmlCore( QObject* parent = nullptr ); - QString m_text; - int m_frames; - int m_curFrame; + QObject* createObjectFromFile( const QString& qmlFile, QObject* parent, QObject* context = nullptr ); + QQuickItem* createItemFromFile( const QString& qmlFile, QQuickItem* parent, QObject* context = nullptr ); - QVector m_pixmaps; + Q_INVOKABLE void deleteLater( QObject* object ); } ; diff --git a/core/src/QtCompat.cpp b/core/src/QtCompat.cpp deleted file mode 100644 index 9af067496..000000000 --- a/core/src/QtCompat.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * QtCompat.cpp - functions and templates for compatibility with older Qt versions - * - * Copyright (c) 2018-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#include "QtCompat.h" - -#if QT_VERSION < 0x050600 - -// taken from qtbase/src/corelib/tools/qversionnumber.cpp - -QVector QVersionNumber::segments() const -{ - if (m_segments.isUsingPointer()) - return *m_segments.pointer_segments; - - QVector result; - result.resize(segmentCount()); - for (int i = 0; i < segmentCount(); ++i) - result[i] = segmentAt(i); - return result; -} - -QVersionNumber QVersionNumber::normalized() const -{ - int i; - for (i = m_segments.size(); i; --i) - if (m_segments.at(i - 1) != 0) - break; - - QVersionNumber result(*this); - result.m_segments.resize(i); - return result; -} - -bool QVersionNumber::isPrefixOf(const QVersionNumber &other) const Q_DECL_NOTHROW -{ - if (segmentCount() > other.segmentCount()) - return false; - for (int i = 0; i < segmentCount(); ++i) { - if (segmentAt(i) != other.segmentAt(i)) - return false; - } - return true; -} - -int QVersionNumber::compare(const QVersionNumber &v1, const QVersionNumber &v2) Q_DECL_NOTHROW -{ - int commonlen; - - if (Q_LIKELY(!v1.m_segments.isUsingPointer() && !v2.m_segments.isUsingPointer())) { - // we can't use memcmp because it interprets the data as unsigned bytes - const qint8 *ptr1 = v1.m_segments.inline_segments + InlineSegmentStartIdx; - const qint8 *ptr2 = v2.m_segments.inline_segments + InlineSegmentStartIdx; - commonlen = qMin(v1.m_segments.size(), - v2.m_segments.size()); - for (int i = 0; i < commonlen; ++i) - if (int x = ptr1[i] - ptr2[i]) - return x; - } else { - commonlen = qMin(v1.segmentCount(), v2.segmentCount()); - for (int i = 0; i < commonlen; ++i) { - if (v1.segmentAt(i) != v2.segmentAt(i)) - return v1.segmentAt(i) - v2.segmentAt(i); - } - } - - // ran out of segments in v1 and/or v2 and need to check the first trailing - // segment to finish the compare - if (v1.segmentCount() > commonlen) { - // v1 is longer - if (v1.segmentAt(commonlen) != 0) - return v1.segmentAt(commonlen); - else - return 1; - } else if (v2.segmentCount() > commonlen) { - // v2 is longer - if (v2.segmentAt(commonlen) != 0) - return -v2.segmentAt(commonlen); - else - return -1; - } - - // the two version numbers are the same - return 0; -} - -QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1, - const QVersionNumber &v2) -{ - int commonlen = qMin(v1.segmentCount(), v2.segmentCount()); - int i; - for (i = 0; i < commonlen; ++i) { - if (v1.segmentAt(i) != v2.segmentAt(i)) - break; - } - - if (i == 0) - return QVersionNumber(); - - // try to use the one with inline segments, if there's one - QVersionNumber result(!v1.m_segments.isUsingPointer() ? v1 : v2); - result.m_segments.resize(i); - return result; -} - -QString QVersionNumber::toString() const -{ - QString version; - version.reserve(qMax(segmentCount() * 2 - 1, 0)); - bool first = true; - for (int i = 0; i < segmentCount(); ++i) { - if (!first) - version += QLatin1Char('.'); - version += QString::number(segmentAt(i)); - first = false; - } - return version; -} - -QVersionNumber QVersionNumber::fromString(const QString &string, int *suffixIndex) -{ - QVector seg; - - const QByteArray cString(string.toLatin1()); - - const char *start = cString.constData(); - const char *end = start; - const char *lastGoodEnd = start; - const char *endOfString = cString.constData() + cString.size(); - - do { - const qulonglong value = strtoull(start, (char **) &end, 10); - if (value > qulonglong(std::numeric_limits::max())) - break; - seg.append(int(value)); - start = end + 1; - lastGoodEnd = end; - } while (start < endOfString && (end < endOfString && *end == '.')); - - if (suffixIndex) - *suffixIndex = int(lastGoodEnd - cString.constData()); - - return QVersionNumber(qMove(seg)); -} - -#endif diff --git a/core/src/QtCompat.h b/core/src/QtCompat.h new file mode 100644 index 000000000..e56cb8494 --- /dev/null +++ b/core/src/QtCompat.h @@ -0,0 +1,37 @@ +/* + * QtCompat.h - functions and templates for compatibility with older Qt versions + * + * Copyright (c) 2017-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0) +#error Qt < 5.7 not supported +#endif + +#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) +#define Q_DISABLE_MOVE(Class) \ + Class(const Class &&) Q_DECL_EQ_DELETE;\ + Class &operator=(const Class &&) Q_DECL_EQ_DELETE; +#endif diff --git a/core/src/RfbClientCallback.h b/core/src/RfbClientCallback.h new file mode 100644 index 000000000..4680295cc --- /dev/null +++ b/core/src/RfbClientCallback.h @@ -0,0 +1,94 @@ +/* + * RfbClientCallback.h - wrapper for using member functions as libvncclient callbacks + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "VncConnection.h" + +using rfbClient = struct _rfbClient; + +struct RfbClientCallback +{ + template + using ReturnType = typename std::result_of::type; + + template + using ReturnTypeIsVoid = std::is_void>; + + template + using EnableIfHasReturnType = typename std::enable_if::value, + ReturnType>::type; + + template + using EnableIfHasNoReturnType = typename std::enable_if>::value, + void>::type; + + template + static VncConnection* vncConnectionFromClient( rfbClient* client, Args... ) + { + return static_cast( VncConnection::clientData( client, VncConnection::VncConnectionTag ) ); + } + + template + static EnableIfHasReturnType wrap(Args...args) + { + if( const auto connection = vncConnectionFromClient(std::forward(args)...); connection ) + { + return (connection->*fn)( std::forward(args)...); + } + + return DefaultReturnValue; + } + + template + static EnableIfHasReturnType wrap(rfbClient* client, Args...args) + { + if( const auto connection = vncConnectionFromClient(client); connection ) + { + return (connection->*fn)( std::forward(args)...); + } + + return DefaultReturnValue; + } + + template + static EnableIfHasNoReturnType wrap(Args...args) + { + if( const auto connection = vncConnectionFromClient(std::forward(args)...); connection ) + { + (connection->*fn)( std::forward(args)...); + } + } + + template + static EnableIfHasNoReturnType wrap(rfbClient* client, Args...args) + { + if( const auto connection = vncConnectionFromClient(client); connection ) + { + (connection->*fn)( std::forward(args)...); + } + } + +}; + diff --git a/core/src/Screenshot.cpp b/core/src/Screenshot.cpp index dcb0c5954..bfd9be4db 100644 --- a/core/src/Screenshot.cpp +++ b/core/src/Screenshot.cpp @@ -1,7 +1,7 @@ /* * Screenshot.cpp - class representing a screenshot * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -35,11 +36,11 @@ #include "Computer.h" #include "ComputerControlInterface.h" #include "Filesystem.h" +#include "PlatformFilesystemFunctions.h" Screenshot::Screenshot( const QString &fileName, QObject* parent ) : QObject( parent ), - m_fileName( fileName ), - m_image() + m_fileName( fileName ) { if( !m_fileName.isEmpty() && QFileInfo( m_fileName ).isFile() ) { @@ -57,7 +58,7 @@ void Screenshot::take( const ComputerControlInterface::Pointer& computerControlI userLogin = tr( "unknown" ); } - const auto dir = VeyonCore::filesystem().expandPath( VeyonCore::config().screenshotDirectory() ); + const auto dir = VeyonCore::filesystem().screenshotDirectoryPath(); if( VeyonCore::filesystem().ensurePathExists( dir ) == false ) { @@ -72,7 +73,23 @@ void Screenshot::take( const ComputerControlInterface::Pointer& computerControlI } // construct filename - m_fileName = dir + QDir::separator() + constructFileName( userLogin, computerControlInterface->computer().hostAddress() ); + m_fileName = dir + QDir::separator() + constructFileName(userLogin, computerControlInterface->computer().hostName()); + + QFile outputFile( m_fileName ); + if( VeyonCore::platform().filesystemFunctions().openFileSafely( + &outputFile, + QFile::WriteOnly | QFile::Truncate, + QFile::ReadOwner | QFile::WriteOwner ) == false ) + { + const auto msg = tr( "Could not open screenshot file %1 for writing." ).arg( m_fileName ); + vCritical() << msg.toUtf8().constData(); + if( qobject_cast( QCoreApplication::instance() ) ) + { + QMessageBox::critical( nullptr, tr( "Screenshot" ), msg ); + } + + return; + } // construct caption auto user = userLogin; @@ -81,20 +98,20 @@ void Screenshot::take( const ComputerControlInterface::Pointer& computerControlI user = QStringLiteral( "%1 (%2)" ).arg( userLogin, computerControlInterface->userFullName() ); } - const auto host = computerControlInterface->computer().hostAddress(); + const auto host = computerControlInterface->computer().hostName(); const auto date = QDate::currentDate().toString( Qt::ISODate ); const auto time = QTime::currentTime().toString( Qt::ISODate ); const auto caption = QStringLiteral( "%1@%2 %3 %4" ).arg( user, host, date, time ); - m_image = computerControlInterface->screen(); + m_image = computerControlInterface->framebuffer(); QPixmap icon( QStringLiteral( ":/core/icon16.png" ) ); QPainter painter( &m_image ); auto font = painter.font(); - font.setPointSize( 14 ); + font.setPointSize( ScreenshotLabelFontPointSize ); font.setBold( true ); painter.setFont( font ); @@ -128,16 +145,17 @@ void Screenshot::take( const ComputerControlInterface::Pointer& computerControlI m_image.setText( metaDataKey( MetaData::Date ), date ); m_image.setText( metaDataKey( MetaData::Time ), time ); - m_image.save( m_fileName, "PNG", 50 ); + m_image.save( &outputFile, "PNG", 50 ); + + Q_EMIT VeyonCore::filesystem().screenshotDirectoryModified(); } -QString Screenshot::constructFileName( const QString& user, const QString& hostAddress, - const QDate& date, const QTime& time ) +QString Screenshot::constructFileName( const QString& user, const QString& hostAddress, QDate date, QTime time ) { - const auto userSimplified = VeyonCore::stripDomain( user ).toLower().remove( - QRegularExpression( QStringLiteral("[^a-z0-9.]") ) ); + static const QRegularExpression nonAllowedCharsRX{QStringLiteral("[^a-z0-9.]")}; + const auto userSimplified = VeyonCore::stripDomain(user).toLower().remove(nonAllowedCharsRX); return QStringLiteral( "%1_%2_%3_%4.png" ).arg( userSimplified, hostAddress, @@ -164,8 +182,8 @@ QString Screenshot::host() const QString Screenshot::date() const { - return QDate::fromString( property( metaDataKey( MetaData::Date ), 2 ), - Qt::ISODate ).toString( Qt::LocalDate ); + return QLocale::system().toString( QDate::fromString( property( metaDataKey( MetaData::Date ), 2 ), Qt::ISODate ), + QLocale::ShortFormat ); } diff --git a/core/include/Screenshot.h b/core/src/Screenshot.h similarity index 88% rename from core/include/Screenshot.h rename to core/src/Screenshot.h index 100c2413b..fdea5b310 100644 --- a/core/include/Screenshot.h +++ b/core/src/Screenshot.h @@ -1,7 +1,7 @@ /* * Screenshot.h - class representing a screenshot * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -69,8 +69,8 @@ class VEYON_CORE_EXPORT Screenshot : public QObject } static QString constructFileName( const QString& user, const QString& hostAddress, - const QDate& date = QDate::currentDate(), - const QTime& time = QTime::currentTime() ); + QDate date = QDate::currentDate(), + QTime time = QTime::currentTime() ); QString user() const; QString host() const; @@ -80,11 +80,13 @@ class VEYON_CORE_EXPORT Screenshot : public QObject static QString metaDataKey( MetaData key ); private: + static constexpr auto ScreenshotLabelFontPointSize = 14; + QString property( const QString& key, int section ) const; QString fileNameSection( int n ) const; - QString m_fileName; - QImage m_image; + QString m_fileName{}; + QImage m_image{}; } ; diff --git a/core/src/ServiceControl.cpp b/core/src/ServiceControl.cpp index fa12dbe2e..d82723e5f 100644 --- a/core/src/ServiceControl.cpp +++ b/core/src/ServiceControl.cpp @@ -1,7 +1,7 @@ /* * ServiceControl.cpp - class for controlling veyon service * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,12 +23,11 @@ */ #include -#include -#include -#include +#include #include "PlatformServiceFunctions.h" #include "ServiceControl.h" +#include "Toast.h" ServiceControl::ServiceControl( const QString& name, @@ -61,8 +60,8 @@ bool ServiceControl::isServiceRunning() void ServiceControl::startService() { - serviceControl( tr( "Starting service %1" ).arg( m_name ), - QtConcurrent::run( [=]() { VeyonCore::platform().serviceFunctions().start( m_name ); } ) ); + serviceControl(tr("Starting %1").arg(m_displayName), + QtConcurrent::run([=]() { VeyonCore::platform().serviceFunctions().start(m_name); })); } @@ -70,71 +69,78 @@ void ServiceControl::startService() void ServiceControl::stopService() { - serviceControl( tr( "Stopping service %1" ).arg( m_name ), - QtConcurrent::run( [=]() { VeyonCore::platform().serviceFunctions().stop( m_name ); } ) ); + serviceControl(tr("Stopping %1").arg(m_displayName), + QtConcurrent::run([=]() { VeyonCore::platform().serviceFunctions().stop(m_name); })); +} + + + +void ServiceControl::restartService() +{ + serviceControl(tr("Restarting %1").arg(m_displayName), + QtConcurrent::run([=]() { + VeyonCore::platform().serviceFunctions().stop(m_name); + VeyonCore::platform().serviceFunctions().start(m_name); + })); } void ServiceControl::registerService() { - serviceControl( tr( "Registering service %1" ).arg( m_name ), - QtConcurrent::run( [=]() { VeyonCore::platform().serviceFunctions().install( m_name, - m_filePath, - PlatformServiceFunctions::StartMode::Auto, - m_displayName ); } ) ); + serviceControl(tr("Registering %1").arg(m_displayName), + QtConcurrent::run([=]() { VeyonCore::platform().serviceFunctions().install(m_name, + m_filePath, + PlatformServiceFunctions::StartMode::Auto, + m_displayName ); })); } void ServiceControl::unregisterService() { - serviceControl( tr( "Unregistering service %1" ).arg( m_name ), - QtConcurrent::run( [=]() { VeyonCore::platform().serviceFunctions().uninstall( m_name ); } ) ); + serviceControl(tr("Unregistering %1").arg(m_displayName), + QtConcurrent::run([=]() { VeyonCore::platform().serviceFunctions().uninstall( m_name ); })); } -void ServiceControl::serviceControl( const QString& title, const Operation& operation ) +void ServiceControl::serviceControl(const QString& title, const Operation& operation) { - if( m_parent ) + if (m_parent) { - graphicalFeedback( title, operation ); + graphicalFeedback(title, operation); } else { - textFeedback( title, operation ); + textFeedback(title, operation); } } -void ServiceControl::graphicalFeedback( const QString& title, const Operation& operation ) +void ServiceControl::graphicalFeedback(const QString& title, const Operation& operation) { - QProgressDialog pd( title, {}, 0, 0, m_parent ); - pd.setWindowTitle( tr( "Service control" ) ); - - auto b = new QProgressBar( &pd ); - b->setMaximum( 100 ); - b->setTextVisible( false ); - pd.setBar( b ); - b->show(); - pd.setWindowModality( Qt::WindowModal ); - pd.show(); - - int j = 0; - while( operation.isFinished() == false ) + auto toast = new Toast(m_parent); + toast->setTitle(tr("Service control")); + toast->setText(title); + toast->applyPreset(Toast::Preset::Information); + toast->setDuration(0); + toast->show(); + + while (operation.isRunning()) { QCoreApplication::processEvents(); - b->setValue( ++j % 100 ); - QThread::msleep( 10 ); + QThread::msleep(10); } + + toast->hide(); } -void ServiceControl::textFeedback( const QString& title, const Operation& operation ) +void ServiceControl::textFeedback(const QString& title, const Operation& operation) { printf( "%s", qUtf8Printable( title ) ); diff --git a/core/include/ServiceControl.h b/core/src/ServiceControl.h similarity index 83% rename from core/include/ServiceControl.h rename to core/src/ServiceControl.h index 2e7a62b4b..bbd9f31e7 100644 --- a/core/include/ServiceControl.h +++ b/core/src/ServiceControl.h @@ -1,7 +1,7 @@ /* * ServiceControl.h - header for the ServiceControl class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -49,13 +49,13 @@ class VEYON_CORE_EXPORT ServiceControl : public QObject void startService(); void stopService(); - + void restartService(); private: using Operation = QFuture; - void serviceControl( const QString& title, const Operation& operation ); - void graphicalFeedback( const QString &title, const Operation& operation ); - void textFeedback( const QString &title, const Operation& operation ); + void serviceControl(const QString& title, const Operation& operation); + void graphicalFeedback(const QString &title, const Operation& operation); + void textFeedback(const QString &title, const Operation& operation); const QString m_name; const QString m_filePath; diff --git a/core/src/SimpleFeatureProvider.cpp b/core/src/SimpleFeatureProvider.cpp deleted file mode 100644 index fccd6d0ea..000000000 --- a/core/src/SimpleFeatureProvider.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * SimpleFeatureProvider.cpp - implementation of SimpleFeatureProvider class - * - * Copyright (c) 2018-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#include "SimpleFeatureProvider.h" - - -bool SimpleFeatureProvider::startFeature( VeyonMasterInterface& master, - const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) -{ - Q_UNUSED(master) - Q_UNUSED(feature) - Q_UNUSED(computerControlInterfaces) - - return false; -} - - - -bool SimpleFeatureProvider::stopFeature( VeyonMasterInterface& master, - const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) -{ - Q_UNUSED(master) - Q_UNUSED(feature) - Q_UNUSED(computerControlInterfaces) - - return false; -} - - - -bool SimpleFeatureProvider::handleFeatureMessage( VeyonMasterInterface& master, - const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) -{ - Q_UNUSED(master) - Q_UNUSED(message) - Q_UNUSED(computerControlInterface) - - return false; -} - - - -bool SimpleFeatureProvider::handleFeatureMessage( VeyonServerInterface& server, - const MessageContext& messageContext, - const FeatureMessage& message ) -{ - Q_UNUSED(server) - Q_UNUSED(messageContext) - Q_UNUSED(message) - - return false; -} - - - -bool SimpleFeatureProvider::handleFeatureMessage( VeyonWorkerInterface& worker, const FeatureMessage& message ) -{ - Q_UNUSED(worker) - Q_UNUSED(message) - - return false; -} diff --git a/core/include/SocketDevice.h b/core/src/SocketDevice.h similarity index 96% rename from core/include/SocketDevice.h rename to core/src/SocketDevice.h index 00f990f25..253b903a6 100644 --- a/core/include/SocketDevice.h +++ b/core/src/SocketDevice.h @@ -1,7 +1,7 @@ /* * SocketDevice.h - SocketDevice abstraction * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/core/src/SystemTrayIcon.cpp b/core/src/SystemTrayIcon.cpp index b6043e747..cbaa6c601 100644 --- a/core/src/SystemTrayIcon.cpp +++ b/core/src/SystemTrayIcon.cpp @@ -1,7 +1,7 @@ /* * SystemTrayIcon.cpp - implementation of SystemTrayIcon class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,7 +22,10 @@ * */ +#include #include +#include +#include #include #include "SystemTrayIcon.h" @@ -35,67 +38,77 @@ SystemTrayIcon::SystemTrayIcon( QObject* parent ) : QObject( parent ), m_systemTrayIconFeature( Feature( QLatin1String( staticMetaObject.className() ), - Feature::Session | Feature::Service | Feature::Worker | Feature::Builtin, + Feature::Flag::Session | Feature::Flag::Service | Feature::Flag::Worker | Feature::Flag::Builtin, Feature::Uid( "8e997d84-ebb9-430f-8f72-d45d9821963d" ), Feature::Uid(), tr( "System tray icon"), {}, {} ) ), - m_features( { m_systemTrayIconFeature } ), - m_systemTrayIcon( nullptr ) + m_hidden(VeyonCore::config().isTrayIconHidden()) { } void SystemTrayIcon::setToolTip( const QString& toolTipText, - FeatureWorkerManager& featureWorkerManager ) + FeatureWorkerManager& featureWorkerManager ) { - if( featureWorkerManager.isWorkerRunning( m_systemTrayIconFeature ) == false ) + if (m_hidden == false) { - featureWorkerManager.startWorker( m_systemTrayIconFeature, FeatureWorkerManager::UnmanagedSessionProcess ); + FeatureMessage featureMessage(m_systemTrayIconFeature.uid(), SetToolTipCommand); + featureMessage.addArgument(Argument::ToolTipText, toolTipText); + + featureWorkerManager.sendMessageToUnmanagedSessionWorker(featureMessage); } +} + - FeatureMessage featureMessage( m_systemTrayIconFeature.uid(), SetToolTipCommand ); - featureMessage.addArgument( ToolTipTextArgument, toolTipText ); - featureWorkerManager.sendMessage( featureMessage ); +void SystemTrayIcon::showMessage( const QString& messageTitle, + const QString& messageText, + FeatureWorkerManager& featureWorkerManager ) +{ + FeatureMessage featureMessage( m_systemTrayIconFeature.uid(), ShowMessageCommand ); + featureMessage.addArgument( Argument::MessageTitle, messageTitle ); + featureMessage.addArgument( Argument::MessageText, messageText ); + + featureWorkerManager.sendMessageToUnmanagedSessionWorker( featureMessage ); } -void SystemTrayIcon::showMessage( const QString& messageTitle, - const QString& messageText, - FeatureWorkerManager& featureWorkerManager ) +void SystemTrayIcon::showMessage(const ComputerControlInterfaceList &computerControlInterfaces, + const QString& messageTitle, const QString& messageText) { - if( featureWorkerManager.isWorkerRunning( m_systemTrayIconFeature ) == false ) - { - featureWorkerManager.startWorker( m_systemTrayIconFeature, FeatureWorkerManager::UnmanagedSessionProcess ); - } + sendFeatureMessage(FeatureMessage{m_systemTrayIconFeature.uid(), ShowMessageCommand} + .addArgument(Argument::MessageTitle, messageTitle) + .addArgument(Argument::MessageText, messageText), + computerControlInterfaces); +} - FeatureMessage featureMessage( m_systemTrayIconFeature.uid(), ShowMessageCommand ); - featureMessage.addArgument( MessageTitleArgument, messageTitle ); - featureMessage.addArgument( MessageTextArgument, messageText ); - featureWorkerManager.sendMessage( featureMessage ); + +void SystemTrayIcon::setOverlay(const ComputerControlInterfaceList& computerControlInterfaces, + const QString &iconUrl) +{ + if (m_hidden == false) + { + sendFeatureMessage(FeatureMessage{m_systemTrayIconFeature.uid(), SetOverlayIcon} + .addArgument(Argument::OverlayIconUrl, iconUrl), + computerControlInterfaces); + } } bool SystemTrayIcon::handleFeatureMessage( VeyonServerInterface& server, - const MessageContext& messageContext, - const FeatureMessage& message ) + const MessageContext& messageContext, + const FeatureMessage& message ) { Q_UNUSED(messageContext) if( m_systemTrayIconFeature.uid() == message.featureUid() ) { // forward message to worker - if( server.featureWorkerManager().isWorkerRunning( m_systemTrayIconFeature ) == false ) - { - server.featureWorkerManager().startWorker( m_systemTrayIconFeature, FeatureWorkerManager::UnmanagedSessionProcess ); - } - - server.featureWorkerManager().sendMessage( message ); - + server.featureWorkerManager().sendMessageToUnmanagedSessionWorker( message ); return true; } @@ -113,16 +126,12 @@ bool SystemTrayIcon::handleFeatureMessage( VeyonWorkerInterface& worker, const F return false; } - if( m_systemTrayIcon == nullptr && VeyonCore::config().isTrayIconHidden() == false ) + if (m_systemTrayIcon == nullptr && m_hidden == false) { m_systemTrayIcon = new QSystemTrayIcon( this ); - QIcon icon( QStringLiteral( ":/core/icon16.png" ) ); - icon.addFile( QStringLiteral( ":/core/icon22.png" ) ); - icon.addFile( QStringLiteral( ":/core/icon32.png" ) ); - icon.addFile( QStringLiteral( ":/core/icon64.png" ) ); + updateIcon(); - m_systemTrayIcon->setIcon( icon ); m_systemTrayIcon->show(); } @@ -131,27 +140,61 @@ bool SystemTrayIcon::handleFeatureMessage( VeyonWorkerInterface& worker, const F case SetToolTipCommand: if( m_systemTrayIcon ) { - m_systemTrayIcon->setToolTip( message.argument( ToolTipTextArgument ).toString() ); + m_systemTrayIcon->setToolTip( message.argument( Argument::ToolTipText ).toString() ); } return true; case ShowMessageCommand: if( m_systemTrayIcon ) { - m_systemTrayIcon->showMessage( message.argument( MessageTitleArgument ).toString(), - message.argument( MessageTextArgument ).toString() ); + m_systemTrayIcon->showMessage( message.argument( Argument::MessageTitle ).toString(), + message.argument( Argument::MessageText ).toString() ); } else { QMessageBox::information( nullptr, - message.argument( MessageTitleArgument ).toString(), - message.argument( MessageTextArgument ).toString() ); + message.argument( Argument::MessageTitle ).toString(), + message.argument( Argument::MessageText ).toString() ); + QCoreApplication::instance()->quit(); } return true; + case SetOverlayIcon: + updateIcon(message.argument(Argument::OverlayIconUrl).toString()); + return true; + default: break; } return false; } + + + +void SystemTrayIcon::updateIcon(const QString& overlayIconUrl) +{ + if (m_systemTrayIcon) + { + QImage overlayIcon; + if (overlayIconUrl.isEmpty() == false) + { + overlayIcon.load(overlayIconUrl); + } + + QIcon icon; + + for(auto size : {16, 22, 32, 64}) + { + QPixmap pixmap(QStringLiteral(":/core/icon%1.png").arg(size)); + if (overlayIcon.isNull() == false) + { + QPainter painter(&pixmap); + painter.drawImage(0, 0, overlayIcon.scaled(pixmap.size())); + } + icon.addPixmap(pixmap); + } + + m_systemTrayIcon->setIcon(icon); + } +} diff --git a/core/include/SystemTrayIcon.h b/core/src/SystemTrayIcon.h similarity index 64% rename from core/include/SystemTrayIcon.h rename to core/src/SystemTrayIcon.h index 3bb81157d..add6027de 100644 --- a/core/include/SystemTrayIcon.h +++ b/core/src/SystemTrayIcon.h @@ -1,7 +1,7 @@ /* * SystemTrayIcon.h - declaration of SystemTrayIcon class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,16 +24,25 @@ #pragma once -#include "SimpleFeatureProvider.h" +#include "FeatureProviderInterface.h" class QSystemTrayIcon; class FeatureWorkerManager; -class VEYON_CORE_EXPORT SystemTrayIcon : public QObject, public SimpleFeatureProvider, public PluginInterface +class VEYON_CORE_EXPORT SystemTrayIcon : public QObject, public FeatureProviderInterface, public PluginInterface { Q_OBJECT Q_INTERFACES(FeatureProviderInterface PluginInterface) public: + enum class Argument + { + ToolTipText, + MessageTitle, + MessageText, + OverlayIconUrl + }; + Q_ENUM(Argument) + explicit SystemTrayIcon( QObject* parent = nullptr ); ~SystemTrayIcon() override = default; @@ -44,9 +53,18 @@ class VEYON_CORE_EXPORT SystemTrayIcon : public QObject, public SimpleFeaturePro const QString& messageText, FeatureWorkerManager& featureWorkerManager ); + void showMessage(const ComputerControlInterfaceList& computerControlInterfaces, + const QString& messageTitle, const QString& messageText); + + void setOverlay(const ComputerControlInterfaceList& computerControlInterfaces, const QString& iconUrl); + void clearOverlay(const ComputerControlInterfaceList& computerControlInterfaces) + { + setOverlay(computerControlInterfaces, {}); + } + Plugin::Uid uid() const override { - return QStringLiteral("3cb1adb1-6b4d-4934-a641-db767df83eea"); + return Plugin::Uid { QStringLiteral("3cb1adb1-6b4d-4934-a641-db767df83eea") }; } QVersionNumber version() const override @@ -79,6 +97,17 @@ class VEYON_CORE_EXPORT SystemTrayIcon : public QObject, public SimpleFeaturePro return m_features; } + bool controlFeature( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) override + { + Q_UNUSED(featureUid) + Q_UNUSED(operation) + Q_UNUSED(arguments) + Q_UNUSED(computerControlInterfaces) + + return false; + } + bool handleFeatureMessage( VeyonServerInterface& server, const MessageContext& messageContext, const FeatureMessage& message ) override; @@ -86,22 +115,19 @@ class VEYON_CORE_EXPORT SystemTrayIcon : public QObject, public SimpleFeaturePro bool handleFeatureMessage( VeyonWorkerInterface& worker, const FeatureMessage& message ) override; private: + void updateIcon(const QString& overlayIconUrl = {}); + enum Commands { SetToolTipCommand, - ShowMessageCommand - }; - - enum Arguments - { - ToolTipTextArgument, - MessageTitleArgument, - MessageTextArgument + ShowMessageCommand, + SetOverlayIcon }; const Feature m_systemTrayIconFeature; - const FeatureList m_features; + const FeatureList m_features = {m_systemTrayIconFeature}; - QSystemTrayIcon* m_systemTrayIcon; + QSystemTrayIcon* m_systemTrayIcon = nullptr; + bool m_hidden = false; }; diff --git a/core/src/Toast.cpp b/core/src/Toast.cpp new file mode 100644 index 000000000..08144790b --- /dev/null +++ b/core/src/Toast.cpp @@ -0,0 +1,2015 @@ +/* + * File based on https://github.com/niklashenning/qt-toast/blob/master/src/Toast.cpp + * + * MIT License + + * Copyright (c) 2024 Niklas Henning + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Toast.h" +#include "VeyonCore.h" + +// Static +int Toast::s_maximumOnScreen = 3; +int Toast::s_spacing = 10; +int Toast::s_offsetX = 20; +int Toast::s_offsetY = 45; +bool Toast::s_alwaysOnMainScreen = false; +QScreen* Toast::s_fixedScreen = nullptr; +Toast::Position Toast::s_position = Toast::Position::BottomRight; +std::deque Toast::s_currentlyShown = std::deque(); +std::deque Toast::s_queue = std::deque(); + +// Static constants +const int Toast::sc_updatePositionDuration = 200; +const int Toast::sc_durationBarUpdateInterval = 5; +const int Toast::sc_dropShadowSize = 5; +const QColor Toast::sc_successAccentColor = QColor("#3E9141"); +const QColor Toast::sc_warningAccentColor = QColor("#E8B849"); +const QColor Toast::sc_errorAccentColor = QColor("#BA2626"); +const QColor Toast::sc_informationAccentColor = QColor("#007FFF"); +const QColor Toast::sc_defaultAccentColor = QColor("#5C5C5C"); +const QColor Toast::sc_defaultBackgroundColor = QColor("#E7F4F9"); +const QColor Toast::sc_defaultTitleColor = QColor("#000000"); +const QColor Toast::sc_defaultTextColor = QColor("#5C5C5C"); +const QColor Toast::sc_defaultIconSeparatorColor = QColor("#D9D9D9"); +const QColor Toast::sc_defaultCloseButtonIconColor = QColor("#000000"); +const QColor Toast::sc_defaultBackgroundColorDark = QColor("#292929"); +const QColor Toast::sc_defaultTitleColorDark = QColor("#FFFFFF"); +const QColor Toast::sc_defaultTextColorDark = QColor("#D0D0D0"); +const QColor Toast::sc_defaultIconSeparatorColorDark = QColor("#585858"); +const QColor Toast::sc_defaultCloseButtonIconColorDark = QColor("#C9C9C9"); + + +Toast::Toast(QWidget* parent) + : QDialog(parent) +{ + // Init attributes + m_duration = 5000; + m_showDurationBar = true; + m_icon = getIconFromEnum(Icon::Information); + m_showIcon = false; + m_iconSize = QSize(18, 18); + m_showIconSeparator = true; + m_iconSeparatorWidth = 2; + m_closeButtonIcon = getIconFromEnum(Icon::Close); + m_showCloseButton = true; + m_closeButtonIconSize = QSize(10, 10); + m_closeButtonSize = QSize(24, 24); + m_closeButtonAlignment = ButtonAlignment::Top; + m_fadeInDuration = 250; + m_fadeOutDuration = 250; + m_resetDurationOnHover = true; + m_stayOnTop = true; + m_borderRadius = 0; + m_backgroundColor = sc_defaultBackgroundColor; + m_titleColor = sc_defaultTitleColor; + m_textColor = sc_defaultTextColor; + m_iconColor = sc_defaultAccentColor; + m_iconSeparatorColor = sc_defaultIconSeparatorColor; + m_closeButtonIconColor = sc_defaultCloseButtonIconColor; + m_durationBarColor = sc_defaultAccentColor; + m_titleFont = font(); + m_titleFont.setBold(true); + m_textFont = font(); + m_margins = QMargins(20, 18, 10, 18); + m_iconMargins = QMargins(0, 0, 15, 0); + m_iconSectionMargins = QMargins(0, 0, 15, 0); + m_textSectionMargins = QMargins(0, 0, 15, 0); + m_closeButtonMargins = QMargins(0, -8, 0, -8); + m_textSectionSpacing = 8; + + m_elapsedTime = 0; + m_fadingOut = false; + m_used = false; + m_parent = parent; + + // Window settings + setAttribute(Qt::WidgetAttribute::WA_TranslucentBackground); + setFocusPolicy(Qt::FocusPolicy::NoFocus); + + // Notification widget (QLabel because QWidget has weird behaviour with stylesheets) + m_notification = new QLabel(this); + + // Drop shadow (has to be drawn manually since only one graphics effect can be applied) + m_dropShadowLayer1 = new QWidget(this); + m_dropShadowLayer2 = new QWidget(this); + m_dropShadowLayer3 = new QWidget(this); + m_dropShadowLayer4 = new QWidget(this); + m_dropShadowLayer5 = new QWidget(this); + m_dropShadowLayer1->setObjectName(QStringLiteral("toast-drop-shadow-layer-1")); + m_dropShadowLayer2->setObjectName(QStringLiteral("toast-drop-shadow-layer-2")); + m_dropShadowLayer3->setObjectName(QStringLiteral("toast-drop-shadow-layer-3")); + m_dropShadowLayer4->setObjectName(QStringLiteral("toast-drop-shadow-layer-4")); + m_dropShadowLayer5->setObjectName(QStringLiteral("toast-drop-shadow-layer-5")); + + // Opacity effect for fading animations + m_opacityEffect = new QGraphicsOpacityEffect(); + m_opacityEffect->setOpacity(1); + setGraphicsEffect(m_opacityEffect); + + // Close button + m_closeButton = new QPushButton(m_notification); + m_closeButton->setCursor(Qt::CursorShape::PointingHandCursor); + m_closeButton->setObjectName(QStringLiteral("toast-close-button")); + connect(m_closeButton, &QPushButton::clicked, this, &Toast::hide); + + // Text and title labels + m_titleLabel = new QLabel(m_notification); + m_textLabel = new QLabel(m_notification); + + // Icon (QPushButton instead of QLabel to get better icon quality) + m_iconWidget = new QPushButton(m_notification); + m_iconWidget->setObjectName(QStringLiteral("toast-icon-widget")); + + // Icon separator + m_iconSeparator = new QWidget(m_notification); + m_iconSeparator->setFixedWidth(2); + + // Duration bar container (used to make border radius possible on 4 px high widget) + m_durationBarContainer = new QWidget(m_notification); + m_durationBarContainer->setFixedHeight(4); + m_durationBarContainer->setStyleSheet(QStringLiteral("background: transparent;")); + + // Duration bar + m_durationBar = new QWidget(m_durationBarContainer); + m_durationBar->setFixedHeight(20); + m_durationBar->move(0, -16); + + // Duration bar chunk + m_durationBarChunk = new QWidget(m_durationBarContainer); + m_durationBarChunk->setFixedHeight(20); + m_durationBarChunk->move(0, -16); + + // Set defaults + setIcon(m_icon); + setIconSize(m_iconSize); + setIconColor(m_iconColor); + setIconSeparatorWidth(m_iconSeparatorWidth); + setCloseButtonIcon(m_closeButtonIcon); + setCloseButtonIconSize(m_closeButtonIconSize); + setCloseButtonSize(m_closeButtonSize); + setCloseButtonAlignment(m_closeButtonAlignment); + setStayOnTop(m_stayOnTop); + setBackgroundColor(m_backgroundColor); + setTitleColor(m_titleColor); + setTextColor(m_textColor); + setBorderRadius(m_borderRadius); + setIconSeparatorColor(m_iconSeparatorColor); + setCloseButtonIconColor(m_closeButtonIconColor); + setDurationBarColor(m_durationBarColor); + setTitleFont(m_titleFont); + setTextFont(m_textFont); + + // Timer for hiding the notification after set duration + m_durationTimer = new QTimer(this); + m_durationTimer->setSingleShot(true); + connect(m_durationTimer, &QTimer::timeout, this, &Toast::fadeOut); + + // Timer for updating the duration bar + m_durationBarTimer = new QTimer(this); + connect(m_durationBarTimer, &QTimer::timeout, this, &Toast::updateDurationBar); + + // Apply stylesheet + setStyleSheet(QStringLiteral( + "#toast-drop-shadow-layer-1 { background: rgba(0, 0, 0, 3); border-radius: 8px; }" + "#toast-drop-shadow-layer-2 { background: rgba(0, 0, 0, 5); border-radius: 8px; }" + "#toast-drop-shadow-layer-3 { background: rgba(0, 0, 0, 6); border-radius: 8px; }" + "#toast-drop-shadow-layer-4 { background: rgba(0, 0, 0, 9); border-radius: 8px; }" + "#toast-drop-shadow-layer-5 { background: rgba(0, 0, 0, 10); border-radius: 8px; }" + "#toast-close-button { background: transparent; }" + "#toast-icon-widget { background: transparent; }" + )); +} + +Toast::~Toast() +{ +} + +int Toast::getMaximumOnScreen() +{ + return s_maximumOnScreen; +} + +int Toast::getSpacing() +{ + return s_spacing; +} + +QPoint Toast::getOffset() +{ + return QPoint(s_offsetX, s_offsetY); +} + +int Toast::getOffsetX() +{ + return s_offsetX; +} + +int Toast::getOffsetY() +{ + return s_offsetY; +} + +bool Toast::isAlwaysOnMainScreen() +{ + return s_alwaysOnMainScreen; +} + +QScreen* Toast::getFixedScreen() +{ + return s_fixedScreen; +} + +Toast::Position Toast::getPosition() +{ + return s_position; +} + +int Toast::getCount() +{ + return s_currentlyShown.size() + s_queue.size(); +} + +int Toast::getVisibleCount() +{ + return s_currentlyShown.size(); +} + +int Toast::getQueuedCount() +{ + return s_queue.size(); +} + +int Toast::getDuration() +{ + return m_duration; +} + +bool Toast::isShowDurationBar() +{ + return m_showDurationBar; +} + +QString Toast::getTitle() +{ + return m_title; +} + +QString Toast::getText() +{ + return m_text; +} + +QPixmap Toast::getIcon() +{ + return m_icon; +} + +bool Toast::isShowIcon() +{ + return m_showIcon; +} + +QSize Toast::getIconSize() +{ + return m_iconSize; +} + +bool Toast::isShowIconSeparator() +{ + return m_showIconSeparator; +} + +int Toast::getIconSeparatorWidth() +{ + return m_iconSeparatorWidth; +} + +QPixmap Toast::getCloseButtonIcon() +{ + return m_closeButtonIcon; +} + +bool Toast::isShowCloseButton() +{ + return m_showCloseButton; +} + +QSize Toast::getCloseButtonIconSize() +{ + return m_closeButtonIconSize; +} + +int Toast::getCloseButtonWidth() +{ + return m_closeButtonSize.width(); +} + +int Toast::getCloseButtonHeight() +{ + return m_closeButtonSize.height(); +} + +QSize Toast::getCloseButtonSize() +{ + return m_closeButtonSize; +} + +Toast::ButtonAlignment Toast::getCloseButtonAlignment() +{ + return m_closeButtonAlignment; +} + +int Toast::getFadeInDuration() +{ + return m_fadeInDuration; +} + +int Toast::getFadeOutDuration() +{ + return m_fadeOutDuration; +} + +bool Toast::isResetDurationOnHover() +{ + return m_resetDurationOnHover; +} + +bool Toast::isStayOnTop() +{ + return m_stayOnTop; +} + +int Toast::getBorderRadius() +{ + return m_borderRadius; +} + +QColor Toast::getBackgroundColor() +{ + return m_backgroundColor; +} + +QColor Toast::getTitleColor() +{ + return m_titleColor; +} + +QColor Toast::getTextColor() +{ + return m_textColor; +} + +QColor Toast::getIconColor() +{ + return m_iconColor; +} + +QColor Toast::getIconSeparatorColor() +{ + return m_iconSeparatorColor; +} + +QColor Toast::getCloseButtonIconColor() +{ + return m_closeButtonIconColor; +} + +QColor Toast::getDurationBarColor() +{ + return m_durationBarColor; +} + +QFont Toast::getTitleFont() +{ + return m_titleFont; +} + +QFont Toast::getTextFont() +{ + return m_textFont; +} + +QMargins Toast::getMargins() +{ + return m_margins; +} + +QMargins Toast::getIconMargins() +{ + return m_iconMargins; +} + +QMargins Toast::getIconSectionMargins() +{ + return m_iconSectionMargins; +} + +QMargins Toast::getTextSectionMargins() +{ + return m_textSectionMargins; +} + +QMargins Toast::getCloseButtonMargins() +{ + return m_closeButtonMargins; +} + +int Toast::getTextSectionSpacing() +{ + return m_textSectionSpacing; +} + +void Toast::setMaximumOnScreen(int maximum) +{ + int freedSpaces = maximum - s_maximumOnScreen; + s_maximumOnScreen = maximum; + + if (freedSpaces > 0) + { + for (int i = 0; i < freedSpaces; i++) + { + showNextInQueue(); + } + } +} + +void Toast::setSpacing(int spacing) +{ + s_spacing = spacing; + updateCurrentlyShowingPositionY(); +} + +void Toast::setOffset(int x, int y) +{ + s_offsetX = x; + s_offsetY = y; + updateCurrentlyShowingPositionXY(); +} + +void Toast::setOffsetX(int offsetX) +{ + s_offsetX = offsetX; + updateCurrentlyShowingPositionX(); +} + +void Toast::setOffsetY(int offsetY) +{ + s_offsetY = offsetY; + updateCurrentlyShowingPositionY(); +} + +void Toast::setAlwaysOnMainScreen(bool enabled) +{ + s_alwaysOnMainScreen = enabled; + updateCurrentlyShowingPositionXY(); +} + +void Toast::setFixedScreen(QScreen* screen) +{ + s_fixedScreen = screen; + updateCurrentlyShowingPositionXY(); +} + +void Toast::setPosition(Position position) +{ + s_position = position; + updateCurrentlyShowingPositionXY(); +} + +void Toast::reset() +{ + // Reset static attributes + s_maximumOnScreen = 3; + s_spacing = 10; + s_offsetX = 20; + s_offsetY = 45; + s_alwaysOnMainScreen = false; + s_fixedScreen = nullptr; + s_position = Position::BottomRight; + + // Hide currently showing toasts and clear queue + for (Toast* toast : s_currentlyShown) + { + toast->setVisible(false); + toast->deleteLater(); + } + + s_currentlyShown.clear(); + s_queue.clear(); +} + +void Toast::setDuration(int duration) +{ + if (m_used) + { + return; + } + m_duration = duration; +} + +void Toast::setShowDurationBar(bool enabled) +{ + if (m_used) + { + return; + } + m_showDurationBar = enabled; +} + +void Toast::setTitle(QString title) +{ + if (m_used) + { + return; + } + m_title = title; + m_titleLabel->setText(title); +} + +void Toast::setText(QString text) +{ + if (m_used) + { + return; + } + m_text = text; + m_textLabel->setText(text); +} + +void Toast::setIcon(QPixmap icon) +{ + if (m_used) + { + return; + } + m_icon = icon; + m_iconWidget->setIcon(QIcon(icon)); + setIconColor(m_iconColor); +} + +void Toast::setIcon(Icon icon) +{ + if (m_used) + { + return; + } + m_icon = getIconFromEnum(icon); + m_iconWidget->setIcon(QIcon(m_icon)); + setIconColor(m_iconColor); +} + +void Toast::setShowIcon(bool enabled) +{ + if (m_used) + { + return; + } + m_showIcon = enabled; +} + +void Toast::setIconSize(QSize size) +{ + if (m_used) + { + return; + } + m_iconSize = size; + m_iconWidget->setFixedSize(size); + m_iconWidget->setIconSize(size); + setIcon(m_icon); +} + +void Toast::setShowIconSeparator(bool enabled) +{ + if (m_used) + { + return; + } + m_showIconSeparator = enabled; + + if (enabled) + { + m_iconSeparator->setFixedWidth(m_iconSeparatorWidth); + } + else { + m_iconSeparator->setFixedWidth(0); + } +} + +void Toast::setIconSeparatorWidth(int width) +{ + if (m_used) + { + return; + } + m_iconSeparatorWidth = width; + + if (m_showIconSeparator) + { + m_iconSeparator->setFixedWidth(width); + } +} + +void Toast::setCloseButtonIcon(QPixmap icon) +{ + if (m_used) + { + return; + } + m_closeButtonIcon = icon; + m_closeButton->setIcon(QIcon(icon)); + setCloseButtonIconColor(m_closeButtonIconColor); +} + +void Toast::setCloseButtonIcon(Icon icon) +{ + if (m_used) + { + return; + } + m_closeButtonIcon = getIconFromEnum(icon); + m_closeButton->setIcon(QIcon(m_closeButtonIcon)); + setCloseButtonIconColor(m_closeButtonIconColor); +} + +void Toast::setShowCloseButton(bool enabled) +{ + if (m_used) + { + return; + } + m_showCloseButton = enabled; +} + +void Toast::setCloseButtonIconSize(QSize size) +{ + if (m_used) + { + return; + } + m_closeButtonIconSize = size; + m_closeButton->setIconSize(size); + setCloseButtonIcon(m_closeButtonIcon); +} + +void Toast::setCloseButtonSize(QSize size) +{ + if (m_used) + { + return; + } + m_closeButtonSize = size; + m_closeButton->setFixedSize(size); +} + +void Toast::setCloseButtonWidth(int width) +{ + if (m_used) + { + return; + } + m_closeButtonSize.setWidth(width); + m_closeButton->setFixedSize(m_closeButtonSize); +} + +void Toast::setCloseButtonHeight(int height) +{ + if (m_used) + { + return; + } + m_closeButtonSize.setHeight(height); + m_closeButton->setFixedSize(m_closeButtonSize); +} + +void Toast::setCloseButtonAlignment(ButtonAlignment alignment) +{ + if (m_used) + { + return; + } + m_closeButtonAlignment = alignment; +} + +void Toast::setFadeInDuration(int duration) +{ + if (m_used) + { + return; + } + m_fadeInDuration = duration; +} + +void Toast::setFadeOutDuration(int duration) +{ + if (m_used) + { + return; + } + m_fadeOutDuration = duration; +} + +void Toast::setResetDurationOnHover(bool enabled) +{ + if (m_used) + { + return; + } + m_resetDurationOnHover = enabled; +} + +void Toast::setStayOnTop(bool enabled) +{ + if (m_used) + { + return; + } + m_stayOnTop = enabled; + + if (enabled) + { + setWindowFlags(Qt::WindowType::Tool + | Qt::WindowType::CustomizeWindowHint + | Qt::WindowType::FramelessWindowHint + | Qt::WindowType::WindowStaysOnTopHint); + } + else + { + setWindowFlags(Qt::WindowType::Tool + | Qt::WindowType::CustomizeWindowHint + | Qt::WindowType::FramelessWindowHint); + } +} + +void Toast::setBorderRadius(int borderRadius) +{ + if (m_used) + { + return; + } + m_borderRadius = borderRadius; +} + +void Toast::setBackgroundColor(QColor color) +{ + if (m_used) + { + return; + } + m_backgroundColor = color; +} + +void Toast::setTitleColor(QColor color) +{ + if (m_used) + { + return; + } + m_titleColor = color; +} + +void Toast::setTextColor(QColor color) +{ + if (m_used) + { + return; + } + m_textColor = color; +} + +void Toast::setIconColor(QColor color) +{ + if (m_used) + { + return; + } + m_iconColor = color; + + QImage recoloredImage = recolorImage(m_iconWidget->icon() + .pixmap(m_iconWidget->iconSize()).toImage(), color); + m_iconWidget->setIcon(QIcon(QPixmap::fromImage(recoloredImage))); +} + +void Toast::setIconSeparatorColor(QColor color) +{ + if (m_used) + { + return; + } + m_iconSeparatorColor = color; +} + +void Toast::setCloseButtonIconColor(QColor color) +{ + if (m_used) + { + return; + } + m_closeButtonIconColor = color; + + QImage recoloredImage = recolorImage(m_closeButton->icon() + .pixmap(m_closeButton->iconSize()).toImage(), color); + m_closeButton->setIcon(QIcon(QPixmap::fromImage(recoloredImage))); +} + +void Toast::setDurationBarColor(QColor color) +{ + if (m_used) + { + return; + } + m_durationBarColor = color; +} + +void Toast::setTitleFont(QFont font) +{ + if (m_used) + { + return; + } + m_titleFont = font; + m_titleLabel->setFont(font); +} + +void Toast::setTextFont(QFont font) +{ + if (m_used) + { + return; + } + m_textFont = font; + m_textLabel->setFont(font); +} + +void Toast::setMargins(QMargins margins) +{ + if (m_used) + { + return; + } + m_margins = margins; +} + +void Toast::setMarginLeft(int margin) +{ + if (m_used) + { + return; + } + m_margins.setLeft(margin); +} + +void Toast::setMarginTop(int margin) +{ + if (m_used) + { + return; + } + m_margins.setTop(margin); +} + +void Toast::setMarginRight(int margin) +{ + if (m_used) + { + return; + } + m_margins.setRight(margin); +} + + +void Toast::setMarginBottom(int margin) +{ + if (m_used) + { + return; + } + m_margins.setBottom(margin); +} + + +void Toast::setIconMargins(QMargins margins) +{ + if (m_used) + { + return; + } + m_iconMargins = margins; +} + + +void Toast::setIconMarginLeft(int margin) +{ + if (m_used) + { + return; + } + m_iconMargins.setLeft(margin); +} + + +void Toast::setIconMarginTop(int margin) +{ + if (m_used) + { + return; + } + m_iconMargins.setTop(margin); +} + + +void Toast::setIconMarginRight(int margin) +{ + if (m_used) + { + return; + } + m_iconMargins.setRight(margin); +} + + +void Toast::setIconMarginBottom(int margin) +{ + if (m_used) + { + return; + } + m_iconMargins.setBottom(margin); +} + + +void Toast::setIconSectionMargins(QMargins margins) +{ + if (m_used) + { + return; + } + m_iconSectionMargins = margins; +} + + +void Toast::setIconSectionMarginLeft(int margin) +{ + if (m_used) + { + return; + } + m_iconSectionMargins.setLeft(margin); +} + + +void Toast::setIconSectionMarginTop(int margin) +{ + if (m_used) + { + return; + } + m_iconSectionMargins.setTop(margin); +} + + +void Toast::setIconSectionMarginRight(int margin) +{ + if (m_used) + { + return; + } + m_iconSectionMargins.setRight(margin); +} + + +void Toast::setIconSectionMarginBottom(int margin) +{ + if (m_used) + { + return; + } + m_iconSectionMargins.setBottom(margin); +} + + +void Toast::setTextSectionMargins(QMargins margins) +{ + if (m_used) + { + return; + } + m_textSectionMargins = margins; +} + + +void Toast::setTextSectionMarginLeft(int margin) +{ + if (m_used) + { + return; + } + m_textSectionMargins.setLeft(margin); +} + + +void Toast::setTextSectionMarginTop(int margin) +{ + if (m_used) + { + return; + } + m_textSectionMargins.setTop(margin); +} + + +void Toast::setTextSectionMarginRight(int margin) +{ + if (m_used) + { + return; + } + m_textSectionMargins.setRight(margin); +} + + +void Toast::setTextSectionMarginBottom(int margin) +{ + if (m_used) + { + return; + } + m_textSectionMargins.setBottom(margin); +} + + +void Toast::setCloseButtonMargins(QMargins margins) +{ + if (m_used) + { + return; + } + m_closeButtonMargins = margins; +} + + +void Toast::setCloseButtonMarginLeft(int margin) +{ + if (m_used) + { + return; + } + m_closeButtonMargins.setLeft(margin); +} + + +void Toast::setCloseButtonMarginTop(int margin) +{ + if (m_used) + { + return; + } + m_closeButtonMargins.setTop(margin); +} + + +void Toast::setCloseButtonMarginRight(int margin) +{ + if (m_used) + { + return; + } + m_closeButtonMargins.setRight(margin); +} + + +void Toast::setCloseButtonMarginBottom(int margin) +{ + if (m_used) + { + return; + } + m_closeButtonMargins.setBottom(margin); +} + + +void Toast::setTextSectionSpacing(int spacing) +{ + if (m_used) + { + return; + } + m_textSectionSpacing = spacing; +} + + +void Toast::setFixedSize(QSize size) +{ + setMinimumSize(size); + setMaximumSize(size); +} + + +void Toast::setFixedSize(int width, int height) +{ + setMinimumSize(width, height); + setMaximumSize(width, height); +} + + +void Toast::setFixedWidth(int width) +{ + setMinimumWidth(width); + setMaximumWidth(width); +} + +void Toast::setFixedHeight(int height) +{ + setMinimumHeight(height); + setMaximumHeight(height); +} + +void Toast::applyPreset(Preset preset) +{ + if (m_used) + { + return; + } + + if (preset == Preset::Success) + { + setIcon(Icon::Success); + setIconColor(sc_successAccentColor); + setDurationBarColor(sc_successAccentColor); + } + else if (preset == Preset::Warning) + { + setIcon(Icon::Warning); + setIconColor(sc_warningAccentColor); + setDurationBarColor(sc_warningAccentColor); + } + else if (preset == Preset::Error) + { + setIcon(Icon::Error); + setIconColor(sc_errorAccentColor); + setDurationBarColor(sc_errorAccentColor); + } + else if (preset == Preset::Information) + { + setIcon(Icon::Information); + setIconColor(sc_informationAccentColor); + setDurationBarColor(sc_informationAccentColor); + } + + if ( +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + (QGuiApplication::styleHints() && + QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark) || +#endif + VeyonCore::useDarkMode()) + { + setBackgroundColor(sc_defaultBackgroundColorDark); + setCloseButtonIconColor(sc_defaultCloseButtonIconColorDark); + setIconSeparatorColor(sc_defaultIconSeparatorColorDark); + setTitleColor(sc_defaultTitleColorDark); + setTextColor(sc_defaultTextColorDark); + } + else + { + setBackgroundColor(sc_defaultBackgroundColor); + setCloseButtonIconColor(sc_defaultCloseButtonIconColor); + setIconSeparatorColor(sc_defaultIconSeparatorColor); + setTitleColor(sc_defaultTitleColor); + setTextColor(sc_defaultTextColor); + } + + setShowDurationBar(true); + setShowIcon(true); + setShowIconSeparator(true); + setIconSeparatorWidth(2); +} + + +void Toast::show() +{ + // Check if already used + if (m_used) + { + return; + } + + // If max notifications on screen not reached, show notification + if (s_maximumOnScreen > int(s_currentlyShown.size())) + { + m_used = true; + s_currentlyShown.push_back(this); + + // Setup UI + setupUI(); + + // Start duration timer + if (m_duration != 0) + { + m_durationTimer->start(m_duration); + } + + // Start duration bar update timer + if (m_duration != 0 && m_showDurationBar) + { + m_durationBarTimer->start(sc_durationBarUpdateInterval); + } + + // Calculate position and show + QPoint position = calculatePosition(); + + // If not first toast on screen, also do a fade down / up animation + if (s_currentlyShown.size() > 1) + { + // Calculate offset if predecessor toast is still in fade down / up animation + Toast* predecessorToast = getPredecessorToast(); + QPoint predecessorTarget = predecessorToast->calculatePosition(); + int predecessorTargetDifferenceY = abs(predecessorToast->y() - predecessorTarget.y()); + + // Calculate start position of fade down / up animation based on position + if (s_position == Position::BottomRight + || s_position == Position::BottomLeft + || s_position == Position::BottomMiddle) + { + move(position.x(), + position.y() - (int)(height() / 1.5) - predecessorTargetDifferenceY); + } + else if (s_position == Position::TopRight + || s_position == Position::TopLeft + || s_position == Position::TopMiddle + || s_position == Position::Center) + { + move(position.x(), + position.y() + (int)(height() / 1.5) + predecessorTargetDifferenceY); + } + + // Start fade down / up animation + QPropertyAnimation* posAnimation = new QPropertyAnimation(this, "pos"); + posAnimation->setEndValue(QPoint(position.x(), position.y())); + posAnimation->setDuration(m_fadeInDuration); + posAnimation->start(QAbstractAnimation::DeleteWhenStopped); + } + else + { + move(position.x(), position.y()); + } + + // Fade in + QDialog::show(); + QPropertyAnimation* fadeInAnimation = new QPropertyAnimation(m_opacityEffect, "opacity"); + fadeInAnimation->setDuration(m_fadeInDuration); + fadeInAnimation->setStartValue(0); + fadeInAnimation->setEndValue(1); + fadeInAnimation->start(QAbstractAnimation::DeleteWhenStopped); + + // Make sure title bar of parent is not grayed out + if (m_parent) + { + m_parent->activateWindow(); + } + + // Update every other currently shown notification + for (Toast* toast : s_currentlyShown) + { + toast->updatePositionXY(); + } + } + else + { + // Add notification to queue instead + s_queue.push_back(this); + } +} + +void Toast::hide() +{ + if (!m_fadingOut) + { + if (m_duration != 0) + { + m_durationTimer->stop(); + } + fadeOut(); + } +} + +void Toast::hide_() +{ + close(); + + int index = 0; + for (Toast* toast : s_currentlyShown) + { + if (toast == this) + { + s_currentlyShown.erase(s_currentlyShown.begin() + index); + m_elapsedTime = 0; + m_fadingOut = false; + + // Emit signal + Q_EMIT closed(); + + // Update every other currently shown notification + for (Toast* toast : s_currentlyShown) + { + toast->updatePositionY(); + } + + // Show next item from queue after updating + QTimer::singleShot(m_fadeInDuration, this, &Toast::deleteAndShowNextInQueue); + + break; + }; + index++; + } +} + +void Toast::enterEvent(EnterEvent* event) +{ + Q_UNUSED(event) + + // Reset timer if hovered and resetting is enabled + if (m_duration != 0 && m_durationTimer->isActive() && m_resetDurationOnHover) + { + m_durationTimer->stop(); + + // Reset duration bar if enabled + if (m_showDurationBar) + { + m_durationBarTimer->stop(); + m_durationBarChunk->setFixedWidth(m_notification->width()); + m_elapsedTime = 0; + } + } +} + +void Toast::leaveEvent(QEvent* event) +{ + Q_UNUSED(event) + + // Start timer again when leaving notification and reset is enabled + if (m_duration != 0 && !m_durationTimer->isActive() && m_resetDurationOnHover) + { + m_durationTimer->start(m_duration); + + // Restart duration bar animation if enabled + if (m_showDurationBar) + { + m_durationBarTimer->start(sc_durationBarUpdateInterval); + } + } +} + +void Toast::fadeOut() +{ + m_fadingOut = true; + QPropertyAnimation* fadeOutAnimation = new QPropertyAnimation(m_opacityEffect, "opacity"); + fadeOutAnimation->setDuration(m_fadeOutDuration); + fadeOutAnimation->setStartValue(1); + fadeOutAnimation->setEndValue(0); + connect(fadeOutAnimation, &QPropertyAnimation::finished, this, &Toast::hide_); + fadeOutAnimation->start(QAbstractAnimation::DeleteWhenStopped); +} + +void Toast::updateDurationBar() +{ + m_elapsedTime += sc_durationBarUpdateInterval; + + if (m_elapsedTime >= m_duration) + { + m_durationBarTimer->stop(); + return; + } + double newChunkWidth = floor(m_durationBarContainer->width() + - (double)m_elapsedTime / (double)m_duration * m_durationBarContainer->width()); + m_durationBarChunk->setFixedWidth(newChunkWidth); +} + +void Toast::showNextInQueue() +{ + if (s_queue.size() > 0) + { + Toast* nextToast = s_queue.front(); + s_queue.pop_front(); + nextToast->show(); + } +} + +void Toast::setupUI() +{ + // Update stylesheet + updateStylesheet(); + + // Calculate title and text width and height + QFontMetrics* titleFontMetrics = new QFontMetrics(m_titleFont); + int titleWidth = titleFontMetrics->boundingRect(m_title).width() + 1; + int titleHeight = titleFontMetrics->boundingRect(m_title).height(); + delete titleFontMetrics; + + QFontMetrics* textFontMetrics = new QFontMetrics(m_textFont); + int textWidth = textFontMetrics->boundingRect(m_text).width() + 1; + int textHeight = textFontMetrics->boundingRect(m_text).height(); + delete textFontMetrics; + + int textSectionSpacing = m_title.isEmpty() || m_text.isEmpty() ? 0 : m_textSectionSpacing; + + int textSectionHeight = m_textSectionMargins.top() + titleHeight + + textSectionSpacing + textHeight + m_textSectionMargins.bottom(); + + // Calculate duration bar height + int durationBarHeight = m_showDurationBar ? m_durationBarContainer->height() : 0; + + // Calculate icon section width and height + int iconSectionWidth = 0; + int iconSectionHeight = 0; + + if (m_showIcon) + { + iconSectionWidth = m_iconSectionMargins.left() + m_iconMargins.left() + + m_iconWidget->width() + m_iconMargins.right() + + m_iconSeparator->width() + m_iconSectionMargins.right(); + iconSectionHeight = m_iconSectionMargins.top() + m_iconMargins.top() + + m_iconWidget->height() + m_iconMargins.bottom() + m_iconSectionMargins.bottom(); + } + + // Calculate close button section size + int closeButtonWidth = m_showCloseButton ? m_closeButton->width() : 0; + int closeButtonHeight = m_showCloseButton ? m_closeButton->height() : 0; + QMargins closeButtonMargins = m_showCloseButton ? m_closeButtonMargins : QMargins(0, 0, 0, 0); + + int closeButtonSectionHeight = m_closeButtonMargins.top() + + closeButtonHeight + m_closeButtonMargins.bottom(); + + // Calculate needed width and height + int width = m_margins.left() + iconSectionWidth + m_textSectionMargins.left() + + std::max(titleWidth, textWidth) + m_textSectionMargins.right() + + closeButtonMargins.left() + closeButtonWidth + + closeButtonMargins.right() + m_margins.right(); + + int height = m_margins.top() + std::max({iconSectionHeight, textSectionHeight, + closeButtonSectionHeight}) + m_margins.bottom() + durationBarHeight; + + int forcedAdditionalHeight = 0; + int forcedReducedHeight = 0; + + // Handle width greater than maximum width + if (width > maximumWidth()) + { + // Enable line break for title and text and recalculate size + int newTitleWidth = std::max(titleWidth, textWidth) - (width - maximumWidth()); + if (newTitleWidth > 0) + { + titleWidth = newTitleWidth; + } + + int newTextWidth = std::max(titleWidth, textWidth) - (width - maximumWidth()); + if (newTextWidth > 0) + { + textWidth = newTextWidth; + } + + m_titleLabel->setMinimumWidth(titleWidth); + m_titleLabel->setWordWrap(true); + if (m_title.isEmpty() == false) + { + titleHeight = m_titleLabel->sizeHint().height(); + } + m_titleLabel->setFixedSize(titleWidth, titleHeight); + + m_textLabel->setMinimumWidth(textWidth); + m_textLabel->setWordWrap(true); + if (m_text.isEmpty() == false) + { + textHeight = m_textLabel->sizeHint().height(); + } + m_textLabel->setFixedSize(textWidth, textHeight); + + // Recalculate width and height + width = maximumWidth(); + + textSectionHeight = m_textSectionMargins.top() + titleHeight + + textSectionSpacing + textHeight + m_textSectionMargins.bottom(); + + height = m_margins.top() + std::max({iconSectionHeight, textSectionHeight, + closeButtonSectionHeight}) + m_margins.bottom() + durationBarHeight; + } + + // Handle height less than minimum height + if (height < minimumHeight()) + { + // Enable word wrap for title and text labels + m_titleLabel->setWordWrap(true); + m_textLabel->setWordWrap(true); + + // Calculate height with initial label width + titleWidth = m_titleLabel->fontMetrics().boundingRect(QRect(0, 0, 0, 0), + Qt::TextFlag::TextWordWrap, m_titleLabel->text()).width(); + + textWidth = m_textLabel->fontMetrics().boundingRect(QRect(0, 0, 0, 0), + Qt::TextFlag::TextWordWrap, m_textLabel->text()).width(); + + int tempWidth = std::max(titleWidth, textWidth); + + titleWidth = m_titleLabel->fontMetrics().boundingRect(QRect(0, 0, tempWidth, 0), + Qt::TextFlag::TextWordWrap, m_titleLabel->text()).width(); + if (m_title.isEmpty() == false) + { + titleHeight = m_titleLabel->fontMetrics().boundingRect(QRect(0, 0, tempWidth, 0), + Qt::TextFlag::TextWordWrap, m_titleLabel->text()).height(); + } + + textWidth = m_textLabel->fontMetrics().boundingRect(QRect(0, 0, tempWidth, 0), + Qt::TextFlag::TextWordWrap, m_textLabel->text()).width(); + if (m_text.isEmpty() == false) + { + textHeight = m_textLabel->fontMetrics().boundingRect(QRect(0, 0, tempWidth, 0), + Qt::TextFlag::TextWordWrap, m_textLabel->text()).height(); + } + + textSectionHeight = m_textSectionMargins.top() + titleHeight + + textSectionSpacing + textHeight + m_textSectionMargins.bottom(); + + height = m_margins.top() + std::max({ iconSectionHeight, textSectionHeight, + closeButtonSectionHeight }) + m_margins.bottom() + durationBarHeight; + + while (tempWidth <= width) + { + // Recalculate height with different text widths to find optimal value + int tempTitleWidth = m_titleLabel->fontMetrics().boundingRect(QRect(0, 0, tempWidth, 0), + Qt::TextFlag::TextWordWrap, m_titleLabel->text()).width(); + + int tempTitleHeight = m_titleLabel->fontMetrics().boundingRect(QRect(0, 0, tempWidth, 0), + Qt::TextFlag::TextWordWrap, m_titleLabel->text()).height(); + + int tempTextWidth = m_textLabel->fontMetrics().boundingRect(QRect(0, 0, tempWidth, 0), + Qt::TextFlag::TextWordWrap, m_textLabel->text()).width(); + + int tempTextHeight = m_textLabel->fontMetrics().boundingRect(QRect(0, 0, tempWidth, 0), + Qt::TextFlag::TextWordWrap, m_textLabel->text()).height(); + + if (m_title.isEmpty()) + { + tempTitleHeight = 0; + } + + if (m_text.isEmpty()) + { + tempTextHeight = 0; + } + + int tempTextSectionHeight = m_textSectionMargins.top() + tempTitleHeight + + textSectionSpacing + tempTextHeight + m_textSectionMargins.bottom(); + + int tempHeight = m_margins.top() + std::max({ iconSectionHeight, tempTextSectionHeight, + closeButtonSectionHeight }) + m_margins.bottom() + durationBarHeight; + + // Store values if calculated height is greater than or equal to min height + if (tempHeight >= minimumHeight()) + { + titleWidth = tempTitleWidth; + titleHeight = tempTitleHeight; + textWidth = tempTextWidth; + textHeight = tempTextHeight; + textSectionHeight = tempTextSectionHeight; + height = tempHeight; + tempWidth += 1; + } + else + { + // Exit loop if calculated height is less than min height + break; + } + } + + // Recalculate width + width = m_margins.left() + iconSectionWidth + m_textSectionMargins.left() + + std::max(titleWidth, textWidth) + m_textSectionMargins.right() + + closeButtonMargins.left() + closeButtonWidth + + closeButtonMargins.right() + m_margins.right(); + + // If min height not met, set height to min height + if (height < minimumHeight()) + { + forcedAdditionalHeight = minimumHeight() - height; + height = minimumHeight(); + } + } + + // Handle width less than minimum width + if (width < minimumWidth()) + { + width = minimumWidth(); + } + + // Handle height greater than maximum height + if (height > maximumHeight()) + { + forcedReducedHeight = height - maximumHeight(); + height = maximumHeight(); + } + + // Calculate width and height including space for drop shadow + int totalWidth = width + sc_dropShadowSize * 2; + int totalHeight = height + sc_dropShadowSize * 2; + + // Resize drop shadow + m_dropShadowLayer1->resize(totalWidth, totalHeight); + m_dropShadowLayer1->move(0, 0); + m_dropShadowLayer2->resize(totalWidth - 2, totalHeight - 2); + m_dropShadowLayer2->move(1, 1); + m_dropShadowLayer3->resize(totalWidth - 4, totalHeight - 4); + m_dropShadowLayer3->move(2, 2); + m_dropShadowLayer4->resize(totalWidth - 6, totalHeight - 6); + m_dropShadowLayer4->move(3, 3); + m_dropShadowLayer5->resize(totalWidth - 8, totalHeight - 8); + m_dropShadowLayer5->move(4, 4); + + // Resize window + QDialog::setFixedSize(totalWidth, totalHeight); + m_notification->setFixedSize(width, height); + m_notification->move(sc_dropShadowSize, sc_dropShadowSize); + m_notification->raise(); + + // Calculate difference between height and height of icon section + int heightIconSectionHeightDifference = std::max({ iconSectionHeight, + textSectionHeight, closeButtonSectionHeight }) - iconSectionHeight; + + if (m_showIcon) + { + // Move icon + m_iconWidget->move(m_margins.left() + m_iconSectionMargins.left()+ m_iconMargins.left(), + m_margins.top() + m_iconSectionMargins.top() + m_iconMargins.top() + + ceil(heightIconSectionHeightDifference / 2) - floor(forcedReducedHeight / 2)); + + // Move and resize icon separator + m_iconSeparator->setFixedHeight(textSectionHeight); + m_iconSeparator->move(m_margins.left() + m_iconSectionMargins.left() + m_iconMargins.left() + + m_iconWidget->width() + m_iconMargins.right(), m_margins.top() + m_iconSectionMargins.top() + + ceil(forcedAdditionalHeight / 2) - floor(forcedReducedHeight / 2)); + } + else + { + // Hide icon section + m_iconWidget->setVisible(false); + m_iconSeparator->setVisible(false); + } + + // Calculate difference between height and height of text section + int heightTextSectionHeightDifference = std::max({iconSectionHeight, + textSectionHeight, closeButtonSectionHeight}) - textSectionHeight; + + // Resize title and text labels + m_titleLabel->setFixedSize(std::max(titleWidth, textWidth), titleHeight); + m_textLabel->setFixedSize(std::max(titleWidth, textWidth), textHeight); + + // Move title and text labels + if (m_showIcon) + { + m_titleLabel->move(m_margins.left() + m_iconSectionMargins.left() + + m_iconMargins.left() + m_iconWidget->width() + m_iconMargins.right() + + m_iconSeparator->width() + m_iconSectionMargins.right() + m_textSectionMargins.left(), + m_margins.top() + m_textSectionMargins.top() + ceil(heightTextSectionHeightDifference / 2) + + ceil(forcedAdditionalHeight / 2) - floor(forcedReducedHeight / 2)); + + m_textLabel->move(m_margins.left() + m_iconSectionMargins.left() + + m_iconMargins.left() + m_iconWidget->width() + m_iconMargins.right() + + m_iconSeparator->width() + m_iconSectionMargins.right() + m_textSectionMargins.left(), + m_margins.top() + m_textSectionMargins.top() + titleHeight + + textSectionSpacing + ceil(heightTextSectionHeightDifference / 2) + + ceil(forcedAdditionalHeight / 2) - floor(forcedReducedHeight / 2)); + } + else { + // Position is different if icon hidden + m_titleLabel->move(m_margins.left() + m_textSectionMargins.left(), + m_margins.top() + m_textSectionMargins.top() + ceil(heightTextSectionHeightDifference / 2) + + ceil(forcedAdditionalHeight / 2) - floor(forcedReducedHeight / 2)); + + m_textLabel->move(m_margins.left() + m_textSectionMargins.left(), + m_margins.top() + m_textSectionMargins.top() + titleHeight + + textSectionSpacing + ceil(heightTextSectionHeightDifference / 2) + + ceil(forcedAdditionalHeight / 2) - floor(forcedReducedHeight / 2)); + } + + // Adjust label position if either title or text is empty + if (m_title.isEmpty() && m_text.isEmpty() == false) + { + m_textLabel->move(m_textLabel->x(), + (int)((height - textHeight - durationBarHeight) / 2)); + } + else if (m_title.isEmpty() == false && m_text.isEmpty()) + { + m_titleLabel->move(m_titleLabel->x(), + (int)((height - titleHeight - durationBarHeight) / 2)); + } + + // Move close button to top, middle, or bottom position + if (m_closeButtonAlignment == ButtonAlignment::Top) + { + m_closeButton->move(width - closeButtonWidth - closeButtonMargins.right() + - m_margins.right(), m_margins.top() + closeButtonMargins.top()); + } + else if (m_closeButtonAlignment == ButtonAlignment::Middle) + { + m_closeButton->move(width - closeButtonWidth - closeButtonMargins.right() + - m_margins.right(), ceil((height - closeButtonHeight - durationBarHeight) / 2)); + } + else if (m_closeButtonAlignment == ButtonAlignment::Bottom) + { + m_closeButton->move(width - closeButtonWidth - closeButtonMargins.right() + - m_margins.right(), height - closeButtonHeight - m_margins.bottom() + - closeButtonMargins.bottom() - durationBarHeight); + } + + // Hide close button if disabled + if (!m_showCloseButton) + { + m_closeButton->setVisible(false); + } + + // Resize, move, and show duration bar if enabled + if (m_showDurationBar) + { + m_durationBarContainer->setFixedWidth(width); + m_durationBarContainer->move(0, height - durationBarHeight); + m_durationBar->setFixedWidth(width); + m_durationBarChunk->setFixedWidth(width); + } + else { + m_durationBarContainer->setVisible(false); + } +} + +QPoint Toast::calculatePosition() +{ + // Calculate vertical space taken up by all the currently showing notifications + int offsetY = 0; + + for (Toast* toast : s_currentlyShown) + { + if (toast == this) + { + break; + } + offsetY += toast->m_notification->height() + s_spacing; + } + + // Get screen + QScreen* primaryScreen = QGuiApplication::primaryScreen(); + QScreen* currentScreen = nullptr; + + if (s_fixedScreen) + { + currentScreen = s_fixedScreen; + } + else if (s_alwaysOnMainScreen || !m_parent) + { + currentScreen = primaryScreen; + } + else + { + QList screens = QGuiApplication::screens(); + + for (QScreen* screen : screens) + { + if (m_parent->geometry().intersects(screen->geometry())) + { + if (!currentScreen) + { + currentScreen = screen; + } + else + { + currentScreen = primaryScreen; + break; + } + } + } + } + + // Calculate x and y position of notification + int x = 0; + int y = 0; + + if (s_position == Position::BottomRight) + { + x = currentScreen->geometry().width() - m_notification->width() + - s_offsetX + currentScreen->geometry().x(); + y = currentScreen->geometry().height() - m_notification->height() + - s_offsetY + currentScreen->geometry().y() - offsetY; + } + else if (s_position == Position::BottomLeft) + { + x = currentScreen->geometry().x() + s_offsetX; + y = currentScreen->geometry().height() - m_notification->height() + - s_offsetY + currentScreen->geometry().y() - offsetY; + } + else if (s_position == Position::BottomMiddle) + { + x = (int)(currentScreen->geometry().x() + + currentScreen->geometry().width() / 2 - m_notification->width() / 2); + y = currentScreen->geometry().height() - m_notification->height() + - s_offsetY + currentScreen->geometry().y() - offsetY; + } + else if (s_position == Position::TopRight) + { + x = currentScreen->geometry().width() - m_notification->width() + - s_offsetX + currentScreen->geometry().x(); + y = currentScreen->geometry().y() + s_offsetY + offsetY; + } + else if (s_position == Position::TopLeft) + { + x = currentScreen->geometry().x() + s_offsetX; + y = currentScreen->geometry().y() + s_offsetY + offsetY; + } + else if (s_position == Position::TopMiddle) + { + x = (int)(currentScreen->geometry().x() + + currentScreen->geometry().width() / 2 - m_notification->width() / 2); + y = currentScreen->geometry().y() + s_offsetY + offsetY; + } + else if (s_position == Position::Center) + { + x = (int)(currentScreen->geometry().x() + + currentScreen->geometry().width() / 2 - m_notification->width() / 2); + y = (int)(currentScreen->geometry().y() + currentScreen->geometry().height() / 2 + - m_notification->height() / 2 + offsetY); + } + + x -= sc_dropShadowSize; + y -= sc_dropShadowSize; + + return QPoint(x, y); +} + +void Toast::updatePositionXY() +{ + QPoint position = calculatePosition(); + + // Animate position change + QPropertyAnimation* posAnimation = new QPropertyAnimation(this, "pos"); + posAnimation->setEndValue(position); + posAnimation->setDuration(sc_updatePositionDuration); + posAnimation->start(QAbstractAnimation::DeleteWhenStopped); +} + +void Toast::updatePositionX() +{ + QPoint position = calculatePosition(); + + // Animate position change + QPropertyAnimation* posAnimation = new QPropertyAnimation(this, "pos"); + posAnimation->setEndValue(QPoint(position.x(), y())); + posAnimation->setDuration(sc_updatePositionDuration); + posAnimation->start(); +} + +void Toast::updatePositionY() +{ + QPoint position = calculatePosition(); + + // Animate position change + QPropertyAnimation* posAnimation = new QPropertyAnimation(this, "pos"); + posAnimation->setEndValue(QPoint(x(), position.y())); + posAnimation->setDuration(sc_updatePositionDuration); + posAnimation->start(QAbstractAnimation::DeleteWhenStopped); +} + +void Toast::updateStylesheet() +{ + m_notification->setStyleSheet(QStringLiteral("background: %1;" + "border-radius: %2px; ").arg(m_backgroundColor.name()).arg(m_borderRadius)); + + m_durationBar->setStyleSheet(QStringLiteral("background: rgba(%1, %2, %3, 100);" + "border-radius: %4px;").arg(m_durationBarColor.red()) + .arg(m_durationBarColor.green()).arg(m_durationBarColor.blue()).arg(m_borderRadius)); + + m_durationBarChunk->setStyleSheet(QStringLiteral("background: rgba(%1, %2, %3, 255);" + "border-bottom-left-radius: %4px; border-bottom-right-radius: %5px;") + .arg(m_durationBarColor.red()).arg(m_durationBarColor.green()) + .arg(m_durationBarColor.blue()).arg(m_borderRadius) + .arg(m_duration == 0 ? m_borderRadius : 0)); + + m_iconSeparator->setStyleSheet(QStringLiteral("background: %1;").arg(m_iconSeparatorColor.name())); + + m_titleLabel->setStyleSheet(QStringLiteral("color: %1;").arg(m_titleColor.name())); + m_textLabel->setStyleSheet(QStringLiteral("color: %1;").arg(m_textColor.name())); +} + +Toast* Toast::getPredecessorToast() +{ + Toast* predecessorToast = nullptr; + + for (Toast* toast : s_currentlyShown) + { + if (toast == this) + { + return predecessorToast; + } + predecessorToast = toast; + } + + return predecessorToast; +} + +QImage Toast::recolorImage(QImage image, QColor color) +{ + // Loop through every pixel + for (int x = 0; x < image.width(); x++) { + for (int y = 0; y < image.height(); y++) { + // Get current color of the pixel + QColor currentColor = image.pixelColor(x, y); + + // Replace the rgb values with rgb of new color and keep alpha the same + QColor newColor = QColor::fromRgba(qRgba(color.red(), color.green(), + color.blue(), currentColor.alpha())); + image.setPixelColor(x, y, newColor); + } + } + return image; +} + +QPixmap Toast::getIconFromEnum(Icon enumIcon) +{ + auto base = QStringLiteral(":/core/toast-%1"); + + if (enumIcon == Icon::Success) + { + return QPixmap(base.arg(QStringLiteral("success.png"))); + } + else if (enumIcon == Icon::Warning) + { + return QPixmap(base.arg(QStringLiteral("warning.png"))); + } + else if (enumIcon == Icon::Error) + { + return QPixmap(base.arg(QStringLiteral("error.png"))); + } + else if (enumIcon == Icon::Information) + { + return QPixmap(base.arg(QStringLiteral("information.png"))); + } + else if (enumIcon == Icon::Close) + { + return QPixmap(base.arg(QStringLiteral("close.png"))); + } + return QPixmap(); +} + +void Toast::updateCurrentlyShowingPositionXY() +{ + for (Toast* toast : s_currentlyShown) + { + toast->updatePositionXY(); + } +} + +void Toast::updateCurrentlyShowingPositionX() +{ + for (Toast* toast : s_currentlyShown) + { + toast->updatePositionX(); + } +} + +void Toast::updateCurrentlyShowingPositionY() +{ + for (Toast* toast : s_currentlyShown) + { + toast->updatePositionY(); + } +} + +void Toast::deleteAndShowNextInQueue() +{ + showNextInQueue(); + deleteLater(); +} diff --git a/core/src/Toast.h b/core/src/Toast.h new file mode 100644 index 000000000..badd0b6be --- /dev/null +++ b/core/src/Toast.h @@ -0,0 +1,319 @@ +/* + * File based on https://github.com/niklashenning/qt-toast/blob/master/src/Toast.h + * + * MIT License + + * Copyright (c) 2024 Niklas Henning + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#pragma once + +#include +#include + +class QGraphicsOpacityEffect; +class QLabel; + +class Toast : public QDialog +{ + Q_OBJECT +public: + enum class Preset + { + Success, + Warning, + Error, + Information, + }; + + enum class Icon + { + Success, + Warning, + Error, + Information, + Close + }; + + enum class Position + { + BottomLeft, + BottomMiddle, + BottomRight, + TopLeft, + TopMiddle, + TopRight, + Center + }; + + enum class ButtonAlignment + { + Top, + Middle, + Bottom + }; + + Toast(QWidget* parent = nullptr); + ~Toast(); + + static int getMaximumOnScreen(); + static int getSpacing(); + static QPoint getOffset(); + static int getOffsetX(); + static int getOffsetY(); + static bool isAlwaysOnMainScreen(); + static QScreen* getFixedScreen(); + static Position getPosition(); + static int getCount(); + static int getVisibleCount(); + static int getQueuedCount(); + int getDuration(); + bool isShowDurationBar(); + QString getTitle(); + QString getText(); + QPixmap getIcon(); + bool isShowIcon(); + QSize getIconSize(); + bool isShowIconSeparator(); + int getIconSeparatorWidth(); + QPixmap getCloseButtonIcon(); + bool isShowCloseButton(); + QSize getCloseButtonIconSize(); + int getCloseButtonWidth(); + int getCloseButtonHeight(); + QSize getCloseButtonSize(); + ButtonAlignment getCloseButtonAlignment(); + int getFadeInDuration(); + int getFadeOutDuration(); + bool isResetDurationOnHover(); + bool isStayOnTop(); + int getBorderRadius(); + QColor getBackgroundColor(); + QColor getTitleColor(); + QColor getTextColor(); + QColor getIconColor(); + QColor getIconSeparatorColor(); + QColor getCloseButtonIconColor(); + QColor getDurationBarColor(); + QFont getTitleFont(); + QFont getTextFont(); + QMargins getMargins(); + QMargins getIconMargins(); + QMargins getIconSectionMargins(); + QMargins getTextSectionMargins(); + QMargins getCloseButtonMargins(); + int getTextSectionSpacing(); + + static void setMaximumOnScreen(int maximum); + static void setSpacing(int spacing); + static void setOffset(int x, int y); + static void setOffsetX(int offsetX); + static void setOffsetY(int offsetY); + static void setAlwaysOnMainScreen(bool enabled); + static void setFixedScreen(QScreen* screen); + static void setPosition(Position position); + static void reset(); + void setDuration(int duration); + void setShowDurationBar(bool enabled); + void setTitle(QString title); + void setText(QString text); + void setIcon(QPixmap icon); + void setIcon(Icon icon); + void setShowIcon(bool enabled); + void setIconSize(QSize size); + void setShowIconSeparator(bool enabled); + void setIconSeparatorWidth(int width); + void setCloseButtonIcon(QPixmap icon); + void setCloseButtonIcon(Icon icon); + void setShowCloseButton(bool enabled); + void setCloseButtonIconSize(QSize size); + void setCloseButtonSize(QSize size); + void setCloseButtonWidth(int width); + void setCloseButtonHeight(int height); + void setCloseButtonAlignment(ButtonAlignment alignment); + void setFadeInDuration(int duration); + void setFadeOutDuration(int duration); + void setResetDurationOnHover(bool enabled); + void setStayOnTop(bool enabled); + void setBorderRadius(int borderRadius); + void setBackgroundColor(QColor color); + void setTitleColor(QColor color); + void setTextColor(QColor color); + void setIconColor(QColor color); + void setIconSeparatorColor(QColor color); + void setCloseButtonIconColor(QColor color); + void setDurationBarColor(QColor color); + void setTitleFont(QFont font); + void setTextFont(QFont font); + void setMargins(QMargins margins); + void setMarginLeft(int margin); + void setMarginTop(int margin); + void setMarginRight(int margin); + void setMarginBottom(int margin); + void setIconMargins(QMargins margins); + void setIconMarginLeft(int margin); + void setIconMarginTop(int margin); + void setIconMarginRight(int margin); + void setIconMarginBottom(int margin); + void setIconSectionMargins(QMargins margins); + void setIconSectionMarginLeft(int margin); + void setIconSectionMarginTop(int margin); + void setIconSectionMarginRight(int margin); + void setIconSectionMarginBottom(int margin); + void setTextSectionMargins(QMargins margins); + void setTextSectionMarginLeft(int margin); + void setTextSectionMarginTop(int margin); + void setTextSectionMarginRight(int margin); + void setTextSectionMarginBottom(int margin); + void setCloseButtonMargins(QMargins margins); + void setCloseButtonMarginLeft(int margin); + void setCloseButtonMarginTop(int margin); + void setCloseButtonMarginRight(int margin); + void setCloseButtonMarginBottom(int margin); + void setTextSectionSpacing(int spacing); + void setFixedSize(QSize size); + void setFixedSize(int width, int height); + void setFixedWidth(int width); + void setFixedHeight(int height); + void applyPreset(Preset preset); + + +public Q_SLOTS: + void show(); + void hide(); + +Q_SIGNALS: + void closed(); + +protected: +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + using EnterEvent = QEnterEvent; +#else + using EnterEvent = QEvent; +#endif + void enterEvent(EnterEvent* event) override; + void leaveEvent(QEvent* event) override; + +private Q_SLOTS: + void hide_(); + void fadeOut(); + void updateDurationBar(); + void deleteAndShowNextInQueue(); + +private: + static int s_maximumOnScreen; + static int s_spacing; + static int s_offsetX; + static int s_offsetY; + static bool s_alwaysOnMainScreen; + static QScreen* s_fixedScreen; + static Position s_position; + static std::deque s_currentlyShown; + static std::deque s_queue; + int m_duration; + bool m_showDurationBar; + QString m_title; + QString m_text; + QPixmap m_icon; + bool m_showIcon; + QSize m_iconSize; + bool m_showIconSeparator; + int m_iconSeparatorWidth; + QPixmap m_closeButtonIcon; + bool m_showCloseButton; + QSize m_closeButtonIconSize; + QSize m_closeButtonSize; + ButtonAlignment m_closeButtonAlignment; + int m_fadeInDuration; + int m_fadeOutDuration; + bool m_resetDurationOnHover; + bool m_stayOnTop; + int m_borderRadius; + QColor m_backgroundColor; + QColor m_titleColor; + QColor m_textColor; + QColor m_iconColor; + QColor m_iconSeparatorColor; + QColor m_closeButtonIconColor; + QColor m_durationBarColor; + QFont m_titleFont; + QFont m_textFont; + QMargins m_margins; + QMargins m_iconMargins; + QMargins m_iconSectionMargins; + QMargins m_textSectionMargins; + QMargins m_closeButtonMargins; + int m_textSectionSpacing; + int m_elapsedTime; + bool m_fadingOut; + bool m_used; + QWidget* m_parent; + QLabel* m_notification; + QWidget* m_dropShadowLayer1; + QWidget* m_dropShadowLayer2; + QWidget* m_dropShadowLayer3; + QWidget* m_dropShadowLayer4; + QWidget* m_dropShadowLayer5; + QGraphicsOpacityEffect* m_opacityEffect; + QPushButton* m_closeButton; + QLabel* m_titleLabel; + QLabel* m_textLabel; + QPushButton* m_iconWidget; + QWidget* m_iconSeparator; + QWidget* m_durationBarContainer; + QWidget* m_durationBar; + QWidget* m_durationBarChunk; + QTimer* m_durationTimer; + QTimer* m_durationBarTimer; + + void setupUI(); + void updatePositionXY(); + void updatePositionX(); + void updatePositionY(); + void updateStylesheet(); + QPoint calculatePosition(); + Toast* getPredecessorToast(); + static QImage recolorImage(QImage image, QColor color); + static QPixmap getIconFromEnum(Icon enumIcon); + static void updateCurrentlyShowingPositionXY(); + static void updateCurrentlyShowingPositionX(); + static void updateCurrentlyShowingPositionY(); + static void showNextInQueue(); + + static const int sc_updatePositionDuration; + static const int sc_durationBarUpdateInterval; + static const int sc_dropShadowSize; + static const QColor sc_successAccentColor; + static const QColor sc_warningAccentColor; + static const QColor sc_errorAccentColor; + static const QColor sc_informationAccentColor; + static const QColor sc_defaultAccentColor; + static const QColor sc_defaultBackgroundColor; + static const QColor sc_defaultTitleColor; + static const QColor sc_defaultTextColor; + static const QColor sc_defaultIconSeparatorColor; + static const QColor sc_defaultCloseButtonIconColor; + static const QColor sc_defaultBackgroundColorDark; + static const QColor sc_defaultTitleColorDark; + static const QColor sc_defaultTextColorDark; + static const QColor sc_defaultIconSeparatorColorDark; + static const QColor sc_defaultCloseButtonIconColorDark; +}; diff --git a/core/src/ToolButton.cpp b/core/src/ToolButton.cpp index 823e11312..c8c5aba2e 100644 --- a/core/src/ToolButton.cpp +++ b/core/src/ToolButton.cpp @@ -1,7 +1,7 @@ /* * ToolButton.cpp - implementation of Veyon-tool-button * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,17 +22,10 @@ * */ -#include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include +#include #include "ToolButton.h" @@ -45,19 +38,24 @@ ToolButton::ToolButton( const QIcon& icon, const QString& altLabel, const QString& description, const QKeySequence& shortcut ) : - m_pixelRatio( 1 ), m_icon( icon ), - m_pixmap(), - m_mouseOver( false ), m_label( label ), m_altLabel( altLabel ), m_descr( description ) { setShortcut( shortcut ); - setAttribute( Qt::WA_NoSystemBackground, true ); + setIcon(icon); + setText(label); + setAutoRaise(true); + setToolButtonStyle(Qt::ToolButtonStyle::ToolButtonTextUnderIcon); - updateSize(); + if (m_altLabel.length() > 0) + { + connect (this, &ToolButton::toggled, this, [this](bool checked) { + setText(checked ? m_altLabel : m_label); + }); + } } @@ -68,7 +66,7 @@ void ToolButton::setIconOnlyMode( QWidget* mainWindow, bool enabled ) const auto toolButtons = mainWindow->findChildren(); for( auto toolButton : toolButtons ) { - toolButton->updateSize(); + toolButton->setToolButtonStyle(enabled ? Qt::ToolButtonIconOnly : Qt::ToolButtonTextUnderIcon); } } @@ -82,52 +80,15 @@ void ToolButton::addTo( QToolBar* toolBar ) - +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +void ToolButton::enterEvent( QEnterEvent* event ) +#else void ToolButton::enterEvent( QEvent* event ) +#endif { - m_mouseOver = true; - if( !s_toolTipsDisabled && !m_label.isEmpty() && !m_descr.isEmpty() ) + if (!s_toolTipsDisabled && !m_descr.isEmpty()) { - auto toolTipPos = mapToGlobal( QPoint( 0, 0 ) ); -#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) - const auto screenRect = QGuiApplication::screenAt( toolTipPos )->availableGeometry(); -#else - int screenNumber = QApplication::desktop()->isVirtualDesktop() ? - QApplication::desktop()->screenNumber( toolTipPos ) : - QApplication::desktop()->screenNumber( this ); - const auto screenRect = QApplication::desktop()->screenGeometry( screenNumber ); -#endif - - auto toolTip = new ToolButtonTip( m_icon.pixmap( 128, 128 ), m_label, m_descr, nullptr, this ); - connect( this, &ToolButton::mouseLeftButton, toolTip, &QWidget::close ); - - if( toolTipPos.x() + toolTip->width() > screenRect.x() + screenRect.width() ) - { - toolTipPos.rx() -= 4; - } - if( toolTipPos.y() + toolTip->height() > screenRect.y() + screenRect.height() ) - { - toolTipPos.ry() -= 30 + toolTip->height(); - } - if( toolTipPos.y() < screenRect.y() ) - { - toolTipPos.setY( screenRect.y() ); - } - if( toolTipPos.x() + toolTip->width() > screenRect.x() + screenRect.width() ) - { - toolTipPos.setX( screenRect.x() + screenRect.width() - toolTip->width() ); - } - if( toolTipPos.x() < screenRect.x() ) - { - toolTipPos.setX( screenRect.x() ); - } - if( toolTipPos.y() + toolTip->height() > screenRect.y() + screenRect.height() ) - { - toolTipPos.setY( screenRect.y() + screenRect.height() - toolTip->height() ); - } - - toolTip->move( toolTipPos += QPoint( -4, height() ) ); - toolTip->show(); + QToolTip::showText(mapToGlobal(QPoint(width() / 2, height())), m_descr, this); } QToolButton::enterEvent( event ); @@ -135,10 +96,9 @@ void ToolButton::enterEvent( QEvent* event ) - void ToolButton::leaveEvent( QEvent* event ) { - if( checkForLeaveEvent() ) + if (checkForLeaveEvent()) { QToolButton::leaveEvent( event ); } @@ -146,84 +106,22 @@ void ToolButton::leaveEvent( QEvent* event ) - void ToolButton::mousePressEvent( QMouseEvent* event ) { - emit mouseLeftButton(); + QToolTip::hideText(); QToolButton::mousePressEvent( event ); } - -void ToolButton::paintEvent( QPaintEvent* ) +QSize ToolButton::sizeHint() const { - const bool active = isDown() || isChecked(); - - QPainter painter(this); - painter.setRenderHint(QPainter::SmoothPixmapTransform); - painter.setRenderHint(QPainter::Antialiasing); - painter.setPen(Qt::NoPen); - - QLinearGradient outlinebrush(0, 0, 0, height()); - QLinearGradient brush(0, 0, 0, height()); - - brush.setSpread(QLinearGradient::PadSpread); - QColor highlight(255, 255, 255, 70); - QColor shadow(0, 0, 0, 70); - QColor sunken(220, 220, 220, 30); - QColor normal1(255, 255, 245, 60); - QColor normal2(255, 255, 235, 10); - - if( active ) - { - outlinebrush.setColorAt( 0.0, shadow ); - outlinebrush.setColorAt( 1.0, highlight ); - brush.setColorAt( 0.0, sunken ); - painter.setPen(Qt::NoPen); - } - else - { - outlinebrush.setColorAt( 1.0, shadow ); - outlinebrush.setColorAt( 0.0, highlight ); - brush.setColorAt( 0.0, normal1 ); - if( m_mouseOver == false ) - { - brush.setColorAt( 1.0, normal2 ); - } - painter.setPen(QPen(outlinebrush, 1)); - } - - painter.setBrush(brush); - - painter.drawRoundedRect( rect(), roundness(), roundness() ); - - const int delta = active ? 1 : 0; - QPoint pixmapPos( ( width() - m_pixmap.width() ) / 2 + delta, margin() / 2 + delta ); - if( s_iconOnlyMode ) - { - pixmapPos.setY( ( height() - m_pixmap.height() ) / 2 - 1 + delta ); - } - painter.drawPixmap( pixmapPos, m_pixmap ); - - if( s_iconOnlyMode == false ) - { - const auto label = ( active && m_altLabel.isEmpty() == false ) ? m_altLabel : m_label; - const int labelX = 1 + ( width() - painter.fontMetrics().width( label ) ) / 2; - const int deltaNormal = delta - 1; - const int deltaShadow = deltaNormal + 1; - - painter.setPen( Qt::black ); - painter.drawText( labelX + deltaShadow, height() - margin() / 2 + deltaShadow, label ); - - painter.setPen( Qt::white ); - painter.drawText( labelX + deltaNormal, height() - margin() / 2 + deltaNormal, label ); - } + const auto sh = QToolButton::sizeHint(); + return QSize(std::max(sh.height() * 1.3, sh.width()), sh.height()); } - bool ToolButton::checkForLeaveEvent() { if( QRect( mapToGlobal( QPoint( 0, 0 ) ), size() ). @@ -233,178 +131,9 @@ bool ToolButton::checkForLeaveEvent() } else { - emit mouseLeftButton(); - m_mouseOver = false; - + QToolTip::hideText(); return true; } - return false; -} - - - -void ToolButton::updateSize() -{ - auto f = QApplication::font(); - f.setPointSizeF( qMax( 7.5, f.pointSizeF() * 0.9 ) ); - setFont( f ); - - m_pixelRatio = fontInfo().pixelSize() / fontInfo().pointSizeF(); - - const auto metrics = fontMetrics(); - - m_pixmap = m_icon.pixmap( static_cast( iconSize() ) ); - - if( s_iconOnlyMode ) - { - setFixedSize( margin() + iconSize(), margin() + iconSize() ); - } - else - { - const int textWidth = ( qMax( metrics.width( m_label ), metrics.width( m_altLabel ) ) / stepSize() + 1 ) * stepSize(); - const int width = qMax( textWidth, iconSize() * 3 / 2 ); - const int height = iconSize() + fontInfo().pixelSize(); - setFixedSize( width + margin(), height + margin() ); - } -} - - - - - - - -ToolButtonTip::ToolButtonTip( const QIcon& icon, const QString &title, - const QString & _description, - QWidget * _parent, QWidget * _tool_btn ) : - QWidget( _parent, Qt::ToolTip ), - m_pixelRatio( fontInfo().pixelSize() / fontInfo().pointSizeF() ), - m_pixmap( icon.pixmap( static_cast( 64 * m_pixelRatio ) ) ), - m_title( title ), - m_description( _description ), - m_toolButton( _tool_btn ) -{ - setAttribute( Qt::WA_DeleteOnClose, true ); - setAttribute( Qt::WA_NoSystemBackground, true ); - - QTimer::singleShot( 0, this, [this]() { resize( sizeHint() ); } ); - - updateMask(); -} - - - - -QSize ToolButtonTip::sizeHint() const -{ - auto f = font(); - f.setBold( true ); - - const auto titleWidth = QFontMetrics( f ).width( m_title ); - const auto descriptionRect = fontMetrics().boundingRect( QRect( 0, 0, 250, 100 ), Qt::TextWordWrap, m_description ); - - return { margin() + m_pixmap.width() + margin() + qMax( titleWidth, descriptionRect.width() ) + margin(), - margin() + qMax( m_pixmap.height(), fontMetrics().height() + margin() + descriptionRect.height() ) + margin() }; -} - - - - -void ToolButtonTip::paintEvent( QPaintEvent* ) -{ - QPainter p( this ); - p.drawImage( 0, 0, m_bg ); -} - - - - -void ToolButtonTip::resizeEvent( QResizeEvent * _re ) -{ - const QColor color_frame = QColor( 48, 48, 48 ); - m_bg = QImage( size(), QImage::Format_ARGB32 ); - m_bg.fill( color_frame.rgba() ); - QPainter p( &m_bg ); - p.setRenderHint( QPainter::Antialiasing ); - QPen pen( color_frame ); - pen.setWidthF( 1.5 ); - p.setPen( pen ); - QLinearGradient grad( 0, 0, 0, height() ); - const QColor color_top = palette().color( QPalette::Active, - QPalette::Window ).light( 120 ); - grad.setColorAt( 0, color_top ); - grad.setColorAt( 1, palette().color( QPalette::Active, - QPalette::Window ). - light( 80 ) ); - p.setBrush( grad ); - p.drawRoundRect( 0, 0, width() - 1, height() - 1, - ROUNDED / width(), ROUNDED / height() ); - if( m_toolButton ) - { - QPoint pt = m_toolButton->mapToGlobal( QPoint( 0, 0 ) ); - p.setPen( color_top ); - p.setBrush( color_top ); - p.setRenderHint( QPainter::Antialiasing, false ); - p.drawLine( pt.x() - x(), 0, - pt.x() + m_toolButton->width() - x() - 2, 0 ); - const int dx = pt.x() - x(); - p.setRenderHint( QPainter::Antialiasing, true ); - if( dx < 10 && dx >= 0 ) - { - p.setPen( pen ); - p.drawImage( dx+1, 0, m_bg.copy( 20, 0, 10-dx, 10 ) ); - p.drawImage( dx, 0, m_bg.copy( 0, 10, 1, 10-dx*2 ) ); - } - } - p.setPen( Qt::black ); - - p.drawPixmap( margin(), margin(), m_pixmap ); - QFont f = p.font(); - f.setBold( true ); - p.setFont( f ); - const auto titleX = margin() + m_pixmap.width() + margin(); - const auto titleY = margin() + fontMetrics().height() - 2; - p.drawText( titleX, titleY, m_title ); - - f.setBold( false ); - p.setFont( f ); - p.drawText( QRect( titleX, - titleY + margin(), - width() - margin() - titleX, - height() - margin() - titleY ), - Qt::TextWordWrap, m_description ); - - updateMask(); - QWidget::resizeEvent( _re ); -} - - - - -void ToolButtonTip::updateMask() -{ - // as this widget has not a rectangular shape AND is a top - // level widget (which doesn't allow painting only particular - // regions), we have to set a mask for it - QBitmap b( size() ); - b.clear(); - - QPainter p( &b ); - p.setBrush( Qt::color1 ); - p.setPen( Qt::color1 ); - p.drawRoundRect( 0, 0, width() - 1, height() - 1, - ROUNDED / width(), ROUNDED / height() ); - - if( m_toolButton ) - { - QPoint pt = m_toolButton->mapToGlobal( QPoint( 0, 0 ) ); - const int dx = pt.x()-x(); - if( dx < 10 && dx >= 0 ) - { - p.fillRect( dx, 0, 10, 10, Qt::color1 ); - } - } - - setMask( b ); + return false; } diff --git a/core/include/ToolButton.h b/core/src/ToolButton.h similarity index 60% rename from core/include/ToolButton.h rename to core/src/ToolButton.h index a7b4ccce7..0dc29b59b 100644 --- a/core/include/ToolButton.h +++ b/core/src/ToolButton.h @@ -1,7 +1,7 @@ /* * ToolButton.h - declaration of class ToolButton * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -60,93 +60,28 @@ class VEYON_CORE_EXPORT ToolButton : public QToolButton return s_toolTipsDisabled; } - void addTo( QToolBar * ); - + void addTo(QToolBar* toolBar); protected: - void enterEvent( QEvent * _e ) override; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + void enterEvent( QEnterEvent* event ) override; +#else + void enterEvent( QEvent* event ) override; +#endif void leaveEvent( QEvent * _e ) override; void mousePressEvent( QMouseEvent * _me ) override; - void paintEvent( QPaintEvent * _pe ) override; - - -signals: - void mouseLeftButton(); - + QSize sizeHint() const override; private: bool checkForLeaveEvent(); - void updateSize(); - static bool s_toolTipsDisabled; static bool s_iconOnlyMode; - int iconSize() const - { - return static_cast( 32 * m_pixelRatio ); - } - - int margin() const - { - return static_cast( 8 * m_pixelRatio ); - } - - int roundness() const - { - return static_cast( 3 * m_pixelRatio ); - } - - int stepSize() const - { - return static_cast( 8 * m_pixelRatio ); - } - - qreal m_pixelRatio; QIcon m_icon; - QPixmap m_pixmap; - bool m_mouseOver; QString m_label; QString m_altLabel; QString m_descr; } ; - - - -class ToolButtonTip : public QWidget -{ - Q_OBJECT -public: - ToolButtonTip( const QIcon& icon, const QString& title, const QString& description, - QWidget* parent, QWidget* toolButton = nullptr ); - - QSize sizeHint( void ) const override; - - -protected: - void paintEvent( QPaintEvent * _pe ) override; - void resizeEvent( QResizeEvent * _re ) override; - - -private: - void updateMask( void ); - - int margin() const - { - return static_cast( 8 * m_pixelRatio ); - } - - const int ROUNDED = 2000; - - qreal m_pixelRatio; - QPixmap m_pixmap; - QString m_title; - QString m_description; - - QImage m_bg; - - QWidget* m_toolButton; - -} ; diff --git a/core/src/TranslationLoader.cpp b/core/src/TranslationLoader.cpp new file mode 100644 index 000000000..51262502f --- /dev/null +++ b/core/src/TranslationLoader.cpp @@ -0,0 +1,82 @@ +/* + * TranslationLoader.cpp - implementation of TranslationLoader class + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include + +#include "TranslationLoader.h" +#include "VeyonConfiguration.h" +#include "VeyonCore.h" + + +TranslationLoader::TranslationLoader( const QString& resourceName ) +{ + load( resourceName ); +} + + + +bool TranslationLoader::load( const QString& resourceName ) +{ + QLocale configuredLocale( QLocale::C ); + + static const QRegularExpression configuredLocaleRX{QStringLiteral( "[^(]*\\(([^)]*)\\)")}; + const auto configuredLocaleMatch = configuredLocaleRX.match(VeyonCore::config().uiLanguage()); + if( configuredLocaleMatch.hasMatch() ) + { + configuredLocale = QLocale( configuredLocaleMatch.captured( 1 ) ); + } + + if( configuredLocale.language() != QLocale::English && + VeyonCore::instance()->findChild( resourceName ) == nullptr ) + { + const auto translationsDirectory = resourceName.startsWith( QLatin1String("qt") ) + ? VeyonCore::qtTranslationsDirectory() + : VeyonCore::translationsDirectory(); + + auto translator = new QTranslator( VeyonCore::instance() ); + translator->setObjectName( resourceName ); + + if( configuredLocale == QLocale::C || + translator->load( QStringLiteral( "%1_%2.qm" ).arg( resourceName, configuredLocale.name() ), + translationsDirectory ) == false ) + { + configuredLocale = QLocale::system(); // Flawfinder: ignore + + if( translator->load( QStringLiteral( "%1_%2.qm" ).arg( resourceName, configuredLocale.name() ), + translationsDirectory ) == false ) + { + delete translator; + return false; + } + } + + QLocale::setDefault( configuredLocale ); + + QCoreApplication::installTranslator( translator ); + } + + return true; +} diff --git a/master/src/RecursiveFilterProxyModel.h b/core/src/TranslationLoader.h similarity index 72% rename from master/src/RecursiveFilterProxyModel.h rename to core/src/TranslationLoader.h index 7825862f1..97d81eb5b 100644 --- a/master/src/RecursiveFilterProxyModel.h +++ b/core/src/TranslationLoader.h @@ -1,7 +1,7 @@ /* - * RecursiveFilterProxyModel.h - proxy model for recursive filtering + * TranslationLoader.h - declaration of TranslationLoader class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2020-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,11 +24,15 @@ #pragma once -#include "krecursivefilterproxymodel.h" +#include -class RecursiveFilterProxyModel : public KRecursiveFilterProxyModel +#include "VeyonCore.h" + +class VEYON_CORE_EXPORT TranslationLoader { public: - explicit RecursiveFilterProxyModel( QObject* parent ); + TranslationLoader( const QString& resourceName ); + + static bool load( const QString& resourceName ); }; diff --git a/core/include/UserGroupsBackendInterface.h b/core/src/UserGroupsBackendInterface.h similarity index 96% rename from core/include/UserGroupsBackendInterface.h rename to core/src/UserGroupsBackendInterface.h index 7452ac20f..fbb961fbb 100644 --- a/core/include/UserGroupsBackendInterface.h +++ b/core/src/UserGroupsBackendInterface.h @@ -1,7 +1,7 @@ /* * UserGroupsBackendInterface.h - interface for a UserGroupsBackend * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/core/src/UserGroupsBackendManager.cpp b/core/src/UserGroupsBackendManager.cpp index 7f97e3a1d..b0f90d092 100644 --- a/core/src/UserGroupsBackendManager.cpp +++ b/core/src/UserGroupsBackendManager.cpp @@ -1,7 +1,7 @@ /* * UserGroupsBackendManager.cpp - implementation of UserGroupsBackendManager * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -28,12 +28,9 @@ UserGroupsBackendManager::UserGroupsBackendManager( QObject* parent ) : - QObject( parent ), - m_backends(), - m_defaultBackend( nullptr ), - m_accessControlBackend( nullptr ) + QObject( parent ) { - for( auto pluginObject : qAsConst( VeyonCore::pluginManager().pluginObjects() ) ) + for( auto pluginObject : std::as_const( VeyonCore::pluginManager().pluginObjects() ) ) { auto pluginInterface = qobject_cast( pluginObject ); auto userGroupsBackendInterface = qobject_cast( pluginObject ); @@ -73,24 +70,24 @@ QMap UserGroupsBackendManager::availableBackends() -UserGroupsBackendInterface* UserGroupsBackendManager::accessControlBackend() +UserGroupsBackendInterface* UserGroupsBackendManager::configuredBackend() { - if( m_accessControlBackend == nullptr ) + if (m_configuredBackend == nullptr) { reloadConfiguration(); } - return m_accessControlBackend; + return m_configuredBackend; } void UserGroupsBackendManager::reloadConfiguration() { - m_accessControlBackend = m_backends.value( VeyonCore::config().accessControlUserGroupsBackend() ); + m_configuredBackend = m_backends.value(VeyonCore::config().userGroupsBackend()); - if( m_accessControlBackend == nullptr ) + if( m_configuredBackend == nullptr ) { - m_accessControlBackend = m_defaultBackend; + m_configuredBackend = m_defaultBackend; } } diff --git a/core/include/UserGroupsBackendManager.h b/core/src/UserGroupsBackendManager.h similarity index 75% rename from core/include/UserGroupsBackendManager.h rename to core/src/UserGroupsBackendManager.h index 832bb3515..b2185f045 100644 --- a/core/include/UserGroupsBackendManager.h +++ b/core/src/UserGroupsBackendManager.h @@ -1,7 +1,7 @@ /* * UserGroupsBackendManager.h - header file for UserGroupsBackendManager * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -30,17 +30,24 @@ class VEYON_CORE_EXPORT UserGroupsBackendManager : public QObject { Q_OBJECT public: + using Backends = QMap; + explicit UserGroupsBackendManager( QObject* parent = nullptr ); + const Backends& backends() const + { + return m_backends; + } + QMap availableBackends(); - UserGroupsBackendInterface* accessControlBackend(); + UserGroupsBackendInterface* configuredBackend(); void reloadConfiguration(); private: - QMap m_backends; - UserGroupsBackendInterface* m_defaultBackend; - UserGroupsBackendInterface* m_accessControlBackend; + Backends m_backends{}; + UserGroupsBackendInterface* m_defaultBackend{nullptr}; + UserGroupsBackendInterface* m_configuredBackend{nullptr}; }; diff --git a/core/src/UserSessionControl.cpp b/core/src/UserSessionControl.cpp deleted file mode 100644 index a4c156383..000000000 --- a/core/src/UserSessionControl.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - * UserSessionControl.cpp - implementation of UserSessionControl class - * - * Copyright (c) 2017-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#include -#include -#include -#include - -#include "UserSessionControl.h" -#include "FeatureWorkerManager.h" -#include "VeyonCore.h" -#include "VeyonConfiguration.h" -#include "VeyonMasterInterface.h" -#include "VeyonServerInterface.h" -#include "PlatformUserFunctions.h" - - -UserSessionControl::UserSessionControl( QObject* parent ) : - QObject( parent ), - m_userSessionInfoFeature( Feature( QStringLiteral( "UserSessionInfo" ), - Feature::Session | Feature::Service | Feature::Worker | Feature::Builtin, - Feature::Uid( "79a5e74d-50bd-4aab-8012-0e70dc08cc72" ), - Feature::Uid(), - tr( "User session control" ), {}, {} ) ), - m_userLogoffFeature( QStringLiteral( "UserLogoff" ), - Feature::Action | Feature::Master | Feature::Service, - Feature::Uid( "7311d43d-ab53-439e-a03a-8cb25f7ed526" ), - Feature::Uid(), - tr( "Log off" ), {}, - tr( "Click this button to log off users from all computers." ), - QStringLiteral( ":/core/system-suspend-hibernate.png" ) ), - m_features( { m_userSessionInfoFeature, m_userLogoffFeature } ) -{ -} - - - -bool UserSessionControl::getUserSessionInfo( const ComputerControlInterfaceList& computerControlInterfaces ) -{ - return sendFeatureMessage( FeatureMessage( m_userSessionInfoFeature.uid(), GetInfo ), - computerControlInterfaces, false ); -} - - - -bool UserSessionControl::startFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) -{ - Q_UNUSED(master); - - if( confirmFeatureExecution( feature, master.mainWindow() ) == false ) - { - return false; - } - - if( feature == m_userLogoffFeature ) - { - return sendFeatureMessage( FeatureMessage( m_userLogoffFeature.uid(), FeatureMessage::DefaultCommand ), - computerControlInterfaces ); - } - - return false; -} - - - -bool UserSessionControl::handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) -{ - Q_UNUSED(master); - - if( message.featureUid() == m_userSessionInfoFeature.uid() ) - { - computerControlInterface->setUserLoginName( message.argument( UserLoginName ).toString() ); - computerControlInterface->setUserFullName( message.argument( UserFullName ).toString() ); - - return true; - } - - return false; -} - - - -bool UserSessionControl::handleFeatureMessage( VeyonServerInterface& server, - const MessageContext& messageContext, - const FeatureMessage& message ) -{ - if( m_userSessionInfoFeature.uid() == message.featureUid() ) - { - FeatureMessage reply( message.featureUid(), message.command() ); - - m_userDataLock.lockForRead(); - if( m_userLoginName.isEmpty() ) - { - queryUserInformation(); - reply.addArgument( UserLoginName, QString() ); - reply.addArgument( UserFullName, QString() ); - } - else - { - reply.addArgument( UserLoginName, m_userLoginName ); - reply.addArgument( UserFullName, m_userFullName ); - } - m_userDataLock.unlock(); - - return server.sendFeatureMessageReply( messageContext, reply ); - } - else if( m_userLogoffFeature.uid() == message.featureUid() ) - { - VeyonCore::platform().userFunctions().logoff(); - return true; - } - - return false; -} - - - -void UserSessionControl::queryUserInformation() -{ - // asynchronously query information about logged on user (which might block - // due to domain controller queries and timeouts etc.) - QtConcurrent::run( [=]() { - const auto userLoginName = VeyonCore::platform().userFunctions().currentUser(); - const auto userFullName = VeyonCore::platform().userFunctions().fullName( userLoginName ); - m_userDataLock.lockForWrite(); - m_userLoginName = userLoginName; - m_userFullName = userFullName; - m_userDataLock.unlock(); - } ); -} - - - -bool UserSessionControl::confirmFeatureExecution( const Feature& feature, QWidget* parent ) -{ - if( VeyonCore::config().confirmUnsafeActions() == false ) - { - return true; - } - - if( feature == m_userLogoffFeature ) - { - return QMessageBox::question( parent, tr( "Confirm user logoff" ), - tr( "Do you really want to log off the selected users?" ) ) == - QMessageBox::Yes; - } - - return false; -} diff --git a/core/src/VariantArrayMessage.cpp b/core/src/VariantArrayMessage.cpp index 95074892c..d52b9e86d 100644 --- a/core/src/VariantArrayMessage.cpp +++ b/core/src/VariantArrayMessage.cpp @@ -1,7 +1,7 @@ /* * VariantArrayMessage.cpp - class for sending/receiving a variant array as message * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -29,7 +29,6 @@ VariantArrayMessage::VariantArrayMessage( QIODevice* ioDevice ) : - m_buffer(), m_stream( &m_buffer ), m_ioDevice( ioDevice ) { @@ -73,21 +72,21 @@ bool VariantArrayMessage::receive() if( m_ioDevice->read( reinterpret_cast( &messageSize ), sizeof(messageSize) ) != sizeof(messageSize) ) // Flawfinder: ignore { - vWarning() << "could not read message size!"; + vDebug() << "could not read message size!"; return false; } messageSize = qFromBigEndian(messageSize); if( messageSize > MaxMessageSize ) { - vCritical() << "invalid message size" << messageSize; + vDebug() << "invalid message size" << messageSize; return false; } const auto data = m_ioDevice->read( messageSize ); // Flawfinder: ignore if( data.size() != static_cast( messageSize ) ) { - vWarning() << "could not read message data!"; + vDebug() << "could not read message data!"; return false; } diff --git a/core/include/VariantArrayMessage.h b/core/src/VariantArrayMessage.h similarity index 91% rename from core/include/VariantArrayMessage.h rename to core/src/VariantArrayMessage.h index 483ea57d7..257fb0e99 100644 --- a/core/include/VariantArrayMessage.h +++ b/core/src/VariantArrayMessage.h @@ -1,7 +1,7 @@ /* * VariantArrayMessage.h - class for sending/receiving a variant array as message * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -46,6 +46,11 @@ class VEYON_CORE_EXPORT VariantArrayMessage QVariant read(); // Flawfinder: ignore + bool atEnd() const + { + return m_buffer.atEnd(); + } + VariantArrayMessage& write( const QVariant& v ); QIODevice* ioDevice() const @@ -58,7 +63,7 @@ class VEYON_CORE_EXPORT VariantArrayMessage MaxMessageSize = 1024*1024*32 }; - QBuffer m_buffer; + QBuffer m_buffer{}; VariantStream m_stream; QIODevice* m_ioDevice; diff --git a/core/src/VariantStream.cpp b/core/src/VariantStream.cpp index 6f96f2340..6e4f05df7 100644 --- a/core/src/VariantStream.cpp +++ b/core/src/VariantStream.cpp @@ -1,7 +1,7 @@ /* * VariantStream.cpp - read/write QVariant objects to/from QIODevice * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,6 +22,10 @@ * */ +#include +#include +#include + #include "VariantStream.h" VariantStream::VariantStream( QIODevice* ioDevice ) : @@ -35,6 +39,16 @@ VariantStream::VariantStream( QIODevice* ioDevice ) : QVariant VariantStream::read() // Flawfinder: ignore { QVariant v; + + m_dataStream.startTransaction(); + const auto isValid = checkVariant(0); + m_dataStream.rollbackTransaction(); + + if (isValid == false) + { + return {}; + } + m_dataStream >> v; if( v.isValid() == false || v.isNull() ) @@ -51,3 +65,215 @@ void VariantStream::write( const QVariant& v ) { m_dataStream << v; } + + + +bool VariantStream::checkBool() +{ + bool b; + m_dataStream >> b; + return m_dataStream.status() == QDataStream::Status::Ok; +} + + + +bool VariantStream::checkByteArray() +{ + const auto pos = m_dataStream.device()->pos(); + + quint32 len; + m_dataStream >> len; + + // null array? + if (len == 0xffffffff) + { + return true; + } + + if (len > MaxByteArraySize) + { + vDebug() << "byte array too big"; + return false; + } + + m_dataStream.device()->seek(pos); + + QByteArray s; + m_dataStream >> s; + + return m_dataStream.status() == QDataStream::Status::Ok; +} + + + +bool VariantStream::checkInt() +{ + int i; + m_dataStream >> i; + return m_dataStream.status() == QDataStream::Status::Ok; +} + + + +bool VariantStream::checkLong() +{ + qlonglong i; + m_dataStream >> i; + return m_dataStream.status() == QDataStream::Status::Ok; +} + + + +bool VariantStream::checkRect() +{ + qint32 i; + m_dataStream >> i >> i >> i >> i; + return m_dataStream.status() == QDataStream::Status::Ok; +} + + + +bool VariantStream::checkString() +{ + const auto pos = m_dataStream.device()->pos(); + + quint32 len; + m_dataStream >> len; + + // null string? + if (len == 0xffffffff) + { + return true; + } + + if (len > MaxStringSize) + { + vDebug() << "string too long"; + return false; + } + + m_dataStream.device()->seek(pos); + + QString s; + m_dataStream >> s; + + return m_dataStream.status() == QDataStream::Status::Ok; +} + + + +bool VariantStream::checkStringList() +{ + quint32 n; + m_dataStream >> n; + + if (n > MaxContainerSize) + { + vDebug() << "QStringList has too many elements"; + return false; + } + + for (quint32 i = 0; i < n; ++i) + { + if (checkString() == false) + { + return false; + } + } + + return m_dataStream.status() == QDataStream::Status::Ok; +} + + + +bool VariantStream::checkUuid() +{ + QUuid uuid; + m_dataStream >> uuid; + return m_dataStream.status() == QDataStream::Status::Ok; +} + + + +bool VariantStream::checkVariant(int depth) +{ + if (depth > MaxCheckRecursionDepth) + { + vDebug() << "max recursion depth reached"; + return false; + } + + quint32 typeId = 0; + m_dataStream >> typeId; + + quint8 isNull = false; + m_dataStream >> isNull; + + switch(typeId) + { + case QMetaType::Bool: return checkBool(); + case QMetaType::QByteArray: return checkByteArray(); + case QMetaType::Int: return checkInt(); + case QMetaType::LongLong: return checkLong(); + case QMetaType::QRect: return checkRect(); + case QMetaType::QString: return checkString(); + case QMetaType::QStringList: return checkStringList(); + case QMetaType::QUuid: return checkUuid(); + case QMetaType::QVariantList: return checkVariantList(depth); + case QMetaType::QVariantMap: return checkVariantMap(depth); + default: + vDebug() << "invalid type" << typeId; + return false; + } + + return m_dataStream.status() == QDataStream::Status::Ok; +} + + + +bool VariantStream::checkVariantList(int depth) +{ + quint32 n; + m_dataStream >> n; + + if (n > MaxContainerSize) + { + vDebug() << "QVariantList has too many elements"; + return false; + } + + for (quint32 i = 0; i < n; ++i) + { + if (checkVariant(depth+1) == false) + { + return false; + } + } + + return m_dataStream.status() == QDataStream::Status::Ok; +} + + + +bool VariantStream::checkVariantMap(int depth) +{ + quint32 n; + m_dataStream >> n; + + if (n > MaxContainerSize) + { + vDebug() << "QVariantMap has too many elements"; + return false; + } + + for (quint32 i = 0; i < n; ++i) + { + if (checkString() == false || + checkVariant(depth+1) == false) + { + return false; + } + } + + return m_dataStream.status() == QDataStream::Status::Ok; +} diff --git a/core/include/VariantStream.h b/core/src/VariantStream.h similarity index 68% rename from core/include/VariantStream.h rename to core/src/VariantStream.h index 4beb61d67..c8a3132fa 100644 --- a/core/include/VariantStream.h +++ b/core/src/VariantStream.h @@ -1,7 +1,7 @@ /* * VariantStream.h - read/write QVariant objects to/from QIODevice * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,6 +31,11 @@ class VEYON_CORE_EXPORT VariantStream { public: + static constexpr auto MaxByteArraySize = 16*1024*1024; + static constexpr auto MaxStringSize = 64*1024; + static constexpr auto MaxContainerSize = 1024; + static constexpr auto MaxCheckRecursionDepth = 3; + explicit VariantStream( QIODevice* ioDevice ); QVariant read(); // Flawfinder: ignore @@ -38,6 +43,18 @@ class VEYON_CORE_EXPORT VariantStream void write( const QVariant& v ); private: + bool checkBool(); + bool checkByteArray(); + bool checkInt(); + bool checkLong(); + bool checkRect(); + bool checkString(); + bool checkStringList(); + bool checkUuid(); + bool checkVariant(int depth); + bool checkVariantList(int depth); + bool checkVariantMap(int depth); + QDataStream m_dataStream; } ; diff --git a/core/src/VeyonConfiguration.cpp b/core/src/VeyonConfiguration.cpp index 0c347b45a..0bda60748 100644 --- a/core/src/VeyonConfiguration.cpp +++ b/core/src/VeyonConfiguration.cpp @@ -2,7 +2,7 @@ * VeyonConfiguration.cpp - a Configuration object storing system wide * configuration values * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -32,8 +32,8 @@ VeyonConfiguration::VeyonConfiguration() : - Configuration::Object( Configuration::Store::LocalBackend, - Configuration::Store::System ) + Configuration::Object(Configuration::Store::Backend::Local, + Configuration::Store::Scope::System) { } @@ -59,4 +59,27 @@ void VeyonConfiguration::upgrade() setApplicationVersion( VeyonCore::ApplicationVersion::Version_4_2 ); } + else if( applicationVersion() < VeyonCore::ApplicationVersion::Version_4_5 ) + { + setVeyonServerPort( legacyPrimaryServicePort() ); + setHideLocalComputer( legacyLocalComputerHidden() ); + setHideComputerFilter( legacyComputerFilterHidden() ); + setAutoAdjustMonitoringIconSize( legacyAutoAdjustGridSize() ); + + setApplicationVersion( VeyonCore::ApplicationVersion::Version_4_5 ); + } + else if (applicationVersion() < VeyonCore::ApplicationVersion::Version_4_7) + { + setApplicationVersion(VeyonCore::ApplicationVersion::Version_4_7); + } + else if (applicationVersion() < VeyonCore::ApplicationVersion::Version_4_8) + { + setApplicationVersion(VeyonCore::ApplicationVersion::Version_4_8); + } + else if (applicationVersion() < VeyonCore::ApplicationVersion::Version_4_9) + { + setUserGroupsBackend(legacyAccessControlUserGroupsBackend()); + setUseDomainUserGroups(legacyDomainGroupsForAccessControlEnabled()); + setApplicationVersion(VeyonCore::ApplicationVersion::Version_4_9); + } } diff --git a/core/include/VeyonConfiguration.h b/core/src/VeyonConfiguration.h similarity index 94% rename from core/include/VeyonConfiguration.h rename to core/src/VeyonConfiguration.h index 084bc8b9f..23d22093f 100644 --- a/core/include/VeyonConfiguration.h +++ b/core/src/VeyonConfiguration.h @@ -2,7 +2,7 @@ * VeyonConfiguration.h - a Configuration object storing system wide * configuration values * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,7 +25,6 @@ #pragma once -#include "VeyonCore.h" #include "Configuration/Object.h" #include "Configuration/Property.h" diff --git a/core/src/VeyonConfigurationProperties.h b/core/src/VeyonConfigurationProperties.h new file mode 100644 index 000000000..b5623b45b --- /dev/null +++ b/core/src/VeyonConfigurationProperties.h @@ -0,0 +1,192 @@ +/* + * VeyonConfigurationProperties.h - definition of every configuration property + * stored in global veyon configuration + * + * Copyright (c) 2016-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING) if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include +#include +#include +#include + +#include "ComputerListModel.h" +#include "Computer.h" +#include "Logger.h" +#include "NetworkObjectDirectory.h" +#include "PlatformSessionFunctions.h" +#include "VncConnectionConfiguration.h" + +#define FOREACH_VEYON_CORE_CONFIG_PROPERTIES(OP) \ + OP( VeyonConfiguration, VeyonCore::config(), VeyonCore::ApplicationVersion, applicationVersion, setApplicationVersion, "ApplicationVersion", "Core", QVariant::fromValue(VeyonCore::ApplicationVersion::Version_4_0), Configuration::Property::Flag::Hidden ) \ + OP( VeyonConfiguration, VeyonCore::config(), QJsonObject, pluginVersions, setPluginVersions, "PluginVersions", "Core", QJsonObject(), Configuration::Property::Flag::Hidden ) \ + OP( VeyonConfiguration, VeyonCore::config(), QString, installationID, setInstallationID, "InstallationID", "Core", QString(), Configuration::Property::Flag::Hidden ) \ + OP(VeyonConfiguration, VeyonCore::config(), int, computerStatePollingInterval, setComputerStatePollingInterval, "ComputerStatePollingInterval", "Core", -1, Configuration::Property::Flag::Hidden) \ + +#define FOREACH_VEYON_VNC_CONNECTION_CONFIG_PROPERTIES(OP) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, useCustomVncConnectionSettings, setUseCustomVncConnectionSettings, "UseCustomSettings", "VncConnection", false, Configuration::Property::Flag::Hidden ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, vncConnectionThreadTerminationTimeout, setVncConnectionThreadTerminationTimeout, "ThreadTerminationTimeout", "VncConnection", VncConnectionConfiguration::DefaultThreadTerminationTimeout, Configuration::Property::Flag::Hidden ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, vncConnectionConnectTimeout, setVncConnectionConnectTimeout, "ConnectTimeout", "VncConnection", VncConnectionConfiguration::DefaultConnectTimeout, Configuration::Property::Flag::Hidden ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, vncConnectionReadTimeout, setVncConnectionReadTimeout, "ReadTimeout", "VncConnection", VncConnectionConfiguration::DefaultReadTimeout, Configuration::Property::Flag::Hidden ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, vncConnectionRetryInterval, setVncConnectionRetryInterval, "ConnectionRetryInterval", "VncConnection", VncConnectionConfiguration::DefaultConnectionRetryInterval, Configuration::Property::Flag::Hidden ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, vncConnectionMessageWaitTimeout, setVncConnectionMessageWaitTimeout, "MessageWaitTimeout", "VncConnection", VncConnectionConfiguration::DefaultMessageWaitTimeout, Configuration::Property::Flag::Hidden ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, vncConnectionFastFramebufferUpdateInterval, setVncConnectionFastFramebufferUpdateInterval, "FastFramebufferUpdateInterval", "VncConnection", VncConnectionConfiguration::DefaultFastFramebufferUpdateInterval, Configuration::Property::Flag::Hidden ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, vncConnectionInitialFramebufferUpdateTimeout, setVncConnectionInitialFramebufferUpdateTimeout, "InitialFramebufferUpdateTimeout", "VncConnection", VncConnectionConfiguration::DefaultInitialFramebufferUpdateTimeout, Configuration::Property::Flag::Hidden ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, vncConnectionFramebufferUpdateTimeout, setVncConnectionFramebufferUpdateTimeout, "FramebufferUpdateTimeout", "VncConnection", VncConnectionConfiguration::DefaultFramebufferUpdateTimeout, Configuration::Property::Flag::Hidden ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, vncConnectionSocketKeepaliveIdleTime, setVncConnectionSocketKeepaliveIdleTime, "SocketKeepaliveIdleTime", "VncConnection", VncConnectionConfiguration::DefaultSocketKeepaliveIdleTime, Configuration::Property::Flag::Hidden ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, vncConnectionSocketKeepaliveInterval, setVncConnectionSocketKeepaliveInterval, "SocketKeepaliveInterval", "VncConnection", VncConnectionConfiguration::DefaultSocketKeepaliveInterval, Configuration::Property::Flag::Hidden ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, vncConnectionSocketKeepaliveCount, setVncConnectionSocketKeepaliveCount, "SocketKeepaliveCount", "VncConnection", VncConnectionConfiguration::DefaultSocketKeepaliveCount, Configuration::Property::Flag::Hidden ) \ + +#define FOREACH_VEYON_UI_CONFIG_PROPERTY(OP) \ + OP( VeyonConfiguration, VeyonCore::config(), QString, applicationName, setApplicationName, "ApplicationName", "UI", QStringLiteral("Veyon"), Configuration::Property::Flag::Hidden ) \ + OP( VeyonConfiguration, VeyonCore::config(), QString, uiLanguage, setUiLanguage, "Language", "UI", QString(), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), VeyonCore::UiStyle, uiStyle, setUiStyle, "Style", "UI", QVariant::fromValue(VeyonCore::UiStyle::Fusion), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), VeyonCore::UiColorScheme, uiColorScheme, setUiColorScheme, "ColorScheme", "UI", QVariant::fromValue(VeyonCore::UiColorScheme::System), Configuration::Property::Flag::Standard ) + +#define FOREACH_VEYON_SERVICE_CONFIG_PROPERTY(OP) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, isTrayIconHidden, setTrayIconHidden, "HideTrayIcon", "Service", false, Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, failedAuthenticationNotificationsEnabled, setFailedAuthenticationNotificationsEnabled, "FailedAuthenticationNotifications", "Service", true, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, remoteConnectionNotificationsEnabled, setRemoteConnectionNotificationsEnabled, "RemoteConnectionNotifications", "Service", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, activeSessionModeEnabled, setActiveSessionModeEnabled, "ActiveSession", "Service", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, multiSessionModeEnabled, setMultiSessionModeEnabled, "MultiSession", "Service", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, maximumSessionCount, setMaximumSessionCount, "MaximumSessionCount", "Service", 100, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, autostartService, setServiceAutostart, "Autostart", "Service", true, Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, clipboardSynchronizationDisabled, setClipboardSynchronizationDisabled, "ClipboardSynchronizationDisabled", "Service", false, Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), PlatformSessionFunctions::SessionMetaDataContent, sessionMetaDataContent, setSessionMetaDataContent, "SessionMetaDataContent", "Service", QVariant::fromValue(PlatformSessionFunctions::SessionMetaDataContent::None), Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), QString, sessionMetaDataEnvironmentVariable, setSessionMetaDataEnvironmentVariable, "SessionMetaDataEnvironmentVariable", "Service", QString(), Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), QString, sessionMetaDataRegistryKey, setSessionMetaDataRegistryKey, "SessionMetaDataRegistryKey", "Service", QString(), Configuration::Property::Flag::Advanced ) \ + +#define FOREACH_VEYON_NETWORK_OBJECT_DIRECTORY_CONFIG_PROPERTY(OP) \ + OP( VeyonConfiguration, VeyonCore::config(), QStringList, enabledNetworkObjectDirectoryPlugins, setEnabledNetworkObjectDirectoryPlugins, "EnabledPlugins", "NetworkObjectDirectory", QStringList(), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, networkObjectDirectoryUpdateInterval, setNetworkObjectDirectoryUpdateInterval, "UpdateInterval", "NetworkObjectDirectory", NetworkObjectDirectory::DefaultUpdateInterval, Configuration::Property::Flag::Standard ) \ + +#define FOREACH_VEYON_USER_GROUPS_BACKEND_CONFIG_PROPERTY(OP) \ + OP( VeyonConfiguration, VeyonCore::config(), QUuid, userGroupsBackend, setUserGroupsBackend, "Backend", "UserGroups", QUuid(), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, useDomainUserGroups, setUseDomainUserGroups, "UseDomainUserGroups", "UserGroups", false, Configuration::Property::Flag::Standard ) \ + +#define FOREACH_VEYON_FEATURES_CONFIG_PROPERTY(OP) \ + OP( VeyonConfiguration, VeyonCore::config(), QStringList, disabledFeatures, setDisabledFeatures, "DisabledFeatures", "Features", QStringList(), Configuration::Property::Flag::Standard ) \ + +#define FOREACH_VEYON_LOGGING_CONFIG_PROPERTY(OP) \ + OP( VeyonConfiguration, VeyonCore::config(), Logger::LogLevel, logLevel, setLogLevel, "LogLevel", "Logging", QVariant::fromValue(Logger::LogLevel::Default), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, logFileSizeLimitEnabled, setLogFileSizeLimitEnabled, "LogFileSizeLimitEnabled", "Logging", false, Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, logFileRotationEnabled, setLogFileRotationEnabled, "LogFileRotationEnabled", "Logging", false, Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, logToStdErr, setLogToStdErr, "LogToStdErr", "Logging", true, Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, logToSystem, setLogToSystem, "LogToSystem", "Logging", false, Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, logFileSizeLimit, setLogFileSizeLimit, "LogFileSizeLimit", "Logging", Logger::DefaultFileSizeLimit, Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, logFileRotationCount, setLogFileRotationCount, "LogFileRotationCount", "Logging", Logger::DefaultFileRotationCount, Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), QString, logFileDirectory, setLogFileDirectory, "LogFileDirectory", "Logging", QLatin1String(Logger::DefaultLogFileDirectory), Configuration::Property::Flag::Standard ) \ + +#define FOREACH_VEYON_TLS_CONFIG_PROPERTY(OP) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, tlsUseCertificateAuthority, setTlsUseCertificateAuthority, "UseCertificateAuthority", "TLS", false, Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), QString, tlsCaCertificateFile, setTlsCaCertificateFile, "CaCertificateFile", "TLS", QStringLiteral("%GLOBALAPPDATA%/tls/ca.pem"), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), QString, tlsHostCertificateFile, setTlsHostCertificateFile, "HostCertificateFile", "TLS", QStringLiteral("%GLOBALAPPDATA%/tls/%HOSTNAME%/cert.pem"), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), QString, tlsHostPrivateKeyFile, setTlsHostPrivateKeyFile, "HostPrivateKeyFile", "TLS", QStringLiteral("%GLOBALAPPDATA%/tls/%HOSTNAME%/private.key"), Configuration::Property::Flag::Standard ) \ + +#define FOREACH_VEYON_VNC_SERVER_CONFIG_PROPERTY(OP) \ + OP( VeyonConfiguration, VeyonCore::config(), QUuid, vncServerPlugin, setVncServerPlugin, "Plugin", "VncServer", QUuid(), Configuration::Property::Flag::Standard ) \ + +#define FOREACH_VEYON_NETWORK_CONFIG_PROPERTY(OP) \ + OP( VeyonConfiguration, VeyonCore::config(), int, veyonServerPort, setVeyonServerPort, "VeyonServerPort", "Network", 11100, Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, vncServerPort, setVncServerPort, "VncServerPort", "Network", 11200, Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, featureWorkerManagerPort, setFeatureWorkerManagerPort, "FeatureWorkerManagerPort", "Network", 11300, Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, demoServerPort, setDemoServerPort, "DemoServerPort", "Network", 11400, Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, isFirewallExceptionEnabled, setFirewallExceptionEnabled, "FirewallExceptionEnabled", "Network", true, Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, localConnectOnly, setLocalConnectOnly, "LocalConnectOnly", "Network", false, Configuration::Property::Flag::Advanced ) \ + +#define FOREACH_VEYON_DIRECTORIES_CONFIG_PROPERTY(OP) \ + OP( VeyonConfiguration, VeyonCore::config(), QString, configurationTemplatesDirectory, setConfigurationTemplatesDirectory, "ConfigurationTemplates", "Directories", QDir::toNativeSeparators(QStringLiteral("%GLOBALAPPDATA%/Config/Templates")), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), QString, userConfigurationDirectory, setUserConfigurationDirectory, "UserConfiguration", "Directories", QDir::toNativeSeparators( QStringLiteral( "%APPDATA%/Config" ) ), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), QString, screenshotDirectory, setScreenshotDirectory, "Screenshots", "Directories", QDir::toNativeSeparators( QStringLiteral( "%APPDATA%/Screenshots" ) ), Configuration::Property::Flag::Standard ) \ + +#define FOREACH_VEYON_MASTER_CONFIG_PROPERTY(OP) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, modernUserInterface, setModernUserInterface, "ModernUserInterface", "Master", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), VncConnectionConfiguration::Quality, computerMonitoringImageQuality, setComputerMonitoringImageQuality, "ComputerMonitoringImageQuality", "Master", QVariant::fromValue(VncConnectionConfiguration::Quality::Medium), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), VncConnectionConfiguration::Quality, remoteAccessImageQuality, setRemoteAccessImageQuality, "RemoteAccessImageQuality", "Master", QVariant::fromValue(VncConnectionConfiguration::Quality::Highest), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, computerMonitoringUpdateInterval, setComputerMonitoringUpdateInterval, "ComputerMonitoringUpdateInterval", "Master", 1000, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, computerMonitoringThumbnailSpacing, setComputerMonitoringThumbnailSpacing, "ComputerMonitoringThumbnailSpacing", "Master", 5, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), ComputerListModel::DisplayRoleContent, computerDisplayRoleContent, setComputerDisplayRoleContent, "ComputerDisplayRoleContent", "Master", QVariant::fromValue(ComputerListModel::DisplayRoleContent::UserAndComputerName), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), ComputerListModel::UidRoleContent, computerUidRoleContent, setComputerUidRoleContent, "ComputerUidRoleContent", "Master", QVariant::fromValue(ComputerListModel::UidRoleContent::NetworkObjectUid), Configuration::Property::Flag::Advanced) \ + OP( VeyonConfiguration, VeyonCore::config(), ComputerListModel::SortOrder, computerMonitoringSortOrder, setComputerMonitoringSortOrder, "ComputerMonitoringSortOrder", "Master", QVariant::fromValue(ComputerListModel::SortOrder::ComputerAndUserName), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), ComputerListModel::AspectRatio, computerMonitoringAspectRatio, setComputerMonitoringAspectRatio, "ComputerMonitoringAspectRatio", "Master", QVariant::fromValue(ComputerListModel::AspectRatio::Auto), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), QColor, computerMonitoringBackgroundColor, setComputerMonitoringBackgroundColor, "ComputerMonitoringBackgroundColor", "Master", QColor(Qt::white), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), QColor, computerMonitoringTextColor, setComputerMonitoringTextColor, "ComputerMonitoringTextColor", "Master", QColor(Qt::black), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, accessControlForMasterEnabled, setAccessControlForMasterEnabled, "AccessControlForMasterEnabled", "Master", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, autoAdjustMonitoringIconSize, setAutoAdjustMonitoringIconSize, "AutoAdjustMonitoringIconSize", "Master", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, autoSelectCurrentLocation, setAutoSelectCurrentLocation, "AutoSelectCurrentLocation", "Master", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, showCurrentLocationOnly, setShowCurrentLocationOnly, "ShowCurrentLocationOnly", "Master", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, allowAddingHiddenLocations, setAllowAddingHiddenLocations, "AllowAddingHiddenLocations", "Master", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, expandLocations, setExpandLocations, "ExpandLocations", "Master", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, hideLocalComputer, setHideLocalComputer, "HideLocalComputer", "Master", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, hideOwnSession, setHideOwnSession, "HideOwnSession", "Master", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, hideEmptyLocations, setHideEmptyLocations, "HideEmptyLocations", "Master", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, hideComputerFilter, setHideComputerFilter, "HideComputerFilter", "Master", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), QUuid, computerDoubleClickFeature, setComputerDoubleClickFeature, "ComputerDoubleClickFeature", "Master", QUuid(QStringLiteral("a18e545b-1321-4d4e-ac34-adc421c6e9c8")), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, enforceSelectedModeForClients, setEnforceSelectedModeForClients, "EnforceSelectedModeForClients", "Master", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, autoOpenComputerSelectPanel, setAutoOpenComputerSelectPanel, "AutoOpenComputerSelectPanel", "Master", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, confirmUnsafeActions, setConfirmUnsafeActions, "ConfirmUnsafeActions", "Master", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, showFeatureWindowsOnSameScreen, setShowFeatureWindowsOnSameScreen, "ShowFeatureWindowsOnSameScreen", "Master", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), Computer::NameSource, computerNameSource, setComputerNameSource, "ComputerNameSource", "Master", QVariant::fromValue(Computer::NameSource::Default), Configuration::Property::Flag::Advanced ) \ + +#define FOREACH_VEYON_AUTHENTICATION_CONFIG_PROPERTY(OP) \ + OP( VeyonConfiguration, VeyonCore::config(), QStringList, enabledAuthenticationPlugins, setEnabledAuthenticationPlugins, "EnabledPlugins", "Authentication", QStringList(), Configuration::Property::Flag::Standard ) \ + +#define FOREACH_VEYON_ACCESS_CONTROL_CONFIG_PROPERTY(OP) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, isAccessRestrictedToUserGroups, setAccessRestrictedToUserGroups, "AccessRestrictedToUserGroups", "AccessControl", false , Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, isAccessControlRulesProcessingEnabled, setAccessControlRulesProcessingEnabled, "AccessControlRulesProcessingEnabled", "AccessControl", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), QStringList, authorizedUserGroups, setAuthorizedUserGroups, "AuthorizedUserGroups", "AccessControl", QStringList(), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), QJsonArray, accessControlRules, setAccessControlRules, "AccessControlRules", "AccessControl", QJsonArray(), Configuration::Property::Flag::Standard ) \ + +#define FOREACH_VEYON_LEGACY_CONFIG_PROPERTY(OP) \ + OP( VeyonConfiguration, VeyonCore::config(), QUuid, legacyAccessControlUserGroupsBackend, setLegacyAccessControlUserGroupsBackend, "UserGroupsBackend", "AccessControl", QUuid(), Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, legacyDomainGroupsForAccessControlEnabled, setLegacyDomainGroupsForAccessControlEnabled, "DomainGroupsEnabled", "AccessControl", false, Configuration::Property::Flag::Standard ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, legacyAutoAdjustGridSize, setLegacyAutoAdjustGridSize, "AutoAdjustGridSize", "Master", false, Configuration::Property::Flag::Legacy ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, legacyOpenComputerManagementAtStart, setLegacyOpenComputerManagementAtStart, "OpenComputerManagementAtStart", "Master", false, Configuration::Property::Flag::Legacy ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, legacyAutoSwitchToCurrentRoom, setLegacyAutoSwitchToCurrentRoom, "AutoSwitchToCurrentRoom", "Master", false, Configuration::Property::Flag::Legacy ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, legacyOnlyCurrentRoomVisible, setLegacyOnlyCurrentRoomVisible, "OnlyCurrentRoomVisible", "Master", false, Configuration::Property::Flag::Legacy ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, legacyManualRoomAdditionAllowed, setLegacyManualRoomAdditionAllowed, "ManualRoomAdditionAllowed", "Master", false, Configuration::Property::Flag::Legacy ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, legacyEmptyRoomsHidden, setLegacyEmptyRoomsHidden, "EmptyRoomsHidden", "Master", false, Configuration::Property::Flag::Legacy ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, legacyConfirmDangerousActions, setLegacyConfirmDangerousActions, "ConfirmDangerousActions", "Master", false, Configuration::Property::Flag::Legacy ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, legacyIsSoftwareSASEnabled, setLegacySoftwareSASEnabled, "SoftwareSASEnabled", "Service", true, Configuration::Property::Flag::Legacy ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, legacyLocalComputerHidden, setLegacyLocalComputerHidden, "LocalComputerHidden", "Master", false, Configuration::Property::Flag::Legacy ) \ + OP( VeyonConfiguration, VeyonCore::config(), bool, legacyComputerFilterHidden, setLegacyComputerFilterHidden, "ComputerFilterHidden", "Master", false, Configuration::Property::Flag::Legacy ) \ + OP( VeyonConfiguration, VeyonCore::config(), int, legacyPrimaryServicePort, setLegacyPrimaryServicePort, "PrimaryServicePort", "Network", 11100, Configuration::Property::Flag::Legacy ) \ + OP( VeyonConfiguration, VeyonCore::config(), QUuid, legacyNetworkObjectDirectoryPlugin, setLegacyNetworkObjectDirectoryPlugin, "Plugin", "NetworkObjectDirectory", QUuid(), Configuration::Property::Flag::Legacy ) \ + +#define FOREACH_VEYON_CONFIG_PROPERTY(OP) \ + FOREACH_VEYON_CORE_CONFIG_PROPERTIES(OP) \ + FOREACH_VEYON_VNC_CONNECTION_CONFIG_PROPERTIES(OP) \ + FOREACH_VEYON_UI_CONFIG_PROPERTY(OP) \ + FOREACH_VEYON_SERVICE_CONFIG_PROPERTY(OP) \ + FOREACH_VEYON_LOGGING_CONFIG_PROPERTY(OP) \ + FOREACH_VEYON_TLS_CONFIG_PROPERTY(OP) \ + FOREACH_VEYON_NETWORK_OBJECT_DIRECTORY_CONFIG_PROPERTY(OP)\ + FOREACH_VEYON_USER_GROUPS_BACKEND_CONFIG_PROPERTY(OP) \ + FOREACH_VEYON_FEATURES_CONFIG_PROPERTY(OP)\ + FOREACH_VEYON_VNC_SERVER_CONFIG_PROPERTY(OP) \ + FOREACH_VEYON_NETWORK_CONFIG_PROPERTY(OP) \ + FOREACH_VEYON_DIRECTORIES_CONFIG_PROPERTY(OP) \ + FOREACH_VEYON_MASTER_CONFIG_PROPERTY(OP) \ + FOREACH_VEYON_AUTHENTICATION_CONFIG_PROPERTY(OP) \ + FOREACH_VEYON_ACCESS_CONTROL_CONFIG_PROPERTY(OP) \ + FOREACH_VEYON_LEGACY_CONFIG_PROPERTY(OP) diff --git a/core/src/VeyonConnection.cpp b/core/src/VeyonConnection.cpp index 74ed62f17..6db1aa893 100644 --- a/core/src/VeyonConnection.cpp +++ b/core/src/VeyonConnection.cpp @@ -1,7 +1,7 @@ /* * VeyonConnection.cpp - implementation of VeyonConnection * - * Copyright (c) 2008-2019 Tobias Junghans + * Copyright (c) 2008-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,8 +24,7 @@ #include "rfb/rfbclient.h" -#include "AuthenticationCredentials.h" -#include "CryptoCore.h" +#include "AuthenticationManager.h" #include "PlatformUserFunctions.h" #include "SocketDevice.h" #include "VariantArrayMessage.h" @@ -35,7 +34,7 @@ static rfbClientProtocolExtension* __veyonProtocolExt = nullptr; -static const uint32_t __veyonSecurityTypes[2] = { rfbSecTypeVeyon, 0 }; +static constexpr std::array __veyonSecurityTypes = { VeyonCore::RfbSecurityTypeVeyon, 0 }; rfbBool handleVeyonMessage( rfbClient* client, rfbServerToClientMsg* msg ) @@ -43,7 +42,7 @@ rfbBool handleVeyonMessage( rfbClient* client, rfbServerToClientMsg* msg ) auto connection = reinterpret_cast( VncConnection::clientData( client, VeyonConnection::VeyonConnectionTag ) ); if( connection ) { - return connection->handleServerMessage( client, msg->type ); + return connection->handleServerMessage( client, msg->type ) ? TRUE : FALSE; } return false; @@ -51,11 +50,7 @@ rfbBool handleVeyonMessage( rfbClient* client, rfbServerToClientMsg* msg ) -VeyonConnection::VeyonConnection( VncConnection* vncConnection ): - m_vncConnection( vncConnection ), - m_veyonAuthType( RfbVeyonAuth::Logon ), - m_user(), - m_userHomeDir() +VeyonConnection::VeyonConnection() { if( __veyonProtocolExt == nullptr ) { @@ -63,38 +58,45 @@ VeyonConnection::VeyonConnection( VncConnection* vncConnection ): __veyonProtocolExt->encodings = nullptr; __veyonProtocolExt->handleEncoding = nullptr; __veyonProtocolExt->handleMessage = handleVeyonMessage; - __veyonProtocolExt->securityTypes = __veyonSecurityTypes; + __veyonProtocolExt->securityTypes = __veyonSecurityTypes.data(); __veyonProtocolExt->handleAuthentication = handleSecTypeVeyon; rfbClientRegisterExtension( __veyonProtocolExt ); } - if( VeyonCore::config().authenticationMethod() == VeyonCore::AuthenticationMethod::KeyFileAuthentication ) - { - m_veyonAuthType = RfbVeyonAuth::KeyFile; - } - connect( m_vncConnection, &VncConnection::connectionPrepared, this, &VeyonConnection::registerConnection, Qt::DirectConnection ); + connect( m_vncConnection, &VncConnection::destroyed, VeyonCore::instance(), [this]() { + delete this; + } ); } VeyonConnection::~VeyonConnection() { - unregisterConnection(); } -void VeyonConnection::sendFeatureMessage( const FeatureMessage& featureMessage, bool wake ) +void VeyonConnection::stopAndDeleteLater() { - if( m_vncConnection.isNull() ) + unregisterConnection(); + + if( m_vncConnection ) { - vCritical() << "cannot enqueue event as VNC connection is invalid"; - return; + m_vncConnection->stopAndDeleteLater(); + m_vncConnection = nullptr; } +} + - m_vncConnection->enqueueEvent( new VncFeatureMessageEvent( featureMessage ), wake ); + +void VeyonConnection::sendFeatureMessage(const FeatureMessage& featureMessage) +{ + if( m_vncConnection ) + { + m_vncConnection->enqueueEvent(new VncFeatureMessageEvent(featureMessage)); + } } @@ -112,18 +114,16 @@ bool VeyonConnection::handleServerMessage( rfbClient* client, uint8_t msg ) return false; } - vDebug() << "received feature message" << featureMessage.command() - << "with arguments" << featureMessage.arguments(); + vDebug() << qUtf8Printable(QStringLiteral("%1:%2").arg(QString::fromUtf8(client->serverHost)).arg(client->serverPort)) + << featureMessage; - emit featureMessageReceived( featureMessage ); + Q_EMIT featureMessageReceived( featureMessage ); return true; } - else - { - vCritical() << "unknown message type" << static_cast( msg ) - << "from server. Closing connection. Will re-open it later."; - } + + vCritical() << "unknown message type" << int( msg ) + << "from server. Closing connection. Will re-open it later."; return false; } @@ -132,7 +132,7 @@ bool VeyonConnection::handleServerMessage( rfbClient* client, uint8_t msg ) void VeyonConnection::registerConnection() { - if( m_vncConnection.isNull() == false ) + if( m_vncConnection ) { m_vncConnection->setClientData( VeyonConnectionTag, this ); } @@ -142,7 +142,7 @@ void VeyonConnection::registerConnection() void VeyonConnection::unregisterConnection() { - if( m_vncConnection.isNull() == false ) + if( m_vncConnection ) { m_vncConnection->setClientData( VeyonConnectionTag, nullptr ); } @@ -152,7 +152,7 @@ void VeyonConnection::unregisterConnection() int8_t VeyonConnection::handleSecTypeVeyon( rfbClient* client, uint32_t authScheme ) { - if( authScheme != rfbSecTypeVeyon ) + if( authScheme != VeyonCore::RfbSecurityTypeVeyon ) { return false; } @@ -167,132 +167,86 @@ int8_t VeyonConnection::handleSecTypeVeyon( rfbClient* client, uint32_t authSche SocketDevice socketDevice( VncConnection::libvncClientDispatcher, client ); VariantArrayMessage message( &socketDevice ); - message.receive(); + if( message.receive() == false ) + { + vDebug() << QThread::currentThreadId() << "invalid authentication message received"; + return false; + } + + const auto authTypeCount = message.read().toInt(); - int authTypeCount = message.read().toInt(); + if( authTypeCount == 0 ) + { + vDebug() << QThread::currentThreadId() << "no auth types received"; + return false; + } - QList authTypes; + auto legacyAuth = false; + PluginUidList authTypes; authTypes.reserve( authTypeCount ); for( int i = 0; i < authTypeCount; ++i ) { - authTypes.append( QVariantHelper::value( message.read() ) ); + if( message.atEnd() ) + { + vDebug() << QThread::currentThreadId() << "less auth types received than announced"; + return false; + } + const auto authType = message.read(); + if( authType.userType() == QMetaType::QUuid ) + { + authTypes.append( authType.toUuid() ); + } + const auto legacyAuthType = VeyonCore::authenticationManager().fromLegacyAuthType( + authType.value() ); + if( legacyAuthType.isNull() == false ) + { + authTypes.append( legacyAuthType ); + legacyAuth = true; + } } vDebug() << QThread::currentThreadId() << "received authentication types:" << authTypes; - RfbVeyonAuth::Type chosenAuthType = RfbVeyonAuth::Token; - if( authTypes.count() > 0 ) - { - chosenAuthType = authTypes.first(); - - // look whether the VncConnection recommends a specific - // authentication type (e.g. VeyonAuthHostBased when running as - // demo client) + auto chosenAuthPlugin = Plugin::Uid(); - for( auto authType : authTypes ) + const auto& plugins = VeyonCore::authenticationManager().plugins(); + for( auto it = plugins.constBegin(), end = plugins.constEnd(); it != end; ++it ) + { + if( authTypes.contains( it.key() ) && it.value()->hasCredentials() ) { - if( connection->veyonAuthType() == authType ) - { - chosenAuthType = authType; - } + chosenAuthPlugin = it.key(); } } - vDebug() << QThread::currentThreadId() << "chose authentication type:" << authTypes; + if( chosenAuthPlugin.isNull() ) + { + vWarning() << QThread::currentThreadId() << "authentication plugins not supported " + "or missing credentials"; + return false; + } VariantArrayMessage authReplyMessage( &socketDevice ); - authReplyMessage.write( chosenAuthType ); - - // send username which is used when displaying an access confirm dialog - if( VeyonCore::authenticationCredentials().hasCredentials( AuthenticationCredentials::Type::UserLogon ) ) + if( legacyAuth ) { - authReplyMessage.write( VeyonCore::authenticationCredentials().logonUsername() ); + const auto legacyAuthType = VeyonCore::authenticationManager().toLegacyAuthType( chosenAuthPlugin ); + vDebug() << QThread::currentThreadId() << "chose legacy authentication type:" << legacyAuthType; + authReplyMessage.write( legacyAuthType ); } else { - authReplyMessage.write( VeyonCore::platform().userFunctions().currentUser() ); + vDebug() << QThread::currentThreadId() << "chose authentication method:" << chosenAuthPlugin; + authReplyMessage.write( chosenAuthPlugin ); } - + // send username which is used when displaying an access confirm dialog + authReplyMessage.write( VeyonCore::platform().userFunctions().currentUser() ); authReplyMessage.send(); VariantArrayMessage authAckMessage( &socketDevice ); authAckMessage.receive(); - switch( chosenAuthType ) - { - case RfbVeyonAuth::KeyFile: - if( VeyonCore::authenticationCredentials().hasCredentials( AuthenticationCredentials::Type::PrivateKey ) ) - { - VariantArrayMessage challengeReceiveMessage( &socketDevice ); - challengeReceiveMessage.receive(); - const auto challenge = challengeReceiveMessage.read().toByteArray(); - - if( challenge.size() != CryptoCore::ChallengeSize ) - { - vCritical() << QThread::currentThreadId() << "challenge size mismatch!"; - return false; - } - - // create local copy of private key so we can modify it within our own thread - auto key = VeyonCore::authenticationCredentials().privateKey(); - if( key.isNull() || key.canSign() == false ) - { - vCritical() << QThread::currentThreadId() << "invalid private key!"; - return false; - } - - const auto signature = key.signMessage( challenge, CryptoCore::DefaultSignatureAlgorithm ); - - VariantArrayMessage challengeResponseMessage( &socketDevice ); - challengeResponseMessage.write( VeyonCore::instance()->authenticationKeyName() ); - challengeResponseMessage.write( signature ); - challengeResponseMessage.send(); - } - break; - - case RfbVeyonAuth::Logon: - { - VariantArrayMessage publicKeyMessage( &socketDevice ); - publicKeyMessage.receive(); - - CryptoCore::PublicKey publicKey = CryptoCore::PublicKey::fromPEM( publicKeyMessage.read().toString() ); - - if( publicKey.canEncrypt() == false ) - { - vCritical() << QThread::currentThreadId() << "can't encrypt with given public key!"; - return false; - } - - CryptoCore::SecureArray plainTextPassword( VeyonCore::authenticationCredentials().logonPassword().toUtf8() ); - CryptoCore::SecureArray encryptedPassword = publicKey.encrypt( plainTextPassword, CryptoCore::DefaultEncryptionAlgorithm ); - if( encryptedPassword.isEmpty() ) - { - vCritical() << QThread::currentThreadId() << "password encryption failed!"; - return false; - } - - VariantArrayMessage passwordResponse( &socketDevice ); - passwordResponse.write( encryptedPassword.toByteArray() ); - passwordResponse.send(); - break; - } - - case RfbVeyonAuth::Token: - { - VariantArrayMessage tokenAuthMessage( &socketDevice ); - tokenAuthMessage.write( VeyonCore::authenticationCredentials().token() ); - tokenAuthMessage.send(); - break; - } - - default: - // nothing to do - we just get accepted - break; - } - - return true; + return plugins[chosenAuthPlugin]->authenticate( &socketDevice ) ? TRUE : FALSE; } diff --git a/core/include/VeyonConnection.h b/core/src/VeyonConnection.h similarity index 72% rename from core/include/VeyonConnection.h rename to core/src/VeyonConnection.h index cca738bb1..d71eaaadd 100644 --- a/core/include/VeyonConnection.h +++ b/core/src/VeyonConnection.h @@ -1,7 +1,7 @@ /* * VeyonConnection.h - declaration of class VeyonConnection * - * Copyright (c) 2008-2019 Tobias Junghans + * Copyright (c) 2008-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,7 +26,6 @@ #include -#include "RfbVeyonAuth.h" #include "VncConnection.h" @@ -36,8 +35,14 @@ class VEYON_CORE_EXPORT VeyonConnection : public QObject { Q_OBJECT public: - explicit VeyonConnection( VncConnection* vncConnection ); - ~VeyonConnection() override; + using Instances = struct { + QMutex mutex; + QHash connections; + }; + + VeyonConnection(); + + void stopAndDeleteLater(); VncConnection* vncConnection() { @@ -54,37 +59,19 @@ class VEYON_CORE_EXPORT VeyonConnection : public QObject return m_vncConnection && m_vncConnection->isConnected(); } - const QString& user() const - { - return m_user; - } - - const QString& userHomeDir() const - { - return m_userHomeDir; - } - - void setVeyonAuthType( RfbVeyonAuth::Type authType ) - { - m_veyonAuthType = authType; - } - - RfbVeyonAuth::Type veyonAuthType() const - { - return m_veyonAuthType; - } - - void sendFeatureMessage( const FeatureMessage& featureMessage, bool wake ); + void sendFeatureMessage(const FeatureMessage& featureMessage); bool handleServerMessage( rfbClient* client, uint8_t msg ); static constexpr auto VeyonConnectionTag = 0xFE14A11; -signals: +Q_SIGNALS: void featureMessageReceived( const FeatureMessage& ); private: + ~VeyonConnection() override; + void registerConnection(); void unregisterConnection(); @@ -92,11 +79,8 @@ class VEYON_CORE_EXPORT VeyonConnection : public QObject static int8_t handleSecTypeVeyon( rfbClient* client, uint32_t authScheme ); static void hookPrepareAuthentication( rfbClient* client ); - QPointer m_vncConnection; - - RfbVeyonAuth::Type m_veyonAuthType; + VncConnection* m_vncConnection{new VncConnection}; - QString m_user; - QString m_userHomeDir; + QString m_accessControlMessage; } ; diff --git a/core/src/VeyonCore.cpp b/core/src/VeyonCore.cpp index 05a325928..2d32f2fd5 100644 --- a/core/src/VeyonCore.cpp +++ b/core/src/VeyonCore.cpp @@ -1,7 +1,7 @@ /* * VeyonCore.cpp - implementation of Veyon Core * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,29 +24,37 @@ #include -#include -#include #include #include #include #include #include -#include +#include #include +#include #include +#include +#include +#include +#include +#include #include +#include +#include "AuthenticationCredentials.h" +#include "AuthenticationManager.h" #include "BuiltinFeatures.h" -#include "ComputerControlInterface.h" +#include "FeatureManager.h" #include "Filesystem.h" #include "HostAddress.h" #include "Logger.h" #include "NetworkObjectDirectoryManager.h" -#include "PasswordDialog.h" #include "PlatformPluginManager.h" #include "PlatformCoreFunctions.h" -#include "PlatformServiceCore.h" +#include "PlatformSessionFunctions.h" #include "PluginManager.h" +#include "QmlCore.h" +#include "TranslationLoader.h" #include "UserGroupsBackendManager.h" #include "VeyonConfiguration.h" #include "VncConnection.h" @@ -55,12 +63,13 @@ VeyonCore* VeyonCore::s_instance = nullptr; -VeyonCore::VeyonCore( QCoreApplication* application, const QString& appComponentName ) : +VeyonCore::VeyonCore( QCoreApplication* application, Component component, const QString& appComponentName ) : QObject( application ), m_filesystem( new Filesystem ), m_config( nullptr ), m_logger( nullptr ), m_authenticationCredentials( nullptr ), + m_authenticationManager( nullptr ), m_cryptoCore( nullptr ), m_pluginManager( nullptr ), m_platformPluginManager( nullptr ), @@ -68,57 +77,69 @@ VeyonCore::VeyonCore( QCoreApplication* application, const QString& appComponent m_builtinFeatures( nullptr ), m_userGroupsBackendManager( nullptr ), m_networkObjectDirectoryManager( nullptr ), - m_localComputerControlInterface( nullptr ), + m_component( component ), m_applicationName( QStringLiteral( "Veyon" ) ), - m_authenticationKeyName(), m_debugging( false ) { Q_ASSERT( application != nullptr ); s_instance = this; - setupApplicationParameters(); - initPlatformPlugin(); initConfiguration(); + initSession(); + initLogging( appComponentName ); initLocaleAndTranslation(); + initUi(); + initCryptoCore(); + initTlsConfiguration(); + + initQmlCore(); + initAuthenticationCredentials(); initPlugins(); initManagers(); - initLocalComputerControlInterface(); + initFeatures(); initSystemInfo(); + + Q_EMIT initialized(); // clazy:exclude=incorrect-emit } VeyonCore::~VeyonCore() { + vDebug(); + + delete m_featureManager; + m_featureManager = nullptr; + + delete m_builtinFeatures; + m_builtinFeatures = nullptr; + delete m_userGroupsBackendManager; m_userGroupsBackendManager = nullptr; delete m_authenticationCredentials; m_authenticationCredentials = nullptr; - delete m_cryptoCore; - m_cryptoCore = nullptr; + delete m_authenticationManager; + m_authenticationManager = nullptr; delete m_logger; m_logger = nullptr; - delete m_builtinFeatures; - m_builtinFeatures = nullptr; - delete m_platformPluginManager; m_platformPluginManager = nullptr; @@ -131,6 +152,12 @@ VeyonCore::~VeyonCore() delete m_filesystem; m_filesystem = nullptr; + delete m_cryptoCore; + m_cryptoCore = nullptr; + + delete m_qmlCore; + m_qmlCore = nullptr; + s_instance = nullptr; } @@ -138,14 +165,12 @@ VeyonCore::~VeyonCore() VeyonCore* VeyonCore::instance() { - Q_ASSERT(s_instance != nullptr); - return s_instance; } -QString VeyonCore::version() +QString VeyonCore::versionString() { return QStringLiteral( VEYON_VERSION ); } @@ -168,11 +193,17 @@ QString VeyonCore::translationsDirectory() QString VeyonCore::qtTranslationsDirectory() { -#ifdef QT_TRANSLATIONS_DIR - return QStringLiteral( QT_TRANSLATIONS_DIR ); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + const auto path = QLibraryInfo::path(QLibraryInfo::TranslationsPath); #else - return translationsDirectory(); + const auto path = QLibraryInfo::location(QLibraryInfo::TranslationsPath); #endif + if( QDir{path}.exists() ) + { + return path; + } + + return translationsDirectory(); } @@ -204,34 +235,11 @@ void VeyonCore::setupApplicationParameters() QCoreApplication::setOrganizationDomain( QStringLiteral( "veyon.io" ) ); QCoreApplication::setApplicationName( QStringLiteral( "Veyon" ) ); - QApplication::setAttribute( Qt::AA_UseHighDpiPixmaps ); -} - + QCoreApplication::setAttribute( Qt::AA_ShareOpenGLContexts ); - -bool VeyonCore::initAuthentication() -{ - switch( config().authenticationMethod() ) - { - case AuthenticationMethod::LogonAuthentication: return initLogonAuthentication(); - case AuthenticationMethod::KeyFileAuthentication: return initKeyFileAuthentication(); - } - - return false; -} - - - -bool VeyonCore::hasSessionId() -{ - return QProcessEnvironment::systemEnvironment().contains( sessionIdEnvironmentVariable() ); -} - - - -int VeyonCore::sessionId() -{ - return QProcessEnvironment::systemEnvironment().value( sessionIdEnvironmentVariable() ).toInt(); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QApplication::setAttribute( Qt::AA_UseHighDpiPixmaps ); +#endif } @@ -282,14 +290,37 @@ void VeyonCore::enforceBranding( QWidget *topLevelWidget ) +bool VeyonCore::useDarkMode() +{ + const auto colorScheme = config().uiColorScheme(); + +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + if (colorScheme == UiColorScheme::System && + QGuiApplication::styleHints() && + QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark) + { + return true; + } +#endif + + if (colorScheme == UiColorScheme::Dark) + { + return true; + } + + return false; +} + + + bool VeyonCore::isDebugging() { - return instance()->m_debugging; + return s_instance && s_instance->m_debugging; } -QByteArray VeyonCore::shortenFuncinfo( QByteArray info ) +QByteArray VeyonCore::shortenFuncinfo( const QByteArray& info ) { const auto funcinfo = cleanupFuncinfo( info ); @@ -327,17 +358,17 @@ QByteArray VeyonCore::cleanupFuncinfo( QByteArray info ) } // operator names with '(', ')', '<', '>' in it - static const char operator_call[] = "operator()"; - static const char operator_lessThan[] = "operator<"; - static const char operator_greaterThan[] = "operator>"; - static const char operator_lessThanEqual[] = "operator<="; - static const char operator_greaterThanEqual[] = "operator>="; + static constexpr std::array operator_call{ "operator()" }; + static constexpr std::array operator_lessThan{ "operator<" }; + static constexpr std::array operator_greaterThan{ "operator>" }; + static constexpr std::array operator_lessThanEqual{ "operator<=" }; + static constexpr std::array operator_greaterThanEqual{ "operator>=" }; // canonize operator names info.replace("operator ", "operator"); // remove argument list - forever { + Q_FOREVER { int parencount = 0; pos = info.lastIndexOf(')'); if (pos == -1) { @@ -361,7 +392,7 @@ QByteArray VeyonCore::cleanupFuncinfo( QByteArray info ) info.truncate(++pos); if (info.at(pos - 1) == ')') { - if (info.indexOf(operator_call) == pos - (int)strlen(operator_call)) + if (info.indexOf(operator_call.data()) == pos - int(strlen(operator_call.data()))) break; // this function returns a pointer to a function @@ -370,9 +401,8 @@ QByteArray VeyonCore::cleanupFuncinfo( QByteArray info ) info.remove(0, info.indexOf('(')); info.chop(1); continue; - } else { - break; } + break; } // find the beginning of the function name @@ -384,22 +414,22 @@ QByteArray VeyonCore::cleanupFuncinfo( QByteArray info ) if (pos > -1) { switch (info.at(pos)) { case ')': - if (info.indexOf(operator_call) == pos - (int)strlen(operator_call) + 1) + if (info.indexOf(operator_call.data()) == pos - int(strlen(operator_call.data())) + 1) pos -= 2; break; case '<': - if (info.indexOf(operator_lessThan) == pos - (int)strlen(operator_lessThan) + 1) + if (info.indexOf(operator_lessThan.data()) == pos - int(strlen(operator_lessThan.data())) + 1) --pos; break; case '>': - if (info.indexOf(operator_greaterThan) == pos - (int)strlen(operator_greaterThan) + 1) + if (info.indexOf(operator_greaterThan.data()) == pos - int(strlen(operator_greaterThan.data())) + 1) --pos; break; case '=': { - int operatorLength = (int)strlen(operator_lessThanEqual); - if (info.indexOf(operator_lessThanEqual) == pos - operatorLength + 1) + const auto operatorLength = int(strlen(operator_lessThanEqual.data())); + if (info.indexOf(operator_lessThanEqual.data()) == pos - operatorLength + 1) pos -= 2; - else if (info.indexOf(operator_greaterThanEqual) == pos - operatorLength + 1) + else if (info.indexOf(operator_greaterThanEqual.data()) == pos - operatorLength + 1) pos -= 2; break; } @@ -485,23 +515,40 @@ QString VeyonCore::formattedUuid( QUuid uuid ) -bool VeyonCore::isAuthenticationKeyNameValid( const QString& authKeyName ) +QString VeyonCore::stringify( const QVariantMap& map ) { - return QRegExp( QStringLiteral("\\w+") ).exactMatch( authKeyName ); + return QString::fromUtf8( QJsonDocument(QJsonObject::fromVariantMap(map)).toJson(QJsonDocument::Compact) ); +} + + + +QString VeyonCore::screenName(const QScreen& screen, int index) +{ + auto screenName = tr("Screen %1").arg(index); + + const auto displayDeviceName = platform().coreFunctions().queryDisplayDeviceName(screen); + if(displayDeviceName.isEmpty() == false) + { + screenName.append(QStringLiteral(" – %1").arg(displayDeviceName)); + } + + return screenName; } int VeyonCore::exec() { - emit applicationLoaded(); + Q_EMIT applicationLoaded(); vDebug() << "Running"; - const auto result = QCoreApplication::instance()->exec(); + const auto result = QCoreApplication::exec(); vDebug() << "Exit"; + Q_EMIT exited(); + return result; } @@ -520,6 +567,31 @@ void VeyonCore::initPlatformPlugin() +void VeyonCore::initSession() +{ + if( component() != Component::Service && config().multiSessionModeEnabled() ) + { + const auto systemEnv = QProcessEnvironment::systemEnvironment(); + if( systemEnv.contains( sessionIdEnvironmentVariable() ) ) + { + m_sessionId = systemEnv.value( sessionIdEnvironmentVariable() ).toInt(); + } + else + { + const auto sessionId = platform().sessionFunctions().currentSessionId(); + if( sessionId != PlatformSessionFunctions::InvalidSessionId ) + { + m_sessionId = sessionId; + } + } + } + else + { + m_sessionId = PlatformSessionFunctions::DefaultSessionId; + } +} + + void VeyonCore::initConfiguration() { m_config = new VeyonConfiguration(); @@ -540,9 +612,11 @@ void VeyonCore::initConfiguration() void VeyonCore::initLogging( const QString& appComponentName ) { - if( hasSessionId() ) + const auto currentSessionId = sessionId(); + + if( currentSessionId != PlatformSessionFunctions::DefaultSessionId ) { - m_logger = new Logger( QStringLiteral("%1-%2").arg( appComponentName ).arg( sessionId() ) ); + m_logger = new Logger( QStringLiteral("%1-%2").arg( appComponentName ).arg( currentSessionId ) ); } else { @@ -558,49 +632,57 @@ void VeyonCore::initLogging( const QString& appComponentName ) void VeyonCore::initLocaleAndTranslation() { - QLocale configuredLocale( QLocale::C ); - - QRegExp localeRegEx( QStringLiteral( "[^(]*\\(([^)]*)\\)") ); - if( localeRegEx.indexIn( config().uiLanguage() ) == 0 ) + if( TranslationLoader::load( QStringLiteral("qtbase") ) == false ) { - configuredLocale = QLocale( localeRegEx.cap( 1 ) ); + TranslationLoader::load( QStringLiteral("qt") ); } - if( configuredLocale.language() != QLocale::English ) - { - auto tr = new QTranslator; - if( configuredLocale == QLocale::C || - tr->load( QStringLiteral( "%1.qm" ).arg( configuredLocale.name() ), translationsDirectory() ) == false ) - { - configuredLocale = QLocale::system(); // Flawfinder: ignore + TranslationLoader::load( QStringLiteral("veyon") ); - if( tr->load( QStringLiteral( "%1.qm" ).arg( configuredLocale.name() ), translationsDirectory() ) == false ) - { - tr->load( QStringLiteral( "%1.qm" ).arg( configuredLocale.language() ), translationsDirectory() ); - } - } + const auto app = qobject_cast( QCoreApplication::instance() ); + if( app ) + { + QGuiApplication::setLayoutDirection( QLocale{}.textDirection() ); + } +} - QLocale::setDefault( configuredLocale ); - QCoreApplication::installTranslator( tr ); - auto qtTr = new QTranslator; - if( qtTr->load( QStringLiteral( "qt_%1.qm" ).arg( configuredLocale.name() ), qtTranslationsDirectory() ) == false ) +void VeyonCore::initUi() +{ + auto app = qobject_cast(QCoreApplication::instance()); + if (app) + { + if (m_config->uiStyle() == UiStyle::Fusion) { - qtTr->load( QStringLiteral( "qt_%1.qm" ).arg( configuredLocale.language() ), qtTranslationsDirectory() ); + app->setStyle(QStyleFactory::create(QStringLiteral("Fusion"))); } - QCoreApplication::installTranslator( qtTr ); - } + app->setStyleSheet(QStringLiteral( + "QToolButton:checked {background-color:#88ddff;}" + "QToolTip {padding:5px; border:0px;}" + )); - if( configuredLocale.language() == QLocale::Hebrew || - configuredLocale.language() == QLocale::Arabic ) - { - auto app = qobject_cast( QCoreApplication::instance() ); - if( app ) + auto toolTipPalette = QToolTip::palette(); + static const char* toolTipBackgroundColor = "#198cb3"; + toolTipPalette.setColor(QPalette::Window, toolTipBackgroundColor); + toolTipPalette.setColor(QPalette::ToolTipBase, toolTipBackgroundColor); + toolTipPalette.setColor(QPalette::ToolTipText, Qt::white); + QToolTip::setPalette(toolTipPalette); + +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) + switch (config().uiColorScheme()) { - QApplication::setLayoutDirection( Qt::RightToLeft ); + case UiColorScheme::Dark: + QGuiApplication::styleHints()->setColorScheme(Qt::ColorScheme::Dark); + break; + case UiColorScheme::Light: + QGuiApplication::styleHints()->setColorScheme(Qt::ColorScheme::Light); + break; + default: + break; } +#endif } } @@ -613,6 +695,13 @@ void VeyonCore::initCryptoCore() +void VeyonCore::initQmlCore() +{ + m_qmlCore = new QmlCore( this ); +} + + + void VeyonCore::initAuthenticationCredentials() { if( m_authenticationCredentials ) @@ -631,87 +720,178 @@ void VeyonCore::initPlugins() // load all other (non-platform) plugins m_pluginManager->loadPlugins(); m_pluginManager->upgradePlugins(); - - m_builtinFeatures = new BuiltinFeatures(); } void VeyonCore::initManagers() { + m_authenticationManager = new AuthenticationManager( this ); m_userGroupsBackendManager = new UserGroupsBackendManager( this ); m_networkObjectDirectoryManager = new NetworkObjectDirectoryManager( this ); } -void VeyonCore::initLocalComputerControlInterface() +void VeyonCore::initFeatures() { - const Computer localComputer( NetworkObject::Uid::createUuid(), - QStringLiteral("localhost"), - QStringLiteral("%1:%2").arg( QHostAddress( QHostAddress::LocalHost ).toString() ).arg( config().primaryServicePort() + sessionId() ) ); + m_builtinFeatures = new BuiltinFeatures(); + m_featureManager = new FeatureManager(this); +} + + - m_localComputerControlInterface = new ComputerControlInterface( localComputer, this ); +void VeyonCore::initSystemInfo() +{ + vDebug() << versionString() << HostAddress::localFQDN() + << QSysInfo::kernelType() << QSysInfo::kernelVersion() + << QSysInfo::prettyProductName() << QSysInfo::productType() << QSysInfo::productVersion(); } -bool VeyonCore::initLogonAuthentication() +void VeyonCore::initTlsConfiguration() { - if( qobject_cast( QCoreApplication::instance() ) ) - { - PasswordDialog dlg( QApplication::activeWindow() ); - if( dlg.exec() && - dlg.credentials().hasCredentials( AuthenticationCredentials::Type::UserLogon ) ) - { - m_authenticationCredentials->setLogonUsername( dlg.username() ); - m_authenticationCredentials->setLogonPassword( dlg.password() ); + auto tlsConfig{TlsConfiguration::defaultConfiguration()}; - return true; - } +#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) + tlsConfig.setProtocol( QSsl::TlsV1_3OrLater ); +#else + tlsConfig.setProtocol( QSsl::TlsV1_2OrLater ); +#endif + + if( config().tlsUseCertificateAuthority() ) + { + loadCertificateAuthorityFiles( &tlsConfig ); + } + else + { + addSelfSignedHostCertificate( &tlsConfig ); } - return false; + TlsConfiguration::setDefaultConfiguration( tlsConfig ); } -bool VeyonCore::initKeyFileAuthentication() +bool VeyonCore::loadCertificateAuthorityFiles( TlsConfiguration* tlsConfig ) { - auto authKeyName = QProcessEnvironment::systemEnvironment().value( QStringLiteral("VEYON_AUTH_KEY_NAME") ); + QFile caCertFile( filesystem().expandPath( config().tlsCaCertificateFile() ) ); - if( authKeyName.isEmpty() == false ) + if( caCertFile.exists() == false ) { - if( isAuthenticationKeyNameValid( authKeyName ) && - m_authenticationCredentials->loadPrivateKey( VeyonCore::filesystem().privateKeyPath( authKeyName ) ) ) - { - m_authenticationKeyName = authKeyName; - } + vCritical() << "TLS CA certificate file" << caCertFile.fileName() << "does not exist"; + return false; } - else + + if( caCertFile.open( QFile::ReadOnly ) == false ) { - // try to auto-detect private key file by searching for readable file - const auto privateKeyBaseDir = VeyonCore::filesystem().expandPath( VeyonCore::config().privateKeyBaseDir() ); - const auto privateKeyDirs = QDir( privateKeyBaseDir ).entryList( QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name ); + vCritical() << "TLS CA certificate file" << caCertFile.fileName() << "is not readable"; + return false; + } - for( const auto& privateKeyDir : privateKeyDirs ) + QSslCertificate caCertificate( caCertFile.readAll() ); + if( caCertificate.isNull() ) + { + vCritical() << caCertFile.fileName() << "does not contain a valid TLS certificate"; + return false; + } + + QFile hostCertFile( filesystem().expandPath( config().tlsHostCertificateFile() ) ); + + if( hostCertFile.exists() == false ) + { + vCritical() << "TLS host certificate file" << hostCertFile.fileName() << "does not exist"; + return false; + } + + if( hostCertFile.open( QFile::ReadOnly ) == false ) + { + vCritical() << "TLS host certificate file" << hostCertFile.fileName() << "is not readable"; + return false; + } + + QSslCertificate hostCertificate( hostCertFile.readAll() ); + if( hostCertificate.isNull() ) + { + vCritical() << hostCertFile.fileName() << "does not contain a valid TLS certificate"; + return false; + } + + QFile hostPrivateKeyFile( filesystem().expandPath( config().tlsHostPrivateKeyFile() ) ); + + if( hostPrivateKeyFile.exists() == false ) + { + vCritical() << "TLS private key file" << hostPrivateKeyFile.fileName() << "does not exist"; + return false; + } + + if( hostPrivateKeyFile.open( QFile::ReadOnly ) == false ) + { + vCritical() << "TLS private key file" << hostPrivateKeyFile.fileName() << "is not readable"; + return false; + } + + const auto hostPrivateKeyFileData = hostPrivateKeyFile.readAll(); + + QSslKey hostPrivateKey; + for( auto algorithm : { QSsl::KeyAlgorithm::Rsa, QSsl::KeyAlgorithm::Ec +#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) + , QSsl::KeyAlgorithm::Dh +#endif + } ) + { + QSslKey currentPrivateKey( hostPrivateKeyFileData, algorithm ); + if( currentPrivateKey.isNull() == false ) { - if( m_authenticationCredentials->loadPrivateKey( VeyonCore::filesystem().privateKeyPath( privateKeyDir ) ) ) - { - m_authenticationKeyName = privateKeyDir; - return true; - } + hostPrivateKey = currentPrivateKey; + break; } } - return false; + if( hostPrivateKey.isNull() ) + { + vCritical() << hostPrivateKeyFile.fileName() << "does contains an invalid or unsupported TLS private key"; + return false; + } + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + tlsConfig->addCaCertificates( TlsConfiguration::systemCaCertificates() ); + tlsConfig->addCaCertificate( caCertificate ); +#else + tlsConfig->setCaCertificates( TlsConfiguration::systemCaCertificates() + QList{caCertificate} ); +#endif + tlsConfig->setLocalCertificate( hostCertificate ); + tlsConfig->setPrivateKey( hostPrivateKey ); + + return true; } -void VeyonCore::initSystemInfo() +bool VeyonCore::addSelfSignedHostCertificate( TlsConfiguration* tlsConfig ) { - vDebug() << version() << HostAddress::localFQDN() - << QSysInfo::kernelType() << QSysInfo::kernelVersion() - << QSysInfo::prettyProductName() << QSysInfo::productType() << QSysInfo::productVersion(); + const auto privateKey = cryptoCore().createPrivateKey(); + if( privateKey.isNull() ) + { + vCritical() << "failed to create private key for host certificate"; + return false; + } + + const auto cert = cryptoCore().createSelfSignedHostCertificate( privateKey ); + if( cert.isNull() ) + { + vCritical() << "failed to create host certificate"; + return false; + } + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + tlsConfig->addCaCertificates( TlsConfiguration::systemCaCertificates() ); +#else + tlsConfig->setCaCertificates( TlsConfiguration::systemCaCertificates() ); +#endif + tlsConfig->setLocalCertificate( QSslCertificate( cert.toPEM().toUtf8() ) ); + tlsConfig->setPrivateKey( QSslKey( privateKey.toPEM().toUtf8(), QSsl::KeyAlgorithm::Rsa ) ); + + return true; } diff --git a/core/include/VeyonCore.h b/core/src/VeyonCore.h similarity index 69% rename from core/include/VeyonCore.h rename to core/src/VeyonCore.h index f3efea6e6..b65cf58c4 100644 --- a/core/include/VeyonCore.h +++ b/core/src/VeyonCore.h @@ -1,7 +1,7 @@ /* * VeyonCore.h - declaration of VeyonCore class + basic headers * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,37 +24,40 @@ #pragma once +#include #include -#include #include +#include #include #include #include #include "QtCompat.h" -#if defined(BUILD_VEYON_CORE_LIBRARY) +#if defined(veyon_core_EXPORTS) # define VEYON_CORE_EXPORT Q_DECL_EXPORT #else # define VEYON_CORE_EXPORT Q_DECL_IMPORT #endif -#define QSL QStringLiteral - class QCoreApplication; +class QScreen; +class QSslConfiguration; class QWidget; class AuthenticationCredentials; +class AuthenticationManager; class BuiltinFeatures; -class ComputerControlInterface; class CryptoCore; +class FeatureManager; class Filesystem; class Logger; class NetworkObjectDirectoryManager; class PlatformPluginInterface; class PlatformPluginManager; class PluginManager; +class QmlCore; class UserGroupsBackendManager; class VeyonConfiguration; @@ -64,19 +67,55 @@ class VEYON_CORE_EXPORT VeyonCore : public QObject { Q_OBJECT public: + using TlsConfiguration = QSslConfiguration; + enum class ApplicationVersion { + Unknown = -1, Version_4_0, Version_4_1, Version_4_2, + Version_4_3, + Version_4_4, + Version_4_5, + Version_4_6, + Version_4_7, + Version_4_8, + Version_4_9, + Version_5_0, }; Q_ENUM(ApplicationVersion) - VeyonCore( QCoreApplication* application, const QString& appComponentName ); + enum class Component { + Service, + Server, + Worker, + Master, + CLI, + Configurator + }; + Q_ENUM(Component) + + enum class UiStyle { + Fusion, + Native + }; + Q_ENUM(UiStyle) + + enum class UiColorScheme { + System, + Light, + Dark + }; + Q_ENUM(UiColorScheme) + + static constexpr char RfbSecurityTypeVeyon = 40; + + VeyonCore( QCoreApplication* application, Component component, const QString& appComponentName ); ~VeyonCore() override; static VeyonCore* instance(); - static QString version(); + static QString versionString(); static QString pluginDir(); static QString translationsDirectory(); static QString qtTranslationsDirectory(); @@ -85,6 +124,11 @@ class VEYON_CORE_EXPORT VeyonCore : public QObject static QString sessionIdEnvironmentVariable(); + static Component component() + { + return instance()->m_component; + } + static VeyonConfiguration& config() { return *( instance()->m_config ); @@ -95,6 +139,11 @@ class VEYON_CORE_EXPORT VeyonCore : public QObject return *( instance()->m_authenticationCredentials ); } + static AuthenticationManager& authenticationManager() + { + return *( instance()->m_authenticationManager ); + } + static CryptoCore& cryptoCore() { return *( instance()->m_cryptoCore ); @@ -110,11 +159,21 @@ class VEYON_CORE_EXPORT VeyonCore : public QObject return *( instance()->m_platformPlugin ); } + static QmlCore& qmlCore() + { + return *( instance()->m_qmlCore ); + } + static BuiltinFeatures& builtinFeatures() { return *( instance()->m_builtinFeatures ); } + static FeatureManager& featureManager() + { + return *( instance()->m_featureManager ); + } + static UserGroupsBackendManager& userGroupsBackendManager() { return *( instance()->m_userGroupsBackendManager ); @@ -130,57 +189,49 @@ class VEYON_CORE_EXPORT VeyonCore : public QObject return *( instance()->m_filesystem ); } - static ComputerControlInterface& localComputerControlInterface() - { - return *( instance()->m_localComputerControlInterface ); - } - static void setupApplicationParameters(); - bool initAuthentication(); - static bool hasSessionId(); - static int sessionId(); + static int sessionId() + { + return instance()->m_sessionId; + } static QString applicationName(); static void enforceBranding( QWidget* topLevelWidget ); + static bool useDarkMode(); static bool isDebugging(); - static QByteArray shortenFuncinfo( QByteArray info ); + static QByteArray shortenFuncinfo( const QByteArray& info ); static QByteArray cleanupFuncinfo( QByteArray info ); static QString stripDomain( const QString& username ); static QString formattedUuid( QUuid uuid ); + static QString stringify( const QVariantMap& map ); - const QString& authenticationKeyName() const - { - return m_authenticationKeyName; - } - - static bool isAuthenticationKeyNameValid( const QString& authKeyName ); - - enum class AuthenticationMethod - { - LogonAuthentication, - KeyFileAuthentication, - }; - Q_ENUM(AuthenticationMethod) + static QString screenName( const QScreen& screen, int index ); int exec(); private: void initPlatformPlugin(); + void initSession(); void initConfiguration(); void initLogging( const QString& appComponentName ); void initLocaleAndTranslation(); + void initUi(); void initCryptoCore(); + void initQmlCore(); void initAuthenticationCredentials(); void initPlugins(); void initManagers(); + void initFeatures(); void initLocalComputerControlInterface(); - bool initLogonAuthentication(); - bool initKeyFileAuthentication(); void initSystemInfo(); + void initTlsConfiguration(); + + bool loadCertificateAuthorityFiles( TlsConfiguration* tlsConfig ); + bool addSelfSignedHostCertificate( TlsConfiguration* tlsConfig ); static VeyonCore* s_instance; @@ -188,22 +239,27 @@ class VEYON_CORE_EXPORT VeyonCore : public QObject VeyonConfiguration* m_config; Logger* m_logger; AuthenticationCredentials* m_authenticationCredentials; + AuthenticationManager* m_authenticationManager; CryptoCore* m_cryptoCore; + QmlCore* m_qmlCore{nullptr}; PluginManager* m_pluginManager; PlatformPluginManager* m_platformPluginManager; PlatformPluginInterface* m_platformPlugin; BuiltinFeatures* m_builtinFeatures; + FeatureManager* m_featureManager{nullptr}; UserGroupsBackendManager* m_userGroupsBackendManager; NetworkObjectDirectoryManager* m_networkObjectDirectoryManager; - ComputerControlInterface* m_localComputerControlInterface; - + Component m_component; QString m_applicationName; - QString m_authenticationKeyName; bool m_debugging; -signals: + int m_sessionId{0}; + +Q_SIGNALS: + void initialized(); void applicationLoaded(); + void exited(); }; diff --git a/core/include/VeyonMasterInterface.h b/core/src/VeyonMasterInterface.h similarity index 66% rename from core/include/VeyonMasterInterface.h rename to core/src/VeyonMasterInterface.h index 3effd6f65..cce2e45a5 100644 --- a/core/include/VeyonMasterInterface.h +++ b/core/src/VeyonMasterInterface.h @@ -1,7 +1,7 @@ /* * VeyonMasterInterface.h - interface class for VeyonMaster * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,9 +25,12 @@ #pragma once #include "Configuration/Object.h" -#include "VeyonCore.h" +#include "ComputerControlInterface.h" class BuiltinFeatures; +class ComputerControlInterface; +class QQuickItem; +class QQuickWindow; class QWidget; class VEYON_CORE_EXPORT VeyonMasterInterface : public QObject @@ -42,7 +45,19 @@ class VEYON_CORE_EXPORT VeyonMasterInterface : public QObject ~VeyonMasterInterface() override = default; virtual QWidget* mainWindow() = 0; + virtual QQuickWindow* appWindow() = 0; + virtual QQuickItem* appContainer() = 0; + virtual Configuration::Object* userConfigurationObject() = 0; virtual void reloadSubFeatures() = 0; + virtual ComputerControlInterface& localSessionControlInterface() = 0; + + virtual const ComputerControlInterfaceList& allComputerControlInterfaces() const = 0; + virtual ComputerControlInterfaceList selectedComputerControlInterfaces() const = 0; + virtual ComputerControlInterfaceList filteredComputerControlInterfaces() const = 0; + +Q_SIGNALS: + void computerControlListModelAboutToReset(); + }; diff --git a/core/include/VeyonServerInterface.h b/core/src/VeyonServerInterface.h similarity index 73% rename from core/include/VeyonServerInterface.h rename to core/src/VeyonServerInterface.h index 2b1614a43..4d5c2212a 100644 --- a/core/include/VeyonServerInterface.h +++ b/core/src/VeyonServerInterface.h @@ -1,7 +1,7 @@ /* * VeyonServerInterface.h - interface class for VeyonServer * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,17 +24,30 @@ #pragma once -class BuiltinFeatures; +#include "VeyonCore.h" + class FeatureMessage; class FeatureWorkerManager; class MessageContext; -class VeyonServerInterface +// clazy:excludeall=copyable-polymorphic + +class VEYON_CORE_EXPORT VeyonServerInterface : public QObject { + Q_OBJECT public: + explicit VeyonServerInterface(QObject* parent) : + QObject(parent) + { + } + virtual ~VeyonServerInterface() = default; virtual FeatureWorkerManager& featureWorkerManager() = 0; virtual bool sendFeatureMessageReply( const MessageContext& context, const FeatureMessage& reply ) = 0; + virtual int vncServerBasePort() const = 0; + + virtual void setMinimumFramebufferUpdateInterval(const MessageContext& context, int interval) = 0; + }; diff --git a/core/src/VeyonServiceControl.cpp b/core/src/VeyonServiceControl.cpp index e0755a0c2..9e205ce19 100644 --- a/core/src/VeyonServiceControl.cpp +++ b/core/src/VeyonServiceControl.cpp @@ -1,7 +1,7 @@ /* * VeyonServiceControl.cpp - class for controlling Veyon service * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/core/include/VeyonServiceControl.h b/core/src/VeyonServiceControl.h similarity index 95% rename from core/include/VeyonServiceControl.h rename to core/src/VeyonServiceControl.h index b5789e17b..0aaf141eb 100644 --- a/core/include/VeyonServiceControl.h +++ b/core/src/VeyonServiceControl.h @@ -1,7 +1,7 @@ /* * VeyonServiceControl.h - class for controlling the Veyon service * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/core/include/VeyonWorkerInterface.h b/core/src/VeyonWorkerInterface.h similarity index 91% rename from core/include/VeyonWorkerInterface.h rename to core/src/VeyonWorkerInterface.h index 30762439f..f5ae21d3f 100644 --- a/core/include/VeyonWorkerInterface.h +++ b/core/src/VeyonWorkerInterface.h @@ -1,7 +1,7 @@ /* * VeyonWorkerInterface.h - interface class for VeyonWorker * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,6 +27,8 @@ class BuiltinFeatures; class FeatureMessage; +// clazy:excludeall=copyable-polymorphic + class VeyonWorkerInterface { public: diff --git a/core/src/VncClientProtocol.cpp b/core/src/VncClientProtocol.cpp index 865a55f0d..0ba5e43a8 100644 --- a/core/src/VncClientProtocol.cpp +++ b/core/src/VncClientProtocol.cpp @@ -1,7 +1,7 @@ /* * VncClientProtocol.cpp - implementation of the VncClientProtocol class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,11 +25,12 @@ extern "C" { #include "rfb/rfbproto.h" -#include "common/d3des.h" +#include "d3des.h" } #include #include +#include #include #include "VncClientProtocol.h" @@ -42,38 +43,37 @@ extern "C" static void vncEncryptBytes(unsigned char *bytes, const char *passwd, size_t passwd_length) { - constexpr int KeyLength = 8; - unsigned char key[KeyLength]; // Flawfinder: ignore - unsigned int i; + static constexpr int KeyLength = 8; + std::array key{}; // Flawfinder: ignore /* key is simply password padded with nulls */ - for (i = 0; i < KeyLength; i++) { - if (i < passwd_length) { - key[i] = static_cast( passwd[i] ); - } else { - key[i] = 0; + for( size_t i = 0; i < key.size(); i++ ) + { + if( i < passwd_length ) + { + key.at(i) = static_cast( passwd[i] ); + } + else + { + key.at(i) = 0; } } - rfbDesKey(key, EN0); + rfbDesKey( key.data(), EN0 ); - for (i = 0; i < CHALLENGESIZE; i += KeyLength) { - rfbDes(bytes+i, bytes+i); + for( size_t i = 0; i < CHALLENGESIZE; i += KeyLength ) + { + rfbDes( bytes+i, bytes+i ); } } -VncClientProtocol::VncClientProtocol( QTcpSocket* socket, const QString& vncPassword ) : +VncClientProtocol::VncClientProtocol( QIODevice* socket, const Password& vncPassword ) : m_socket( socket ), - m_state( Disconnected ), - m_vncPassword( vncPassword.toUtf8() ), - m_serverInitMessage(), - m_pixelFormat( { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ), - m_framebufferWidth( 0 ), - m_framebufferHeight( 0 ) + m_vncPassword( vncPassword ) { } @@ -81,7 +81,7 @@ VncClientProtocol::VncClientProtocol( QTcpSocket* socket, const QString& vncPass void VncClientProtocol::start() { - m_state = Protocol; + m_state = State::Protocol; } @@ -90,19 +90,19 @@ bool VncClientProtocol::read() // Flawfinder: ignore { switch( m_state ) { - case Protocol: + case State::Protocol: return readProtocol(); - case SecurityInit: + case State::SecurityInit: return receiveSecurityTypes(); - case SecurityChallenge: + case State::SecurityChallenge: return receiveSecurityChallenge(); - case SecurityResult: + case State::SecurityResult: return receiveSecurityResult(); - case FramebufferInit: + case State::FramebufferInit: return receiveServerInitMessage(); default: @@ -114,49 +114,60 @@ bool VncClientProtocol::read() // Flawfinder: ignore -bool VncClientProtocol::setPixelFormat( rfbPixelFormat pixelFormat ) +void VncClientProtocol::setPixelFormat(rfbPixelFormat pixelFormat) +{ + m_pixelFormat = pixelFormat; +} + + + +void VncClientProtocol::setEncodings(const QVector& encodings) +{ + m_encodings = encodings; +} + + + +bool VncClientProtocol::sendPixelFormat() { - rfbSetPixelFormatMsg spf; + rfbSetPixelFormatMsg spf{}; spf.type = rfbSetPixelFormat; spf.pad1 = 0; spf.pad2 = 0; - spf.format = pixelFormat; - spf.format.redMax = qFromBigEndian(pixelFormat.redMax); - spf.format.greenMax = qFromBigEndian(pixelFormat.greenMax); - spf.format.blueMax = qFromBigEndian(pixelFormat.blueMax); + spf.format = m_pixelFormat; + spf.format.redMax = qToBigEndian(spf.format.redMax); + spf.format.greenMax = qToBigEndian(spf.format.greenMax); + spf.format.blueMax = qToBigEndian(spf.format.blueMax); - return m_socket->write( reinterpret_cast( &spf ), sz_rfbSetPixelFormatMsg ) == sz_rfbSetPixelFormatMsg; + return m_socket->write(reinterpret_cast(&spf), sz_rfbSetPixelFormatMsg) == sz_rfbSetPixelFormatMsg; } -bool VncClientProtocol::setEncodings( const QVector& encodings ) +bool VncClientProtocol::sendEncodings() { - if( encodings.size() > MAX_ENCODINGS ) + if (m_encodings.size() > MAX_ENCODINGS) { return false; } - alignas(rfbSetEncodingsMsg) char buf[sz_rfbSetEncodingsMsg + MAX_ENCODINGS * 4]; // Flawfinder: ignore - - auto setEncodingsMsg = reinterpret_cast( buf ); - auto encs = reinterpret_cast( &buf[sz_rfbSetEncodingsMsg] ); + rfbSetEncodingsMsg setEncodingsMsg{}; + setEncodingsMsg.type = rfbSetEncodings; - setEncodingsMsg->type = rfbSetEncodings; - setEncodingsMsg->pad = 0; - setEncodingsMsg->nEncodings = 0; + std::array encs{}; - for( auto encoding : encodings ) + for (const auto encoding : std::as_const(m_encodings)) { - encs[setEncodingsMsg->nEncodings++] = qFromBigEndian( encoding ); + encs.at(setEncodingsMsg.nEncodings++) = qToBigEndian( encoding ); } - const auto len = sz_rfbSetEncodingsMsg + setEncodingsMsg->nEncodings * 4; + const auto len = setEncodingsMsg.nEncodings * 4; - setEncodingsMsg->nEncodings = qFromBigEndian(setEncodingsMsg->nEncodings); + setEncodingsMsg.nEncodings = qToBigEndian(setEncodingsMsg.nEncodings); - return m_socket->write( buf, len ) == len; + return m_socket->write(reinterpret_cast(&setEncodingsMsg), sz_rfbSetEncodingsMsg) == sz_rfbSetEncodingsMsg && + m_socket->write(reinterpret_cast(encs.data()), len) == len; } @@ -183,6 +194,13 @@ void VncClientProtocol::requestFramebufferUpdate( bool incremental ) bool VncClientProtocol::receiveMessage() { + if( m_socket->bytesAvailable() > MaximumMessageSize ) + { + vCritical() << "Message too big or invalid"; + m_socket->close(); + return false; + } + uint8_t messageType = 0; if( m_socket->peek( reinterpret_cast( &messageType ), sizeof(messageType) ) != sizeof(messageType) ) { @@ -233,11 +251,12 @@ bool VncClientProtocol::readProtocol() return false; } - QRegExp protocolRX( QStringLiteral("RFB (\\d\\d\\d)\\.(\\d\\d\\d)\n") ); + static const QRegularExpression rfbRX{QStringLiteral("RFB (\\d\\d\\d)\\.(\\d\\d\\d)\n")}; + const auto match = rfbRX.match(QString::fromUtf8(protocol)); - if( protocolRX.indexIn( QString::fromUtf8( protocol ) ) != 0 || - protocolRX.cap( 1 ).toInt() != 3 || - protocolRX.cap( 2 ).toInt() < 7 ) + if( match.hasMatch() == false || + match.captured( 1 ).toInt() != 3 || + match.captured( 2 ).toInt() < 7 ) { vCritical() << "invalid protocol version"; m_socket->close(); @@ -247,7 +266,7 @@ bool VncClientProtocol::readProtocol() m_socket->write( protocol ); - m_state = SecurityInit; + m_state = State::SecurityInit; return true; } @@ -274,7 +293,7 @@ bool VncClientProtocol::receiveSecurityTypes() } const auto securityTypeList = m_socket->read( securityTypeCount ); - if( securityTypeList.count() != securityTypeCount ) + if( securityTypeList.size() != securityTypeCount ) { vCritical() << "could not read security types!"; m_socket->close(); @@ -282,20 +301,27 @@ bool VncClientProtocol::receiveSecurityTypes() return false; } - const char securityType = rfbSecTypeVncAuth; + char securityType = rfbSecTypeInvalid; - if( securityTypeList.contains( securityType ) == false ) + if( securityTypeList.contains( rfbSecTypeVncAuth ) ) + { + securityType = rfbSecTypeVncAuth; + m_state = State::SecurityChallenge; + } + else if( securityTypeList.contains( rfbSecTypeNone ) ) { - vCritical() << "no supported security type!"; + securityType = rfbSecTypeNone; + m_state = State::SecurityResult; + } + else + { + vCritical() << "unsupported security types!" << securityTypeList; m_socket->close(); - return false; } m_socket->write( &securityType, sizeof(securityType) ); - m_state = SecurityChallenge; - return true; } @@ -308,14 +334,15 @@ bool VncClientProtocol::receiveSecurityChallenge() { if( m_socket->bytesAvailable() >= CHALLENGESIZE ) { - uint8_t challenge[CHALLENGESIZE]; - m_socket->read( reinterpret_cast( challenge ), CHALLENGESIZE ); + std::array challenge{}; + m_socket->read( challenge.data(), challenge.size() ); - vncEncryptBytes( challenge, m_vncPassword.constData(), static_cast( m_vncPassword.size() ) ); + vncEncryptBytes( reinterpret_cast( challenge.data() ), m_vncPassword.constData(), + size_t( m_vncPassword.size() ) ); - m_socket->write( reinterpret_cast( challenge ), CHALLENGESIZE ); + m_socket->write( challenge.data(), CHALLENGESIZE ); - m_state = SecurityResult; + m_state = State::SecurityResult; return true; } @@ -348,7 +375,7 @@ bool VncClientProtocol::receiveSecurityResult() m_socket->write( reinterpret_cast( &clientInitMessage ), sz_rfbClientInitMsg ); // wait for server init message - m_state = FramebufferInit; + m_state = State::FramebufferInit; return true; } @@ -362,8 +389,8 @@ bool VncClientProtocol::receiveServerInitMessage() { rfbServerInitMsg message; - if( m_socket->bytesAvailable() >= sz_rfbServerInitMsg && - m_socket->peek( reinterpret_cast( &message ), sz_rfbServerInitMsg ) == sz_rfbServerInitMsg ) + if (m_socket->bytesAvailable() >= sz_rfbServerInitMsg && + m_socket->peek(reinterpret_cast(&message), sz_rfbServerInitMsg) == sz_rfbServerInitMsg) { const auto nameLength = qFromBigEndian( message.nameLength ); @@ -379,6 +406,10 @@ bool VncClientProtocol::receiveServerInitMessage() memcpy( &m_pixelFormat, &message.format, sz_rfbPixelFormat ); // Flawfinder: ignore + m_pixelFormat.redMax = qFromBigEndian(m_pixelFormat.redMax); + m_pixelFormat.greenMax = qFromBigEndian(m_pixelFormat.greenMax); + m_pixelFormat.blueMax = qFromBigEndian(m_pixelFormat.blueMax); + if( static_cast( m_socket->peek( nameLength ).size() ) == nameLength ) { m_serverInitMessage = m_socket->read( sz_rfbServerInitMsg + nameLength ); @@ -387,7 +418,7 @@ bool VncClientProtocol::receiveServerInitMessage() m_framebufferWidth = qFromBigEndian( serverInitMessage->framebufferWidth ); m_framebufferHeight = qFromBigEndian( serverInitMessage->framebufferHeight ); - m_state = Running; + m_state = State::Running; return true; } @@ -485,7 +516,7 @@ bool VncClientProtocol::receiveCutTextMessage() return false; } - return readMessage( sz_rfbServerCutTextMsg + qFromBigEndian( message.length ) ); + return readMessage( sz_rfbServerCutTextMsg + static_cast( qFromBigEndian( message.length ) ) ); } @@ -550,12 +581,12 @@ bool VncClientProtocol::handleRect( QBuffer& buffer, rfbFramebufferUpdateRectHea case rfbEncodingXCursor: return width * height == 0 || ( buffer.read( sz_rfbXCursorColors ).size() == sz_rfbXCursorColors && - buffer.read( 2 * bytesPerRow * height ).size() == static_cast( 2 * bytesPerRow * height ) ); + buffer.read( size_t(2) * bytesPerRow * height ).size() == static_cast( 2 * bytesPerRow * height ) ); case rfbEncodingRichCursor: return width * height == 0 || - ( buffer.read( width * height * bytesPerPixel ).size() == static_cast( width * height * bytesPerPixel ) && - buffer.read( bytesPerRow * height ).size() == static_cast( bytesPerRow * height ) ); + ( buffer.read( size_t(width) * height * bytesPerPixel ).size() == static_cast( width * height * bytesPerPixel ) && + buffer.read( size_t(bytesPerRow) * height ).size() == static_cast( bytesPerRow * height ) ); case rfbEncodingSupportedMessages: return buffer.read( sz_rfbSupportedMessages ).size() == sz_rfbSupportedMessages; @@ -566,7 +597,7 @@ bool VncClientProtocol::handleRect( QBuffer& buffer, rfbFramebufferUpdateRectHea return buffer.read( width ).size() == static_cast( width ); case rfbEncodingRaw: - return buffer.read( width * height * bytesPerPixel ).size() == static_cast( width * height * bytesPerPixel ); + return buffer.read( size_t(width) * height * bytesPerPixel ).size() == static_cast( width * height * bytesPerPixel ); case rfbEncodingCopyRect: return buffer.read( sz_rfbCopyRect ).size() == sz_rfbCopyRect; @@ -589,6 +620,12 @@ bool VncClientProtocol::handleRect( QBuffer& buffer, rfbFramebufferUpdateRectHea case rfbEncodingZYWRLE: return handleRectEncodingZRLE( buffer ); + case rfbEncodingTight: + return handleRectEncodingTight(buffer, rectHeader); + + case rfbEncodingExtDesktopSize: + return handleRectEncodingExtDesktopSize(buffer); + case rfbEncodingPointerPos: case rfbEncodingKeyboardLedState: case rfbEncodingNewFBSize: @@ -596,7 +633,11 @@ bool VncClientProtocol::handleRect( QBuffer& buffer, rfbFramebufferUpdateRectHea return true; default: - vCritical() << "Unsupported rect encoding" << rectHeader.encoding; + vCritical() << "Unsupported rect encoding" << +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + Qt::hex << +#endif + rectHeader.encoding; m_socket->close(); break; } @@ -618,7 +659,7 @@ bool VncClientProtocol::handleRectEncodingRRE( QBuffer& buffer, uint bytesPerPix const auto rectDataSize = qFromBigEndian( hdr.nSubrects ) * ( bytesPerPixel + sz_rfbRectangle ); const auto totalDataSize = static_cast( bytesPerPixel + rectDataSize ); - return buffer.read( totalDataSize ).size() == totalDataSize; + return totalDataSize < MaxMessageSize && buffer.read( totalDataSize ).size() == totalDataSize; } @@ -635,15 +676,15 @@ bool VncClientProtocol::handleRectEncodingCoRRE( QBuffer& buffer, uint bytesPerP const auto rectDataSize = qFromBigEndian( hdr.nSubrects ) * ( bytesPerPixel + 4 ); const auto totalDataSize = static_cast( bytesPerPixel + rectDataSize ); - return buffer.read( totalDataSize ).size() == totalDataSize; + return totalDataSize < MaxMessageSize && buffer.read( totalDataSize ).size() == totalDataSize; } bool VncClientProtocol::handleRectEncodingHextile( QBuffer& buffer, - const rfbFramebufferUpdateRectHeader rectHeader, - uint bytesPerPixel ) + const rfbFramebufferUpdateRectHeader rectHeader, + uint bytesPerPixel ) { const uint rx = rectHeader.r.x; const uint ry = rectHeader.r.y; @@ -654,7 +695,8 @@ bool VncClientProtocol::handleRectEncodingHextile( QBuffer& buffer, { for( uint x = rx; x < rx+rw; x += 16 ) { - uint w = 16, h = 16; + uint w = 16; + uint h = 16; if( rx+rw - x < 16 ) { w = rx+rw - x; @@ -741,7 +783,7 @@ bool VncClientProtocol::handleRectEncodingZlib( QBuffer& buffer ) const auto n = qFromBigEndian( hdr.nBytes ); - return buffer.read( n ).size() == static_cast( n ); + return n < MaxMessageSize && uint32_t(buffer.read(n).size()) == n; } @@ -757,7 +799,167 @@ bool VncClientProtocol::handleRectEncodingZRLE(QBuffer &buffer) const auto n = qFromBigEndian( hdr.length ); - return buffer.read( n ).size() == static_cast( n ); + return n < MaxMessageSize && uint32_t(buffer.read(n).size()) == n; +} + + + +bool VncClientProtocol::handleRectEncodingTight(QBuffer& buffer, + const rfbFramebufferUpdateRectHeader rectHeader) +{ + static const auto readCompactLength = [](QBuffer& buffer) -> int64_t + { + int64_t len; + uint8_t b; + + if (buffer.read(reinterpret_cast(&b), 1 ) != 1) + { + return -1; + } + + len = int(b) & 0x7f; + + if (b & 0x80) + { + if (buffer.read(reinterpret_cast(&b), 1) != 1) + { + return -1; + } + + len |= (int(b) & 0x7f) << 7; + + if (b & 0x80) + { + if (buffer.read(reinterpret_cast(&b), 1) != 1) + { + return -1; + } + + len |= (int(b) & 0xff) << 14; + } + } + + return len; + }; + + auto bitsPerPixel = m_pixelFormat.bitsPerPixel; + if (bitsPerPixel == 32 && + m_pixelFormat.depth == 24 && + m_pixelFormat.redMax == 255 && + m_pixelFormat.greenMax == 255 && + m_pixelFormat.blueMax == 255) + { + bitsPerPixel = 24; + } + + const auto bytesPerPixel = bitsPerPixel / 8; + + uint8_t compCtl = 255; + if (buffer.read(reinterpret_cast(&compCtl), 1) != 1) + { + return false; + } + + compCtl >>= 4; // ignore compression stream reset bits + + if ((compCtl & rfbTightNoZlib) == rfbTightNoZlib) + { + compCtl &= ~(rfbTightNoZlib); + } + + if (compCtl == rfbTightFill) + { + return buffer.read(bytesPerPixel).size() == bytesPerPixel; + } + + if (compCtl == rfbTightJpeg) + { + const auto dataLength = readCompactLength(buffer); + return buffer.read(dataLength).size() == dataLength; + } + + if (compCtl > rfbTightMaxSubencoding) + { + vWarning() << "bad subencoding value received"; + return false; + } + + if (compCtl & rfbTightExplicitFilter) + { + uint8_t filterId = 0; + if (buffer.read(reinterpret_cast(&filterId), 1) != 1) + { + return false; + } + + switch (filterId) + { + case rfbTightFilterCopy: + break; + case rfbTightFilterPalette: + { + uint8_t numColors; + if (buffer.read(reinterpret_cast(&numColors), 1) != 1) + { + return false; + } + const auto tightRectColors = numColors + 1; + if (tightRectColors < 2) + { + return false; + } + const auto rectBytes = tightRectColors * bytesPerPixel; + if (buffer.read(rectBytes).size() != rectBytes) + { + return false; + } + bitsPerPixel = tightRectColors == 2 ? 1 : 8; + break; + } + case rfbTightFilterGradient: + break; + default: + vWarning() << "invalid filter ID"; + return false; + } + } + + const int MaximumUncompressedSize = 12; + + const int rowSize = (rectHeader.r.w * bitsPerPixel + 7) / 8; + const int uncompressedRectSize = rectHeader.r.h * rowSize; + if (uncompressedRectSize < MaximumUncompressedSize) + { + return buffer.read(uncompressedRectSize).size() == uncompressedRectSize; + } + + const auto compressedLength = readCompactLength(buffer); + if (compressedLength <= 0) + { + vWarning() << "bad compressed length received"; + return false; + } + + return buffer.read(compressedLength).size() == compressedLength; +} + + + +bool VncClientProtocol::handleRectEncodingExtDesktopSize(QBuffer& buffer) +{ + rfbExtDesktopSizeMsg extDesktopSizeMsg; + if (buffer.peek(reinterpret_cast(&extDesktopSizeMsg), sz_rfbExtDesktopSizeMsg) != sz_rfbExtDesktopSizeMsg) + { + return false; + } + + const auto totalMessageSize = sz_rfbExtDesktopSizeMsg + extDesktopSizeMsg.numberOfScreens * sz_rfbExtDesktopScreen; + if (buffer.bytesAvailable() >= totalMessageSize) + { + return buffer.read(totalMessageSize).size() == totalMessageSize; + } + + return false; } diff --git a/core/include/VncClientProtocol.h b/core/src/VncClientProtocol.h similarity index 73% rename from core/include/VncClientProtocol.h rename to core/src/VncClientProtocol.h index 8b03fd2f8..a7d709788 100644 --- a/core/include/VncClientProtocol.h +++ b/core/src/VncClientProtocol.h @@ -1,7 +1,7 @@ /* * VncClientProtocol.h - header file for the VncClientProtocol class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,19 +24,22 @@ #pragma once -#include - #include "rfb/rfbproto.h" -#include "VeyonCore.h" +#include + +#include "CryptoCore.h" class QBuffer; -class QTcpSocket; +class QIODevice; class VEYON_CORE_EXPORT VncClientProtocol { public: - enum State { + using Password = CryptoCore::PlaintextPassword; + + enum class State + { Disconnected, Protocol, SecurityInit, @@ -47,7 +50,7 @@ class VEYON_CORE_EXPORT VncClientProtocol StateCount } ; - VncClientProtocol( QTcpSocket* socket, const QString& vncPassword ); + VncClientProtocol( QIODevice* socket, const Password& vncPassword ); State state() const { @@ -72,8 +75,11 @@ class VEYON_CORE_EXPORT VncClientProtocol return m_framebufferHeight; } - bool setPixelFormat( rfbPixelFormat pixelFormat ); - bool setEncodings( const QVector& encodings ); + void setPixelFormat(rfbPixelFormat pixelFormat); + void setEncodings(const QVector& encodings); + + bool sendPixelFormat(); + bool sendEncodings(); void requestFramebufferUpdate( bool incremental ); @@ -94,7 +100,15 @@ class VEYON_CORE_EXPORT VncClientProtocol return m_lastUpdatedRect; } +protected: + void setState(State state) + { + m_state = state; + } + private: + static constexpr auto MaxMessageSize = 64*1024*1024; + bool readProtocol(); bool receiveSecurityTypes(); bool receiveSecurityChallenge(); @@ -118,20 +132,26 @@ class VEYON_CORE_EXPORT VncClientProtocol uint bytesPerPixel ); bool handleRectEncodingZlib( QBuffer& buffer ); bool handleRectEncodingZRLE( QBuffer& buffer ); + bool handleRectEncodingTight(QBuffer& buffer, + const rfbFramebufferUpdateRectHeader rectHeader); + bool handleRectEncodingExtDesktopSize(QBuffer& buffer); static bool isPseudoEncoding( rfbFramebufferUpdateRectHeader header ); - QTcpSocket* m_socket; - State m_state; + static constexpr auto MaximumMessageSize = 4096*4096*4; + + QIODevice* m_socket{nullptr}; + State m_state{State::Disconnected}; - QByteArray m_vncPassword; + Password m_vncPassword{}; - QByteArray m_serverInitMessage; + QByteArray m_serverInitMessage{}; - rfbPixelFormat m_pixelFormat; + rfbPixelFormat m_pixelFormat{}; + QVector m_encodings{}; - quint16 m_framebufferWidth; - quint16 m_framebufferHeight; + quint16 m_framebufferWidth{0}; + quint16 m_framebufferHeight{0}; QByteArray m_lastMessage; QRect m_lastUpdatedRect; diff --git a/core/src/VncConnection.cpp b/core/src/VncConnection.cpp index fc98699b3..f75f5290b 100644 --- a/core/src/VncConnection.cpp +++ b/core/src/VncConnection.cpp @@ -1,7 +1,7 @@ /* * VncConnection.cpp - implementation of VncConnection class * - * Copyright (c) 2008-2019 Tobias Junghans + * Copyright (c) 2008-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,167 +31,47 @@ #include #include #include +#include +#include #include #include "PlatformNetworkFunctions.h" #include "VeyonConfiguration.h" #include "VncConnection.h" +#include "RfbClientCallback.h" #include "SocketDevice.h" #include "VncEvents.h" -rfbBool VncConnection::hookInitFrameBuffer( rfbClient* client ) -{ - auto connection = static_cast( clientData( client, VncConnectionTag ) ); - if( connection ) - { - return connection->initFrameBuffer( client ); - } - - return false; -} - - - - -void VncConnection::hookUpdateFB( rfbClient* client, int x, int y, int w, int h ) -{ - auto connection = static_cast( clientData( client, VncConnectionTag ) ); - if( connection ) - { - emit connection->imageUpdated( x, y, w, h ); - } -} - - - - -void VncConnection::hookFinishFrameBufferUpdate( rfbClient* client ) -{ - auto connection = static_cast( clientData( client, VncConnectionTag ) ); - if( connection ) - { - connection->finishFrameBufferUpdate(); - } -} - - - - -rfbBool VncConnection::hookHandleCursorPos( rfbClient* client, int x, int y ) -{ - auto connection = static_cast( clientData( client, VncConnectionTag ) ); - if( connection ) - { - emit connection->cursorPosChanged( x, y ); - } - - return true; -} - - - - -void VncConnection::hookCursorShape( rfbClient* client, int xh, int yh, int w, int h, int bpp ) -{ - if( bpp != 4 ) - { - vWarning() << QThread::currentThreadId() << "bytes per pixel != 4"; - return; - } - - QImage alpha( client->rcMask, w, h, QImage::Format_Indexed8 ); - alpha.setColorTable( { qRgb(255,255,255), qRgb(0,0,0) } ); - - QPixmap cursorShape( QPixmap::fromImage( QImage( client->rcSource, w, h, QImage::Format_RGB32 ) ) ); - cursorShape.setMask( QBitmap::fromImage( alpha ) ); - - auto connection = static_cast( clientData( client, VncConnectionTag ) ); - if( connection ) - { - emit connection->cursorShapeUpdated( cursorShape, xh, yh ); - } -} - - - -void VncConnection::hookCutText( rfbClient* client, const char* text, int textlen ) -{ - auto connection = static_cast( clientData( client, VncConnectionTag ) ); - const auto cutText = QString::fromUtf8( text, textlen ); - - if( connection && cutText.isEmpty() == false ) - { - emit connection->gotCut( cutText ); - } -} - - - -void VncConnection::rfbClientLogDebug( const char* format, ... ) -{ - va_list args; - va_start( args, format ); - - static constexpr int MaxMessageLength = 256; - char message[MaxMessageLength]; - - vsnprintf( message, sizeof(message), format, args ); - message[MaxMessageLength-1] = 0; - - va_end(args); - - vDebug() << QThread::currentThreadId() << message; -} - - - - -void VncConnection::rfbClientLogNone( const char* format, ... ) -{ - Q_UNUSED(format); -} - - - -void VncConnection::framebufferCleanup( void* framebuffer ) -{ - delete[] static_cast( framebuffer ); -} - - - - VncConnection::VncConnection( QObject* parent ) : QThread( parent ), - m_state( State::Disconnected ), - m_framebufferState( FramebufferState::Invalid ), - m_controlFlags(), - m_client( nullptr ), - m_quality( Quality::Default ), - m_host(), - m_port( -1 ), - m_globalMutex(), - m_eventQueueMutex(), - m_updateIntervalSleeper(), - m_framebufferUpdateInterval( 0 ), - m_image(), - m_scaledScreen(), - m_scaledSize(), - m_imgLock() + m_verifyServerCertificate( VeyonCore::config().tlsUseCertificateAuthority() ), + m_defaultPort( VeyonCore::config().veyonServerPort() ) { + if( VeyonCore::config().useCustomVncConnectionSettings() ) + { + m_threadTerminationTimeout = VeyonCore::config().vncConnectionThreadTerminationTimeout(); + m_connectTimeout = VeyonCore::config().vncConnectionConnectTimeout(); + m_readTimeout = VeyonCore::config().vncConnectionReadTimeout(); + m_connectionRetryInterval = VeyonCore::config().vncConnectionRetryInterval(); + m_messageWaitTimeout = VeyonCore::config().vncConnectionMessageWaitTimeout(); + m_fastFramebufferUpdateInterval = VeyonCore::config().vncConnectionFastFramebufferUpdateInterval(); + m_initialFramebufferUpdateTimeout = VeyonCore::config().vncConnectionInitialFramebufferUpdateTimeout(); + m_framebufferUpdateTimeout = VeyonCore::config().vncConnectionFramebufferUpdateTimeout(); + m_socketKeepaliveIdleTime = VeyonCore::config().vncConnectionSocketKeepaliveIdleTime(); + m_socketKeepaliveInterval = VeyonCore::config().vncConnectionSocketKeepaliveInterval(); + m_socketKeepaliveCount = VeyonCore::config().vncConnectionSocketKeepaliveCount(); + } } VncConnection::~VncConnection() { - stop(); - if( isRunning() ) { vWarning() << "Waiting for VNC connection thread to finish."; - wait( ThreadTerminationTimeout ); + wait( m_threadTerminationTimeout ); } if( isRunning() ) @@ -231,7 +111,15 @@ QImage VncConnection::image() void VncConnection::restart() { - setControlFlag( ControlFlag::RestartConnection, true ); + if (isRunning()) + { + setControlFlag(ControlFlag::RestartConnection, true); + } + else + { + setControlFlag(ControlFlag::TerminateThread, false); + start(); + } } @@ -240,7 +128,7 @@ void VncConnection::stop() { setClientData( VncConnectionTag, nullptr ); - m_scaledScreen = {}; + m_scaledFramebuffer = {}; setControlFlag( ControlFlag::TerminateThread, true ); @@ -253,12 +141,12 @@ void VncConnection::stopAndDeleteLater() { if( isRunning() ) { - connect( this, &VncConnection::finished, this, &VncConnection::deleteLater ); + setControlFlag( ControlFlag::DeleteAfterFinished, true ); stop(); } else { - deleteLater(); + deleteLaterInMainThread(); } } @@ -269,26 +157,37 @@ void VncConnection::setHost( const QString& host ) QMutexLocker locker( &m_globalMutex ); m_host = host; - // is IPv6-mapped IPv4 address? - QRegExp rx( QStringLiteral( "::[fF]{4}:(\\d+.\\d+.\\d+.\\d+)" ) ); - if( rx.indexIn( m_host ) == 0 ) - { - // then use plain IPv4 address as libvncclient cannot handle - // IPv6-mapped IPv4 addresses on Windows properly - m_host = rx.cap( 1 ); - } - else if( m_host == QLatin1String( "::1" ) ) - { - m_host = QHostAddress( QHostAddress::LocalHost ).toString(); - } - else if( m_host.count( QLatin1Char(':') ) == 1 ) - { - // hostname + port number? - QRegExp rx2( QStringLiteral("(.*[^:]):(\\d+)$") ); - if( rx2.indexIn( m_host ) == 0 ) + static const QRegularExpression ipv6MappedRX1{QStringLiteral("^::[fF]{4}:(\\d+.\\d+.\\d+.\\d+)$")}; + static const QRegularExpression ipv6MappedRX2{QStringLiteral("^::[fF]{4}:(\\d+.\\d+.\\d+.\\d+):(\\d+)$")}; + static const QRegularExpression ipv6MappedRX3{QStringLiteral("^\\[::[fF]{4}:(\\d+.\\d+.\\d+.\\d+)\\]:(\\d+)$")}; + static const QRegularExpression ipv6WithPortRX{QStringLiteral("^\\[([0-9a-fA-F:]+)\\]:(\\d+)$")}; + static const QRegularExpression ipv6IrregularWithPortRX{QStringLiteral("^([0-9a-fA-F:]+):(\\d{5})$"), QRegularExpression::InvertedGreedinessOption}; + static const QRegularExpression anyWithPortRX{QStringLiteral("^([^:]+):(\\d+)$")}; + + QRegularExpressionMatch match; + if( + // if IPv6-mapped IPv4 address use plain IPv4 address as libvncclient cannot handle IPv6-mapped IPv4 addresses on Windows properly + (match = ipv6MappedRX1.match(m_host)).hasMatch() || + (match = ipv6MappedRX2.match(m_host)).hasMatch() || + (match = ipv6MappedRX3.match(m_host)).hasMatch() || + // any other IPv6 address with port number + (match = ipv6WithPortRX.match(m_host)).hasMatch() || + // irregular IPv6 address + port number specification where port number can be identified if > 9999 + (match = ipv6IrregularWithPortRX.match(m_host)).hasMatch() || + // any other notation with trailing port number + (match = anyWithPortRX.match(m_host)).hasMatch() + ) + { + const auto matchedHost = match.captured( 1 ); + if( matchedHost.isEmpty() == false ) { - m_host = rx2.cap( 1 ); - m_port = rx2.cap( 2 ).toInt(); + m_host = matchedHost; + } + + const auto port = match.captured( 2 ).toInt(); + if( port > 0 ) + { + m_port = port; } } } @@ -306,6 +205,33 @@ void VncConnection::setPort( int port ) +void VncConnection::setQuality(VncConnectionConfiguration::Quality quality) +{ + m_quality = quality; + + if (m_client) + { + updateEncodingSettingsFromQuality(); + enqueueEvent(new VncUpdateFormatAndEncodingsEvent); + } +} + + + +void VncConnection::setUseRemoteCursor( bool enabled ) +{ + m_useRemoteCursor = enabled; + + if( m_client ) + { + m_client->appData.useRemoteCursor = enabled ? TRUE : FALSE; + + enqueueEvent(new VncUpdateFormatAndEncodingsEvent); + } +} + + + void VncConnection::setServerReachable() { setControlFlag( ControlFlag::ServerReachable, true ); @@ -313,6 +239,30 @@ void VncConnection::setServerReachable() +void VncConnection::enqueueEvent(VncEvent* event) +{ + if( state() != State::Connected ) + { + return; + } + + m_eventQueueMutex.lock(); + m_eventQueue.enqueue( event ); + m_eventQueueMutex.unlock(); + + m_updateIntervalSleeper.wakeAll(); +} + + + +bool VncConnection::isEventQueueEmpty() +{ + QMutexLocker lock( &m_eventQueueMutex ); + return m_eventQueue.isEmpty(); +} + + + void VncConnection::setScaledSize( QSize s ) { QMutexLocker globalLock( &m_globalMutex ); @@ -320,16 +270,16 @@ void VncConnection::setScaledSize( QSize s ) if( m_scaledSize != s ) { m_scaledSize = s; - setControlFlag( ControlFlag::ScaledScreenNeedsUpdate, true ); + setControlFlag( ControlFlag::ScaledFramebufferNeedsUpdate, true ); } } -QImage VncConnection::scaledScreen() +QImage VncConnection::scaledFramebuffer() { - rescaleScreen(); - return m_scaledScreen; + rescaleFramebuffer(); + return m_scaledFramebuffer; } @@ -337,33 +287,43 @@ QImage VncConnection::scaledScreen() void VncConnection::setFramebufferUpdateInterval( int interval ) { m_framebufferUpdateInterval = interval; + + if (state() == State::Connected) + { + if (m_framebufferUpdateInterval <= 0) + { + setControlFlag(ControlFlag::TriggerFramebufferUpdate, true); + } + + m_updateIntervalSleeper.wakeAll(); + } } -void VncConnection::rescaleScreen() +void VncConnection::rescaleFramebuffer() { - if( hasValidFrameBuffer() == false || m_scaledSize.isNull() ) + if( hasValidFramebuffer() == false || m_scaledSize.isNull() ) { - m_scaledScreen = {}; + m_scaledFramebuffer = {}; return; } - if( isControlFlagSet( ControlFlag::ScaledScreenNeedsUpdate ) == false ) + if( isControlFlagSet( ControlFlag::ScaledFramebufferNeedsUpdate ) == false ) { return; } QReadLocker locker( &m_imgLock ); - if( m_image.size().isValid() == false ) + if (m_image.isNull() || m_image.size().isValid() == false) { return; } - m_scaledScreen = m_image.scaled( m_scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); + m_scaledFramebuffer = m_image.scaled( m_scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); - setControlFlag( ControlFlag::ScaledScreenNeedsUpdate, false ); + setControlFlag( ControlFlag::ScaledFramebufferNeedsUpdate, false ); } @@ -392,13 +352,65 @@ void VncConnection::setClientData( int tag, void* data ) +qint64 VncConnection::libvncClientDispatcher( char* buffer, const qint64 bytes, + SocketDevice::SocketOperation operation, void* user ) +{ + auto client = static_cast( user ); + switch( operation ) + { + case SocketDevice::SocketOpRead: + return ReadFromRFBServer( client, buffer, static_cast( bytes ) ) ? bytes : 0; + + case SocketDevice::SocketOpWrite: + return WriteToRFBServer( client, buffer, static_cast( bytes ) ) ? bytes : 0; + } + + return 0; +} + + + +void VncConnection::mouseEvent( int x, int y, uint buttonMask ) +{ + enqueueEvent(new VncPointerEvent(x, y, buttonMask)); +} + + + +void VncConnection::keyEvent( unsigned int key, bool pressed ) +{ + enqueueEvent(new VncKeyEvent(key, pressed)); +} + + + +void VncConnection::clientCut( const QString& text ) +{ + enqueueEvent(new VncClientCutEvent(text )); +} + + + void VncConnection::run() { while( isControlFlagSet( ControlFlag::TerminateThread ) == false ) { + QElapsedTimer connectionTimer; + connectionTimer.start(); + establishConnection(); handleConnection(); closeConnection(); + + const auto minimumConnectionTime = m_framebufferUpdateInterval > 0 ? + int(m_framebufferUpdateInterval) : + m_connectionRetryInterval; + QThread::msleep(std::max(0, minimumConnectionTime - connectionTimer.elapsed())); + } + + if( isControlFlagSet( ControlFlag::DeleteAfterFinished ) ) + { + deleteLaterInMainThread(); } } @@ -416,23 +428,34 @@ void VncConnection::establishConnection() while( isControlFlagSet( ControlFlag::TerminateThread ) == false && state() != State::Connected ) // try to connect as long as the server allows { + m_globalMutex.lock(); m_client = rfbGetClient( RfbBitsPerSample, RfbSamplesPerPixel, RfbBytesPerPixel ); - m_client->MallocFrameBuffer = hookInitFrameBuffer; m_client->canHandleNewFBSize = true; - m_client->GotFrameBufferUpdate = hookUpdateFB; - m_client->FinishedFrameBufferUpdate = hookFinishFrameBufferUpdate; - m_client->HandleCursorPos = hookHandleCursorPos; - m_client->GotCursorShape = hookCursorShape; - m_client->GotXCutText = hookCutText; + m_client->MallocFrameBuffer = RfbClientCallback::wrap<&VncConnection::initFrameBuffer>; + m_client->GotFrameBufferUpdate = RfbClientCallback::wrap<&VncConnection::imageUpdated>; + m_client->FinishedFrameBufferUpdate = RfbClientCallback::wrap<&VncConnection::finishFrameBufferUpdate>; + m_client->HandleCursorPos = RfbClientCallback::wrap<&VncConnection::updateCursorPosition>; + m_client->GotCursorShape = RfbClientCallback::wrap<&VncConnection::updateCursorShape>; + m_client->GotXCutText = RfbClientCallback::wrap<&VncConnection::updateClipboard>; + + m_client->ConnectToRFBServer = RfbClientCallback::wrap<&VncConnection::openTlsSocket, RFB_INVALID_SOCKET>; + m_client->ReadFromSocket = RfbClientCallback::wrap<&VncConnection::readFromTlsSocket, -1>; + m_client->WriteToSocket = RfbClientCallback::wrap<&VncConnection::writeToTlsSocket, -1>; + m_client->CloseSocket = RfbClientCallback::wrap<&VncConnection::closeTlsSocket>; + + m_client->connectTimeout = m_connectTimeout / 1000; + m_client->readTimeout = m_readTimeout / 1000; + m_globalMutex.unlock(); + setClientData( VncConnectionTag, this ); - emit connectionPrepared(); + Q_EMIT connectionPrepared(); m_globalMutex.lock(); if( m_port < 0 ) // use default port? { - m_client->serverPort = VeyonCore::config().primaryServicePort(); + m_client->serverPort = m_defaultPort; } else { @@ -446,41 +469,55 @@ void VncConnection::establishConnection() setControlFlag( ControlFlag::ServerReachable, false ); - if( rfbInitClient( m_client, nullptr, nullptr ) && - isControlFlagSet( ControlFlag::TerminateThread ) == false ) + const auto clientInitialized = rfbInitClient( m_client, nullptr, nullptr ); + if( clientInitialized == FALSE ) { - m_framebufferUpdateWatchdog.restart(); + // rfbInitClient() calls rfbClientCleanup() when failed + m_client = nullptr; + } + + // do not continue/sleep when already requested to stop + if( isControlFlagSet( ControlFlag::TerminateThread ) ) + { + return; + } - emit connectionEstablished(); + if( clientInitialized ) + { + m_fullFramebufferUpdateTimer.restart(); + m_incrementalFramebufferUpdateTimer.restart(); VeyonCore::platform().networkFunctions(). configureSocketKeepalive( static_cast( m_client->sock ), true, - SocketKeepaliveIdleTime, SocketKeepaliveInterval, SocketKeepaliveCount ); + m_socketKeepaliveIdleTime, m_socketKeepaliveInterval, m_socketKeepaliveCount ); setState( State::Connected ); } else { - // rfbInitClient() calls rfbClientCleanup() when failed - m_client = nullptr; - - // do not sleep when already requested to stop - if( isControlFlagSet( ControlFlag::TerminateThread ) ) - { - break; - } - // guess reason why connection failed if( isControlFlagSet( ControlFlag::ServerReachable ) == false ) { - if( VeyonCore::platform().networkFunctions().ping( m_host ) == false ) + if (isControlFlagSet(ControlFlag::SkipHostPing)) { - setState( State::HostOffline ); + setState(State::HostOffline); } else { - setState( State::ServiceUnreachable ); + const auto pingResult = VeyonCore::platform().networkFunctions().ping(m_host); + switch (pingResult) + { + case PlatformNetworkFunctions::PingResult::ReplyReceived: + setState(State::ServerNotRunning); + break; + case PlatformNetworkFunctions::PingResult::NameResolutionFailed: + setState(State::HostNameResolutionFailed); + break; + default: + setState(State::HostOffline); + } } + } else if( m_framebufferState == FramebufferState::Invalid ) { @@ -496,12 +533,12 @@ void VncConnection::establishConnection() sleeperMutex.lock(); if( m_framebufferUpdateInterval > 0 ) { - m_updateIntervalSleeper.wait( &sleeperMutex, QDeadlineTimer( m_framebufferUpdateInterval ) ); + m_updateIntervalSleeper.wait( &sleeperMutex, m_framebufferUpdateInterval ); } else { // default: retry every second - m_updateIntervalSleeper.wait( &sleeperMutex, QDeadlineTimer( ConnectionRetryInterval ) ); + m_updateIntervalSleeper.wait( &sleeperMutex, m_connectionRetryInterval ); } sleeperMutex.unlock(); } @@ -521,12 +558,19 @@ void VncConnection::handleConnection() { loopTimer.start(); - const int i = WaitForMessage( m_client, MessageWaitTimeout ); + const auto waitTimeout = isControlFlagSet(ControlFlag::SkipFramebufferUpdates) ? + m_messageWaitTimeout / 10 + : + (m_framebufferUpdateInterval > 0 ? m_messageWaitTimeout * 100 : m_messageWaitTimeout); + + const int i = WaitForMessage(m_client, waitTimeout); + if( isControlFlagSet( ControlFlag::TerminateThread ) || i < 0 ) { break; } - else if( i ) + + if( i ) { // handle all available messages bool handledOkay = true; @@ -539,28 +583,32 @@ void VncConnection::handleConnection() break; } } - - sendEvents(); - - const auto remainingUpdateInterval = m_framebufferUpdateInterval - loopTimer.elapsed(); - - if( m_framebufferState == FramebufferState::Initialized || - m_framebufferUpdateWatchdog.elapsed() >= qMax( 2*m_framebufferUpdateInterval, FramebufferUpdateWatchdogTimeout ) ) + else if (m_fullFramebufferUpdateTimer.elapsed() >= fullFramebufferUpdateTimeout()) { - SendFramebufferUpdateRequest( m_client, 0, 0, m_client->width, m_client->height, false ); + requestFrameufferUpdate(FramebufferUpdateType::Full); + m_fullFramebufferUpdateTimer.restart(); + } + else if (m_framebufferUpdateInterval > 0 && + m_incrementalFramebufferUpdateTimer.elapsed() > incrementalFramebufferUpdateTimeout()) + { + requestFrameufferUpdate(FramebufferUpdateType::Incremental); + m_incrementalFramebufferUpdateTimer.restart(); + } + else if (isControlFlagSet(ControlFlag::TriggerFramebufferUpdate)) + { + setControlFlag(ControlFlag::TriggerFramebufferUpdate, false); + requestFrameufferUpdate(FramebufferUpdateType::Incremental); + } - const auto remainingFastUpdateInterval = FastFramebufferUpdateInterval - loopTimer.elapsed(); + const auto remainingUpdateInterval = m_framebufferUpdateInterval - loopTimer.elapsed(); - sleeperMutex.lock(); - m_updateIntervalSleeper.wait( &sleeperMutex, QDeadlineTimer( remainingFastUpdateInterval ) ); - sleeperMutex.unlock(); - } - else if( m_framebufferState == FramebufferState::Valid && - remainingUpdateInterval > 0 && - isControlFlagSet( ControlFlag::TerminateThread ) == false ) + // compat with Veyon Server < 4.7 + if (remainingUpdateInterval > 0 && + isControlFlagSet(ControlFlag::RequiresManualUpdateRateControl) && + isControlFlagSet(ControlFlag::TerminateThread) == false) { sleeperMutex.lock(); - m_updateIntervalSleeper.wait( &sleeperMutex, QDeadlineTimer( remainingUpdateInterval ) ); + m_updateIntervalSleeper.wait( &sleeperMutex, remainingUpdateInterval ); sleeperMutex.unlock(); } @@ -587,7 +635,7 @@ void VncConnection::setState( State state ) { if( m_state.exchange( state ) != state ) { - emit stateChanged(); + Q_EMIT stateChanged(); } } @@ -597,11 +645,11 @@ void VncConnection::setControlFlag( VncConnection::ControlFlag flag, bool on ) { if( on ) { - m_controlFlags |= static_cast( flag ); + m_controlFlags |= uint( flag ); } else { - m_controlFlags &= ~static_cast( flag ); + m_controlFlags &= ~uint( flag ); } } @@ -609,13 +657,13 @@ void VncConnection::setControlFlag( VncConnection::ControlFlag flag, bool on ) bool VncConnection::isControlFlagSet( VncConnection::ControlFlag flag ) { - return m_controlFlags & static_cast( flag ); + return m_controlFlags & uint( flag ); } -bool VncConnection::initFrameBuffer( rfbClient* client ) +rfbBool VncConnection::initFrameBuffer( rfbClient* client ) { if( client->format.bitsPerPixel != RfbBitsPerSample * RfbBytesPerPixel ) { @@ -623,7 +671,7 @@ bool VncConnection::initFrameBuffer( rfbClient* client ) return false; } - const auto pixelCount = static_cast( client->width ) * client->height; + const auto pixelCount = uint32_t(client->width) * uint32_t(client->height); client->frameBuffer = reinterpret_cast( new RfbPixel[pixelCount] ); @@ -643,48 +691,131 @@ bool VncConnection::initFrameBuffer( rfbClient* client ) client->format.greenMax = 0xff; client->format.blueMax = 0xff; - client->appData.encodingsString = "zrle ultra copyrect hextile zlib corre rre raw"; - client->appData.useRemoteCursor = false; - client->appData.compressLevel = 0; + client->appData.useRemoteCursor = m_useRemoteCursor ? TRUE : FALSE; client->appData.useBGR233 = false; - client->appData.qualityLevel = 9; - client->appData.enableJPEG = false; - - switch( m_quality ) - { - case Quality::Screenshot: - // make sure to use lossless raw encoding - client->appData.encodingsString = "raw"; - break; - case Quality::RemoteControl: - client->appData.useRemoteCursor = true; - break; - case Quality::Thumbnail: - client->appData.compressLevel = 9; - client->appData.qualityLevel = 5; - client->appData.enableJPEG = true; - break; - default: - break; - } + + updateEncodingSettingsFromQuality(); m_framebufferState = FramebufferState::Initialized; - emit framebufferSizeChanged( client->width, client->height ); + Q_EMIT framebufferSizeChanged( client->width, client->height ); return true; } +void VncConnection::requestFrameufferUpdate(FramebufferUpdateType updateType) +{ + if (isControlFlagSet(ControlFlag::SkipFramebufferUpdates) == false) + { + switch (updateType) + { + case FramebufferUpdateType::Incremental: + SendIncrementalFramebufferUpdateRequest(m_client); + break; + case FramebufferUpdateType::Full: + SendFramebufferUpdateRequest(m_client, 0, 0, m_client->width, m_client->height, false); + break; + } + } +} + + + void VncConnection::finishFrameBufferUpdate() { - m_framebufferUpdateWatchdog.restart(); + m_incrementalFramebufferUpdateTimer.restart(); + m_fullFramebufferUpdateTimer.restart(); m_framebufferState = FramebufferState::Valid; - setControlFlag( ControlFlag::ScaledScreenNeedsUpdate, true ); + setControlFlag( ControlFlag::ScaledFramebufferNeedsUpdate, true ); + + Q_EMIT framebufferUpdateComplete(); +} + + + +int VncConnection::fullFramebufferUpdateTimeout() const +{ + return m_framebufferState == FramebufferState::Valid ? + m_framebufferUpdateTimeout + : + std::max(int(m_framebufferUpdateInterval), m_initialFramebufferUpdateTimeout); +} + + + +int VncConnection::incrementalFramebufferUpdateTimeout() const +{ + return m_framebufferState == FramebufferState::Valid ? + int(m_framebufferUpdateInterval) + : + std::min(int(m_framebufferUpdateInterval), m_initialFramebufferUpdateTimeout); +} + + + +void VncConnection::updateEncodingSettingsFromQuality() +{ + m_client->appData.encodingsString = m_quality == VncConnectionConfiguration::Quality::Highest ? + "zrle ultra copyrect hextile zlib corre rre raw" : + "tight zywrle zrle ultra"; + + m_client->appData.compressLevel = 9; + + m_client->appData.qualityLevel = [this] { + switch(m_quality) + { + case VncConnectionConfiguration::Quality::Highest: return 9; + case VncConnectionConfiguration::Quality::High: return 7; + case VncConnectionConfiguration::Quality::Medium: return 5; + case VncConnectionConfiguration::Quality::Low: return 3; + case VncConnectionConfiguration::Quality::Lowest: return 0; + } + return 5; + }(); + + m_client->appData.enableJPEG = m_quality != VncConnectionConfiguration::Quality::Highest; +} + - emit framebufferUpdateComplete(); + +rfbBool VncConnection::updateCursorPosition( int x, int y ) +{ + Q_EMIT cursorPosChanged( x, y ); + return true; +} + + + +void VncConnection::updateCursorShape( rfbClient* client, int xh, int yh, int w, int h, int bpp ) +{ + if( bpp != 4 ) + { + vWarning() << QThread::currentThreadId() << "bytes per pixel != 4"; + return; + } + + QImage alpha( client->rcMask, w, h, QImage::Format_Indexed8 ); + alpha.setColorTable( { qRgb(255,255,255), qRgb(0,0,0) } ); + + QPixmap cursorShape( QPixmap::fromImage( QImage( client->rcSource, w, h, QImage::Format_RGB32 ) ) ); + cursorShape.setMask( QBitmap::fromImage( alpha ) ); + + Q_EMIT cursorShapeUpdated( cursorShape, xh, yh ); +} + + + +void VncConnection::updateClipboard( const char* text, int textlen ) +{ + const auto cutText = QString::fromUtf8( text, textlen ); + + if( cutText.isEmpty() == false ) + { + Q_EMIT gotCut( cutText ); + } } @@ -716,66 +847,111 @@ void VncConnection::sendEvents() -void VncConnection::enqueueEvent( VncEvent* event, bool wake ) +void VncConnection::deleteLaterInMainThread() { - if( state() != State::Connected ) - { - return; - } + QTimer::singleShot( 0, VeyonCore::instance(), [this]() { delete this; } ); +} - m_eventQueueMutex.lock(); - m_eventQueue.enqueue( event ); - m_eventQueueMutex.unlock(); - if( wake ) - { - m_updateIntervalSleeper.wakeAll(); - } + +void VncConnection::rfbClientLogDebug( const char* format, ... ) +{ + va_list args; + va_start( args, format ); + + static constexpr int MaxMessageLength = 256; + std::array message{}; + + vsnprintf( message.data(), sizeof(message), format, args ); + message[MaxMessageLength-1] = 0; + + va_end(args); + + vDebug() << QThread::currentThreadId() << message.data(); } -bool VncConnection::isEventQueueEmpty() + +void VncConnection::rfbClientLogNone( const char* format, ... ) { - QMutexLocker lock( &m_eventQueueMutex ); - return m_eventQueue.isEmpty(); + Q_UNUSED(format) } -void VncConnection::mouseEvent( int x, int y, int buttonMask ) +void VncConnection::framebufferCleanup( void* framebuffer ) { - enqueueEvent( new VncPointerEvent( x, y, buttonMask ), true ); + delete[] static_cast( framebuffer ); } -void VncConnection::keyEvent( unsigned int key, bool pressed ) +rfbSocket VncConnection::openTlsSocket( const char* hostname, int port ) { - enqueueEvent( new VncKeyEvent( key, pressed ), true ); + delete m_sslSocket; + + m_sslSocket = new QSslSocket; + connect(m_sslSocket, QOverload&>::of(&QSslSocket::sslErrors), + []( const QList &errors) { + for( const auto& err : errors ) + { + vWarning() << "SSL error" << err; + } + } ); + + m_sslSocket->setPeerVerifyMode( m_verifyServerCertificate ? QSslSocket::VerifyPeer : QSslSocket::QueryPeer ); + + m_sslSocket->connectToHostEncrypted( QString::fromUtf8(hostname), port ); + if( m_sslSocket->waitForEncrypted() == false || m_sslSocket->socketDescriptor() < 0 ) + { + delete m_sslSocket; + m_sslSocket = nullptr; + return RFB_INVALID_SOCKET; + } + + return m_sslSocket->socketDescriptor(); } -void VncConnection::clientCut( const QString& text ) +int VncConnection::readFromTlsSocket( char* buffer, unsigned int len ) { - enqueueEvent( new VncClientCutEvent( text ), true ); + if( m_sslSocket == nullptr ) + { + return -1; + } + + if( m_sslSocket->bytesAvailable() <= 0 ) + { + if( m_sslSocket->waitForReadyRead(10) == false ) + { + errno = EAGAIN; + return -1; + } + } + + return m_sslSocket->read( buffer, len ); } -qint64 VncConnection::libvncClientDispatcher( char* buffer, const qint64 bytes, - SocketDevice::SocketOperation operation, void* user ) +int VncConnection::writeToTlsSocket( const char* buffer, unsigned int len ) { - auto client = static_cast( user ); - switch( operation ) + if( m_sslSocket == nullptr ) { - case SocketDevice::SocketOpRead: - return ReadFromRFBServer( client, buffer, static_cast( bytes ) ) ? bytes : 0; - - case SocketDevice::SocketOpWrite: - return WriteToRFBServer( client, buffer, static_cast( bytes ) ) ? bytes : 0; + return -1; } - return 0; + const auto ret = m_sslSocket->write( buffer, len ); + m_sslSocket->flush(); + return ret; +} + + + +void VncConnection::closeTlsSocket() +{ + delete m_sslSocket; + m_sslSocket = nullptr; } diff --git a/core/include/VncConnection.h b/core/src/VncConnection.h similarity index 52% rename from core/include/VncConnection.h rename to core/src/VncConnection.h index 797e635cf..7eb84a4d1 100644 --- a/core/include/VncConnection.h +++ b/core/src/VncConnection.h @@ -1,7 +1,7 @@ /* * VncConnection.h - declaration of VncConnection class * - * Copyright (c) 2008-2019 Tobias Junghans + * Copyright (c) 2008-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,6 +27,8 @@ #pragma once +#include + #include #include #include @@ -36,25 +38,19 @@ #include #include -#include "VeyonCore.h" #include "SocketDevice.h" +#include "VeyonCore.h" +#include "VncConnectionConfiguration.h" using rfbClient = struct _rfbClient; +class QSslSocket; class VncEvent; class VEYON_CORE_EXPORT VncConnection : public QThread { Q_OBJECT public: - enum class Quality - { - Thumbnail, - Screenshot, - RemoteControl, - Default - } ; - enum class FramebufferState { Invalid, @@ -62,21 +58,28 @@ class VEYON_CORE_EXPORT VncConnection : public QThread Valid } ; + enum class FramebufferUpdateType + { + Full, + Incremental + }; + enum class State { None, Disconnected, Connecting, HostOffline, - ServiceUnreachable, + HostNameResolutionFailed, + ServerNotRunning, AuthenticationFailed, + AccessControlFailed, ConnectionFailed, Connected } ; Q_ENUM(State) explicit VncConnection( QObject *parent = nullptr ); - ~VncConnection() override; static void initLogging( bool debug ); @@ -104,29 +107,43 @@ class VEYON_CORE_EXPORT VncConnection : public QThread return m_host; } - void setQuality( Quality quality ) - { - m_quality = quality ; - } + void setQuality(VncConnectionConfiguration::Quality quality); + + void setUseRemoteCursor( bool enabled ); void setServerReachable(); - void enqueueEvent( VncEvent* event, bool wake ); + void enqueueEvent(VncEvent* event); bool isEventQueueEmpty(); /** \brief Returns whether framebuffer data is valid, i.e. at least one full FB update received */ - bool hasValidFrameBuffer() const + bool hasValidFramebuffer() const { return m_framebufferState == FramebufferState::Valid; } void setScaledSize( QSize s ); - QImage scaledScreen(); + QImage scaledFramebuffer(); void setFramebufferUpdateInterval( int interval ); - void rescaleScreen(); + void setSkipFramebufferUpdates(bool on) + { + setControlFlag(ControlFlag::SkipFramebufferUpdates, on); + } + + void setSkipHostPing( bool on ) + { + setControlFlag( ControlFlag::SkipHostPing, on ); + } + + void setRequiresManualUpdateRateControl(bool on) + { + setControlFlag(ControlFlag::RequiresManualUpdateRateControl, on); + } + + void rescaleFramebuffer(); static constexpr int VncConnectionTag = 0x590123; @@ -136,13 +153,12 @@ class VEYON_CORE_EXPORT VncConnection : public QThread static qint64 libvncClientDispatcher( char * buffer, const qint64 bytes, SocketDevice::SocketOperation operation, void * user ); - void mouseEvent( int x, int y, int buttonMask ); + void mouseEvent( int x, int y, uint buttonMask ); void keyEvent( unsigned int key, bool pressed ); void clientCut( const QString& text ); -signals: +Q_SIGNALS: void connectionPrepared(); - void connectionEstablished(); void imageUpdated( int x, int y, int w, int h ); void framebufferUpdateComplete(); void framebufferSizeChanged( int w, int h ); @@ -155,16 +171,6 @@ class VEYON_CORE_EXPORT VncConnection : public QThread void run() override; private: - // intervals and timeouts - static constexpr int ThreadTerminationTimeout = 30000; - static constexpr int ConnectionRetryInterval = 1000; - static constexpr int MessageWaitTimeout = 500; - static constexpr int FastFramebufferUpdateInterval = 100; - static constexpr int FramebufferUpdateWatchdogTimeout = 10000; - static constexpr int SocketKeepaliveIdleTime = 1000; - static constexpr int SocketKeepaliveInterval = 500; - static constexpr int SocketKeepaliveCount = 5; - // RFB parameters using RfbPixel = uint32_t; static constexpr int RfbBitsPerSample = 8; @@ -172,12 +178,19 @@ class VEYON_CORE_EXPORT VncConnection : public QThread static constexpr int RfbBytesPerPixel = sizeof(RfbPixel); enum class ControlFlag { - ScaledScreenNeedsUpdate = 0x01, + ScaledFramebufferNeedsUpdate = 0x01, ServerReachable = 0x02, TerminateThread = 0x04, RestartConnection = 0x08, + DeleteAfterFinished = 0x10, + SkipHostPing = 0x20, + RequiresManualUpdateRateControl = 0x40, + TriggerFramebufferUpdate = 0x80, + SkipFramebufferUpdates = 0x100 }; + ~VncConnection() override; + void establishConnection(); void handleConnection(); void closeConnection(); @@ -187,47 +200,76 @@ class VEYON_CORE_EXPORT VncConnection : public QThread void setControlFlag( ControlFlag flag, bool on ); bool isControlFlagSet( ControlFlag flag ); - bool initFrameBuffer( rfbClient* client ); + rfbBool initFrameBuffer( rfbClient* client ); + void requestFrameufferUpdate(FramebufferUpdateType updateType); void finishFrameBufferUpdate(); + int fullFramebufferUpdateTimeout() const; + int incrementalFramebufferUpdateTimeout() const; + + void updateEncodingSettingsFromQuality(); + + rfbBool updateCursorPosition( int x, int y ); + void updateCursorShape( rfbClient* client, int xh, int yh, int w, int h, int bpp ); + void updateClipboard( const char *text, int textlen ); + void sendEvents(); - // hooks for LibVNCClient - static int8_t hookInitFrameBuffer( rfbClient* client ); - static void hookUpdateFB( rfbClient* client, int x, int y, int w, int h ); - static void hookFinishFrameBufferUpdate( rfbClient* client ); - static int8_t hookHandleCursorPos( rfbClient* client, int x, int y ); - static void hookCursorShape( rfbClient* client, int xh, int yh, int w, int h, int bpp ); - static void hookCutText( rfbClient* client, const char *text, int textlen ); + void deleteLaterInMainThread(); + static void rfbClientLogDebug( const char* format, ... ); static void rfbClientLogNone( const char* format, ... ); static void framebufferCleanup( void* framebuffer ); + rfbSocket openTlsSocket( const char* hostname, int port ); + int readFromTlsSocket( char* buffer, unsigned int len ); + int writeToTlsSocket( const char* buffer, unsigned int len ); + void closeTlsSocket(); + + // intervals and timeouts + int m_threadTerminationTimeout{VncConnectionConfiguration::DefaultThreadTerminationTimeout}; + int m_connectTimeout{VncConnectionConfiguration::DefaultConnectTimeout}; + int m_readTimeout{VncConnectionConfiguration::DefaultReadTimeout}; + int m_connectionRetryInterval{VncConnectionConfiguration::DefaultConnectionRetryInterval}; + int m_messageWaitTimeout{VncConnectionConfiguration::DefaultMessageWaitTimeout}; + int m_fastFramebufferUpdateInterval{VncConnectionConfiguration::DefaultFastFramebufferUpdateInterval}; + int m_initialFramebufferUpdateTimeout{VncConnectionConfiguration::DefaultInitialFramebufferUpdateTimeout}; + int m_framebufferUpdateTimeout{VncConnectionConfiguration::DefaultFramebufferUpdateTimeout}; + int m_socketKeepaliveIdleTime{VncConnectionConfiguration::DefaultSocketKeepaliveIdleTime}; + int m_socketKeepaliveInterval{VncConnectionConfiguration::DefaultSocketKeepaliveInterval}; + int m_socketKeepaliveCount{VncConnectionConfiguration::DefaultSocketKeepaliveCount}; + // states and flags - std::atomic m_state; - std::atomic m_framebufferState; - QAtomicInt m_controlFlags; + std::atomic m_state{State::Disconnected}; + std::atomic m_framebufferState{FramebufferState::Invalid}; + QAtomicInteger m_controlFlags{}; + + QSslSocket* m_sslSocket{nullptr}; + const bool m_verifyServerCertificate{true}; // connection parameters and data - rfbClient* m_client; - Quality m_quality; - QString m_host; - int m_port; + rfbClient* m_client{nullptr}; + VncConnectionConfiguration::Quality m_quality = VncConnectionConfiguration::Quality::Highest; + QString m_host{}; + int m_port{-1}; + int m_defaultPort{-1}; + bool m_useRemoteCursor{false}; // thread and timing control - QMutex m_globalMutex; - QMutex m_eventQueueMutex; - QWaitCondition m_updateIntervalSleeper; - QAtomicInt m_framebufferUpdateInterval; - QElapsedTimer m_framebufferUpdateWatchdog; + QMutex m_globalMutex{}; + QMutex m_eventQueueMutex{}; + QWaitCondition m_updateIntervalSleeper{}; + QAtomicInt m_framebufferUpdateInterval{0}; + QElapsedTimer m_fullFramebufferUpdateTimer{}; + QElapsedTimer m_incrementalFramebufferUpdateTimer{}; // queue for RFB and custom events - QQueue m_eventQueue; + QQueue m_eventQueue{}; // framebuffer data and thread synchronization objects - QImage m_image; - QImage m_scaledScreen; - QSize m_scaledSize; - QReadWriteLock m_imgLock; + QImage m_image{}; + QImage m_scaledFramebuffer{}; + QSize m_scaledSize{}; + QReadWriteLock m_imgLock{}; } ; diff --git a/core/src/VncConnectionConfiguration.h b/core/src/VncConnectionConfiguration.h new file mode 100644 index 000000000..0a925c563 --- /dev/null +++ b/core/src/VncConnectionConfiguration.h @@ -0,0 +1,56 @@ +/* + * VncConnectionConfiguration.h - declaration of VncConnectionConfiguration + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "VeyonCore.h" + +class VEYON_CORE_EXPORT VncConnectionConfiguration +{ + Q_GADGET +public: + enum class Quality + { + Highest, + High, + Medium, + Low, + Lowest + }; + Q_ENUM(Quality) + + // intervals and timeouts + static constexpr int DefaultThreadTerminationTimeout = 30000; + static constexpr int DefaultConnectTimeout = 10000; + static constexpr int DefaultReadTimeout = 30000; + static constexpr int DefaultConnectionRetryInterval = 1000; + static constexpr int DefaultMessageWaitTimeout = 500; + static constexpr int DefaultFastFramebufferUpdateInterval = 100; + static constexpr int DefaultInitialFramebufferUpdateTimeout = 10000; + static constexpr int DefaultFramebufferUpdateTimeout = 60000; + static constexpr int DefaultSocketKeepaliveIdleTime = 1000; + static constexpr int DefaultSocketKeepaliveInterval = 500; + static constexpr int DefaultSocketKeepaliveCount = 5; + +} ; diff --git a/core/src/VncEvents.cpp b/core/src/VncEvents.cpp index 7f0071fdd..ffc981e50 100644 --- a/core/src/VncEvents.cpp +++ b/core/src/VncEvents.cpp @@ -1,7 +1,7 @@ /* * VncEvents.cpp - implementation of VNC event classes * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -36,12 +36,12 @@ VncKeyEvent::VncKeyEvent( unsigned int key, bool pressed ) : void VncKeyEvent::fire( rfbClient* client ) { - SendKeyEvent( client, m_key, m_pressed ); + SendKeyEvent( client, m_key, m_pressed ? TRUE : FALSE ); } -VncPointerEvent::VncPointerEvent(int x, int y, int buttonMask) : +VncPointerEvent::VncPointerEvent(int x, int y, uint buttonMask) : m_x( x ), m_y( y ), m_buttonMask( buttonMask ) @@ -52,7 +52,7 @@ VncPointerEvent::VncPointerEvent(int x, int y, int buttonMask) : void VncPointerEvent::fire(rfbClient *client) { - SendPointerEvent( client, m_x, m_y, m_buttonMask ); + SendPointerEvent( client, m_x, m_y, int(m_buttonMask) ); } @@ -68,3 +68,10 @@ void VncClientCutEvent::fire( rfbClient* client ) { SendClientCutText( client, m_text.data(), m_text.size() ); // clazy:exclude=detaching-member } + + + +void VncUpdateFormatAndEncodingsEvent::fire( rfbClient* client ) +{ + SetFormatAndEncodings(client); +} diff --git a/core/include/VncEvents.h b/core/src/VncEvents.h similarity index 86% rename from core/include/VncEvents.h rename to core/src/VncEvents.h index 92d24190c..1177459f1 100644 --- a/core/include/VncEvents.h +++ b/core/src/VncEvents.h @@ -1,7 +1,7 @@ /* * VncEvent.h - declaration of VncEvent and subclasses * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -55,14 +55,14 @@ class VncKeyEvent : public VncEvent class VncPointerEvent : public VncEvent { public: - VncPointerEvent( int x, int y, int buttonMask ); + VncPointerEvent( int x, int y, uint buttonMask ); void fire( rfbClient* client ) override; private: int m_x; int m_y; - int m_buttonMask; + uint m_buttonMask; } ; @@ -76,3 +76,9 @@ class VncClientCutEvent : public VncEvent private: QByteArray m_text; } ; + +class VncUpdateFormatAndEncodingsEvent : public VncEvent +{ +public: + void fire( rfbClient* client ) override; +}; diff --git a/core/src/VncFeatureMessageEvent.cpp b/core/src/VncFeatureMessageEvent.cpp index 202313f4c..ee566b8ef 100644 --- a/core/src/VncFeatureMessageEvent.cpp +++ b/core/src/VncFeatureMessageEvent.cpp @@ -1,7 +1,7 @@ /* * FeatureMessageEvent.cpp - implementation of FeatureMessageEvent * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,6 +22,8 @@ * */ +#include "rfb/rfbclient.h" + #include "SocketDevice.h" #include "VncConnection.h" #include "VncFeatureMessageEvent.h" @@ -36,13 +38,10 @@ VncFeatureMessageEvent::VncFeatureMessageEvent( const FeatureMessage& featureMes void VncFeatureMessageEvent::fire( rfbClient* client ) { - vDebug() << "sending message" << m_featureMessage.featureUid() - << "command" << m_featureMessage.command() - << "arguments" << m_featureMessage.arguments(); + vDebug() << qUtf8Printable(QStringLiteral("%1:%2").arg(QString::fromUtf8(client->serverHost)).arg(client->serverPort)) + << m_featureMessage; SocketDevice socketDevice( VncConnection::libvncClientDispatcher, client ); - const char messageType = FeatureMessage::RfbMessageType; - socketDevice.write( &messageType, sizeof(messageType) ); - m_featureMessage.send( &socketDevice ); + m_featureMessage.sendAsRfbMessage(&socketDevice); } diff --git a/core/include/VncFeatureMessageEvent.h b/core/src/VncFeatureMessageEvent.h similarity index 95% rename from core/include/VncFeatureMessageEvent.h rename to core/src/VncFeatureMessageEvent.h index 34636f7a2..6e64c7ca3 100644 --- a/core/include/VncFeatureMessageEvent.h +++ b/core/src/VncFeatureMessageEvent.h @@ -1,7 +1,7 @@ /* * FeatureMessageEvent.h - declaration of class FeatureMessageEvent * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/core/include/VncServerClient.h b/core/src/VncServerClient.h similarity index 83% rename from core/include/VncServerClient.h rename to core/src/VncServerClient.h index 08914841d..e8b5c5915 100644 --- a/core/include/VncServerClient.h +++ b/core/src/VncServerClient.h @@ -1,7 +1,7 @@ /* * VncServerClient.h - header file for the VncServerClient class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -35,9 +35,7 @@ class VEYON_CORE_EXPORT VncServerClient : public QObject public: enum class AuthState { Init, - Challenge, - Password, - Token, + Stage1, Successful, Failed, } ; @@ -54,9 +52,9 @@ class VEYON_CORE_EXPORT VncServerClient : public QObject explicit VncServerClient( QObject* parent = nullptr ) : QObject( parent ), - m_protocolState( VncServerProtocol::Disconnected ), + m_protocolState( VncServerProtocol::State::Disconnected ), m_authState( AuthState::Init ), - m_authType( RfbVeyonAuth::Invalid ), + m_authMethodUid(), m_accessControlState( AccessControlState::Init ), m_username(), m_hostAddress(), @@ -84,14 +82,14 @@ class VEYON_CORE_EXPORT VncServerClient : public QObject m_authState = authState; } - RfbVeyonAuth::Type authType() const + Plugin::Uid authMethodUid() const { - return m_authType; + return m_authMethodUid; } - void setAuthType( RfbVeyonAuth::Type authType ) + void setAuthMethodUid( Plugin::Uid pluginUid ) { - m_authType = authType; + m_authMethodUid = pluginUid; } AccessControlState accessControlState() const @@ -104,6 +102,16 @@ class VEYON_CORE_EXPORT VncServerClient : public QObject m_accessControlState = accessControlState; } + const QString& accessControlDetails() const + { + return m_accessControlDetails; + } + + void setAccessControlDetails(const QString& details) + { + m_accessControlDetails = details; + } + QElapsedTimer& accessControlTimer() { return m_accessControlTimer; @@ -149,20 +157,21 @@ class VEYON_CORE_EXPORT VncServerClient : public QObject m_privateKey = privateKey; } -public slots: +public Q_SLOTS: void finishAccessControl() { - emit accessControlFinished( this ); + Q_EMIT accessControlFinished( this ); } -signals: +Q_SIGNALS: void accessControlFinished( VncServerClient* ); private: VncServerProtocol::State m_protocolState; AuthState m_authState; - RfbVeyonAuth::Type m_authType; + Plugin::Uid m_authMethodUid; AccessControlState m_accessControlState; + QString m_accessControlDetails; QElapsedTimer m_accessControlTimer; QString m_username; QString m_hostAddress; diff --git a/core/include/VncServerPluginInterface.h b/core/src/VncServerPluginInterface.h similarity index 82% rename from core/include/VncServerPluginInterface.h rename to core/src/VncServerPluginInterface.h index bc3beea09..a9d5cad49 100644 --- a/core/include/VncServerPluginInterface.h +++ b/core/src/VncServerPluginInterface.h @@ -1,7 +1,7 @@ /* * VncServerPluginInterface.h - abstract interface class for VNC server plugins * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,6 +24,7 @@ #pragma once +#include "CryptoCore.h" #include "PluginInterface.h" // clazy:excludeall=copyable-polymorphic @@ -31,6 +32,12 @@ class VncServerPluginInterface { public: + using Password = CryptoCore::PlaintextPassword; + + virtual ~VncServerPluginInterface() = default; + + virtual QStringList supportedSessionTypes() const = 0; + /*! * \brief Create configuration widget for VNC server plugin - used in Configurator */ @@ -43,11 +50,11 @@ class VncServerPluginInterface * \param serverPort the port the VNC server should listen at * \param password the password to be used for VNC authentication */ - virtual void runServer( int serverPort, const QString& password ) = 0; + virtual bool runServer( int serverPort, const Password& password ) = 0; virtual int configuredServerPort() = 0; - virtual QString configuredPassword() = 0; + virtual Password configuredPassword() = 0; } ; diff --git a/core/src/VncServerProtocol.cpp b/core/src/VncServerProtocol.cpp index c65886dac..7800a6ea4 100644 --- a/core/src/VncServerProtocol.cpp +++ b/core/src/VncServerProtocol.cpp @@ -1,7 +1,7 @@ /* * VncServerProtocol.cpp - implementation of the VncServerProtocol class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,21 +25,23 @@ #include "rfb/rfbproto.h" #include +#include #include -#include "AuthenticationCredentials.h" +#include "AccessControlProvider.h" +#include "BuiltinFeatures.h" #include "VariantArrayMessage.h" #include "VncServerClient.h" #include "VncServerProtocol.h" -VncServerProtocol::VncServerProtocol( QTcpSocket* socket, - VncServerClient* client ) : +VncServerProtocol::VncServerProtocol(QTcpSocket* socket, VncServerClient* client) : m_socket( socket ), m_client( client ), m_serverInitMessage() { + m_client->setHostAddress(m_socket->peerAddress().toString()); m_client->setAccessControlState( VncServerClient::AccessControlState::Init ); } @@ -54,15 +56,15 @@ VncServerProtocol::State VncServerProtocol::state() const void VncServerProtocol::start() { - if( state() == Disconnected ) + if( state() == State::Disconnected ) { - char protocol[sz_rfbProtocolVersionMsg+1]; // Flawfinder: ignore + std::array protocol{}; // Flawfinder: ignore - sprintf( protocol, rfbProtocolVersionFormat, 3, 8 ); // Flawfinder: ignore + sprintf( protocol.data(), rfbProtocolVersionFormat, 3, 8 ); // Flawfinder: ignore - m_socket->write( protocol, sz_rfbProtocolVersionMsg ); + m_socket->write( protocol.data(), sz_rfbProtocolVersionMsg ); - setState( Protocol ); + setState( State::Protocol ); } } @@ -72,29 +74,40 @@ bool VncServerProtocol::read() { switch( state() ) { - case Protocol: + case State::Protocol: return readProtocol(); - case SecurityInit: + case State::SecurityInit: return receiveSecurityTypeResponse(); - case AuthenticationTypes: - return receiveAuthenticationTypeResponse(); + case State::AuthenticationMethods: + return receiveAuthenticationMethodResponse(); - case Authenticating: + case State::Authenticating: return receiveAuthenticationMessage(); - case AccessControl: + case State::AccessControl: return processAccessControl(); - case FramebufferInit: + case State::FramebufferInit: return processFramebufferInit(); - case Close: + case State::Close: vDebug() << "closing connection per protocol state"; m_socket->close(); break; + case State::Closing: + if (m_socket->isOpen()) + { + m_socket->readAll(); + } + else + { + setState(State::Close); + } + return false; + default: break; } @@ -124,16 +137,15 @@ bool VncServerProtocol::readProtocol() return false; } - QRegExp protocolRX( QStringLiteral("RFB (\\d\\d\\d)\\.(\\d\\d\\d)\n") ); - - if( protocolRX.indexIn( QString::fromUtf8( protocol ) ) != 0 ) + static const QRegularExpression rfbRX{QStringLiteral("RFB (\\d\\d\\d)\\.(\\d\\d\\d)\n")}; + if (rfbRX.match(QString::fromUtf8(protocol)).hasMatch() == false) { vCritical() << "invalid protocol version"; m_socket->close(); return false; } - setState( SecurityInit ); + setState( State::SecurityInit ); return sendSecurityTypes(); } @@ -146,8 +158,8 @@ bool VncServerProtocol::readProtocol() bool VncServerProtocol::sendSecurityTypes() { // send list of supported security types - const char securityTypeList[2] = { 1, rfbSecTypeVeyon }; // Flawfinder: ignore - m_socket->write( securityTypeList, sizeof( securityTypeList ) ); + constexpr std::array securityTypeList{ 1, VeyonCore::RfbSecurityTypeVeyon }; + m_socket->write( securityTypeList.data(), sizeof( securityTypeList ) ); return true; } @@ -161,7 +173,7 @@ bool VncServerProtocol::receiveSecurityTypeResponse() char chosenSecurityType = 0; if( m_socket->read( &chosenSecurityType, sizeof(chosenSecurityType) ) != sizeof(chosenSecurityType) || - chosenSecurityType != rfbSecTypeVeyon ) + chosenSecurityType != VeyonCore::RfbSecurityTypeVeyon ) { vCritical() << "protocol initialization failed"; m_socket->close(); @@ -169,9 +181,9 @@ bool VncServerProtocol::receiveSecurityTypeResponse() return false; } - setState( AuthenticationTypes ); + setState( State::AuthenticationMethods ); - return sendAuthenticationTypes(); + return sendAuthenticationMethods(); } return false; @@ -179,12 +191,12 @@ bool VncServerProtocol::receiveSecurityTypeResponse() -bool VncServerProtocol::sendAuthenticationTypes() +bool VncServerProtocol::sendAuthenticationMethods() { - const auto authTypes = supportedAuthTypes(); + const auto authTypes = supportedAuthMethodUids(); VariantArrayMessage message( m_socket ); - message.write( authTypes.count() ); + message.write(int(authTypes.count())); for( auto authType : authTypes ) { @@ -196,15 +208,16 @@ bool VncServerProtocol::sendAuthenticationTypes() -bool VncServerProtocol::receiveAuthenticationTypeResponse() +bool VncServerProtocol::receiveAuthenticationMethodResponse() { VariantArrayMessage message( m_socket ); if( message.isReadyForReceive() && message.receive() ) { - const auto chosenAuthType = QVariantHelper::value( message.read() ); + const auto chosenAuthMethodUid = message.read().toUuid(); - if( supportedAuthTypes().contains( chosenAuthType ) == false ) + if( chosenAuthMethodUid.isNull() || + supportedAuthMethodUids().contains( chosenAuthMethodUid ) == false ) { vCritical() << "unsupported authentication type chosen by client!"; m_socket->close(); @@ -212,20 +225,12 @@ bool VncServerProtocol::receiveAuthenticationTypeResponse() return false; } - if( chosenAuthType == RfbVeyonAuth::None ) - { - vWarning() << "skipping authentication."; - setState( AccessControl ); - return true; - } - const auto username = message.read().toString(); - m_client->setAuthType( chosenAuthType ); + m_client->setAuthMethodUid( chosenAuthMethodUid ); m_client->setUsername( username ); - m_client->setHostAddress( m_socket->peerAddress().toString() ); - setState( Authenticating ); + setState( State::Authenticating ); // send auth ack message VariantArrayMessage( m_socket ).send(); @@ -265,7 +270,7 @@ bool VncServerProtocol::processAuthentication( VariantArrayMessage& message ) const auto authResult = qToBigEndian(rfbVncAuthOK); m_socket->write( reinterpret_cast( &authResult ), sizeof(authResult) ); - setState( AccessControl ); + setState( State::AccessControl ); return true; } @@ -291,7 +296,7 @@ bool VncServerProtocol::processAccessControl() switch( m_client->accessControlState() ) { case VncServerClient::AccessControlState::Successful: - setState( FramebufferInit ); + setState( State::FramebufferInit ); return true; case VncServerClient::AccessControlState::Pending: @@ -300,8 +305,10 @@ bool VncServerProtocol::processAccessControl() default: vCritical() << "access control failed - closing connection"; - m_socket->close(); - break; + m_socket->read(sz_rfbClientInitMsg); + sendEmptyServerInitMessage(); + sendFailedAccessControlDetails(); + return true; } return false; @@ -309,6 +316,29 @@ bool VncServerProtocol::processAccessControl() +void VncServerProtocol::sendFailedAccessControlDetails() +{ + VeyonCore::builtinFeatures().accessControlProvider().sendDetails(m_socket, client()->accessControlDetails()); + + QObject::connect (&m_accessControlDetailsSendTimer, &QTimer::timeout, m_socket, [this]() { + VeyonCore::builtinFeatures().accessControlProvider().sendDetails(m_socket, client()->accessControlDetails()); + }); + QTimer::singleShot(AccessControlCloseDelay, m_socket, &QAbstractSocket::close); + m_accessControlDetailsSendTimer.start(AccessControlDetailsSendInterval); + + setState(State::Closing); +} + + + +void VncServerProtocol::sendEmptyServerInitMessage() +{ + rfbServerInitMsg message{}; + m_socket->write(reinterpret_cast(&message), sizeof(message)); +} + + + bool VncServerProtocol::processFramebufferInit() { if( m_socket->bytesAvailable() >= sz_rfbClientInitMsg && @@ -319,7 +349,7 @@ bool VncServerProtocol::processFramebufferInit() m_socket->write( m_serverInitMessage ); - setState( Running ); + setState( State::Running ); return true; } diff --git a/core/include/VncServerProtocol.h b/core/src/VncServerProtocol.h similarity index 75% rename from core/include/VncServerProtocol.h rename to core/src/VncServerProtocol.h index c4fa14454..271459d7a 100644 --- a/core/include/VncServerProtocol.h +++ b/core/src/VncServerProtocol.h @@ -1,7 +1,7 @@ /* * VncServerProtocol.h - header file for the VncServerProtocol class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,7 +24,10 @@ #pragma once -#include "RfbVeyonAuth.h" +#include + +#include "VeyonCore.h" +#include "Plugin.h" class QTcpSocket; @@ -36,21 +39,24 @@ class VncServerClient; class VEYON_CORE_EXPORT VncServerProtocol { public: - enum State { + using AuthMethodUids = QVector; + + enum class State + { Disconnected, Protocol, SecurityInit, - AuthenticationTypes, + AuthenticationMethods, Authenticating, AccessControl, FramebufferInit, Running, Close, + Closing, StateCount } ; - VncServerProtocol( QTcpSocket* socket, - VncServerClient* client ); + VncServerProtocol(QTcpSocket* socket, VncServerClient* client); virtual ~VncServerProtocol() = default; State state() const; @@ -64,7 +70,7 @@ class VEYON_CORE_EXPORT VncServerProtocol } protected: - virtual QVector supportedAuthTypes() const = 0; + virtual AuthMethodUids supportedAuthMethodUids() const = 0; virtual void processAuthenticationMessage( VariantArrayMessage& message ) = 0; virtual void performAccessControl() = 0; @@ -84,19 +90,28 @@ class VEYON_CORE_EXPORT VncServerProtocol bool readProtocol(); bool sendSecurityTypes(); bool receiveSecurityTypeResponse(); - bool sendAuthenticationTypes(); - bool receiveAuthenticationTypeResponse(); + bool sendAuthenticationMethods(); + bool receiveAuthenticationMethodResponse(); bool receiveAuthenticationMessage(); bool processAuthentication( VariantArrayMessage& message ); bool processAccessControl(); + void sendFailedAccessControlDetails(); + + void sendEmptyServerInitMessage(); + bool processFramebufferInit(); private: + static constexpr auto AccessControlCloseDelay = 10000; + static constexpr auto AccessControlDetailsSendInterval = 100; + QTcpSocket* m_socket; VncServerClient* m_client; QByteArray m_serverInitMessage; + QTimer m_accessControlDetailsSendTimer; + } ; diff --git a/core/src/VncView.cpp b/core/src/VncView.cpp index 3d0f2f517..23cc79b0e 100644 --- a/core/src/VncView.cpp +++ b/core/src/VncView.cpp @@ -1,7 +1,7 @@ /* - * VncView.cpp - VNC viewer widget + * VncView.cpp - abstract base for all VNC views * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,148 +22,93 @@ * */ -#define XK_KOREAN -#include "rfb/keysym.h" -#include "rfb/rfbproto.h" +#include +#include -#include "VncView.h" -#include "PlatformInputDeviceFunctions.h" -#include "KeyboardShortcutTrapper.h" -#include "ProgressWidget.h" -#include "VeyonConnection.h" +#include -#include -#include +#include +#include #include -#include #include +#include "PlatformInputDeviceFunctions.h" +#include "KeyboardShortcutTrapper.h" +#include "VeyonConnection.h" +#include "VncConnection.h" +#include "VncView.h" -VncView::VncView( const QString &host, int port, QWidget *parent, Mode mode ) : - QWidget( parent ), - m_vncConn( new VncConnection( QCoreApplication::instance() ) ), - m_veyonConnection( new VeyonConnection( m_vncConn ) ), - m_mode( mode ), - m_cursorShape(), - m_cursorX( 0 ), - m_cursorY( 0 ), - m_framebufferSize( 0, 0 ), - m_cursorHotX( 0 ), - m_cursorHotY( 0 ), - m_viewOnly( true ), - m_viewOnlyFocus( true ), - m_initDone( false ), - m_buttonMask( 0 ), - m_establishingConnectionWidget( nullptr ), - m_keyboardShortcutTrapper( VeyonCore::platform().inputDeviceFunctions().createKeyboardShortcutTrapper( this ) ), - m_mouseBorderSignalTimer( this ) -{ - m_vncConn->setHost( host ); - m_vncConn->setPort( port ); - - if( m_mode == DemoMode ) - { - m_vncConn->setQuality( VncConnection::Quality::Default ); - m_veyonConnection->setVeyonAuthType( RfbVeyonAuth::Token ); - m_establishingConnectionWidget = new ProgressWidget( - tr( "Establishing connection to %1 ..." ).arg( m_vncConn->host() ), - QStringLiteral( ":/core/watch%1.png" ), 16, this ); - connect( m_vncConn, &VncConnection::stateChanged, - this, &VncView::updateConnectionState ); - } - else if( m_mode == RemoteControlMode ) - { - m_vncConn->setQuality( VncConnection::Quality::RemoteControl ); - } - - connect( m_vncConn, &VncConnection::imageUpdated, this, &VncView::updateImage ); - connect( m_vncConn, &VncConnection::framebufferSizeChanged, this, &VncView::updateFramebufferSize ); - - connect( m_vncConn, &VncConnection::cursorPosChanged, this, &VncView::updateCursorPos ); - connect( m_vncConn, &VncConnection::cursorShapeUpdated, this, &VncView::updateCursorShape ); +VncView::VncView( const ComputerControlInterface::Pointer& computerControlInterface ) : + m_computerControlInterface( [computerControlInterface]() { + if( computerControlInterface->state() == ComputerControlInterface::State::Disconnected || + computerControlInterface->connection() == nullptr ) + { + computerControlInterface->start(); + } + return computerControlInterface; + }() ), + m_previousUpdateMode( m_computerControlInterface->updateMode() ), + m_connection( computerControlInterface->connection()->vncConnection() ), + m_framebufferSize( m_connection->image().size() ), + m_keyboardShortcutTrapper( VeyonCore::platform().inputDeviceFunctions().createKeyboardShortcutTrapper( nullptr ) ) +{ // handle/forward trapped keyboard shortcuts - connect( m_keyboardShortcutTrapper, &KeyboardShortcutTrapper::shortcutTrapped, - this, &VncView::handleShortcut ); - - // set up mouse border signal timer - m_mouseBorderSignalTimer.setSingleShot( true ); - m_mouseBorderSignalTimer.setInterval( MouseBorderSignalDelay ); - connect( &m_mouseBorderSignalTimer, &QTimer::timeout, this, &VncView::mouseAtBorder ); - - // set up background color - if( parent == nullptr ) - { - parent = this; - } - QPalette pal = parent->palette(); - pal.setColor( parent->backgroundRole(), Qt::black ); - parent->setPalette( pal ); - - show(); + QObject::connect( m_keyboardShortcutTrapper, &KeyboardShortcutTrapper::shortcutTrapped, + m_keyboardShortcutTrapper, [this]( KeyboardShortcutTrapper::Shortcut shortcut ) { + handleShortcut( shortcut ); + } ); - resize( QApplication::desktop()->availableGeometry( this ).size() - QSize( 10, 30 ) ); - - setFocusPolicy( Qt::StrongFocus ); - setFocus(); - - m_vncConn->start(); + m_computerControlInterface->setUpdateMode( ComputerControlInterface::UpdateMode::Live ); } VncView::~VncView() { - // do not receive any signals during connection shutdown - m_vncConn->disconnect( this ); - unpressModifiers(); - delete m_keyboardShortcutTrapper; - delete m_veyonConnection; - m_veyonConnection = nullptr; + m_computerControlInterface->setUpdateMode( m_previousUpdateMode ); - m_vncConn->stopAndDeleteLater(); - m_vncConn = nullptr; + delete m_keyboardShortcutTrapper; } -bool VncView::eventFilter(QObject *obj, QEvent *event) +QSize VncView::scaledSize() const { - if( m_viewOnly ) + if( isScaledView() == false ) { - if( event->type() == QEvent::KeyPress || - event->type() == QEvent::KeyRelease || - event->type() == QEvent::MouseButtonDblClick || - event->type() == QEvent::MouseButtonPress || - event->type() == QEvent::MouseButtonRelease || - event->type() == QEvent::Wheel ) - { - return true; - } + return effectiveFramebufferSize(); } - return QWidget::eventFilter(obj, event); + return effectiveFramebufferSize().scaled( viewSize(), Qt::KeepAspectRatio ); } -QSize VncView::sizeHint() const +QSize VncView::effectiveFramebufferSize() const { - return framebufferSize(); + const auto viewportSize = m_viewport.size(); + + if( viewportSize.isEmpty() == false ) + { + return viewportSize; + } + + return m_framebufferSize; } -QSize VncView::scaledSize() const +void VncView::setViewport(QRect viewport) { - if( isScaledView() == false ) + if( m_viewport != viewport ) { - return m_framebufferSize; - } + m_viewport = viewport; - return m_framebufferSize.scaled( size(), Qt::KeepAspectRatio ); + updateGeometry(); + } } @@ -174,27 +119,31 @@ void VncView::setViewOnly( bool viewOnly ) { return; } + m_viewOnly = viewOnly; + if( m_connection ) + { + m_connection->setUseRemoteCursor( !viewOnly ); + } + if( m_viewOnly ) { - releaseKeyboard(); m_keyboardShortcutTrapper->setEnabled( false ); - updateLocalCursor(); } else { - grabKeyboard(); - updateLocalCursor(); m_keyboardShortcutTrapper->setEnabled( true ); } + + updateLocalCursor(); } void VncView::sendShortcut( VncView::Shortcut shortcut ) { - if( isViewOnly() ) + if( viewOnly() ) { return; } @@ -237,8 +186,8 @@ void VncView::sendShortcut( VncView::Shortcut shortcut ) unpressKey( XK_Meta_L ); break; case ShortcutWin: - pressKey( XK_Meta_L ); - unpressKey( XK_Meta_L ); + pressKey( XK_Super_L ); + unpressKey( XK_Super_L ); break; case ShortcutMenu: pressKey( XK_Menu ); @@ -260,53 +209,53 @@ void VncView::sendShortcut( VncView::Shortcut shortcut ) -void VncView::handleShortcut( KeyboardShortcutTrapper::Shortcut shortcut ) +bool VncView::isScaledView() const { - unsigned int key = 0; + return viewSize().width() < effectiveFramebufferSize().width() || + viewSize().height() < effectiveFramebufferSize().height(); +} - switch( shortcut ) + + +qreal VncView::scaleFactor() const +{ + if( isScaledView() ) { - case KeyboardShortcutTrapper::SuperKeyDown: - m_mods[XK_Super_L] = true; - break; - case KeyboardShortcutTrapper::SuperKeyUp: - m_mods.remove( XK_Super_L ); - break; - case KeyboardShortcutTrapper::AltTab: key = XK_Tab; break; - case KeyboardShortcutTrapper::AltEsc: key = XK_Escape; break; - case KeyboardShortcutTrapper::AltSpace: key = XK_KP_Space; break; - case KeyboardShortcutTrapper::AltF4: key = XK_F4; break; - case KeyboardShortcutTrapper::CtrlEsc: key = XK_Escape; break; - default: - break; + return qreal( scaledSize().width() ) / effectiveFramebufferSize().width(); } - if( key ) + return 1; +} + + + +QPoint VncView::mapToFramebuffer( QPoint pos ) +{ + if( effectiveFramebufferSize().isEmpty() ) { - m_vncConn->keyEvent( key, true ); - m_vncConn->keyEvent( key, false ); + return { 0, 0 }; } + + return { pos.x() * effectiveFramebufferSize().width() / scaledSize().width() + viewport().x(), + pos.y() * effectiveFramebufferSize().height() / scaledSize().height() + viewport().y() }; } -void VncView::updateCursorPos( int x, int y ) +QRect VncView::mapFromFramebuffer( QRect r ) { - if( isViewOnly() ) + if( effectiveFramebufferSize().isEmpty() ) { - if( !m_cursorShape.isNull() ) - { - update( m_cursorX, m_cursorY, - m_cursorShape.width(), m_cursorShape.height() ); - } - m_cursorX = x; - m_cursorY = y; - if( !m_cursorShape.isNull() ) - { - update( m_cursorX, m_cursorY, - m_cursorShape.width(), m_cursorShape.height() ); - } + return {}; } + + r.translate( -viewport().x(), -viewport().y() ); + + const auto dx = scaledSize().width() / qreal( effectiveFramebufferSize().width() ); + const auto dy = scaledSize().height() / qreal( effectiveFramebufferSize().height() ); + + return { int(r.x()*dx), int(r.y()*dy), + int(r.width()*dx), int(r.height()*dy) }; } @@ -315,46 +264,123 @@ void VncView::updateCursorShape( const QPixmap& cursorShape, int xh, int yh ) { const auto scale = scaleFactor(); - m_cursorHotX = static_cast( xh*scale ); - m_cursorHotY = static_cast( yh*scale ); - m_cursorShape = cursorShape.scaled( static_cast( cursorShape.width()*scale ), - static_cast( cursorShape.height()*scale ), + m_cursorHot = { int( xh*scale ), int( yh*scale ) }; + m_cursorShape = cursorShape.scaled( int( cursorShape.width()*scale ), + int( cursorShape.height()*scale ), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); - if( isViewOnly() ) + updateLocalCursor(); +} + + + +void VncView::updateFramebufferSize( int w, int h ) +{ + m_framebufferSize = QSize( w, h ); + + updateGeometry(); +} + + + +void VncView::updateImage( int x, int y, int w, int h ) +{ + x -= viewport().x(); + y -= viewport().y(); + + const auto scale = scaleFactor(); + updateView( qMax( 0, qFloor( x*scale - 1 ) ), qMax( 0, qFloor( y*scale - 1 ) ), + qCeil( w*scale + 2 ), qCeil( h*scale + 2 ) ); +} + + + +void VncView::unpressModifiers() +{ + const auto keys = m_mods.keys(); + for( auto key : keys ) { - update( m_cursorX, m_cursorY, m_cursorShape.width(), m_cursorShape.height() ); + m_connection->keyEvent( key, false ); } + m_mods.clear(); +} - updateLocalCursor(); + + +void VncView::handleShortcut( KeyboardShortcutTrapper::Shortcut shortcut ) +{ + unsigned int key = 0; + + switch( shortcut ) + { + case KeyboardShortcutTrapper::SuperKeyDown: + m_mods[XK_Super_L] = true; + break; + case KeyboardShortcutTrapper::SuperKeyUp: + m_mods.remove( XK_Super_L ); + break; + case KeyboardShortcutTrapper::AltTab: key = XK_Tab; break; + case KeyboardShortcutTrapper::AltEsc: key = XK_Escape; break; + case KeyboardShortcutTrapper::AltSpace: key = XK_KP_Space; break; + case KeyboardShortcutTrapper::AltF4: key = XK_F4; break; + case KeyboardShortcutTrapper::CtrlEsc: key = XK_Escape; break; + default: + break; + } + + if( key ) + { + m_connection->keyEvent( key, true ); + m_connection->keyEvent( key, false ); + } } -void VncView::focusInEvent( QFocusEvent* event ) +bool VncView::handleEvent( QEvent* event ) { - if( !m_viewOnlyFocus ) + switch( event->type() ) { - setViewOnly( false ); + case QEvent::KeyPress: + case QEvent::KeyRelease: + keyEventHandler( dynamic_cast( event ) ); + return true; + case QEvent::HoverMove: + hoverEventHandler( dynamic_cast( event ) ); + return true; + case QEvent::MouseButtonDblClick: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + mouseEventHandler( dynamic_cast( event ) ); + return true; + case QEvent::Wheel: + wheelEventHandler( dynamic_cast( event ) ); + return true; + default: + break; } - QWidget::focusInEvent( event ); + + return false; } -void VncView::focusOutEvent( QFocusEvent* event ) +void VncView::hoverEventHandler( QHoverEvent* event ) { - m_viewOnlyFocus = isViewOnly(); - if( !isViewOnly() ) + if( event && m_viewOnly == false ) { - setViewOnly( true ); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + const auto pos = mapToFramebuffer(event->position().toPoint()); +#else + const auto pos = mapToFramebuffer(event->pos()); +#endif + m_connection->mouseEvent( pos.x(), pos.y(), m_buttonMask ); } - QWidget::focusOutEvent( event ); } -// our builtin keyboard-handler void VncView::keyEventHandler( QKeyEvent* event ) { if( event == nullptr ) @@ -362,7 +388,7 @@ void VncView::keyEventHandler( QKeyEvent* event ) return; } - bool pressed = event->type() == QEvent::KeyPress; + const auto pressed = event->type() == QEvent::KeyPress; #ifdef Q_OS_LINUX // on Linux/X11 native key codes are equal to the ones used by RFB protocol @@ -491,7 +517,7 @@ void VncView::keyEventHandler( QKeyEvent* event ) key >= 64 && key < 0xF000 ) { unpressModifiers(); - m_vncConn->keyEvent( XK_ISO_Level3_Shift, true ); + m_connection->keyEvent( XK_ISO_Level3_Shift, true ); } #endif @@ -504,12 +530,12 @@ void VncView::keyEventHandler( QKeyEvent* event ) if( pressed ) { unpressModifiers(); - m_vncConn->keyEvent( XK_Control_L, true ); - m_vncConn->keyEvent( XK_Alt_L, true ); - m_vncConn->keyEvent( XK_Delete, true ); - m_vncConn->keyEvent( XK_Delete, false ); - m_vncConn->keyEvent( XK_Alt_L, false ); - m_vncConn->keyEvent( XK_Control_L, false ); + m_connection->keyEvent( XK_Control_L, true ); + m_connection->keyEvent( XK_Alt_L, true ); + m_connection->keyEvent( XK_Delete, true ); + m_connection->keyEvent( XK_Delete, false ); + m_connection->keyEvent( XK_Alt_L, false ); + m_connection->keyEvent( XK_Control_L, false ); key = 0; } } @@ -535,11 +561,7 @@ void VncView::keyEventHandler( QKeyEvent* event ) if( key ) { // forward key event to the VNC connection - m_vncConn->keyEvent( key, pressed ); - - // signal key event - used by RemoteControlWidget to close itself - // when pressing Esc - emit keyEvent( key, pressed ); + m_connection->keyEvent( key, pressed ); // inform Qt that we handled the key event event->accept(); @@ -548,210 +570,9 @@ void VncView::keyEventHandler( QKeyEvent* event ) - -void VncView::unpressModifiers() -{ - const auto keys = m_mods.keys(); - for( auto key : keys ) - { - m_vncConn->keyEvent( key, false ); - } - m_mods.clear(); -} - - - -bool VncView::isScaledView() const -{ - return width() < m_framebufferSize.width() || - height() < m_framebufferSize.height(); -} - - - -qreal VncView::scaleFactor() const -{ - if( isScaledView() ) - { - return static_cast( scaledSize().width() ) / m_framebufferSize.width(); - } - - return 1; -} - - - -QPoint VncView::mapToFramebuffer( QPoint pos ) -{ - if( m_framebufferSize.isEmpty() ) - { - return { 0, 0 }; - } - - return { pos.x() * m_framebufferSize.width() / scaledSize().width(), - pos.y() * m_framebufferSize.height() / scaledSize().height() }; -} - - - -QRect VncView::mapFromFramebuffer( QRect r ) -{ - if( m_framebufferSize.isEmpty() ) - { - return {}; - } - - const auto dx = scaledSize().width() / static_cast( m_framebufferSize.width() ); - const auto dy = scaledSize().height() / static_cast( m_framebufferSize.height() ); - - return { static_cast(r.x()*dx), static_cast(r.y()*dy), - static_cast(r.width()*dx), static_cast(r.height()*dy) }; -} - - - -void VncView::updateLocalCursor() -{ - if( isViewOnly() ) - { - setCursor( Qt::ArrowCursor ); - } - else if( m_cursorShape.isNull() == false ) - { - setCursor( QCursor( m_cursorShape, m_cursorHotX, m_cursorHotY ) ); - } - else - { - setCursor( Qt::BlankCursor ); - } -} - - - -void VncView::pressKey( unsigned int key ) -{ - m_vncConn->keyEvent( key, true ); -} - - - -void VncView::unpressKey( unsigned int key ) -{ - m_vncConn->keyEvent( key, false ); -} - - - -bool VncView::event( QEvent * event ) -{ - switch( event->type() ) - { - case QEvent::KeyPress: - case QEvent::KeyRelease: - keyEventHandler( dynamic_cast( event ) ); - return true; - case QEvent::MouseButtonDblClick: - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseMove: - mouseEventHandler( dynamic_cast( event ) ); - return true; - case QEvent::Wheel: - wheelEventHandler( dynamic_cast( event ) ); - return true; - default: - return QWidget::event(event); - } -} - - - -void VncView::paintEvent( QPaintEvent* paintEvent ) -{ - QPainter p( this ); - p.setRenderHint( QPainter::SmoothPixmapTransform ); - - const auto& image = m_vncConn->image(); - - if( image.isNull() || image.format() == QImage::Format_Invalid ) - { - p.fillRect( paintEvent->rect(), Qt::black ); - return; - } - - if( isScaledView() ) - { - // repaint everything in scaled mode to avoid artifacts at rectangle boundaries - p.drawImage( QRect( QPoint( 0, 0 ), scaledSize() ), image ); - } - else - { - p.drawImage( 0, 0, image ); - } - - if( isViewOnly() && !m_cursorShape.isNull() ) - { - const QRect cursorRect = mapFromFramebuffer( - QRect( QPoint( m_cursorX - m_cursorHotX, - m_cursorY - m_cursorHotY ), - m_cursorShape.size() ) ); - // parts of cursor within updated region? - if( paintEvent->region().intersects( cursorRect ) ) - { - // then repaint it - p.drawPixmap( cursorRect.topLeft(), m_cursorShape ); - } - } - - // draw black borders if neccessary - const int screenWidth = scaledSize().width(); - if( screenWidth < width() ) - { - p.fillRect( screenWidth, 0, width() - screenWidth, height(), Qt::black ); - } - - const int screenHeight = scaledSize().height(); - if( screenHeight < height() ) - { - p.fillRect( 0, screenHeight, width(), height() - screenHeight, Qt::black ); - } -} - - - -void VncView::resizeEvent( QResizeEvent* event ) -{ - update(); - - if( m_establishingConnectionWidget ) - { - m_establishingConnectionWidget->move( 10, 10 ); - } - - updateLocalCursor(); - - QWidget::resizeEvent( event ); -} - - - -void VncView::wheelEventHandler( QWheelEvent* event ) -{ - if( event == nullptr ) - { - return; - } - - const auto p = mapToFramebuffer( event->pos() ); - m_vncConn->mouseEvent( p.x(), p.y(), m_buttonMask | ( ( event->delta() < 0 ) ? rfbButton5Mask : rfbButton4Mask ) ); - m_vncConn->mouseEvent( p.x(), p.y(), m_buttonMask ); -} - - - void VncView::mouseEventHandler( QMouseEvent* event ) { - if( event == nullptr ) + if( event == nullptr || m_viewOnly ) { return; } @@ -762,11 +583,11 @@ void VncView::mouseEventHandler( QMouseEvent* event ) int rfb; }; - const ButtonTranslation buttonTranslationMap[] = { + static constexpr std::array buttonTranslationMap{ { { Qt::LeftButton, rfbButton1Mask }, - { Qt::MidButton, rfbButton2Mask }, + { Qt::MiddleButton, rfbButton2Mask }, { Qt::RightButton, rfbButton3Mask } - } ; + } }; if( event->type() != QEvent::MouseMove ) { @@ -777,79 +598,64 @@ void VncView::mouseEventHandler( QMouseEvent* event ) if( event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick ) { - m_buttonMask |= i.rfb; + m_buttonMask |= uint(i.rfb); } else { - m_buttonMask &= ~i.rfb; + m_buttonMask &= ~uint(i.rfb); } } } } - else - { - if( event->pos().y() == 0 ) - { - if( m_mouseBorderSignalTimer.isActive() == false ) - { - m_mouseBorderSignalTimer.start(); - } - } - else - { - m_mouseBorderSignalTimer.stop(); - } - } - if( !m_viewOnly ) - { - const QPoint p = mapToFramebuffer( event->pos() ); - m_vncConn->mouseEvent( p.x(), p.y(), m_buttonMask ); - } + const auto pos = mapToFramebuffer( event->pos() ); + m_connection->mouseEvent( pos.x(), pos.y(), m_buttonMask ); } -void VncView::updateImage( int x, int y, int w, int h ) +void VncView::wheelEventHandler( QWheelEvent* event ) { - if( m_initDone == false ) + if( event == nullptr ) { - setAttribute( Qt::WA_OpaquePaintEvent ); - installEventFilter( this ); + return; + } - setMouseTracking( true ); // get mouse events even when there is no mousebutton pressed - setFocusPolicy( Qt::WheelFocus ); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + const auto p = mapToFramebuffer( event->position().toPoint() ); + const uint scrollButtonMask = ( event->angleDelta().y() < 0 ) ? rfbButton5Mask : rfbButton4Mask; +#else + const auto p = mapToFramebuffer( event->pos() ); + const uint scrollButtonMask = ( event->delta() < 0 ) ? rfbButton5Mask : rfbButton4Mask; +#endif + m_connection->mouseEvent( p.x(), p.y(), m_buttonMask | scrollButtonMask ); + m_connection->mouseEvent( p.x(), p.y(), m_buttonMask ); +} - resize( sizeHint() ); - emit connectionEstablished(); - m_initDone = true; +void VncView::updateLocalCursor() +{ + if( m_cursorShape.isNull() == false && viewOnly() == false ) + { + setViewCursor( QCursor( m_cursorShape, m_cursorHot.x(), m_cursorHot.y() ) ); + } + else + { + setViewCursor( Qt::ArrowCursor ); } - - const auto scale = scaleFactor(); - - update( qMax( 0, qFloor( x*scale - 1 ) ), qMax( 0, qFloor( y*scale - 1 ) ), - qCeil( w*scale + 2 ), qCeil( h*scale + 2 ) ); } -void VncView::updateFramebufferSize( int w, int h ) +void VncView::pressKey( unsigned int key ) { - m_framebufferSize = QSize( w, h ); - - resize( w, h ); - - emit sizeHintChanged(); + m_connection->keyEvent( key, true ); } -void VncView::updateConnectionState() +void VncView::unpressKey( unsigned int key ) { - if( m_establishingConnectionWidget ) - { - m_establishingConnectionWidget->setVisible( m_vncConn->state() != VncConnection::State::Connected ); - } + m_connection->keyEvent( key, false ); } diff --git a/core/src/VncView.h b/core/src/VncView.h new file mode 100644 index 000000000..6c67fb783 --- /dev/null +++ b/core/src/VncView.h @@ -0,0 +1,154 @@ +/* + * VncView.h - abstract base for all VNC views + * + * Copyright (c) 2006-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include +#include + +#include "KeyboardShortcutTrapper.h" +#include "ComputerControlInterface.h" + +class QHoverEvent; +class QKeyEvent; +class QMouseEvent; +class QWheelEvent; +class KeyboardShortcutTrapper; + +// clazy:excludeall=copyable-polymorphic + +class VEYON_CORE_EXPORT VncView +{ +public: + enum Shortcut + { + ShortcutCtrlAltDel, + ShortcutCtrlEscape, + ShortcutAltTab, + ShortcutAltF4, + ShortcutWinTab, + ShortcutWin, + ShortcutMenu, + ShortcutAltCtrlF1, + ShortcutCount + } ; + + VncView( const ComputerControlInterface::Pointer& computerControlInterface ); + virtual ~VncView(); + + ComputerControlInterface::Pointer computerControlInterface() const + { + return m_computerControlInterface; + } + + VncConnection* connection() const + { + return m_connection; + } + + bool viewOnly() const + { + return m_viewOnly; + } + + QSize scaledSize() const; + + QSize effectiveFramebufferSize() const; + + const QRect& viewport() const + { + return m_viewport; + } + + void setViewport( QRect viewport ); + + virtual void setViewOnly( bool viewOnly ); + void sendShortcut( VncView::Shortcut shortcut ); + +protected: + template + void connectUpdateFunctions( SubClass* object ) + { + QObject::connect( connection(), &VncConnection::imageUpdated, object, + [this](int x, int y, int w, int h) { updateImage( x, y, w, h ); } ); + QObject::connect( connection(), &VncConnection::framebufferSizeChanged, object, + [this]( int w, int h ) { updateFramebufferSize( w, h ); } ); + + QObject::connect( connection(), &VncConnection::cursorShapeUpdated, object, + [this]( const QPixmap& cursorShape, int xh, int yh ) { updateCursorShape( cursorShape, xh, yh ); } ); + } + + virtual void updateView( int x, int y, int w, int h ) = 0; + virtual QSize viewSize() const = 0; + virtual void setViewCursor( const QCursor& cursor ) = 0; + virtual void updateGeometry() = 0; + + void updateCursorShape( const QPixmap& cursorShape, int xh, int yh ); + void updateFramebufferSize( int w, int h ); + void updateImage( int x, int y, int w, int h ); + + void unpressModifiers(); + + void handleShortcut( KeyboardShortcutTrapper::Shortcut shortcut ); + bool handleEvent( QEvent* handleEvent ); + + virtual void hoverEventHandler( QHoverEvent* event ); + virtual void keyEventHandler( QKeyEvent* event ); + virtual void mouseEventHandler( QMouseEvent* event ); + virtual void wheelEventHandler( QWheelEvent* event ); + + bool isScaledView() const; + + auto cursorShape() const + { + return m_cursorShape; + } + + qreal scaleFactor() const; + QPoint mapToFramebuffer( QPoint pos ); + QRect mapFromFramebuffer( QRect rect ); + + void updateLocalCursor(); + +private: + void pressKey( unsigned int key ); + void unpressKey( unsigned int key ); + + ComputerControlInterface::Pointer m_computerControlInterface; + ComputerControlInterface::UpdateMode m_previousUpdateMode; + + VncConnection* m_connection{nullptr}; + QPixmap m_cursorShape{}; + QPoint m_cursorHot{0, 0}; + QSize m_framebufferSize{0, 0}; + bool m_viewOnly{true}; + + QRect m_viewport{}; + + uint m_buttonMask{0}; + QMap m_mods; + + KeyboardShortcutTrapper* m_keyboardShortcutTrapper{nullptr}; + +} ; diff --git a/core/src/VncViewItem.cpp b/core/src/VncViewItem.cpp new file mode 100644 index 000000000..03283bd1b --- /dev/null +++ b/core/src/VncViewItem.cpp @@ -0,0 +1,125 @@ +/* + * VncViewItem.cpp - QtQuick VNC view item + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#include + +#include "QSGImageTexture.h" +#include "VncViewItem.h" + + +VncViewItem::VncViewItem( const ComputerControlInterface::Pointer& computerControlInterface, QQuickItem* parent ) : + QQuickItem( parent ), + VncView( computerControlInterface ) +{ + connectUpdateFunctions( this ); + + setAcceptHoverEvents( true ); + setAcceptedMouseButtons( Qt::AllButtons ); + setKeepMouseGrab( true ); + + setFlag( ItemHasContents ); + setFlag( ItemIsFocusScope ); +} + + + +VncViewItem::~VncViewItem() +{ + // do not receive any signals during connection shutdown + connection()->disconnect( this ); +} + + + +QSGNode* VncViewItem::updatePaintNode( QSGNode* oldNode, UpdatePaintNodeData* updatePaintNodeData ) +{ + Q_UNUSED(updatePaintNodeData) + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + // TODO + return oldNode; +#else + auto* node = static_cast(oldNode); + if( !node ) + { + node = new QSGSimpleTextureNode(); + auto texture = new QSGImageTexture(); + node->setTexture( texture ); + } + + const auto texture = qobject_cast( node->texture() ); + + if( viewport().isValid() ) + { + texture->setImage( computerControlInterface()->framebuffer().copy( viewport() ) ); + } + else + { + texture->setImage( computerControlInterface()->framebuffer() ); + } + node->setRect( boundingRect() ); + + return node; +#endif +} + + + +void VncViewItem::setViewCursor( const QCursor& cursor ) +{ + setCursor( cursor ); +} + + + +void VncViewItem::updateGeometry() +{ +} + + + +QSize VncViewItem::viewSize() const +{ + return { int(width()), int(height()) }; +} + + + +void VncViewItem::updateView( int x, int y, int w, int h ) +{ + Q_UNUSED(x) + Q_UNUSED(y) + Q_UNUSED(w) + Q_UNUSED(h) + + update(); +} + + + +bool VncViewItem::event( QEvent* event ) +{ + return handleEvent( event ) || QQuickItem::event( event ); +} diff --git a/core/src/VncViewItem.h b/core/src/VncViewItem.h new file mode 100644 index 000000000..1be12d9b8 --- /dev/null +++ b/core/src/VncViewItem.h @@ -0,0 +1,51 @@ +/* + * VncViewItem.h - QtQuick VNC view item + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +#include "VncView.h" + +class VEYON_CORE_EXPORT VncViewItem : public QQuickItem, public VncView +{ + Q_OBJECT +public: + VncViewItem( const ComputerControlInterface::Pointer& computerControlInterface, QQuickItem* parent = nullptr ); + ~VncViewItem() override; + + QSGNode* updatePaintNode( QSGNode *oldNode, UpdatePaintNodeData* updatePaintNodeData ) override; + +protected: + void updateView( int x, int y, int w, int h ) override; + QSize viewSize() const override; + void setViewCursor( const QCursor& cursor ) override; + void updateGeometry() override; + + bool event( QEvent* event ) override; + +private: + QSize m_framebufferSize; + +}; diff --git a/core/src/VncViewWidget.cpp b/core/src/VncViewWidget.cpp new file mode 100644 index 000000000..4908e8d17 --- /dev/null +++ b/core/src/VncViewWidget.cpp @@ -0,0 +1,356 @@ +/* + * VncViewWidget.cpp - VNC viewer widget + * + * Copyright (c) 2006-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include +#include +#include + +#include "VeyonConnection.h" +#include "VncConnection.h" +#include "VncViewWidget.h" + + +VncViewWidget::VncViewWidget( const ComputerControlInterface::Pointer& computerControlInterface, + QRect viewport, QWidget* parent ) : + QWidget( parent ), + VncView( computerControlInterface ) +{ + setViewport( viewport ); + + connectUpdateFunctions( this ); + + connect( connection(), &VncConnection::stateChanged, this, &VncViewWidget::updateConnectionState ); + connect( &m_busyIndicatorTimer, &QTimer::timeout, this, QOverload<>::of(&QWidget::repaint) ); + + // set up mouse border signal timer + m_mouseBorderSignalTimer.setSingleShot( true ); + m_mouseBorderSignalTimer.setInterval( MouseBorderSignalDelay ); + connect( &m_mouseBorderSignalTimer, &QTimer::timeout, this, &VncViewWidget::mouseAtBorder ); + + // set up background color + if( parent == nullptr ) + { + parent = this; + } + QPalette pal = parent->palette(); + pal.setColor( parent->backgroundRole(), Qt::black ); + parent->setPalette( pal ); + + show(); + + setFocusPolicy( Qt::WheelFocus ); + setFocus(); + + setAttribute( Qt::WA_OpaquePaintEvent ); + installEventFilter( this ); + + setMouseTracking( true ); + + updateConnectionState(); +} + + + +VncViewWidget::~VncViewWidget() +{ + // do not receive any signals during connection shutdown + connection()->disconnect( this ); +} + + + +QSize VncViewWidget::sizeHint() const +{ + QSize availableSize{QGuiApplication::primaryScreen()->availableVirtualSize()}; +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + const auto* windowScreen = windowHandle() ? windowHandle()->screen() : nullptr; +#else + const auto* windowScreen = screen(); +#endif + if (windowScreen) + { + availableSize = windowScreen->availableVirtualSize(); + } + + availableSize -= window()->frameSize() - window()->size(); + + const auto size = effectiveFramebufferSize(); + if (size.isEmpty()) + { + return availableSize; + } + + if (size.width() > availableSize.width() || + size.height() > availableSize.height()) + { + return size.scaled(availableSize, Qt::KeepAspectRatio); + } + + return size; +} + + + +void VncViewWidget::setViewOnly( bool enabled ) +{ + if( enabled == viewOnly() ) + { + return; + } + + if( enabled ) + { + releaseKeyboard(); + } + else + { + grabKeyboard(); + } + + VncView::setViewOnly( enabled ); +} + + + +void VncViewWidget::updateView( int x, int y, int w, int h ) +{ + update( x, y, w, h ); +} + + + +QSize VncViewWidget::viewSize() const +{ + return size(); +} + + + +void VncViewWidget::setViewCursor(const QCursor& cursor) +{ + setCursor( cursor ); +} + + + +void VncViewWidget::updateGeometry() +{ + resize( effectiveFramebufferSize() ); + + Q_EMIT sizeHintChanged(); +} + + + +bool VncViewWidget::event( QEvent* event ) +{ + return VncView::handleEvent( event ) || QWidget::event( event ); +} + + + +bool VncViewWidget::eventFilter( QObject* obj, QEvent* event ) +{ + if( viewOnly() ) + { + if( event->type() == QEvent::KeyPress || + event->type() == QEvent::KeyRelease || + event->type() == QEvent::MouseButtonDblClick || + event->type() == QEvent::MouseButtonPress || + event->type() == QEvent::MouseButtonRelease || + event->type() == QEvent::Wheel ) + { + return true; + } + } + + return QWidget::eventFilter( obj, event ); +} + + + +void VncViewWidget::focusInEvent( QFocusEvent* event ) +{ + if( m_viewOnlyFocus == false ) + { + setViewOnly( false ); + } + + QWidget::focusInEvent( event ); +} + + + +void VncViewWidget::focusOutEvent( QFocusEvent* event ) +{ + m_viewOnlyFocus = viewOnly(); + + if( viewOnly() == false ) + { + setViewOnly( true ); + } + + QWidget::focusOutEvent( event ); +} + + + +void VncViewWidget::mouseEventHandler( QMouseEvent* event ) +{ + if( event == nullptr ) + { + return; + } + + VncView::mouseEventHandler( event ); + + if( event->type() == QEvent::MouseMove ) + { + if( event->pos().y() == 0 ) + { + if( m_mouseBorderSignalTimer.isActive() == false ) + { + m_mouseBorderSignalTimer.start(); + } + } + else + { + m_mouseBorderSignalTimer.stop(); + } + } +} + + + +void VncViewWidget::paintEvent( QPaintEvent* paintEvent ) +{ + QPainter p( this ); + p.setRenderHint( QPainter::SmoothPixmapTransform ); + + const auto& image = connection()->image(); + + if( image.isNull() || image.format() == QImage::Format_Invalid ) + { + p.fillRect( paintEvent->rect(), Qt::black ); + drawBusyIndicator( &p ); + return; + } + + auto source = viewport(); + if( source.isNull() || source.isEmpty() ) + { + source = { QPoint{ 0, 0 }, image.size() }; + } + + if( isScaledView() ) + { + // repaint everything in scaled mode to avoid artifacts at rectangle boundaries + p.drawImage( QRect( QPoint( 0, 0 ), scaledSize() ), image, source ); + } + else + { + p.drawImage( { 0, 0 }, image, source ); + } + + if( connection()->state() != VncConnection::State::Connected ) + { + drawBusyIndicator( &p ); + } + + // draw black borders if neccessary + const int screenWidth = scaledSize().width(); + if( screenWidth < width() ) + { + p.fillRect( screenWidth, 0, width() - screenWidth, height(), Qt::black ); + } + + const int screenHeight = scaledSize().height(); + if( screenHeight < height() ) + { + p.fillRect( 0, screenHeight, width(), height() - screenHeight, Qt::black ); + } +} + + + +void VncViewWidget::resizeEvent( QResizeEvent* event ) +{ + update(); + + updateLocalCursor(); + + QWidget::resizeEvent( event ); +} + + + +void VncViewWidget::drawBusyIndicator( QPainter* painter ) +{ + static constexpr int BusyIndicatorSize = 100; + static constexpr int BusyIndicatorSpeed = 5; + + QRect drawingRect{ + ( width() - BusyIndicatorSize ) / 2, + ( height() - BusyIndicatorSize ) / 2, + BusyIndicatorSize, BusyIndicatorSize, + }; + + QColor color(QStringLiteral("#00acdc")); + QConicalGradient gradient; + gradient.setCenter(drawingRect.center()); + gradient.setAngle((360 - m_busyIndicatorState) % 360); + gradient.setColorAt(0, color); + color.setAlpha(0); + gradient.setColorAt(0.75, color); + color.setAlpha(255); + gradient.setColorAt(1, color); + + QPen pen(QBrush(gradient), 20); + pen.setCapStyle(Qt::RoundCap); + painter->setPen(pen); + + painter->setRenderHint(QPainter::Antialiasing); + painter->drawArc( drawingRect, + ( 360 - ( m_busyIndicatorState % 360 ) ) * 16, 270 * 16 ); + + m_busyIndicatorState += BusyIndicatorSpeed; +} + + + +void VncViewWidget::updateConnectionState() +{ + if( connection()->state() != VncConnection::State::Connected ) + { + m_busyIndicatorTimer.start( BusyIndicatorUpdateInterval ); + } + else + { + m_busyIndicatorTimer.stop(); + + resize( effectiveFramebufferSize() ); + } +} diff --git a/core/src/VncViewWidget.h b/core/src/VncViewWidget.h new file mode 100644 index 000000000..f94060277 --- /dev/null +++ b/core/src/VncViewWidget.h @@ -0,0 +1,78 @@ +/* + * VncViewWidget.h - VNC viewer widget + * + * Copyright (c) 2006-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include +#include + +#include "VncView.h" +#include "ComputerControlInterface.h" + +class VEYON_CORE_EXPORT VncViewWidget : public QWidget, public VncView +{ + Q_OBJECT +public: + VncViewWidget( const ComputerControlInterface::Pointer& computerControlInterface, QRect viewport, + QWidget* parent ); + + ~VncViewWidget() override; + + QSize sizeHint() const override; + + void setViewOnly( bool enabled ) override; + +Q_SIGNALS: + void mouseAtBorder(); + void sizeHintChanged(); + +protected: + void updateView( int x, int y, int w, int h ) override; + QSize viewSize() const override; + void setViewCursor( const QCursor& cursor ) override; + + void updateGeometry() override; + + bool event( QEvent* handleEvent ) override; + bool eventFilter( QObject* obj, QEvent* handleEvent ) override; + void focusInEvent( QFocusEvent* handleEvent ) override; + void focusOutEvent( QFocusEvent* handleEvent ) override; + void mouseEventHandler( QMouseEvent* handleEvent ) override; + void paintEvent( QPaintEvent* handleEvent ) override; + void resizeEvent( QResizeEvent* handleEvent ) override; + +private: + void drawBusyIndicator( QPainter* painter ); + void updateConnectionState(); + + bool m_viewOnlyFocus{true}; + + static constexpr auto BusyIndicatorUpdateInterval = 25; + QTimer m_busyIndicatorTimer{this}; + int m_busyIndicatorState{0}; + + static constexpr int MouseBorderSignalDelay = 500; + QTimer m_mouseBorderSignalTimer{this}; + +} ; diff --git a/core/src/d3des.c b/core/src/d3des.c new file mode 100644 index 000000000..e76ece79a --- /dev/null +++ b/core/src/d3des.c @@ -0,0 +1,437 @@ +/* + * This is D3DES (V5.09) by Richard Outerbridge with the double and + * triple-length support removed for use in VNC. Also the bytebit[] array + * has been reversed so that the most significant bit in each byte of the + * key is ignored, not the least significant. + * + * These changes are: + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This software 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. + */ + +/* D3DES (V5.09) - + * + * A portable, public domain, version of the Data Encryption Standard. + * + * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge. + * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation + * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis + * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau, + * for humouring me on. + * + * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge. + * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992. + */ + +#include "d3des.h" + +#if defined(__GNUC__) +#define TLS __thread +#elif defined(_MSC_VER) +#define TLS __declspec(thread) +#else +#define TLS +#endif + +static void scrunch(unsigned char *, unsigned long *); +static void unscrun(unsigned long *, unsigned char *); +static void desfunc(unsigned long *, unsigned long *); +static void cookey(unsigned long *); + +static TLS unsigned long KnL[32] = { 0L }; +/* +static unsigned long KnR[32] = { 0L }; +static unsigned long Kn3[32] = { 0L }; +static unsigned char Df_Key[24] = { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10, + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 }; +*/ + +static const unsigned short bytebit[8] = { + 01, 02, 04, 010, 020, 040, 0100, 0200 }; + +static const unsigned long bigbyte[24] = { + 0x800000L, 0x400000L, 0x200000L, 0x100000L, + 0x80000L, 0x40000L, 0x20000L, 0x10000L, + 0x8000L, 0x4000L, 0x2000L, 0x1000L, + 0x800L, 0x400L, 0x200L, 0x100L, + 0x80L, 0x40L, 0x20L, 0x10L, + 0x8L, 0x4L, 0x2L, 0x1L }; + +/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */ + +static const unsigned char pc1[56] = { + 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, + 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, + 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, + 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; + +static const unsigned char totrot[16] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 }; + +static const unsigned char pc2[48] = { + 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, + 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, + 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, + 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; + +void rfbDesKey(unsigned char *key, + int edf) +{ + register int i, j, l, m, n; + unsigned char pc1m[56], pcr[56]; + unsigned long kn[32]; + + for ( j = 0; j < 56; j++ ) { + l = pc1[j]; + m = l & 07; + pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0; + } + for( i = 0; i < 16; i++ ) { + if( edf == DE1 ) m = (15 - i) << 1; + else m = i << 1; + n = m + 1; + kn[m] = kn[n] = 0L; + for( j = 0; j < 28; j++ ) { + l = j + totrot[i]; + if( l < 28 ) pcr[j] = pc1m[l]; + else pcr[j] = pc1m[l - 28]; + } + for( j = 28; j < 56; j++ ) { + l = j + totrot[i]; + if( l < 56 ) pcr[j] = pc1m[l]; + else pcr[j] = pc1m[l - 28]; + } + for( j = 0; j < 24; j++ ) { + if( pcr[pc2[j]] ) kn[m] |= bigbyte[j]; + if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j]; + } + } + cookey(kn); + return; + } + +static void rfbUseKey(register unsigned long *from) +{ + register unsigned long *to, *endp; + + to = KnL, endp = &KnL[32]; + while( to < endp ) *to++ = *from++; + return; + } + + +static void cookey(register unsigned long *raw1) +{ + register unsigned long *cook, *raw0; + unsigned long dough[32]; + register int i; + + cook = dough; + for( i = 0; i < 16; i++, raw1++ ) { + raw0 = raw1++; + *cook = (*raw0 & 0x00fc0000L) << 6; + *cook |= (*raw0 & 0x00000fc0L) << 10; + *cook |= (*raw1 & 0x00fc0000L) >> 10; + *cook++ |= (*raw1 & 0x00000fc0L) >> 6; + *cook = (*raw0 & 0x0003f000L) << 12; + *cook |= (*raw0 & 0x0000003fL) << 16; + *cook |= (*raw1 & 0x0003f000L) >> 4; + *cook++ |= (*raw1 & 0x0000003fL); + } + rfbUseKey(dough); + return; + } + + +void rfbDes(unsigned char *inblock, + unsigned char *outblock) +{ + unsigned long work[2]; + + scrunch(inblock, work); + desfunc(work, KnL); + unscrun(work, outblock); + return; + } + +static void scrunch(register unsigned char *outof, + register unsigned long *into) +{ + *into = (*outof++ & 0xffL) << 24; + *into |= (*outof++ & 0xffL) << 16; + *into |= (*outof++ & 0xffL) << 8; + *into++ |= (*outof++ & 0xffL); + *into = (*outof++ & 0xffL) << 24; + *into |= (*outof++ & 0xffL) << 16; + *into |= (*outof++ & 0xffL) << 8; + *into |= (*outof & 0xffL); + return; + } + +static void unscrun(register unsigned long *outof, + register unsigned char *into) +{ + *into++ = (unsigned char)((*outof >> 24) & 0xffL); + *into++ = (unsigned char)((*outof >> 16) & 0xffL); + *into++ = (unsigned char)((*outof >> 8) & 0xffL); + *into++ = (unsigned char)( *outof++ & 0xffL); + *into++ = (unsigned char)((*outof >> 24) & 0xffL); + *into++ = (unsigned char)((*outof >> 16) & 0xffL); + *into++ = (unsigned char)((*outof >> 8) & 0xffL); + *into = (unsigned char)( *outof & 0xffL); + return; + } + +static const unsigned long SP1[64] = { + 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, + 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, + 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, + 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, + 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, + 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, + 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, + 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, + 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, + 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, + 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, + 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, + 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, + 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, + 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, + 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L }; + +static const unsigned long SP2[64] = { + 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, + 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, + 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, + 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, + 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, + 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, + 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, + 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, + 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, + 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, + 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, + 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, + 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, + 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, + 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, + 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L }; + +static const unsigned long SP3[64] = { + 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, + 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, + 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, + 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, + 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, + 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, + 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, + 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, + 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, + 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, + 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, + 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, + 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, + 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L, + 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, + 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L }; + +static const unsigned long SP4[64] = { + 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, + 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, + 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, + 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L, + 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L, + 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L, + 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L, + 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L, + 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L, + 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L, + 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L, + 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, + 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L, + 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L, + 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, + 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L }; + +static const unsigned long SP5[64] = { + 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, + 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, + 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, + 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L, + 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L, + 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L, + 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L, + 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L, + 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L, + 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L, + 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L, + 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L, + 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L, + 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L, + 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, + 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L }; + +static const unsigned long SP6[64] = { + 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, + 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, + 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, + 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L, + 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L, + 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L, + 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L, + 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L, + 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L, + 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L, + 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L, + 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L, + 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L, + 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L, + 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, + 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L }; + +static const unsigned long SP7[64] = { + 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, + 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, + 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, + 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L, + 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L, + 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L, + 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L, + 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L, + 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L, + 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L, + 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L, + 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L, + 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L, + 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L, + 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, + 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L }; + +static const unsigned long SP8[64] = { + 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, + 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, + 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, + 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L, + 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L, + 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L, + 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L, + 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L, + 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L, + 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L, + 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L, + 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L, + 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L, + 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L, + 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L, + 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L }; + +static void desfunc(register unsigned long *block, + register unsigned long *keys) +{ + register unsigned long fval, work, right, leftt; + register int round; + + leftt = block[0]; + right = block[1]; + work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; + right ^= work; + leftt ^= (work << 4); + work = ((leftt >> 16) ^ right) & 0x0000ffffL; + right ^= work; + leftt ^= (work << 16); + work = ((right >> 2) ^ leftt) & 0x33333333L; + leftt ^= work; + right ^= (work << 2); + work = ((right >> 8) ^ leftt) & 0x00ff00ffL; + leftt ^= work; + right ^= (work << 8); + right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL; + work = (leftt ^ right) & 0xaaaaaaaaL; + leftt ^= work; + right ^= work; + leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL; + + for( round = 0; round < 8; round++ ) { + work = (right << 28) | (right >> 4); + work ^= *keys++; + fval = SP7[ work & 0x3fL]; + fval |= SP5[(work >> 8) & 0x3fL]; + fval |= SP3[(work >> 16) & 0x3fL]; + fval |= SP1[(work >> 24) & 0x3fL]; + work = right ^ *keys++; + fval |= SP8[ work & 0x3fL]; + fval |= SP6[(work >> 8) & 0x3fL]; + fval |= SP4[(work >> 16) & 0x3fL]; + fval |= SP2[(work >> 24) & 0x3fL]; + leftt ^= fval; + work = (leftt << 28) | (leftt >> 4); + work ^= *keys++; + fval = SP7[ work & 0x3fL]; + fval |= SP5[(work >> 8) & 0x3fL]; + fval |= SP3[(work >> 16) & 0x3fL]; + fval |= SP1[(work >> 24) & 0x3fL]; + work = leftt ^ *keys++; + fval |= SP8[ work & 0x3fL]; + fval |= SP6[(work >> 8) & 0x3fL]; + fval |= SP4[(work >> 16) & 0x3fL]; + fval |= SP2[(work >> 24) & 0x3fL]; + right ^= fval; + } + + right = (right << 31) | (right >> 1); + work = (leftt ^ right) & 0xaaaaaaaaL; + leftt ^= work; + right ^= work; + leftt = (leftt << 31) | (leftt >> 1); + work = ((leftt >> 8) ^ right) & 0x00ff00ffL; + right ^= work; + leftt ^= (work << 8); + work = ((leftt >> 2) ^ right) & 0x33333333L; + right ^= work; + leftt ^= (work << 2); + work = ((right >> 16) ^ leftt) & 0x0000ffffL; + leftt ^= work; + right ^= (work << 16); + work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; + leftt ^= work; + right ^= (work << 4); + *block++ = right; + *block = leftt; + return; + } + +/* Validation sets: + * + * Single-length key, single-length plaintext - + * Key : 0123 4567 89ab cdef + * Plain : 0123 4567 89ab cde7 + * Cipher : c957 4425 6a5e d31d + * + * Double-length key, single-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 + * Plain : 0123 4567 89ab cde7 + * Cipher : 7f1d 0a77 826b 8aff + * + * Double-length key, double-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 + * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff + * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7 + * + * Triple-length key, single-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 + * Plain : 0123 4567 89ab cde7 + * Cipher : de0b 7c06 ae5e 0ed5 + * + * Triple-length key, double-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 + * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff + * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5 + * + * d3des V5.0a rwo 9208.07 18:44 Graven Imagery + **********************************************************************/ diff --git a/core/src/d3des.h b/core/src/d3des.h new file mode 100644 index 000000000..4bb6bdbda --- /dev/null +++ b/core/src/d3des.h @@ -0,0 +1,46 @@ +#ifndef D3DES_H +#define D3DES_H + +/* + * This is D3DES (V5.09) by Richard Outerbridge with the double and + * triple-length support removed for use in VNC. + * + * These changes are: + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This software 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. + */ + +/* d3des.h - + * + * Headers and defines for d3des.c + * Graven Imagery, 1992. + * + * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge + * (GEnie : OUTER; CIS : [71755,204]) + */ + +#define EN0 0 /* MODE == encrypt */ +#define DE1 1 /* MODE == decrypt */ + +extern void rfbDesKey(unsigned char *, int); +/* hexkey[8] MODE + * Sets the internal key register according to the hexadecimal + * key contained in the 8 bytes of hexkey, according to the DES, + * for encryption or decryption according to MODE. + */ + + +extern void rfbDes(unsigned char *, unsigned char *); +/* from[8] to[8] + * Encrypts/Decrypts (according to the key currently loaded in the + * internal key register) one block of eight bytes at address 'from' + * into the block at address 'to'. They can be the same. + */ + +/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery + ********************************************************************/ + +#endif diff --git a/core/include/veyonconfig.h.in b/core/src/veyonconfig.h.in similarity index 61% rename from core/include/veyonconfig.h.in rename to core/src/veyonconfig.h.in index 018a9ddb0..83b96dce1 100644 --- a/core/include/veyonconfig.h.in +++ b/core/src/veyonconfig.h.in @@ -1,7 +1,11 @@ #pragma once #define VEYON_VERSION "@VERSION_STRING@" +#define VEYON_VERSION_MAJOR @VERSION_MAJOR@ +#define VEYON_VERSION_MINOR @VERSION_MINOR@ #define VEYON_PLUGIN_DIR "@VEYON_PLUGIN_DIR@" #define VEYON_TRANSLATIONS_DIR "@VEYON_TRANSLATIONS_DIR@" #define VEYON_EXECUTABLE_SUFFIX "@CMAKE_EXECUTABLE_SUFFIX@" #define VEYON_SHARED_LIBRARY_SUFFIX "@CMAKE_SHARED_LIBRARY_SUFFIX@" +#define CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@" +#cmakedefine VEYON_WITH_TESTS "@WITH_TESTS@" diff --git a/master/CMakeLists.txt b/master/CMakeLists.txt index 2dbdc9633..125a4df55 100644 --- a/master/CMakeLists.txt +++ b/master/CMakeLists.txt @@ -1,31 +1,19 @@ -INCLUDE(BuildApplication) -INCLUDE(WindowsBuildHelpers) +include(BuildVeyonApplication) +include(WindowsBuildHelpers) -SET(kitemmodels_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/kitemmodels/src) -SET(kitemmodels_SOURCES - ${kitemmodels_SOURCE_DIR}/kextracolumnsproxymodel.cpp - ${kitemmodels_SOURCE_DIR}/krecursivefilterproxymodel.cpp - ${kitemmodels_SOURCE_DIR}/kextracolumnsproxymodel.h - ${kitemmodels_SOURCE_DIR}/krecursivefilterproxymodel.h -) +file(GLOB master_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.*) -FILE(GLOB master_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h) -FILE(GLOB master_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/*.ui) +set(master_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/resources/master.qrc) +if(VEYON_DEBUG) + set(master_RESOURCES ${master_RESOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/examples.qrc) +endif() +set(master_RESOURCES ${master_RESOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/qml/qml.qrc) -SET(master_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/resources/master.qrc) -IF(VEYON_DEBUG) -SET(master_RESOURCES ${master_RESOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/examples.qrc) -ENDIF() +build_veyon_application(veyon-master ${master_SOURCES} ${master_RESOURCES}) -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src ${kitemmodels_SOURCE_DIR}) -BUILD_APPLICATION(veyon-master ${master_SOURCES} ${master_INCLUDES} ${master_RESOURCES} ${kitemmodels_SOURCES}) -TARGET_LINK_LIBRARIES(veyon-master veyon-core) +add_windows_resource(veyon-master) +make_graphical_app(veyon-master) -ADD_WINDOWS_RESOURCE(veyon-master) -MAKE_GRAPHICAL_APP(veyon-master) - -IF(VEYON_BUILD_LINUX) - XDG_INSTALL(${CMAKE_CURRENT_BINARY_DIR}/data/veyon-master.desktop ${CMAKE_CURRENT_SOURCE_DIR}/data/veyon-master.xpm ${CMAKE_CURRENT_SOURCE_DIR}/data/veyon-master.png ${CMAKE_CURRENT_SOURCE_DIR}/data/veyon-master.svg) -ENDIF() - -COTIRE_VEYON(veyon-master) +if(VEYON_BUILD_LINUX) + xdg_install(${CMAKE_CURRENT_BINARY_DIR}/data/veyon-master.desktop ${CMAKE_CURRENT_SOURCE_DIR}/data/veyon-master.xpm ${CMAKE_CURRENT_SOURCE_DIR}/data/veyon-master.png ${CMAKE_CURRENT_SOURCE_DIR}/data/veyon-master.svg) +endif() diff --git a/master/data/veyon-master.desktop.in b/master/data/veyon-master.desktop.in index 34f1c0373..061704d1f 100644 --- a/master/data/veyon-master.desktop.in +++ b/master/data/veyon-master.desktop.in @@ -7,5 +7,7 @@ Terminal=false Name=Veyon Master Comment=Monitor and control remote computers Comment[de]=Entfernte Computer beobachten und steuern +Comment[ru]=Наблюдение за удалёнными компьютерами и управление ими +Comment[pt]=Monitore e controle computadores remotos Categories=Qt;Education;Network;RemoteAccess; Keywords=classroom,control,computer,room,lab,monitoring,teacher,student diff --git a/master/qml/AppDrawer.qml b/master/qml/AppDrawer.qml new file mode 100644 index 000000000..c51e3393c --- /dev/null +++ b/master/qml/AppDrawer.qml @@ -0,0 +1,98 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.0 +import QtQml.Models 2.1 + +Drawer { + id: drawer + + ColumnLayout { + anchors.fill: parent + Rectangle { + color: themeColor + Layout.fillWidth: true + height: drawerTitleLayout.implicitHeight + RowLayout { + id: drawerTitleLayout + anchors.fill: parent + Image { + id: logo + source: "qrc:/core/icon64.png" + Layout.maximumHeight: titleLabel.implicitHeight*1.4 + Layout.maximumWidth: Layout.maximumHeight + Layout.margins: 10 + } + Label { + id: titleLabel + color: "white" + text: drawerMenu.subPageTitle ? drawerMenu.subPageTitle : appWindow.title + font.capitalization: Font.AllUppercase + font.bold: true + fontSizeMode: Label.Fit + font.pointSize: dummy.font.pointSize*1.4 + } + Label { + id: dummy + Layout.fillWidth: true + } + } + } + + MenuItem { + id: drawerGoBackItem + visible: drawerMenu.model.rootIndex.valid + onClicked: drawerMenu.model.rootIndex = drawerMenu.model.parentModelIndex() + Image { + anchors.left: parent.left + source: "qrc:/core/go-previous.png" + width: height + height: parent.implicitHeight*0.8 + anchors.verticalCenter: parent.verticalCenter + } + Layout.fillWidth: true + } + + ListView { + id: drawerMenu + property var subPageTitle: masterCore.computerSelectModel.value(model.rootIndex, "name") + model: DelegateModel { + model: masterCore.computerSelectModel + delegate: RowLayout { + spacing: 0 + width: drawerMenu.width + MenuItem { + text: name + checkable: true + checked: checkState + visible: String(type) === "Host" + Layout.fillWidth: true + onClicked: checkState = checked ? Qt.Checked : Qt.Unchecked + } + CheckBox { + id: checkBox + checkState: model.checkState + onClicked: model.checkState = checkState + visible: String(type) === "Location" + tristate: checkState == Qt.PartiallyChecked + Layout.maximumWidth: height + } + MenuItem { + text: name + visible: String(type) === "Location" + Image { + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + source: "qrc:/core/go-next.png" + width: height + height: parent.implicitHeight*0.8 + } + Layout.fillWidth: true + onClicked: drawerMenu.model.rootIndex = drawerMenu.model.modelIndex(index) + } + } + } + Layout.fillWidth: true + Layout.fillHeight: true + } + } +} diff --git a/master/qml/ButtonMenu.qml b/master/qml/ButtonMenu.qml new file mode 100644 index 000000000..07f3afd2c --- /dev/null +++ b/master/qml/ButtonMenu.qml @@ -0,0 +1,31 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.0 + +Menu { + id: control + + property alias model: repeater.model + + signal itemSelected(var itemData) + + function exec(button) + { + parent = button; + popup(0, button.height); + } + + Repeater { + id: repeater + model: groupSelector.availableGroups + MenuItem { + contentItem: Label { + text: modelData.text + color: modelData.color + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + onClicked: control.itemSelected(modelData) + } + } +} diff --git a/master/qml/ComputerDelegate.qml b/master/qml/ComputerDelegate.qml new file mode 100644 index 000000000..83fc91d53 --- /dev/null +++ b/master/qml/ComputerDelegate.qml @@ -0,0 +1,68 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.0 + +Rectangle { + id: item + width: view.cellWidth + height: view.cellHeight + + property var textColor + property var view + property bool isComputerItem: true + property bool selected: false + property var objectUid: uid + property var groups: model.groups + + function addGroup(group) + { + var groups = Array.from(model.groups); + groups.push(String(group)) + model.groups = Array.from(new Set(groups)); + } + + function removeGroup(group) + { + model.groups = Array.from(model.groups).filter(item => item !== String(group)) + } + + color: selected ? themeColor : "transparent"; + + ColumnLayout { + anchors.fill: parent + //clip: true + id: computerItemLayout + spacing: 0 + Image { + source: imageId; + Layout.alignment: Qt.AlignCenter + Layout.margins: 5 + MouseArea { + anchors.fill: parent + onClicked: item.selected = !item.selected + } + } + Label { + id: label + text: display; + Layout.maximumWidth: view.cellWidth + Layout.margins: 5 + Layout.alignment: Qt.AlignCenter + clip: true + elide: Label.ElideRight + color: parent.GridView.isCurrentItem ? "white" : item.textColor + + } + + RowLayout { + Repeater { + model: item.groups + delegate: Rectangle { + width: view.cellWidth / 5 + height: 3 + color: modelData + } + } + } + } +} diff --git a/master/qml/ComputerGroupSelector.qml b/master/qml/ComputerGroupSelector.qml new file mode 100644 index 000000000..9b3056386 --- /dev/null +++ b/master/qml/ComputerGroupSelector.qml @@ -0,0 +1,70 @@ +import QtQuick 2.10 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.0 + +Repeater { + model: [ "#ff0000", "#00aa00", "#0000ff", "#ffaa00", "#00aaff"] + + property var availableGroups: { + var groups = [] + for( let i = 0; i < count; ++i ) + { + let item = itemAt(i) + groups.push( { "text": item.name, "color": item.groupColor } ) + } + return groups + } + + property var selectedGroups: { + let groups = [] + for( let i = 0; i < count; ++i ) + { + let item = itemAt(i) + if( item.checked ) + { + groups.push( item.groupColor ) + } + } + return groups + } + + Button { + id: control + checkable: true + padding: 5 + leftPadding: padding*3 + rightPadding: padding*3 + Layout.fillWidth: true + + property var groupColor: modelData + property alias name: nameInput.text + + background: Rectangle { + anchors.fill: parent + color: checked ? modelData : "white" + border.color: modelData + border.width: 1 + } + + contentItem: TextInput { + id: nameInput + color: control.checked ? "white" : modelData + text: qsTr("Group %1").arg(index+1) + onEditingFinished: focus = false + MouseArea { + anchors.fill: parent + onClicked: { + if( nameInput.focus ) + { + nameInput.focus = false + } + else + { + control.checked = !control.checked + } + } + onPressAndHold: nameInput.focus = true + } + } + } +} diff --git a/master/qml/ComputerMonitoring.qml b/master/qml/ComputerMonitoring.qml new file mode 100644 index 000000000..c421cb26c --- /dev/null +++ b/master/qml/ComputerMonitoring.qml @@ -0,0 +1,220 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.0 +import QtQml.Models 2.12 +import Veyon.Master 5.0 + +Page { + + title: qsTr("Computers") + readonly property bool canBeClosed: false + + header: Flow { + Repeater { + model: masterCore.featureListModel + delegate: FeatureButton { + text: displayName + iconSource: iconUrl + onClicked: computerMonitoring.runFeature(uid) + } + } + } + + ButtonMenu { + id: addToGroupPopupMenu + model: computerGroupSelector.availableGroups + onItemSelected: computerMonitoringView.addSelectedToGroup(itemData.color) + } + + ButtonMenu { + id: removeFromGroupPopupMenu + model: computerGroupSelector.availableGroups + onItemSelected: computerMonitoringView.removeSelectedFromGroup(itemData.color) + } + + ComputerMonitoringItem { + + id: computerMonitoring + searchFilter: searchFilterInput.text + groupFilter: computerGroupSelector.selectedGroups + anchors.fill: parent + + selectedObjects: { + let objectUids = [] + for( let item in computerMonitoringView.selectedItems ) + { + objectUids.push(computerMonitoringView.selectedItems[item].objectUid) + } + return objectUids + } + + Rectangle { + anchors.fill: parent + color: computerMonitoring.backgroundColor + } + + GridView { + id: computerMonitoringView + anchors.fill: parent + clip: true + anchors.margins: 2 + model: computerMonitoring.model + cellWidth: computerMonitoring.iconSize.width + 10 + cellHeight: computerMonitoring.iconSize.height + 25 + dummyLabel.implicitHeight + 3 + delegate: ComputerDelegate { + view: computerMonitoringView + textColor: computerMonitoring.textColor + } + + ScrollBar.vertical: ScrollBar { + visible: computerMonitoringView.contentHeight > computerMonitoringView.height + policy: visible ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff + } + + Label { + id: dummyLabel + visible: false + } + + function setAllSelected( selected ) + { + for( let child in contentItem.children ) + { + var item = contentItem.children[child] + if( item.isComputerItem ) + { + item.selected = selected + } + } + } + + function addSelectedToGroup( group ) + { + for( let item in selectedItems ) + { + selectedItems[item].addGroup( [group] ) + } + } + + function removeSelectedFromGroup( group ) + { + for( let item in selectedItems ) + { + selectedItems[item].removeGroup( [group] ) + } + } + + property var selectedItems : { + var items = [] + for( let child in contentItem.children ) + { + let item = contentItem.children[child] + if( item.isComputerItem && item.selected ) + { + items.push(item) + } + } + return items + } + + property var allItems : { + var items = [] + for( let child in contentItem.children ) + { + var item = contentItem.children[child] + if( item.isComputerItem ) + { + items.push(item) + } + } + return items + } + + property bool selecting: selectedItems.length > 0 + } + } + + footer: GridLayout { + columnSpacing: 10 + columns: appWindow.landscape ? 10 : 1 + + RowLayout { + Layout.leftMargin: 5 + Layout.rightMargin: 5 + visible: !computerMonitoringView.selecting + ComputerGroupSelector { + id: computerGroupSelector + } + Layout.maximumWidth: appWindow.landscape ? implicitWidth : parent.width - Layout.leftMargin - Layout.rightMargin + } + + TextField { + id: searchFilterInput + placeholderText: qsTr("Search users and computers") + implicitWidth: parent.width / 5 + visible: !computerMonitoringView.selecting && appWindow.landscape + padding: 3 + } + + RowLayout { + visible: computerMonitoringView.selecting + Layout.alignment: Qt.AlignCenter + Repeater { + model: ListModel { + ListElement { + displayName: qsTr("Select all") + iconUrl: "qrc:/master/edit-select-all.png" + handler: () => { computerMonitoringView.setAllSelected(true) } + } + ListElement { + displayName: qsTr("Unselect all") + iconUrl: "qrc:/master/homerun.png" + handler: () => { computerMonitoringView.setAllSelected(false) } + } + ListElement { + displayName: qsTr("Add to group") + iconUrl: "qrc:/master/add-group.png" + handler: (button) => { addToGroupPopupMenu.exec(button); } + } + ListElement { + displayName: qsTr("Remove from group") + iconUrl: "qrc:/master/remove-group.png" + handler: (button) => { removeFromGroupPopupMenu.exec(button) } + } + } + + Button { + padding: 7 + leftPadding: 10 + rightPadding: 10 + topInset: 0 + bottomInset: 0 + leftInset: 0 + rightInset: 0 + background: Rectangle { + color: parent.down ? "#ccc" : parent.hovered ? "#ddd" : "white" + border.color: "#888" + border.width: 1 + } + text: displayName + display: Button.TextUnderIcon + icon.source: iconUrl + icon.color: "transparent" + onClicked: handler(this) + } + } + } + + Slider { + id: computerScreenSizeSlider + from: ComputerMonitoringItem.MinimumComputerScreenSize + to: ComputerMonitoringItem.MaximumComputerScreenSize + value: computerMonitoring.iconSize.width + implicitWidth: appWindow.landscape ? parent.width / 4 : parent.width + visible: !computerMonitoringView.selecting + onMoved: computerMonitoring.computerScreenSize = value + Layout.alignment: Qt.AlignRight + Layout.rightMargin: 10 + } + } +} diff --git a/master/qml/FeatureButton.qml b/master/qml/FeatureButton.qml new file mode 100644 index 000000000..a5d579246 --- /dev/null +++ b/master/qml/FeatureButton.qml @@ -0,0 +1,45 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.12 + +Button { + + property alias iconSource: icon.source + + id: control + + topInset: 0 + bottomInset: 0 + padding: 4 + width: height*1.3 + + background: Rectangle { + color: control.down ? "#ddd" : control.hovered ? "#eee" : "transparent" + width: parent.width + } + + contentItem: ColumnLayout { + id: col + spacing: 0 + Image { + id: icon + Layout.maximumHeight: appWindow.landscape ? label.implicitHeight*3 : label.implicitHeight * 2 + Layout.maximumWidth: Layout.maximumHeight + Layout.alignment: Qt.AlignCenter + } + + Label { + id: label + text: control.text + horizontalAlignment: Label.AlignHCenter + verticalAlignment: Label.AlignBottom + fontSizeMode: Label.Fit + Layout.fillWidth: true + Layout.leftMargin: 5 + Layout.rightMargin: 5 + Layout.bottomMargin: 5 + minimumPointSize: font.pointSize * 0.75 + elide: Label.ElideRight + } + } +} diff --git a/master/qml/MainWindow.qml b/master/qml/MainWindow.qml new file mode 100644 index 000000000..22802d619 --- /dev/null +++ b/master/qml/MainWindow.qml @@ -0,0 +1,51 @@ +import QtQuick 2.0 +import QtQuick.Window 2.1 +import QtQuick.Controls 2.0 +import QtQuick.Controls.Material 2.0 +import QtQuick.Layouts 1.0 +import Veyon.Master 5.0 +import "qrc:/master" + +ApplicationWindow { + id: appWindow + visible: true + width: 1600 + height: 900 + font.pointSize: 10 + + property color themeColor: "#00BCD4"; + property bool landscape: width > height + + Material.theme: Material.Light + Material.accent: Material.Cyan + Material.primary: Material.Cyan + + title: qsTr("Veyon Master") + + Component.onCompleted: { + masterCore.appWindow = this + masterCore.appContainer = container + } + + ColumnLayout { + anchors.fill: parent + spacing: 0 + + TitleBar { + Layout.fillWidth: true + container: container + appDrawer: AppDrawer { + width: Math.max(300, landscape ? 0.25 * appWindow.width : 0.5*appWindow.width) + height: appWindow.height + } + } + + SwipeView { + id: container + Layout.fillHeight: true + Layout.fillWidth: true + + ComputerMonitoring { } + } + } +} diff --git a/master/qml/TitleBar.qml b/master/qml/TitleBar.qml new file mode 100644 index 000000000..804cbfaa7 --- /dev/null +++ b/master/qml/TitleBar.qml @@ -0,0 +1,67 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.0 +import "qrc:/master" + +Rectangle { + id: control + height: layout.implicitHeight + //spacing: 0 + color: themeColor + + property var appDrawer + property var container + + RowLayout { + id: layout + spacing: 0 + anchors.fill: parent + + Image { + id: appMenu + source: "qrc:/master/application-menu.png" + Layout.maximumHeight: tabsLayout.implicitHeight // TODO + Layout.maximumWidth: Layout.maximumHeight + Layout.alignment: Qt.AlignVCenter + Layout.margins: 5 + MouseArea { + anchors.fill: parent + onClicked: appDrawer.open() + } + } + + RowLayout { + id: tabsLayout + spacing: 0 + Repeater { + model: container.contentChildren + + TitleBarTab { + Layout.topMargin: 2 + Layout.fillHeight: true + text: modelData.title + canBeClosed: modelData.canBeClosed + active: container.currentIndex === index + onClicked: { + if( active ) + { + if( container.currentItem.header ) + { + container.currentItem.header.visible = !container.currentItem.header.visible + } + } + else + { + container.currentIndex = index + } + } + onClosed: modelData.close() + } + } + } + + Item { + Layout.fillWidth: true + } + } +} diff --git a/master/qml/TitleBarTab.qml b/master/qml/TitleBarTab.qml new file mode 100644 index 000000000..42c472ab7 --- /dev/null +++ b/master/qml/TitleBarTab.qml @@ -0,0 +1,74 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.0 + +Item { + property bool active: false + property alias text: label.text + property bool canBeClosed: true + + signal clicked() + signal closed() + + id: item + + implicitWidth: labelLayout.implicitWidth + implicitHeight: labelLayout.implicitHeight - label.Layout.margins + + MouseArea { + anchors.fill: parent + onClicked: item.clicked(); + } + + Rectangle { + color: "white" + visible: active + anchors.fill: parent + } + + RowLayout { + id: labelLayout + anchors.fill: parent + spacing: 0 + Label { + id: label + Layout.margins: 8 + font.bold: true + font.capitalization: Font.AllUppercase + color: active ? "#444" : "white" + } + Item { + width: height + height: closeLabel.implicitHeight + visible: canBeClosed + Rectangle { + anchors.centerIn: parent + width: height + height: parent.height + opacity: closeButtonMouseArea.pressed ? 0.5 : closeButtonMouseArea.containsMouse ? 0.3 : 0 + color: closeButtonMouseArea.pressed ? "#aaaaaa" : active ? label.color : "white" + } + Label { + id: closeLabel + anchors.centerIn: parent + color: label.color + text: "×" + font.bold: true + font.pointSize: label.font.pointSize*1.5 + } + + MouseArea { + id: closeButtonMouseArea + anchors.fill: parent + hoverEnabled: true + onClicked: closed() + } + } + Item { + id: spacer + visible: canBeClosed + width: label.Layout.margins + height: 1 + } + } +} diff --git a/master/qml/qml.qrc b/master/qml/qml.qrc new file mode 100644 index 000000000..94f8c1020 --- /dev/null +++ b/master/qml/qml.qrc @@ -0,0 +1,13 @@ + + + MainWindow.qml + TitleBarTab.qml + FeatureButton.qml + ButtonMenu.qml + ComputerGroupSelector.qml + ComputerDelegate.qml + ComputerMonitoring.qml + AppDrawer.qml + TitleBar.qml + + diff --git a/master/resources/add-group.png b/master/resources/add-group.png new file mode 100644 index 000000000..ad1a8d8a7 Binary files /dev/null and b/master/resources/add-group.png differ diff --git a/master/resources/align-grid.png b/master/resources/align-grid.png index e7768a55d..ec8c5648a 100644 Binary files a/master/resources/align-grid.png and b/master/resources/align-grid.png differ diff --git a/master/resources/application-menu.png b/master/resources/application-menu.png new file mode 100644 index 000000000..20068ad9b Binary files /dev/null and b/master/resources/application-menu.png differ diff --git a/master/resources/applications-education.png b/master/resources/applications-education.png deleted file mode 100644 index 706360c3e..000000000 Binary files a/master/resources/applications-education.png and /dev/null differ diff --git a/master/resources/camera-photo.png b/master/resources/camera-photo.png index f8ab91dbb..964a472cf 100644 Binary files a/master/resources/camera-photo.png and b/master/resources/camera-photo.png differ diff --git a/master/resources/computer-slideshow.png b/master/resources/computer-slideshow.png new file mode 100644 index 000000000..04d32f179 Binary files /dev/null and b/master/resources/computer-slideshow.png differ diff --git a/master/resources/computers.png b/master/resources/computers.png new file mode 100644 index 000000000..e11fbd7ce Binary files /dev/null and b/master/resources/computers.png differ diff --git a/master/resources/edit-find.png b/master/resources/edit-find.png new file mode 100644 index 000000000..bb1f522e7 Binary files /dev/null and b/master/resources/edit-find.png differ diff --git a/master/resources/edit-select-all.png b/master/resources/edit-select-all.png new file mode 100644 index 000000000..d6b2f1b80 Binary files /dev/null and b/master/resources/edit-select-all.png differ diff --git a/master/resources/exchange-positions-zorder-dark.png b/master/resources/exchange-positions-zorder-dark.png new file mode 100644 index 000000000..59d1dc0fc Binary files /dev/null and b/master/resources/exchange-positions-zorder-dark.png differ diff --git a/master/resources/homerun-dark.png b/master/resources/homerun-dark.png new file mode 100644 index 000000000..0ba4f08b5 Binary files /dev/null and b/master/resources/homerun-dark.png differ diff --git a/master/resources/homerun.png b/master/resources/homerun.png new file mode 100644 index 000000000..45b77bd40 Binary files /dev/null and b/master/resources/homerun.png differ diff --git a/master/resources/host-access-denied.png b/master/resources/host-access-denied.png new file mode 100644 index 000000000..bcddd3785 Binary files /dev/null and b/master/resources/host-access-denied.png differ diff --git a/master/resources/host-dns-error.png b/master/resources/host-dns-error.png new file mode 100644 index 000000000..28e0a7197 Binary files /dev/null and b/master/resources/host-dns-error.png differ diff --git a/master/resources/host-offline.png b/master/resources/host-offline.png new file mode 100644 index 000000000..11d4e72a7 Binary files /dev/null and b/master/resources/host-offline.png differ diff --git a/master/resources/host-online.png b/master/resources/host-online.png new file mode 100644 index 000000000..fff4f82de Binary files /dev/null and b/master/resources/host-online.png differ diff --git a/master/resources/host-service-error.png b/master/resources/host-service-error.png new file mode 100644 index 000000000..f76310cd8 Binary files /dev/null and b/master/resources/host-service-error.png differ diff --git a/master/resources/master.qrc b/master/resources/master.qrc index 236d681d1..05bd9ab3e 100644 --- a/master/resources/master.qrc +++ b/master/resources/master.qrc @@ -1,16 +1,32 @@ zoom-fit-best.png + zoom-fit-best-dark.png camera-photo.png - preferences-desktop-display.png - preferences-desktop-display-blue.png - preferences-desktop-display-orange.png - preferences-desktop-display-gray.png - preferences-desktop-display-red.png + host-offline.png + host-online.png + host-dns-error.png + host-service-error.png + host-access-denied.png splash.png - applications-education.png + computers.png align-grid.png exchange-positions-zorder.png + exchange-positions-zorder-dark.png powered-on.png + powered-on-dark.png + edit-find.png + add-group.png + remove-group.png + edit-select-all.png + homerun.png + homerun-dark.png + application-menu.png + computer-slideshow.png + spotlight.png + update-realtime-enabled.png + update-realtime-enabled-dark.png + update-realtime-disabled.png + update-realtime-disabled-dark.png diff --git a/master/resources/powered-on-dark.png b/master/resources/powered-on-dark.png new file mode 100644 index 000000000..7cea1b6f7 Binary files /dev/null and b/master/resources/powered-on-dark.png differ diff --git a/master/resources/preferences-desktop-display-blue.png b/master/resources/preferences-desktop-display-blue.png deleted file mode 100644 index 5668baf1a..000000000 Binary files a/master/resources/preferences-desktop-display-blue.png and /dev/null differ diff --git a/master/resources/preferences-desktop-display-gray.png b/master/resources/preferences-desktop-display-gray.png deleted file mode 100644 index ac58363e5..000000000 Binary files a/master/resources/preferences-desktop-display-gray.png and /dev/null differ diff --git a/master/resources/preferences-desktop-display-orange.png b/master/resources/preferences-desktop-display-orange.png deleted file mode 100644 index 2d1f1ea07..000000000 Binary files a/master/resources/preferences-desktop-display-orange.png and /dev/null differ diff --git a/master/resources/preferences-desktop-display-red.png b/master/resources/preferences-desktop-display-red.png deleted file mode 100644 index c4db932c6..000000000 Binary files a/master/resources/preferences-desktop-display-red.png and /dev/null differ diff --git a/master/resources/preferences-desktop-display.png b/master/resources/preferences-desktop-display.png deleted file mode 100644 index af00f3434..000000000 Binary files a/master/resources/preferences-desktop-display.png and /dev/null differ diff --git a/master/resources/remove-group.png b/master/resources/remove-group.png new file mode 100644 index 000000000..453ab822b Binary files /dev/null and b/master/resources/remove-group.png differ diff --git a/master/resources/splash.png b/master/resources/splash.png index 92d0181fc..39938c0b9 100644 Binary files a/master/resources/splash.png and b/master/resources/splash.png differ diff --git a/master/resources/spotlight.png b/master/resources/spotlight.png new file mode 100644 index 000000000..2104c1fe7 Binary files /dev/null and b/master/resources/spotlight.png differ diff --git a/master/resources/update-realtime-disabled-dark.png b/master/resources/update-realtime-disabled-dark.png new file mode 100644 index 000000000..7d6d1d266 Binary files /dev/null and b/master/resources/update-realtime-disabled-dark.png differ diff --git a/master/resources/update-realtime-disabled.png b/master/resources/update-realtime-disabled.png new file mode 100644 index 000000000..c5f02c3f8 Binary files /dev/null and b/master/resources/update-realtime-disabled.png differ diff --git a/master/resources/update-realtime-enabled-dark.png b/master/resources/update-realtime-enabled-dark.png new file mode 100644 index 000000000..eab99b9ca Binary files /dev/null and b/master/resources/update-realtime-enabled-dark.png differ diff --git a/master/resources/update-realtime-enabled.png b/master/resources/update-realtime-enabled.png new file mode 100644 index 000000000..787bb9be2 Binary files /dev/null and b/master/resources/update-realtime-enabled.png differ diff --git a/master/resources/zoom-fit-best-dark.png b/master/resources/zoom-fit-best-dark.png new file mode 100644 index 000000000..31a3feb69 Binary files /dev/null and b/master/resources/zoom-fit-best-dark.png differ diff --git a/master/src/CheckableItemProxyModel.cpp b/master/src/CheckableItemProxyModel.cpp index a58b926c2..86d55be59 100644 --- a/master/src/CheckableItemProxyModel.cpp +++ b/master/src/CheckableItemProxyModel.cpp @@ -1,7 +1,7 @@ /* * CheckableItemProxyModel.cpp - proxy model for overlaying checked property * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,7 +23,6 @@ */ #include "CheckableItemProxyModel.h" -#include "QtCompat.h" #if defined(QT_TESTLIB_LIB) && QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) #include @@ -32,14 +31,10 @@ CheckableItemProxyModel::CheckableItemProxyModel( int uidRole, QObject *parent ) : QIdentityProxyModel(parent), - m_uidRole( uidRole ), - m_exceptionRole( -1 ), - m_exceptionData() + m_uidRole( uidRole ) { connect( this, &QIdentityProxyModel::rowsInserted, this, &CheckableItemProxyModel::updateNewRows ); - connect( this, &QIdentityProxyModel::rowsAboutToBeRemoved, - this, &CheckableItemProxyModel::removeRowStates ); #if defined(QT_TESTLIB_LIB) && QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) new QAbstractItemModelTester( this, QAbstractItemModelTester::FailureReportingMode::Warning, this ); @@ -75,9 +70,9 @@ Qt::ItemFlags CheckableItemProxyModel::flags( const QModelIndex& index ) const QVariant CheckableItemProxyModel::data( const QModelIndex& index, int role ) const { - if( !index.isValid() ) + if( index.isValid() == false ) { - return QVariant(); + return {}; } if( role == Qt::CheckStateRole && index.column() == 0 && @@ -99,12 +94,12 @@ bool CheckableItemProxyModel::setData( const QModelIndex& index, const QVariant& } const auto uuid = indexToUuid( index ); - const auto checkState = checkStateFromVariant( value ); + const auto checkState = value.value(); - if( qAsConst(m_checkStates)[uuid] != checkState ) + if( std::as_const(m_checkStates)[uuid] != checkState ) { m_checkStates[uuid] = checkState; - emit dataChanged( index, index, { Qt::CheckStateRole } ); + Q_EMIT dataChanged( index, index, { Qt::CheckStateRole } ); setChildData( index, checkState ); setParentData( index.parent(), checkState ); @@ -117,24 +112,32 @@ bool CheckableItemProxyModel::setData( const QModelIndex& index, const QVariant& void CheckableItemProxyModel::updateNewRows(const QModelIndex &parent, int first, int last) { - // also set newly inserted items checked if parent is checked - if( parent.isValid() && checkStateFromVariant( data( parent, Qt::CheckStateRole ) ) == Qt::Checked ) + if( parent.isValid() ) { - for( int i = first; i <= last; ++i ) + auto parentState = data( parent, Qt::CheckStateRole ).value(); + if( parentState == Qt::Checked ) { - setData( index( i, 0, parent ), Qt::Checked, Qt::CheckStateRole ); + // also set newly inserted items checked if parent is checked + for( int i = first; i <= last; ++i ) + { + setData( index( i, 0, parent ), Qt::Checked, Qt::CheckStateRole ); + } } - } -} - - + else if( parentState == Qt::Unchecked ) + { + // make sure parent is (partially) checked if one of the newly inserted items was checked previously + for( int i = first; i <= last; ++i ) + { + if( data( index( i, 0, parent ), Qt::CheckStateRole ).value() == Qt::Checked ) + { + parentState = Qt::Checked; + } + } -void CheckableItemProxyModel::removeRowStates(const QModelIndex &parent, int first, int last) -{ - for( int i = first; i <= last; ++i ) - { - m_checkStates.remove( QIdentityProxyModel::data( index( i, 0, parent ), m_uidRole ).toUuid() ); + setParentData( parent, parentState ); + } } + } @@ -145,7 +148,8 @@ QJsonArray CheckableItemProxyModel::saveStates() for( auto it = m_checkStates.constBegin(), end = m_checkStates.constEnd(); it != end; ++it ) { - if( it.value() == Qt::Checked ) + if( it.value() == Qt::Checked && + match( index( 0, 0 ), m_uidRole, it.key(), 1, Qt::MatchExactly | Qt::MatchRecursive ).isEmpty() == false ) { data += it.key().toString(); } @@ -165,13 +169,16 @@ void CheckableItemProxyModel::loadStates( const QJsonArray& data ) for( const auto& item : data ) { const QUuid uid = QUuid( item.toString() ); - const auto indexList = match( index( 0, 0 ), m_uidRole, uid, 1, + const auto indexList = match( index( 0, 0 ), m_uidRole, uid, 1, // clazy:exclude=inefficient-qlist Qt::MatchExactly | Qt::MatchRecursive ); if( indexList.isEmpty() == false && hasChildren( indexList.first() ) == false ) { setData( indexList.first(), Qt::Checked, Qt::CheckStateRole ); } + + // allow items being added dynamically even if we can't propagate the check state at the moment + m_checkStates[uid] = Qt::Checked; } endResetModel(); @@ -204,7 +211,7 @@ bool CheckableItemProxyModel::setChildData( const QModelIndex& index, Qt::CheckS const auto childIndex = this->index( i, 0, index ); const auto childUuid = indexToUuid( childIndex ); - if( qAsConst(m_checkStates)[childUuid] != checkState ) + if( std::as_const(m_checkStates)[childUuid] != checkState ) { m_checkStates[childUuid] = checkState; modified = true; @@ -218,7 +225,7 @@ bool CheckableItemProxyModel::setChildData( const QModelIndex& index, Qt::CheckS if( modified ) { - emit dataChanged( this->index( 0, 0, index ), this->index( childCount-1, 0, index ), { Qt::CheckStateRole } ); + Q_EMIT dataChanged( this->index( 0, 0, index ), this->index( childCount-1, 0, index ), { Qt::CheckStateRole } ); } } @@ -238,7 +245,7 @@ void CheckableItemProxyModel::setParentData( const QModelIndex& index, Qt::Check for( int i = 0; i < childCount; ++i ) { - if( checkStateFromVariant( data( this->index( i, 0, index ), Qt::CheckStateRole ) ) != checkState ) + if( data( this->index( i, 0, index ), Qt::CheckStateRole ).value() != checkState ) { checkState = Qt::PartiallyChecked; break; @@ -247,10 +254,10 @@ void CheckableItemProxyModel::setParentData( const QModelIndex& index, Qt::Check const auto uuid = indexToUuid( index ); - if( qAsConst(m_checkStates)[uuid] != checkState ) + if( std::as_const(m_checkStates)[uuid] != checkState ) { m_checkStates[uuid] = checkState; - emit dataChanged( index, index, { Qt::CheckStateRole } ); + Q_EMIT dataChanged( index, index, { Qt::CheckStateRole } ); setParentData( index.parent(), checkState ); } diff --git a/master/src/CheckableItemProxyModel.h b/master/src/CheckableItemProxyModel.h index be144b26c..998fc6728 100644 --- a/master/src/CheckableItemProxyModel.h +++ b/master/src/CheckableItemProxyModel.h @@ -1,7 +1,7 @@ /* * CheckableItemProxyModel.h - proxy model for overlaying checked property * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -28,8 +28,6 @@ #include #include -#include "QtCompat.h" - class CheckableItemProxyModel : public QIdentityProxyModel { Q_OBJECT @@ -45,7 +43,6 @@ class CheckableItemProxyModel : public QIdentityProxyModel bool setData(const QModelIndex &index, const QVariant &value, int role) override; void updateNewRows(const QModelIndex &parent, int first, int last); - void removeRowStates(const QModelIndex &parent, int first, int last); QJsonArray saveStates(); void loadStates( const QJsonArray& data ); @@ -55,14 +52,9 @@ class CheckableItemProxyModel : public QIdentityProxyModel bool setChildData( const QModelIndex &index, Qt::CheckState checkState ); void setParentData( const QModelIndex &index, Qt::CheckState checkState ); - Qt::CheckState checkStateFromVariant( const QVariant& data ) const - { - return QVariantHelper::value( data ); - } - - int m_uidRole; - int m_exceptionRole; - QVariant m_exceptionData; + int m_uidRole{-1}; + int m_exceptionRole{-1}; + QVariant m_exceptionData{}; QHash m_checkStates; }; diff --git a/master/src/ComputerControlListModel.cpp b/master/src/ComputerControlListModel.cpp index d648670f6..673fbe49b 100644 --- a/master/src/ComputerControlListModel.cpp +++ b/master/src/ComputerControlListModel.cpp @@ -1,7 +1,7 @@ /* * ComputerControlListModel.cpp - data model for computer control objects * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,11 +25,12 @@ #include #include "ComputerControlListModel.h" +#include "ComputerImageProvider.h" #include "ComputerManager.h" #include "FeatureManager.h" +#include "PlatformSessionFunctions.h" #include "VeyonMaster.h" #include "UserConfig.h" -#include "VeyonConfiguration.h" #if defined(QT_TESTLIB_LIB) && QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) #include @@ -37,25 +38,26 @@ ComputerControlListModel::ComputerControlListModel( VeyonMaster* masterCore, QObject* parent ) : - QAbstractListModel( parent ), + ComputerListModel( parent ), m_master( masterCore ), - m_displayRoleContent( static_cast( VeyonCore::config().computerDisplayRoleContent() ) ), - m_sortOrder( static_cast( VeyonCore::config().computerDisplayRoleContent() ) ), - m_iconDefault(), - m_iconConnectionProblem(), - m_iconDemoMode() + m_imageProvider( new ComputerImageProvider( this ) ), + m_iconHostOffline(QStringLiteral(":/master/host-offline.png")), + m_iconHostOnline(QStringLiteral(":/master/host-online.png")), + m_iconHostNameResolutionFailed(QStringLiteral(":/master/host-dns-error.png")), + m_iconHostAccessDenied(QStringLiteral(":/master/host-access-denied.png")), + m_iconHostServiceError(QStringLiteral(":/master/host-service-error.png")) { #if defined(QT_TESTLIB_LIB) && QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) new QAbstractItemModelTester( this, QAbstractItemModelTester::FailureReportingMode::Warning, this ); #endif - loadIcons(); - connect( &m_master->computerManager(), &ComputerManager::computerSelectionReset, this, &ComputerControlListModel::reload ); connect( &m_master->computerManager(), &ComputerManager::computerSelectionChanged, this, &ComputerControlListModel::update ); + updateComputerScreenSize(); + reload(); } @@ -77,7 +79,7 @@ QVariant ComputerControlListModel::data( const QModelIndex& index, int role ) co { if( index.isValid() == false ) { - return QVariant(); + return {}; } if( index.row() >= m_computerControlInterfaces.count() ) @@ -102,38 +104,110 @@ QVariant ComputerControlListModel::data( const QModelIndex& index, int role ) co return computerSortRole( computerControl ); case UidRole: - return computerControl->computer().networkObjectUid(); + return uidRoleData(computerControl); case StateRole: return QVariant::fromValue( computerControl->state() ); + case UserLoginNameRole: + return computerControl->userLoginName(); + + case ImageIdRole: + return QStringLiteral("image://%1/%2/%3").arg( imageProvider()->id(), + VeyonCore::formattedUuid( computerControl->computer().networkObjectUid() ), + QString::number( computerControl->timestamp() ) ); + + case GroupsRole: + return computerControl->groups(); + + case FramebufferRole: + return computerControl->framebuffer(); + + case ControlInterfaceRole: + return QVariant::fromValue( computerControl ); + + default: + break; + } + + return {}; +} + + + +bool ComputerControlListModel::setData( const QModelIndex& index, const QVariant& value, int role ) +{ + if( index.isValid() == false ) + { + return false; + } + + if( index.row() >= m_computerControlInterfaces.count() ) + { + vCritical() << "index out of range!"; + } + + const auto computerControl = std::as_const(m_computerControlInterfaces)[index.row()]; + + switch( role ) + { + case GroupsRole: + computerControl->setGroups( value.toStringList() ); + Q_EMIT dataChanged( index, index, { role } ); + return true; + default: break; } - return QVariant(); + return false; } void ComputerControlListModel::updateComputerScreenSize() { - const auto size = computerScreenSize(); + auto ratio = 16.0 / 9.0; + + switch( aspectRatio() ) + { + case AspectRatio::Auto: ratio = averageAspectRatio(); break; + case AspectRatio::AR16_9: ratio = 16.0 / 9.0; break; + case AspectRatio::AR16_10: ratio = 16.0 / 10.0; break; + case AspectRatio::AR3_2: ratio = 3.0 / 2.0; break; + case AspectRatio::AR4_3: ratio = 4.0 / 3.0; break; + + } + + const QSize newSize{ m_master->userConfig().monitoringScreenSize(), + int(m_master->userConfig().monitoringScreenSize() / ratio) }; for( auto& controlInterface : m_computerControlInterfaces ) { - controlInterface->setScaledScreenSize( size ); + controlInterface->setScaledFramebufferSize( newSize ); + } + + if( m_computerScreenSize != newSize ) + { + m_computerScreenSize = newSize; + + for( int i = 0; i < rowCount(); ++i ) + { + updateScreen( index( i ) ); + } + + Q_EMIT computerScreenSizeChanged(); } } -ComputerControlInterface::Pointer ComputerControlListModel::computerControlInterface( const QModelIndex& index ) const +ComputerControlInterface::Pointer ComputerControlListModel::computerControlInterface( const QModelIndex& index ) const { if( index.isValid() == false || index.row() >= m_computerControlInterfaces.count() ) { vCritical() << "invalid ComputerControlInterface requested!"; - return ComputerControlInterface::Pointer(); + return {}; } return m_computerControlInterfaces[index.row()]; @@ -141,6 +215,56 @@ ComputerControlInterface::Pointer ComputerControlListModel::computerControlInter +ComputerControlInterface::Pointer ComputerControlListModel::computerControlInterface( NetworkObject::Uid uid ) const +{ + for( auto& controlInterface : m_computerControlInterfaces ) + { + if( controlInterface->computer().networkObjectUid() == uid ) + { + return controlInterface; + } + } + return {}; +} + + + +QImage ComputerControlListModel::computerDecorationRole( const ComputerControlInterface::Pointer& controlInterface ) const +{ + switch( controlInterface->state() ) + { + case ComputerControlInterface::State::Connected: + { + const auto image = controlInterface->scaledFramebuffer(); + if( image.isNull() == false ) + { + return image; + } + + return scaleAndAlignIcon(m_iconHostOnline, controlInterface->scaledFramebufferSize()); + } + + case ComputerControlInterface::State::HostNameResolutionFailed: + return scaleAndAlignIcon(m_iconHostNameResolutionFailed, controlInterface->scaledFramebufferSize()); + + case ComputerControlInterface::State::ServerNotRunning: + return scaleAndAlignIcon(m_iconHostServiceError, controlInterface->scaledFramebufferSize()); + + case ComputerControlInterface::State::AuthenticationFailed: + return scaleAndAlignIcon(m_iconHostAccessDenied, controlInterface->scaledFramebufferSize()); + + case ComputerControlInterface::State::AccessControlFailed: + return scaleAndAlignIcon(m_iconHostAccessDenied, controlInterface->scaledFramebufferSize()); + + default: + break; + } + + return scaleAndAlignIcon(m_iconHostOffline, controlInterface->scaledFramebufferSize()); +} + + + void ComputerControlListModel::reload() { beginResetModel(); @@ -150,14 +274,11 @@ void ComputerControlListModel::reload() m_computerControlInterfaces.clear(); m_computerControlInterfaces.reserve( computerList.size() ); - int row = 0; - for( const auto& computer : computerList ) { const auto controlInterface = ComputerControlInterface::Pointer::create( computer ); m_computerControlInterfaces.append( controlInterface ); - startComputerControlInterface( controlInterface, index( row ) ); - ++row; + startComputerControlInterface( controlInterface.data() ); } endResetModel(); @@ -197,7 +318,7 @@ void ComputerControlListModel::update() beginInsertRows( QModelIndex(), row, row ); const auto controlInterface = ComputerControlInterface::Pointer::create( computer ); m_computerControlInterfaces.insert( row, controlInterface ); - startComputerControlInterface( controlInterface, index( row ) ); + startComputerControlInterface( controlInterface.data() ); endInsertRows(); } else if( row >= m_computerControlInterfaces.count() ) @@ -205,41 +326,78 @@ void ComputerControlListModel::update() beginInsertRows( QModelIndex(), row, row ); const auto controlInterface = ComputerControlInterface::Pointer::create( computer ); m_computerControlInterfaces.append( controlInterface ); - startComputerControlInterface( controlInterface, index( row ) ); // clazy:exclude=detaching-member + startComputerControlInterface( controlInterface.data() ); endInsertRows(); } ++row; } + + updateComputerScreenSize(); +} + + + +QModelIndex ComputerControlListModel::interfaceIndex( ComputerControlInterface* controlInterface ) const +{ + return ComputerListModel::index( m_computerControlInterfaces.indexOf( controlInterface->weakPointer() ), 0 ); +} + + + +QVariant ComputerControlListModel::uidRoleData(const ComputerControlInterface::Pointer& controlInterface) const +{ + static const QUuid uidRoleNamespace(QStringLiteral("7480c1c0-2b9f-46f1-92a6-0978bbfcd191")); + + switch (uidRoleContent()) + { + case UidRoleContent::NetworkObjectUid: + return controlInterface->computer().networkObjectUid(); + case UidRoleContent::SessionMetaDataHash: + if (controlInterface->sessionInfo().metaData.isEmpty()) + { + return controlInterface->computer().networkObjectUid(); + } + return QUuid::createUuidV5(uidRoleNamespace, controlInterface->sessionInfo().metaData); + } + + return {}; } void ComputerControlListModel::updateState( const QModelIndex& index ) { - emit dataChanged( index, index, { Qt::DisplayRole, Qt::DecorationRole, Qt::ToolTipRole } ); + Q_EMIT dataChanged( index, index, { Qt::DisplayRole, Qt::DecorationRole, Qt::ToolTipRole, ImageIdRole, FramebufferRole } ); +} + + + +void ComputerControlListModel::updateAccessControlDetails(const QModelIndex& index) +{ + Q_EMIT dataChanged(index, index, { Qt::ToolTipRole }); } void ComputerControlListModel::updateScreen( const QModelIndex& index ) { - emit dataChanged( index, index, { Qt::DecorationRole } ); + Q_EMIT dataChanged( index, index, { Qt::DecorationRole, ImageIdRole, FramebufferRole } ); } void ComputerControlListModel::updateActiveFeatures( const QModelIndex& index ) { - emit dataChanged( index, index, { Qt::ToolTipRole } ); - emit activeFeaturesChanged( index ); + Q_EMIT dataChanged( index, index, { Qt::ToolTipRole } ); + Q_EMIT activeFeaturesChanged( index ); } void ComputerControlListModel::updateUser( const QModelIndex& index ) { - emit dataChanged( index, index, { Qt::DisplayRole, Qt::ToolTipRole } ); + Q_EMIT dataChanged( index, index, { Qt::DisplayRole, Qt::ToolTipRole } ); auto controlInterface = computerControlInterface( index ); if( controlInterface.isNull() == false ) @@ -250,99 +408,98 @@ void ComputerControlListModel::updateUser( const QModelIndex& index ) -void ComputerControlListModel::startComputerControlInterface( const ComputerControlInterface::Pointer& controlInterface, - const QModelIndex& index ) +void ComputerControlListModel::updateSessionInfo(const QModelIndex& index) { - controlInterface->start( computerScreenSize() ); - - connect( controlInterface.data(), &ComputerControlInterface::featureMessageReceived, this, - [=]( const FeatureMessage& featureMessage, ComputerControlInterface::Pointer computerControlInterface ) { - m_master->featureManager().handleFeatureMessage( *m_master, featureMessage, computerControlInterface ); - } ); - - connect( controlInterface.data(), &ComputerControlInterface::screenUpdated, - this, [=] () { updateScreen( index ); } ); - - connect( controlInterface.data(), &ComputerControlInterface::activeFeaturesChanged, - this, [=] () { updateActiveFeatures( index ); } ); + if (uidRoleContent() == UidRoleContent::SessionMetaDataHash) + { + Q_EMIT dataChanged(index, index, {Qt::ToolTipRole, UidRole}); + } + else + { + Q_EMIT dataChanged(index, index, {Qt::ToolTipRole}); - connect( controlInterface.data(), &ComputerControlInterface::stateChanged, - this, [=] () { updateState( index ); } ); + } - connect( controlInterface.data(), &ComputerControlInterface::userChanged, - this, [=]() { updateUser( index ); } ); + auto controlInterface = computerControlInterface( index ); + if (controlInterface.isNull() == false) + { + m_master->computerManager().updateSessionInfo(controlInterface); + } } -void ComputerControlListModel::stopComputerControlInterface( const ComputerControlInterface::Pointer& controlInterface ) +void ComputerControlListModel::startComputerControlInterface( ComputerControlInterface* controlInterface ) { - m_master->stopAllModeFeatures( { controlInterface } ); - - controlInterface->disconnect( &m_master->computerManager() ); + controlInterface->start( computerScreenSize(), ComputerControlInterface::UpdateMode::Monitoring ); - controlInterface->setUserLoginName( {} ); - controlInterface->setUserFullName( {} ); - m_master->computerManager().updateUser( controlInterface ); -} + connect( controlInterface, &ComputerControlInterface::framebufferSizeChanged, + this, &ComputerControlListModel::updateComputerScreenSize ); + connect( controlInterface, &ComputerControlInterface::scaledFramebufferUpdated, + this, [=] () { updateScreen( interfaceIndex( controlInterface ) ); } ); + connect( controlInterface, &ComputerControlInterface::activeFeaturesChanged, + this, [=] () { updateActiveFeatures( interfaceIndex( controlInterface ) ); } ); -QSize ComputerControlListModel::computerScreenSize() const -{ - return { m_master->userConfig().monitoringScreenSize(), - m_master->userConfig().monitoringScreenSize() * 9 / 16 }; -} + connect( controlInterface, &ComputerControlInterface::stateChanged, + this, [=] () { updateState( interfaceIndex( controlInterface ) ); } ); + connect( controlInterface, &ComputerControlInterface::userChanged, + this, [=]() { updateUser( interfaceIndex( controlInterface ) ); } ); + connect(controlInterface, &ComputerControlInterface::sessionInfoChanged, + this, [=]() { updateSessionInfo(interfaceIndex(controlInterface)); }); -void ComputerControlListModel::loadIcons() -{ - m_iconDefault = prepareIcon( QImage( QStringLiteral(":/master/preferences-desktop-display-gray.png") ) ); - m_iconConnectionProblem = prepareIcon( QImage( QStringLiteral(":/master/preferences-desktop-display-red.png") ) ); - m_iconDemoMode = prepareIcon( QImage( QStringLiteral(":/master/preferences-desktop-display-orange.png") ) ); + connect(controlInterface, &ComputerControlInterface::accessControlDetailsChanged, + this, [=] () { updateAccessControlDetails(interfaceIndex(controlInterface)); }); } -QImage ComputerControlListModel::prepareIcon(const QImage &icon) +void ComputerControlListModel::stopComputerControlInterface( const ComputerControlInterface::Pointer& controlInterface ) { - QImage wideIcon( icon.width() * 16 / 9, icon.height(), QImage::Format_ARGB32 ); - wideIcon.fill( Qt::transparent ); - QPainter p( &wideIcon ); - p.drawImage( ( wideIcon.width() - icon.width() ) / 2, 0, icon ); - return wideIcon; + m_master->stopAllFeatures( { controlInterface } ); + + controlInterface->disconnect(this); + controlInterface->disconnect( &m_master->computerManager() ); + + m_master->computerManager().clearOverlayModelData(controlInterface); } -QImage ComputerControlListModel::computerDecorationRole( const ComputerControlInterface::Pointer& controlInterface ) const +double ComputerControlListModel::averageAspectRatio() const { - QImage image; + QSize size{ 16, 9 }; - switch( controlInterface->state() ) + for( const auto& controlInterface : m_computerControlInterfaces ) { - case ComputerControlInterface::State::Connected: - image = controlInterface->scaledScreen(); - if( image.isNull() == false ) + const auto currentSize = controlInterface->screenSize(); + if( currentSize.isValid() ) { - return image; + size += currentSize; } + } - image = m_iconDefault; - break; + return double(size.width()) / double(size.height()); +} - case ComputerControlInterface::State::AuthenticationFailed: - case ComputerControlInterface::State::ServiceUnreachable: - image = m_iconConnectionProblem; - break; - default: - image = m_iconDefault; - break; - } - return image.scaled( controlInterface->scaledScreenSize(), Qt::KeepAspectRatio ); +QImage ComputerControlListModel::scaleAndAlignIcon( const QImage& icon, QSize size ) const +{ + const auto scaledIcon = icon.scaled(size.width(), size.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + + QImage scaledAndAlignedIcon( size, QImage::Format_ARGB32 ); + scaledAndAlignedIcon.fill( Qt::transparent ); + + QPainter painter( &scaledAndAlignedIcon ); + painter.drawImage( ( scaledAndAlignedIcon.width() - scaledIcon.width() ) / 2, + ( scaledAndAlignedIcon.height() - scaledIcon.height() ) / 2, + scaledIcon ); + + return scaledAndAlignedIcon; } @@ -350,26 +507,34 @@ QImage ComputerControlListModel::computerDecorationRole( const ComputerControlIn QString ComputerControlListModel::computerToolTipRole( const ComputerControlInterface::Pointer& controlInterface ) const { const QString state( computerStateDescription( controlInterface ) ); + const QString name(tr("Name: %1").arg(controlInterface->computerName())); const QString location( tr( "Location: %1" ).arg( controlInterface->computer().location() ) ); - const QString host( tr( "Host/IP address: %1" ).arg( controlInterface->computer().hostAddress() ) ); - const QString user( loggedOnUserInformation( controlInterface ) ); - const QString features( tr( "Active features: %1" ).arg( activeFeatures( controlInterface ) ) ); - - if( user.isEmpty() ) + const QString host = + controlInterface->computer().hostAddress().isNull() ? + tr("Hostname: %1").arg(controlInterface->computer().hostName().isEmpty() ? + QStringLiteral("<%1>").arg(tr("unknown")) + : + controlInterface->computer().hostName()) + : + tr("IP address: %1").arg(controlInterface->computer().hostAddress().toString()); + const QString user(userInformation(controlInterface)); + const QString features = activeFeaturesInformation(controlInterface); + + if (controlInterface->state() != ComputerControlInterface::State::Connected) { - return QStringLiteral( "%1
%2
%3
%4" ).arg( state, location, host, features ); + return QStringLiteral("%1
%2
%3
%4").arg(state, name, location, host); } - return QStringLiteral( "%1
%2
%3
%4
%5" ).arg( state, location, host, features, user); + return QStringLiteral("%1
%2
%3
%4
%5
%6").arg(state, name, location, host, features, user); } QString ComputerControlListModel::computerDisplayRole( const ComputerControlInterface::Pointer& controlInterface ) const { - if( m_displayRoleContent != DisplayComputerName && - controlInterface->state() == ComputerControlInterface::State::Connected && - controlInterface->userLoginName().isEmpty() == false ) + if( displayRoleContent() != DisplayRoleContent::ComputerName && + controlInterface->state() == ComputerControlInterface::State::Connected && + controlInterface->userLoginName().isEmpty() == false ) { auto user = controlInterface->userFullName(); if( user.isEmpty() ) @@ -377,44 +542,51 @@ QString ComputerControlListModel::computerDisplayRole( const ComputerControlInte user = controlInterface->userLoginName(); } - if( m_displayRoleContent == DisplayUserName ) + if( displayRoleContent() == DisplayRoleContent::UserName ) { return user; } - else - { - return QStringLiteral("%1 - %2").arg( user, controlInterface->computer().name() ); - } + + return QStringLiteral("%1 - %2").arg(user, controlInterface->computerName()); } - if( m_displayRoleContent != DisplayUserName ) + if( displayRoleContent() != DisplayRoleContent::UserName ) { - return controlInterface->computer().name(); + return controlInterface->computerName(); } - return {}; + return tr("[no user]"); } QString ComputerControlListModel::computerSortRole( const ComputerControlInterface::Pointer& controlInterface ) const { - switch( m_sortOrder ) + switch( sortOrder() ) { - case SortByComputerAndUserName: - return controlInterface->computer().location() + controlInterface->computer().name() + - controlInterface->computer().hostAddress() + controlInterface->userLoginName(); + case SortOrder::ComputerAndUserName: + return controlInterface->computer().location() + controlInterface->computerName() + + controlInterface->computer().hostName() + controlInterface->userLoginName(); - case SortByComputerName: - return controlInterface->computer().location() + controlInterface->computer().name() + - controlInterface->computer().hostAddress(); + case SortOrder::ComputerName: + return controlInterface->computer().location() + controlInterface->computerName() + + controlInterface->computer().hostName(); - case SortByUserName: + case SortOrder::UserName: if( controlInterface->userFullName().isEmpty() == false ) { return controlInterface->userFullName(); } + return controlInterface->userLoginName(); + + case SortOrder::LastPartOfUserName: + const QStringList parts = controlInterface->userFullName().split(QLatin1Char(' '), Qt::SkipEmptyParts); + if( parts.isEmpty() == false ) + { + return parts.constLast(); + } + return controlInterface->userLoginName(); } @@ -428,7 +600,11 @@ QString ComputerControlListModel::computerStateDescription( const ComputerContro switch( controlInterface->state() ) { case ComputerControlInterface::State::Connected: - return tr( "Online and connected" ); + if (controlInterface->hasValidFramebuffer()) + { + return tr("Online and connected"); + } + [[fallthrough]]; case ComputerControlInterface::State::Connecting: return tr( "Establishing connection" ); @@ -436,12 +612,18 @@ QString ComputerControlListModel::computerStateDescription( const ComputerContro case ComputerControlInterface::State::HostOffline: return tr( "Computer offline or switched off" ); - case ComputerControlInterface::State::ServiceUnreachable: - return tr( "Service unreachable or not running" ); + case ComputerControlInterface::State::HostNameResolutionFailed: + return tr("Hostname could not be resolved"); + + case ComputerControlInterface::State::ServerNotRunning: + return tr( "Veyon Server unreachable or not running" ); case ComputerControlInterface::State::AuthenticationFailed: return tr( "Authentication failed or access denied" ); + case ComputerControlInterface::State::AccessControlFailed: + return controlInterface->accessControlDetails(); + default: break; } @@ -451,70 +633,43 @@ QString ComputerControlListModel::computerStateDescription( const ComputerContro -QString ComputerControlListModel::loggedOnUserInformation( const ComputerControlInterface::Pointer& controlInterface ) +QString ComputerControlListModel::userInformation(const ComputerControlInterface::Pointer& controlInterface) { - if( controlInterface->state() == ComputerControlInterface::State::Connected ) + if (controlInterface->userLoginName().isEmpty()) { - if( controlInterface->userLoginName().isEmpty() ) - { - return tr( "No user logged on" ); - } - - auto user = controlInterface->userLoginName(); - if( controlInterface->userFullName().isEmpty() == false ) - { - user = QStringLiteral( "%1 (%2)" ).arg( user, controlInterface->userFullName() ); - } + return tr("No user logged on"); + } - return tr( "Logged on user: %1" ).arg( user ); + auto user = controlInterface->userLoginName(); + if (controlInterface->userFullName().isEmpty() == false) + { + user = QStringLiteral("%1 (%2)").arg(controlInterface->userFullName(), user); } - return {}; + return tr("Logged on user: %1").arg(user); } -QString ComputerControlListModel::activeFeatures( const ComputerControlInterface::Pointer& controlInterface ) const +QString ComputerControlListModel::activeFeaturesInformation(const ComputerControlInterface::Pointer& controlInterface) { QStringList featureNames; + featureNames.reserve(controlInterface->activeFeatures().size()); - for( const auto& feature : m_master->features() ) + for (const auto& feature : VeyonCore::featureManager().features()) { - if( controlInterface->activeFeatures().contains( feature.uid().toString() ) ) + if (feature.testFlag(Feature::Flag::Master) && + feature.displayName().isEmpty() == false && + controlInterface->activeFeatures().contains(feature.uid())) { - featureNames.append( feature.displayName() ); + featureNames.append(feature.displayName()); } } - featureNames.removeAll( {} ); - - return featureNames.join( QStringLiteral(", ") ); -} - - - -Qt::ItemFlags ComputerControlListModel::flags( const QModelIndex& index ) const -{ - auto defaultFlags = QAbstractListModel::flags( index ); - - if( index.isValid() ) + if (featureNames.isEmpty()) { - return Qt::ItemIsDragEnabled | defaultFlags; + return tr("No features active"); } - return Qt::ItemIsDropEnabled | defaultFlags; -} - - - -Qt::DropActions ComputerControlListModel::supportedDragActions() const -{ - return Qt::MoveAction; -} - - - -Qt::DropActions ComputerControlListModel::supportedDropActions() const -{ - return Qt::MoveAction; + return tr("Active features: %1").arg(featureNames.join(QStringLiteral(", "))); } diff --git a/master/src/ComputerControlListModel.h b/master/src/ComputerControlListModel.h index d02abed86..7bbb3acd8 100644 --- a/master/src/ComputerControlListModel.h +++ b/master/src/ComputerControlListModel.h @@ -1,7 +1,7 @@ /* * ComputerControlListModel.h - data model for computer control objects * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,92 +25,92 @@ #pragma once #include +#include #include +#include "ComputerListModel.h" #include "ComputerControlInterface.h" +class ComputerImageProvider; class VeyonMaster; -class ComputerControlListModel : public QAbstractListModel +class ComputerControlListModel : public ComputerListModel { Q_OBJECT public: - enum { - UidRole = Qt::UserRole, - StateRole - }; - - enum DisplayRoleContent { - DisplayUserAndComputerName, - DisplayUserName, - DisplayComputerName, - }; - Q_ENUM(DisplayRoleContent) - - enum SortOrder { - SortByComputerAndUserName, - SortByUserName, - SortByComputerName, - }; - Q_ENUM(SortOrder) - explicit ComputerControlListModel( VeyonMaster* masterCore, QObject* parent = nullptr ); int rowCount( const QModelIndex& parent = QModelIndex() ) const override; QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const override; + bool setData( const QModelIndex& index, const QVariant& value, int role ) override; + + ComputerImageProvider* imageProvider() const + { + return m_imageProvider; + } + void updateComputerScreenSize(); + QSize computerScreenSize() const + { + return m_computerScreenSize; + } + const ComputerControlInterfaceList& computerControlInterfaces() const { return m_computerControlInterfaces; } ComputerControlInterface::Pointer computerControlInterface( const QModelIndex& index ) const; + ComputerControlInterface::Pointer computerControlInterface( NetworkObject::Uid uid ) const; - Qt::ItemFlags flags( const QModelIndex& index ) const override; - - Qt::DropActions supportedDragActions() const override; - Qt::DropActions supportedDropActions() const override; + QImage computerDecorationRole( const ComputerControlInterface::Pointer& controlInterface ) const; void reload(); -signals: +Q_SIGNALS: void activeFeaturesChanged( QModelIndex ); + void computerScreenSizeChanged(); private: void update(); + QModelIndex interfaceIndex( ComputerControlInterface* controlInterface ) const; + QVariant uidRoleData(const ComputerControlInterface::Pointer& controlInterface) const; + void updateState( const QModelIndex& index ); + void updateAccessControlDetails(const QModelIndex& index); void updateScreen( const QModelIndex& index ); void updateActiveFeatures( const QModelIndex& index ); void updateUser( const QModelIndex& index ); + void updateSessionInfo(const QModelIndex& index); - void startComputerControlInterface( const ComputerControlInterface::Pointer& controlInterface, const QModelIndex& index ); + void startComputerControlInterface( ComputerControlInterface* controlInterface ); void stopComputerControlInterface( const ComputerControlInterface::Pointer& controlInterface ); - QSize computerScreenSize() const; + double averageAspectRatio() const; - void loadIcons(); - QImage prepareIcon( const QImage& icon ); - QImage computerDecorationRole( const ComputerControlInterface::Pointer& controlInterface ) const; + QImage scaleAndAlignIcon( const QImage& icon, QSize size ) const; QString computerToolTipRole( const ComputerControlInterface::Pointer& controlInterface ) const; QString computerDisplayRole( const ComputerControlInterface::Pointer& controlInterface ) const; QString computerSortRole( const ComputerControlInterface::Pointer& controlInterface ) const; static QString computerStateDescription( const ComputerControlInterface::Pointer& controlInterface ); - static QString loggedOnUserInformation( const ComputerControlInterface::Pointer& controlInterface ); - QString activeFeatures( const ComputerControlInterface::Pointer& controlInterface ) const; + static QString userInformation(const ComputerControlInterface::Pointer& controlInterface); + static QString activeFeaturesInformation(const ComputerControlInterface::Pointer& controlInterface); VeyonMaster* m_master; - DisplayRoleContent m_displayRoleContent; - SortOrder m_sortOrder; + ComputerImageProvider* m_imageProvider; + QImage m_iconHostOffline; + QImage m_iconHostOnline; + QImage m_iconHostNameResolutionFailed; + QImage m_iconHostAccessDenied; + QImage m_iconHostServiceError; - QImage m_iconDefault; - QImage m_iconConnectionProblem; - QImage m_iconDemoMode; + QSize m_computerScreenSize{}; - ComputerControlInterfaceList m_computerControlInterfaces; + ComputerControlInterfaceList m_computerControlInterfaces{}; }; diff --git a/master/src/ComputerImageProvider.cpp b/master/src/ComputerImageProvider.cpp new file mode 100644 index 000000000..9f22a3138 --- /dev/null +++ b/master/src/ComputerImageProvider.cpp @@ -0,0 +1,48 @@ +/* + * ComputerImageProvider.cpp - data model for computer control objects + * + * Copyright (c) 2017-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "ComputerControlListModel.h" +#include "ComputerImageProvider.h" + +ComputerImageProvider::ComputerImageProvider( ComputerControlListModel* model ) : + QQuickImageProvider( QQmlImageProviderBase::Image ), + m_model( model ) +{ +} + + + +QImage ComputerImageProvider::requestImage( const QString& id, QSize* size, const QSize& requestedSize ) +{ + Q_UNUSED(size) + Q_UNUSED(requestedSize) + + const auto controlInterface = m_model->computerControlInterface( NetworkObject::Uid{id} ); + if( controlInterface ) + { + return m_model->computerDecorationRole( controlInterface ); + } + + return {}; +} diff --git a/master/src/ComputerImageProvider.h b/master/src/ComputerImageProvider.h new file mode 100644 index 000000000..7d44e463e --- /dev/null +++ b/master/src/ComputerImageProvider.h @@ -0,0 +1,47 @@ +/* + * ComputerImageProvider.h - image provider for computers + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +class ComputerControlListModel; + +// clazy:excludeall=copyable-polymorphic +class ComputerImageProvider : public QQuickImageProvider +{ +public: + explicit ComputerImageProvider( ComputerControlListModel* model ); + + QImage requestImage( const QString& id, QSize *size, const QSize &requestedSize ) override; + + QString id() const + { + return QStringLiteral("computers"); + } + +private: + ComputerControlListModel* m_model; + +}; diff --git a/master/src/ComputerItemDelegate.cpp b/master/src/ComputerItemDelegate.cpp new file mode 100644 index 000000000..5b299e7fc --- /dev/null +++ b/master/src/ComputerItemDelegate.cpp @@ -0,0 +1,105 @@ +/* + * ComputerItemDelegate.cpp - implementation of ComputerItemDelegate + + * Copyright (c) 2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include + +#include "ComputerControlListModel.h" +#include "ComputerItemDelegate.h" +#include "FeatureManager.h" + + +ComputerItemDelegate::ComputerItemDelegate(QObject* parent) : + QStyledItemDelegate(parent) +{ + initFeaturePixmaps(); +} + + + +void ComputerItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const +{ + QStyledItemDelegate::paint(painter, option, index); + + if (index.isValid() && index.model()) + { + drawFeatureIcons(painter, option.rect.topLeft(), + index.model()->data(index, ComputerControlListModel::ControlInterfaceRole).value()); + } +} + + + +void ComputerItemDelegate::initFeaturePixmaps() +{ + for (const auto& feature : VeyonCore::featureManager().features() ) + { + if (feature.testFlag(Feature::Flag::Master) && !feature.iconUrl().isEmpty()) + { + m_featurePixmaps[feature.uid()] = QIcon(feature.iconUrl()).pixmap(QSize(OverlayIconSize, OverlayIconSize)); + } + } +} + + + +void ComputerItemDelegate::drawFeatureIcons(QPainter* painter, const QPoint& pos, ComputerControlInterface::Pointer controlInterface) const +{ + if (painter && + controlInterface && + controlInterface->state() == ComputerControlInterface::State::Connected) + { + auto count = 0; + for (const auto& feature : controlInterface->activeFeatures()) + { + if (m_featurePixmaps.contains(feature)) + { + count++; + } + } + + if (count == 0) + { + return; + } + + int x = pos.x() + OverlayIconsPadding; + const int y = pos.y() + OverlayIconsPadding; + + painter->setRenderHint(QPainter::Antialiasing); + painter->setBrush(QColor(255, 255, 255, 192)); + painter->setPen(QColor(25, 140, 179)); + painter->drawRoundedRect(QRect(x, y, count * (OverlayIconSize + OverlayIconSpacing), OverlayIconSize), + OverlayIconsRadius, OverlayIconsRadius); + + for (const auto& feature : controlInterface->activeFeatures()) + { + const auto it = m_featurePixmaps.find(feature); + if (it != m_featurePixmaps.constEnd()) + { + painter->drawPixmap(QPoint(x, y), *it); + x += OverlayIconSize + OverlayIconSpacing; + } + } + } +} diff --git a/master/src/ComputerItemDelegate.h b/master/src/ComputerItemDelegate.h new file mode 100644 index 000000000..96835bd35 --- /dev/null +++ b/master/src/ComputerItemDelegate.h @@ -0,0 +1,51 @@ +/* + * ComputerItemDelegate.h - header file for ComputerItemDelegate + * + * Copyright (c) 2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include +#include + +#include "ComputerControlInterface.h" + +class ComputerItemDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + ComputerItemDelegate(QObject* parent = nullptr); + + virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; + +private: + void initFeaturePixmaps(); + void drawFeatureIcons(QPainter* painter, const QPoint& pos, ComputerControlInterface::Pointer controlInterface) const; + + static constexpr int OverlayIconSize = 32; + static constexpr int OverlayIconSpacing = 4; + static constexpr int OverlayIconsPadding = 8; + static constexpr int OverlayIconsRadius = 6; + + QMap m_featurePixmaps; + +}; diff --git a/master/src/ComputerManager.cpp b/master/src/ComputerManager.cpp index d415fc318..4d9c0465b 100644 --- a/master/src/ComputerManager.cpp +++ b/master/src/ComputerManager.cpp @@ -1,7 +1,7 @@ /* * ComputerManager.cpp - maintains and provides a computer object list * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,6 +27,7 @@ #include #include #include +#include #include "ComputerManager.h" #include "VeyonConfiguration.h" @@ -36,8 +37,8 @@ #include "NetworkObjectFilterProxyModel.h" #include "NetworkObjectOverlayDataModel.h" #include "NetworkObjectTreeModel.h" +#include "PlatformFilesystemFunctions.h" #include "UserConfig.h" -#include "UserSessionControl.h" ComputerManager::ComputerManager( UserConfig& config, QObject* parent ) : @@ -45,11 +46,11 @@ ComputerManager::ComputerManager( UserConfig& config, QObject* parent ) : m_config( config ), m_networkObjectDirectory( VeyonCore::networkObjectDirectoryManager().configuredDirectory() ), m_networkObjectModel( new NetworkObjectTreeModel( m_networkObjectDirectory, this ) ), - m_networkObjectOverlayDataModel( new NetworkObjectOverlayDataModel( tr( "User" ), this ) ), + m_networkObjectOverlayDataModel(new NetworkObjectOverlayDataModel({tr("User"), tr("Logged in since")}, this)), m_computerTreeModel( new CheckableItemProxyModel( NetworkObjectModel::UidRole, this ) ), m_networkObjectFilterProxyModel( new NetworkObjectFilterProxyModel( this ) ), m_localHostNames( QHostInfo::localHostName().toLower() ), - m_localHostAddresses( QHostInfo::fromName( QHostInfo::localHostName() ).addresses() ) + m_localHostAddresses(QHostInfo::fromName(QHostInfo::localHostName()).addresses()) { if( m_networkObjectDirectory == nullptr ) { @@ -118,7 +119,7 @@ bool ComputerManager::saveComputerAndUsersList( const QString& fileName ) // fetch user const auto user = m_networkObjectOverlayDataModel->data( mapToUserNameModelIndex( networkObjectIndex ) ).toString(); // create new line with computer and user - lines += computer.name() + QLatin1Char(';') + computer.hostAddress() + QLatin1Char(';') + user; // clazy:exclude=reserve-candidates + lines += computer.displayName() + QLatin1Char(';') + computer.hostName() + QLatin1Char(';') + user; // clazy:exclude=reserve-candidates } } @@ -126,7 +127,10 @@ bool ComputerManager::saveComputerAndUsersList( const QString& fileName ) lines += QString(); QFile outputFile( fileName ); - if( outputFile.open( QFile::WriteOnly | QFile::Truncate ) == false ) + if( VeyonCore::platform().filesystemFunctions().openFileSafely( + &outputFile, + QFile::WriteOnly | QFile::Truncate, + QFile::ReadOwner | QFile::WriteOwner ) == false ) { return false; } @@ -138,7 +142,7 @@ bool ComputerManager::saveComputerAndUsersList( const QString& fileName ) -void ComputerManager::updateUser( const ComputerControlInterface::Pointer& controlInterface ) +void ComputerManager::updateUser(const ComputerControlInterface::Pointer& controlInterface) const { const auto networkObjectIndex = findNetworkObject( controlInterface->computer().networkObjectUid() ); @@ -149,9 +153,72 @@ void ComputerManager::updateUser( const ComputerControlInterface::Pointer& contr { user = controlInterface->userLoginName(); } - m_networkObjectOverlayDataModel->setData( mapToUserNameModelIndex( networkObjectIndex ), - user, - Qt::DisplayRole ); + m_networkObjectOverlayDataModel->setData(mapToUserNameModelIndex(networkObjectIndex), user); + + if (controlInterface->computerNameSource() == Computer::NameSource::UserFullName || + controlInterface->computerNameSource() == Computer::NameSource::UserLoginName) + { + const auto computerName = controlInterface->computerName(); + if (computerName.isEmpty() == false) + { + m_networkObjectOverlayDataModel->setData(m_networkObjectOverlayDataModel->mapFromSource(networkObjectIndex), + computerName); + } + } + } +} + + + +void ComputerManager::updateSessionInfo(const ComputerControlInterface::Pointer& controlInterface) const +{ + const auto networkObjectIndex = findNetworkObject(controlInterface->computer().networkObjectUid()); + + if (networkObjectIndex.isValid()) + { + const auto uptime24h = controlInterface->sessionInfo().uptime % (60*60*24); + const auto uptimeDays = controlInterface->sessionInfo().uptime / (60*60*24); + const QString uptimeString = (uptimeDays > 0 ? + ((uptimeDays > 1 ? tr("%1 days").arg(uptimeDays) : tr("1 day")) + QStringLiteral(", ")) : + QString()) + + QTime::fromMSecsSinceStartOfDay(uptime24h * 1000).toString(QStringLiteral("hh:mm:ss")); + m_networkObjectOverlayDataModel->setData(mapToSessionUptimeModelIndex(networkObjectIndex), + uptimeString, + Qt::DisplayRole); + + switch (controlInterface->computerNameSource()) + { + case Computer::NameSource::HostAddress: + case Computer::NameSource::SessionClientName: + case Computer::NameSource::SessionClientAddress: + case Computer::NameSource::SessionHostName: + case Computer::NameSource::SessionMetaData: + { + const auto computerName = controlInterface->computerName(); + if (computerName.isEmpty() == false) + { + m_networkObjectOverlayDataModel->setData(m_networkObjectOverlayDataModel->mapFromSource(networkObjectIndex), + computerName); + } + break; + } + default: + break; + } + } +} + + + +void ComputerManager::clearOverlayModelData(const ComputerControlInterface::Pointer& controlInterface) const +{ + const auto networkObjectIndex = findNetworkObject(controlInterface->computer().networkObjectUid()); + + if (networkObjectIndex.isValid()) + { + m_networkObjectOverlayDataModel->setData(mapToUserNameModelIndex(networkObjectIndex), {}); + m_networkObjectOverlayDataModel->setData(mapToSessionUptimeModelIndex(networkObjectIndex), {}); + m_networkObjectOverlayDataModel->setData(m_networkObjectOverlayDataModel->mapFromSource(networkObjectIndex), {}); } } @@ -159,12 +226,12 @@ void ComputerManager::updateUser( const ComputerControlInterface::Pointer& contr void ComputerManager::checkChangedData( const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector& roles ) { - Q_UNUSED(topLeft); - Q_UNUSED(bottomRight); + Q_UNUSED(topLeft) + Q_UNUSED(bottomRight) if( roles.contains( Qt::CheckStateRole ) ) { - emit computerSelectionChanged(); + Q_EMIT computerSelectionChanged(); } } @@ -172,17 +239,21 @@ void ComputerManager::checkChangedData( const QModelIndex& topLeft, const QModel void ComputerManager::initLocations() { - for( const auto& hostName : qAsConst( m_localHostNames ) ) + for( const auto& hostName : std::as_const( m_localHostNames ) ) { vDebug() << "initializing locations for hostname" << hostName; } - for( const auto& address : qAsConst( m_localHostAddresses ) ) + for( const auto& address : std::as_const( m_localHostAddresses ) ) { vDebug() << "initializing locations for host address" << address.toString(); } - m_currentLocations.append( findLocationOfComputer( m_localHostNames, m_localHostAddresses, QModelIndex() ) ); + const auto currentLocation = findLocationOfComputer(m_localHostNames, m_localHostAddresses, {}); + if (currentLocation.isEmpty() == false) + { + m_currentLocations.append(currentLocation); + } vDebug() << "found locations" << m_currentLocations; @@ -214,7 +285,10 @@ void ComputerManager::initNetworkObjectLayer() m_computerTreeModel->setException( NetworkObjectModel::TypeRole, QVariant::fromValue( NetworkObject::Type::Label ) ); m_computerTreeModel->setSourceModel( m_networkObjectFilterProxyModel ); - if( VeyonCore::config().localComputerHidden() ) + const auto hideLocalComputer = VeyonCore::config().hideLocalComputer(); + const auto hideOwnSession = VeyonCore::config().hideOwnSession(); + + if( hideLocalComputer || hideOwnSession ) { QStringList localHostNames( { QStringLiteral("localhost"), @@ -224,14 +298,37 @@ void ComputerManager::initNetworkObjectLayer() localHostNames.append( m_localHostNames ); - for( const auto& address : qAsConst( m_localHostAddresses ) ) + for( const auto& address : std::as_const( m_localHostAddresses ) ) { localHostNames.append( address.toString() ); // clazy:exclude=reserve-candidates } - vDebug() << "excluding local computer via" << localHostNames; + QStringList ownSessionNames; + ownSessionNames.reserve( localHostNames.size() ); + + if( hideOwnSession ) + { + const auto sessionServerPort = QString::number( VeyonCore::config().veyonServerPort() + + VeyonCore::sessionId() ); + + for( const auto& localHostName : std::as_const(localHostNames) ) + { + ownSessionNames.append( QStringLiteral("%1:%2").arg( localHostName, sessionServerPort ) ); + } + + vDebug() << "excluding own session via" << ownSessionNames; + } + + if( hideLocalComputer ) + { + vDebug() << "excluding local computer via" << localHostNames; + } + else + { + localHostNames.clear(); + } - m_networkObjectFilterProxyModel->setComputerExcludeFilter( localHostNames ); + m_networkObjectFilterProxyModel->setComputerExcludeFilter( localHostNames + ownSessionNames ); } m_networkObjectFilterProxyModel->setEmptyGroupsExcluded( VeyonCore::config().hideEmptyLocations() ); @@ -244,7 +341,7 @@ void ComputerManager::initComputerTreeModel() QJsonArray checkedNetworkObjects; if( VeyonCore::config().autoSelectCurrentLocation() ) { - for( const auto& location : qAsConst( m_currentLocations ) ) + for( const auto& location : std::as_const( m_currentLocations ) ) { const auto computersAtLocation = getComputersAtLocation( location ); for( const auto& computer : computersAtLocation ) @@ -285,7 +382,8 @@ void ComputerManager::updateLocationFilterList() -QString ComputerManager::findLocationOfComputer( const QStringList& hostNames, const QList& hostAddresses, const QModelIndex& parent ) +QString ComputerManager::findLocationOfComputer(const QStringList& hostNames, const QList& hostAddresses, + const QModelIndex& parent) const { QAbstractItemModel* model = networkObjectModel(); @@ -293,12 +391,16 @@ QString ComputerManager::findLocationOfComputer( const QStringList& hostNames, c for( int i = 0; i < rows; ++i ) { - QModelIndex entryIndex = model->index( i, 0, parent ); - - auto objectType = static_cast( model->data( entryIndex, NetworkObjectModel::TypeRole ).toInt() ); + const auto entryIndex = model->index(i, 0, parent); + const auto objectType = NetworkObject::Type(model->data(entryIndex, NetworkObjectModel::TypeRole).toInt()); - if( objectType == NetworkObject::Type::Location ) + if( NetworkObject::isContainer(objectType) ) { + if (model->canFetchMore(entryIndex)) + { + model->fetchMore(entryIndex); + } + const auto location = findLocationOfComputer( hostNames, hostAddresses, entryIndex ); if( location.isEmpty() == false ) { @@ -323,35 +425,37 @@ QString ComputerManager::findLocationOfComputer( const QStringList& hostNames, c -ComputerList ComputerManager::getComputersAtLocation( const QString& locationName, const QModelIndex& parent ) +ComputerList ComputerManager::getComputersAtLocation(const QString& locationName, const QModelIndex& parent, bool parentMatches) const { QAbstractItemModel* model = computerTreeModel(); int rows = model->rowCount( parent ); ComputerList computers; + computers.reserve( rows ); for( int i = 0; i < rows; ++i ) { - QModelIndex entryIndex = model->index( i, 0, parent ); - - auto objectType = static_cast( model->data( entryIndex, NetworkObjectModel::TypeRole ).toInt() ); - - switch( objectType ) + const auto entryIndex = model->index(i, 0, parent); + const auto objectType = NetworkObject::Type(model->data(entryIndex, NetworkObjectModel::TypeRole).toInt()); + const auto objectName = model->data(entryIndex, NetworkObjectModel::NameRole).toString(); + if( NetworkObject::isContainer(objectType) ) { - case NetworkObject::Type::Location: - if( model->data( entryIndex, NetworkObjectModel::NameRole ).toString() == locationName ) + const auto currentLocationMatches = objectName == locationName; + if (parentMatches || currentLocationMatches || hasSubLocations(entryIndex)) { - computers += getComputersAtLocation( locationName, entryIndex ); + computers += getComputersAtLocation(locationName, entryIndex, parentMatches || currentLocationMatches); + } + } + else if( objectType == NetworkObject::Type::Host ) + { + if (parentMatches) + { + computers += Computer(model->data(entryIndex, NetworkObjectModel::UidRole).toUuid(), + objectName, + model->data(entryIndex, NetworkObjectModel::HostAddressRole).toString(), + model->data(entryIndex, NetworkObjectModel::MacAddressRole).toString()); } - break; - case NetworkObject::Type::Host: - computers += Computer( model->data( entryIndex, NetworkObjectModel::UidRole ).toUuid(), - model->data( entryIndex, NetworkObjectModel::NameRole ).toString(), - model->data( entryIndex, NetworkObjectModel::HostAddressRole ).toString(), - model->data( entryIndex, NetworkObjectModel::MacAddressRole ).toString() ); - break; - default: break; } } @@ -360,7 +464,28 @@ ComputerList ComputerManager::getComputersAtLocation( const QString& locationNam -ComputerList ComputerManager::selectedComputers( const QModelIndex& parent ) +bool ComputerManager::hasSubLocations(const QModelIndex& index) const +{ + const auto model = computerTreeModel(); + const auto rows = model->rowCount(index); + + for (int i = 0; i < rows; ++i) + { + const auto objectType = NetworkObject::Type(model->data(model->index(i, 0, index), + NetworkObjectModel::TypeRole).toInt()); + + if (objectType == NetworkObject::Type::Location || objectType == NetworkObject::Type::DesktopGroup) + { + return true; + } + } + + return false; +} + + + +ComputerList ComputerManager::selectedComputers(const QModelIndex& parent) const { QAbstractItemModel* model = computerTreeModel(); @@ -372,26 +497,24 @@ ComputerList ComputerManager::selectedComputers( const QModelIndex& parent ) { QModelIndex entryIndex = model->index( i, 0, parent ); - if( QVariantHelper::value( model->data( entryIndex, NetworkObjectModel::CheckStateRole ) ) == Qt::Unchecked ) + if( model->data( entryIndex, NetworkObjectModel::CheckStateRole ).value() == Qt::Unchecked ) { continue; } - auto objectType = static_cast( model->data( entryIndex, NetworkObjectModel::TypeRole ).toInt() ); + const auto objectType = NetworkObject::Type( model->data(entryIndex, NetworkObjectModel::TypeRole).toInt() ); - switch( objectType ) + if( NetworkObject::isContainer(objectType) ) { - case NetworkObject::Type::Location: computers += selectedComputers( entryIndex ); - break; - case NetworkObject::Type::Host: + } + else if( objectType == NetworkObject::Type::Host ) + { computers += Computer( model->data( entryIndex, NetworkObjectModel::UidRole ).toUuid(), model->data( entryIndex, NetworkObjectModel::NameRole ).toString(), model->data( entryIndex, NetworkObjectModel::HostAddressRole ).toString(), model->data( entryIndex, NetworkObjectModel::MacAddressRole ).toString(), model->data( parent, NetworkObjectModel::NameRole ).toString() ); - break; - default: break; } } @@ -400,7 +523,7 @@ ComputerList ComputerManager::selectedComputers( const QModelIndex& parent ) -QModelIndex ComputerManager::findNetworkObject( NetworkObject::Uid networkObjectUid, const QModelIndex& parent ) +QModelIndex ComputerManager::findNetworkObject(NetworkObject::Uid networkObjectUid, const QModelIndex& parent) const { QAbstractItemModel* model = networkObjectModel(); @@ -410,9 +533,9 @@ QModelIndex ComputerManager::findNetworkObject( NetworkObject::Uid networkObject { QModelIndex entryIndex = model->index( i, 0, parent ); - auto objectType = static_cast( model->data( entryIndex, NetworkObjectModel::TypeRole ).toInt() ); + const auto objectType = NetworkObject::Type( model->data(entryIndex, NetworkObjectModel::TypeRole).toInt() ); - if( objectType == NetworkObject::Type::Location ) + if( NetworkObject::isContainer(objectType) ) { QModelIndex index = findNetworkObject( networkObjectUid, entryIndex ); if( index.isValid() ) @@ -434,10 +557,20 @@ QModelIndex ComputerManager::findNetworkObject( NetworkObject::Uid networkObject -QModelIndex ComputerManager::mapToUserNameModelIndex( const QModelIndex& networkObjectIndex ) +QModelIndex ComputerManager::mapToUserNameModelIndex(const QModelIndex& networkObjectIndex) const { // map arbitrary index from m_networkObjectModel to username column in m_networkObjectOverlayDataModel const auto parent = m_networkObjectOverlayDataModel->mapFromSource( networkObjectIndex.parent() ); return m_networkObjectOverlayDataModel->index( networkObjectIndex.row(), OverlayDataUsernameColumn, parent ); } + + + +QModelIndex ComputerManager::mapToSessionUptimeModelIndex(const QModelIndex& networkObjectIndex) const +{ + // map arbitrary index from m_networkObjectModel to username column in m_networkObjectOverlayDataModel + const auto parent = m_networkObjectOverlayDataModel->mapFromSource(networkObjectIndex.parent()); + + return m_networkObjectOverlayDataModel->index(networkObjectIndex.row(), OverlayDataSessionUptimeColumn, parent); +} diff --git a/master/src/ComputerManager.h b/master/src/ComputerManager.h index f803259fa..64964a8fb 100644 --- a/master/src/ComputerManager.h +++ b/master/src/ComputerManager.h @@ -1,7 +1,7 @@ /* * ComputerManager.h - maintains and provides a computer object list * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,6 +26,7 @@ #include "CheckableItemProxyModel.h" #include "ComputerControlInterface.h" +#include "NetworkObjectDirectory.h" class QHostAddress; class NetworkObjectDirectory; @@ -40,26 +41,28 @@ class ComputerManager : public QObject ComputerManager( UserConfig& config, QObject* parent ); ~ComputerManager() override; - QAbstractItemModel* networkObjectModel() + QAbstractItemModel* networkObjectModel() const { return m_networkObjectModel; } - QAbstractItemModel* computerTreeModel() + QAbstractItemModel* computerTreeModel() const { return m_computerTreeModel; } - ComputerList selectedComputers( const QModelIndex& parent ); + ComputerList selectedComputers(const QModelIndex& parent) const; void addLocation( const QString& location ); void removeLocation( const QString& location ); bool saveComputerAndUsersList( const QString& fileName ); - void updateUser( const ComputerControlInterface::Pointer& controlInterface ); + void updateUser(const ComputerControlInterface::Pointer& controlInterface) const; + void updateSessionInfo(const ComputerControlInterface::Pointer& controlInterface) const; + void clearOverlayModelData(const ComputerControlInterface::Pointer& controlInterface) const; -signals: +Q_SIGNALS: void computerSelectionReset(); void computerSelectionChanged(); @@ -71,15 +74,19 @@ class ComputerManager : public QObject void initComputerTreeModel(); void updateLocationFilterList(); - QString findLocationOfComputer( const QStringList& hostNames, const QList& hostAddresses, const QModelIndex& parent ); + QString findLocationOfComputer(const QStringList& hostNames, const QList& hostAddresses, + const QModelIndex& parent) const; - ComputerList getComputersAtLocation( const QString& locationName, const QModelIndex& parent = QModelIndex() ); + ComputerList getComputersAtLocation(const QString& locationName, const QModelIndex& parent = {}, bool parentMatches = false) const; + bool hasSubLocations(const QModelIndex& index) const; - QModelIndex findNetworkObject( NetworkObject::Uid networkObjectUid, const QModelIndex& parent = QModelIndex() ); + QModelIndex findNetworkObject(NetworkObject::Uid networkObjectUid, const QModelIndex& parent = {}) const; - QModelIndex mapToUserNameModelIndex( const QModelIndex& networkObjectIndex ); + QModelIndex mapToUserNameModelIndex(const QModelIndex& networkObjectIndex) const; + QModelIndex mapToSessionUptimeModelIndex(const QModelIndex& networkObjectIndex) const; static constexpr int OverlayDataUsernameColumn = 1; + static constexpr int OverlayDataSessionUptimeColumn = 2; UserConfig& m_config; diff --git a/master/src/ComputerMonitoringItem.cpp b/master/src/ComputerMonitoringItem.cpp new file mode 100644 index 000000000..1c7b782d6 --- /dev/null +++ b/master/src/ComputerMonitoringItem.cpp @@ -0,0 +1,188 @@ +/* + * ComputerMonitoringItem.cpp - provides a view with computer monitor thumbnails + * + * Copyright (c) 2017-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "ComputerControlListModel.h" +#include "ComputerMonitoringItem.h" +#include "ComputerMonitoringModel.h" +#include "VeyonMaster.h" +#include "FeatureManager.h" +#include "VeyonConfiguration.h" + + +ComputerMonitoringItem::ComputerMonitoringItem( QQuickItem* parent ) : + QQuickItem( parent ) +{ +} + + + +ComputerControlInterfaceList ComputerMonitoringItem::selectedComputerControlInterfaces() const +{ + const auto& computerControlListModel = master()->computerControlListModel(); + ComputerControlInterfaceList computerControlInterfaces; + + computerControlInterfaces.reserve( m_selectedObjects.size() ); + + for( const auto& selectedObject : m_selectedObjects ) + { + computerControlInterfaces.append( computerControlListModel.computerControlInterface( selectedObject ) ); + } + + return computerControlInterfaces; +} + + + +void ComputerMonitoringItem::componentComplete() +{ + initializeView( this ); + + if( VeyonCore::config().autoAdjustMonitoringIconSize() ) + { + initiateIconSizeAutoAdjust(); + } + + QQuickItem::componentComplete(); +} + + + +void ComputerMonitoringItem::setUseCustomComputerPositions( bool enabled ) +{ +} + + + +void ComputerMonitoringItem::alignComputers() +{ +} + + + +void ComputerMonitoringItem::runFeature( QString uid ) +{ + ComputerMonitoringView::runFeature( VeyonCore::featureManager().feature( Feature::Uid( uid ) ) ); +} + + + +QObject* ComputerMonitoringItem::model() const +{ + return dataModel(); +} + + + +QColor ComputerMonitoringItem::backgroundColor() const +{ + return m_backgroundColor; +} + + + +QColor ComputerMonitoringItem::textColor() const +{ + return m_textColor; +} + + + +const QSize& ComputerMonitoringItem::iconSize() const +{ + return m_iconSize; +} + + + +void ComputerMonitoringItem::setColors( const QColor& backgroundColor, const QColor& textColor ) +{ + m_backgroundColor = backgroundColor; + m_textColor = textColor; + + Q_EMIT backgroundColorChanged(); + Q_EMIT textColorChanged(); +} + + + +QJsonArray ComputerMonitoringItem::saveComputerPositions() +{ + return {}; +} + + + +bool ComputerMonitoringItem::useCustomComputerPositions() +{ + return false; +} + + + +void ComputerMonitoringItem::loadComputerPositions( const QJsonArray& positions ) +{ +} + + + +void ComputerMonitoringItem::setIconSize( const QSize& size ) +{ + if( size != m_iconSize ) + { + m_iconSize = size; + + Q_EMIT iconSizeChanged(); + } +} + + + +QVariantList ComputerMonitoringItem::selectedObjects() const +{ + QVariantList objects; // clazy:exclude=inefficient-qlist + objects.reserve(m_selectedObjects.size()); + + for( const auto& object : std::as_const(m_selectedObjects) ) + { + objects.append( object ); + } + + return objects; +} + + + +void ComputerMonitoringItem::setSelectedObjects( const QVariantList& objects ) +{ + m_selectedObjects.clear(); + + for( const auto& object : objects ) + { + const auto uuid = object.toUuid(); + if( uuid.isNull() == false ) + { + m_selectedObjects.append( uuid ); + } + } +} diff --git a/master/src/ComputerMonitoringItem.h b/master/src/ComputerMonitoringItem.h new file mode 100644 index 000000000..0f8f41cf8 --- /dev/null +++ b/master/src/ComputerMonitoringItem.h @@ -0,0 +1,91 @@ +/* + * ComputerMonitoringItem.h - provides a view with computer monitor thumbnails + * + * Copyright (c) 2017-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "ComputerMonitoringView.h" +#include "FlexibleListView.h" + +#include + +class FlexibleListView; + +class ComputerMonitoringItem : public QQuickItem, public ComputerMonitoringView +{ + Q_OBJECT + Q_PROPERTY(QObject* model READ model CONSTANT) + Q_PROPERTY(QColor backgroundColor READ backgroundColor NOTIFY backgroundColorChanged) + Q_PROPERTY(QColor textColor READ textColor NOTIFY textColorChanged) + Q_PROPERTY(QSize iconSize READ iconSize NOTIFY iconSizeChanged) + Q_PROPERTY(QString searchFilter READ searchFilter WRITE setSearchFilter) + Q_PROPERTY(QStringList groupFilter READ groupFilter WRITE setGroupFilter) + Q_PROPERTY(QVariantList selectedObjects READ selectedObjects WRITE setSelectedObjects) + Q_PROPERTY(int computerScreenSize READ computerScreenSize WRITE setComputerScreenSize) +public: + enum class ComputerScreenSize { + MinimumComputerScreenSize = MinimumComputerScreenSize, + DefaultComputerScreenSize = DefaultComputerScreenSize, + MaximumComputerScreenSize = MaximumComputerScreenSize, + }; + Q_ENUM(ComputerScreenSize) + + explicit ComputerMonitoringItem( QQuickItem* parent = nullptr ); + ~ComputerMonitoringItem() override = default; + + ComputerControlInterfaceList selectedComputerControlInterfaces() const override; + + void componentComplete() override; + + void setUseCustomComputerPositions( bool enabled ) override; + void alignComputers() override; + + Q_INVOKABLE void runFeature( QString featureUid ); + +private: + QObject* model() const; + QColor backgroundColor() const; + QColor textColor() const; + const QSize& iconSize() const; + + void setColors( const QColor& backgroundColor, const QColor& textColor ) override; + QJsonArray saveComputerPositions() override; + bool useCustomComputerPositions() override; + void loadComputerPositions( const QJsonArray& positions ) override; + void setIconSize( const QSize& size ) override; + + QVariantList selectedObjects() const; + void setSelectedObjects( const QVariantList& objects ); + + QColor m_backgroundColor; + QColor m_textColor; + QSize m_iconSize; + + QList m_selectedObjects; + +Q_SIGNALS: + void backgroundColorChanged(); + void textColorChanged(); + void iconSizeChanged(); + +}; diff --git a/master/src/ComputerMonitoringModel.cpp b/master/src/ComputerMonitoringModel.cpp new file mode 100644 index 000000000..8b2adc576 --- /dev/null +++ b/master/src/ComputerMonitoringModel.cpp @@ -0,0 +1,147 @@ +/* + * ComputerMonitoringModel.cpp - implementation of ComputerMonitoringModel + * + * Copyright (c) 2018-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "ComputerControlListModel.h" +#include "ComputerMonitoringModel.h" + +#if defined(QT_TESTLIB_LIB) && QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) +#include +#endif + + +ComputerMonitoringModel::ComputerMonitoringModel( ComputerControlListModel* sourceModel, QObject* parent ) : + QSortFilterProxyModel( parent ) +{ +#if defined(QT_TESTLIB_LIB) && QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) + new QAbstractItemModelTester( this, QAbstractItemModelTester::FailureReportingMode::Warning, this ); +#endif + + setSourceModel( sourceModel ); + setFilterCaseSensitivity( Qt::CaseInsensitive ); + setSortRole( Qt::InitialSortOrderRole ); + setStateRole( ComputerControlListModel::StateRole ); + setUserLoginNameRole( ComputerControlListModel::UserLoginNameRole ); + setGroupsRole( ComputerControlListModel::GroupsRole ); + sort( 0 ); +} + + + +void ComputerMonitoringModel::setStateRole( int role ) +{ + beginResetModel(); + m_stateRole = role; + endResetModel(); +} + + + +void ComputerMonitoringModel::setUserLoginNameRole( int role ) +{ + beginResetModel(); + m_userLoginNameRole = role; + endResetModel(); +} + + + +void ComputerMonitoringModel::setGroupsRole( int role ) +{ + beginResetModel(); + m_groupsRole = role; + endResetModel(); +} + + + +void ComputerMonitoringModel::setStateFilter( ComputerControlInterface::State state ) +{ + beginResetModel(); + m_stateFilter = state; + endResetModel(); +} + + + +void ComputerMonitoringModel::setFilterNonEmptyUserLoginNames( bool enabled ) +{ + if( enabled != m_filterNonEmptyUserLoginNames ) + { + beginResetModel(); + m_filterNonEmptyUserLoginNames = enabled; + endResetModel(); + } +} + + + +void ComputerMonitoringModel::setGroupsFilter( const QStringList& groups ) +{ + beginResetModel(); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + m_groupsFilter = { groups.begin(), groups.end() }; +#else + m_groupsFilter = groups.toSet(); +#endif + endResetModel(); +} + + + +bool ComputerMonitoringModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const +{ + if( m_stateFilter != ComputerControlInterface::State::None && + stateRole() >= 0 && + sourceModel()->data( sourceModel()->index( sourceRow, 0, sourceParent ), + m_stateRole ).value() != m_stateFilter ) + { + return false; + } + + if( m_filterNonEmptyUserLoginNames && + userLoginNameRole() >= 0 && + sourceModel()->data( sourceModel()->index( sourceRow, 0, sourceParent ), + m_userLoginNameRole ).toString().isEmpty() ) + { + return false; + } + + if( m_groupsRole >= 0 && groupsFilter().isEmpty() == false ) + { + const auto groups = sourceModel()->data( sourceModel()->index( sourceRow, 0, sourceParent ), m_groupsRole ).toStringList(); + +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + const auto groupSet = QSet{ groups.begin(), groups.end() }; +#else + const auto groupSet = groups.toSet(); +#endif + + if( groupSet.intersects( groupsFilter() ) == false ) + { + return false; + } + } + + return QSortFilterProxyModel::filterAcceptsRow( sourceRow, sourceParent ); +} diff --git a/master/src/ComputerMonitoringModel.h b/master/src/ComputerMonitoringModel.h new file mode 100644 index 000000000..f420073a7 --- /dev/null +++ b/master/src/ComputerMonitoringModel.h @@ -0,0 +1,92 @@ +/* + * ComputerSortFilterProxyModel.h - header file for ComputerSortFilterProxyModel + * + * Copyright (c) 2018-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +#include "ComputerControlInterface.h" + +class ComputerControlListModel; + +class ComputerMonitoringModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + explicit ComputerMonitoringModel( ComputerControlListModel* sourceModel, QObject* parent ); + + int stateRole() const + { + return m_stateRole; + } + + void setStateRole( int role ); + + int userLoginNameRole() const + { + return m_userLoginNameRole; + } + + void setUserLoginNameRole( int role ); + + int groupsRole() const + { + return m_groupsRole; + } + + void setGroupsRole( int role ); + + ComputerControlInterface::State stateFilter() const + { + return m_stateFilter; + } + + void setStateFilter( ComputerControlInterface::State state ); + + bool filterNonEmptyUserLoginNames() const + { + return m_filterNonEmptyUserLoginNames; + } + + void setFilterNonEmptyUserLoginNames( bool enabled ); + + const QSet& groupsFilter() const + { + return m_groupsFilter; + } + + void setGroupsFilter( const QStringList& groups ); + +protected: + bool filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const override; + +private: + int m_stateRole{-1}; + int m_userLoginNameRole{-1}; + int m_groupsRole{-1}; + ComputerControlInterface::State m_stateFilter{ComputerControlInterface::State::None}; + bool m_filterNonEmptyUserLoginNames{false}; + QSet m_groupsFilter; + +}; diff --git a/master/src/ComputerMonitoringView.cpp b/master/src/ComputerMonitoringView.cpp new file mode 100644 index 000000000..141bc812f --- /dev/null +++ b/master/src/ComputerMonitoringView.cpp @@ -0,0 +1,253 @@ +/* + * ComputerMonitoringView.cpp - provides a view with computer monitor thumbnails + * + * Copyright (c) 2017-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "ComputerControlListModel.h" +#include "ComputerManager.h" +#include "ComputerMonitoringView.h" +#include "ComputerMonitoringModel.h" +#include "VeyonMaster.h" +#include "FeatureManager.h" +#include "VeyonConfiguration.h" +#include "UserConfig.h" + + +ComputerMonitoringView::ComputerMonitoringView() : + m_master( VeyonCore::instance()->findChild() ) +{ + m_autoAdjustIconSize = VeyonCore::config().autoAdjustMonitoringIconSize() || + master()->userConfig().autoAdjustMonitoringIconSize(); + + m_iconSizeAutoAdjustTimer.setInterval( IconSizeAdjustDelay ); + m_iconSizeAutoAdjustTimer.setSingleShot( true ); +} + + + +void ComputerMonitoringView::initializeView( QObject* self ) +{ + const auto autoAdjust = [this]() { initiateIconSizeAutoAdjust(); }; + + QObject::connect( &m_iconSizeAutoAdjustTimer, &QTimer::timeout, self, [this]() { performIconSizeAutoAdjust(); } ); + QObject::connect( dataModel(), &ComputerMonitoringModel::rowsInserted, self, autoAdjust ); + QObject::connect( dataModel(), &ComputerMonitoringModel::rowsRemoved, self, autoAdjust ); + QObject::connect( &m_master->computerControlListModel(), &ComputerControlListModel::computerScreenSizeChanged, self, + [this]() { setIconSize( m_master->computerControlListModel().computerScreenSize() ); } ); + + setColors( VeyonCore::config().computerMonitoringBackgroundColor(), + VeyonCore::config().computerMonitoringTextColor() ); + + setIconSize( m_master->computerControlListModel().computerScreenSize() ); + + setComputerScreenSize( m_master->userConfig().monitoringScreenSize() ); + + loadComputerPositions( m_master->userConfig().computerPositions() ); + setUseCustomComputerPositions( m_master->userConfig().useCustomComputerPositions() ); +} + + + +void ComputerMonitoringView::saveConfiguration() +{ + m_master->userConfig().setFilterPoweredOnComputers( dataModel()->stateFilter() != ComputerControlInterface::State::None ); + m_master->userConfig().setFilterComputersWithLoggedOnUsers( dataModel()->filterNonEmptyUserLoginNames() ); + m_master->userConfig().setComputerPositions( saveComputerPositions() ); + m_master->userConfig().setUseCustomComputerPositions( useCustomComputerPositions() ); +} + + + +ComputerMonitoringModel* ComputerMonitoringView::dataModel() const +{ + return m_master->computerMonitoringModel(); +} + + + +QString ComputerMonitoringView::searchFilter() const +{ +#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) + return dataModel()->filterRegularExpression().pattern(); +#else + return dataModel()->filterRegExp().pattern(); +#endif +} + + + +void ComputerMonitoringView::setSearchFilter( const QString& searchFilter ) +{ +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1) + dataModel()->setFilterRegularExpression( searchFilter ); +#else + dataModel()->setFilterRegExp( searchFilter ); +#endif +} + + + +void ComputerMonitoringView::setFilterPoweredOnComputers( bool enabled ) +{ + dataModel()->setStateFilter( enabled ? ComputerControlInterface::State::Connected : + ComputerControlInterface::State::None ); +} + + + +void ComputerMonitoringView::setFilterComputersWithLoggedOnUsers( bool enabled ) +{ + dataModel()->setFilterNonEmptyUserLoginNames( enabled ); +} + + + +QStringList ComputerMonitoringView::groupFilter() const +{ +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + const auto groupsFilter = dataModel()->groupsFilter(); + return { groupsFilter.begin(), groupsFilter.end() }; +#else + return dataModel()->groupsFilter().toList(); +#endif +} + + + +void ComputerMonitoringView::setGroupFilter( const QStringList& groups ) +{ + dataModel()->setGroupsFilter( groups ); +} + + + +void ComputerMonitoringView::setComputerScreenSize( int size ) +{ + if( m_computerScreenSize != size ) + { + const auto minSize = MinimumComputerScreenSize; + const auto maxSize = MaximumComputerScreenSize; + size = qBound( minSize, size, maxSize ); + + m_computerScreenSize = size; + + m_master->userConfig().setMonitoringScreenSize( size ); + + m_master->computerControlListModel().updateComputerScreenSize(); + } +} + + + +int ComputerMonitoringView::computerScreenSize() const +{ + return m_computerScreenSize; +} + + + +void ComputerMonitoringView::setAutoAdjustIconSize( bool enabled ) +{ + m_autoAdjustIconSize = enabled; + + if( m_autoAdjustIconSize ) + { + performIconSizeAutoAdjust(); + } +} + + + +bool ComputerMonitoringView::performIconSizeAutoAdjust() +{ + m_iconSizeAutoAdjustTimer.stop(); + + return m_autoAdjustIconSize && dataModel()->rowCount() > 0; +} + + + + +void ComputerMonitoringView::initiateIconSizeAutoAdjust() +{ + m_iconSizeAutoAdjustTimer.start(); +} + + + +void ComputerMonitoringView::runFeature( const Feature& feature ) +{ + auto computerControlInterfaces = selectedComputerControlInterfaces(); + if( computerControlInterfaces.isEmpty() ) + { + computerControlInterfaces = m_master->filteredComputerControlInterfaces(); + } + + const auto alreadyActive = feature.testFlag( Feature::Flag::Mode ) && + isFeatureOrRelatedFeatureActive( computerControlInterfaces, feature.uid() ); + + if( feature.testFlag( Feature::Flag::Mode ) ) + { + for( const auto& currentFeature : m_master->features() ) + { + // stop already active or all other active mode features + if( currentFeature.testFlag( Feature::Flag::Mode ) && ( alreadyActive || currentFeature != feature ) ) + { + VeyonCore::featureManager().stopFeature( *m_master, currentFeature, computerControlInterfaces ); + + const auto subFeatures = m_master->subFeatures( currentFeature.uid() ); + for( const auto& subFeature : subFeatures ) + { + VeyonCore::featureManager().stopFeature( *m_master, subFeature, computerControlInterfaces ); + } + } + } + } + + if( alreadyActive == false ) + { + VeyonCore::featureManager().startFeature( *m_master, feature, computerControlInterfaces ); + } +} + + + +bool ComputerMonitoringView::isFeatureOrRelatedFeatureActive( const ComputerControlInterfaceList& computerControlInterfaces, + Feature::Uid featureUid ) const +{ + const auto& relatedFeatures = VeyonCore::featureManager().relatedFeatures( featureUid ); + + for( const auto& controlInterface : computerControlInterfaces ) + { + if( controlInterface->activeFeatures().contains( featureUid ) || + std::find_if( relatedFeatures.begin(), relatedFeatures.end(), + [&controlInterface](const auto& relatedFeature) { + return controlInterface->activeFeatures().contains( relatedFeature.uid() ); + } ) + != relatedFeatures.end() ) + { + return true; + } + } + + return false; +} diff --git a/master/src/ComputerMonitoringView.h b/master/src/ComputerMonitoringView.h new file mode 100644 index 000000000..e32984410 --- /dev/null +++ b/master/src/ComputerMonitoringView.h @@ -0,0 +1,107 @@ +/* + * ComputerMonitoringView.h - provides a view with computer monitor thumbnails + * + * Copyright (c) 2017-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +#include "ComputerControlInterface.h" + +class ComputerMonitoringModel; +class VeyonMaster; + +// clazy:excludeall=copyable-polymorphic + +class ComputerMonitoringView +{ +public: + static constexpr int MinimumComputerScreenSize = 50; + static constexpr int MaximumComputerScreenSize = 1000; + static constexpr int DefaultComputerScreenSize = 150; + + static constexpr auto IconSizeAdjustStepSize = 10; + static constexpr auto IconSizeAdjustDelay = 250; + + ComputerMonitoringView(); + virtual ~ComputerMonitoringView() = default; + + void initializeView( QObject* self ); + + void saveConfiguration(); + + ComputerMonitoringModel* dataModel() const; + + virtual ComputerControlInterfaceList selectedComputerControlInterfaces() const = 0; + ComputerControlInterfaceList filteredComputerControlInterfaces() const; + + QString searchFilter() const; + void setSearchFilter( const QString& searchFilter ); + + void setFilterPoweredOnComputers( bool enabled ); + void setFilterComputersWithLoggedOnUsers( bool enabled ); + + QStringList groupFilter() const; + void setGroupFilter( const QStringList& groups ); + + void setComputerScreenSize( int size ); + int computerScreenSize() const; + + virtual void alignComputers() = 0; + + bool autoAdjustIconSize() const + { + return m_autoAdjustIconSize; + } + void setAutoAdjustIconSize( bool enabled ); + +protected: + virtual void setColors( const QColor& backgroundColor, const QColor& textColor ) = 0; + virtual QJsonArray saveComputerPositions() = 0; + virtual bool useCustomComputerPositions() = 0; + virtual void loadComputerPositions( const QJsonArray& positions ) = 0; + virtual void setUseCustomComputerPositions( bool enabled ) = 0; + virtual void setIconSize( const QSize& size ) = 0; + + virtual bool performIconSizeAutoAdjust(); + + void initiateIconSizeAutoAdjust(); + + VeyonMaster* master() const + { + return m_master; + } + + void runFeature( const Feature& feature ); + + bool isFeatureOrRelatedFeatureActive( const ComputerControlInterfaceList& computerControlInterfaces, + Feature::Uid featureUid ) const; + +private: + VeyonMaster* m_master{nullptr}; + int m_computerScreenSize{DefaultComputerScreenSize}; + + bool m_autoAdjustIconSize{false}; + QTimer m_iconSizeAutoAdjustTimer{}; + +}; diff --git a/master/src/ComputerMonitoringWidget.cpp b/master/src/ComputerMonitoringWidget.cpp index 0f8b50db5..e114a1b2a 100644 --- a/master/src/ComputerMonitoringWidget.cpp +++ b/master/src/ComputerMonitoringWidget.cpp @@ -1,7 +1,7 @@ /* * ComputerMonitoringWidget.cpp - provides a view with computer monitor thumbnails * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,359 +22,396 @@ * */ +#include #include #include #include -#include #include "ComputerControlListModel.h" -#include "ComputerManager.h" +#include "ComputerItemDelegate.h" +#include "ComputerMonitoringModel.h" #include "ComputerMonitoringWidget.h" -#include "ComputerSortFilterProxyModel.h" #include "VeyonMaster.h" #include "FeatureManager.h" #include "VeyonConfiguration.h" -#include "UserConfig.h" -#include "ui_ComputerMonitoringWidget.h" ComputerMonitoringWidget::ComputerMonitoringWidget( QWidget *parent ) : - QWidget(parent), - ui(new Ui::ComputerMonitoringWidget), - m_master( nullptr ), + FlexibleListView( parent ), m_featureMenu( new QMenu( this ) ) { - ui->setupUi( this ); + const auto computerMonitoringThumbnailSpacing = VeyonCore::config().computerMonitoringThumbnailSpacing(); - ui->listView->setUidRole( ComputerControlListModel::UidRole ); + setContextMenuPolicy( Qt::CustomContextMenu ); + setAcceptDrops( true ); + setDragEnabled( true ); + setDragDropMode( QAbstractItemView::DropOnly ); + setDefaultDropAction( Qt::MoveAction ); + setSelectionMode( QAbstractItemView::ExtendedSelection ); + setFlow( QListView::LeftToRight ); + setWrapping( true ); + setResizeMode( QListView::Adjust ); + setSpacing( computerMonitoringThumbnailSpacing ); + setViewMode( QListView::IconMode ); + setUniformItemSizes( true ); + setSelectionRectVisible( true ); - connect( ui->listView, &QListView::doubleClicked, - this, &ComputerMonitoringWidget::runDoubleClickFeature ); + setItemDelegate(new ComputerItemDelegate(this)); - connect( ui->listView, &QListView::customContextMenuRequested, - this, &ComputerMonitoringWidget::showContextMenu ); + setUidRole( ComputerControlListModel::UidRole ); + + connect( this, &QListView::doubleClicked, this, &ComputerMonitoringWidget::runDoubleClickFeature ); + connect( this, &QListView::customContextMenuRequested, + this, [this]( QPoint pos ) { showContextMenu( mapToGlobal( pos ) ); } ); + + initializeView( this ); + + setModel( dataModel() ); } -ComputerMonitoringWidget::~ComputerMonitoringWidget() +ComputerControlInterfaceList ComputerMonitoringWidget::selectedComputerControlInterfaces() const { - if( m_master ) + ComputerControlInterfaceList computerControlInterfaces; + + const auto selectedIndices = selectionModel()->selectedIndexes(); // clazy:exclude=inefficient-qlist + computerControlInterfaces.reserve( selectedIndices.size() ); + + for( const auto& index : selectedIndices ) { - m_master->userConfig().setFilterPoweredOnComputers( listModel().stateFilter() != ComputerControlInterface::State::None ); - m_master->userConfig().setComputerPositions( ui->listView->savePositions() ); - m_master->userConfig().setUseCustomComputerPositions( ui->listView->flexible() ); + computerControlInterfaces.append( model()->data( index, ComputerControlListModel::ControlInterfaceRole ) + .value() ); } - delete ui; + return computerControlInterfaces; } -void ComputerMonitoringWidget::setVeyonMaster( VeyonMaster& masterCore ) +bool ComputerMonitoringWidget::performIconSizeAutoAdjust() { - if( m_master ) + if( ComputerMonitoringView::performIconSizeAutoAdjust() == false) { - return; + return false; } - m_master = &masterCore; + m_ignoreResizeEvent = true; - auto palette = ui->listView->palette(); - palette.setColor( QPalette::Base, VeyonCore::config().computerMonitoringBackgroundColor() ); - palette.setColor( QPalette::Text, VeyonCore::config().computerMonitoringTextColor() ); - ui->listView->setPalette( palette ); + auto size = iconSize().width(); - // attach proxy model to view - ui->listView->setModel( &listModel() ); + setComputerScreenSize( size ); + QApplication::processEvents(); - // load custom positions - ui->listView->loadPositions( m_master->userConfig().computerPositions() ); - ui->listView->setFlexible( m_master->userConfig().useCustomComputerPositions() ); -} - - - -ComputerControlInterfaceList ComputerMonitoringWidget::selectedComputerControlInterfaces() -{ - const auto& computerControlListModel = m_master->computerControlListModel(); - ComputerControlInterfaceList computerControlInterfaces; - - const auto selectedIndices = ui->listView->selectionModel()->selectedIndexes(); - computerControlInterfaces.reserve( selectedIndices.size() ); + while( verticalScrollBar()->isVisible() == false && + horizontalScrollBar()->isVisible() == false && + size < MaximumComputerScreenSize ) + { + size += IconSizeAdjustStepSize; + setComputerScreenSize( size ); + QApplication::processEvents(); + } - for( const auto& index : selectedIndices ) + while( ( verticalScrollBar()->isVisible() || + horizontalScrollBar()->isVisible() ) && + size > MinimumComputerScreenSize ) { - const auto sourceIndex = listModel().mapToSource( index ); - computerControlInterfaces.append( computerControlListModel.computerControlInterface( sourceIndex ) ); + size -= IconSizeAdjustStepSize; + setComputerScreenSize( size ); + QApplication::processEvents(); } - return computerControlInterfaces; + Q_EMIT computerScreenSizeAdjusted( size ); + + m_ignoreResizeEvent = false; + + return true; } -void ComputerMonitoringWidget::setSearchFilter( const QString& searchFilter ) + +void ComputerMonitoringWidget::setUseCustomComputerPositions( bool enabled ) { - listModel().setFilterRegExp( searchFilter ); + setFlexible( enabled ); } -void ComputerMonitoringWidget::setFilterPoweredOnComputers( bool enabled ) +void ComputerMonitoringWidget::alignComputers() { - listModel().setStateFilter( enabled ? ComputerControlInterface::State::Connected : ComputerControlInterface::State::None ); + alignToGrid(); } -void ComputerMonitoringWidget::setComputerScreenSize( int size ) +void ComputerMonitoringWidget::showContextMenu( QPoint globalPos ) { - if( m_master ) - { - m_master->userConfig().setMonitoringScreenSize( size ); + populateFeatureMenu( selectedComputerControlInterfaces() ); - m_master->computerControlListModel().updateComputerScreenSize(); - - ui->listView->setIconSize( QSize( size, size * 9 / 16 ) ); - } + m_featureMenu->exec( globalPos ); } -void ComputerMonitoringWidget::autoAdjustComputerScreenSize() +void ComputerMonitoringWidget::setIconSize( const QSize& size ) { - int size = ui->listView->iconSize().width(); + QAbstractItemView::setIconSize( size ); +} + + - if( ui->listView->verticalScrollBar()->isVisible() || - ui->listView->horizontalScrollBar()->isVisible() ) +void ComputerMonitoringWidget::setColors( const QColor& backgroundColor, const QColor& textColor ) +{ + auto pal = palette(); + if (VeyonCore::useDarkMode()) { - while( ( ui->listView->verticalScrollBar()->isVisible() || - ui->listView->horizontalScrollBar()->isVisible() ) && - size > MinimumComputerScreenSize ) - { - size -= 10; - setComputerScreenSize( size ); - QApplication::processEvents(); - } + pal.setColor(QPalette::Base, textColor); + pal.setColor(QPalette::Text, backgroundColor); } else { - while( ui->listView->verticalScrollBar()->isVisible() == false && - ui->listView->horizontalScrollBar()->isVisible() == false && - size < MaximumComputerScreenSize ) - { - size += 10; - setComputerScreenSize( size ); - QApplication::processEvents(); - } - - setComputerScreenSize( size-20 ); + pal.setColor(QPalette::Base, backgroundColor); + pal.setColor(QPalette::Text, textColor); } - - emit computerScreenSizeAdjusted( m_master->userConfig().monitoringScreenSize() ); + setPalette( pal ); } -void ComputerMonitoringWidget::setUseCustomComputerPositions( bool enabled ) +QJsonArray ComputerMonitoringWidget::saveComputerPositions() { - ui->listView->setFlexible( enabled ); + return savePositions(); } -void ComputerMonitoringWidget::alignComputers() +bool ComputerMonitoringWidget::useCustomComputerPositions() { - ui->listView->alignToGrid(); + return flexible(); } -void ComputerMonitoringWidget::showContextMenu( QPoint pos ) +void ComputerMonitoringWidget::loadComputerPositions( const QJsonArray& positions ) { - populateFeatureMenu( activeFeatures( selectedComputerControlInterfaces() ) ); - - m_featureMenu->exec( ui->listView->mapToGlobal( pos ) ); + loadPositions( positions ); } -void ComputerMonitoringWidget::runDoubleClickFeature( const QModelIndex& index ) +void ComputerMonitoringWidget::populateFeatureMenu( const ComputerControlInterfaceList& computerControlInterfaces ) { - const Feature& feature = m_master->featureManager().feature( VeyonCore::config().computerDoubleClickFeature() ); + Plugin::Uid previousPluginUid; - if( index.isValid() && feature.isValid() ) - { - ui->listView->selectionModel()->select( index, QItemSelectionModel::SelectCurrent ); - runFeature( feature ); - } -} + m_featureMenu->clear(); + for( const auto& feature : master()->features() ) + { + if( feature.testFlag( Feature::Flag::Meta ) ) + { + continue; + } + Plugin::Uid pluginUid = VeyonCore::featureManager().pluginUid( feature.uid() ); -void ComputerMonitoringWidget::runFeature( const Feature& feature ) -{ - if( m_master == nullptr ) - { - return; - } + if( previousPluginUid.isNull() == false && + pluginUid != previousPluginUid && + feature.testFlag( Feature::Flag::Mode ) == false ) + { + m_featureMenu->addSeparator(); + } - ComputerControlInterfaceList computerControlInterfaces = selectedComputerControlInterfaces(); + previousPluginUid = pluginUid; - // mode feature already active? - if( feature.testFlag( Feature::Mode ) && - activeFeatures( computerControlInterfaces ).contains( feature.uid().toString() ) ) - { - // then stop it - m_master->featureManager().stopFeature( *m_master, feature, computerControlInterfaces ); - } - else - { - // stop all other active mode feature - if( feature.testFlag( Feature::Mode ) ) + if( feature.displayNameActive().isEmpty() == false && + isFeatureOrRelatedFeatureActive( computerControlInterfaces, feature.uid() ) ) + { + addFeatureToMenu( feature, feature.displayNameActive() ); + } + else { - for( const auto& currentFeature : m_master->features() ) + const auto subFeatures = master()->subFeatures( feature.uid() ); + if( subFeatures.isEmpty() ) { - if( currentFeature.testFlag( Feature::Mode ) && currentFeature != feature ) - { - m_master->featureManager().stopFeature( *m_master, currentFeature, computerControlInterfaces ); - } + addFeatureToMenu( feature, feature.displayName() ); + } + else + { + addSubFeaturesToMenu( feature, subFeatures, feature.displayName() ); } } - - m_master->featureManager().startFeature( *m_master, feature, computerControlInterfaces ); } } -ComputerSortFilterProxyModel& ComputerMonitoringWidget::listModel() +void ComputerMonitoringWidget::addFeatureToMenu( const Feature& feature, const QString& label ) { - return m_master->computerSortFilterProxyModel(); + m_featureMenu->addAction( QIcon( feature.iconUrl() ), + label, + m_featureMenu, [=] () { runFeature( feature ); } ); } -void ComputerMonitoringWidget::showEvent( QShowEvent* event ) +void ComputerMonitoringWidget::addSubFeaturesToMenu( const Feature& parentFeature, const FeatureList& subFeatures, const QString& label ) { - if( event->spontaneous() == false && - VeyonCore::config().autoAdjustGridSize() ) + auto menu = m_featureMenu->addMenu( QIcon( parentFeature.iconUrl() ), label ); + + for( const auto& subFeature : subFeatures ) { - QTimer::singleShot( 250, this, &ComputerMonitoringWidget::autoAdjustComputerScreenSize ); + menu->addAction(QIcon(subFeature.iconUrl()), subFeature.displayName(), +#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0) + subFeature.shortcut(), +#endif + this, [=]() { runFeature( subFeature ); } +#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0) + , subFeature.shortcut() +#endif + ); } - - QWidget::showEvent( event ); } -void ComputerMonitoringWidget::wheelEvent( QWheelEvent* event ) +void ComputerMonitoringWidget::runDoubleClickFeature( const QModelIndex& index ) { - if( event->modifiers().testFlag( Qt::ControlModifier ) ) - { - setComputerScreenSize( qBound( MinimumComputerScreenSize, - ui->listView->iconSize().width() + event->angleDelta().y() / 8, - MaximumComputerScreenSize ) ); - - emit computerScreenSizeAdjusted( m_master->userConfig().monitoringScreenSize() ); + const Feature& feature = VeyonCore::featureManager().feature( VeyonCore::config().computerDoubleClickFeature() ); - event->accept(); - } - else + if( index.isValid() && feature.isValid() ) { - QWidget::wheelEvent( event ); + selectionModel()->select( index, QItemSelectionModel::SelectCurrent ); + runFeature( feature ); } } -FeatureUidList ComputerMonitoringWidget::activeFeatures( const ComputerControlInterfaceList& computerControlInterfaces ) +void ComputerMonitoringWidget::resetIgnoreNumberOfMouseEvents( ) { - FeatureUidList featureUidList; + m_ignoreNumberOfMouseEvents = IgnoredNumberOfMouseEventsWhileHold; +} - for( const auto& controlInterface : computerControlInterfaces ) + + +void ComputerMonitoringWidget::runMousePressAndHoldFeature( ) +{ + m_mousePressAndHold.stop(); + const auto selectedInterfaces = selectedComputerControlInterfaces(); + if( !m_ignoreMousePressAndHoldEvent && + selectedInterfaces.count() > 0 && + selectedInterfaces.count() < 2 && + selectedInterfaces.first()->state() == ComputerControlInterface::State::Connected && + selectedInterfaces.first()->hasValidFramebuffer() ) { - featureUidList.append( controlInterface->activeFeatures() ); + m_ignoreMousePressAndHoldEvent = true; + resetIgnoreNumberOfMouseEvents(); + delete m_computerZoomWidget; + m_computerZoomWidget = new ComputerZoomWidget( selectedInterfaces.first() ); + connect( m_computerZoomWidget, &ComputerZoomWidget::keypressInComputerZoomWidget, this, &ComputerMonitoringWidget::resetIgnoreNumberOfMouseEvents ); } +} + - featureUidList.removeDuplicates(); - return featureUidList; +void ComputerMonitoringWidget::stopMousePressAndHoldFeature( ) +{ + disconnect( m_computerZoomWidget, &ComputerZoomWidget::keypressInComputerZoomWidget, this, &ComputerMonitoringWidget::resetIgnoreNumberOfMouseEvents ); + m_ignoreMousePressAndHoldEvent = false; + m_ignoreNumberOfMouseEvents = 0; + m_computerZoomWidget->close(); + delete m_computerZoomWidget; + m_computerZoomWidget = nullptr; } -void ComputerMonitoringWidget::populateFeatureMenu( const FeatureUidList& activeFeatures ) +void ComputerMonitoringWidget::mousePressEvent( QMouseEvent* event ) { - Plugin::Uid previousPluginUid; + if( event->buttons() == Qt::LeftButton && indexAt(event->pos()).isValid() ) + { + if( !m_ignoreMousePressAndHoldEvent ) + { + m_mousePressAndHold.setInterval( 500 ); + m_mousePressAndHold.start(); + connect(&m_mousePressAndHold, &QTimer::timeout, this, &ComputerMonitoringWidget::runMousePressAndHoldFeature ); + } + } + QListView::mousePressEvent( event ); +} + - m_featureMenu->clear(); - for( const auto& feature : m_master->features() ) +void ComputerMonitoringWidget::mouseReleaseEvent( QMouseEvent* event ) +{ + m_mousePressAndHold.stop(); + if ( m_ignoreMousePressAndHoldEvent ) { - Plugin::Uid pluginUid = m_master->featureManager().pluginUid( feature ); + stopMousePressAndHoldFeature(); + } + QListView::mouseReleaseEvent( event ); +} - if( previousPluginUid.isNull() == false && - pluginUid != previousPluginUid && - feature.testFlag( Feature::Mode ) == false ) - { - m_featureMenu->addSeparator(); - } - previousPluginUid = pluginUid; - auto label = feature.displayName(); - if( activeFeatures.contains( feature.uid().toString() ) && - feature.displayNameActive().isEmpty() == false ) +void ComputerMonitoringWidget::mouseMoveEvent( QMouseEvent* event ) +{ + m_mousePressAndHold.stop(); + if ( m_ignoreNumberOfMouseEvents <= 0 ) + { + if ( m_ignoreMousePressAndHoldEvent ) { - label = feature.displayNameActive(); + stopMousePressAndHoldFeature(); } - const auto subFeatures = m_master->subFeatures( feature.uid() ); + QListView::mouseMoveEvent( event ); + } else + { + m_ignoreNumberOfMouseEvents--; + event->accept(); + } +} + - if( subFeatures.isEmpty() ) - { - addFeatureToMenu( feature, label ); - } - else - { - addSubFeaturesToMenu( feature, subFeatures, label ); - } + +void ComputerMonitoringWidget::resizeEvent( QResizeEvent* event ) +{ + FlexibleListView::resizeEvent( event ); + + if( m_ignoreResizeEvent == false ) + { + initiateIconSizeAutoAdjust(); } } -void ComputerMonitoringWidget::addFeatureToMenu( const Feature& feature, const QString& label ) +void ComputerMonitoringWidget::showEvent( QShowEvent* event ) { -#if QT_VERSION < 0x050600 -#warning Building legacy compat code for unsupported version of Qt - auto action = m_featureMenu->addAction( QIcon( feature.iconUrl() ), label ); - connect( action, &QAction::triggered, this, [=] () { runFeature( feature ); } ); -#else - m_featureMenu->addAction( QIcon( feature.iconUrl() ), - label, - this, [=] () { runFeature( feature ); } ); -#endif + if( event->spontaneous() == false ) + { + initiateIconSizeAutoAdjust(); + } + + FlexibleListView::showEvent( event ); } -void ComputerMonitoringWidget::addSubFeaturesToMenu( const Feature& parentFeature, const FeatureList& subFeatures, const QString& label ) +void ComputerMonitoringWidget::wheelEvent( QWheelEvent* event ) { - auto menu = m_featureMenu->addMenu( QIcon( parentFeature.iconUrl() ), label ); + if( m_ignoreWheelEvent == false && + event->modifiers().testFlag( Qt::ControlModifier ) ) + { + setComputerScreenSize( iconSize().width() + event->angleDelta().y() / 8 ); - for( const auto& subFeature : subFeatures ) + Q_EMIT computerScreenSizeAdjusted( computerScreenSize() ); + + event->accept(); + } + else { -#if QT_VERSION < 0x050600 -#warning Building legacy compat code for unsupported version of Qt - auto action = menu->addAction( QIcon( subFeature.iconUrl() ), subFeature.displayName() ); - action->setShortcut( subFeature.shortcut() ); - connect( action, &QAction::triggered, this, [=] () { runFeature( subFeature ); } ); -#else - menu->addAction( QIcon( subFeature.iconUrl() ), subFeature.displayName(), this, - [=]() { runFeature( subFeature ); }, subFeature.shortcut() ); -#endif + QListView::wheelEvent( event ); } } diff --git a/master/src/ComputerMonitoringWidget.h b/master/src/ComputerMonitoringWidget.h index c62962b31..b9cca4c24 100644 --- a/master/src/ComputerMonitoringWidget.h +++ b/master/src/ComputerMonitoringWidget.h @@ -1,7 +1,7 @@ /* * ComputerMonitoringWidget.h - provides a view with computer monitor thumbnails * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,66 +24,74 @@ #pragma once -#include "ComputerControlInterface.h" +#include "ComputerMonitoringView.h" +#include "FlexibleListView.h" +#include "ComputerZoomWidget.h" #include -class QMenu; +class FlexibleListView; -namespace Ui { -class ComputerMonitoringWidget; -} - -class ComputerSortFilterProxyModel; -class VeyonMaster; - -class ComputerMonitoringWidget : public QWidget +class ComputerMonitoringWidget : public FlexibleListView, public ComputerMonitoringView { Q_OBJECT public: - enum { - MinimumComputerScreenSize = 50, - MaximumComputerScreenSize = 1000, - DefaultComputerScreenSize = 150 - }; - explicit ComputerMonitoringWidget( QWidget *parent = nullptr ); - ~ComputerMonitoringWidget() override; + ~ComputerMonitoringWidget() override = default; + + ComputerControlInterfaceList selectedComputerControlInterfaces() const override; - void setVeyonMaster( VeyonMaster& masterCore ); + void setUseCustomComputerPositions( bool enabled ) override; + void alignComputers() override; - ComputerControlInterfaceList selectedComputerControlInterfaces(); + void showContextMenu( QPoint globalPos ); - void setSearchFilter( const QString& searchFilter ); - void setFilterPoweredOnComputers( bool enabled ); - void setComputerScreenSize( int size ); - void autoAdjustComputerScreenSize(); - void setUseCustomComputerPositions( bool enabled ); - void alignComputers(); + void setIconSize( const QSize& size ) override; - void showContextMenu( QPoint pos ); + void setIgnoreWheelEvent( bool enabled ) + { + m_ignoreWheelEvent = enabled; + } + + void resetIgnoreNumberOfMouseEvents( ); + + QTimer m_mousePressAndHold; private: + void setColors( const QColor& backgroundColor, const QColor& textColor ) override; + QJsonArray saveComputerPositions() override; + bool useCustomComputerPositions() override; + void loadComputerPositions( const QJsonArray& positions ) override; + + bool performIconSizeAutoAdjust() override; + + void populateFeatureMenu( const ComputerControlInterfaceList& computerControlInterfaces ); + void addFeatureToMenu( const Feature& feature, const QString& label ); + void addSubFeaturesToMenu( const Feature& parentFeature, const FeatureList& subFeatures, const QString& label ); + void runDoubleClickFeature( const QModelIndex& index ); - void runFeature( const Feature& feature ); + void runMousePressAndHoldFeature( ); + void stopMousePressAndHoldFeature( ); - ComputerSortFilterProxyModel& listModel(); + void mousePressEvent( QMouseEvent* event ) override; + void mouseReleaseEvent( QMouseEvent* event ) override; + void mouseMoveEvent( QMouseEvent* event ) override; + void resizeEvent( QResizeEvent* event ) override; void showEvent( QShowEvent* event ) override; void wheelEvent( QWheelEvent* event ) override; - FeatureUidList activeFeatures( const ComputerControlInterfaceList& computerControlInterfaces ); - - void populateFeatureMenu( const FeatureUidList& activeFeatures ); - void addFeatureToMenu( const Feature& feature, const QString& label ); - void addSubFeaturesToMenu( const Feature& parentFeature, const FeatureList& subFeatures, const QString& label ); + QMenu* m_featureMenu{}; + bool m_ignoreMousePressAndHoldEvent{false}; + bool m_ignoreWheelEvent{false}; + bool m_ignoreResizeEvent{false}; + int m_ignoreNumberOfMouseEvents = 0; - Ui::ComputerMonitoringWidget *ui; + static constexpr auto IgnoredNumberOfMouseEventsWhileHold = 3; - VeyonMaster* m_master; - QMenu* m_featureMenu; + ComputerZoomWidget* m_computerZoomWidget{nullptr}; -signals: +Q_SIGNALS: void computerScreenSizeAdjusted( int size ); }; diff --git a/master/src/ComputerMonitoringWidget.ui b/master/src/ComputerMonitoringWidget.ui deleted file mode 100644 index 77cc42711..000000000 --- a/master/src/ComputerMonitoringWidget.ui +++ /dev/null @@ -1,83 +0,0 @@ - - - ComputerMonitoringWidget - - - - 0 - 0 - 1155 - 670 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Qt::CustomContextMenu - - - true - - - true - - - QAbstractItemView::DropOnly - - - Qt::MoveAction - - - QAbstractItemView::ExtendedSelection - - - QListView::LeftToRight - - - true - - - QListView::Adjust - - - 16 - - - QListView::IconMode - - - true - - - true - - - - - - - - FlexibleListView - QListView -
FlexibleListView.h
-
-
- - -
diff --git a/master/src/RecursiveFilterProxyModel.cpp b/master/src/ComputerSelectModel.cpp similarity index 57% rename from master/src/RecursiveFilterProxyModel.cpp rename to master/src/ComputerSelectModel.cpp index d3eddbfe7..1f5263e00 100644 --- a/master/src/RecursiveFilterProxyModel.cpp +++ b/master/src/ComputerSelectModel.cpp @@ -1,7 +1,7 @@ /* - * RecursiveFilterProxyModel.cpp - proxy model for recursive filtering + * ComputerSelectModel.cpp - data model for computer selection * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,16 +22,34 @@ * */ -#include "RecursiveFilterProxyModel.h" +#include "ComputerSelectModel.h" +#include "VeyonCore.h" #if defined(QT_TESTLIB_LIB) && QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) #include #endif -RecursiveFilterProxyModel::RecursiveFilterProxyModel( QObject* parent ) : - KRecursiveFilterProxyModel( parent ) +ComputerSelectModel::ComputerSelectModel( QAbstractItemModel* sourceModel, QObject* parent ) : + QSortFilterProxyModel(parent) { #if defined(QT_TESTLIB_LIB) && QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) new QAbstractItemModelTester( this, QAbstractItemModelTester::FailureReportingMode::Warning, this ); #endif + + setSourceModel( sourceModel ); + setFilterCaseSensitivity( Qt::CaseInsensitive ); + setFilterKeyColumn( -1 ); // filter all columns instead of first one only + sort( 0 ); +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) + setRecursiveFilteringEnabled(true); +#else + vWarning() << "Built with Qt < 5.10 – filtering computers/users will not work properly"; +#endif +} + + + +QVariant ComputerSelectModel::value( const QModelIndex& index, const QString& role ) const +{ + return data( index, roleNames().key( role.toUtf8() ) ); } diff --git a/master/src/ComputerSelectModel.h b/master/src/ComputerSelectModel.h new file mode 100644 index 000000000..7a7614c0d --- /dev/null +++ b/master/src/ComputerSelectModel.h @@ -0,0 +1,37 @@ +/* + * ComputerSelectListModel.h - data model for computer selection + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +class ComputerSelectModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + explicit ComputerSelectModel( QAbstractItemModel* sourceModel, QObject* parent = nullptr ); + + Q_INVOKABLE QVariant value( const QModelIndex& index, const QString& role ) const; + +}; diff --git a/master/src/ComputerSelectPanel.cpp b/master/src/ComputerSelectPanel.cpp index 7f8caa5d1..d94f727aa 100644 --- a/master/src/ComputerSelectPanel.cpp +++ b/master/src/ComputerSelectPanel.cpp @@ -1,7 +1,7 @@ /* * ComputerSelectPanel.cpp - provides a view for a network object tree * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,33 +26,29 @@ #include #include +#include "ComputerSelectModel.h" #include "ComputerSelectPanel.h" #include "ComputerManager.h" #include "NetworkObjectModel.h" -#include "RecursiveFilterProxyModel.h" #include "LocationDialog.h" #include "VeyonConfiguration.h" #include "ui_ComputerSelectPanel.h" -ComputerSelectPanel::ComputerSelectPanel( ComputerManager& computerManager, QWidget *parent ) : +ComputerSelectPanel::ComputerSelectPanel( ComputerManager& computerManager, ComputerSelectModel* model, QWidget* parent ) : QWidget(parent), ui(new Ui::ComputerSelectPanel), m_computerManager( computerManager ), - m_filterProxyModel( new RecursiveFilterProxyModel( this ) ) + m_model( model ) { - m_filterProxyModel->setSourceModel( computerManager.computerTreeModel() ); - m_filterProxyModel->setFilterCaseSensitivity( Qt::CaseInsensitive ); - m_filterProxyModel->setFilterKeyColumn( -1 ); // filter all columns instead of first one only - ui->setupUi(this); // capture keyboard events for tree view ui->treeView->installEventFilter( this ); // set computer tree model as data model - ui->treeView->setModel( m_filterProxyModel ); + ui->treeView->setModel( m_model ); // set default sort order ui->treeView->sortByColumn( 0, Qt::AscendingOrder ); @@ -60,10 +56,17 @@ ComputerSelectPanel::ComputerSelectPanel( ComputerManager& computerManager, QWid ui->addLocationButton->setVisible( VeyonCore::config().showCurrentLocationOnly() && VeyonCore::config().allowAddingHiddenLocations() ); - ui->filterLineEdit->setHidden( VeyonCore::config().computerFilterHidden() ); + ui->filterLineEdit->setHidden( VeyonCore::config().hideComputerFilter() ); connect( ui->filterLineEdit, &QLineEdit::textChanged, this, &ComputerSelectPanel::updateFilter ); + + if (VeyonCore::config().expandLocations()) + { + connect(m_model, &QAbstractItemModel::modelReset, + this, &ComputerSelectPanel::fetchAndExpandAll); + fetchAndExpandAll(); + } } @@ -108,7 +111,7 @@ void ComputerSelectPanel::removeLocation() const auto index = ui->treeView->selectionModel()->currentIndex(); if( index.isValid() && - QVariantHelper::value( model->data( index, NetworkObjectModel::TypeRole ) ) == NetworkObject::Type::Location ) + model->data( index, NetworkObjectModel::TypeRole ).value() == NetworkObject::Type::Location ) { m_computerManager.removeLocation( model->data( index, NetworkObjectModel::NameRole ).toString() ); } @@ -140,7 +143,7 @@ void ComputerSelectPanel::updateFilter() if( filter.isEmpty() ) { - m_filterProxyModel->setFilterWildcard( filter ); + m_model->setFilterWildcard( filter ); for( int i = 0; i < model->rowCount(); ++i ) { @@ -168,7 +171,31 @@ void ComputerSelectPanel::updateFilter() m_previousFilter = filter; - m_filterProxyModel->setFilterWildcard( filter ); + m_model->setFilterWildcard( filter ); ui->treeView->expandAll(); } } + + + +void ComputerSelectPanel::fetchAndExpandAll() +{ + fetchAll(m_model->index(0, 0)); + QTimer::singleShot(0, this, [this]{ui->treeView->expandAll();}); +} + + + +void ComputerSelectPanel::fetchAll(const QModelIndex& index) +{ + if (m_model->canFetchMore(index)) + { + m_model->fetchMore(index); + } + + const auto rowCount = m_model->rowCount(index); + for (int i = 0; i < rowCount; ++i) + { + fetchAll(m_model->index(i, 0, index)); + } +} diff --git a/master/src/ComputerSelectPanel.h b/master/src/ComputerSelectPanel.h index 94a45a8fa..473e8e73f 100644 --- a/master/src/ComputerSelectPanel.h +++ b/master/src/ComputerSelectPanel.h @@ -1,7 +1,7 @@ /* * ComputerSelectPanel.h - provides a view for a network object tree * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -32,27 +32,30 @@ class ComputerSelectPanel; } class ComputerManager; -class RecursiveFilterProxyModel; +class ComputerSelectModel; class ComputerSelectPanel : public QWidget { Q_OBJECT public: - explicit ComputerSelectPanel( ComputerManager& computerManager, QWidget *parent = nullptr ); + explicit ComputerSelectPanel( ComputerManager& computerManager, ComputerSelectModel* model, QWidget* parent = nullptr ); ~ComputerSelectPanel() override; bool eventFilter(QObject *watched, QEvent *event) override; -private slots: +private Q_SLOTS: void addLocation(); void removeLocation(); void saveList(); void updateFilter(); private: + void fetchAndExpandAll(); + void fetchAll(const QModelIndex& index); + Ui::ComputerSelectPanel *ui; ComputerManager& m_computerManager; - RecursiveFilterProxyModel* m_filterProxyModel; + ComputerSelectModel* m_model; QString m_previousFilter; QModelIndexList m_expandedGroups; diff --git a/master/src/ComputerSelectPanel.ui b/master/src/ComputerSelectPanel.ui index 9e779ece9..036b23e56 100644 --- a/master/src/ComputerSelectPanel.ui +++ b/master/src/ComputerSelectPanel.ui @@ -2,24 +2,18 @@ ComputerSelectPanel - - Computer management - - + - - - 0 - 0 - - QAbstractScrollArea::AdjustToContents QAbstractItemView::NoEditTriggers + + true + true @@ -30,14 +24,14 @@ 180 - false + true - Computer search + Search computers diff --git a/master/src/ComputerSortFilterProxyModel.cpp b/master/src/ComputerSortFilterProxyModel.cpp deleted file mode 100644 index 039f3cd58..000000000 --- a/master/src/ComputerSortFilterProxyModel.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * ComputerSortFilterProxyModel.cpp - implementation of ComputerSortFilterProxyModel - * - * Copyright (c) 2018-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#include "ComputerSortFilterProxyModel.h" - -#if defined(QT_TESTLIB_LIB) && QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) -#include -#endif - - -ComputerSortFilterProxyModel::ComputerSortFilterProxyModel( QObject* parent ) : - QSortFilterProxyModel( parent ), - m_stateRole( -1 ), - m_stateFilter( ComputerControlInterface::State::None ) -{ -#if defined(QT_TESTLIB_LIB) && QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) - new QAbstractItemModelTester( this, QAbstractItemModelTester::FailureReportingMode::Warning, this ); -#endif - - setFilterCaseSensitivity( Qt::CaseInsensitive ); -} - - - -void ComputerSortFilterProxyModel::setStateRole( int role ) -{ - beginResetModel(); - m_stateRole = role; - endResetModel(); -} - - - -void ComputerSortFilterProxyModel::setStateFilter( ComputerControlInterface::State state ) -{ - beginResetModel(); - m_stateFilter = state; - endResetModel(); -} - - - -bool ComputerSortFilterProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const -{ - if( m_stateFilter != ComputerControlInterface::State::None && - m_stateRole >= 0 && - QVariantHelper::value( - sourceModel()->data( sourceModel()->index( sourceRow, 0, sourceParent ), m_stateRole ) ) != m_stateFilter ) - { - return false; - } - - return QSortFilterProxyModel::filterAcceptsRow( sourceRow, sourceParent ); -} diff --git a/master/src/ComputerZoomWidget.cpp b/master/src/ComputerZoomWidget.cpp new file mode 100644 index 000000000..84fbf05c1 --- /dev/null +++ b/master/src/ComputerZoomWidget.cpp @@ -0,0 +1,179 @@ +/* + * ComputerZoomWidget.cpp - fullscreen preview widget + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include + +#include "ComputerZoomWidget.h" +#include "VeyonConfiguration.h" +#include "VeyonMasterInterface.h" +#include "PlatformCoreFunctions.h" +#include "VncViewWidget.h" + + +ComputerZoomWidget::ComputerZoomWidget( const ComputerControlInterface::Pointer& computerControlInterface ) : + QWidget(), + m_vncView( new VncViewWidget( computerControlInterface, {}, this ) ) +{ + QApplication::setOverrideCursor(Qt::BlankCursor); + + const auto openOnMasterScreen = VeyonCore::config().showFeatureWindowsOnSameScreen(); + const auto master = VeyonCore::instance()->findChild(); + const auto masterWindow = master->mainWindow(); + if( master && openOnMasterScreen ) + { + move( masterWindow->x(), masterWindow->y() ); + } else { + move( 0, 0 ); + } + + updateComputerZoomWidgetTitle(); + connect( m_vncView->computerControlInterface().data(), &ComputerControlInterface::userChanged, + this, &ComputerZoomWidget::updateComputerZoomWidgetTitle ); + + setWindowIcon( QPixmap( QStringLiteral(":/remoteaccess/kmag.png") ) ); + setAttribute( Qt::WA_DeleteOnClose, true ); + + m_vncView->move( 0, 0 ); + m_vncView->installEventFilter( this ); + connect( m_vncView, &VncViewWidget::sizeHintChanged, this, &ComputerZoomWidget::updateSize ); + + setWindowState(Qt::WindowMaximized); + VeyonCore::platform().coreFunctions().raiseWindow( this, false ); + + show(); +} + + + +ComputerZoomWidget::~ComputerZoomWidget() +{ + delete m_vncView; +} + + + +bool ComputerZoomWidget::eventFilter( QObject* object, QEvent* event ) +{ + if( event->type() == QEvent::KeyPress ) + { + Q_EMIT keypressInComputerZoomWidget( ); + + const auto screens = m_vncView->computerControlInterface()->screens(); + const auto key = static_cast( event )->key(); + if ( screens.size() > 1 && ( key == Qt::Key_Tab || key == Qt::Key_Backtab ) ) + { + if( key == Qt::Key_Tab ) + { + if ( m_currentScreen < screens.size() - 1 ) + { + m_currentScreen++; + } else + { + m_currentScreen = -1; + } + } + + if( key == Qt::Key_Backtab ) + { + if ( m_currentScreen == -1 ) + { + m_currentScreen = screens.size()-1; + } else if ( m_currentScreen > 0 ) + { + m_currentScreen--; + } else + { + m_currentScreen = -1; + } + } + + showNormal(); + if ( m_currentScreen == -1) + { + m_vncView->setViewport( {} ); + } + else + { + m_vncView->setViewport(screens[m_currentScreen].geometry); + } + setWindowState(Qt::WindowMaximized); + return true; + } + + return false; + } + + return QObject::eventFilter(object, event); +} + + + +void ComputerZoomWidget::updateComputerZoomWidgetTitle() +{ + const auto username = m_vncView->computerControlInterface()->userFullName().isEmpty() ? + m_vncView->computerControlInterface()->userLoginName() : + m_vncView->computerControlInterface()->userFullName(); + + if (username.isEmpty()) + { + setWindowTitle( QStringLiteral( "%1 - %2" ).arg( m_vncView->computerControlInterface()->computerName(), + VeyonCore::applicationName() ) ); + } + else + { + setWindowTitle( QStringLiteral( "%1 - %2 - %3" ).arg( username, + m_vncView->computerControlInterface()->computerName(), + VeyonCore::applicationName() ) ); + } +} + + + +void ComputerZoomWidget::resizeEvent( QResizeEvent* event ) +{ + m_vncView->resize( size() ); + + QWidget::resizeEvent( event ); +} + + + +void ComputerZoomWidget::updateSize() +{ + if( !( windowState() & Qt::WindowFullScreen ) && + m_vncView->sizeHint().isEmpty() == false ) + { + resize( m_vncView->sizeHint() ); + } +} + + + +void ComputerZoomWidget::closeEvent( QCloseEvent* event ) +{ + m_vncView->setViewport({}); + QApplication::restoreOverrideCursor(); +} diff --git a/master/src/ComputerZoomWidget.h b/master/src/ComputerZoomWidget.h new file mode 100644 index 000000000..80698932c --- /dev/null +++ b/master/src/ComputerZoomWidget.h @@ -0,0 +1,58 @@ +/* + * ComputerZoomWidget.h - fullscreen preview widget + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "ComputerControlInterface.h" + +#include + +class VncViewWidget; + +// clazy:excludeall=ctor-missing-parent-argument +class ComputerZoomWidget : public QWidget +{ + Q_OBJECT +public: + ComputerZoomWidget( const ComputerControlInterface::Pointer& computerControlInterface ); + ~ComputerZoomWidget() override; + +protected: + bool eventFilter( QObject* object, QEvent* event ) override; + + void resizeEvent( QResizeEvent* event ) override; + void closeEvent( QCloseEvent* event ) override; + +private: + void updateSize(); + void updateComputerZoomWidgetTitle(); + + int m_currentScreen{-1}; + + VncViewWidget* m_vncView; + +Q_SIGNALS: + void keypressInComputerZoomWidget( ); + +} ; diff --git a/master/src/DocumentationFigureCreator.cpp b/master/src/DocumentationFigureCreator.cpp index ab16d4626..32d578475 100644 --- a/master/src/DocumentationFigureCreator.cpp +++ b/master/src/DocumentationFigureCreator.cpp @@ -1,7 +1,7 @@ /* * DocumentationFigureCreator.cpp - helper for creating documentation figures * - * Copyright (c) 2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -37,37 +37,27 @@ #include #include +#include "AuthenticationPluginInterface.h" #include "ComputerMonitoringWidget.h" #include "DocumentationFigureCreator.h" #include "FeatureManager.h" #include "LocationDialog.h" #include "MainToolBar.h" #include "MainWindow.h" -#include "PasswordDialog.h" #include "Plugin.h" #include "PluginManager.h" #include "Screenshot.h" #include "ScreenshotManagementPanel.h" #include "ToolButton.h" #include "VeyonConfiguration.h" -#include "VncView.h" +#include "VncViewWidget.h" #ifdef VEYON_DEBUG -DocumentationFigureCreator::DocumentationFigureCreator() : - QObject(), - m_master( nullptr ), - m_eventLoop( this ) -{ - m_master = new VeyonMaster; -} - - - void DocumentationFigureCreator::run() { - auto mainWindow = m_master->mainWindow(); + auto mainWindow = m_master.mainWindow(); mainWindow->move( 0, 0 ); mainWindow->resize( 3000, 1000 ); @@ -77,14 +67,16 @@ void DocumentationFigureCreator::run() createFeatureFigures(); createContextMenuFigure(); + createDemoMenuFigure(); createLogonDialogFigure(); createLocationDialogFigure(); createScreenshotManagementPanelFigure(); + createUserLoginDialogFigure(); createTextMessageDialogFigure(); createOpenWebsiteDialogFigure(); createWebsiteMenuFigure(); - createRunProgramDialogFigure(); - createProgramMenuFigure(); + createStartAppDialogFigure(); + createAppMenuFigure(); createRemoteAccessHostDialogFigure(); createRemoteAccessWindowFigure(); createPowerDownOptionsFigure(); @@ -102,18 +94,18 @@ void DocumentationFigureCreator::createFeatureFigures() int x = -1; int w = 0; - auto toolbar = m_master->mainWindow()->findChild(); + auto toolbar = m_master.mainWindow()->findChild(); const QStringList separatedPluginFeatures( { QStringLiteral("a54ee018-42bf-4569-90c7-0d8470125ccf"), QStringLiteral("80580500-2e59-4297-9e35-e53959b028cd") } ); - const auto& features = m_master->features(); + const auto& features = m_master.features(); for( const auto& feature : features ) { auto btn = toolbar->findChild( feature.name() ); - const auto pluginUid = m_master->featureManager().pluginUid( feature ); + const auto pluginUid = VeyonCore::featureManager().pluginUid( feature.uid() ); if( previousPluginUid.isNull() ) { @@ -127,7 +119,7 @@ void DocumentationFigureCreator::createFeatureFigures() if( pluginUid != previousPluginUid || separatedFeature ) { auto fileName = VeyonCore::pluginManager().pluginName( previousPluginUid ); - if( separatedFeature ) + if( separatedFeature && previousFeature ) { fileName = previousFeature->name(); } @@ -161,7 +153,7 @@ void DocumentationFigureCreator::createFeatureFigures() void DocumentationFigureCreator::createContextMenuFigure() { - auto view = m_master->mainWindow()->findChild(); + auto view = m_master.mainWindow()->findChild(); auto menu = view->findChild(); connect( menu, &QMenu::aboutToShow, this, [menu]() { @@ -176,15 +168,20 @@ void DocumentationFigureCreator::createContextMenuFigure() void DocumentationFigureCreator::createLogonDialogFigure() { - PasswordDialog dialog( m_master->mainWindow() ); - dialog.show(); - dialog.findChild( QStringLiteral("password") )->setText( QStringLiteral( "TeacherPassword") ); - dialog.findChild( QStringLiteral("password") )->cursorForward( false ); - dialog.findChild( QStringLiteral("username") )->setText( tr( "Teacher") ); + auto authLogonPlugin = VeyonCore::pluginManager().find( + []( const PluginInterface* plugin ) { return plugin->name() == QStringLiteral("AuthLogon"); } ); - grabDialog( &dialog, {}, QStringLiteral("LogonDialog.png") ); - - dialog.exec(); + if( authLogonPlugin ) + { + scheduleUiOperation( []() { + auto dialog = dynamic_cast( QApplication::activeWindow() ); + dialog->findChild( QStringLiteral("password") )->setText( QStringLiteral( "TeacherPassword") ); + dialog->findChild( QStringLiteral("password") )->cursorForward( false ); + dialog->findChild( QStringLiteral("username") )->setText( tr( "Teacher") ); + grabDialog( dialog, {}, QStringLiteral("LogonDialog.png") ); + } ); + authLogonPlugin->initializeCredentials(); + } } @@ -200,7 +197,7 @@ void DocumentationFigureCreator::createLocationDialogFigure() } QStringListModel locationsModel( locations, this ); - LocationDialog dialog( &locationsModel, m_master->mainWindow() ); + LocationDialog dialog( &locationsModel, m_master.mainWindow() ); grabDialog( &dialog, QSize( 300, 200 ), QStringLiteral("LocationDialog.png") ); @@ -211,7 +208,7 @@ void DocumentationFigureCreator::createLocationDialogFigure() void DocumentationFigureCreator::createScreenshotManagementPanelFigure() { - auto window = m_master->mainWindow(); + auto window = m_master.mainWindow(); auto panel = window->findChild(); auto panelButton = window->findChild( QStringLiteral("screenshotManagementPanelButton") ); auto list = panel->findChild(); @@ -271,29 +268,16 @@ void DocumentationFigureCreator::createScreenshotManagementPanelFigure() -void DocumentationFigureCreator::createPowerDownOptionsFigure() +void DocumentationFigureCreator::createDemoMenuFigure() { - auto toolbar = m_master->mainWindow()->findChild(); - auto powerDownButton = toolbar->findChild( QStringLiteral("PowerDown") ); - - scheduleUiOperation( [this, powerDownButton]() { - scheduleUiOperation( [this, powerDownButton]() { - auto menu = powerDownButton->menu(); - - grabWindow( m_master->mainWindow(), powerDownButton->mapTo( m_master->mainWindow(), QPoint( 0, 0 ) ), - QSize( qMax( powerDownButton->width(), menu->width() ), - powerDownButton->height() + menu->height() ), - QStringLiteral("PowerDownOptions.png") ); - menu->close(); - } ); - auto menu = powerDownButton->menu(); - menu->close(); + grabMenu( m_master.mainWindow(), QStringLiteral("Demo"), QStringLiteral("DemoMenu.png") ); +} - powerDownButton->click(); - } ); - powerDownButton->showMenu(); +void DocumentationFigureCreator::createPowerDownOptionsFigure() +{ + grabMenu( m_master.mainWindow(), QStringLiteral("PowerDown"), QStringLiteral("PowerDownOptions.png") ); } @@ -308,7 +292,24 @@ void DocumentationFigureCreator::createPowerDownTimeInputDialogFigure() grabDialog( dialog, {}, QStringLiteral("PowerDownTimeInputDialog.png") ); }); - m_master->runFeature( m_master->featureManager().feature( Feature::Uid( "352de795-7fc4-4850-bc57-525bcb7033f5" ) ) ); + m_master.runFeature( VeyonCore::featureManager().feature( Feature::Uid( "352de795-7fc4-4850-bc57-525bcb7033f5" ) ) ); +} + + + +void DocumentationFigureCreator::createUserLoginDialogFigure() +{ + scheduleUiOperation( []() { + auto dialog = qobject_cast( QApplication::activeWindow() ); + + dialog->findChild( QStringLiteral("password") )->setText( QStringLiteral( "TeacherPassword") ); + dialog->findChild( QStringLiteral("password") )->cursorForward( false ); + dialog->findChild( QStringLiteral("username") )->setText( tr( "generic-student-user") ); + + grabDialog( dialog, {}, QStringLiteral("UserLoginDialog.png") ); + }); + + m_master.runFeature( VeyonCore::featureManager().feature( Feature::Uid( "7310707d-3918-460d-a949-65bd152cb958" ) ) ); } @@ -323,7 +324,7 @@ void DocumentationFigureCreator::createTextMessageDialogFigure() grabDialog( dialog, {}, QStringLiteral("TextMessageDialog.png") ); }); - m_master->runFeature( m_master->featureManager().feature( Feature::Uid( "e75ae9c8-ac17-4d00-8f0d-019348346208" ) ) ); + m_master.runFeature( VeyonCore::featureManager().feature( Feature::Uid( "e75ae9c8-ac17-4d00-8f0d-019348346208" ) ) ); } @@ -338,83 +339,55 @@ void DocumentationFigureCreator::createOpenWebsiteDialogFigure() grabDialog( dialog, {}, QStringLiteral("OpenWebsiteDialog.png") ); }); - m_master->runFeature( m_master->featureManager().feature( Feature::Uid( "8a11a75d-b3db-48b6-b9cb-f8422ddd5b0c" ) ) ); + m_master.runFeature( VeyonCore::featureManager().feature( Feature::Uid( "8a11a75d-b3db-48b6-b9cb-f8422ddd5b0c" ) ) ); } void DocumentationFigureCreator::createWebsiteMenuFigure() { - auto toolbar = m_master->mainWindow()->findChild(); - auto openWebsiteButton = toolbar->findChild( QStringLiteral("OpenWebsite") ); - - auto menu = new QMenu; - menu->addAction( QStringLiteral("Intranet") ); - menu->addAction( QStringLiteral("Wikipedia") ); - menu->addAction( QIcon( QStringLiteral(":/core/document-edit.png") ), tr("Custom website") ); + const auto openWebsiteButton = m_master.mainWindow()->findChild( QStringLiteral("OpenWebsite") ); - scheduleUiOperation( [this, openWebsiteButton, menu]() { - scheduleUiOperation( [this, openWebsiteButton, menu]() { + QMenu menu; + menu.addAction( QStringLiteral("Intranet") ); + menu.addAction( QStringLiteral("Wikipedia") ); + menu.addAction( QIcon( QStringLiteral(":/core/document-edit.png") ), tr("Custom website") ); - grabWindow( m_master->mainWindow(), openWebsiteButton->mapTo( m_master->mainWindow(), QPoint( 0, 0 ) ), - QSize( qMax( openWebsiteButton->width(), menu->width() ), - openWebsiteButton->height() + menu->height() ), - QStringLiteral("OpenWebsiteMenu.png") ); - menu->close(); - } ); + openWebsiteButton->setMenu( &menu ); - menu->close(); - openWebsiteButton->showMenu(); - } ); - - openWebsiteButton->setMenu( menu ); - openWebsiteButton->showMenu(); + grabMenu( m_master.mainWindow(), openWebsiteButton->objectName(), QStringLiteral("OpenWebsiteMenu.png") ); } -void DocumentationFigureCreator::createRunProgramDialogFigure() +void DocumentationFigureCreator::createStartAppDialogFigure() { scheduleUiOperation( []() { auto dialog = qobject_cast( QApplication::activeWindow() ); dialog->findChild()->setText( QStringLiteral("notepad") ); dialog->setFocus(); - grabDialog( dialog, {}, QStringLiteral("RunProgramDialog.png") ); + grabDialog( dialog, {}, QStringLiteral("StartAppDialog.png") ); }); - m_master->runFeature( m_master->featureManager().feature( Feature::Uid( "da9ca56a-b2ad-4fff-8f8a-929b2927b442" ) ) ); + m_master.runFeature( VeyonCore::featureManager().feature( Feature::Uid( "da9ca56a-b2ad-4fff-8f8a-929b2927b442" ) ) ); } -void DocumentationFigureCreator::createProgramMenuFigure() +void DocumentationFigureCreator::createAppMenuFigure() { - auto toolbar = m_master->mainWindow()->findChild(); - auto runProgramButton = toolbar->findChild( QStringLiteral("RunProgram") ); - - auto menu = new QMenu; - menu->addAction( tr("Open file manager") ); - menu->addAction( tr("Start learning tool") ); - menu->addAction( tr("Play tutorial video") ); - menu->addAction( QIcon( QStringLiteral(":/core/document-edit.png") ), tr("Custom program") ); - - scheduleUiOperation( [this, runProgramButton, menu]() { - scheduleUiOperation( [this, runProgramButton, menu]() { - - grabWindow( m_master->mainWindow(), runProgramButton->mapTo( m_master->mainWindow(), QPoint( 0, 0 ) ), - QSize( qMax( runProgramButton->width(), menu->width() ), - runProgramButton->height() + menu->height() ), - QStringLiteral("RunProgramMenu.png") ); - menu->close(); - } ); + const auto startAppButton = m_master.mainWindow()->findChild( QStringLiteral("StartApp") ); - menu->close(); - runProgramButton->showMenu(); - } ); + QMenu menu; + menu.addAction( tr("Open file manager") ); + menu.addAction( tr("Start learning tool") ); + menu.addAction( tr("Play tutorial video") ); + menu.addAction( QIcon( QStringLiteral(":/core/document-edit.png") ), tr("Custom application") ); + + startAppButton->setMenu( &menu ); - runProgramButton->setMenu( menu ); - runProgramButton->showMenu(); + grabMenu( m_master.mainWindow(), startAppButton->objectName(), QStringLiteral("StartAppMenu.png") ); } @@ -428,7 +401,7 @@ void DocumentationFigureCreator::createRemoteAccessHostDialogFigure() grabDialog( dialog, {}, QStringLiteral("RemoteAccessHostDialog.png") ); } ); - m_master->runFeature( m_master->featureManager().feature( Feature::Uid( "a18e545b-1321-4d4e-ac34-adc421c6e9c8" ) ) ); + m_master.runFeature( VeyonCore::featureManager().feature( Feature::Uid( "a18e545b-1321-4d4e-ac34-adc421c6e9c8" ) ) ); } @@ -446,10 +419,11 @@ void DocumentationFigureCreator::createRemoteAccessWindowFigure() scheduleUiOperation( [this]() { auto window = QApplication::activeWindow(); - auto vncView = window->findChild(); + auto vncView = window->findChild(); Q_ASSERT(vncView != nullptr); - for( auto timeline : window->findChildren() ) + auto timeline = window->findChild(); + if( timeline ) { timeline->stop(); timeline->setCurrentTime( 0 ); @@ -465,25 +439,15 @@ void DocumentationFigureCreator::createRemoteAccessWindowFigure() auto shortcuts = window->findChild( QStringLiteral("shortcuts") ); Q_ASSERT(shortcuts != nullptr); - scheduleUiOperation( [this, window, shortcuts]() { - auto menu = shortcuts->menu(); - - grabWindow( window, shortcuts->mapTo( window, QPoint( 0, 0 ) ), - QSize( qMax( shortcuts->width(), menu->width() ), - shortcuts->height() + menu->height() ), - QStringLiteral("RemoteAccessShortcutsMenu.png") ); - menu->close(); - window->close(); - m_eventLoop.quit(); - } ); - - shortcuts->showMenu(); + grabMenu( window, QStringLiteral("shortcuts"), QStringLiteral("RemoteAccessShortcutsMenu.png") ); + window->close(); + m_eventLoop.quit(); } ); } ); } ); } ); - m_master->runFeature( m_master->featureManager().feature( Feature::Uid( "ca00ad68-1709-4abe-85e2-48dff6ccf8a2" ) ) ); + m_master.runFeature( VeyonCore::featureManager().feature( Feature::Uid( "ca00ad68-1709-4abe-85e2-48dff6ccf8a2" ) ) ); m_eventLoop.exec(); } @@ -495,7 +459,7 @@ void DocumentationFigureCreator::createFileTransferDialogFigure() auto dialog = qobject_cast( QApplication::activeWindow() ); dialog->setDirectory( QDir::current() ); - dialog->findChildren().first()->setText( QStringLiteral("\"%1.pdf\" \"%2.pdf\"").arg( tr("Handout"), tr("Texts to read") ) ); + dialog->findChildren().constFirst()->setText( QStringLiteral("\"%1.pdf\" \"%2.pdf\"").arg( tr("Handout"), tr("Texts to read") ) ); dialog->setResult( QDialog::Accepted ); dialog->setVisible( false ); @@ -505,37 +469,68 @@ void DocumentationFigureCreator::createFileTransferDialogFigure() dialog->setFocus(); dialog->move( 0, 0 ); - grabWindow( dialog, QStringLiteral("FileTransferDialogStart.png") ); + scheduleUiOperation( [dialog, this]() { + + grabWindow( dialog, QStringLiteral("FileTransferDialogStart.png") ); - dialog->findChild()->button( QDialogButtonBox::Ok )->click(); + dialog->findChild()->button( QDialogButtonBox::Ok )->click(); - scheduleUiOperation( [dialog]() { - grabDialog( dialog, {}, QStringLiteral("FileTransferDialogFinished.png") ); - }); + scheduleUiOperation( [dialog]() { + grabDialog( dialog, {}, QStringLiteral("FileTransferDialogFinished.png") ); + }); + } ); } ); } ); - m_master->runFeature( m_master->featureManager().feature( Feature::Uid( "4a70bd5a-fab2-4a4b-a92a-a1e81d2b75ed" ) ) ); + m_master.runFeature( VeyonCore::featureManager().feature( Feature::Uid( "4a70bd5a-fab2-4a4b-a92a-a1e81d2b75ed" ) ) ); } void DocumentationFigureCreator::hideComputers() { - auto view = m_master->mainWindow()->findChild(); + auto view = m_master.mainWindow()->findChild(); view->setSearchFilter( QStringLiteral("XXXXXX") ); } -void DocumentationFigureCreator::scheduleUiOperation( const std::function& operation ) +void DocumentationFigureCreator::scheduleUiOperation( const std::function& operation, + QObject* context ) +{ + QTimer::singleShot( DialogDelay, context, operation ); +} + + + +void DocumentationFigureCreator::grabMenu( QWidget* window, const QString& buttonName, const QString& fileName ) { - QTimer::singleShot( DialogDelay, this, operation ); + const auto button = window->findChild( buttonName ); + + scheduleUiOperation( [window, button, &fileName]() { + scheduleUiOperation( [window, button, &fileName]() { + auto menu = button->menu(); + + grabWindow( window, button->mapTo( window, QPoint( 0, 0 ) ), + QSize( qMax( button->width(), menu->width() ), + button->height() + menu->height() ), + fileName ); + menu->close(); + }, window ); + auto menu = button->menu(); + menu->close(); + + button->setDown(true); + button->showMenu(); + }, window ); + + button->setDown(true); + button->showMenu(); } -void DocumentationFigureCreator::grabWidget(QWidget* widget, const QPoint& pos, const QSize& size, const QString& fileName) +void DocumentationFigureCreator::grabWidget(QWidget* widget, QPoint pos, QSize size, const QString& fileName) { QPixmap pixmap( size ); widget->render( &pixmap, QPoint(), QRegion( QRect( pos, size ) ) ); @@ -544,7 +539,7 @@ void DocumentationFigureCreator::grabWidget(QWidget* widget, const QPoint& pos, -void DocumentationFigureCreator::grabDialog(QDialog* dialog, const QSize& size, const QString& fileName) +void DocumentationFigureCreator::grabDialog(QDialog* dialog, QSize size, const QString& fileName) { dialog->show(); dialog->setFocus(); @@ -575,7 +570,7 @@ void DocumentationFigureCreator::grabWindow(QWidget* widget, const QString& file -void DocumentationFigureCreator::grabWindow(QWidget* widget, const QPoint& pos, const QSize& size, const QString& fileName) +void DocumentationFigureCreator::grabWindow(QWidget* widget, QPoint pos, QSize size, const QString& fileName) { QGuiApplication::sync(); diff --git a/master/src/DocumentationFigureCreator.h b/master/src/DocumentationFigureCreator.h index 9b6dfcd0c..10cff68d1 100644 --- a/master/src/DocumentationFigureCreator.h +++ b/master/src/DocumentationFigureCreator.h @@ -1,7 +1,7 @@ /* * DocumentationFigureCreator.h - helper for creating documentation figures * - * Copyright (c) 2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,11 +31,12 @@ #ifdef VEYON_DEBUG +// clazy:excludeall=ctor-missing-parent-argument class DocumentationFigureCreator : public QObject { Q_OBJECT public: - DocumentationFigureCreator(); + DocumentationFigureCreator() = default; void run(); @@ -47,28 +48,36 @@ class DocumentationFigureCreator : public QObject void createLogonDialogFigure(); void createLocationDialogFigure(); void createScreenshotManagementPanelFigure(); + void createDemoMenuFigure(); void createPowerDownOptionsFigure(); void createPowerDownTimeInputDialogFigure(); + void createUserLoginDialogFigure(); void createTextMessageDialogFigure(); void createOpenWebsiteDialogFigure(); void createWebsiteMenuFigure(); - void createRunProgramDialogFigure(); - void createProgramMenuFigure(); + void createStartAppDialogFigure(); + void createAppMenuFigure(); void createRemoteAccessHostDialogFigure(); void createRemoteAccessWindowFigure(); void createFileTransferDialogFigure(); void hideComputers(); - void scheduleUiOperation( const std::function& operation ); + void scheduleUiOperation( const std::function& operation ) + { + scheduleUiOperation( operation, this ); + } - static void grabWidget( QWidget* widget, const QPoint& pos, const QSize& size, const QString& fileName ); - static void grabDialog( QDialog* dialog, const QSize& size, const QString& fileName ); + static void scheduleUiOperation( const std::function& operation, QObject* context ); + + static void grabMenu( QWidget* window, const QString& buttonName, const QString& fileName ); + static void grabWidget( QWidget* widget, QPoint pos, const QSize size, const QString& fileName ); + static void grabDialog( QDialog* dialog, QSize size, const QString& fileName ); static void grabWindow( QWidget* widget, const QString& fileName ); - static void grabWindow( QWidget* widget, const QPoint& pos, const QSize& size, const QString& fileName ); + static void grabWindow( QWidget* widget, QPoint pos, const QSize size, const QString& fileName ); - VeyonMaster* m_master; - QEventLoop m_eventLoop; + VeyonMaster m_master{VeyonCore::instance()}; + QEventLoop m_eventLoop{}; } ; diff --git a/master/src/FeatureListModel.cpp b/master/src/FeatureListModel.cpp new file mode 100644 index 000000000..985fdcfe5 --- /dev/null +++ b/master/src/FeatureListModel.cpp @@ -0,0 +1,95 @@ +/* + * FeatureListModel.cpp - data model for features + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "FeatureListModel.h" +#include "VeyonMaster.h" + +#if defined(QT_TESTLIB_LIB) && QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) +#include +#endif + + +FeatureListModel::FeatureListModel( VeyonMaster* masterCore, QObject* parent ) : + QAbstractListModel( parent ), + m_master( masterCore ) +{ +#if defined(QT_TESTLIB_LIB) && QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) + new QAbstractItemModelTester( this, QAbstractItemModelTester::FailureReportingMode::Warning, this ); +#endif +} + + + +int FeatureListModel::rowCount( const QModelIndex& parent ) const +{ + if( parent.isValid() ) + { + return 0; + } + + return m_master->features().count(); +} + + + +QVariant FeatureListModel::data( const QModelIndex& index, int role ) const +{ + if( index.isValid() == false ) + { + return {}; + } + + if( index.row() >= m_master->features().count() ) + { + vCritical() << "index out of range!"; + } + + const auto feature = m_master->features()[index.row()]; + + switch( DataRole(role) ) + { + case DataRole::Name: return feature.name(); + case DataRole::DisplayName: return feature.displayName(); + case DataRole::DisplayNameActive: return feature.displayNameActive(); + case DataRole::IconUrl: return QString{ QStringLiteral("qrc") + feature.iconUrl() }; + case DataRole::Description: return feature.description(); + case DataRole::Uid: return feature.uid(); + } + + return {}; +} + + + +QHash FeatureListModel::roleNames() const +{ + return { + { int(DataRole::Name), "name" }, + { int(DataRole::DisplayName), "displayName" }, + { int(DataRole::DisplayNameActive), "displayNameActive" }, + { int(DataRole::IconUrl), "iconUrl" }, + { int(DataRole::Description), "description" }, + { int(DataRole::Uid), "uid" }, + }; +} diff --git a/master/src/FeatureListModel.h b/master/src/FeatureListModel.h new file mode 100644 index 000000000..0c48a4b4d --- /dev/null +++ b/master/src/FeatureListModel.h @@ -0,0 +1,57 @@ +/* + * FeatureListListModel.h - data model for features + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +#include "Feature.h" + +class VeyonMaster; + +class FeatureListModel : public QAbstractListModel +{ + Q_OBJECT +public: + enum class DataRole { + Name, + DisplayName, + DisplayNameActive, + Description, + IconUrl, + Uid, + }; + + explicit FeatureListModel( VeyonMaster* masterCore, QObject* parent = nullptr ); + + int rowCount( const QModelIndex& parent = QModelIndex() ) const override; + + QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const override; + + QHash roleNames() const override; + +private: + VeyonMaster* m_master; + +}; diff --git a/master/src/FlexibleListView.cpp b/master/src/FlexibleListView.cpp index 68c6b7e2c..ccf2381f7 100644 --- a/master/src/FlexibleListView.cpp +++ b/master/src/FlexibleListView.cpp @@ -1,7 +1,7 @@ /* * FlexibleListView.cpp - list view with flexible icon positions * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,12 +22,12 @@ * */ +#include #include #include #include #include "FlexibleListView.h" -#include "QtCompat.h" FlexibleListView::FlexibleListView( QWidget* parent ) : @@ -82,7 +82,7 @@ void FlexibleListView::alignToGrid() { m_positions[uid] = QPointF( qMax( 0, qRound( m_positions[uid].x() ) ), qMax( 0, qRound( m_positions[uid].y() ) ) ); - setPositionForIndex( toItemPosition( qAsConst(m_positions)[uid] ), index ); + setPositionForIndex( toItemPosition( std::as_const(m_positions)[uid] ), index ); } } } @@ -136,6 +136,47 @@ void FlexibleListView::doItemsLayout() +bool FlexibleListView::viewportEvent( QEvent* event ) +{ + const auto ret = QListView::viewportEvent( event ); + if( event->type() == QEvent::ToolTip ) + { + m_toolTipPos = ret ? static_cast(event)->pos() : QPoint{}; + } + + return ret; +} + + + +void FlexibleListView::dataChanged( const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector& roles ) +{ + QListView::dataChanged( topLeft, bottomRight, roles ); + + if (roles.contains(m_uidRole)) + { + restorePositions(); + } + + if( m_toolTipPos.isNull() == false && ( roles.isEmpty() || roles.contains(Qt::ToolTipRole) ) ) + { + if( viewport()->mapToGlobal(m_toolTipPos) != QCursor::pos() ) + { + m_toolTipPos = QPoint(); + return; + } + + const auto index = indexAt( m_toolTipPos ); + if( index.row() >= topLeft.row() && index.row() <= bottomRight.row() ) + { + QHelpEvent he( QEvent::ToolTip, m_toolTipPos, viewport()->mapToGlobal(m_toolTipPos) ); + QListView::viewportEvent( &he ); + } + } +} + + + void FlexibleListView::restorePositions() { auto m = model(); @@ -152,7 +193,7 @@ void FlexibleListView::restorePositions() if( uid.isNull() == false && m_positions.contains( uid ) ) { - setPositionForIndex( toItemPosition( qAsConst(m_positions)[uid] ), index ); + setPositionForIndex( toItemPosition( std::as_const(m_positions)[uid] ), index ); } } } @@ -188,7 +229,8 @@ QSizeF FlexibleListView::effectiveGridSize() const { return rectForIndex( m->index( 0, 0 ) ).size() + QSize( spacing(), spacing() ); } - else if( iconSize().isEmpty() == false ) + + if( iconSize().isEmpty() == false ) { return iconSize() + QSize( spacing(), spacing() ); } diff --git a/master/src/FlexibleListView.h b/master/src/FlexibleListView.h index 2b5157a22..0f508ee85 100644 --- a/master/src/FlexibleListView.h +++ b/master/src/FlexibleListView.h @@ -1,7 +1,7 @@ /* * FlexibleListView.h - list view with flexible icon positions * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -46,11 +46,15 @@ class FlexibleListView : public QListView public: void doItemsLayout() override; +protected: + bool viewportEvent( QEvent* event ) override; + void dataChanged( const QModelIndex& topLeft, const QModelIndex& bottomRight, + const QVector& roles ) override; + private: void restorePositions(); void updatePositions(); -private: QSizeF effectiveGridSize() const; QPointF toGridPoint( QPoint pos ) const; QPoint toItemPosition( QPointF gridPoint ) const; @@ -58,4 +62,5 @@ class FlexibleListView : public QListView int m_uidRole; QHash m_positions; + QPoint m_toolTipPos; }; diff --git a/master/src/KExtraColumnsProxyModel.cpp b/master/src/KExtraColumnsProxyModel.cpp new file mode 100644 index 000000000..0d879641f --- /dev/null +++ b/master/src/KExtraColumnsProxyModel.cpp @@ -0,0 +1,349 @@ +/* + SPDX-FileCopyrightText: 2015 Klarälvdalens Datakonsult AB, a KDAB Group company + SPDX-FileContributor: David Faure + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ + +#include "KExtraColumnsProxyModel.h" + +#include + +class KExtraColumnsProxyModelPrivate +{ + Q_DECLARE_PUBLIC(KExtraColumnsProxyModel) + KExtraColumnsProxyModel *const q_ptr; + +public: + KExtraColumnsProxyModelPrivate(KExtraColumnsProxyModel *model) + : q_ptr(model) + { + } + + void _ec_sourceLayoutAboutToBeChanged(const QList &sourceParents, QAbstractItemModel::LayoutChangeHint hint); + void _ec_sourceLayoutChanged(const QList &sourceParents, QAbstractItemModel::LayoutChangeHint hint); + + // Configuration (doesn't change once source model is plugged in) + QVector m_extraHeaders; + + // for layoutAboutToBeChanged/layoutChanged + QVector layoutChangePersistentIndexes; + QVector layoutChangeProxyColumns; + QModelIndexList proxyIndexes; +}; + +KExtraColumnsProxyModel::KExtraColumnsProxyModel(QObject *parent) + : QIdentityProxyModel(parent) + , d_ptr(new KExtraColumnsProxyModelPrivate(this)) +{ + // The handling of persistent model indexes assumes mapToSource can be called for any index + // This breaks for the extra column, so we'll have to do it ourselves +#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) + setHandleSourceLayoutChanges(false); +#endif +} + +KExtraColumnsProxyModel::~KExtraColumnsProxyModel() +{ +} + +void KExtraColumnsProxyModel::appendColumn(const QString &header) +{ + Q_D(KExtraColumnsProxyModel); + d->m_extraHeaders.append(header); +} + +void KExtraColumnsProxyModel::removeExtraColumn(int idx) +{ + Q_D(KExtraColumnsProxyModel); + d->m_extraHeaders.remove(idx); +} + +bool KExtraColumnsProxyModel::setExtraColumnData(const QModelIndex &parent, int row, int extraColumn, const QVariant &data, int role) +{ + Q_UNUSED(parent); + Q_UNUSED(row); + Q_UNUSED(extraColumn); + Q_UNUSED(data); + Q_UNUSED(role); + return false; +} + +void KExtraColumnsProxyModel::extraColumnDataChanged(const QModelIndex &parent, int row, int extraColumn, const QVector &roles) +{ + const QModelIndex idx = index(row, proxyColumnForExtraColumn(extraColumn), parent); + Q_EMIT dataChanged(idx, idx, roles); +} + +void KExtraColumnsProxyModel::setSourceModel(QAbstractItemModel *model) +{ + if (sourceModel()) { + disconnect(sourceModel(), + SIGNAL(layoutAboutToBeChanged(QList, QAbstractItemModel::LayoutChangeHint)), + this, + SLOT(_ec_sourceLayoutAboutToBeChanged(QList, QAbstractItemModel::LayoutChangeHint))); + disconnect(sourceModel(), + SIGNAL(layoutChanged(QList, QAbstractItemModel::LayoutChangeHint)), + this, + SLOT(_ec_sourceLayoutChanged(QList, QAbstractItemModel::LayoutChangeHint))); + } + + QIdentityProxyModel::setSourceModel(model); + + if (model) { + // The handling of persistent model indexes assumes mapToSource can be called for any index + // This breaks for the extra column, so we'll have to do it ourselves +#if QT_VERSION < QT_VERSION_CHECK(6, 8, 0) + disconnect(model, + SIGNAL(layoutAboutToBeChanged(QList, QAbstractItemModel::LayoutChangeHint)), + this, + SLOT(_q_sourceLayoutAboutToBeChanged(QList, QAbstractItemModel::LayoutChangeHint))); + disconnect(model, + SIGNAL(layoutChanged(QList, QAbstractItemModel::LayoutChangeHint)), + this, + SLOT(_q_sourceLayoutChanged(QList, QAbstractItemModel::LayoutChangeHint))); +#endif + connect(model, + SIGNAL(layoutAboutToBeChanged(QList, QAbstractItemModel::LayoutChangeHint)), + this, + SLOT(_ec_sourceLayoutAboutToBeChanged(QList, QAbstractItemModel::LayoutChangeHint))); + connect(model, + SIGNAL(layoutChanged(QList, QAbstractItemModel::LayoutChangeHint)), + this, + SLOT(_ec_sourceLayoutChanged(QList, QAbstractItemModel::LayoutChangeHint))); + } +} + +QModelIndex KExtraColumnsProxyModel::mapToSource(const QModelIndex &proxyIndex) const +{ + if (!proxyIndex.isValid()) { // happens in e.g. rowCount(mapToSource(parent)) + return QModelIndex(); + } + const int column = proxyIndex.column(); + if (column >= sourceModel()->columnCount()) { + return QModelIndex(); + } + return QIdentityProxyModel::mapToSource(proxyIndex); +} + +QModelIndex KExtraColumnsProxyModel::buddy(const QModelIndex &proxyIndex) const +{ + if (sourceModel()) { + const int column = proxyIndex.column(); + if (column >= sourceModel()->columnCount()) { + return proxyIndex; + } + } + return QIdentityProxyModel::buddy(proxyIndex); +} + +QModelIndex KExtraColumnsProxyModel::sibling(int row, int column, const QModelIndex &idx) const +{ + if (row == idx.row() && column == idx.column()) { + return idx; + } + return index(row, column, parent(idx)); +} + +QItemSelection KExtraColumnsProxyModel::mapSelectionToSource(const QItemSelection &selection) const +{ + QItemSelection sourceSelection; + + if (!sourceModel()) { + return sourceSelection; + } + + // mapToSource will give invalid index for our additional columns, so truncate the selection + // to the columns known by the source model + const int sourceColumnCount = sourceModel()->columnCount(); + QItemSelection::const_iterator it = selection.constBegin(); + const QItemSelection::const_iterator end = selection.constEnd(); + for (; it != end; ++it) { + Q_ASSERT(it->model() == this); + QModelIndex topLeft = it->topLeft(); + Q_ASSERT(topLeft.isValid()); + Q_ASSERT(topLeft.model() == this); + topLeft = topLeft.sibling(topLeft.row(), 0); + QModelIndex bottomRight = it->bottomRight(); + Q_ASSERT(bottomRight.isValid()); + Q_ASSERT(bottomRight.model() == this); + if (bottomRight.column() >= sourceColumnCount) { + bottomRight = bottomRight.sibling(bottomRight.row(), sourceColumnCount - 1); + } + // This can lead to duplicate source indexes, so use merge(). + const QItemSelectionRange range(mapToSource(topLeft), mapToSource(bottomRight)); + QItemSelection newSelection; + newSelection << range; + sourceSelection.merge(newSelection, QItemSelectionModel::Select); + } + + return sourceSelection; +} + +int KExtraColumnsProxyModel::columnCount(const QModelIndex &parent) const +{ + Q_D(const KExtraColumnsProxyModel); + return QIdentityProxyModel::columnCount(parent) + d->m_extraHeaders.count(); +} + +QVariant KExtraColumnsProxyModel::data(const QModelIndex &index, int role) const +{ + Q_D(const KExtraColumnsProxyModel); + const int extraCol = extraColumnForProxyColumn(index.column()); + if (extraCol >= 0 && !d->m_extraHeaders.isEmpty()) { + return extraColumnData(index.parent(), index.row(), extraCol, role); + } + return sourceModel()->data(mapToSource(index), role); +} + +bool KExtraColumnsProxyModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + Q_D(const KExtraColumnsProxyModel); + const int extraCol = extraColumnForProxyColumn(index.column()); + if (extraCol >= 0 && !d->m_extraHeaders.isEmpty()) { + return setExtraColumnData(index.parent(), index.row(), extraCol, value, role); + } + return sourceModel()->setData(mapToSource(index), value, role); +} + +Qt::ItemFlags KExtraColumnsProxyModel::flags(const QModelIndex &index) const +{ + const int extraCol = extraColumnForProxyColumn(index.column()); + if (extraCol >= 0) { + // extra columns are readonly + return Qt::ItemIsSelectable | Qt::ItemIsEnabled; + } + return sourceModel() != nullptr ? sourceModel()->flags(mapToSource(index)) : Qt::NoItemFlags; +} + +bool KExtraColumnsProxyModel::hasChildren(const QModelIndex &index) const +{ + if (index.column() > 0) { + return false; + } + return QIdentityProxyModel::hasChildren(index); +} + +QVariant KExtraColumnsProxyModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + Q_D(const KExtraColumnsProxyModel); + if (orientation == Qt::Horizontal) { + const int extraCol = extraColumnForProxyColumn(section); + if (extraCol >= 0) { + // Only text is supported, in headers for extra columns + if (role == Qt::DisplayRole) { + return d->m_extraHeaders.at(extraCol); + } + return QVariant(); + } + } + return QIdentityProxyModel::headerData(section, orientation, role); +} + +QModelIndex KExtraColumnsProxyModel::index(int row, int column, const QModelIndex &parent) const +{ + const int extraCol = extraColumnForProxyColumn(column); + if (extraCol >= 0) { + // We store the internal pointer of the index for column 0 in the proxy index for extra columns. + // This will be useful in the parent method. + return createIndex(row, column, QIdentityProxyModel::index(row, 0, parent).internalPointer()); + } + return QIdentityProxyModel::index(row, column, parent); +} + +QModelIndex KExtraColumnsProxyModel::parent(const QModelIndex &child) const +{ + const int extraCol = extraColumnForProxyColumn(child.column()); + if (extraCol >= 0) { + // Create an index for column 0 and use that to get the parent. + const QModelIndex proxySibling = createIndex(child.row(), 0, child.internalPointer()); + return QIdentityProxyModel::parent(proxySibling); + } + return QIdentityProxyModel::parent(child); +} + +int KExtraColumnsProxyModel::extraColumnForProxyColumn(int proxyColumn) const +{ + if (sourceModel() != nullptr) { + const int sourceColumnCount = sourceModel()->columnCount(); + if (proxyColumn >= sourceColumnCount) { + return proxyColumn - sourceColumnCount; + } + } + return -1; +} + +int KExtraColumnsProxyModel::proxyColumnForExtraColumn(int extraColumn) const +{ + return sourceModel()->columnCount() + extraColumn; +} + +void KExtraColumnsProxyModelPrivate::_ec_sourceLayoutAboutToBeChanged(const QList &sourceParents, + QAbstractItemModel::LayoutChangeHint hint) +{ + Q_Q(KExtraColumnsProxyModel); + + QList parents; + parents.reserve(sourceParents.size()); + for (const QPersistentModelIndex &parent : sourceParents) { + if (!parent.isValid()) { + parents << QPersistentModelIndex(); + continue; + } + const QModelIndex mappedParent = q->mapFromSource(parent); + Q_ASSERT(mappedParent.isValid()); + parents << mappedParent; + } + + Q_EMIT q->layoutAboutToBeChanged(parents, hint); + + const QModelIndexList persistentIndexList = q->persistentIndexList(); + layoutChangePersistentIndexes.reserve(persistentIndexList.size()); + layoutChangeProxyColumns.reserve(persistentIndexList.size()); + + for (QModelIndex proxyPersistentIndex : persistentIndexList) { + proxyIndexes << proxyPersistentIndex; + Q_ASSERT(proxyPersistentIndex.isValid()); + const int column = proxyPersistentIndex.column(); + layoutChangeProxyColumns << column; + if (column >= q->sourceModel()->columnCount()) { + proxyPersistentIndex = proxyPersistentIndex.sibling(proxyPersistentIndex.row(), 0); + } + const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex); + Q_ASSERT(srcPersistentIndex.isValid()); + layoutChangePersistentIndexes << srcPersistentIndex; + } +} + +void KExtraColumnsProxyModelPrivate::_ec_sourceLayoutChanged(const QList &sourceParents, QAbstractItemModel::LayoutChangeHint hint) +{ + Q_Q(KExtraColumnsProxyModel); + for (int i = 0; i < proxyIndexes.size(); ++i) { + const QModelIndex proxyIdx = proxyIndexes.at(i); + QModelIndex newProxyIdx = q->mapFromSource(layoutChangePersistentIndexes.at(i)); + if (proxyIdx.column() >= q->sourceModel()->columnCount()) { + newProxyIdx = newProxyIdx.sibling(newProxyIdx.row(), layoutChangeProxyColumns.at(i)); + } + q->changePersistentIndex(proxyIdx, newProxyIdx); + } + + layoutChangePersistentIndexes.clear(); + layoutChangeProxyColumns.clear(); + proxyIndexes.clear(); + + QList parents; + parents.reserve(sourceParents.size()); + for (const QPersistentModelIndex &parent : sourceParents) { + if (!parent.isValid()) { + parents << QPersistentModelIndex(); + continue; + } + const QModelIndex mappedParent = q->mapFromSource(parent); + Q_ASSERT(mappedParent.isValid()); + parents << mappedParent; + } + + Q_EMIT q->layoutChanged(parents, hint); +} + +#include "moc_KExtraColumnsProxyModel.cpp" diff --git a/master/src/KExtraColumnsProxyModel.h b/master/src/KExtraColumnsProxyModel.h new file mode 100644 index 000000000..813269cec --- /dev/null +++ b/master/src/KExtraColumnsProxyModel.h @@ -0,0 +1,142 @@ +/* + SPDX-FileCopyrightText: 2015 Klarälvdalens Datakonsult AB, a KDAB Group company + SPDX-FileContributor: David Faure + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ + +#ifndef KEXTRACOLUMNSPROXYMODEL_H +#define KEXTRACOLUMNSPROXYMODEL_H + +#include +#include + +class KExtraColumnsProxyModelPrivate; + +/** + * @class KExtraColumnsProxyModel KExtraColumnsProxyModel.h KExtraColumnsProxyModel + * + * This proxy appends extra columns (after all existing columns). + * + * The proxy supports source models that have a tree structure. + * It also supports editing, and propagating changes from the source model. + * Row insertion/removal, column insertion/removal in the source model are supported. + * + * Not supported: adding/removing extra columns at runtime; having a different number of columns in subtrees; + * drag-n-drop support in the extra columns; moving columns. + * + * Derive from KExtraColumnsProxyModel, call appendColumn (typically in the constructor) for each extra column, + * and reimplement extraColumnData() to allow KExtraColumnsProxyModel to retrieve the data to show in the extra columns. + * + * If you want your new column(s) to be somewhere else than at the right of the existing columns, you can + * use a KRearrangeColumnsProxyModel on top. + * + * Author: David Faure, KDAB + * @since 5.13 + */ +class KExtraColumnsProxyModel : public QIdentityProxyModel +{ + Q_OBJECT +public: + /** + * Base class constructor. + * Remember to call setSourceModel afterwards, and appendColumn. + */ + explicit KExtraColumnsProxyModel(QObject *parent = nullptr); + /** + * Destructor. + */ + ~KExtraColumnsProxyModel() override; + + // API + + /** + * Appends an extra column. + * @param header an optional text for the horizontal header + * This does not emit any signals - do it in the initial setup phase + */ + void appendColumn(const QString &header = QString()); + + /** + * Removes an extra column. + * @param idx index of the extra column (starting from 0). + * This does not emit any signals - do it in the initial setup phase + * @since 5.24 + */ + void removeExtraColumn(int idx); + + /** + * This method is called by data() for extra columns. + * Reimplement this method to return the data for the extra columns. + * + * @param parent the parent model index in the proxy model (only useful in tree models) + * @param row the row number for which the proxy model is querying for data (child of @p parent, if set) + * @param extraColumn the number of the extra column, starting at 0 (this doesn't require knowing how many columns the source model has) + * @param role the role being queried + * @return the data at @p row and @p extraColumn + */ + virtual QVariant extraColumnData(const QModelIndex &parent, int row, int extraColumn, int role = Qt::DisplayRole) const = 0; + + // KF6 TODO: add extraColumnFlags() virtual method + + /** + * This method is called by setData() for extra columns. + * Reimplement this method to set the data for the extra columns, if editing is supported. + * Remember to call extraColumnDataChanged() after changing the data storage. + * The default implementation returns false. + */ + virtual bool setExtraColumnData(const QModelIndex &parent, int row, int extraColumn, const QVariant &data, int role = Qt::EditRole); + + /** + * This method can be called by your derived class when the data in an extra column has changed. + * The use case is data that changes "by itself", unrelated to setData. + */ + void extraColumnDataChanged(const QModelIndex &parent, int row, int extraColumn, const QVector &roles); + + /** + * Returns the extra column number (0, 1, ...) for a given column number of the proxymodel. + * This basically means subtracting the amount of columns in the source model. + */ + int extraColumnForProxyColumn(int proxyColumn) const; + /** + * Returns the proxy column number for a given extra column number (starting at 0). + * This basically means adding the amount of columns in the source model. + */ + int proxyColumnForExtraColumn(int extraColumn) const; + + // Implementation + /// @reimp + void setSourceModel(QAbstractItemModel *model) override; + /// @reimp + QModelIndex mapToSource(const QModelIndex &proxyIndex) const override; + /// @reimp + QItemSelection mapSelectionToSource(const QItemSelection &selection) const override; + /// @reimp + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + /// @reimp + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + /// @reimp + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + /// @reimp + QModelIndex sibling(int row, int column, const QModelIndex &idx) const override; + /// @reimp + QModelIndex buddy(const QModelIndex &index) const override; + /// @reimp + Qt::ItemFlags flags(const QModelIndex &index) const override; + /// @reimp + bool hasChildren(const QModelIndex &index) const override; + /// @reimp + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + /// @reimp + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; + /// @reimp + QModelIndex parent(const QModelIndex &child) const override; + +private: + Q_DECLARE_PRIVATE(KExtraColumnsProxyModel) + Q_PRIVATE_SLOT(d_func(), void _ec_sourceLayoutAboutToBeChanged(const QList &, QAbstractItemModel::LayoutChangeHint)) + Q_PRIVATE_SLOT(d_func(), void _ec_sourceLayoutChanged(const QList &, QAbstractItemModel::LayoutChangeHint)) + const QScopedPointer d_ptr; +}; + +#endif diff --git a/master/src/KItemModelsIntegration.cpp b/master/src/KItemModelsIntegration.cpp deleted file mode 100644 index 4618c2595..000000000 --- a/master/src/KItemModelsIntegration.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include "kitemmodels_debug.h" - -Q_LOGGING_CATEGORY(KITEMMODELS_LOG, "kf5.kitemmodels"); - diff --git a/master/src/LocationDialog.cpp b/master/src/LocationDialog.cpp index 29b9f05ca..f3102e925 100644 --- a/master/src/LocationDialog.cpp +++ b/master/src/LocationDialog.cpp @@ -1,7 +1,7 @@ /* * LocationDialog.cpp - header file for LocationDialog * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,19 +27,27 @@ #include "ui_LocationDialog.h" LocationDialog::LocationDialog( QAbstractItemModel* locationListModel, QWidget* parent ) : - QDialog( parent ), - ui( new Ui::LocationDialog ), - m_sortFilterProxyModel( this ) + QDialog(parent), + ui(new Ui::LocationDialog) { ui->setupUi( this ); - m_sortFilterProxyModel.setSourceModel( locationListModel ); + m_networkObjectFilterProxyModel.setSourceModel(locationListModel); + m_networkObjectFilterProxyModel.setComputersExcluded(true); + + m_sortFilterProxyModel.setSourceModel(&m_networkObjectFilterProxyModel); +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) + m_sortFilterProxyModel.setRecursiveFilteringEnabled(true); +#endif + m_sortFilterProxyModel.setFilterCaseSensitivity( Qt::CaseInsensitive ); m_sortFilterProxyModel.sort( 0 ); - ui->listView->setModel( &m_sortFilterProxyModel ); + ui->treeView->setModel(&m_sortFilterProxyModel); - connect( ui->listView->selectionModel(), &QItemSelectionModel::currentChanged, - this, &LocationDialog::updateSelection ); + connect (ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, + this, &LocationDialog::updateSelection); + connect (ui->treeView, &QTreeView::activated, + this, &LocationDialog::accept); updateSearchFilter(); } @@ -55,10 +63,15 @@ LocationDialog::~LocationDialog() void LocationDialog::updateSearchFilter() { - m_sortFilterProxyModel.setFilterRegExp( QRegExp( ui->filterLineEdit->text() ) ); - m_sortFilterProxyModel.setFilterCaseSensitivity( Qt::CaseInsensitive ); + ui->treeView->expandAll(); + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1) + m_sortFilterProxyModel.setFilterRegularExpression( ui->filterLineEdit->text() ); +#else + m_sortFilterProxyModel.setFilterRegExp( ui->filterLineEdit->text() ); +#endif - ui->listView->selectionModel()->setCurrentIndex( m_sortFilterProxyModel.index( 0, 0 ), + ui->treeView->selectionModel()->setCurrentIndex( m_sortFilterProxyModel.index( 0, 0 ), QItemSelectionModel::ClearAndSelect ); } diff --git a/master/src/LocationDialog.h b/master/src/LocationDialog.h index d4ef8a06a..9309329a4 100644 --- a/master/src/LocationDialog.h +++ b/master/src/LocationDialog.h @@ -1,7 +1,7 @@ /* * LocationDialog.h - header file for LocationDialog * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,7 +25,8 @@ #pragma once #include -#include + +#include "NetworkObjectFilterProxyModel.h" namespace Ui { class LocationDialog; @@ -43,13 +44,14 @@ class LocationDialog : public QDialog return m_selectedLocation; } -private slots: +private Q_SLOTS: void updateSearchFilter(); void updateSelection( const QModelIndex& current, const QModelIndex& previous ); private: Ui::LocationDialog *ui; - QSortFilterProxyModel m_sortFilterProxyModel; + QSortFilterProxyModel m_sortFilterProxyModel{this}; + NetworkObjectFilterProxyModel m_networkObjectFilterProxyModel{this}; QString m_selectedLocation; }; diff --git a/master/src/LocationDialog.ui b/master/src/LocationDialog.ui index 18a4fd8af..e20f25168 100644 --- a/master/src/LocationDialog.ui +++ b/master/src/LocationDialog.ui @@ -2,14 +2,6 @@ LocationDialog - - - 0 - 0 - 640 - 480 - - 640 @@ -27,23 +19,20 @@
- - - - QAbstractScrollArea::AdjustToContents - - - QListView::Adjust - - - - Qt::Horizontal + Qt::Orientation::Horizontal - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + + + + + + + QAbstractScrollArea::SizeAdjustPolicy::AdjustToContents @@ -115,22 +104,6 @@ - - listView - activated(QModelIndex) - LocationDialog - accept() - - - 312 - 134 - - - 396 - 143 - - - updateSearchFilter() diff --git a/master/src/MainToolBar.cpp b/master/src/MainToolBar.cpp index 939b7d164..d47231e26 100644 --- a/master/src/MainToolBar.cpp +++ b/master/src/MainToolBar.cpp @@ -1,7 +1,7 @@ /* * MainToolBar.cpp - MainToolBar for MainWindow * - * Copyright (c) 2007-2019 Tobias Junghans + * Copyright (c) 2007-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,8 +22,6 @@ */ #include -#include -#include #include "MainToolBar.h" #include "MainWindow.h" @@ -36,9 +34,7 @@ MainToolBar::MainToolBar( QWidget* parent ) : QToolBar( tr( "Configuration" ), parent ), m_mainWindow( dynamic_cast( parent ) ) { - QPalette pal = palette(); - pal.setBrush( QPalette::Window, QPixmap( QStringLiteral(":/core/toolbar-background.png") ) ); - setPalette( pal ); + setIconSize(QSize(32, 32)); ToolButton::setToolTipsDisabled( m_mainWindow->masterCore().userConfig().noToolTips() ); ToolButton::setIconOnlyMode( m_mainWindow, m_mainWindow->masterCore().userConfig().toolButtonIconOnlyMode() ); @@ -50,23 +46,11 @@ void MainToolBar::contextMenuEvent( QContextMenuEvent* event ) { QMenu menu( this ); -#if QT_VERSION < 0x050600 -#warning Building legacy compat code for unsupported version of Qt - auto toolTipAction = menu.addAction( tr( "Disable balloon tooltips" ) ); - connect( toolTipAction, &QAction::triggered, this, &MainToolBar::toggleToolTips ); -#else - auto toolTipAction = menu.addAction( tr( "Disable balloon tooltips" ), this, &MainToolBar::toggleToolTips ); -#endif + auto toolTipAction = menu.addAction(tr("Disable tooltips"), this, &MainToolBar::toggleToolTips); toolTipAction->setCheckable( true ); toolTipAction->setChecked( m_mainWindow->masterCore().userConfig().noToolTips() ); -#if QT_VERSION < 0x050600 -#warning Building legacy compat code for unsupported version of Qt - auto iconModeAction = menu.addAction( tr( "Show icons only" ) ); - connect( iconModeAction, &QAction::triggered, this, &MainToolBar::toggleIconMode ); -#else auto iconModeAction = menu.addAction( tr( "Show icons only" ), this, &MainToolBar::toggleIconMode ); -#endif iconModeAction->setCheckable( true ); iconModeAction->setChecked( m_mainWindow->masterCore().userConfig().toolButtonIconOnlyMode() ); @@ -75,17 +59,6 @@ void MainToolBar::contextMenuEvent( QContextMenuEvent* event ) -void MainToolBar::paintEvent( QPaintEvent* event ) -{ - QPainter p( this ); - p.setPen( QColor( 48, 48, 48 ) ); - p.fillRect( event->rect(), palette().brush( QPalette::Window ) ); - p.drawLine( 0, 0, width(), 0 ); - p.drawLine( 0, height()-1, width(), height()-1 ); -} - - - void MainToolBar::toggleToolTips() { bool newToolTipState = !m_mainWindow->masterCore().userConfig().noToolTips(); diff --git a/master/src/MainToolBar.h b/master/src/MainToolBar.h index cd04f675d..b10e67f6b 100644 --- a/master/src/MainToolBar.h +++ b/master/src/MainToolBar.h @@ -1,7 +1,7 @@ /* * MainToolBar.h - MainToolBar for MainWindow * - * Copyright (c) 2007-2019 Tobias Junghans + * Copyright (c) 2007-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -40,7 +40,6 @@ class MainToolBar : public QToolBar void toggleIconMode(); void contextMenuEvent( QContextMenuEvent* event ) override; - void paintEvent( QPaintEvent* event ) override; MainWindow* m_mainWindow; diff --git a/master/src/MainWindow.cpp b/master/src/MainWindow.cpp index 1595423de..c14d21b6c 100644 --- a/master/src/MainWindow.cpp +++ b/master/src/MainWindow.cpp @@ -1,7 +1,7 @@ /* * MainWindow.cpp - implementation of MainWindow class * - * Copyright (c) 2004-2019 Tobias Junghans + * Copyright (c) 2004-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,6 +23,8 @@ */ #include +#include +#include #include #include #include @@ -31,9 +33,9 @@ #include "AboutDialog.h" #include "AccessControlProvider.h" +#include "AuthenticationManager.h" #include "MainWindow.h" #include "BuiltinFeatures.h" -#include "AuthenticationCredentials.h" #include "ComputerControlListModel.h" #include "ComputerManager.h" #include "ComputerSelectPanel.h" @@ -42,6 +44,8 @@ #include "MonitoringMode.h" #include "NetworkObjectDirectory.h" #include "NetworkObjectDirectoryManager.h" +#include "SlideshowPanel.h" +#include "SpotlightPanel.h" #include "ToolButton.h" #include "VeyonConfiguration.h" #include "VeyonMaster.h" @@ -63,84 +67,201 @@ MainWindow::MainWindow( VeyonMaster &masterCore, QWidget* parent ) : restoreState( QByteArray::fromBase64( m_master.userConfig().windowState().toUtf8() ) ); restoreGeometry( QByteArray::fromBase64( m_master.userConfig().windowGeometry().toUtf8() ) ); - ui->computerMonitoringWidget->setVeyonMaster( m_master ); - // add widgets to status bar - ui->statusBar->addWidget( ui->computerSelectPanelButton ); - ui->statusBar->addWidget( ui->screenshotManagementPanelButton ); + ui->statusBar->addWidget( ui->panelButtons ); ui->statusBar->addWidget( ui->spacerLabel1 ); ui->statusBar->addWidget( ui->filterLineEdit, 2 ); ui->statusBar->addWidget( ui->filterPoweredOnComputersButton ); + ui->statusBar->addWidget( ui->filterComputersWithLoggedOnUsersButton ); ui->statusBar->addWidget( ui->spacerLabel2, 1 ); ui->statusBar->addWidget( ui->gridSizeSlider, 2 ); - ui->statusBar->addWidget( ui->autoFitButton ); + ui->statusBar->addWidget( ui->autoAdjustComputerIconSizeButton ); ui->statusBar->addWidget( ui->spacerLabel3 ); - ui->statusBar->addWidget( ui->useCustomComputerArrangementButton ); + ui->statusBar->addWidget( ui->useCustomComputerPositionsButton ); ui->statusBar->addWidget( ui->alignComputersButton ); ui->statusBar->addWidget( ui->spacerLabel4 ); ui->statusBar->addWidget( ui->aboutButton ); // create all views - auto splitter = new QSplitter( Qt::Horizontal, ui->centralWidget ); - splitter->setChildrenCollapsible( false ); + auto mainSplitter = new QSplitter( Qt::Horizontal, ui->centralWidget ); + mainSplitter->setChildrenCollapsible( false ); + mainSplitter->setObjectName( QStringLiteral("MainSplitter") ); + + auto monitoringSplitter = new QSplitter( Qt::Vertical, mainSplitter ); + monitoringSplitter->setChildrenCollapsible( false ); + monitoringSplitter->setObjectName( QStringLiteral("MonitoringSplitter") ); + + auto slideshowSpotlightSplitter = new QSplitter( Qt::Horizontal, monitoringSplitter ); + slideshowSpotlightSplitter->setChildrenCollapsible( false ); + slideshowSpotlightSplitter->setObjectName( QStringLiteral("SlideshowSpotlightSplitter") ); + + auto computerSelectPanel = new ComputerSelectPanel( m_master.computerManager(), m_master.computerSelectModel() ); + auto screenshotManagementPanel = new ScreenshotManagementPanel(); + auto slideshowPanel = new SlideshowPanel( m_master.userConfig(), ui->computerMonitoringWidget ); + auto spotlightPanel = new SpotlightPanel( m_master.userConfig(), ui->computerMonitoringWidget ); + + slideshowSpotlightSplitter->addWidget( slideshowPanel ); + slideshowSpotlightSplitter->addWidget( spotlightPanel ); + slideshowSpotlightSplitter->setStretchFactor( slideshowSpotlightSplitter->indexOf(slideshowPanel), 1 ); + slideshowSpotlightSplitter->setStretchFactor( slideshowSpotlightSplitter->indexOf(spotlightPanel), 1 ); + + monitoringSplitter->addWidget( slideshowSpotlightSplitter ); + monitoringSplitter->addWidget( ui->computerMonitoringWidget ); + monitoringSplitter->setStretchFactor( monitoringSplitter->indexOf(slideshowSpotlightSplitter), 1 ); + monitoringSplitter->setStretchFactor( monitoringSplitter->indexOf(ui->computerMonitoringWidget), 1 ); + + mainSplitter->addWidget( computerSelectPanel ); + mainSplitter->addWidget( screenshotManagementPanel ); + mainSplitter->addWidget( monitoringSplitter ); + + mainSplitter->setStretchFactor( mainSplitter->indexOf(monitoringSplitter), 1 ); + + + static const QHash panelButtons{ + { computerSelectPanel, ui->computerSelectPanelButton }, + { screenshotManagementPanel, ui->screenshotManagementPanelButton }, + { slideshowPanel, ui->slideshowPanelButton }, + { spotlightPanel, ui->spotlightPanelButton } + }; + + for( auto it = panelButtons.constBegin(), end = panelButtons.constEnd(); it != end; ++it ) + { + it.key()->hide(); + it.key()->installEventFilter( this ); + connect( *it, &QAbstractButton::toggled, it.key(), &QWidget::setVisible ); + } - ui->centralLayout->addWidget( splitter ); + QList splitterSizes; + for( auto* splitter : { slideshowSpotlightSplitter, monitoringSplitter, mainSplitter } ) + { + splitter->setHandleWidth( 7 ); + splitter->setStyleSheet( QStringLiteral("QSplitter::handle:hover{background-color:#66a0b3;}") ); - m_computerSelectPanel = new ComputerSelectPanel( m_master.computerManager(), splitter ); - m_screenshotManagementPanel = new ScreenshotManagementPanel( splitter ); + splitter->installEventFilter( this ); - splitter->addWidget( m_computerSelectPanel ); - splitter->addWidget( m_screenshotManagementPanel ); - splitter->addWidget( ui->computerMonitoringWidget ); + int index = 0; - // hide views per default and connect related button - m_computerSelectPanel->hide(); - m_screenshotManagementPanel->hide(); + const auto splitterStates = m_master.userConfig().splitterStates()[splitter->objectName()].toArray(); + splitterSizes.clear(); + splitterSizes.reserve( splitterStates.size() ); - connect( ui->computerSelectPanelButton, &QAbstractButton::toggled, - m_computerSelectPanel, &QWidget::setVisible ); - connect( ui->screenshotManagementPanelButton, &QAbstractButton::toggled, - m_screenshotManagementPanel, &QWidget::setVisible ); + for( const auto& sizeObject : splitterStates ) + { + auto size = sizeObject.toInt(); + const auto widget = splitter->widget( index ); + const auto button = panelButtons.value( widget ); + + if( widget ) + { + if( button ) + { + widget->setVisible( size > 0 ); + button->setChecked( size > 0 ); + } + size = qAbs( size ); + if( splitter->orientation() == Qt::Horizontal ) + { + widget->resize( size, widget->height() ); + } + else + { + widget->resize( widget->width(), size ); + } + + widget->setProperty( originalSizePropertyName(), widget->size() ); + } + splitterSizes.append( size ); + ++index; + } + splitter->setSizes( splitterSizes ); + } + + const auto SplitterContentBaseSize = 500; + + if( spotlightPanel->property( originalSizePropertyName() ).isNull() || + slideshowPanel->property( originalSizePropertyName() ).isNull() ) + { + slideshowSpotlightSplitter->setSizes( { SplitterContentBaseSize, SplitterContentBaseSize } ); + } + + if( slideshowSpotlightSplitter->property( originalSizePropertyName() ).isNull() || + ui->computerMonitoringWidget->property( originalSizePropertyName() ).isNull() ) + { + monitoringSplitter->setSizes( { SplitterContentBaseSize, SplitterContentBaseSize } ); + } + + ui->centralLayout->addWidget( mainSplitter ); if( VeyonCore::config().autoOpenComputerSelectPanel() ) { ui->computerSelectPanelButton->setChecked( true ); } - // initialize search filter - ui->filterPoweredOnComputersButton->setChecked( m_master.userConfig().filterPoweredOnComputers() ); + // initialize filter controls connect( ui->filterLineEdit, &QLineEdit::textChanged, - ui->computerMonitoringWidget, &ComputerMonitoringWidget::setSearchFilter ); + this, [this]( const QString& filter ) { ui->computerMonitoringWidget->setSearchFilter( filter ); } ); connect( ui->filterPoweredOnComputersButton, &QToolButton::toggled, - ui->computerMonitoringWidget, &ComputerMonitoringWidget::setFilterPoweredOnComputers ); + this, [this]( bool enabled ) { ui->computerMonitoringWidget->setFilterPoweredOnComputers( enabled ); } ); + connect( ui->filterComputersWithLoggedOnUsersButton, &QToolButton::toggled, + this, [this]( bool enabled ) { ui->computerMonitoringWidget->setFilterComputersWithLoggedOnUsers( enabled ); } ); + ui->filterPoweredOnComputersButton->setChecked(m_master.userConfig().filterPoweredOnComputers()); + ui->filterComputersWithLoggedOnUsersButton->setChecked(m_master.userConfig().filterComputersWithLoggedOnUsers()); // initialize monitoring screen size slider ui->gridSizeSlider->setMinimum( ComputerMonitoringWidget::MinimumComputerScreenSize ); ui->gridSizeSlider->setMaximum( ComputerMonitoringWidget::MaximumComputerScreenSize ); + ui->gridSizeSlider->setValue( ui->computerMonitoringWidget->computerScreenSize() ); + + ui->autoAdjustComputerIconSizeButton->setChecked( ui->computerMonitoringWidget->autoAdjustIconSize() ); connect( ui->gridSizeSlider, &QSlider::valueChanged, - ui->computerMonitoringWidget, &ComputerMonitoringWidget::setComputerScreenSize ); + this, [this]( int size ) { ui->computerMonitoringWidget->setComputerScreenSize( size ); } ); connect( ui->computerMonitoringWidget, &ComputerMonitoringWidget::computerScreenSizeAdjusted, ui->gridSizeSlider, &QSlider::setValue ); - connect( ui->autoFitButton, &QToolButton::clicked, - ui->computerMonitoringWidget, &ComputerMonitoringWidget::autoAdjustComputerScreenSize ); + connect( ui->autoAdjustComputerIconSizeButton, &QToolButton::toggled, + this, [this]( bool enabled ) { + ui->computerMonitoringWidget->setAutoAdjustIconSize( enabled ); + m_master.userConfig().setAutoAdjustMonitoringIconSize( enabled ); + } ); - int size = ComputerMonitoringWidget::DefaultComputerScreenSize; - if( m_master.userConfig().monitoringScreenSize() >= ComputerMonitoringWidget::MinimumComputerScreenSize ) + // initialize computer placement controls + auto customComputerPositionsControlMenu = new QMenu; + const auto darkSuffix = VeyonCore::useDarkMode() ? QStringLiteral("-dark") : QString(); + customComputerPositionsControlMenu->addAction(QIcon(QStringLiteral(":/core/document-open%1.png").arg(darkSuffix)), + tr("Load computer positions"), + this, &MainWindow::loadComputerPositions); + customComputerPositionsControlMenu->addAction(QIcon(QStringLiteral(":/core/document-save%1.png").arg(darkSuffix)), + tr("Save computer positions"), + this, &MainWindow::saveComputerPositions); + ui->useCustomComputerPositionsButton->setMenu(customComputerPositionsControlMenu); + + ui->useCustomComputerPositionsButton->setChecked(m_master.userConfig().useCustomComputerPositions()); + connect(ui->useCustomComputerPositionsButton, &QToolButton::toggled, + ui->computerMonitoringWidget, &ComputerMonitoringWidget::setUseCustomComputerPositions); + connect(ui->alignComputersButton, &QToolButton::clicked, + ui->computerMonitoringWidget, &ComputerMonitoringWidget::alignComputers); + + // connect spotlight panel visibility to spotlight panel button checked state + connect( spotlightPanel, &SpotlightPanel::visibilityChanged, + ui->spotlightPanelButton, [this](bool isVisible) { + ui->spotlightPanelButton->setChecked (isVisible); + } ); + + const auto toolButtons = findChildren(); + for(auto* btn : toolButtons) { - size = m_master.userConfig().monitoringScreenSize(); + btn->setIconSize(QSize(20, 20)); } - ui->gridSizeSlider->setValue( size ); - ui->computerMonitoringWidget->setComputerScreenSize( size ); - - // initialize computer placement controls - ui->useCustomComputerArrangementButton->setChecked( m_master.userConfig().useCustomComputerPositions() ); - connect( ui->useCustomComputerArrangementButton, &QToolButton::toggled, - ui->computerMonitoringWidget, &ComputerMonitoringWidget::setUseCustomComputerPositions ); - connect( ui->alignComputersButton, &QToolButton::clicked, - ui->computerMonitoringWidget, &ComputerMonitoringWidget::alignComputers ); - + if (VeyonCore::useDarkMode()) + { + ui->aboutButton->setIcon(QIcon(QStringLiteral(":/core/help-about-dark.png"))); + ui->filterComputersWithLoggedOnUsersButton->setIcon(QIcon(QStringLiteral(":/core/user-group-new-dark.png"))); + ui->autoAdjustComputerIconSizeButton->setIcon(QIcon(QStringLiteral(":/master/zoom-fit-best-dark.png"))); + ui->alignComputersButton->setIcon(QIcon(QStringLiteral(":/master/homerun-dark.png"))); + ui->useCustomComputerPositionsButton->setIcon(QIcon(QStringLiteral(":/master/exchange-positions-zorder-dark.png"))); + ui->filterPoweredOnComputersButton->setIcon(QIcon(QStringLiteral(":/master/powered-on-dark.png"))); + } // create the main toolbar ui->toolBar->layout()->setSpacing( 2 ); @@ -151,13 +272,7 @@ MainWindow::MainWindow( VeyonMaster &masterCore, QWidget* parent ) : addFeaturesToToolBar(); reloadSubFeatures(); - m_modeGroup->button( static_cast( qHash( VeyonCore::builtinFeatures().monitoringMode().feature().uid() ) ) )->setChecked( true ); - - // setup system tray icon - QIcon icon( QStringLiteral(":/core/icon16.png") ); - icon.addFile( QStringLiteral(":/core/icon22.png") ); - icon.addFile( QStringLiteral(":/core/icon32.png") ); - icon.addFile( QStringLiteral(":/core/icon64.png") ); + m_modeGroup->button(int(qHash(VeyonCore::builtinFeatures().monitoringMode().feature().uid())))->setChecked(true); // clazy:exclude=qt6-qhash-signature VeyonCore::enforceBranding( this ); } @@ -166,6 +281,8 @@ MainWindow::MainWindow( VeyonMaster &masterCore, QWidget* parent ) : MainWindow::~MainWindow() { + ui->computerMonitoringWidget->saveConfiguration(); + delete ui; } @@ -173,24 +290,19 @@ MainWindow::~MainWindow() bool MainWindow::initAuthentication() { - if( VeyonCore::instance()->initAuthentication() ) + if( VeyonCore::authenticationManager().initializeCredentials() == false ) { - return true; + vCritical() << "failed to initialize credentials"; + return false; } - if( VeyonCore::config().authenticationMethod() == VeyonCore::AuthenticationMethod::KeyFileAuthentication ) + if( VeyonCore::authenticationManager().initializedPlugin()->checkCredentials() == false ) { - QMessageBox::information( nullptr, - tr( "Authentication impossible" ), - tr( "No authentication key files were found or your current ones " - "are outdated. Please create new key files using the %1 " - "Configurator. Alternatively set up logon authentication " - "using the %1 Configurator. Otherwise you won't be " - "able to access computers using %1." ).arg( VeyonCore::applicationName() ) ); - + vCritical() << "failed to check credentials"; + return false; } - return false; + return true; } @@ -198,16 +310,18 @@ bool MainWindow::initAuthentication() bool MainWindow::initAccessControl() { if( VeyonCore::config().accessControlForMasterEnabled() && - VeyonCore::authenticationCredentials().hasCredentials( AuthenticationCredentials::Type::UserLogon ) ) + VeyonCore::authenticationManager().initializedPlugin()->requiresAccessControl() ) { - const auto accessControlResult = - AccessControlProvider().checkAccess( VeyonCore::authenticationCredentials().logonUsername(), - QHostAddress( QHostAddress::LocalHost ).toString(), - QStringList() ); - if( accessControlResult == AccessControlProvider::Access::Deny ) + const auto username = VeyonCore::authenticationManager().initializedPlugin()->accessControlUser(); + const auto authMethodUid = VeyonCore::authenticationManager().toUid( VeyonCore::authenticationManager().initializedPlugin() ); + const auto accessControlResult = VeyonCore::builtinFeatures().accessControlProvider() + .checkAccess( username, + QHostAddress( QHostAddress::LocalHost ).toString(), + QStringList(), + authMethodUid ); + if (accessControlResult.access == AccessControlProvider::Access::Deny) { - vWarning() << "user" << VeyonCore::authenticationCredentials().logonUsername() - << "is not allowed to access computers"; + vWarning() << "user" << username << "is not allowed to access computers"; QMessageBox::critical( nullptr, tr( "Access denied" ), tr( "According to the local configuration you're not allowed " "to access computers in the network. Please log in with a different " @@ -235,11 +349,18 @@ void MainWindow::reloadSubFeatures() +ComputerControlInterfaceList MainWindow::selectedComputerControlInterfaces() const +{ + return ui->computerMonitoringWidget->selectedComputerControlInterfaces(); +} + + + void MainWindow::closeEvent( QCloseEvent* event ) { if( m_master.currentMode() != VeyonCore::builtinFeatures().monitoringMode().feature().uid() ) { - const Feature& activeFeature = m_master.featureManager().feature( m_master.currentMode() ); + const Feature& activeFeature = VeyonCore::featureManager().feature( m_master.currentMode() ); QMessageBox::information( this, tr( "Feature active" ), tr( "The feature \"%1\" is still active. Please stop it before closing %2." ). @@ -248,6 +369,36 @@ void MainWindow::closeEvent( QCloseEvent* event ) return; } + QJsonObject splitterStates; + const auto splitters = findChildren(); + for( const auto* splitter : splitters ) + { + const auto sizes = splitter->sizes(); + QJsonArray splitterSizes; + int i = 0; + int hiddenSize = 0; + for( auto size : sizes ) + { + auto widget = splitter->widget(i); + const auto originalSize = widget->property( originalSizePropertyName() ).toSize(); + if( widget->size().isEmpty() && originalSize.isEmpty() == false ) + { + size = splitter->orientation() == Qt::Horizontal ? -originalSize.width() : -originalSize.height(); + hiddenSize += qAbs(size); + } + else + { + size -= hiddenSize; + } + + splitterSizes.append( size ); + ++i; + } + splitterStates[splitter->objectName()] = splitterSizes; + } + + m_master.userConfig().setSplitterStates( splitterStates ); + m_master.userConfig().setWindowState( QString::fromLatin1( saveState().toBase64() ) ); m_master.userConfig().setWindowGeometry( QString::fromLatin1( saveGeometry().toBase64() ) ); @@ -256,6 +407,24 @@ void MainWindow::closeEvent( QCloseEvent* event ) +bool MainWindow::eventFilter( QObject* object, QEvent* event ) +{ + if( event->type() == QEvent::Resize ) + { + const auto widget = qobject_cast( object ); + const auto resizeEvent = static_cast( event ); + + if( resizeEvent->oldSize().isEmpty() == false ) + { + widget->setProperty( originalSizePropertyName(), resizeEvent->oldSize() ); + } + } + + return QMainWindow::eventFilter( object, event ); +} + + + void MainWindow::keyPressEvent( QKeyEvent* event ) { switch( event->key() ) @@ -288,7 +457,12 @@ void MainWindow::addFeaturesToToolBar() { for( const auto& feature : m_master.features() ) { - ToolButton* btn = new ToolButton( QIcon( feature.iconUrl() ), + if( feature.testFlag( Feature::Flag::Meta ) ) + { + continue; + } + + auto btn = new ToolButton( QIcon( feature.iconUrl() ), feature.displayName(), feature.displayNameActive(), feature.description(), @@ -296,11 +470,15 @@ void MainWindow::addFeaturesToToolBar() connect( btn, &QToolButton::clicked, this, [=] () { m_master.runFeature( feature ); updateModeButtonGroup(); + if( feature.testFlag( Feature::Flag::Mode ) ) + { + reloadSubFeatures(); + } } ); btn->setObjectName( feature.name() ); btn->addTo( ui->toolBar ); - if( feature.testFlag( Feature::Mode ) ) + if( feature.testFlag( Feature::Flag::Mode ) ) { btn->setCheckable( true ); m_modeGroup->addButton( btn, buttonId( feature ) ); @@ -319,9 +497,11 @@ void MainWindow::addSubFeaturesToToolButton( QToolButton* button, const Feature& button->setMenu( nullptr ); } + const auto parentFeatureIsMode = parentFeature.testFlag( Feature::Flag::Mode ); const auto subFeatures = m_master.subFeatures( parentFeature.uid() ); - if( subFeatures.isEmpty() ) + if( subFeatures.isEmpty() || + ( parentFeatureIsMode && button->isChecked() ) ) { return; } @@ -332,17 +512,35 @@ void MainWindow::addSubFeaturesToToolButton( QToolButton* button, const Feature& for( const auto& subFeature : subFeatures ) { -#if QT_VERSION < 0x050600 -#warning Building legacy compat code for unsupported version of Qt - auto action = menu->addAction( QIcon( subFeature.iconUrl() ), subFeature.displayName() ); - action->setShortcut( subFeature.shortcut() ); - connect( action, &QAction::triggered, this, [=] () { m_master.runFeature( subFeature ); } ); -#else - auto action = menu->addAction( QIcon( subFeature.iconUrl() ), subFeature.displayName(), this, - [=]() { m_master.runFeature( subFeature ); }, subFeature.shortcut() ); + auto action = menu->addAction(QIcon(subFeature.iconUrl()), subFeature.displayName(), +#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0) + subFeature.shortcut(), #endif + this, [=]() + { + m_master.runFeature( subFeature ); + if( parentFeatureIsMode ) + { + if( subFeature.testFlag( Feature::Flag::Option ) == false ) + { + button->setChecked( true ); + } + reloadSubFeatures(); + } + } +#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0) + , subFeature.shortcut() +#endif + ); + action->setToolTip( subFeature.description() ); action->setObjectName( subFeature.uid().toString() ); + + if( subFeature.testFlag( Feature::Flag::Option ) ) + { + action->setCheckable( true ); + action->setChecked( subFeature.testFlag( Feature::Flag::Checked ) ); + } } button->setMenu( menu ); @@ -360,3 +558,49 @@ void MainWindow::updateModeButtonGroup() m_modeGroup->button( buttonId( monitoringMode ) )->setChecked( true ); } } + + + +void MainWindow::loadComputerPositions() +{ + if (const auto fileName = QFileDialog::getOpenFileName(this, tr("Load computer positions"), + QDir::homePath(), tr("JSON files (*.json)")); + !fileName.isEmpty()) + { + if (QFile file(fileName); file.open(QFile::ReadOnly)) + { + const auto& computerPositionsProperty = m_master.userConfig().computerPositionsProperty(); + const auto config = QJsonDocument::fromJson(file.readAll()).object(); + const auto uiConfig = config[computerPositionsProperty.parentKey()].toObject(); + const auto computerPositions = uiConfig[computerPositionsProperty.key()].toObject()[QStringLiteral("JsonStoreArray")].toArray(); + + ui->computerMonitoringWidget->loadPositions(computerPositions); + ui->computerMonitoringWidget->setUseCustomComputerPositions(true); + ui->computerMonitoringWidget->doItemsLayout(); + } + } +} + + + +void MainWindow::saveComputerPositions() +{ + if (const auto fileName = QFileDialog::getSaveFileName(this, tr("Save computer positions"), + QDir::homePath(), tr("JSON files (*.json)")); + !fileName.isEmpty()) + { + if (QFile file(fileName); file.open(QFile::WriteOnly | QFile::Truncate)) + { + const auto& computerPositionsProperty = m_master.userConfig().computerPositionsProperty(); + + // create structure identical to UserConfig so file with positions can be used as template for UserConfig + QJsonObject computerPositions; + computerPositions[QStringLiteral("JsonStoreArray")] = ui->computerMonitoringWidget->savePositions(); + QJsonObject uiConfig; + uiConfig[computerPositionsProperty.key()] = computerPositions; + QJsonObject config; + config[computerPositionsProperty.parentKey()] = uiConfig; + file.write(QJsonDocument(config).toJson()); + } + } +} diff --git a/master/src/MainWindow.h b/master/src/MainWindow.h index aa43c7abe..3a61b23d1 100644 --- a/master/src/MainWindow.h +++ b/master/src/MainWindow.h @@ -1,7 +1,7 @@ /* * MainWindow.h - main window of Veyon Master Application * - * Copyright (c) 2004-2019 Tobias Junghans + * Copyright (c) 2004-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,13 +26,11 @@ #include -#include "Feature.h" +#include "ComputerControlInterface.h" class QButtonGroup; class QToolButton; -class ComputerSelectPanel; -class ScreenshotManagementPanel; class VeyonMaster; namespace Ui { @@ -57,18 +55,26 @@ class MainWindow : public QMainWindow void reloadSubFeatures(); + ComputerControlInterfaceList selectedComputerControlInterfaces() const; + protected: void closeEvent( QCloseEvent* event ) override; + bool eventFilter( QObject* object, QEvent* event ) override; void keyPressEvent( QKeyEvent *e ) override; -private slots: +private Q_SLOTS: void showAboutDialog(); private: - static int buttonId( const Feature& feature ) + static int buttonId(const Feature& feature) // clazy:exclude=qt6-qhash-signature + { + return int(qHash(feature.uid())); + } + + static constexpr const char* originalSizePropertyName() { - return static_cast( qHash( feature.uid() ) ); + return "originalSize"; } void addFeaturesToToolBar(); @@ -76,13 +82,13 @@ private slots: void updateModeButtonGroup(); + void loadComputerPositions(); + void saveComputerPositions(); + Ui::MainWindow* ui; VeyonMaster& m_master; QButtonGroup* m_modeGroup; - ComputerSelectPanel* m_computerSelectPanel; - ScreenshotManagementPanel* m_screenshotManagementPanel; - } ; diff --git a/master/src/MainWindow.ui b/master/src/MainWindow.ui index 8fd7564f9..8da76f00a 100644 --- a/master/src/MainWindow.ui +++ b/master/src/MainWindow.ui @@ -35,18 +35,18 @@ 0
- - + + - 790 + 890 570 69 37 - Adjust optimal size + Adjust size of computer icons automatically Auto @@ -55,11 +55,14 @@ :/master/zoom-fit-best.png:/master/zoom-fit-best.png + + true + - 660 + 760 580 111 25 @@ -81,60 +84,8 @@ 150 - Qt::Horizontal - - - - - - 20 - 570 - 227 - 37 - - - - Locations && computers - - - - :/master/applications-education.png:/master/applications-education.png - - - true - - - Qt::ToolButtonTextBesideIcon - - - buttonGroup - - - - - - 260 - 570 - 158 - 37 - - - - Screenshots - - - - :/master/camera-photo.png:/master/camera-photo.png - - - true - - - Qt::ToolButtonTextBesideIcon + Qt::Orientation::Horizontal - - buttonGroup - @@ -152,7 +103,7 @@ - 1230 + 1260 570 71 37 @@ -172,7 +123,7 @@ - 840 + 940 570 99 30 @@ -182,7 +133,7 @@ - 480 + 470 570 113 38 @@ -195,8 +146,8 @@ - 610 - 570 + 620 + 560 31 30 @@ -211,7 +162,7 @@ - 1100 + 1110 570 69 37 @@ -225,17 +176,19 @@ :/master/align-grid.png:/master/align-grid.png - + - 960 + 1010 570 69 37 - Use custom computer arrangement + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. @@ -248,7 +201,7 @@ - 1110 + 1170 570 99 30 @@ -258,7 +211,7 @@ - 580 + 590 570 69 37 @@ -275,6 +228,130 @@ true + + + + 0 + 0 + 702 + 39 + + + + + 0 + + + QLayout::SizeConstraint::SetMinimumSize + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Locations && computers + + + + :/master/computers.png:/master/computers.png + + + true + + + Qt::ToolButtonStyle::ToolButtonTextBesideIcon + + + buttonGroup + + + + + + + Screenshots + + + + :/master/camera-photo.png:/master/camera-photo.png + + + true + + + Qt::ToolButtonStyle::ToolButtonTextBesideIcon + + + buttonGroup + + + + + + + Slideshow + + + + :/master/computer-slideshow.png:/master/computer-slideshow.png + + + true + + + Qt::ToolButtonStyle::ToolButtonTextBesideIcon + + + + + + + Spotlight + + + + :/master/spotlight.png:/master/spotlight.png + + + true + + + Qt::ToolButtonStyle::ToolButtonTextBesideIcon + + + + + + + + + 670 + 570 + 69 + 37 + + + + Only show computers with logged on users + + + + :/core/user-group-new.png:/core/user-group-new.png + + + true + + @@ -293,17 +370,17 @@ - - MainToolBar - QToolBar -
MainToolBar.h
-
ComputerMonitoringWidget - QWidget + QListView
ComputerMonitoringWidget.h
1
+ + MainToolBar + QToolBar +
MainToolBar.h
+
@@ -327,7 +404,7 @@ - useCustomComputerArrangementButton + useCustomComputerPositionsButton toggled(bool) alignComputersButton setEnabled(bool) diff --git a/master/src/NetworkObjectFilterProxyModel.cpp b/master/src/NetworkObjectFilterProxyModel.cpp index bf10177fd..0d698ac1e 100644 --- a/master/src/NetworkObjectFilterProxyModel.cpp +++ b/master/src/NetworkObjectFilterProxyModel.cpp @@ -1,7 +1,7 @@ /* * NetworkObjectFilterProxyModel.cpp - implementation of NetworkObjectFilterProxyModel * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,10 +31,7 @@ NetworkObjectFilterProxyModel::NetworkObjectFilterProxyModel( QObject* parent ) : - QSortFilterProxyModel( parent ), - m_groupList(), - m_computerExcludeList(), - m_excludeEmptyGroups( false ) + QSortFilterProxyModel( parent ) { #if defined(QT_TESTLIB_LIB) && QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) new QAbstractItemModelTester( this, QAbstractItemModelTester::FailureReportingMode::Warning, this ); @@ -61,30 +58,110 @@ void NetworkObjectFilterProxyModel::setComputerExcludeFilter( const QStringList& +void NetworkObjectFilterProxyModel::setEmptyGroupsExcluded(bool enabled) +{ + beginResetModel(); + m_excludeEmptyGroups = enabled; + endResetModel(); +} + + +void NetworkObjectFilterProxyModel::setComputersExcluded(bool enabled) +{ + beginResetModel(); + m_excludeComputers = enabled; + endResetModel(); +} + + + bool NetworkObjectFilterProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const { - if( sourceParent.isValid() ) + const auto index = sourceModel()->index(sourceRow, 0, sourceParent); + if (filterAcceptsRowRecursive(index)) + { + return true; + } + + const auto objectType = NetworkObject::Type(sourceModel()->data(index, NetworkObjectModel::TypeRole).toInt()); + if (NetworkObject::isContainer(objectType)) + { + return parentContainerAccepted(index); + } + + return false; +} + + + +bool NetworkObjectFilterProxyModel::filterAcceptsRowRecursive(const QModelIndex& index) const +{ + const auto objectType = NetworkObject::Type(sourceModel()->data(index, NetworkObjectModel::TypeRole).toInt()); + + if (objectType == NetworkObject::Type::Host) { + if (m_excludeComputers) + { + return false; + } + + const auto parentAccepted = m_groupList.isEmpty() || + parentContainerAccepted(index.parent()); + if (parentAccepted == false) + { + return false; + } + if( m_computerExcludeList.isEmpty() ) { return true; } - const auto hostAddress = sourceModel()->data( sourceModel()->index( sourceRow, 0, sourceParent ), - NetworkObjectModel::HostAddressRole ).toString(); + const auto hostAddress = sourceModel()->data(index, NetworkObjectModel::HostAddressRole).toString(); return m_computerExcludeList.contains( hostAddress, Qt::CaseInsensitive ) == false; } - - if( m_excludeEmptyGroups && sourceModel()->rowCount( sourceModel()->index( sourceRow, 0 ) ) == 0 ) + else if (NetworkObject::isContainer(objectType)) { - return false; - } + if (sourceModel()->canFetchMore(index)) + { + sourceModel()->fetchMore(index); + } - if( m_groupList.isEmpty() ) - { - return true; + const auto rows = sourceModel()->rowCount(index); + + if (m_excludeEmptyGroups && rows == 0) + { + return false; + } + + if (m_groupList.isEmpty()) + { + return true; + } + + for (int i = 0; i < rows; ++i) + { + const auto rowIndex = sourceModel()->index(i, 0, index); + const auto rowObjectType = NetworkObject::Type(sourceModel()->data(rowIndex, NetworkObjectModel::TypeRole).toInt()); + + if (NetworkObject::isContainer(rowObjectType) && filterAcceptsRowRecursive(rowIndex)) + { + return true; + } + } + + return m_groupList.contains(sourceModel()->data(index).toString()); } - return m_groupList.contains( sourceModel()->data( sourceModel()->index( sourceRow, 0 ) ).toString() ); + return true; +} + + + +bool NetworkObjectFilterProxyModel::parentContainerAccepted(const QModelIndex& index) const +{ + return index.isValid() && + (m_groupList.contains(sourceModel()->data(index).toString()) || + parentContainerAccepted(index.parent())); } diff --git a/master/src/NetworkObjectFilterProxyModel.h b/master/src/NetworkObjectFilterProxyModel.h index d0e7bd9a8..e585ba94c 100644 --- a/master/src/NetworkObjectFilterProxyModel.h +++ b/master/src/NetworkObjectFilterProxyModel.h @@ -1,7 +1,7 @@ /* * NetworkObjectFilterProxyModel.h - header file for NetworkObjectFilterProxyModel * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -34,17 +34,19 @@ class NetworkObjectFilterProxyModel : public QSortFilterProxyModel void setGroupFilter( const QStringList& groupList ); void setComputerExcludeFilter( const QStringList& computerExcludeList ); - void setEmptyGroupsExcluded( bool enabled ) - { - m_excludeEmptyGroups = enabled; - } + void setEmptyGroupsExcluded(bool enabled); + void setComputersExcluded(bool enabled); protected: bool filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const override; private: + bool filterAcceptsRowRecursive(const QModelIndex& index) const; + bool parentContainerAccepted(const QModelIndex& index) const; + QStringList m_groupList; QStringList m_computerExcludeList; - bool m_excludeEmptyGroups; + bool m_excludeEmptyGroups = false; + bool m_excludeComputers = false; }; diff --git a/master/src/NetworkObjectOverlayDataModel.cpp b/master/src/NetworkObjectOverlayDataModel.cpp index e3b10c159..961f7f9c5 100644 --- a/master/src/NetworkObjectOverlayDataModel.cpp +++ b/master/src/NetworkObjectOverlayDataModel.cpp @@ -1,7 +1,7 @@ /* * NetworkObjectOverlayDataModel.cpp - overlay model for NetworkObjectModel to provide extra data * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,8 +31,7 @@ #endif -NetworkObjectOverlayDataModel::NetworkObjectOverlayDataModel( const QString& overlayDataHeader, - QObject *parent ) : +NetworkObjectOverlayDataModel::NetworkObjectOverlayDataModel(const QStringList& overlayDataHeaders, QObject *parent) : KExtraColumnsProxyModel( parent ), m_overlayDataRole( Qt::DisplayRole ) { @@ -41,43 +40,125 @@ NetworkObjectOverlayDataModel::NetworkObjectOverlayDataModel( const QString& ove setSourceModel( new QStandardItemModel( this ) ); new QAbstractItemModelTester( this, QAbstractItemModelTester::FailureReportingMode::Warning, this ); #endif - appendColumn( overlayDataHeader ); + for (const auto& header : overlayDataHeaders) + { + appendColumn(header); + } +} + + + +QVariant NetworkObjectOverlayDataModel::data(const QModelIndex& index, int role) const +{ + if (index.column() > 0) + { + return KExtraColumnsProxyModel::data(index, role); + } + + const auto networkObjectUid = lookupNetworkObjectId(index); + if (m_overlayData.contains(networkObjectUid)) + { + const auto& overlayData = std::as_const(m_overlayData)[networkObjectUid]; + if (overlayData.contains(role)) + { + const auto value = std::as_const(overlayData)[role]; + if (value.isValid()) + { + return value; + } + } + } + + return KExtraColumnsProxyModel::data(index, role); +} + + + +bool NetworkObjectOverlayDataModel::setData(const QModelIndex& index, const QVariant& value, int role) +{ + if (index.column() > 0) + { + return KExtraColumnsProxyModel::setData(index, value, role); + } + + const auto networkObjectUid = lookupNetworkObjectId(index); + if (networkObjectUid.isNull()) + { + return false; + } + + auto& overlayData = m_overlayData[networkObjectUid]; // clazy:exclude=detaching-member + if (overlayData.value(role) != value) + { + overlayData[role] = value; + Q_EMIT dataChanged(index, index, {role}); + } + + return true; } QVariant NetworkObjectOverlayDataModel::extraColumnData(const QModelIndex &parent, int row, int extraColumn, int role) const { - if( extraColumn != 0 || role != m_overlayDataRole ) + if (role != m_overlayDataRole) { - return QVariant(); + return {}; } - NetworkObject::Uid networkObjectUid = data( index( row, 0, parent ), NetworkObjectModel::UidRole ).toUuid(); + const auto networkObjectUid = lookupNetworkObjectId(parent, row); - if( networkObjectUid.isNull() == false && m_overlayData.contains( networkObjectUid ) ) + if( networkObjectUid.isNull() == false && m_extraColumnsData.contains( networkObjectUid ) ) { - return m_overlayData[networkObjectUid]; + return m_extraColumnsData[networkObjectUid].value(extraColumn); } - return QVariant(); + return {}; } + bool NetworkObjectOverlayDataModel::setExtraColumnData( const QModelIndex &parent, int row, int extraColumn, const QVariant &data, int role) { - if( extraColumn != 0 || role != m_overlayDataRole ) + if (role != m_overlayDataRole) { return false; } - const auto networkObjectUid = KExtraColumnsProxyModel::data( index( row, 0, parent ), NetworkObjectModel::UidRole ).toUuid(); + const auto networkObjectUid = lookupNetworkObjectId(parent, row); + auto& rowData = m_extraColumnsData[networkObjectUid]; // clazy:exclude=detaching-member - if( m_overlayData[networkObjectUid] != data ) + if (extraColumn >= rowData.count() || + rowData[extraColumn] != data) { - m_overlayData[networkObjectUid] = data; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + rowData.resize(extraColumn+1); +#else + std::fill_n(std::back_inserter(rowData), extraColumn + 1 - rowData.size(), QVariant{}); +#endif + rowData[extraColumn] = data; + m_extraColumnsData[networkObjectUid] = rowData; extraColumnDataChanged( parent, row, extraColumn, { m_overlayDataRole } ); } return true; } + + + +NetworkObject::Uid NetworkObjectOverlayDataModel::lookupNetworkObjectId(const QModelIndex& index) const +{ + if (index.isValid() == false) + { + return {}; + } + + return KExtraColumnsProxyModel::data(index, NetworkObjectModel::UidRole).toUuid(); +} + + + +NetworkObject::Uid NetworkObjectOverlayDataModel::lookupNetworkObjectId(const QModelIndex& parent, int row) const +{ + return lookupNetworkObjectId(index(row, 0, parent)); +} diff --git a/master/src/NetworkObjectOverlayDataModel.h b/master/src/NetworkObjectOverlayDataModel.h index 6486c24f0..d8460ef7c 100644 --- a/master/src/NetworkObjectOverlayDataModel.h +++ b/master/src/NetworkObjectOverlayDataModel.h @@ -1,7 +1,7 @@ /* * NetworkObjectOverlayDataModel.h - overlay model for NetworkObjectModel to provide extra data * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,23 +24,31 @@ #pragma once -#include "kextracolumnsproxymodel.h" +#include "KExtraColumnsProxyModel.h" #include "NetworkObject.h" class NetworkObjectOverlayDataModel : public KExtraColumnsProxyModel { Q_OBJECT public: - explicit NetworkObjectOverlayDataModel( const QString& overlayDataHeader, - QObject *parent = nullptr ); + explicit NetworkObjectOverlayDataModel(const QStringList& overlayDataHeaders, + QObject *parent = nullptr); - QVariant extraColumnData( const QModelIndex &parent, int row, int extraColumn, int role ) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - bool setExtraColumnData( const QModelIndex &parent, int row, int extraColumn, const QVariant &data, int role ) override; + bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::DisplayRole) override; + + QVariant extraColumnData(const QModelIndex& parent, int row, int extraColumn, int role = Qt::DisplayRole) const override; + + bool setExtraColumnData(const QModelIndex& parent, int row, int extraColumn, const QVariant& data, int role = Qt::DisplayRole) override; private: + NetworkObject::Uid lookupNetworkObjectId(const QModelIndex& index) const; + NetworkObject::Uid lookupNetworkObjectId(const QModelIndex& parent, int row) const; + int m_overlayDataRole; - QHash m_overlayData; + QHash> m_overlayData; + QHash> m_extraColumnsData; }; diff --git a/master/src/NetworkObjectTreeModel.cpp b/master/src/NetworkObjectTreeModel.cpp index 5f3fe0593..1b9ab3f0f 100644 --- a/master/src/NetworkObjectTreeModel.cpp +++ b/master/src/NetworkObjectTreeModel.cpp @@ -1,7 +1,7 @@ /* * NetworkObjectTreeModel.cpp - data model returning hierarchically grouped network objects * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -112,7 +112,7 @@ QVariant NetworkObjectTreeModel::headerData( int section, Qt::Orientation orient return tr( "Locations/Computers" ); } - return QVariant(); + return {}; } @@ -136,9 +136,9 @@ QVariant NetworkObjectTreeModel::data( const QModelIndex& index, int role ) cons case UidRole: return networkObject.uid(); case NameRole: return networkObject.name(); case TypeRole: return QVariant::fromValue( networkObject.type() ); - case HostAddressRole: return networkObject.hostAddress(); - case MacAddressRole: return networkObject.macAddress(); - case DirectoryAddressRole: return networkObject.directoryAddress(); + case HostAddressRole: return networkObject.property( NetworkObject::Property::HostAddress ); + case MacAddressRole: return networkObject.property( NetworkObject::Property::MacAddress ); + case DirectoryAddressRole: return networkObject.property( NetworkObject::Property::DirectoryAddress ); default: break; } @@ -200,9 +200,35 @@ void NetworkObjectTreeModel::fetchMore( const QModelIndex& parent ) -void NetworkObjectTreeModel::beginInsertObjects( const NetworkObject& parent, int index, int count ) +Qt::ItemFlags NetworkObjectTreeModel::flags( const QModelIndex& index ) const +{ + const auto defaultFlags = NetworkObjectModel::flags( index ); + + if( index.isValid() == false ) + { + return defaultFlags; + } + + const auto& networkObject = object( index ); + + switch( networkObject.type() ) + { + case NetworkObject::Type::None: + case NetworkObject::Type::Host: + case NetworkObject::Type::Label: + return defaultFlags | Qt::ItemNeverHasChildren; + default: + break; + } + + return defaultFlags; +} + + + +void NetworkObjectTreeModel::beginInsertObjects(NetworkObject::ModelId parentId, int index, int count) { - beginInsertRows( objectIndex( parent.modelId() ), index, index+count-1 ); + beginInsertRows(objectIndex(parentId), index, index+count-1); } @@ -214,9 +240,9 @@ void NetworkObjectTreeModel::endInsertObjects() -void NetworkObjectTreeModel::beginRemoveObjects( const NetworkObject& parent, int index, int count ) +void NetworkObjectTreeModel::beginRemoveObjects(NetworkObject::ModelId parentId, int index, int count) { - beginRemoveRows( objectIndex( parent.modelId() ), index, index+count-1 ); + beginRemoveRows(objectIndex(parentId), index, index+count-1); } @@ -228,11 +254,11 @@ void NetworkObjectTreeModel::endRemoveObjects() -void NetworkObjectTreeModel::updateObject( const NetworkObject& parent, int row ) +void NetworkObjectTreeModel::updateObject(NetworkObject::ModelId parentId, int row) { - const auto index = createIndex( row, 0, parent.modelId() ); + const auto index = createIndex(row, 0, parentId); - emit dataChanged( index, index ); + Q_EMIT dataChanged( index, index ); } diff --git a/master/src/NetworkObjectTreeModel.h b/master/src/NetworkObjectTreeModel.h index f68133691..0462f50c7 100644 --- a/master/src/NetworkObjectTreeModel.h +++ b/master/src/NetworkObjectTreeModel.h @@ -1,7 +1,7 @@ /* * NetworkObjectTreeModel.h - data model returning hierarchically grouped network objects * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -49,15 +49,16 @@ class NetworkObjectTreeModel : public NetworkObjectModel bool canFetchMore( const QModelIndex& parent ) const override; void fetchMore( const QModelIndex& parent ) override; + Qt::ItemFlags flags( const QModelIndex& index ) const override; private: - void beginInsertObjects( const NetworkObject& parent, int index, int count ); + void beginInsertObjects(NetworkObject::ModelId parentId, int index, int count); void endInsertObjects(); - void beginRemoveObjects( const NetworkObject& parent, int index, int count ); + void beginRemoveObjects(NetworkObject::ModelId parentId, int index, int count); void endRemoveObjects(); - void updateObject( const NetworkObject& parent, int index ); + void updateObject(NetworkObject::ModelId parent, int index ); QModelIndex objectIndex( NetworkObject::ModelId object, int column = 0 ) const; const NetworkObject& object( const QModelIndex& index ) const; diff --git a/master/src/ScreenshotManagementPanel.cpp b/master/src/ScreenshotManagementPanel.cpp index 00ec92b55..725df1773 100644 --- a/master/src/ScreenshotManagementPanel.cpp +++ b/master/src/ScreenshotManagementPanel.cpp @@ -1,7 +1,7 @@ /* * ScreenshotManagementPanel.cpp - implementation of screenshot management view * - * Copyright (c) 2004-2019 Tobias Junghans + * Copyright (c) 2004-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,8 +23,8 @@ */ #include -#include -#include +#include +#include #include "Filesystem.h" #include "ScreenshotManagementPanel.h" @@ -37,19 +37,23 @@ ScreenshotManagementPanel::ScreenshotManagementPanel( QWidget *parent ) : QWidget( parent ), - ui( new Ui::ScreenshotManagementPanel ), - m_fsModel( this ) + ui( new Ui::ScreenshotManagementPanel ) { ui->setupUi( this ); VeyonCore::filesystem().ensurePathExists( VeyonCore::config().screenshotDirectory() ); - m_fsModel.setNameFilters( { QStringLiteral("*.png") } ); - m_fsModel.setFilter( QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Files ); - m_fsModel.setRootPath( VeyonCore::filesystem().expandPath( VeyonCore::config().screenshotDirectory() ) ); + m_fsWatcher.addPath( VeyonCore::filesystem().screenshotDirectoryPath() ); + connect( &m_fsWatcher, &QFileSystemWatcher::directoryChanged, this, &ScreenshotManagementPanel::updateModel ); - ui->list->setModel( &m_fsModel ); - ui->list->setRootIndex( m_fsModel.index( m_fsModel.rootPath() ) ); + m_reloadTimer.setInterval( FsModelResetDelay ); + m_reloadTimer.setSingleShot( true ); + + connect( &m_reloadTimer, &QTimer::timeout, this, &ScreenshotManagementPanel::updateModel ); + connect( &VeyonCore::filesystem(), &Filesystem::screenshotDirectoryModified, + &m_reloadTimer, QOverload<>::of(&QTimer::start) ); + + ui->list->setModel( &m_model ); connect( ui->list->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &ScreenshotManagementPanel::updateScreenshot ); @@ -57,6 +61,13 @@ ScreenshotManagementPanel::ScreenshotManagementPanel( QWidget *parent ) : connect( ui->showBtn, &QPushButton::clicked, this, &ScreenshotManagementPanel::showScreenshot ); connect( ui->deleteBtn, &QPushButton::clicked, this, &ScreenshotManagementPanel::deleteScreenshot ); + + if (VeyonCore::useDarkMode()) + { + ui->showBtn->setIcon(QIcon(QStringLiteral(":/core/edit-find-dark.png"))); + } + + updateModel(); } @@ -92,19 +103,41 @@ void ScreenshotManagementPanel::resizeEvent( QResizeEvent* event ) -void ScreenshotManagementPanel::updateScreenshot( const QModelIndex &idx ) +void ScreenshotManagementPanel::updateModel() +{ + const auto currentFile = m_model.data( ui->list->currentIndex(), Qt::DisplayRole ).toString(); + + const QDir dir{ VeyonCore::filesystem().screenshotDirectoryPath() }; + const auto files = dir.entryList( { QStringLiteral("*.png") }, + QDir::Filter::Files, QDir::SortFlag::Name ); + + m_model.setStringList( files ); + + ui->list->setCurrentIndex( m_model.index( files.indexOf( currentFile ) ) ); +} + + + +QString ScreenshotManagementPanel::filePath( const QModelIndex& index ) const +{ + return VeyonCore::filesystem().screenshotDirectoryPath() + QDir::separator() + m_model.data( index, Qt::DisplayRole ).toString(); +} + + + +void ScreenshotManagementPanel::updateScreenshot( const QModelIndex& index ) { - setPreview( Screenshot( m_fsModel.filePath( idx ) ) ); + setPreview( Screenshot( filePath( index ) ) ); } -void ScreenshotManagementPanel::screenshotDoubleClicked( const QModelIndex &idx ) +void ScreenshotManagementPanel::screenshotDoubleClicked( const QModelIndex& index ) { auto screenshotWindow = new QLabel; - screenshotWindow->setPixmap( m_fsModel.filePath( idx ) ); + screenshotWindow->setPixmap( filePath( index ) ); screenshotWindow->setScaledContents( true ); - screenshotWindow->setWindowTitle( m_fsModel.fileName( idx ) ); + screenshotWindow->setWindowTitle( QFileInfo( filePath( index ) ).fileName() ); screenshotWindow->setAttribute( Qt::WA_DeleteOnClose, true ); screenshotWindow->showNormal(); } @@ -123,8 +156,19 @@ void ScreenshotManagementPanel::showScreenshot() void ScreenshotManagementPanel::deleteScreenshot() { - if( ui->list->currentIndex().isValid() ) + const auto selection = ui->list->selectionModel()->selectedIndexes(); + if( selection.size() > 1 && + QMessageBox::question( this, + tr("Screenshot"), + tr("Do you really want to delete all selected screenshots?") ) != QMessageBox::Yes ) + { + return; + } + + for( const auto& index : selection ) { - m_fsModel.remove( ui->list->currentIndex() ); + QFile::remove( filePath( index ) ); } + + updateModel(); } diff --git a/master/src/ScreenshotManagementPanel.h b/master/src/ScreenshotManagementPanel.h index 1ca98edcc..9f1e8c0a7 100644 --- a/master/src/ScreenshotManagementPanel.h +++ b/master/src/ScreenshotManagementPanel.h @@ -1,7 +1,7 @@ /* * ScreenshotManagementPanel.h - declaration of screenshot management view * - * Copyright (c) 2004-2019 Tobias Junghans + * Copyright (c) 2004-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,7 +24,9 @@ #pragma once -#include +#include +#include +#include #include class QModelIndex; @@ -38,7 +40,7 @@ class ScreenshotManagementPanel : public QWidget { Q_OBJECT public: - explicit ScreenshotManagementPanel( QWidget *parent ); + explicit ScreenshotManagementPanel( QWidget *parent = nullptr ); ~ScreenshotManagementPanel() override; void setPreview( const Screenshot& screenshot ); @@ -47,13 +49,23 @@ class ScreenshotManagementPanel : public QWidget void resizeEvent( QResizeEvent* event ) override; private: - void updateScreenshot( const QModelIndex &idx ); - void screenshotDoubleClicked( const QModelIndex &idx ); + void updateModel(); + + QString filePath( const QModelIndex& index ) const; + + void updateScreenshot( const QModelIndex& index ); + void screenshotDoubleClicked( const QModelIndex& index ); void showScreenshot(); void deleteScreenshot(); Ui::ScreenshotManagementPanel* ui; - QFileSystemModel m_fsModel; + + QStringListModel m_model{this}; + QFileSystemWatcher m_fsWatcher{this}; + + QTimer m_reloadTimer{this}; + + static constexpr auto FsModelResetDelay = 1000; } ; diff --git a/master/src/ScreenshotManagementPanel.ui b/master/src/ScreenshotManagementPanel.ui index c3249f1c0..7832c7872 100644 --- a/master/src/ScreenshotManagementPanel.ui +++ b/master/src/ScreenshotManagementPanel.ui @@ -8,6 +8,12 @@ All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::ExtendedSelection +
@@ -32,7 +38,6 @@ - 75 true @@ -51,7 +56,6 @@ - 75 true @@ -64,7 +68,6 @@ - 75 true @@ -80,7 +83,6 @@ - 75 true @@ -99,15 +101,9 @@ Show - + :/core/edit-find.png:/core/edit-find.png - - - 22 - 22 - - @@ -119,12 +115,6 @@ :/core/edit-delete.png:/core/edit-delete.png - - - 22 - 22 - - @@ -149,7 +139,6 @@ - diff --git a/master/src/SlideshowModel.cpp b/master/src/SlideshowModel.cpp new file mode 100644 index 000000000..ba0f83e0d --- /dev/null +++ b/master/src/SlideshowModel.cpp @@ -0,0 +1,202 @@ +/* + * SlideshowModel.cpp - implementation of SlideshowModel + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "ComputerListModel.h" +#include "SlideshowModel.h" + + +SlideshowModel::SlideshowModel( QAbstractItemModel* sourceModel, QObject* parent ) : + QSortFilterProxyModel( parent ) +{ + setSourceModel( sourceModel ); + + connect( sourceModel, &QAbstractItemModel::rowsInserted, this, + [this]( const QModelIndex &parent, int start, int end ) + { + Q_UNUSED(parent) + Q_UNUSED(end) + if( start <= m_currentRow ) + { + showNext(); + } + } ); + connect( sourceModel, &QAbstractItemModel::rowsRemoved, this, + [this]( const QModelIndex &parent, int start, int end ) + { + Q_UNUSED(parent) + Q_UNUSED(end) + if( start <= m_currentRow ) + { + showPrevious(); + } + } ); + + connect( &m_timer, &QTimer::timeout, this, &SlideshowModel::showNext ); +} + + + +void SlideshowModel::setIconSize( QSize size ) +{ + m_iconSize = size; + + Q_EMIT dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ), { Qt::DisplayRole, Qt::DecorationRole } ); +} + + + +QVariant SlideshowModel::data( const QModelIndex& index, int role ) const +{ + if( m_currentControlInterface.isNull() ) + { + return {}; + } + + const auto sourceIndex = mapToSource( index ); + if( sourceIndex.isValid() == false ) + { + return {}; + } + + if( role == Qt::DecorationRole ) + { + auto framebuffer = sourceModel()->data(sourceIndex, ComputerListModel::FramebufferRole).value(); + if (framebuffer.isNull()) + { + framebuffer = sourceModel()->data(sourceIndex, Qt::DecorationRole).value(); + } + + return framebuffer.scaled(m_iconSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); + } + + return QSortFilterProxyModel::data( index, role ); +} + + + +void SlideshowModel::setRunning( bool running, int duration ) +{ + m_timer.stop(); + m_timer.setInterval( duration ); + + if( running ) + { + m_timer.start(); + } +} + + + +void SlideshowModel::showPrevious() +{ + auto valid = false; + + for( int i = 0; i < sourceModel()->rowCount(); ++i ) + { + setCurrentRow( m_currentRow - 1 ); + + if( m_currentControlInterface && + m_currentControlInterface->state() == ComputerControlInterface::State::Connected && + m_currentControlInterface->hasValidFramebuffer() ) + { + valid = true; + break; + } + } + + if( valid == false ) + { + m_currentRow = 0; + m_currentControlInterface.clear(); + } + + if( m_timer.isActive() ) + { + m_timer.stop(); + m_timer.start(); + } +} + + + +void SlideshowModel::showNext() +{ + auto valid = false; + + for( int i = 0; i < sourceModel()->rowCount(); ++i ) + { + setCurrentRow( m_currentRow + 1 ); + + if( m_currentControlInterface && + m_currentControlInterface->state() == ComputerControlInterface::State::Connected && + m_currentControlInterface->hasValidFramebuffer() ) + { + valid = true; + break; + } + } + + if( valid == false ) + { + m_currentRow = 0; + m_currentControlInterface.clear(); + } + + if( m_timer.isActive() ) + { + m_timer.stop(); + m_timer.start(); + } +} + + + +bool SlideshowModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const +{ + return sourceRow < sourceModel()->rowCount() && + m_currentControlInterface == sourceModel()->data( sourceModel()->index( sourceRow, 0, sourceParent ), + ComputerListModel::ControlInterfaceRole ) + .value(); +} + + + +void SlideshowModel::setCurrentRow( int row ) +{ + if( sourceModel()->rowCount() > 0 ) + { + m_currentRow = qMax( 0, row ) % qMax( 1, sourceModel()->rowCount() ); + + m_currentControlInterface = sourceModel()->data( sourceModel()->index( m_currentRow, 0 ), + ComputerListModel::ControlInterfaceRole ) + .value(); + } + else + { + m_currentRow = 0; + m_currentControlInterface.clear(); + } + + invalidateFilter(); +} diff --git a/master/src/ComputerSortFilterProxyModel.h b/master/src/SlideshowModel.h similarity index 61% rename from master/src/ComputerSortFilterProxyModel.h rename to master/src/SlideshowModel.h index 34a38005a..0e68f26a8 100644 --- a/master/src/ComputerSortFilterProxyModel.h +++ b/master/src/SlideshowModel.h @@ -1,7 +1,7 @@ /* - * ComputerSortFilterProxyModel.h - header file for ComputerSortFilterProxyModel + * SlideshowModel.h - header file for SlideshowModel * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2020-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,34 +25,36 @@ #pragma once #include +#include #include "ComputerControlInterface.h" -class ComputerSortFilterProxyModel : public QSortFilterProxyModel +class SlideshowModel : public QSortFilterProxyModel { Q_OBJECT public: - explicit ComputerSortFilterProxyModel( QObject* parent ); + SlideshowModel( QAbstractItemModel* sourceModel, QObject* parent = nullptr ); - int stateRole() const - { - return m_stateRole; - } + void setIconSize( QSize size ); - void setStateRole( int role ); + QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override; - ComputerControlInterface::State stateFilter() const - { - return m_stateFilter; - } - - void setStateFilter( ComputerControlInterface::State state ); +public: + void setRunning( bool running, int duration ); + void showPrevious(); + void showNext(); protected: bool filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const override; private: - int m_stateRole; - ComputerControlInterface::State m_stateFilter; + void setCurrentRow( int row ); + + QSize m_iconSize; + + QTimer m_timer; + + int m_currentRow{0}; + ComputerControlInterface::Pointer m_currentControlInterface; }; diff --git a/master/src/SlideshowPanel.cpp b/master/src/SlideshowPanel.cpp new file mode 100644 index 000000000..3114efe46 --- /dev/null +++ b/master/src/SlideshowPanel.cpp @@ -0,0 +1,126 @@ +/* + * SlideshowPanel.cpp - implementation of SlideshowPanel + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "ComputerMonitoringModel.h" +#include "ComputerMonitoringWidget.h" +#include "SlideshowModel.h" +#include "SlideshowPanel.h" +#include "UserConfig.h" + +#include "ui_SlideshowPanel.h" + + +SlideshowPanel::SlideshowPanel( UserConfig& config, ComputerMonitoringWidget* computerMonitoringWidget, QWidget *parent ) : + QWidget( parent ), + ui( new Ui::SlideshowPanel ), + m_config( config ), + m_model( new SlideshowModel( computerMonitoringWidget->dataModel(), this ) ) +{ + ui->setupUi( this ); + + ui->monitoringWidget->setAutoAdjustIconSize( false ); + ui->monitoringWidget->setUseCustomComputerPositions( false ); + ui->monitoringWidget->setAcceptDrops( false ); + ui->monitoringWidget->setDragEnabled( false ); + ui->monitoringWidget->setIgnoreWheelEvent( true ); + ui->monitoringWidget->setSelectionMode( QListView::SingleSelection ); + ui->monitoringWidget->setModel( m_model ); + + if (VeyonCore::useDarkMode()) + { + QIcon startStopIcon; + startStopIcon.addPixmap(QPixmap(QStringLiteral(":/core/media-playback-pause-dark.png")), QIcon::Mode::Normal, QIcon::State::On); + startStopIcon.addPixmap(QPixmap(QStringLiteral(":/core/media-playback-start-dark.png")), QIcon::Mode::Normal, QIcon::State::Off); + ui->startStopButton->setIcon(startStopIcon); + ui->showPreviousButton->setIcon(QIcon(QStringLiteral(":/core/go-previous-dark.png"))); + ui->showNextButton->setIcon(QIcon(QStringLiteral(":/core/go-next-dark.png"))); + ui->viewInSeparateWindowButton->setIcon(QIcon(QStringLiteral(":/core/view-fullscreen-dark.png"))); + } + + connect( ui->startStopButton, &QAbstractButton::toggled, this, &SlideshowPanel::updateDuration ); + connect( ui->durationSlider, &QSlider::valueChanged, this, &SlideshowPanel::updateDuration ); + + connect( ui->showPreviousButton, &QAbstractButton::clicked, m_model, &SlideshowModel::showPrevious ); + connect( ui->showNextButton, &QAbstractButton::clicked, m_model, &SlideshowModel::showNext ); + + connect(ui->viewInSeparateWindowButton, &QToolButton::toggled, this, &SlideshowPanel::switchViewMode); + + ui->durationSlider->setValue( m_config.slideshowDuration() ); + + updateDuration(); +} + + + +SlideshowPanel::~SlideshowPanel() +{ + delete ui; +} + + + +void SlideshowPanel::resizeEvent( QResizeEvent* event ) +{ + static constexpr auto ExtraMargin = 10; + + const auto spacing = ui->monitoringWidget->spacing(); + const auto labelHeight = ui->monitoringWidget->fontMetrics().height(); + + ui->monitoringWidget->setIconSize( { ui->monitoringWidget->width() - ExtraMargin - spacing * 2, + ui->monitoringWidget->height() - ExtraMargin - labelHeight - spacing * 2 } ); + + m_model->setIconSize( ui->monitoringWidget->iconSize() ); + + QWidget::resizeEvent( event ); +} + + + +void SlideshowPanel::updateDuration() +{ + const int duration = ui->durationSlider->value(); + + m_model->setRunning( ui->startStopButton->isChecked(), duration ); + m_config.setSlideshowDuration( duration ); + + ui->durationLabel->setText( QStringLiteral("%1 s").arg( duration / 1000 ) ); +} + + + +void SlideshowPanel::switchViewMode() +{ + if (ui->viewInSeparateWindowButton->isChecked()) + { + m_originalParent = parentWidget(); + setParent(nullptr); + setWindowTitle(tr("%1 Master – Slideshow").arg(VeyonCore::applicationName())); + showMaximized(); + } + else + { + setParent(m_originalParent); + m_originalParent = nullptr; + } +} diff --git a/master/src/SlideshowPanel.h b/master/src/SlideshowPanel.h new file mode 100644 index 000000000..1e0e8170f --- /dev/null +++ b/master/src/SlideshowPanel.h @@ -0,0 +1,60 @@ +/* + * SlideshowPanel.h - declaration of SlideshowPanel + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +class ComputerMonitoringWidget; +class SlideshowModel; +class UserConfig; + +namespace Ui { +class SlideshowPanel; +} + +class SlideshowPanel : public QWidget +{ + Q_OBJECT +public: + explicit SlideshowPanel( UserConfig& config, ComputerMonitoringWidget* computerMonitoringWidget, + QWidget* parent = nullptr ); + ~SlideshowPanel() override; + + static constexpr auto DefaultDuration = 3000; + +protected: + void resizeEvent( QResizeEvent* event ) override; + +private: + void updateDuration(); + void switchViewMode(); + + Ui::SlideshowPanel* ui; + + UserConfig& m_config; + SlideshowModel* m_model; + QWidget* m_originalParent = nullptr; + +} ; diff --git a/master/src/SlideshowPanel.ui b/master/src/SlideshowPanel.ui new file mode 100644 index 000000000..36b006bf1 --- /dev/null +++ b/master/src/SlideshowPanel.ui @@ -0,0 +1,164 @@ + + + SlideshowPanel + + + + :/master/computer-slideshow.png:/master/computer-slideshow.png + + + + 0 + + + 0 + + + 4 + + + 0 + + + 0 + + + + + + + + + 4 + + + 4 + + + 4 + + + + + Previous + + + Previous + + + + :/core/go-previous.png:/core/go-previous.png + + + + + + + Start/pause + + + + :/core/media-playback-start.png + :/core/media-playback-pause.png:/core/media-playback-start.png + + + true + + + true + + + + + + + Next + + + + :/core/go-next.png:/core/go-next.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Duration: + + + + + + + 1000 + + + 10000 + + + 1000 + + + 1000 + + + 3000 + + + Qt::Horizontal + + + + + + + + + + + + + + View in separate window + + + + :/core/view-fullscreen.png:/core/view-fullscreen.png + + + true + + + + + + + + + + + ComputerMonitoringWidget + QListView +
ComputerMonitoringWidget.h
+ 1 +
+
+ + + + + +
diff --git a/master/src/SpotlightModel.cpp b/master/src/SpotlightModel.cpp new file mode 100644 index 000000000..a0501adcb --- /dev/null +++ b/master/src/SpotlightModel.cpp @@ -0,0 +1,112 @@ +/* + * SpotlightModel.cpp - implementation of SpotlightModel + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "SpotlightModel.h" + + +SpotlightModel::SpotlightModel( QAbstractItemModel* sourceModel, QObject* parent ) : + QSortFilterProxyModel( parent ) +{ + setSourceModel( sourceModel ); +} + + + +void SpotlightModel::setIconSize( QSize size ) +{ + m_iconSize = size; + + Q_EMIT dataChanged( index( 0, 0 ), index( rowCount() - 1, 0 ), { Qt::DisplayRole, Qt::DecorationRole } ); +} + + + +void SpotlightModel::setUpdateInRealtime( bool enabled ) +{ + m_updateInRealtime = enabled; + + for( const auto& controlInterface : std::as_const(m_controlInterfaces) ) + { + controlInterface->setUpdateMode( m_updateInRealtime + ? ComputerControlInterface::UpdateMode::Live + : ComputerControlInterface::UpdateMode::Monitoring ); + } +} + + + +void SpotlightModel::add( const ComputerControlInterface::Pointer& controlInterface ) +{ + m_controlInterfaces.append( controlInterface ); + + controlInterface->setUpdateMode( m_updateInRealtime + ? ComputerControlInterface::UpdateMode::Live + : ComputerControlInterface::UpdateMode::Monitoring ); + + invalidateFilter(); +} + + + +void SpotlightModel::remove( const ComputerControlInterface::Pointer& controlInterface ) +{ + m_controlInterfaces.removeAll( controlInterface ); + + controlInterface->setUpdateMode( ComputerControlInterface::UpdateMode::Monitoring ); + + invalidateFilter(); +} + + + +QVariant SpotlightModel::data( const QModelIndex& index, int role ) const +{ + const auto sourceIndex = mapToSource( index ); + if( sourceIndex.isValid() == false ) + { + return {}; + } + + if( role == Qt::DecorationRole ) + { + auto framebuffer = sourceModel()->data(sourceIndex, ComputerListModel::FramebufferRole).value(); + if (framebuffer.isNull()) + { + framebuffer = sourceModel()->data(sourceIndex, Qt::DecorationRole).value(); + } + + return framebuffer.scaled(m_iconSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); + } + + return QSortFilterProxyModel::data( index, role ); +} + + + +bool SpotlightModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const +{ + return m_controlInterfaces.contains( sourceModel()->data( sourceModel()->index( sourceRow, 0, sourceParent ), + ComputerListModel::ControlInterfaceRole ) + .value() ); +} diff --git a/master/src/SpotlightModel.h b/master/src/SpotlightModel.h new file mode 100644 index 000000000..ca354f83d --- /dev/null +++ b/master/src/SpotlightModel.h @@ -0,0 +1,56 @@ +/* + * SpotlightModel.h - header file for SpotlightModel + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +#include "ComputerControlListModel.h" + +class SpotlightModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + static constexpr auto ControlInterfaceRole = ComputerControlListModel::ControlInterfaceRole; + + SpotlightModel( QAbstractItemModel* sourceModel, QObject* parent = nullptr ); + + void setIconSize( QSize size ); + void setUpdateInRealtime( bool enabled ); + + void add( const ComputerControlInterface::Pointer& controlInterface ); + void remove( const ComputerControlInterface::Pointer& controlInterface ); + + QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override; + +protected: + bool filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const override; + +private: + QSize m_iconSize; + bool m_updateInRealtime{false}; + + ComputerControlInterfaceList m_controlInterfaces; + +}; diff --git a/master/src/SpotlightPanel.cpp b/master/src/SpotlightPanel.cpp new file mode 100644 index 000000000..4861f5d59 --- /dev/null +++ b/master/src/SpotlightPanel.cpp @@ -0,0 +1,216 @@ +/* + * SpotlightPanel.cpp - implementation of SpotlightPanel + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include +#include + +#include "ComputerMonitoringModel.h" +#include "ComputerMonitoringWidget.h" +#include "SpotlightModel.h" +#include "SpotlightPanel.h" +#include "UserConfig.h" + +#include "ui_SpotlightPanel.h" + + +SpotlightPanel::SpotlightPanel( UserConfig& config, ComputerMonitoringWidget* computerMonitoringWidget, QWidget* parent ) : + QWidget( parent ), + ui( new Ui::SpotlightPanel ), + m_config( config ), + m_globalComputerMonitoringWidget( computerMonitoringWidget ), + m_model( new SpotlightModel( m_globalComputerMonitoringWidget->dataModel(), this ) ) +{ + ui->setupUi( this ); + + ui->monitoringWidget->setAutoAdjustIconSize( false ); + ui->monitoringWidget->setUseCustomComputerPositions( false ); + ui->monitoringWidget->setAcceptDrops( false ); + ui->monitoringWidget->setDragEnabled( false ); + ui->monitoringWidget->setIgnoreWheelEvent( true ); + ui->monitoringWidget->setModel( m_model ); + + if (VeyonCore::useDarkMode()) + { + QIcon realtimeViewIcon; + realtimeViewIcon.addPixmap(QPixmap(QStringLiteral(":/master/update-realtime-enabled-dark.png")), QIcon::Mode::Normal, QIcon::State::On); + realtimeViewIcon.addPixmap(QPixmap(QStringLiteral(":/master/update-realtime-disabled-dark.png")), QIcon::Mode::Normal, QIcon::State::Off); + ui->realtimeViewButton->setIcon(realtimeViewIcon); + ui->addButton->setIcon(QIcon(QStringLiteral(":/core/go-up-dark.png"))); + ui->removeButton->setIcon(QIcon(QStringLiteral(":/core/go-down-dark.png"))); + } + + connect( ui->addButton, &QAbstractButton::clicked, this, &SpotlightPanel::add ); + connect( ui->removeButton, &QAbstractButton::clicked, this, &SpotlightPanel::remove ); + connect( ui->realtimeViewButton, &QAbstractButton::toggled, this, &SpotlightPanel::setRealtimeView ); + + connect( m_globalComputerMonitoringWidget, &QAbstractItemView::pressed, this, &SpotlightPanel::addPressedItem ); + connect( ui->monitoringWidget, &QAbstractItemView::pressed, this, &SpotlightPanel::removePressedItem ); + + connect( m_model, &QAbstractItemModel::rowsRemoved, this, [=]() { + if( m_model->rowCount() <= 0 ) + { + ui->stackedWidget->setCurrentWidget( ui->helpPage ); + } + } ); + + setRealtimeView( m_config.spotlightRealtime() ); +} + + + +SpotlightPanel::~SpotlightPanel() +{ + delete ui; +} + + + +void SpotlightPanel::resizeEvent( QResizeEvent* event ) +{ + updateIconSize(); + + QWidget::resizeEvent( event ); +} + + + +void SpotlightPanel::hideEvent(QHideEvent* event) +{ + Q_EMIT visibilityChanged( false ); + + QWidget::hideEvent( event ); +} + + + +void SpotlightPanel::showEvent(QShowEvent* event) +{ + Q_EMIT visibilityChanged( true ); + + QWidget::showEvent( event ); +} + + + +void SpotlightPanel::add() +{ + const auto selectedComputerControlInterfaces = m_globalComputerMonitoringWidget->selectedComputerControlInterfaces(); + + if( selectedComputerControlInterfaces.isEmpty() ) + { + QMessageBox::information( this, tr("Spotlight"), + tr( "Please select at least one computer to add.") ); + return; + } + + for( const auto& controlInterface : selectedComputerControlInterfaces ) + { + m_model->add( controlInterface ); + } + + if( ui->stackedWidget->currentWidget() != ui->viewPage ) + { + ui->stackedWidget->setCurrentWidget( ui->viewPage ); + + // due to a bug in QListView force relayout of all items to show decorations (thumbnails) properly + updateIconSize(); + } + + show(); +} + + + +void SpotlightPanel::remove() +{ + auto selection = ui->monitoringWidget->selectionModel()->selectedIndexes(); + if( selection.isEmpty() && m_model->rowCount() > 0 ) + { + const auto lastIndex = m_model->index(m_model->rowCount() - 1, 0); + ui->monitoringWidget->selectionModel()->select(lastIndex, QItemSelectionModel::Select); + selection = ui->monitoringWidget->selectionModel()->selectedIndexes(); + } + + while( selection.isEmpty() == false ) + { + m_model->remove( m_model->data( selection.first(), SpotlightModel::ControlInterfaceRole ) + .value() ); + + selection = ui->monitoringWidget->selectionModel()->selectedIndexes(); + } + + if( m_model->rowCount() <= 0 ) + { + hide(); + } +} + + + +void SpotlightPanel::setRealtimeView( bool enabled ) +{ + m_model->setUpdateInRealtime( enabled ); + + m_config.setSpotlightRealtime( enabled ); + + ui->realtimeViewButton->setChecked( enabled ); +} + + + +void SpotlightPanel::updateIconSize() +{ + static constexpr auto ExtraMargin = 10; + + const auto spacing = ui->monitoringWidget->spacing(); + const auto labelHeight = ui->monitoringWidget->fontMetrics().height(); + + ui->monitoringWidget->setIconSize( { ui->monitoringWidget->width() - ExtraMargin - spacing * 2, + ui->monitoringWidget->height() - ExtraMargin - labelHeight - spacing * 2 } ); + m_model->setIconSize( ui->monitoringWidget->iconSize() ); +} + + + +void SpotlightPanel::addPressedItem( const QModelIndex& index ) +{ + if( QGuiApplication::mouseButtons().testFlag( Qt::MiddleButton ) ) + { + m_globalComputerMonitoringWidget->selectionModel()->select( index, QItemSelectionModel::SelectCurrent ); + + add(); + } +} + + + +void SpotlightPanel::removePressedItem( const QModelIndex& index ) +{ + if( QGuiApplication::mouseButtons().testFlag( Qt::MiddleButton ) ) + { + ui->monitoringWidget->selectionModel()->select( index, QItemSelectionModel::SelectCurrent ); + + remove(); + } +} diff --git a/master/src/SpotlightPanel.h b/master/src/SpotlightPanel.h new file mode 100644 index 000000000..9f9393838 --- /dev/null +++ b/master/src/SpotlightPanel.h @@ -0,0 +1,69 @@ +/* + * SpotlightPanel.h - declaration of SpotlightPanel + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +class ComputerMonitoringWidget; +class SpotlightModel; +class UserConfig; + +namespace Ui { +class SpotlightPanel; +} + +class SpotlightPanel : public QWidget +{ + Q_OBJECT +public: + explicit SpotlightPanel( UserConfig& config, ComputerMonitoringWidget* computerMonitoringWidget, + QWidget* parent = nullptr ); + ~SpotlightPanel() override; + +Q_SIGNALS: + void visibilityChanged( bool isVisible ); + +protected: + void resizeEvent( QResizeEvent* event ) override; + void hideEvent( QHideEvent* event) override; + void showEvent( QShowEvent* event) override; + +private: + void add(); + void remove(); + void setRealtimeView( bool enabled ); + void updateIconSize(); + + void addPressedItem( const QModelIndex& index ); + void removePressedItem( const QModelIndex& index ); + + Ui::SpotlightPanel* ui; + + UserConfig& m_config; + + ComputerMonitoringWidget* m_globalComputerMonitoringWidget; + SpotlightModel* m_model; + +} ; diff --git a/master/src/SpotlightPanel.ui b/master/src/SpotlightPanel.ui new file mode 100644 index 000000000..7c3a8b9b7 --- /dev/null +++ b/master/src/SpotlightPanel.ui @@ -0,0 +1,212 @@ + + + SpotlightPanel + + + + 0 + + + 0 + + + 4 + + + 0 + + + 0 + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + + + + + 128 + 128 + 128 + + + + + + + + + 128 + 128 + 128 + + + + + + + + + 119 + 120 + 120 + + + + + + + + + 20 + + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + Qt::AlignCenter + + + true + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + 4 + + + 4 + + + 4 + + + + + Add selected computers + + + + :/core/go-up.png:/core/go-up.png + + + + + + + Remove selected computers + + + + :/core/go-down.png:/core/go-down.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Update computers in realtime + + + + :/master/update-realtime-disabled.png + :/master/update-realtime-enabled.png:/master/update-realtime-disabled.png + + + true + + + true + + + + + + + + + + + + + + + + + + ComputerMonitoringWidget + QListView +
ComputerMonitoringWidget.h
+ 1 +
+
+ + + + + +
diff --git a/master/src/UserConfig.cpp b/master/src/UserConfig.cpp index 4caeab408..61dc9fb40 100644 --- a/master/src/UserConfig.cpp +++ b/master/src/UserConfig.cpp @@ -2,7 +2,7 @@ * UserConfig.cpp - Configuration object storing personal settings * for the Veyon Master Application * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,21 +23,27 @@ * */ -#include - -#include "VeyonCore.h" +#include "Configuration/JsonStore.h" +#include "Filesystem.h" #include "UserConfig.h" +#include "VeyonConfiguration.h" -UserConfig::UserConfig( Configuration::Store::Backend backend ) : - Configuration::Object( backend, Configuration::Store::User, QStringLiteral("VeyonMaster") ) +UserConfig::UserConfig(const QString& storeName) : + Configuration::Object(Configuration::Store::Backend::JsonFile, Configuration::Store::Scope::User, storeName) { - if( isStoreWritable() == false ) + const QString templateFileName = VeyonCore::filesystem().expandPath(VeyonCore::config().configurationTemplatesDirectory()) + + QDir::separator() + storeName + QStringLiteral(".json"); + if (QFileInfo(templateFileName).isReadable()) { - QMessageBox::information( nullptr, - tr( "No write access" ), - tr( "Could not save your personal settings! " - "Please check the user configuration " - "file path using the %1 Configurator." ).arg( VeyonCore::applicationName() ) ); + Configuration::JsonStore jsonStore(Configuration::Store::Scope::System, templateFileName); + *this += UserConfig(&jsonStore); } } + + + +UserConfig::UserConfig(Configuration::Store* store) : + Configuration::Object(store) +{ +} diff --git a/master/src/UserConfig.h b/master/src/UserConfig.h index 5792aeb87..851d12e55 100644 --- a/master/src/UserConfig.h +++ b/master/src/UserConfig.h @@ -1,7 +1,7 @@ /* * UserConfig.h - UserConfig class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,10 +25,12 @@ #pragma once #include +#include #include "Configuration/Object.h" #include "Configuration/Property.h" -#include "ComputerMonitoringWidget.h" +#include "ComputerMonitoringView.h" +#include "SlideshowPanel.h" #include "VeyonMaster.h" // clazy:excludeall=ctor-missing-parent-argument,copyable-polymorphic @@ -37,17 +39,23 @@ class UserConfig : public Configuration::Object { Q_OBJECT public: - explicit UserConfig( Configuration::Store::Backend backend ); + UserConfig(const QString& storeName); + explicit UserConfig(Configuration::Store* store); #define FOREACH_PERSONAL_CONFIG_PROPERTY(OP) \ OP( UserConfig, VeyonMaster::userConfig(), QJsonArray, checkedNetworkObjects, setCheckedNetworkObjects, "CheckedNetworkObjects", "UI", QJsonArray(), Configuration::Property::Flag::Standard ) \ OP( UserConfig, VeyonMaster::userConfig(), QJsonArray, computerPositions, setComputerPositions, "ComputerPositions", "UI", QJsonArray(), Configuration::Property::Flag::Standard ) \ OP( UserConfig, VeyonMaster::userConfig(), bool, useCustomComputerPositions, setUseCustomComputerPositions, "UseCustomComputerPositions", "UI", false, Configuration::Property::Flag::Standard ) \ OP( UserConfig, VeyonMaster::userConfig(), bool, filterPoweredOnComputers, setFilterPoweredOnComputers, "FilterPoweredOnComputers", "UI", false, Configuration::Property::Flag::Standard ) \ - OP( UserConfig, VeyonMaster::userConfig(), int, monitoringScreenSize, setMonitoringScreenSize, "MonitoringScreenSize", "UI", ComputerMonitoringWidget::DefaultComputerScreenSize, Configuration::Property::Flag::Standard ) \ + OP( UserConfig, VeyonMaster::userConfig(), bool, filterComputersWithLoggedOnUsers, setFilterComputersWithLoggedOnUsers, "FilterComputersWithLoggedOnUsers", "UI", false, Configuration::Property::Flag::Standard ) \ + OP( UserConfig, VeyonMaster::userConfig(), int, monitoringScreenSize, setMonitoringScreenSize, "MonitoringScreenSize", "UI", ComputerMonitoringView::DefaultComputerScreenSize, Configuration::Property::Flag::Standard ) \ + OP( UserConfig, VeyonMaster::userConfig(), bool, autoAdjustMonitoringIconSize, setAutoAdjustMonitoringIconSize, "AutoAdjustMonitoringIconSize", "UI", false, Configuration::Property::Flag::Standard ) \ + OP( UserConfig, VeyonMaster::userConfig(), int, slideshowDuration, setSlideshowDuration, "SlideshowDuration", "UI", SlideshowPanel::DefaultDuration, Configuration::Property::Flag::Standard ) \ + OP( UserConfig, VeyonMaster::userConfig(), bool, spotlightRealtime, setSpotlightRealtime, "SpotlightRealtime", "UI", true, Configuration::Property::Flag::Standard ) \ OP( UserConfig, VeyonMaster::userConfig(), int, defaultRole, setDefaultRole, "DefaultRole", "Authentication", 0, Configuration::Property::Flag::Standard ) \ OP( UserConfig, VeyonMaster::userConfig(), bool, toolButtonIconOnlyMode, setToolButtonIconOnlyMode, "ToolButtonIconOnlyMode", "UI", false, Configuration::Property::Flag::Standard ) \ OP( UserConfig, VeyonMaster::userConfig(), bool, noToolTips, setNoToolTips, "NoToolTips", "UI", false, Configuration::Property::Flag::Standard ) \ + OP( UserConfig, VeyonMaster::userConfig(), QJsonObject, splitterStates, setSplitterStates, "SplitterStates", "UI", {}, Configuration::Property::Flag::Standard ) \ OP( UserConfig, VeyonMaster::userConfig(), QString, windowState, setWindowState, "WindowState", "UI", QString(), Configuration::Property::Flag::Standard ) \ OP( UserConfig, VeyonMaster::userConfig(), QString, windowGeometry, setWindowGeometry, "WindowGeometry", "UI", QString(), Configuration::Property::Flag::Standard ) \ diff --git a/master/src/VeyonMaster.cpp b/master/src/VeyonMaster.cpp index 1fddd06e7..58ba8d99f 100644 --- a/master/src/VeyonMaster.cpp +++ b/master/src/VeyonMaster.cpp @@ -1,7 +1,7 @@ /* * VeyonMaster.cpp - management of application-global instances * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,94 +22,126 @@ * */ -#include "VeyonMaster.h" +#include +#include +#include +#include +#include + #include "BuiltinFeatures.h" #include "ComputerControlListModel.h" -#include "ComputerSortFilterProxyModel.h" +#include "ComputerImageProvider.h" +#include "ComputerManager.h" +#include "ComputerMonitoringItem.h" +#include "ComputerMonitoringModel.h" #include "FeatureManager.h" -#include "VncConnection.h" -#include "VeyonConfiguration.h" -#include "VeyonConnection.h" #include "MainWindow.h" -#include "ComputerManager.h" #include "MonitoringMode.h" -#include "UserConfig.h" #include "PluginManager.h" +#include "UserConfig.h" +#include "VeyonConfiguration.h" +#include "VeyonMaster.h" VeyonMaster::VeyonMaster( QObject* parent ) : VeyonMasterInterface( parent ), - m_userConfig( new UserConfig( Configuration::Store::JsonFile ) ), - m_featureManager( new FeatureManager() ), + m_userConfig(new UserConfig(QStringLiteral("VeyonMaster"))), m_features( featureList() ), + m_featureListModel( new FeatureListModel( this ) ), m_computerManager( new ComputerManager( *m_userConfig, this ) ), m_computerControlListModel( new ComputerControlListModel( this, this ) ), - m_computerSortFilterProxyModel( new ComputerSortFilterProxyModel( this ) ), - m_mainWindow( nullptr ), + m_computerMonitoringModel( new ComputerMonitoringModel( m_computerControlListModel, this ) ), + m_computerSelectModel( new ComputerSelectModel( m_computerManager->computerTreeModel(), this ) ), + m_localSessionControlInterface( Computer( NetworkObject::Uid::createUuid(), + QStringLiteral("localhost"), + QStringLiteral("%1"). + arg( QHostAddress( QHostAddress::LocalHost ).toString() ) ), + VeyonCore::config().veyonServerPort() + VeyonCore::sessionId(), + this ), m_currentMode( VeyonCore::builtinFeatures().monitoringMode().feature().uid() ) { + if (m_userConfig->isStoreWritable() == false) + { + QMessageBox::information(nullptr, + tr("No write access"), + tr("Could not save your personal settings! Please check the user configuration " + "file path using the %1 Configurator.").arg(VeyonCore::applicationName())); + } + + connect(m_computerControlListModel, &ComputerControlListModel::modelAboutToBeReset, + this, &VeyonMaster::computerControlListModelAboutToReset); + if( VeyonCore::config().enforceSelectedModeForClients() ) { connect( m_computerControlListModel, &ComputerControlListModel::activeFeaturesChanged, this, &VeyonMaster::enforceDesignatedMode ); } - connect( &VeyonCore::localComputerControlInterface(), &ComputerControlInterface::featureMessageReceived, - this, [=]( const FeatureMessage& featureMessage, ComputerControlInterface::Pointer computerControlInterface ) { - m_featureManager->handleFeatureMessage( *this, featureMessage, computerControlInterface ); - } ); - - VeyonCore::localComputerControlInterface().start( QSize() ); + m_localSessionControlInterface.start({}, ComputerControlInterface::UpdateMode::Disabled); - // attach computer list model to proxy model - m_computerSortFilterProxyModel->setSourceModel( m_computerControlListModel ); - m_computerSortFilterProxyModel->setSortRole( Qt::InitialSortOrderRole ); - m_computerSortFilterProxyModel->setStateRole( ComputerControlListModel::StateRole ); - m_computerSortFilterProxyModel->sort( 0 ); - - m_mainWindow = new MainWindow( *this ); + initUserInterface(); } VeyonMaster::~VeyonMaster() { - stopAllModeFeatures( m_computerControlListModel->computerControlInterfaces() ); + shutdown(); + delete m_qmlAppEngine; delete m_mainWindow; delete m_computerManager; m_userConfig->flushStore(); delete m_userConfig; - - delete m_featureManager; } FeatureList VeyonMaster::subFeatures( Feature::Uid parentFeatureUid ) const { - FeatureList features; - const auto disabledFeatures = VeyonCore::config().disabledFeatures(); - const auto pluginUids = VeyonCore::pluginManager().pluginUids(); + if( disabledFeatures.contains( parentFeatureUid.toString() ) ) + { + return {}; + } + + const auto& relatedFeatures = VeyonCore::featureManager().relatedFeatures( parentFeatureUid ); - for( const auto& pluginUid : pluginUids ) + FeatureList subFeatures; + subFeatures.reserve( relatedFeatures.size() ); + + for( const auto& relatedFeature : relatedFeatures ) { - for( const auto& feature : m_featureManager->features( pluginUid ) ) + if( relatedFeature.testFlag( Feature::Flag::Master ) && + relatedFeature.parentUid() == parentFeatureUid && + disabledFeatures.contains( relatedFeature.uid().toString() ) == false ) { - if( feature.testFlag( Feature::Master ) && - feature.parentUid() == parentFeatureUid && - disabledFeatures.contains( parentFeatureUid.toString() ) == false && - disabledFeatures.contains( feature.uid().toString() ) == false ) - { - features += feature; - } + subFeatures += relatedFeature; } } - return features; + return subFeatures; +} + + + +FeatureList VeyonMaster::allFeatures() const +{ + FeatureList featureList; + + for( const auto& feature : std::as_const( features() ) ) + { + featureList.append(feature); // clazy:exclude=reserve-candidates + const auto modeSubFeatures = subFeatures( feature.uid() ); + for( const auto& subFeature : modeSubFeatures ) + { + featureList.append( subFeature ); + } + } + + return featureList; } @@ -130,22 +162,50 @@ Configuration::Object* VeyonMaster::userConfigurationObject() void VeyonMaster::reloadSubFeatures() { - m_mainWindow->reloadSubFeatures(); + if( m_mainWindow ) + { + m_mainWindow->reloadSubFeatures(); + } } -ComputerControlInterfaceList VeyonMaster::filteredComputerControlInterfaces() +const ComputerControlInterfaceList& VeyonMaster::allComputerControlInterfaces() const { - const auto rowCount = m_computerSortFilterProxyModel->rowCount(); + return m_computerControlListModel->computerControlInterfaces(); +} + + + +ComputerControlInterfaceList VeyonMaster::selectedComputerControlInterfaces() const +{ + if( m_mainWindow ) + { + return m_mainWindow->selectedComputerControlInterfaces(); + } + + const auto monitoringItem = m_appContainer->findChild(); + if( monitoringItem ) + { + return monitoringItem->selectedComputerControlInterfaces(); + } + + return {}; +} + + + +ComputerControlInterfaceList VeyonMaster::filteredComputerControlInterfaces() const +{ + const auto rowCount = m_computerMonitoringModel->rowCount(); ComputerControlInterfaceList computerControlInterfaces; computerControlInterfaces.reserve( rowCount ); for( int i = 0; i < rowCount; ++i ) { - const auto index = m_computerSortFilterProxyModel->index( i, 0 ); - const auto sourceIndex = m_computerSortFilterProxyModel->mapToSource( index ); + const auto index = m_computerMonitoringModel->index( i, 0 ); + const auto sourceIndex = m_computerMonitoringModel->mapToSource( index ); computerControlInterfaces.append( m_computerControlListModel->computerControlInterface( sourceIndex ) ); } @@ -158,26 +218,27 @@ void VeyonMaster::runFeature( const Feature& feature ) { const auto computerControlInterfaces = filteredComputerControlInterfaces(); - if( feature.testFlag( Feature::Mode ) ) + if( feature.testFlag( Feature::Flag::Mode ) ) { - stopAllModeFeatures( computerControlInterfaces ); + stopAllFeatures( computerControlInterfaces ); - if( m_currentMode == feature.uid() ) + if( m_currentMode == feature.uid() || + subFeatures( feature.uid() ).contains( VeyonCore::featureManager().feature( m_currentMode ) ) ) { const Feature& monitoringModeFeature = VeyonCore::builtinFeatures().monitoringMode().feature(); - m_featureManager->startFeature( *this, monitoringModeFeature, computerControlInterfaces ); + VeyonCore::featureManager().startFeature( *this, monitoringModeFeature, computerControlInterfaces ); m_currentMode = monitoringModeFeature.uid(); } else { - m_featureManager->startFeature( *this, feature, computerControlInterfaces ); + VeyonCore::featureManager().startFeature( *this, feature, computerControlInterfaces ); m_currentMode = feature.uid(); } } else { - m_featureManager->startFeature( *this, feature, computerControlInterfaces ); + VeyonCore::featureManager().startFeature( *this, feature, computerControlInterfaces ); } } @@ -188,74 +249,147 @@ void VeyonMaster::enforceDesignatedMode( const QModelIndex& index ) auto controlInterface = m_computerControlListModel->computerControlInterface( index ); if( controlInterface ) { - auto designatedModeFeature = m_featureManager->feature( controlInterface->designatedModeFeature() ); + const auto designatedModeFeature = controlInterface->designatedModeFeature(); - // stop all other active mode feature - for( const auto& currentFeature : features() ) + if( designatedModeFeature.isNull() == false && + designatedModeFeature != VeyonCore::builtinFeatures().monitoringMode().feature().uid() && + controlInterface->activeFeatures().contains( designatedModeFeature ) == false && + controlInterface->activeFeatures().contains( VeyonCore::featureManager().metaFeatureUid(designatedModeFeature) ) == false ) { - if( currentFeature.testFlag( Feature::Mode ) && currentFeature != designatedModeFeature ) - { - featureManager().stopFeature( *this, currentFeature, { controlInterface } ); - } + VeyonCore::featureManager().startFeature( *this, VeyonCore::featureManager().feature(designatedModeFeature), + { controlInterface } ); } + } +} - if( designatedModeFeature != VeyonCore::builtinFeatures().monitoringMode().feature() ) - { - featureManager().startFeature( *this, designatedModeFeature, { controlInterface } ); - } + + +void VeyonMaster::stopAllFeatures( const ComputerControlInterfaceList& computerControlInterfaces ) +{ + const auto features = allFeatures(); + + for( const auto& feature : features ) + { + VeyonCore::featureManager().stopFeature( *this, feature, computerControlInterfaces ); } } -void VeyonMaster::stopAllModeFeatures( const ComputerControlInterfaceList& computerControlInterfaces ) +void VeyonMaster::initUserInterface() { - // stop any previously active featues - for( const auto& feature : qAsConst( features() ) ) + if( VeyonCore::config().modernUserInterface() ) { - if( feature.testFlag( Feature::Mode ) ) - { - m_featureManager->stopFeature( *this, feature, computerControlInterfaces ); - } + QQuickStyle::setStyle( QStringLiteral("Material") ); + + m_computerControlListModel->updateComputerScreenSize(); + + const auto veyonVersion = QVersionNumber( 5, 0 ); + const auto majorVersion = veyonVersion.majorVersion(); + const auto minorVersion = veyonVersion.minorVersion(); + + qmlRegisterType( "Veyon.Master", majorVersion, minorVersion, "ComputerMonitoringItem" ); + + m_qmlAppEngine = new QQmlApplicationEngine( this ); + m_qmlAppEngine->addImageProvider( m_computerControlListModel->imageProvider()->id(), + m_computerControlListModel->imageProvider() ); + m_qmlAppEngine->rootContext()->setContextProperty( QStringLiteral("masterCore"), this ); + m_qmlAppEngine->load( QStringLiteral(":/master/MainWindow.qml") ); + } + else + { + m_mainWindow = new MainWindow( *this ); } } -FeatureList VeyonMaster::featureList() const +void VeyonMaster::setAppWindow( QQuickWindow* appWindow ) { - FeatureList features; + if( m_appWindow != appWindow ) + { + m_appWindow = appWindow; + Q_EMIT appWindowChanged(); + } +} - const auto disabledFeatures = VeyonCore::config().disabledFeatures(); - const auto pluginUids = VeyonCore::pluginManager().pluginUids(); - for( const auto& pluginUid : pluginUids ) + +void VeyonMaster::setAppContainer( QQuickItem* appContainer ) +{ + if( m_appContainer != appContainer ) { - for( const auto& feature : m_featureManager->features( pluginUid ) ) + m_appContainer = appContainer; + Q_EMIT appContainerChanged(); + } +} + + + +void VeyonMaster::shutdown() +{ + stopAllFeatures( m_computerControlListModel->computerControlInterfaces() ); + + const auto allMessageQueuesEmpty = [&]() { + for( const auto& computerControlInterface : m_computerControlListModel->computerControlInterfaces() ) { - if( feature.testFlag( Feature::Master ) && - feature.testFlag( Feature::Mode ) && - feature.parentUid().isNull() && - disabledFeatures.contains( feature.uid().toString() ) == false ) + if( computerControlInterface->isMessageQueueEmpty() == false ) { - features += feature; + return false; } } + + return true; + }; + + static constexpr auto MessageQueueWaitTimeout = 60 * 1000; + static constexpr auto MessageQueuePollInterval = 10; + + QElapsedTimer messageQueueWaitTimer; + messageQueueWaitTimer.start(); + + while( allMessageQueuesEmpty() == false && + messageQueueWaitTimer.elapsed() < MessageQueueWaitTimeout ) + { + QThread::msleep(MessageQueuePollInterval); } - for( const auto& pluginUid : pluginUids ) + vDebug() << "finished in" << messageQueueWaitTimer.elapsed() << "ms"; +} + + + +FeatureList VeyonMaster::featureList() const +{ + FeatureList features; + + const auto disabledFeatures = VeyonCore::config().disabledFeatures(); + auto pluginUids = VeyonCore::pluginManager().pluginUids(); + + std::sort(pluginUids.begin(), pluginUids.end(), [](const Plugin::Uid a, const Plugin::Uid b) { + return a.toString() < b.toString(); + }); + + const auto addFeatures = [&]( const std::function& extraFilter ) { - for( const auto& feature : m_featureManager->features( pluginUid ) ) + for(const auto& pluginUid : std::as_const(pluginUids)) { - if( feature.testFlag( Feature::Master ) && - feature.testFlag( Feature::Mode ) == false && - feature.parentUid().isNull() && - disabledFeatures.contains( feature.uid().toString() ) == false ) + for( const auto& feature : VeyonCore::featureManager().features( pluginUid ) ) { - features += feature; + if( feature.testFlag( Feature::Flag::Master ) && + feature.testFlag( Feature::Flag::Meta ) == false && + feature.parentUid().isNull() && + disabledFeatures.contains( feature.uid().toString() ) == false && + extraFilter( feature ) ) + { + features += feature; + } } } - } + }; + + addFeatures( []( const Feature& feature ) { return feature.testFlag( Feature::Flag::Mode ); } ); + addFeatures( []( const Feature& feature ) { return feature.testFlag( Feature::Flag::Mode ) == false; } ); return features; } diff --git a/master/src/VeyonMaster.h b/master/src/VeyonMaster.h index ba25f7afd..62f5bdeac 100644 --- a/master/src/VeyonMaster.h +++ b/master/src/VeyonMaster.h @@ -1,7 +1,7 @@ /* * VeyonMaster.h - global instances * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,35 +24,34 @@ #pragma once -#include +#include #include "Feature.h" +#include "FeatureListModel.h" #include "Computer.h" #include "ComputerControlInterface.h" +#include "ComputerSelectModel.h" #include "VeyonMasterInterface.h" class QModelIndex; +class QQmlApplicationEngine; class BuiltinFeatures; class ComputerControlListModel; class ComputerManager; -class ComputerSortFilterProxyModel; -class FeatureManager; +class ComputerMonitoringModel; class MainWindow; class UserConfig; class VeyonMaster : public VeyonMasterInterface { Q_OBJECT + Q_PROPERTY(QQuickWindow* appWindow READ appWindow WRITE setAppWindow NOTIFY appWindowChanged) + Q_PROPERTY(QQuickItem* appContainer READ appContainer WRITE setAppContainer NOTIFY appContainerChanged) public: explicit VeyonMaster( QObject* parent = nullptr ); ~VeyonMaster() override; - FeatureManager& featureManager() - { - return *m_featureManager; - } - UserConfig& userConfig() { return *m_userConfig; @@ -68,11 +67,24 @@ class VeyonMaster : public VeyonMasterInterface return *m_computerControlListModel; } - ComputerSortFilterProxyModel& computerSortFilterProxyModel() + ComputerMonitoringModel* computerMonitoringModel() const + { + return m_computerMonitoringModel; + } + + ComputerSelectModel* computerSelectModel() const + { + return m_computerSelectModel; + } + + FeatureListModel* featureListModel() const { - return *m_computerSortFilterProxyModel; + return m_featureListModel; } + Q_PROPERTY(QObject* computerSelectModel READ computerSelectModel CONSTANT) + Q_PROPERTY(QObject* featureListModel READ featureListModel CONSTANT) + const FeatureList& features() const { return m_features; @@ -80,33 +92,72 @@ class VeyonMaster : public VeyonMasterInterface FeatureList subFeatures( Feature::Uid parentFeatureUid ) const; + FeatureList allFeatures() const; + const Feature::Uid& currentMode() const { return m_currentMode; } QWidget* mainWindow() override; + + QQuickWindow* appWindow() override + { + return m_appWindow; + } + + QQuickItem* appContainer() override + { + return m_appContainer; + } + Configuration::Object* userConfigurationObject() override; void reloadSubFeatures() override; - ComputerControlInterfaceList filteredComputerControlInterfaces(); + ComputerControlInterface& localSessionControlInterface() override + { + return m_localSessionControlInterface; + } + + const ComputerControlInterfaceList& allComputerControlInterfaces() const override; -public slots: + ComputerControlInterfaceList selectedComputerControlInterfaces() const override; + + ComputerControlInterfaceList filteredComputerControlInterfaces() const override; + +public Q_SLOTS: void runFeature( const Feature& feature ); void enforceDesignatedMode( const QModelIndex& index ); - void stopAllModeFeatures( const ComputerControlInterfaceList& computerControlInterfaces ); + void stopAllFeatures( const ComputerControlInterfaceList& computerControlInterfaces ); + +Q_SIGNALS: + void appWindowChanged(); + void appContainerChanged(); private: + void shutdown(); + + void initUserInterface(); + + void setAppWindow( QQuickWindow* appWindow ); + void setAppContainer( QQuickItem* appContainer ); + FeatureList featureList() const; UserConfig* m_userConfig; - FeatureManager* m_featureManager; const FeatureList m_features; + FeatureListModel* m_featureListModel{nullptr}; ComputerManager* m_computerManager; ComputerControlListModel* m_computerControlListModel; - ComputerSortFilterProxyModel* m_computerSortFilterProxyModel; + ComputerMonitoringModel* m_computerMonitoringModel; + ComputerSelectModel* m_computerSelectModel; + + ComputerControlInterface m_localSessionControlInterface; - MainWindow* m_mainWindow; + MainWindow* m_mainWindow{nullptr}; + QQmlApplicationEngine* m_qmlAppEngine{nullptr}; + QQuickWindow* m_appWindow{nullptr}; + QQuickItem* m_appContainer{nullptr}; Feature::Uid m_currentMode; diff --git a/master/src/kitemmodels_debug.h b/master/src/kitemmodels_debug.h deleted file mode 100644 index b637c7582..000000000 --- a/master/src/kitemmodels_debug.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include -#include - -Q_DECLARE_LOGGING_CATEGORY(KITEMMODELS_LOG); - diff --git a/master/src/kitemmodels_export.h b/master/src/kitemmodels_export.h deleted file mode 100644 index b7c411b08..000000000 --- a/master/src/kitemmodels_export.h +++ /dev/null @@ -1,2 +0,0 @@ -#define KITEMMODELS_EXPORT - diff --git a/master/src/main.cpp b/master/src/main.cpp index 9d7a74722..2b83dcb6d 100644 --- a/master/src/main.cpp +++ b/master/src/main.cpp @@ -1,7 +1,7 @@ /* * main.cpp - startup routine for Veyon Master Application * - * Copyright (c) 2004-2019 Tobias Junghans + * Copyright (c) 2004-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,21 +23,24 @@ */ #include +#include #include #include "DocumentationFigureCreator.h" -#include "VeyonMaster.h" #include "MainWindow.h" +#include "VeyonConfiguration.h" +#include "VeyonMaster.h" int main( int argc, char** argv ) { VeyonCore::setupApplicationParameters(); - QApplication app( argc, argv ); - app.connect( &app, &QApplication::lastWindowClosed, &QApplication::quit ); + const auto modernUi = VeyonConfiguration().modernUserInterface(); + + QGuiApplication* app = modernUi ? new QGuiApplication( argc, argv ) : new QApplication( argc, argv ); - VeyonCore core( &app, QStringLiteral("Master") ); + VeyonCore core( app, VeyonCore::Component::Master, QStringLiteral("Master") ); #ifdef VEYON_DEBUG if( qEnvironmentVariableIsSet( "VEYON_MASTER_CREATE_DOC_FIGURES") ) @@ -47,21 +50,27 @@ int main( int argc, char** argv ) } #endif - QSplashScreen splashScreen( QPixmap( QStringLiteral(":/master/splash.png") ) ); - splashScreen.show(); + QSplashScreen* splashScreen = nullptr; + + if( modernUi == false ) + { + splashScreen = new QSplashScreen( QPixmap( QStringLiteral(":/master/splash.png") ) ); + splashScreen->show(); + } if( MainWindow::initAuthentication() == false || - MainWindow::initAccessControl() == false ) + MainWindow::initAccessControl() == false ) { return -1; } VeyonMaster masterCore( &core ); - // hide splash-screen as soon as main-window is shown - splashScreen.finish( masterCore.mainWindow() ); - - masterCore.mainWindow()->show(); + if( masterCore.mainWindow() ) + { + splashScreen->finish( masterCore.mainWindow() ); + masterCore.mainWindow()->show(); + } return core.exec(); } diff --git a/master/veyon-master.1 b/master/veyon-master.1 index ebd2a0602..f7735c3d0 100644 --- a/master/veyon-master.1 +++ b/master/veyon-master.1 @@ -2,7 +2,7 @@ .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) -.TH VEYON MASTER 1 2018-12-07 Veyon +.TH VEYON-MASTER 1 2018-12-07 Veyon .SH NAME veyon-master \- Veyon Master Application .SH SYNOPSIS diff --git a/master/veyon-master.rc.in b/master/veyon-master.rc.in index 11df1fa76..ef6c5733f 100644 --- a/master/veyon-master.rc.in +++ b/master/veyon-master.rc.in @@ -1,11 +1,11 @@ veyonmastericon ICON data/veyon-master.ico #include -ID_MANIFEST RT_MANIFEST data/veyon-master.exe.manifest +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST data/veyon-master.exe.manifest VS_VERSION_INFO VERSIONINFO FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,@VERSION_BUILD@ - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGSMASK 0x0L FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_APP FILESUBTYPE VFT2_UNKNOWN @@ -17,11 +17,16 @@ BEGIN BEGIN VALUE "Comments", "Virtual Eye On Networks (https://veyon.io)\0" VALUE "CompanyName", "Veyon Solutions\0" - VALUE "FileDescription", "Veyon Master Application\0" + VALUE "ProductName", "Veyon\0" + VALUE "ProductVersion", "@VERSION_STRING@\0" + VALUE "FileDescription", "Veyon Master\0" VALUE "FileVersion", "@VERSION_STRING@\0" - VALUE "LegalCopyright", "Copyright (c) 2004-2019 Tobias Junghans\0" + VALUE "LegalCopyright", "Copyright (c) 2017-2025 Veyon Solutions / Tobias Junghans\0" VALUE "OriginalFilename", "veyon-master.exe\0" - VALUE "ProductName", "Veyon\0" END END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04E4 + END END diff --git a/nsis/veyon.nsi.in b/nsis/veyon.nsi.in index 5e6e6fc23..3bbeb84a2 100644 --- a/nsis/veyon.nsi.in +++ b/nsis/veyon.nsi.in @@ -2,10 +2,10 @@ !define COMP_NAME "Veyon Solutions" !define WEB_SITE "https://veyon.io" !define VERSION "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@.@VERSION_BUILD@" -!define COPYRIGHT "2004-2019 Tobias Junghans / Veyon Solutions" +!define COPYRIGHT "2004-2025 Veyon Solutions / Tobias Junghans" !define DESCRIPTION "Veyon Installer" -!define LICENSE_TXT "@CMAKE_SOURCE_DIR@/COPYING" -!define INSTALLER_NAME "veyon-${VERSION}-@MINGW_PLATFORM@-setup.exe" +!define LICENSE_TXT "COPYING" +!define INSTALLER_NAME "veyon-${VERSION}-@VEYON_WINDOWS_ARCH@-setup.exe" !define MAIN_APP_EXE "veyon-master.exe" !define INSTALL_TYPE "SetShellVarContext all" !define REG_ROOT "HKLM" @@ -24,7 +24,7 @@ VIAddVersionKey "FileVersion" "${VERSION}" ###################################################################### -SetCompressor /SOLID Lzma +SetCompressor /SOLID lzma Name "${APP_NAME}" Caption "${APP_NAME} ${VERSION}" OutFile "${INSTALLER_NAME}" @@ -32,7 +32,7 @@ BrandingText "${APP_NAME} ${VERSION}" XPStyle on InstallDirRegKey "${REG_ROOT}" "${REG_APP_PATH}" "" InstallDir "$PROGRAMFILES64\Veyon" -ShowInstDetails show +ShowInstDetails hide RequestExecutionLevel admin ###################################################################### @@ -44,13 +44,13 @@ RequestExecutionLevel admin !define MUI_ABORTWARNING !define MUI_UNABORTWARNING -!define MUI_WELCOMEFINISHPAGE_BITMAP "@CMAKE_SOURCE_DIR@/nsis/welcome-page.bmp" -!define MUI_UNWELCOMEFINISHPAGE_BITMAP "@CMAKE_SOURCE_DIR@/nsis/welcome-page.bmp" +!define MUI_WELCOMEFINISHPAGE_BITMAP "nsis/welcome-page.bmp" +!define MUI_UNWELCOMEFINISHPAGE_BITMAP "nsis/welcome-page.bmp" -!define MUI_ICON "@CMAKE_SOURCE_DIR@/nsis/installer.ico" -!define MUI_UNICON "@CMAKE_SOURCE_DIR@/nsis/uninstaller.ico" +!define MUI_ICON "nsis/installer.ico" +!define MUI_UNICON "nsis/uninstaller.ico" !define MUI_HEADERIMAGE -!define MUI_HEADERIMAGE_BITMAP "@CMAKE_SOURCE_DIR@/nsis/header.bmp" +!define MUI_HEADERIMAGE_BITMAP "nsis/header.bmp" !define MUI_HEADERIMAGE_RIGHT !define MUI_LANGDLL_REGISTRY_ROOT "${REG_ROOT}" @@ -178,11 +178,17 @@ File "translations/*.qm" # QCA plugins SetOutPath "$INSTDIR\crypto" File "crypto/*.dll" +# Qt image format plugin +SetOutPath "$INSTDIR\imageformats" +File "imageformats/qjpeg.dll" # Qt platform plugin SetOutPath "$INSTDIR\platforms" File "platforms/qwindows.dll" SetOutPath "$INSTDIR\styles" File "styles/*.dll" +# Qt TLS backend +SetOutPath "$INSTDIR\tls" +File "tls/qopensslbackend.dll" # configuration ExecWait '"$INSTDIR\veyon-wcli.exe" service register' ExecWait '"$INSTDIR\veyon-wcli.exe" config set Network/FirewallExceptionEnabled 1' @@ -295,9 +301,11 @@ Delete "$INSTDIR\*.dll" Delete "$INSTDIR\*.TXT" Delete "$INSTDIR\*.url" RmDir /r "$INSTDIR\crypto" +RmDir /r "$INSTDIR\imageformats" RmDir /r "$INSTDIR\plugins" RmDir /r "$INSTDIR\platforms" RmDir /r "$INSTDIR\styles" +RmDir /r "$INSTDIR\tls" RmDir /r "$INSTDIR\translations" RmDir /r "$INSTDIR\interception" diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index d171cc0bf..e311eb745 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -1,7 +1,7 @@ -FILE(GLOB plugins RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) +file(GLOB plugins RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) -FOREACH(plugin ${plugins}) - IF(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${plugin}) - ADD_SUBDIRECTORY(${plugin}) - ENDIF() -ENDFOREACH() +foreach(plugin ${plugins}) + if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${plugin}) + add_subdirectory(${plugin}) + endif() +endforeach() diff --git a/plugins/authkeys/AuthKeysConfiguration.h b/plugins/authkeys/AuthKeysConfiguration.h new file mode 100644 index 000000000..bd2ff3229 --- /dev/null +++ b/plugins/authkeys/AuthKeysConfiguration.h @@ -0,0 +1,44 @@ +/* + * AuthKeysConfiguration.h - configuration values for AuthKeys plugin + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +#include "Configuration/Proxy.h" + +#define FOREACH_AUTH_KEYS_CONFIG_PROPERTY(OP) \ + OP( VeyonConfiguration, m_configuration, QString, privateKeyBaseDir, setPrivateKeyBaseDir, "PrivateKeyBaseDir", "AuthKeys", QDir::toNativeSeparators( QStringLiteral( "%GLOBALAPPDATA%/keys/private" ) ), Configuration::Property::Flag::Advanced ) \ + OP( VeyonConfiguration, m_configuration, QString, publicKeyBaseDir, setPublicKeyBaseDir, "PublicKeyBaseDir", "AuthKeys", QDir::toNativeSeparators( QStringLiteral( "%GLOBALAPPDATA%/keys/public" ) ), Configuration::Property::Flag::Advanced ) \ + +#define FOREACH_AUTH_KEYS_LEGACY_CONFIG_PROPERTY(OP) \ + OP( VeyonConfiguration, m_configuration, QString, legacyPrivateKeyBaseDir, setLegacyPrivateKeyBaseDir, "PrivateKeyBaseDir", "Authentication", QDir::toNativeSeparators( QStringLiteral( "%GLOBALAPPDATA%/keys/private" ) ), Configuration::Property::Flag::Legacy ) \ + OP( VeyonConfiguration, m_configuration, QString, legacyPublicKeyBaseDir, setLegacyPublicKeyBaseDir, "PublicKeyBaseDir", "Authentication", QDir::toNativeSeparators( QStringLiteral( "%GLOBALAPPDATA%/keys/public" ) ), Configuration::Property::Flag::Legacy ) \ + +#define FOREACH_AUTH_KEYS_ALL_CONFIG_PROPERTY(OP) \ + FOREACH_AUTH_KEYS_CONFIG_PROPERTY(OP) \ + FOREACH_AUTH_KEYS_LEGACY_CONFIG_PROPERTY(OP) + +// clazy:excludeall=missing-qobject-macro +DECLARE_CONFIG_PROXY(AuthKeysConfiguration, FOREACH_AUTH_KEYS_ALL_CONFIG_PROPERTY) diff --git a/plugins/authkeys/AuthKeysConfigurationPage.cpp b/plugins/authkeys/AuthKeysConfigurationWidget.cpp similarity index 53% rename from plugins/authkeys/AuthKeysConfigurationPage.cpp rename to plugins/authkeys/AuthKeysConfigurationWidget.cpp index 50ce66c12..a61ec63d5 100644 --- a/plugins/authkeys/AuthKeysConfigurationPage.cpp +++ b/plugins/authkeys/AuthKeysConfigurationWidget.cpp @@ -1,7 +1,7 @@ /* - * AuthKeysConfigurationPage.cpp - implementation of the authentication configuration page + * AuthKeysConfigurationWidget.cpp - implementation of the authentication configuration page * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,36 +26,43 @@ #include #include -#include "AuthKeysConfigurationPage.h" +#include "AuthKeysConfiguration.h" +#include "AuthKeysConfigurationWidget.h" #include "AuthKeysManager.h" #include "FileSystemBrowser.h" -#include "PlatformUserFunctions.h" +#include "UserGroupsBackendManager.h" #include "VeyonConfiguration.h" #include "Configuration/UiMapping.h" -#include "ui_AuthKeysConfigurationPage.h" +#include "ui_AuthKeysConfigurationWidget.h" -AuthKeysConfigurationPage::AuthKeysConfigurationPage() : - ConfigurationPage(), - ui(new Ui::AuthKeysConfigurationPage), - m_authKeyTableModel( this ), +AuthKeysConfigurationWidget::AuthKeysConfigurationWidget( AuthKeysConfiguration& configuration, + AuthKeysManager& manager ) : + QWidget( QApplication::activeWindow() ), + ui( new Ui::AuthKeysConfigurationWidget ), + m_configuration( configuration ), + m_manager( manager ), + m_authKeyTableModel( m_manager, this ), m_keyFilesFilter( tr( "Key files (*.pem)" ) ) { ui->setupUi(this); - Configuration::UiMapping::setFlags( ui->keyFileDirectories, Configuration::Property::Flag::Advanced ); + ui->privateKeyBaseDir->setText( m_configuration.privateKeyBaseDir() ); + ui->publicKeyBaseDir->setText( m_configuration.publicKeyBaseDir() ); #define CONNECT_BUTTON_SLOT(name) \ - connect( ui->name, &QAbstractButton::clicked, this, &AuthKeysConfigurationPage::name ); + connect( ui->name, &QAbstractButton::clicked, this, &AuthKeysConfigurationWidget::name ); - CONNECT_BUTTON_SLOT( openPublicKeyBaseDir ); - CONNECT_BUTTON_SLOT( openPrivateKeyBaseDir ); - CONNECT_BUTTON_SLOT( createKeyPair ); - CONNECT_BUTTON_SLOT( deleteKey ); - CONNECT_BUTTON_SLOT( importKey ); - CONNECT_BUTTON_SLOT( exportKey ); - CONNECT_BUTTON_SLOT( setAccessGroup ); + CONNECT_BUTTON_SLOT( openPublicKeyBaseDir ) + CONNECT_BUTTON_SLOT( openPrivateKeyBaseDir ) + CONNECT_BUTTON_SLOT( createKeyPair ) + CONNECT_BUTTON_SLOT( deleteKey ) + CONNECT_BUTTON_SLOT( importKey ) + CONNECT_BUTTON_SLOT( exportKey ) + CONNECT_BUTTON_SLOT( setAccessGroup ) + + FOREACH_AUTH_KEYS_CONFIG_PROPERTY(CONNECT_WIDGET_TO_PROPERTY) reloadKeyTable(); @@ -63,61 +70,40 @@ AuthKeysConfigurationPage::AuthKeysConfigurationPage() : } -AuthKeysConfigurationPage::~AuthKeysConfigurationPage() -{ - delete ui; -} - - - -void AuthKeysConfigurationPage::resetWidgets() -{ - FOREACH_VEYON_KEY_AUTHENTICATION_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY); - - reloadKeyTable(); -} - - -void AuthKeysConfigurationPage::connectWidgetsToProperties() +AuthKeysConfigurationWidget::~AuthKeysConfigurationWidget() { - FOREACH_VEYON_KEY_AUTHENTICATION_CONFIG_PROPERTY(CONNECT_WIDGET_TO_PROPERTY); + delete ui; } -void AuthKeysConfigurationPage::applyConfiguration() -{ -} -void AuthKeysConfigurationPage::openPublicKeyBaseDir() +void AuthKeysConfigurationWidget::openPublicKeyBaseDir() { - FileSystemBrowser( FileSystemBrowser::ExistingDirectory ). - exec( ui->publicKeyBaseDir ); + FileSystemBrowser(FileSystemBrowser::ExistingDirectory, this).exec(ui->publicKeyBaseDir); } -void AuthKeysConfigurationPage::openPrivateKeyBaseDir() +void AuthKeysConfigurationWidget::openPrivateKeyBaseDir() { - FileSystemBrowser( FileSystemBrowser::ExistingDirectory ). - exec( ui->privateKeyBaseDir ); + FileSystemBrowser(FileSystemBrowser::ExistingDirectory, this).exec(ui->privateKeyBaseDir); } -void AuthKeysConfigurationPage::createKeyPair() +void AuthKeysConfigurationWidget::createKeyPair() { const auto keyName = QInputDialog::getText( this, tr( "Authentication key name" ), tr( "Please enter the name of the user group or role for which to create an authentication key pair:") ); if( keyName.isEmpty() == false ) { - AuthKeysManager authKeysManager; - const auto success = authKeysManager.createKeyPair( keyName ); + const auto success = m_manager.createKeyPair( keyName ); - showResultMessage( success, tr( "Create key pair" ), authKeysManager.resultMessage() ); + showResultMessage( success, tr( "Create key pair" ), m_manager.resultMessage() ); reloadKeyTable(); } @@ -125,7 +111,7 @@ void AuthKeysConfigurationPage::createKeyPair() -void AuthKeysConfigurationPage::deleteKey() +void AuthKeysConfigurationWidget::deleteKey() { const auto title = ui->deleteKey->text(); @@ -139,10 +125,9 @@ void AuthKeysConfigurationPage::deleteKey() if( QMessageBox::question( this, title, tr( "Do you really want to delete authentication key \"%1/%2\"?" ).arg( name, type ) ) == QMessageBox::Yes ) { - AuthKeysManager authKeysManager; - const auto success = authKeysManager.deleteKey( name, type ); + const auto success = m_manager.deleteKey( name, type ); - showResultMessage( success, title, authKeysManager.resultMessage() ); + showResultMessage( success, title, m_manager.resultMessage() ); reloadKeyTable(); } @@ -155,7 +140,7 @@ void AuthKeysConfigurationPage::deleteKey() -void AuthKeysConfigurationPage::importKey() +void AuthKeysConfigurationWidget::importKey() { const auto title = ui->importKey->text(); @@ -165,27 +150,30 @@ void AuthKeysConfigurationPage::importKey() return; } - const auto keyName = QInputDialog::getText( this, tr( "Authentication key name" ), - tr( "Please enter the name of the user group or role for which to import the authentication key:"), - QLineEdit::Normal, - AuthKeysManager::keyNameFromExportedKeyFile( inputFile ) ); + auto keyName = AuthKeysManager::keyNameFromExportedKeyFile(inputFile); + if (keyName.isEmpty()) + { + keyName = QInputDialog::getText(this, tr("Authentication key name"), + tr("Please enter the name of the user group or role for which to import the authentication key.\n\nMake sure that the names of the keys belonging to each other are identical on all computers."), + QLineEdit::Normal); + } + if( keyName.isEmpty() ) { return; } - AuthKeysManager authKeysManager; - const auto keyType = authKeysManager.detectKeyType( inputFile ); - const auto success = authKeysManager.importKey( keyName, keyType, inputFile ); + const auto keyType = m_manager.detectKeyType( inputFile ); + const auto success = m_manager.importKey( keyName, keyType, inputFile ); - showResultMessage( success, title, authKeysManager.resultMessage() ); + showResultMessage( success, title, m_manager.resultMessage() ); reloadKeyTable(); } -void AuthKeysConfigurationPage::exportKey() +void AuthKeysConfigurationWidget::exportKey() { const auto title = ui->exportKey->text(); @@ -201,10 +189,9 @@ void AuthKeysConfigurationPage::exportKey() m_keyFilesFilter ); if( outputFile.isEmpty() == false ) { - AuthKeysManager authKeysManager; - const auto success = authKeysManager.exportKey( name, type, outputFile ); + const auto success = m_manager.exportKey( name, type, outputFile, true ); - showResultMessage( success, title, authKeysManager.resultMessage() ); + showResultMessage( success, title, m_manager.resultMessage() ); } } else @@ -215,7 +202,7 @@ void AuthKeysConfigurationPage::exportKey() -void AuthKeysConfigurationPage::setAccessGroup() +void AuthKeysConfigurationWidget::setAccessGroup() { const auto title = ui->setAccessGroup->text(); @@ -223,8 +210,8 @@ void AuthKeysConfigurationPage::setAccessGroup() if( key.isEmpty() == false ) { - const auto userGroups = VeyonCore::platform().userFunctions().userGroups( VeyonCore::config().domainGroupsForAccessControlEnabled() ); - const auto currentGroup = AuthKeysManager().accessGroup( key ); + const auto userGroups = VeyonCore::userGroupsBackendManager().configuredBackend()->userGroups(VeyonCore::config().useDomainUserGroups()); + const auto currentGroup = m_manager.accessGroup( key ); bool ok = false; const auto selectedGroup = QInputDialog::getItem( this, title, @@ -233,10 +220,9 @@ void AuthKeysConfigurationPage::setAccessGroup() if( ok && selectedGroup.isEmpty() == false ) { - AuthKeysManager manager; - const auto success = manager.setAccessGroup( key, selectedGroup ); + const auto success = m_manager.setAccessGroup( key, selectedGroup ); - showResultMessage( success, title, manager.resultMessage() ); + showResultMessage( success, title, m_manager.resultMessage() ); reloadKeyTable(); } @@ -249,7 +235,7 @@ void AuthKeysConfigurationPage::setAccessGroup() -void AuthKeysConfigurationPage::reloadKeyTable() +void AuthKeysConfigurationWidget::reloadKeyTable() { m_authKeyTableModel.reload(); ui->keyTable->resizeColumnsToContents(); @@ -257,7 +243,7 @@ void AuthKeysConfigurationPage::reloadKeyTable() -QString AuthKeysConfigurationPage::selectedKey() const +QString AuthKeysConfigurationWidget::selectedKey() const { const auto row = ui->keyTable->currentIndex().row(); if( row >= 0 && row < m_authKeyTableModel.rowCount() ) @@ -270,7 +256,7 @@ QString AuthKeysConfigurationPage::selectedKey() const -void AuthKeysConfigurationPage::showResultMessage( bool success, const QString& title, const QString& message ) +void AuthKeysConfigurationWidget::showResultMessage( bool success, const QString& title, const QString& message ) { if( message.isEmpty() ) { diff --git a/plugins/authkeys/AuthKeysConfigurationPage.h b/plugins/authkeys/AuthKeysConfigurationWidget.h similarity index 68% rename from plugins/authkeys/AuthKeysConfigurationPage.h rename to plugins/authkeys/AuthKeysConfigurationWidget.h index fdcfedfe4..c76c15c6e 100644 --- a/plugins/authkeys/AuthKeysConfigurationPage.h +++ b/plugins/authkeys/AuthKeysConfigurationWidget.h @@ -1,7 +1,7 @@ /* - * AuthKeysConfigurationPage.h - header for the AuthKeysConfigurationPage class + * AuthKeysConfigurationWidget.h - header for the AuthKeysConfigurationDialog class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,25 +24,26 @@ #pragma once +#include + #include "AuthKeysTableModel.h" -#include "ConfigurationPage.h" namespace Ui { -class AuthKeysConfigurationPage; +class AuthKeysConfigurationWidget; } -class AuthKeysConfigurationPage : public ConfigurationPage +class AuthKeysConfiguration; +class AuthKeysManager; + +// clazy:excludeall=ctor-missing-parent-argument +class AuthKeysConfigurationWidget : public QWidget { Q_OBJECT public: - AuthKeysConfigurationPage(); - ~AuthKeysConfigurationPage() override; - - void resetWidgets() override; - void connectWidgetsToProperties() override; - void applyConfiguration() override; + AuthKeysConfigurationWidget( AuthKeysConfiguration& configuration, AuthKeysManager& manager ); + ~AuthKeysConfigurationWidget() override; -private slots: +private: void openPublicKeyBaseDir(); void openPrivateKeyBaseDir(); void createKeyPair(); @@ -52,11 +53,12 @@ private slots: void setAccessGroup(); void reloadKeyTable(); -private: QString selectedKey() const; void showResultMessage( bool success, const QString& title, const QString& message ); - Ui::AuthKeysConfigurationPage *ui; + Ui::AuthKeysConfigurationWidget* ui; + AuthKeysConfiguration& m_configuration; + AuthKeysManager& m_manager; AuthKeysTableModel m_authKeyTableModel; const QString m_keyFilesFilter; diff --git a/plugins/authkeys/AuthKeysConfigurationPage.ui b/plugins/authkeys/AuthKeysConfigurationWidget.ui similarity index 93% rename from plugins/authkeys/AuthKeysConfigurationPage.ui rename to plugins/authkeys/AuthKeysConfigurationWidget.ui index d941e9b67..5b94f8686 100644 --- a/plugins/authkeys/AuthKeysConfigurationPage.ui +++ b/plugins/authkeys/AuthKeysConfigurationWidget.ui @@ -1,14 +1,7 @@ - AuthKeysConfigurationPage - - - Authentication keys - - - - :/core/application-x-pem-key.png:/core/application-x-pem-key.png - + AuthKeysConfigurationWidget + 0 @@ -130,9 +123,6 @@ - - ... - :/core/document-open.png:/core/document-open.png @@ -141,9 +131,6 @@ - - ... - :/core/document-open.png:/core/document-open.png diff --git a/plugins/authkeys/AuthKeysManager.cpp b/plugins/authkeys/AuthKeysManager.cpp index 419ac80ff..a6877b4b3 100644 --- a/plugins/authkeys/AuthKeysManager.cpp +++ b/plugins/authkeys/AuthKeysManager.cpp @@ -1,7 +1,7 @@ /* * AuthKeysManager.cpp - implementation of AuthKeysManager class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,7 +24,9 @@ #include #include +#include +#include "AuthKeysConfiguration.h" #include "AuthKeysManager.h" #include "CommandLineIO.h" #include "CryptoCore.h" @@ -33,8 +35,9 @@ #include "VeyonConfiguration.h" -AuthKeysManager::AuthKeysManager( QObject* parent ) : +AuthKeysManager::AuthKeysManager( AuthKeysConfiguration& configuration, QObject* parent ) : QObject( parent ), + m_configuration( configuration ), m_keyTypePrivate( QStringLiteral("private") ), m_keyTypePublic( QStringLiteral("public") ), m_checkPermissions( tr( "Please check your permissions." ) ), @@ -48,16 +51,24 @@ AuthKeysManager::AuthKeysManager( QObject* parent ) : +bool AuthKeysManager::isKeyNameValid( const QString& authKeyName ) +{ + static const QRegularExpression keyNameRX{QStringLiteral("^[\\w-]+$")}; + return keyNameRX.match(authKeyName).hasMatch(); +} + + + bool AuthKeysManager::createKeyPair( const QString& name ) { - if( VeyonCore::isAuthenticationKeyNameValid( name ) == false) + if( isKeyNameValid( name ) == false) { m_resultMessage = m_invalidKeyName; return false; } - const auto privateKeyFileName = VeyonCore::filesystem().privateKeyPath( name ); - const auto publicKeyFileName = VeyonCore::filesystem().publicKeyPath( name ); + const auto privateKeyFileName = privateKeyPath( name ); + const auto publicKeyFileName = publicKeyPath( name ); if( QFileInfo::exists( privateKeyFileName ) || QFileInfo::exists( publicKeyFileName ) ) { @@ -67,7 +78,7 @@ bool AuthKeysManager::createKeyPair( const QString& name ) CommandLineIO::print( tr( "Creating new key pair for \"%1\"" ).arg( name ) ); - const auto privateKey = CryptoCore::KeyGenerator().createRSA( CryptoCore::RsaKeySize ); + const auto privateKey = VeyonCore::cryptoCore().createPrivateKey(); const auto publicKey = privateKey.toPublicKey(); if( privateKey.isNull() || publicKey.isNull() ) @@ -123,7 +134,7 @@ bool AuthKeysManager::deleteKey( const QString& name, const QString& type ) -bool AuthKeysManager::exportKey( const QString& name, const QString& type, const QString& outputFile ) +bool AuthKeysManager::exportKey( const QString& name, const QString& type, const QString& outputFile, bool overwriteExisting ) { if( checkKey( name, type ) == false ) { @@ -138,7 +149,7 @@ bool AuthKeysManager::exportKey( const QString& name, const QString& type, const return false; } - if( QFileInfo::exists( outputFile ) ) + if( overwriteExisting == false && QFileInfo::exists( outputFile ) ) { m_resultMessage = tr( "File \"%1\" already exists." ).arg( outputFile ); return false; @@ -159,7 +170,7 @@ bool AuthKeysManager::exportKey( const QString& name, const QString& type, const bool AuthKeysManager::importKey( const QString& name, const QString& type, const QString& inputFile ) { - if( VeyonCore::isAuthenticationKeyNameValid( name ) == false) + if( isKeyNameValid( name ) == false) { m_resultMessage = m_invalidKeyName; return false; @@ -182,7 +193,7 @@ bool AuthKeysManager::importKey( const QString& name, const QString& type, const return false; } - keyFileName = VeyonCore::filesystem().privateKeyPath( name ); + keyFileName = privateKeyPath( name ); } else if( type == m_keyTypePublic ) { @@ -193,7 +204,7 @@ bool AuthKeysManager::importKey( const QString& name, const QString& type, const return false; } - keyFileName = VeyonCore::filesystem().publicKeyPath( name ); + keyFileName = publicKeyPath( name ); } else { @@ -235,10 +246,10 @@ bool AuthKeysManager::importKey( const QString& name, const QString& type, const QStringList AuthKeysManager::listKeys() { - const auto privateKeyBaseDir = VeyonCore::filesystem().expandPath( VeyonCore::config().privateKeyBaseDir() ); + const auto privateKeyBaseDir = VeyonCore::filesystem().expandPath( m_configuration.privateKeyBaseDir() ); const auto privateKeyDirs = QDir( privateKeyBaseDir ).entryList( QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name ); - const auto publicKeyBaseDir = VeyonCore::filesystem().expandPath( VeyonCore::config().publicKeyBaseDir() ); + const auto publicKeyBaseDir = VeyonCore::filesystem().expandPath( m_configuration.publicKeyBaseDir() ); const auto publicKeyDirs = QDir( publicKeyBaseDir ).entryList( QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name ); QStringList keys; @@ -269,14 +280,14 @@ QStringList AuthKeysManager::listKeys() bool AuthKeysManager::extractPublicFromPrivateKey( const QString& name ) { - if( VeyonCore::isAuthenticationKeyNameValid( name ) == false) + if( isKeyNameValid( name ) == false) { m_resultMessage = m_invalidKeyName; return false; } - const auto privateKeyFileName = VeyonCore::filesystem().privateKeyPath( name ); - const auto publicKeyFileName = VeyonCore::filesystem().publicKeyPath( name ); + const auto privateKeyFileName = privateKeyPath( name ); + const auto publicKeyFileName = publicKeyPath( name ); if( QFileInfo::exists( privateKeyFileName ) == false ) { @@ -421,7 +432,7 @@ QString AuthKeysManager::accessGroup( const QString& key ) -QString AuthKeysManager::keyPairId( const QString& key ) +QString AuthKeysManager::keyPairId(const QString& key) // clazy:exclude=qt6-qhash-signature { const auto nameAndType = key.split( QLatin1Char('/') ); const auto name = nameAndType.value( 0 ); @@ -460,11 +471,12 @@ QString AuthKeysManager::exportedKeyFileName( const QString& name, const QString QString AuthKeysManager::keyNameFromExportedKeyFile( const QString& keyFile ) { - QRegExp rx( QStringLiteral("^(.*)_(.*)_key.pem$") ); + static const QRegularExpression keyNameRX{QStringLiteral("^(.*)_(.*)_key.pem$")}; + const auto keyNameMatch = keyNameRX.match(QFileInfo(keyFile).fileName()); - if( rx.indexIn( QFileInfo( keyFile ).fileName() ) == 0 ) + if( keyNameMatch.hasMatch() ) { - return rx.cap( 1 ); + return keyNameMatch.captured( 1 ); } return {}; @@ -472,9 +484,29 @@ QString AuthKeysManager::keyNameFromExportedKeyFile( const QString& keyFile ) +QString AuthKeysManager::privateKeyPath( const QString& name ) const +{ + const QString d = VeyonCore::filesystem().expandPath( m_configuration.privateKeyBaseDir() ) + + QDir::separator() + name + QDir::separator() + QStringLiteral( "key" ); + + return QDir::toNativeSeparators( d ); +} + + + +QString AuthKeysManager::publicKeyPath(const QString& name) const +{ + const QString d = VeyonCore::filesystem().expandPath( m_configuration.publicKeyBaseDir() ) + + QDir::separator() + name + QDir::separator() + QStringLiteral( "key" ); + + return QDir::toNativeSeparators( d ); +} + + + bool AuthKeysManager::checkKey( const QString& name, const QString& type, bool checkIsReadable ) { - if( VeyonCore::isAuthenticationKeyNameValid( name ) == false ) + if( isKeyNameValid( name ) == false ) { m_resultMessage = m_invalidKeyName; return false; @@ -511,11 +543,12 @@ QString AuthKeysManager::keyFilePathFromType( const QString& name, const QString { if( type == m_keyTypePrivate ) { - return VeyonCore::filesystem().privateKeyPath( name ); + return privateKeyPath( name ); } - else if( type == m_keyTypePublic ) + + if( type == m_keyTypePublic ) { - return VeyonCore::filesystem().publicKeyPath( name ); + return publicKeyPath( name ); } return {}; @@ -531,7 +564,8 @@ bool AuthKeysManager::setKeyFilePermissions( const QString& name, const QString& { return setPrivateKeyFilePermissions( keyFilePath ); } - else if( type == m_keyTypePublic ) + + if( type == m_keyTypePublic ) { return setPublicKeyFilePermissions( keyFilePath ); } diff --git a/plugins/authkeys/AuthKeysManager.h b/plugins/authkeys/AuthKeysManager.h index 7d26ca4bd..7cfa51d43 100644 --- a/plugins/authkeys/AuthKeysManager.h +++ b/plugins/authkeys/AuthKeysManager.h @@ -1,7 +1,7 @@ /* * AuthKeysManager.h - declaration of AuthKeysManager class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,13 +26,17 @@ #include "CryptoCore.h" +class AuthKeysConfiguration; + class AuthKeysManager : public QObject { Q_OBJECT public: - explicit AuthKeysManager( QObject* parent = nullptr ); + explicit AuthKeysManager( AuthKeysConfiguration& configuration, QObject* parent = nullptr ); ~AuthKeysManager() override = default; + static bool isKeyNameValid( const QString& authKeyName ); + const QString& resultMessage() const { return m_resultMessage; @@ -40,7 +44,7 @@ class AuthKeysManager : public QObject bool createKeyPair( const QString& name ); bool deleteKey( const QString& name, const QString& type ); - bool exportKey( const QString& name, const QString& type, const QString& outputFile ); + bool exportKey( const QString& name, const QString& type, const QString& outputFile, bool overwriteExisting ); bool importKey( const QString& name, const QString& type, const QString& inputFile ); QStringList listKeys(); bool extractPublicFromPrivateKey( const QString& name ); @@ -58,6 +62,9 @@ class AuthKeysManager : public QObject static QString exportedKeyFileName( const QString& name, const QString& type ); static QString keyNameFromExportedKeyFile( const QString& keyFile ); + QString privateKeyPath( const QString& name ) const; + QString publicKeyPath( const QString& name ) const; + private: bool checkKey( const QString& name, const QString& type, bool checkIsReadable = true ); @@ -66,6 +73,7 @@ class AuthKeysManager : public QObject bool setPrivateKeyFilePermissions( const QString& fileName ) const; bool setPublicKeyFilePermissions( const QString& fileName ) const; + AuthKeysConfiguration& m_configuration; const QString m_keyTypePrivate; const QString m_keyTypePublic; const QString m_checkPermissions; diff --git a/plugins/authkeys/AuthKeysPlugin.cpp b/plugins/authkeys/AuthKeysPlugin.cpp index c1f01bff5..d42dcab8f 100644 --- a/plugins/authkeys/AuthKeysPlugin.cpp +++ b/plugins/authkeys/AuthKeysPlugin.cpp @@ -1,7 +1,7 @@ /* * AuthKeysPlugin.cpp - implementation of AuthKeysPlugin class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,13 +22,24 @@ * */ -#include "AuthKeysConfigurationPage.h" +#include +#include +#include +#include +#include + +#include "AuthKeysConfigurationWidget.h" #include "AuthKeysPlugin.h" #include "AuthKeysManager.h" +#include "Filesystem.h" +#include "VariantArrayMessage.h" +#include "VeyonConfiguration.h" AuthKeysPlugin::AuthKeysPlugin( QObject* parent ) : QObject( parent ), + m_configuration( &VeyonCore::config() ), + m_manager( m_configuration ), m_commands( { { QStringLiteral("create"), tr( "Create new authentication key pair" ) }, { QStringLiteral("delete"), tr( "Delete authentication key" ) }, @@ -43,23 +54,187 @@ AuthKeysPlugin::AuthKeysPlugin( QObject* parent ) : -QStringList AuthKeysPlugin::commands() const +void AuthKeysPlugin::upgrade(const QVersionNumber& oldVersion) { - return m_commands.keys(); + if( oldVersion < QVersionNumber( 2, 0 ) ) + { + m_configuration.setPublicKeyBaseDir( m_configuration.legacyPublicKeyBaseDir() ); + m_configuration.setPrivateKeyBaseDir( m_configuration.legacyPrivateKeyBaseDir() ); + } } -QString AuthKeysPlugin::commandHelp( const QString& command ) const +QWidget* AuthKeysPlugin::createAuthenticationConfigurationWidget() { - return m_commands.value( command ); + return new AuthKeysConfigurationWidget( m_configuration, m_manager ); +} + + + +bool AuthKeysPlugin::initializeCredentials() +{ + m_privateKey = {}; + + auto authKeyName = QProcessEnvironment::systemEnvironment().value( QStringLiteral("VEYON_AUTH_KEY_NAME") ); + + if( authKeyName.isEmpty() == false ) + { + if( AuthKeysManager::isKeyNameValid( authKeyName ) && + loadPrivateKey( m_manager.privateKeyPath( authKeyName ) ) ) + { + m_authKeyName = authKeyName; + return true; + } + } + else + { + // try to auto-detect private key file by searching for readable file + const auto privateKeyBaseDir = VeyonCore::filesystem().expandPath( m_configuration.privateKeyBaseDir() ); + const auto privateKeyDirs = QDir( privateKeyBaseDir ).entryList( QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name ); + + for( const auto& privateKeyDir : privateKeyDirs ) + { + if( loadPrivateKey( m_manager.privateKeyPath( privateKeyDir ) ) ) + { + m_authKeyName = privateKeyDir; + return true; + } + } + } + + return false; +} + + + +bool AuthKeysPlugin::hasCredentials() const +{ + return m_privateKey.isNull() == false; +} + + + +bool AuthKeysPlugin::checkCredentials() const +{ + if( hasCredentials() == false ) + { + vWarning() << "Authentication key files not set up properly!"; + + QMessageBox::critical( QApplication::activeWindow(), + authenticationTestTitle(), + tr( "Authentication key files are not set up properly on this computer. " + "Please create new key files or switch to a different authentication method " + "using the Veyon Configurator." ) ); + + return false; + } + + return true; +} + + + +VncServerClient::AuthState AuthKeysPlugin::performAuthentication( VncServerClient* client, VariantArrayMessage& message ) const +{ + switch( client->authState() ) + { + case VncServerClient::AuthState::Init: + client->setChallenge( CryptoCore::generateChallenge() ); + if( VariantArrayMessage( message.ioDevice() ).write( client->challenge() ).send() == false ) + { + vWarning() << "failed to send challenge"; + return VncServerClient::AuthState::Failed; + } + return VncServerClient::AuthState::Stage1; + + case VncServerClient::AuthState::Stage1: + { + // get authentication key name + const auto authKeyName = message.read().toString(); // Flawfinder: ignore + + if( AuthKeysManager::isKeyNameValid( authKeyName ) == false ) + { + vDebug() << "invalid auth key name!"; + return VncServerClient::AuthState::Failed; + } + + // now try to verify received signed data using public key of the user + // under which the client claims to run + const auto signature = message.read().toByteArray(); // Flawfinder: ignore + + const auto publicKeyPath = m_manager.publicKeyPath( authKeyName ); + + CryptoCore::PublicKey publicKey( publicKeyPath ); + if( publicKey.isNull() || publicKey.isPublic() == false ) + { + vWarning() << "failed to load public key from" << publicKeyPath; + return VncServerClient::AuthState::Failed; + } + + vDebug() << "loaded public key from" << publicKeyPath; + if( publicKey.verifyMessage( client->challenge(), signature, CryptoCore::DefaultSignatureAlgorithm ) == false ) + { + vWarning() << "FAIL"; + return VncServerClient::AuthState::Failed; + } + + vDebug() << "SUCCESS"; + return VncServerClient::AuthState::Successful; + } + + default: + break; + } + + return VncServerClient::AuthState::Failed; } -ConfigurationPage* AuthKeysPlugin::createConfigurationPage() +bool AuthKeysPlugin::authenticate( QIODevice* socket ) const { - return new AuthKeysConfigurationPage(); + VariantArrayMessage challengeReceiveMessage( socket ); + challengeReceiveMessage.receive(); + const auto challenge = challengeReceiveMessage.read().toByteArray(); + + if( challenge.size() != CryptoCore::ChallengeSize ) + { + vCritical() << QThread::currentThreadId() << "challenge size mismatch!"; + return false; + } + + // create local copy of private key so we can modify it within our own thread + auto key = m_privateKey; + + if( key.isNull() || key.canSign() == false ) + { + vCritical() << QThread::currentThreadId() << "invalid private key!"; + return false; + } + + const auto signature = key.signMessage( challenge, CryptoCore::DefaultSignatureAlgorithm ); + + VariantArrayMessage challengeResponseMessage( socket ); + challengeResponseMessage.write( m_authKeyName ); + challengeResponseMessage.write( signature ); + challengeResponseMessage.send(); + + return true; +} + + + +QStringList AuthKeysPlugin::commands() const +{ + return m_commands.keys(); +} + + + +QString AuthKeysPlugin::commandHelp( const QString& command ) const +{ + return m_commands.value( command ); } @@ -67,6 +242,11 @@ ConfigurationPage* AuthKeysPlugin::createConfigurationPage() CommandLinePluginInterface::RunResult AuthKeysPlugin::handle_help( const QStringList& arguments ) { const auto command = arguments.value( 0 ); + if( command.isEmpty() ) + { + error( tr("Please specify the command to display help for.") ); + return NoResult; + } const QMap commands = { { QStringLiteral("create"), @@ -110,9 +290,9 @@ CommandLinePluginInterface::RunResult AuthKeysPlugin::handle_help( const QString return NoResult; } - print( tr("Please specify the command to display help for!") ); + error( tr("The specified command does not exist or no help is available for it.") ); - return Unknown; + return NoResult; } @@ -127,15 +307,14 @@ CommandLinePluginInterface::RunResult AuthKeysPlugin::handle_setaccessgroup( con const auto key = arguments[0]; const auto accessGroup = arguments[1]; - AuthKeysManager manager; - if( manager.setAccessGroup( key, accessGroup ) == false ) + if( m_manager.setAccessGroup( key, accessGroup ) == false ) { - error( manager.resultMessage() ); + error( m_manager.resultMessage() ); return Failed; } - info( manager.resultMessage() ); + info( m_manager.resultMessage() ); return Successful; } @@ -149,15 +328,14 @@ CommandLinePluginInterface::RunResult AuthKeysPlugin::handle_create( const QStri return NotEnoughArguments; } - AuthKeysManager manager; - if( manager.createKeyPair( arguments.first() ) == false ) + if( m_manager.createKeyPair( arguments.first() ) == false ) { - error( manager.resultMessage() ); + error( m_manager.resultMessage() ); return Failed; } - info( manager.resultMessage() ); + info( m_manager.resultMessage() ); return Successful; } @@ -166,7 +344,7 @@ CommandLinePluginInterface::RunResult AuthKeysPlugin::handle_create( const QStri CommandLinePluginInterface::RunResult AuthKeysPlugin::handle_delete( const QStringList& arguments ) { - if( arguments.size() < 1 ) + if( arguments.isEmpty() ) { return NotEnoughArguments; } @@ -175,15 +353,14 @@ CommandLinePluginInterface::RunResult AuthKeysPlugin::handle_delete( const QStri const auto name = nameAndType.value( 0 ); const auto type = nameAndType.value( 1 ); - AuthKeysManager manager; - if( manager.deleteKey( name, type ) == false ) + if( m_manager.deleteKey( name, type ) == false ) { - error( manager.resultMessage() ); + error( m_manager.resultMessage() ); return Failed; } - info( manager.resultMessage() ); + info( m_manager.resultMessage() ); return Successful; } @@ -192,7 +369,7 @@ CommandLinePluginInterface::RunResult AuthKeysPlugin::handle_delete( const QStri CommandLinePluginInterface::RunResult AuthKeysPlugin::handle_export( const QStringList& arguments ) { - if( arguments.size() < 1 ) + if( arguments.isEmpty() ) { return NotEnoughArguments; } @@ -208,15 +385,14 @@ CommandLinePluginInterface::RunResult AuthKeysPlugin::handle_export( const QStri outputFile = AuthKeysManager::exportedKeyFileName( name, type ); } - AuthKeysManager manager; - if( manager.exportKey( name, type, outputFile ) == false ) + if( m_manager.exportKey( name, type, outputFile, arguments.contains( QLatin1String("-f") ) ) == false ) { - error( manager.resultMessage() ); + error( m_manager.resultMessage() ); return Failed; } - info( manager.resultMessage() ); + info( m_manager.resultMessage() ); return Successful; } @@ -225,11 +401,17 @@ CommandLinePluginInterface::RunResult AuthKeysPlugin::handle_export( const QStri CommandLinePluginInterface::RunResult AuthKeysPlugin::handle_import( const QStringList& arguments ) { - if( arguments.size() < 1 ) + if( arguments.isEmpty() ) { return NotEnoughArguments; } + if( QFileInfo::exists( arguments[0] ) ) + { + error( tr( "Please specify the key name (e.g. \"teacher/public\") as the first argument." ) ); + return InvalidArguments; + } + const auto nameAndType = arguments[0].split( QLatin1Char('/') ); const auto name = nameAndType.value( 0 ); const auto type = nameAndType.value( 1 ); @@ -241,15 +423,14 @@ CommandLinePluginInterface::RunResult AuthKeysPlugin::handle_import( const QStri inputFile = AuthKeysManager::exportedKeyFileName( name, type ); } - AuthKeysManager manager; - if( manager.importKey( name, type, inputFile ) == false ) + if( m_manager.importKey( name, type, inputFile ) == false ) { - error( manager.resultMessage() ); + error( m_manager.resultMessage() ); return Failed; } - info( manager.resultMessage() ); + info( m_manager.resultMessage() ); return Successful; } @@ -279,40 +460,55 @@ CommandLinePluginInterface::RunResult AuthKeysPlugin::handle_extract( const QStr return NotEnoughArguments; } - AuthKeysManager manager; - if( manager.extractPublicFromPrivateKey( arguments.first() ) == false ) + if( m_manager.extractPublicFromPrivateKey( arguments.first() ) == false ) { - error( manager.resultMessage() ); + error( m_manager.resultMessage() ); return Failed; } - info( manager.resultMessage() ); + info( m_manager.resultMessage() ); return Successful; } +bool AuthKeysPlugin::loadPrivateKey( const QString& privateKeyFile ) +{ + vDebug() << privateKeyFile; + + if( privateKeyFile.isEmpty() ) + { + return false; + } + + m_privateKey = CryptoCore::PrivateKey( privateKeyFile ); + + return m_privateKey.isNull() == false && m_privateKey.isPrivate(); +} + + + void AuthKeysPlugin::printAuthKeyTable() { - AuthKeysTableModel tableModel; + AuthKeysTableModel tableModel( m_manager ); tableModel.reload(); - CommandLineIO::TableHeader tableHeader( { tr("NAME"), tr("TYPE"), tr("PAIR ID"), tr("ACCESS GROUP") } ); - CommandLineIO::TableRows tableRows; + TableHeader tableHeader( { tr("NAME"), tr("TYPE"), tr("PAIR ID"), tr("ACCESS GROUP") } ); + TableRows tableRows; tableRows.reserve( tableModel.rowCount() ); for( int i = 0; i < tableModel.rowCount(); ++i ) { tableRows.append( { authKeysTableData( tableModel, i, AuthKeysTableModel::ColumnKeyName ), - authKeysTableData( tableModel, i, AuthKeysTableModel::ColumnKeyType ), - authKeysTableData( tableModel, i, AuthKeysTableModel::ColumnKeyPairID ), - authKeysTableData( tableModel, i, AuthKeysTableModel::ColumnAccessGroup ) } ); + authKeysTableData( tableModel, i, AuthKeysTableModel::ColumnKeyType ), + authKeysTableData( tableModel, i, AuthKeysTableModel::ColumnKeyPairID ), + authKeysTableData( tableModel, i, AuthKeysTableModel::ColumnAccessGroup ) } ); } - CommandLineIO::printTable( CommandLineIO::Table( tableHeader, tableRows ) ); + printTable( Table( tableHeader, tableRows ) ); } @@ -326,10 +522,13 @@ QString AuthKeysPlugin::authKeysTableData( const AuthKeysTableModel& tableModel, void AuthKeysPlugin::printAuthKeyList() { - const auto keys = AuthKeysManager().listKeys(); + const auto keys = m_manager.listKeys(); for( const auto& key : keys ) { print( key ); } } + + +IMPLEMENT_CONFIG_PROXY(AuthKeysConfiguration) diff --git a/plugins/authkeys/AuthKeysPlugin.h b/plugins/authkeys/AuthKeysPlugin.h index cde3c1bc9..ab9023607 100644 --- a/plugins/authkeys/AuthKeysPlugin.h +++ b/plugins/authkeys/AuthKeysPlugin.h @@ -1,7 +1,7 @@ /* * AuthKeysPlugin.h - declaration of AuthKeysPlugin class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,35 +24,37 @@ #pragma once +#include "AuthenticationPluginInterface.h" +#include "AuthKeysConfiguration.h" +#include "AuthKeysManager.h" #include "CommandLineIO.h" #include "CommandLinePluginInterface.h" -#include "ConfigurationPagePluginInterface.h" class AuthKeysTableModel; class AuthKeysPlugin : public QObject, + AuthenticationPluginInterface, CommandLinePluginInterface, PluginInterface, - CommandLineIO, - ConfigurationPagePluginInterface + CommandLineIO { Q_OBJECT Q_PLUGIN_METADATA(IID "io.veyon.Veyon.Plugins.AuthKeys") Q_INTERFACES(PluginInterface - CommandLinePluginInterface - ConfigurationPagePluginInterface) + AuthenticationPluginInterface + CommandLinePluginInterface) public: explicit AuthKeysPlugin( QObject* parent = nullptr ); ~AuthKeysPlugin() override = default; Plugin::Uid uid() const override { - return QStringLiteral("4790bad8-4c56-40d5-8361-099a68f0c24b"); + return Plugin::Uid{ QStringLiteral("0c69b301-81b4-42d6-8fae-128cdd113314") }; } QVersionNumber version() const override { - return QVersionNumber( 1, 1 ); + return QVersionNumber( 2, 0 ); } QString name() const override @@ -62,7 +64,7 @@ class AuthKeysPlugin : public QObject, QString description() const override { - return tr( "Command line support for managing authentication keys" ); + return tr( "Key file authentication" ); } QString vendor() const override @@ -75,6 +77,25 @@ class AuthKeysPlugin : public QObject, return QStringLiteral( "Tobias Junghans" ); } + void upgrade( const QVersionNumber& oldVersion ) override; + + QString authenticationMethodName() const override + { + return tr("Key file"); + } + + QWidget* createAuthenticationConfigurationWidget() override; + + bool initializeCredentials() override; + bool hasCredentials() const override; + bool checkCredentials() const override; + + // server side authentication + VncServerClient::AuthState performAuthentication( VncServerClient* client, VariantArrayMessage& message ) const override; + + // client side authentication + bool authenticate( QIODevice* socket ) const override; + QString commandLineModuleName() const override { return QStringLiteral( "authkeys" ); @@ -88,9 +109,7 @@ class AuthKeysPlugin : public QObject, QStringList commands() const override; QString commandHelp( const QString& command ) const override; - ConfigurationPage* createConfigurationPage() override; - -public slots: +public Q_SLOTS: CommandLinePluginInterface::RunResult handle_help( const QStringList& arguments ); CommandLinePluginInterface::RunResult handle_setaccessgroup( const QStringList& arguments ); CommandLinePluginInterface::RunResult handle_create( const QStringList& arguments ); @@ -101,9 +120,17 @@ public slots: CommandLinePluginInterface::RunResult handle_extract( const QStringList& arguments ); private: - static void printAuthKeyTable(); + bool loadPrivateKey( const QString& privateKeyFile ); + + void printAuthKeyTable(); static QString authKeysTableData( const AuthKeysTableModel& tableModel, int row, int column ); - static void printAuthKeyList(); + void printAuthKeyList(); + + AuthKeysConfiguration m_configuration; + AuthKeysManager m_manager; + + CryptoCore::PrivateKey m_privateKey{}; + QString m_authKeyName; QMap m_commands; diff --git a/plugins/authkeys/AuthKeysTableModel.cpp b/plugins/authkeys/AuthKeysTableModel.cpp index fd4ab786b..bf1e9a540 100644 --- a/plugins/authkeys/AuthKeysTableModel.cpp +++ b/plugins/authkeys/AuthKeysTableModel.cpp @@ -1,7 +1,7 @@ /* * AuthKeysTableModel.cpp - implementation of AuthKeysTableModel class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,27 +25,19 @@ #include "AuthKeysTableModel.h" #include "AuthKeysManager.h" -AuthKeysTableModel::AuthKeysTableModel( QObject* parent ) : +AuthKeysTableModel::AuthKeysTableModel( AuthKeysManager& manager, QObject* parent ) : QAbstractTableModel( parent ), - m_manager( new AuthKeysManager( this ) ), - m_keys() + m_manager( manager ) { } -AuthKeysTableModel::~AuthKeysTableModel() -{ - delete m_manager; -} - - - void AuthKeysTableModel::reload() { beginResetModel(); - m_keys = m_manager->listKeys(); + m_keys = m_manager.listKeys(); endResetModel(); } @@ -74,7 +66,7 @@ QVariant AuthKeysTableModel::data( const QModelIndex& index, int role ) const { if( index.isValid() == false || role != Qt::DisplayRole ) { - return QVariant(); + return {}; } const auto& key = m_keys[index.row()]; @@ -83,12 +75,12 @@ QVariant AuthKeysTableModel::data( const QModelIndex& index, int role ) const { case ColumnKeyName: return key.split( QLatin1Char('/') ).value( 0 ); case ColumnKeyType: return key.split( QLatin1Char('/') ).value( 1 ); - case ColumnAccessGroup: return m_manager->accessGroup( key ); - case ColumnKeyPairID: return m_manager->keyPairId( key ); + case ColumnAccessGroup: return m_manager.accessGroup( key ); + case ColumnKeyPairID: return m_manager.keyPairId( key ); default: break; } - return QVariant(); + return {}; } @@ -97,7 +89,7 @@ QVariant AuthKeysTableModel::headerData( int section, Qt::Orientation orientatio { if( orientation != Qt::Horizontal || role != Qt::DisplayRole ) { - return QVariant(); + return {}; } switch( section ) @@ -110,5 +102,5 @@ QVariant AuthKeysTableModel::headerData( int section, Qt::Orientation orientatio break; } - return QVariant(); + return {}; } diff --git a/plugins/authkeys/AuthKeysTableModel.h b/plugins/authkeys/AuthKeysTableModel.h index 24eba90d5..14af56d5f 100644 --- a/plugins/authkeys/AuthKeysTableModel.h +++ b/plugins/authkeys/AuthKeysTableModel.h @@ -1,7 +1,7 @@ /* * AuthKeysTableModel.h - declaration of AuthKeysTableModel class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -40,8 +40,8 @@ class AuthKeysTableModel : public QAbstractTableModel ColumnCount }; - explicit AuthKeysTableModel( QObject* parent = nullptr ); - ~AuthKeysTableModel() override; + explicit AuthKeysTableModel( AuthKeysManager& manager, QObject* parent = nullptr ); + ~AuthKeysTableModel() override = default; void reload(); @@ -56,7 +56,7 @@ class AuthKeysTableModel : public QAbstractTableModel QVariant headerData( int section, Qt::Orientation orientation, int role ) const override; private: - AuthKeysManager* m_manager; - QStringList m_keys; + AuthKeysManager& m_manager; + QStringList m_keys{}; }; diff --git a/plugins/authkeys/CMakeLists.txt b/plugins/authkeys/CMakeLists.txt index 517c6e75f..c96104c50 100644 --- a/plugins/authkeys/CMakeLists.txt +++ b/plugins/authkeys/CMakeLists.txt @@ -1,13 +1,14 @@ -INCLUDE(BuildPlugin) +include(BuildVeyonPlugin) -BUILD_PLUGIN(authkeys +build_veyon_plugin(authkeys AuthKeysPlugin.cpp - AuthKeysConfigurationPage.cpp - AuthKeysConfigurationPage.ui + AuthKeysConfigurationWidget.cpp + AuthKeysConfigurationWidget.ui AuthKeysTableModel.cpp AuthKeysManager.cpp AuthKeysPlugin.h - AuthKeysConfigurationPage.h + AuthKeysConfigurationWidget.h + AuthKeysConfiguration.h AuthKeysTableModel.h AuthKeysManager.h -) + ) diff --git a/core/src/PasswordDialog.cpp b/plugins/authlogon/AuthLogonDialog.cpp similarity index 70% rename from core/src/PasswordDialog.cpp rename to plugins/authlogon/AuthLogonDialog.cpp index 06b068984..8d0245526 100644 --- a/core/src/PasswordDialog.cpp +++ b/plugins/authlogon/AuthLogonDialog.cpp @@ -1,7 +1,7 @@ /* - * PasswordDialog.cpp - dialog for querying logon credentials + * AuthLogonDialog.cpp - dialog for querying logon credentials * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,15 +25,15 @@ #include #include -#include "PasswordDialog.h" +#include "AuthLogonDialog.h" #include "PlatformUserFunctions.h" -#include "ui_PasswordDialog.h" +#include "ui_AuthLogonDialog.h" -PasswordDialog::PasswordDialog( QWidget *parent ) : +AuthLogonDialog::AuthLogonDialog( QWidget *parent ) : QDialog( parent ), - ui( new Ui::PasswordDialog ) + ui( new Ui::AuthLogonDialog ) { ui->setupUi( this ); @@ -51,40 +51,28 @@ PasswordDialog::PasswordDialog( QWidget *parent ) : -PasswordDialog::~PasswordDialog() +AuthLogonDialog::~AuthLogonDialog() { delete ui; } -QString PasswordDialog::username() const +QString AuthLogonDialog::username() const { return ui->username->text(); } -QString PasswordDialog::password() const +CryptoCore::PlaintextPassword AuthLogonDialog::password() const { - return ui->password->text(); + return ui->password->text().toUtf8(); } - -AuthenticationCredentials PasswordDialog::credentials() const -{ - AuthenticationCredentials cred; - cred.setLogonUsername( username() ); - cred.setLogonPassword( password() ); - - return cred; -} - - - -void PasswordDialog::accept() +void AuthLogonDialog::accept() { if( VeyonCore::platform().userFunctions().authenticate( username(), password() ) == false ) { @@ -100,7 +88,7 @@ void PasswordDialog::accept() -void PasswordDialog::updateOkButton() +void AuthLogonDialog::updateOkButton() { ui->buttonBox->button( QDialogButtonBox::Ok )-> setEnabled( !username().isEmpty() && !password().isEmpty() ); diff --git a/core/include/PasswordDialog.h b/plugins/authlogon/AuthLogonDialog.h similarity index 68% rename from core/include/PasswordDialog.h rename to plugins/authlogon/AuthLogonDialog.h index 9adc69f3e..41346e5e3 100644 --- a/core/include/PasswordDialog.h +++ b/plugins/authlogon/AuthLogonDialog.h @@ -1,7 +1,7 @@ /* - * PasswordDialog.h - declaration of password dialog + * AuthLogonDialog.h - declaration of password dialog * - * Copyright (c) 2010-2016 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,31 +24,29 @@ #pragma once -#include "AuthenticationCredentials.h" +#include "CryptoCore.h" #include -namespace Ui { class PasswordDialog; } +namespace Ui { class AuthLogonDialog; } -class VEYON_CORE_EXPORT PasswordDialog : public QDialog +class AuthLogonDialog : public QDialog { Q_OBJECT public: - explicit PasswordDialog( QWidget *parent ); - ~PasswordDialog() override; + explicit AuthLogonDialog( QWidget *parent ); + ~AuthLogonDialog() override; QString username() const; - QString password() const; - - AuthenticationCredentials credentials() const; + CryptoCore::PlaintextPassword password() const; void accept() override; -private slots: +private Q_SLOTS: void updateOkButton(); private: - Ui::PasswordDialog *ui; + Ui::AuthLogonDialog *ui; } ; diff --git a/core/src/PasswordDialog.ui b/plugins/authlogon/AuthLogonDialog.ui similarity index 90% rename from core/src/PasswordDialog.ui rename to plugins/authlogon/AuthLogonDialog.ui index f06882490..3aaac1da0 100644 --- a/core/src/PasswordDialog.ui +++ b/plugins/authlogon/AuthLogonDialog.ui @@ -1,12 +1,12 @@ - PasswordDialog - + AuthLogonDialog + Veyon Logon - + :/core/application-x-pem-key.png:/core/application-x-pem-key.png @@ -68,13 +68,13 @@ - + buttonBox accepted() - PasswordDialog + AuthLogonDialog accept() @@ -90,7 +90,7 @@ buttonBox rejected() - PasswordDialog + AuthLogonDialog reject() @@ -106,7 +106,7 @@ password textChanged(QString) - PasswordDialog + AuthLogonDialog updateOkButton() @@ -122,7 +122,7 @@ username textChanged(QString) - PasswordDialog + AuthLogonDialog updateOkButton() diff --git a/plugins/authlogon/AuthLogonPlugin.cpp b/plugins/authlogon/AuthLogonPlugin.cpp new file mode 100644 index 000000000..ebfa84d99 --- /dev/null +++ b/plugins/authlogon/AuthLogonPlugin.cpp @@ -0,0 +1,168 @@ +/* + * AuthLogonPlugin.cpp - implementation of AuthLogonPlugin class + * + * Copyright (c) 2018-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include +#include + +#include "AuthLogonPlugin.h" +#include "AuthLogonDialog.h" +#include "PlatformUserFunctions.h" +#include "VariantArrayMessage.h" + + +AuthLogonPlugin::AuthLogonPlugin( QObject* parent ) : + QObject( parent ) +{ +} + + + +bool AuthLogonPlugin::initializeCredentials() +{ + m_username.clear(); + m_password.clear(); + + if( qobject_cast( QCoreApplication::instance() ) ) + { + AuthLogonDialog logonDialog( QApplication::activeWindow() ); + if( logonDialog.exec() == AuthLogonDialog::Accepted ) + { + m_username = logonDialog.username(); + m_password = logonDialog.password(); + + return true; + } + } + + return false; +} + + + +bool AuthLogonPlugin::hasCredentials() const +{ + return m_username.isEmpty() == false && m_password.isEmpty() == false; +} + + + +bool AuthLogonPlugin::checkCredentials() const +{ + if( hasCredentials() == false ) + { + vWarning() << "Invalid username or password!"; + + QMessageBox::critical( QApplication::activeWindow(), + authenticationTestTitle(), + tr( "The supplied username or password is wrong. Please enter valid credentials or " + "switch to a different authentication method using the Veyon Configurator." ) ); + + return false; + } + + return true; +} + + + +VncServerClient::AuthState AuthLogonPlugin::performAuthentication( VncServerClient* client, VariantArrayMessage& message ) const +{ + switch( client->authState() ) + { + case VncServerClient::AuthState::Init: + client->setPrivateKey( VeyonCore::cryptoCore().createPrivateKey() ); + + if( VariantArrayMessage( message.ioDevice() ).write( client->privateKey().toPublicKey().toPEM() ).send() ) + { + return VncServerClient::AuthState::Stage1; + } + + vDebug() << "failed to send public key"; + return VncServerClient::AuthState::Failed; + + case VncServerClient::AuthState::Stage1: + { + auto privateKey = client->privateKey(); + + client->setUsername( message.read().toString() ); // Flawfinder: ignore + CryptoCore::PlaintextPassword encryptedPassword( message.read().toByteArray() ); // Flawfinder: ignore + + CryptoCore::PlaintextPassword decryptedPassword; + + if( privateKey.decrypt( encryptedPassword, + &decryptedPassword, + CryptoCore::DefaultEncryptionAlgorithm ) == false ) + { + vWarning() << "failed to decrypt password"; + return VncServerClient::AuthState::Failed; + } + + vInfo() << "authenticating user" << client->username(); + + if( VeyonCore::platform().userFunctions().authenticate( client->username(), decryptedPassword.toByteArray() ) ) + { + vDebug() << "SUCCESS"; + return VncServerClient::AuthState::Successful; + } + + vDebug() << "FAIL"; + return VncServerClient::AuthState::Failed; + } + + default: + break; + } + + return VncServerClient::AuthState::Failed; +} + + + +bool AuthLogonPlugin::authenticate( QIODevice* socket ) const +{ + VariantArrayMessage publicKeyMessage( socket ); + publicKeyMessage.receive(); + + auto publicKey = CryptoCore::PublicKey::fromPEM( publicKeyMessage.read().toString() ); + + if( publicKey.canEncrypt() == false ) + { + vCritical() << QThread::currentThreadId() << "can't encrypt with given public key!"; + return false; + } + + const auto encryptedPassword = publicKey.encrypt( m_password, CryptoCore::DefaultEncryptionAlgorithm ); + if( encryptedPassword.isEmpty() ) + { + vCritical() << QThread::currentThreadId() << "password encryption failed!"; + return false; + } + + VariantArrayMessage response( socket ); + response.write( m_username ); + response.write( encryptedPassword.toByteArray() ); + response.send(); + + return true; +} diff --git a/plugins/authlogon/AuthLogonPlugin.h b/plugins/authlogon/AuthLogonPlugin.h new file mode 100644 index 000000000..ede00257e --- /dev/null +++ b/plugins/authlogon/AuthLogonPlugin.h @@ -0,0 +1,99 @@ +/* + * AuthLogonPlugin.h - declaration of AuthLogonPlugin class + * + * Copyright (c) 2018-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "AuthenticationPluginInterface.h" + +class AuthLogonPlugin : public QObject, + AuthenticationPluginInterface, + PluginInterface +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "io.veyon.Veyon.Plugins.AuthLogon") + Q_INTERFACES(PluginInterface + AuthenticationPluginInterface) +public: + explicit AuthLogonPlugin( QObject* parent = nullptr ); + ~AuthLogonPlugin() override = default; + + Plugin::Uid uid() const override + { + return Plugin::Uid{ QStringLiteral("63611f7c-b457-42c7-832e-67d0f9281085") }; + } + + QVersionNumber version() const override + { + return QVersionNumber( 1, 0 ); + } + + QString name() const override + { + return QStringLiteral( "AuthLogon" ); + } + + QString description() const override + { + return tr( "Logon authentication" ); + } + + QString vendor() const override + { + return QStringLiteral( "Veyon Community" ); + } + + QString copyright() const override + { + return QStringLiteral( "Tobias Junghans" ); + } + + QString authenticationMethodName() const override + { + return tr("Logon"); + } + + QWidget* createAuthenticationConfigurationWidget() override + { + return nullptr; + } + + bool initializeCredentials() override; + bool hasCredentials() const override; + + bool checkCredentials() const override; + + VncServerClient::AuthState performAuthentication( VncServerClient* client, VariantArrayMessage& message ) const override; + + bool authenticate( QIODevice* socket ) const override; + + QString accessControlUser() const override + { + return m_username; + } + +private: + QString m_username; + CryptoCore::PlaintextPassword m_password; + +}; diff --git a/plugins/authlogon/CMakeLists.txt b/plugins/authlogon/CMakeLists.txt new file mode 100644 index 000000000..646956ed4 --- /dev/null +++ b/plugins/authlogon/CMakeLists.txt @@ -0,0 +1,9 @@ +include(BuildVeyonPlugin) + +build_veyon_plugin(authlogon + AuthLogonPlugin.cpp + AuthLogonPlugin.h + AuthLogonDialog.cpp + AuthLogonDialog.h + AuthLogonDialog.ui + ) diff --git a/plugins/authsimple/AuthSimpleConfiguration.h b/plugins/authsimple/AuthSimpleConfiguration.h new file mode 100644 index 000000000..c97d0c0a4 --- /dev/null +++ b/plugins/authsimple/AuthSimpleConfiguration.h @@ -0,0 +1,34 @@ +/* + * AuthSimpleConfiguration.h - configuration values for AuthSimple plugin + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "Configuration/Proxy.h" + +#define FOREACH_AUTH_SIMPLE_CONFIG_PROPERTY(OP) \ + OP( AuthSimpleConfiguration, m_configuration, Configuration::Password, password, setPassword, "Password", "AuthSimple", QString(), Configuration::Property::Flag::Standard ) \ + +// clazy:excludeall=missing-qobject-macro + +DECLARE_CONFIG_PROXY(AuthSimpleConfiguration, FOREACH_AUTH_SIMPLE_CONFIG_PROPERTY) diff --git a/plugins/authsimple/AuthSimpleDialog.cpp b/plugins/authsimple/AuthSimpleDialog.cpp new file mode 100644 index 000000000..c1057a274 --- /dev/null +++ b/plugins/authsimple/AuthSimpleDialog.cpp @@ -0,0 +1,81 @@ +/* + * AuthSimpleDialog.cpp - dialog for querying logon credentials + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include +#include + +#include "AuthSimpleDialog.h" +#include "AuthSimpleConfiguration.h" +#include "VeyonConfiguration.h" + +#include "ui_AuthSimpleDialog.h" + + +AuthSimpleDialog::AuthSimpleDialog( QWidget *parent ) : + QDialog( parent ), + ui( new Ui::AuthSimpleDialog ) +{ + ui->setupUi( this ); + ui->password->setFocus(); + + connect( ui->password, &QLineEdit::textChanged, this, [this]() { + ui->buttonBox->button( QDialogButtonBox::Ok )->setDisabled( password().isEmpty() ); + } ); + + ui->buttonBox->button( QDialogButtonBox::Ok )->setDisabled( true ); + + VeyonCore::enforceBranding( this ); +} + + + +AuthSimpleDialog::~AuthSimpleDialog() +{ + delete ui; +} + + + +CryptoCore::PlaintextPassword AuthSimpleDialog::password() const +{ + return ui->password->text().toUtf8(); +} + + + +void AuthSimpleDialog::accept() +{ + AuthSimpleConfiguration config( &VeyonCore::config() ); + + if( config.password().plainText() != password() ) + { + QMessageBox::critical( window(), + tr( "Authentication error" ), + tr( "Logon failed with given password. Please try again!" ) ); + } + else + { + QDialog::accept(); + } +} diff --git a/plugins/authsimple/AuthSimpleDialog.h b/plugins/authsimple/AuthSimpleDialog.h new file mode 100644 index 000000000..8eb3345d4 --- /dev/null +++ b/plugins/authsimple/AuthSimpleDialog.h @@ -0,0 +1,47 @@ +/* + * AuthSimpleDialog.h - declaration of password dialog + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "CryptoCore.h" + +#include + +namespace Ui { class AuthSimpleDialog; } + +class AuthSimpleDialog : public QDialog +{ + Q_OBJECT +public: + explicit AuthSimpleDialog( QWidget *parent ); + ~AuthSimpleDialog() override; + + CryptoCore::PlaintextPassword password() const; + + void accept() override; + +private: + Ui::AuthSimpleDialog *ui; + +} ; diff --git a/plugins/authsimple/AuthSimpleDialog.ui b/plugins/authsimple/AuthSimpleDialog.ui new file mode 100644 index 000000000..5fdb0cb97 --- /dev/null +++ b/plugins/authsimple/AuthSimpleDialog.ui @@ -0,0 +1,82 @@ + + + AuthSimpleDialog + + + Veyon Logon + + + + :/core/application-x-pem-key.png:/core/application-x-pem-key.png + + + + 15 + + + + + Please enter the Veyon password: + + + + + + + + 350 + 0 + + + + QLineEdit::Password + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + AuthSimpleDialog + accept() + + + 206 + 137 + + + 169 + 79 + + + + + buttonBox + rejected() + AuthSimpleDialog + reject() + + + 206 + 137 + + + 169 + 79 + + + + + diff --git a/plugins/authsimple/AuthSimplePlugin.cpp b/plugins/authsimple/AuthSimplePlugin.cpp new file mode 100644 index 000000000..27730650b --- /dev/null +++ b/plugins/authsimple/AuthSimplePlugin.cpp @@ -0,0 +1,188 @@ +/* + * AuthSimplePlugin.cpp - implementation of AuthSimplePlugin class + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include + +#include "AuthSimplePlugin.h" +#include "AuthSimpleConfiguration.h" +#include "AuthSimpleDialog.h" +#include "VariantArrayMessage.h" +#include "VeyonConfiguration.h" +#include "Configuration/UiMapping.h" + + +AuthSimplePlugin::AuthSimplePlugin( QObject* parent ) : + QObject( parent ) +{ +} + + + +QWidget* AuthSimplePlugin::createAuthenticationConfigurationWidget() +{ + auto lineEdit = new QLineEdit; + lineEdit->setEchoMode( QLineEdit::Password ); + + AuthSimpleConfiguration config( &VeyonCore::config() ); + + Configuration::UiMapping::initWidgetFromProperty( config.passwordProperty(), lineEdit ); + Configuration::UiMapping::connectWidgetToProperty( config.passwordProperty(), lineEdit ); + + return lineEdit; +} + + + +bool AuthSimplePlugin::initializeCredentials() +{ + m_password.clear(); + + if( qobject_cast( QCoreApplication::instance() ) ) + { + AuthSimpleDialog passwordDialog( QApplication::activeWindow() ); + if( passwordDialog.exec() == AuthSimpleDialog::Accepted ) + { + m_password = passwordDialog.password(); + + return true; + } + } + + return false; +} + + + +bool AuthSimplePlugin::hasCredentials() const +{ + return m_password.isEmpty() == false; +} + + + +bool AuthSimplePlugin::checkCredentials() const +{ + if( hasCredentials() == false ) + { + vWarning() << "Invalid password!"; + + QMessageBox::critical( QApplication::activeWindow(), + authenticationTestTitle(), + tr( "The supplied password is wrong. Please enter the correct password or " + "switch to a different authentication method using the Veyon Configurator." ) ); + + return false; + } + + return true; +} + + + +VncServerClient::AuthState AuthSimplePlugin::performAuthentication( VncServerClient* client, VariantArrayMessage& message ) const +{ + switch( client->authState() ) + { + case VncServerClient::AuthState::Init: + client->setPrivateKey( VeyonCore::cryptoCore().createPrivateKey() ); + + if( VariantArrayMessage( message.ioDevice() ).write( client->privateKey().toPublicKey().toPEM() ).send() ) + { + return VncServerClient::AuthState::Stage1; + } + + vDebug() << "failed to send public key"; + return VncServerClient::AuthState::Failed; + + case VncServerClient::AuthState::Stage1: + { + auto privateKey = client->privateKey(); + + CryptoCore::PlaintextPassword encryptedPassword( message.read().toByteArray() ); // Flawfinder: ignore + + CryptoCore::PlaintextPassword decryptedPassword; + + if( privateKey.decrypt( encryptedPassword, + &decryptedPassword, + CryptoCore::DefaultEncryptionAlgorithm ) == false ) + { + vWarning() << "failed to decrypt password"; + return VncServerClient::AuthState::Failed; + } + + vInfo() << "authenticating user" << client->username(); + + AuthSimpleConfiguration config( &VeyonCore::config() ); + + if( config.password().plainText() == decryptedPassword ) + { + vDebug() << "SUCCESS"; + return VncServerClient::AuthState::Successful; + } + + vDebug() << "FAIL"; + return VncServerClient::AuthState::Failed; + } + + default: + break; + } + + return VncServerClient::AuthState::Failed; + +} + + + +bool AuthSimplePlugin::authenticate( QIODevice* socket ) const +{ + VariantArrayMessage publicKeyMessage( socket ); + publicKeyMessage.receive(); + + auto publicKey = CryptoCore::PublicKey::fromPEM( publicKeyMessage.read().toString() ); + + if( publicKey.canEncrypt() == false ) + { + vCritical() << QThread::currentThreadId() << "can't encrypt with given public key!"; + return false; + } + + auto encryptedPassword = publicKey.encrypt( m_password, CryptoCore::DefaultEncryptionAlgorithm ); + if( encryptedPassword.isEmpty() ) + { + vCritical() << QThread::currentThreadId() << "password encryption failed!"; + return false; + } + + VariantArrayMessage response( socket ); + response.write( encryptedPassword.toByteArray() ); + response.send(); + + return true; +} + + +IMPLEMENT_CONFIG_PROXY(AuthSimpleConfiguration) diff --git a/plugins/authsimple/AuthSimplePlugin.h b/plugins/authsimple/AuthSimplePlugin.h new file mode 100644 index 000000000..528f77d2d --- /dev/null +++ b/plugins/authsimple/AuthSimplePlugin.h @@ -0,0 +1,90 @@ +/* + * AuthSimplePlugin.h - declaration of AuthSimplePlugin class + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "AuthenticationPluginInterface.h" + +class AuthSimplePlugin : public QObject, + AuthenticationPluginInterface, + PluginInterface +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "io.veyon.Veyon.Plugins.AuthSimple") + Q_INTERFACES(PluginInterface + AuthenticationPluginInterface) +public: + explicit AuthSimplePlugin( QObject* parent = nullptr ); + ~AuthSimplePlugin() override = default; + + Plugin::Uid uid() const override + { + return Plugin::Uid{ QStringLiteral("73430b14-ef69-4c75-a145-ba635d1cc676") }; + } + + QVersionNumber version() const override + { + return QVersionNumber( 1, 0 ); + } + + QString name() const override + { + return QStringLiteral( "AuthSimple" ); + } + + QString description() const override + { + return tr( "Simple password authentication" ); + } + + QString vendor() const override + { + return QStringLiteral( "Veyon Community" ); + } + + QString copyright() const override + { + return QStringLiteral( "Tobias Junghans" ); + } + + QString authenticationMethodName() const override + { + return tr("Simple password"); + } + + QWidget* createAuthenticationConfigurationWidget() override; + + bool initializeCredentials() override; + bool hasCredentials() const override; + + bool checkCredentials() const override; + + VncServerClient::AuthState performAuthentication( VncServerClient* client, VariantArrayMessage& message ) const override; + + bool authenticate( QIODevice* socket ) const override; + +private: + CryptoCore::PlaintextPassword m_password; + +}; diff --git a/plugins/authsimple/CMakeLists.txt b/plugins/authsimple/CMakeLists.txt new file mode 100644 index 000000000..8ae1d2f25 --- /dev/null +++ b/plugins/authsimple/CMakeLists.txt @@ -0,0 +1,10 @@ +include(BuildVeyonPlugin) + +build_veyon_plugin(authsimple + AuthSimplePlugin.cpp + AuthSimplePlugin.h + AuthSimpleConfiguration.h + AuthSimpleDialog.cpp + AuthSimpleDialog.h + AuthSimpleDialog.ui + ) diff --git a/plugins/builtindirectory/BuiltinDirectory.cpp b/plugins/builtindirectory/BuiltinDirectory.cpp index 899ffb28b..3f74134d2 100644 --- a/plugins/builtindirectory/BuiltinDirectory.cpp +++ b/plugins/builtindirectory/BuiltinDirectory.cpp @@ -1,7 +1,7 @@ /* * BuiltinDirectory.cpp - NetworkObjects from VeyonConfiguration * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -30,7 +30,7 @@ BuiltinDirectory::BuiltinDirectory( BuiltinDirectoryConfiguration& configuration, QObject* parent ) : - NetworkObjectDirectory( parent ), + NetworkObjectDirectory( configuration.directoryName(), parent ), m_configuration( configuration ) { } @@ -47,19 +47,19 @@ void BuiltinDirectory::update() for( const auto& networkObjectValue : networkObjects ) { - const NetworkObject networkObject( networkObjectValue.toObject() ); + const NetworkObject networkObject{networkObjectValue.toObject(), this}; if( networkObject.type() == NetworkObject::Type::Location ) { groupUids.append( networkObject.uid() ); // clazy:exclude=reserve-candidates - addOrUpdateObject( networkObject, NetworkObject( NetworkObject::Type::Root ) ); + addOrUpdateObject( networkObject, rootObject() ); updateLocation( networkObject, networkObjects ); } } - removeObjects( NetworkObject( NetworkObject::Type::Root ), [groupUids]( const NetworkObject& object ) { + removeObjects( rootObject(), [groupUids]( const NetworkObject& object ) { return object.type() == NetworkObject::Type::Location && groupUids.contains( object.uid() ) == false; } ); } @@ -71,7 +71,7 @@ void BuiltinDirectory::updateLocation( const NetworkObject& locationObject, cons for( const auto& networkObjectValue : networkObjects ) { - NetworkObject networkObject( networkObjectValue.toObject() ); + NetworkObject networkObject{networkObjectValue.toObject(), this}; if( networkObject.parentUid() == locationObject.uid() ) { diff --git a/plugins/builtindirectory/BuiltinDirectory.h b/plugins/builtindirectory/BuiltinDirectory.h index af68c4684..e2c9f0943 100644 --- a/plugins/builtindirectory/BuiltinDirectory.h +++ b/plugins/builtindirectory/BuiltinDirectory.h @@ -1,7 +1,7 @@ /* * BuiltinDirectory.h - NetworkObjects from VeyonConfiguration * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/plugins/builtindirectory/BuiltinDirectoryConfiguration.h b/plugins/builtindirectory/BuiltinDirectoryConfiguration.h index 66159b32b..ddb93d87f 100644 --- a/plugins/builtindirectory/BuiltinDirectoryConfiguration.h +++ b/plugins/builtindirectory/BuiltinDirectoryConfiguration.h @@ -1,7 +1,7 @@ /* * BuiltinDirectoryConfiguration.h - configuration values for BuiltinDirectory plugin * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -29,8 +29,11 @@ #include "Configuration/Proxy.h" #define FOREACH_BUILTIN_DIRECTORY_CONFIG_PROPERTY(OP) \ + OP( BuiltinDirectoryConfiguration, m_configuration, QString, directoryName, setDirectoryName, "DirectoryName", "BuiltinDirectory", BuiltinDirectoryConfiguration::tr("Builtin directory"), Configuration::Property::Flag::Standard ) \ OP( BuiltinDirectoryConfiguration, m_configuration, QJsonArray, networkObjects, setNetworkObjects, "NetworkObjects", "BuiltinDirectory", QJsonArray(), Configuration::Property::Flag::Standard ) \ /* legacy properties required for upgrade */ \ OP( BuiltinDirectoryConfiguration, m_configuration, QJsonArray, legacyLocalDataNetworkObjects, setLegacyLocalDataNetworkObjects, "NetworkObjects", "LocalData", QJsonArray(), Configuration::Property::Flag::Legacy ) \ +// clazy:excludeall=missing-qobject-macro + DECLARE_CONFIG_PROXY(BuiltinDirectoryConfiguration, FOREACH_BUILTIN_DIRECTORY_CONFIG_PROPERTY) diff --git a/plugins/builtindirectory/BuiltinDirectoryConfigurationPage.cpp b/plugins/builtindirectory/BuiltinDirectoryConfigurationPage.cpp index f78551901..0673ab1ce 100644 --- a/plugins/builtindirectory/BuiltinDirectoryConfigurationPage.cpp +++ b/plugins/builtindirectory/BuiltinDirectoryConfigurationPage.cpp @@ -1,7 +1,7 @@ /* * BuiltinDirectoryConfigurationPage.cpp - implementation of BuiltinDirectoryConfigurationPage * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -56,6 +56,8 @@ BuiltinDirectoryConfigurationPage::~BuiltinDirectoryConfigurationPage() void BuiltinDirectoryConfigurationPage::resetWidgets() { + FOREACH_BUILTIN_DIRECTORY_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY); + populateLocations(); ui->locationTableWidget->setCurrentCell( 0, 0 ); @@ -65,6 +67,7 @@ void BuiltinDirectoryConfigurationPage::resetWidgets() void BuiltinDirectoryConfigurationPage::connectWidgetsToProperties() { + FOREACH_BUILTIN_DIRECTORY_CONFIG_PROPERTY(CONNECT_WIDGET_TO_PROPERTY); } @@ -78,8 +81,10 @@ void BuiltinDirectoryConfigurationPage::applyConfiguration() void BuiltinDirectoryConfigurationPage::addLocation() { ObjectManager objectManager( m_configuration.networkObjects() ); - objectManager.add( NetworkObject( NetworkObject::Type::Location, tr( "New location" ), - {}, {}, {}, QUuid::createUuid() ) ); + objectManager.add( NetworkObject( nullptr, + NetworkObject::Type::Location, tr( "New location" ), + {}, + QUuid::createUuid() ) ); m_configuration.setNetworkObjects( objectManager.objects() ); populateLocations(); @@ -110,11 +115,22 @@ void BuiltinDirectoryConfigurationPage::updateLocation() void BuiltinDirectoryConfigurationPage::removeLocation() { + auto currentRow = ui->locationTableWidget->currentRow(); + ObjectManager objectManager( m_configuration.networkObjects() ); objectManager.remove( currentLocationObject().uid(), true ); m_configuration.setNetworkObjects( objectManager.objects() ); populateLocations(); + + if( currentRow > 0 ) + { + ui->locationTableWidget->setCurrentCell( currentRow-1, 0 ); + } + else if ( ui->locationTableWidget->rowCount() > 0 ) + { + ui->locationTableWidget->setCurrentCell( currentRow, 0 ); + } } @@ -128,8 +144,9 @@ void BuiltinDirectoryConfigurationPage::addComputer() } ObjectManager objectManager( m_configuration.networkObjects() ); - objectManager.add( NetworkObject( NetworkObject::Type::Host, tr( "New computer" ), - {}, {}, {}, + objectManager.add( NetworkObject( nullptr, + NetworkObject::Type::Host, tr( "New computer" ), + {}, QUuid::createUuid(), currentLocationUid ) ); m_configuration.setNetworkObjects( objectManager.objects() ); @@ -176,12 +193,14 @@ void BuiltinDirectoryConfigurationPage::populateLocations() ui->locationTableWidget->setUpdatesEnabled( false ); ui->locationTableWidget->clear(); + ui->addComputerButton->setEnabled( false ); + int rowCount = 0; const auto networkObjects = m_configuration.networkObjects(); for( const auto& networkObjectValue : networkObjects ) { - const NetworkObject networkObject( networkObjectValue.toObject() ); + const NetworkObject networkObject{networkObjectValue.toObject()}; if( networkObject.type() == NetworkObject::Type::Location ) { auto item = new QTableWidgetItem( networkObject.name() ); @@ -192,6 +211,11 @@ void BuiltinDirectoryConfigurationPage::populateLocations() } ui->locationTableWidget->setUpdatesEnabled( true ); + + if( rowCount > 0 ) + { + ui->addComputerButton->setEnabled( true ); + } } @@ -208,7 +232,7 @@ void BuiltinDirectoryConfigurationPage::populateComputers() const auto networkObjects = m_configuration.networkObjects(); for( const auto& networkObjectValue : networkObjects ) { - const NetworkObject networkObject( networkObjectValue.toObject() ); + const NetworkObject networkObject{networkObjectValue.toObject()}; if( networkObject.type() == NetworkObject::Type::Host && networkObject.parentUid() == parentUid ) @@ -219,8 +243,8 @@ void BuiltinDirectoryConfigurationPage::populateComputers() ui->computerTableWidget->setRowCount( rowCount+1 ); ui->computerTableWidget->setItem( rowCount, 0, nameItem ); - ui->computerTableWidget->setItem( rowCount, 1, new QTableWidgetItem( networkObject.hostAddress() ) ); - ui->computerTableWidget->setItem( rowCount, 2, new QTableWidgetItem( networkObject.macAddress() ) ); + ui->computerTableWidget->setItem( rowCount, 1, new QTableWidgetItem( networkObject.property( NetworkObject::Property::HostAddress ).toString() ) ); + ui->computerTableWidget->setItem( rowCount, 2, new QTableWidgetItem( networkObject.property( NetworkObject::Property::MacAddress ).toString() ) ); ++rowCount; } } @@ -235,11 +259,10 @@ NetworkObject BuiltinDirectoryConfigurationPage::currentLocationObject() const const auto selectedLocation = ui->locationTableWidget->currentItem(); if( selectedLocation ) { - return NetworkObject( NetworkObject::Type::Location, + return NetworkObject( nullptr, + NetworkObject::Type::Location, selectedLocation->text(), {}, - {}, - {}, selectedLocation->data( NetworkObjectModel::UidRole ).toUuid(), selectedLocation->data( NetworkObjectModel::ParentUidRole ).toUuid() ); } @@ -258,11 +281,13 @@ NetworkObject BuiltinDirectoryConfigurationPage::currentComputerObject() const auto hostAddressItem = ui->computerTableWidget->item( row, 1 ); auto macAddressItem = ui->computerTableWidget->item( row, 2 ); - return NetworkObject( NetworkObject::Type::Host, + return NetworkObject( nullptr, + NetworkObject::Type::Host, nameItem->text(), - hostAddressItem->text().trimmed(), - macAddressItem->text().trimmed(), - {}, + { + { NetworkObject::propertyKey(NetworkObject::Property::HostAddress), hostAddressItem->text().trimmed() }, + { NetworkObject::propertyKey(NetworkObject::Property::MacAddress), macAddressItem->text().trimmed() } + }, nameItem->data( NetworkObjectModel::UidRole ).toUuid(), nameItem->data( NetworkObjectModel::ParentUidRole ).toUuid() ); } diff --git a/plugins/builtindirectory/BuiltinDirectoryConfigurationPage.h b/plugins/builtindirectory/BuiltinDirectoryConfigurationPage.h index bb77ff161..3e1176527 100644 --- a/plugins/builtindirectory/BuiltinDirectoryConfigurationPage.h +++ b/plugins/builtindirectory/BuiltinDirectoryConfigurationPage.h @@ -1,7 +1,7 @@ /* * BuiltinDirectoryConfigurationPage.h - header for the BuiltinDirectoryConfigurationPage class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -44,7 +44,7 @@ class BuiltinDirectoryConfigurationPage : public ConfigurationPage void connectWidgetsToProperties() override; void applyConfiguration() override; -private slots: +private Q_SLOTS: void addLocation(); void updateLocation(); void removeLocation(); diff --git a/plugins/builtindirectory/BuiltinDirectoryConfigurationPage.ui b/plugins/builtindirectory/BuiltinDirectoryConfigurationPage.ui index 7d0c78bc0..7e5a0ba6c 100644 --- a/plugins/builtindirectory/BuiltinDirectoryConfigurationPage.ui +++ b/plugins/builtindirectory/BuiltinDirectoryConfigurationPage.ui @@ -3,201 +3,201 @@ BuiltinDirectoryConfigurationPage - Locations & computers + Builtin directory - - - :/builtindirectory/builtindirectory.png:/builtindirectory/builtindirectory.png - - + 0 0 - - - - Builtin directory + + + + + + Directory name + + + + + + + + + + + + Locations + + + + + + + Computers + + + + + + + false + + + true + + + false + + + + Locations + + + + + + + + QAbstractItemView::SelectRows + + + 150 + + + true + + + false + + + + Name + + + + + Host address/IP + + + + + MAC address + + + + + + + + + + Add new location + + + + + + + :/core/list-add.png:/core/list-add.png + + + + + + + Remove selected location + + + + + + + :/core/edit-delete.png:/core/edit-delete.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Add new computer + + + + + + + :/core/list-add.png:/core/list-add.png + + + + + + + Remove selected computer + + + + + + + :/core/edit-delete.png:/core/edit-delete.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + true + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + + true - - - - - Computers - - - - - - - Locations - - - - - - - - - Add new computer - - - - - - - :/core/list-add.png:/core/list-add.png - - - - - - - Remove selected computer - - - - - - - :/core/edit-delete.png:/core/edit-delete.png - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - QAbstractItemView::SelectRows - - - 150 - - - true - - - false - - - - Name - - - - - Host address/IP - - - - - MAC address - - - - - - - - - - Add new location - - - - - - - :/core/list-add.png:/core/list-add.png - - - - - - - Remove selected location - - - - - - - :/core/edit-delete.png:/core/edit-delete.png - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - false - - - true - - - false - - - - Locations - - - - - - - - - true - - - - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - - - true - - - - - diff --git a/plugins/builtindirectory/BuiltinDirectoryPlugin.cpp b/plugins/builtindirectory/BuiltinDirectoryPlugin.cpp index 81d0d451b..dfe70247e 100644 --- a/plugins/builtindirectory/BuiltinDirectoryPlugin.cpp +++ b/plugins/builtindirectory/BuiltinDirectoryPlugin.cpp @@ -1,7 +1,7 @@ /* * BuiltinDirectoryPlugin.cpp - implementation of BuiltinDirectoryPlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,6 +23,7 @@ */ #include +#include #include "BuiltinDirectoryConfigurationPage.h" #include "BuiltinDirectory.h" @@ -30,6 +31,7 @@ #include "CommandLineIO.h" #include "ConfigurationManager.h" #include "ObjectManager.h" +#include "PlatformFilesystemFunctions.h" #include "VeyonConfiguration.h" @@ -69,9 +71,10 @@ NetworkObjectDirectory *BuiltinDirectoryPlugin::createNetworkObjectDirectory( QO -ConfigurationPage *BuiltinDirectoryPlugin::createConfigurationPage() +ConfigurationPage* BuiltinDirectoryPlugin::createNetworkObjectDirectoryConfigurationPage() { return new BuiltinDirectoryConfigurationPage( m_configuration ); + } @@ -112,7 +115,7 @@ CommandLinePluginInterface::RunResult BuiltinDirectoryPlugin::handle_help( const formatArgument(), QStringLiteral("\"%name%;%host%;%mac%\"") } }, { tr( "Import CSV file with location name in first column" ), { QStringLiteral("computers-with-rooms.csv"), - formatArgument(), QStringLiteral("\"%location%,%name%,%mac%\"") } }, + formatArgument(), QStringLiteral("\"%location%;%name%;%mac%\"") } }, { tr( "Import text file with with key/value pairs using regular expressions" ), { QStringLiteral("hostlist.txt"), locationArgument(), exampleRoom(), @@ -124,7 +127,8 @@ CommandLinePluginInterface::RunResult BuiltinDirectoryPlugin::handle_help( const return NoResult; } - else if( command == exportCommand() ) + + if( command == exportCommand() ) { printUsage( commandLineModuleName(), exportCommand(), { { tr("FILE"), {} } }, { { tr("LOCATION"), locationArgument() }, @@ -140,12 +144,14 @@ CommandLinePluginInterface::RunResult BuiltinDirectoryPlugin::handle_help( const formatArgument(), QStringLiteral("\"%type%;%name%;%host%;%mac%\"") } }, { tr( "Export all computers in a specific location to a CSV file" ), { QStringLiteral("computers.csv"), + locationArgument(), exampleRoom(), formatArgument(), QStringLiteral("\"%name%;%host%;%mac%\"") } } } ); return NoResult; } - else if( command == addCommand() ) + + if( command == addCommand() ) { printUsage( commandLineModuleName(), addCommand(), { { tr("TYPE"), {} }, { tr("NAME"), {} } }, { { tr("HOST ADDRESS"), {} }, @@ -162,7 +168,8 @@ CommandLinePluginInterface::RunResult BuiltinDirectoryPlugin::handle_help( const return NoResult; } - else if( command == removeCommand() ) + + if( command == removeCommand() ) { printUsage( commandLineModuleName(), removeCommand(), { { tr("OBJECT"), {} } } ); @@ -177,7 +184,9 @@ CommandLinePluginInterface::RunResult BuiltinDirectoryPlugin::handle_help( const return NoResult; } - return Unknown; + error( tr("The specified command does not exist or no help is available for it.") ); + + return NoResult; } @@ -196,7 +205,7 @@ CommandLinePluginInterface::RunResult BuiltinDirectoryPlugin::handle_add( const if( type == typeLocation() ) { - object = NetworkObject( NetworkObject::Type::Location, name ); + object = NetworkObject( nullptr, NetworkObject::Type::Location, name ); } else if( type == typeComputer() ) { @@ -207,8 +216,12 @@ CommandLinePluginInterface::RunResult BuiltinDirectoryPlugin::handle_add( const } const auto macAddress = arguments.value( 3 ); const auto parent = findNetworkObject( arguments.value( 4 ) ); - object = NetworkObject( NetworkObject::Type::Host, name, hostAddress, macAddress, - {}, NetworkObject::Uid(), parent.isValid() ? parent.uid() : NetworkObject::Uid() ); + object = NetworkObject( nullptr, NetworkObject::Type::Host, name, + { + { NetworkObject::propertyKey(NetworkObject::Property::HostAddress), hostAddress }, + { NetworkObject::propertyKey(NetworkObject::Property::MacAddress), macAddress } + }, + {}, parent.isValid() ? parent.uid() : NetworkObject::Uid{} ); } else { @@ -227,7 +240,7 @@ CommandLinePluginInterface::RunResult BuiltinDirectoryPlugin::handle_add( const CommandLinePluginInterface::RunResult BuiltinDirectoryPlugin::handle_clear( const QStringList& arguments ) { - Q_UNUSED(arguments); + Q_UNUSED(arguments) m_configuration.setNetworkObjects( {} ); @@ -249,7 +262,7 @@ CommandLinePluginInterface::RunResult BuiltinDirectoryPlugin::handle_dump( const { for( const auto& networkObjectValue : objects ) { - tableRows.append( dumpNetworkObject( NetworkObject( networkObjectValue.toObject() ) ) ); + tableRows.append( dumpNetworkObject( NetworkObject{networkObjectValue.toObject()} ) ); } } else @@ -268,12 +281,12 @@ CommandLinePluginInterface::RunResult BuiltinDirectoryPlugin::handle_list( const { if( arguments.isEmpty() ) { - listObjects( m_configuration.networkObjects(), NetworkObject( NetworkObject::Type::None ) ); + listObjects( m_configuration.networkObjects(), NetworkObject{} ); } else { const auto parents = BuiltinDirectory( m_configuration, this ).queryObjects( NetworkObject::Type::Location, - NetworkObject::Attribute::Name, + NetworkObject::Property::Name, arguments.first() ); for( const auto& parent : parents ) @@ -327,7 +340,8 @@ CommandLinePluginInterface::RunResult BuiltinDirectoryPlugin::handle_import( con error( tr( "File \"%1\" does not exist!" ).arg( inputFileName ) ); return Failed; } - else if( inputFile.open( QFile::ReadOnly | QFile::Text ) == false ) + + if( inputFile.open( QFile::ReadOnly | QFile::Text ) == false ) { error( tr( "Can't open file \"%1\" for reading!" ).arg( inputFileName ) ); return Failed; @@ -404,7 +418,10 @@ CommandLinePluginInterface::RunResult BuiltinDirectoryPlugin::handle_export( con const auto& outputFileName = arguments.first(); QFile outputFile( outputFileName ); - if( outputFile.open( QFile::WriteOnly | QFile::Truncate | QFile::Text ) == false ) + if( VeyonCore::platform().filesystemFunctions().openFileSafely( + &outputFile, + QFile::WriteOnly | QFile::Truncate | QFile::Text, + QFile::ReadOwner | QFile::WriteOwner ) == false ) { error( tr( "Can't open file \"%1\" for writing!" ).arg( outputFileName ) ); return Failed; @@ -458,7 +475,7 @@ void BuiltinDirectoryPlugin::listObjects( const QJsonArray& objects, const Netwo { for( const auto& networkObjectValue : objects ) { - const NetworkObject networkObject( networkObjectValue.toObject() ); + const NetworkObject networkObject{networkObjectValue.toObject()}; if( ( parent.type() == NetworkObject::Type::None && networkObject.parentUid().isNull() ) || networkObject.parentUid() == parent.uid() ) @@ -473,12 +490,14 @@ void BuiltinDirectoryPlugin::listObjects( const QJsonArray& objects, const Netwo QStringList BuiltinDirectoryPlugin::dumpNetworkObject( const NetworkObject& object ) { - return { VeyonCore::formattedUuid( object.uid() ), - VeyonCore::formattedUuid( object.parentUid() ), - networkObjectTypeName( object ), - object.name(), - object.hostAddress(), - object.macAddress() }; + return { + VeyonCore::formattedUuid( object.uid() ), + VeyonCore::formattedUuid( object.parentUid() ), + networkObjectTypeName( object ), + object.name(), + object.property( NetworkObject::Property::HostAddress ).toString(), + object.property( NetworkObject::Property::MacAddress ).toString() + }; } @@ -492,7 +511,9 @@ QString BuiltinDirectoryPlugin::listNetworkObject( const NetworkObject& object ) case NetworkObject::Type::Host: return QLatin1Char('\t') + tr( "Computer \"%1\" (host address: \"%2\" MAC address: \"%3\")" ). - arg( object.name(), object.hostAddress(), object.macAddress() ); + arg( object.name(), + object.property( NetworkObject::Property::HostAddress ).toString(), + object.property( NetworkObject::Property::MacAddress ).toString() ); default: break; } @@ -525,11 +546,13 @@ NetworkObject::Type BuiltinDirectoryPlugin::parseNetworkObjectType( const QStrin { return NetworkObject::Type::Location; } - else if( typeName == typeNameComputer() ) + + if( typeName == typeNameComputer() ) { return NetworkObject::Type::Host; } - else if( typeName == typeNameRoot() ) + + if( typeName == typeNameRoot() ) { return NetworkObject::Type::Root; } @@ -591,19 +614,19 @@ bool BuiltinDirectoryPlugin::importFile( QFile& inputFile, } else if( parentLocation.isValid() == false ) { - parentLocation = NetworkObject( NetworkObject::Type::Location, it.key() ); - objectManager.add( parentLocation ); + parentLocation = NetworkObject( nullptr, NetworkObject::Type::Location, it.key() ); + objectManager.update( parentLocation, true ); parentLocationUid = parentLocation.uid(); } - for( const NetworkObject& networkObject : qAsConst(it.value()) ) + for( const NetworkObject& networkObject : std::as_const(it.value()) ) { - objectManager.add( NetworkObject( networkObject.type(), - networkObject.name(), - networkObject.hostAddress(), - networkObject.macAddress(), - {}, NetworkObject::Uid(), - parentLocationUid ) ); + objectManager.update( NetworkObject( nullptr, + networkObject.type(), + networkObject.name(), + networkObject.properties(), + {}, + parentLocationUid ), true ); } } @@ -624,6 +647,11 @@ bool BuiltinDirectoryPlugin::exportFile( QFile& outputFile, const QString& forma if( location.isEmpty() == false ) { locationObject = objectManager.findByName( location ); + if (locationObject.isValid() == false) + { + error(tr("Location \"%1\" not found." ).arg(location)); + return false; + } } QStringList lines; @@ -631,7 +659,11 @@ bool BuiltinDirectoryPlugin::exportFile( QFile& outputFile, const QString& forma for( auto it = networkObjects.constBegin(), end = networkObjects.constEnd(); it != end; ++it ) { - const NetworkObject networkObject( it->toObject() ); + const NetworkObject networkObject{it->toObject()}; + if (networkObject.type() != NetworkObject::Type::Host) + { + continue; + } auto currentLocation = location; @@ -653,7 +685,7 @@ bool BuiltinDirectoryPlugin::exportFile( QFile& outputFile, const QString& forma // append empty string to generate final newline at end of file lines += QString(); - outputFile.write( lines.join( QStringLiteral("\r\n") ).toUtf8() ); + outputFile.write(lines.join(QLatin1Char('\n')).toUtf8()); return true; } @@ -663,13 +695,14 @@ bool BuiltinDirectoryPlugin::exportFile( QFile& outputFile, const QString& forma NetworkObject BuiltinDirectoryPlugin::findNetworkObject( const QString& uidOrName ) const { const ObjectManager objectManager( m_configuration.networkObjects() ); + const QUuid uid{uidOrName}; - if( QUuid( uidOrName ).isNull() ) + if( uid.isNull() ) { return objectManager.findByName( uidOrName ); } - return objectManager.findByUid( uidOrName ); + return objectManager.findByUid( uid ); } @@ -678,29 +711,28 @@ NetworkObject BuiltinDirectoryPlugin::toNetworkObject( const QString& line, cons QString& location ) { QStringList placeholders; - QRegExp varDetectionRX( QStringLiteral("\\((%\\w+%):[^)]+\\)") ); - int pos = 0; + static const QRegularExpression varDetectionRX{QStringLiteral("\\((%\\w+%):[^)]+\\)")}; + auto varDetectionMatchIterator = varDetectionRX.globalMatch(regExWithPlaceholders); - while( ( pos = varDetectionRX.indexIn( regExWithPlaceholders, pos ) ) != -1 ) + while( varDetectionMatchIterator.hasNext() ) { - placeholders.append( varDetectionRX.cap(1) ); - pos += varDetectionRX.matchedLength(); + placeholders.append( varDetectionMatchIterator.next().captured(1) ); } QString rxString = regExWithPlaceholders; - for( const auto& var : qAsConst(placeholders) ) + for( const auto& var : std::as_const(placeholders) ) { rxString.replace( QStringLiteral("%1:").arg( var ), QString() ); } - QRegExp rx( rxString ); - if( rx.indexIn( line ) != -1 ) + auto match = QRegularExpression( rxString ).match( line ); + if( match.hasMatch() ) { auto objectType = NetworkObject::Type::Host; const auto typeIndex = placeholders.indexOf( QStringLiteral("%type%") ); if( typeIndex != -1 ) { - objectType = parseNetworkObjectType( rx.cap( 1 + typeIndex ) ); + objectType = parseNetworkObjectType( match.captured( 1 + typeIndex ) ); } const auto locationIndex = placeholders.indexOf( QStringLiteral("%location%") ); @@ -708,18 +740,18 @@ NetworkObject BuiltinDirectoryPlugin::toNetworkObject( const QString& line, cons const auto hostIndex = placeholders.indexOf( QStringLiteral("%host%") ); const auto macIndex = placeholders.indexOf( QStringLiteral("%mac%") ); - auto name = ( nameIndex != -1 ) ? rx.cap( 1 + nameIndex ).trimmed() : QString(); - auto host = ( hostIndex != -1 ) ? rx.cap( 1 + hostIndex ).trimmed() : QString(); - auto mac = ( macIndex != -1 ) ? rx.cap( 1 + macIndex ).trimmed() : QString(); + auto name = ( nameIndex != -1 ) ? match.captured( 1 + nameIndex ).trimmed() : QString(); + auto host = ( hostIndex != -1 ) ? match.captured( 1 + hostIndex ).trimmed() : QString(); + auto mac = ( macIndex != -1 ) ? match.captured( 1 + macIndex ).trimmed() : QString(); if( objectType == NetworkObject::Type::Location ) { - return NetworkObject( NetworkObject::Type::Location, name ); + return NetworkObject( nullptr, NetworkObject::Type::Location, name ); } if( location.isEmpty() && locationIndex != -1 ) { - location = rx.cap( 1 + locationIndex ).trimmed(); + location = match.captured( 1 + locationIndex ).trimmed(); } if( host.isEmpty() ) @@ -730,10 +762,15 @@ NetworkObject BuiltinDirectoryPlugin::toNetworkObject( const QString& line, cons { name = host; } - return NetworkObject( NetworkObject::Type::Host, name, host, mac ); + return NetworkObject( nullptr, + NetworkObject::Type::Host, name, + { + { NetworkObject::propertyKey(NetworkObject::Property::HostAddress), host }, + { NetworkObject::propertyKey(NetworkObject::Property::MacAddress), mac } + } ); } - return NetworkObject( NetworkObject::Type::None ); + return NetworkObject{}; } @@ -745,8 +782,8 @@ QString BuiltinDirectoryPlugin::toFormattedString( const NetworkObject& networkO return QString( formatString ). replace( QStringLiteral("%location%"), location ). replace( QStringLiteral("%name%"), networkObject.name() ). - replace( QStringLiteral("%host%"), networkObject.hostAddress() ). - replace( QStringLiteral("%mac%"), networkObject.macAddress() ). + replace( QStringLiteral("%host%"), networkObject.property( NetworkObject::Property::HostAddress ).toString() ). + replace( QStringLiteral("%mac%"), networkObject.property( NetworkObject::Property::MacAddress ).toString() ). replace( QStringLiteral("%type%"), networkObjectTypeName( networkObject ) ); } diff --git a/plugins/builtindirectory/BuiltinDirectoryPlugin.h b/plugins/builtindirectory/BuiltinDirectoryPlugin.h index 2540fa412..9a4d82065 100644 --- a/plugins/builtindirectory/BuiltinDirectoryPlugin.h +++ b/plugins/builtindirectory/BuiltinDirectoryPlugin.h @@ -1,7 +1,7 @@ /* * BuiltinDirectoryPlugin.h - declaration of BuiltinDirectoryPlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,7 +26,6 @@ #include "CommandLinePluginInterface.h" #include "CommandLineIO.h" -#include "ConfigurationPagePluginInterface.h" #include "BuiltinDirectoryConfiguration.h" #include "NetworkObject.h" #include "NetworkObjectDirectoryPluginInterface.h" @@ -36,7 +35,6 @@ class QFile; class BuiltinDirectoryPlugin : public QObject, PluginInterface, NetworkObjectDirectoryPluginInterface, - ConfigurationPagePluginInterface, CommandLinePluginInterface, CommandLineIO { @@ -44,7 +42,6 @@ class BuiltinDirectoryPlugin : public QObject, Q_PLUGIN_METADATA(IID "io.veyon.Veyon.Plugins.BuiltinDirectory") Q_INTERFACES(PluginInterface NetworkObjectDirectoryPluginInterface - ConfigurationPagePluginInterface CommandLinePluginInterface) public: explicit BuiltinDirectoryPlugin( QObject* paren = nullptr ); @@ -52,7 +49,7 @@ class BuiltinDirectoryPlugin : public QObject, Plugin::Uid uid() const override { - return QStringLiteral("14bacaaa-ebe5-449c-b881-5b382f952571"); + return Plugin::Uid{ QStringLiteral("14bacaaa-ebe5-449c-b881-5b382f952571") }; } QVersionNumber version() const override @@ -94,7 +91,7 @@ class BuiltinDirectoryPlugin : public QObject, NetworkObjectDirectory* createNetworkObjectDirectory( QObject* parent ) override; - ConfigurationPage* createConfigurationPage() override; + ConfigurationPage* createNetworkObjectDirectoryConfigurationPage() override; QString commandLineModuleName() const override { @@ -109,7 +106,7 @@ class BuiltinDirectoryPlugin : public QObject, QStringList commands() const override; QString commandHelp( const QString& command ) const override; -public slots: +public Q_SLOTS: CommandLinePluginInterface::RunResult handle_help( const QStringList& arguments ); CommandLinePluginInterface::RunResult handle_add( const QStringList& arguments ); CommandLinePluginInterface::RunResult handle_clear( const QStringList& arguments ); diff --git a/plugins/builtindirectory/CMakeLists.txt b/plugins/builtindirectory/CMakeLists.txt index 4d36618f1..f435247e6 100644 --- a/plugins/builtindirectory/CMakeLists.txt +++ b/plugins/builtindirectory/CMakeLists.txt @@ -1,6 +1,6 @@ -INCLUDE(BuildPlugin) +include(BuildVeyonPlugin) -BUILD_PLUGIN(builtindirectory +build_veyon_plugin(builtindirectory BuiltinDirectoryPlugin.cpp BuiltinDirectoryConfigurationPage.cpp BuiltinDirectoryConfigurationPage.ui @@ -9,5 +9,4 @@ BUILD_PLUGIN(builtindirectory BuiltinDirectoryConfiguration.h BuiltinDirectoryConfigurationPage.h BuiltinDirectory.h - builtindirectory.qrc -) + ) diff --git a/plugins/builtindirectory/builtindirectory.qrc b/plugins/builtindirectory/builtindirectory.qrc deleted file mode 100644 index d3a90fc32..000000000 --- a/plugins/builtindirectory/builtindirectory.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - builtindirectory.png - - diff --git a/plugins/config/CMakeLists.txt b/plugins/config/CMakeLists.txt deleted file mode 100644 index 2a83a39d1..000000000 --- a/plugins/config/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -INCLUDE(BuildPlugin) - -BUILD_PLUGIN(config ConfigCommandLinePlugin.cpp ConfigCommandLinePlugin.h) diff --git a/plugins/demo/CMakeLists.txt b/plugins/demo/CMakeLists.txt index 99c84a07f..41a175172 100644 --- a/plugins/demo/CMakeLists.txt +++ b/plugins/demo/CMakeLists.txt @@ -1,7 +1,8 @@ -INCLUDE(BuildPlugin) +include(BuildVeyonPlugin) -BUILD_PLUGIN(demo +build_veyon_plugin(demo DemoFeaturePlugin.cpp + DemoAuthentication.cpp DemoConfigurationPage.cpp DemoConfigurationPage.ui DemoServer.cpp @@ -9,6 +10,7 @@ BUILD_PLUGIN(demo DemoServerProtocol.cpp DemoClient.cpp DemoFeaturePlugin.h + DemoAuthentication.h DemoConfiguration.h DemoConfigurationPage.h DemoServer.h @@ -16,6 +18,4 @@ BUILD_PLUGIN(demo DemoServerProtocol.h DemoClient.h demo.qrc -) - -TARGET_LINK_LIBRARIES(demo ${LZO_LIBRARIES}) + ) diff --git a/plugins/demo/DemoAuthentication.cpp b/plugins/demo/DemoAuthentication.cpp new file mode 100644 index 000000000..213c1f2ce --- /dev/null +++ b/plugins/demo/DemoAuthentication.cpp @@ -0,0 +1,97 @@ +/* + * DemoAuthentication.cpp - implementation of DemoAuthentication class + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "DemoAuthentication.h" +#include "VariantArrayMessage.h" + + +DemoAuthentication::DemoAuthentication( Plugin::Uid pluginUid ) : + m_pluginUid( pluginUid ) +{ +} + + + +bool DemoAuthentication::initializeCredentials() +{ + m_accessToken = CryptoCore::generateChallenge().toBase64(); + + return hasCredentials(); +} + + + +bool DemoAuthentication::hasCredentials() const +{ + return m_accessToken.isEmpty() == false && + QByteArray::fromBase64( m_accessToken.toByteArray() ).size() == CryptoCore::ChallengeSize; +} + + + +bool DemoAuthentication::checkCredentials() const +{ + return true; +} + + + +VncServerClient::AuthState DemoAuthentication::performAuthentication( VncServerClient* client, VariantArrayMessage& message ) const +{ + switch( client->authState() ) + { + case VncServerClient::AuthState::Init: + return VncServerClient::AuthState::Stage1; + + case VncServerClient::AuthState::Stage1: + { + const CryptoCore::PlaintextPassword token = message.read().toByteArray(); // Flawfinder: ignore + + if( hasCredentials() && token == m_accessToken ) + { + vDebug() << "SUCCESS"; + return VncServerClient::AuthState::Successful; + } + + vDebug() << "FAIL"; + return VncServerClient::AuthState::Failed; + } + + default: + break; + } + + return VncServerClient::AuthState::Failed; +} + + + +bool DemoAuthentication::authenticate( QIODevice* socket ) const +{ + VariantArrayMessage tokenAuthMessage( socket ); + tokenAuthMessage.write( m_accessToken.toByteArray() ); + tokenAuthMessage.send(); + + return true; +} diff --git a/plugins/demo/DemoAuthentication.h b/plugins/demo/DemoAuthentication.h new file mode 100644 index 000000000..34d6cabe5 --- /dev/null +++ b/plugins/demo/DemoAuthentication.h @@ -0,0 +1,82 @@ +/* + * DemoAuthentication.h - declaration of DemoAuthentication class + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "AuthenticationPluginInterface.h" + +// clazy:excludeall=copyable-polymorphic + +class DemoAuthentication : public AuthenticationPluginInterface +{ +public: + using AccessToken = CryptoCore::PlaintextPassword; + + explicit DemoAuthentication( Plugin::Uid pluginUid ); + ~DemoAuthentication() override = default; + + QString authenticationMethodName() const override + { + return {}; + } + + QWidget* createAuthenticationConfigurationWidget() override + { + return nullptr; + } + + bool initializeCredentials() override; + bool hasCredentials() const override; + + bool checkCredentials() const override; + + VncServerClient::AuthState performAuthentication( VncServerClient* client, VariantArrayMessage& message ) const override; + + bool authenticate( QIODevice* socket ) const override; + + bool requiresAccessControl() const override + { + return false; + } + + const AccessToken& accessToken() const + { + return m_accessToken; + } + + void setAccessToken( const AccessToken& token ) + { + m_accessToken = token; + } + + const Plugin::Uid& pluginUid() const + { + return m_pluginUid; + } + +private: + AccessToken m_accessToken{}; + const Plugin::Uid m_pluginUid; + +}; diff --git a/plugins/demo/DemoClient.cpp b/plugins/demo/DemoClient.cpp index 2a9d8f07e..5aa9c9247 100644 --- a/plugins/demo/DemoClient.cpp +++ b/plugins/demo/DemoClient.cpp @@ -1,7 +1,7 @@ /* * DemoClient.cpp - client widget for demo mode * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,20 +23,17 @@ */ #include -#include #include -#include #include "DemoClient.h" -#include "VeyonConfiguration.h" #include "LockWidget.h" #include "PlatformCoreFunctions.h" -#include "VncView.h" +#include "VncViewWidget.h" -DemoClient::DemoClient( const QString& host, bool fullscreen, QObject* parent ) : +DemoClient::DemoClient( const QString& host, int port, bool fullscreen, QRect viewport, QObject* parent ) : QObject( parent ), - m_toplevel( nullptr ) + m_computerControlInterface( ComputerControlInterface::Pointer::create( Computer( {}, host, host ), port, this ) ) { if( fullscreen ) { @@ -45,41 +42,28 @@ DemoClient::DemoClient( const QString& host, bool fullscreen, QObject* parent ) else { m_toplevel = new QWidget(); + m_toplevel->setWindowFlags(Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint); + m_toplevel->move(0, 0); } m_toplevel->setWindowTitle( tr( "%1 Demo" ).arg( VeyonCore::applicationName() ) ); m_toplevel->setWindowIcon( QPixmap( QStringLiteral(":/core/icon64.png") ) ); m_toplevel->setAttribute( Qt::WA_DeleteOnClose, false ); + m_toplevel->installEventFilter(this); - if( fullscreen == false ) - { - m_toplevel->setWindowFlags( Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint ); - m_toplevel->resize( QApplication::desktop()->availableGeometry( m_toplevel ).size() - QSize( 10, 30 ) ); - } - - m_vncView = new VncView( host, VeyonCore::config().demoServerPort(), m_toplevel, VncView::DemoMode ); - - auto toplevelLayout = new QVBoxLayout; - toplevelLayout->setMargin( 0 ); - toplevelLayout->setSpacing( 0 ); - toplevelLayout->addWidget( m_vncView ); - - m_toplevel->setLayout( toplevelLayout ); + m_vncView = new VncViewWidget( m_computerControlInterface, viewport, m_toplevel ); connect( m_toplevel, &QObject::destroyed, this, &DemoClient::viewDestroyed ); - connect( m_vncView, &VncView::sizeHintChanged, this, &DemoClient::resizeToplevelWidget ); + connect( m_vncView, &VncViewWidget::sizeHintChanged, this, &DemoClient::resizeToplevelWidget ); - m_toplevel->move( 0, 0 ); - if( fullscreen ) - { - m_toplevel->showFullScreen(); - } - else + if (fullscreen == false) { m_toplevel->show(); } - VeyonCore::platform().coreFunctions().raiseWindow( m_toplevel ); + resizeToplevelWidget(); + + VeyonCore::platform().coreFunctions().raiseWindow( m_toplevel, fullscreen ); VeyonCore::platform().coreFunctions().disableScreenSaver(); } @@ -95,6 +79,19 @@ DemoClient::~DemoClient() +bool DemoClient::eventFilter(QObject* watched, QEvent* event) +{ + if (watched == m_toplevel && event->type() == QEvent::Resize) + { + m_vncView->setFixedSize(m_toplevel->size()); + return true; + } + + return QObject::eventFilter(watched, event); +} + + + void DemoClient::viewDestroyed( QObject* obj ) { // prevent double deletion of toplevel widget @@ -112,10 +109,10 @@ void DemoClient::resizeToplevelWidget() { if( m_toplevel->windowState() & Qt::WindowFullScreen ) { - m_vncView->resize( m_toplevel->size() ); + m_vncView->setFixedSize(m_toplevel->size()); } else { - m_toplevel->resize( m_vncView->sizeHint() ); + m_toplevel->resize(m_vncView->sizeHint()); } } diff --git a/plugins/demo/DemoClient.h b/plugins/demo/DemoClient.h index 909b16734..d46a5ff9c 100644 --- a/plugins/demo/DemoClient.h +++ b/plugins/demo/DemoClient.h @@ -1,7 +1,7 @@ /* - * DemoClient.h - client for demo-server + * DemoClient.h - client for demo server * - * Copyright (c) 2006-2013 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,20 +26,27 @@ #include -class VncView; +#include "ComputerControlInterface.h" + +class VncViewWidget; class DemoClient : public QObject { Q_OBJECT public: - DemoClient( const QString& host, bool fullscreen, QObject* parent = nullptr ); + DemoClient( const QString& host, int port, bool fullscreen, QRect viewport, QObject* parent = nullptr ); ~DemoClient() override; +protected: + bool eventFilter(QObject* watched, QEvent* event) override; + private: void viewDestroyed( QObject* obj ); void resizeToplevelWidget(); - QWidget* m_toplevel; - VncView* m_vncView; + QWidget* m_toplevel{nullptr}; + + ComputerControlInterface::Pointer m_computerControlInterface; + VncViewWidget* m_vncView{nullptr}; } ; diff --git a/plugins/demo/DemoConfiguration.h b/plugins/demo/DemoConfiguration.h index 1e75f4f76..4d3b8bbc8 100644 --- a/plugins/demo/DemoConfiguration.h +++ b/plugins/demo/DemoConfiguration.h @@ -1,7 +1,7 @@ /* * DemoConfiguration.h - configuration values for Demo plugin * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -29,9 +29,11 @@ #define FOREACH_DEMO_CONFIG_PROPERTY(OP) \ OP( DemoConfiguration, m_configuration, bool, slowDownThumbnailUpdates, setSlowDownThumbnailUpdates, "SlowDownThumbnailUpdates", "Demo", true, Configuration::Property::Flag::Advanced ) \ - OP( DemoConfiguration, m_configuration, bool, multithreadingEnabled, setMultithreadingEnabled, "MultithreadingEnabled", "Demo", true, Configuration::Property::Flag::Hidden ) \ + OP( DemoConfiguration, m_configuration, int, bandwidthLimit, setBandwidthLimit, "BandwidthLimit", "Demo", 100, Configuration::Property::Flag::Advanced ) \ OP( DemoConfiguration, m_configuration, int, framebufferUpdateInterval, setFramebufferUpdateInterval, "FramebufferUpdateInterval", "Demo", 100, Configuration::Property::Flag::Advanced ) \ OP( DemoConfiguration, m_configuration, int, keyFrameInterval, setKeyFrameInterval, "KeyFrameInterval", "Demo", 10, Configuration::Property::Flag::Advanced ) \ OP( DemoConfiguration, m_configuration, int, memoryLimit, setMemoryLimit, "MemoryLimit", "Demo", 128, Configuration::Property::Flag::Advanced ) \ +// clazy:excludeall=missing-qobject-macro + DECLARE_CONFIG_PROXY(DemoConfiguration, FOREACH_DEMO_CONFIG_PROPERTY) diff --git a/plugins/demo/DemoConfigurationPage.cpp b/plugins/demo/DemoConfigurationPage.cpp index 60cd0ebdc..76cc20226 100644 --- a/plugins/demo/DemoConfigurationPage.cpp +++ b/plugins/demo/DemoConfigurationPage.cpp @@ -1,7 +1,7 @@ /* * DemoConfigurationPage.cpp - implementation of DemoConfigurationPage * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/plugins/demo/DemoConfigurationPage.h b/plugins/demo/DemoConfigurationPage.h index 57f499979..d9d0fa062 100644 --- a/plugins/demo/DemoConfigurationPage.h +++ b/plugins/demo/DemoConfigurationPage.h @@ -1,7 +1,7 @@ /* * DemoConfigurationPage.h - header for the DemoConfigurationPage class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/plugins/demo/DemoConfigurationPage.ui b/plugins/demo/DemoConfigurationPage.ui index 572e49aaa..2aa71d49e 100644 --- a/plugins/demo/DemoConfigurationPage.ui +++ b/plugins/demo/DemoConfigurationPage.ui @@ -22,7 +22,7 @@ Tunables - + s @@ -38,14 +38,14 @@ - - + + - Use multithreading (experimental) + Update interval - + MB @@ -64,14 +64,7 @@ - - - - Update interval - - - - + ms @@ -90,7 +83,21 @@ + + + + Slow down thumbnail updates while demo is running + + + + + + Memory limit + + + + Key frame interval @@ -98,16 +105,22 @@ - + - Memory limit + Bandwidth limit - - - - Slow down thumbnail updates while demo is running + + + + MB/s + + + 1 + + + 1000 @@ -129,6 +142,13 @@ + + slowDownThumbnailUpdates + framebufferUpdateInterval + keyFrameInterval + memoryLimit + bandwidthLimit + diff --git a/plugins/demo/DemoFeaturePlugin.cpp b/plugins/demo/DemoFeaturePlugin.cpp index 9e718c858..fc2b5b502 100644 --- a/plugins/demo/DemoFeaturePlugin.cpp +++ b/plugins/demo/DemoFeaturePlugin.cpp @@ -1,7 +1,7 @@ /* * DemoFeaturePlugin.cpp - implementation of DemoFeaturePlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,84 +22,151 @@ * */ -#include +#include +#include -#include "DemoServer.h" #include "AuthenticationCredentials.h" #include "Computer.h" -#include "CryptoCore.h" #include "DemoClient.h" #include "DemoConfigurationPage.h" #include "DemoFeaturePlugin.h" -#include "Logger.h" +#include "DemoServer.h" #include "FeatureWorkerManager.h" +#include "HostAddress.h" +#include "Logger.h" +#include "PlatformPluginInterface.h" +#include "PlatformSessionFunctions.h" #include "VeyonConfiguration.h" +#include "VeyonMasterInterface.h" #include "VeyonServerInterface.h" DemoFeaturePlugin::DemoFeaturePlugin( QObject* parent ) : QObject( parent ), - m_fullscreenDemoFeature( QStringLiteral( "FullscreenDemo" ), - Feature::Mode | Feature::AllComponents, - Feature::Uid( "7b6231bd-eb89-45d3-af32-f70663b2f878" ), - Feature::Uid(), - tr( "Fullscreen demo" ), tr( "Stop demo" ), - tr( "In this mode your screen is being displayed in " - "fullscreen mode on all computers while input " - "devices of the users are locked." ), - QStringLiteral(":/demo/presentation-fullscreen.png") ), - m_windowDemoFeature( QStringLiteral( "WindowDemo" ), - Feature::Mode | Feature::AllComponents, - Feature::Uid( "ae45c3db-dc2e-4204-ae8b-374cdab8c62c" ), - Feature::Uid(), - tr( "Window demo" ), tr( "Stop demo" ), - tr( "In this mode your screen being displayed in a " - "window on all computers. The users are " - "able to switch to other windows as needed." ), - QStringLiteral(":/demo/presentation-window.png") ), + DemoAuthentication( uid() ), + m_demoFeature( QStringLiteral( "Demo" ), + Feature::Flag::Mode | Feature::Flag::AllComponents, + Feature::Uid( "6f4cd922-b63e-40bf-9451-536065c7cdf9" ), + Feature::Uid(), + tr( "Demo" ), tr( "Stop demo" ), + tr( "Share your screen or allow a user to share his screen with other users." ), + QStringLiteral(":/demo/demo.png") ), + m_demoClientFullScreenFeature( QStringLiteral( "FullScreenDemo" ), + Feature::Flag::Meta | Feature::Flag::AllComponents, + Feature::Uid( "7b6231bd-eb89-45d3-af32-f70663b2f878" ), + {}, tr("Full screen demo"), {}, {} ), + m_demoClientWindowFeature( QStringLiteral( "WindowDemo" ), + Feature::Flag::Meta | Feature::Flag::AllComponents, + Feature::Uid( "ae45c3db-dc2e-4204-ae8b-374cdab8c62c" ), + {}, tr("Window demo"), {}, {} ), + m_shareOwnScreenFullScreenFeature( QStringLiteral( "ShareOwnScreenFullScreen" ), + Feature::Flag::Mode | Feature::Flag::AllComponents, + Feature::Uid( "07b375e1-8ab6-4b48-bcb7-75fb3d56035b" ), + m_demoFeature.uid(), + tr( "Share your own screen in fullscreen mode" ), {}, + tr( "In this mode your screen is being displayed in " + "full screen mode on all computers while the input " + "devices of the users are locked." ), + QStringLiteral(":/demo/presentation-fullscreen.png") ), + m_shareOwnScreenWindowFeature( QStringLiteral( "ShareOwnScreenWindow" ), + Feature::Flag::Mode | Feature::Flag::AllComponents, + Feature::Uid( "68c55fb9-127e-4c9f-9c90-28b998bf1a47" ), + m_demoFeature.uid(), + tr( "Share your own screen in a window" ), {}, + tr( "In this mode your screen being displayed in a " + "window on all computers. The users are " + "able to switch to other windows as needed." ), + QStringLiteral(":/demo/presentation-window.png") ), + m_shareUserScreenFullScreenFeature( QStringLiteral( "ShareUserScreenFullScreen" ), + Feature::Flag::Mode | Feature::Flag::AllComponents, + Feature::Uid( "b4e542e2-1deb-48ac-910a-bbf8ac9a0bde" ), + m_demoFeature.uid(), + tr( "Share selected user's screen in fullscreen mode" ), {}, + tr( "In this mode the screen of the selected user is being displayed " + "in full screen mode on all computers while the input " + "devices of the users are locked." ), + QStringLiteral(":/demo/presentation-fullscreen.png") ), + m_shareUserScreenWindowFeature( QStringLiteral( "ShareUserScreenWindow" ), + Feature::Flag::Mode | Feature::Flag::AllComponents, + Feature::Uid( "ebfc5ec4-f725-4bfc-a93a-c6d4864c6806" ), + m_demoFeature.uid(), + tr( "Share selected user's screen in a window" ), {}, + tr( "In this mode the screen of the selected user being displayed " + "in a window on all computers. The users are " + "able to switch to other windows as needed." ), + QStringLiteral(":/demo/presentation-window.png") ), m_demoServerFeature( QStringLiteral( "DemoServer" ), - Feature::Session | Feature::Service | Feature::Worker | Feature::Builtin, + Feature::Flag::Session | Feature::Flag::Service | Feature::Flag::Worker, Feature::Uid( "e4b6e743-1f5b-491d-9364-e091086200f4" ), - Feature::Uid(), - tr( "Demo server" ), {}, {} ), - m_features( { m_fullscreenDemoFeature, m_windowDemoFeature, m_demoServerFeature } ), - m_demoAccessToken( QString::fromLatin1( CryptoCore::generateChallenge().toBase64() ) ), - m_demoClientHosts(), - m_configuration( &VeyonCore::config() ), - m_demoServer( nullptr ), - m_demoClient( nullptr ) + m_demoFeature.uid(), + {}, {}, {} ), + m_staticFeatures( { + m_demoFeature, m_demoServerFeature, + m_demoClientFullScreenFeature, m_demoClientWindowFeature, + m_shareOwnScreenFullScreenFeature, m_shareOwnScreenWindowFeature, + m_shareUserScreenFullScreenFeature, m_shareUserScreenWindowFeature + } ), + m_configuration( &VeyonCore::config() ) { + connect( qGuiApp, &QGuiApplication::screenAdded, this, &DemoFeaturePlugin::addScreen ); + connect( qGuiApp, &QGuiApplication::screenRemoved, this, &DemoFeaturePlugin::removeScreen ); + connect( &m_demoServerControlTimer, &QTimer::timeout, this, &DemoFeaturePlugin::controlDemoServer ); + + updateFeatures(); } -bool DemoFeaturePlugin::startFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) +Feature::Uid DemoFeaturePlugin::metaFeature( Feature::Uid featureUid ) const { - Q_UNUSED(master); - - if( feature == m_windowDemoFeature || feature == m_fullscreenDemoFeature ) + if( featureUid == m_shareOwnScreenFullScreenFeature.uid() || + featureUid == m_shareUserScreenFullScreenFeature.uid() ) + { + return m_demoClientFullScreenFeature.uid(); + } + else if( featureUid == m_shareOwnScreenWindowFeature.uid() || + featureUid == m_shareUserScreenWindowFeature.uid() ) { - FeatureMessage featureMessage( m_demoServerFeature.uid(), StartDemoServer ); - featureMessage.addArgument( DemoAccessToken, m_demoAccessToken ); + return m_demoClientWindowFeature.uid(); + } - VeyonCore::localComputerControlInterface().sendFeatureMessage( featureMessage, true ); + return FeatureProviderInterface::metaFeature( featureUid ); +} - const auto disableUpdates = m_configuration.slowDownThumbnailUpdates(); - for( const auto& computerControlInterface : computerControlInterfaces ) + +bool DemoFeaturePlugin::controlFeature( Feature::Uid featureUid, + Operation operation, + const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) +{ + if( featureUid == m_demoServerFeature.uid() ) + { + if( operation == Operation::Start ) { - m_demoClientHosts += computerControlInterface->computer().hostAddress(); - if( disableUpdates ) - { - computerControlInterface->disableUpdates(); - } + m_demoServerArguments = arguments; + m_demoServerControlInterfaces = computerControlInterfaces; + m_demoServerControlTimer.start( DemoServerControlInterval ); + controlDemoServer(); + } + else if( operation == Operation::Stop ) + { + m_demoServerControlTimer.stop(); + m_demoServerControlInterfaces = computerControlInterfaces; + controlDemoServer(); + m_demoServerControlInterfaces.clear(); + } + else + { + return false; } - vDebug() << "clients:" << m_demoClientHosts; + return true; + } - return sendFeatureMessage( FeatureMessage( feature.uid(), StartDemoClient ).addArgument( DemoAccessToken, m_demoAccessToken ), - computerControlInterfaces ); + if( featureUid == m_demoClientFullScreenFeature.uid() || featureUid == m_demoClientWindowFeature.uid() ) + { + return controlDemoClient( featureUid, operation, arguments, computerControlInterfaces ); } return false; @@ -107,50 +174,121 @@ bool DemoFeaturePlugin::startFeature( VeyonMasterInterface& master, const Featur -bool DemoFeaturePlugin::stopFeature( VeyonMasterInterface& master, const Feature& feature, +bool DemoFeaturePlugin::startFeature( VeyonMasterInterface& master, const Feature& feature, const ComputerControlInterfaceList& computerControlInterfaces ) { - Q_UNUSED(master); - - if( feature == m_windowDemoFeature || feature == m_fullscreenDemoFeature ) + if( feature == m_shareOwnScreenWindowFeature || feature == m_shareOwnScreenFullScreenFeature ) { - sendFeatureMessage( FeatureMessage( feature.uid(), StopDemoClient ), computerControlInterfaces ); + // start demo clients + controlFeature( feature == m_shareOwnScreenFullScreenFeature ? m_demoClientFullScreenFeature.uid() + : m_demoClientWindowFeature.uid(), + Operation::Start, {}, computerControlInterfaces ); - const auto enableUpdates = m_configuration.slowDownThumbnailUpdates(); + // start demo server + controlFeature( m_demoServerFeature.uid(), Operation::Start, {}, + { master.localSessionControlInterface().weakPointer() } ); - for( const auto& computerControlInterface : computerControlInterfaces ) + return true; + } + + if( feature == m_shareUserScreenWindowFeature || feature == m_shareUserScreenFullScreenFeature ) + { + const auto selectedComputerControlInterfaces = master.selectedComputerControlInterfaces(); + if( selectedComputerControlInterfaces.size() < 1 ) { - m_demoClientHosts.removeAll( computerControlInterface->computer().hostAddress() ); - if( enableUpdates ) - { - computerControlInterface->enableUpdates(); - } + QMessageBox::critical( master.mainWindow(), feature.name(), + tr( "Please select a user screen to share.") ); + return true; } - vDebug() << "clients:" << m_demoClientHosts; + if( selectedComputerControlInterfaces.size() > 1 ) + { + QMessageBox::critical( master.mainWindow(), feature.name(), + tr( "Please select only one user screen to share.") ); + return true; + } - // no demo clients left? - if( m_demoClientHosts.isEmpty() ) + auto vncServerPortOffset = 0; + auto demoServerPort = VeyonCore::config().demoServerPort(); + + const auto& demoServerInterface = selectedComputerControlInterfaces.constFirst(); + const auto demoServerHost = demoServerInterface->computer().hostName(); + const auto primaryServerPort = HostAddress::parsePortNumber( demoServerHost ); + + if( primaryServerPort > 0 ) { - // then we can stop the server - const FeatureMessage featureMessage( m_demoServerFeature.uid(), StopDemoServer ); - VeyonCore::localComputerControlInterface().sendFeatureMessage( featureMessage, true ); + const auto sessionId = primaryServerPort - VeyonCore::config().veyonServerPort(); + vncServerPortOffset = sessionId; + demoServerPort += sessionId; } + // start demo clients + auto userDemoControlInterfaces = computerControlInterfaces; + userDemoControlInterfaces.removeAll( demoServerInterface ); + + const QVariantMap demoClientArgs{ + { argToString(Argument::DemoServerHost), HostAddress::parseHost(demoServerHost) }, + { argToString(Argument::DemoServerPort), demoServerPort }, + }; + + controlFeature( feature == m_shareUserScreenFullScreenFeature ? m_demoClientFullScreenFeature.uid() + : m_demoClientWindowFeature.uid(), + Operation::Start, demoClientArgs, userDemoControlInterfaces ); + + controlFeature( m_demoClientWindowFeature.uid(), Operation::Start, demoClientArgs, + { master.localSessionControlInterface().weakPointer() } ); + + // start demo server + controlFeature( m_demoServerFeature.uid(), Operation::Start, + { + { argToString(Argument::VncServerPortOffset), vncServerPortOffset }, + { argToString(Argument::DemoServerPort), demoServerPort }, + }, + selectedComputerControlInterfaces ); + return true; } + const auto screenIndex = m_screenSelectionFeatures.indexOf( feature ); + if( screenIndex >= 0 ) + { + m_screenSelection = screenIndex; + + updateFeatures(); + } + return false; } -bool DemoFeaturePlugin::handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) +bool DemoFeaturePlugin::stopFeature( VeyonMasterInterface& master, const Feature& feature, + const ComputerControlInterfaceList& computerControlInterfaces ) { - Q_UNUSED(master); - Q_UNUSED(message); - Q_UNUSED(computerControlInterface); + if( feature == m_demoFeature || + feature == m_shareOwnScreenWindowFeature || feature == m_shareOwnScreenFullScreenFeature || + feature == m_shareUserScreenWindowFeature || feature == m_shareUserScreenFullScreenFeature ) + { + controlFeature( m_demoClientFullScreenFeature.uid(), Operation::Stop, {}, computerControlInterfaces ); + controlFeature( m_demoClientWindowFeature.uid(), Operation::Stop, {}, computerControlInterfaces ); + + controlFeature( m_demoClientWindowFeature.uid(), Operation::Stop, {}, + { master.localSessionControlInterface().weakPointer() } ); + + // no demo clients left? + if( m_demoServerClients.isEmpty() ) + { + // then we can stop the server + m_demoServerControlTimer.stop(); + + // reset demo access token + initializeCredentials(); + } + + controlDemoServer(); + + return true; + } return false; } @@ -158,49 +296,53 @@ bool DemoFeaturePlugin::handleFeatureMessage( VeyonMasterInterface& master, cons bool DemoFeaturePlugin::handleFeatureMessage( VeyonServerInterface& server, - const MessageContext& messageContext, - const FeatureMessage& message ) + const MessageContext& messageContext, + const FeatureMessage& message ) { if( message.featureUid() == m_demoServerFeature.uid() ) { - if( server.featureWorkerManager().isWorkerRunning( m_demoServerFeature ) == false ) - { - server.featureWorkerManager().startWorker( m_demoServerFeature, FeatureWorkerManager::ManagedSystemProcess ); - } - if( message.command() == StartDemoServer ) { // add VNC server password to message server.featureWorkerManager(). - sendMessage( FeatureMessage( m_demoServerFeature.uid(), StartDemoServer ). - addArgument( VncServerPort, VeyonCore::config().vncServerPort() + VeyonCore::sessionId() ). - addArgument( VncServerPassword, VeyonCore::authenticationCredentials().internalVncServerPassword() ). - addArgument( DemoAccessToken, message.argument( DemoAccessToken ) ) ); + sendMessageToManagedSystemWorker( + FeatureMessage{ message } + .addArgument( Argument::VncServerPassword, VeyonCore::authenticationCredentials().internalVncServerPassword().toByteArray() ) + .addArgument( Argument::VncServerPort, server.vncServerBasePort() + message.argument(Argument::VncServerPortOffset).toInt() ) ); } - else + else if( message.command() != StopDemoServer || + server.featureWorkerManager().isWorkerRunning( m_demoServerFeature.uid() ) ) { // forward message to worker - server.featureWorkerManager().sendMessage( message ); + server.featureWorkerManager().sendMessageToManagedSystemWorker( message ); } return true; } - else if( message.featureUid() == m_fullscreenDemoFeature.uid() || - message.featureUid() == m_windowDemoFeature.uid() ) + + if( message.featureUid() == m_demoClientFullScreenFeature.uid() || + message.featureUid() == m_demoClientWindowFeature.uid() ) { // if a demo server is started, it's likely that the demo accidentally was // started on master computer as well therefore we deny starting a demo on // hosts on which a demo server is running - exception: debug mode - if( server.featureWorkerManager().isWorkerRunning( m_demoServerFeature ) && - VeyonCore::config().logLevel() < Logger::LogLevel::Debug ) + if( message.featureUid() == m_demoClientFullScreenFeature.uid() && + server.featureWorkerManager().isWorkerRunning( m_demoServerFeature.uid() ) && + VeyonCore::config().logLevel() < Logger::LogLevel::Debug ) { return false; } - if( server.featureWorkerManager().isWorkerRunning( Feature( message.featureUid() ) ) == false && - message.command() != StopDemoClient ) + if( message.command() == StopDemoClient && + server.featureWorkerManager().isWorkerRunning( message.featureUid() ) == false ) + { + return true; + } + + if( VeyonCore::platform().sessionFunctions().currentSessionHasUser() == false ) { - server.featureWorkerManager().startWorker( Feature( message.featureUid() ), FeatureWorkerManager::ManagedSystemProcess ); + vDebug() << "not starting demo client since not running in a user session"; + return true; } auto socket = qobject_cast( messageContext.ioDevice() ); @@ -210,18 +352,18 @@ bool DemoFeaturePlugin::handleFeatureMessage( VeyonServerInterface& server, return false; } - if( message.command() == StartDemoClient ) + if( message.command() == StartDemoClient && + message.argument( Argument::DemoServerHost ).toString().isEmpty() ) { - // construct a new message as we have to append the peer address as demo server host - FeatureMessage startDemoClientMessage( message.featureUid(), message.command() ); - startDemoClientMessage.addArgument( DemoAccessToken, message.argument( DemoAccessToken ) ); - startDemoClientMessage.addArgument( DemoServerHost, socket->peerAddress().toString() ); - server.featureWorkerManager().sendMessage( startDemoClientMessage ); + // set the peer address as demo server host + server.featureWorkerManager().sendMessageToManagedSystemWorker( + FeatureMessage{ message } + .addArgument( Argument::DemoServerHost, socket->peerAddress().toString() ) ); } else { // forward message to worker - server.featureWorkerManager().sendMessage( message ); + server.featureWorkerManager().sendMessageToManagedSystemWorker( message ); } return true; @@ -243,38 +385,49 @@ bool DemoFeaturePlugin::handleFeatureMessage( VeyonWorkerInterface& worker, cons case StartDemoServer: if( m_demoServer == nullptr ) { - m_demoServer = new DemoServer( message.argument( VncServerPort ).toInt(), - message.argument( VncServerPassword ).toString(), - message.argument( DemoAccessToken ).toString(), + setAccessToken( message.argument( Argument::DemoAccessToken ).toByteArray() ); + + m_demoServer = new DemoServer( message.argument( Argument::VncServerPort ).toInt(), + message.argument( Argument::VncServerPassword ).toByteArray(), + *this, m_configuration, + message.argument( Argument::DemoServerPort ).toInt(), this ); } return true; case StopDemoServer: - delete m_demoServer; + if( m_demoServer ) + { + m_demoServer->terminate(); + } m_demoServer = nullptr; + + QCoreApplication::quit(); + return true; default: break; } } - else if( message.featureUid() == m_fullscreenDemoFeature.uid() || - message.featureUid() == m_windowDemoFeature.uid() ) + else if( message.featureUid() == m_demoClientFullScreenFeature.uid() || + message.featureUid() == m_demoClientWindowFeature.uid() ) { switch( message.command() ) { case StartDemoClient: - VeyonCore::authenticationCredentials().setToken( message.argument( DemoAccessToken ).toString() ); + setAccessToken( message.argument( Argument::DemoAccessToken ).toByteArray() ); if( m_demoClient == nullptr ) { - const auto demoServerHost = message.argument( DemoServerHost ).toString(); - const auto isFullscreenDemo = message.featureUid() == m_fullscreenDemoFeature.uid(); + const auto demoServerHost = message.argument( Argument::DemoServerHost ).toString(); + const auto demoServerPort = message.argument( Argument::DemoServerPort ).toInt(); + const auto isFullscreenDemo = message.featureUid() == m_demoClientFullScreenFeature.uid(); + const auto viewport = message.argument( Argument::Viewport ).toRect(); vDebug() << "connecting with master" << demoServerHost; - m_demoClient = new DemoClient( demoServerHost, isFullscreenDemo ); + m_demoClient = new DemoClient( demoServerHost, demoServerPort, isFullscreenDemo, viewport ); } return true; @@ -303,4 +456,207 @@ ConfigurationPage* DemoFeaturePlugin::createConfigurationPage() +void DemoFeaturePlugin::addScreen( QScreen* screen ) +{ + m_screens = QGuiApplication::screens(); + + const auto screenIndex = m_screens.indexOf( screen ) + 1; + if( m_screenSelection > ScreenSelectionNone && + screenIndex <= m_screenSelection ) + { + m_screenSelection++; + } + + updateFeatures(); +} + + + +void DemoFeaturePlugin::removeScreen( QScreen* screen ) +{ + const auto screenIndex = m_screens.indexOf( screen ) + 1; + if( screenIndex == m_screenSelection ) + { + m_screenSelection = ScreenSelectionNone; + } + + m_screens = QGuiApplication::screens(); + + m_screenSelection = qMin( m_screenSelection, m_screens.size() ); + + updateFeatures(); +} + + + +void DemoFeaturePlugin::updateFeatures() +{ + m_screenSelectionFeatures.clear(); + + if( m_screens.size() > 1 ) + { + m_screenSelectionFeatures.reserve( m_screens.size() + 1 ); + + auto allScreensFlags = Feature::Flag::Option | Feature::Flag::Master; + if( m_screenSelection <= ScreenSelectionNone ) + { + allScreensFlags |= Feature::Flag::Checked; + } + + m_screenSelectionFeatures.append( Feature{ QStringLiteral("DemoAllScreens"), + allScreensFlags, + Feature::Uid("2aca1e9f-25f9-4d0f-9729-01b03c80ab28"), + m_demoFeature.uid(), tr("All screens"), {}, {}, {} } ); + + int index = 1; + for( auto screen : std::as_const(m_screens) ) + { + const auto name = QStringLiteral( "DemoScreen%1" ).arg( index ); + const auto screenName = VeyonCore::screenName(*screen, index); + + auto flags = Feature::Flag::Option | Feature::Flag::Master; + if( index == m_screenSelection ) + { + flags |= Feature::Flag::Checked; + } + + m_screenSelectionFeatures.append( Feature{ name, flags, + Feature::Uid::createUuidV5( m_demoFeature.uid(), name ), + m_demoFeature.uid(), screenName, {}, {}, {} } ); + ++index; + } + } + + m_features = m_staticFeatures + m_screenSelectionFeatures; + + const auto master = VeyonCore::instance()->findChild(); + if( master ) + { + master->reloadSubFeatures(); + } +} + + + + +QRect DemoFeaturePlugin::viewportFromScreenSelection() const +{ + if( m_screenSelection <= ScreenSelectionNone ) + { + return {}; + } + + QPoint minimumScreenPosition{}; + for( const auto* screen : m_screens ) + { + minimumScreenPosition.setX( qMin( minimumScreenPosition.x(), screen->geometry().x() ) ); + minimumScreenPosition.setY( qMin( minimumScreenPosition.y(), screen->geometry().y() ) ); + } + + const auto screen = m_screens.value( m_screenSelection - 1 ); + if( screen ) + { + return screen->geometry().translated( -minimumScreenPosition ); + } + + return {}; +} + + + +void DemoFeaturePlugin::controlDemoServer() +{ + if( m_demoServerControlTimer.isActive() ) + { + const auto demoServerPort = m_demoServerArguments.value( argToString(Argument::DemoServerPort), + VeyonCore::config().demoServerPort() + VeyonCore::sessionId() ).toInt(); + const auto vncServerPortOffset = m_demoServerArguments.value( argToString(Argument::VncServerPortOffset), + VeyonCore::sessionId() ).toInt(); + const auto demoAccessToken = m_demoServerArguments.value( argToString(Argument::DemoAccessToken), + accessToken().toByteArray() ).toByteArray(); + + sendFeatureMessage( FeatureMessage{ m_demoServerFeature.uid(), StartDemoServer } + .addArgument( Argument::DemoAccessToken, demoAccessToken ) + .addArgument( Argument::VncServerPortOffset, vncServerPortOffset ) + .addArgument( Argument::DemoServerPort, demoServerPort ), + m_demoServerControlInterfaces ); + } + else + { + sendFeatureMessage( FeatureMessage{ m_demoServerFeature.uid(), StopDemoServer }, + m_demoServerControlInterfaces ); + } +} + + + +bool DemoFeaturePlugin::controlDemoClient( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) +{ + if( operation == Operation::Start ) + { + const auto demoAccessToken = arguments.value( argToString(Argument::DemoAccessToken), + accessToken().toByteArray() ).toByteArray(); + const auto demoServerHost = arguments.value( argToString(Argument::DemoServerHost) ).toString(); + const auto demoServerPort = arguments.value( argToString(Argument::DemoServerPort), + VeyonCore::config().demoServerPort() + VeyonCore::sessionId() ).toInt(); + + QRect viewport{ + arguments.value( argToString(Argument::ViewportX) ).toInt(), + arguments.value( argToString(Argument::ViewportY) ).toInt(), + arguments.value( argToString(Argument::ViewportWidth) ).toInt(), + arguments.value( argToString(Argument::ViewportHeight) ).toInt() + }; + + if( viewport.isNull() || viewport.isEmpty() ) + { + viewport = viewportFromScreenSelection(); + } + + const auto disableUpdates = m_configuration.slowDownThumbnailUpdates(); + + for( const auto& computerControlInterface : computerControlInterfaces ) + { + m_demoServerClients += computerControlInterface; + + if( disableUpdates ) + { + computerControlInterface->setUpdateMode( ComputerControlInterface::UpdateMode::Disabled ); + } + } + + sendFeatureMessage( FeatureMessage{ featureUid, StartDemoClient } + .addArgument( Argument::DemoAccessToken, demoAccessToken ) + .addArgument( Argument::DemoServerHost, demoServerHost ) + .addArgument( Argument::DemoServerPort, demoServerPort ) + .addArgument( Argument::Viewport, viewport ), + computerControlInterfaces ); + + return true; + } + + if( operation == Operation::Stop ) + { + const auto enableUpdates = m_configuration.slowDownThumbnailUpdates(); + + for( const auto& computerControlInterface : computerControlInterfaces ) + { + m_demoServerClients.removeAll( computerControlInterface ); + + if (enableUpdates && + computerControlInterface->updateMode() == ComputerControlInterface::UpdateMode::Disabled) + { + computerControlInterface->setUpdateMode( ComputerControlInterface::UpdateMode::Monitoring ); + } + } + + sendFeatureMessage( FeatureMessage{ featureUid, StopDemoClient }, computerControlInterfaces ); + + return true; + } + + return false; +} + + IMPLEMENT_CONFIG_PROXY(DemoConfiguration) diff --git a/plugins/demo/DemoFeaturePlugin.h b/plugins/demo/DemoFeaturePlugin.h index 675daeea5..fac6497ba 100644 --- a/plugins/demo/DemoFeaturePlugin.h +++ b/plugins/demo/DemoFeaturePlugin.h @@ -1,7 +1,7 @@ /* * DemoFeaturePlugin.h - declaration of DemoFeaturePlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,25 +24,49 @@ #pragma once +#include + +#include "AuthenticationPluginInterface.h" #include "ConfigurationPagePluginInterface.h" +#include "DemoAuthentication.h" #include "DemoConfiguration.h" #include "FeatureProviderInterface.h" +class QScreen; + class DemoServer; class DemoClient; -class DemoFeaturePlugin : public QObject, FeatureProviderInterface, PluginInterface, ConfigurationPagePluginInterface +class DemoFeaturePlugin : public QObject, FeatureProviderInterface, PluginInterface, ConfigurationPagePluginInterface, DemoAuthentication { Q_OBJECT Q_PLUGIN_METADATA(IID "io.veyon.Veyon.Plugins.Demo") - Q_INTERFACES(PluginInterface FeatureProviderInterface ConfigurationPagePluginInterface) + Q_INTERFACES(PluginInterface + FeatureProviderInterface + ConfigurationPagePluginInterface + AuthenticationPluginInterface) public: + enum class Argument { + DemoAccessToken, + VncServerPort, + VncServerPassword, + DemoServerHost, + DemoServerPort, + Viewport, + ViewportX, + ViewportY, + ViewportWidth, + ViewportHeight, + VncServerPortOffset + }; + Q_ENUM(Argument) + explicit DemoFeaturePlugin( QObject* parent = nullptr ); ~DemoFeaturePlugin() override = default; Plugin::Uid uid() const override { - return QStringLiteral("1b08265b-348f-4978-acaa-45d4f6b90bd9"); + return Plugin::Uid{ QStringLiteral("1b08265b-348f-4978-acaa-45d4f6b90bd9") }; } QVersionNumber version() const override @@ -75,15 +99,17 @@ class DemoFeaturePlugin : public QObject, FeatureProviderInterface, PluginInterf return m_features; } + Feature::Uid metaFeature( Feature::Uid featureUid ) const override; + + bool controlFeature( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) override; + bool startFeature( VeyonMasterInterface& master, const Feature& feature, const ComputerControlInterfaceList& computerControlInterfaces ) override; bool stopFeature( VeyonMasterInterface& master, const Feature& feature, const ComputerControlInterfaceList& computerControlInterfaces ) override; - bool handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) override; - bool handleFeatureMessage( VeyonServerInterface& server, const MessageContext& messageContext, const FeatureMessage& message ) override; @@ -93,6 +119,20 @@ class DemoFeaturePlugin : public QObject, FeatureProviderInterface, PluginInterf ConfigurationPage* createConfigurationPage() override; private: + static constexpr auto ScreenSelectionNone = 0; + static constexpr auto DemoServerControlInterval = 1000; + + void addScreen( QScreen* screen ); + void removeScreen( QScreen* screen ); + + void updateFeatures(); + + QRect viewportFromScreenSelection() const; + + void controlDemoServer(); + bool controlDemoClient( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ); + enum Commands { StartDemoServer, StopDemoServer, @@ -100,24 +140,29 @@ class DemoFeaturePlugin : public QObject, FeatureProviderInterface, PluginInterf StopDemoClient }; - enum Arguments { - DemoAccessToken, - VncServerPort, - VncServerPassword, - DemoServerHost, - }; - - const Feature m_fullscreenDemoFeature; - const Feature m_windowDemoFeature; + const Feature m_demoFeature; + const Feature m_demoClientFullScreenFeature; + const Feature m_demoClientWindowFeature; + const Feature m_shareOwnScreenFullScreenFeature; + const Feature m_shareOwnScreenWindowFeature; + const Feature m_shareUserScreenFullScreenFeature; + const Feature m_shareUserScreenWindowFeature; const Feature m_demoServerFeature; - const FeatureList m_features; + const FeatureList m_staticFeatures{}; + FeatureList m_features{}; - QString m_demoAccessToken; - QStringList m_demoClientHosts; + FeatureList m_screenSelectionFeatures{}; + int m_screenSelection{ScreenSelectionNone}; + QList m_screens{QGuiApplication::screens()}; DemoConfiguration m_configuration; - DemoServer* m_demoServer; - DemoClient* m_demoClient; + DemoServer* m_demoServer{nullptr}; + DemoClient* m_demoClient{nullptr}; + + ComputerControlInterfaceList m_demoServerControlInterfaces{}; + ComputerControlInterfaceList m_demoServerClients{}; + QVariantMap m_demoServerArguments{}; + QTimer m_demoServerControlTimer{this}; }; diff --git a/plugins/demo/DemoServer.cpp b/plugins/demo/DemoServer.cpp index 55118cc24..dc1718f1a 100644 --- a/plugins/demo/DemoServer.cpp +++ b/plugins/demo/DemoServer.cpp @@ -2,7 +2,7 @@ * DemoServer.cpp - multi-threaded slim VNC-server for demo-purposes (optimized * for lot of clients accessing server in read-only-mode) * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,41 +23,36 @@ * */ -#include +#include "rfb/rfbproto.h" + #include #include "DemoConfiguration.h" #include "DemoServer.h" #include "DemoServerConnection.h" -#include "VeyonConfiguration.h" +#include "VncClientProtocol.h" -DemoServer::DemoServer( int vncServerPort, const QString& vncServerPassword, const QString& demoAccessToken, - const DemoConfiguration& configuration, QObject *parent ) : - QObject( parent ), +DemoServer::DemoServer( int vncServerPort, const Password& vncServerPassword, const DemoAuthentication& authentication, + const DemoConfiguration& configuration, int demoServerPort, QObject *parent ) : + QTcpServer( parent ), + m_authentication( authentication ), m_configuration( configuration ), m_memoryLimit( m_configuration.memoryLimit() * 1024*1024 ), m_keyFrameInterval( m_configuration.keyFrameInterval() * 1000 ), m_vncServerPort( vncServerPort ), - m_demoAccessToken( demoAccessToken ), - m_tcpServer( new QTcpServer( this ) ), m_vncServerSocket( new QTcpSocket( this ) ), - m_vncClientProtocol( m_vncServerSocket, vncServerPassword ), - m_framebufferUpdateTimer( this ), - m_lastFullFramebufferUpdate(), - m_requestFullFramebufferUpdate( false ), - m_keyFrame( 0 ) + m_vncClientProtocol(new VncClientProtocol(m_vncServerSocket, vncServerPassword)), + m_bandwidthLimit(qMax(1, m_configuration.bandwidthLimit()) * 1024) { - connect( m_tcpServer, &QTcpServer::newConnection, this, &DemoServer::acceptPendingConnections ); - connect( m_vncServerSocket, &QTcpSocket::readyRead, this, &DemoServer::readFromVncServer ); connect( m_vncServerSocket, &QTcpSocket::disconnected, this, &DemoServer::reconnectToVncServer ); connect( &m_framebufferUpdateTimer, &QTimer::timeout, this, &DemoServer::requestFramebufferUpdate ); - if( m_tcpServer->listen( QHostAddress::Any, static_cast( VeyonCore::config().demoServerPort() ) ) == false ) + if( listen( QHostAddress::Any, demoServerPort ) == false ) { - vCritical() << "could not listen to demo server port"; + vCritical() << "could not listen on demo server port"; return; } @@ -70,25 +65,42 @@ DemoServer::DemoServer( int vncServerPort, const QString& vncServerPassword, con DemoServer::~DemoServer() { - vDebug() << "disconnecting signals"; - m_vncServerSocket->disconnect( this ); - m_tcpServer->disconnect( this ); + delete m_vncClientProtocol; + delete m_vncServerSocket; +} + - vDebug() << "deleting connections"; - QList l; - while( !( l = findChildren() ).isEmpty() ) +void DemoServer::terminate() +{ + m_vncServerSocket->disconnect( this ); + + const auto connections = findChildren(); + if( connections.isEmpty() ) { - delete l.front(); + deleteLater(); } + else + { + for( auto connection : connections ) + { + connection->quit(); + } + + for( auto connection : connections ) + { + connection->wait( ConnectionThreadWaitTime ); + } + + QTimer::singleShot( TerminateRetryInterval, this, &DemoServer::terminate ); + } +} - vDebug() << "deleting server socket"; - delete m_vncServerSocket; - vDebug() << "deleting TCP server"; - delete m_tcpServer; - vDebug() << "finished"; +const QByteArray& DemoServer::serverInitMessage() const +{ + return m_vncClientProtocol->serverInitMessage(); } @@ -109,16 +121,25 @@ void DemoServer::lockDataForRead() -void DemoServer::acceptPendingConnections() +void DemoServer::incomingConnection( qintptr socketDescriptor ) { - if( m_vncClientProtocol.state() != VncClientProtocol::Running ) + vDebug() << socketDescriptor; + + m_pendingConnections.append( socketDescriptor ); + + if( m_vncClientProtocol->state() == VncClientProtocol::State::Running ) { - return; + acceptPendingConnections(); } +} + + - while( m_tcpServer->hasPendingConnections() ) +void DemoServer::acceptPendingConnections() +{ + while( m_pendingConnections.isEmpty() == false ) { - new DemoServerConnection( m_demoAccessToken, m_tcpServer->nextPendingConnection(), this ); + new DemoServerConnection( this, m_authentication, m_pendingConnections.takeFirst() ); } } @@ -126,7 +147,7 @@ void DemoServer::acceptPendingConnections() void DemoServer::reconnectToVncServer() { - m_vncClientProtocol.start(); + m_vncClientProtocol->start(); m_vncServerSocket->connectToHost( QHostAddress::LocalHost, static_cast( m_vncServerPort ) ); } @@ -135,13 +156,13 @@ void DemoServer::reconnectToVncServer() void DemoServer::readFromVncServer() { - if( m_vncClientProtocol.state() != VncClientProtocol::Running ) + if( m_vncClientProtocol->state() != VncClientProtocol::State::Running ) { - while( m_vncClientProtocol.read() ) + while( m_vncClientProtocol->read() ) { } - if( m_vncClientProtocol.state() == VncClientProtocol::Running ) + if( m_vncClientProtocol->state() == VncClientProtocol::State::Running ) { start(); } @@ -158,7 +179,7 @@ void DemoServer::readFromVncServer() void DemoServer::requestFramebufferUpdate() { - if( m_vncClientProtocol.state() != VncClientProtocol::Running ) + if( m_vncClientProtocol->state() != VncClientProtocol::State::Running ) { return; } @@ -167,13 +188,13 @@ void DemoServer::requestFramebufferUpdate() m_lastFullFramebufferUpdate.elapsed() >= m_keyFrameInterval ) { vDebug() << "Requesting full framebuffer update"; - m_vncClientProtocol.requestFramebufferUpdate( false ); + m_vncClientProtocol->requestFramebufferUpdate( false ); m_lastFullFramebufferUpdate.restart(); m_requestFullFramebufferUpdate = false; } else { - m_vncClientProtocol.requestFramebufferUpdate( true ); + m_vncClientProtocol->requestFramebufferUpdate( true ); } } @@ -181,15 +202,15 @@ void DemoServer::requestFramebufferUpdate() bool DemoServer::receiveVncServerMessage() { - if( m_vncClientProtocol.receiveMessage() ) + if( m_vncClientProtocol->receiveMessage() ) { - if( m_vncClientProtocol.lastMessageType() == rfbFramebufferUpdate ) + if( m_vncClientProtocol->lastMessageType() == rfbFramebufferUpdate ) { - enqueueFramebufferUpdateMessage( m_vncClientProtocol.lastMessage() ); + enqueueFramebufferUpdateMessage( m_vncClientProtocol->lastMessage() ); } else { - vWarning() << "skipping server message of type" << static_cast( m_vncClientProtocol.lastMessageType() ); + vWarning() << "skipping server message of type" << static_cast( m_vncClientProtocol->lastMessageType() ); } return true; @@ -212,11 +233,11 @@ void DemoServer::enqueueFramebufferUpdateMessage( const QByteArray& message ) vDebug() << "locking for write took" << writeLockTime.elapsed() << "ms"; } - const auto lastUpdatedRect = m_vncClientProtocol.lastUpdatedRect(); + const auto lastUpdatedRect = m_vncClientProtocol->lastUpdatedRect(); const bool isFullUpdate = ( lastUpdatedRect.x() == 0 && lastUpdatedRect.y() == 0 && - lastUpdatedRect.width() == m_vncClientProtocol.framebufferWidth() && - lastUpdatedRect.height() == m_vncClientProtocol.framebufferHeight() ); + lastUpdatedRect.width() == m_vncClientProtocol->framebufferWidth() && + lastUpdatedRect.height() == m_vncClientProtocol->framebufferHeight() ); const auto queueSize = framebufferUpdateMessageQueueSize(); @@ -225,9 +246,32 @@ void DemoServer::enqueueFramebufferUpdateMessage( const QByteArray& message ) if( m_keyFrameTimer.elapsed() > 1 ) { const auto memTotal = queueSize / 1024; - vDebug() - << " MEMTOTAL:" << memTotal - << " KB/s:" << ( memTotal * 1000 ) / m_keyFrameTimer.elapsed(); + const auto bandwidth = qMax(1, (memTotal * 1000) / m_keyFrameTimer.elapsed()); + const auto clientCount = qMin(1, findChildren().count()); + const auto totalBandwidth = bandwidth * clientCount; + + auto newQuality = m_quality; + if (totalBandwidth > m_bandwidthLimit) + { + newQuality = qMax(int(MinimumQuality), + m_quality - qMax(1, int(totalBandwidth / m_bandwidthLimit))); + } + else if (totalBandwidth < m_bandwidthLimit * 4 / 5) + { + newQuality = qMin(int(MaximumQuality), + m_quality + qMax(1, int(m_bandwidthLimit / totalBandwidth))); + } + + if (newQuality != m_quality) + { + setVncServerEncodings(newQuality); + } + + vDebug() << "message count:" << m_framebufferUpdateMessages.size() + << "queue size (KB):" << memTotal + << "total bandwidth (KB/s):" << totalBandwidth << "of" << m_bandwidthLimit + << "bandwidth per client (KB/s):" << bandwidth + << "quality" << m_quality; } m_keyFrameTimer.restart(); ++m_keyFrame; @@ -253,7 +297,7 @@ qint64 DemoServer::framebufferUpdateMessageQueueSize() const { qint64 size = 0; - for( const auto& message : qAsConst( m_framebufferUpdateMessages ) ) + for( const auto& message : std::as_const( m_framebufferUpdateMessages ) ) { size += message.size(); } @@ -265,8 +309,10 @@ qint64 DemoServer::framebufferUpdateMessageQueueSize() const void DemoServer::start() { + vDebug(); + setVncServerPixelFormat(); - setVncServerEncodings(); + setVncServerEncodings(DefaultQuality); m_requestFullFramebufferUpdate = true; @@ -286,7 +332,7 @@ bool DemoServer::setVncServerPixelFormat() rfbPixelFormat format; format.bitsPerPixel = 32; - format.depth = 32; + format.depth = 24; format.bigEndian = qFromBigEndian( 1 ) == 1 ? true : false; format.trueColour = 1; format.redShift = 16; @@ -298,25 +344,32 @@ bool DemoServer::setVncServerPixelFormat() format.pad1 = 0; format.pad2 = 0; - return m_vncClientProtocol.setPixelFormat( format ); + m_vncClientProtocol->setPixelFormat(format); + + return m_vncClientProtocol->sendPixelFormat(); } -bool DemoServer::setVncServerEncodings() +bool DemoServer::setVncServerEncodings(int quality) { - return m_vncClientProtocol. - setEncodings( { - rfbEncodingUltraZip, - rfbEncodingUltra, - rfbEncodingCopyRect, - rfbEncodingHextile, - rfbEncodingCoRRE, - rfbEncodingRRE, - rfbEncodingRaw, - rfbEncodingCompressLevel9, - rfbEncodingQualityLevel7, - rfbEncodingNewFBSize, - rfbEncodingLastRect - } ); + m_quality = quality; + + m_vncClientProtocol->setEncodings({ + rfbEncodingTight, + rfbEncodingZYWRLE, + rfbEncodingZRLE, + rfbEncodingUltra, + rfbEncodingCopyRect, + rfbEncodingHextile, + rfbEncodingCoRRE, + rfbEncodingRRE, + rfbEncodingRaw, + rfbEncodingCompressLevel9, + rfbEncodingQualityLevel0 + quality, + rfbEncodingNewFBSize, + rfbEncodingLastRect + }); + + return m_vncClientProtocol->sendEncodings(); } diff --git a/plugins/demo/DemoServer.h b/plugins/demo/DemoServer.h index 04251a50f..16071e0bb 100644 --- a/plugins/demo/DemoServer.h +++ b/plugins/demo/DemoServer.h @@ -2,7 +2,7 @@ * DemoServer.h - multi-threaded slim VNC-server for demo-purposes (optimized * for lot of clients accessing server in read-only-mode) * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,32 +27,36 @@ #include #include +#include #include -#include "VncClientProtocol.h" +#include "CryptoCore.h" +class DemoAuthentication; class DemoConfiguration; class QTcpServer; +class QTcpSocket; +class VncClientProtocol; -class DemoServer : public QObject +class DemoServer : public QTcpServer { Q_OBJECT public: + using Password = CryptoCore::PlaintextPassword; using MessageList = QVector; - DemoServer( int vncServerPort, const QString& vncServerPassword, const QString& demoAccessToken, - const DemoConfiguration& configuration, QObject *parent ); + DemoServer( int vncServerPort, const Password& vncServerPassword, const DemoAuthentication& authentication, + const DemoConfiguration& configuration, int demoServerPort, QObject *parent ); ~DemoServer() override; + void terminate(); + const DemoConfiguration& configuration() const { return m_configuration; } - const QByteArray& serverInitMessage() const - { - return m_vncClientProtocol.serverInitMessage(); - } + const QByteArray& serverInitMessage() const; void lockDataForRead(); @@ -72,6 +76,7 @@ class DemoServer : public QObject } private: + void incomingConnection( qintptr socketDescriptor ) override; void acceptPendingConnections(); void reconnectToVncServer(); void readFromVncServer(); @@ -84,25 +89,33 @@ class DemoServer : public QObject void start(); bool setVncServerPixelFormat(); - bool setVncServerEncodings(); + bool setVncServerEncodings(int quality); + static constexpr auto ConnectionThreadWaitTime = 5000; + static constexpr auto TerminateRetryInterval = 1000; + static constexpr auto MinimumQuality = 0; + static constexpr auto DefaultQuality = 6; + static constexpr auto MaximumQuality = 9; + + const DemoAuthentication& m_authentication; const DemoConfiguration& m_configuration; const qint64 m_memoryLimit; const int m_keyFrameInterval; const int m_vncServerPort; - const QString m_demoAccessToken; - QTcpServer* m_tcpServer; + QList m_pendingConnections; QTcpSocket* m_vncServerSocket; - VncClientProtocol m_vncClientProtocol; - - QReadWriteLock m_dataLock; - QTimer m_framebufferUpdateTimer; - QElapsedTimer m_lastFullFramebufferUpdate; - QElapsedTimer m_keyFrameTimer; - bool m_requestFullFramebufferUpdate; - - int m_keyFrame; - MessageList m_framebufferUpdateMessages; + VncClientProtocol* m_vncClientProtocol; + + QReadWriteLock m_dataLock{}; + QTimer m_framebufferUpdateTimer{this}; + QElapsedTimer m_lastFullFramebufferUpdate{}; + QElapsedTimer m_keyFrameTimer{}; + bool m_requestFullFramebufferUpdate{false}; + + int m_keyFrame{0}; + MessageList m_framebufferUpdateMessages{}; + int m_quality = DefaultQuality; + int m_bandwidthLimit; } ; diff --git a/plugins/demo/DemoServerConnection.cpp b/plugins/demo/DemoServerConnection.cpp index f86d18b0c..041ab3cf8 100644 --- a/plugins/demo/DemoServerConnection.cpp +++ b/plugins/demo/DemoServerConnection.cpp @@ -2,7 +2,7 @@ * DemoServer.cpp - multi-threaded slim VNC-server for demo-purposes (optimized * for lot of clients accessing server in read-only-mode) * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,59 +23,83 @@ * */ +#include "rfb/rfbproto.h" + #include #include "DemoConfiguration.h" #include "DemoServer.h" #include "DemoServerConnection.h" +#include "FeatureMessage.h" -DemoServerConnection::DemoServerConnection( const QString& demoAccessToken, - QTcpSocket* socket, - DemoServer* demoServer ) : - QObject( demoServer ), +DemoServerConnection::DemoServerConnection( DemoServer* demoServer, + const DemoAuthentication& authentication, + quintptr socketDescriptor ) : + QThread( demoServer ), + m_authentication( authentication ), m_demoServer( demoServer ), - m_socket( socket ), - m_vncServerClient(), - m_serverProtocol( demoAccessToken, m_socket, &m_vncServerClient ), + m_socketDescriptor( socketDescriptor ), m_rfbClientToServerMessageSizes( { std::pair( rfbSetPixelFormat, sz_rfbSetPixelFormatMsg ), std::pair( rfbFramebufferUpdateRequest, sz_rfbFramebufferUpdateRequestMsg ), std::pair( rfbKeyEvent, sz_rfbKeyEventMsg ), std::pair( rfbPointerEvent, sz_rfbPointerEventMsg ), } ), - m_keyFrame( -1 ), - m_framebufferUpdateMessageIndex( 0 ), m_framebufferUpdateInterval( m_demoServer->configuration().framebufferUpdateInterval() ) { - connect( m_socket, &QTcpSocket::readyRead, this, &DemoServerConnection::processClient ); - connect( m_socket, &QTcpSocket::disconnected, this, &DemoServerConnection::deleteLater ); - - m_serverProtocol.setServerInitMessage( m_demoServer->serverInitMessage() ); - m_serverProtocol.start(); + start(); } -DemoServerConnection::~DemoServerConnection() +void DemoServerConnection::run() { + vDebug() << m_socketDescriptor; + + m_socket = new QTcpSocket; + + if( m_socket->setSocketDescriptor( m_socketDescriptor ) == false ) + { + vCritical() << "failed to set socket descriptor"; + delete m_socket; + m_socket = nullptr; + deleteLater(); + return; + } + + connect( m_socket, &QTcpSocket::readyRead, this, &DemoServerConnection::processClient, Qt::DirectConnection ); + connect( m_socket, &QTcpSocket::disconnected, this, &DemoServerConnection::quit ); + + m_serverProtocol = new DemoServerProtocol( m_authentication, m_socket, &m_vncServerClient ), + + m_serverProtocol->setServerInitMessage( m_demoServer->serverInitMessage() ); + m_serverProtocol->start(); + + exec(); + + delete m_serverProtocol; delete m_socket; + + m_socket = nullptr; + + deleteLater(); } void DemoServerConnection::processClient() { - if( m_serverProtocol.state() != VncServerProtocol::Running ) + if( m_serverProtocol->state() != VncServerProtocol::State::Running ) { - while( m_serverProtocol.read() ) + while( m_serverProtocol->read() ) { } // try again later in case we could not proceed because of // external protocol dependencies or in case we're finished // and already have RFB messages in receive queue - QTimer::singleShot( ProtocolRetryTime, this, &DemoServerConnection::processClient ); + QTimer::singleShot( ProtocolRetryTime, m_socket, [this]() { processClient(); } ); } else { @@ -112,6 +136,18 @@ bool DemoServerConnection::receiveClientMessage() } break; + case FeatureMessage::RfbMessageType: + { + FeatureMessage featureMessage; + m_socket->getChar(nullptr); + if( featureMessage.isReadyForReceive(m_socket) && featureMessage.receive(m_socket) ) + { + return true; + } + m_socket->ungetChar(messageType); + break; + } + default: if( m_rfbClientToServerMessageSizes.contains( messageType ) == false ) { @@ -157,9 +193,10 @@ void DemoServerConnection::sendFramebufferUpdate() } bool sentUpdates = false; - for( ; m_framebufferUpdateMessageIndex < framebufferUpdateMessageCount; ++m_framebufferUpdateMessageIndex ) + while( m_framebufferUpdateMessageIndex < framebufferUpdateMessageCount ) { m_socket->write( framebufferUpdateMessages[m_framebufferUpdateMessageIndex] ); + ++m_framebufferUpdateMessageIndex; sentUpdates = true; } @@ -168,6 +205,6 @@ void DemoServerConnection::sendFramebufferUpdate() if( sentUpdates == false ) { // did not send updates but client still waiting for update? then try again soon - QTimer::singleShot( m_framebufferUpdateInterval, this, &DemoServerConnection::sendFramebufferUpdate ); + QTimer::singleShot( m_framebufferUpdateInterval, m_socket, [this]() { sendFramebufferUpdate(); } ); } } diff --git a/plugins/demo/DemoServerConnection.h b/plugins/demo/DemoServerConnection.h index 6b364f436..58bdc32ea 100644 --- a/plugins/demo/DemoServerConnection.h +++ b/plugins/demo/DemoServerConnection.h @@ -1,7 +1,7 @@ /* * DemoServerConnection.h - header file for DemoServerConnection class * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -33,35 +33,36 @@ class DemoServer; // the demo server creates an instance of this class for each client connection, // i.e. each client is connected to a different server thread for best // performance -class DemoServerConnection : public QObject +class DemoServerConnection : public QThread { Q_OBJECT public: - enum { - ProtocolRetryTime = 250, - }; + static constexpr int ProtocolRetryTime = 250; - DemoServerConnection( const QString& demoAccessToken, QTcpSocket* socket, DemoServer* demoServer ); - ~DemoServerConnection() override; + DemoServerConnection( DemoServer* demoServer, const DemoAuthentication& authentication, quintptr socketDescriptor ); + ~DemoServerConnection() = default; -public slots: - void processClient(); +private: + void run() override; + + void processClient(); // clazy:exclude=thread-with-slots void sendFramebufferUpdate(); -private: bool receiveClientMessage(); + const DemoAuthentication& m_authentication; DemoServer* m_demoServer; - QTcpSocket* m_socket; + quintptr m_socketDescriptor; + QTcpSocket* m_socket{nullptr}; - VncServerClient m_vncServerClient; - DemoServerProtocol m_serverProtocol; + VncServerClient m_vncServerClient{}; + DemoServerProtocol* m_serverProtocol{nullptr}; const QMap m_rfbClientToServerMessageSizes; - int m_keyFrame; - int m_framebufferUpdateMessageIndex; + int m_keyFrame{-1}; + int m_framebufferUpdateMessageIndex{0}; const int m_framebufferUpdateInterval; diff --git a/plugins/demo/DemoServerProtocol.cpp b/plugins/demo/DemoServerProtocol.cpp index dc9f16c87..e89b465b6 100644 --- a/plugins/demo/DemoServerProtocol.cpp +++ b/plugins/demo/DemoServerProtocol.cpp @@ -1,7 +1,7 @@ /* * DemoServerProtocol.cpp - implementation of DemoServerProtocol class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,29 +22,32 @@ * */ +#include + +#include "DemoAuthentication.h" #include "DemoServerProtocol.h" #include "VariantArrayMessage.h" #include "VncServerClient.h" -DemoServerProtocol::DemoServerProtocol( const QString& demoAccessToken, QTcpSocket* socket, VncServerClient* client ) : +DemoServerProtocol::DemoServerProtocol( const DemoAuthentication& authentication, QTcpSocket* socket, VncServerClient* client ) : VncServerProtocol( socket, client ), - m_demoAccessToken( demoAccessToken ) + m_authentication( authentication ) { } -QVector DemoServerProtocol::supportedAuthTypes() const +DemoServerProtocol::AuthMethodUids DemoServerProtocol::supportedAuthMethodUids() const { - return { RfbVeyonAuth::Token }; + return { m_authentication.pluginUid() }; } void DemoServerProtocol::processAuthenticationMessage( VariantArrayMessage& message ) { - if( client()->authType() == RfbVeyonAuth::Token ) + if( client()->authMethodUid() == m_authentication.pluginUid() ) { client()->setAuthState( performTokenAuthentication( message ) ); } @@ -68,10 +71,10 @@ VncServerClient::AuthState DemoServerProtocol::performTokenAuthentication( Varia switch( client()->authState() ) { case VncServerClient::AuthState::Init: - return VncServerClient::AuthState::Token; + return VncServerClient::AuthState::Stage1; - case VncServerClient::AuthState::Token: - if( message.read().toString() == m_demoAccessToken ) + case VncServerClient::AuthState::Stage1: + if( message.read().toByteArray() == m_authentication.accessToken().toByteArray() ) { vDebug() << "SUCCESS"; return VncServerClient::AuthState::Successful; diff --git a/plugins/demo/DemoServerProtocol.h b/plugins/demo/DemoServerProtocol.h index 5e71ff6c7..9bf01eff8 100644 --- a/plugins/demo/DemoServerProtocol.h +++ b/plugins/demo/DemoServerProtocol.h @@ -1,7 +1,7 @@ /* * DemoServerProtocol.h - header file for DemoServerProtocol class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,21 +27,23 @@ #include "VncServerClient.h" #include "VncServerProtocol.h" +class DemoAuthentication; + // clazy:excludeall=copyable-polymorphic class DemoServerProtocol : public VncServerProtocol { public: - DemoServerProtocol( const QString& demoAccessToken, QTcpSocket* socket, VncServerClient* client ); + DemoServerProtocol( const DemoAuthentication& authentication, QTcpSocket* socket, VncServerClient* client ); protected: - QVector supportedAuthTypes() const override; + AuthMethodUids supportedAuthMethodUids() const override; void processAuthenticationMessage( VariantArrayMessage& message ) override; void performAccessControl() override; private: VncServerClient::AuthState performTokenAuthentication( VariantArrayMessage& message ); - const QString m_demoAccessToken; + const DemoAuthentication& m_authentication; } ; diff --git a/plugins/demo/demo.png b/plugins/demo/demo.png new file mode 100644 index 000000000..4c7629e86 Binary files /dev/null and b/plugins/demo/demo.png differ diff --git a/plugins/demo/demo.qrc b/plugins/demo/demo.qrc index f99f62946..c3c5fc57d 100644 --- a/plugins/demo/demo.qrc +++ b/plugins/demo/demo.qrc @@ -1,5 +1,6 @@ + demo.png presentation-fullscreen.png presentation-window.png window-duplicate.png diff --git a/plugins/desktopservices/CMakeLists.txt b/plugins/desktopservices/CMakeLists.txt index 9020c5d57..f2445e4ae 100644 --- a/plugins/desktopservices/CMakeLists.txt +++ b/plugins/desktopservices/CMakeLists.txt @@ -1,13 +1,13 @@ -INCLUDE(BuildPlugin) +include(BuildVeyonPlugin) -BUILD_PLUGIN(desktopservices +build_veyon_plugin(desktopservices DesktopServiceObject.cpp DesktopServicesConfigurationPage.cpp DesktopServicesConfigurationPage.ui DesktopServicesFeaturePlugin.cpp - RunProgramDialog.cpp - RunProgramDialog.h - RunProgramDialog.ui + StartAppDialog.cpp + StartAppDialog.h + StartAppDialog.ui OpenWebsiteDialog.cpp OpenWebsiteDialog.h OpenWebsiteDialog.ui @@ -16,5 +16,4 @@ BUILD_PLUGIN(desktopservices DesktopServicesConfigurationPage.h DesktopServicesFeaturePlugin.h desktopservices.qrc -) - + ) diff --git a/plugins/desktopservices/DesktopServiceObject.cpp b/plugins/desktopservices/DesktopServiceObject.cpp index 4412ba3c0..5b67335b0 100644 --- a/plugins/desktopservices/DesktopServiceObject.cpp +++ b/plugins/desktopservices/DesktopServiceObject.cpp @@ -1,7 +1,7 @@ /* * DesktopServiceObject.cpp - data class representing a desktop service object * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/plugins/desktopservices/DesktopServiceObject.h b/plugins/desktopservices/DesktopServiceObject.h index 7cee1b158..888bbf013 100644 --- a/plugins/desktopservices/DesktopServiceObject.h +++ b/plugins/desktopservices/DesktopServiceObject.h @@ -1,7 +1,7 @@ /* * DesktopServiceObject.h - data class representing a desktop service object * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -30,6 +30,7 @@ class QJsonObject; +// clazy:excludeall=rule-of-three class DesktopServiceObject { public: @@ -39,7 +40,7 @@ class DesktopServiceObject enum class Type { None, - Program, + Application, Website, } ; diff --git a/plugins/desktopservices/DesktopServicesConfiguration.h b/plugins/desktopservices/DesktopServicesConfiguration.h index c982221a4..47db3a4bd 100644 --- a/plugins/desktopservices/DesktopServicesConfiguration.h +++ b/plugins/desktopservices/DesktopServicesConfiguration.h @@ -1,7 +1,7 @@ /* * DesktopServicesConfiguration.h - configuration values for DesktopServices * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -28,7 +28,10 @@ #include "Configuration/Proxy.h" #define FOREACH_DESKTOP_SERVICES_CONFIG_PROPERTY(OP) \ - OP( DesktopServicesConfiguration, m_configuration, QJsonArray, predefinedPrograms, setPredefinedPrograms, "PredefinedPrograms", "DesktopServices", QJsonArray(), Configuration::Property::Flag::Standard ) \ + OP( DesktopServicesConfiguration, m_configuration, QJsonArray, legacyPredefinedPrograms, setLegacyPredefinedPrograms, "PredefinedPrograms", "DesktopServices", QJsonArray(), Configuration::Property::Flag::Legacy) \ + OP( DesktopServicesConfiguration, m_configuration, QJsonArray, predefinedApplications, setPredefinedApplications, "PredefinedApplications", "DesktopServices", QJsonArray(), Configuration::Property::Flag::Standard ) \ OP( DesktopServicesConfiguration, m_configuration, QJsonArray, predefinedWebsites, setPredefinedWebsites, "PredefinedWebsites", "DesktopServices", QJsonArray(), Configuration::Property::Flag::Standard ) \ +// clazy:excludeall=missing-qobject-macro + DECLARE_CONFIG_PROXY(DesktopServicesConfiguration, FOREACH_DESKTOP_SERVICES_CONFIG_PROPERTY) diff --git a/plugins/desktopservices/DesktopServicesConfigurationPage.cpp b/plugins/desktopservices/DesktopServicesConfigurationPage.cpp index 887f15527..5611bb68f 100644 --- a/plugins/desktopservices/DesktopServicesConfigurationPage.cpp +++ b/plugins/desktopservices/DesktopServicesConfigurationPage.cpp @@ -1,7 +1,7 @@ /* * DesktopServicesConfigurationPage.cpp - implementation of the DesktopServicesConfigurationPage class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -48,7 +48,7 @@ DesktopServicesConfigurationPage::~DesktopServicesConfigurationPage() void DesktopServicesConfigurationPage::resetWidgets() { - loadObjects( m_configuration.predefinedPrograms(), ui->programTable ); + loadObjects( m_configuration.predefinedApplications(), ui->applicationTable ); loadObjects( m_configuration.predefinedWebsites(), ui->websiteTable ); } @@ -66,35 +66,35 @@ void DesktopServicesConfigurationPage::applyConfiguration() -void DesktopServicesConfigurationPage::addProgram() +void DesktopServicesConfigurationPage::addApplication() { - auto programs = m_configuration.predefinedPrograms(); + auto applications = m_configuration.predefinedApplications(); - addServiceObject( ui->programTable, DesktopServiceObject::Type::Program, tr( "New program" ), programs ); + addServiceObject( ui->applicationTable, DesktopServiceObject::Type::Application, tr( "New application" ), applications ); - m_configuration.setPredefinedPrograms( programs ); + m_configuration.setPredefinedApplications( applications ); } -void DesktopServicesConfigurationPage::updateProgram() +void DesktopServicesConfigurationPage::updateApplication() { - auto programs = m_configuration.predefinedPrograms(); + auto applications = m_configuration.predefinedApplications(); - updateServiceObject( ui->programTable, DesktopServiceObject::Type::Program, programs ); + updateServiceObject( ui->applicationTable, DesktopServiceObject::Type::Application, applications ); - m_configuration.setPredefinedPrograms( programs ); + m_configuration.setPredefinedApplications( applications ); } -void DesktopServicesConfigurationPage::removeProgram() +void DesktopServicesConfigurationPage::removeApplication() { - auto programs = m_configuration.predefinedPrograms(); + auto applications = m_configuration.predefinedApplications(); - removeServiceObject( ui->programTable, DesktopServiceObject::Type::Program, programs ); + removeServiceObject( ui->applicationTable, DesktopServiceObject::Type::Application, applications ); - m_configuration.setPredefinedPrograms( programs ); + m_configuration.setPredefinedApplications( applications ); } diff --git a/plugins/desktopservices/DesktopServicesConfigurationPage.h b/plugins/desktopservices/DesktopServicesConfigurationPage.h index b9cfb1c17..5894116fb 100644 --- a/plugins/desktopservices/DesktopServicesConfigurationPage.h +++ b/plugins/desktopservices/DesktopServicesConfigurationPage.h @@ -1,7 +1,7 @@ /* * DesktopServicesConfigurationPage.h - header for the DesktopServicesConfigurationPage class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -45,10 +45,10 @@ class DesktopServicesConfigurationPage : public ConfigurationPage void connectWidgetsToProperties() override; void applyConfiguration() override; -private slots: - void addProgram(); - void updateProgram(); - void removeProgram(); +private Q_SLOTS: + void addApplication(); + void updateApplication(); + void removeApplication(); void addWebsite(); void updateWebsite(); void removeWebsite(); diff --git a/plugins/desktopservices/DesktopServicesConfigurationPage.ui b/plugins/desktopservices/DesktopServicesConfigurationPage.ui index 3a20e90a9..10066b2c2 100644 --- a/plugins/desktopservices/DesktopServicesConfigurationPage.ui +++ b/plugins/desktopservices/DesktopServicesConfigurationPage.ui @@ -3,7 +3,7 @@ DesktopServicesConfigurationPage - Programs & websites + Applications & websites @@ -19,11 +19,11 @@ - Predefined programs + Predefined applications - + QAbstractItemView::SelectRows @@ -49,9 +49,9 @@ - + - Add new program + Add new application @@ -63,9 +63,9 @@ - + - Remove selected program + Remove selected application @@ -101,7 +101,7 @@ - Add new program + Add new website @@ -176,10 +176,10 @@ - addProgramButton + addApplicationButton clicked() DesktopServicesConfigurationPage - addProgram() + addApplication() 296 @@ -192,10 +192,10 @@ - removeProgramButton + removeApplicationButton clicked() DesktopServicesConfigurationPage - removeProgram() + removeApplication() 296 @@ -240,10 +240,10 @@ - programTable + applicationTable cellChanged(int,int) DesktopServicesConfigurationPage - updateProgram() + updateApplication() 148 @@ -273,11 +273,11 @@ - addProgram() - removeProgram() + addApplication() + removeApplication() addWebsite() removeWebsite() - updateProgram() + updateApplication() updateWebsite() diff --git a/plugins/desktopservices/DesktopServicesFeaturePlugin.cpp b/plugins/desktopservices/DesktopServicesFeaturePlugin.cpp index 7470805b2..90054c6b4 100644 --- a/plugins/desktopservices/DesktopServicesFeaturePlugin.cpp +++ b/plugins/desktopservices/DesktopServicesFeaturePlugin.cpp @@ -1,7 +1,7 @@ /* * DesktopServicesFeaturePlugin.cpp - implementation of DesktopServicesFeaturePlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,9 +22,11 @@ * */ +#include #include #include #include +#include #include #include @@ -32,35 +34,36 @@ #include "ComputerControlInterface.h" #include "DesktopServicesConfigurationPage.h" #include "DesktopServicesFeaturePlugin.h" +#include "FeatureWorkerManager.h" #include "ObjectManager.h" #include "OpenWebsiteDialog.h" #include "PlatformCoreFunctions.h" #include "PlatformUserFunctions.h" -#include "RunProgramDialog.h" +#include "QmlCore.h" +#include "StartAppDialog.h" #include "VeyonConfiguration.h" #include "VeyonMasterInterface.h" +#include "VeyonServerInterface.h" DesktopServicesFeaturePlugin::DesktopServicesFeaturePlugin( QObject* parent ) : QObject( parent ), m_configuration( &VeyonCore::config() ), - m_runProgramFeature( QStringLiteral( "RunProgram" ), - Feature::Action | Feature::AllComponents, + m_startAppFeature( QStringLiteral( "StartApp" ), + Feature::Flag::Action | Feature::Flag::AllComponents, Feature::Uid( "da9ca56a-b2ad-4fff-8f8a-929b2927b442" ), Feature::Uid(), - tr( "Run program" ), {}, - tr( "Click this button to run a program on all computers." ), + tr( "Start application" ), {}, + tr( "Click this button to start an application on all computers." ), QStringLiteral(":/desktopservices/preferences-desktop-launch-feedback.png") ), m_openWebsiteFeature( QStringLiteral( "OpenWebsite" ), - Feature::Action | Feature::AllComponents, + Feature::Flag::Action | Feature::Flag::AllComponents, Feature::Uid( "8a11a75d-b3db-48b6-b9cb-f8422ddd5b0c" ), Feature::Uid(), tr( "Open website" ), {}, tr( "Click this button to open a website on all computers." ), QStringLiteral(":/desktopservices/internet-web-browser.png") ), - m_predefinedProgramsFeatures(), - m_predefinedWebsitesFeatures(), - m_features( { m_runProgramFeature, m_openWebsiteFeature } ) + m_features( { m_startAppFeature, m_openWebsiteFeature } ) { connect( VeyonCore::instance(), &VeyonCore::applicationLoaded, this, &DesktopServicesFeaturePlugin::updateFeatures ); @@ -68,27 +71,73 @@ DesktopServicesFeaturePlugin::DesktopServicesFeaturePlugin( QObject* parent ) : +void DesktopServicesFeaturePlugin::upgrade(const QVersionNumber& oldVersion) +{ + if( oldVersion < QVersionNumber( 1, 2 ) && + m_configuration.legacyPredefinedPrograms().isEmpty() == false ) + { + m_configuration.setPredefinedApplications( m_configuration.legacyPredefinedPrograms() ); + } +} + + + +bool DesktopServicesFeaturePlugin::controlFeature( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) +{ + if( operation != Operation::Start ) + { + return false; + } + + if( featureUid == m_startAppFeature.uid() ) + { + const auto apps = arguments.value( argToString(Argument::Applications) ).toStringList(); + + sendFeatureMessage( FeatureMessage{ featureUid, FeatureMessage::DefaultCommand } + .addArgument( Argument::Applications, apps ), + computerControlInterfaces ); + + return true; + } + + if( featureUid == m_openWebsiteFeature.uid() ) + { + const auto websites = arguments.value( argToString(Argument::WebsiteUrls) ).toStringList(); + + sendFeatureMessage( FeatureMessage{ featureUid, FeatureMessage::DefaultCommand } + .addArgument( Argument::WebsiteUrls, websites ), + computerControlInterfaces ); + + return true; + } + + return false; +} + + + bool DesktopServicesFeaturePlugin::startFeature( VeyonMasterInterface& master, const Feature& feature, const ComputerControlInterfaceList& computerControlInterfaces ) { - if( feature == m_runProgramFeature ) + if( feature == m_startAppFeature ) { - runProgram( master, computerControlInterfaces ); + executeStartAppDialog( master, computerControlInterfaces ); } else if( feature == m_openWebsiteFeature ) { - openWebsite( master, computerControlInterfaces ); + executeOpenWebsiteDialog( master, computerControlInterfaces ); } - else if( m_predefinedProgramsFeatures.contains( feature ) ) + else if( m_predefinedAppsFeatures.contains( feature ) ) { - sendFeatureMessage( FeatureMessage( m_runProgramFeature.uid(), FeatureMessage::DefaultCommand ). - addArgument( ProgramsArgument, predefinedServicePath( feature.uid() ) ), computerControlInterfaces ); + sendFeatureMessage( FeatureMessage( m_startAppFeature.uid(), FeatureMessage::DefaultCommand ). + addArgument( Argument::Applications, predefinedServicePath( feature.uid() ) ), computerControlInterfaces ); } else if( m_predefinedWebsitesFeatures.contains( feature ) ) { sendFeatureMessage( FeatureMessage( m_openWebsiteFeature.uid(), FeatureMessage::DefaultCommand ). - addArgument( WebsiteUrlArgument, predefinedServicePath( feature.uid() ) ), computerControlInterfaces ); + addArgument( Argument::WebsiteUrls, predefinedServicePath( feature.uid() ) ), computerControlInterfaces ); } else @@ -101,48 +150,24 @@ bool DesktopServicesFeaturePlugin::startFeature( VeyonMasterInterface& master, c -bool DesktopServicesFeaturePlugin::stopFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) -{ - Q_UNUSED(master); - Q_UNUSED(feature); - Q_UNUSED(computerControlInterfaces); - - return false; -} - - - -bool DesktopServicesFeaturePlugin::handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) -{ - Q_UNUSED(master); - Q_UNUSED(message); - Q_UNUSED(computerControlInterface); - - return false; -} - - - bool DesktopServicesFeaturePlugin::handleFeatureMessage( VeyonServerInterface& server, const MessageContext& messageContext, const FeatureMessage& message ) { Q_UNUSED(messageContext) - Q_UNUSED(server); - if( message.featureUid() == m_runProgramFeature.uid() ) + if( message.featureUid() == m_startAppFeature.uid() ) { - const auto programs = message.argument( ProgramsArgument ).toStringList(); - for( const auto& program : programs ) + const auto apps = message.argument( Argument::Applications ).toStringList(); + for( const auto& app : apps ) { - runProgramAsUser( program ); + runApplicationAsUser( app ); } } else if( message.featureUid() == m_openWebsiteFeature.uid() ) { - openWebsite( message.argument( WebsiteUrlArgument ).toString() ); + // forward message to worker running with user privileges + server.featureWorkerManager().sendMessageToUnmanagedSessionWorker( message ); } else { @@ -156,8 +181,14 @@ bool DesktopServicesFeaturePlugin::handleFeatureMessage( VeyonServerInterface& s bool DesktopServicesFeaturePlugin::handleFeatureMessage( VeyonWorkerInterface& worker, const FeatureMessage& message ) { - Q_UNUSED(worker); - Q_UNUSED(message); + Q_UNUSED(worker) + + if( message.featureUid() == m_openWebsiteFeature.uid() ) + { + openWebsite( message.argument( Argument::WebsiteUrls ).toString() ); + QCoreApplication::quit(); + return true; + } return false; } @@ -185,11 +216,11 @@ bool DesktopServicesFeaturePlugin::eventFilter( QObject* object, QEvent* event ) { DesktopServicesConfiguration userConfig( master->userConfigurationObject() ); - if( menu->objectName() == m_runProgramFeature.name() ) + if( menu->objectName() == m_startAppFeature.name() ) { - ObjectManager objectManager( userConfig.predefinedPrograms() ); + ObjectManager objectManager( userConfig.predefinedApplications() ); objectManager.remove( DesktopServiceObject::Uid( menu->activeAction()->objectName() ) ); - userConfig.setPredefinedPrograms( objectManager.objects() ); + userConfig.setPredefinedApplications( objectManager.objects() ); } else if( menu->objectName() == m_openWebsiteFeature.name() ) { @@ -213,21 +244,21 @@ bool DesktopServicesFeaturePlugin::eventFilter( QObject* object, QEvent* event ) void DesktopServicesFeaturePlugin::updateFeatures() { - updatePredefinedProgramFeatures(); + updatePredefinedApplicationFeatures(); updatePredefinedWebsiteFeatures(); - m_features = FeatureList( { m_runProgramFeature, m_openWebsiteFeature } ) + - m_predefinedProgramsFeatures + m_predefinedWebsitesFeatures; + m_features = FeatureList( { m_startAppFeature, m_openWebsiteFeature } ) + + m_predefinedAppsFeatures + m_predefinedWebsitesFeatures; auto master = VeyonCore::instance()->findChild(); if( master ) { master->reloadSubFeatures(); - auto runProgramButton = master->mainWindow()->findChild( m_runProgramFeature.name() ); - if( runProgramButton && runProgramButton->menu() ) + auto startAppButton = master->mainWindow()->findChild( m_startAppFeature.name() ); + if( startAppButton && startAppButton->menu() ) { - runProgramButton->menu()->installEventFilter( this ); + startAppButton->menu()->installEventFilter( this ); } auto openWebsiteButton = master->mainWindow()->findChild( m_openWebsiteFeature.name() ); @@ -255,65 +286,109 @@ void DesktopServicesFeaturePlugin::openMenu( const QString& objectName ) -void DesktopServicesFeaturePlugin::runProgram( VeyonMasterInterface& master, - const ComputerControlInterfaceList& computerControlInterfaces ) +void DesktopServicesFeaturePlugin::executeStartAppDialog( VeyonMasterInterface& master, + const ComputerControlInterfaceList& computerControlInterfaces ) { - RunProgramDialog runProgramDialog( master.mainWindow() ); + if( master.appWindow() ) + { + auto dialog = VeyonCore::qmlCore().createObjectFromFile( QStringLiteral("qrc:/desktopservices/StartAppDialog.qml"), + master.appWindow(), + this ); + connect( this, &DesktopServicesFeaturePlugin::acceptStartAppDialog, dialog, // clazy:exclude=connect-non-signal + [this, &master, computerControlInterfaces]( const QString& app, const QString& saveItemName ) { + startApp( app, saveItemName, master, computerControlInterfaces ); + } ); + return; + } - if( runProgramDialog.exec() == QDialog::Accepted ) + StartAppDialog startAppDialog( master.mainWindow() ); + + if( startAppDialog.exec() == QDialog::Accepted ) { - sendFeatureMessage( FeatureMessage( m_runProgramFeature.uid(), FeatureMessage::DefaultCommand ). - addArgument( ProgramsArgument, runProgramDialog.programs().split( QLatin1Char('\n') ) ), - computerControlInterfaces ); + startApp( startAppDialog.apps(), + startAppDialog.remember() ? startAppDialog.presetName() : QString{}, + master, computerControlInterfaces ); + } +} - if( runProgramDialog.remember() ) - { - DesktopServicesConfiguration userConfig( master.userConfigurationObject() ); - ObjectManager objectManager( userConfig.predefinedPrograms() ); - objectManager.add( DesktopServiceObject( DesktopServiceObject::Type::Program, - runProgramDialog.presetName(), - runProgramDialog.programs() ) ); - userConfig.setPredefinedPrograms( objectManager.objects() ); - userConfig.flushStore(); - updateFeatures(); - } +void DesktopServicesFeaturePlugin::startApp( const QString& app, const QString& saveItemName, + VeyonMasterInterface& master, + const ComputerControlInterfaceList& computerControlInterfaces ) +{ + controlFeature( m_startAppFeature.uid(), Operation::Start, + { { argToString(Argument::Applications), app.split( QLatin1Char('\n') ) } }, + computerControlInterfaces ); + + if( saveItemName.isEmpty() == false ) + { + DesktopServicesConfiguration userConfig( master.userConfigurationObject() ); + + ObjectManager objectManager( userConfig.predefinedApplications() ); + objectManager.add( DesktopServiceObject( DesktopServiceObject::Type::Application, + saveItemName, app ) ); + userConfig.setPredefinedApplications( objectManager.objects() ); + userConfig.flushStore(); + + updateFeatures(); } } -void DesktopServicesFeaturePlugin::openWebsite( VeyonMasterInterface& master, +void DesktopServicesFeaturePlugin::executeOpenWebsiteDialog( VeyonMasterInterface& master, const ComputerControlInterfaceList& computerControlInterfaces ) { + if( master.appWindow() ) + { + auto dialog = VeyonCore::qmlCore().createObjectFromFile( QStringLiteral("qrc:/desktopservices/OpenWebsiteDialog.qml"), + master.appWindow(), + this ); + connect( this, &DesktopServicesFeaturePlugin::acceptOpenWebsiteDialog, dialog, // clazy:exclude=connect-non-signal + [this, &master, computerControlInterfaces]( const QString& app, const QString& saveItemName ) { + openWebsite( app, saveItemName, master, computerControlInterfaces ); + } ); + return; + } + OpenWebsiteDialog openWebsiteDialog( master.mainWindow() ); if( openWebsiteDialog.exec() == QDialog::Accepted ) { - sendFeatureMessage( FeatureMessage( m_openWebsiteFeature.uid(), FeatureMessage::DefaultCommand ). - addArgument( WebsiteUrlArgument, openWebsiteDialog.website() ), - computerControlInterfaces ); + openWebsite( openWebsiteDialog.website(), + openWebsiteDialog.remember() ? openWebsiteDialog.presetName() : QString{}, + master, computerControlInterfaces ); + } +} - if( openWebsiteDialog.remember() ) - { - DesktopServicesConfiguration userConfig( master.userConfigurationObject() ); - ObjectManager objectManager( userConfig.predefinedWebsites() ); - objectManager.add( DesktopServiceObject( DesktopServiceObject::Type::Website, - openWebsiteDialog.presetName(), - openWebsiteDialog.website() ) ); - userConfig.setPredefinedWebsites( objectManager.objects() ); - userConfig.flushStore(); - updateFeatures(); - } +void DesktopServicesFeaturePlugin::openWebsite( const QString& website, const QString& saveItemName, + VeyonMasterInterface& master, + const ComputerControlInterfaceList& computerControlInterfaces ) +{ + controlFeature( m_openWebsiteFeature.uid(), Operation::Start, + { { argToString(Argument::WebsiteUrls), website } }, + computerControlInterfaces ); + + if( saveItemName.isEmpty() == false ) + { + DesktopServicesConfiguration userConfig( master.userConfigurationObject() ); + + ObjectManager objectManager( userConfig.predefinedWebsites() ); + objectManager.add( DesktopServiceObject( DesktopServiceObject::Type::Website, + saveItemName, website ) ); + userConfig.setPredefinedWebsites( objectManager.objects() ); + userConfig.flushStore(); + + updateFeatures(); } } -void DesktopServicesFeaturePlugin::runProgramAsUser( const QString& commandLine ) +void DesktopServicesFeaturePlugin::runApplicationAsUser( const QString& commandLine ) { vDebug() << "launching" << commandLine; @@ -325,7 +400,7 @@ void DesktopServicesFeaturePlugin::runProgramAsUser( const QString& commandLine { const auto commandLineSplit = commandLine.split( QLatin1Char('"') ); program = commandLineSplit.value( 1 ); - parameters = commandLine.mid( program.size() + 2 ).split( QLatin1Char(' ') ); + parameters = commandLine.mid( program.size() + 2 ).split(QLatin1Char(' ') ); } // parse command line format program.exe -foo -bar else if( commandLine.contains( QLatin1Char(' ') ) ) @@ -365,7 +440,7 @@ bool DesktopServicesFeaturePlugin::openWebsite( const QString& urlString ) { vWarning() << "could not open URL" << url << "via QDesktopServices - trying native generic URL handler"; - runProgramAsUser( QStringLiteral("%1 %2").arg( + runApplicationAsUser( QStringLiteral("%1 %2").arg( VeyonCore::platform().coreFunctions().genericUrlHandler(), url.toString() ) ); } @@ -375,17 +450,17 @@ bool DesktopServicesFeaturePlugin::openWebsite( const QString& urlString ) -void DesktopServicesFeaturePlugin::updatePredefinedPrograms() +void DesktopServicesFeaturePlugin::updatePredefinedApplications() { - m_predefinedPrograms = m_configuration.predefinedPrograms(); + m_predefinedApps = m_configuration.predefinedApplications(); auto master = VeyonCore::instance()->findChild(); if( master ) { - const auto userPrograms = DesktopServicesConfiguration( master->userConfigurationObject() ).predefinedPrograms(); - for( const auto& userProgram : userPrograms ) + const auto userApps = DesktopServicesConfiguration( master->userConfigurationObject() ).predefinedApplications(); + for( const auto& userApp : userApps ) { - m_predefinedPrograms.append( userProgram ); + m_predefinedApps.append( userApp ); } } } @@ -409,30 +484,30 @@ void DesktopServicesFeaturePlugin::updatePredefinedWebsites() -void DesktopServicesFeaturePlugin::updatePredefinedProgramFeatures() +void DesktopServicesFeaturePlugin::updatePredefinedApplicationFeatures() { - m_predefinedProgramsFeatures.clear(); + m_predefinedAppsFeatures.clear(); - updatePredefinedPrograms(); + updatePredefinedApplications(); - if( m_predefinedPrograms.isEmpty() == false ) + if( m_predefinedApps.isEmpty() == false ) { - m_predefinedProgramsFeatures.reserve( m_predefinedPrograms.size()+1 ); + m_predefinedAppsFeatures.reserve( m_predefinedApps.size()+1 ); - for( const auto& program : qAsConst(m_predefinedPrograms) ) + for( const auto& app : std::as_const(m_predefinedApps) ) { - const auto programObject = DesktopServiceObject( program.toObject() ); - m_predefinedProgramsFeatures.append( Feature( m_runProgramFeature.name(), Feature::Action | Feature::Master, - programObject.uid(), m_runProgramFeature.uid(), - programObject.name(), {}, - tr("Run program \"%1\"").arg( programObject.path() ) ) ); + const auto appObject = DesktopServiceObject( app.toObject() ); + m_predefinedAppsFeatures.append( Feature( m_startAppFeature.name(), Feature::Flag::Action | Feature::Flag::Master, + appObject.uid(), m_startAppFeature.uid(), + appObject.name(), {}, + tr("Start application \"%1\"").arg( appObject.path() ) ) ); } - auto primaryFeature = m_runProgramFeature; + auto primaryFeature = m_startAppFeature; primaryFeature.setIconUrl( QStringLiteral(":/core/document-edit.png") ); - primaryFeature.setParentUid( m_runProgramFeature.uid() ); - primaryFeature.setDisplayName( tr("Custom program") ); - m_predefinedProgramsFeatures.append( primaryFeature ); + primaryFeature.setParentUid( m_startAppFeature.uid() ); + primaryFeature.setDisplayName( tr("Custom application") ); + m_predefinedAppsFeatures.append( primaryFeature ); } } @@ -448,10 +523,10 @@ void DesktopServicesFeaturePlugin::updatePredefinedWebsiteFeatures() { m_predefinedWebsitesFeatures.reserve( m_predefinedWebsites.size()+1 ); - for( const auto& website : qAsConst(m_predefinedWebsites) ) + for( const auto& website : std::as_const(m_predefinedWebsites) ) { const auto websiteObject = DesktopServiceObject( website.toObject() ); - m_predefinedWebsitesFeatures.append( Feature( m_openWebsiteFeature.name(), Feature::Action | Feature::Master, + m_predefinedWebsitesFeatures.append( Feature( m_openWebsiteFeature.name(), Feature::Flag::Action | Feature::Flag::Master, websiteObject.uid(), m_openWebsiteFeature.uid(), websiteObject.name(), {}, tr("Open website \"%1\"").arg( websiteObject.path() ) ) ); @@ -469,7 +544,7 @@ void DesktopServicesFeaturePlugin::updatePredefinedWebsiteFeatures() QString DesktopServicesFeaturePlugin::predefinedServicePath( Feature::Uid subFeatureUid ) const { - for( const auto& services : { m_predefinedPrograms, m_predefinedWebsites } ) + for( const auto& services : { m_predefinedApps, m_predefinedWebsites } ) { for( const auto& service : services ) { diff --git a/plugins/desktopservices/DesktopServicesFeaturePlugin.h b/plugins/desktopservices/DesktopServicesFeaturePlugin.h index 57d2a35aa..05bdca85f 100644 --- a/plugins/desktopservices/DesktopServicesFeaturePlugin.h +++ b/plugins/desktopservices/DesktopServicesFeaturePlugin.h @@ -1,7 +1,7 @@ /* * DesktopServicesFeaturePlugin.h - declaration of DesktopServicesFeaturePlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -39,17 +39,24 @@ class DesktopServicesFeaturePlugin : public QObject, PluginInterface, FeatureProviderInterface ConfigurationPagePluginInterface) public: + enum class Argument + { + Applications, + WebsiteUrls + }; + Q_ENUM(Argument) + explicit DesktopServicesFeaturePlugin( QObject* parent = nullptr ); ~DesktopServicesFeaturePlugin() override = default; Plugin::Uid uid() const override { - return QStringLiteral("a54ee018-42bf-4569-90c7-0d8470125ccf"); + return Plugin::Uid{ QStringLiteral("a54ee018-42bf-4569-90c7-0d8470125ccf") }; } QVersionNumber version() const override { - return QVersionNumber( 1, 1 ); + return QVersionNumber( 2, 0 ); } QString name() const override @@ -59,7 +66,7 @@ class DesktopServicesFeaturePlugin : public QObject, PluginInterface, QString description() const override { - return tr( "Start programs and services in user desktop" ); + return tr( "Start apps and open websites in user sessions" ); } QString vendor() const override @@ -72,20 +79,19 @@ class DesktopServicesFeaturePlugin : public QObject, PluginInterface, return QStringLiteral("Tobias Junghans"); } + void upgrade( const QVersionNumber& oldVersion ) override; + const FeatureList& featureList() const override { return m_features; } + bool controlFeature( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) override; + bool startFeature( VeyonMasterInterface& master, const Feature& feature, const ComputerControlInterfaceList& computerControlInterfaces ) override; - bool stopFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) override; - - bool handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) override; - bool handleFeatureMessage( VeyonServerInterface& server, const MessageContext& messageContext, const FeatureMessage& message ) override; @@ -94,41 +100,47 @@ class DesktopServicesFeaturePlugin : public QObject, PluginInterface, ConfigurationPage* createConfigurationPage() override; +Q_SIGNALS: + Q_INVOKABLE void acceptStartAppDialog( const QString& app, const QString& saveItemName ); + Q_INVOKABLE void acceptOpenWebsiteDialog( const QString& website, const QString& saveItemName ); + private: bool eventFilter( QObject* object, QEvent* event ) override; void updateFeatures(); void openMenu( const QString& objectName ); - void runProgram( VeyonMasterInterface& master, const ComputerControlInterfaceList& computerControlInterfaces ); - void openWebsite( VeyonMasterInterface& master, const ComputerControlInterfaceList& computerControlInterfaces ); + void executeStartAppDialog( VeyonMasterInterface& master, + const ComputerControlInterfaceList& computerControlInterfaces ); + void startApp( const QString& app, const QString& saveItemName, + VeyonMasterInterface& master, const ComputerControlInterfaceList& computerControlInterfaces ); + + void executeOpenWebsiteDialog( VeyonMasterInterface& master, + const ComputerControlInterfaceList& computerControlInterfaces ); + void openWebsite( const QString& website, const QString& saveItemName, + VeyonMasterInterface& master, const ComputerControlInterfaceList& computerControlInterfaces ); - void runProgramAsUser( const QString& commandLine ); + void runApplicationAsUser( const QString& commandLine ); bool openWebsite( const QString& urlString ); - void updatePredefinedPrograms(); + void updatePredefinedApplications(); void updatePredefinedWebsites(); - void updatePredefinedProgramFeatures(); + void updatePredefinedApplicationFeatures(); void updatePredefinedWebsiteFeatures(); QString predefinedServicePath( Feature::Uid subFeatureUid ) const; - enum Arguments { - ProgramsArgument, - WebsiteUrlArgument - }; - DesktopServicesConfiguration m_configuration; - QJsonArray m_predefinedPrograms; + QJsonArray m_predefinedApps; QJsonArray m_predefinedWebsites; - const Feature m_runProgramFeature; + const Feature m_startAppFeature; const Feature m_openWebsiteFeature; - FeatureList m_predefinedProgramsFeatures; - FeatureList m_predefinedWebsitesFeatures; + FeatureList m_predefinedAppsFeatures{}; + FeatureList m_predefinedWebsitesFeatures{}; FeatureList m_features; diff --git a/plugins/desktopservices/OpenWebsiteDialog.cpp b/plugins/desktopservices/OpenWebsiteDialog.cpp index 051ece2f0..6b3b30382 100644 --- a/plugins/desktopservices/OpenWebsiteDialog.cpp +++ b/plugins/desktopservices/OpenWebsiteDialog.cpp @@ -1,7 +1,7 @@ /* * OpenWebsiteDialog.cpp - implementation of OpenWebsiteDialog * - * Copyright (c) 2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/plugins/desktopservices/OpenWebsiteDialog.h b/plugins/desktopservices/OpenWebsiteDialog.h index 92354c9d8..ce607c0f2 100644 --- a/plugins/desktopservices/OpenWebsiteDialog.h +++ b/plugins/desktopservices/OpenWebsiteDialog.h @@ -1,7 +1,7 @@ /* * OpenWebsiteDialog.h - declaration of class OpenWebsiteDialog * - * Copyright (c) 2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public diff --git a/plugins/desktopservices/OpenWebsiteDialog.qml b/plugins/desktopservices/OpenWebsiteDialog.qml new file mode 100644 index 000000000..b30672dd6 --- /dev/null +++ b/plugins/desktopservices/OpenWebsiteDialog.qml @@ -0,0 +1,47 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.1 +import QtQuick.Dialogs 1.0 +import QtQuick.Layouts 1.0 + +Dialog { + title: qsTr("Open website") + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + standardButtons: Dialog.Ok | Dialog.Cancel + visible: true + modal: true + + onAccepted: { + context.acceptOpenWebsiteDialog(urlInput.text, remember.checked ? saveName.text : "") + qmlCore.deleteLater(this) + } + onRejected: qmlCore.deleteLater(this) + + ColumnLayout { + anchors.fill: parent + Label { + text: qsTr("Please enter the URL of the website to open:") + wrapMode: Label.WordWrap + Layout.fillWidth: true + } + + TextField { + id: urlInput + focus: true + placeholderText: qsTr("e.g. www.veyon.io") + Layout.fillWidth: true + } + + CheckBox { + id: remember + text: qsTr("Remember and add to website menu") + } + + TextField { + id: saveName + enabled: remember.checked + placeholderText: qsTr("Website name") + Layout.fillWidth: true + } + } +} diff --git a/plugins/desktopservices/RunProgramDialog.cpp b/plugins/desktopservices/StartAppDialog.cpp similarity index 59% rename from plugins/desktopservices/RunProgramDialog.cpp rename to plugins/desktopservices/StartAppDialog.cpp index 75adc2a4b..67499718f 100644 --- a/plugins/desktopservices/RunProgramDialog.cpp +++ b/plugins/desktopservices/StartAppDialog.cpp @@ -1,7 +1,7 @@ /* - * RunProgramDialog.cpp - implementation of RunProgramDialog + * StartAppDialog.cpp - implementation of StartAppDialog * - * Copyright (c) 2004-2019 Tobias Junghans + * Copyright (c) 2004-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,49 +24,49 @@ #include -#include "RunProgramDialog.h" +#include "StartAppDialog.h" -#include "ui_RunProgramDialog.h" +#include "ui_StartAppDialog.h" -RunProgramDialog::RunProgramDialog( QWidget* parent ) : +StartAppDialog::StartAppDialog( QWidget* parent ) : QDialog( parent ), - ui( new Ui::RunProgramDialog ), - m_programs(), + ui( new Ui::StartAppDialog ), + m_apps(), m_remember( false ), m_presetName() { ui->setupUi( this ); - connect( ui->programInputTextEdit, &QTextEdit::textChanged, this, &RunProgramDialog::validate ); - connect( ui->rememberCheckBox, &QCheckBox::toggled, this, &RunProgramDialog::validate ); - connect( ui->presetNameEdit, &QLineEdit::textChanged, this, &RunProgramDialog::validate ); + connect( ui->appInputTextEdit, &QTextEdit::textChanged, this, &StartAppDialog::validate ); + connect( ui->rememberCheckBox, &QCheckBox::toggled, this, &StartAppDialog::validate ); + connect( ui->presetNameEdit, &QLineEdit::textChanged, this, &StartAppDialog::validate ); validate(); - ui->programInputTextEdit->setFocus(); + ui->appInputTextEdit->setFocus(); } -RunProgramDialog::~RunProgramDialog() +StartAppDialog::~StartAppDialog() { delete ui; } -void RunProgramDialog::validate() +void StartAppDialog::validate() { ui->buttonBox->button( QDialogButtonBox::Ok )->setEnabled( - ui->programInputTextEdit->toPlainText().isEmpty() == false && + ui->appInputTextEdit->toPlainText().isEmpty() == false && ( ui->rememberCheckBox->isChecked() == false || ui->presetNameEdit->text().isEmpty() == false ) ); } -void RunProgramDialog::accept() +void StartAppDialog::accept() { - m_programs = ui->programInputTextEdit->toPlainText(); + m_apps = ui->appInputTextEdit->toPlainText(); m_remember = ui->rememberCheckBox->isChecked(); m_presetName = ui->presetNameEdit->text(); diff --git a/plugins/desktopservices/RunProgramDialog.h b/plugins/desktopservices/StartAppDialog.h similarity index 72% rename from plugins/desktopservices/RunProgramDialog.h rename to plugins/desktopservices/StartAppDialog.h index c1bb4a3c1..4def30246 100644 --- a/plugins/desktopservices/RunProgramDialog.h +++ b/plugins/desktopservices/StartAppDialog.h @@ -1,7 +1,7 @@ /* - * RunProgramDialog.h - declaration of class RunProgramDialog + * StartAppDialog.h - declaration of class StartAppDialog * - * Copyright (c) 2004-2019 Tobias Junghans + * Copyright (c) 2004-2025 Tobias Junghans * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public @@ -24,18 +24,18 @@ #include -namespace Ui { class RunProgramDialog; } +namespace Ui { class StartAppDialog; } -class RunProgramDialog : public QDialog +class StartAppDialog : public QDialog { Q_OBJECT public: - explicit RunProgramDialog( QWidget *parent ); - ~RunProgramDialog() override; + explicit StartAppDialog( QWidget *parent ); + ~StartAppDialog() override; - const QString& programs() const + const QString& apps() const { - return m_programs; + return m_apps; } bool remember() const @@ -52,8 +52,8 @@ class RunProgramDialog : public QDialog void validate(); void accept() override; - Ui::RunProgramDialog* ui; - QString m_programs; + Ui::StartAppDialog* ui; + QString m_apps; bool m_remember; QString m_presetName; diff --git a/plugins/desktopservices/StartAppDialog.qml b/plugins/desktopservices/StartAppDialog.qml new file mode 100644 index 000000000..c1a95bc99 --- /dev/null +++ b/plugins/desktopservices/StartAppDialog.qml @@ -0,0 +1,49 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.1 +import QtQuick.Dialogs 1.0 +import QtQuick.Layouts 1.0 + +Dialog { + title: qsTr("Start application") + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + standardButtons: Dialog.Ok | Dialog.Cancel + visible: true + modal: true + + onAccepted: { + context.acceptStartAppDialog(appNameInput.text, remember.checked ? saveName.text : "") + qmlCore.deleteLater(this) + } + onRejected: qmlCore.deleteLater(this) + + ColumnLayout { + anchors.fill: parent + Label { + text: qsTr("Please enter the applications to start on the selected computers. You can separate multiple applications by line.") + wrapMode: Label.WordWrap + Layout.fillWidth: true + } + + TextArea { + id: appNameInput + focus: true + // work around bug in lupdate which requires double-escaped backslashes + placeholderText: qsTr("e.g. \"C:\\\\Program Files\\\\VideoLAN\\\\VLC\\\\vlc.exe\"").replace(/\\\\/g, '\\') + Layout.fillWidth: true + Layout.fillHeight: true + } + + CheckBox { + id: remember + text: qsTr("Remember and add to application menu") + } + + TextField { + id: saveName + enabled: remember.checked + placeholderText: qsTr("Application name") + Layout.fillWidth: true + } + } +} diff --git a/plugins/desktopservices/RunProgramDialog.ui b/plugins/desktopservices/StartAppDialog.ui similarity index 88% rename from plugins/desktopservices/RunProgramDialog.ui rename to plugins/desktopservices/StartAppDialog.ui index f4ccba3da..963f80522 100644 --- a/plugins/desktopservices/RunProgramDialog.ui +++ b/plugins/desktopservices/StartAppDialog.ui @@ -1,10 +1,10 @@ Tobias Junghans - RunProgramDialog - + StartAppDialog + - Run programs + Start application @@ -39,7 +39,7 @@ - + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" @@ -48,7 +48,7 @@ - Remember and add to program menu + Remember and add to application menu @@ -65,7 +65,7 @@ - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. + Please enter the applications to start on the selected computers. You can separate multiple applications by line. true @@ -94,7 +94,7 @@ buttonBox accepted() - RunProgramDialog + StartAppDialog accept() @@ -110,7 +110,7 @@ buttonBox rejected() - RunProgramDialog + StartAppDialog reject() diff --git a/plugins/desktopservices/desktopservices.qrc b/plugins/desktopservices/desktopservices.qrc index 9fdbc2f3e..3d0ad497a 100644 --- a/plugins/desktopservices/desktopservices.qrc +++ b/plugins/desktopservices/desktopservices.qrc @@ -3,5 +3,7 @@ internet-web-browser.png preferences-desktop-launch-feedback.png desktop-services.png + OpenWebsiteDialog.qml + StartAppDialog.qml diff --git a/plugins/filetransfer/CMakeLists.txt b/plugins/filetransfer/CMakeLists.txt index 5e11cada5..7a0278882 100644 --- a/plugins/filetransfer/CMakeLists.txt +++ b/plugins/filetransfer/CMakeLists.txt @@ -1,8 +1,12 @@ -INCLUDE(BuildPlugin) +include(BuildVeyonPlugin) -BUILD_PLUGIN(filetransfer +build_veyon_plugin(filetransfer FileTransferPlugin.cpp FileTransferPlugin.h + FileTransferConfiguration.h + FileTransferConfigurationPage.cpp + FileTransferConfigurationPage.h + FileTransferConfigurationPage.ui FileTransferController.cpp FileTransferController.h FileTransferListModel.cpp @@ -14,4 +18,4 @@ BUILD_PLUGIN(filetransfer FileReadThread.cpp FileReadThread.h filetransfer.qrc -) + ) diff --git a/plugins/filetransfer/FileReadThread.cpp b/plugins/filetransfer/FileReadThread.cpp index 7ec86c715..b46d868b2 100644 --- a/plugins/filetransfer/FileReadThread.cpp +++ b/plugins/filetransfer/FileReadThread.cpp @@ -1,7 +1,7 @@ /* * FileReadThread.cpp - implementation of FileReadThread class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,15 +27,7 @@ FileReadThread::FileReadThread( const QString& fileName, QObject* parent ) : QObject( parent ), - m_mutex(), - m_thread( new QThread ), - m_file( nullptr ), - m_currentChunk(), - m_timer( new QTimer ), - m_fileName( fileName ), - m_chunkReady( false ), - m_filePos( 0 ), - m_fileSize( 0 ) + m_fileName( fileName ) { m_timer->moveToThread( m_thread ); m_thread->start(); diff --git a/plugins/filetransfer/FileReadThread.h b/plugins/filetransfer/FileReadThread.h index af733f96d..34172235c 100644 --- a/plugins/filetransfer/FileReadThread.h +++ b/plugins/filetransfer/FileReadThread.h @@ -1,7 +1,7 @@ /* * FileReadThread.h - declaration of FileReadThread class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -46,16 +46,16 @@ class FileReadThread : public QObject int progress(); private: - QMutex m_mutex; - QThread* m_thread; - QFile* m_file; - QByteArray m_currentChunk; + QMutex m_mutex{}; + QThread* m_thread{new QThread}; + QFile* m_file{nullptr}; + QByteArray m_currentChunk{}; - QTimer* m_timer; + QTimer* m_timer{new QTimer}; QString m_fileName; - bool m_chunkReady; - qint64 m_filePos; - qint64 m_fileSize; + bool m_chunkReady{false}; + qint64 m_filePos{0}; + qint64 m_fileSize{0}; }; diff --git a/plugins/filetransfer/FileTransferConfiguration.h b/plugins/filetransfer/FileTransferConfiguration.h new file mode 100644 index 000000000..430977bc7 --- /dev/null +++ b/plugins/filetransfer/FileTransferConfiguration.h @@ -0,0 +1,38 @@ +/* + * FileTransferConfiguration.h - configuration values for FileTransfer plugin + * + * Copyright (c) 2017-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "VeyonConfiguration.h" +#include "Configuration/Proxy.h" + +#define FOREACH_FILE_TRANSFER_CONFIG_PROPERTY(OP) \ + OP( FileTransferConfiguration, m_configuration, bool, rememberLastFileTransferSourceDirectory, setRememberLastFileTransferSourceDirectory, "RememberLastSourceDirectory", "FileTransfer", true, Configuration::Property::Flag::Advanced ) \ + OP( FileTransferConfiguration, m_configuration, bool, fileTransferCreateDestinationDirectory, setFileTransferCreateDestinationDirectory, "CreateDestinationDirectory", "FileTransfer", true, Configuration::Property::Flag::Advanced ) \ + OP( FileTransferConfiguration, m_configuration, QString, fileTransferDefaultSourceDirectory, setFileTransferDefaultSourceDirectory, "DefaultSourceDirectory", "FileTransfer", QStringLiteral("%HOME%"), Configuration::Property::Flag::Advanced ) \ + OP( FileTransferConfiguration, m_configuration, QString, fileTransferDestinationDirectory, setFileTransferDestinationDirectory, "DestinationDirectory", "FileTransfer", QStringLiteral("%HOME%"), Configuration::Property::Flag::Advanced ) \ + +// clazy:excludeall=missing-qobject-macro + +DECLARE_CONFIG_PROXY(FileTransferConfiguration, FOREACH_FILE_TRANSFER_CONFIG_PROPERTY) diff --git a/plugins/filetransfer/FileTransferConfigurationPage.cpp b/plugins/filetransfer/FileTransferConfigurationPage.cpp new file mode 100644 index 000000000..4fca328ea --- /dev/null +++ b/plugins/filetransfer/FileTransferConfigurationPage.cpp @@ -0,0 +1,86 @@ +/* + * FileTransferConfigurationPage.cpp - implementation of FileTransferConfigurationPage + * + * Copyright (c) 2017-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "FileSystemBrowser.h" +#include "FileTransferConfiguration.h" +#include "FileTransferConfigurationPage.h" +#include "Configuration/UiMapping.h" + +#include "ui_FileTransferConfigurationPage.h" + +FileTransferConfigurationPage::FileTransferConfigurationPage( FileTransferConfiguration& configuration, QWidget* parent ) : + ConfigurationPage( parent ), + ui( new Ui::FileTransferConfigurationPage ), + m_configuration( configuration ) +{ + ui->setupUi(this); + + connect( ui->browseDefaultSourceDirectory, &QAbstractButton::clicked, + this, &FileTransferConfigurationPage::browseDefaultSourceDirectory ); + + connect( ui->browseDestinationDirectory, &QAbstractButton::clicked, + this, &FileTransferConfigurationPage::browseDestinationDirectory ); + + Configuration::UiMapping::setFlags( this, Configuration::Property::Flag::Advanced ); +} + + + +FileTransferConfigurationPage::~FileTransferConfigurationPage() +{ + delete ui; +} + + + +void FileTransferConfigurationPage::resetWidgets() +{ + FOREACH_FILE_TRANSFER_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY); +} + + + +void FileTransferConfigurationPage::connectWidgetsToProperties() +{ + FOREACH_FILE_TRANSFER_CONFIG_PROPERTY(CONNECT_WIDGET_TO_PROPERTY) +} + + + +void FileTransferConfigurationPage::applyConfiguration() +{ +} + + +void FileTransferConfigurationPage::browseDefaultSourceDirectory() +{ + FileSystemBrowser(FileSystemBrowser::ExistingDirectory, this).exec(ui->fileTransferDefaultSourceDirectory); +} + + + +void FileTransferConfigurationPage::browseDestinationDirectory() +{ + FileSystemBrowser(FileSystemBrowser::ExistingDirectory, this).exec(ui->fileTransferDestinationDirectory); +} diff --git a/plugins/filetransfer/FileTransferConfigurationPage.h b/plugins/filetransfer/FileTransferConfigurationPage.h new file mode 100644 index 000000000..1b30426f7 --- /dev/null +++ b/plugins/filetransfer/FileTransferConfigurationPage.h @@ -0,0 +1,54 @@ +/* + * FileTransferConfigurationPage.h - header for the FileTransferConfigurationPage class + * + * Copyright (c) 2017-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "ConfigurationPage.h" + +namespace Ui { +class FileTransferConfigurationPage; +} + +class FileTransferConfiguration; + +class FileTransferConfigurationPage : public ConfigurationPage +{ + Q_OBJECT +public: + explicit FileTransferConfigurationPage( FileTransferConfiguration& configuration, QWidget* parent = nullptr ); + ~FileTransferConfigurationPage() override; + + void resetWidgets() override; + void connectWidgetsToProperties() override; + void applyConfiguration() override; + +private: + void browseDefaultSourceDirectory(); + void browseDestinationDirectory(); + + Ui::FileTransferConfigurationPage *ui; + + FileTransferConfiguration& m_configuration; + +}; diff --git a/plugins/filetransfer/FileTransferConfigurationPage.ui b/plugins/filetransfer/FileTransferConfigurationPage.ui new file mode 100644 index 000000000..67c7cf994 --- /dev/null +++ b/plugins/filetransfer/FileTransferConfigurationPage.ui @@ -0,0 +1,107 @@ + + + FileTransferConfigurationPage + + + File transfer + + + + :/filetransfer/document-share.png:/filetransfer/document-share.png + + + + 0 + + + 0 + + + + + Directories + + + + + + Destination directory + + + + + + + + + + + :/core/document-open.png:/core/document-open.png + + + + + + + + :/core/document-open.png:/core/document-open.png + + + + + + + + + + Default source directory + + + + + + + + + + Options + + + + + + Remember last source directory + + + + + + + Create destination directory if it does not exist + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + diff --git a/plugins/filetransfer/FileTransferController.cpp b/plugins/filetransfer/FileTransferController.cpp index 14486b98f..2b03ee2c5 100644 --- a/plugins/filetransfer/FileTransferController.cpp +++ b/plugins/filetransfer/FileTransferController.cpp @@ -1,7 +1,7 @@ /* * FileTransferController.cpp - implementation of FileTransferController class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,15 +31,7 @@ FileTransferController::FileTransferController( FileTransferPlugin* plugin ) : QObject( plugin ), - m_plugin( plugin ), - m_currentFileIndex( -1 ), - m_currentTransferId(), - m_files(), - m_flags( Transfer ), - m_interfaces(), - m_fileReadThread( nullptr ), - m_fileState( FileStateFinished ), - m_processTimer( this ) + m_plugin( plugin ) { m_processTimer.setInterval( ProcessInterval ); connect( &m_processTimer, &QTimer::timeout, this, &FileTransferController::process ); @@ -49,10 +41,7 @@ FileTransferController::FileTransferController( FileTransferPlugin* plugin ) : FileTransferController::~FileTransferController() { - if( m_fileReadThread ) - { - delete m_fileReadThread; - } + delete m_fileReadThread; } @@ -61,7 +50,7 @@ void FileTransferController::setFiles( const QStringList& files ) { m_files = files; m_currentFileIndex = 0; - emit filesChanged(); + Q_EMIT filesChanged(); } @@ -88,7 +77,7 @@ void FileTransferController::start() m_fileState = FileStateOpen; m_processTimer.start(); - emit started(); + Q_EMIT started(); } } @@ -109,7 +98,7 @@ void FileTransferController::stop() m_plugin->sendCancelMessage( m_currentTransferId, m_interfaces ); } - emit finished(); + Q_EMIT finished(); } @@ -167,8 +156,10 @@ void FileTransferController::process() m_plugin->sendOpenTransferFolderMessage( m_interfaces ); } + m_plugin->sendStopWorkerMessage(m_interfaces); + m_processTimer.stop(); - emit finished(); + Q_EMIT finished(); } else { @@ -195,7 +186,7 @@ bool FileTransferController::openFile() { delete m_fileReadThread; m_fileReadThread = nullptr; - emit errorOccured( tr( "Could not open file \"%1\" for reading! Please check your permissions!" ).arg( m_currentFileIndex ) ); + Q_EMIT errorOccured( tr( "Could not open file \"%1\" for reading! Please check your permissions!" ).arg( m_currentFileIndex ) ); return false; } @@ -255,12 +246,12 @@ void FileTransferController::updateProgress() { if( m_files.isEmpty() == false && m_fileReadThread ) { - emit progressChanged( m_currentFileIndex * 100 / m_files.count() + + Q_EMIT progressChanged( m_currentFileIndex * 100 / m_files.count() + m_fileReadThread->progress() / m_files.count() ); } else if( m_files.count() > 0 && m_currentFileIndex >= m_files.count() ) { - emit progressChanged( 100 ); + Q_EMIT progressChanged( 100 ); } } @@ -268,7 +259,7 @@ void FileTransferController::updateProgress() bool FileTransferController::allQueuesEmpty() { - for( const auto& controlInterface : qAsConst(m_interfaces) ) + for( const auto& controlInterface : std::as_const(m_interfaces) ) { if( controlInterface->isMessageQueueEmpty() == false ) { diff --git a/plugins/filetransfer/FileTransferController.h b/plugins/filetransfer/FileTransferController.h index 495a08a5a..4181c4130 100644 --- a/plugins/filetransfer/FileTransferController.h +++ b/plugins/filetransfer/FileTransferController.h @@ -1,7 +1,7 @@ /* * FileTransferController.h - declaration of FileTransferController class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,6 +31,7 @@ class FileReadThread; class FileTransferPlugin; +// clazy:excludeall=ctor-missing-parent-argument class FileTransferController : public QObject { Q_OBJECT @@ -60,7 +61,7 @@ class FileTransferController : public QObject bool isRunning() const; -signals: +Q_SIGNALS: void errorOccured( const QString& message ); void filesChanged(); void progressChanged( int progress ); @@ -89,16 +90,16 @@ class FileTransferController : public QObject FileTransferPlugin* m_plugin; - int m_currentFileIndex; - QUuid m_currentTransferId; - QStringList m_files; - Flags m_flags; - ComputerControlInterfaceList m_interfaces; + int m_currentFileIndex{-1}; + QUuid m_currentTransferId{}; + QStringList m_files{}; + Flags m_flags{Transfer}; + ComputerControlInterfaceList m_interfaces{}; - FileReadThread* m_fileReadThread; + FileReadThread* m_fileReadThread{nullptr}; - FileState m_fileState; + FileState m_fileState{FileStateFinished}; - QTimer m_processTimer; + QTimer m_processTimer{this}; }; diff --git a/plugins/filetransfer/FileTransferDialog.cpp b/plugins/filetransfer/FileTransferDialog.cpp index a5b4a81eb..c8d47acf4 100644 --- a/plugins/filetransfer/FileTransferDialog.cpp +++ b/plugins/filetransfer/FileTransferDialog.cpp @@ -1,7 +1,7 @@ /* * FileTransferDialog.cpp - implementation of FileTransferDialog * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/plugins/filetransfer/FileTransferDialog.h b/plugins/filetransfer/FileTransferDialog.h index 47d247015..ff9b4b168 100644 --- a/plugins/filetransfer/FileTransferDialog.h +++ b/plugins/filetransfer/FileTransferDialog.h @@ -1,7 +1,7 @@ /* * FileTransferDialog.h - declaration of class FileTransferDialog * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public diff --git a/plugins/filetransfer/FileTransferFileDialog.qml b/plugins/filetransfer/FileTransferFileDialog.qml new file mode 100644 index 000000000..71e987c6c --- /dev/null +++ b/plugins/filetransfer/FileTransferFileDialog.qml @@ -0,0 +1,19 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.0 +import QtQuick.Dialogs 1.0 +import QtQuick.Layouts 1.0 + +FileDialog { + title: qsTr("Select one or more files to transfer") + selectMultiple: true + visible: true + modality: Qt.ApplicationModal + + Component.onCompleted: folder = context.lastFileTransferSourceDirectory + + onAccepted: { + context.acceptSelectedFiles(fileUrls) + qmlCore.deleteLater(this) + } + onRejected: qmlCore.deleteLater(this) +} diff --git a/plugins/filetransfer/FileTransferListModel.cpp b/plugins/filetransfer/FileTransferListModel.cpp index 694da1887..94a5000af 100644 --- a/plugins/filetransfer/FileTransferListModel.cpp +++ b/plugins/filetransfer/FileTransferListModel.cpp @@ -1,7 +1,7 @@ /* * FileTransferListModel.cpp - implementation of FileTransferListModel class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -29,9 +29,9 @@ FileTransferListModel::FileTransferListModel( FileTransferController* controller, QObject* parent ) : QStringListModel( parent ), m_controller( controller ), - m_scheduledPixmap( QIcon( QSL( ":/filetransfer/file-scheduled.png" ) ) ), - m_transferringPixmap( QIcon( QSL( ":/filetransfer/file-transferring.png" ) ) ), - m_finishedPixmap( QIcon( QSL( ":/filetransfer/file-finished.png" ) ) ) + m_scheduledPixmap( QIcon( QStringLiteral( ":/filetransfer/file-scheduled.png" ) ) ), + m_transferringPixmap( QIcon( QStringLiteral( ":/filetransfer/file-transferring.png" ) ) ), + m_finishedPixmap( QIcon( QStringLiteral( ":/filetransfer/file-finished.png" ) ) ) { setStringList( m_controller->files() ); @@ -39,7 +39,7 @@ FileTransferListModel::FileTransferListModel( FileTransferController* controller this, [this]() { setStringList( m_controller->files() ); } ); connect( m_controller, &FileTransferController::progressChanged, - this, [this]() { emit dataChanged( index( 0 ), index( rowCount() ), { Qt::DecorationRole } ); } ); + this, [this]() { Q_EMIT dataChanged( index( 0 ), index( rowCount() ), { Qt::DecorationRole } ); } ); connect( m_controller, &FileTransferController::started, this, [this]() { setStringList( m_controller->files() ); } ); @@ -57,7 +57,8 @@ QVariant FileTransferListModel::data( const QModelIndex& index, int role ) const { return m_finishedPixmap; } - else if( index.row() > currentRow || m_controller->isRunning() == false ) + + if( index.row() > currentRow || m_controller->isRunning() == false ) { return m_scheduledPixmap; } diff --git a/plugins/filetransfer/FileTransferListModel.h b/plugins/filetransfer/FileTransferListModel.h index 2570c7b17..a25b16b7c 100644 --- a/plugins/filetransfer/FileTransferListModel.h +++ b/plugins/filetransfer/FileTransferListModel.h @@ -1,7 +1,7 @@ /* * FileTransferListModel.h - declaration of FileTransferListModel class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/plugins/filetransfer/FileTransferPlugin.cpp b/plugins/filetransfer/FileTransferPlugin.cpp index c85e96a51..a60d0ce2f 100644 --- a/plugins/filetransfer/FileTransferPlugin.cpp +++ b/plugins/filetransfer/FileTransferPlugin.cpp @@ -1,7 +1,7 @@ /* * FileTransferPlugin.cpp - implementation of FileTransferPlugin class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,17 +22,23 @@ * */ +#include #include #include #include #include +#include #include "BuiltinFeatures.h" +#include "Filesystem.h" +#include "FileTransferConfigurationPage.h" #include "FileTransferController.h" #include "FileTransferDialog.h" #include "FileTransferPlugin.h" #include "FileTransferUserConfiguration.h" #include "FeatureWorkerManager.h" +#include "PlatformFilesystemFunctions.h" +#include "QmlCore.h" #include "SystemTrayIcon.h" #include "VeyonMasterInterface.h" #include "VeyonServerInterface.h" @@ -42,16 +48,14 @@ FileTransferPlugin::FileTransferPlugin( QObject* parent ) : QObject( parent ), m_fileTransferFeature( QStringLiteral( "FileTransfer" ), - Feature::Action | Feature::AllComponents, + Feature::Flag::Action | Feature::Flag::AllComponents, Feature::Uid( "4a70bd5a-fab2-4a4b-a92a-a1e81d2b75ed" ), Feature::Uid(), tr( "File transfer" ), {}, tr( "Click this button to transfer files from your computer to all computers." ), QStringLiteral(":/filetransfer/applications-office.png") ), m_features( { m_fileTransferFeature } ), - m_fileTransferController( nullptr ), - m_currentFile(), - m_currentTransferId() + m_configuration( &VeyonCore::config() ) { } @@ -64,69 +68,125 @@ FileTransferPlugin::~FileTransferPlugin() -bool FileTransferPlugin::startFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) +bool FileTransferPlugin::controlFeature( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) { - if( feature == m_fileTransferFeature ) + if( hasFeature( featureUid ) == false ) { - FileTransferUserConfiguration config( master.userConfigurationObject() ); - - auto files = QFileDialog::getOpenFileNames( master.mainWindow(), - tr( "Select one or more files to transfer" ), - config.lastFileTransferSourceDirectory() ); + return false; + } - if( files.isEmpty() == false ) + if( operation == Operation::Initialize ) + { + auto files = arguments.value( argToString(Argument::Files) ).toStringList(); + if( files.isEmpty() ) { - config.setLastFileTransferSourceDirectory( QFileInfo( files.first() ).absolutePath() ); + return false; + } - if( m_fileTransferController == nullptr ) + for( auto& file : files ) + { + QFileInfo fileInfo( file ); + if( fileInfo.dir() == QDir::current() ) { - m_fileTransferController = new FileTransferController( this ); + file = fileInfo.fileName(); } + } - for( auto& file : files ) - { - QFileInfo fileInfo( file ); - if( fileInfo.dir() == QDir::current() ) - { - file = fileInfo.fileName(); - } - } + if( m_fileTransferController == nullptr ) + { + m_fileTransferController = new FileTransferController( this ); + } - m_fileTransferController->setFiles( files ); - m_fileTransferController->setInterfaces( computerControlInterfaces ); + m_fileTransferController->setFiles( files ); + m_fileTransferController->setInterfaces( computerControlInterfaces ); - auto dialog = new FileTransferDialog( m_fileTransferController, master.mainWindow() ); - connect( dialog, &QDialog::finished, dialog, &QDialog::deleteLater ); - dialog->exec(); + return true; + } + + if( operation == Operation::Start ) + { + if( m_fileTransferController ) + { + m_fileTransferController->start(); } return true; } - return false; + if( operation == Operation::Stop ) + { + if( m_fileTransferController ) + { + m_fileTransferController->stop(); + } + } + + return true; } -bool FileTransferPlugin::stopFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) +bool FileTransferPlugin::startFeature( VeyonMasterInterface& master, const Feature& feature, + const ComputerControlInterfaceList& computerControlInterfaces ) { - Q_UNUSED(master) - Q_UNUSED(feature) - Q_UNUSED(computerControlInterfaces) + if( feature != m_fileTransferFeature ) + { + return false; + } - return false; -} + const auto userConfigObject = master.userConfigurationObject(); + m_lastFileTransferSourceDirectory = FileTransferUserConfiguration( userConfigObject ).lastFileTransferSourceDirectory(); + if( m_configuration.rememberLastFileTransferSourceDirectory() == false || + QDir( m_lastFileTransferSourceDirectory ).exists() == false ) + { + m_lastFileTransferSourceDirectory = VeyonCore::filesystem().expandPath( m_configuration.fileTransferDefaultSourceDirectory() ); + } + if( master.appWindow() ) + { + auto dialog = VeyonCore::qmlCore().createObjectFromFile( QStringLiteral("qrc:/filetransfer/FileTransferFileDialog.qml"), + master.appWindow(), + this ); + connect( this, &FileTransferPlugin::acceptSelectedFiles, dialog, // clazy:exclude=connect-non-signal + [this, computerControlInterfaces, userConfigObject]( const QList& fileUrls ) + { + QStringList files; + files.reserve( fileUrls.size() ); + for( const auto& url : fileUrls ) + { + files.append( url.toString( QUrl::RemoveScheme ) ); + } + FileTransferUserConfiguration( userConfigObject ). + setLastFileTransferSourceDirectory( QFileInfo( files.first() ).absolutePath() ); + + controlFeature( m_fileTransferFeature.uid(), Operation::Initialize, + { { argToString(Argument::Files), files } }, computerControlInterfaces ); + } ); -bool FileTransferPlugin::handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) -{ - Q_UNUSED(master) - Q_UNUSED(message) - Q_UNUSED(computerControlInterface) + return true; + } + + auto files = QFileDialog::getOpenFileNames( master.mainWindow(), + tr( "Select one or more files to transfer" ), + lastFileTransferSourceDirectory() ); + + if( files.isEmpty() == false ) + { + FileTransferUserConfiguration( userConfigObject ). + setLastFileTransferSourceDirectory( QFileInfo( files.first() ).absolutePath() ); + + if( controlFeature( feature.uid(), Operation::Initialize, + { { argToString(Argument::Files), files } }, computerControlInterfaces ) ) + { + auto dialog = new FileTransferDialog( m_fileTransferController, master.mainWindow() ); + connect( dialog, &QDialog::finished, dialog, &QDialog::deleteLater ); + dialog->exec(); + } + + return true; + } return false; } @@ -141,21 +201,16 @@ bool FileTransferPlugin::handleFeatureMessage( VeyonServerInterface& server, if( m_fileTransferFeature.uid() == message.featureUid() ) { - if( server.featureWorkerManager().isWorkerRunning( m_fileTransferFeature ) == false ) - { - server.featureWorkerManager().startWorker( m_fileTransferFeature, FeatureWorkerManager::UnmanagedSessionProcess ); - } - if( message.command() == FileTransferFinishCommand ) { VeyonCore::builtinFeatures().systemTrayIcon().showMessage( m_fileTransferFeature.displayName(), tr( "Received file \"%1\"." ). - arg( message.argument( Filename ).toString() ), + arg( message.argument( Argument::Filename ).toString() ), server.featureWorkerManager() ); } // forward message to worker - server.featureWorkerManager().sendMessage( message ); + server.featureWorkerManager().sendMessageToUnmanagedSessionWorker( message ); return true; } @@ -175,9 +230,10 @@ bool FileTransferPlugin::handleFeatureMessage( VeyonWorkerInterface& worker, con { case FileTransferStartCommand: m_currentFile.close(); - // TODO: make path configurable - m_currentFile.setFileName( QDir::homePath() + QDir::separator() + message.argument( Filename ).toString() ); - if( m_currentFile.exists() && message.argument( OverwriteExistingFile ).toBool() == false ) + + m_currentFileName = destinationDirectory() + QDir::separator() + message.argument( Argument::Filename ).toString(); + m_currentFile.setFileName( m_currentFileName ); + if( m_currentFile.exists() && message.argument( Argument::OverwriteExistingFile ).toBool() == false ) { QMessageBox::critical( nullptr, m_fileTransferFeature.displayName(), tr( "Could not receive file \"%1\" as it already exists." ). @@ -185,9 +241,12 @@ bool FileTransferPlugin::handleFeatureMessage( VeyonWorkerInterface& worker, con return true; } - if( m_currentFile.open( QFile::WriteOnly | QFile::Truncate ) ) + if( VeyonCore::platform().filesystemFunctions().openFileSafely( + &m_currentFile, + QFile::WriteOnly | QFile::Truncate, + QFile::ReadOwner | QFile::WriteOwner | QFile::ReadGroup | QFile::WriteGroup | QFile::ReadOther ) ) { - m_currentTransferId = message.argument( TransferId ).toUuid(); + m_currentTransferId = message.argument( Argument::TransferId ).toUuid(); } else { @@ -198,9 +257,9 @@ bool FileTransferPlugin::handleFeatureMessage( VeyonWorkerInterface& worker, con return true; case FileTransferContinueCommand: - if( message.argument( TransferId ).toUuid() == m_currentTransferId ) + if( message.argument( Argument::TransferId ).toUuid() == m_currentTransferId ) { - m_currentFile.write( message.argument( DataChunk ).toByteArray() ); + m_currentFile.write( message.argument( Argument::DataChunk ).toByteArray() ); } else { @@ -209,7 +268,7 @@ bool FileTransferPlugin::handleFeatureMessage( VeyonWorkerInterface& worker, con return true; case FileTransferCancelCommand: - if( message.argument( TransferId ).toUuid() == m_currentTransferId ) + if( message.argument( Argument::TransferId ).toUuid() == m_currentTransferId ) { m_currentFile.remove(); } @@ -221,15 +280,19 @@ bool FileTransferPlugin::handleFeatureMessage( VeyonWorkerInterface& worker, con case FileTransferFinishCommand: m_currentFile.close(); - if( message.argument( OpenFileInApplication ).toBool() ) + if( message.argument( Argument::OpenFileInApplication ).toBool() ) { - QDesktopServices::openUrl( QUrl::fromLocalFile( m_currentFile.fileName() ) ); + QDesktopServices::openUrl( QUrl::fromLocalFile( m_currentFileName ) ); } m_currentFile.setFileName( {} ); return true; case OpenTransferFolder: - QDesktopServices::openUrl( QUrl::fromLocalFile( QDir::homePath() ) ); + QDesktopServices::openUrl( QUrl::fromLocalFile( destinationDirectory() ) ); + return true; + + case StopWorker: + QCoreApplication::quit(); return true; default: @@ -246,9 +309,9 @@ void FileTransferPlugin::sendStartMessage( QUuid transferId, const QString& file bool overwriteExistingFile, const ComputerControlInterfaceList& interfaces ) { sendFeatureMessage( FeatureMessage( m_fileTransferFeature.uid(), FileTransferStartCommand ). - addArgument( TransferId, transferId ). - addArgument( Filename, fileName ). - addArgument( OverwriteExistingFile, overwriteExistingFile ), + addArgument( Argument::TransferId, transferId ). + addArgument( Argument::Filename, fileName ). + addArgument( Argument::OverwriteExistingFile, overwriteExistingFile ), interfaces ); } @@ -258,8 +321,8 @@ void FileTransferPlugin::sendDataMessage( QUuid transferId, const QByteArray& da const ComputerControlInterfaceList& interfaces ) { sendFeatureMessage( FeatureMessage( m_fileTransferFeature.uid(), FileTransferContinueCommand ). - addArgument( TransferId, transferId ). - addArgument( DataChunk, data ), + addArgument( Argument::TransferId, transferId ). + addArgument( Argument::DataChunk, data ), interfaces ); } @@ -269,7 +332,7 @@ void FileTransferPlugin::sendCancelMessage( QUuid transferId, const ComputerControlInterfaceList& interfaces ) { sendFeatureMessage( FeatureMessage( m_fileTransferFeature.uid(), FileTransferCancelCommand ). - addArgument( TransferId, transferId ), interfaces ); + addArgument( Argument::TransferId, transferId ), interfaces ); } @@ -278,9 +341,9 @@ void FileTransferPlugin::sendFinishMessage( QUuid transferId, const QString& fil bool openFileInApplication, const ComputerControlInterfaceList& interfaces ) { sendFeatureMessage( FeatureMessage( m_fileTransferFeature.uid(), FileTransferFinishCommand ). - addArgument( TransferId, transferId ). - addArgument( Filename, fileName ). - addArgument( OpenFileInApplication, openFileInApplication ), interfaces ); + addArgument( Argument::TransferId, transferId ). + addArgument( Argument::Filename, fileName ). + addArgument( Argument::OpenFileInApplication, openFileInApplication ), interfaces ); } @@ -289,3 +352,35 @@ void FileTransferPlugin::sendOpenTransferFolderMessage( const ComputerControlInt { sendFeatureMessage( FeatureMessage( m_fileTransferFeature.uid(), OpenTransferFolder ), interfaces ); } + + + +void FileTransferPlugin::sendStopWorkerMessage(const ComputerControlInterfaceList& interfaces) +{ + sendFeatureMessage(FeatureMessage(m_fileTransferFeature.uid(), Commands::StopWorker), interfaces); +} + + + +QString FileTransferPlugin::destinationDirectory() const +{ + auto dir = VeyonCore::filesystem().expandPath( m_configuration.fileTransferDestinationDirectory() ); + if( QDir( dir ).exists() == false && + m_configuration.fileTransferCreateDestinationDirectory() && + VeyonCore::filesystem().ensurePathExists( dir ) == false ) + { + return QDir::homePath(); + } + + return dir; +} + + + +ConfigurationPage* FileTransferPlugin::createConfigurationPage() +{ + return new FileTransferConfigurationPage( m_configuration ); +} + + +IMPLEMENT_CONFIG_PROXY(FileTransferConfiguration) diff --git a/plugins/filetransfer/FileTransferPlugin.h b/plugins/filetransfer/FileTransferPlugin.h index 23a0a2693..d6951009d 100644 --- a/plugins/filetransfer/FileTransferPlugin.h +++ b/plugins/filetransfer/FileTransferPlugin.h @@ -1,7 +1,7 @@ /* * FileTransferPlugin.h - declaration of FileTransferPlugin class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,23 +25,41 @@ #pragma once #include +#include +#include "ConfigurationPagePluginInterface.h" #include "FeatureProviderInterface.h" +#include "FileTransferConfiguration.h" class FileTransferController; +class FileTransferUserConfiguration; -class FileTransferPlugin : public QObject, FeatureProviderInterface, PluginInterface +class FileTransferPlugin : public QObject, FeatureProviderInterface, PluginInterface, ConfigurationPagePluginInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "io.veyon.Veyon.Plugins.FileTransfer") - Q_INTERFACES(PluginInterface FeatureProviderInterface) + Q_INTERFACES(PluginInterface + FeatureProviderInterface + ConfigurationPagePluginInterface) + Q_PROPERTY(QString lastFileTransferSourceDirectory READ lastFileTransferSourceDirectory) public: + enum class Argument + { + TransferId, + Filename, + DataChunk, + OpenFileInApplication, + OverwriteExistingFile, + Files + }; + Q_ENUM(Argument) + explicit FileTransferPlugin( QObject* parent = nullptr ); ~FileTransferPlugin() override; Plugin::Uid uid() const override { - return QStringLiteral("d4bb9c42-9eef-4ecb-8dd5-dfd84b355481"); + return Plugin::Uid{ QStringLiteral("d4bb9c42-9eef-4ecb-8dd5-dfd84b355481") }; } QVersionNumber version() const override @@ -74,15 +92,12 @@ class FileTransferPlugin : public QObject, FeatureProviderInterface, PluginInter return m_features; } + bool controlFeature( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) override; + bool startFeature( VeyonMasterInterface& master, const Feature& feature, const ComputerControlInterfaceList& computerControlInterfaces ) override; - bool stopFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) override; - - bool handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) override; - bool handleFeatureMessage( VeyonServerInterface& server, const MessageContext& messageContext, const FeatureMessage& message ) override; @@ -96,8 +111,21 @@ class FileTransferPlugin : public QObject, FeatureProviderInterface, PluginInter void sendFinishMessage( QUuid transferId, const QString& fileName, bool openFileInApplication, const ComputerControlInterfaceList& interfaces ); void sendOpenTransferFolderMessage( const ComputerControlInterfaceList& interfaces ); + void sendStopWorkerMessage(const ComputerControlInterfaceList& interfaces); + + ConfigurationPage* createConfigurationPage() override; + +Q_SIGNALS: + Q_INVOKABLE void acceptSelectedFiles( const QList& fileUrls ); private: + const QString& lastFileTransferSourceDirectory() const + { + return m_lastFileTransferSourceDirectory; + } + + QString destinationDirectory() const; + enum Commands { FileTransferStartCommand, @@ -105,25 +133,21 @@ class FileTransferPlugin : public QObject, FeatureProviderInterface, PluginInter FileTransferCancelCommand, FileTransferFinishCommand, OpenTransferFolder, + StopWorker, CommandCount }; - enum Arguments - { - TransferId, - Filename, - DataChunk, - OpenFileInApplication, - OverwriteExistingFile, - ArgumentsCount - }; - const Feature m_fileTransferFeature; const FeatureList m_features; - FileTransferController* m_fileTransferController; + FileTransferConfiguration m_configuration; + + QString m_lastFileTransferSourceDirectory; + + FileTransferController* m_fileTransferController{nullptr}; - QFile m_currentFile; - QUuid m_currentTransferId; + QFile m_currentFile{}; + QString m_currentFileName; + QUuid m_currentTransferId{}; }; diff --git a/plugins/filetransfer/FileTransferUserConfiguration.h b/plugins/filetransfer/FileTransferUserConfiguration.h index 64bc14a47..8ca1de001 100644 --- a/plugins/filetransfer/FileTransferUserConfiguration.h +++ b/plugins/filetransfer/FileTransferUserConfiguration.h @@ -1,7 +1,7 @@ /* * FileTransferUserConfiguration.h - user config values for file transfer * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -32,6 +32,8 @@ #define FOREACH_FILE_TRANSFER_USER_CONFIG_PROPERTIES(OP) \ OP( FileTransferUserConfiguration, config, QString, lastFileTransferSourceDirectory, setLastFileTransferSourceDirectory, "LastSourceDirectory", "FileTransfer", QDir::homePath(), Configuration::Property::Flag::Standard ) +// clazy:excludeall=missing-qobject-macro + class FileTransferUserConfiguration : public Configuration::Proxy { public: diff --git a/plugins/filetransfer/document-share.png b/plugins/filetransfer/document-share.png new file mode 100644 index 000000000..068481cfc Binary files /dev/null and b/plugins/filetransfer/document-share.png differ diff --git a/plugins/filetransfer/filetransfer.qrc b/plugins/filetransfer/filetransfer.qrc index f092a78af..1f343d175 100644 --- a/plugins/filetransfer/filetransfer.qrc +++ b/plugins/filetransfer/filetransfer.qrc @@ -1,8 +1,10 @@ - + applications-office.png file-scheduled.png file-transferring.png file-finished.png + document-share.png + FileTransferFileDialog.qml diff --git a/plugins/ldap/AuthLdapConfiguration.h b/plugins/ldap/AuthLdapConfiguration.h new file mode 100644 index 000000000..d400858d4 --- /dev/null +++ b/plugins/ldap/AuthLdapConfiguration.h @@ -0,0 +1,14 @@ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later + +#pragma once + +#include "Configuration/Proxy.h" + +#define FOREACH_AUTH_LDAP_CONFIG_PROPERTY(OP) \ + OP( AuthLdapConfiguration, m_configuration, QString, usernameBindDnMapping, setUsernameBindMapping, "UsernameBindDnMapping", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ + +// clazy:excludeall=missing-qobject-macro + +DECLARE_CONFIG_PROXY(AuthLdapConfiguration, FOREACH_AUTH_LDAP_CONFIG_PROPERTY) diff --git a/plugins/ldap/AuthLdapConfigurationWidget.cpp b/plugins/ldap/AuthLdapConfigurationWidget.cpp new file mode 100644 index 000000000..4a377d746 --- /dev/null +++ b/plugins/ldap/AuthLdapConfigurationWidget.cpp @@ -0,0 +1,29 @@ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later + +#include "AuthLdapConfiguration.h" +#include "AuthLdapConfigurationWidget.h" +#include "VeyonConfiguration.h" +#include "Configuration/UiMapping.h" + +#include "ui_AuthLdapConfigurationWidget.h" + + +AuthLdapConfigurationWidget::AuthLdapConfigurationWidget( AuthLdapConfiguration& configuration ) : + QWidget( QApplication::activeWindow() ), + ui( new Ui::AuthLdapConfigurationWidget ), + m_configuration( configuration ) +{ + ui->setupUi(this); + + FOREACH_AUTH_LDAP_CONFIG_PROPERTY(CONNECT_WIDGET_TO_PROPERTY) + FOREACH_AUTH_LDAP_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY) +} + + + +AuthLdapConfigurationWidget::~AuthLdapConfigurationWidget() +{ + delete ui; +} diff --git a/plugins/ldap/AuthLdapConfigurationWidget.h b/plugins/ldap/AuthLdapConfigurationWidget.h new file mode 100644 index 000000000..913b38faf --- /dev/null +++ b/plugins/ldap/AuthLdapConfigurationWidget.h @@ -0,0 +1,27 @@ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later + +#pragma once + +#include + +namespace Ui { +class AuthLdapConfigurationWidget; +} + +class AuthLdapConfiguration; + +// clazy:excludeall=ctor-missing-parent-argument +class AuthLdapConfigurationWidget : public QWidget +{ + Q_OBJECT +public: + AuthLdapConfigurationWidget( AuthLdapConfiguration& configuration ); + ~AuthLdapConfigurationWidget() override; + +private: + Ui::AuthLdapConfigurationWidget* ui; + AuthLdapConfiguration& m_configuration; + +}; diff --git a/plugins/ldap/AuthLdapConfigurationWidget.ui b/plugins/ldap/AuthLdapConfigurationWidget.ui new file mode 100644 index 000000000..0010e2ee1 --- /dev/null +++ b/plugins/ldap/AuthLdapConfigurationWidget.ui @@ -0,0 +1,45 @@ + + + AuthLdapConfigurationWidget + + + + 0 + + + 0 + + + + + General + + + + + + Username to bind DN mapping: + + + + + + + + 600 + 0 + + + + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + + + + + + + + + diff --git a/plugins/ldap/AuthLdapCore.cpp b/plugins/ldap/AuthLdapCore.cpp new file mode 100644 index 000000000..7ee50de18 --- /dev/null +++ b/plugins/ldap/AuthLdapCore.cpp @@ -0,0 +1,56 @@ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later + +#include "AuthLdapCore.h" +#include "LdapClient.h" +#include "LdapConfiguration.h" +#include "VeyonConfiguration.h" + + +AuthLdapCore::AuthLdapCore( QObject* parent ) : + QObject( parent ), + m_configuration( &VeyonCore::config() ) +{ +} + + + +void AuthLdapCore::clear() +{ + m_username.clear(); + m_password.clear(); +} + + + +bool AuthLdapCore::hasCredentials() const +{ + return m_username.isEmpty() == false && m_password.isEmpty() == false; +} + + + +bool AuthLdapCore::authenticate() +{ + Configuration::Object configCopy; + configCopy += VeyonCore::config(); + + LdapConfiguration ldapConfig( &configCopy ); + ldapConfig.setUseBindCredentials( true ); + ldapConfig.setBindPassword( Configuration::Password::fromPlainText( m_password ) ); + + if( m_configuration.usernameBindDnMapping().isEmpty() ) + { + ldapConfig.setBindDn( m_username ); + } + else + { + ldapConfig.setBindDn( m_configuration.usernameBindDnMapping().replace( QStringLiteral("%username%"), m_username ) ); + } + + return LdapClient( ldapConfig ).isBound(); +} + + +IMPLEMENT_CONFIG_PROXY(AuthLdapConfiguration) diff --git a/plugins/ldap/AuthLdapCore.h b/plugins/ldap/AuthLdapCore.h new file mode 100644 index 000000000..b441aea1d --- /dev/null +++ b/plugins/ldap/AuthLdapCore.h @@ -0,0 +1,52 @@ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later + +#pragma once + +#include "AuthLdapConfiguration.h" + +class AuthLdapCore : public QObject +{ + Q_OBJECT +public: + explicit AuthLdapCore( QObject* parent = nullptr ); + + AuthLdapConfiguration& configuration() + { + return m_configuration; + } + + void clear(); + + const QString& username() const + { + return m_username; + } + + void setUsername( const QString& username ) + { + m_username = username; + } + + const CryptoCore::PlaintextPassword& password() const + { + return m_password; + } + + void setPassword( const CryptoCore::PlaintextPassword& password ) + { + m_password = password; + } + + bool hasCredentials() const; + + bool authenticate(); + +private: + AuthLdapConfiguration m_configuration; + + QString m_username{}; + CryptoCore::PlaintextPassword m_password{}; + +}; diff --git a/plugins/ldap/AuthLdapDialog.cpp b/plugins/ldap/AuthLdapDialog.cpp new file mode 100644 index 000000000..f9b9e6e09 --- /dev/null +++ b/plugins/ldap/AuthLdapDialog.cpp @@ -0,0 +1,81 @@ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later + +#include +#include + +#include "AuthLdapDialog.h" +#include "AuthLdapCore.h" +#include "PlatformUserFunctions.h" + +#include "ui_AuthLdapDialog.h" + + +AuthLdapDialog::AuthLdapDialog( const LdapConfiguration& config, QWidget* parent ) : + QDialog( parent ), + ui( new Ui::AuthLdapDialog ), + m_config( config ) +{ + ui->setupUi( this ); + + ui->username->setText( VeyonCore::platform().userFunctions().currentUser() ); + + if( ui->username->text().isEmpty() == false ) + { + ui->password->setFocus(); + } + + updateOkButton(); + + VeyonCore::enforceBranding( this ); +} + + + +AuthLdapDialog::~AuthLdapDialog() +{ + delete ui; +} + + + +QString AuthLdapDialog::username() const +{ + return ui->username->text(); +} + + + +CryptoCore::PlaintextPassword AuthLdapDialog::password() const +{ + return ui->password->text().toUtf8(); +} + + + +void AuthLdapDialog::accept() +{ + AuthLdapCore core; + core.setUsername( username() ); + core.setPassword( password() ); + + if( core.authenticate() == false ) + { + QMessageBox::critical( window(), + tr( "Authentication error" ), + tr( "Logon failed with given username and password. Please try again!" ) ); + } + else + { + QDialog::accept(); + } +} + + + +void AuthLdapDialog::updateOkButton() +{ + ui->buttonBox->button( QDialogButtonBox::Ok )-> + setEnabled( !username().isEmpty() && !password().isEmpty() ); +} diff --git a/plugins/ldap/AuthLdapDialog.h b/plugins/ldap/AuthLdapDialog.h new file mode 100644 index 000000000..4b936035e --- /dev/null +++ b/plugins/ldap/AuthLdapDialog.h @@ -0,0 +1,34 @@ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later + +#pragma once + +#include "CryptoCore.h" + +#include + +class LdapConfiguration; + +namespace Ui { class AuthLdapDialog; } + +class AuthLdapDialog : public QDialog +{ + Q_OBJECT +public: + explicit AuthLdapDialog( const LdapConfiguration& config, QWidget *parent ); + ~AuthLdapDialog() override; + + QString username() const; + CryptoCore::PlaintextPassword password() const; + + void accept() override; + +private Q_SLOTS: + void updateOkButton(); + +private: + Ui::AuthLdapDialog *ui; + const LdapConfiguration& m_config; + +} ; diff --git a/plugins/ldap/AuthLdapDialog.ui b/plugins/ldap/AuthLdapDialog.ui new file mode 100644 index 000000000..d8c850034 --- /dev/null +++ b/plugins/ldap/AuthLdapDialog.ui @@ -0,0 +1,142 @@ + + + AuthLdapDialog + + + Veyon Logon + + + + :/core/application-x-pem-key.png:/core/application-x-pem-key.png + + + + + + Please enter your domain/LDAP username and password in order to access computers. + + + true + + + + + + + 16 + + + + + Username + + + + + + + + 350 + 0 + + + + + + + + Password + + + + + + + QLineEdit::Password + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + AuthLdapDialog + accept() + + + 206 + 137 + + + 169 + 79 + + + + + buttonBox + rejected() + AuthLdapDialog + reject() + + + 206 + 137 + + + 169 + 79 + + + + + password + textChanged(QString) + AuthLdapDialog + updateOkButton() + + + 204 + 107 + + + 169 + 78 + + + + + username + textChanged(QString) + AuthLdapDialog + updateOkButton() + + + 204 + 76 + + + 169 + 78 + + + + + + updateOkButton() + + diff --git a/plugins/ldap/CMakeLists.txt b/plugins/ldap/CMakeLists.txt index 011451ce0..8982ee7e2 100644 --- a/plugins/ldap/CMakeLists.txt +++ b/plugins/ldap/CMakeLists.txt @@ -1,11 +1,20 @@ -INCLUDE(BuildPlugin) +include(BuildVeyonPlugin) -ADD_SUBDIRECTORY(kldap) -ADD_SUBDIRECTORY(common) +add_subdirectory(kldap) +add_subdirectory(common) -BUILD_PLUGIN(ldap +build_veyon_plugin(ldap LdapPlugin.cpp LdapPlugin.h -) + AuthLdapConfiguration.h + AuthLdapConfigurationWidget.cpp + AuthLdapConfigurationWidget.h + AuthLdapConfigurationWidget.ui + AuthLdapCore.cpp + AuthLdapCore.h + AuthLdapDialog.cpp + AuthLdapDialog.h + AuthLdapDialog.ui + ) -TARGET_LINK_LIBRARIES(ldap ldap-common) +target_link_libraries(ldap PRIVATE ldap-common) diff --git a/plugins/ldap/LdapPlugin.cpp b/plugins/ldap/LdapPlugin.cpp index addb45ca4..ab36a693b 100644 --- a/plugins/ldap/LdapPlugin.cpp +++ b/plugins/ldap/LdapPlugin.cpp @@ -1,46 +1,34 @@ -/* - * LdapPlugin.cpp - implementation of LdapPlugin class - * - * Copyright (c) 2017-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later +#include +#include + +#include "AuthLdapConfigurationWidget.h" +#include "AuthLdapDialog.h" #include "CommandLineIO.h" #include "ConfigurationManager.h" #include "LdapNetworkObjectDirectory.h" #include "LdapPlugin.h" #include "LdapConfigurationPage.h" +#include "LdapConfigurationTest.h" #include "LdapDirectory.h" +#include "LdapNetworkObjectDirectoryConfigurationPage.h" +#include "VariantArrayMessage.h" #include "VeyonConfiguration.h" - LdapPlugin::LdapPlugin( QObject* parent ) : QObject( parent ), m_configuration( &VeyonCore::config() ), m_ldapClient( nullptr ), m_ldapDirectory( nullptr ), m_commands( { -{ QStringLiteral("autoconfigurebasedn"), tr( "Auto-configure the base DN via naming context" ) }, -{ QStringLiteral("query"), tr( "Query objects from LDAP directory" ) }, -{ QStringLiteral("help"), tr( "Show help about command" ) }, - } ) + { QStringLiteral("autoconfigurebasedn"), tr( "Auto-configure the base DN via naming context" ) }, + { QStringLiteral("query"), tr( "Query objects from LDAP directory" ) }, + { QStringLiteral("testbind"), tr( "Test binding to an LDAP server" ) }, + { QStringLiteral("help"), tr( "Show help about command" ) } + } ) { } @@ -82,7 +70,7 @@ void LdapPlugin::upgrade( const QVersionNumber& oldVersion ) if( rawBindPassword.size() < MaximumPlaintextPasswordLength ) { // setting it again will encrypt it - m_configuration.setBindPassword( Configuration::Password::fromPlainText( rawBindPassword ) ); + m_configuration.setBindPassword( Configuration::Password::fromPlainText( rawBindPassword.toUtf8() ) ); } } else if( oldVersion < QVersionNumber( 1, 2 ) ) @@ -97,6 +85,146 @@ void LdapPlugin::upgrade( const QVersionNumber& oldVersion ) +QWidget* LdapPlugin::createAuthenticationConfigurationWidget() +{ + return new AuthLdapConfigurationWidget( m_authCore.configuration() ); +} + + + +bool LdapPlugin::initializeCredentials() +{ + m_authCore.clear(); + + if( qobject_cast( QCoreApplication::instance() ) ) + { + AuthLdapDialog logonDialog( m_configuration, QApplication::activeWindow() ); + if( logonDialog.exec() == AuthLdapDialog::Accepted ) + { + m_authCore.setUsername( logonDialog.username() ); + m_authCore.setPassword( logonDialog.password() ); + + return true; + } + } + + return false; +} + + +bool LdapPlugin::hasCredentials() const +{ + return m_authCore.hasCredentials(); +} + + + +bool LdapPlugin::checkCredentials() const +{ + if( hasCredentials() == false ) + { + vWarning() << "Invalid username or password!"; + + QMessageBox::critical( QApplication::activeWindow(), + authenticationTestTitle(), + tr( "The supplied username or password is wrong. Please enter valid credentials or " + "switch to a different authentication method using the Veyon Configurator." ) ); + + return false; + } + + return true; +} + + + +VncServerClient::AuthState LdapPlugin::performAuthentication( VncServerClient* client, VariantArrayMessage& message ) const +{ + switch( client->authState() ) + { + case VncServerClient::AuthState::Init: + client->setPrivateKey( VeyonCore::cryptoCore().createPrivateKey() ); + + if( VariantArrayMessage( message.ioDevice() ).write( client->privateKey().toPublicKey().toPEM() ).send() ) + { + return VncServerClient::AuthState::Stage1; + } + + vDebug() << "failed to send public key"; + return VncServerClient::AuthState::Failed; + + case VncServerClient::AuthState::Stage1: + { + auto privateKey = client->privateKey(); + + client->setUsername( message.read().toString() ); // Flawfinder: ignore + CryptoCore::PlaintextPassword encryptedPassword( message.read().toByteArray() ); // Flawfinder: ignore + + CryptoCore::PlaintextPassword decryptedPassword; + + if( privateKey.decrypt( encryptedPassword, + &decryptedPassword, + CryptoCore::DefaultEncryptionAlgorithm ) == false ) + { + vWarning() << "failed to decrypt password"; + return VncServerClient::AuthState::Failed; + } + + vInfo() << "authenticating user" << client->username(); + + AuthLdapCore authCore; + authCore.setUsername( client->username() ); + authCore.setPassword( decryptedPassword ); + + if( authCore.authenticate() ) + { + vDebug() << "SUCCESS"; + return VncServerClient::AuthState::Successful; + } + + vDebug() << "FAIL"; + return VncServerClient::AuthState::Failed; + } + + default: + break; + } + + return VncServerClient::AuthState::Failed; +} + + + +bool LdapPlugin::authenticate( QIODevice* socket ) const +{ + VariantArrayMessage publicKeyMessage( socket ); + publicKeyMessage.receive(); + + auto publicKey = CryptoCore::PublicKey::fromPEM( publicKeyMessage.read().toString() ); + + if( publicKey.canEncrypt() == false ) + { + vCritical() << QThread::currentThreadId() << "can't encrypt with given public key!"; + return false; + } + + const auto encryptedPassword = publicKey.encrypt( m_authCore.password(), CryptoCore::DefaultEncryptionAlgorithm ); + if( encryptedPassword.isEmpty() ) + { + vCritical() << QThread::currentThreadId() << "password encryption failed!"; + return false; + } + + VariantArrayMessage response( socket ); + response.write( m_authCore.username() ); + response.write( encryptedPassword.toByteArray() ); + response.send(); + + return true; +} + + + QStringList LdapPlugin::commands() const { return m_commands.keys(); @@ -118,6 +246,15 @@ NetworkObjectDirectory *LdapPlugin::createNetworkObjectDirectory( QObject* paren +ConfigurationPage* LdapPlugin::createNetworkObjectDirectoryConfigurationPage() +{ + auto page = new LdapNetworkObjectDirectoryConfigurationPage; + page->setWindowTitle( name() ); + return page; +} + + + void LdapPlugin::reloadConfiguration() { delete m_ldapDirectory; @@ -128,7 +265,7 @@ void LdapPlugin::reloadConfiguration() QStringList LdapPlugin::userGroups( bool queryDomainGroups ) { - Q_UNUSED(queryDomainGroups); + Q_UNUSED(queryDomainGroups) return LdapClient::stripBaseDn( ldapDirectory().userGroups(), ldapClient().baseDn() ); } @@ -137,7 +274,7 @@ QStringList LdapPlugin::userGroups( bool queryDomainGroups ) QStringList LdapPlugin::groupsOfUser( const QString& username, bool queryDomainGroups ) { - Q_UNUSED(queryDomainGroups); + Q_UNUSED(queryDomainGroups) const auto strippedUsername = VeyonCore::stripDomain( username ); @@ -238,7 +375,7 @@ CommandLinePluginInterface::RunResult LdapPlugin::handle_query( const QStringLis return InvalidArguments; } - for( const auto& result : qAsConst( results ) ) + for( const auto& result : std::as_const( results ) ) { printf( "%s\n", qUtf8Printable( result ) ); } @@ -248,11 +385,38 @@ CommandLinePluginInterface::RunResult LdapPlugin::handle_query( const QStringLis +CommandLinePluginInterface::RunResult LdapPlugin::handle_testbind( const QStringList& arguments ) +{ + Q_UNUSED(arguments) + + const auto result = LdapConfigurationTest( m_configuration ).testBind(); + if( result ) + { + CommandLineIO::info( result.message ); + return Successful; + } + + CommandLineIO::error( result.message ); + return Failed; +} + + + CommandLinePluginInterface::RunResult LdapPlugin::handle_help( const QStringList& arguments ) { QString command = arguments.value( 0 ); + if( command == QLatin1String("testbind") ) + { + printf( "\n" + "ldap testbind\n" + "\n" + "Test binding to the LDAP server using the current configuration.\n" + "\n\n" ); + return NoResult; + } + if( command == QLatin1String("autoconfigurebasedn") ) { printf( "\n" @@ -265,7 +429,8 @@ CommandLinePluginInterface::RunResult LdapPlugin::handle_help( const QStringList " ldap[s]://[user[:password]@]hostname[:port]\n\n" ); return NoResult; } - else if( command == QLatin1String("query") ) + + if( command == QLatin1String("query") ) { printf( "\n" "ldap query [filter]\n" diff --git a/plugins/ldap/LdapPlugin.h b/plugins/ldap/LdapPlugin.h index 3d986de7d..5d47e2141 100644 --- a/plugins/ldap/LdapPlugin.h +++ b/plugins/ldap/LdapPlugin.h @@ -1,29 +1,11 @@ -/* - * LdapPlugin.h - declaration of LdapPlugin class - * - * Copyright (c) 2017-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #pragma once +#include "AuthLdapCore.h" +#include "AuthenticationPluginInterface.h" #include "CommandLinePluginInterface.h" #include "ConfigurationPagePluginInterface.h" #include "LdapConfiguration.h" @@ -32,15 +14,18 @@ class LdapDirectory; -class LdapPlugin : public QObject, PluginInterface, - CommandLinePluginInterface, - NetworkObjectDirectoryPluginInterface, - UserGroupsBackendInterface, - ConfigurationPagePluginInterface +class LdapPlugin : public QObject, + PluginInterface, + AuthenticationPluginInterface, + CommandLinePluginInterface, + NetworkObjectDirectoryPluginInterface, + UserGroupsBackendInterface, + ConfigurationPagePluginInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "io.veyon.Veyon.Plugins.Ldap") Q_INTERFACES(PluginInterface + AuthenticationPluginInterface CommandLinePluginInterface NetworkObjectDirectoryPluginInterface UserGroupsBackendInterface @@ -51,7 +36,7 @@ class LdapPlugin : public QObject, PluginInterface, Plugin::Uid uid() const override { - return QStringLiteral("6f0a491e-c1c6-4338-8244-f823b0bf8670"); + return Plugin::Uid{ QStringLiteral("6f0a491e-c1c6-4338-8244-f823b0bf8670") }; } QVersionNumber version() const override @@ -81,6 +66,28 @@ class LdapPlugin : public QObject, PluginInterface, void upgrade( const QVersionNumber& oldVersion ) override; + QString authenticationMethodName() const override + { + return tr("LDAP bind"); + } + + QWidget* createAuthenticationConfigurationWidget() override; + + bool initializeCredentials() override; + bool hasCredentials() const override; + bool checkCredentials() const override; + + // server side authentication + VncServerClient::AuthState performAuthentication( VncServerClient* client, VariantArrayMessage& message ) const override; + + // client side authentication + bool authenticate( QIODevice* socket ) const override; + + QString accessControlUser() const override + { + return m_authCore.username(); + } + QString commandLineModuleName() const override { return QStringLiteral( "ldap" ); @@ -101,6 +108,8 @@ class LdapPlugin : public QObject, PluginInterface, NetworkObjectDirectory* createNetworkObjectDirectory( QObject* parent ) override; + ConfigurationPage* createNetworkObjectDirectoryConfigurationPage() override; + QString userGroupsBackendName() const override { return tr( "%1 (load users and groups from LDAP/AD)" ).arg( name() ); @@ -113,10 +122,10 @@ class LdapPlugin : public QObject, PluginInterface, ConfigurationPage* createConfigurationPage() override; - -public slots: +public Q_SLOTS: CommandLinePluginInterface::RunResult handle_autoconfigurebasedn( const QStringList& arguments ); CommandLinePluginInterface::RunResult handle_query( const QStringList& arguments ); + CommandLinePluginInterface::RunResult handle_testbind( const QStringList& arguments ); CommandLinePluginInterface::RunResult handle_help( const QStringList& arguments ); private: @@ -132,4 +141,6 @@ public slots: LdapDirectory* m_ldapDirectory; QMap m_commands; + AuthLdapCore m_authCore; + }; diff --git a/plugins/ldap/common/CMakeLists.txt b/plugins/ldap/common/CMakeLists.txt index 97222d87c..f39fad943 100644 --- a/plugins/ldap/common/CMakeLists.txt +++ b/plugins/ldap/common/CMakeLists.txt @@ -1,4 +1,4 @@ -SET(ldap_common_SOURCES +set(ldap_common_SOURCES LdapBrowseDialog.cpp LdapBrowseDialog.ui LdapBrowseDialog.h @@ -11,17 +11,26 @@ SET(ldap_common_SOURCES LdapConfigurationPage.h LdapConfigurationPage.cpp LdapConfigurationPage.ui + LdapConfigurationTest.h + LdapConfigurationTest.cpp LdapDirectory.cpp LdapDirectory.h LdapNetworkObjectDirectory.cpp LdapNetworkObjectDirectory.h + LdapNetworkObjectDirectoryConfigurationPage.h + LdapNetworkObjectDirectoryConfigurationPage.cpp + LdapNetworkObjectDirectoryConfigurationPage.ui ldap.qrc ) -ADD_LIBRARY(ldap-common SHARED ${ldap_common_SOURCES}) -TARGET_INCLUDE_DIRECTORIES(ldap-common PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) -TARGET_INCLUDE_DIRECTORIES(ldap-common PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -TARGET_LINK_LIBRARIES(ldap-common kldap-light veyon-core) -SET_TARGET_PROPERTIES(ldap-common PROPERTIES LINK_FLAGS "-Wl,-no-undefined") -INSTALL(TARGETS ldap-common DESTINATION ${VEYON_LIB_DIR}) -COTIRE_VEYON(ldap-common) +add_library(ldap-common SHARED ${ldap_common_SOURCES}) +target_include_directories(ldap-common PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${Ldap_INCLUDE_DIRS}) +target_include_directories(ldap-common PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(ldap-common PRIVATE kldap-light veyon-core) +set_default_target_properties(ldap-common) +if(WITH_PCH) + target_precompile_headers(ldap-common REUSE_FROM veyon-library-pch) +endif() +if(NOT WITH_CORE_ONLY) + install(TARGETS ldap-common DESTINATION ${VEYON_LIB_DIR}) +endif() diff --git a/plugins/ldap/common/LdapBrowseDialog.cpp b/plugins/ldap/common/LdapBrowseDialog.cpp index 33a646049..dae5bfdea 100644 --- a/plugins/ldap/common/LdapBrowseDialog.cpp +++ b/plugins/ldap/common/LdapBrowseDialog.cpp @@ -1,26 +1,6 @@ -/* - * LdapBrowseDialog.cpp - dialog for browsing LDAP directories - * - * Copyright (c) 2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #include "LdapBrowseDialog.h" #include "LdapBrowseModel.h" diff --git a/plugins/ldap/common/LdapBrowseDialog.h b/plugins/ldap/common/LdapBrowseDialog.h index e9cf9641a..3b0648f33 100644 --- a/plugins/ldap/common/LdapBrowseDialog.h +++ b/plugins/ldap/common/LdapBrowseDialog.h @@ -1,26 +1,6 @@ -/* - * LdapBrowseDialog.h - dialog for browsing LDAP directories - * - * Copyright (c) 2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #pragma once diff --git a/plugins/ldap/common/LdapBrowseModel.cpp b/plugins/ldap/common/LdapBrowseModel.cpp index 720bd5da2..96c643433 100644 --- a/plugins/ldap/common/LdapBrowseModel.cpp +++ b/plugins/ldap/common/LdapBrowseModel.cpp @@ -1,26 +1,8 @@ -/* - * LdapModel.cpp - item model for browsing LDAP directories - * - * Copyright (c) 2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later + +#include #include "LdapClient.h" #include "LdapConfiguration.h" @@ -57,8 +39,12 @@ class LdapBrowseModelNode { qDeleteAll(m_childItems); } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + Q_DISABLE_COPY_MOVE(LdapBrowseModelNode) +#else Q_DISABLE_COPY(LdapBrowseModelNode) Q_DISABLE_MOVE(LdapBrowseModelNode) +#endif Type type() const { @@ -224,7 +210,7 @@ Qt::ItemFlags LdapBrowseModel::flags( const QModelIndex& index ) const int LdapBrowseModel::columnCount( const QModelIndex& parent ) const { - Q_UNUSED(parent); + Q_UNUSED(parent) return 1; } @@ -334,7 +320,7 @@ void LdapBrowseModel::populateRoot() const { if( context.isEmpty() == false ) { - namingContexts.replaceInStrings( QRegExp( QStringLiteral(".*,%1").arg( context ) ), {} ); + namingContexts.replaceInStrings( QRegularExpression( QStringLiteral(".*,%1").arg( context ) ), {} ); } } namingContexts.removeAll( {} ); @@ -350,14 +336,7 @@ void LdapBrowseModel::populateRoot() const auto parent = m_root; QStringList fullDn; const auto dns = namingContext.split( QLatin1Char(',') ); -#if QT_VERSION < 0x050600 -#warning Building compat code for unsupported version of Qt - using QStringListReverseIterator = std::reverse_iterator; - for( auto it = QStringListReverseIterator(dns.cend()), - end = QStringListReverseIterator(dns.cbegin()); it != end; ++it ) -#else for( auto it = dns.crbegin(), end = dns.crend(); it != end; ++it ) -#endif { fullDn.prepend( *it ); auto node = new Node( Node::DN, fullDn.join( QLatin1Char(',') ), parent ); @@ -394,19 +373,19 @@ void LdapBrowseModel::populateNode( const QModelIndex& parent ) { beginInsertRows( parent, 0, itemCount - 1 ); - for( const auto& dn : dns ) + for( const auto& dn : std::as_const(dns) ) { node->appendChild( new Node( Node::DN, dn, node ) ); } - for( const auto& attribute : qAsConst(attributes) ) + for( const auto& attribute : std::as_const(attributes) ) { node->appendChild( new Node( Node::Attribute, attribute, node ) ); } endInsertRows(); - emit layoutChanged(); + Q_EMIT layoutChanged(); } node->setPopulated( true ); diff --git a/plugins/ldap/common/LdapBrowseModel.h b/plugins/ldap/common/LdapBrowseModel.h index 1f848ca5d..2f6fa0615 100644 --- a/plugins/ldap/common/LdapBrowseModel.h +++ b/plugins/ldap/common/LdapBrowseModel.h @@ -1,26 +1,6 @@ -/* - * LdapModel.h - item model for browsing LDAP directories - * - * Copyright (c) 2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #pragma once diff --git a/plugins/ldap/common/LdapClient.cpp b/plugins/ldap/common/LdapClient.cpp index 93481ee55..5d535139c 100644 --- a/plugins/ldap/common/LdapClient.cpp +++ b/plugins/ldap/common/LdapClient.cpp @@ -1,26 +1,6 @@ -/* - * LdapClient.cpp - class representing the LDAP directory and providing access to directory entries - * - * Copyright (c) 2016-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #include "LdapConfiguration.h" #include "LdapClient.h" @@ -32,16 +12,16 @@ #include "ldapserver.h" -static inline KLDAP::LdapUrl::Scope kldapUrlScope( LdapClient::Scope scope ) +static inline KLDAPCore::LdapUrl::Scope kldapUrlScope(LdapClient::Scope scope) { - switch( scope ) + switch (scope) { - case LdapClient::Scope::Base: return KLDAP::LdapUrl::Base; - case LdapClient::Scope::One: return KLDAP::LdapUrl::One; - case LdapClient::Scope::Sub: return KLDAP::LdapUrl::Sub; + case LdapClient::Scope::Base: return KLDAPCore::LdapUrl::Base; + case LdapClient::Scope::One: return KLDAPCore::LdapUrl::One; + case LdapClient::Scope::Sub: return KLDAPCore::LdapUrl::Sub; } - return KLDAP::LdapUrl::Base; + return KLDAPCore::LdapUrl::Base; } @@ -49,9 +29,10 @@ static inline KLDAP::LdapUrl::Scope kldapUrlScope( LdapClient::Scope scope ) LdapClient::LdapClient( const LdapConfiguration& configuration, const QUrl& url, QObject* parent ) : QObject( parent ), m_configuration( configuration ), - m_server( new KLDAP::LdapServer ), - m_connection( new KLDAP::LdapConnection ), - m_operation( new KLDAP::LdapOperation ) + m_server( new KLDAPCore::LdapServer ), + m_connection( new KLDAPCore::LdapConnection ), + m_operation( new KLDAPCore::LdapOperation ), + m_queryTimeout(m_configuration.queryTimeout()) { connectAndBind( url ); } @@ -118,7 +99,7 @@ LdapClient::Objects LdapClient::queryObjects( const QString& dn, const QStringLi Objects entries; int result = -1; - auto id = m_operation->search( KLDAP::LdapDN( dn ), kldapUrlScope( scope ), filter, QStringList( attributes ) ); + auto id = m_operation->search(KLDAPCore::LdapDN(dn), kldapUrlScope(scope), filter, attributes); if( id != -1 ) { @@ -130,7 +111,7 @@ LdapClient::Objects LdapClient::queryObjects( const QString& dn, const QStringLi auto isFirstResult = true; - while( ( result = m_operation->waitForResult( id, LdapQueryTimeout ) ) == KLDAP::LdapOperation::RES_SEARCH_ENTRY ) + while ((result = m_operation->waitForResult(id, m_queryTimeout)) == KLDAPCore::LdapOperation::RES_SEARCH_ENTRY) { if( isFirstResult ) { @@ -214,14 +195,14 @@ QStringList LdapClient::queryAttributeValues( const QString& dn, const QString& QStringList entries; int result = -1; - int id = m_operation->search( KLDAP::LdapDN( dn ), kldapUrlScope( scope ), filter, QStringList( attribute ) ); + int id = m_operation->search(KLDAPCore::LdapDN(dn), kldapUrlScope(scope), filter, QStringList(attribute)); if( id != -1 ) { bool isFirstResult = true; QString realAttributeName = attribute.toLower(); - while( ( result = m_operation->waitForResult( id, LdapQueryTimeout ) ) == KLDAP::LdapOperation::RES_SEARCH_ENTRY ) + while ((result = m_operation->waitForResult(id, m_queryTimeout)) == KLDAPCore::LdapOperation::RES_SEARCH_ENTRY) { if( isFirstResult ) { @@ -289,11 +270,11 @@ QStringList LdapClient::queryDistinguishedNames( const QString& dn, const QStrin QStringList distinguishedNames; int result = -1; - int id = m_operation->search( KLDAP::LdapDN( dn ), kldapUrlScope( scope ), filter, QStringList() ); + int id = m_operation->search( KLDAPCore::LdapDN(dn), kldapUrlScope(scope), filter, QStringList() ); if( id != -1 ) { - while( ( result = m_operation->waitForResult( id, LdapQueryTimeout ) ) == KLDAP::LdapOperation::RES_SEARCH_ENTRY ) + while ((result = m_operation->waitForResult(id, m_queryTimeout)) == KLDAPCore::LdapOperation::RES_SEARCH_ENTRY) { distinguishedNames += m_operation->object().dn().toString(); } @@ -344,7 +325,7 @@ QStringList LdapClient::queryObjectAttributes( const QString& dn ) return {}; } - if( m_operation->waitForResult( id, LdapQueryTimeout ) == KLDAP::LdapOperation::RES_SEARCH_ENTRY ) + if (m_operation->waitForResult(id, m_queryTimeout) == KLDAPCore::LdapOperation::RES_SEARCH_ENTRY) { const auto keys = m_operation->object().attributes().keys(); vDebug() << "results" << keys; @@ -414,7 +395,8 @@ QString LdapClient::stripBaseDn( const QString& dn, const QString& baseDn ) // cut off comma and base DN return dn.left( dn.length() - baseDn.length() - 1 ); } - else if( fullDnLower == baseDnLower ) + + if( fullDnLower == baseDnLower ) { return {}; } @@ -456,7 +438,7 @@ bool LdapClient::connectAndBind( const QUrl& url ) { if( url.isValid() ) { - m_server->setUrl( KLDAP::LdapUrl( url ) ); + m_server->setUrl(KLDAPCore::LdapUrl(url)); } else { @@ -466,25 +448,25 @@ bool LdapClient::connectAndBind( const QUrl& url ) if( m_configuration.useBindCredentials() ) { m_server->setBindDn( m_configuration.bindDn() ); - m_server->setPassword( m_configuration.bindPassword().plainText() ); - m_server->setAuth( KLDAP::LdapServer::Simple ); + m_server->setPassword( QString::fromUtf8( m_configuration.bindPassword().plainText().toByteArray() ) ); + m_server->setAuth(KLDAPCore::LdapServer::Simple); } else { - m_server->setAuth( KLDAP::LdapServer::Anonymous ); + m_server->setAuth(KLDAPCore::LdapServer::Anonymous); } const auto security = static_cast( m_configuration.connectionSecurity() ); switch( security ) { case ConnectionSecurityTLS: - m_server->setSecurity( KLDAP::LdapServer::TLS ); + m_server->setSecurity(KLDAPCore::LdapServer::TLS); break; case ConnectionSecuritySSL: - m_server->setSecurity( KLDAP::LdapServer::SSL ); + m_server->setSecurity(KLDAPCore::LdapServer::SSL); break; default: - m_server->setSecurity( KLDAP::LdapServer::None ); + m_server->setSecurity(KLDAPCore::LdapServer::None); break; } } @@ -517,18 +499,18 @@ void LdapClient::initTLS() switch( m_configuration.tlsVerifyMode() ) { case TLSVerifyDefault: - m_server->setTLSRequireCertificate( KLDAP::LdapServer::TLSReqCertDefault ); + m_server->setTLSRequireCertificate(KLDAPCore::LdapServer::TLSReqCertDefault); break; case TLSVerifyNever: - m_server->setTLSRequireCertificate( KLDAP::LdapServer::TLSReqCertNever ); + m_server->setTLSRequireCertificate(KLDAPCore::LdapServer::TLSReqCertNever); break; case TLSVerifyCustomCert: - m_server->setTLSRequireCertificate( KLDAP::LdapServer::TLSReqCertHard ); + m_server->setTLSRequireCertificate(KLDAPCore::LdapServer::TLSReqCertHard); m_server->setTLSCACertFile( m_configuration.tlsCACertificateFile() ); break; default: vCritical() << "invalid TLS verify mode specified!"; - m_server->setTLSRequireCertificate( KLDAP::LdapServer::TLSReqCertDefault ); + m_server->setTLSRequireCertificate(KLDAPCore::LdapServer::TLSReqCertDefault); break; } } @@ -542,6 +524,13 @@ bool LdapClient::reconnect() m_connection->setServer( *m_server ); + if( qEnvironmentVariableIsSet( "VEYON_DEBUG_LDAP_LIBRARY") ) + { + const auto debugLevel = LdapLibraryDebugAny; + ldap_set_option( nullptr, LDAP_OPT_DEBUG_LEVEL, &debugLevel ); + ber_set_option( nullptr, LDAP_OPT_DEBUG_LEVEL, &debugLevel ); + } + if( m_connection->connect() != 0 ) { vWarning() << "LDAP connect failed:" << errorString(); diff --git a/plugins/ldap/common/LdapClient.h b/plugins/ldap/common/LdapClient.h index c17ae3d05..a06d0ab80 100644 --- a/plugins/ldap/common/LdapClient.h +++ b/plugins/ldap/common/LdapClient.h @@ -1,41 +1,32 @@ -/* - * LdapClient.h - class implementing an LDAP client - * - * Copyright (c) 2016-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #pragma once #include #include +#include "LdapCommon.h" + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) namespace KLDAP { class LdapConnection; class LdapOperation; class LdapServer; } +namespace KLDAPCore = KLDAP; +#else +namespace KLDAPCore { +class LdapConnection; +class LdapOperation; +class LdapServer; +} +#endif class LdapConfiguration; -class LdapClient : public QObject +class LDAP_COMMON_EXPORT LdapClient : public QObject { Q_OBJECT public: @@ -119,18 +110,24 @@ class LdapClient : public QObject static QStringList toRDNs( const QString& dn ); + static QString cn() + { + return QStringLiteral("cn"); + } + + static constexpr int DefaultQueryTimeout = 3000; + private: - static constexpr int LdapQueryTimeout = 3000; - static constexpr int LdapConnectionTimeout = 60*1000; + static constexpr auto LdapLibraryDebugAny = -1; bool reconnect(); bool connectAndBind( const QUrl& url ); void initTLS(); const LdapConfiguration& m_configuration; - KLDAP::LdapServer* m_server; - KLDAP::LdapConnection* m_connection; - KLDAP::LdapOperation* m_operation; + KLDAPCore::LdapServer* m_server; + KLDAPCore::LdapConnection* m_connection; + KLDAPCore::LdapOperation* m_operation; enum State { @@ -147,4 +144,6 @@ class LdapClient : public QObject QString m_baseDn; QString m_namingContextAttribute; + const int m_queryTimeout{DefaultQueryTimeout}; + }; diff --git a/plugins/ldap/common/LdapCommon.h b/plugins/ldap/common/LdapCommon.h new file mode 100644 index 000000000..65949459a --- /dev/null +++ b/plugins/ldap/common/LdapCommon.h @@ -0,0 +1,12 @@ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later + +#pragma once + +#if defined(ldap_common_EXPORTS) +#define LDAP_COMMON_EXPORT Q_DECL_EXPORT +#else +#define LDAP_COMMON_EXPORT Q_DECL_IMPORT +#endif + diff --git a/plugins/ldap/common/LdapConfiguration.cpp b/plugins/ldap/common/LdapConfiguration.cpp index fd3d1aa77..3a204263f 100644 --- a/plugins/ldap/common/LdapConfiguration.cpp +++ b/plugins/ldap/common/LdapConfiguration.cpp @@ -1,26 +1,6 @@ -/* - * LdapConfiguration.cpp - LDAP-specific configuration values - * - * Copyright (c) 2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #include "VeyonConfiguration.h" #include "LdapConfiguration.h" diff --git a/plugins/ldap/common/LdapConfiguration.h b/plugins/ldap/common/LdapConfiguration.h index 1cdb89ddf..74b1c1397 100644 --- a/plugins/ldap/common/LdapConfiguration.h +++ b/plugins/ldap/common/LdapConfiguration.h @@ -1,34 +1,16 @@ -/* - * LdapConfiguration.h - LDAP-specific configuration values - * - * Copyright (c) 2017-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #pragma once #include "Configuration/Proxy.h" #include "CryptoCore.h" #include "LdapClient.h" +#include "LdapCommon.h" #define FOREACH_LDAP_CONFIG_PROPERTY(OP) \ + OP( LdapConfiguration, m_configuration, QString, directoryName, setDirectoryName, "DirectoryName", "LDAP", LdapConfiguration::tr("LDAP directory"), Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, QString, serverHost, setServerHost, "ServerHost", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, int, serverPort, setServerPort, "ServerPort", "LDAP", 389, Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, int, connectionSecurity, setConnectionSecurity, "ConnectionSecurity", "LDAP", LdapClient::ConnectionSecurityNone, Configuration::Property::Flag::Standard ) \ @@ -38,6 +20,7 @@ OP( LdapConfiguration, m_configuration, QString, bindDn, setBindDn, "BindDN", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, Configuration::Password, bindPassword, setBindPassword, "BindPassword", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, bool, queryNamingContext, setQueryNamingContext, "QueryNamingContext", "LDAP", false, Configuration::Property::Flag::Standard ) \ + OP( LdapConfiguration, m_configuration, int, queryTimeout, setQueryTimeout, "QueryTimeout", "LDAP", LdapClient::DefaultQueryTimeout, Configuration::Property::Flag::Advanced ) \ OP( LdapConfiguration, m_configuration, QString, baseDn, setBaseDn, "BaseDN", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, QString, namingContextAttribute, setNamingContextAttribute, "NamingContextAttribute", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, QString, userTree, setUserTree, "UserTree", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ @@ -47,14 +30,16 @@ OP( LdapConfiguration, m_configuration, bool, recursiveSearchOperations, setRecursiveSearchOperations, "RecursiveSearchOperations", "LDAP", false, Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, QString, userLoginNameAttribute, setUserLoginNameAttribute, "UserLoginNameAttribute", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, QString, groupMemberAttribute, setGroupMemberAttribute, "GroupMemberAttribute", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ - OP( LdapConfiguration, m_configuration, QString, computerDisplayNameAttribute, setComputerDisplayNameAttribute, "ComputerDisplayNameAttribute", "LDAP", QStringLiteral("cn"), Configuration::Property::Flag::Standard ) \ + OP( LdapConfiguration, m_configuration, QString, computerDisplayNameAttribute, setComputerDisplayNameAttribute, "ComputerDisplayNameAttribute", "LDAP", LdapClient::cn(), Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, QString, computerHostNameAttribute, setComputerHostNameAttribute, "ComputerHostNameAttribute", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, bool, computerHostNameAsFQDN, setComputerHostNameAsFQDN, "ComputerHostNameAsFQDN", "LDAP", false, Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, QString, computerMacAddressAttribute, setComputerMacAddressAttribute, "ComputerMacAddressAttribute", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ - OP( LdapConfiguration, m_configuration, QString, locationNameAttribute, setLocationNameAttribute, "LocationNameAttribute", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ + OP( LdapConfiguration, m_configuration, QString, locationNameAttribute, setLocationNameAttribute, "LocationNameAttribute", "LDAP", LdapClient::cn(), Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, QString, usersFilter, setUsersFilter, "UsersFilter", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, QString, userGroupsFilter, setUserGroupsFilter, "UserGroupsFilter", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, QString, computersFilter, setComputersFilter, "ComputersFilter", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ + OP( LdapConfiguration, m_configuration, bool, queryNestedUserGroups, setQueryNestedUserGroups, "QueryNestedUserGroups", "LDAP", false, Configuration::Property::Flag::Standard ) \ + OP( LdapConfiguration, m_configuration, bool, mapContainerStructureToLocations, setMapContainerStructureToLocations, "MapContainerStructureToLocations", "LDAP", false, Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, bool, identifyGroupMembersByNameAttribute, setIdentifyGroupMembersByNameAttribute, "IdentifyGroupMembersByNameAttribute", "LDAP", false, Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, QString, computerGroupsFilter, setComputerGroupsFilter, "ComputerGroupsFilter", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ OP( LdapConfiguration, m_configuration, QString, computerContainersFilter, setComputerContainersFilter, "ComputerContainersFilter", "LDAP", QString(), Configuration::Property::Flag::Standard ) \ @@ -73,4 +58,6 @@ FOREACH_LDAP_CONFIG_PROPERTY(OP) \ FOREACH_LDAP_LEGACY_CONFIG_PROPERTY(OP) -DECLARE_CONFIG_PROXY(LdapConfiguration, FOREACH_LDAP_PROXIES_CONFIG_PROPERTY) +// clazy:excludeall=missing-qobject-macro + +DECLARE_CONFIG_PROXY(LDAP_COMMON_EXPORT LdapConfiguration, FOREACH_LDAP_PROXIES_CONFIG_PROPERTY) diff --git a/plugins/ldap/common/LdapConfigurationPage.cpp b/plugins/ldap/common/LdapConfigurationPage.cpp index a823c0046..0d01d2bf1 100644 --- a/plugins/ldap/common/LdapConfigurationPage.cpp +++ b/plugins/ldap/common/LdapConfigurationPage.cpp @@ -1,26 +1,6 @@ -/* - * LdapConfigurationPage.cpp - implementation of the LdapConfigurationPage class - * - * Copyright (c) 2016-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #include #include @@ -28,6 +8,7 @@ #include "LdapConfiguration.h" #include "LdapConfigurationPage.h" +#include "LdapConfigurationTest.h" #include "Configuration/UiMapping.h" #include "LdapDirectory.h" #include "LdapBrowseDialog.h" @@ -41,6 +22,8 @@ LdapConfigurationPage::LdapConfigurationPage( LdapConfiguration& configuration, { ui->setupUi(this); + Configuration::UiMapping::setFlags(ui->queryTimeoutLabel, Configuration::Property::Flag::Advanced); + #define CONNECT_BUTTON_SLOT(name) connect( ui->name, &QPushButton::clicked, this, &LdapConfigurationPage::name ); connect( ui->browseBaseDn, &QPushButton::clicked, this, &LdapConfigurationPage::browseBaseDn ); @@ -57,47 +40,49 @@ LdapConfigurationPage::LdapConfigurationPage( LdapConfiguration& configuration, connect( ui->browseComputerLocationAttribute, &QPushButton::clicked, this, [this]() { browseAttribute( ui->computerLocationAttribute, m_configuration.computerTree() ); } ); connect( ui->browseLocationNameAttribute, &QPushButton::clicked, this, [this]() { browseAttribute( ui->locationNameAttribute, m_configuration.computerTree() ); } ); - CONNECT_BUTTON_SLOT( testBindInteractively ); - CONNECT_BUTTON_SLOT( testBaseDn ); - CONNECT_BUTTON_SLOT( testNamingContext ); - CONNECT_BUTTON_SLOT( testUserTree ); - CONNECT_BUTTON_SLOT( testGroupTree ); - CONNECT_BUTTON_SLOT( testComputerTree ); - CONNECT_BUTTON_SLOT( testComputerGroupTree ); - - CONNECT_BUTTON_SLOT( testUserLoginNameAttribute ); - CONNECT_BUTTON_SLOT( testGroupMemberAttribute ); - CONNECT_BUTTON_SLOT( testComputerDisplayNameAttribute ); - CONNECT_BUTTON_SLOT( testComputerHostNameAttribute ); - CONNECT_BUTTON_SLOT( testComputerMacAddressAttribute ); - CONNECT_BUTTON_SLOT( testComputerLocationAttribute ); - CONNECT_BUTTON_SLOT( testLocationNameAttribute ); - - CONNECT_BUTTON_SLOT( testUsersFilter ); - CONNECT_BUTTON_SLOT( testUserGroupsFilter ); - CONNECT_BUTTON_SLOT( testComputersFilter ); - CONNECT_BUTTON_SLOT( testComputerGroupsFilter ); - CONNECT_BUTTON_SLOT( testComputerContainersFilter ); - - CONNECT_BUTTON_SLOT( testGroupsOfUser ); - CONNECT_BUTTON_SLOT( testGroupsOfComputer ); - CONNECT_BUTTON_SLOT( testComputerObjectByIpAddress ); - CONNECT_BUTTON_SLOT( testLocationEntries ); - CONNECT_BUTTON_SLOT( testLocations ); - - CONNECT_BUTTON_SLOT( browseCACertificateFile ); + CONNECT_BUTTON_SLOT( testBind ) + CONNECT_BUTTON_SLOT( testBaseDn ) + CONNECT_BUTTON_SLOT( testNamingContext ) + CONNECT_BUTTON_SLOT( testUserTree ) + CONNECT_BUTTON_SLOT( testGroupTree ) + CONNECT_BUTTON_SLOT( testComputerTree ) + CONNECT_BUTTON_SLOT( testComputerGroupTree ) + + CONNECT_BUTTON_SLOT( testUserLoginNameAttribute ) + CONNECT_BUTTON_SLOT( testGroupMemberAttribute ) + CONNECT_BUTTON_SLOT( testComputerDisplayNameAttribute ) + CONNECT_BUTTON_SLOT( testComputerHostNameAttribute ) + CONNECT_BUTTON_SLOT( testComputerMacAddressAttribute ) + CONNECT_BUTTON_SLOT( testComputerLocationAttribute ) + CONNECT_BUTTON_SLOT( testLocationNameAttribute ) + + CONNECT_BUTTON_SLOT( testUsersFilter ) + CONNECT_BUTTON_SLOT( testUserGroupsFilter ) + CONNECT_BUTTON_SLOT( testComputersFilter ) + CONNECT_BUTTON_SLOT( testComputerGroupsFilter ) + CONNECT_BUTTON_SLOT( testComputerContainersFilter ) + + CONNECT_BUTTON_SLOT( testGroupsOfUser ) + CONNECT_BUTTON_SLOT( testGroupsOfComputer ) + CONNECT_BUTTON_SLOT( testComputerObjectByIpAddress ) + CONNECT_BUTTON_SLOT( testLocationEntries ) + CONNECT_BUTTON_SLOT( testLocations ) + + CONNECT_BUTTON_SLOT( browseCACertificateFile ) connect( ui->tlsVerifyMode, QOverload::of( &QComboBox::currentIndexChanged ), ui->tlsCACertificateFile, [=]() { ui->tlsCACertificateFile->setEnabled( ui->tlsVerifyMode->currentIndex() == LdapClient::TLSVerifyCustomCert ); } ); - const auto browseButtons = findChildren( QRegularExpression( QStringLiteral("browse.*") ) ); + static const QRegularExpression browseButtonsRX{QStringLiteral("browse.*")}; + const auto browseButtons = findChildren(browseButtonsRX); for( auto button : browseButtons ) { button->setToolTip( tr( "Browse" ) ); } - const auto testButtons = findChildren( QRegularExpression( QStringLiteral("test.*") ) ); + static const QRegularExpression testButtonsRX{QStringLiteral("test.*")}; + const auto testButtons = findChildren( testButtonsRX ); for( auto button : testButtons ) { button->setToolTip( tr( "Test" ) ); @@ -115,7 +100,7 @@ LdapConfigurationPage::~LdapConfigurationPage() void LdapConfigurationPage::resetWidgets() { - FOREACH_LDAP_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY); + FOREACH_LDAP_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY) } @@ -175,154 +160,62 @@ void LdapConfigurationPage::browseAttribute( QLineEdit* lineEdit, const QString& -void LdapConfigurationPage::testBindInteractively() +void LdapConfigurationPage::testBind() { - testBind( false ); + showTestResult( LdapConfigurationTest( m_configuration ).testBind() ); } void LdapConfigurationPage::testBaseDn() { - if( testBindQuietly() ) - { - vDebug() << "[TEST][LDAP] Testing base DN"; - - LdapClient ldapClient( m_configuration ); - QStringList entries = ldapClient.queryBaseDn(); - - if( entries.isEmpty() ) - { - QMessageBox::critical( this, tr( "LDAP base DN test failed"), - tr( "Could not query the configured base DN. " - "Please check the base DN parameter.\n\n" - "%1" ).arg( ldapClient.errorDescription() ) ); - } - else - { - QMessageBox::information( this, tr( "LDAP base DN test successful" ), - tr( "The LDAP base DN has been queried successfully. " - "The following entries were found:\n\n%1" ). - arg( entries.join(QLatin1Char('\n')) ) ); - } - } + showTestResult( LdapConfigurationTest( m_configuration ).testBaseDn() ); } void LdapConfigurationPage::testNamingContext() { - if( testBindQuietly() ) - { - vDebug() << "[TEST][LDAP] Testing naming context"; - - LdapClient ldapClient( m_configuration ); - const auto baseDn = ldapClient.queryNamingContexts().value( 0 ); - - if( baseDn.isEmpty() ) - { - QMessageBox::critical( this, tr( "LDAP naming context test failed"), - tr( "Could not query the base DN via naming contexts. " - "Please check the naming context attribute parameter.\n\n" - "%1" ).arg( ldapClient.errorDescription() ) ); - } - else - { - QMessageBox::information( this, tr( "LDAP naming context test successful" ), - tr( "The LDAP naming context has been queried successfully. " - "The following base DN was found:\n%1" ). - arg( baseDn ) ); - } - } + showTestResult( LdapConfigurationTest( m_configuration ).testNamingContext() ); } void LdapConfigurationPage::testUserTree() { - if( testBindQuietly() ) - { - vDebug() << "[TEST][LDAP] Testing user tree"; - - LdapDirectory ldapDirectory( m_configuration ); - ldapDirectory.disableAttributes(); - ldapDirectory.disableFilters(); - int count = ldapDirectory.users().count(); - - reportLdapTreeQueryResult( tr( "user tree" ), count, ui->userTreeLabel->text(), - ldapDirectory.client().errorDescription() ); - } + showTestResult( LdapConfigurationTest( m_configuration ).testUserTree() ); } void LdapConfigurationPage::testGroupTree() { - if( testBindQuietly() ) - { - vDebug() << "[TEST][LDAP] Testing group tree"; - - LdapDirectory ldapDirectory( m_configuration ); - ldapDirectory.disableAttributes(); - ldapDirectory.disableFilters(); - int count = ldapDirectory.groups().count(); - - reportLdapTreeQueryResult( tr( "group tree" ), count, ui->groupTreeLabel->text(), - ldapDirectory.client().errorDescription() ); - } + showTestResult( LdapConfigurationTest( m_configuration ).testGroupTree() ); } void LdapConfigurationPage::testComputerTree() { - if( testBindQuietly() ) - { - vDebug() << "[TEST][LDAP] Testing computer tree"; - - LdapDirectory ldapDirectory( m_configuration ); - ldapDirectory.disableAttributes(); - ldapDirectory.disableFilters(); - int count = ldapDirectory.computersByHostName().count(); - - reportLdapTreeQueryResult( tr( "computer tree" ), count, ui->computerTreeLabel->text(), - ldapDirectory.client().errorDescription() ); - } + showTestResult( LdapConfigurationTest( m_configuration ).testComputerTree() ); } void LdapConfigurationPage::testComputerGroupTree() { - if( testBindQuietly() ) - { - vDebug() << "[TEST][LDAP] Testing computer group tree"; - - LdapDirectory ldapDirectory( m_configuration ); - ldapDirectory.disableAttributes(); - ldapDirectory.disableFilters(); - int count = ldapDirectory.computerGroups().count(); - - reportLdapTreeQueryResult( tr( "computer group tree" ), count, ui->computerGroupTreeLabel->text(), - ldapDirectory.client().errorDescription() ); - } + showTestResult( LdapConfigurationTest( m_configuration ).testComputerGroupTree() ); } void LdapConfigurationPage::testUserLoginNameAttribute() { - QString userFilter = QInputDialog::getText( this, tr( "Enter username" ), - tr( "Please enter a user login name (wildcards allowed) which to query:") ); + const auto userFilter = QInputDialog::getText( this, tr( "Enter username" ), + tr( "Please enter a user login name (wildcards allowed) which to query:") ); if( userFilter.isEmpty() == false ) { - vDebug() << "[TEST][LDAP] Testing user login attribute for" << userFilter; - - LdapDirectory ldapDirectory( m_configuration ); - ldapDirectory.disableFilters(); - - reportLdapObjectQueryResults( tr( "user objects" ), { ui->userLoginNameAttributeLabel->text() }, - ldapDirectory.users( userFilter ), ldapDirectory ); + showTestResult( LdapConfigurationTest( m_configuration ).testUserLoginNameAttribute( userFilter ) ); } } @@ -330,29 +223,11 @@ void LdapConfigurationPage::testUserLoginNameAttribute() void LdapConfigurationPage::testGroupMemberAttribute() { - QString groupFilter = QInputDialog::getText( this, tr( "Enter group name" ), - tr( "Please enter a group name whose members to query:") ); + const auto groupFilter = QInputDialog::getText( this, tr( "Enter group name" ), + tr( "Please enter a group name whose members to query:") ); if( groupFilter.isEmpty() == false ) { - vDebug() << "[TEST][LDAP] Testing group member attribute for" << groupFilter; - - LdapDirectory ldapDirectory( m_configuration ); - ldapDirectory.disableFilters(); - - QStringList groups = ldapDirectory.groups( groupFilter ); - - if( groups.isEmpty() == false ) - { - reportLdapObjectQueryResults( tr( "group members" ), { ui->groupMemberAttributeLabel->text() }, - ldapDirectory.groupMembers( groups.first() ), ldapDirectory ); - } - else - { - QMessageBox::warning( this, tr( "Group not found"), - tr( "Could not find a group with the name \"%1\". " - "Please check the group name or the group " - "tree parameter.").arg( groupFilter ) ); - } + showTestResult( LdapConfigurationTest( m_configuration ).testGroupMemberAttribute( groupFilter ) ); } } @@ -360,17 +235,11 @@ void LdapConfigurationPage::testGroupMemberAttribute() void LdapConfigurationPage::testComputerDisplayNameAttribute() { - auto computerName = QInputDialog::getText( this, tr( "Enter computer display name" ), - tr( "Please enter a computer display name to query:") ); + const auto computerName = QInputDialog::getText( this, tr( "Enter computer display name" ), + tr( "Please enter a computer display name to query:") ); if( computerName.isEmpty() == false ) { - vDebug() << "[TEST][LDAP] Testing computer display name attribute"; - - LdapDirectory ldapDirectory( m_configuration ); - ldapDirectory.disableFilters(); - - reportLdapObjectQueryResults( tr( "computer objects" ), { ui->computerDisplayNameAttributeLabel->text() }, - ldapDirectory.computersByDisplayName( computerName ), ldapDirectory ); + showTestResult( LdapConfigurationTest( m_configuration ).testComputerDisplayNameAttribute( computerName ) ); } } @@ -379,36 +248,11 @@ void LdapConfigurationPage::testComputerDisplayNameAttribute() void LdapConfigurationPage::testComputerHostNameAttribute() { - QString computerName = QInputDialog::getText( this, tr( "Enter computer name" ), - tr( "Please enter a computer hostname to query:") ); + const auto computerName = QInputDialog::getText( this, tr( "Enter computer name" ), + tr( "Please enter a computer hostname to query:") ); if( computerName.isEmpty() == false ) { - if( m_configuration.computerHostNameAsFQDN() && - computerName.contains( QLatin1Char('.') ) == false ) - { - QMessageBox::critical( this, tr( "Invalid hostname" ), - tr( "You configured computer hostnames to be stored " - "as fully qualified domain names (FQDN) but entered " - "a hostname without domain." ) ); - return; - } - else if( m_configuration.computerHostNameAsFQDN() == false && - computerName.contains( QLatin1Char('.') ) ) - { - QMessageBox::critical( this, tr( "Invalid hostname" ), - tr( "You configured computer hostnames to be stored " - "as simple hostnames without a domain name but " - "entered a hostname with a domain name part." ) ); - return; - } - - vDebug() << "[TEST][LDAP] Testing computer hostname attribute"; - - LdapDirectory ldapDirectory( m_configuration ); - ldapDirectory.disableFilters(); - - reportLdapObjectQueryResults( tr( "computer objects" ), { ui->computerHostNameAttributeLabel->text() }, - ldapDirectory.computersByHostName( computerName ), ldapDirectory ); + showTestResult( LdapConfigurationTest( m_configuration ).testComputerHostNameAttribute( computerName ) ); } } @@ -416,20 +260,11 @@ void LdapConfigurationPage::testComputerHostNameAttribute() void LdapConfigurationPage::testComputerMacAddressAttribute() { - QString computerDn = QInputDialog::getText( this, tr( "Enter computer DN" ), - tr( "Please enter the DN of a computer whose MAC address to query:") ); + const auto computerDn = QInputDialog::getText( this, tr( "Enter computer DN" ), + tr( "Please enter the DN of a computer whose MAC address to query:") ); if( computerDn.isEmpty() == false ) { - vDebug() << "[TEST][LDAP] Testing computer MAC address attribute"; - - LdapDirectory ldapDirectory( m_configuration ); - ldapDirectory.disableFilters(); - - QString macAddress = ldapDirectory.computerMacAddress( computerDn ); - - reportLdapObjectQueryResults( tr( "computer MAC addresses" ), { ui->computerMacAddressAttributeLabel->text() }, - macAddress.isEmpty() ? QStringList() : QStringList( macAddress ), - ldapDirectory ); + showTestResult( LdapConfigurationTest( m_configuration ).testComputerMacAddressAttribute( computerDn ) ); } } @@ -441,12 +276,7 @@ void LdapConfigurationPage::testComputerLocationAttribute() tr( "Please enter the name of a computer location (wildcards allowed):") ); if( locationName.isEmpty() == false ) { - vDebug() << "[TEST][LDAP] Testing computer location attribute for" << locationName; - - LdapDirectory ldapDirectory( m_configuration ); - - reportLdapObjectQueryResults( tr( "computer locations" ), { ui->computerLocationAttributeLabel->text() }, - ldapDirectory.computerLocations( locationName ), ldapDirectory ); + showTestResult( LdapConfigurationTest( m_configuration ).testComputerLocationAttribute( locationName ) ); } } @@ -458,12 +288,7 @@ void LdapConfigurationPage::testLocationNameAttribute() tr( "Please enter the name of a computer location (wildcards allowed):") ); if( locationName.isEmpty() == false ) { - vDebug() << "[TEST][LDAP] Testing location name attribute for" << locationName; - - LdapDirectory ldapDirectory( m_configuration ); - - reportLdapObjectQueryResults( tr( "computer locations" ), { ui->locationNameAttributeLabel->text() }, - ldapDirectory.computerLocations( locationName ), ldapDirectory ); + showTestResult( LdapConfigurationTest( m_configuration ).testLocationNameAttribute( locationName ) ); } } @@ -471,88 +296,46 @@ void LdapConfigurationPage::testLocationNameAttribute() void LdapConfigurationPage::testUsersFilter() { - vDebug() << "[TEST][LDAP] Testing users filter"; - - LdapDirectory ldapDirectory( m_configuration ); - int count = ldapDirectory.users().count(); - - reportLdapFilterTestResult( tr( "users" ), count, ldapDirectory.client().errorDescription() ); + showTestResult( LdapConfigurationTest( m_configuration ).testUsersFilter() ); } void LdapConfigurationPage::testUserGroupsFilter() { - vDebug() << "[TEST][LDAP] Testing user groups filter"; - - LdapDirectory ldapDirectory( m_configuration ); - int count = ldapDirectory.userGroups().count(); - - reportLdapFilterTestResult( tr( "user groups" ), count, ldapDirectory.client().errorDescription() ); + showTestResult( LdapConfigurationTest( m_configuration ).testUserGroupsFilter() ); } void LdapConfigurationPage::testComputersFilter() { - vDebug() << "[TEST][LDAP] Testing computers filter"; - - LdapDirectory ldapDirectory( m_configuration ); - const auto count = ldapDirectory.computersByHostName().count(); - - reportLdapFilterTestResult( tr( "computers" ), count, ldapDirectory.client().errorDescription() ); + showTestResult( LdapConfigurationTest( m_configuration ).testComputersFilter() ); } void LdapConfigurationPage::testComputerGroupsFilter() { - vDebug() << "[TEST][LDAP] Testing computer groups filter"; - - LdapDirectory ldapDirectory( m_configuration ); - int count = ldapDirectory.computerGroups().count(); - - reportLdapFilterTestResult( tr( "computer groups" ), count, ldapDirectory.client().errorDescription() ); + showTestResult( LdapConfigurationTest( m_configuration ).testComputerGroupsFilter() ); } void LdapConfigurationPage::testComputerContainersFilter() { - vDebug() << "[TEST][LDAP] Testing computer containers filter"; - - LdapDirectory ldapDirectory( m_configuration ); - const auto count = ldapDirectory.computerLocations().count(); - - reportLdapFilterTestResult( tr( "computer containers" ), count, ldapDirectory.client().errorDescription() ); + showTestResult( LdapConfigurationTest( m_configuration ).testComputerContainersFilter() ); } void LdapConfigurationPage::testGroupsOfUser() { - QString username = QInputDialog::getText( this, tr( "Enter username" ), - tr( "Please enter a user login name whose group memberships to query:") ); + const auto username = QInputDialog::getText( this, tr( "Enter username" ), + tr( "Please enter a user login name whose group memberships to query:") ); if( username.isEmpty() == false ) { - vDebug() << "[TEST][LDAP] Testing groups of user" << username; - - LdapDirectory ldapDirectory( m_configuration ); - - QStringList userObjects = ldapDirectory.users(username); - - if( userObjects.isEmpty() == false ) - { - reportLdapObjectQueryResults( tr( "groups of user" ), { ui->userLoginNameAttributeLabel->text(), - ui->groupMemberAttributeLabel->text() }, - ldapDirectory.groupsOfUser( userObjects.first() ), ldapDirectory ); - } - else - { - QMessageBox::warning( this, tr( "User not found" ), - tr( "Could not find a user with the name \"%1\". Please check the username " - "or the user tree parameter.").arg( username ) ); - } + showTestResult( LdapConfigurationTest( m_configuration ).testGroupsOfUser( username ) ); } } @@ -560,29 +343,11 @@ void LdapConfigurationPage::testGroupsOfUser() void LdapConfigurationPage::testGroupsOfComputer() { - QString computerHostName = QInputDialog::getText( this, tr( "Enter hostname" ), + const auto computerHostName = QInputDialog::getText( this, tr( "Enter hostname" ), tr( "Please enter a computer hostname whose group memberships to query:") ); if( computerHostName.isEmpty() == false ) { - vDebug() << "[TEST][LDAP] Testing groups of computer for" << computerHostName; - - LdapDirectory ldapDirectory( m_configuration ); - - QStringList computerObjects = ldapDirectory.computersByHostName(computerHostName); - - if( computerObjects.isEmpty() == false ) - { - reportLdapObjectQueryResults( tr( "groups of computer" ), { ui->computerHostNameAttributeLabel->text(), - ui->groupMemberAttributeLabel->text() }, - ldapDirectory.groupsOfComputer( computerObjects.first() ), ldapDirectory ); - } - else - { - QMessageBox::warning( this, tr( "Computer not found" ), - tr( "Could not find a computer with the hostname \"%1\". " - "Please check the hostname or the computer tree " - "parameter.").arg( computerHostName ) ); - } + showTestResult( LdapConfigurationTest( m_configuration ).testGroupsOfComputer( computerHostName ) ); } } @@ -590,30 +355,11 @@ void LdapConfigurationPage::testGroupsOfComputer() void LdapConfigurationPage::testComputerObjectByIpAddress() { - QString computerIpAddress = QInputDialog::getText( this, tr( "Enter computer IP address" ), + const auto computerIpAddress = QInputDialog::getText( this, tr( "Enter computer IP address" ), tr( "Please enter a computer IP address which to resolve to an computer object:") ); if( computerIpAddress.isEmpty() == false ) { - vDebug() << "[TEST][LDAP] Testing computer object resolve by IP address" << computerIpAddress; - - LdapDirectory ldapDirectory( m_configuration ); - - QString computerName = ldapDirectory.hostToLdapFormat( computerIpAddress ); - - vDebug() << "[TEST][LDAP] Resolved IP address to computer name" << computerName; - - if( computerName.isEmpty() ) - { - QMessageBox::critical( this, tr( "Hostname lookup failed" ), - tr( "Could not lookup hostname for IP address %1. " - "Please check your DNS server settings." ).arg( computerIpAddress ) ); - } - else - { - reportLdapObjectQueryResults( tr( "computers" ), { ui->computerHostNameAttributeLabel->text() }, - ldapDirectory.computersByHostName( computerName ), ldapDirectory ); - } - + showTestResult( LdapConfigurationTest( m_configuration ).testComputerObjectByIpAddress( computerIpAddress ) ); } } @@ -625,12 +371,7 @@ void LdapConfigurationPage::testLocationEntries() tr( "Please enter the name of a location whose entries to query:") ); if( locationName.isEmpty() == false ) { - vDebug() << "[TEST][LDAP] Testing location entries for" << locationName; - - LdapDirectory ldapDirectory( m_configuration ); - reportLdapObjectQueryResults( tr( "location entries" ), { ui->computerGroupsFilterLabel->text(), - ui->computerLocationsIdentifications->title() }, - ldapDirectory.computerLocationEntries( locationName ), ldapDirectory ); + showTestResult( LdapConfigurationTest( m_configuration ).testLocationEntries( locationName ) ); } } @@ -638,12 +379,7 @@ void LdapConfigurationPage::testLocationEntries() void LdapConfigurationPage::testLocations() { - vDebug() << "[TEST][LDAP] Querying all locations"; - - LdapDirectory ldapDirectory( m_configuration ); - reportLdapObjectQueryResults( tr( "location entries" ), { ui->computerGroupsFilterLabel->text(), - ui->computerLocationsIdentifications->title() }, - ldapDirectory.computerLocations(), ldapDirectory ); + showTestResult( LdapConfigurationTest( m_configuration ).testLocations() ); } @@ -660,124 +396,15 @@ void LdapConfigurationPage::browseCACertificateFile() -bool LdapConfigurationPage::testBind( bool quiet ) -{ - vDebug() << "[TEST][LDAP] Testing bind"; - - LdapClient ldapClient( m_configuration ); - - if( ldapClient.isConnected() == false ) - { - QMessageBox::critical( this, tr( "LDAP connection failed"), - tr( "Could not connect to the LDAP server. " - "Please check the server parameters.\n\n" - "%1" ).arg( ldapClient.errorDescription() ) ); - } - else if( ldapClient.isBound() == false ) - { - QMessageBox::critical( this, tr( "LDAP bind failed"), - tr( "Could not bind to the LDAP server. " - "Please check the server parameters " - "and bind credentials.\n\n" - "%1" ).arg( ldapClient.errorDescription() ) ); - } - else if( quiet == false ) - { - QMessageBox::information( this, tr( "LDAP bind successful"), - tr( "Successfully connected to the LDAP " - "server and performed an LDAP bind. " - "The basic LDAP settings are " - "configured correctly." ) ); - } - - return ldapClient.isConnected() && ldapClient.isBound(); -} - - - - -void LdapConfigurationPage::reportLdapTreeQueryResult( const QString& name, int count, - const QString& parameter, const QString& errorDescription ) -{ - if( count <= 0 ) - { - QMessageBox::critical( this, tr( "LDAP %1 test failed").arg( name ), - tr( "Could not query any entries in configured %1. " - "Please check the parameter \"%2\".\n\n" - "%3" ).arg( name, parameter, errorDescription ) ); - } - else - { - QMessageBox::information( this, tr( "LDAP %1 test successful" ).arg( name ), - tr( "The %1 has been queried successfully and " - "%2 entries were found." ).arg( name ).arg( count ) ); - } -} - - - - - -void LdapConfigurationPage::reportLdapObjectQueryResults( const QString &objectsName, const QStringList& parameterNames, - const QStringList& results, const LdapDirectory &directory ) -{ - if( results.isEmpty() ) - { - QStringList parameters; - parameters.reserve( parameterNames.count() ); - - for( const auto& parameterName : parameterNames ) - { - parameters += QStringLiteral("\"%1\"").arg( parameterName ); - } - - QMessageBox::critical( this, tr( "LDAP test failed"), - tr( "Could not query any %1. " - "Please check the parameter(s) %2 and enter the name of an existing object.\n\n" - "%3" ).arg( objectsName, parameters.join( QStringLiteral(" %1 ").arg( tr("and") ) ), - directory.client().errorDescription() ) ); - } - else - { - QMessageBox::information( this, tr( "LDAP test successful" ), - tr( "%1 %2 have been queried successfully:\n\n%3" ). - arg( results.count() ). - arg( objectsName, formatResultsString( results ) ) ); - } -} - - - - - -void LdapConfigurationPage::reportLdapFilterTestResult( const QString &filterObjects, int count, const QString &errorDescription ) +void LdapConfigurationPage::showTestResult( const LdapConfigurationTest::Result& result ) { - if( count <= 0 ) + if( result ) { - QMessageBox::critical( this, tr( "LDAP filter test failed"), - tr( "Could not query any %1 using the configured filter. " - "Please check the LDAP filter for %1.\n\n" - "%2" ).arg( filterObjects, errorDescription ) ); + QMessageBox::information( this, result.title, result.message ); } else { - QMessageBox::information( this, tr( "LDAP filter test successful" ), - tr( "%1 %2 have been queried successfully using the configured filter." ). - arg( count ).arg( filterObjects ) ); - } -} - - -QString LdapConfigurationPage::formatResultsString( const QStringList &results ) -{ - static constexpr auto FirstResult = 0; - static constexpr auto MaxResults = 3; - - if( results.count() <= MaxResults ) - { - return results.join(QLatin1Char('\n')); + QMessageBox::critical( this, result.title, result.message ); } - - return QStringLiteral( "%1\n[...]" ).arg( results.mid( FirstResult, MaxResults ).join( QLatin1Char('\n') ) ); } diff --git a/plugins/ldap/common/LdapConfigurationPage.h b/plugins/ldap/common/LdapConfigurationPage.h index 490c36a87..ab2c77fe6 100644 --- a/plugins/ldap/common/LdapConfigurationPage.h +++ b/plugins/ldap/common/LdapConfigurationPage.h @@ -1,30 +1,12 @@ -/* - * LdapConfigurationPage.h - header for the LdapConfigurationPage class - * - * Copyright (c) 2016-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #pragma once #include "ConfigurationPage.h" +#include "LdapConfigurationTest.h" +#include "LdapCommon.h" class LdapConfiguration; class LdapDirectory; @@ -35,7 +17,7 @@ class LdapConfigurationPage; class QLineEdit; -class LdapConfigurationPage : public ConfigurationPage +class LDAP_COMMON_EXPORT LdapConfigurationPage : public ConfigurationPage { Q_OBJECT public: @@ -51,7 +33,7 @@ class LdapConfigurationPage : public ConfigurationPage void browseObjectTree( QLineEdit* lineEdit ); void browseAttribute( QLineEdit* lineEdit, const QString& tree ); - void testBindInteractively(); + void testBind(); void testBaseDn(); void testNamingContext(); void testUserTree(); @@ -78,19 +60,7 @@ class LdapConfigurationPage : public ConfigurationPage void browseCACertificateFile(); - bool testBindQuietly() - { - return testBind( true ); - } - - bool testBind( bool quiet ); - void reportLdapTreeQueryResult( const QString& name, int count, const QString& parameter, - const QString& errorDescription ); - void reportLdapObjectQueryResults( const QString &objectsName, const QStringList& parameterNames, - const QStringList &results, const LdapDirectory& directory ); - void reportLdapFilterTestResult( const QString &filterObjects, int count, const QString &errorDescription ); - - static QString formatResultsString( const QStringList& results ); + void showTestResult( const LdapConfigurationTest::Result& result ); Ui::LdapConfigurationPage *ui; diff --git a/plugins/ldap/common/LdapConfigurationPage.ui b/plugins/ldap/common/LdapConfigurationPage.ui index dc11becee..85e6741e0 100644 --- a/plugins/ldap/common/LdapConfigurationPage.ui +++ b/plugins/ldap/common/LdapConfigurationPage.ui @@ -16,6 +16,20 @@ 0 + + + + + + Directory name + + + + + + + + @@ -71,7 +85,7 @@ - + :/core/dialog-ok-apply.png:/core/dialog-ok-apply.png @@ -80,33 +94,30 @@ - - + + - Bind DN + Query timeout - - - - 65536 - - - 389 + + + + + + + false - - + + - Bind password + Bind DN - - - @@ -117,6 +128,19 @@ + + + + ms + + + 500 + + + 60000 + + + @@ -124,10 +148,20 @@ - - - - false + + + + 65536 + + + 389 + + + + + + + Bind password @@ -829,6 +863,29 @@ + + + + Query options + + + + + + Query nested user groups (supported by AD only) + + + + + + + Map container/OU structure 1:1 to locations + + + + + + @@ -1013,9 +1070,10 @@ serverPort anonymousBind useBindCredentials - testBindInteractively + testBind bindDn bindPassword + queryTimeout connectionSecurity tlsVerifyMode tlsCACertificateFile @@ -1071,6 +1129,8 @@ testComputersFilter testComputerGroupsFilter testComputerContainersFilter + queryNestedUserGroups + mapContainerStructureToLocations identifyGroupMembersByDN identifyGroupMembersByNameAttribute computerLocationsByGroups @@ -1359,11 +1419,27 @@ + + computerLocationsByContainer + toggled(bool) + mapContainerStructureToLocations + setEnabled(bool) + + + 281 + 536 + + + 281 + 309 + + + - - + + diff --git a/plugins/ldap/common/LdapConfigurationTest.cpp b/plugins/ldap/common/LdapConfigurationTest.cpp new file mode 100644 index 000000000..d51241e5b --- /dev/null +++ b/plugins/ldap/common/LdapConfigurationTest.cpp @@ -0,0 +1,638 @@ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later + +#include "LdapConfiguration.h" +#include "LdapConfigurationTest.h" +#include "LdapDirectory.h" + + +LdapConfigurationTest::LdapConfigurationTest( LdapConfiguration& configuration ) : + m_configuration( configuration ) +{ +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testBind() +{ + vDebug() << "[TEST][LDAP] Testing bind"; + + LdapClient ldapClient( m_configuration ); + + if( ldapClient.isConnected() == false ) + { + return { false, + LdapConfiguration::tr( "LDAP connection failed"), + LdapConfiguration::tr( "Could not connect to the LDAP server. " + "Please check the server parameters.\n\n" + "%1" ).arg( ldapClient.errorDescription() ) }; + } + else if( ldapClient.isBound() == false ) + { + return { false, + LdapConfiguration::tr( "LDAP bind failed"), + LdapConfiguration::tr( "Could not bind to the LDAP server. " + "Please check the server parameters " + "and bind credentials.\n\n" + "%1" ).arg( ldapClient.errorDescription() ) }; + } + + return { true, + LdapConfiguration::tr( "LDAP bind successful"), + LdapConfiguration::tr( "Successfully connected to the LDAP " + "server and performed an LDAP bind. " + "The basic LDAP settings are " + "configured correctly." ) }; +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testBaseDn() +{ + const auto bindTestResult = testBind(); + if( bindTestResult ) + { + vDebug() << "[TEST][LDAP] Testing base DN"; + + LdapClient ldapClient( m_configuration ); + QStringList entries = ldapClient.queryBaseDn(); + + if( entries.isEmpty() ) + { + return { false, + LdapConfiguration::tr( "LDAP base DN test failed"), + LdapConfiguration::tr( "Could not query the configured base DN. " + "Please check the base DN parameter.\n\n" + "%1" ).arg( ldapClient.errorDescription() ) }; + } + + return { true, + LdapConfiguration::tr( "LDAP base DN test successful" ), + LdapConfiguration::tr( "The LDAP base DN has been queried successfully. " + "The following entries were found:\n\n%1" ). + arg( entries.join(QLatin1Char('\n')) ) }; + } + + return bindTestResult; +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testNamingContext() +{ + const auto bindTestResult = testBind(); + if( bindTestResult ) + { + vDebug() << "[TEST][LDAP] Testing naming context"; + + LdapClient ldapClient( m_configuration ); + const auto baseDn = ldapClient.queryNamingContexts().value( 0 ); + + if( baseDn.isEmpty() ) + { + return { false, + LdapConfiguration::tr( "LDAP naming context test failed"), + LdapConfiguration::tr( "Could not query the base DN via naming contexts. " + "Please check the naming context attribute parameter.\n\n" + "%1" ).arg( ldapClient.errorDescription() ) }; + } + + return { true, + LdapConfiguration::tr( "LDAP naming context test successful" ), + LdapConfiguration::tr( "The LDAP naming context has been queried successfully. " + "The following base DN was found:\n%1" ). + arg( baseDn ) }; + } + + return bindTestResult; +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testUserTree() +{ + const auto bindTestResult = testBind(); + if( bindTestResult ) + { + vDebug() << "[TEST][LDAP] Testing user tree"; + + LdapDirectory ldapDirectory( m_configuration ); + ldapDirectory.disableAttributes(); + ldapDirectory.disableFilters(); + int count = ldapDirectory.users().count(); + + return reportLdapTreeQueryResult( LdapConfiguration::tr( "user tree" ), count, LdapConfiguration::tr( "User tree" ), + ldapDirectory.client().errorDescription() ); + } + + return bindTestResult; +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testGroupTree() +{ + const auto bindTestResult = testBind(); + if( bindTestResult ) + { + vDebug() << "[TEST][LDAP] Testing group tree"; + + LdapDirectory ldapDirectory( m_configuration ); + ldapDirectory.disableAttributes(); + ldapDirectory.disableFilters(); + const auto count = ldapDirectory.groups().count(); + + return reportLdapTreeQueryResult( LdapConfiguration::tr( "group tree" ), count, LdapConfiguration::tr( "Group tree" ), + ldapDirectory.client().errorDescription() ); + } + + return bindTestResult; +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testComputerTree() +{ + const auto bindTestResult = testBind(); + if( bindTestResult ) + { + vDebug() << "[TEST][LDAP] Testing computer tree"; + + LdapDirectory ldapDirectory( m_configuration ); + ldapDirectory.disableAttributes(); + ldapDirectory.disableFilters(); + int count = ldapDirectory.computersByHostName().count(); + + return reportLdapTreeQueryResult( LdapConfiguration::tr( "computer tree" ), count, + LdapConfiguration::tr( "Computer tree" ), + ldapDirectory.client().errorDescription() ); + } + + return bindTestResult; +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testComputerGroupTree() +{ + const auto bindTestResult = testBind(); + if( bindTestResult ) + { + vDebug() << "[TEST][LDAP] Testing computer group tree"; + + LdapDirectory ldapDirectory( m_configuration ); + ldapDirectory.disableAttributes(); + ldapDirectory.disableFilters(); + int count = ldapDirectory.computerGroups().count(); + + return reportLdapTreeQueryResult( LdapConfiguration::tr( "computer group tree" ), count, + LdapConfiguration::tr( "Computer group tree" ), + ldapDirectory.client().errorDescription() ); + } + + return bindTestResult; +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testUserLoginNameAttribute( const QString& userFilter ) +{ + if( userFilter.isEmpty() == false ) + { + vDebug() << "[TEST][LDAP] Testing user login attribute for" << userFilter; + + LdapDirectory ldapDirectory( m_configuration ); + ldapDirectory.disableFilters(); + + return reportLdapObjectQueryResults( LdapConfiguration::tr( "user objects" ), + { LdapConfiguration::tr( "User login name attribute" ) }, + ldapDirectory.users( userFilter ), ldapDirectory ); + } + + return invalidTestValueSuppliedResult(); +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testGroupMemberAttribute( const QString& groupFilter ) +{ + if( groupFilter.isEmpty() == false ) + { + vDebug() << "[TEST][LDAP] Testing group member attribute for" << groupFilter; + + LdapDirectory ldapDirectory( m_configuration ); + ldapDirectory.disableFilters(); + + QStringList groups = ldapDirectory.groups( groupFilter ); + + if( groups.isEmpty() == false ) + { + return reportLdapObjectQueryResults( LdapConfiguration::tr( "group members" ), + { LdapConfiguration::tr( "Group member attribute") }, + ldapDirectory.groupMembers( groups.first() ), ldapDirectory ); + } + + return { false, + LdapConfiguration::tr( "Group not found"), + LdapConfiguration::tr( "Could not find a group with the name \"%1\". " + "Please check the group name or the group " + "tree parameter.").arg( groupFilter ) }; + } + + return invalidTestValueSuppliedResult(); +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testComputerDisplayNameAttribute( const QString& computerName ) +{ + if( computerName.isEmpty() == false ) + { + vDebug() << "[TEST][LDAP] Testing computer display name attribute"; + + LdapDirectory ldapDirectory( m_configuration ); + ldapDirectory.disableFilters(); + + return reportLdapObjectQueryResults( LdapConfiguration::tr( "computer objects" ), + { LdapConfiguration::tr( "Computer display name attribute" ) }, + ldapDirectory.computersByDisplayName( computerName ), ldapDirectory ); + } + + return invalidTestValueSuppliedResult(); +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testComputerHostNameAttribute( const QString& computerName ) +{ + if( computerName.isEmpty() == false ) + { + if( m_configuration.computerHostNameAsFQDN() && + computerName.contains( QLatin1Char('.') ) == false ) + { + return { false, + LdapConfiguration::tr( "Invalid hostname" ), + LdapConfiguration::tr( "You configured computer hostnames to be stored " + "as fully qualified domain names (FQDN) but entered " + "a hostname without domain." ) }; + } + + if( m_configuration.computerHostNameAsFQDN() == false && + computerName.contains( QLatin1Char('.') ) ) + { + return { false, + LdapConfiguration::tr( "Invalid hostname" ), + LdapConfiguration::tr( "You configured computer hostnames to be stored " + "as simple hostnames without a domain name but " + "entered a hostname with a domain name part." ) }; + } + + vDebug() << "[TEST][LDAP] Testing computer hostname attribute"; + + LdapDirectory ldapDirectory( m_configuration ); + ldapDirectory.disableFilters(); + + return reportLdapObjectQueryResults( LdapConfiguration::tr( "computer objects" ), + { LdapConfiguration::tr( "Computer hostname attribute" ) }, + ldapDirectory.computersByHostName( computerName ), ldapDirectory ); + } + + return invalidTestValueSuppliedResult(); +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testComputerMacAddressAttribute( const QString& computerDn ) +{ + if( computerDn.isEmpty() == false ) + { + vDebug() << "[TEST][LDAP] Testing computer MAC address attribute"; + + LdapDirectory ldapDirectory( m_configuration ); + ldapDirectory.disableFilters(); + + const auto macAddress = ldapDirectory.computerMacAddress( computerDn ); + + return reportLdapObjectQueryResults( LdapConfiguration::tr( "computer MAC addresses" ), + { LdapConfiguration::tr( "Computer MAC address attribute" ) }, + macAddress.isEmpty() ? QStringList() : QStringList( macAddress ), + ldapDirectory ); + } + + return invalidTestValueSuppliedResult(); +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testComputerLocationAttribute( const QString& locationName ) +{ + if( locationName.isEmpty() == false ) + { + vDebug() << "[TEST][LDAP] Testing computer location attribute for" << locationName; + + LdapDirectory ldapDirectory( m_configuration ); + + return reportLdapObjectQueryResults( LdapConfiguration::tr( "computer locations" ), + { LdapConfiguration::tr( "Computer location attribute" ) }, + ldapDirectory.computerLocations( locationName ), ldapDirectory ); + } + + return invalidTestValueSuppliedResult(); +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testLocationNameAttribute( const QString& locationName ) +{ + if( locationName.isEmpty() == false ) + { + vDebug() << "[TEST][LDAP] Testing location name attribute for" << locationName; + + LdapDirectory ldapDirectory( m_configuration ); + + return reportLdapObjectQueryResults( LdapConfiguration::tr( "computer locations" ), + { LdapConfiguration::tr( "Location name attribute" ) }, + ldapDirectory.computerLocations( locationName ), ldapDirectory ); + } + + return invalidTestValueSuppliedResult(); +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testUsersFilter() +{ + vDebug() << "[TEST][LDAP] Testing users filter"; + + LdapDirectory ldapDirectory( m_configuration ); + const auto count = ldapDirectory.users().count(); + + return reportLdapFilterTestResult( LdapConfiguration::tr( "users" ), count, ldapDirectory.client().errorDescription() ); +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testUserGroupsFilter() +{ + vDebug() << "[TEST][LDAP] Testing user groups filter"; + + LdapDirectory ldapDirectory( m_configuration ); + const auto count = ldapDirectory.userGroups().count(); + + return reportLdapFilterTestResult( LdapConfiguration::tr( "user groups" ), count, ldapDirectory.client().errorDescription() ); +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testComputersFilter() +{ + vDebug() << "[TEST][LDAP] Testing computers filter"; + + LdapDirectory ldapDirectory( m_configuration ); + const auto count = ldapDirectory.computersByHostName().count(); + + return reportLdapFilterTestResult( LdapConfiguration::tr( "computers" ), count, ldapDirectory.client().errorDescription() ); +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testComputerGroupsFilter() +{ + vDebug() << "[TEST][LDAP] Testing computer groups filter"; + + LdapDirectory ldapDirectory( m_configuration ); + const auto count = ldapDirectory.computerGroups().count(); + + return reportLdapFilterTestResult( LdapConfiguration::tr( "computer groups" ), count, ldapDirectory.client().errorDescription() ); +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testComputerContainersFilter() +{ + vDebug() << "[TEST][LDAP] Testing computer containers filter"; + + LdapDirectory ldapDirectory( m_configuration ); + const auto count = ldapDirectory.computerLocations().count(); + + return reportLdapFilterTestResult( LdapConfiguration::tr( "computer containers" ), count, ldapDirectory.client().errorDescription() ); +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testGroupsOfUser( const QString& username ) +{ + if( username.isEmpty() == false ) + { + vDebug() << "[TEST][LDAP] Testing groups of user" << username; + + LdapDirectory ldapDirectory( m_configuration ); + + const auto userObjects = ldapDirectory.users(username); + + if( userObjects.isEmpty() == false ) + { + return reportLdapObjectQueryResults( LdapConfiguration::tr( "groups of user" ), + { LdapConfiguration::tr("User login name attribute"), + LdapConfiguration::tr("Group member attribute") }, + ldapDirectory.groupsOfUser( userObjects.first() ), ldapDirectory ); + } + + return { false, + LdapConfiguration::tr( "User not found" ), + LdapConfiguration::tr( "Could not find a user with the name \"%1\". Please check the username " + "or the user tree parameter.").arg( username ) }; + } + + return invalidTestValueSuppliedResult(); +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testGroupsOfComputer( const QString& computerHostName ) +{ + if( computerHostName.isEmpty() == false ) + { + vDebug() << "[TEST][LDAP] Testing groups of computer for" << computerHostName; + + LdapDirectory ldapDirectory( m_configuration ); + + QStringList computerObjects = ldapDirectory.computersByHostName(computerHostName); + + if( computerObjects.isEmpty() == false ) + { + return reportLdapObjectQueryResults( LdapConfiguration::tr( "groups of computer" ), + { LdapConfiguration::tr( "Computer hostname attribute" ), + LdapConfiguration::tr( "Group member attribute" ) }, + ldapDirectory.groupsOfComputer( computerObjects.first() ), ldapDirectory ); + } + + return { false, + LdapConfiguration::tr( "Computer not found" ), + LdapConfiguration::tr( "Could not find a computer with the hostname \"%1\". " + "Please check the hostname or the computer tree " + "parameter.").arg( computerHostName ) }; + } + + return invalidTestValueSuppliedResult(); +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testComputerObjectByIpAddress( const QString& computerIpAddress ) +{ + if( computerIpAddress.isEmpty() == false ) + { + vDebug() << "[TEST][LDAP] Testing computer object resolve by IP address" << computerIpAddress; + + LdapDirectory ldapDirectory( m_configuration ); + + QString computerName = ldapDirectory.hostToLdapFormat( computerIpAddress ); + + vDebug() << "[TEST][LDAP] Resolved IP address to computer name" << computerName; + + if( computerName.isEmpty() == false ) + { + return reportLdapObjectQueryResults( LdapConfiguration::tr( "computers" ), + { LdapConfiguration::tr( "Computer hostname attribute" ) }, + ldapDirectory.computersByHostName( computerName ), ldapDirectory ); + } + + return { false, + LdapConfiguration::tr( "Hostname lookup failed" ), + LdapConfiguration::tr( "Could not lookup hostname for IP address %1. " + "Please check your DNS server settings." ).arg( computerIpAddress ) }; + } + + return invalidTestValueSuppliedResult(); +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testLocationEntries( const QString& locationName ) +{ + if( locationName.isEmpty() == false ) + { + vDebug() << "[TEST][LDAP] Testing location entries for" << locationName; + + LdapDirectory ldapDirectory( m_configuration ); + return reportLdapObjectQueryResults( LdapConfiguration::tr( "location entries" ), + { LdapConfiguration::tr( "Computer groups filter" ), + LdapConfiguration::tr( "Computer locations identification") }, + ldapDirectory.computerLocationEntries( locationName ), ldapDirectory ); + } + + return invalidTestValueSuppliedResult(); + +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::testLocations() +{ + vDebug() << "[TEST][LDAP] Querying all locations"; + + LdapDirectory ldapDirectory( m_configuration ); + return reportLdapObjectQueryResults( LdapConfiguration::tr( "location entries" ), + { LdapConfiguration::tr( "Filter for computer groups" ), + LdapConfiguration::tr( "Computer locations identification") }, + ldapDirectory.computerLocations(), ldapDirectory ); +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::invalidTestValueSuppliedResult() +{ + return { false, + LdapConfiguration::tr( "Invalid test value"), + LdapConfiguration::tr("An empty or invalid value has been supplied for this test.") }; +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::reportLdapTreeQueryResult( const QString& name, int count, + const QString& parameter, const QString& errorDescription ) +{ + if( count <= 0 ) + { + return { false, + LdapConfiguration::tr( "LDAP %1 test failed").arg( name ), + LdapConfiguration::tr( "Could not query any entries in configured %1. " + "Please check the parameter \"%2\".\n\n" + "%3" ).arg( name, parameter, errorDescription ) }; + } + + return { true, + LdapConfiguration::tr( "LDAP %1 test successful" ).arg( name ), + LdapConfiguration::tr( "The %1 has been queried successfully and " + "%2 entries were found." ).arg( name ).arg( count ) }; +} + + + +LdapConfigurationTest::Result LdapConfigurationTest::reportLdapObjectQueryResults( const QString &objectsName, + const QStringList& parameterNames, + const QStringList& results, const LdapDirectory &directory ) +{ + if( results.isEmpty() ) + { + QStringList parameters; + parameters.reserve( parameterNames.count() ); + + for( const auto& parameterName : parameterNames ) + { + parameters += QStringLiteral("\"%1\"").arg( parameterName ); + } + + return { false, + LdapConfiguration::tr( "LDAP test failed"), + LdapConfiguration::tr( "Could not query any %1. " + "Please check the parameter(s) %2 and enter the name of an existing object.\n\n" + "%3" ).arg( objectsName, parameters.join( QStringLiteral(" %1 ") + .arg( LdapConfiguration::tr("and") ) ), + directory.client().errorDescription() ) }; + } + + return { true, + LdapConfiguration::tr( "LDAP test successful" ), + LdapConfiguration::tr( "%1 %2 have been queried successfully:\n\n%3" ).arg( results.count() ) + .arg( objectsName, formatResultsString( results ) ) }; +} + + + + + +LdapConfigurationTest::Result LdapConfigurationTest::reportLdapFilterTestResult( const QString &filterObjects, int count, + const QString &errorDescription ) +{ + if( count <= 0 ) + { + return { false, + LdapConfiguration::tr( "LDAP filter test failed"), + LdapConfiguration::tr( "Could not query any %1 using the configured filter. " + "Please check the LDAP filter for %1.\n\n" + "%2" ).arg( filterObjects, errorDescription ) }; + } + + return { true, + LdapConfiguration::tr( "LDAP filter test successful" ), + LdapConfiguration::tr( "%1 %2 have been queried successfully using the configured filter." ) + .arg( count ).arg( filterObjects ) }; +} + + + +QString LdapConfigurationTest::formatResultsString( const QStringList &results ) +{ + static constexpr auto FirstResult = 0; + static constexpr auto MaxResults = 3; + + if( results.count() <= MaxResults ) + { + return results.join(QLatin1Char('\n')); + } + + return QStringLiteral( "%1\n[...]" ).arg( results.mid( FirstResult, MaxResults ).join( QLatin1Char('\n') ) ); +} diff --git a/plugins/ldap/common/LdapConfigurationTest.h b/plugins/ldap/common/LdapConfigurationTest.h new file mode 100644 index 000000000..dea63a1f2 --- /dev/null +++ b/plugins/ldap/common/LdapConfigurationTest.h @@ -0,0 +1,68 @@ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later + +#pragma once + +#include + +#include "LdapCommon.h" + +class LdapConfiguration; +class LdapDirectory; + +class LDAP_COMMON_EXPORT LdapConfigurationTest +{ +public: + explicit LdapConfigurationTest( LdapConfiguration& configuration ); + + struct Result + { + bool success{false}; + QString title; + QString message; + operator bool() const + { + return success; + } + }; + +public: + Result testBind(); + Result testBaseDn(); + Result testNamingContext(); + Result testUserTree(); + Result testGroupTree(); + Result testComputerTree(); + Result testComputerGroupTree(); + Result testUserLoginNameAttribute( const QString& userFilter ); + Result testGroupMemberAttribute( const QString& groupFilter ); + Result testComputerDisplayNameAttribute( const QString& computerName ); + Result testComputerHostNameAttribute( const QString& computerName ); + Result testComputerMacAddressAttribute( const QString& computerDn ); + Result testComputerLocationAttribute( const QString& locationName ); + Result testLocationNameAttribute( const QString& locationName ); + Result testUsersFilter(); + Result testUserGroupsFilter(); + Result testComputersFilter(); + Result testComputerGroupsFilter(); + Result testComputerContainersFilter(); + Result testGroupsOfUser( const QString& username ); + Result testGroupsOfComputer( const QString& computerHostName ); + Result testComputerObjectByIpAddress( const QString& computerIpAddress ); + Result testLocationEntries( const QString& locationName ); + Result testLocations(); + + static Result invalidTestValueSuppliedResult(); + + Result reportLdapTreeQueryResult( const QString& name, int count, const QString& parameter, + const QString& errorDescription ); + Result reportLdapObjectQueryResults( const QString &objectsName, const QStringList& parameterNames, + const QStringList &results, const LdapDirectory& directory ); + Result reportLdapFilterTestResult( const QString &filterObjects, int count, const QString &errorDescription ); + + static QString formatResultsString( const QStringList& results ); + + LdapConfiguration& m_configuration; + +}; diff --git a/plugins/ldap/common/LdapDirectory.cpp b/plugins/ldap/common/LdapDirectory.cpp index a8c486bb8..cd8dc45e0 100644 --- a/plugins/ldap/common/LdapDirectory.cpp +++ b/plugins/ldap/common/LdapDirectory.cpp @@ -1,26 +1,6 @@ -/* - * LdapDirectory.cpp - class representing the LDAP directory and providing access to directory entries - * - * Copyright (c) 2016-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #include "HostAddress.h" #include "LdapConfiguration.h" @@ -43,14 +23,28 @@ LdapDirectory::LdapDirectory( const LdapConfiguration& configuration, QObject* p m_userLoginNameAttribute = m_configuration.userLoginNameAttribute(); m_groupMemberAttribute = m_configuration.groupMemberAttribute(); + + m_groupMemberFilterAttribute = m_groupMemberAttribute; + if( m_configuration.queryNestedUserGroups() && + m_groupMemberFilterAttribute.contains( QLatin1Char(':') ) == false ) + { + m_groupMemberFilterAttribute.append( QLatin1String(":1.2.840.113556.1.4.1941:") ); + } + m_computerDisplayNameAttribute = m_configuration.computerDisplayNameAttribute(); m_computerHostNameAttribute = m_configuration.computerHostNameAttribute(); m_computerHostNameAsFQDN = m_configuration.computerHostNameAsFQDN(); m_computerMacAddressAttribute = m_configuration.computerMacAddressAttribute(); m_locationNameAttribute = m_configuration.locationNameAttribute(); + + if( m_computerDisplayNameAttribute.isEmpty() ) + { + m_computerDisplayNameAttribute = LdapClient::cn(); + } + if( m_locationNameAttribute.isEmpty() ) { - m_locationNameAttribute = QStringLiteral("cn"); + m_locationNameAttribute = LdapClient::cn(); } m_usersFilter = m_configuration.usersFilter(); @@ -65,6 +59,7 @@ LdapDirectory::LdapDirectory( const LdapConfiguration& configuration, QObject* p m_computerLocationsByAttribute = m_configuration.computerLocationsByAttribute(); m_computerLocationAttribute = m_configuration.computerLocationAttribute(); + m_mapContainerStructureToLocations = m_configuration.mapContainerStructureToLocations(); } @@ -173,7 +168,7 @@ QStringList LdapDirectory::users( const QString& filterValue ) QStringList LdapDirectory::groups( const QString& filterValue ) { return m_client.queryDistinguishedNames( groupsDn(), - LdapClient::constructQueryFilter( QStringLiteral( "cn" ), filterValue ), + LdapClient::constructQueryFilter( LdapClient::cn(), filterValue ), m_defaultSearchScope ); } @@ -182,7 +177,7 @@ QStringList LdapDirectory::groups( const QString& filterValue ) QStringList LdapDirectory::userGroups( const QString& filterValue ) { return m_client.queryDistinguishedNames( groupsDn(), - LdapClient::constructQueryFilter( QStringLiteral( "cn" ), filterValue, m_userGroupsFilter ), + LdapClient::constructQueryFilter( LdapClient::cn(), filterValue, m_userGroupsFilter ), m_defaultSearchScope ); } @@ -265,13 +260,13 @@ QStringList LdapDirectory::groupMembers( const QString& groupDn ) QStringList LdapDirectory::groupsOfUser( const QString& userDn ) { const auto userId = groupMemberUserIdentification( userDn ); - if( m_groupMemberAttribute.isEmpty() || userId.isEmpty() ) + if( m_groupMemberFilterAttribute.isEmpty() || userId.isEmpty() ) { return {}; } return m_client.queryDistinguishedNames( groupsDn(), - LdapClient::constructQueryFilter( m_groupMemberAttribute, userId, m_userGroupsFilter ), + LdapClient::constructQueryFilter( m_groupMemberFilterAttribute, userId, m_userGroupsFilter ), m_defaultSearchScope ); } @@ -280,13 +275,13 @@ QStringList LdapDirectory::groupsOfUser( const QString& userDn ) QStringList LdapDirectory::groupsOfComputer( const QString& computerDn ) { const auto computerId = groupMemberComputerIdentification( computerDn ); - if( m_groupMemberAttribute.isEmpty() || computerId.isEmpty() ) + if( m_groupMemberFilterAttribute.isEmpty() || computerId.isEmpty() ) { return {}; } return m_client.queryDistinguishedNames( computerGroupsDn(), - LdapClient::constructQueryFilter( m_groupMemberAttribute, computerId, m_computerGroupsFilter ), + LdapClient::constructQueryFilter( m_groupMemberFilterAttribute, computerId, m_computerGroupsFilter ), m_defaultSearchScope ); } @@ -298,20 +293,21 @@ QStringList LdapDirectory::locationsOfComputer( const QString& computerDn ) { return m_client.queryAttributeValues( computerDn, m_computerLocationAttribute ); } - else if( m_computerLocationsByContainer ) + + if( m_computerLocationsByContainer ) { return m_client.queryAttributeValues( LdapClient::parentDn( computerDn ), m_locationNameAttribute ); } const auto computerId = groupMemberComputerIdentification( computerDn ); - if( m_groupMemberAttribute.isEmpty() || computerId.isEmpty() ) + if( m_groupMemberFilterAttribute.isEmpty() || computerId.isEmpty() ) { return {}; } return m_client.queryAttributeValues( computerGroupsDn(), m_locationNameAttribute, - LdapClient::constructQueryFilter( m_groupMemberAttribute, computerId, m_computerGroupsFilter ), + LdapClient::constructQueryFilter( m_groupMemberFilterAttribute, computerId, m_computerGroupsFilter ), m_defaultSearchScope ); } @@ -324,14 +320,6 @@ QString LdapDirectory::userLoginName( const QString& userDn ) -QString LdapDirectory::computerDisplayName( const QString& computerDn ) -{ - return m_client.queryAttributeValues( computerDn, m_computerDisplayNameAttribute ).value( 0 ); - -} - - - QString LdapDirectory::computerHostName( const QString& computerDn ) { if( computerDn.isEmpty() ) @@ -388,7 +376,8 @@ QStringList LdapDirectory::computerLocationEntries( const QString& locationName LdapClient::constructQueryFilter( m_computerLocationAttribute, locationName, m_computersFilter ), m_defaultSearchScope ); } - else if( m_computerLocationsByContainer ) + + if( m_computerLocationsByContainer ) { const auto locationDnFilter = LdapClient::constructQueryFilter( m_locationNameAttribute, locationName, m_computerContainersFilter ); const auto locationDns = m_client.queryDistinguishedNames( computersDn(), locationDnFilter, m_defaultSearchScope ); @@ -398,15 +387,39 @@ QStringList LdapDirectory::computerLocationEntries( const QString& locationName m_defaultSearchScope ); } - auto memberComputers = groupMembers( computerGroups( locationName ).value( 0 ) ); + const auto groups = computerGroups( locationName ); + if( groups.size() != 1 ) + { + vWarning() << "location" << locationName << "does not resolve to exactly one computer group:" << groups; + } + + if( groups.isEmpty() ) + { + return {}; + } + + auto memberComputers = groupMembers( groups.value( 0 ) ); // computer filter configured? if( m_computersFilter.isEmpty() == false ) { + const auto computerHostNames = computersByHostName(); + +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + auto memberComputersSet = QSet( memberComputers.begin(), memberComputers.end() ); + const auto computerHostNameSet = QSet( computerHostNames.begin(), computerHostNames.end() ); +#else auto memberComputersSet = memberComputers.toSet(); + const auto computerHostNameSet = computersByHostName().toSet(); +#endif // then return intersection of filtered computer list and group members - return memberComputersSet.intersect( computersByHostName().toSet() ).toList(); + const auto computerIntersection = memberComputersSet.intersect( computerHostNameSet ); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + return { computerIntersection.begin(), computerIntersection.end() }; +#else + return computerIntersection.toList(); +#endif } return memberComputers; diff --git a/plugins/ldap/common/LdapDirectory.h b/plugins/ldap/common/LdapDirectory.h index 95b95687f..af0bd1254 100644 --- a/plugins/ldap/common/LdapDirectory.h +++ b/plugins/ldap/common/LdapDirectory.h @@ -1,36 +1,17 @@ -/* - * LdapDirectory.h - class representing the LDAP directory and providing access to directory entries - * - * Copyright (c) 2016-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #pragma once #include "LdapClient.h" +#include "LdapCommon.h" #include "VeyonCore.h" class LdapConfiguration; class LdapClient; -class LdapDirectory : public QObject +class LDAP_COMMON_EXPORT LdapDirectory : public QObject { Q_OBJECT public: @@ -71,7 +52,6 @@ class LdapDirectory : public QObject QStringList locationsOfComputer( const QString& computerDn ); QString userLoginName( const QString& userDn ); - QString computerDisplayName( const QString& computerDn ); QString computerHostName( const QString& computerDn ); QString computerMacAddress( const QString& computerDn ); QString groupMemberUserIdentification( const QString& userDn ); @@ -117,6 +97,11 @@ class LdapDirectory : public QObject return m_computerLocationsByContainer; } + bool mapContainerStructureToLocations() const + { + return m_mapContainerStructureToLocations; + } + private: LdapClient::Scope computerSearchScope() const; @@ -132,6 +117,7 @@ class LdapDirectory : public QObject QString m_userLoginNameAttribute; QString m_groupMemberAttribute; + QString m_groupMemberFilterAttribute; QString m_computerDisplayNameAttribute; QString m_computerHostNameAttribute; QString m_computerMacAddressAttribute; @@ -150,4 +136,6 @@ class LdapDirectory : public QObject bool m_computerLocationsByAttribute = false; bool m_computerHostNameAsFQDN = false; + bool m_mapContainerStructureToLocations = false; + }; diff --git a/plugins/ldap/common/LdapNetworkObjectDirectory.cpp b/plugins/ldap/common/LdapNetworkObjectDirectory.cpp index d1636484a..f16dc8ca4 100644 --- a/plugins/ldap/common/LdapNetworkObjectDirectory.cpp +++ b/plugins/ldap/common/LdapNetworkObjectDirectory.cpp @@ -1,48 +1,28 @@ -/* - * LdapNetworkObjectDirectory.cpp - provides a NetworkObjectDirectory for LDAP - * - * Copyright (c) 2017-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #include "LdapConfiguration.h" #include "LdapDirectory.h" #include "LdapNetworkObjectDirectory.h" -LdapNetworkObjectDirectory::LdapNetworkObjectDirectory( const LdapConfiguration& ldapConfiguration, - QObject* parent ) : - NetworkObjectDirectory( parent ), - m_ldapDirectory( ldapConfiguration ) +LdapNetworkObjectDirectory::LdapNetworkObjectDirectory(const LdapConfiguration& ldapConfiguration, + QObject* parent) : + NetworkObjectDirectory(ldapConfiguration.directoryName(), parent), + m_ldapDirectory(ldapConfiguration) { } -NetworkObjectList LdapNetworkObjectDirectory::queryObjects( NetworkObject::Type type, - NetworkObject::Attribute attribute, const QVariant& value ) +NetworkObjectList LdapNetworkObjectDirectory::queryObjects(NetworkObject::Type type, + NetworkObject::Property property, const QVariant& value) { - switch( type ) + switch (type) { - case NetworkObject::Type::Location: return queryLocations( attribute, value ); - case NetworkObject::Type::Host: return queryHosts( attribute, value ); + case NetworkObject::Type::Location: return queryLocations(property, value); + case NetworkObject::Type::Host: return queryHosts(property, value); default: break; } @@ -51,89 +31,138 @@ NetworkObjectList LdapNetworkObjectDirectory::queryObjects( NetworkObject::Type -NetworkObjectList LdapNetworkObjectDirectory::queryParents( const NetworkObject& object ) +NetworkObjectList LdapNetworkObjectDirectory::queryParents(const NetworkObject& object) { - switch( object.type() ) + NetworkObjectList parents; + + if (object.type() == NetworkObject::Type::Host || object.type() == NetworkObject::Type::Location) { - case NetworkObject::Type::Host: - return { NetworkObject( NetworkObject::Type::Location, - m_ldapDirectory.locationsOfComputer( object.directoryAddress() ).value( 0 ) ) }; - case NetworkObject::Type::Location: - return { NetworkObject( NetworkObject::Type::Root ) }; - default: - break; + if (m_ldapDirectory.computerLocationsByContainer()) + { + const auto parentDn = LdapClient::parentDn(object.property(NetworkObject::Property::DirectoryAddress).toString()); + if (parentDn.isEmpty() == false) + { + const NetworkObject parentObject{this, NetworkObject::Type::Location, parentDn, { + { NetworkObject::propertyKey(NetworkObject::Property::DirectoryAddress), parentDn} + }}; + parents.append(parentObject); + + // computer tree root DN not yet reached? + if (QString::compare(parentDn, m_ldapDirectory.computersDn(), Qt::CaseInsensitive) != 0) + { + parents.append(queryParents(parentObject)); + } + } + } + else if (object.type() == NetworkObject::Type::Host) + { + const auto locations = m_ldapDirectory.locationsOfComputer(object.property(NetworkObject::Property::DirectoryAddress).toString()); + const NetworkObject parentObject(this, NetworkObject::Type::Location, locations.value(0)); + parents.append(parentObject); + } } - return { NetworkObject( NetworkObject::Type::None ) }; + return parents; } void LdapNetworkObjectDirectory::update() { - const auto locations = m_ldapDirectory.computerLocations(); - const NetworkObject rootObject( NetworkObject::Type::Root ); + updateObjects(rootObject()); - for( const auto& location : qAsConst( locations ) ) - { - const NetworkObject locationObject( NetworkObject::Type::Location, location ); + setObjectPopulated(rootObject()); +} - addOrUpdateObject( locationObject, rootObject ); - updateLocation( locationObject ); + +void LdapNetworkObjectDirectory::fetchObjects(const NetworkObject& parent) +{ + if (parent.type() == NetworkObject::Type::Root) + { + update(); + } + else if (parent.type() != NetworkObject::Type::Location) + { + setObjectPopulated(parent); } + else + { + updateObjects(parent); - removeObjects( NetworkObject( NetworkObject::Type::Root ), [locations]( const NetworkObject& object ) { - return object.type() == NetworkObject::Type::Location && locations.contains( object.name() ) == false; } ); + setObjectPopulated(parent); + } } -void LdapNetworkObjectDirectory::updateLocation( const NetworkObject& locationObject ) +void LdapNetworkObjectDirectory::updateObjects(const NetworkObject& parent) { - const auto computers = m_ldapDirectory.computerLocationEntries( locationObject.name() ); - - for( const auto& computer : qAsConst( computers ) ) + if (m_ldapDirectory.computerLocationsByContainer() && m_ldapDirectory.mapContainerStructureToLocations()) { - const auto hostObject = computerToObject( &m_ldapDirectory, computer ); - if( hostObject.type() == NetworkObject::Type::Host ) + updateLocations(parent); + updateComputers(parent); + } + else if (parent.type() == NetworkObject::Type::Root) + { + const auto locationNames = m_ldapDirectory.computerLocations(); + + for (const auto& locationName : std::as_const(locationNames)) { - addOrUpdateObject( hostObject, locationObject ); + addOrUpdateObject(NetworkObject{this, NetworkObject::Type::Location, locationName}, parent); } + + removeObjects(parent, [&locationNames](const NetworkObject& object) { + return object.type() == NetworkObject::Type::Location && locationNames.contains(object.name()) == false; }); } + else + { + const auto computerDns = m_ldapDirectory.computerLocationEntries(parent.name()); + + for (const auto& computerDn : std::as_const(computerDns)) + { + const auto hostObject = computerToObject(computerDn); + if (hostObject.type() == NetworkObject::Type::Host) + { + addOrUpdateObject(hostObject, parent); + } + } - removeObjects( locationObject, [computers]( const NetworkObject& object ) { - return object.type() == NetworkObject::Type::Host && computers.contains( object.directoryAddress() ) == false; } ); + removeObjects(parent, [&computerDns](const NetworkObject& object) { + return object.type() == NetworkObject::Type::Host && + computerDns.contains(object.property(NetworkObject::Property::DirectoryAddress).toString()) == false; + }); + } } -NetworkObjectList LdapNetworkObjectDirectory::queryLocations( NetworkObject::Attribute attribute, const QVariant& value ) +NetworkObjectList LdapNetworkObjectDirectory::queryLocations(NetworkObject::Property property, const QVariant& value) { QString name; - switch( attribute ) + switch (property) { - case NetworkObject::Attribute::None: + case NetworkObject::Property::None: break; - case NetworkObject::Attribute::Name: + case NetworkObject::Property::Name: name = value.toString(); break; default: - vCritical() << "Can't query locations by attribute" << attribute; + vCritical() << "Can't query locations by property" << property; return {}; } - const auto locations = m_ldapDirectory.computerLocations( name ); + const auto locations = m_ldapDirectory.computerLocations(name); NetworkObjectList locationObjects; locationObjects.reserve( locations.size() ); - for( const auto& location : locations ) + for (const auto& location : locations) { - locationObjects.append( NetworkObject( NetworkObject::Type::Location, location ) ); + locationObjects.append(NetworkObject{this, NetworkObject::Type::Location, location}); } return locationObjects; @@ -141,37 +170,45 @@ NetworkObjectList LdapNetworkObjectDirectory::queryLocations( NetworkObject::Att -NetworkObjectList LdapNetworkObjectDirectory::queryHosts( NetworkObject::Attribute attribute, const QVariant& value ) +NetworkObjectList LdapNetworkObjectDirectory::queryHosts(NetworkObject::Property property, const QVariant& value) { QStringList computers; - switch( attribute ) + switch (property) { - case NetworkObject::Attribute::None: - computers = m_ldapDirectory.computersByHostName( {} ); + case NetworkObject::Property::None: + computers = m_ldapDirectory.computersByHostName({}); break; - case NetworkObject::Attribute::Name: - computers = m_ldapDirectory.computersByDisplayName( value.toString() ); + case NetworkObject::Property::Name: + computers = m_ldapDirectory.computersByDisplayName(value.toString()); break; - case NetworkObject::Attribute::HostAddress: - computers = m_ldapDirectory.computersByHostName( m_ldapDirectory.hostToLdapFormat( value.toString() ) ); + case NetworkObject::Property::HostAddress: + { + const auto hostName = m_ldapDirectory.hostToLdapFormat(value.toString()); + if (hostName.isEmpty()) + { + return {}; + } + computers = m_ldapDirectory.computersByHostName(hostName); break; + } + default: - vCritical() << "Can't query hosts by attribute" << attribute; + vCritical() << "Can't query hosts by attribute" << property; return {}; } NetworkObjectList hostObjects; - hostObjects.reserve( computers.size() ); + hostObjects.reserve(computers.size()); - for( const auto& computer : computers ) + for (const auto& computer : std::as_const(computers)) { - const auto hostObject = computerToObject( &m_ldapDirectory, computer ); - if( hostObject.isValid() ) + const auto hostObject = computerToObject(computer); + if (hostObject.isValid()) { - hostObjects.append( hostObject ); + hostObjects.append(hostObject); } } @@ -180,42 +217,130 @@ NetworkObjectList LdapNetworkObjectDirectory::queryHosts( NetworkObject::Attribu -NetworkObject LdapNetworkObjectDirectory::computerToObject( LdapDirectory* directory, const QString& computerDn ) +void LdapNetworkObjectDirectory::updateLocations(const NetworkObject& parent) +{ + auto baseDn = parent.property(NetworkObject::Property::DirectoryAddress).toString(); + if (parent.type() == NetworkObject::Type::Root) + { + baseDn = m_ldapDirectory.computersDn(); + } + + const auto locations = m_ldapDirectory.client().queryObjects(baseDn, { m_ldapDirectory.locationNameAttribute() }, + m_ldapDirectory.computerContainersFilter(), LdapClient::Scope::One); + for (auto it = locations.begin(), end = locations.end(); it != end; ++it) + { + for (const auto& locationName : std::as_const(it.value().first())) + { + addOrUpdateObject(NetworkObject{ + this, NetworkObject::Type::Location, locationName, { + { NetworkObject::propertyKey(NetworkObject::Property::DirectoryAddress), it.key()}, + } + }, + parent); + } + } + + const auto locationDNs = locations.keys(); + + removeObjects(parent, [locationDNs](const NetworkObject& object) { + return object.type() == NetworkObject::Type::Location && + locationDNs.contains(object.property(NetworkObject::Property::DirectoryAddress).toString()) == false; }); +} + + + +void LdapNetworkObjectDirectory::updateComputers(const NetworkObject& parent) { - auto displayNameAttribute = directory->computerDisplayNameAttribute(); - if( displayNameAttribute.isEmpty() ) + auto baseDn = parent.property(NetworkObject::Property::DirectoryAddress).toString(); + if (parent.type() == NetworkObject::Type::Root) { - displayNameAttribute = QStringLiteral("cn"); + baseDn = m_ldapDirectory.computersDn(); } - auto hostNameAttribute = directory->computerHostNameAttribute(); - if( hostNameAttribute.isEmpty() ) + const auto displayNameAttribute = m_ldapDirectory.computerDisplayNameAttribute(); + auto hostNameAttribute = m_ldapDirectory.computerHostNameAttribute(); + if (hostNameAttribute.isEmpty()) { - hostNameAttribute = QStringLiteral("cn"); + hostNameAttribute = LdapClient::cn(); } - QStringList computerAttributes{ displayNameAttribute, hostNameAttribute }; + QStringList computerAttributes{displayNameAttribute, hostNameAttribute}; - auto macAddressAttribute = directory->computerMacAddressAttribute(); - if( macAddressAttribute.isEmpty() == false ) + const auto macAddressAttribute = m_ldapDirectory.computerMacAddressAttribute(); + if (macAddressAttribute.isEmpty() == false) { - computerAttributes.append( macAddressAttribute ); + computerAttributes.append(macAddressAttribute); } computerAttributes.removeDuplicates(); - const auto computers = directory->client().queryObjects( computerDn, computerAttributes, - directory->computersFilter(), LdapClient::Scope::Base ); - if( computers.isEmpty() == false ) + const auto computers = m_ldapDirectory.client().queryObjects(baseDn, computerAttributes, + m_ldapDirectory.computersFilter(), LdapClient::Scope::One); + + QStringList computerDns; + + for (auto it = computers.begin(), end = computers.end(); it != end; ++it) + { + const auto displayName = it.value()[displayNameAttribute].value(0); + const auto hostName = it.value()[hostNameAttribute].value(0); + const auto macAddress = (macAddressAttribute.isEmpty() == false) ? it.value()[hostNameAttribute].value(0) : QString(); + + addOrUpdateObject(NetworkObject{this, NetworkObject::Type::Host, displayName, { + { NetworkObject::propertyKey(NetworkObject::Property::HostAddress), hostName}, + { NetworkObject::propertyKey(NetworkObject::Property::MacAddress), macAddress}, + { NetworkObject::propertyKey(NetworkObject::Property::DirectoryAddress), it.key()}, + } + }, + parent); + + computerDns.append(it.key()); + } + + removeObjects(parent, [computerDns](const NetworkObject& object) { + return object.type() == NetworkObject::Type::Host && + computerDns.contains(object.property(NetworkObject::Property::DirectoryAddress).toString()) == false; + }); +} + + + +NetworkObject LdapNetworkObjectDirectory::computerToObject(const QString& computerDn) +{ + const auto displayNameAttribute = m_ldapDirectory.computerDisplayNameAttribute(); + + auto hostNameAttribute = m_ldapDirectory.computerHostNameAttribute(); + if (hostNameAttribute.isEmpty()) + { + hostNameAttribute = LdapClient::cn(); + } + + QStringList computerAttributes{displayNameAttribute, hostNameAttribute}; + + auto macAddressAttribute = m_ldapDirectory.computerMacAddressAttribute(); + if (macAddressAttribute.isEmpty() == false) + { + computerAttributes.append(macAddressAttribute); + } + + computerAttributes.removeDuplicates(); + + const auto computers = m_ldapDirectory.client().queryObjects(computerDn, computerAttributes, + m_ldapDirectory.computersFilter(), LdapClient::Scope::Base); + if (computers.isEmpty() == false) { const auto& computerDn = computers.firstKey(); const auto& computer = computers.first(); - const auto displayName = computer[displayNameAttribute].value( 0 ); - const auto hostName = computer[hostNameAttribute].value( 0 ); - const auto macAddress = ( macAddressAttribute.isEmpty() == false ) ? computer[macAddressAttribute].value( 0 ) : QString(); - - return NetworkObject( NetworkObject::Type::Host, displayName, hostName, macAddress, computerDn ); + const auto displayName = computer[displayNameAttribute].value(0); + const auto hostName = computer[hostNameAttribute].value(0); + const auto macAddress = (macAddressAttribute.isEmpty() == false) ? computer[macAddressAttribute].value(0) : QString(); + + return NetworkObject{this, NetworkObject::Type::Host, displayName, { + { NetworkObject::propertyKey(NetworkObject::Property::HostAddress), hostName}, + { NetworkObject::propertyKey(NetworkObject::Property::MacAddress), macAddress}, + { NetworkObject::propertyKey(NetworkObject::Property::DirectoryAddress), computerDn}, + } + }; } - return NetworkObject( NetworkObject::Type::None ); + return NetworkObject{this, NetworkObject::Type::None}; } diff --git a/plugins/ldap/common/LdapNetworkObjectDirectory.h b/plugins/ldap/common/LdapNetworkObjectDirectory.h index b6bb210dc..00a4cedd3 100644 --- a/plugins/ldap/common/LdapNetworkObjectDirectory.h +++ b/plugins/ldap/common/LdapNetworkObjectDirectory.h @@ -1,50 +1,36 @@ -/* - * LdapNetworkObjectDirectory.h - provides a NetworkObjectDirectory for LDAP - * - * Copyright (c) 2017-2019 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #pragma once #include "LdapDirectory.h" #include "NetworkObjectDirectory.h" -class LdapNetworkObjectDirectory : public NetworkObjectDirectory +class LDAP_COMMON_EXPORT LdapNetworkObjectDirectory : public NetworkObjectDirectory { Q_OBJECT public: - LdapNetworkObjectDirectory( const LdapConfiguration& ldapConfiguration, QObject* parent ); + LdapNetworkObjectDirectory(const LdapConfiguration& ldapConfiguration, QObject* parent); - NetworkObjectList queryObjects( NetworkObject::Type type, - NetworkObject::Attribute attribute, const QVariant& value ) override; - NetworkObjectList queryParents( const NetworkObject& childId ) override; + NetworkObjectList queryObjects(NetworkObject::Type type, + NetworkObject::Property property, const QVariant& value) override; + NetworkObjectList queryParents(const NetworkObject& childId) override; - static NetworkObject computerToObject( LdapDirectory* directory, const QString& computerDn ); + NetworkObject computerToObject(const QString& computerDn); private: void update() override; - void updateLocation( const NetworkObject& locationObject ); + void fetchObjects(const NetworkObject& parent) override; - NetworkObjectList queryLocations( NetworkObject::Attribute attribute, const QVariant& value ); - NetworkObjectList queryHosts( NetworkObject::Attribute attribute, const QVariant& value ); + void updateObjects(const NetworkObject& parent); + + NetworkObjectList queryLocations(NetworkObject::Property property, const QVariant& value); + NetworkObjectList queryHosts(NetworkObject::Property property, const QVariant& value); + + void updateLocations(const NetworkObject& parent); + void updateComputers(const NetworkObject& parent); LdapDirectory m_ldapDirectory; + }; diff --git a/plugins/ldap/common/LdapNetworkObjectDirectoryConfigurationPage.cpp b/plugins/ldap/common/LdapNetworkObjectDirectoryConfigurationPage.cpp new file mode 100644 index 000000000..1bbd7ee73 --- /dev/null +++ b/plugins/ldap/common/LdapNetworkObjectDirectoryConfigurationPage.cpp @@ -0,0 +1,21 @@ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later + +#include "LdapNetworkObjectDirectoryConfigurationPage.h" + +#include "ui_LdapNetworkObjectDirectoryConfigurationPage.h" + +LdapNetworkObjectDirectoryConfigurationPage::LdapNetworkObjectDirectoryConfigurationPage( QWidget* parent ) : + ConfigurationPage( parent ), + ui(new Ui::LdapNetworkObjectDirectoryConfigurationPage) +{ + ui->setupUi(this); +} + + + +LdapNetworkObjectDirectoryConfigurationPage::~LdapNetworkObjectDirectoryConfigurationPage() +{ + delete ui; +} diff --git a/plugins/ldap/common/LdapNetworkObjectDirectoryConfigurationPage.h b/plugins/ldap/common/LdapNetworkObjectDirectoryConfigurationPage.h new file mode 100644 index 000000000..224cd7f84 --- /dev/null +++ b/plugins/ldap/common/LdapNetworkObjectDirectoryConfigurationPage.h @@ -0,0 +1,28 @@ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later + +#pragma once + +#include "ConfigurationPage.h" +#include "LdapCommon.h" + +namespace Ui { +class LdapNetworkObjectDirectoryConfigurationPage; +} + +class LDAP_COMMON_EXPORT LdapNetworkObjectDirectoryConfigurationPage : public ConfigurationPage +{ + Q_OBJECT +public: + explicit LdapNetworkObjectDirectoryConfigurationPage( QWidget* parent = nullptr ); + ~LdapNetworkObjectDirectoryConfigurationPage() override; + + void resetWidgets() override {}; + void connectWidgetsToProperties() override {}; + void applyConfiguration() override {}; + +private: + Ui::LdapNetworkObjectDirectoryConfigurationPage *ui; + +}; diff --git a/plugins/ldap/common/LdapNetworkObjectDirectoryConfigurationPage.ui b/plugins/ldap/common/LdapNetworkObjectDirectoryConfigurationPage.ui new file mode 100644 index 000000000..4504f2a4d --- /dev/null +++ b/plugins/ldap/common/LdapNetworkObjectDirectoryConfigurationPage.ui @@ -0,0 +1,32 @@ + + + LdapNetworkObjectDirectoryConfigurationPage + + + LDAP + + + + 0 + + + 0 + + + + + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + + diff --git a/plugins/ldap/kldap/CMakeLists.txt b/plugins/ldap/kldap/CMakeLists.txt index cb313d7f2..4527e06b0 100644 --- a/plugins/ldap/kldap/CMakeLists.txt +++ b/plugins/ldap/kldap/CMakeLists.txt @@ -1,26 +1,31 @@ -INCLUDE(BuildPlugin) +include(BuildVeyonPlugin) # libraries and functions for LDAP support -FIND_PACKAGE(Ldap REQUIRED) -FIND_PACKAGE(Sasl2 REQUIRED) +find_package(Ldap REQUIRED) +find_package(Sasl2 REQUIRED) -SET(CMAKE_REQUIRED_INCLUDES lber.h ldap.h) -SET(CMAKE_REQUIRED_LIBRARIES ${Ldap_LIBRARIES} ${Sasl2_LIBRARIES} ${OPENSSL_LIBRARIES}) -CHECK_FUNCTION_EXISTS(ldap_start_tls_s HAVE_LDAP_START_TLS_S) -CHECK_FUNCTION_EXISTS(ldap_initialize HAVE_LDAP_INITIALIZE) -CHECK_FUNCTION_EXISTS(ber_memfree HAVE_BER_MEMFREE) -CHECK_FUNCTION_EXISTS(ldap_unbind_ext HAVE_LDAP_UNBIND_EXT) -CHECK_FUNCTION_EXISTS(ldap_extended_operation HAVE_LDAP_EXTENDED_OPERATION) -CHECK_FUNCTION_EXISTS(ldap_extended_operation_s HAVE_LDAP_EXTENDED_OPERATION_S) +set(CMAKE_REQUIRED_INCLUDES lber.h ldap.h) +set(CMAKE_REQUIRED_LIBRARIES ${Ldap_LIBRARIES} ${Sasl2_LIBRARIES} ${OPENSSL_LIBRARIES}) +check_function_exists(ldap_start_tls_s HAVE_LDAP_START_TLS_S) +check_function_exists(ldap_initialize HAVE_LDAP_INITIALIZE) +check_function_exists(ber_memfree HAVE_BER_MEMFREE) +check_function_exists(ldap_unbind_ext HAVE_LDAP_UNBIND_EXT) +check_function_exists(ldap_extended_operation HAVE_LDAP_EXTENDED_OPERATION) +check_function_exists(ldap_extended_operation_s HAVE_LDAP_EXTENDED_OPERATION_S) CHECK_SYMBOL_EXISTS(ldap_extended_operation ldap.h HAVE_LDAP_EXTENDED_OPERATION_PROTOTYPE) CHECK_SYMBOL_EXISTS(ldap_extended_operation_s ldap.h HAVE_LDAP_EXTENDED_OPERATION_S_PROTOTYPE) -CHECK_INCLUDE_FILES(ldap.h HAVE_LDAP_H) -SET(LDAP_FOUND TRUE) +check_include_files(ldap.h HAVE_LDAP_H) +set(LDAP_FOUND TRUE) -SET(kldap_SOURCE_DIR ${CMAKE_SOURCE_DIR}/3rdparty/kldap/src) -CONFIGURE_FILE(${kldap_SOURCE_DIR}/kldap_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/kldap_config.h) +if(NOT WITH_QT6) + set(kldap_SOURCE_DIR ${CMAKE_SOURCE_DIR}/3rdparty/kldap-qt-compat/src/core) + configure_file(${kldap_SOURCE_DIR}/../kldap_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/kldap_config.h) +else() + set(kldap_SOURCE_DIR ${CMAKE_SOURCE_DIR}/3rdparty/kldap/src/core) + configure_file(${kldap_SOURCE_DIR}/kldap_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/kldap_config.h) +endif() -SET(kldap_SOURCES +set(kldap_SOURCES ${kldap_SOURCE_DIR}/ber.cpp ${kldap_SOURCE_DIR}/ldif.cpp ${kldap_SOURCE_DIR}/ldapurl.cpp @@ -31,13 +36,14 @@ SET(kldap_SOURCES ${kldap_SOURCE_DIR}/ldapcontrol.cpp ${kldap_SOURCE_DIR}/ldapdn.cpp ${CMAKE_CURRENT_SOURCE_DIR}/KLdapIntegration.cpp -) - -ADD_LIBRARY(kldap-light SHARED ${kldap_SOURCES}) -TARGET_LINK_LIBRARIES(kldap-light Qt5::Core ${Ldap_LIBRARIES} ${Sasl2_LIBRARIES}) -TARGET_INCLUDE_DIRECTORIES(kldap-light PRIVATE ${Ldap_INCLUDE_DIRS}) -TARGET_INCLUDE_DIRECTORIES(kldap-light PUBLIC ${kldap_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) -SET_TARGET_PROPERTIES(kldap-light PROPERTIES LINK_FLAGS "-Wl,-no-undefined") -INSTALL(TARGETS kldap-light DESTINATION ${VEYON_LIB_DIR}) -COTIRE_VEYON(kldap-light) + ) +add_library(kldap-light SHARED ${kldap_SOURCES}) +target_link_libraries(kldap-light PRIVATE Qt${QT_MAJOR_VERSION}::Core) +target_link_libraries(kldap-light PUBLIC ${Ldap_LIBRARIES} ${Sasl2_LIBRARIES}) +target_include_directories(kldap-light PRIVATE ${Ldap_INCLUDE_DIRS}) +target_include_directories(kldap-light PUBLIC ${kldap_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) +set_default_target_properties(kldap-light) +if(NOT WITH_CORE_ONLY) + install(TARGETS kldap-light DESTINATION ${VEYON_LIB_DIR}) +endif() diff --git a/plugins/ldap/kldap/KLdapIntegration.cpp b/plugins/ldap/kldap/KLdapIntegration.cpp index a53a5f274..f0afdbfd0 100644 --- a/plugins/ldap/kldap/KLdapIntegration.cpp +++ b/plugins/ldap/kldap/KLdapIntegration.cpp @@ -1,27 +1,9 @@ -/* - * KLdapIntegration.cpp - definition of logging category for kldap - * - * Copyright (c) 2016 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2016-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later +#include "ldap_core_debug.h" #include "ldap_debug.h" +Q_LOGGING_CATEGORY(LDAP_CORE_LOG, "KLDAP"); Q_LOGGING_CATEGORY(LDAP_LOG, "KLDAP"); diff --git a/plugins/ldap/kldap/kldap_core_export.h b/plugins/ldap/kldap/kldap_core_export.h new file mode 100644 index 000000000..2754058d8 --- /dev/null +++ b/plugins/ldap/kldap/kldap_core_export.h @@ -0,0 +1,8 @@ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later + +#pragma once + +#define KLDAP_CORE_EXPORT __attribute__((visibility("default"))) +#define KLDAP_CORE_NO_EXPORT __attribute__((visibility("hidden"))) diff --git a/plugins/ldap/kldap/kldap_export.h b/plugins/ldap/kldap/kldap_export.h index d2461aa2e..1f27b1a70 100644 --- a/plugins/ldap/kldap/kldap_export.h +++ b/plugins/ldap/kldap/kldap_export.h @@ -1,28 +1,8 @@ -/* - * kldap_export.h - definition of symbol visibility macros for kldap - * - * Copyright (c) 2016 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #pragma once -#define KLDAP_EXPORT +#define KLDAP_EXPORT __attribute__((visibility("default"))) #define KLDAP_NO_EXPORT __attribute__((visibility("hidden"))) diff --git a/plugins/ldap/kldap/klocalizedstring.h b/plugins/ldap/kldap/klocalizedstring.h index 82d5afdf0..e0ca23143 100644 --- a/plugins/ldap/kldap/klocalizedstring.h +++ b/plugins/ldap/kldap/klocalizedstring.h @@ -1,26 +1,6 @@ -/* - * klocalizedstring.h - dummy replacements for i18n() functions of KDE - * - * Copyright (c) 2016 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #pragma once diff --git a/plugins/ldap/kldap/ldap_core_debug.h b/plugins/ldap/kldap/ldap_core_debug.h new file mode 100644 index 000000000..9d7a93c6c --- /dev/null +++ b/plugins/ldap/kldap/ldap_core_debug.h @@ -0,0 +1,11 @@ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later + +#pragma once + +#include +#include + +Q_DECLARE_LOGGING_CATEGORY(LDAP_CORE_LOG); + diff --git a/plugins/ldap/kldap/ldap_debug.h b/plugins/ldap/kldap/ldap_debug.h index e9b28e891..83d17c201 100644 --- a/plugins/ldap/kldap/ldap_debug.h +++ b/plugins/ldap/kldap/ldap_debug.h @@ -1,26 +1,6 @@ -/* - * ldap_debug.h - declaration of logging category for kldap - * - * Copyright (c) 2016 Tobias Junghans - * - * This file is part of Veyon - https://veyon.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program 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 (see COPYING); if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ +// Copyright (c) 2019-2025 Tobias Junghans +// This file is part of Veyon - https://veyon.io +// SPDX-License-Identifier: LGPL-2.0-or-later #pragma once @@ -28,4 +8,3 @@ #include Q_DECLARE_LOGGING_CATEGORY(LDAP_LOG); - diff --git a/plugins/platform/CMakeLists.txt b/plugins/platform/CMakeLists.txt index 3500ea400..b4458a780 100644 --- a/plugins/platform/CMakeLists.txt +++ b/plugins/platform/CMakeLists.txt @@ -1,7 +1,7 @@ -IF(VEYON_BUILD_WIN32) -ADD_SUBDIRECTORY(windows) -ENDIF() +if(VEYON_BUILD_WINDOWS) + add_subdirectory(windows) +endif() -IF(VEYON_BUILD_LINUX) -ADD_SUBDIRECTORY(linux) -ENDIF() +if(VEYON_BUILD_LINUX) + add_subdirectory(linux) +endif() diff --git a/plugins/platform/common/LogonHelper.cpp b/plugins/platform/common/LogonHelper.cpp new file mode 100644 index 000000000..639e9e2b2 --- /dev/null +++ b/plugins/platform/common/LogonHelper.cpp @@ -0,0 +1,70 @@ +/* + * LogonHelper.cpp - implementation of LogonHelper class + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "LogonHelper.h" +#include "PersistentLogonCredentials.h" +#include "PlatformPluginInterface.h" +#include "PlatformUserFunctions.h" +#include "ServiceDataManager.h" + + +LogonHelper::LogonHelper( QObject* parent ) : + QObject( parent ) +{ + connect( VeyonCore::instance(), &VeyonCore::applicationLoaded, + this, &LogonHelper::checkPendingLogonTasks ); +} + + + +bool LogonHelper::prepare( const QString& username, const Password& password ) +{ + if( VeyonCore::platform().userFunctions().isAnyUserLoggedInLocally() ) + { + vInfo() << "Skipping user logon as a user is already logged on"; + return false; + } + + return PersistentLogonCredentials::write( username, password ); +} + + + +void LogonHelper::checkPendingLogonTasks() +{ + if( VeyonCore::component() == VeyonCore::Component::Server && + ServiceDataManager::serviceDataTokenFromEnvironment().isEmpty() == false && + VeyonCore::platform().userFunctions().isAnyUserLoggedInLocally() == false ) + { + vDebug() << "Reading logon credentials"; + QString username; + Password password; + if( PersistentLogonCredentials::read( &username, &password ) ) + { + PersistentLogonCredentials::clear(); + + VeyonCore::platform().userFunctions().performLogon( username, password ); + } + } +} diff --git a/plugins/platform/common/LogonHelper.h b/plugins/platform/common/LogonHelper.h new file mode 100644 index 000000000..c8a5add34 --- /dev/null +++ b/plugins/platform/common/LogonHelper.h @@ -0,0 +1,44 @@ +/* + * LogonHelper.h - declaration of LogonHelper class + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "CryptoCore.h" + +// clazy:exclude=copyable-polymorphic + +class LogonHelper : public QObject +{ + Q_OBJECT +public: + using Password = CryptoCore::SecureArray; + + LogonHelper( QObject* parent = nullptr ); + + bool prepare( const QString& username, const Password& password ); + +private: + void checkPendingLogonTasks(); + +}; diff --git a/plugins/platform/common/PersistentLogonCredentials.cpp b/plugins/platform/common/PersistentLogonCredentials.cpp new file mode 100644 index 000000000..1894a45fa --- /dev/null +++ b/plugins/platform/common/PersistentLogonCredentials.cpp @@ -0,0 +1,92 @@ +/* + * PersistentLogonCredentials.cpp - implementation of PersistentLogonCredentials class + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include + +#include "PersistentLogonCredentials.h" +#include "ServiceDataManager.h" +#include "VariantStream.h" + + +bool PersistentLogonCredentials::read( QString* username, Password* password ) +{ + if( username == nullptr || password == nullptr ) + { + vCritical() << "Invalid input pointers"; + return false; + } + + auto logonData = ServiceDataManager::read( ServiceDataManager::serviceDataTokenFromEnvironment() ); + if( logonData.isEmpty() ) + { + vCritical() << "Empty data"; + return false; + } + + QBuffer logonDataBuffer( &logonData ); + if( logonDataBuffer.open( QBuffer::ReadOnly ) == false ) + { + vCritical() << "Failed to open buffer"; + return false; + } + + VariantStream stream( &logonDataBuffer ); + *username = stream.read().toString(); + *password = VeyonCore::cryptoCore().decryptPassword( stream.read().toString() ); + + return username->isEmpty() == false && password->isEmpty() == false; +} + + + +bool PersistentLogonCredentials::write( const QString& username, const Password& password ) +{ + QBuffer logonDataBuffer; + if( logonDataBuffer.open( QBuffer::WriteOnly ) == false ) + { + vCritical() << "Failed to open buffer"; + return false; + } + + VariantStream stream( &logonDataBuffer ); + stream.write( username ); + stream.write( VeyonCore::cryptoCore().encryptPassword( password ) ); + + if( ServiceDataManager::write( ServiceDataManager::serviceDataTokenFromEnvironment(), + logonDataBuffer.data() ) == false ) + { + vCritical() << "Failed to write persistent service data"; + return false; + } + + return true; +} + + + +bool PersistentLogonCredentials::clear() +{ + return ServiceDataManager::write( ServiceDataManager::serviceDataTokenFromEnvironment(), {} ); +} + diff --git a/plugins/platform/common/PersistentLogonCredentials.h b/plugins/platform/common/PersistentLogonCredentials.h new file mode 100644 index 000000000..f2198d2b0 --- /dev/null +++ b/plugins/platform/common/PersistentLogonCredentials.h @@ -0,0 +1,40 @@ +/* + * PersistentLogonCredentials.h - declaration of PersistentLogonCredentials class + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "CryptoCore.h" + +// clazy:exclude=copyable-polymorphic + +class PersistentLogonCredentials +{ +public: + using Password = CryptoCore::SecureArray; + + static bool read( QString* username, Password* password ); + static bool write( const QString& username, const Password& password ); + static bool clear(); + +}; diff --git a/plugins/platform/common/PlatformSessionManager.cpp b/plugins/platform/common/PlatformSessionManager.cpp new file mode 100644 index 000000000..b7ce11b17 --- /dev/null +++ b/plugins/platform/common/PlatformSessionManager.cpp @@ -0,0 +1,168 @@ +/* + * PlatformSessionManager.cpp - implementation of PlatformSessionManager class + * + * Copyright (c) 2018-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include +#include + +#include "PlatformSessionManager.h" +#include "VariantArrayMessage.h" +#include "VeyonConfiguration.h" + + +PlatformSessionManager::PlatformSessionManager( QObject* parent ) : + QThread( parent ), + m_mode( VeyonCore::config().multiSessionModeEnabled() ? Mode::Multi : + VeyonCore::config().activeSessionModeEnabled() ? + Mode::Active : + Mode::Local + ), + m_maximumSessionCount( VeyonCore::config().maximumSessionCount() ) +{ + vDebug(); + + start(); +} + + + +PlatformSessionManager::~PlatformSessionManager() +{ + vDebug(); + + quit(); + wait(); +} + + + +void PlatformSessionManager::run() +{ + if( mode() == Mode::Multi ) + { + auto server = new QLocalServer; + server->setSocketOptions( QLocalServer::WorldAccessOption ); + server->listen( serverName() ); + + connect( server, &QLocalServer::newConnection, server, [this, server]() { + auto connection = server->nextPendingConnection(); + connect( connection, &QLocalSocket::disconnected, connection, &QLocalSocket::deleteLater ); + + m_mutex.lock(); + VariantArrayMessage(connection).write( m_sessions ).send(); + m_mutex.unlock(); + + connection->flush(); + connection->disconnectFromServer(); + } ); + } + + QThread::run(); +} + +PlatformSessionManager::SessionId PlatformSessionManager::openSession( const PlatformSessionId& platformSessionId ) +{ + QMutexLocker l( &m_mutex ); + + const auto sessionIds = m_sessions.values(); + + for( SessionId i = 0; i < m_maximumSessionCount; ++i ) + { + if( sessionIds.contains( i ) == false ) + { + vDebug() << "Opening session" << i << "for platform session" << platformSessionId; + m_sessions[platformSessionId] = i; + + return i; + } + } + + vWarning() << "Failed to allocate session for platform session" << platformSessionId; + + return PlatformSessionFunctions::InvalidSessionId; +} + + + +void PlatformSessionManager::closeSession( const PlatformSessionId& platformSessionId ) +{ + QMutexLocker l( &m_mutex ); + + const auto closedSessionId = m_sessions.take( platformSessionId ).toInt(); + + vDebug() << "Closing session" << closedSessionId << "for platform session" << platformSessionId; +} + + + +PlatformSessionManager::SessionId PlatformSessionManager::resolveSessionId( const PlatformSessionId& platformSessionId ) +{ + if( VeyonCore::component() == VeyonCore::Component::Service ) + { + return PlatformSessionFunctions::DefaultSessionId; + } + + QLocalSocket socket; + socket.connectToServer( serverName(), QLocalSocket::ReadOnly ); + if( socket.waitForConnected( ServerConnectTimeout ) == false ) + { + if( VeyonCore::component() != VeyonCore::Component::CLI && + VeyonCore::component() != VeyonCore::Component::Configurator ) + { + vCritical() << "could not read session map"; + } + + return PlatformSessionFunctions::InvalidSessionId; + } + + if( waitForMessage( &socket ) ) + { + VariantArrayMessage message( &socket ); + message.receive(); + return message.read().toMap().value( platformSessionId, PlatformSessionFunctions::InvalidSessionId ).toInt(); + } + + vCritical() << "could not receive session map"; + + return PlatformSessionFunctions::InvalidSessionId; +} + + + +bool PlatformSessionManager::waitForMessage(QLocalSocket* socket) +{ + // wait for acknowledge + QElapsedTimer messageTimeoutTimer; + messageTimeoutTimer.start(); + + VariantArrayMessage inMessage( socket ); + while( messageTimeoutTimer.elapsed() < MessageReadTimeout && + inMessage.isReadyForReceive() == false ) + { + socket->waitForReadyRead( SocketWaitTimeout ); + } + + return inMessage.isReadyForReceive(); +} diff --git a/plugins/platform/common/PlatformSessionManager.h b/plugins/platform/common/PlatformSessionManager.h new file mode 100644 index 000000000..dd7db10fc --- /dev/null +++ b/plugins/platform/common/PlatformSessionManager.h @@ -0,0 +1,92 @@ +/* + * PlatformSessionManager.h - declaration of PlatformSessionManager class + * + * Copyright (c) 2018-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include +#include + +#include "PlatformSessionFunctions.h" + +class QLocalSocket; + +// clazy:excludeall=copyable-polymorphic + +class PlatformSessionManager : public QThread +{ + Q_OBJECT +public: + enum class Mode + { + Local, + Active, + Multi + }; + Q_ENUM(Mode) + + using SessionId = PlatformSessionFunctions::SessionId; + using PlatformSessionId = QString; + + PlatformSessionManager( QObject* parent = nullptr ); + ~PlatformSessionManager() override; + + SessionId openSession( const PlatformSessionId& platformSessionId ); + void closeSession( const PlatformSessionId& platformSessionId ); + + static SessionId resolveSessionId( const PlatformSessionId& platformSessionId ); + + Mode mode() const + { + return m_mode; + } + + int maximumSessionCount() const + { + return m_maximumSessionCount; + } + + using SessionMap = QMap; + +protected: + void run() override; + +private: + static constexpr auto ServerConnectTimeout = 5000; + static constexpr auto SocketWaitTimeout = 1000; + static constexpr auto MessageReadTimeout = 10000; + + static QString serverName() + { + return QStringLiteral("VeyonSessionManager"); + } + + static bool waitForMessage( QLocalSocket* socket ); + + const Mode m_mode; + const int m_maximumSessionCount; + + QMutex m_mutex; + QVariantMap m_sessions; + +}; diff --git a/plugins/platform/common/ServiceDataManager.cpp b/plugins/platform/common/ServiceDataManager.cpp new file mode 100644 index 000000000..07a74c230 --- /dev/null +++ b/plugins/platform/common/ServiceDataManager.cpp @@ -0,0 +1,206 @@ +/* + * ServiceDataManager.cpp - implementation of ServiceDataManager class + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include +#include + +#include "ServiceDataManager.h" + + +ServiceDataManager::ServiceDataManager( QObject* parent ) : + QThread( parent ), + m_token( CryptoCore::generateChallenge().toHex() ) +{ + vDebug(); + + start(); +} + + + +ServiceDataManager::~ServiceDataManager() +{ + vDebug(); + + quit(); + wait(); +} + + + +QByteArray ServiceDataManager::read( const Token& token ) +{ + QLocalSocket socket; + socket.connectToServer( serverName() ); + if( socket.waitForConnected() == false ) + { + vCritical() << "connection timed out"; + return {}; + } + + VariantArrayMessage outMessage( &socket ); + outMessage.write( token.toByteArray() ); + outMessage.write( static_cast( Command::ReadData ) ); + + sendMessage( &socket, outMessage ); + + if( waitForMessage( &socket ) == false ) + { + vCritical() << "no response"; + return {}; + } + + VariantArrayMessage response( &socket ); + response.receive(); + + return response.read().toByteArray(); +} + + + +bool ServiceDataManager::write( const Token& token, const Data& data ) +{ + QLocalSocket socket; + socket.connectToServer( serverName() ); + + if( socket.waitForConnected() == false ) + { + vCritical() << "connection timed out"; + return false; + } + + VariantArrayMessage outMessage( &socket ); + outMessage.write( token.toByteArray() ); + outMessage.write( static_cast( Command::WriteData ) ); + outMessage.write( data.toByteArray() ); + + sendMessage( &socket, outMessage ); + + return waitForMessage( &socket ); +} + + + +ServiceDataManager::Token ServiceDataManager::serviceDataTokenFromEnvironment() +{ + return QProcessEnvironment::systemEnvironment().value( + QLatin1String( serviceDataTokenEnvironmentVariable() ) ).toUtf8(); +} + + + +void ServiceDataManager::run() +{ + m_server = new QLocalServer; + m_server->setSocketOptions( QLocalServer::UserAccessOption ); + + if( m_server->listen( serverName() ) == false ) + { + vCritical() << "can't listen" << m_server->errorString(); + return; + } + + connect( m_server, &QLocalServer::newConnection, m_server, [this]() { acceptConnection(); } ); + + QThread::run(); +} + + + +bool ServiceDataManager::waitForMessage( QLocalSocket* socket ) +{ + // wait for acknowledge + QElapsedTimer messageTimeoutTimer; + messageTimeoutTimer.start(); + + VariantArrayMessage inMessage( socket ); + while( messageTimeoutTimer.elapsed() < MessageReadTimeout && + inMessage.isReadyForReceive() == false ) + { + socket->waitForReadyRead( SocketWaitTimeout ); + } + + return inMessage.isReadyForReceive(); +} + + + +void ServiceDataManager::sendMessage( QLocalSocket* socket, VariantArrayMessage& message ) +{ + message.send(); + socket->flush(); + socket->waitForBytesWritten(); +} + + + +void ServiceDataManager::acceptConnection() +{ + auto socket = m_server->nextPendingConnection(); + + connect( socket, &QLocalSocket::readyRead, + socket, [this, socket]() { handleConnection( socket ); } ); +} + + + +void ServiceDataManager::handleConnection( QLocalSocket* socket ) +{ + VariantArrayMessage inMessage( socket ); + + if( inMessage.isReadyForReceive() && inMessage.receive() ) + { + const auto token = inMessage.read().toByteArray(); + if( token != m_token.toByteArray() ) + { + vCritical() << "Invalid token"; + socket->close(); + return; + } + + const auto command = static_cast( inMessage.read().toInt() ); + + if( command == Command::WriteData ) + { + m_data = inMessage.read().toByteArray(); + + VariantArrayMessage acknowledge( socket ); + acknowledge.send(); + } + else if( command == Command::ReadData ) + { + VariantArrayMessage response( socket ); + response.write( m_data.toByteArray() ); + response.send(); + } + else + { + vCritical() << "unknown command"; + socket->close(); + } + socket->flush(); + } +} diff --git a/plugins/platform/common/ServiceDataManager.h b/plugins/platform/common/ServiceDataManager.h new file mode 100644 index 000000000..474a23d28 --- /dev/null +++ b/plugins/platform/common/ServiceDataManager.h @@ -0,0 +1,90 @@ +/* + * ServiceDataManager.h - header file for ServiceDataManager class + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +#include "CryptoCore.h" +#include "VariantArrayMessage.h" + +class QLocalServer; +class QLocalSocket; + +class ServiceDataManager : public QThread +{ + Q_OBJECT +public: + enum class Command { + NoCommand, + ReadData, + WriteData, + }; + Q_ENUM(Command) + + using Data = CryptoCore::PlaintextPassword; + using Token = CryptoCore::PlaintextPassword; + + ServiceDataManager( QObject* parent = nullptr ); + ~ServiceDataManager() override; + + const Token& token() const + { + return m_token; + } + + static QByteArray read( const Token& token ); + static bool write( const Token& token, const Data& data ); + + static const char* serviceDataTokenEnvironmentVariable() + { + return "VEYON_SERVICE_DATA_TOKEN"; + } + + static Token serviceDataTokenFromEnvironment(); + +protected: + void run() override; + +private: + static constexpr auto SocketWaitTimeout = 1000; + static constexpr auto MessageReadTimeout = 10000; + + static bool waitForMessage( QLocalSocket* socket ); + static void sendMessage( QLocalSocket* socket, VariantArrayMessage& message ); + + void acceptConnection(); + void handleConnection( QLocalSocket* socket ); + + static QString serverName() + { + return QStringLiteral("VeyonServiceDataManager"); + } + + QLocalServer* m_server{nullptr}; + + Token m_token; + Data m_data; + +}; diff --git a/plugins/platform/linux/CMakeLists.txt b/plugins/platform/linux/CMakeLists.txt index ad797141c..89c9074a2 100644 --- a/plugins/platform/linux/CMakeLists.txt +++ b/plugins/platform/linux/CMakeLists.txt @@ -1,15 +1,42 @@ -ADD_SUBDIRECTORY(auth-helper) +add_subdirectory(auth-helper) -FIND_PACKAGE(X11 REQUIRED) -FIND_PACKAGE(Qt5DBus REQUIRED) -FIND_PACKAGE(PkgConfig QUIET) -pkg_check_modules(procps REQUIRED libprocps) +find_package(X11 REQUIRED) +find_package(PkgConfig QUIET) +pkg_check_modules(procps libproc2) +if(procps_FOUND) + add_definitions(-DHAVE_LIBPROC2) + include(CheckCXXSourceCompiles) + check_cxx_source_compiles("#include + int main() + { + pids_stack* stack = nullptr; + (void) PIDS_VAL(0, s_int, stack); + } + " LIBPROC2_PIDS_VAL_NEW_API) + if (NOT LIBPROC2_PIDS_VAL_NEW_API) + add_definitions(-DLIBPROC2_PIDS_VAL_OLD_API) + endif() +else() + pkg_check_modules(procps libprocps) + if(procps_FOUND) + add_definitions(-DHAVE_LIBPROCPS) + else() + message(FATAL_ERROR "libproc2/libprocps not found") + endif() +endif() -INCLUDE(BuildPlugin) +pkg_check_modules(fakekey libfakekey) -INCLUDE_DIRECTORIES(${procps_INCLUDE_DIRS}) +include(BuildVeyonPlugin) -BUILD_PLUGIN(linux-platform +if(NOT fakekey_FOUND) + set(libfakekey_SOURCES ${libfakekey_DIR}/src/libfakekey.c) + set_source_files_properties(${libfakekey_SOURCES} PROPERTIES + COMPILE_FLAGS "-Wno-deprecated-declarations -Wno-pointer-sign" + SKIP_PRECOMPILE_HEADERS TRUE) +endif() + +build_veyon_plugin(linux-platform LinuxPlatformPlugin.cpp LinuxCoreFunctions.cpp LinuxPlatformConfigurationPage.h @@ -18,8 +45,10 @@ BUILD_PLUGIN(linux-platform LinuxFilesystemFunctions.cpp LinuxInputDeviceFunctions.cpp LinuxNetworkFunctions.cpp + LinuxServerProcess.cpp LinuxServiceCore.cpp LinuxServiceFunctions.cpp + LinuxSessionFunctions.cpp LinuxUserFunctions.cpp LinuxPlatformPlugin.h LinuxPlatformConfiguration.h @@ -27,16 +56,51 @@ BUILD_PLUGIN(linux-platform LinuxDesktopIntegration.h LinuxFilesystemFunctions.h LinuxInputDeviceFunctions.h + LinuxKeyboardInput.h + LinuxKeyboardInput.cpp LinuxKeyboardShortcutTrapper.h LinuxNetworkFunctions.h + LinuxServerProcess.h LinuxServiceCore.h LinuxServiceFunctions.h + LinuxSessionFunctions.h LinuxUserFunctions.h linux.qrc -) + ../common/LogonHelper.h + ../common/LogonHelper.cpp + ../common/PersistentLogonCredentials.h + ../common/PersistentLogonCredentials.cpp + ../common/PlatformSessionManager.h + ../common/PlatformSessionManager.cpp + ../common/ServiceDataManager.h + ../common/ServiceDataManager.cpp + ${libfakekey_SOURCES} + ) -TARGET_LINK_LIBRARIES(linux-platform - ${X11_LIBRARIES} - Qt5::DBus - ${procps_LDFLAGS} +set_source_files_properties(LinuxCoreFunctions.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION TRUE) + +target_include_directories(linux-platform PRIVATE + ../common + ${libfakekey_DIR} + ${procps_INCLUDE_DIRS} ) + +if(WITH_QT6) + find_package(Qt6 COMPONENTS DBus REQUIRED) +else() + find_package(Qt5DBus REQUIRED) +endif() + +target_link_libraries(linux-platform PRIVATE Qt${QT_MAJOR_VERSION}::DBus) + +target_link_libraries(linux-platform PRIVATE + ${X11_LIBRARIES} + ${procps_LDFLAGS}) + +if(fakekey_FOUND) + target_include_directories(linux-platform PRIVATE ${fakekey_INCLUDE_DIRS}) + target_link_libraries(linux-platform PRIVATE ${fakekey_LDFLAGS}) +else() + target_include_directories(linux-platform PRIVATE ${libfakekey_DIR}) + target_link_libraries(linux-platform PRIVATE ${X11_XTest_LIB}) +endif() diff --git a/plugins/platform/linux/LinuxCoreFunctions.cpp b/plugins/platform/linux/LinuxCoreFunctions.cpp index 5c360c69c..651849946 100644 --- a/plugins/platform/linux/LinuxCoreFunctions.cpp +++ b/plugins/platform/linux/LinuxCoreFunctions.cpp @@ -1,7 +1,7 @@ /* * LinuxCoreFunctions.cpp - implementation of LinuxCoreFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,35 +22,31 @@ * */ +#include +#include #include #include #include +#include #include #include #include +#include +#ifdef HAVE_LIBPROCPS +#include +#endif #include "LinuxCoreFunctions.h" #include "LinuxDesktopIntegration.h" #include "LinuxUserFunctions.h" #include "PlatformUserFunctions.h" +#include "ProcessHelper.h" #include #include -LinuxCoreFunctions::LinuxCoreFunctions() : - m_screenSaverTimeout( 0 ), - m_screenSaverPreferBlanking( 0 ), - m_dpmsEnabled( false ), - m_dpmsStandbyTimeout( 0 ), - m_dpmsSuspendTimeout( 0 ), - m_dpmsOffTimeout( 0 ) -{ -} - - - bool LinuxCoreFunctions::applyConfiguration() { return true; @@ -75,21 +71,18 @@ void LinuxCoreFunctions::writeToNativeLoggingSystem( const QString& message, Log void LinuxCoreFunctions::reboot() { - if( isRunningAsAdmin() ) - { - QProcess::startDetached( QStringLiteral("reboot") ); - } - else + if( systemdLoginManager()->call( QStringLiteral("Reboot"), false ).type() != QDBusMessage::ReplyMessage && + consoleKitManager()->call( QStringLiteral("Restart") ).type() != QDBusMessage::ReplyMessage ) { + prepareSessionBusAccess(); + kdeSessionManager()->asyncCall( QStringLiteral("logout"), - static_cast( LinuxDesktopIntegration::KDE::ShutdownConfirmNo ), - static_cast( LinuxDesktopIntegration::KDE::ShutdownTypeReboot ), - static_cast( LinuxDesktopIntegration::KDE::ShutdownModeForceNow ) ); + LinuxDesktopIntegration::KDE::ShutdownConfirmNo, + LinuxDesktopIntegration::KDE::ShutdownTypeReboot, + LinuxDesktopIntegration::KDE::ShutdownModeForceNow ); gnomeSessionManager()->asyncCall( QStringLiteral("RequestReboot") ); mateSessionManager()->asyncCall( QStringLiteral("RequestReboot") ); xfcePowerManager()->asyncCall( QStringLiteral("Reboot") ); - systemdLoginManager()->asyncCall( QStringLiteral("Reboot") ); - consoleKitManager()->asyncCall( QStringLiteral("Restart") ); } } @@ -99,30 +92,36 @@ void LinuxCoreFunctions::powerDown( bool installUpdates ) { Q_UNUSED(installUpdates) - if( isRunningAsAdmin() ) - { - QProcess::startDetached( QStringLiteral("poweroff") ); - } - else + if( systemdLoginManager()->call( QStringLiteral("PowerOff"), false ).type() != QDBusMessage::ReplyMessage && + consoleKitManager()->call( QStringLiteral("Stop") ).type() != QDBusMessage::ReplyMessage ) { + prepareSessionBusAccess(); + kdeSessionManager()->asyncCall( QStringLiteral("logout"), - static_cast( LinuxDesktopIntegration::KDE::ShutdownConfirmNo ), - static_cast( LinuxDesktopIntegration::KDE::ShutdownTypeHalt ), - static_cast( LinuxDesktopIntegration::KDE::ShutdownModeForceNow ) ); + LinuxDesktopIntegration::KDE::ShutdownConfirmNo, + LinuxDesktopIntegration::KDE::ShutdownTypeHalt, + LinuxDesktopIntegration::KDE::ShutdownModeForceNow ); gnomeSessionManager()->asyncCall( QStringLiteral("RequestShutdown") ); mateSessionManager()->asyncCall( QStringLiteral("RequestShutdown") ); xfcePowerManager()->asyncCall( QStringLiteral("Shutdown") ); - systemdLoginManager()->asyncCall( QStringLiteral("PowerOff") ); - consoleKitManager()->asyncCall( QStringLiteral("Stop") ); } } -void LinuxCoreFunctions::raiseWindow( QWidget* widget ) +void LinuxCoreFunctions::raiseWindow( QWidget* widget, bool stayOnTop ) { widget->activateWindow(); widget->raise(); + + if( stayOnTop ) + { +#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)) + widget->setWindowFlag( Qt::WindowStaysOnTopHint, true ); +#else + widget->setWindowFlags( widget->windowFlags() | Qt::WindowStaysOnTopHint ); +#endif + } } @@ -131,7 +130,8 @@ void LinuxCoreFunctions::disableScreenSaver() auto display = XOpenDisplay( nullptr ); // query and disable screen saver - int interval, allowExposures; + int interval; + int allowExposures; XGetScreenSaver( display, &m_screenSaverTimeout, &interval, &m_screenSaverPreferBlanking, &allowExposures ); XSetScreenSaver( display, 0, interval, 0, allowExposures ); @@ -154,7 +154,7 @@ void LinuxCoreFunctions::disableScreenSaver() DPMSGetTimeouts( display, &m_dpmsStandbyTimeout, &m_dpmsSuspendTimeout, &m_dpmsOffTimeout ); DPMSSetTimeouts( display, 0, 0, 0 ); } - else + else if( qEnvironmentVariableIsSet("XRDP_SESSION") == false ) { vWarning() << "DPMS extension not supported!"; } @@ -170,7 +170,10 @@ void LinuxCoreFunctions::restoreScreenSaverSettings() auto display = XOpenDisplay( nullptr ); // restore screensaver settings - int timeout, interval, preferBlanking, allowExposures; + int timeout; + int interval; + int preferBlanking; + int allowExposures; XGetScreenSaver( display, &timeout, &interval, &preferBlanking, &allowExposures ); XSetScreenSaver( display, m_screenSaverTimeout, interval, m_screenSaverPreferBlanking, allowExposures ); @@ -217,18 +220,6 @@ bool LinuxCoreFunctions::runProgramAsAdmin( const QString& program, const QStrin { const auto commandLine = QStringList( program ) + parameters; - const auto desktop = QProcessEnvironment::systemEnvironment().value( QStringLiteral("XDG_CURRENT_DESKTOP") ); - if( desktop == QLatin1String("KDE") && - QStandardPaths::findExecutable( QStringLiteral("kdesudo") ).isEmpty() == false ) - { - return QProcess::execute( QStringLiteral("kdesudo"), commandLine ) == 0; - } - - if( QStandardPaths::findExecutable( QStringLiteral("gksudo") ).isEmpty() == false ) - { - return QProcess::execute( QStringLiteral("gksudo"), commandLine ) == 0; - } - return QProcess::execute( QStringLiteral("pkexec"), commandLine ) == 0; } @@ -237,37 +228,65 @@ bool LinuxCoreFunctions::runProgramAsAdmin( const QString& program, const QStrin bool LinuxCoreFunctions::runProgramAsUser( const QString& program, const QStringList& parameters, const QString& username, const QString& desktop ) { - Q_UNUSED(desktop); + Q_UNUSED(desktop) + + const auto uid = LinuxUserFunctions::userIdFromName( username ); + if( uid < 0 ) + { + vCritical() << "failed to resolve uid from username" << username; + return false; + } + + const auto gid = LinuxUserFunctions::userGroupIdFromName( username ); + if( gid < 0 ) + { + vCritical() << "failed to resolve gid from username" << username; + return false; + } + + const auto adjustChildProcessPrivileges = [uid, gid]() + { + const auto isRoot = getuid() == 0 || geteuid() == 0; + if (setgroups(0, nullptr) != 0 && isRoot) + { + qFatal( "Could not drop all supplementary groups for child process!" ); + } + if (setgid(gid) != 0 && isRoot) + { + qFatal( "Could not set GID for child process!" ); + } + if (setuid(uid) != 0 && isRoot) + { + qFatal( "Could not set UID for child process!" ); + } + }; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + auto process = new QProcess; + process->setChildProcessModifier(adjustChildProcessPrivileges); +#else class UserProcess : public QProcess // clazy:exclude=missing-qobject-macro { public: - explicit UserProcess( uid_t uid, QObject* parent = nullptr ) : + explicit UserProcess(const std::function& modifier, QObject* parent = nullptr) : QProcess( parent ), - m_uid( uid ) + m_modifier(modifier) { } void setupChildProcess() override { - if( setuid( m_uid ) != 0 ) - { - qFatal( "Could not set UID for child process!" ); - } + m_modifier(); } private: - const uid_t m_uid; + const std::function& m_modifier; }; - const auto uid = LinuxUserFunctions::userIdFromName( username ); - if( uid <= 0 ) - { - return false; - } + auto process = new UserProcess(adjustChildProcessPrivileges); +#endif - auto process = new UserProcess( uid ); - process->connect( process, QOverload::of( &QProcess::finished ), &QProcess::deleteLater ); + QObject::connect( process, QOverload::of( &QProcess::finished ), &QProcess::deleteLater ); process->start( program, parameters ); return true; @@ -282,6 +301,46 @@ QString LinuxCoreFunctions::genericUrlHandler() const +QString LinuxCoreFunctions::queryDisplayDeviceName(const QScreen& screen) const +{ + QStringList nameParts; +#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) + nameParts.append(screen.manufacturer()); + nameParts.append(screen.model()); +#endif + nameParts.removeAll({}); + if(nameParts.isEmpty()) + { + return screen.name(); + } + + return QStringLiteral("%1 [%2]").arg(nameParts.join(QLatin1Char(' ')), screen.name()); +} + + + +bool LinuxCoreFunctions::prepareSessionBusAccess() +{ + const auto uid = LinuxUserFunctions::userIdFromName( VeyonCore::platform().userFunctions().currentUser() ); + if( uid > 0 ) + { + if( seteuid(uid) == 0 ) + { + return true; + } + + vWarning() << "could not set effective UID - DBus calls on the session bus likely will fail"; + } + else + { + vWarning() << "could not determine UID of current user - DBus calls on the session bus likely will fail"; + } + + return false; +} + + + /*! Returns DBus interface for session manager of KDE desktop */ LinuxCoreFunctions::DBusInterfacePointer LinuxCoreFunctions::kdeSessionManager() { @@ -345,3 +404,144 @@ LinuxCoreFunctions::DBusInterfacePointer LinuxCoreFunctions::consoleKitManager() QStringLiteral("org.freedesktop.ConsoleKit.Manager"), QDBusConnection::systemBus() ); } + + + +bool LinuxCoreFunctions::isSystemdManaged() +{ + if (QFile::exists(QStringLiteral("/sbin/systemd")) == false && + QFile::exists(QStringLiteral("/usr/sbin/systemd")) == false && + QFile::exists(QStringLiteral("/lib/systemd/systemd")) == false) + { + return false; + } + + const auto status = ProcessHelper(QStringLiteral("systemctl"), {QStringLiteral("is-system-running")}).runAndReadAll().trimmed(); + return status.isEmpty() == false && status != "offline"; +} + + + +int LinuxCoreFunctions::systemctl( const QStringList& arguments ) +{ + QProcess process; + process.start( QStringLiteral("systemctl"), + QStringList( { QStringLiteral("--no-pager"), QStringLiteral("-q") } ) + arguments ); + + if( process.waitForFinished() && process.exitStatus() == QProcess::NormalExit ) + { + return process.exitCode(); + } + + return -1; +} + + + +void LinuxCoreFunctions::restartDisplayManagers() +{ + for( const auto& displayManager : { + QStringLiteral("gdm"), + QStringLiteral("lightdm"), + QStringLiteral("lxdm"), + QStringLiteral("nodm"), + QStringLiteral("sddm"), + QStringLiteral("wdm"), + QStringLiteral("xdm") } ) + { + systemctl( { QStringLiteral("restart"), displayManager } ); + } +} + + + +#ifdef HAVE_LIBPROCPS +void LinuxCoreFunctions::forEachChildProcess( const std::function& visitor, + int parentPid, int flags, bool visitParent ) +{ + QProcessEnvironment sessionEnv; + + const auto proc = openproc( flags | PROC_FILLSTAT /* required for proc_t::ppid */ ); + proc_t* procInfo = nullptr; + + QList ppids; + + while( ( procInfo = readproc( proc, nullptr ) ) ) + { + if( procInfo->ppid == parentPid ) + { + if( visitParent == false || visitor( procInfo ) ) + { + ppids.append( procInfo->tid ); + } + } + else if( ppids.contains( procInfo->ppid ) && visitor( procInfo ) ) + { + ppids.append( procInfo->tid ); + } + + freeproc( procInfo ); + } + + closeproc( proc ); +} +#elif defined(HAVE_LIBPROC2) +void LinuxCoreFunctions::forEachChildProcess(const std::function& visitor, + int parentPid, const std::vector& items, bool visitParent) +{ + QProcessEnvironment sessionEnv; + + pids_info* info = nullptr; + pids_stack* stack; + QList ppids; + + std::vector allItems{PIDS_ID_PID, PIDS_ID_PPID}; + static constexpr auto PidItemIndex = 0; + static constexpr auto PPidItemIndex = 1; + + allItems.insert(allItems.end(), items.cbegin(), items.cend()); + + if (procps_pids_new(&info, allItems.data(), allItems.size()) < 0) + { + return; + } + + while ((stack = procps_pids_get(info, PIDS_FETCH_TASKS_ONLY))) + { + const auto ppid = PIDS_VAL(PPidItemIndex, s_int, stack); + + if (ppid == parentPid) + { + if (visitParent == false || visitor(stack)) + { + ppids.append(PIDS_VAL(PidItemIndex, s_int, stack)); + } + } + else if (ppids.contains(ppid) && visitor(stack)) + { + ppids.append(PIDS_VAL(PidItemIndex, s_int, stack)); + } + } + + procps_pids_unref(&info); +} +#endif + + +bool LinuxCoreFunctions::waitForProcess( qint64 pid, int timeout, int sleepInterval ) +{ + QElapsedTimer timeoutTimer; + timeoutTimer.start(); + + while( QFileInfo::exists( QStringLiteral("/proc/%1").arg( pid ) ) ) + { + if( timeoutTimer.elapsed() >= timeout ) + { + return false; + } + + QThread::msleep( static_cast( sleepInterval ) ); + } + + return true; +} diff --git a/plugins/platform/linux/LinuxCoreFunctions.h b/plugins/platform/linux/LinuxCoreFunctions.h index 6a7026444..a7d79341c 100644 --- a/plugins/platform/linux/LinuxCoreFunctions.h +++ b/plugins/platform/linux/LinuxCoreFunctions.h @@ -1,7 +1,7 @@ /* * LinuxCoreFunctions.h - declaration of LinuxCoreFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,15 +25,26 @@ #pragma once #include +#include #include "PlatformCoreFunctions.h" +#ifdef HAVE_LIBPROC2 +#include +#ifdef LIBPROC2_PIDS_VAL_OLD_API +#undef PIDS_VAL +#define PIDS_VAL(relative_enum, type, stack) stack->head[relative_enum].result.type +#endif +#else +struct proc_t; +#endif + // clazy:excludeall=copyable-polymorphic class LinuxCoreFunctions : public PlatformCoreFunctions { public: - LinuxCoreFunctions(); + LinuxCoreFunctions() = default; bool applyConfiguration() override; @@ -43,7 +54,7 @@ class LinuxCoreFunctions : public PlatformCoreFunctions void reboot() override; void powerDown( bool installUpdates ) override; - void raiseWindow( QWidget* widget ) override; + void raiseWindow( QWidget* widget, bool stayOnTop ) override; void disableScreenSaver() override; void restoreScreenSaverSettings() override; @@ -61,8 +72,11 @@ class LinuxCoreFunctions : public PlatformCoreFunctions QString genericUrlHandler() const override; + QString queryDisplayDeviceName(const QScreen& screen) const override; + using DBusInterfacePointer = QSharedPointer; + static bool prepareSessionBusAccess(); static DBusInterfacePointer kdeSessionManager(); static DBusInterfacePointer gnomeSessionManager(); static DBusInterfacePointer mateSessionManager(); @@ -70,12 +84,27 @@ class LinuxCoreFunctions : public PlatformCoreFunctions static DBusInterfacePointer systemdLoginManager(); static DBusInterfacePointer consoleKitManager(); + static bool isSystemdManaged(); + static int systemctl( const QStringList& arguments ); + + static void restartDisplayManagers(); + +#ifdef HAVE_LIBPROC2 + static void forEachChildProcess(const std::function& visitor, + int parentPid, const std::vector& items, bool visitParent); +#else + static void forEachChildProcess( const std::function& visitor, + int parentPid, int flags, bool visitParent ); +#endif + + static bool waitForProcess( qint64 pid, int timeout, int sleepInterval ); + private: - int m_screenSaverTimeout; - int m_screenSaverPreferBlanking; - bool m_dpmsEnabled; - unsigned short m_dpmsStandbyTimeout; - unsigned short m_dpmsSuspendTimeout; - unsigned short m_dpmsOffTimeout; + int m_screenSaverTimeout{0}; + int m_screenSaverPreferBlanking{0}; + bool m_dpmsEnabled{false}; + unsigned short m_dpmsStandbyTimeout{0}; + unsigned short m_dpmsSuspendTimeout{0}; + unsigned short m_dpmsOffTimeout{0}; }; diff --git a/plugins/platform/linux/LinuxDesktopIntegration.h b/plugins/platform/linux/LinuxDesktopIntegration.h index a363de213..7cadb2c31 100644 --- a/plugins/platform/linux/LinuxDesktopIntegration.h +++ b/plugins/platform/linux/LinuxDesktopIntegration.h @@ -1,7 +1,7 @@ /* * LinuxDesktopIntegration.h - declaration of LinuxDesktopIntegration class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -29,19 +29,19 @@ class LinuxDesktopIntegration public: class KDE { public: - enum ShutdownConfirm { + enum ShutdownConfirm : int { ShutdownConfirmDefault = -1, ShutdownConfirmNo = 0, ShutdownConfirmYes = 1 }; - enum ShutdownMode { + enum ShutdownMode : int { ShutdownModeDefault = -1, ShutdownModeSchedule = 0, ShutdownModeTryNow = 1, ShutdownModeForceNow = 2, ShutdownModeInteractive = 3 }; - enum ShutdownType { + enum ShutdownType : int { ShutdownTypeDefault = -1, ShutdownTypeNone = 0, ShutdownTypeReboot = 1, @@ -52,7 +52,7 @@ class LinuxDesktopIntegration class Gnome { public: - enum GsmManagerLogoutMode { + enum GsmLogoutMode : uint { GSM_MANAGER_LOGOUT_MODE_NORMAL = 0, GSM_MANAGER_LOGOUT_MODE_NO_CONFIRMATION, GSM_MANAGER_LOGOUT_MODE_FORCE @@ -61,7 +61,7 @@ class LinuxDesktopIntegration class Mate { public: - enum { + enum GsmLogoutMode : uint { GSM_LOGOUT_MODE_NORMAL = 0, GSM_LOGOUT_MODE_NO_CONFIRMATION, GSM_LOGOUT_MODE_FORCE diff --git a/plugins/platform/linux/LinuxFilesystemFunctions.cpp b/plugins/platform/linux/LinuxFilesystemFunctions.cpp index 1efacf3ee..4d02938fa 100644 --- a/plugins/platform/linux/LinuxFilesystemFunctions.cpp +++ b/plugins/platform/linux/LinuxFilesystemFunctions.cpp @@ -1,7 +1,7 @@ /* * LinuxFilesystemFunctions.cpp - implementation of LinuxFilesystemFunctions class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,9 +24,11 @@ #include +#include #include #include #include +#include #include "LinuxFilesystemFunctions.h" @@ -109,3 +111,75 @@ bool LinuxFilesystemFunctions::setFileOwnerGroupPermissions( const QString& file return QFile( filePath ).setPermissions( permissions ); } + + + +bool LinuxFilesystemFunctions::openFileSafely( QFile* file, QIODevice::OpenMode openMode, QFile::Permissions permissions ) +{ + if( file == nullptr ) + { + return false; + } + + int flags = O_NOFOLLOW | O_CLOEXEC; + if( openMode & QFile::ReadOnly ) + { + flags |= O_RDONLY; + } + + if( openMode & QFile::WriteOnly ) + { + flags |= O_WRONLY; + + if( permissions ) + { + flags |= O_CREAT; + } + } + + if( openMode & QFile::Append ) + { + flags |= O_APPEND; + } + else if( openMode & QFile::Truncate ) + { + flags |= O_TRUNC; + } + + int fileMode = + ( permissions.testFlag( QFile::ReadOwner ) || permissions.testFlag( QFile::ReadUser ) ? S_IRUSR : 0 ) | + ( permissions.testFlag( QFile::WriteOwner ) || permissions.testFlag( QFile::WriteUser ) ? S_IWUSR : 0 ) | + ( permissions.testFlag( QFile::ExeOwner ) || permissions.testFlag( QFile::ExeUser ) ? S_IXUSR : 0 ) | + ( permissions.testFlag( QFile::ReadGroup ) ? S_IRGRP : 0 ) | + ( permissions.testFlag( QFile::WriteGroup ) ? S_IWGRP : 0 ) | + ( permissions.testFlag( QFile::ExeGroup ) ? S_IXGRP : 0 ) | + ( permissions.testFlag( QFile::ReadOther ) ? S_IROTH : 0 ) | + ( permissions.testFlag( QFile::WriteOther ) ? S_IWOTH : 0 ) | + ( permissions.testFlag( QFile::ExeOther ) ? S_IXOTH : 0 ); + + int fd = open( file->fileName().toUtf8().constData(), flags, fileMode ); + if( fd == -1 ) + { + return false; + } + + struct stat s{}; + if( fstat(fd, &s) != 0 ) + { + close(fd); + return false; + } + + if( s.st_uid != getuid() ) + { + close(fd); + return false; + } + + if( fileMode ) + { + (void) fchmod( fd, fileMode ); + } + + return file->open( fd, openMode, QFileDevice::AutoCloseHandle ); +} diff --git a/plugins/platform/linux/LinuxFilesystemFunctions.h b/plugins/platform/linux/LinuxFilesystemFunctions.h index 9c1c661ec..2cb424187 100644 --- a/plugins/platform/linux/LinuxFilesystemFunctions.h +++ b/plugins/platform/linux/LinuxFilesystemFunctions.h @@ -1,7 +1,7 @@ /* * LinuxFilesystemFunctions.h - declaration of LinuxFilesystemFunctions class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -39,4 +39,6 @@ class LinuxFilesystemFunctions : public PlatformFilesystemFunctions bool setFileOwnerGroup( const QString& filePath, const QString& ownerGroup ) override; bool setFileOwnerGroupPermissions( const QString& filePath, QFile::Permissions permissions ) override; + bool openFileSafely( QFile* file, QFile::OpenMode openMode, QFile::Permissions permissions ) override; + }; diff --git a/plugins/platform/linux/LinuxInputDeviceFunctions.cpp b/plugins/platform/linux/LinuxInputDeviceFunctions.cpp index 2aef7120a..95e32adb0 100644 --- a/plugins/platform/linux/LinuxInputDeviceFunctions.cpp +++ b/plugins/platform/linux/LinuxInputDeviceFunctions.cpp @@ -1,7 +1,7 @@ /* * LinuxInputDeviceFunctions.cpp - implementation of LinuxInputDeviceFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -29,18 +29,6 @@ #include -LinuxInputDeviceFunctions::LinuxInputDeviceFunctions() : - m_inputDevicesDisabled( false ), - m_origKeyTable( nullptr ), - m_keyCodeMin( 0 ), - m_keyCodeMax( 0 ), - m_keyCodeCount( 0 ), - m_keySymsPerKeyCode( 0 ) -{ -} - - - void LinuxInputDeviceFunctions::enableInputDevices() { if( m_inputDevicesDisabled ) @@ -79,23 +67,20 @@ void LinuxInputDeviceFunctions::setEmptyKeyMapTable() XFree( m_origKeyTable ); } - Display* display = XOpenDisplay( nullptr ); + auto display = XOpenDisplay( nullptr ); XDisplayKeycodes( display, &m_keyCodeMin, &m_keyCodeMax ); m_keyCodeCount = m_keyCodeMax - m_keyCodeMin; - m_origKeyTable = XGetKeyboardMapping( display, static_cast( m_keyCodeMin ), - m_keyCodeCount, &m_keySymsPerKeyCode ); + m_origKeyTable = XGetKeyboardMapping( display, ::KeyCode( m_keyCodeMin ), m_keyCodeCount, &m_keySymsPerKeyCode ); - KeySym* newKeyTable = XGetKeyboardMapping( display, static_cast( m_keyCodeMin ), - m_keyCodeCount, &m_keySymsPerKeyCode ); + auto newKeyTable = XGetKeyboardMapping( display, ::KeyCode( m_keyCodeMin ), m_keyCodeCount, &m_keySymsPerKeyCode ); for( int i = 0; i < m_keyCodeCount * m_keySymsPerKeyCode; i++ ) { newKeyTable[i] = 0; } - XChangeKeyboardMapping( display, m_keyCodeMin, m_keySymsPerKeyCode, - newKeyTable, m_keyCodeCount ); + XChangeKeyboardMapping( display, m_keyCodeMin, m_keySymsPerKeyCode, newKeyTable, m_keyCodeCount ); XFlush( display ); XFree( newKeyTable ); XCloseDisplay( display ); @@ -108,7 +93,7 @@ void LinuxInputDeviceFunctions::restoreKeyMapTable() Display* display = XOpenDisplay( nullptr ); XChangeKeyboardMapping( display, m_keyCodeMin, m_keySymsPerKeyCode, - static_cast( m_origKeyTable ), m_keyCodeCount ); + static_cast<::KeySym *>( m_origKeyTable ), m_keyCodeCount ); XFlush( display ); XCloseDisplay( display ); diff --git a/plugins/platform/linux/LinuxInputDeviceFunctions.h b/plugins/platform/linux/LinuxInputDeviceFunctions.h index 051cd8faf..cae3a5553 100644 --- a/plugins/platform/linux/LinuxInputDeviceFunctions.h +++ b/plugins/platform/linux/LinuxInputDeviceFunctions.h @@ -1,7 +1,7 @@ /* * LinuxInputDeviceFunctions.h - declaration of LinuxInputDeviceFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,7 +31,7 @@ class LinuxInputDeviceFunctions : public PlatformInputDeviceFunctions { public: - LinuxInputDeviceFunctions(); + LinuxInputDeviceFunctions() = default; virtual ~LinuxInputDeviceFunctions() = default; void enableInputDevices() override; @@ -43,11 +43,11 @@ class LinuxInputDeviceFunctions : public PlatformInputDeviceFunctions void setEmptyKeyMapTable(); void restoreKeyMapTable(); - bool m_inputDevicesDisabled; - void* m_origKeyTable; - int m_keyCodeMin; - int m_keyCodeMax; - int m_keyCodeCount; - int m_keySymsPerKeyCode; + bool m_inputDevicesDisabled{false}; + void* m_origKeyTable{nullptr}; + int m_keyCodeMin{0}; + int m_keyCodeMax{0}; + int m_keyCodeCount{0}; + int m_keySymsPerKeyCode{0}; }; diff --git a/plugins/platform/linux/LinuxKeyboardInput.cpp b/plugins/platform/linux/LinuxKeyboardInput.cpp new file mode 100644 index 000000000..6c89737d6 --- /dev/null +++ b/plugins/platform/linux/LinuxKeyboardInput.cpp @@ -0,0 +1,77 @@ +/* + * LinuxKeyboardInput.cpp - implementation of LinuxKeyboardInput class + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "LinuxKeyboardInput.h" + +#include + +#include + + +LinuxKeyboardInput::LinuxKeyboardInput() : + m_display( XOpenDisplay( nullptr ) ), + m_fakeKeyHandle( m_display ? fakekey_init( m_display ) : nullptr ) +{ +} + + + +LinuxKeyboardInput::~LinuxKeyboardInput() +{ + if( m_fakeKeyHandle ) + { + free( m_fakeKeyHandle ); + } + + if( m_display ) + { + XCloseDisplay( m_display ); + } +} + + + +void LinuxKeyboardInput::pressAndReleaseKey( uint32_t keysym ) +{ + fakekey_press_keysym( m_fakeKeyHandle, keysym, 0 ); + fakekey_release( m_fakeKeyHandle ); +} + + + +void LinuxKeyboardInput::pressAndReleaseKey( const QByteArray& utf8Data ) +{ + fakekey_press( m_fakeKeyHandle, reinterpret_cast( utf8Data.constData() ), utf8Data.size(), 0 ); + fakekey_release( m_fakeKeyHandle ); +} + + + +void LinuxKeyboardInput::sendString( const QString& string ) +{ + for( int i = 0; i < string.size(); ++i ) + { + pressAndReleaseKey( string.mid( i, 1 ).toUtf8() ); + } +} diff --git a/plugins/platform/linux/LinuxKeyboardInput.h b/plugins/platform/linux/LinuxKeyboardInput.h new file mode 100644 index 000000000..5936c5681 --- /dev/null +++ b/plugins/platform/linux/LinuxKeyboardInput.h @@ -0,0 +1,50 @@ +/* + * LinuxKeyboardInput.h - declaration of LinuxKeyboardInput class + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +// clazy:excludeall=copyable-polymorphic + +class LinuxKeyboardInput +{ +public: + using FakeKey = struct FakeKey; + using Display = struct _XDisplay; + + LinuxKeyboardInput(); + ~LinuxKeyboardInput(); + + void pressAndReleaseKey( uint32_t keysym ); + + void pressAndReleaseKey( const QByteArray& utf8Data ); + + void sendString( const QString& string ); + +private: + Display* m_display; + FakeKey* m_fakeKeyHandle; + +}; diff --git a/plugins/platform/linux/LinuxKeyboardShortcutTrapper.h b/plugins/platform/linux/LinuxKeyboardShortcutTrapper.h index 54608d593..f0a05720f 100644 --- a/plugins/platform/linux/LinuxKeyboardShortcutTrapper.h +++ b/plugins/platform/linux/LinuxKeyboardShortcutTrapper.h @@ -1,7 +1,7 @@ /* * LinuxKeyboardShortcutTrapper.h - dummy KeyboardShortcutTrapper implementation * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -39,7 +39,7 @@ class LinuxKeyboardShortcutTrapper : public KeyboardShortcutTrapper void setEnabled( bool on ) override { - Q_UNUSED(on); + Q_UNUSED(on) } } ; diff --git a/plugins/platform/linux/LinuxNetworkFunctions.cpp b/plugins/platform/linux/LinuxNetworkFunctions.cpp index 26c1ad6df..7e91da43c 100644 --- a/plugins/platform/linux/LinuxNetworkFunctions.cpp +++ b/plugins/platform/linux/LinuxNetworkFunctions.cpp @@ -1,7 +1,7 @@ /* * LinuxNetworkFunctions.cpp - implementation of LinuxNetworkFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -29,13 +29,23 @@ #include "LinuxNetworkFunctions.h" -bool LinuxNetworkFunctions::ping( const QString& hostAddress ) +LinuxNetworkFunctions::PingResult LinuxNetworkFunctions::ping(const QString& hostAddress) { QProcess pingProcess; - pingProcess.start( QStringLiteral("ping"), { QStringLiteral("-W"), QStringLiteral("1"), QStringLiteral("-c"), QString::number( PingTimeout / 1000 ), hostAddress } ); - pingProcess.waitForFinished( PingProcessTimeout ); + pingProcess.start( QStringLiteral("ping"), { QStringLiteral("-c"), QStringLiteral("1"), QStringLiteral("-w"), QString::number( PingTimeout / 1000 ), hostAddress } ); + if (pingProcess.waitForFinished(PingProcessTimeout)) + { + switch (pingProcess.exitCode()) + { + case 0: return PingResult::ReplyReceived; + case 1: return PingResult::TimedOut; + case 2: return PingResult::NameResolutionFailed; + default: + break; + } + } - return pingProcess.exitCode() == 0; + return PingResult::Unknown; } diff --git a/plugins/platform/linux/LinuxNetworkFunctions.h b/plugins/platform/linux/LinuxNetworkFunctions.h index 999b3715d..d0d41548a 100644 --- a/plugins/platform/linux/LinuxNetworkFunctions.h +++ b/plugins/platform/linux/LinuxNetworkFunctions.h @@ -1,7 +1,7 @@ /* * LinuxNetworkFunctions.h - declaration of LinuxNetworkFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,7 +31,7 @@ class LinuxNetworkFunctions : public PlatformNetworkFunctions { public: - bool ping( const QString& hostAddress ) override; + PingResult ping(const QString& hostAddress) override; bool configureFirewallException( const QString& applicationPath, const QString& description, bool enabled ) override; bool configureSocketKeepalive( Socket socket, bool enabled, int idleTime, int interval, int probes ) override; diff --git a/plugins/platform/linux/LinuxPlatformConfiguration.h b/plugins/platform/linux/LinuxPlatformConfiguration.h index 9301e0472..1ab49d95c 100644 --- a/plugins/platform/linux/LinuxPlatformConfiguration.h +++ b/plugins/platform/linux/LinuxPlatformConfiguration.h @@ -1,7 +1,7 @@ /* * LinuxPlatformConfiguration.h - configuration values for LinuxPlatform plugin * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -28,7 +28,9 @@ #define FOREACH_LINUX_PLATFORM_CONFIG_PROPERTY(OP) \ OP( LinuxPlatformConfiguration, m_configuration, QString, pamServiceName, setPamServiceName, "PamServiceName", "Linux", QString(), Configuration::Property::Flag::Advanced ) \ - OP( LinuxPlatformConfiguration, m_configuration, QString, displayManagerUsers, setDisplayManagerUsers, "DisplayManagerUsers", "Linux", QStringLiteral("gdm,lightdm,sddm,mdm"), Configuration::Property::Flag::Advanced ) \ + OP( LinuxPlatformConfiguration, m_configuration, int, minimumUserSessionLifetime, setMinimumUserSessionLifetime, "MinimumUserSessionLifetime", "Linux", 3, Configuration::Property::Flag::Advanced ) \ + OP( LinuxPlatformConfiguration, m_configuration, QString, userLoginKeySequence, setUserLoginKeySequence, "UserLoginKeySequence", "Linux", QStringLiteral("%username%%password%"), Configuration::Property::Flag::Advanced ) \ +// clazy:excludeall=missing-qobject-macro DECLARE_CONFIG_PROXY(LinuxPlatformConfiguration, FOREACH_LINUX_PLATFORM_CONFIG_PROPERTY) diff --git a/plugins/platform/linux/LinuxPlatformConfigurationPage.cpp b/plugins/platform/linux/LinuxPlatformConfigurationPage.cpp index 19e2b5e49..87daa345e 100644 --- a/plugins/platform/linux/LinuxPlatformConfigurationPage.cpp +++ b/plugins/platform/linux/LinuxPlatformConfigurationPage.cpp @@ -1,7 +1,7 @@ /* * LinuxPlatformConfigurationPage.cpp - page for configuring service application * - * Copyright (c) 2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,7 +31,6 @@ LinuxPlatformConfigurationPage::LinuxPlatformConfigurationPage() : - ConfigurationPage(), ui( new Ui::LinuxPlatformConfigurationPage ), m_configuration( &VeyonCore::config() ) { diff --git a/plugins/platform/linux/LinuxPlatformConfigurationPage.h b/plugins/platform/linux/LinuxPlatformConfigurationPage.h index b76ccddc8..f6f6df1a7 100644 --- a/plugins/platform/linux/LinuxPlatformConfigurationPage.h +++ b/plugins/platform/linux/LinuxPlatformConfigurationPage.h @@ -1,7 +1,7 @@ /* * LinuxPlatformConfigurationPage.h - header for the LinuxPlatformConfigurationPage class * - * Copyright (c) 2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,6 +31,7 @@ namespace Ui { class LinuxPlatformConfigurationPage; } +// clazy:excludeall=ctor-missing-parent-argument class LinuxPlatformConfigurationPage : public ConfigurationPage { Q_OBJECT diff --git a/plugins/platform/linux/LinuxPlatformConfigurationPage.ui b/plugins/platform/linux/LinuxPlatformConfigurationPage.ui index 2c7cb3f6f..d167a9950 100644 --- a/plugins/platform/linux/LinuxPlatformConfigurationPage.ui +++ b/plugins/platform/linux/LinuxPlatformConfigurationPage.ui @@ -42,18 +42,47 @@ - Session management + User sessions - + - Display manager users + Minimum session lifetime before server start - + + + s + + + 1 + + + 60 + + + + + + + + + + User login + + + + + + Login key sequence + + + + + diff --git a/plugins/platform/linux/LinuxPlatformPlugin.cpp b/plugins/platform/linux/LinuxPlatformPlugin.cpp index 8ff5cb343..e85c228e3 100644 --- a/plugins/platform/linux/LinuxPlatformPlugin.cpp +++ b/plugins/platform/linux/LinuxPlatformPlugin.cpp @@ -1,7 +1,7 @@ /* * LinuxPlatformPlugin.cpp - implementation of LinuxPlatformPlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,21 +22,25 @@ * */ +#include +#include + #include "LinuxPlatformPlugin.h" #include "LinuxPlatformConfiguration.h" #include "LinuxPlatformConfigurationPage.h" LinuxPlatformPlugin::LinuxPlatformPlugin( QObject* parent ) : - QObject( parent ), - m_linuxCoreFunctions(), - m_linuxFilesystemFunctions(), - m_linuxInputDeviceFunctions(), - m_linuxNetworkFunctions(), - m_linuxServiceFunctions(), - m_linuxUserFunctions() + QObject( parent ) { // make sure to load global config from default config dirs independent of environment variables qunsetenv( "XDG_CONFIG_DIRS" ); + + // don't abort with SIGPIPE when writing to closed sockets e.g. while shutting down VncConnection + ::signal(SIGPIPE, SIG_IGN); + + ::signal(SIGKILL, abort); + ::signal(SIGBUS, abort); + ::signal(SIGSEGV, abort); } @@ -54,4 +58,41 @@ ConfigurationPage* LinuxPlatformPlugin::createConfigurationPage() } + +void LinuxPlatformPlugin::abort(int signal) +{ + qInstallMessageHandler(nullptr); + + vCritical() << "Received signal" << signal; + + qCritical().noquote() << formattedBacktraceString(); + + qFatal("Aborting due to severe error"); + ::abort(); +} + + + +QString LinuxPlatformPlugin::formattedBacktraceString() +{ + static constexpr int BackTraceMaxDepth = 20; + + void* stackFrame[BackTraceMaxDepth + 1]; + const auto frameCount = backtrace(stackFrame, BackTraceMaxDepth + 1); + + char** humanReadableFrames = backtrace_symbols(stackFrame, frameCount); + + QStringList list{QLatin1String("BACKTRACE:")}; + list.reserve(frameCount); + for (int i = 1; i < frameCount; i++) + { + list.append(QStringLiteral("\t %1").arg( QLatin1String(humanReadableFrames[i]))); + } + + free(humanReadableFrames); + + return list.join(QLatin1String("\n")); +} + + IMPLEMENT_CONFIG_PROXY(LinuxPlatformConfiguration) diff --git a/plugins/platform/linux/LinuxPlatformPlugin.h b/plugins/platform/linux/LinuxPlatformPlugin.h index 7e95f57cf..14b6daf84 100644 --- a/plugins/platform/linux/LinuxPlatformPlugin.h +++ b/plugins/platform/linux/LinuxPlatformPlugin.h @@ -1,7 +1,7 @@ /* * LinuxPlatformPlugin.h - declaration of LinuxPlatformPlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -32,6 +32,7 @@ #include "LinuxInputDeviceFunctions.h" #include "LinuxNetworkFunctions.h" #include "LinuxServiceFunctions.h" +#include "LinuxSessionFunctions.h" #include "LinuxUserFunctions.h" class LinuxPlatformPlugin : public QObject, PlatformPluginInterface, PluginInterface, ConfigurationPagePluginInterface @@ -45,7 +46,7 @@ class LinuxPlatformPlugin : public QObject, PlatformPluginInterface, PluginInter Plugin::Uid uid() const override { - return QStringLiteral("63928a8a-4c51-4bfd-888e-9e13c6f3907a"); + return Plugin::Uid{ QStringLiteral("63928a8a-4c51-4bfd-888e-9e13c6f3907a") }; } QVersionNumber version() const override @@ -103,6 +104,11 @@ class LinuxPlatformPlugin : public QObject, PlatformPluginInterface, PluginInter return m_linuxServiceFunctions; } + PlatformSessionFunctions& sessionFunctions() override + { + return m_linuxSessionFunctions; + } + PlatformUserFunctions& userFunctions() override { return m_linuxUserFunctions; @@ -110,12 +116,16 @@ class LinuxPlatformPlugin : public QObject, PlatformPluginInterface, PluginInter ConfigurationPage* createConfigurationPage() override; + static void abort(int signal); + static QString formattedBacktraceString(); + private: - LinuxCoreFunctions m_linuxCoreFunctions; - LinuxFilesystemFunctions m_linuxFilesystemFunctions; - LinuxInputDeviceFunctions m_linuxInputDeviceFunctions; - LinuxNetworkFunctions m_linuxNetworkFunctions; - LinuxServiceFunctions m_linuxServiceFunctions; - LinuxUserFunctions m_linuxUserFunctions; + LinuxCoreFunctions m_linuxCoreFunctions{}; + LinuxFilesystemFunctions m_linuxFilesystemFunctions{}; + LinuxInputDeviceFunctions m_linuxInputDeviceFunctions{}; + LinuxNetworkFunctions m_linuxNetworkFunctions{}; + LinuxServiceFunctions m_linuxServiceFunctions{}; + LinuxSessionFunctions m_linuxSessionFunctions{}; + LinuxUserFunctions m_linuxUserFunctions{}; }; diff --git a/plugins/platform/linux/LinuxServerProcess.cpp b/plugins/platform/linux/LinuxServerProcess.cpp new file mode 100644 index 000000000..bc4030f69 --- /dev/null +++ b/plugins/platform/linux/LinuxServerProcess.cpp @@ -0,0 +1,144 @@ +/* + * LinuxServiceFunctions.cpp - implementation of LinuxServerProcess class + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include + +#include +#ifdef HAVE_LIBPROCPS +#include +#endif +#include +#include +#include + +#include "Filesystem.h" +#include "LinuxCoreFunctions.h" +#include "LinuxServerProcess.h" +#include "VeyonConfiguration.h" + + +LinuxServerProcess::LinuxServerProcess( const QProcessEnvironment& processEnvironment, + const QString& sessionPath, int sessionId, QObject* parent ) : + QProcess( parent ), + m_sessionPath( sessionPath ), + m_sessionId( sessionId ) +{ + setProcessEnvironment( processEnvironment ); +} + + + +LinuxServerProcess::~LinuxServerProcess() +{ + stop(); +} + + + +void LinuxServerProcess::start() +{ + if( VeyonCore::config().logToSystem() ) + { + setProcessChannelMode( QProcess::ForwardedChannels ); + } + + const auto catchsegv{ QStringLiteral("/usr/bin/catchsegv") }; + if( qEnvironmentVariableIsSet("VEYON_VALGRIND_SERVERS") ) + { + QProcess::start( QStringLiteral("/usr/bin/valgrind"), + { QStringLiteral("--error-limit=no"), + QStringLiteral("--log-file=valgrind-veyon-server-%1.log").arg(m_sessionId), + VeyonCore::filesystem().serverFilePath() } ); + } + else if( VeyonCore::isDebugging() && QFileInfo::exists( catchsegv ) ) + { + QProcess::start( catchsegv, { VeyonCore::filesystem().serverFilePath() } ); + } + else + { + QProcess::start( VeyonCore::filesystem().serverFilePath(), QStringList{} ); + } +} + + + +void LinuxServerProcess::stop() +{ + const auto sendSignalRecursively = []( pid_t pid, int sig ) { + if( pid > 0 ) + { +#ifdef HAVE_LIBPROCPS + LinuxCoreFunctions::forEachChildProcess( + [=]( proc_t* procInfo ) { + if( procInfo->tid > 0 && ::kill( procInfo->tid, sig ) < 0 && errno != ESRCH ) + { + vCritical() << "kill() failed with" << errno; + } + return true; + }, + pid, 0, true ); +#elif defined(HAVE_LIBPROC2) + LinuxCoreFunctions::forEachChildProcess([=](const pids_stack* stack) + { + const pid_t tid = PIDS_VAL(0, s_int, stack); + if (tid > 0 && ::kill(tid, sig) < 0 && errno != ESRCH) + { + vCritical() << "kill() failed with" << errno; + } + return true; + }, + pid, + {}, true); +#endif + + if( ::kill( pid, sig ) < 0 && errno != ESRCH ) + { + vCritical() << "kill() failed with" << errno; + } + + // clean up process + waitpid( pid, nullptr, WNOHANG ); + } + }; + + const auto pid = pid_t(processId()); + + // manually set process state since we're managing the process termination on our own + setProcessState( QProcess::NotRunning ); + + // tell x11vnc and child processes (in case spawned via catchsegv) to shutdown + sendSignalRecursively( pid, SIGINT ); + + if( LinuxCoreFunctions::waitForProcess( pid, ServerShutdownTimeout, ServerWaitSleepInterval ) == false ) + { + sendSignalRecursively( pid, SIGTERM ); + + if( LinuxCoreFunctions::waitForProcess( pid, ServerTerminateTimeout, ServerWaitSleepInterval ) == false ) + { + vWarning() << "server for session" << m_sessionPath << "still running - killing now"; + sendSignalRecursively( pid, SIGKILL ); + LinuxCoreFunctions::waitForProcess( pid, ServerKillTimeout, ServerWaitSleepInterval ); + } + } +} diff --git a/core/include/PlatformServiceCore.h b/plugins/platform/linux/LinuxServerProcess.h similarity index 56% rename from core/include/PlatformServiceCore.h rename to plugins/platform/linux/LinuxServerProcess.h index 3aaafc12c..d7070cc3d 100644 --- a/core/include/PlatformServiceCore.h +++ b/plugins/platform/linux/LinuxServerProcess.h @@ -1,7 +1,7 @@ /* - * PlatformServiceCore.h - declaration of PlatformServiceCore class + * LinuxServerProcess.h - declaration of LinuxServerProcess class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2021-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,33 +24,28 @@ #pragma once -#include "VeyonCore.h" +#include // clazy:excludeall=copyable-polymorphic -class VEYON_CORE_EXPORT PlatformServiceCore +class LinuxServerProcess : public QProcess { + Q_OBJECT public: - using SessionId = int; + explicit LinuxServerProcess( const QProcessEnvironment& processEnvironment, + const QString& sessionPath, int sessionId, + QObject* parent = nullptr ); + ~LinuxServerProcess() override; - constexpr static SessionId SessionIdInvalid = -1; - constexpr static SessionId SessionIdMax = 99; - - PlatformServiceCore(); - - SessionId openSession( const QVariant& sessionData ); - void closeSession( SessionId sessionId ); - - QVariant sessionDataFromId( SessionId sessionId ) const; - SessionId sessionIdFromData( const QVariant& data ) const; - - bool multiSession() const - { - return m_multiSession; - } + void start(); + void stop(); private: - QMap m_sessions; - bool m_multiSession; + static constexpr auto ServerShutdownTimeout = 1000; + static constexpr auto ServerTerminateTimeout = 3000; + static constexpr auto ServerKillTimeout = 3000; + static constexpr auto ServerWaitSleepInterval = 100; + const QString m_sessionPath; + int m_sessionId; }; diff --git a/plugins/platform/linux/LinuxServiceCore.cpp b/plugins/platform/linux/LinuxServiceCore.cpp index 188a30313..83985441a 100644 --- a/plugins/platform/linux/LinuxServiceCore.cpp +++ b/plugins/platform/linux/LinuxServiceCore.cpp @@ -1,7 +1,7 @@ /* * LinuxServiceFunctions.cpp - implementation of LinuxServiceFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,23 +22,20 @@ * */ -#include #include #include -#include +#include #include -#include - -#include "Filesystem.h" -#include "LinuxCoreFunctions.h" +#include "LinuxPlatformConfiguration.h" +#include "LinuxServerProcess.h" #include "LinuxServiceCore.h" -#include "ProcessHelper.h" +#include "LinuxSessionFunctions.h" +#include "VeyonConfiguration.h" LinuxServiceCore::LinuxServiceCore( QObject* parent ) : - QObject( parent ), - m_loginManager( LinuxCoreFunctions::systemdLoginManager() ) + QObject( parent ) { connectToLoginManager(); } @@ -54,12 +51,7 @@ LinuxServiceCore::~LinuxServiceCore() void LinuxServiceCore::run() { - const auto sessions = listSessions(); - - for( const auto& s : sessions ) - { - startServer( s, QDBusObjectPath( s ) ); - } + startServers(); QEventLoop eventLoop; eventLoop.exec(); @@ -69,86 +61,34 @@ void LinuxServiceCore::run() void LinuxServiceCore::startServer( const QString& login1SessionId, const QDBusObjectPath& sessionObjectPath ) { - const auto sessionPath = sessionObjectPath.path(); - - const auto sessionType = getSessionType( sessionPath ); + Q_UNUSED(login1SessionId) - if( sessionType == QLatin1String("wayland") ) - { - vCritical() << "Can't start Veyon Server in Wayland sessions as this is not yet supported. Please switch to X11-based sessions!"; - return; - } - - // do not start server for non-graphical sessions - if( sessionType != QLatin1String("x11") ) - { - return; - } - - const auto sessionLeader = getSessionLeaderPid( sessionPath ); - if( sessionLeader < 0 ) - { - vCritical() << "No leader available for session" << sessionPath; - return; - } - - auto sessionEnvironment = getSessionEnvironment( sessionLeader ); - - if( sessionEnvironment.isEmpty() ) - { - vWarning() << "Environment for session" << sessionPath << "not yet available - retrying in" - << SessionEnvironmentProbingInterval << "msecs"; - QTimer::singleShot( SessionEnvironmentProbingInterval, this, - [=]() { startServer( login1SessionId, sessionObjectPath ); } ); - return; - } - - if( multiSession() == false && m_serverProcesses.isEmpty() == false ) - { - // make sure no other server is still running - stopAllServers(); - } - - const auto sessionUptime = getSessionUptimeSeconds( sessionPath ); - - if( sessionUptime >= 0 && sessionUptime < SessionUptimeSecondsMinimum ) - { - vDebug() << "Session" << sessionPath << "too young - retrying in" << SessionUptimeProbingInterval << "msecs"; - QTimer::singleShot( SessionUptimeProbingInterval, this, [=]() { startServer( login1SessionId, sessionObjectPath ); } ); - return; - } - - const auto seat = getSessionSeat( sessionPath ); - const auto display = getSessionDisplay( sessionPath ); - - vInfo() << "Starting server for new session" << sessionPath - << "with display" << display - << "at seat" << seat.path; - - if( multiSession() ) - { - const auto sessionId = openSession( QStringList( { sessionPath, display, seat.path } ) ); - sessionEnvironment.insert( VeyonCore::sessionIdEnvironmentVariable(), QString::number( sessionId ) ); - } + const auto sessionPath = sessionObjectPath.path(); - auto process = new QProcess( this ); - process->setProcessEnvironment( sessionEnvironment ); - process->start( VeyonCore::filesystem().serverFilePath() ); + vDebug() << "new session" << sessionPath; - m_serverProcesses[sessionPath] = process; + startServer( sessionPath ); } void LinuxServiceCore::stopServer( const QString& login1SessionId, const QDBusObjectPath& sessionObjectPath ) { - Q_UNUSED( login1SessionId ); + Q_UNUSED(login1SessionId) const auto sessionPath = sessionObjectPath.path(); + vDebug() << "session removed" << sessionPath; + if( m_serverProcesses.contains( sessionPath ) ) { stopServer( sessionPath ); + + // make sure to (re-)start server instances for preempted/suspended sessions such as the login manager session + if( m_sessionManager.mode() != PlatformSessionManager::Mode::Multi ) + { + startServers(); + } } } @@ -181,192 +121,198 @@ void LinuxServiceCore::connectToLoginManager() -void LinuxServiceCore::stopServer( const QString& sessionPath ) +void LinuxServiceCore::startServers() { - if( m_serverProcesses.contains( sessionPath ) == false ) + vDebug(); + + const auto sessions = LinuxSessionFunctions::listSessions(); + + for( const auto& s : sessions ) { - return; + if( m_serverProcesses.contains( s ) == false && + m_deferredServerSessions.contains( s ) == false && + ( m_sessionManager.mode() == PlatformSessionManager::Mode::Multi || m_serverProcesses.isEmpty() ) ) + { + startServer( s ); + } } +} - vInfo() << "stopping server for removed session" << sessionPath; - auto process = qAsConst(m_serverProcesses)[sessionPath]; - process->terminate(); - if( ProcessHelper::waitForProcess( process, ServerTerminateTimeout, ServerWaitSleepInterval ) == false ) +void LinuxServiceCore::startServer( const QString& sessionPath ) +{ + const auto sessionType = LinuxSessionFunctions::getSessionType( sessionPath ); + + if( sessionType == LinuxSessionFunctions::Type::Wayland ) { - vWarning() << "server for session" << sessionPath << "still running - killing now"; - process->kill(); - ProcessHelper::waitForProcess( process, ServerKillTimeout, ServerWaitSleepInterval ); + vWarning() << "Wayland session detected but trying to start Veyon Server anyway, even though Veyon Server does " + "not supported Wayland sessions. If you encounter problems, please switch to X11-based sessions!"; } - if( multiSession() ) + // do not start server for non-graphical sessions + if( sessionType == LinuxSessionFunctions::Type::TTY ) { - closeSession( process->processEnvironment().value( VeyonCore::sessionIdEnvironmentVariable() ).toInt() ); + vDebug() << "Not starting Veyon Server in TTY session"; + return; } - delete process; - m_serverProcesses.remove( sessionPath ); -} + // do not start server for sessions with unspecified type + if (sessionType == LinuxSessionFunctions::Type::Unspecified) + { + vDebug() << "Not starting Veyon Server in a session with unspecified type"; + return; + } + const auto sessionState = LinuxSessionFunctions::getSessionState( sessionPath ); + if( sessionState == LinuxSessionFunctions::State::Opening ) + { + vDebug() << "Session" << sessionPath << "still is being opening - retrying in" << SessionStateProbingInterval << "msecs"; + deferServerStart( sessionPath, SessionStateProbingInterval ); + return; + } + // only start server for online or active sessions + if( sessionState != LinuxSessionFunctions::State::Online && + sessionState != LinuxSessionFunctions::State::Active ) + { + vInfo() << "Not starting server for session" << sessionPath << "in state" << sessionState; + return; + } -void LinuxServiceCore::stopAllServers() -{ - while( m_serverProcesses.isEmpty() == false ) + const auto sessionLeader = LinuxSessionFunctions::getSessionLeaderPid( sessionPath ); + if( sessionLeader < 0 ) { - stopServer( m_serverProcesses.firstKey() ); + vCritical() << "No leader available for session" << sessionPath; + return; } -} + auto sessionEnvironment = LinuxSessionFunctions::getSessionEnvironment( sessionLeader ); + if( sessionEnvironment.isEmpty() ) + { + vWarning() << "Environment for session" << sessionPath << "not yet available - retrying in" + << SessionEnvironmentProbingInterval << "msecs"; + deferServerStart( sessionPath, SessionEnvironmentProbingInterval ); + return; + } -QStringList LinuxServiceCore::listSessions() -{ - QStringList sessions; + if( m_sessionManager.mode() != PlatformSessionManager::Mode::Multi ) + { + // make sure no other server is still running + stopAllServers(); + } - const QDBusReply reply = m_loginManager->call( QStringLiteral("ListSessions") ); + const auto sessionUptime = LinuxSessionFunctions::getSessionUptimeSeconds( sessionPath ); + const auto minimumSessionUptime = LinuxPlatformConfiguration(&VeyonCore::config()).minimumUserSessionLifetime(); - if( reply.isValid() ) + if( sessionUptime >= 0 && + sessionUptime < minimumSessionUptime ) { - const auto data = reply.value(); - - data.beginArray(); - while( data.atEnd() == false ) - { - LoginDBusSession session; + vDebug() << "Session" << sessionPath << "too young - retrying in" << minimumSessionUptime - sessionUptime << "msecs"; + deferServerStart( sessionPath, int(minimumSessionUptime - sessionUptime) ); + return; + } - data.beginStructure(); - data >> session.id >> session.uid >> session.name >> session.seatId >> session.path; - data.endStructure(); + sessionEnvironment.insert( LinuxSessionFunctions::sessionPathEnvVarName(), sessionPath ); - sessions.append( session.path.path() ); + // if pam-systemd is not in use, we have to set the XDG_SESSION_ID environment variable manually + if( sessionEnvironment.contains( LinuxSessionFunctions::xdgSessionIdEnvVarName() ) == false ) + { + const auto sessionId = LinuxSessionFunctions::getSessionId(sessionPath); + if (sessionId.isEmpty() == false) + { + sessionEnvironment.insert(LinuxSessionFunctions::xdgSessionIdEnvVarName(), sessionId); } - return sessions; } - else + + // workaround for #817 where LinuxSessionFunctions::getSessionEnvironment() does not return all + // environment variables when executed via systemd for an established KDE session and xdg-open fails + if (sessionEnvironment.value(LinuxSessionFunctions::xdgCurrentDesktopEnvVarName()) == QLatin1String("KDE") && + sessionEnvironment.contains(LinuxSessionFunctions::kdeSessionVersionEnvVarName()) == false) { - vCritical() << "Could not query sessions:" << reply.error().message(); + sessionEnvironment.insert(LinuxSessionFunctions::xdgCurrentDesktopEnvVarName(), QStringLiteral("X-Generic")); } - return sessions; -} + const auto sessionId = m_sessionManager.openSession( sessionPath ); + vInfo() << "Starting server for new session" << sessionPath + << "with ID" << sessionId + << "at seat" << LinuxSessionFunctions::getSessionSeat( sessionPath ).path; + sessionEnvironment.insert( QLatin1String( ServiceDataManager::serviceDataTokenEnvironmentVariable() ), + QString::fromUtf8( m_dataManager.token().toByteArray() ) ); -QVariant LinuxServiceCore::getSessionProperty( const QString& session, const QString& property ) -{ - QDBusInterface loginManager( QStringLiteral("org.freedesktop.login1"), - session, - QStringLiteral("org.freedesktop.DBus.Properties"), - QDBusConnection::systemBus() ); + auto serverProcess = new LinuxServerProcess( sessionEnvironment, sessionPath, sessionId, this ); + serverProcess->start(); - const QDBusReply reply = loginManager.call( QStringLiteral("Get"), - QStringLiteral("org.freedesktop.login1.Session"), - property ); + connect( serverProcess, &QProcess::stateChanged, this, [=]() { checkSessionState( sessionPath ); } ); - if( reply.isValid() == false ) - { - vCritical() << "Could not query session property" << property << reply.error().message(); - return QVariant(); - } - - return reply.value().variant(); + m_serverProcesses[sessionPath] = serverProcess; + m_deferredServerSessions.removeAll( sessionPath ); } -int LinuxServiceCore::getSessionLeaderPid( const QString& session ) +void LinuxServiceCore::deferServerStart( const QString& sessionPath, int delay ) { - const auto leader = getSessionProperty( session, QStringLiteral("Leader") ); + QTimer::singleShot( delay, this, [=]() { startServer( sessionPath ); } ); - if( leader.isNull() ) + if( m_deferredServerSessions.contains( sessionPath ) == false ) { - return -1; + m_deferredServerSessions.append( sessionPath ); } - - return leader.toInt(); } -qint64 LinuxServiceCore::getSessionUptimeSeconds( const QString& session ) +void LinuxServiceCore::stopServer( const QString& sessionPath ) { - const auto timestamp = getSessionProperty( session, QStringLiteral("Timestamp") ); + m_sessionManager.closeSession( sessionPath ); - if( timestamp.isNull() ) + if( m_serverProcesses.contains( sessionPath ) == false ) { - return -1; + return; } - return QDateTime::currentMSecsSinceEpoch() / 1000 - static_cast( timestamp.toLongLong() / ( 1000 * 1000 ) ); -} - - - -QString LinuxServiceCore::getSessionType( const QString& session ) -{ - return getSessionProperty( session, QStringLiteral("Type") ).toString(); -} - - - -QString LinuxServiceCore::getSessionDisplay( const QString& session ) -{ - return getSessionProperty( session, QStringLiteral("Display") ).toString(); -} - + vInfo() << "stopping server for removed session" << sessionPath; + auto serverProcess = std::as_const(m_serverProcesses)[sessionPath]; + serverProcess->disconnect(this); + serverProcess->stop(); + serverProcess->deleteLater(); -QString LinuxServiceCore::getSessionId( const QString& session ) -{ - return getSessionProperty( session, QStringLiteral("Id") ).toString(); + m_serverProcesses.remove( sessionPath ); } -LinuxServiceCore::LoginDBusSessionSeat LinuxServiceCore::getSessionSeat( const QString& session ) +void LinuxServiceCore::stopAllServers() { - const auto seatArgument = getSessionProperty( session, QStringLiteral("Seat") ).value(); - - LoginDBusSessionSeat seat; - seatArgument.beginStructure(); - seatArgument >> seat.id; - seatArgument >> seat.path; - seatArgument.endStructure(); - - return seat; + while( m_serverProcesses.isEmpty() == false ) + { + stopServer( m_serverProcesses.firstKey() ); + } } -QProcessEnvironment LinuxServiceCore::getSessionEnvironment( int sessionLeaderPid ) +void LinuxServiceCore::checkSessionState( const QString& sessionPath ) { - QProcessEnvironment sessionEnv; - - PROCTAB* proc = openproc( PROC_FILLSTATUS | PROC_FILLENV ); - proc_t* procInfo = nullptr; - - QList ppids; - - while( ( procInfo = readproc( proc, nullptr ) ) ) + const auto sessionState = LinuxSessionFunctions::getSessionState( sessionPath ); + if( sessionState == LinuxSessionFunctions::State::Closing || + sessionState == LinuxSessionFunctions::State::Unknown ) + { + vDebug() << "Stopping server for currently closing session" << sessionPath; + stopServer( sessionPath ); + } + else { - if( ( procInfo->ppid == sessionLeaderPid || ppids.contains( procInfo->ppid ) ) && - procInfo->environ != nullptr ) + // restart server if crashed + const auto serverProcess = m_serverProcesses.value(sessionPath); + if (serverProcess && serverProcess->state() == QProcess::NotRunning) { - for( int i = 0; procInfo->environ[i]; ++i ) - { - const auto env = QString::fromUtf8( procInfo->environ[i] ).split( QLatin1Char('=') ); - sessionEnv.insert( env.first(), env.mid( 1 ).join( QLatin1Char('=') ) ); - } - - ppids.append( procInfo->tid ); + QTimer::singleShot(ServerRestartInterval, serverProcess, [serverProcess]() { serverProcess->start(); }); } - - freeproc( procInfo ); } - - closeproc( proc ); - - return sessionEnv; } diff --git a/plugins/platform/linux/LinuxServiceCore.h b/plugins/platform/linux/LinuxServiceCore.h index 5d844045a..4c0939c66 100644 --- a/plugins/platform/linux/LinuxServiceCore.h +++ b/plugins/platform/linux/LinuxServiceCore.h @@ -1,7 +1,7 @@ /* * LinuxServiceCore.h - declaration of LinuxServiceCore class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,14 +24,15 @@ #pragma once -#include - #include "LinuxCoreFunctions.h" -#include "PlatformServiceCore.h" +#include "PlatformSessionManager.h" +#include "ServiceDataManager.h" + +class LinuxServerProcess; // clazy:excludeall=copyable-polymorphic -class LinuxServiceCore : public QObject, PlatformServiceCore +class LinuxServiceCore : public QObject { Q_OBJECT public: @@ -40,50 +41,30 @@ class LinuxServiceCore : public QObject, PlatformServiceCore void run(); -private slots: +private Q_SLOTS: void startServer( const QString& login1SessionId, const QDBusObjectPath& sessionObjectPath ); void stopServer( const QString& login1SessionId, const QDBusObjectPath& sessionObjectPath ); private: static constexpr auto LoginManagerReconnectInterval = 3000; - static constexpr auto ServerTerminateTimeout = 3000; - static constexpr auto ServerKillTimeout = 10000; - static constexpr auto ServerWaitSleepInterval = 100; static constexpr auto SessionEnvironmentProbingInterval = 1000; - static constexpr auto SessionUptimeSecondsMinimum = 3; - static constexpr auto SessionUptimeProbingInterval = 1000; - - using LoginDBusSession = struct { - QString id; - quint32 uid{0}; - QString name; - QString seatId; - QDBusObjectPath path; - } ; - - using LoginDBusSessionSeat = struct { - QString id; - QString path; - } ; + static constexpr auto SessionStateProbingInterval = 1000; + static constexpr auto ServerRestartInterval = 5000; void connectToLoginManager(); + void startServers(); + void startServer( const QString& sessionPath ); + void deferServerStart( const QString& sessionPath, int delay ); void stopServer( const QString& sessionPath ); void stopAllServers(); - QStringList listSessions(); - - static QVariant getSessionProperty( const QString& session, const QString& property ); - - static int getSessionLeaderPid( const QString& session ); - static qint64 getSessionUptimeSeconds( const QString& session ); - static QString getSessionType( const QString& session ); - static QString getSessionDisplay( const QString& session ); - static QString getSessionId( const QString& session ); - static LoginDBusSessionSeat getSessionSeat( const QString& session ); + void checkSessionState( const QString& sessionPath ); - static QProcessEnvironment getSessionEnvironment( int sessionLeaderPid ); + LinuxCoreFunctions::DBusInterfacePointer m_loginManager{LinuxCoreFunctions::systemdLoginManager()}; + QMap m_serverProcesses; + QStringList m_deferredServerSessions; - LinuxCoreFunctions::DBusInterfacePointer m_loginManager; - QMap m_serverProcesses; + ServiceDataManager m_dataManager{}; + PlatformSessionManager m_sessionManager{}; }; diff --git a/plugins/platform/linux/LinuxServiceFunctions.cpp b/plugins/platform/linux/LinuxServiceFunctions.cpp index d2f5745bc..b60a8f347 100644 --- a/plugins/platform/linux/LinuxServiceFunctions.cpp +++ b/plugins/platform/linux/LinuxServiceFunctions.cpp @@ -1,7 +1,7 @@ /* * LinuxServiceFunctions.cpp - implementation of LinuxServiceFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,6 +22,7 @@ * */ +#include "LinuxCoreFunctions.h" #include "LinuxServiceCore.h" #include "LinuxServiceFunctions.h" @@ -35,7 +36,7 @@ QString LinuxServiceFunctions::veyonServiceName() const bool LinuxServiceFunctions::isRegistered( const QString& name ) { - Q_UNUSED(name); + Q_UNUSED(name) vCritical() << "Querying service registration is not supported on this platform."; @@ -46,21 +47,21 @@ bool LinuxServiceFunctions::isRegistered( const QString& name ) bool LinuxServiceFunctions::isRunning( const QString& name ) { - return systemctl( { QStringLiteral("status"), name } ) == 0; + return LinuxCoreFunctions::systemctl( { QStringLiteral("status"), name } ) == 0; } bool LinuxServiceFunctions::start( const QString& name ) { - return systemctl( { QStringLiteral("start"), name } ) == 0; + return LinuxCoreFunctions::systemctl( { QStringLiteral("start"), name } ) == 0; } bool LinuxServiceFunctions::stop( const QString& name ) { - return systemctl( { QStringLiteral("stop"), name } ) == 0; + return LinuxCoreFunctions::systemctl( { QStringLiteral("stop"), name } ) == 0; } @@ -93,21 +94,27 @@ bool LinuxServiceFunctions::uninstall( const QString& name ) bool LinuxServiceFunctions::setStartMode( const QString& name, PlatformServiceFunctions::StartMode startMode ) { + if (LinuxCoreFunctions::isSystemdManaged() == false) + { + vWarning() << "System is not managed by systemd – unable to configure start mode for service" << name; + return true; + } + if( startMode == StartMode::Auto ) { - return systemctl( { QStringLiteral("enable"), name } ) == 0; + return LinuxCoreFunctions::systemctl( { QStringLiteral("enable"), name } ) == 0; } - return systemctl( { QStringLiteral("disable"), name } ) == 0; + return LinuxCoreFunctions::systemctl( { QStringLiteral("disable"), name } ) == 0; } -bool LinuxServiceFunctions::runAsService( const QString& name, const std::function& serviceMain ) +bool LinuxServiceFunctions::runAsService( const QString& name, const ServiceEntryPoint& serviceEntryPoint ) { - Q_UNUSED(name); + Q_UNUSED(name) - serviceMain(); + serviceEntryPoint(); return true; } @@ -119,11 +126,3 @@ void LinuxServiceFunctions::manageServerInstances() LinuxServiceCore serviceCore; serviceCore.run(); } - - - -int LinuxServiceFunctions::systemctl( const QStringList& arguments ) -{ - return QProcess::execute( QStringLiteral("systemctl"), - QStringList( { QStringLiteral("--no-pager"), QStringLiteral("-q") } ) + arguments ); -} diff --git a/plugins/platform/linux/LinuxServiceFunctions.h b/plugins/platform/linux/LinuxServiceFunctions.h index cc20e83c9..ada1eda94 100644 --- a/plugins/platform/linux/LinuxServiceFunctions.h +++ b/plugins/platform/linux/LinuxServiceFunctions.h @@ -1,7 +1,7 @@ /* * LinuxServiceFunctions.h - declaration of LinuxServiceFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -41,10 +41,7 @@ class LinuxServiceFunctions : public PlatformServiceFunctions StartMode startMode, const QString& displayName) override; bool uninstall( const QString& name ) override; bool setStartMode( const QString& name, StartMode startMode ) override; - bool runAsService( const QString& name, const std::function& serviceMain ) override; + bool runAsService( const QString& name, const ServiceEntryPoint& serviceEntryPoint ) override; void manageServerInstances() override; -private: - static int systemctl( const QStringList& arguments ); - }; diff --git a/plugins/platform/linux/LinuxSessionFunctions.cpp b/plugins/platform/linux/LinuxSessionFunctions.cpp new file mode 100644 index 000000000..ec40ccd9a --- /dev/null +++ b/plugins/platform/linux/LinuxSessionFunctions.cpp @@ -0,0 +1,506 @@ +/* + * LinuxSessionFunctions.cpp - implementation of LinuxSessionFunctions class + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_LIBPROCPS +#include +#endif + +#include "LinuxCoreFunctions.h" +#include "LinuxSessionFunctions.h" +#include "PlatformSessionManager.h" + + +LinuxSessionFunctions::SessionId LinuxSessionFunctions::currentSessionId() +{ + return PlatformSessionManager::resolveSessionId( currentSessionPath() ); +} + + + +LinuxSessionFunctions::SessionUptime LinuxSessionFunctions::currentSessionUptime() const +{ + return getSessionUptimeSeconds(currentSessionPath()); +} + + + +QString LinuxSessionFunctions::currentSessionClientAddress() const +{ + return getSessionProperty(currentSessionPath(), QStringLiteral("RemoteHost")).toString(); +} + + + +QString LinuxSessionFunctions::currentSessionClientName() const +{ + return currentSessionClientAddress(); +} + + + +QString LinuxSessionFunctions::currentSessionHostName() const +{ + return QHostInfo::localHostName(); +} + + + +QString LinuxSessionFunctions::currentSessionType() const +{ + const auto env = QProcessEnvironment::systemEnvironment(); + + if( env.contains( QStringLiteral("WAYLAND_DISPLAY") ) ) + { + return QStringLiteral("wayland"); + } + else if( env.contains( QStringLiteral("DISPLAY") ) ) + { + return QStringLiteral("x11"); + } + + return getSessionProperty( currentSessionPath(), QStringLiteral("Type") ).toString(); +} + + + +bool LinuxSessionFunctions::currentSessionHasUser() const +{ + return getSessionClass( currentSessionPath() ) == Class::User; +} + + + +bool LinuxSessionFunctions::currentSessionIsRemote() const +{ + return isRemote( currentSessionPath() ); +} + + + +LinuxSessionFunctions::EnvironmentVariables LinuxSessionFunctions::currentSessionEnvironmentVariables() const +{ + const auto sessionLeader = getSessionLeaderPid(currentSessionPath()); + auto sessionEnv = getSessionEnvironment(sessionLeader); + if (sessionEnv.isEmpty()) + { + sessionEnv = QProcessEnvironment::systemEnvironment(); + } + const auto sessionEnvVars = sessionEnv.keys(); + + EnvironmentVariables envVars; + for (const auto& sessionEnvVar : sessionEnvVars) + { + envVars[sessionEnvVar] = sessionEnv.value(sessionEnvVar); + } + + return envVars; +} + + + +QVariant LinuxSessionFunctions::querySettingsValueInCurrentSession(const QString& key) const +{ + return QSettings(QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName()).value(key); +} + + + +QStringList LinuxSessionFunctions::listSessions() +{ + QStringList sessions; + + const QDBusReply reply = LinuxCoreFunctions::systemdLoginManager()->call( QStringLiteral("ListSessions") ); + + if( reply.isValid() ) + { + const auto data = reply.value(); + + data.beginArray(); + while( data.atEnd() == false ) + { + LoginDBusSession session; + + data.beginStructure(); + data >> session.id >> session.uid >> session.name >> session.seatId >> session.path; + data.endStructure(); + + sessions.append( session.path.path() ); + } + return sessions; + } + + vCritical() << "Could not query sessions:" << reply.error().message(); + + return sessions; +} + + + +QVariant LinuxSessionFunctions::getSessionProperty(const QString& session, const QString& property, bool logErrors) +{ + QDBusInterface loginManager( QStringLiteral("org.freedesktop.login1"), + session, + QStringLiteral("org.freedesktop.DBus.Properties"), + QDBusConnection::systemBus() ); + + if (loginManager.connection().isConnected() == false) + { + vDebug() << "system bus not connected"; + return {}; + } + + const QDBusReply reply = loginManager.call( QStringLiteral("Get"), + QStringLiteral("org.freedesktop.login1.Session"), + property ); + + if( reply.isValid() == false ) + { + if (logErrors) + { + vCritical() << "Could not query property" << property + << "of session" << session + << "error:" << reply.error().message(); + } + return {}; + } + + return reply.value().variant(); +} + + + +int LinuxSessionFunctions::getSessionLeaderPid( const QString& session ) +{ + const auto leader = getSessionProperty( session, QStringLiteral("Leader") ); + + if( leader.isNull() ) + { + return -1; + } + + return leader.toInt(); +} + + + +LinuxSessionFunctions::SessionUptime LinuxSessionFunctions::getSessionUptimeSeconds( const QString& session ) +{ + const auto sessionUptimeUsec = getSessionProperty( session, QStringLiteral("Timestamp") ); + + if( sessionUptimeUsec.isNull() ) + { + return -1; + } + +#if QT_VERSION < QT_VERSION_CHECK(5, 8, 0) + const auto currentTimestamp = QDateTime::currentMSecsSinceEpoch() / 1000; +#else + const auto currentTimestamp = QDateTime::currentSecsSinceEpoch(); +#endif + + return SessionUptime(currentTimestamp - sessionUptimeUsec.toLongLong() / (1000 * 1000)); +} + + + +LinuxSessionFunctions::Class LinuxSessionFunctions::getSessionClass( const QString& session ) +{ + auto sessionClass = getSessionProperty(session, QStringLiteral("Class")).toString(); + if (sessionClass.isEmpty() && session == currentSessionPath()) + { + sessionClass = QProcessEnvironment::systemEnvironment().value(LinuxSessionFunctions::xdgSessionClassEnvVarName()); + } + + if( sessionClass == QLatin1String("user") ) + { + return Class::User; + } + else if( sessionClass == QLatin1String("greeter") ) + { + return Class::Greeter; + } + else if( sessionClass == QLatin1String("lock-screen") ) + { + return Class::LockScreen; + } + + return Class::Unknown; +} + + + +LinuxSessionFunctions::Type LinuxSessionFunctions::getSessionType( const QString& session ) +{ + const auto type = getSessionProperty( session, QStringLiteral("Type") ).toString(); + if( type == QLatin1String("tty") ) + { + return Type::TTY; + } + else if( type == QLatin1String("x11") ) + { + return Type::X11; + } + else if( type == QLatin1String("mir") ) + { + return Type::Mir; + } + else if( type == QLatin1String("wayland") ) + { + return Type::Wayland; + } + else if (type == QLatin1String("unspecified")) + { + return Type::Unspecified; + } + + if( type.isEmpty() == false ) + { + vWarning() << "unknown session type" << type; + } + + return Type::Unspecified; +} + + + +QString LinuxSessionFunctions::getSessionId(const QString& session, bool logErrors) +{ + return getSessionProperty(session, QStringLiteral("Id"), logErrors).toString(); +} + + + +QString LinuxSessionFunctions::getSessionUser(const QString& session) +{ + quint32 uid{0}; + QString userObjectPath; + + const auto reply = getSessionProperty(session, QStringLiteral("User")); + if (reply.isValid()) + { + const auto replyData = reply.value(); + replyData.beginStructure(); + replyData >> uid >> userObjectPath; + replyData.endStructure(); + + return userObjectPath; + } + + return {}; +} + + + +LinuxSessionFunctions::State LinuxSessionFunctions::getSessionState( const QString& session ) +{ + static const QMap stateMap{ + { QStringLiteral("offline"), State::Offline }, + { QStringLiteral("lingering"), State::Lingering }, + { QStringLiteral("online"), State::Online }, + { QStringLiteral("active"), State::Active }, + { QStringLiteral("opening"), State::Opening }, + { QStringLiteral("closing"), State::Closing } + }; + + const auto stateString = getSessionProperty( session, QStringLiteral("State") ).toString(); + const auto state = stateMap.value( stateString, State::Unknown ); + if( state == State::Unknown && stateString.isEmpty() == false ) + { + vDebug() << stateString; + } + + return state; +} + + + +LinuxSessionFunctions::LoginDBusSessionSeat LinuxSessionFunctions::getSessionSeat( const QString& session ) +{ + const auto seatArgument = getSessionProperty( session, QStringLiteral("Seat") ).value(); + + LoginDBusSessionSeat seat; + seatArgument.beginStructure(); + seatArgument >> seat.id; + seatArgument >> seat.path; + seatArgument.endStructure(); + + return seat; +} + + + +QProcessEnvironment LinuxSessionFunctions::getSessionEnvironment( int sessionLeaderPid ) +{ + QProcessEnvironment sessionEnv; + +#ifdef HAVE_LIBPROCPS + LinuxCoreFunctions::forEachChildProcess( + [&sessionEnv]( proc_t* procInfo ) { + if( procInfo->environ != nullptr ) + { + for( int i = 0; procInfo->environ[i]; ++i ) + { + const auto env = QString::fromUtf8( procInfo->environ[i] ); + const auto separatorPos = env.indexOf( QLatin1Char('=') ); + if( separatorPos > 0 ) + { + sessionEnv.insert( env.left( separatorPos ), env.mid( separatorPos+1 ) ); + } + } + + return true; + } + + return false; + }, + sessionLeaderPid, PROC_FILLENV, true ); +#elif defined(HAVE_LIBPROC2) + LinuxCoreFunctions::forEachChildProcess([&sessionEnv](const pids_stack* stack) + { + static constexpr auto EnvironItemIndex = 2; + const auto environ = PIDS_VAL(EnvironItemIndex, strv, stack); + + if (environ != nullptr) + { + for (int i = 0; environ[i]; ++i) + { + const auto env = QString::fromUtf8(environ[i]); + const auto separatorPos = env.indexOf(QLatin1Char('=')); + if (separatorPos > 0) + { + sessionEnv.insert(env.left(separatorPos), env.mid(separatorPos+1)); + } + } + + return true; + } + + return false; + }, + sessionLeaderPid, {PIDS_ENVIRON_V}, true); +#endif + + return sessionEnv; +} + + + +QString LinuxSessionFunctions::currentSessionPath(bool ignoreErrors) +{ + const auto xdgSessionPath = QProcessEnvironment::systemEnvironment().value( sessionPathEnvVarName() ); + if (xdgSessionPath.isEmpty() == false) + { + return xdgSessionPath; + } + + const auto sessionAuto = QStringLiteral("/org/freedesktop/login1/session/auto"); + const auto sessionSelf = QStringLiteral("/org/freedesktop/login1/session/self"); // systemd < 243 + static QString sessionPathFromXdgSessionId; + + static bool hasSessionAuto = false; + static bool hasSessionSelf = false; + + if (hasSessionAuto) + { + return sessionAuto; + } + + if (hasSessionSelf) + { + return sessionSelf; + } + + if (sessionPathFromXdgSessionId.isEmpty() == false) + { + return sessionPathFromXdgSessionId; + } + + if (getSessionId(sessionAuto, false).isNull() == false) + { + hasSessionAuto = true; + return sessionAuto; + } + + if (getSessionId(sessionSelf, false).isNull() == false) + { + hasSessionSelf = true; + return sessionSelf; + } + + const auto xdgSessionId = QProcessEnvironment::systemEnvironment().value(xdgSessionIdEnvVarName()); + if (xdgSessionId.isEmpty() == false) + { + const QDBusReply reply = LinuxCoreFunctions::systemdLoginManager()->call( + QDBus::Block, QStringLiteral("GetSession"), xdgSessionId); + + if (reply.isValid()) + { + sessionPathFromXdgSessionId = reply.value().path(); + return sessionPathFromXdgSessionId; + } + } + + if (ignoreErrors == false) + { + vWarning() << "could not determine dbus object path of current session – please make sure systemd is " + "up to date and/or the environment variable" << xdgSessionIdEnvVarName() << "is set"; + } + + return {}; +} + + + +bool LinuxSessionFunctions::isOpen( const QString& session ) +{ + const auto state = getSessionState( session ); + + return state == State::Active || + state == State::Online || + state == State::Opening; +} + + +bool LinuxSessionFunctions::isGraphical( const QString& session ) +{ + const auto type = getSessionType( session ); + + return type == Type::X11 || + type == Type::Wayland || + type == Type::Mir; +} + + + +bool LinuxSessionFunctions::isRemote( const QString& session ) +{ + return getSessionProperty( session, QStringLiteral("Remote") ).toBool(); +} diff --git a/plugins/platform/linux/LinuxSessionFunctions.h b/plugins/platform/linux/LinuxSessionFunctions.h new file mode 100644 index 000000000..7567ed8a4 --- /dev/null +++ b/plugins/platform/linux/LinuxSessionFunctions.h @@ -0,0 +1,142 @@ +/* + * LinuxSessionFunctions.h - declaration of LinuxSessionFunctions class + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include +#include + +#include "PlatformSessionFunctions.h" + +// clazy:excludeall=copyable-polymorphic + +class LinuxSessionFunctions : public PlatformSessionFunctions +{ + Q_GADGET +public: + using LoginDBusSession = struct LoginDBusSession { + QString id; + quint32 uid{0}; + QString name; + QString seatId; + QDBusObjectPath path; + } ; + + using LoginDBusSessionSeat = struct { + QString id; + QString path; + } ; + + enum class State + { + Unknown, + Offline, + Lingering, + Online, + Active, + Opening, + Closing + }; + Q_ENUM(State) + + enum class Class + { + Unknown, + User, + Greeter, + LockScreen + }; + Q_ENUM(Class) + + enum class Type + { + Unspecified, + TTY, + X11, + Mir, + Wayland + }; + Q_ENUM(Type) + + SessionId currentSessionId() override; + + SessionUptime currentSessionUptime() const override; + QString currentSessionClientAddress() const override; + QString currentSessionClientName() const override; + QString currentSessionHostName() const override; + + QString currentSessionType() const override; + bool currentSessionHasUser() const override; + bool currentSessionIsRemote() const override; + + EnvironmentVariables currentSessionEnvironmentVariables() const override; + QVariant querySettingsValueInCurrentSession(const QString& key) const override; + + static QStringList listSessions(); + + static QVariant getSessionProperty(const QString& session, const QString& property, bool logErrors = true); + + static int getSessionLeaderPid( const QString& session ); + static SessionUptime getSessionUptimeSeconds( const QString& session ); + static Class getSessionClass( const QString& session ); + static Type getSessionType( const QString& session ); + static QString getSessionId(const QString& session, bool logErrors = true); + static QString getSessionUser( const QString& session ); + static State getSessionState( const QString& session ); + static LoginDBusSessionSeat getSessionSeat( const QString& session ); + + static QProcessEnvironment getSessionEnvironment( int sessionLeaderPid ); + + static QString currentSessionPath(bool ignoreErrors = false); + + static QString kdeSessionVersionEnvVarName() + { + return QStringLiteral("KDE_SESSION_VERSION"); + } + + static QString xdgCurrentDesktopEnvVarName() + { + return QStringLiteral("XDG_CURRENT_DESKTOP"); + } + + static QString xdgSessionIdEnvVarName() + { + return QStringLiteral("XDG_SESSION_ID"); + } + + static QString xdgSessionClassEnvVarName() + { + return QStringLiteral("XDG_SESSION_CLASS"); + } + + static QString sessionPathEnvVarName() + { + return QStringLiteral("VEYON_SESSION_PATH"); + } + + static bool isOpen( const QString& session ); + static bool isGraphical( const QString& session ); + static bool isRemote( const QString& session ); + +}; diff --git a/plugins/platform/linux/LinuxUserFunctions.cpp b/plugins/platform/linux/LinuxUserFunctions.cpp index a5e774410..39f94ea19 100644 --- a/plugins/platform/linux/LinuxUserFunctions.cpp +++ b/plugins/platform/linux/LinuxUserFunctions.cpp @@ -1,7 +1,7 @@ /* * LinuxUserFunctions.cpp - implementation of LinuxUserFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,20 +25,28 @@ #include #include #include +#include #include "LinuxCoreFunctions.h" #include "LinuxDesktopIntegration.h" +#include "LinuxKeyboardInput.h" #include "LinuxPlatformConfiguration.h" +#include "LinuxSessionFunctions.h" #include "LinuxUserFunctions.h" #include "VeyonConfiguration.h" +#define XK_MISCELLANY + +#include +#include + #include #include QString LinuxUserFunctions::fullName( const QString& username ) { - auto pw_entry = getpwnam( VeyonCore::stripDomain( username ).toUtf8().constData() ); + const auto pw_entry = getpwnam(username.toUtf8().constData()); if( pw_entry ) { @@ -61,7 +69,7 @@ QString LinuxUserFunctions::fullName( const QString& username ) QStringList LinuxUserFunctions::userGroups( bool queryDomainGroups ) { - Q_UNUSED(queryDomainGroups); + Q_UNUSED(queryDomainGroups) QStringList groupList; @@ -167,12 +175,10 @@ QStringList LinuxUserFunctions::userGroups( bool queryDomainGroups ) QStringList LinuxUserFunctions::groupsOfUser( const QString& username, bool queryDomainGroups ) { - Q_UNUSED(queryDomainGroups); + Q_UNUSED(queryDomainGroups) QStringList groupList; - const auto strippedUsername = VeyonCore::stripDomain( username ); - QProcess getentProcess; getentProcess.start( QStringLiteral("getent"), { QStringLiteral("group") } ); getentProcess.waitForFinished(); @@ -182,7 +188,7 @@ QStringList LinuxUserFunctions::groupsOfUser( const QString& username, bool quer { const auto groupComponents = group.split( QLatin1Char(':') ); if( groupComponents.size() == 4 && - groupComponents.last().split( QLatin1Char(',') ).contains( strippedUsername ) ) + groupComponents.last().split( QLatin1Char(',') ).contains(username)) { groupList += groupComponents.first(); // clazy:exclude=reserve-candidates } @@ -195,26 +201,34 @@ QStringList LinuxUserFunctions::groupsOfUser( const QString& username, bool quer -bool LinuxUserFunctions::isAnyUserLoggedOn() +bool LinuxUserFunctions::isAnyUserLoggedInLocally() { - QProcess whoProcess; - whoProcess.start( QStringLiteral("who") ); - whoProcess.waitForFinished( WhoProcessTimeout ); - - if( whoProcess.exitCode() != 0 ) + const auto sessions = LinuxSessionFunctions::listSessions(); + for( const auto& session : sessions ) { - return false; + if( LinuxSessionFunctions::isOpen( session ) && + LinuxSessionFunctions::isGraphical( session ) && + LinuxSessionFunctions::isRemote( session ) == false && + LinuxSessionFunctions::getSessionClass( session ) == LinuxSessionFunctions::Class::User ) + { + return true; + } } - const auto displayManagerUsers = LinuxPlatformConfiguration( &VeyonCore::config() ).displayManagerUsers(). - split( QLatin1Char(',') ); + return false; +} + + - const auto lines = whoProcess.readAll().split( '\n' ); - for( const auto& line : lines ) +bool LinuxUserFunctions::isAnyUserLoggedInRemotely() +{ + const auto sessions = LinuxSessionFunctions::listSessions(); + for( const auto& session : sessions ) { - const auto user = QString::fromUtf8( line.split( ' ' ).value( 0 ) ); - if( user.isEmpty() == false && - displayManagerUsers.contains( user ) == false ) + if( LinuxSessionFunctions::isOpen( session ) && + LinuxSessionFunctions::isGraphical( session ) && + LinuxSessionFunctions::isRemote( session ) && + LinuxSessionFunctions::getSessionClass( session ) == LinuxSessionFunctions::Class::User ) { return true; } @@ -229,6 +243,23 @@ QString LinuxUserFunctions::currentUser() { QString username; + if (VeyonCore::component() != VeyonCore::Component::CLI && m_systemBus.isConnected()) + { + const auto sessionPath = LinuxSessionFunctions::currentSessionPath(true); + if (sessionPath.isEmpty() == false) + { + const auto sessionUserPath = LinuxSessionFunctions::getSessionUser(sessionPath); + if (sessionUserPath.isEmpty() == false) + { + username = getUserProperty(sessionUserPath, QStringLiteral("Name")).toString(); + if (username.isEmpty() == false) + { + return username; + } + } + } + } + const auto envUser = qgetenv( "USER" ); struct passwd * pw_entry = nullptr; @@ -266,38 +297,118 @@ QString LinuxUserFunctions::currentUser() -void LinuxUserFunctions::logon( const QString& username, const QString& password ) +bool LinuxUserFunctions::prepareLogon( const QString& username, const Password& password ) { - Q_UNUSED(username); - Q_UNUSED(password); + if( m_logonHelper.prepare( username, password ) ) + { + LinuxCoreFunctions::restartDisplayManagers(); + return true; + } - // TODO + return false; +} + + + +bool LinuxUserFunctions::performLogon( const QString& username, const Password& password ) +{ + LinuxKeyboardInput input; + + auto sequence = LinuxPlatformConfiguration( &VeyonCore::config() ).userLoginKeySequence(); + + if( sequence.isEmpty() == true ) + { + sequence = QStringLiteral("%username%%password%"); + } + + static const QRegularExpression keySequenceRX(QStringLiteral("(<[\\w\\d_]+>|%username%|%password%|[\\w\\d]+)")); + auto matchIterator = keySequenceRX.globalMatch(sequence); + if( matchIterator.hasNext() == false ) + { + vCritical() << "invalid user login key sequence"; + return false; + } + + while( matchIterator.hasNext() ) + { + const auto token = matchIterator.next().captured(0); + if( token == QStringLiteral("%username%") ) + { + input.sendString( username ); + } + else if( token == QStringLiteral("%password%") ) + { + input.sendString( QString::fromUtf8( password.toByteArray() ) ); + } + else if( token.startsWith( QLatin1Char('<') ) && token.endsWith( QLatin1Char('>') ) ) + { + const auto keysymString = token.mid( 1, token.length() - 2 ); + const auto keysym = XStringToKeysym( keysymString.toLatin1().constData() ); + if( keysym != NoSymbol ) + { + input.pressAndReleaseKey( keysym ); + } + else + { + vCritical() << "unresolved keysym" << keysymString; + return false; + } + } + else if( token.isEmpty() == false ) + { + input.sendString( token ); + } + } + + return true; } void LinuxUserFunctions::logoff() { + LinuxCoreFunctions::prepareSessionBusAccess(); + // logout via common session managers - LinuxCoreFunctions::kdeSessionManager()->asyncCall( QStringLiteral("logout"), - static_cast( LinuxDesktopIntegration::KDE::ShutdownConfirmNo ), - static_cast( LinuxDesktopIntegration::KDE::ShutdownTypeLogout ), - static_cast( LinuxDesktopIntegration::KDE::ShutdownModeForceNow ) ); - LinuxCoreFunctions::gnomeSessionManager()->asyncCall( QStringLiteral("Logout"), - static_cast( LinuxDesktopIntegration::Gnome::GSM_MANAGER_LOGOUT_MODE_FORCE ) ); - LinuxCoreFunctions::mateSessionManager()->asyncCall( QStringLiteral("Logout"), - static_cast( LinuxDesktopIntegration::Mate::GSM_LOGOUT_MODE_FORCE ) ); + // logout via common session managers + for( const auto& call : std::initializer_list> + { + []() { + return LinuxCoreFunctions::kdeSessionManager() + ->call( QStringLiteral("logout"), + LinuxDesktopIntegration::KDE::ShutdownConfirmNo, + LinuxDesktopIntegration::KDE::ShutdownTypeLogout, + LinuxDesktopIntegration::KDE::ShutdownModeForceNow ); + }, + []() { + return LinuxCoreFunctions::gnomeSessionManager() + ->call( QStringLiteral("Logout"), + LinuxDesktopIntegration::Gnome::GSM_MANAGER_LOGOUT_MODE_FORCE ); + }, + []() { + return LinuxCoreFunctions::mateSessionManager() + ->call( QStringLiteral("Logout"), + LinuxDesktopIntegration::Mate::GSM_LOGOUT_MODE_FORCE ); + } + } ) + { + // call successful? + if( call().type() == QDBusMessage::ReplyMessage ) + { + return; + } + } // Xfce logout - QProcess::startDetached( QStringLiteral("xfce4-session-logout --logout") ); + QProcess::startDetached( QStringLiteral("xfce4-session-logout --logout"), {} ); // LXDE logout QProcess::startDetached( QStringLiteral("kill -TERM %1"). - arg( QProcessEnvironment::systemEnvironment().value( QStringLiteral("_LXSESSION_PID") ).toInt() ) ); + arg( QProcessEnvironment::systemEnvironment().value( QStringLiteral("_LXSESSION_PID") ).toInt() ), {} ); // terminate session via systemd LinuxCoreFunctions::systemdLoginManager()->asyncCall( QStringLiteral("TerminateSession"), - QProcessEnvironment::systemEnvironment().value( QStringLiteral("XDG_SESSION_ID") ) ); + QProcessEnvironment::systemEnvironment().value( LinuxSessionFunctions::xdgSessionIdEnvVarName() ) ); // close session via ConsoleKit as a last resort LinuxCoreFunctions::consoleKitManager()->asyncCall( QStringLiteral("CloseSession"), @@ -306,10 +417,10 @@ void LinuxUserFunctions::logoff() -bool LinuxUserFunctions::authenticate( const QString& username, const QString& password ) +bool LinuxUserFunctions::authenticate( const QString& username, const Password& password ) { QProcess p; - p.start( QStringLiteral( "veyon-auth-helper" ), QProcess::ReadWrite | QProcess::Unbuffered ); + p.start( QStringLiteral( "veyon-auth-helper" ), QStringList{}, QProcess::ReadWrite | QProcess::Unbuffered ); if( p.waitForStarted() == false ) { vCritical() << "failed to start VeyonAuthHelper"; @@ -319,13 +430,13 @@ bool LinuxUserFunctions::authenticate( const QString& username, const QString& p const auto pamService = LinuxPlatformConfiguration( &VeyonCore::config() ).pamServiceName(); QDataStream ds( &p ); - ds << VeyonCore::stripDomain( username ); - ds << password; - ds << pamService; + ds << username.toUtf8(); + ds << password.toByteArray(); + ds << pamService.toUtf8(); - p.waitForFinished(); + p.waitForFinished( AuthHelperTimeout ); - if( p.exitCode() != 0 ) + if( p.state() != QProcess::NotRunning || p.exitCode() != 0 ) { vCritical() << "VeyonAuthHelper failed:" << p.exitCode() << p.readAllStandardOutput().trimmed() << p.readAllStandardError().trimmed(); @@ -347,5 +458,52 @@ uid_t LinuxUserFunctions::userIdFromName( const QString& username ) return pw_entry->pw_uid; } - return 0; + return -1; +} + + + +gid_t LinuxUserFunctions::userGroupIdFromName( const QString& username ) +{ + const auto pw_entry = getpwnam( username.toUtf8().constData() ); + + if( pw_entry ) + { + return pw_entry->pw_gid; + } + + return -1; +} + + + +QVariant LinuxUserFunctions::getUserProperty(const QString& userPath, const QString& property, bool logErrors) +{ + QDBusInterface loginManager(QStringLiteral("org.freedesktop.login1"), + userPath, + QStringLiteral("org.freedesktop.DBus.Properties"), + QDBusConnection::systemBus()); + + if (loginManager.connection().isConnected() == false) + { + vDebug() << "system bus not connected"; + return {}; + } + + const QDBusReply reply = loginManager.call(QStringLiteral("Get"), + QStringLiteral("org.freedesktop.login1.User"), + property); + + if( reply.isValid() == false ) + { + if (logErrors) + { + vCritical() << "Could not query property" << property + << "of user" << userPath + << "error:" << reply.error().message(); + } + return {}; + } + + return reply.value().variant(); } diff --git a/plugins/platform/linux/LinuxUserFunctions.h b/plugins/platform/linux/LinuxUserFunctions.h index f5c098440..a23dd09b5 100644 --- a/plugins/platform/linux/LinuxUserFunctions.h +++ b/plugins/platform/linux/LinuxUserFunctions.h @@ -1,7 +1,7 @@ /* * LinuxUserFunctions.h - declaration of LinuxUserFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,6 +24,9 @@ #pragma once +#include + +#include "LogonHelper.h" #include "PlatformUserFunctions.h" #include @@ -38,17 +41,26 @@ class LinuxUserFunctions : public PlatformUserFunctions QStringList userGroups( bool queryDomainGroups ) override; QStringList groupsOfUser( const QString& username, bool queryDomainGroups ) override; - bool isAnyUserLoggedOn() override; + bool isAnyUserLoggedInLocally() override; + bool isAnyUserLoggedInRemotely() override; QString currentUser() override; - void logon( const QString& username, const QString& password ) override; + bool prepareLogon( const QString& username, const Password& password ) override; + bool performLogon( const QString& username, const Password& password ) override; void logoff() override; - bool authenticate( const QString& username, const QString& password ) override; + bool authenticate( const QString& username, const Password& password ) override; static uid_t userIdFromName( const QString& username ); + static gid_t userGroupIdFromName( const QString& username ); + + static QVariant getUserProperty(const QString& userPath, const QString& property, bool logErrors = true); private: - static constexpr auto WhoProcessTimeout = 3000; + QDBusConnection m_systemBus = QDBusConnection::systemBus(); + + static constexpr auto AuthHelperTimeout = 10000; + + LogonHelper m_logonHelper{}; }; diff --git a/plugins/platform/linux/auth-helper/CMakeLists.txt b/plugins/platform/linux/auth-helper/CMakeLists.txt index 5736237e2..46840492c 100644 --- a/plugins/platform/linux/auth-helper/CMakeLists.txt +++ b/plugins/platform/linux/auth-helper/CMakeLists.txt @@ -1,13 +1,14 @@ -INCLUDE_DIRECTORIES(${PAM_INCLUDE_DIR}) +find_package(PAM REQUIRED) -FIND_PACKAGE(PAM REQUIRED) +set(CMAKE_SKIP_BUILD_RPATH TRUE) +set(CMAKE_INSTALL_RPATH "") +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) -SET(CMAKE_SKIP_BUILD_RPATH TRUE) -SET(CMAKE_INSTALL_RPATH "") -SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) +add_executable(veyon-auth-helper ${CMAKE_CURRENT_SOURCE_DIR}/VeyonAuthHelper.cpp) -ADD_EXECUTABLE(veyon-auth-helper ${CMAKE_CURRENT_SOURCE_DIR}/VeyonAuthHelper.cpp) +set_default_target_properties(veyon-auth-helper) -TARGET_LINK_LIBRARIES(veyon-auth-helper Qt5::Core ${PAM_LIBRARY}) +target_include_directories(veyon-auth-helper PRIVATE ${PAM_INCLUDE_DIR}) +target_link_libraries(veyon-auth-helper PRIVATE ${PAM_LIBRARY} Qt${QT_MAJOR_VERSION}::Core) -INSTALL(TARGETS veyon-auth-helper RUNTIME DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE SETUID GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +install(TARGETS veyon-auth-helper RUNTIME DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE SETUID GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/plugins/platform/linux/auth-helper/VeyonAuthHelper.cpp b/plugins/platform/linux/auth-helper/VeyonAuthHelper.cpp index e1f415da9..f8f75abed 100644 --- a/plugins/platform/linux/auth-helper/VeyonAuthHelper.cpp +++ b/plugins/platform/linux/auth-helper/VeyonAuthHelper.cpp @@ -1,7 +1,7 @@ /* * VeyonAuthHelper.cpp - main file for Veyon Authentication Helper * - * Copyright (c) 2010-2019 Tobias Junghans + * Copyright (c) 2010-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,9 +27,9 @@ #include -static QByteArray pam_username; -static QByteArray pam_password; -static QByteArray pam_service; +static QByteArray pam_username; // clazy:exclude=non-pod-global-static +static QByteArray pam_password; // clazy:exclude=non-pod-global-static +static QByteArray pam_service; // clazy:exclude=non-pod-global-static static int pam_conv( int num_msg, const struct pam_message** msg, struct pam_response** resp, void * ) { @@ -70,23 +70,18 @@ static int pam_conv( int num_msg, const struct pam_message** msg, struct pam_res int main() { - QString username, password, service; QFile stdIn; stdIn.open( 0, QFile::ReadOnly | QFile::Unbuffered ); QDataStream ds( &stdIn ); - ds >> username; - ds >> password; - ds >> service; + ds >> pam_username; + ds >> pam_password; + ds >> pam_service; - if( service.isEmpty() ) + if( pam_service.isEmpty() ) { - service = QStringLiteral("login"); + pam_service = QByteArrayLiteral("login"); } - pam_username = username.toUtf8(); - pam_password = password.toUtf8(); - pam_service = service.toUtf8(); - struct pam_conv pconv = { &pam_conv, nullptr }; pam_handle_t* pamh = nullptr; auto err = pam_start( pam_service.constData(), nullptr, &pconv, &pamh ); @@ -97,6 +92,14 @@ int main() { printf( "pam_authenticate: %s\n", pam_strerror( pamh, err ) ); } + else + { + err = pam_acct_mgmt( pamh, PAM_SILENT ); + if( err != PAM_SUCCESS ) + { + printf( "pam_acct_mgmt: %s\n", pam_strerror( pamh, err ) ); + } + } } else { diff --git a/plugins/platform/windows/CMakeLists.txt b/plugins/platform/windows/CMakeLists.txt index fcbf84749..412f2cc59 100644 --- a/plugins/platform/windows/CMakeLists.txt +++ b/plugins/platform/windows/CMakeLists.txt @@ -1,8 +1,6 @@ -INCLUDE(BuildPlugin) +include(BuildVeyonPlugin) -ADD_DEFINITIONS(-DULTRAVNC_VEYON_SUPPORT -DUNICODE -D_UNICODE -D_WIN32_WINNT=0x0600) - -BUILD_PLUGIN(windows-platform +build_veyon_plugin(windows-platform WindowsPlatformPlugin.cpp WindowsPlatformConfigurationPage.h WindowsPlatformConfigurationPage.cpp @@ -15,10 +13,13 @@ BUILD_PLUGIN(windows-platform WindowsServiceControl.cpp WindowsServiceCore.cpp WindowsServiceFunctions.cpp + WindowsSessionFunctions.cpp WindowsUserFunctions.cpp WtsSessionManager.cpp + DesktopInputController.cpp SasEventListener.cpp XEventLog.cpp + ${ultravnc_DIR}/winvnc/winvnc/vnckeymap.cpp ${ultravnc_DIR}/addon/ms-logon/authSSP/authSSP.cpp ${ultravnc_DIR}/addon/ms-logon/authSSP/GenClientServerContext.cpp WindowsPlatformConfiguration.h @@ -31,16 +32,32 @@ BUILD_PLUGIN(windows-platform WindowsServiceControl.h WindowsServiceCore.h WindowsServiceFunctions.h + WindowsSessionFunctions.h WindowsUserFunctions.h WtsSessionManager.h + DesktopInputController.h SasEventListener.h + ../common/LogonHelper.h + ../common/LogonHelper.cpp + ../common/PersistentLogonCredentials.h + ../common/PersistentLogonCredentials.cpp + ../common/PlatformSessionManager.h + ../common/PlatformSessionManager.cpp + ../common/ServiceDataManager.h + ../common/ServiceDataManager.cpp XEventLog.h windows.qrc -) - -INCLUDE_DIRECTORIES(${ultravnc_DIR}/addon/ms-logon/authSSP) -INCLUDE_DIRECTORIES(${Qt5Gui_PRIVATE_INCLUDE_DIRS}) + ) -TARGET_LINK_LIBRARIES(windows-platform -lwtsapi32 -lnetapi32 -luserenv -linterception) +target_include_directories(windows-platform PRIVATE + ../common + ${ultravnc_DIR}/addon/ms-logon/authSSP + ${ultravnc_DIR}/winvnc/winvnc + ${ultravnc_DIR} + ) -SET_TARGET_PROPERTIES(windows-platform PROPERTIES COMPILE_FLAGS "-Wno-unknown-pragmas") +target_link_libraries(windows-platform PRIVATE -lws2_32 -lwtsapi32 -lnetapi32 -luserenv -limm32 -linterception -liphlpapi) +target_link_libraries(windows-platform PRIVATE Qt${QT_MAJOR_VERSION}::GuiPrivate) +target_compile_definitions(windows-platform PRIVATE ULTRAVNC_VEYON_SUPPORT) +target_compile_options(windows-platform PRIVATE "-Wno-unknown-pragmas") +set_source_files_properties(WindowsNetworkFunctions.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION TRUE SKIP_PRECOMPILE_HEADERS TRUE) diff --git a/plugins/platform/windows/DesktopInputController.cpp b/plugins/platform/windows/DesktopInputController.cpp new file mode 100644 index 000000000..22a59a777 --- /dev/null +++ b/plugins/platform/windows/DesktopInputController.cpp @@ -0,0 +1,141 @@ +/* + * DesktopInputController.cpp - implementation of DesktopInputController class + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "vnckeymap.h" + +#include + +#include "DesktopInputController.h" +#include "VeyonCore.h" + + + +// wrapper used by vncKeymap +void keybd_uni_event( BYTE bVk, BYTE bScan, DWORD dwFlags, ULONG_PTR dwExtraInfo ) +{ + keybd_event( bVk, bScan, dwFlags, dwExtraInfo ); +} + + + +DesktopInputController::DesktopInputController( int keyEventInterval ) : + m_keyEventInterval( static_cast( keyEventInterval ) ) +{ +} + + + +DesktopInputController::~DesktopInputController() +{ + m_requestStop = 1; + + m_thread.join(); +} + + + +void DesktopInputController::pressKey( KeyCode key ) +{ + m_dataMutex.lock(); + m_keys.enqueue( { key, true } ); + m_dataMutex.unlock(); + + m_inputWaitCondition.wakeAll(); +} + + + +void DesktopInputController::releaseKey( KeyCode key ) +{ + m_dataMutex.lock(); + m_keys.enqueue( { key, false } ); + m_dataMutex.unlock(); + + m_inputWaitCondition.wakeAll(); +} + + + +void DesktopInputController::pressAndReleaseKey( KeyCode key ) +{ + pressKey( key ); + releaseKey( key ); +} + + + +void DesktopInputController::pressAndReleaseKey( QChar character ) +{ + pressAndReleaseKey( static_cast( character.unicode() ) ); +} + + + +void DesktopInputController::pressAndReleaseKey( QLatin1Char character ) +{ + pressAndReleaseKey( static_cast( character.unicode() ) ); +} + + + +void DesktopInputController::run() +{ + auto desktop = OpenInputDesktop( 0, false, GENERIC_WRITE ); + if (!desktop) + { + const auto error = GetLastError(); + vCritical() << "failed to open input desktop:" << error; + return; + } + + if (SetThreadDesktop(desktop)) + { + vncKeymap::ClearShiftKeys(); + + QMutex waitMutex; + + while (m_requestStop == 0) + { + waitMutex.lock(); + m_inputWaitCondition.wait( &waitMutex, ThreadSleepInterval ); + waitMutex.unlock(); + + m_dataMutex.lock(); + while( m_keys.isEmpty() == false ) + { + const auto key = m_keys.dequeue(); + vncKeymap::keyEvent( key.first, key.second, false, false ); + QThread::msleep( m_keyEventInterval ); + } + m_dataMutex.unlock(); + } + } + else + { + const auto error = GetLastError(); + vCritical() << "failed to set thread desktop:" << error; + } + + CloseDesktop(desktop); +} diff --git a/plugins/platform/windows/DesktopInputController.h b/plugins/platform/windows/DesktopInputController.h new file mode 100644 index 000000000..0b002bdc5 --- /dev/null +++ b/plugins/platform/windows/DesktopInputController.h @@ -0,0 +1,67 @@ +/* + * DesktopInputController.h - declaration of DesktopInputController class + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +#include +#include +#include + +// clazy:excludeall=copyable-polymorphic + +class DesktopInputController : public QObject +{ + Q_OBJECT +public: + using KeyCode = uint32_t; + + DesktopInputController( int keyEventInterval ); + ~DesktopInputController() override; + + void pressKey( KeyCode key ); + + void releaseKey( KeyCode key ); + + void pressAndReleaseKey( KeyCode key ); + void pressAndReleaseKey( QChar character ); + void pressAndReleaseKey( QLatin1Char character ); + +private: + void run(); + + static constexpr int ThreadSleepInterval = 100; + + HANDLE m_threadHandle = 0; + QMutex m_dataMutex; + QQueue > m_keys; + QWaitCondition m_inputWaitCondition; + QAtomicInt m_requestStop; + + unsigned long m_keyEventInterval; + + std::thread m_thread = std::thread([this](){ run(); }); + +}; diff --git a/plugins/platform/windows/SasEventListener.cpp b/plugins/platform/windows/SasEventListener.cpp index 70729cfd2..f7f264a66 100644 --- a/plugins/platform/windows/SasEventListener.cpp +++ b/plugins/platform/windows/SasEventListener.cpp @@ -1,7 +1,7 @@ /* * SasEventListener.cpp - implementation of SasEventListener class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -29,15 +29,15 @@ SasEventListener::SasEventListener() { const wchar_t* sasDll = L"\\sas.dll"; - wchar_t sasPath[MAX_PATH] = { 0 }; // Flawfinder: ignore - if( GetSystemDirectory( sasPath, MAX_PATH - wcslen(sasDll) - 1 ) == 0 ) // Flawfinder: ignore + std::array sasPath{}; + if( GetSystemDirectory( sasPath.data(), static_cast( MAX_PATH - wcslen(sasDll) - 1 ) ) == 0 ) { vCritical() << "could not determine system directory"; } - wcscat( sasPath, sasDll ); + wcscat( sasPath.data(), sasDll ); - m_sasLibrary = LoadLibrary( sasPath ); // Flawfinder: ignore - m_sendSas = (SendSas)GetProcAddress( m_sasLibrary, "SendSAS" ); + m_sasLibrary = LoadLibrary( sasPath.data() ); // Flawfinder: ignore + m_sendSas = reinterpret_cast( GetProcAddress( m_sasLibrary, "SendSAS" ) ); if( m_sendSas == nullptr ) { @@ -69,11 +69,11 @@ void SasEventListener::stop() void SasEventListener::run() { - HANDLE eventObjects[2] = { m_sasEvent, m_stopEvent }; + std::array eventObjects{ m_sasEvent, m_stopEvent }; while( isInterruptionRequested() == false ) { - int event = WaitForMultipleObjects( 2, eventObjects, false, WaitPeriod ); + const auto event = WaitForMultipleObjects( eventObjects.size(), eventObjects.data(), FALSE, WaitPeriod ); switch( event ) { diff --git a/plugins/platform/windows/SasEventListener.h b/plugins/platform/windows/SasEventListener.h index f54d96e8e..cf1b0c43d 100644 --- a/plugins/platform/windows/SasEventListener.h +++ b/plugins/platform/windows/SasEventListener.h @@ -1,7 +1,7 @@ /* * SasEventListener.h - header file for SasEventListener class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,18 +24,19 @@ #pragma once +#include + #include #include "VeyonCore.h" class SasEventListener : public QThread { + Q_OBJECT public: using SendSas = void (WINAPI *)(BOOL asUser); - enum { - WaitPeriod = 1000 - }; + static constexpr DWORD WaitPeriod = 1000; SasEventListener(); ~SasEventListener() override; diff --git a/plugins/platform/windows/WindowsCoreFunctions.cpp b/plugins/platform/windows/WindowsCoreFunctions.cpp index 2add04816..d4d858d79 100644 --- a/plugins/platform/windows/WindowsCoreFunctions.cpp +++ b/plugins/platform/windows/WindowsCoreFunctions.cpp @@ -1,7 +1,7 @@ /* * WindowsCoreFunctions.cpp - implementation of WindowsCoreFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,6 +23,7 @@ */ #include +#include #include #include @@ -32,33 +33,15 @@ #include "VeyonConfiguration.h" #include "WindowsCoreFunctions.h" #include "WindowsPlatformConfiguration.h" +#include "WindowsPlatformPlugin.h" #include "WtsSessionManager.h" #include "XEventLog.h" -#define SHUTDOWN_FLAGS (SHUTDOWN_FORCE_OTHERS | SHUTDOWN_FORCE_SELF) -#define SHUTDOWN_REASON (SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_FLAG_PLANNED) - -static const int screenSaverSettingsCount = 3; -static const UINT screenSaverSettingsGetList[screenSaverSettingsCount] = -{ - SPI_GETLOWPOWERTIMEOUT, - SPI_GETPOWEROFFTIMEOUT, - SPI_GETSCREENSAVETIMEOUT -}; - -static const UINT screenSaverSettingsSetList[screenSaverSettingsCount] = -{ - SPI_SETLOWPOWERTIMEOUT, - SPI_SETPOWEROFFTIMEOUT, - SPI_SETSCREENSAVETIMEOUT -}; - -static UINT screenSaverSettings[screenSaverSettingsCount]; - static bool configureSoftwareSAS( bool enabled ) { - HKEY hkLocal, hkLocalKey; + HKEY hkLocal; + HKEY hkLocalKey; DWORD dw; if( RegCreateKeyEx( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies", @@ -87,13 +70,6 @@ static bool configureSoftwareSAS( bool enabled ) -WindowsCoreFunctions::WindowsCoreFunctions() : - m_eventLog( nullptr ) -{ -} - - - WindowsCoreFunctions::~WindowsCoreFunctions() { delete m_eventLog; @@ -119,6 +95,10 @@ bool WindowsCoreFunctions::applyConfiguration() void WindowsCoreFunctions::initNativeLoggingSystem( const QString& appName ) { + SetConsoleOutputCP( CP_UTF8 ); + setvbuf( stdout, nullptr, _IOFBF, ConsoleOutputBufferSize ); + setvbuf( stderr, nullptr, _IOFBF, ConsoleOutputBufferSize ); + m_eventLog = new CXEventLog( toConstWCharArray( appName ) ); } @@ -137,7 +117,7 @@ void WindowsCoreFunctions::writeToNativeLoggingSystem( const QString& message, L break; } - if( messageType > 0 ) + if( messageType > 0 && m_eventLog ) { m_eventLog->Write( static_cast( messageType ), toConstWCharArray( message ) ); } @@ -148,7 +128,7 @@ void WindowsCoreFunctions::writeToNativeLoggingSystem( const QString& message, L void WindowsCoreFunctions::reboot() { enablePrivilege( SE_SHUTDOWN_NAME, true ); - InitiateShutdown( nullptr, nullptr, 0, SHUTDOWN_FLAGS | SHUTDOWN_RESTART, SHUTDOWN_REASON ); + InitiateShutdown( nullptr, nullptr, 0, ShutdownFlags | SHUTDOWN_RESTART, ShutdownReason ); } @@ -157,8 +137,8 @@ void WindowsCoreFunctions::powerDown( bool installUpdates ) { enablePrivilege( SE_SHUTDOWN_NAME, true ); InitiateShutdown( nullptr, nullptr, 0, - SHUTDOWN_FLAGS | SHUTDOWN_POWEROFF | ( installUpdates ? SHUTDOWN_INSTALL_UPDATES : 0 ), - SHUTDOWN_REASON ); + ShutdownFlags | SHUTDOWN_POWEROFF | ( installUpdates ? SHUTDOWN_INSTALL_UPDATES : 0 ), + ShutdownReason ); } @@ -182,18 +162,18 @@ static QWindow* windowForWidget( const QWidget* widget ) -void WindowsCoreFunctions::raiseWindow( QWidget* widget ) +void WindowsCoreFunctions::raiseWindow( QWidget* widget, bool stayOnTop ) { widget->activateWindow(); widget->raise(); - QWindow* window = windowForWidget( widget ); + auto window = windowForWidget( widget ); if( window ) { - QPlatformNativeInterface* interfacep = QGuiApplication::platformNativeInterface(); - auto windowHandle = static_cast( interfacep->nativeResourceForWindow( QByteArrayLiteral( "handle" ), window ) ); + auto windowHandle = HWND( QGuiApplication::platformNativeInterface()-> + nativeResourceForWindow( QByteArrayLiteral( "handle" ), window ) ); - SetWindowPos( windowHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); + SetWindowPos( windowHandle, stayOnTop ? HWND_TOPMOST : HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); } } @@ -201,10 +181,10 @@ void WindowsCoreFunctions::raiseWindow( QWidget* widget ) void WindowsCoreFunctions::disableScreenSaver() { - for( int i = 0; i < screenSaverSettingsCount; ++i ) + for( size_t i = 0; i < ScreenSaverSettingsCount; ++i ) { - SystemParametersInfo( screenSaverSettingsGetList[i], 0, &screenSaverSettings[i], 0 ); - SystemParametersInfo( screenSaverSettingsSetList[i], 0, nullptr, 0 ); + SystemParametersInfo( ScreenSaverSettingsGetList.at(i), 0, &m_screenSaverSettings.at(i), 0 ); + SystemParametersInfo( ScreenSaverSettingsSetList.at(i), 0, nullptr, 0 ); } SetThreadExecutionState( ES_CONTINUOUS | ES_DISPLAY_REQUIRED ); @@ -214,9 +194,9 @@ void WindowsCoreFunctions::disableScreenSaver() void WindowsCoreFunctions::restoreScreenSaverSettings() { - for( int i = 0; i < screenSaverSettingsCount; ++i ) + for( size_t i = 0; i < ScreenSaverSettingsCount; ++i ) { - SystemParametersInfo( screenSaverSettingsSetList[i], screenSaverSettings[i], nullptr, 0 ); + SystemParametersInfo( ScreenSaverSettingsSetList.at(i), m_screenSaverSettings.at(i), nullptr, 0 ); } SetThreadExecutionState( ES_CONTINUOUS ); @@ -252,12 +232,10 @@ QString WindowsCoreFunctions::activeDesktopName() auto desktopHandle = GetThreadDesktop( GetCurrentThreadId() ); - wchar_t inputDesktopName[256]; // Flawfinder: ignore - inputDesktopName[0] = 0; - if( GetUserObjectInformation( desktopHandle, UOI_NAME, inputDesktopName, - sizeof( inputDesktopName ) / sizeof( wchar_t ), nullptr ) ) + std::array inputDesktopName{}; + if( GetUserObjectInformation( desktopHandle, UOI_NAME, inputDesktopName.data(), inputDesktopName.size(), nullptr ) ) { - desktopName = QString( QStringLiteral( "winsta0\\%1" ) ).arg( QString::fromWCharArray( inputDesktopName ) ); + desktopName = QString( QStringLiteral( "winsta0\\%1" ) ).arg( QString::fromWCharArray( inputDesktopName.data() ) ); } return desktopName; @@ -299,7 +277,7 @@ bool WindowsCoreFunctions::runProgramAsAdmin( const QString& program, const QStr { const auto parametersJoined = parameters.join( QLatin1Char(' ') ); - SHELLEXECUTEINFO sei{0}; + SHELLEXECUTEINFO sei{}; sei.cbSize = sizeof(sei); sei.lpVerb = L"runas"; sei.lpFile = toConstWCharArray( program ); @@ -324,14 +302,14 @@ bool WindowsCoreFunctions::runProgramAsUser( const QString& program, { vDebug() << program << parameters << username << desktop; - const auto baseProcessId = WtsSessionManager::findProcessId( username ); + const auto baseProcessId = WtsSessionManager::findUserProcessId( username ); if( baseProcessId == WtsSessionManager::InvalidProcess ) { vCritical() << "could not determine base process ID for user" << username; return false; } - auto processHandle = runProgramInSession( program, parameters, sessionIdEnvironment(), baseProcessId, desktop ); + auto processHandle = runProgramInSession( program, parameters, {}, baseProcessId, desktop ); if( processHandle ) { CloseHandle( processHandle ); @@ -350,6 +328,101 @@ QString WindowsCoreFunctions::genericUrlHandler() const +QString WindowsCoreFunctions::queryDisplayDeviceName(const QScreen& screen) const +{ + if(screen.name().isEmpty()) + { + return {}; + } + + const auto screenDeviceName = toConstWCharArray(screen.name()); + + UINT32 requiredPaths, requiredModes; + GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &requiredPaths, &requiredModes); + std::vector paths(requiredPaths); + std::vector modes(requiredModes); + QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &requiredPaths, paths.data(), &requiredModes, modes.data(), nullptr); + + for(const auto& p : paths) + { + DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName{}; + sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME; + sourceName.header.size = sizeof(sourceName); + sourceName.header.adapterId = p.sourceInfo.adapterId; + sourceName.header.id = p.sourceInfo.id; + DisplayConfigGetDeviceInfo(&sourceName.header); + + if(wcscmp(screenDeviceName, sourceName.viewGdiDeviceName) == 0) + { + DISPLAYCONFIG_TARGET_DEVICE_NAME name{}; + name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; + name.header.size = sizeof(name); + name.header.adapterId = p.sourceInfo.adapterId; + name.header.id = p.targetInfo.id; + DisplayConfigGetDeviceInfo(&name.header); + + const auto monitorFriendlyDeviceName = QString::fromWCharArray(name.monitorFriendlyDeviceName); + const auto outputName = [&]() -> QString { + switch(name.outputTechnology) + { + case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI: + return QStringLiteral("HDMI-%1").arg(name.connectorInstance); + case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI: + return QStringLiteral("DVI-%1").arg(name.connectorInstance); + case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED: + return QStringLiteral("eDP-%1").arg(name.connectorInstance); + case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL: + return QStringLiteral("DP-%1").arg(name.connectorInstance); + case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS: + return QStringLiteral("LVDS-%1").arg(name.connectorInstance); +#if __MINGW64_VERSION_MAJOR < 8 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wswitch" + case 15: +#pragma GCC diagnostic pop +#else + case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST: +#endif + return QStringLiteral("Miracast-%1").arg(name.connectorInstance); + case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO: + return QStringLiteral("S-Video-%1").arg(name.connectorInstance); + case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL: + return WindowsPlatformPlugin::tr("Internal display") + + ( name.connectorInstance > 1 ? + QStringLiteral(" %2").arg(name.connectorInstance) : QString{} ); + default: + break; + } + return {}; + }(); + if(monitorFriendlyDeviceName.isEmpty()) + { + if(outputName.isEmpty() == false) + { + return outputName; + } + // use display device string as fallback + } + else + { + return monitorFriendlyDeviceName + + ( outputName.isEmpty() ? QString {} : QStringLiteral(" [%1]").arg(outputName) ); + } + } + } + + DISPLAY_DEVICE displayDevice{}; + displayDevice.cb = sizeof(displayDevice); + if(EnumDisplayDevices(screenDeviceName, 0, &displayDevice, 0)) + { + return QString::fromWCharArray(displayDevice.DeviceString); + } + + return {}; +} + + + bool WindowsCoreFunctions::enablePrivilege( LPCWSTR privilegeName, bool enable ) { HANDLE token; @@ -359,11 +432,13 @@ bool WindowsCoreFunctions::enablePrivilege( LPCWSTR privilegeName, bool enable ) if( !OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_READ, &token ) ) { + vCritical() << "could not open process token"; return false; } if( !LookupPrivilegeValue( nullptr, privilegeName, &luid ) ) { + vCritical() << "could not lookup privilege value"; return false; } @@ -371,7 +446,7 @@ bool WindowsCoreFunctions::enablePrivilege( LPCWSTR privilegeName, bool enable ) tokenPrivileges.Privileges[0].Luid = luid; tokenPrivileges.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; - bool ret = AdjustTokenPrivileges( token, false, &tokenPrivileges, 0, nullptr, nullptr ); + const auto ret = AdjustTokenPrivileges( token, false, &tokenPrivileges, 0, nullptr, nullptr ); CloseHandle( token ); @@ -386,7 +461,7 @@ QSharedPointer WindowsCoreFunctions::toWCharArray( const QString& qstri qstring.toWCharArray( wcharArray ); wcharArray[qstring.size()] = 0; - return { wcharArray, []( wchar_t* buffer ) { delete[] buffer; } }; + return { wcharArray, []( const wchar_t* buffer ) { delete[] buffer; } }; } @@ -516,48 +591,115 @@ HANDLE WindowsCoreFunctions::runProgramInSession( const QString& program, -QStringList WindowsCoreFunctions::sessionIdEnvironment() +QStringList WindowsCoreFunctions::queryProcessEnvironmentVariables(DWORD processId) +{ + const auto processHandle = OpenProcess(PROCESS_QUERY_INFORMATION, false, processId); + if (processHandle == nullptr) + { + vCritical() << "OpenProcess()" << GetLastError(); + return {}; + } + + HANDLE processToken = nullptr; + if (OpenProcessToken(processHandle, MAXIMUM_ALLOWED, &processToken ) == false) + { + vCritical() << "OpenProcessToken()" << GetLastError(); + CloseHandle(processHandle); + return {}; + } + + LPVOID envBlock = nullptr; + if (CreateEnvironmentBlock(&envBlock, processToken, false) == false || + envBlock == nullptr) + { + vCritical() << "CreateEnvironmentBlock()" << GetLastError(); + CloseHandle(processHandle); + CloseHandle(processToken); + return {}; + } + + const auto env = reinterpret_cast(envBlock); + size_t envPos = 0; + size_t envCurVarStart = 0; + + QStringList envVars; + while (envPos < MaximumEnvironmentBlockSize-1 && !(env[envPos] == 0 && env[envPos+1] == 0)) + { + if (env[envPos] == 0) + { + envVars.append(QString::fromWCharArray(env + envCurVarStart)); + envCurVarStart = envPos+1; + } + ++envPos; + } + + DestroyEnvironmentBlock(envBlock); + CloseHandle(processHandle); + CloseHandle(processToken); + + return envVars; +} + + + +bool WindowsCoreFunctions::terminateProcess( ProcessId processId, DWORD timeout ) { - if( VeyonCore::config().multiSessionModeEnabled() ) + if( processId != WtsSessionManager::InvalidProcess ) { - auto currentSession = WtsSessionManager::currentSession(); - if( currentSession != WtsSessionManager::activeConsoleSession() ) + const auto processHandle = OpenProcess( PROCESS_TERMINATE, false, processId ); + if( processHandle ) { - return { QStringLiteral("%1=%2"). - arg( VeyonCore::sessionIdEnvironmentVariable() ). - arg( currentSession % 100 ) }; + const auto result = TerminateProcess( processHandle, 0 ); + WaitForSingleObject( processHandle, timeout ); + CloseHandle( processHandle ); + + return result; } + + vCritical() << "could not open process with ID" << processId; } - return {}; + return false; } wchar_t* WindowsCoreFunctions::appendToEnvironmentBlock( const wchar_t* env, const QStringList& strings ) { - static constexpr auto ENV_POS_MAX = 1024*1024; + if (env == nullptr) + { + return nullptr; + } + + static constexpr auto MaximumExtraStringsLength = 1024*1024; size_t envPos = 0; - while( envPos < ENV_POS_MAX-1 && !(env[envPos] == 0 && env[envPos+1] == 0) ) + while (envPos < MaximumEnvironmentBlockSize-1 && !(env[envPos] == 0 && env[envPos+1] == 0)) { ++envPos; } ++envPos; - if( envPos >= ENV_POS_MAX-1 ) + if (envPos >= MaximumEnvironmentBlockSize-1) + { + return nullptr; + } + + const auto stringsTotalLength = size_t( strings.join( QLatin1Char(' ') ).size() ); + if( stringsTotalLength >= MaximumExtraStringsLength ) { return nullptr; } - auto newEnv = new wchar_t[envPos+static_cast( strings.join( QLatin1Char(' ') ).size())+2]; - memcpy( newEnv, env, envPos*2 ); + auto newEnv = new wchar_t[envPos + stringsTotalLength + 2]; + memcpy( newEnv, env, envPos*2 ); // Flawfinder: ignore for( const auto& string : strings ) { - memcpy( &newEnv[envPos], toConstWCharArray( string ), static_cast( string.size()*2 ) ); - envPos += static_cast( string.size() ); + const auto stringLength = size_t(string.size()); + memcpy( &newEnv[envPos], toConstWCharArray( string ), stringLength * sizeof(wchar_t) ); // Flawfinder: ignore + envPos += stringLength; newEnv[envPos] = 0; ++envPos; } diff --git a/plugins/platform/windows/WindowsCoreFunctions.h b/plugins/platform/windows/WindowsCoreFunctions.h index 12fa0521b..d81b2805c 100644 --- a/plugins/platform/windows/WindowsCoreFunctions.h +++ b/plugins/platform/windows/WindowsCoreFunctions.h @@ -1,7 +1,7 @@ /* * WindowsCoreFunctions.h - declaration of WindowsCoreFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -35,7 +35,9 @@ class CXEventLog; class WindowsCoreFunctions : public PlatformCoreFunctions { public: - WindowsCoreFunctions(); + using ProcessId = DWORD; + + WindowsCoreFunctions() = default; ~WindowsCoreFunctions() override; bool applyConfiguration() override; @@ -46,7 +48,7 @@ class WindowsCoreFunctions : public PlatformCoreFunctions void reboot() override; void powerDown( bool installUpdates ) override; - void raiseWindow( QWidget* widget ) override; + void raiseWindow( QWidget* widget, bool stayOnTop ) override; void disableScreenSaver() override; void restoreScreenSaverSettings() override; @@ -65,6 +67,8 @@ class WindowsCoreFunctions : public PlatformCoreFunctions QString genericUrlHandler() const override; + QString queryDisplayDeviceName(const QScreen& screen) const override; + static bool enablePrivilege( LPCWSTR privilegeName, bool enable ); static QSharedPointer toWCharArray( const QString& qstring ); @@ -76,14 +80,38 @@ class WindowsCoreFunctions : public PlatformCoreFunctions DWORD baseProcessId, const QString& desktop ); - static QStringList sessionIdEnvironment(); + static QStringList queryProcessEnvironmentVariables(DWORD processId); + + static bool terminateProcess( ProcessId processId, DWORD timeout = DefaultProcessTerminationTimeout ); private: + static constexpr int ConsoleOutputBufferSize = 256; + static constexpr DWORD DefaultProcessTerminationTimeout = 5000; + static constexpr size_t ScreenSaverSettingsCount = 3; + + static constexpr auto MaximumEnvironmentBlockSize = 1024*1024; + + static constexpr auto ShutdownFlags = SHUTDOWN_FORCE_OTHERS | SHUTDOWN_FORCE_SELF; + static constexpr auto ShutdownReason = SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_FLAG_PLANNED; + + const std::array ScreenSaverSettingsGetList = { + SPI_GETLOWPOWERTIMEOUT, + SPI_GETPOWEROFFTIMEOUT, + SPI_GETSCREENSAVETIMEOUT + }; + + const std::array ScreenSaverSettingsSetList = { + SPI_SETLOWPOWERTIMEOUT, + SPI_SETPOWEROFFTIMEOUT, + SPI_SETSCREENSAVETIMEOUT + }; + static wchar_t* appendToEnvironmentBlock( const wchar_t* env, const QStringList& strings ); static void setTaskbarState( bool enabled ); static void setStartMenuState( bool enabled ); static void setDesktopState( bool enabled ); - CXEventLog* m_eventLog; + CXEventLog* m_eventLog{nullptr}; + std::array m_screenSaverSettings{}; }; diff --git a/plugins/platform/windows/WindowsFilesystemFunctions.cpp b/plugins/platform/windows/WindowsFilesystemFunctions.cpp index bc3bfceb8..6678019ce 100644 --- a/plugins/platform/windows/WindowsFilesystemFunctions.cpp +++ b/plugins/platform/windows/WindowsFilesystemFunctions.cpp @@ -1,7 +1,7 @@ /* * WindowsFilesystemFunctions.cpp - implementation of WindowsFilesystemFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,12 +27,13 @@ #include #include #include +#include #include "WindowsCoreFunctions.h" #include "WindowsFilesystemFunctions.h" -static QString windowsConfigPath( REFKNOWNFOLDERID folderId ) +static QString windowsConfigPath( const KNOWNFOLDERID folderId ) { QString result; @@ -95,8 +96,8 @@ QString WindowsFilesystemFunctions::fileOwnerGroup( const QString& filePath ) return {}; } - wchar_t* name = new wchar_t[nameSize]; - wchar_t* domain = new wchar_t[domainSize]; + auto name = new wchar_t[nameSize]; + auto domain = new wchar_t[domainSize]; if( LookupAccountSid( nullptr, ownerSID, name, &nameSize, domain, &domainSize, &sidNameUse ) == false ) { @@ -119,15 +120,15 @@ QString WindowsFilesystemFunctions::fileOwnerGroup( const QString& filePath ) bool WindowsFilesystemFunctions::setFileOwnerGroup( const QString& filePath, const QString& ownerGroup ) { DWORD sidLen = SECURITY_MAX_SID_SIZE; - char ownerGroupSID[SECURITY_MAX_SID_SIZE]; // Flawfinder: ignore - wchar_t domain[PATH_MAX]; // Flawfinder: ignore - domain[0] = 0; - DWORD domainLen = PATH_MAX; + std::array ownerGroupSID{}; + std::array domain{}; + + DWORD domainLen = domain.size(); SID_NAME_USE sidNameUse; if( LookupAccountName( nullptr, WindowsCoreFunctions::toConstWCharArray( ownerGroup ), - ownerGroupSID, &sidLen, - domain, &domainLen, &sidNameUse ) == false ) + ownerGroupSID.data(), &sidLen, + domain.data(), &domainLen, &sidNameUse ) == false ) { vCritical() << "Could not look up SID structure:" << GetLastError(); return false; @@ -139,7 +140,7 @@ bool WindowsFilesystemFunctions::setFileOwnerGroup( const QString& filePath, con const auto filePathWide = WindowsCoreFunctions::toWCharArray( filePath ); const auto result = SetNamedSecurityInfo( filePathWide.data(), SE_FILE_OBJECT, - OWNER_SECURITY_INFORMATION, ownerGroupSID, nullptr, nullptr, nullptr ); + OWNER_SECURITY_INFORMATION, ownerGroupSID.data(), nullptr, nullptr, nullptr ); if( result != ERROR_SUCCESS ) { @@ -178,10 +179,8 @@ bool WindowsFilesystemFunctions::setFileOwnerGroupPermissions( const QString& fi return false; } - const int NUM_ACES = 2; - EXPLICIT_ACCESS ea[NUM_ACES]; - - ZeroMemory( &ea, NUM_ACES * sizeof(EXPLICIT_ACCESS) ); + static constexpr auto ExplicitAccessCount = 2; + std::array ea{}; // set read access for owner ea[0].grfAccessPermissions = 0; @@ -201,7 +200,7 @@ bool WindowsFilesystemFunctions::setFileOwnerGroupPermissions( const QString& fi ea[0].grfInheritance = NO_INHERITANCE; ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[0].Trustee.TrusteeType = TRUSTEE_IS_GROUP; - ea[0].Trustee.ptstrName = (LPTSTR) ownerSID; + ea[0].Trustee.ptstrName = LPTSTR(ownerSID); // set full control for Administrators ea[1].grfAccessPermissions = GENERIC_ALL; @@ -209,10 +208,10 @@ bool WindowsFilesystemFunctions::setFileOwnerGroupPermissions( const QString& fi ea[1].grfInheritance = NO_INHERITANCE; ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; - ea[1].Trustee.ptstrName = (LPTSTR) adminSID; + ea[1].Trustee.ptstrName = LPTSTR(adminSID); PACL acl = nullptr; - if( SetEntriesInAcl( NUM_ACES, ea, nullptr, &acl ) != ERROR_SUCCESS ) + if( SetEntriesInAcl( ExplicitAccessCount, ea.data(), nullptr, &acl ) != ERROR_SUCCESS ) { vCritical() << "SetEntriesInAcl() failed"; FreeSid( adminSID ); @@ -233,3 +232,24 @@ bool WindowsFilesystemFunctions::setFileOwnerGroupPermissions( const QString& fi return result == ERROR_SUCCESS; } + + + +bool WindowsFilesystemFunctions::openFileSafely( QFile* file, QIODevice::OpenMode openMode, QFileDevice::Permissions permissions ) +{ + if( file == nullptr ) + { + return false; + } + + if( file->open( openMode ) && + file->symLinkTarget().isEmpty() && + file->setPermissions( permissions ) ) + { + return true; + } + + file->close(); + + return false; +} diff --git a/plugins/platform/windows/WindowsFilesystemFunctions.h b/plugins/platform/windows/WindowsFilesystemFunctions.h index f77411b95..54815e7a3 100644 --- a/plugins/platform/windows/WindowsFilesystemFunctions.h +++ b/plugins/platform/windows/WindowsFilesystemFunctions.h @@ -1,7 +1,7 @@ /* * WindowsFilesystemFunctions.h - declaration of WindowsFilesystemFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -39,4 +39,6 @@ class WindowsFilesystemFunctions : public PlatformFilesystemFunctions bool setFileOwnerGroup( const QString& filePath, const QString& ownerGroup ) override; bool setFileOwnerGroupPermissions( const QString& filePath, QFile::Permissions permissions ) override; + bool openFileSafely( QFile* file, QFile::OpenMode openMode, QFile::Permissions permissions ) override; + }; diff --git a/plugins/platform/windows/WindowsInputDeviceFunctions.cpp b/plugins/platform/windows/WindowsInputDeviceFunctions.cpp index 8cd46229a..a7f6b2d4c 100644 --- a/plugins/platform/windows/WindowsInputDeviceFunctions.cpp +++ b/plugins/platform/windows/WindowsInputDeviceFunctions.cpp @@ -1,7 +1,7 @@ /* * WindowsInputDeviceFunctions.cpp - implementation of WindowsInputDeviceFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -29,8 +29,22 @@ #include "ConfigurationManager.h" #include "PlatformServiceFunctions.h" +#include "ProcessHelper.h" +#include "VeyonConfiguration.h" +#include "WindowsCoreFunctions.h" #include "WindowsInputDeviceFunctions.h" #include "WindowsKeyboardShortcutTrapper.h" +#include "WindowsPlatformConfiguration.h" +#include "WtsSessionManager.h" + + +class Powercfg : public ProcessHelper +{ +public: + Powercfg(const QStringList& arguments) : ProcessHelper(QStringLiteral("powercfg"), arguments) + { + } +}; static int interception_is_any( InterceptionDevice device ) @@ -42,17 +56,6 @@ static int interception_is_any( InterceptionDevice device ) -WindowsInputDeviceFunctions::WindowsInputDeviceFunctions() : - m_inputDevicesDisabled( false ), - m_interceptionContext( nullptr ), - m_hidServiceName( QStringLiteral("hidserv") ), - m_hidServiceStatusInitialized( false ), - m_hidServiceActivated( false ) -{ -} - - - WindowsInputDeviceFunctions::~WindowsInputDeviceFunctions() { if( m_inputDevicesDisabled ) @@ -69,6 +72,7 @@ void WindowsInputDeviceFunctions::enableInputDevices() { disableInterception(); restoreHIDService(); + restorePowerScheme(); m_inputDevicesDisabled = false; } @@ -82,6 +86,7 @@ void WindowsInputDeviceFunctions::disableInputDevices() { enableInterception(); stopHIDService(); + setCustomPowerScheme(); m_inputDevicesDisabled = true; } @@ -98,30 +103,51 @@ KeyboardShortcutTrapper* WindowsInputDeviceFunctions::createKeyboardShortcutTrap void WindowsInputDeviceFunctions::checkInterceptionInstallation() { - const auto context = interception_create_context(); - if( context ) + if( VeyonCore::config().multiSessionModeEnabled() ) { - // a valid context means the interception driver is installed properly - // so nothing to do here - interception_destroy_context( context ); + uninstallInterception(); } - // try to (re)install interception driver - else if( installInterception() == false ) + else if( WindowsPlatformConfiguration( &VeyonCore::config() ).useInterceptionDriver() ) { - // failed to uninstall it so we can try to install it again on next reboot - uninstallInterception(); + const auto context = interception_create_context(); + if( context ) + { + // a valid context means the interception driver is installed properly + // so nothing to do here + interception_destroy_context( context ); + } + // try to (re)install interception driver + else if( installInterception() == false ) + { + // failed to uninstall it so we can try to install it again on next reboot + uninstallInterception(); + } } } -void WindowsInputDeviceFunctions::enableInterception() +void WindowsInputDeviceFunctions::stopOnScreenKeyboard() { - m_interceptionContext = interception_create_context(); + WindowsCoreFunctions::terminateProcess( WtsSessionManager::findProcessId( QStringLiteral("osk.exe") ) ); + WindowsCoreFunctions::terminateProcess( WtsSessionManager::findProcessId( QStringLiteral("tabtip.exe") ) ); +} + - interception_set_filter( m_interceptionContext, - interception_is_any, - INTERCEPTION_FILTER_KEY_ALL | INTERCEPTION_FILTER_MOUSE_ALL ); + +void WindowsInputDeviceFunctions::enableInterception() +{ + if( WindowsPlatformConfiguration( &VeyonCore::config() ).useInterceptionDriver() ) + { + m_interceptionContext = interception_create_context(); + + if( m_interceptionContext ) + { + interception_set_filter( m_interceptionContext, + interception_is_any, + INTERCEPTION_FILTER_KEY_ALL | INTERCEPTION_FILTER_MOUSE_ALL ); + } + } } @@ -159,6 +185,43 @@ void WindowsInputDeviceFunctions::restoreHIDService() +void WindowsInputDeviceFunctions::setCustomPowerScheme() +{ + if (WindowsPlatformConfiguration(&VeyonCore::config()).useCustomPowerSchemeForScreenLock() == false || + m_originalPowerSchemeId.isEmpty() == false) + { + return; + } + + QUuid activeSchemeId{Powercfg{{QStringLiteral("/getactivescheme")}}.runAndReadAll().split(':').value(1).trimmed().split(' ').constFirst()}; + if (activeSchemeId.isNull() || activeSchemeId == CustomPowerSchemeId) + { + return; + } + + m_originalPowerSchemeId = activeSchemeId.toString(QUuid::WithoutBraces); + Powercfg{{QStringLiteral("/delete"), CustomPowerSchemeIdString}}.run(); + Powercfg{{QStringLiteral("/duplicatescheme"), m_originalPowerSchemeId, CustomPowerSchemeIdString}}.run(); + Powercfg{{QStringLiteral("/setacvalueindex"), CustomPowerSchemeIdString, + QStringLiteral("4f971e89-eebd-4455-a8de-9e59040e7347"), QStringLiteral("7648efa3-dd9c-4e3e-b566-50f929386280"), QStringLiteral("0")}}.run(); + Powercfg{{QStringLiteral("/setdcvalueindex"), CustomPowerSchemeIdString, + QStringLiteral("4f971e89-eebd-4455-a8de-9e59040e7347"), QStringLiteral("7648efa3-dd9c-4e3e-b566-50f929386280"), QStringLiteral("0")}}.run(); + Powercfg{{QStringLiteral("/setactive"), CustomPowerSchemeIdString}}.run(); +} + + + +void WindowsInputDeviceFunctions::restorePowerScheme() +{ + if (m_originalPowerSchemeId.isNull() == false) + { + Powercfg{{QStringLiteral("/setactive"), m_originalPowerSchemeId}}.run(); + Powercfg{{QStringLiteral("/delete"), CustomPowerSchemeIdString}}.run(); + } +} + + + void WindowsInputDeviceFunctions::stopHIDService() { initHIDServiceStatus(); diff --git a/plugins/platform/windows/WindowsInputDeviceFunctions.h b/plugins/platform/windows/WindowsInputDeviceFunctions.h index 357e4952f..734ace705 100644 --- a/plugins/platform/windows/WindowsInputDeviceFunctions.h +++ b/plugins/platform/windows/WindowsInputDeviceFunctions.h @@ -1,7 +1,7 @@ /* * WindowsInputDeviceFunctions.h - declaration of WindowsInputDeviceFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -33,8 +33,8 @@ class WindowsInputDeviceFunctions : public PlatformInputDeviceFunctions { public: - WindowsInputDeviceFunctions(); - ~WindowsInputDeviceFunctions(); + WindowsInputDeviceFunctions() = default; + virtual ~WindowsInputDeviceFunctions(); void enableInputDevices() override; void disableInputDevices() override; @@ -43,21 +43,31 @@ class WindowsInputDeviceFunctions : public PlatformInputDeviceFunctions static void checkInterceptionInstallation(); + static void stopOnScreenKeyboard(); + private: + const QUuid CustomPowerSchemeId{QStringLiteral("2699bf3e-30c6-4c74-914a-47d4504203f6")}; + const QString CustomPowerSchemeIdString = CustomPowerSchemeId.toString(QUuid::WithoutBraces); + + static constexpr auto OnScreenKeyboardTerminateTimeout = 5000; + void enableInterception(); void disableInterception(); void initHIDServiceStatus(); void stopHIDService(); void restoreHIDService(); + void setCustomPowerScheme(); + void restorePowerScheme(); static bool installInterception(); static bool uninstallInterception(); static int interceptionInstaller( const QString& argument ); - bool m_inputDevicesDisabled; - InterceptionContext m_interceptionContext; - QString m_hidServiceName; - bool m_hidServiceStatusInitialized; - bool m_hidServiceActivated; + bool m_inputDevicesDisabled{false}; + InterceptionContext m_interceptionContext{nullptr}; + QString m_hidServiceName{QStringLiteral("hidserv")}; + bool m_hidServiceStatusInitialized{false}; + bool m_hidServiceActivated{false}; + QString m_originalPowerSchemeId{}; }; diff --git a/plugins/platform/windows/WindowsKeyboardShortcutTrapper.cpp b/plugins/platform/windows/WindowsKeyboardShortcutTrapper.cpp index 6a50beb60..14d20e4b6 100644 --- a/plugins/platform/windows/WindowsKeyboardShortcutTrapper.cpp +++ b/plugins/platform/windows/WindowsKeyboardShortcutTrapper.cpp @@ -1,7 +1,7 @@ /* * WindowsKeyboardShortcutTrapper.cpp - class for trapping shortcuts on Windows * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -105,7 +105,6 @@ LRESULT CALLBACK TaskKeyHookLL( int nCode, WPARAM wp, LPARAM lp ) WindowsKeyboardShortcutTrapper::WindowsKeyboardShortcutTrapper( QObject* parent ) : KeyboardShortcutTrapper( parent ), - m_enabled( false ), m_pollTimer( this ) { connect( &m_pollTimer, &QTimer::timeout, @@ -167,6 +166,6 @@ void WindowsKeyboardShortcutTrapper::forwardTrappedShortcuts() while( __trappedShortcuts.isEmpty() == false ) { - emit shortcutTrapped( __trappedShortcuts.takeFirst() ); + Q_EMIT shortcutTrapped( __trappedShortcuts.takeFirst() ); } } diff --git a/plugins/platform/windows/WindowsKeyboardShortcutTrapper.h b/plugins/platform/windows/WindowsKeyboardShortcutTrapper.h index 7dd68d176..2cc003c83 100644 --- a/plugins/platform/windows/WindowsKeyboardShortcutTrapper.h +++ b/plugins/platform/windows/WindowsKeyboardShortcutTrapper.h @@ -1,7 +1,7 @@ /* * WindowsKeyboardShortcutTrapper.cpp - class for trapping shortcuts on Windows * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -46,7 +46,7 @@ class WindowsKeyboardShortcutTrapper : public KeyboardShortcutTrapper static QMutex s_refCntMutex; static int s_refCnt; - bool m_enabled; + bool m_enabled{false}; QTimer m_pollTimer; } ; diff --git a/plugins/platform/windows/WindowsNetworkFunctions.cpp b/plugins/platform/windows/WindowsNetworkFunctions.cpp index ecccdc665..07b30b40f 100644 --- a/plugins/platform/windows/WindowsNetworkFunctions.cpp +++ b/plugins/platform/windows/WindowsNetworkFunctions.cpp @@ -1,7 +1,7 @@ /* * WindowsNetworkFunctions.cpp - implementation of WindowsNetworkFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,9 +27,15 @@ #include #include #include +#include +#include +#include +#include +#include #include +#include "HostAddress.h" #include "WindowsCoreFunctions.h" #include "WindowsNetworkFunctions.h" @@ -188,7 +194,7 @@ static bool configureFirewallException( INetFwPolicy2* fwPolicy2, const wchar_t* if( hr != S_OK ) { // failed because firewall service not running / disabled? - if( hr == static_cast( 0x800706D9 ) ) + if( hr == WindowsNetworkFunctions::WindowsFirewallServiceError ) { // then assume this is intended, log a warning and // pretend everything went well @@ -206,13 +212,44 @@ static bool configureFirewallException( INetFwPolicy2* fwPolicy2, const wchar_t* -bool WindowsNetworkFunctions::ping( const QString& hostAddress ) +WindowsNetworkFunctions::WindowsNetworkFunctions() : PlatformNetworkFunctions() { - QProcess pingProcess; - pingProcess.start( QStringLiteral("ping"), { QStringLiteral("-n"), QStringLiteral("1"), QStringLiteral("-w"), QString::number( PingTimeout ), hostAddress } ); - pingProcess.waitForFinished( PingProcessTimeout ); + WSADATA wsadata; + const auto error = WSAStartup( MAKEWORD(2,0), &wsadata ); + if( error != S_OK ) + { + vCritical() << "failed to initialize WinSock:" << error; + } +} + + + +WindowsNetworkFunctions::PingResult WindowsNetworkFunctions::ping(const QString& hostAddress) +{ + auto result = PingResult::Unknown; + + const auto ipAddress = HostAddress(hostAddress).convert(HostAddress::Type::IpAddress); + if (ipAddress.isEmpty() == false) + { + const auto addressProtocol = QHostAddress(ipAddress).protocol(); + + if (addressProtocol == QAbstractSocket::IPv4Protocol && pingIPv4Address(ipAddress, &result)) + { + return result; + } + + if (addressProtocol == QAbstractSocket::IPv6Protocol && pingIPv6Address(ipAddress, &result)) + { + return result; + } + } + + if (pingViaUtility(hostAddress, &result)) + { + return result; + } - return pingProcess.exitCode() == 0; + return PingResult::Unknown; } @@ -296,3 +333,188 @@ bool WindowsNetworkFunctions::configureSocketKeepalive( Socket socket, bool enab return true; } + + + +bool WindowsNetworkFunctions::pingIPv4Address(const QString& hostAddress, PingResult* result) +{ + if( result == nullptr ) + { + return false; + } + + *result = PingResult::Unknown; + + const IPAddr ipAddress = inet_addr(hostAddress.toLatin1().constData()); + if( ipAddress == INADDR_NONE ) + { + return false; + } + + const auto icmpHandle = IcmpCreateFile(); + if( icmpHandle == INVALID_HANDLE_VALUE ) + { + IcmpCloseHandle(icmpHandle); + return false; + } + + std::array sendData{'V', 'e', 'y', 'o', 'n', 0}; + std::array replyBuffer; + + const auto success = IcmpSendEcho(icmpHandle, ipAddress, sendData.data(), sendData.size(), + nullptr, replyBuffer.data(), replyBuffer.size(), PingTimeout) > 0 && + reinterpret_cast(replyBuffer.data())->Status == IP_SUCCESS; + + const auto error = GetLastError(); + + IcmpCloseHandle(icmpHandle); + + if( success ) + { + *result = PingResult::ReplyReceived; + return true; + } + + if (error == IP_REQ_TIMED_OUT) + { + *result = PingResult::TimedOut; + return true; + } + + return false; +} + + + +bool WindowsNetworkFunctions::pingIPv6Address(const QString& hostAddress, PingResult* result) +{ + if( result == nullptr ) + { + return false; + } + + *result = PingResult::Unknown; + + SOCKADDR_IN6 icmp6LocalAddr{}; + icmp6LocalAddr.sin6_addr = in6addr_any; + icmp6LocalAddr.sin6_family = AF_INET6; + + SOCKADDR_IN6 icmp6RemoteAddr{}; + struct addrinfo hints{}; + struct addrinfo *res = nullptr; + + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_STREAM; + + if( getaddrinfo(hostAddress.toLatin1().constData(), nullptr, &hints, &res) != 0 ) + { + return false; + } + + auto resalloc = res; + + while( res != nullptr ) + { + if( res->ai_family == AF_INET6 ) + { + memcpy( &icmp6RemoteAddr, res->ai_addr, res->ai_addrlen ); + icmp6RemoteAddr.sin6_family = AF_INET6; + break; + } + + res = res->ai_next; + } + + freeaddrinfo(resalloc); + + if( icmp6RemoteAddr.sin6_family != AF_INET6 ) + { + return false; + } + + const auto icmpFile = Icmp6CreateFile(); + if( icmpFile == INVALID_HANDLE_VALUE ) + { + return false; + } + + using ICMPV6_ECHO_REPLY = struct { + IPV6_ADDRESS_EX Address; + ULONG Status; + unsigned int RoundTripTime; + }; + + std::array sendData{'V', 'e', 'y', 'o', 'n', 0}; + std::array replyBuffer; + + const auto success = Icmp6SendEcho2(icmpFile, nullptr, nullptr, nullptr, + &icmp6LocalAddr, + &icmp6RemoteAddr, + sendData.data(), sendData.size(), + nullptr, replyBuffer.data(), replyBuffer.size(), PingTimeout) > 0 && + reinterpret_cast(replyBuffer.data())->Status == IP_SUCCESS; + + const auto error = GetLastError(); + + IcmpCloseHandle(icmpFile); + + if( success ) + { + *result = PingResult::ReplyReceived; + return true; + } + + if (error == IP_REQ_TIMED_OUT) + { + *result = PingResult::TimedOut; + return true; + } + + return false; +} + + + +bool WindowsNetworkFunctions::pingViaUtility(const QString& hostAddress, PingResult* result) +{ + if (result == nullptr) + { + return false; + } + + *result = PingResult::Unknown; + + const QStringList pingArguments = { + QStringLiteral("-n"), QStringLiteral("1"), + QStringLiteral("-w"), QString::number(PingTimeout), + hostAddress + }; + + QProcess pingProcess; + pingProcess.start(QStringLiteral("ping"), pingArguments); + if (pingProcess.waitForStarted(PingProcessTimeout)) + { + if (pingProcess.waitForFinished(PingProcessTimeout)) + { + if (QString::fromUtf8(pingProcess.readAll()).split(QLatin1Char('\n')).filter(QStringLiteral("=")).size() >= 2) + { + *result = PingResult::ReplyReceived; + } + else if (pingProcess.exitCode() == 1) + { + *result = PingResult::NameResolutionFailed; + } + else + { + *result = PingResult::TimedOut; + } + } + else + { + *result = PingResult::NameResolutionFailed; + } + return true; + } + + return false; +} diff --git a/plugins/platform/windows/WindowsNetworkFunctions.h b/plugins/platform/windows/WindowsNetworkFunctions.h index 77bd618a4..d86144c40 100644 --- a/plugins/platform/windows/WindowsNetworkFunctions.h +++ b/plugins/platform/windows/WindowsNetworkFunctions.h @@ -1,7 +1,7 @@ /* * WindowsNetworkFunctions.h - declaration of WindowsNetworkFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,14 +26,25 @@ #include "PlatformNetworkFunctions.h" +#include + // clazy:exclude=copyable-polymorphic class WindowsNetworkFunctions : public PlatformNetworkFunctions { public: - bool ping( const QString& hostAddress ) override; + WindowsNetworkFunctions(); + + PingResult ping(const QString& hostAddress) override; bool configureFirewallException( const QString& applicationPath, const QString& description, bool enabled ) override; bool configureSocketKeepalive( Socket socket, bool enabled, int idleTime, int interval, int probes ) override; + static constexpr auto WindowsFirewallServiceError = HRESULT(0x800706D9); + +private: + bool pingIPv4Address(const QString& hostAddress, PingResult* result); + bool pingIPv6Address(const QString& hostAddress, PingResult* result); + bool pingViaUtility(const QString& hostAddress, PingResult* result); + }; diff --git a/plugins/platform/windows/WindowsPlatformConfiguration.h b/plugins/platform/windows/WindowsPlatformConfiguration.h index ca21385ac..452d001b7 100644 --- a/plugins/platform/windows/WindowsPlatformConfiguration.h +++ b/plugins/platform/windows/WindowsPlatformConfiguration.h @@ -1,7 +1,7 @@ /* * WindowsPlatformConfiguration.h - configuration values for WindowsPlatform plugin * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,13 +25,19 @@ #pragma once #include "Configuration/Proxy.h" +#include "WindowsSessionFunctions.h" #define FOREACH_WINDOWS_PLATFORM_CONFIG_PROPERTY(OP) \ OP( WindowsPlatformConfiguration, m_configuration, bool, isSoftwareSASEnabled, setSoftwareSASEnabled, "SoftwareSASEnabled", "Windows", true, Configuration::Property::Flag::Advanced ) \ + OP( WindowsPlatformConfiguration, m_configuration, WindowsSessionFunctions::InterferingWindowHandling, interferingWindowHandling, setInterferingWindowHandling, "InterferingWindowHandling", "Windows", QVariant::fromValue(WindowsSessionFunctions::InterferingWindowHandling::FixWindowAttributes), Configuration::Property::Flag::Advanced ) \ OP( WindowsPlatformConfiguration, m_configuration, bool, disableSSPIBasedUserAuthentication, setDisableSSPIBasedUserAuthentication, "DisableSSPIBasedUserAuthentication", "Windows", false, Configuration::Property::Flag::Advanced ) \ OP( WindowsPlatformConfiguration, m_configuration, bool, hideDesktopForScreenLock, setHideDesktopForScreenLock, "HideDesktopForScreenLock", "Windows", true, Configuration::Property::Flag::Advanced ) \ OP( WindowsPlatformConfiguration, m_configuration, bool, hideTaskbarForScreenLock, setHideTaskbarForScreenLock, "HideTaskbarForScreenLock", "Windows", true, Configuration::Property::Flag::Advanced ) \ OP( WindowsPlatformConfiguration, m_configuration, bool, hideStartMenuForScreenLock, setHideStartMenuForScreenLock, "HideStartMenuForScreenLock", "Windows", true, Configuration::Property::Flag::Advanced ) \ - + OP( WindowsPlatformConfiguration, m_configuration, bool, useCustomPowerSchemeForScreenLock, setUseCustomPowerSchemeForScreenLock, "UseCustomPowerSchemeForScreenLock", "Windows", true, Configuration::Property::Flag::Advanced ) \ + OP( WindowsPlatformConfiguration, m_configuration, bool, useInterceptionDriver, setUseInterceptionDriver, "UseInterceptionDriver", "Windows", true, Configuration::Property::Flag::Advanced ) \ + OP( WindowsPlatformConfiguration, m_configuration, int, logonInputStartDelay, setLogonInputStartDelay, "LogonInputStartDelay", "Windows", 1000, Configuration::Property::Flag::Advanced ) \ + OP( WindowsPlatformConfiguration, m_configuration, int, logonKeyPressInterval, setLogonKeyPressInterval, "LogonKeyPressInterval", "Windows", 10, Configuration::Property::Flag::Advanced ) \ + OP( WindowsPlatformConfiguration, m_configuration, bool, logonConfirmLegalNotice, setLogonConfirmLegalNotice, "LogonConfirmLegalNotice", "Windows", false, Configuration::Property::Flag::Advanced ) \ DECLARE_CONFIG_PROXY(WindowsPlatformConfiguration, FOREACH_WINDOWS_PLATFORM_CONFIG_PROPERTY) diff --git a/plugins/platform/windows/WindowsPlatformConfigurationPage.cpp b/plugins/platform/windows/WindowsPlatformConfigurationPage.cpp index b88b9d359..4ed9e640b 100644 --- a/plugins/platform/windows/WindowsPlatformConfigurationPage.cpp +++ b/plugins/platform/windows/WindowsPlatformConfigurationPage.cpp @@ -1,7 +1,7 @@ /* * WindowsPlatformConfigurationPage.cpp - page for configuring service application * - * Copyright (c) 2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,7 +31,6 @@ WindowsPlatformConfigurationPage::WindowsPlatformConfigurationPage() : - ConfigurationPage(), ui( new Ui::WindowsPlatformConfigurationPage ), m_configuration( &VeyonCore::config() ) { @@ -51,14 +50,14 @@ WindowsPlatformConfigurationPage::~WindowsPlatformConfigurationPage() void WindowsPlatformConfigurationPage::resetWidgets() { - FOREACH_WINDOWS_PLATFORM_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY); + FOREACH_WINDOWS_PLATFORM_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY) } void WindowsPlatformConfigurationPage::connectWidgetsToProperties() { - FOREACH_WINDOWS_PLATFORM_CONFIG_PROPERTY(CONNECT_WIDGET_TO_PROPERTY); + FOREACH_WINDOWS_PLATFORM_CONFIG_PROPERTY(CONNECT_WIDGET_TO_PROPERTY) } diff --git a/plugins/platform/windows/WindowsPlatformConfigurationPage.h b/plugins/platform/windows/WindowsPlatformConfigurationPage.h index 05534f68d..facddc021 100644 --- a/plugins/platform/windows/WindowsPlatformConfigurationPage.h +++ b/plugins/platform/windows/WindowsPlatformConfigurationPage.h @@ -1,7 +1,7 @@ /* * WindowsPlatformConfigurationPage.h - header for the WindowsPlatformConfigurationPage class * - * Copyright (c) 2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/plugins/platform/windows/WindowsPlatformConfigurationPage.ui b/plugins/platform/windows/WindowsPlatformConfigurationPage.ui index 4cac631de..843e07462 100644 --- a/plugins/platform/windows/WindowsPlatformConfigurationPage.ui +++ b/plugins/platform/windows/WindowsPlatformConfigurationPage.ui @@ -29,6 +29,41 @@ + + + + + + Handling of interfering windows + + + + + + + + None + + + + + Fix window attributes + + + + + Terminate related process + + + + + Close session + + + + + + @@ -48,6 +83,68 @@ + + + + User login + + + + + + ms + + + 5 + + + 100 + + + 5 + + + + + + + ms + + + 100 + + + 5000 + + + 100 + + + + + + + Input start delay + + + + + + + Simulated key presses interval + + + + + + + Confirm legal notice (message displayed before user logs in) + + + + + + @@ -75,13 +172,27 @@ + + + + Use input device interception driver + + + + + + + Use custom power scheme with disabled power button + + + - Qt::Vertical + Qt::Orientation::Vertical @@ -95,10 +206,16 @@ isSoftwareSASEnabled + interferingWindowHandling disableSSPIBasedUserAuthentication + logonInputStartDelay + logonKeyPressInterval + logonConfirmLegalNotice hideTaskbarForScreenLock hideStartMenuForScreenLock hideDesktopForScreenLock + useInterceptionDriver + useCustomPowerSchemeForScreenLock diff --git a/plugins/platform/windows/WindowsPlatformPlugin.cpp b/plugins/platform/windows/WindowsPlatformPlugin.cpp index 5fb224cfa..809f7e898 100644 --- a/plugins/platform/windows/WindowsPlatformPlugin.cpp +++ b/plugins/platform/windows/WindowsPlatformPlugin.cpp @@ -1,7 +1,7 @@ /* * WindowsPlatformPlugin.cpp - implementation of WindowsPlatformPlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,18 +22,23 @@ * */ +#include +#include + #include "WindowsPlatformPlugin.h" #include "WindowsPlatformConfigurationPage.h" WindowsPlatformPlugin::WindowsPlatformPlugin( QObject* parent ) : - QObject( parent ), - m_windowsCoreFunctions(), - m_windowsFilesystemFunctions(), - m_windowsInputDeviceFunctions(), - m_windowsNetworkFunctions(), - m_windowsServiceFunctions(), - m_windowsUserFunctions() + QObject( parent ) { + if( qobject_cast(QCoreApplication::instance()) ) + { + // create invisible dummy window to make the Qt Windows platform plugin receive + // WM_DISPLAYCHANGE events and update the screens returned by QGuiApplication::screens() + // even if the current Veyon component such as the Veyon Server does not create a window + m_dummyWindow = new QWindow; + m_dummyWindow->create(); + } } diff --git a/plugins/platform/windows/WindowsPlatformPlugin.h b/plugins/platform/windows/WindowsPlatformPlugin.h index 2ae1c0ee9..89b4ccad3 100644 --- a/plugins/platform/windows/WindowsPlatformPlugin.h +++ b/plugins/platform/windows/WindowsPlatformPlugin.h @@ -1,7 +1,7 @@ /* * WindowsPlatformPlugin.h - declaration of WindowsPlatformPlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -32,8 +32,11 @@ #include "WindowsInputDeviceFunctions.h" #include "WindowsNetworkFunctions.h" #include "WindowsServiceFunctions.h" +#include "WindowsSessionFunctions.h" #include "WindowsUserFunctions.h" +class QWindow; + class WindowsPlatformPlugin : public QObject, PlatformPluginInterface, PluginInterface, ConfigurationPagePluginInterface { Q_OBJECT @@ -45,7 +48,7 @@ class WindowsPlatformPlugin : public QObject, PlatformPluginInterface, PluginInt Plugin::Uid uid() const override { - return QStringLiteral("1baa01e0-02d6-4494-a766-788f5b225991"); + return Plugin::Uid{ QStringLiteral("1baa01e0-02d6-4494-a766-788f5b225991") }; } QVersionNumber version() const override @@ -103,6 +106,11 @@ class WindowsPlatformPlugin : public QObject, PlatformPluginInterface, PluginInt return m_windowsServiceFunctions; } + PlatformSessionFunctions& sessionFunctions() override + { + return m_windowsSessionFunctions; + } + PlatformUserFunctions& userFunctions() override { return m_windowsUserFunctions; @@ -111,11 +119,13 @@ class WindowsPlatformPlugin : public QObject, PlatformPluginInterface, PluginInt ConfigurationPage* createConfigurationPage() override; private: - WindowsCoreFunctions m_windowsCoreFunctions; - WindowsFilesystemFunctions m_windowsFilesystemFunctions; - WindowsInputDeviceFunctions m_windowsInputDeviceFunctions; - WindowsNetworkFunctions m_windowsNetworkFunctions; - WindowsServiceFunctions m_windowsServiceFunctions; - WindowsUserFunctions m_windowsUserFunctions; + WindowsCoreFunctions m_windowsCoreFunctions{}; + WindowsFilesystemFunctions m_windowsFilesystemFunctions{}; + WindowsInputDeviceFunctions m_windowsInputDeviceFunctions{}; + WindowsNetworkFunctions m_windowsNetworkFunctions{}; + WindowsServiceFunctions m_windowsServiceFunctions{}; + WindowsSessionFunctions m_windowsSessionFunctions{}; + WindowsUserFunctions m_windowsUserFunctions{}; + QWindow* m_dummyWindow{nullptr}; }; diff --git a/plugins/platform/windows/WindowsServiceControl.cpp b/plugins/platform/windows/WindowsServiceControl.cpp index 840158139..1cbc8cff2 100644 --- a/plugins/platform/windows/WindowsServiceControl.cpp +++ b/plugins/platform/windows/WindowsServiceControl.cpp @@ -1,7 +1,7 @@ /* * WindowsServiceControl.h - class for managing a Windows service * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -35,11 +35,19 @@ WindowsServiceControl::WindowsServiceControl( const QString& name ) : if( m_serviceManager ) { - m_serviceHandle = OpenService( m_serviceManager, WindowsCoreFunctions::toConstWCharArray( m_name ), SERVICE_ALL_ACCESS ); + m_serviceHandle = OpenService( m_serviceManager, WindowsCoreFunctions::toConstWCharArray( m_name ), + SERVICE_ALL_ACCESS ); + if( m_serviceHandle == nullptr ) + { + const auto error = GetLastError(); + vCritical() << qUtf8Printable( QStringLiteral("failed to open service \"%1\" (error %2)") + .arg(m_name).arg(error) ); + } } else { - vCritical() << "the Service Control Manager could not be contacted - service " << m_name << "was not started."; + const auto error = GetLastError(); + vCritical() << qUtf8Printable( QStringLiteral("failed to contact the Service Control Manager (error %1)").arg(error) ); } } @@ -94,7 +102,7 @@ bool WindowsServiceControl::start() { if( status.dwCurrentState == SERVICE_START_PENDING ) { - Sleep( 1000 ); + Sleep( ServiceWaitSleepInterval ); } else { @@ -123,15 +131,37 @@ bool WindowsServiceControl::stop() } SERVICE_STATUS status; + if( QueryServiceStatus( m_serviceHandle, &status ) && + status.dwCurrentState == SERVICE_STOPPED ) + { + return true; + } + + while( status.dwCurrentState == SERVICE_STOP_PENDING ) + { + Sleep( 1000 ); + if( QueryServiceStatus( m_serviceHandle, &status ) == false ) + { + const auto error = GetLastError(); + vWarning() << "failed to wait for stopping service" << m_name + << qUtf8Printable(QStringLiteral("(error %1)").arg(error)); + + return false; + } + + if( status.dwCurrentState == SERVICE_STOPPED ) + { + return true; + } + } - // Try to stop the service if( ControlService( m_serviceHandle, SERVICE_CONTROL_STOP, &status ) ) { while( QueryServiceStatus( m_serviceHandle, &status ) ) { if( status.dwCurrentState == SERVICE_STOP_PENDING ) { - Sleep( 1000 ); + Sleep( ServiceWaitSleepInterval ); } else { @@ -141,31 +171,41 @@ bool WindowsServiceControl::stop() if( status.dwCurrentState != SERVICE_STOPPED ) { - vWarning() << "service" << m_name << "could not be stopped."; + vWarning() << "failed to stop service" << m_name; return false; } + + return true; } - return true; + const auto error = GetLastError(); + vWarning() << "failed to stop service" << m_name + << qUtf8Printable(QStringLiteral("(error %1)").arg(error)); + + return false; } bool WindowsServiceControl::install( const QString& filePath, const QString& displayName ) { + const auto binaryPath = QStringLiteral("\"%1\"").arg( QString( filePath ).replace( QLatin1Char('"'), QString() ) ); + + const wchar_t* dependencies = L"Tcpip\0RpcSs\0LSM\0\0"; + m_serviceHandle = CreateService( m_serviceManager, // SCManager database WindowsCoreFunctions::toConstWCharArray( m_name ), // name of service WindowsCoreFunctions::toConstWCharArray( displayName ),// name to display SERVICE_ALL_ACCESS, // desired access - SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, + SERVICE_WIN32_OWN_PROCESS, // service type SERVICE_AUTO_START, // start type SERVICE_ERROR_NORMAL, // error control type - WindowsCoreFunctions::toConstWCharArray( filePath ), // service's binary + WindowsCoreFunctions::toConstWCharArray( binaryPath ), // service's binary nullptr, // no load ordering group nullptr, // no tag identifier - nullptr, // dependencies + dependencies, // dependencies nullptr, // LocalSystem account nullptr ); // no password @@ -178,23 +218,27 @@ bool WindowsServiceControl::install( const QString& filePath, const QString& dis } else { - vCritical() << qUtf8Printable( tr( "The service \"%1\" could not be installed." ).arg( m_name ) ); + vCritical() << qUtf8Printable( tr("The service \"%1\" could not be installed (error %2).") + .arg( m_name ).arg( error ) ); } return false; } SC_ACTION serviceActions; - serviceActions.Delay = 10000; + serviceActions.Delay = ServiceActionDelay; serviceActions.Type = SC_ACTION_RESTART; - SERVICE_FAILURE_ACTIONS serviceFailureActions; - serviceFailureActions.dwResetPeriod = 0; - serviceFailureActions.lpRebootMsg = nullptr; - serviceFailureActions.lpCommand = nullptr; + SERVICE_FAILURE_ACTIONS serviceFailureActions{}; serviceFailureActions.lpsaActions = &serviceActions; serviceFailureActions.cActions = 1; - ChangeServiceConfig2( m_serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, &serviceFailureActions ); + if( ChangeServiceConfig2( m_serviceHandle, SERVICE_CONFIG_FAILURE_ACTIONS, &serviceFailureActions ) == false ) + { + const auto error = GetLastError(); + vCritical() << qUtf8Printable( tr("Could not change the failure actions config for service \"%1\" (error %2).") + .arg( m_name ).arg( error ) ); + return false; + } // Everything went fine vInfo() << qUtf8Printable( tr( "The service \"%1\" has been installed successfully." ).arg( m_name ) ); @@ -218,7 +262,9 @@ bool WindowsServiceControl::uninstall() if( DeleteService( m_serviceHandle ) == false ) { - vCritical() << qUtf8Printable( tr( "The service \"%1\" could not be uninstalled." ).arg( m_name ) ); + const auto error = GetLastError(); + vCritical() << qUtf8Printable( tr( "The service \"%1\" could not be uninstalled (error %2)." ) + .arg( m_name ).arg( error ) ); return false; } @@ -231,7 +277,7 @@ bool WindowsServiceControl::uninstall() bool WindowsServiceControl::setStartType( int startType ) { - if( checkService() == false ) + if( checkService() == false || startType == InvalidStartType ) { return false; } @@ -249,7 +295,9 @@ bool WindowsServiceControl::setStartType( int startType ) nullptr // lpDisplayName ) == false ) { - vCritical() << qUtf8Printable( tr( "The start type of service \"%1\" could not be changed." ).arg( m_name ) ); + const auto error = GetLastError(); + vCritical() << qUtf8Printable( tr("The start type of service \"%1\" could not be changed (error %2).") + .arg( m_name ).arg( error ) ); return false; } diff --git a/plugins/platform/windows/WindowsServiceControl.h b/plugins/platform/windows/WindowsServiceControl.h index 60d6a1d32..30400f108 100644 --- a/plugins/platform/windows/WindowsServiceControl.h +++ b/plugins/platform/windows/WindowsServiceControl.h @@ -1,7 +1,7 @@ /* * WindowsService.h - class for managing a Windows service * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -32,6 +32,8 @@ class WindowsServiceControl : public QObject { Q_OBJECT public: + static constexpr auto InvalidStartType = SERVICE_DISABLED+1; + WindowsServiceControl( const QString& name ); ~WindowsServiceControl() override; @@ -46,6 +48,9 @@ class WindowsServiceControl : public QObject private: bool checkService() const; + static constexpr auto ServiceActionDelay = 10000; + static constexpr auto ServiceWaitSleepInterval = 1000; + const QString m_name; SC_HANDLE m_serviceManager; SC_HANDLE m_serviceHandle; diff --git a/plugins/platform/windows/WindowsServiceCore.cpp b/plugins/platform/windows/WindowsServiceCore.cpp index 81a73450c..9fe3e95a9 100644 --- a/plugins/platform/windows/WindowsServiceCore.cpp +++ b/plugins/platform/windows/WindowsServiceCore.cpp @@ -1,7 +1,7 @@ /* * WindowsServiceCore.cpp - implementation of WindowsServiceCore class * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -30,42 +30,34 @@ #include "Filesystem.h" #include "WindowsServiceCore.h" #include "SasEventListener.h" -#include "PlatformUserFunctions.h" #include "VeyonConfiguration.h" #include "WindowsCoreFunctions.h" #include "WindowsInputDeviceFunctions.h" #include "WtsSessionManager.h" +// clazy:excludeall=rule-of-three class VeyonServerProcess { public: - VeyonServerProcess() : - m_subProcessHandle( nullptr ) - { - } + VeyonServerProcess() = default; ~VeyonServerProcess() { stop(); } - void start( DWORD wtsSessionId, bool multiSession ) + void start( DWORD wtsSessionId, const ServiceDataManager::Token& token ) { - stop(); - - const auto baseProcessId = WtsSessionManager::findWinlogonProcessId( wtsSessionId ); + const auto baseProcessId = WtsSessionManager::findProcessId(QStringLiteral("winlogon.exe"), wtsSessionId); const auto user = WtsSessionManager::querySessionInformation( wtsSessionId, WtsSessionManager::SessionInfo::UserName ); - QStringList extraEnv; - if( multiSession ) - { - extraEnv.append( QStringLiteral("%1=%2"). - arg( VeyonCore::sessionIdEnvironmentVariable() ). - arg( wtsSessionId % 100 ) ); - } + const QStringList extraEnv{ + QStringLiteral("%1=%2").arg( QLatin1String( ServiceDataManager::serviceDataTokenEnvironmentVariable() ), + QString::fromUtf8( token.toByteArray() ) ) + }; - vInfo() << "Starting server for session" << wtsSessionId << "with user" << user; + vInfo() << "Starting server for WTS session" << wtsSessionId << "with user" << user; m_subProcessHandle = WindowsCoreFunctions::runProgramInSession( VeyonCore::filesystem().serverFilePath(), {}, extraEnv, baseProcessId, {} ); @@ -84,11 +76,10 @@ class VeyonServerProcess { vWarning() << "Terminating server"; TerminateProcess( m_subProcessHandle, 0 ); + WaitForSingleObject(m_subProcessHandle, ServerWaitTime); } CloseHandle( m_subProcessHandle ); m_subProcessHandle = nullptr; - - Sleep( ServerPostStopWaitTime ); } } @@ -105,11 +96,10 @@ class VeyonServerProcess private: - static constexpr auto ServerQueryTime = 100; - static constexpr auto ServerWaitTime = 10000; - static constexpr auto ServerPostStopWaitTime = 1000; + static constexpr auto ServerQueryTime = 10; + static constexpr auto ServerWaitTime = 3000; - HANDLE m_subProcessHandle; + HANDLE m_subProcessHandle{nullptr}; } ; @@ -118,17 +108,21 @@ class VeyonServerProcess WindowsServiceCore* WindowsServiceCore::s_instance = nullptr; -WindowsServiceCore::WindowsServiceCore( const QString& name, std::function serviceMainEntry ) : +WindowsServiceCore::WindowsServiceCore( const QString& name, + const PlatformServiceFunctions::ServiceEntryPoint& serviceEntryPoint ) : m_name( WindowsCoreFunctions::toWCharArray( name ) ), - m_serviceMainEntry( serviceMainEntry ), - m_status(), - m_statusHandle( 0 ), - m_stopServiceEvent( nullptr ), - m_serverShutdownEvent( nullptr ), - m_sessionChangeEvent( 0 ) + m_serviceEntryPoint( serviceEntryPoint ) { s_instance = this; + // allocate session 0 (PlatformSessionFunctions::DefaultSessionId) so we can always assign it to the console session + if( m_sessionManager.mode() != PlatformSessionManager::Mode::Active || + ( WtsSessionManager::activeSessions().size() <= 1 && + WtsSessionManager::activeConsoleSession() != WtsSessionManager::InvalidSession ) ) + { + m_sessionManager.openSession( QStringLiteral("0 (console)") ); + } + // enable privileges required to create process with access token from other process WindowsCoreFunctions::enablePrivilege( SE_ASSIGNPRIMARYTOKEN_NAME, true ); WindowsCoreFunctions::enablePrivilege( SE_INCREASE_QUOTA_NAME, true ); @@ -136,12 +130,6 @@ WindowsServiceCore::WindowsServiceCore( const QString& name, std::function dispatchTable = { { { m_name.data(), serviceMainStatic }, { nullptr, nullptr } - } ; + } } ; + + WindowsInputDeviceFunctions::checkInterceptionInstallation(); - if( !StartServiceCtrlDispatcher( dispatchTable ) ) + if( !StartServiceCtrlDispatcher( dispatchTable.data() ) ) { vCritical() << "StartServiceCtrlDispatcher failed."; return false; @@ -171,18 +161,16 @@ bool WindowsServiceCore::runAsService() void WindowsServiceCore::manageServerInstances() { - WindowsInputDeviceFunctions::checkInterceptionInstallation(); - m_serverShutdownEvent = CreateEvent( nullptr, false, false, L"Global\\SessionEventUltra" ); ResetEvent( m_serverShutdownEvent ); - if( multiSession() ) + if( m_sessionManager.mode() != PlatformSessionManager::Mode::Local ) { manageServersForAllSessions(); } else { - manageServerForActiveConsoleSession(); + manageServerForConsoleSession(); } CloseHandle( m_serverShutdownEvent ); @@ -194,7 +182,9 @@ void WindowsServiceCore::manageServersForAllSessions() { QMap serverProcesses; - while( WaitForSingleObject( m_stopServiceEvent, SessionPollingInterval ) == WAIT_TIMEOUT ) + const auto activeSessionOnly = m_sessionManager.mode() == PlatformSessionManager::Mode::Active; + + do { auto wtsSessionIds = WtsSessionManager::activeSessions(); @@ -205,11 +195,26 @@ void WindowsServiceCore::manageServersForAllSessions() wtsSessionIds.append( consoleSessionId ); } - for( auto it = serverProcesses.begin(), end = serverProcesses.end(); it != end; ) + const auto includeConsoleSession = activeSessionOnly && + wtsSessionIds.size() == 1 && + wtsSessionIds.first() == consoleSessionId; + const auto excludeConsoleSession = activeSessionOnly && + wtsSessionIds.size() > 1; + + if( excludeConsoleSession ) + { + wtsSessionIds.removeAll( consoleSessionId ); + } + + for( auto it = serverProcesses.begin(); it != serverProcesses.end(); ) { if( wtsSessionIds.contains( it.key() ) == false ) { delete it.value(); + if( it.key() != consoleSessionId || excludeConsoleSession ) + { + m_sessionManager.closeSession( QString::number(it.key() ) ); + } it = serverProcesses.erase( it ); } else @@ -222,13 +227,22 @@ void WindowsServiceCore::manageServersForAllSessions() { if( serverProcesses.contains( wtsSessionId ) == false ) { + if( wtsSessionId != consoleSessionId || includeConsoleSession ) + { + m_sessionManager.openSession( QString::number(wtsSessionId) ); + } + auto serverProcess = new VeyonServerProcess; - serverProcess->start( wtsSessionId, multiSession() && wtsSessionId != consoleSessionId ); + serverProcess->start( wtsSessionId, m_dataManager.token() ); serverProcesses[wtsSessionId] = serverProcess; } } - } + + std::array events{m_sessionChangeEvent, m_stopServiceEvent}; + WaitForMultipleObjects(events.size(), events.data(), FALSE, SessionPollingInterval); + + } while (m_serviceStopRequested == 0); vInfo() << "Service shutdown"; @@ -239,7 +253,7 @@ void WindowsServiceCore::manageServersForAllSessions() -void WindowsServiceCore::manageServerForActiveConsoleSession() +void WindowsServiceCore::manageServerForConsoleSession() { VeyonServerProcess veyonServerProcess; @@ -247,9 +261,8 @@ void WindowsServiceCore::manageServerForActiveConsoleSession() QElapsedTimer lastServerStart; - while( WaitForSingleObject( m_stopServiceEvent, SessionPollingInterval ) == WAIT_TIMEOUT ) - { - const auto sessionChanged = m_sessionChangeEvent.testAndSetOrdered( 1, 0 ); + do { + const auto sessionChanged = m_sessionChanged.testAndSetOrdered(1, 0); const auto wtsSessionId = WtsSessionManager::activeConsoleSession(); if( oldWtsSessionId != wtsSessionId || sessionChanged ) @@ -270,19 +283,32 @@ void WindowsServiceCore::manageServerForActiveConsoleSession() if( wtsSessionId != WtsSessionManager::InvalidSession || sessionChanged ) { - veyonServerProcess.start( wtsSessionId, multiSession() ); - lastServerStart.restart(); + veyonServerProcess.stop(); + if (m_serviceStopRequested == 0 && + wtsSessionId != WtsSessionManager::InvalidSession) + { + veyonServerProcess.start( wtsSessionId, m_dataManager.token() ); + lastServerStart.restart(); + } } oldWtsSessionId = wtsSessionId; } - else if( veyonServerProcess.isRunning() == false ) + else if (veyonServerProcess.isRunning() == false) { - veyonServerProcess.start( wtsSessionId, multiSession() ); + if (wtsSessionId != WtsSessionManager::InvalidSession) + { + veyonServerProcess.start( wtsSessionId, m_dataManager.token() ); + lastServerStart.restart(); + } + oldWtsSessionId = wtsSessionId; - lastServerStart.restart(); } - } + + std::array events{m_sessionChangeEvent, m_stopServiceEvent}; + WaitForMultipleObjects(events.size(), events.data(), FALSE, SessionPollingInterval); + + } while (m_serviceStopRequested == 0); vInfo() << "Service shutdown"; @@ -302,7 +328,7 @@ void WindowsServiceCore::serviceMainStatic( DWORD argc, LPWSTR* argv ) -DWORD WindowsServiceCore::serviceCtrlStatic(DWORD ctrlCode, DWORD eventType, LPVOID eventData, LPVOID context) +DWORD WindowsServiceCore::serviceCtrlStatic( DWORD ctrlCode, DWORD eventType, LPVOID eventData, LPVOID context ) { return instance()->serviceCtrl( ctrlCode, eventType, eventData, context ); } @@ -315,32 +341,37 @@ void WindowsServiceCore::serviceMain() m_statusHandle = RegisterServiceCtrlHandlerEx( m_name.data(), serviceCtrlStatic, &context ); - if( m_statusHandle == 0 ) + if( m_statusHandle == nullptr ) { + vCritical() << "Invalid service status handle"; return; } memset( &m_status, 0, sizeof( m_status ) ); - m_status.dwServiceType = SERVICE_WIN32 | SERVICE_INTERACTIVE_PROCESS; + m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - if( reportStatus( SERVICE_START_PENDING, NO_ERROR, 15000 ) == false ) + if( reportStatus( SERVICE_START_PENDING, NO_ERROR, ServiceStartTimeout ) == false ) { + vCritical() << "Service start timed out"; reportStatus( SERVICE_STOPPED, 0, 0 ); return; } - m_stopServiceEvent = CreateEvent( 0, FALSE, FALSE, 0 ); + m_stopServiceEvent = CreateEvent( nullptr, false, false, nullptr ); + m_sessionChangeEvent = CreateEvent(nullptr, false, false, nullptr); if( reportStatus( SERVICE_RUNNING, NO_ERROR, 0 ) == false ) { + vCritical() << "Could not report service as running"; return; } SasEventListener sasEventListener; sasEventListener.start(); - m_serviceMainEntry(); + m_serviceEntryPoint(); + CloseHandle(m_sessionChangeEvent); CloseHandle( m_stopServiceEvent ); sasEventListener.stop(); @@ -354,16 +385,48 @@ void WindowsServiceCore::serviceMain() DWORD WindowsServiceCore::serviceCtrl( DWORD ctrlCode, DWORD eventType, LPVOID eventData, LPVOID context ) { - Q_UNUSED(eventData) - Q_UNUSED(context) + Q_UNUSED(context); + + static const QMap controlMessages{ + { SERVICE_CONTROL_SHUTDOWN, "SHUTDOWN" }, + { SERVICE_CONTROL_STOP, "STOP" }, + { SERVICE_CONTROL_PAUSE, "PAUSE" }, + { SERVICE_CONTROL_CONTINUE, "CONTINUE" }, + { SERVICE_CONTROL_INTERROGATE, "INTERROGATE" }, + { SERVICE_CONTROL_PARAMCHANGE, "PARAM CHANGE" }, + { SERVICE_CONTROL_DEVICEEVENT, "DEVICE EVENT" }, + { SERVICE_CONTROL_HARDWAREPROFILECHANGE, "HARDWARE PROFILE CHANGE" }, + { SERVICE_CONTROL_POWEREVENT, "POWER EVENT" }, + { SERVICE_CONTROL_SESSIONCHANGE, "SESSION CHANGE" } + }; + + static const QMap sessionChangeEventTypes{ + { WTS_CONSOLE_CONNECT, "CONSOLE CONNECT" }, + { WTS_CONSOLE_DISCONNECT, "CONSOLE DISCONNECT" }, + { WTS_REMOTE_CONNECT, "REMOTE CONNECT" }, + { WTS_REMOTE_DISCONNECT, "REMOTE DISCONNECT" }, + { WTS_SESSION_LOGON, "LOGON" }, + { WTS_SESSION_LOGOFF, "LOGOFF" }, + { WTS_SESSION_LOCK, "LOCK" }, + { WTS_SESSION_UNLOCK, "UNLOCK" }, + { WTS_SESSION_REMOTE_CONTROL, "REMOTE CONTROL" }, + { WTS_SESSION_CREATE, "CREATE" }, + { WTS_SESSION_TERMINATE, "TERMINATE" } + }; + + if( ctrlCode != SERVICE_CONTROL_SESSIONCHANGE && + controlMessages.contains( ctrlCode ) ) + { + vDebug() << "control code:" << controlMessages[ctrlCode] << "event type:" << eventType; + } // What control code have we been sent? switch( ctrlCode ) { case SERVICE_CONTROL_SHUTDOWN: case SERVICE_CONTROL_STOP: - // STOP : The service must stop m_status.dwCurrentState = SERVICE_STOP_PENDING; + m_serviceStopRequested = 1; SetEvent( m_stopServiceEvent ); break; @@ -372,15 +435,22 @@ DWORD WindowsServiceCore::serviceCtrl( DWORD ctrlCode, DWORD eventType, LPVOID e break; case SERVICE_CONTROL_SESSIONCHANGE: + if( sessionChangeEventTypes.contains( eventType ) ) + { + const auto notification = reinterpret_cast( eventData ); + vDebug() << "session change event:" << sessionChangeEventTypes[eventType] + << "for session" << ( notification ? notification->dwSessionId : -1 ); + } switch( eventType ) { - case WTS_SESSION_LOGOFF: - vInfo() << "Session change event: WTS_SESSION_LOGOFF"; - m_sessionChangeEvent = 1; - break; case WTS_SESSION_LOGON: - vInfo() << "Session change event: WTS_SESSION_LOGON"; - m_sessionChangeEvent = 1; + case WTS_SESSION_LOGOFF: + case WTS_CONSOLE_CONNECT: + case WTS_CONSOLE_DISCONNECT: + case WTS_REMOTE_CONNECT: + case WTS_REMOTE_DISCONNECT: + m_sessionChanged = 1; + SetEvent(m_sessionChangeEvent); break; } break; @@ -431,8 +501,6 @@ bool WindowsServiceCore::reportStatus( DWORD state, DWORD exitCode, DWORD waitHi m_status.dwCheckPoint = checkpoint++; } - vDebug() << "reporting service status:" << static_cast( state ); - // Tell the SCM our new status if( !( result = SetServiceStatus( m_statusHandle, &m_status ) ) ) { diff --git a/plugins/platform/windows/WindowsServiceCore.h b/plugins/platform/windows/WindowsServiceCore.h index 5fd4ef913..06989570f 100644 --- a/plugins/platform/windows/WindowsServiceCore.h +++ b/plugins/platform/windows/WindowsServiceCore.h @@ -1,7 +1,7 @@ /* * WindowsServiceCore.h - header file for WindowsServiceCore class * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,13 +24,17 @@ #pragma once -#include "PlatformServiceCore.h" +#include -class WindowsServiceCore : public PlatformServiceCore +#include "PlatformServiceFunctions.h" +#include "PlatformSessionManager.h" +#include "ServiceDataManager.h" + +class WindowsServiceCore { public: - WindowsServiceCore( const QString& name, std::function serviceMainEntry ); - ~WindowsServiceCore(); + WindowsServiceCore( const QString& name, const PlatformServiceFunctions::ServiceEntryPoint& serviceEntryPoint ); + ~WindowsServiceCore() = default; static WindowsServiceCore* instance(); @@ -40,7 +44,7 @@ class WindowsServiceCore : public PlatformServiceCore private: void manageServersForAllSessions(); - void manageServerForActiveConsoleSession(); + void manageServerForConsoleSession(); static void WINAPI serviceMainStatic( DWORD argc, LPWSTR* argv ); static DWORD WINAPI serviceCtrlStatic( DWORD ctrlCode, DWORD eventType, LPVOID eventData, LPVOID context ); @@ -50,16 +54,22 @@ class WindowsServiceCore : public PlatformServiceCore bool reportStatus( DWORD state, DWORD exitCode, DWORD waitHint ); QSharedPointer m_name; - std::function m_serviceMainEntry; + const PlatformServiceFunctions::ServiceEntryPoint& m_serviceEntryPoint; static WindowsServiceCore* s_instance; - SERVICE_STATUS m_status; - SERVICE_STATUS_HANDLE m_statusHandle; - HANDLE m_stopServiceEvent; - HANDLE m_serverShutdownEvent; - QAtomicInt m_sessionChangeEvent; + SERVICE_STATUS m_status{}; + SERVICE_STATUS_HANDLE m_statusHandle{nullptr}; + HANDLE m_sessionChangeEvent{nullptr}; + HANDLE m_stopServiceEvent{nullptr}; + HANDLE m_serverShutdownEvent{nullptr}; + QAtomicInt m_serviceStopRequested{0}; + QAtomicInt m_sessionChanged{0}; + + ServiceDataManager m_dataManager{}; + PlatformSessionManager m_sessionManager{}; - static constexpr auto SessionPollingInterval = 100; + static constexpr auto SessionPollingInterval = 5000; static constexpr auto MinimumServerUptimeTime = 10000; + static constexpr auto ServiceStartTimeout = 15000; } ; diff --git a/plugins/platform/windows/WindowsServiceFunctions.cpp b/plugins/platform/windows/WindowsServiceFunctions.cpp index 6772ae10a..c3fe4c9be 100644 --- a/plugins/platform/windows/WindowsServiceFunctions.cpp +++ b/plugins/platform/windows/WindowsServiceFunctions.cpp @@ -1,7 +1,7 @@ /* * WindowsServiceFunctions.cpp - implementation of WindowsServiceFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -85,9 +85,9 @@ bool WindowsServiceFunctions::setStartMode( const QString& name, PlatformService -bool WindowsServiceFunctions::runAsService( const QString& name, const std::function& serviceMain ) +bool WindowsServiceFunctions::runAsService( const QString& name, const ServiceEntryPoint& serviceEntryPoint ) { - WindowsServiceCore windowsServiceCore( name, serviceMain ); + WindowsServiceCore windowsServiceCore( name, serviceEntryPoint ); return windowsServiceCore.runAsService(); } diff --git a/plugins/platform/windows/WindowsServiceFunctions.h b/plugins/platform/windows/WindowsServiceFunctions.h index 9f8ff5e06..2d8f5b715 100644 --- a/plugins/platform/windows/WindowsServiceFunctions.h +++ b/plugins/platform/windows/WindowsServiceFunctions.h @@ -1,7 +1,7 @@ /* * WindowsServiceFunctions.h - declaration of WindowsServiceFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -38,10 +38,10 @@ class WindowsServiceFunctions : public PlatformServiceFunctions bool start( const QString& name ) override; bool stop( const QString& name ) override; bool install( const QString& name, const QString& filePath, - StartMode startMode, const QString& displayName ) override; + StartMode startMode, const QString& displayName ) override; bool uninstall( const QString& name ) override; bool setStartMode( const QString& name, StartMode startMode ) override; - bool runAsService( const QString& name, const std::function& serviceMain ) override; + bool runAsService( const QString& name, const ServiceEntryPoint& serviceEntryPoint ) override; void manageServerInstances() override; private: diff --git a/plugins/platform/windows/WindowsSessionFunctions.cpp b/plugins/platform/windows/WindowsSessionFunctions.cpp new file mode 100644 index 000000000..a51955550 --- /dev/null +++ b/plugins/platform/windows/WindowsSessionFunctions.cpp @@ -0,0 +1,259 @@ +/* + * WindowsSessionFunctions.cpp - implementation of WindowsSessionFunctions class + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include + +#include +#include +#include + +#include "WindowsCoreFunctions.h" +#include "PlatformSessionManager.h" +#include "PlatformUserFunctions.h" +#include "VeyonConfiguration.h" +#include "WindowsPlatformConfiguration.h" +#include "WindowsSessionFunctions.h" +#include "WtsSessionManager.h" + + +WindowsSessionFunctions::WindowsSessionFunctions() +{ + if (VeyonCore::component() == VeyonCore::Component::Server) + { + QObject::connect (VeyonCore::instance(), &VeyonCore::initialized, + VeyonCore::instance(), [this]() { initInterferingWindowHandling(); }); + } +} + + + +WindowsSessionFunctions::SessionId WindowsSessionFunctions::currentSessionId() +{ + const auto currentSession = WtsSessionManager::currentSession(); + + if( currentSession == WtsSessionManager::activeConsoleSession() ) + { + return DefaultSessionId; + } + + return PlatformSessionManager::resolveSessionId( QString::number(currentSession) ); +} + + + +WindowsSessionFunctions::SessionUptime WindowsSessionFunctions::currentSessionUptime() const +{ + return WtsSessionManager::querySessionInformation(WtsSessionManager::currentSession(), + WtsSessionManager::SessionInfo::SessionUptime).toInt(); +} + + + +QString WindowsSessionFunctions::currentSessionClientAddress() const +{ + return WtsSessionManager::querySessionInformation(WtsSessionManager::currentSession(), + WtsSessionManager::SessionInfo::ClientAddress); +} + + + +QString WindowsSessionFunctions::currentSessionClientName() const +{ + return WtsSessionManager::querySessionInformation(WtsSessionManager::currentSession(), + WtsSessionManager::SessionInfo::ClientName); +} + + + +QString WindowsSessionFunctions::currentSessionHostName() const +{ + return QHostInfo::localHostName(); +} + + + +QString WindowsSessionFunctions::currentSessionType() const +{ + if(WtsSessionManager::currentSession() == WtsSessionManager::activeConsoleSession() ) + { + return QStringLiteral("console"); + } + + return QStringLiteral("rdp"); +} + + + +bool WindowsSessionFunctions::currentSessionIsRemote() const +{ + return WtsSessionManager::isRemote( WtsSessionManager::currentSession() ); +} + + + +bool WindowsSessionFunctions::currentSessionHasUser() const +{ + return WtsSessionManager::querySessionInformation( WtsSessionManager::currentSession(), + WtsSessionManager::SessionInfo::UserName ).isEmpty() == false; +} + + + +PlatformSessionFunctions::EnvironmentVariables WindowsSessionFunctions::currentSessionEnvironmentVariables() const +{ + const auto processId = WtsSessionManager::findProcessId(QStringLiteral("explorer.exe"), WtsSessionManager::currentSession()); + const auto envStrings = WindowsCoreFunctions::queryProcessEnvironmentVariables(processId); + + EnvironmentVariables environmentVariables; + for (const auto& envString : envStrings) + { + const auto envStringParts = envString.split(QLatin1Char('=')); + if (envStringParts.size() >= 2) + { + environmentVariables[envStringParts.at(0)] = envStringParts.mid(1).join(QLatin1Char('=')); + } + } + + return environmentVariables; +} + + + +QVariant WindowsSessionFunctions::querySettingsValueInCurrentSession(const QString& key) const +{ + if (key.startsWith(QLatin1String("HKEY"))) + { + HANDLE userToken = nullptr; + const auto sessionId = WtsSessionManager::currentSession(); + if (WTSQueryUserToken(sessionId, &userToken) == false) + { + vCritical() << "could not query user token for session" << sessionId; + return {}; + } + + auto keyParts = key.split(QLatin1Char('\\')); + if (keyParts.constFirst() == QStringLiteral("HKEY_CURRENT_USER")) + { + keyParts[0] = WtsSessionManager::queryUserSid(sessionId); + keyParts.prepend(QStringLiteral("HKEY_USERS")); + } + + if (ImpersonateLoggedOnUser(userToken) == false) + { + vCritical() << "could not impersonate session user"; + return {}; + } + + const auto value = QSettings(keyParts.mid(0, keyParts.length()-1).join(QLatin1Char('\\')), QSettings::NativeFormat) + .value(keyParts.constLast()); + + RevertToSelf(); + CloseHandle(userToken); + + return value; + } + + return QSettings(QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName()).value(key); +} + + +void WindowsSessionFunctions::initInterferingWindowHandling() +{ + WindowsPlatformConfiguration config(&VeyonCore::config()); + + m_interferingWindowHandling = config.interferingWindowHandling(); + + if (m_interferingWindowHandling != InterferingWindowHandling::None) + { + QObject::connect (&m_desktopWindowsInspectionTimer, &QTimer::timeout, &m_desktopWindowsInspectionTimer, [this]() { + inspectDesktopWindows(); + }); + m_desktopWindowsInspectionTimer.start(DesktopWindowsInspectionInterval); + } +} + + + +void WindowsSessionFunctions::inspectDesktopWindows() +{ + EnumWindows([](HWND window, LPARAM instance) -> WINBOOL CALLBACK { + const auto _this = reinterpret_cast(instance); + return _this->inspectDesktopWindow(window); + }, LPARAM(this)); +} + + + +WINBOOL WindowsSessionFunctions::inspectDesktopWindow(HWND window) +{ + const auto windowStyle = GetWindowLong(window, GWL_EXSTYLE); + if (windowStyle & (WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_LAYERED)) { + COLORREF crKey; + BYTE alpha; + DWORD flags; + if (GetLayeredWindowAttributes(window, &crKey, &alpha, &flags) && (flags & LWA_COLORKEY)) + { + std::wstring windowTitle(GetWindowTextLength(window) + 1, L'\0'); + GetWindowTextW(window, &windowTitle[0], windowTitle.size()); + + switch (m_interferingWindowHandling) + { + case InterferingWindowHandling::FixWindowAttributes: + vDebug() << "fixing attributes of interfering window" << window << windowTitle << flags << crKey << alpha; + SetLayeredWindowAttributes(window, 0, 255, LWA_COLORKEY | LWA_ALPHA); + SetWindowLong(window, GWL_EXSTYLE, + windowStyle & ~(WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_TOPMOST)); + RedrawWindow(window, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN); + ShowWindow(window, SW_HIDE); + break; + case InterferingWindowHandling::TerminateProcess: + { + vDebug() << "terminating process of interfering window" << window << windowTitle << flags << crKey << alpha; + DWORD processId = 0; + if (GetWindowThreadProcessId(window, &processId)) + { + const auto processHandle = OpenProcess(PROCESS_TERMINATE, 0, processId); + if (processHandle) + { + TerminateProcess(processHandle, 0); + CloseHandle(processHandle); + } + else + { + PostMessage(window, WM_QUIT, 0, 0); + } + } + break; + } + case InterferingWindowHandling::CloseSession: + vDebug() << "closing session due to interfering window" << window << windowTitle << flags << crKey << alpha; + VeyonCore::platform().userFunctions().logoff(); + break; + default: + break; + } + } + } + return TRUE; +} diff --git a/plugins/platform/windows/WindowsSessionFunctions.h b/plugins/platform/windows/WindowsSessionFunctions.h new file mode 100644 index 000000000..d93ebe47d --- /dev/null +++ b/plugins/platform/windows/WindowsSessionFunctions.h @@ -0,0 +1,71 @@ +/* + * WindowsSessionFunctions.h - declaration of WindowsSessionFunctions class + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +#include "PlatformSessionFunctions.h" + +// clazy:excludeall=copyable-polymorphic + +class WindowsSessionFunctions : public PlatformSessionFunctions +{ + Q_GADGET +public: + enum class InterferingWindowHandling { + None, + FixWindowAttributes, + TerminateProcess, + CloseSession + }; + Q_ENUM(InterferingWindowHandling) + + WindowsSessionFunctions(); + + SessionId currentSessionId() override; + + SessionUptime currentSessionUptime() const override; + QString currentSessionClientAddress() const override; + QString currentSessionClientName() const override; + QString currentSessionHostName() const override; + + QString currentSessionType() const override; + bool currentSessionHasUser() const override; + bool currentSessionIsRemote() const override; + + EnvironmentVariables currentSessionEnvironmentVariables() const override; + QVariant querySettingsValueInCurrentSession(const QString& key) const override; + +private: + void initInterferingWindowHandling(); + void inspectDesktopWindows(); + WINBOOL inspectDesktopWindow(HWND window); + + static constexpr auto DesktopWindowsInspectionInterval = 1000; + + InterferingWindowHandling m_interferingWindowHandling = InterferingWindowHandling::None; + QTimer m_desktopWindowsInspectionTimer; + +}; diff --git a/plugins/platform/windows/WindowsUserFunctions.cpp b/plugins/platform/windows/WindowsUserFunctions.cpp index 235977752..7aae0c2ad 100644 --- a/plugins/platform/windows/WindowsUserFunctions.cpp +++ b/plugins/platform/windows/WindowsUserFunctions.cpp @@ -1,7 +1,7 @@ /* * WindowsUserFunctions.cpp - implementation of WindowsUserFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,42 +22,45 @@ * */ -#include -#include -#include +#include +#include + +#include "DesktopInputController.h" #include "VeyonConfiguration.h" #include "WindowsCoreFunctions.h" +#include "WindowsInputDeviceFunctions.h" #include "WindowsPlatformConfiguration.h" #include "WindowsUserFunctions.h" #include "WtsSessionManager.h" #include "authSSP.h" +#define XK_MISCELLANY + +#include "keysymdef.h" + QString WindowsUserFunctions::fullName( const QString& username ) { - QString fullName; - - auto realUsername = username; - LPWSTR domainController = nullptr; + QString dcName; - const auto nameParts = username.split( QLatin1Char('\\') ); - if( nameParts.size() > 1 ) + const auto domain = domainFromUsername(username); + if( domain.isEmpty() == false ) { - realUsername = nameParts[1]; - if( NetGetDCName( nullptr, WindowsCoreFunctions::toConstWCharArray( nameParts[0] ), - reinterpret_cast( &domainController ) ) != NERR_Success ) - { - domainController = nullptr; - } + dcName = domainController(domain); } + const auto usernameWithoutDomain = VeyonCore::stripDomain(username); + LPUSER_INFO_2 buf = nullptr; - const auto nStatus = NetUserGetInfo( domainController, - WindowsCoreFunctions::toConstWCharArray( realUsername ), + const auto nStatus = NetUserGetInfo( dcName.isEmpty() ? nullptr + : WindowsCoreFunctions::toConstWCharArray(dcName), + WindowsCoreFunctions::toConstWCharArray( usernameWithoutDomain ), 2, reinterpret_cast( &buf ) ); + QString fullName; + if( nStatus == NERR_Success && buf != nullptr ) { fullName = QString::fromWCharArray( buf->usri2_full_name ); @@ -68,11 +71,6 @@ QString WindowsUserFunctions::fullName( const QString& username ) NetApiBufferFree( buf ); } - if( domainController != nullptr ) - { - NetApiBufferFree( domainController ); - } - return fullName; } @@ -112,9 +110,36 @@ QStringList WindowsUserFunctions::groupsOfUser( const QString& username, bool qu -bool WindowsUserFunctions::isAnyUserLoggedOn() +bool WindowsUserFunctions::isAnyUserLoggedInLocally() +{ + const auto sessions = WtsSessionManager::activeSessions(); + for( const auto session : sessions ) + { + if( WtsSessionManager::querySessionInformation( session, WtsSessionManager::SessionInfo::UserName ).isEmpty() == false && + WtsSessionManager::isRemote( session ) == false ) + { + return true; + } + } + + return false; +} + + + +bool WindowsUserFunctions::isAnyUserLoggedInRemotely() { - return WtsSessionManager::loggedOnUsers().isEmpty() == false; + const auto sessions = WtsSessionManager::activeSessions(); + for( const auto session : sessions ) + { + if( WtsSessionManager::querySessionInformation( session, WtsSessionManager::SessionInfo::UserName ).isEmpty() == false && + WtsSessionManager::isRemote( session ) ) + { + return true; + } + } + + return false; } @@ -129,11 +154,11 @@ QString WindowsUserFunctions::currentUser() // check whether we just got the name of the local computer if( !domainName.isEmpty() ) { - wchar_t computerName[MAX_PATH]; // Flawfinder: ignore - DWORD size = MAX_PATH; - GetComputerName( computerName, &size ); + std::array computerName{}; // Flawfinder: ignore + DWORD size = MAX_COMPUTERNAME_LENGTH; + GetComputerName( computerName.data(), &size ); - if( domainName == QString::fromWCharArray( computerName ) ) + if( domainName == QString::fromWCharArray( computerName.data() ) ) { // reset domain name as we do not need to store local computer name domainName.clear(); @@ -150,12 +175,61 @@ QString WindowsUserFunctions::currentUser() -void WindowsUserFunctions::logon( const QString& username, const QString& password ) +bool WindowsUserFunctions::prepareLogon( const QString& username, const Password& password ) { - Q_UNUSED(username); - Q_UNUSED(password); + if( m_logonHelper.prepare( username, password ) ) + { + logoff(); + return true; + } - // TODO + return false; +} + + + +bool WindowsUserFunctions::performLogon( const QString& username, const Password& password ) +{ + WindowsPlatformConfiguration config( &VeyonCore::config() ); + + DesktopInputController input( config.logonKeyPressInterval() ); + + const auto ctrlAltDel = []() { + auto sasEvent = OpenEvent( EVENT_MODIFY_STATE, false, L"Global\\VeyonServiceSasEvent" ); + SetEvent( sasEvent ); + CloseHandle( sasEvent ); + }; + + const auto sendString = [&input]( const QString& string ) { + for( const auto& character : string ) + { + input.pressAndReleaseKey( character ); + } + }; + + WindowsInputDeviceFunctions::stopOnScreenKeyboard(); + + ctrlAltDel(); + + QThread::msleep( static_cast( config.logonInputStartDelay() ) ); + + if( config.logonConfirmLegalNotice() ) + { + input.pressAndReleaseKey( XK_Return ); + QThread::msleep( static_cast( config.logonInputStartDelay() ) ); + } + + input.pressAndReleaseKey( XK_Delete ); + + sendString( username ); + + input.pressAndReleaseKey( XK_Tab ); + + sendString( QString::fromUtf8( password.toByteArray() ) ); + + input.pressAndReleaseKey( XK_Return ); + + return true; } @@ -167,7 +241,7 @@ void WindowsUserFunctions::logoff() -bool WindowsUserFunctions::authenticate( const QString& username, const QString& password ) +bool WindowsUserFunctions::authenticate( const QString& username, const Password& password ) { QString domain; QString user; @@ -185,27 +259,31 @@ bool WindowsUserFunctions::authenticate( const QString& username, const QString& auto domainWide = WindowsCoreFunctions::toWCharArray( domain ); auto userWide = WindowsCoreFunctions::toWCharArray( user ); - auto passwordWide = WindowsCoreFunctions::toWCharArray( password ); + auto passwordWide = WindowsCoreFunctions::toWCharArray( QString::fromUtf8( password.toByteArray() ) ); bool result = false; - WindowsPlatformConfiguration config( &VeyonCore::config() ); - - if( config.disableSSPIBasedUserAuthentication() ) + if( WindowsPlatformConfiguration( &VeyonCore::config() ).disableSSPIBasedUserAuthentication() ) { - HANDLE token = nullptr; - result = LogonUserW( userWide.data(), domainWide.data(), passwordWide.data(), - LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &token ); - vDebug() << "LogonUserW()" << result << GetLastError(); - if( token ) + for (auto logonProvider: {LOGON32_PROVIDER_DEFAULT, LOGON32_PROVIDER_WINNT50, LOGON32_PROVIDER_WINNT40}) { - CloseHandle( token ); + HANDLE token = nullptr; + result = LogonUserW(userWide.data(), domain.isEmpty() ? nullptr : domainWide.data(), passwordWide.data(), + LOGON32_LOGON_NETWORK, logonProvider, &token); + const auto error = GetLastError(); + vDebug() << "LogonUserW()" << logonProvider << result << error; + if (token) + { + CloseHandle(token); + break; + } } } else { result = SSPLogonUser( domainWide.data(), userWide.data(), passwordWide.data() ); - vDebug() << "SSPLogonUser()" << result << GetLastError(); + const auto error = GetLastError(); + vDebug() << "SSPLogonUser()" << result << error; } return result; @@ -213,23 +291,53 @@ bool WindowsUserFunctions::authenticate( const QString& username, const QString& -QString WindowsUserFunctions::domainController() +QString WindowsUserFunctions::domainFromUsername( const QString& username ) { - QString dcName; - LPBYTE outBuffer = nullptr; + const auto nameParts = username.split( QLatin1Char('\\') ); + if( nameParts.size() > 1 ) + { + return nameParts[0]; + } + + return {}; +} - if( NetGetDCName( nullptr, nullptr, &outBuffer ) == NERR_Success ) + + +QString WindowsUserFunctions::domainController( const QString& domainName ) +{ + const auto domainNamePointer = domainName.isEmpty() ? nullptr + : WindowsCoreFunctions::toConstWCharArray(domainName); + + PDOMAIN_CONTROLLER_INFO dcInfo; + + const auto dsResult = DsGetDcName( nullptr, domainNamePointer, nullptr, nullptr, DS_DIRECTORY_SERVICE_REQUIRED, &dcInfo ); + if( dsResult == ERROR_SUCCESS ) { - dcName = QString::fromUtf16( reinterpret_cast( outBuffer ) ); + const auto dcName = QString::fromUtf16(reinterpret_cast(dcInfo->DomainControllerName)). + replace( QLatin1Char('\\'), QString() ); - NetApiBufferFree( outBuffer ); + NetApiBufferFree( dcInfo ); + + return dcName; } - else + + vWarning() << "DsGetDcName() failed with" << dsResult << "falling back to NetGetDCName()"; + + LPBYTE outBuffer = nullptr; + const auto netResult = NetGetDCName( nullptr, domainNamePointer, &outBuffer ); + if( netResult == NERR_Success ) { - vWarning() << "could not query domain controller name!"; + const auto dcName = QString::fromUtf16(reinterpret_cast(outBuffer)); + + NetApiBufferFree( outBuffer ); + + return dcName; } - return dcName; + vWarning() << "querying domain controller for domain" << domainName << "failed with:" << netResult; + + return {}; } @@ -238,151 +346,161 @@ QStringList WindowsUserFunctions::domainUserGroups() { const auto dc = domainController(); - QStringList groupList; - LPBYTE outBuffer = nullptr; DWORD entriesRead = 0; DWORD totalEntries = 0; - if( NetGroupEnum( WindowsCoreFunctions::toConstWCharArray( dc ), 0, &outBuffer, MAX_PREFERRED_LENGTH, &entriesRead, &totalEntries, nullptr ) == NERR_Success ) + const auto status = NetGroupEnum( WindowsCoreFunctions::toConstWCharArray(dc), 0, &outBuffer, MAX_PREFERRED_LENGTH, + &entriesRead, &totalEntries, nullptr ); + if( status == NERR_Success ) { const auto* groupInfos = reinterpret_cast( outBuffer ); + QStringList groupList; groupList.reserve( static_cast( entriesRead ) ); for( DWORD i = 0; i < entriesRead; ++i ) { - groupList += QString::fromUtf16( reinterpret_cast( groupInfos[i].grpi0_name ) ); + groupList += QString::fromUtf16(reinterpret_cast(groupInfos[i].grpi0_name)); } if( entriesRead < totalEntries ) { - vWarning() << "not all domain groups fetched"; + vWarning() << "not all domain groups fetched from DC" << dc << entriesRead << totalEntries; } NetApiBufferFree( outBuffer ); + + return groupList; } else { - vWarning() << "could not fetch domain groups"; + vWarning() << "failed to fetch domain groups from DC" << dc << status; } - return groupList; + return {}; } QStringList WindowsUserFunctions::domainGroupsOfUser( const QString& username ) { - const auto dc = domainController(); - - QStringList groupList; + const auto dc = domainController( domainFromUsername(username) ); + const auto usernameWithoutDomain = VeyonCore::stripDomain(username); LPBYTE outBuffer = nullptr; DWORD entriesRead = 0; DWORD totalEntries = 0; - const auto usernameWithoutDomain = VeyonCore::stripDomain( username ); - - if( NetUserGetGroups( WindowsCoreFunctions::toConstWCharArray( dc ), - WindowsCoreFunctions::toConstWCharArray( usernameWithoutDomain ), - 0, &outBuffer, MAX_PREFERRED_LENGTH, - &entriesRead, &totalEntries ) == NERR_Success ) + const auto status = NetUserGetGroups( WindowsCoreFunctions::toConstWCharArray(dc), + WindowsCoreFunctions::toConstWCharArray(usernameWithoutDomain), + 0, &outBuffer, MAX_PREFERRED_LENGTH, + &entriesRead, &totalEntries ); + if( status == NERR_Success ) { const auto* groupUsersInfo = reinterpret_cast( outBuffer ); + QStringList groupList; groupList.reserve( static_cast( entriesRead ) ); for( DWORD i = 0; i < entriesRead; ++i ) { - groupList += QString::fromUtf16( reinterpret_cast( groupUsersInfo[i].grui0_name ) ); + groupList += QString::fromUtf16(reinterpret_cast(groupUsersInfo[i].grui0_name)); } if( entriesRead < totalEntries ) { - vWarning() << "not all domain groups fetched for user" << username; + vWarning() << "not all domain groups fetched for user" << username << "from DC" << dc + << entriesRead << totalEntries; } NetApiBufferFree( outBuffer ); + + return groupList; } else { - vWarning() << "could not fetch domain groups for user" << username; + vWarning() << "failed to fetch domain groups for user" << username << "from DC" << dc << status; } - return groupList; + return {}; } QStringList WindowsUserFunctions::localUserGroups() { - QStringList groupList; - LPBYTE outBuffer = nullptr; DWORD entriesRead = 0; DWORD totalEntries = 0; - if( NetLocalGroupEnum( nullptr, 0, &outBuffer, MAX_PREFERRED_LENGTH, &entriesRead, &totalEntries, nullptr ) == NERR_Success ) + const auto result = NetLocalGroupEnum( nullptr, 0, &outBuffer, MAX_PREFERRED_LENGTH, + &entriesRead, &totalEntries, nullptr ); + if( result == NERR_Success ) { const auto* groupInfos = reinterpret_cast( outBuffer ); + QStringList groupList; groupList.reserve( static_cast( entriesRead ) ); for( DWORD i = 0; i < entriesRead; ++i ) { - groupList += QString::fromUtf16( reinterpret_cast( groupInfos[i].lgrpi0_name ) ); + groupList += QString::fromUtf16(reinterpret_cast(groupInfos[i].lgrpi0_name)); } if( entriesRead < totalEntries ) { - vWarning() << "not all local groups fetched"; + vWarning() << "not all local groups fetched" << entriesRead << totalEntries; } NetApiBufferFree( outBuffer ); + + return groupList; } else { - vWarning() << "could not fetch local groups"; + vWarning() << "failed to fetch local groups:" << result; } - return groupList; + return {}; } QStringList WindowsUserFunctions::localGroupsOfUser( const QString& username ) { - QStringList groupList; - LPBYTE outBuffer = nullptr; DWORD entriesRead = 0; DWORD totalEntries = 0; - if( NetUserGetLocalGroups( nullptr, WindowsCoreFunctions::toConstWCharArray( username ), - 0, 0, &outBuffer, MAX_PREFERRED_LENGTH, - &entriesRead, &totalEntries ) == NERR_Success ) + const auto result = NetUserGetLocalGroups( nullptr, WindowsCoreFunctions::toConstWCharArray(username), + 0, 0, &outBuffer, MAX_PREFERRED_LENGTH, + &entriesRead, &totalEntries ); + if( result == NERR_Success ) { const auto* localGroupUsersInfo = reinterpret_cast( outBuffer ); + QStringList groupList; groupList.reserve( static_cast( entriesRead ) ); for( DWORD i = 0; i < entriesRead; ++i ) { - groupList += QString::fromUtf16( reinterpret_cast( localGroupUsersInfo[i].lgrui0_name ) ); + groupList += QString::fromUtf16(reinterpret_cast(localGroupUsersInfo[i].lgrui0_name)); } if( entriesRead < totalEntries ) { - vWarning() << "not all local groups fetched for user" << username; + vWarning() << "not all local groups fetched for user" << username << entriesRead << totalEntries; } NetApiBufferFree( outBuffer ); + + return groupList; } else { - vWarning() << "could not fetch local groups for user" << username; + vWarning() << "failed to fetch local groups for user" << username << result; } - return groupList; + return {}; } diff --git a/plugins/platform/windows/WindowsUserFunctions.h b/plugins/platform/windows/WindowsUserFunctions.h index d4969cd73..0f53b8754 100644 --- a/plugins/platform/windows/WindowsUserFunctions.h +++ b/plugins/platform/windows/WindowsUserFunctions.h @@ -1,7 +1,7 @@ /* * WindowsUserFunctions.h - declaration of WindowsUserFunctions class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,6 +24,7 @@ #pragma once +#include "LogonHelper.h" #include "PlatformUserFunctions.h" // clazy:exclude=copyable-polymorphic @@ -36,21 +37,28 @@ class WindowsUserFunctions : public PlatformUserFunctions QStringList userGroups( bool queryDomainGroups ) override; QStringList groupsOfUser( const QString& username, bool queryDomainGroups ) override; - bool isAnyUserLoggedOn() override; + bool isAnyUserLoggedInLocally() override; + bool isAnyUserLoggedInRemotely() override; + QString currentUser() override; - void logon( const QString& username, const QString& password ) override; + bool prepareLogon( const QString& username, const Password& password ) override; + bool performLogon( const QString& username, const Password& password ) override; + void logoff() override; - bool authenticate( const QString& username, const QString& password ) override; + bool authenticate( const QString& username, const Password& password ) override; private: - static QString domainController(); + static QString domainFromUsername( const QString& username ); + static QString domainController( const QString& domainName = {} ); static QStringList domainUserGroups(); static QStringList domainGroupsOfUser( const QString& username ); static QStringList localUserGroups(); static QStringList localGroupsOfUser( const QString& username ); + LogonHelper m_logonHelper{}; + }; diff --git a/plugins/platform/windows/WtsSessionManager.cpp b/plugins/platform/windows/WtsSessionManager.cpp index c175dcc28..bb9ab2c31 100644 --- a/plugins/platform/windows/WtsSessionManager.cpp +++ b/plugins/platform/windows/WtsSessionManager.cpp @@ -1,7 +1,7 @@ /* * WtsSessionManager.cpp - implementation of WtsSessionManager class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,6 +22,7 @@ * */ +#include #include #include @@ -52,126 +53,210 @@ WtsSessionManager::SessionId WtsSessionManager::activeConsoleSession() WtsSessionManager::SessionList WtsSessionManager::activeSessions() { - SessionList sessionList; - PWTS_SESSION_INFO sessions; DWORD sessionCount = 0; - auto result = WTSEnumerateSessions( WTS_CURRENT_SERVER_HANDLE, 0, 1, &sessions, &sessionCount ); + const auto result = WTSEnumerateSessions( WTS_CURRENT_SERVER_HANDLE, 0, 1, &sessions, &sessionCount ); if( result == false ) { - return sessionList; + return {}; } + SessionList sessionList; sessionList.reserve( sessionCount ); for( DWORD sessionIndex = 0; sessionIndex < sessionCount; ++sessionIndex ) { - auto session = &sessions[sessionIndex]; - if( session->State == WTSActive ) + const auto session = &sessions[sessionIndex]; + if( session->State == WTSActive || + QString::fromWCharArray(session->pWinStationName) + .compare( QLatin1String("multiseat"), Qt::CaseInsensitive ) == 0 ) { sessionList.append( session->SessionId ); } } + WTSFreeMemory( sessions ); + return sessionList; } -QString WtsSessionManager::querySessionInformation( SessionId sessionId, SessionInfo sessionInfo ) +QString WtsSessionManager::querySessionInformation(SessionId sessionId, SessionInfo sessionInfo) { - if( sessionId == InvalidSession ) + if (sessionId == InvalidSession) { vCritical() << "called with invalid session ID"; return {}; } - WTS_INFO_CLASS infoClass = WTSInitialProgram; + WTS_INFO_CLASS infoClass{}; - switch( sessionInfo ) + switch (sessionInfo) { case SessionInfo::UserName: infoClass = WTSUserName; break; case SessionInfo::DomainName: infoClass = WTSDomainName; break; + case SessionInfo::SessionUptime: infoClass = WTSSessionInfo; break; + case SessionInfo::ClientAddress: infoClass = WTSClientAddress; break; + case SessionInfo::ClientName: infoClass = WTSClientName; break; default: vCritical() << "invalid session info" << sessionInfo << "requested"; return {}; } QString result; - LPTSTR pBuffer = nullptr; - DWORD dwBufferLen; + LPWSTR queryBuffer = nullptr; + DWORD bufferLen; - if( WTSQuerySessionInformation( WTS_CURRENT_SERVER_HANDLE, sessionId, infoClass, - &pBuffer, &dwBufferLen ) ) + if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, infoClass, &queryBuffer, &bufferLen)) { - result = QString::fromWCharArray( pBuffer ); + switch (infoClass) + { + case WTSClientAddress: + { + const auto clientAddress = PWTS_CLIENT_ADDRESS(queryBuffer); + switch (clientAddress->AddressFamily) + { + case AF_UNSPEC: + result = QString::fromLatin1(reinterpret_cast(clientAddress->Address)); + break; + case AF_INET: + result = QStringLiteral("%1.%2.%3.%4") + .arg(int(clientAddress->Address[2])) + .arg(int(clientAddress->Address[3])) + .arg(int(clientAddress->Address[4])) + .arg(int(clientAddress->Address[5])); + break; + case AF_INET6: + for (int i = 2; i < 18; i++) + { + if (i != 2 && i % 2 == 0) + { + result.append(QLatin1Char(':')); + } + result.append(QStringLiteral("%1").arg( int(clientAddress->Address[i]), 16, 2, QLatin1Char('0'))); + } + break; + } + break; + } + case WTSSessionInfo: + { + const auto sessionInfoData = PWTSINFO(queryBuffer); + switch (sessionInfo) + { + case SessionInfo::SessionUptime: + result = QString::number((sessionInfoData->CurrentTime.QuadPart - + qMax(sessionInfoData->ConnectTime.QuadPart, sessionInfoData->LogonTime.QuadPart)) + / (1000*1000*10)); + break; + default: + vCritical() << "unhandled session info" << sessionInfo; + break; + } + break; + } + default: + result = QString::fromWCharArray(queryBuffer); + break; + } + } + else + { + const auto lastError = GetLastError(); + vCritical() << lastError; } - WTSFreeMemory( pBuffer ); - - vDebug() << sessionId << sessionInfo << result; + WTSFreeMemory(queryBuffer); return result; } -WtsSessionManager::ProcessId WtsSessionManager::findWinlogonProcessId( SessionId sessionId ) +QString WtsSessionManager::queryUserSid(SessionId sessionId) { - if( sessionId == InvalidSession ) + HANDLE userToken = nullptr; + if (WTSQueryUserToken(sessionId, &userToken) == false) { - vCritical() << "called with invalid session ID"; - return InvalidProcess; + vCritical() << "could not query user token for session" << sessionId; + return {}; } - PWTS_PROCESS_INFO processInfo = nullptr; - DWORD processCount = 0; - - if( WTSEnumerateProcesses( WTS_CURRENT_SERVER_HANDLE, 0, 1, &processInfo, &processCount ) == false ) + DWORD tokenSize = 0; + if (GetTokenInformation(userToken, TokenUser, nullptr, 0, &tokenSize) || + tokenSize == 0 || + GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - return InvalidProcess; + CloseHandle(userToken); + return {}; } - auto pid = InvalidProcess; - const auto processName = QStringLiteral("winlogon.exe"); + const auto userInfo = reinterpret_cast(HeapAlloc(GetProcessHeap(), 0, tokenSize)); + if (!userInfo) + { + CloseHandle(userToken); + return {}; + } - for( DWORD proc = 0; proc < processCount; ++proc ) + if (!GetTokenInformation(userToken, TokenUser, userInfo, tokenSize, &tokenSize)) { - if( processInfo[proc].ProcessId == 0 ) - { - continue; - } + HeapFree(GetProcessHeap(), 0, userInfo); + CloseHandle(userToken); + return {}; + } - if( processName.compare( QString::fromWCharArray( processInfo[proc].pProcessName ), Qt::CaseInsensitive ) == 0 && - sessionId == processInfo[proc].SessionId ) - { - pid = processInfo[proc].ProcessId; - break; - } + QString sid; + wchar_t* stringSid = nullptr; + if (ConvertSidToStringSid(userInfo->User.Sid, &stringSid) && stringSid) + { + sid = QString::fromWCharArray(stringSid); + LocalFree(stringSid); } - WTSFreeMemory( processInfo ); + HeapFree(GetProcessHeap(), 0, userInfo); + CloseHandle(userToken); - return pid; + return sid; +} + + + +bool WtsSessionManager::isRemote( SessionId sessionId ) +{ + const auto WTSIsRemoteSession = static_cast(29); + + BOOL *isRDP = nullptr; + DWORD dataLen = 0; + + if( WTSQuerySessionInformation( WTS_CURRENT_SERVER_HANDLE, sessionId, WTSIsRemoteSession, + reinterpret_cast(&isRDP), &dataLen ) && + isRDP ) + { + const auto result = *isRDP; + WTSFreeMemory( isRDP ); + return result; + } + + return false; } -WtsSessionManager::ProcessId WtsSessionManager::findProcessId( const QString& userName ) +WtsSessionManager::ProcessId WtsSessionManager::findUserProcessId( const QString& userName ) { DWORD sidLen = SECURITY_MAX_SID_SIZE; // Flawfinder: ignore - char userSID[SECURITY_MAX_SID_SIZE]; // Flawfinder: ignore - wchar_t domainName[MAX_PATH]; // Flawfinder: ignore - domainName[0] = 0; - DWORD domainLen = MAX_PATH; + std::array userSID{}; + std::array domainName{}; + DWORD domainLen = domainName.size(); SID_NAME_USE sidNameUse; if( LookupAccountName( nullptr, // system name WindowsCoreFunctions::toConstWCharArray( userName ), - userSID, + userSID.data(), &sidLen, - domainName, + domainName.data(), &domainLen, &sidNameUse ) == false ) { @@ -194,7 +279,7 @@ WtsSessionManager::ProcessId WtsSessionManager::findProcessId( const QString& us { if( processInfo[proc].ProcessId > 0 && processInfo[proc].pUserSid != nullptr && - EqualSid( processInfo[proc].pUserSid, userSID ) ) + EqualSid( processInfo[proc].pUserSid, userSID.data() ) ) { pid = processInfo[proc].ProcessId; break; @@ -208,44 +293,38 @@ WtsSessionManager::ProcessId WtsSessionManager::findProcessId( const QString& us -QStringList WtsSessionManager::loggedOnUsers() +WtsSessionManager::ProcessId WtsSessionManager::findProcessId(const QString& processName, SessionId sessionId) { - PWTS_SESSION_INFO sessionInfo = nullptr; - DWORD sessionCount = 0; + PWTS_PROCESS_INFO processInfo = nullptr; + DWORD processCount = 0; - if( WTSEnumerateSessions( WTS_CURRENT_SERVER_HANDLE, 0, 1, &sessionInfo, &sessionCount ) == false ) + if( WTSEnumerateProcesses( WTS_CURRENT_SERVER_HANDLE, 0, 1, &processInfo, &processCount ) == false ) { - return {}; + return InvalidProcess; } - QStringList users; + auto pid = InvalidProcess; - for( DWORD session = 0; session < sessionCount; ++session ) + for( DWORD proc = 0; proc < processCount; ++proc ) { - if( sessionInfo[session].State != WTSActive ) + if( processInfo[proc].ProcessId == 0 ) { continue; } - LPTSTR userBuffer = nullptr; - DWORD bytesReturned = 0; - if( WTSQuerySessionInformation( WTS_CURRENT_SERVER_HANDLE, sessionInfo[session].SessionId, WTSUserName, - &userBuffer, &bytesReturned ) == false || - userBuffer == nullptr ) + if (sessionId != InvalidSession && processInfo[proc].SessionId != sessionId) { continue; } - const auto user = QString::fromWCharArray( userBuffer ); - if( user.isEmpty() == false && users.contains( user ) == false ) + if( processName.compare( QString::fromWCharArray( processInfo[proc].pProcessName ), Qt::CaseInsensitive ) == 0 ) { - users.append( user ); + pid = processInfo[proc].ProcessId; + break; } - - WTSFreeMemory( userBuffer ); } - WTSFreeMemory( sessionInfo ); + WTSFreeMemory( processInfo ); - return users; + return pid; } diff --git a/plugins/platform/windows/WtsSessionManager.h b/plugins/platform/windows/WtsSessionManager.h index 5826ed117..165ee06f8 100644 --- a/plugins/platform/windows/WtsSessionManager.h +++ b/plugins/platform/windows/WtsSessionManager.h @@ -1,7 +1,7 @@ /* * WtsSessionManager.h - header file for WtsSessionManager class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -39,6 +39,9 @@ class WtsSessionManager enum class SessionInfo { UserName, DomainName, + SessionUptime, + ClientAddress, + ClientName }; Q_ENUM(SessionInfo) @@ -53,10 +56,11 @@ class WtsSessionManager static SessionList activeSessions(); static QString querySessionInformation( SessionId sessionId, SessionInfo sessionInfo ); + static QString queryUserSid(SessionId sessionId); - static ProcessId findWinlogonProcessId( SessionId sessionId ); - static ProcessId findProcessId( const QString& userName ); + static bool isRemote( SessionId sessionId ); - static QStringList loggedOnUsers(); + static ProcessId findUserProcessId( const QString& userName ); + static ProcessId findProcessId(const QString& processName, SessionId sessionId = InvalidSession); } ; diff --git a/plugins/platform/windows/XEventLog.cpp b/plugins/platform/windows/XEventLog.cpp index 27a7f73d3..af849dcc8 100644 --- a/plugins/platform/windows/XEventLog.cpp +++ b/plugins/platform/windows/XEventLog.cpp @@ -55,7 +55,7 @@ CXEventLog::CXEventLog(LPCTSTR lpszApp /* = NULL*/, LPCTSTR lpszEventMessageDll /* = NULL*/) { #ifdef _DEBUG - if ((lpszApp == NULL) || (lpszApp[0] == _T('\0'))) + if ((lpszApp == nullptr) || (lpszApp[0] == _T('\0'))) { TRACE(_T("=== No app specified in CXEventLog ctor. ") _T("Be sure to call Init() before calling Write(). ===\n")); @@ -85,10 +85,7 @@ CXEventLog::CXEventLog(LPCTSTR lpszApp /* = NULL*/, CXEventLog::~CXEventLog() { Close(); - if (m_pszAppName) - { - delete [] m_pszAppName; - } + delete [] m_pszAppName; m_pszAppName = nullptr; } @@ -268,7 +265,7 @@ BOOL CXEventLog::Write(WORD wType, LPCTSTR lpszMessage) BOOL CXEventLog::RegisterSource(LPCTSTR lpszApp, LPCTSTR lpszEventMessageDll) { - _ASSERTE((lpszApp != NULL) && (lpszApp[0] != _T('\0'))); + _ASSERTE((lpszApp != nullptr) && (lpszApp[0] != _T('\0'))); if (!lpszApp || lpszApp[0] == _T('\0')) { return FALSE; @@ -277,8 +274,8 @@ BOOL CXEventLog::RegisterSource(LPCTSTR lpszApp, TCHAR szRegPath[] = _T("SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application\\"); - TCHAR szKey[_MAX_PATH*2]; // Flawfinder: ignore - memset(szKey, 0, _MAX_PATH*2*sizeof(TCHAR)); + TCHAR szKey[MAX_PATH*2]; // Flawfinder: ignore + memset(szKey, 0, MAX_PATH*2*sizeof(TCHAR)); wcsncpy(szKey, szRegPath, MAX_PATH*2-2); // Flawfinder: ignore wcsncat(szKey, lpszApp, MAX_PATH*2-2); // Flawfinder: ignore diff --git a/plugins/platform/windows/XEventLog.h b/plugins/platform/windows/XEventLog.h index 271da492a..4dde4dd39 100644 --- a/plugins/platform/windows/XEventLog.h +++ b/plugins/platform/windows/XEventLog.h @@ -18,7 +18,7 @@ class CXEventLog { // Construction public: - CXEventLog(LPCTSTR lpszApp = NULL, LPCTSTR lpszEventMessageDll = NULL); + CXEventLog(LPCTSTR lpszApp = nullptr, LPCTSTR lpszEventMessageDll = nullptr); ~CXEventLog(); // Attributes @@ -28,11 +28,11 @@ class CXEventLog // Operations public: void Close(); - BOOL Init(LPCTSTR lpszApp, LPCTSTR lpszEventMessageDll = NULL); + BOOL Init(LPCTSTR lpszApp, LPCTSTR lpszEventMessageDll = nullptr); BOOL Write(WORD wType, LPCTSTR lpszMessage); // Implementation -protected: +private: HANDLE m_hEventLog; LPTSTR m_pszAppName; PSID GetUserSid(); diff --git a/plugins/powercontrol/CMakeLists.txt b/plugins/powercontrol/CMakeLists.txt index 5c338782e..524288d7e 100644 --- a/plugins/powercontrol/CMakeLists.txt +++ b/plugins/powercontrol/CMakeLists.txt @@ -1,10 +1,10 @@ -INCLUDE(BuildPlugin) +include(BuildVeyonPlugin) -BUILD_PLUGIN(powercontrol +build_veyon_plugin(powercontrol PowerControlFeaturePlugin.cpp PowerControlFeaturePlugin.h PowerDownTimeInputDialog.cpp PowerDownTimeInputDialog.h PowerDownTimeInputDialog.ui powercontrol.qrc -) + ) diff --git a/plugins/powercontrol/PowerControlFeaturePlugin.cpp b/plugins/powercontrol/PowerControlFeaturePlugin.cpp index 8988230ce..58594dd99 100644 --- a/plugins/powercontrol/PowerControlFeaturePlugin.cpp +++ b/plugins/powercontrol/PowerControlFeaturePlugin.cpp @@ -1,7 +1,7 @@ /* * PowerControlFeaturePlugin.cpp - implementation of PowerControlFeaturePlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,6 +22,7 @@ * */ +#include #include #include #include @@ -46,7 +47,7 @@ PowerControlFeaturePlugin::PowerControlFeaturePlugin( QObject* parent ) : { QStringLiteral("on"), tr( "Power on a computer via Wake-on-LAN (WOL)" ) }, } ), m_powerOnFeature( QStringLiteral( "PowerOn" ), - Feature::Action | Feature::AllComponents, + Feature::Flag::Action | Feature::Flag::AllComponents, Feature::Uid( "f483c659-b5e7-4dbc-bd91-2c9403e70ebd" ), Feature::Uid(), tr( "Power on" ), {}, @@ -54,14 +55,14 @@ PowerControlFeaturePlugin::PowerControlFeaturePlugin( QObject* parent ) : "This way you do not have to power on each computer by hand." ), QStringLiteral(":/powercontrol/preferences-system-power-management.png") ), m_rebootFeature( QStringLiteral( "Reboot" ), - Feature::Action | Feature::AllComponents, + Feature::Flag::Action | Feature::Flag::AllComponents, Feature::Uid( "4f7d98f0-395a-4fff-b968-e49b8d0f748c" ), Feature::Uid(), tr( "Reboot" ), {}, tr( "Click this button to reboot all computers." ), QStringLiteral(":/powercontrol/system-reboot.png") ), m_powerDownFeature( QStringLiteral( "PowerDown" ), - Feature::Action | Feature::AllComponents, + Feature::Flag::Action | Feature::Flag::AllComponents, Feature::Uid( "6f5a27a0-0e2f-496e-afcc-7aae62eede10" ), Feature::Uid(), tr( "Power down" ), {}, @@ -69,22 +70,22 @@ PowerControlFeaturePlugin::PowerControlFeaturePlugin( QObject* parent ) : "This way you do not have to power down each computer by hand." ), QStringLiteral(":/powercontrol/system-shutdown.png") ), m_powerDownNowFeature( QStringLiteral( "PowerDownNow" ), - Feature::Action | Feature::AllComponents, + Feature::Flag::Action | Feature::Flag::AllComponents, Feature::Uid( "a88039f2-6716-40d8-b4e1-9f5cd48e91ed" ), m_powerDownFeature.uid(), tr( "Power down now" ), {}, {} ), m_installUpdatesAndPowerDownFeature( QStringLiteral( "InstallUpdatesAndPowerDown" ), - Feature::Action | Feature::AllComponents, + Feature::Flag::Action | Feature::Flag::AllComponents, Feature::Uid( "09bcb3a1-fc11-4d03-8cf1-efd26be8655b" ), m_powerDownFeature.uid(), tr( "Install updates and power down" ), {}, {} ), m_powerDownConfirmedFeature( QStringLiteral( "PowerDownConfirmed" ), - Feature::Action | Feature::AllComponents, + Feature::Flag::Action | Feature::Flag::AllComponents, Feature::Uid( "ea2406be-d5c7-42b8-9f04-53469d3cc34c" ), m_powerDownFeature.uid(), tr( "Power down after user confirmation" ), {}, {} ), m_powerDownDelayedFeature( QStringLiteral( "PowerDownDelayed" ), - Feature::Action | Feature::AllComponents, + Feature::Flag::Action | Feature::Flag::AllComponents, Feature::Uid( "352de795-7fc4-4850-bc57-525bcb7033f5" ), m_powerDownFeature.uid(), tr( "Power down after timeout" ), {}, {} ), @@ -116,43 +117,77 @@ const FeatureList &PowerControlFeaturePlugin::featureList() const -bool PowerControlFeaturePlugin::startFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) +bool PowerControlFeaturePlugin::controlFeature( Feature::Uid featureUid, + Operation operation, + const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) { - if( m_features.contains( feature ) == false ) + if( operation != Operation::Start || hasFeature( featureUid ) == false ) { return false; } - if( feature == m_powerOnFeature ) + if( featureUid == m_powerOnFeature.uid() ) { for( const auto& controlInterface : computerControlInterfaces ) { broadcastWOLPacket( controlInterface->computer().macAddress() ); } } - else if( feature == m_powerDownDelayedFeature ) + else if( featureUid == m_powerDownDelayedFeature.uid() ) { - PowerDownTimeInputDialog dialog( master.mainWindow() ); + const auto shutdownTimeout = arguments.value( argToString(Argument::ShutdownTimeout), 60 ).toInt(); - if( dialog.exec() ) - { - sendFeatureMessage( FeatureMessage( feature.uid(), FeatureMessage::DefaultCommand ). - addArgument( ShutdownTimeout, dialog.seconds() ), - computerControlInterfaces ); - } + sendFeatureMessage( FeatureMessage{ featureUid, FeatureMessage::DefaultCommand } + .addArgument( Argument::ShutdownTimeout, shutdownTimeout ), + computerControlInterfaces ); } else { - if( confirmFeatureExecution( feature, master.mainWindow() ) == false ) + sendFeatureMessage( FeatureMessage{ featureUid, FeatureMessage::DefaultCommand }, computerControlInterfaces ); + } + + return true; +} + + + +bool PowerControlFeaturePlugin::startFeature( VeyonMasterInterface& master, const Feature& feature, + const ComputerControlInterfaceList& computerControlInterfaces ) +{ + if( hasFeature( feature.uid() ) == false ) + { + return false; + } + + if( feature == m_powerOnFeature ) + { + return controlFeature( feature.uid(), Operation::Start, {}, computerControlInterfaces ); + } + + if( feature == m_powerDownDelayedFeature ) + { + PowerDownTimeInputDialog dialog( master.mainWindow() ); + + if( dialog.exec() ) { - return false; + return controlFeature( feature.uid(), Operation::Start, + { { argToString(Argument::ShutdownTimeout), dialog.seconds() } }, + computerControlInterfaces ); } - sendFeatureMessage( FeatureMessage( feature.uid(), FeatureMessage::DefaultCommand ), computerControlInterfaces ); + return true; } - return true; + const auto executeOnAllComputers = + computerControlInterfaces.size() >= master.filteredComputerControlInterfaces().size(); + + if (confirmFeatureExecution(feature, executeOnAllComputers, master.mainWindow()) == false) + { + return false; + } + + return controlFeature( feature.uid(), Operation::Start, {}, computerControlInterfaces ); } @@ -174,20 +209,19 @@ bool PowerControlFeaturePlugin::handleFeatureMessage( VeyonServerInterface& serv } else if( message.featureUid() == m_powerDownConfirmedFeature.uid() ) { - if( VeyonCore::platform().userFunctions().isAnyUserLoggedOn() == false ) + if( VeyonCore::platform().userFunctions().isAnyUserLoggedInLocally() == false && + VeyonCore::platform().userFunctions().isAnyUserLoggedInRemotely() == false ) { VeyonCore::platform().coreFunctions().powerDown( false ); } else { - featureWorkerManager.startWorker( m_powerDownConfirmedFeature, FeatureWorkerManager::ManagedSystemProcess ); - featureWorkerManager.sendMessage( message ); + featureWorkerManager.sendMessageToManagedSystemWorker( message ); } } else if( message.featureUid() == m_powerDownDelayedFeature.uid() ) { - featureWorkerManager.startWorker( m_powerDownDelayedFeature, FeatureWorkerManager::ManagedSystemProcess ); - featureWorkerManager.sendMessage( message ); + featureWorkerManager.sendMessageToManagedSystemWorker( message ); } else if( message.featureUid() == m_rebootFeature.uid() ) { @@ -212,9 +246,10 @@ bool PowerControlFeaturePlugin::handleFeatureMessage( VeyonWorkerInterface& work confirmShutdown(); return true; } - else if( message.featureUid() == m_powerDownDelayedFeature.uid() ) + + if( message.featureUid() == m_powerDownDelayedFeature.uid() ) { - displayShutdownTimeout( message.argument( ShutdownTimeout ).toInt() ); + displayShutdownTimeout( message.argument( Argument::ShutdownTimeout ).toInt() ); return true; } @@ -250,7 +285,7 @@ CommandLinePluginInterface::RunResult PowerControlFeaturePlugin::handle_help( co CommandLinePluginInterface::RunResult PowerControlFeaturePlugin::handle_on( const QStringList& arguments ) { - if( arguments.size() < 1 ) + if( arguments.isEmpty() ) { return NotEnoughArguments; } @@ -260,7 +295,21 @@ CommandLinePluginInterface::RunResult PowerControlFeaturePlugin::handle_on( cons -bool PowerControlFeaturePlugin::confirmFeatureExecution( const Feature& feature, QWidget* parent ) +bool PowerControlFeaturePlugin::eventFilter(QObject* watched, QEvent* event) +{ + if (event->type() == QEvent::Close && + qobject_cast(watched)) + { + event->ignore(); + return true; + } + + return QObject::eventFilter(watched, event); +} + + + +bool PowerControlFeaturePlugin::confirmFeatureExecution( const Feature& feature, bool all, QWidget* parent ) { if( VeyonCore::config().confirmUnsafeActions() == false ) { @@ -270,29 +319,32 @@ bool PowerControlFeaturePlugin::confirmFeatureExecution( const Feature& feature, if( feature == m_rebootFeature ) { return QMessageBox::question( parent, tr( "Confirm reboot" ), - tr( "Do you really want to reboot the selected computers?" ) ) == + all ? tr( "Do you really want to reboot ALL computers?" ) + : tr( "Do you really want to reboot the selected computers?" ) ) == QMessageBox::Yes; } - else if( feature == m_powerDownFeature || + + if( feature == m_powerDownFeature || feature == m_powerDownNowFeature || feature == m_installUpdatesAndPowerDownFeature || feature == m_powerDownConfirmedFeature || feature == m_powerDownDelayedFeature ) { return QMessageBox::question( parent, tr( "Confirm power down" ), - tr( "Do you really want to power down the selected computer?" ) ) == + all ? tr( "Do you really want to power down ALL computers?" ) + : tr( "Do you really want to power down the selected computers?" ) ) == QMessageBox::Yes; } - return false; + return true; } bool PowerControlFeaturePlugin::broadcastWOLPacket( QString macAddress ) { - const int MAC_SIZE = 6; - unsigned int mac[MAC_SIZE]; // Flawfinder: ignore + static constexpr size_t MAC_SIZE = 6; + std::array mac{}; if( macAddress.isEmpty() ) { @@ -322,11 +374,11 @@ bool PowerControlFeaturePlugin::broadcastWOLPacket( QString macAddress ) QByteArray datagram( MAC_SIZE*17, static_cast( 0xff ) ); - for( int i = 1; i < 17; ++i ) + for( size_t i = 1; i < 17; ++i ) { - for(int j = 0; j < MAC_SIZE; ++j ) + for( size_t j = 0; j < MAC_SIZE; ++j ) { - datagram[i*MAC_SIZE+j] = static_cast( mac[j] ); + datagram[uint(i*MAC_SIZE+j)] = static_cast( mac.at(j) ); } } @@ -358,7 +410,7 @@ void PowerControlFeaturePlugin::confirmShutdown() tr( "The computer was remotely requested to power down. Do you want to power down the computer now?" ), QMessageBox::Yes | QMessageBox::No ); m.show(); - VeyonCore::platform().coreFunctions().raiseWindow( &m ); + VeyonCore::platform().coreFunctions().raiseWindow( &m, true ); if( m.exec() == QMessageBox::Yes ) { @@ -382,7 +434,7 @@ static void updateDialog( QProgressDialog* dialog, int newValue ) if( remainingSeconds <= 0 ) { - VeyonCore::platform().coreFunctions().powerDown( false ); + dialog->accept(); } } @@ -395,6 +447,7 @@ void PowerControlFeaturePlugin::displayShutdownTimeout( int shutdownTimeout ) dialog.setMaximum( shutdownTimeout ); dialog.setCancelButton( nullptr ); dialog.setWindowFlags( Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint ); + dialog.installEventFilter(this); auto progressBar = dialog.findChild(); if( progressBar ) @@ -405,7 +458,7 @@ void PowerControlFeaturePlugin::displayShutdownTimeout( int shutdownTimeout ) updateDialog( &dialog, 0 ); dialog.show(); - VeyonCore::platform().coreFunctions().raiseWindow( &dialog ); + VeyonCore::platform().coreFunctions().raiseWindow( &dialog, true ); QTimer powerdownTimer; powerdownTimer.start( 1000 ); @@ -415,4 +468,6 @@ void PowerControlFeaturePlugin::displayShutdownTimeout( int shutdownTimeout ) } ); dialog.exec(); + + VeyonCore::platform().coreFunctions().powerDown(false); } diff --git a/plugins/powercontrol/PowerControlFeaturePlugin.h b/plugins/powercontrol/PowerControlFeaturePlugin.h index 90963223e..37d4cc9fc 100644 --- a/plugins/powercontrol/PowerControlFeaturePlugin.h +++ b/plugins/powercontrol/PowerControlFeaturePlugin.h @@ -1,7 +1,7 @@ /* * PowerControlFeaturePlugin.h - declaration of PowerControlFeaturePlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,24 +27,30 @@ #include "CommandLineIO.h" #include "CommandLinePluginInterface.h" #include "Feature.h" -#include "SimpleFeatureProvider.h" +#include "FeatureProviderInterface.h" class PowerControlFeaturePlugin : public QObject, PluginInterface, CommandLineIO, CommandLinePluginInterface, - SimpleFeatureProvider + FeatureProviderInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "io.veyon.Veyon.Plugins.PowerControl") Q_INTERFACES(PluginInterface CommandLinePluginInterface FeatureProviderInterface) public: + enum class Argument + { + ShutdownTimeout + }; + Q_ENUM(Argument) + explicit PowerControlFeaturePlugin( QObject* parent = nullptr ); ~PowerControlFeaturePlugin() override = default; Plugin::Uid uid() const override { - return QStringLiteral("4122e8ca-b617-4e36-b851-8e050ed2d82e"); + return Plugin::Uid{ QStringLiteral("4122e8ca-b617-4e36-b851-8e050ed2d82e") }; } QVersionNumber version() const override @@ -87,6 +93,9 @@ class PowerControlFeaturePlugin : public QObject, const FeatureList& featureList() const override; + bool controlFeature( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) override; + bool startFeature( VeyonMasterInterface& master, const Feature& feature, const ComputerControlInterfaceList& computerControlInterfaces ) override; @@ -96,16 +105,15 @@ class PowerControlFeaturePlugin : public QObject, bool handleFeatureMessage( VeyonWorkerInterface& worker, const FeatureMessage& message ) override; -public slots: +public Q_SLOTS: CommandLinePluginInterface::RunResult handle_help( const QStringList& arguments ); CommandLinePluginInterface::RunResult handle_on( const QStringList& arguments ); -private: - enum Arguments { - ShutdownTimeout - }; +protected: + bool eventFilter(QObject* watched, QEvent* event) override; - bool confirmFeatureExecution( const Feature& feature, QWidget* parent ); +private: + bool confirmFeatureExecution( const Feature& feature, bool all, QWidget* parent ); static bool broadcastWOLPacket( QString macAddress ); void confirmShutdown(); diff --git a/plugins/powercontrol/PowerDownTimeInputDialog.cpp b/plugins/powercontrol/PowerDownTimeInputDialog.cpp index d786caba9..ecc13bf91 100644 --- a/plugins/powercontrol/PowerDownTimeInputDialog.cpp +++ b/plugins/powercontrol/PowerDownTimeInputDialog.cpp @@ -1,7 +1,7 @@ /* * PowerDownTimeInputDialog.h - implementation of PowerDownTimeInputDialog class * - * Copyright (c) 2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/plugins/powercontrol/PowerDownTimeInputDialog.h b/plugins/powercontrol/PowerDownTimeInputDialog.h index d8d478b99..cbda224c2 100644 --- a/plugins/powercontrol/PowerDownTimeInputDialog.h +++ b/plugins/powercontrol/PowerDownTimeInputDialog.h @@ -1,7 +1,7 @@ /* * PowerDownTimeInputDialog.h - declaration of PowerDownTimeInputDialog class * - * Copyright (c) 2019 Tobias Junghans + * Copyright (c) 2019-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/plugins/remoteaccess/CMakeLists.txt b/plugins/remoteaccess/CMakeLists.txt index d19f22d24..1fbd4f558 100644 --- a/plugins/remoteaccess/CMakeLists.txt +++ b/plugins/remoteaccess/CMakeLists.txt @@ -1,5 +1,11 @@ -INCLUDE(BuildPlugin) +include(BuildVeyonPlugin) -BUILD_PLUGIN(remoteaccess RemoteAccessFeaturePlugin.cpp RemoteAccessWidget.cpp - RemoteAccessFeaturePlugin.h RemoteAccessWidget.h - remoteaccess.qrc) +build_veyon_plugin(remoteaccess + RemoteAccessFeaturePlugin.h + RemoteAccessFeaturePlugin.cpp + RemoteAccessPage.h + RemoteAccessPage.cpp + RemoteAccessWidget.h + RemoteAccessWidget.cpp + remoteaccess.qrc + ) diff --git a/plugins/remoteaccess/RemoteAccessFeaturePlugin.cpp b/plugins/remoteaccess/RemoteAccessFeaturePlugin.cpp index 341863951..c0d93d0fa 100644 --- a/plugins/remoteaccess/RemoteAccessFeaturePlugin.cpp +++ b/plugins/remoteaccess/RemoteAccessFeaturePlugin.cpp @@ -1,7 +1,7 @@ /* * RemoteAccessFeaturePlugin.cpp - implementation of RemoteAccessFeaturePlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,37 +23,55 @@ */ #include +#include +#include #include -#include "AuthenticationCredentials.h" +#include "AuthenticationManager.h" +#include "FeatureWorkerManager.h" #include "RemoteAccessFeaturePlugin.h" +#include "RemoteAccessPage.h" #include "RemoteAccessWidget.h" +#include "VeyonConfiguration.h" #include "VeyonMasterInterface.h" +#include "VeyonServerInterface.h" +#include "VncView.h" RemoteAccessFeaturePlugin::RemoteAccessFeaturePlugin( QObject* parent ) : QObject( parent ), m_remoteViewFeature( QStringLiteral( "RemoteView" ), - Feature::Session | Feature::Master, + Feature::Flag::Session | Feature::Flag::Master, Feature::Uid( "a18e545b-1321-4d4e-ac34-adc421c6e9c8" ), Feature::Uid(), tr( "Remote view" ), {}, tr( "Open a remote view for a computer without interaction." ), QStringLiteral(":/remoteaccess/kmag.png") ), m_remoteControlFeature( QStringLiteral( "RemoteControl" ), - Feature::Session | Feature::Master, + Feature::Flag::Session | Feature::Flag::Master, Feature::Uid( "ca00ad68-1709-4abe-85e2-48dff6ccf8a2" ), Feature::Uid(), tr( "Remote control" ), {}, tr( "Open a remote control window for a computer." ), QStringLiteral(":/remoteaccess/krdc.png") ), - m_features( { m_remoteViewFeature, m_remoteControlFeature } ), + m_clipboardExchangeFeature(QStringLiteral("ClipboardExchange"), + Feature::Flag::Meta, + Feature::Uid("8fa73e19-3d66-4d59-9783-c2a1bb07e20e"), + Feature::Uid(), + tr("Exchange clipboard contents"), {}, {}), + m_features({m_remoteViewFeature, m_remoteControlFeature, m_clipboardExchangeFeature}), m_commands( { { QStringLiteral("view"), m_remoteViewFeature.displayName() }, { QStringLiteral("control"), m_remoteControlFeature.displayName() }, { QStringLiteral("help"), tr( "Show help about command" ) }, - } ) + } ), + m_clipboardSynchronizationDisabled(VeyonCore::config().clipboardSynchronizationDisabled()) { + if (VeyonCore::component() == VeyonCore::Component::Server && m_clipboardSynchronizationDisabled == false) + { + connect (QGuiApplication::clipboard(), &QClipboard::dataChanged, + this, &RemoteAccessFeaturePlugin::updateClipboardData); + } } @@ -65,48 +83,126 @@ const FeatureList &RemoteAccessFeaturePlugin::featureList() const +bool RemoteAccessFeaturePlugin::controlFeature(Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces) +{ + if (hasFeature(featureUid) && + operation == Operation::Start) + { + sendFeatureMessage(FeatureMessage{featureUid} + .addArgument(Argument::HostName, arguments.value(argToString(Argument::HostName))), + computerControlInterfaces); + return true; + } + + return false; +} + + + bool RemoteAccessFeaturePlugin::startFeature( VeyonMasterInterface& master, const Feature& feature, const ComputerControlInterfaceList& computerControlInterfaces ) { - // determine which computer to access and ask if neccessary - ComputerControlInterface::Pointer remoteAccessComputer; + Q_UNUSED(computerControlInterfaces) + + if( hasFeature( feature.uid() ) == false ) + { + return false; + } + + const auto viewOnly = feature.uid() == m_remoteViewFeature.uid() || + remoteControlEnabled() == false; + + const auto selectedComputerControlInterfaces = master.selectedComputerControlInterfaces(); - if( ( feature.uid() == m_remoteViewFeature.uid() || - feature.uid() == m_remoteControlFeature.uid() ) && - computerControlInterfaces.count() != 1 ) + if (selectedComputerControlInterfaces.count() > 0) + { + for (const auto& computerControlInterface : selectedComputerControlInterfaces) + { + createRemoteAccessWindow(computerControlInterface, viewOnly, &master); + } + } + else { - QString hostName = QInputDialog::getText( master.mainWindow(), - tr( "Remote access" ), - tr( "Please enter the hostname or IP address of the computer to access:" ) ); - if( hostName.isEmpty() ) + const auto hostAddress = QInputDialog::getText(master.mainWindow(), + tr("Remote access"), + tr("No computer has been selected so you can enter a hostname " + "or IP address of a computer for manual access:")); + if (hostAddress.isEmpty()) { return false; } Computer customComputer; - customComputer.setHostAddress( hostName ); - customComputer.setName( hostName ); - remoteAccessComputer = ComputerControlInterface::Pointer::create( customComputer ); + customComputer.setHostAddress(hostAddress); + customComputer.setDisplayName(hostAddress); + + createRemoteAccessWindow(ComputerControlInterface::Pointer::create(customComputer), viewOnly, &master); } - else if( computerControlInterfaces.count() >= 1 ) + + return true; +} + + + +bool RemoteAccessFeaturePlugin::handleFeatureMessage(ComputerControlInterface::Pointer computerControlInterface, + const FeatureMessage& message) +{ + Q_UNUSED(computerControlInterface) + + if (message.featureUid() == m_clipboardExchangeFeature.uid() && m_clipboardSynchronizationDisabled == false) { - remoteAccessComputer = computerControlInterfaces.first(); + for (auto it = m_vncViews.constBegin(), end = m_vncViews.constEnd(); it != end; ++it) + { + if (it->first && it->second->computerControlInterface() == computerControlInterface) + { + loadClipboardData(message); + } + } + + return true; } - if( remoteAccessComputer.isNull() ) + return false; +} + + + +bool RemoteAccessFeaturePlugin::handleFeatureMessage(VeyonServerInterface &server, + const MessageContext &messageContext, + const FeatureMessage &message) +{ + Q_UNUSED(messageContext) + + if (message.featureUid() == m_remoteViewFeature.uid() || + message.featureUid() == m_remoteControlFeature.uid()) { - return false; + // forward message to worker + server.featureWorkerManager().sendMessageToUnmanagedSessionWorker(message); + return true; } - - if( feature.uid() == m_remoteViewFeature.uid() ) + else if (message.featureUid() == m_clipboardExchangeFeature.uid() && m_clipboardSynchronizationDisabled == false) { - new RemoteAccessWidget( remoteAccessComputer, true ); - + loadClipboardData(message); return true; } - else if( feature.uid() == m_remoteControlFeature.uid() ) + + return false; +} + + + +bool RemoteAccessFeaturePlugin::handleFeatureMessage(VeyonWorkerInterface &worker, const FeatureMessage &message) +{ + Q_UNUSED(worker) + + if (message.featureUid() == m_remoteViewFeature.uid() || + message.featureUid() == m_remoteControlFeature.uid()) { - new RemoteAccessWidget( remoteAccessComputer, false ); + const auto viewOnly = message.featureUid() == m_remoteViewFeature.uid() || + remoteControlEnabled() == false; + + remoteAccess(message.argument(Argument::HostName).toString(), viewOnly); return true; } @@ -116,6 +212,26 @@ bool RemoteAccessFeaturePlugin::startFeature( VeyonMasterInterface& master, cons +void RemoteAccessFeaturePlugin::sendAsyncFeatureMessages(VeyonServerInterface& server, + const MessageContext& messageContext) +{ + const auto clipboardDataVersion = messageContext.ioDevice()->property(clipboardDataVersionProperty()).toInt(); + + if (m_clipboardSynchronizationDisabled == false && clipboardDataVersion != m_clipboardDataVersion) + { + FeatureMessage message{m_clipboardExchangeFeature.uid()}; + + m_clipboardDataMutex.lock(); + storeClipboardData(&message, m_clipboardText, m_clipboardImage); + m_clipboardDataMutex.unlock(); + + server.sendFeatureMessageReply(messageContext, message); + messageContext.ioDevice()->setProperty(clipboardDataVersionProperty(), m_clipboardDataVersion); + } +} + + + QStringList RemoteAccessFeaturePlugin::commands() const { return m_commands.keys(); @@ -137,7 +253,18 @@ CommandLinePluginInterface::RunResult RemoteAccessFeaturePlugin::handle_view( co return NotEnoughArguments; } - return remoteAccess( arguments.first(), true ) ? Successful : Failed; + if( remoteViewEnabled() == false ) + { + return InvalidCommand; + } + + if (remoteAccess(arguments.first(), true)) + { + qApp->exec(); + return Successful; + } + + return Failed; } @@ -149,7 +276,18 @@ CommandLinePluginInterface::RunResult RemoteAccessFeaturePlugin::handle_control( return NotEnoughArguments; } - return remoteAccess( arguments.first(), false ) ? Successful : Failed; + if( remoteControlEnabled() == false ) + { + return InvalidCommand; + } + + if (remoteAccess(arguments.first(), false)) + { + qApp->exec(); + return Successful; + } + + return Failed; } @@ -161,7 +299,8 @@ CommandLinePluginInterface::RunResult RemoteAccessFeaturePlugin::handle_help( co printf( "\nremoteaccess view \n\n" ); return NoResult; } - else if( arguments.value( 0 ) == QLatin1String("control") ) + + if( arguments.value( 0 ) == QLatin1String("control") ) { printf( "\nremoteaccess control \n}n" ); return NoResult; @@ -172,15 +311,25 @@ CommandLinePluginInterface::RunResult RemoteAccessFeaturePlugin::handle_help( co -bool RemoteAccessFeaturePlugin::initAuthentication() +bool RemoteAccessFeaturePlugin::remoteViewEnabled() const { - if( VeyonCore::instance()->initAuthentication() == false ) - { - vWarning() << "Could not initialize authentication"; - return false; - } + return VeyonCore::config().disabledFeatures().contains( m_remoteViewFeature.uid().toString() ) == false; - return true; +} + + + +bool RemoteAccessFeaturePlugin::remoteControlEnabled() const +{ + return VeyonCore::config().disabledFeatures().contains( m_remoteControlFeature.uid().toString() ) == false; +} + + + +bool RemoteAccessFeaturePlugin::initAuthentication() +{ + return VeyonCore::authenticationManager().initializeCredentials() && + VeyonCore::authenticationManager().initializedPlugin()->checkCredentials(); } @@ -193,12 +342,155 @@ bool RemoteAccessFeaturePlugin::remoteAccess( const QString& hostAddress, bool v } Computer remoteComputer; - remoteComputer.setName( hostAddress ); - remoteComputer.setHostAddress( hostAddress ); + remoteComputer.setDisplayName(hostAddress); + remoteComputer.setHostAddress(hostAddress); - new RemoteAccessWidget( ComputerControlInterface::Pointer::create( remoteComputer ), viewOnly ); + if( remoteControlEnabled() == false ) + { + viewOnly = true; + } - qApp->exec(); + createRemoteAccessWindow(ComputerControlInterface::Pointer::create(remoteComputer), viewOnly, nullptr); return true; } + + + +void RemoteAccessFeaturePlugin::createRemoteAccessWindow(const ComputerControlInterface::Pointer& computerControlInterface, + bool viewOnly, VeyonMasterInterface* master) +{ + VncView* vncView{nullptr}; + QObject* remoteAccessView{nullptr}; + + if (master && master->appContainer()) + { + auto page = new RemoteAccessPage(computerControlInterface, viewOnly, master->appContainer()); + // forward clipboard changes as long as the page exists + connect(QGuiApplication::clipboard(), &QClipboard::dataChanged, page, [=]() + { + sendClipboardData(page->computerControlInterface()); + }); + + remoteAccessView = page; + vncView = page->vncView(); + } + else + { + auto widget = new RemoteAccessWidget(computerControlInterface, viewOnly, + remoteViewEnabled() && remoteControlEnabled()); + + // forward clipboard changes as long as the widget exists + connect(QGuiApplication::clipboard(), &QClipboard::dataChanged, widget, [=]() + { + sendClipboardData(widget->computerControlInterface()); + }); + + remoteAccessView = widget; + vncView = widget->vncView(); + } + + connect(remoteAccessView, &QObject::destroyed, this, [this](QObject* view) { + for (auto it = m_vncViews.begin(); it != m_vncViews.end();) // clazy:exclude=detaching-member + { + if (it->first == nullptr || it->first == view) + { + it = m_vncViews.erase(it); + } + else + { + it++; + } + } + }); + + m_vncViews.append(qMakePair(remoteAccessView, vncView)); +} + + + +void RemoteAccessFeaturePlugin::storeClipboardData(FeatureMessage *message, const QString& text, const QImage& image) +{ + QBuffer buffer; + buffer.open(QIODevice::WriteOnly); + image.save(&buffer, clipboardImageFormat()); + buffer.close(); + + message->addArgument(Argument::ClipboardText, text); + message->addArgument(Argument::ClipboardImage, buffer.data()); +} + + + +void RemoteAccessFeaturePlugin::loadClipboardData(const FeatureMessage &message) +{ + if (m_clipboardSynchronizationDisabled) + { + return; + } + + const auto clipboard = QGuiApplication::clipboard(); + + const auto text = message.argument(Argument::ClipboardText).toString(); + if (text.isEmpty() == false && clipboard->text() != text) + { + clipboard->setText(text); + } + + // TODO: better support for image I/O on Windows via QWindowsMime + + const auto image = QImage::fromData(message.argument(Argument::ClipboardImage).toByteArray(), + clipboardImageFormat()); + if (image.isNull() == false && clipboard->image() != image) + { + clipboard->setImage(image); + } +} + + + +void RemoteAccessFeaturePlugin::sendClipboardData(ComputerControlInterface::Pointer computerControlInterface) +{ + if (m_clipboardSynchronizationDisabled) + { + return; + } + + FeatureMessage message{m_clipboardExchangeFeature.uid()}; + + const auto clipboard = QGuiApplication::clipboard(); + + // TODO: better support for image I/O on Windows via QWindowsMime + storeClipboardData(&message, clipboard->text(), clipboard->image()); + + computerControlInterface->sendFeatureMessage(message); +} + + + +void RemoteAccessFeaturePlugin::updateClipboardData() +{ + if (m_clipboardSynchronizationDisabled) + { + return; + } + + m_clipboardDataMutex.lock(); + + const auto clipboard = QGuiApplication::clipboard(); + + if (m_clipboardText != clipboard->text()) + { + m_clipboardText = clipboard->text(); + ++m_clipboardDataVersion; + } + + // TODO: better support for image I/O on Windows via QWindowsMime + if (m_clipboardImage != clipboard->image()) + { + m_clipboardImage = clipboard->image(); + ++m_clipboardDataVersion; + } + + m_clipboardDataMutex.unlock(); +} diff --git a/plugins/remoteaccess/RemoteAccessFeaturePlugin.h b/plugins/remoteaccess/RemoteAccessFeaturePlugin.h index 951276acb..b34873ccf 100644 --- a/plugins/remoteaccess/RemoteAccessFeaturePlugin.h +++ b/plugins/remoteaccess/RemoteAccessFeaturePlugin.h @@ -1,7 +1,7 @@ /* * RemoteAccessFeaturePlugin.h - declaration of RemoteAccessFeaturePlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,22 +25,31 @@ #pragma once #include "Computer.h" -#include "SimpleFeatureProvider.h" +#include "FeatureProviderInterface.h" #include "CommandLinePluginInterface.h" +class VncView; -class RemoteAccessFeaturePlugin : public QObject, CommandLinePluginInterface, SimpleFeatureProvider, PluginInterface +class RemoteAccessFeaturePlugin : public QObject, CommandLinePluginInterface, FeatureProviderInterface, PluginInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "io.veyon.Veyon.Plugins.RemoteAccess") Q_INTERFACES(PluginInterface FeatureProviderInterface CommandLinePluginInterface) public: + enum class Argument + { + HostName, + ClipboardText, + ClipboardImage + }; + Q_ENUM(Argument) + explicit RemoteAccessFeaturePlugin( QObject* parent = nullptr ); ~RemoteAccessFeaturePlugin() override = default; Plugin::Uid uid() const override { - return QStringLiteral("387a0c43-1355-4ff6-9e1f-d098e9ce5127"); + return Plugin::Uid{ QStringLiteral("387a0c43-1355-4ff6-9e1f-d098e9ce5127") }; } QVersionNumber version() const override @@ -70,9 +79,23 @@ class RemoteAccessFeaturePlugin : public QObject, CommandLinePluginInterface, Si const FeatureList& featureList() const override; + bool controlFeature( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) override; + bool startFeature( VeyonMasterInterface& master, const Feature& feature, const ComputerControlInterfaceList& computerControlInterfaces ) override; + bool handleFeatureMessage(ComputerControlInterface::Pointer computerControlInterface, + const FeatureMessage& message) override; + + bool handleFeatureMessage(VeyonServerInterface& server, + const MessageContext& messageContext, + const FeatureMessage& message) override; + + bool handleFeatureMessage(VeyonWorkerInterface& worker, const FeatureMessage& message) override; + + void sendAsyncFeatureMessages(VeyonServerInterface& server, const MessageContext& messageContext) override; + QString commandLineModuleName() const override { return QStringLiteral( "remoteaccess" ); @@ -87,19 +110,48 @@ class RemoteAccessFeaturePlugin : public QObject, CommandLinePluginInterface, Si QString commandHelp( const QString& command ) const override; -private slots: +private Q_SLOTS: CommandLinePluginInterface::RunResult handle_view( const QStringList& arguments ); CommandLinePluginInterface::RunResult handle_control( const QStringList& arguments ); CommandLinePluginInterface::RunResult handle_help( const QStringList& arguments ); private: + static const char* clipboardDataVersionProperty() + { + return "clipboardDataVersion"; + } + + static const char* clipboardImageFormat() + { + return "PNG"; + } + + bool remoteViewEnabled() const; + bool remoteControlEnabled() const; bool initAuthentication(); bool remoteAccess( const QString& hostAddress, bool viewOnly ); + void createRemoteAccessWindow(const ComputerControlInterface::Pointer& computerControlInterface, bool viewOnly, + VeyonMasterInterface* master); + + void storeClipboardData(FeatureMessage* message, const QString& text, const QImage& image); + void loadClipboardData(const FeatureMessage& message); + void sendClipboardData(ComputerControlInterface::Pointer computerControlInterface); + + void updateClipboardData(); const Feature m_remoteViewFeature; const Feature m_remoteControlFeature; + const Feature m_clipboardExchangeFeature; const FeatureList m_features; QMap m_commands; + bool m_clipboardSynchronizationDisabled; + QMutex m_clipboardDataMutex; + int m_clipboardDataVersion{0}; + QString m_clipboardText; + QImage m_clipboardImage; + + QList, VncView *> > m_vncViews{}; + }; diff --git a/plugins/remoteaccess/RemoteAccessPage.cpp b/plugins/remoteaccess/RemoteAccessPage.cpp new file mode 100644 index 000000000..a3697a2f5 --- /dev/null +++ b/plugins/remoteaccess/RemoteAccessPage.cpp @@ -0,0 +1,70 @@ +/* + * RemoteAccessPage.h - logic for RemoteAccessPage + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include "QmlCore.h" +#include "RemoteAccessPage.h" +#include "Screenshot.h" +#include "VncViewItem.h" + + +RemoteAccessPage::RemoteAccessPage( const ComputerControlInterface::Pointer& computerControlInterface, + bool viewOnly, + QQuickItem* parent ) : + QObject( parent ), + m_computerControlInterface( computerControlInterface ), + m_view( new VncViewItem( m_computerControlInterface ) ), + m_item( VeyonCore::qmlCore().createItemFromFile( QStringLiteral("qrc:/remoteaccess/RemoteAccessPage.qml"), parent, this ) ) +{ + m_view->setViewOnly( viewOnly ); + + connect( m_item, &QObject::destroyed, this, &RemoteAccessPage::deleteLater ); +} + + + +RemoteAccessPage::~RemoteAccessPage() +{ + delete m_view; +} + + + +QQuickItem* RemoteAccessPage::view() const +{ + return m_view; +} + + + +VncView* RemoteAccessPage::vncView() const +{ + return m_view; +} + + +/* +void RemoteAccessPage::takeScreenshot() +{ + Screenshot().take( m_computerControlInterface ); +} +*/ diff --git a/plugins/remoteaccess/RemoteAccessPage.h b/plugins/remoteaccess/RemoteAccessPage.h new file mode 100644 index 000000000..8eab5ea19 --- /dev/null +++ b/plugins/remoteaccess/RemoteAccessPage.h @@ -0,0 +1,65 @@ +/* + * RemoteAccessPage.h - logic for RemoteAccessPage + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#pragma once + +#include + +#include "ComputerControlInterface.h" + +class VncView; +class VncViewItem; + +// clazy:excludeall=ctor-missing-parent-argument + +class RemoteAccessPage : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString computerName READ computerName CONSTANT) + Q_PROPERTY(QQuickItem* view READ view CONSTANT) +public: + explicit RemoteAccessPage( const ComputerControlInterface::Pointer& computerControlInterface, + bool viewOnly, + QQuickItem* parent ); + ~RemoteAccessPage() override; + + ComputerControlInterface::Pointer computerControlInterface() const + { + return m_computerControlInterface; + } + + QString computerName() const + { + return m_computerControlInterface->computer().displayName(); + } + + QQuickItem* view() const; + + VncView* vncView() const; + +private: + ComputerControlInterface::Pointer m_computerControlInterface; + VncViewItem* m_view; + QQuickItem* m_item; + +} ; diff --git a/plugins/remoteaccess/RemoteAccessPage.qml b/plugins/remoteaccess/RemoteAccessPage.qml new file mode 100644 index 000000000..50edda3e4 --- /dev/null +++ b/plugins/remoteaccess/RemoteAccessPage.qml @@ -0,0 +1,21 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.0 + +Page { + title: qsTr("Remote access: %1").arg(context.computerName) + property bool canBeClosed: true + Rectangle { + anchors.fill: parent + color: "darkGray" + } + Component.onCompleted: { + context.view.parent = this; + context.view.anchors.fill = this; + SwipeView.view.currentIndex = SwipeView.view.count-1 + } + function close() + { + SwipeView.view.currentIndex = 0; + qmlCore.deleteLater(this) + } +} diff --git a/plugins/remoteaccess/RemoteAccessWidget.cpp b/plugins/remoteaccess/RemoteAccessWidget.cpp index 3c0307d06..b9febdf1b 100644 --- a/plugins/remoteaccess/RemoteAccessWidget.cpp +++ b/plugins/remoteaccess/RemoteAccessWidget.cpp @@ -1,7 +1,7 @@ /* * RemoteAccessWidget.cpp - widget containing a VNC-view and controls for it * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -21,6 +21,7 @@ * USA. */ +#include #include #include #include @@ -30,8 +31,11 @@ #include "rfb/keysym.h" #include "RemoteAccessWidget.h" -#include "VncView.h" +#include "RemoteAccessFeaturePlugin.h" +#include "VncViewWidget.h" +#include "VeyonConfiguration.h" #include "VeyonConnection.h" +#include "VeyonMasterInterface.h" #include "Computer.h" #include "ComputerControlInterface.h" #include "PlatformCoreFunctions.h" @@ -40,97 +44,85 @@ // toolbar for remote-control-widget -RemoteAccessWidgetToolBar::RemoteAccessWidgetToolBar( RemoteAccessWidget* parent, bool viewOnly ) : +RemoteAccessWidgetToolBar::RemoteAccessWidgetToolBar( RemoteAccessWidget* parent, + bool startViewOnly, bool showViewOnlyToggleButton ) : QWidget( parent ), m_parent( parent ), m_showHideTimeLine( ShowHideAnimationDuration, this ), - m_iconStateTimeLine( 0, this ), - m_connecting( false ), - m_viewOnlyButton( new ToolButton( QPixmap( QStringLiteral(":/remoteaccess/kmag.png") ), tr( "View only" ), tr( "Remote control" ) ) ), + m_viewOnlyButton( showViewOnlyToggleButton ? new ToolButton( QPixmap( QStringLiteral(":/remoteaccess/kmag.png") ), tr( "View only" ), tr( "Remote control" ) ) : nullptr ), + m_selectScreenButton( new ToolButton( QPixmap( QStringLiteral(":/remoteaccess/preferences-system-windows-effect-desktopgrid.png") ), tr( "Select screen" ) ) ), m_sendShortcutButton( new ToolButton( QPixmap( QStringLiteral(":/remoteaccess/preferences-desktop-keyboard.png") ), tr( "Send shortcut" ) ) ), m_screenshotButton( new ToolButton( QPixmap( QStringLiteral(":/remoteaccess/camera-photo.png") ), tr( "Screenshot" ) ) ), - m_fullScreenButton( new ToolButton( QPixmap( QStringLiteral(":/remoteaccess/view-fullscreen.png") ), tr( "Fullscreen" ), tr( "Window" ) ) ), - m_exitButton( new ToolButton( QPixmap( QStringLiteral(":/remoteaccess/application-exit.png") ), tr( "Exit" ) ) ) + m_fullScreenButton( new ToolButton( QPixmap( QStringLiteral(":/core/view-fullscreen.png") ), tr( "Fullscreen" ), tr( "Window" ) ) ), + m_exitButton( new ToolButton( QPixmap( QStringLiteral(":/remoteaccess/application-exit.png") ), tr( "Exit" ) ) ), + m_screenSelectActions( new QActionGroup(this) ) { - QPalette pal = palette(); - pal.setBrush( QPalette::Window, QPixmap( QStringLiteral(":/core/toolbar-background.png") ) ); - setPalette( pal ); - setAttribute( Qt::WA_NoSystemBackground, true ); move( 0, 0 ); show(); - startConnection(); - m_viewOnlyButton->setCheckable( true ); + if( m_viewOnlyButton ) + { + m_viewOnlyButton->setCheckable( true ); + m_viewOnlyButton->setChecked( startViewOnly ); + connect( m_viewOnlyButton, &ToolButton::toggled, this, &RemoteAccessWidgetToolBar::updateControls ); + connect( m_viewOnlyButton, &QAbstractButton::toggled, parent, &RemoteAccessWidget::setViewOnly ); + } + m_fullScreenButton->setCheckable( true ); - m_viewOnlyButton->setChecked( viewOnly ); m_fullScreenButton->setChecked( false ); - connect( m_viewOnlyButton, &ToolButton::toggled, this, &RemoteAccessWidgetToolBar::updateControls ); - connect( m_viewOnlyButton, &QAbstractButton::toggled, parent, &RemoteAccessWidget::toggleViewOnly ); connect( m_fullScreenButton, &QAbstractButton::toggled, parent, &RemoteAccessWidget::toggleFullScreen ); connect( m_screenshotButton, &QAbstractButton::clicked, parent, &RemoteAccessWidget::takeScreenshot ); connect( m_exitButton, &QAbstractButton::clicked, parent, &QWidget::close ); auto vncView = parent->vncView(); + connect( vncView->connection(), &VncConnection::stateChanged, this, &RemoteAccessWidgetToolBar::updateConnectionState ); + + m_selectScreenButton->setMenu( new QMenu ); + m_selectScreenButton->setPopupMode( QToolButton::InstantPopup ); + m_selectScreenButton->setObjectName( QStringLiteral("screens") ); + + updateScreens(); auto shortcutMenu = new QMenu(); -#if QT_VERSION < 0x050600 -#warning Building legacy compat code for unsupported version of Qt - connect( shortcutMenu->addAction( tr( "Ctrl+Alt+Del" ) ), &QAction::triggered, - vncView, [=]() { vncView->sendShortcut( VncView::ShortcutCtrlAltDel ); } ); - connect( shortcutMenu->addAction( tr( "Ctrl+Esc" ) ), &QAction::triggered, - vncView, [=]() { vncView->sendShortcut( VncView::ShortcutCtrlEscape ); } ); - connect( shortcutMenu->addAction( tr( "Alt+Tab" ) ), &QAction::triggered, - vncView, [=]() { vncView->sendShortcut( VncView::ShortcutAltTab ); } ); - connect( shortcutMenu->addAction( tr( "Alt+F4" ) ), &QAction::triggered, - vncView, [=]() { vncView->sendShortcut( VncView::ShortcutAltF4 ); } ); - connect( shortcutMenu->addAction( tr( "Win+Tab" ) ), &QAction::triggered, - vncView, [=]() { vncView->sendShortcut( VncView::ShortcutWinTab ); } ); - connect( shortcutMenu->addAction( tr( "Win" ) ), &QAction::triggered, - vncView, [=]() { vncView->sendShortcut( VncView::ShortcutWin ); } ); - connect( shortcutMenu->addAction( tr( "Menu" ) ), &QAction::triggered, - vncView, [=]() { vncView->sendShortcut( VncView::ShortcutMenu ); } ); - connect( shortcutMenu->addAction( tr( "Alt+Ctrl+F1" ) ), &QAction::triggered, - vncView, [=]() { vncView->sendShortcut( VncView::ShortcutAltCtrlF1 ); } ); -#else - shortcutMenu->addAction( tr( "Ctrl+Alt+Del" ), vncView, [=]() { vncView->sendShortcut( VncView::ShortcutCtrlAltDel ); } ); - shortcutMenu->addAction( tr( "Ctrl+Esc" ), vncView, [=]() { vncView->sendShortcut( VncView::ShortcutCtrlEscape ); } ); - shortcutMenu->addAction( tr( "Alt+Tab" ), vncView, [=]() { vncView->sendShortcut( VncView::ShortcutAltTab ); } ); - shortcutMenu->addAction( tr( "Alt+F4" ), vncView, [=]() { vncView->sendShortcut( VncView::ShortcutAltF4 ); } ); - shortcutMenu->addAction( tr( "Win+Tab" ), vncView, [=]() { vncView->sendShortcut( VncView::ShortcutWinTab ); } ); - shortcutMenu->addAction( tr( "Win" ), vncView, [=]() { vncView->sendShortcut( VncView::ShortcutWin ); } ); - shortcutMenu->addAction( tr( "Menu" ), vncView, [=]() { vncView->sendShortcut( VncView::ShortcutMenu ); } ); - shortcutMenu->addAction( tr( "Alt+Ctrl+F1" ), vncView, [=]() { vncView->sendShortcut( VncView::ShortcutAltCtrlF1 ); } ); -#endif + shortcutMenu->addAction( tr( "Ctrl+Alt+Del" ), this, [=]() { vncView->sendShortcut( VncView::ShortcutCtrlAltDel ); } ); + shortcutMenu->addAction( tr( "Ctrl+Esc" ), this, [=]() { vncView->sendShortcut( VncView::ShortcutCtrlEscape ); } ); + shortcutMenu->addAction( tr( "Alt+Tab" ), this, [=]() { vncView->sendShortcut( VncView::ShortcutAltTab ); } ); + shortcutMenu->addAction( tr( "Alt+F4" ), this, [=]() { vncView->sendShortcut( VncView::ShortcutAltF4 ); } ); + shortcutMenu->addAction( tr( "Win+Tab" ), this, [=]() { vncView->sendShortcut( VncView::ShortcutWinTab ); } ); + shortcutMenu->addAction( tr( "Win" ), this, [=]() { vncView->sendShortcut( VncView::ShortcutWin ); } ); + shortcutMenu->addAction( tr( "Menu" ), this, [=]() { vncView->sendShortcut( VncView::ShortcutMenu ); } ); + shortcutMenu->addAction( tr( "Alt+Ctrl+F1" ), this, [=]() { vncView->sendShortcut( VncView::ShortcutAltCtrlF1 ); } ); m_sendShortcutButton->setMenu( shortcutMenu ); m_sendShortcutButton->setPopupMode( QToolButton::InstantPopup ); m_sendShortcutButton->setObjectName( QStringLiteral("shortcuts") ); auto layout = new QHBoxLayout( this ); - layout->setMargin( 1 ); + layout->setContentsMargins( 1, 1, 1, 1 ); layout->setSpacing( 1 ); layout->addStretch( 0 ); + layout->addWidget( m_selectScreenButton ); layout->addWidget( m_sendShortcutButton ); - layout->addWidget( m_viewOnlyButton ); + if( m_viewOnlyButton ) + { + layout->addWidget( m_viewOnlyButton ); + } layout->addWidget( m_screenshotButton ); layout->addWidget( m_fullScreenButton ); layout->addWidget( m_exitButton ); layout->addSpacing( 5 ); - connect( vncView, &VncView::startConnection, this, &RemoteAccessWidgetToolBar::startConnection ); - connect( vncView, &VncView::connectionEstablished, this, &RemoteAccessWidgetToolBar::connectionEstablished ); - setFixedHeight( m_exitButton->height() ); + setFixedHeight(m_exitButton->minimumSizeHint().height()); connect( &m_showHideTimeLine, &QTimeLine::valueChanged, this, &RemoteAccessWidgetToolBar::updatePosition ); - m_iconStateTimeLine.setFrameRange( 0, 100 ); - m_iconStateTimeLine.setDuration( 1500 ); - m_iconStateTimeLine.setUpdateInterval( 60 ); - m_iconStateTimeLine.setCurveShape( QTimeLine::SineCurve ); - connect( &m_iconStateTimeLine, &QTimeLine::valueChanged, this, &RemoteAccessWidgetToolBar::updateConnectionAnimation ); - connect( &m_iconStateTimeLine, &QTimeLine::finished, &m_iconStateTimeLine, &QTimeLine::start ); + connect( vncView->computerControlInterface().data(), &ComputerControlInterface::screensChanged, + this, &RemoteAccessWidgetToolBar::updateScreens ); + + connect( m_parent, &RemoteAccessWidget::screenChangedInRemoteAccessWidget, + this, &RemoteAccessWidgetToolBar::updateScreenSelectActions ); } @@ -148,7 +140,7 @@ void RemoteAccessWidgetToolBar::appear() void RemoteAccessWidgetToolBar::disappear() { - if( !m_connecting && !rect().contains( mapFromGlobal( QCursor::pos() ) ) ) + if( rect().contains( mapFromGlobal( QCursor::pos() ) ) == false ) { QTimer::singleShot( DisappearDelay, this, [this]() { if( m_showHideTimeLine.state() != QTimeLine::Running ) @@ -169,6 +161,26 @@ void RemoteAccessWidgetToolBar::updateControls( bool viewOnly ) +void RemoteAccessWidgetToolBar::updateScreenSelectActions( int newScreen ) +{ + const auto screens = m_parent->vncView()->computerControlInterface()->screens(); + const auto m_screenSelectActions = m_selectScreenButton->menu()->actions(); + for (const auto& screenSelectAction : m_screenSelectActions) + { + if ( newScreen == -1 ) + { + screenSelectAction->setChecked(true); + break; + } + if ( screenSelectAction->text() == screens[newScreen].name ) + { + screenSelectAction->setChecked(true); + } + } +} + + + void RemoteAccessWidgetToolBar::leaveEvent( QEvent *event ) { disappear(); @@ -180,43 +192,21 @@ void RemoteAccessWidgetToolBar::leaveEvent( QEvent *event ) void RemoteAccessWidgetToolBar::paintEvent( QPaintEvent *paintEv ) { QPainter p( this ); - QFont f = p.font(); - p.setOpacity( 0.8-0.8*m_showHideTimeLine.currentValue() ); + p.setOpacity( 0.8 ); p.fillRect( paintEv->rect(), palette().brush( QPalette::Window ) ); p.setOpacity( 1 ); - f.setPointSize( 12 ); - f.setBold( true ); - p.setFont( f ); - - //p.setPen( Qt::white ); - //p.drawText( 64, 22, m_parent->windowTitle() ); - - p.setPen( QColor( 192, 192, 192 ) ); + auto f = p.font(); f.setPointSize( 10 ); + f.setBold( true ); p.setFont( f ); - if( m_connecting ) - { - QString dots; - for( int i = 0; i < ( m_iconStateTimeLine.currentTime() / 120 ) % 6; ++i ) - { - dots += QLatin1Char('.'); - } - p.drawText( 32, height() / 2 + fontMetrics().height(), tr( "Connecting %1" ).arg( dots ) ); - } - else - { - p.drawText( 32, height() / 2 + fontMetrics().height(), tr( "Connected." ) ); - } -} - - - -void RemoteAccessWidgetToolBar::updateConnectionAnimation() -{ - repaint(); + p.setPen(palette().color(QPalette::Text)); + p.drawText( height() / 2, height() / 2 + fontMetrics().height() / 2, + m_parent->vncView() && m_parent->vncView()->connection() && + m_parent->vncView()->connection()->state() == VncConnection::State::Connected ? + tr( "Connected." ) : tr( "Connecting..." ) ); } @@ -233,68 +223,207 @@ void RemoteAccessWidgetToolBar::updatePosition() -void RemoteAccessWidgetToolBar::startConnection() +void RemoteAccessWidgetToolBar::updateConnectionState() { - m_connecting = true; - m_iconStateTimeLine.start(); - appear(); - update(); + if( m_parent->vncView()->connection()->state() == VncConnection::State::Connected ) + { + disappear(); + } + else + { + appear(); + } } - -void RemoteAccessWidgetToolBar::connectionEstablished() +void RemoteAccessWidgetToolBar::updateScreens() { - m_connecting = false; - m_iconStateTimeLine.stop(); - disappear(); + const auto checkedScreenName = m_screenSelectActions->checkedAction() ? + m_screenSelectActions->checkedAction()->text() : QString{}; - // within the next 1000ms the username should be known and therefore we update - QTimer::singleShot( 1000, this, QOverload<>::of( &RemoteAccessWidgetToolBar::update ) ); -} + const auto screens = m_parent->vncView()->computerControlInterface()->screens(); + m_selectScreenButton->setVisible(screens.size() > 1); + + const auto menu = m_selectScreenButton->menu(); + menu->clear(); + if(screens.size() > 1) + { + const auto showAllScreens = menu->addAction( tr( "All screens" ), this, [=]() { + m_parent->vncView()->setViewport({}); + }); + + m_screenSelectActions->addAction(showAllScreens); + showAllScreens->setCheckable(true); + showAllScreens->setChecked(checkedScreenName.isEmpty() || + checkedScreenName == showAllScreens->text()); + + menu->addSeparator(); + + QPoint minimumScreenPosition{}; + for (const auto& screen : screens) + { + minimumScreenPosition.setX(qMin(minimumScreenPosition.x(), screen.geometry.x())); + minimumScreenPosition.setY(qMin(minimumScreenPosition.y(), screen.geometry.y())); + } + + for (const auto& screen : screens) + { + const auto action = menu->addAction(screen.name, this, [=]() { + m_parent->vncView()->setViewport(screen.geometry.translated(-minimumScreenPosition)); + }); + action->setCheckable(true); + if(action->text() == checkedScreenName) + { + action->setChecked(true); + } + m_screenSelectActions->addAction(action); + } + + if(m_screenSelectActions->checkedAction()) + { + m_screenSelectActions->checkedAction()->trigger(); + } + else + { + showAllScreens->setChecked(true); + showAllScreens->trigger(); + } + } + else + { + m_parent->vncView()->setViewport({}); + } +} -RemoteAccessWidget::RemoteAccessWidget( const ComputerControlInterface::Pointer& computerControlInterface, bool viewOnly ) : +RemoteAccessWidget::RemoteAccessWidget( const ComputerControlInterface::Pointer& computerControlInterface, + bool startViewOnly, bool showViewOnlyToggleButton ) : QWidget( nullptr ), m_computerControlInterface( computerControlInterface ), - m_vncView( new VncView( computerControlInterface->computer().hostAddress(), -1, this, VncView::RemoteControlMode ) ), - m_connection( new VeyonConnection( m_vncView->vncConnection() ) ), - m_toolBar( new RemoteAccessWidgetToolBar( this, viewOnly ) ) + m_vncView( new VncViewWidget( computerControlInterface, {}, this ) ), + m_toolBar( new RemoteAccessWidgetToolBar( this, startViewOnly, showViewOnlyToggleButton ) ) { - setWindowTitle( tr( "%1 - %2 Remote Access" ).arg( computerControlInterface->computer().name(), - VeyonCore::applicationName() ) ); + const auto openOnMasterScreen = VeyonCore::config().showFeatureWindowsOnSameScreen(); + const auto master = VeyonCore::instance()->findChild(); + if( master && openOnMasterScreen ) + { + const auto masterWindow = master->mainWindow(); + move( masterWindow->x(), masterWindow->y() ); + } else { + move( 0, 0 ); + } + + updateRemoteAccessTitle(); + connect( m_computerControlInterface.data(), &ComputerControlInterface::userChanged, this, &RemoteAccessWidget::updateRemoteAccessTitle ); + setWindowIcon( QPixmap( QStringLiteral(":/remoteaccess/kmag.png") ) ); setAttribute( Qt::WA_DeleteOnClose, true ); m_vncView->move( 0, 0 ); - connect( m_vncView, &VncView::mouseAtBorder, m_toolBar, &RemoteAccessWidgetToolBar::appear ); - connect( m_vncView, &VncView::keyEvent, this, &RemoteAccessWidget::checkKeyEvent ); - connect( m_vncView, &VncView::sizeHintChanged, this, &RemoteAccessWidget::updateSize ); + m_vncView->installEventFilter( this ); + connect( m_vncView, &VncViewWidget::mouseAtBorder, m_toolBar, &RemoteAccessWidgetToolBar::appear ); + connect( m_vncView, &VncViewWidget::sizeHintChanged, this, &RemoteAccessWidget::updateSize ); showMaximized(); - VeyonCore::platform().coreFunctions().raiseWindow( this ); + VeyonCore::platform().coreFunctions().raiseWindow( this, false ); showNormal(); - move( 0, 0 ); + updateSize(); - toggleViewOnly( viewOnly ); + setViewOnly( startViewOnly ); } RemoteAccessWidget::~RemoteAccessWidget() { - delete m_connection; delete m_vncView; } +VncView* RemoteAccessWidget::vncView() const +{ + return m_vncView; +} + + + +bool RemoteAccessWidget::eventFilter( QObject* object, QEvent* event ) +{ + if( event->type() == QEvent::KeyRelease && + dynamic_cast( event )->key() == Qt::Key_Escape && + m_vncView->connection()->isConnected() == false ) + { + close(); + return true; + } + + if( object == m_vncView && event->type() == QEvent::FocusOut ) + { + m_toolBar->disappear(); + } + + if( event->type() == QEvent::KeyPress && m_vncView->viewOnly() ) + { + const auto screens = m_vncView->computerControlInterface()->screens(); + const auto key = static_cast( event )->key(); + if ( screens.size() > 1 && ( key == Qt::Key_Tab || key == Qt::Key_Backtab ) ) + { + if( key == Qt::Key_Tab ) + { + if ( m_currentScreen < screens.size() - 1 ) + { + m_currentScreen++; + } else + { + m_currentScreen = -1; + } + } + + if( key == Qt::Key_Backtab ) + { + if ( m_currentScreen == -1 ) + { + m_currentScreen = screens.size()-1; + } else if ( m_currentScreen > 0 ) + { + m_currentScreen--; + } else + { + m_currentScreen = -1; + } + } + + if ( m_currentScreen == -1) + { + m_vncView->setViewport( {} ); + } + else + { + m_vncView->setViewport(screens[m_currentScreen].geometry); + } + Q_EMIT screenChangedInRemoteAccessWidget(m_currentScreen); + return true; + } + + return false; + } + + return QWidget::eventFilter( object, event ); +} + + + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +void RemoteAccessWidget::enterEvent( QEnterEvent* event ) +#else void RemoteAccessWidget::enterEvent( QEvent* event ) +#endif { m_toolBar->disappear(); @@ -306,7 +435,7 @@ void RemoteAccessWidget::enterEvent( QEvent* event ) void RemoteAccessWidget::leaveEvent( QEvent* event ) { QTimer::singleShot( AppearDelay, this, [this]() { - if( underMouse() == false ) + if( underMouse() == false && window()->isActiveWindow() ) { m_toolBar->appear(); } @@ -319,7 +448,7 @@ void RemoteAccessWidget::leaveEvent( QEvent* event ) void RemoteAccessWidget::resizeEvent( QResizeEvent* event ) { - m_vncView->resize( size() ); + m_vncView->setFixedSize(size()); m_toolBar->setFixedSize( width(), m_toolBar->height() ); QWidget::resizeEvent( event ); @@ -327,20 +456,9 @@ void RemoteAccessWidget::resizeEvent( QResizeEvent* event ) -void RemoteAccessWidget::checkKeyEvent( unsigned int key, bool pressed ) -{ - if( pressed && key == XK_Escape && !m_connection->isConnected() ) - { - close(); - } -} - - - void RemoteAccessWidget::updateSize() { - if( !( windowState() & Qt::WindowFullScreen ) && - m_vncView->sizeHint().isEmpty() == false ) + if (!(windowState() & Qt::WindowFullScreen)) { resize( m_vncView->sizeHint() ); } @@ -362,7 +480,7 @@ void RemoteAccessWidget::toggleFullScreen( bool _on ) -void RemoteAccessWidget::toggleViewOnly( bool viewOnly ) +void RemoteAccessWidget::setViewOnly( bool viewOnly ) { m_vncView->setViewOnly( viewOnly ); m_toolBar->updateControls( viewOnly ); @@ -375,3 +493,23 @@ void RemoteAccessWidget::takeScreenshot() { Screenshot().take( m_computerControlInterface ); } + + + +void RemoteAccessWidget::updateRemoteAccessTitle() +{ + const auto username = m_computerControlInterface->userFullName().isEmpty() ? + m_computerControlInterface->userLoginName() : m_computerControlInterface->userFullName(); + + if (username.isEmpty() ) + { + setWindowTitle(tr("%1 - %2 Remote Access").arg(m_computerControlInterface->computerName(), + VeyonCore::applicationName())); + } + else + { + setWindowTitle(tr("%1 - %2 - %3 Remote Access").arg(username, + m_computerControlInterface->computerName(), + VeyonCore::applicationName())); + } +} diff --git a/plugins/remoteaccess/RemoteAccessWidget.h b/plugins/remoteaccess/RemoteAccessWidget.h index a8a6e28ba..03618e8e0 100644 --- a/plugins/remoteaccess/RemoteAccessWidget.h +++ b/plugins/remoteaccess/RemoteAccessWidget.h @@ -1,7 +1,7 @@ /* * RemoteAccessWidget.h - widget containing a VNC view and controls for it * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -28,8 +28,10 @@ #include #include +class QActionGroup; + class VncView; -class VeyonConnection; +class VncViewWidget; class RemoteAccessWidget; class ToolButton; @@ -39,12 +41,14 @@ class RemoteAccessWidgetToolBar : public QWidget { Q_OBJECT public: - RemoteAccessWidgetToolBar( RemoteAccessWidget* parent, bool viewOnly ); + RemoteAccessWidgetToolBar( RemoteAccessWidget* parent, + bool startViewOnly, bool showViewOnlyToggleButton ); ~RemoteAccessWidgetToolBar() override = default; void appear(); void disappear(); void updateControls( bool viewOnly ); + void updateScreenSelectActions( int newScreen ); protected: @@ -53,23 +57,22 @@ class RemoteAccessWidgetToolBar : public QWidget private: - void updateConnectionAnimation(); void updatePosition(); - void startConnection(); - void connectionEstablished(); + void updateConnectionState(); + void updateScreens(); - RemoteAccessWidget * m_parent; + RemoteAccessWidget *m_parent; QTimeLine m_showHideTimeLine; - QTimeLine m_iconStateTimeLine; - - bool m_connecting; ToolButton* m_viewOnlyButton; + ToolButton* m_selectScreenButton; ToolButton* m_sendShortcutButton; ToolButton* m_screenshotButton; ToolButton* m_fullScreenButton; ToolButton* m_exitButton; + QActionGroup* m_screenSelectActions{nullptr}; + static constexpr int ShowHideAnimationDuration = 300; static constexpr int DisappearDelay = 500; @@ -83,34 +86,44 @@ class RemoteAccessWidget : public QWidget { Q_OBJECT public: - explicit RemoteAccessWidget( const ComputerControlInterface::Pointer& computerControlInterface, bool viewOnly = false ); + explicit RemoteAccessWidget( const ComputerControlInterface::Pointer& computerControlInterface, + bool startViewOnly, bool showViewOnlyToggleButton ); ~RemoteAccessWidget() override; - VncView* vncView() const + ComputerControlInterface::Pointer computerControlInterface() const { - return m_vncView; + return m_computerControlInterface; } + VncView* vncView() const; + void toggleFullScreen( bool ); - void toggleViewOnly( bool viewOnly ); + void setViewOnly( bool viewOnly ); void takeScreenshot(); - protected: + bool eventFilter( QObject* object, QEvent* event ) override; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + void enterEvent( QEnterEvent* event ) override; +#else void enterEvent( QEvent* event ) override; +#endif void leaveEvent( QEvent* event ) override; void resizeEvent( QResizeEvent* event ) override; - private: - void checkKeyEvent( unsigned int, bool ); void updateSize(); + void updateRemoteAccessTitle(); ComputerControlInterface::Pointer m_computerControlInterface; - VncView* m_vncView; - VeyonConnection* m_connection; + VncViewWidget* m_vncView; RemoteAccessWidgetToolBar* m_toolBar; static constexpr int AppearDelay = 500; + int m_currentScreen{-1}; + +Q_SIGNALS: + void screenChangedInRemoteAccessWidget( int newScreen ); + } ; diff --git a/plugins/remoteaccess/camera-photo.png b/plugins/remoteaccess/camera-photo.png index f8ab91dbb..964a472cf 100644 Binary files a/plugins/remoteaccess/camera-photo.png and b/plugins/remoteaccess/camera-photo.png differ diff --git a/plugins/remoteaccess/preferences-system-windows-effect-desktopgrid.png b/plugins/remoteaccess/preferences-system-windows-effect-desktopgrid.png new file mode 100644 index 000000000..647bb1707 Binary files /dev/null and b/plugins/remoteaccess/preferences-system-windows-effect-desktopgrid.png differ diff --git a/plugins/remoteaccess/remoteaccess.qrc b/plugins/remoteaccess/remoteaccess.qrc index 914c9a4c1..af61eee96 100644 --- a/plugins/remoteaccess/remoteaccess.qrc +++ b/plugins/remoteaccess/remoteaccess.qrc @@ -1,10 +1,11 @@ - - view-fullscreen.png - application-exit.png - krdc.png - kmag.png - camera-photo.png - preferences-desktop-keyboard.png - + + preferences-system-windows-effect-desktopgrid.png + application-exit.png + krdc.png + kmag.png + camera-photo.png + preferences-desktop-keyboard.png + RemoteAccessPage.qml + diff --git a/plugins/remoteaccess/view-fullscreen.png b/plugins/remoteaccess/view-fullscreen.png deleted file mode 100644 index 6fc7cf047..000000000 Binary files a/plugins/remoteaccess/view-fullscreen.png and /dev/null differ diff --git a/plugins/screenlock/CMakeLists.txt b/plugins/screenlock/CMakeLists.txt index d58b9e75f..97e967257 100644 --- a/plugins/screenlock/CMakeLists.txt +++ b/plugins/screenlock/CMakeLists.txt @@ -1,3 +1,3 @@ -INCLUDE(BuildPlugin) +include(BuildVeyonPlugin) -BUILD_PLUGIN(screenlock ScreenLockFeaturePlugin.cpp ScreenLockFeaturePlugin.h screenlock.qrc) +build_veyon_plugin(screenlock ScreenLockFeaturePlugin.cpp ScreenLockFeaturePlugin.h screenlock.qrc) diff --git a/plugins/screenlock/ScreenLockFeaturePlugin.cpp b/plugins/screenlock/ScreenLockFeaturePlugin.cpp index 2f2a8729f..c45c959f4 100644 --- a/plugins/screenlock/ScreenLockFeaturePlugin.cpp +++ b/plugins/screenlock/ScreenLockFeaturePlugin.cpp @@ -1,7 +1,7 @@ /* * ScreenLockFeaturePlugin.cpp - implementation of ScreenLockFeaturePlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -28,13 +28,14 @@ #include "FeatureWorkerManager.h" #include "LockWidget.h" #include "PlatformCoreFunctions.h" +#include "PlatformSessionFunctions.h" #include "VeyonServerInterface.h" ScreenLockFeaturePlugin::ScreenLockFeaturePlugin( QObject* parent ) : QObject( parent ), m_screenLockFeature( QStringLiteral( "ScreenLock" ), - Feature::Mode | Feature::AllComponents, + Feature::Flag::Mode | Feature::Flag::AllComponents, Feature::Uid( "ccb535a2-1d24-4cc1-a709-8b47d2b2ac79" ), Feature::Uid(), tr( "Lock" ), tr( "Unlock" ), @@ -43,7 +44,16 @@ ScreenLockFeaturePlugin::ScreenLockFeaturePlugin( QObject* parent ) : "In this mode all input devices are locked and " "the screens are blacked." ), QStringLiteral(":/screenlock/system-lock-screen.png") ), - m_features( { m_screenLockFeature } ), + m_lockInputDevicesFeature( QStringLiteral( "InputDevicesLock" ), + Feature::Flag::Mode | Feature::Flag::AllComponents | Feature::Flag::Meta, + Feature::Uid( "e4a77879-e544-4fec-bc18-e534f33b934c" ), + {}, + tr( "Lock input devices" ), tr( "Unlock input devices" ), + tr( "To reclaim all user's full attention you can lock " + "their computers using this button. " + "In this mode all input devices are locked while the desktop is still visible." ), + QStringLiteral(":/screenlock/system-lock-screen.png") ), + m_features( { m_screenLockFeature, m_lockInputDevicesFeature } ), m_lockWidget( nullptr ) { } @@ -57,44 +67,30 @@ ScreenLockFeaturePlugin::~ScreenLockFeaturePlugin() -bool ScreenLockFeaturePlugin::startFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) +bool ScreenLockFeaturePlugin::controlFeature( Feature::Uid featureUid, Operation operation, + const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) { - Q_UNUSED(master); + Q_UNUSED(arguments) - if( feature == m_screenLockFeature ) + if( hasFeature( featureUid ) == false ) { - return sendFeatureMessage( FeatureMessage( m_screenLockFeature.uid(), StartLockCommand ), - computerControlInterfaces ); + return false; } - return false; -} - - - -bool ScreenLockFeaturePlugin::stopFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) -{ - Q_UNUSED(master); - - if( feature == m_screenLockFeature ) + if( operation == Operation::Start ) { - return sendFeatureMessage( FeatureMessage( m_screenLockFeature.uid(), StopLockCommand ), - computerControlInterfaces ); - } - - return false; -} + sendFeatureMessage( FeatureMessage{ featureUid, StartLockCommand }, computerControlInterfaces ); + return true; + } + if( operation == Operation::Stop ) + { + sendFeatureMessage( FeatureMessage{ featureUid, StopLockCommand }, computerControlInterfaces ); -bool ScreenLockFeaturePlugin::handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) -{ - Q_UNUSED(master); - Q_UNUSED(message); - Q_UNUSED(computerControlInterface); + return true; + } return false; } @@ -107,16 +103,23 @@ bool ScreenLockFeaturePlugin::handleFeatureMessage( VeyonServerInterface& server { Q_UNUSED(messageContext) - if( m_screenLockFeature.uid() == message.featureUid() ) + if( message.featureUid() == m_screenLockFeature.uid() || + message.featureUid() == m_lockInputDevicesFeature.uid() ) { - if( server.featureWorkerManager().isWorkerRunning( m_screenLockFeature ) == false && - message.command() != StopLockCommand ) + if( server.featureWorkerManager().isWorkerRunning( message.featureUid() ) == false && + message.command() == StopLockCommand ) { - server.featureWorkerManager().startWorker( m_screenLockFeature, FeatureWorkerManager::ManagedSystemProcess ); + return true; + } + + if( VeyonCore::platform().sessionFunctions().currentSessionHasUser() == false ) + { + vDebug() << "not locking screen since not running in a user session"; + return true; } // forward message to worker - server.featureWorkerManager().sendMessage( message ); + server.featureWorkerManager().sendMessageToManagedSystemWorker( message ); return true; } @@ -128,9 +131,10 @@ bool ScreenLockFeaturePlugin::handleFeatureMessage( VeyonServerInterface& server bool ScreenLockFeaturePlugin::handleFeatureMessage( VeyonWorkerInterface& worker, const FeatureMessage& message ) { - Q_UNUSED(worker); + Q_UNUSED(worker) - if( m_screenLockFeature.uid() == message.featureUid() ) + if( message.featureUid() == m_screenLockFeature.uid() || + message.featureUid() == m_lockInputDevicesFeature.uid() ) { switch( message.command() ) { @@ -139,7 +143,13 @@ bool ScreenLockFeaturePlugin::handleFeatureMessage( VeyonWorkerInterface& worker { VeyonCore::platform().coreFunctions().disableScreenSaver(); - m_lockWidget = new LockWidget( LockWidget::BackgroundPixmap, + auto mode = LockWidget::BackgroundPixmap; + if( message.featureUid() == m_lockInputDevicesFeature.uid() ) + { + mode = LockWidget::DesktopVisible; + } + + m_lockWidget = new LockWidget( mode, QPixmap( QStringLiteral(":/screenlock/locked-screen-background.png" ) ) ); } return true; diff --git a/plugins/screenlock/ScreenLockFeaturePlugin.h b/plugins/screenlock/ScreenLockFeaturePlugin.h index 109ef1761..f3387931b 100644 --- a/plugins/screenlock/ScreenLockFeaturePlugin.h +++ b/plugins/screenlock/ScreenLockFeaturePlugin.h @@ -1,7 +1,7 @@ /* * ScreenLockFeaturePlugin.h - declaration of ScreenLockFeaturePlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -39,7 +39,7 @@ class ScreenLockFeaturePlugin : public QObject, FeatureProviderInterface, Plugin Plugin::Uid uid() const override { - return QStringLiteral("2ad98ccb-e9a5-43ef-8c4c-876ac5efbcb1"); + return Plugin::Uid{ QStringLiteral("2ad98ccb-e9a5-43ef-8c4c-876ac5efbcb1") }; } QVersionNumber version() const override @@ -72,14 +72,8 @@ class ScreenLockFeaturePlugin : public QObject, FeatureProviderInterface, Plugin return m_features; } - bool startFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) override; - - bool stopFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) override; - - bool handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) override; + bool controlFeature( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) override; bool handleFeatureMessage( VeyonServerInterface& server, const MessageContext& messageContext, @@ -96,6 +90,7 @@ class ScreenLockFeaturePlugin : public QObject, FeatureProviderInterface, Plugin }; const Feature m_screenLockFeature; + const Feature m_lockInputDevicesFeature; const FeatureList m_features; LockWidget* m_lockWidget; diff --git a/plugins/screenshot/CMakeLists.txt b/plugins/screenshot/CMakeLists.txt index 13b9ff095..7e08d889c 100644 --- a/plugins/screenshot/CMakeLists.txt +++ b/plugins/screenshot/CMakeLists.txt @@ -1,7 +1,9 @@ -INCLUDE(BuildPlugin) +include(BuildVeyonPlugin) -BUILD_PLUGIN(screenshot +build_veyon_plugin(screenshot ScreenshotFeaturePlugin.cpp ScreenshotFeaturePlugin.h + ScreenshotListModel.cpp + ScreenshotListModel.h screenshot.qrc -) + ) diff --git a/plugins/screenshot/ScreenshotFeaturePlugin.cpp b/plugins/screenshot/ScreenshotFeaturePlugin.cpp index 8e068d4b8..1dcaf3a3f 100644 --- a/plugins/screenshot/ScreenshotFeaturePlugin.cpp +++ b/plugins/screenshot/ScreenshotFeaturePlugin.cpp @@ -1,7 +1,7 @@ /* * ScreenshotFeaturePlugin.cpp - implementation of ScreenshotFeaturePlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,17 +23,19 @@ */ #include +#include -#include "ScreenshotFeaturePlugin.h" #include "ComputerControlInterface.h" -#include "VeyonMasterInterface.h" #include "Screenshot.h" - +#include "ScreenshotFeaturePlugin.h" +#include "ScreenshotListModel.h" +#include "QmlCore.h" +#include "VeyonMasterInterface.h" ScreenshotFeaturePlugin::ScreenshotFeaturePlugin( QObject* parent ) : QObject( parent ), m_screenshotFeature( Feature( QStringLiteral( "Screenshot" ), - Feature::Action | Feature::Master, + Feature::Flag::Action | Feature::Flag::Master, Feature::Uid( "d5ee3aac-2a87-4d05-b827-0c20344490bd" ), Feature::Uid(), tr( "Screenshot" ), {}, @@ -41,6 +43,11 @@ ScreenshotFeaturePlugin::ScreenshotFeaturePlugin( QObject* parent ) : QStringLiteral(":/screenshot/camera-photo.png") ) ), m_features( { m_screenshotFeature } ) { + if( VeyonCore::component() == VeyonCore::Component::Master ) + { + connect( VeyonCore::instance(), &VeyonCore::applicationLoaded, + this, &ScreenshotFeaturePlugin::initUi ); + } } @@ -52,17 +59,32 @@ const FeatureList &ScreenshotFeaturePlugin::featureList() const -bool ScreenshotFeaturePlugin::startFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) +bool ScreenshotFeaturePlugin::controlFeature( Feature::Uid featureUid, + Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) { - if( feature.uid() == m_screenshotFeature.uid() ) + Q_UNUSED(arguments) + + if( hasFeature( featureUid ) && operation == Operation::Start ) { for( const auto& controlInterface : computerControlInterfaces ) { Screenshot().take( controlInterface ); - } + return true; + } + + return false; +} + + + +bool ScreenshotFeaturePlugin::startFeature( VeyonMasterInterface& master, const Feature& feature, + const ComputerControlInterfaceList& computerControlInterfaces ) +{ + if( controlFeature( feature.uid(), Operation::Start, {}, computerControlInterfaces ) ) + { QMessageBox::information( master.mainWindow(), tr( "Screenshots taken" ), tr( "Screenshot of %1 computer have been taken successfully." ). @@ -71,5 +93,21 @@ bool ScreenshotFeaturePlugin::startFeature( VeyonMasterInterface& master, const return true; } - return true; + return false; +} + + + +void ScreenshotFeaturePlugin::initUi() +{ + auto master = VeyonCore::instance()->findChild(); + if( master->appContainer() ) + { + qmlRegisterType( "Veyon.Plugins.Screenshot", version().majorVersion(), version().minorVersion(), + "ScreenshotListModel" ); + VeyonCore::qmlCore().createItemFromFile( QStringLiteral("qrc:/screenshot/ScreenshotManagementPage.qml"), + master->appContainer(), + this ); + + } } diff --git a/plugins/screenshot/ScreenshotFeaturePlugin.h b/plugins/screenshot/ScreenshotFeaturePlugin.h index 9fa5aa158..b28400aad 100644 --- a/plugins/screenshot/ScreenshotFeaturePlugin.h +++ b/plugins/screenshot/ScreenshotFeaturePlugin.h @@ -1,7 +1,7 @@ /* * ScreenshotFeaturePlugin.h - declaration of ScreenshotFeature class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,9 +25,9 @@ #pragma once #include "Feature.h" -#include "SimpleFeatureProvider.h" +#include "FeatureProviderInterface.h" -class ScreenshotFeaturePlugin : public QObject, SimpleFeatureProvider, PluginInterface +class ScreenshotFeaturePlugin : public QObject, FeatureProviderInterface, PluginInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "io.veyon.Veyon.Plugins.Screenshot") @@ -38,12 +38,12 @@ class ScreenshotFeaturePlugin : public QObject, SimpleFeatureProvider, PluginInt Plugin::Uid uid() const override { - return QStringLiteral("ee322521-f4fb-482d-b082-82a79003afa7"); + return Plugin::Uid{ QStringLiteral("ee322521-f4fb-482d-b082-82a79003afa7") }; } QVersionNumber version() const override { - return QVersionNumber( 1, 1 ); + return QVersionNumber( 2, 0 ); } QString name() const override @@ -68,11 +68,16 @@ class ScreenshotFeaturePlugin : public QObject, SimpleFeatureProvider, PluginInt const FeatureList& featureList() const override; + bool controlFeature( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) override; + bool startFeature( VeyonMasterInterface& master, const Feature& feature, const ComputerControlInterfaceList& computerControlInterfaces ) override; private: + void initUi(); + const Feature m_screenshotFeature; const FeatureList m_features; diff --git a/plugins/screenshot/ScreenshotListModel.cpp b/plugins/screenshot/ScreenshotListModel.cpp new file mode 100644 index 000000000..0c01f1794 --- /dev/null +++ b/plugins/screenshot/ScreenshotListModel.cpp @@ -0,0 +1,101 @@ +/* + * ScreenshotListModel.cpp - implementation of ScreenshotListModel + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include +#include + +#include "Filesystem.h" +#include "ScreenshotListModel.h" +#include "VeyonConfiguration.h" +#include "VeyonCore.h" + + +ScreenshotListModel::ScreenshotListModel( QObject* parent ) : + QStringListModel( parent ) +{ + VeyonCore::filesystem().ensurePathExists( VeyonCore::config().screenshotDirectory() ); + + m_fsWatcher.addPath( VeyonCore::filesystem().screenshotDirectoryPath() ); + connect( &m_fsWatcher, &QFileSystemWatcher::directoryChanged, this, &ScreenshotListModel::updateModel ); + + m_reloadTimer.setInterval( FsModelResetDelay ); + m_reloadTimer.setSingleShot( true ); + + connect( &m_reloadTimer, &QTimer::timeout, this, &ScreenshotListModel::updateModel ); + connect( &VeyonCore::filesystem(), &Filesystem::screenshotDirectoryModified, + &m_reloadTimer, QOverload<>::of(&QTimer::start) ); + + updateModel(); +} + + + +QHash ScreenshotListModel::roleNames() const +{ + //auto roles = QStringListModel::roleNames(); + QHash roles; + roles[Qt::DisplayRole] = "name"; + roles[Qt::UserRole+1] = "url"; + return roles; +} + + + +QVariant ScreenshotListModel::data(const QModelIndex& index, int role) const +{ + if( role == Qt::UserRole+1 ) + { + return QString{QStringLiteral("file://") + filePath(index)}; + } + + return QStringListModel::data(index, role); +} + + + +void ScreenshotListModel::updateModel() +{ + setStringList( QDir{ VeyonCore::filesystem().screenshotDirectoryPath() } + .entryList( { QStringLiteral("*.png") }, QDir::Filter::Files, QDir::SortFlag::Name ) ); +} + + + +QString ScreenshotListModel::filePath( const QModelIndex& index ) const +{ + return VeyonCore::filesystem().screenshotDirectoryPath() + QDir::separator() + + data( index, Qt::DisplayRole ).toString(); +} + + + +void ScreenshotListModel::deleteScreenshot( const QModelIndexList& indexes ) +{ + for( const auto& index : indexes ) + { + QFile::remove( filePath( index ) ); + } + + updateModel(); +} diff --git a/plugins/screenshot/ScreenshotListModel.h b/plugins/screenshot/ScreenshotListModel.h new file mode 100644 index 000000000..8e3e9e332 --- /dev/null +++ b/plugins/screenshot/ScreenshotListModel.h @@ -0,0 +1,54 @@ +/* + * ScreenshotListModel.h - declaration of ScreenshotListModel + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include +#include +#include + +class ScreenshotListModel : public QStringListModel +{ + Q_OBJECT +public: + explicit ScreenshotListModel( QObject *parent = nullptr ); + + QHash roleNames() const override; + + QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override; + + void deleteScreenshot( const QModelIndexList& indexes ); + +private: + void updateModel(); + + QString filePath( const QModelIndex& index ) const; + + QFileSystemWatcher m_fsWatcher{this}; + + QTimer m_reloadTimer{this}; + + static constexpr auto FsModelResetDelay = 1000; + +} ; diff --git a/plugins/screenshot/ScreenshotManagementPage.qml b/plugins/screenshot/ScreenshotManagementPage.qml new file mode 100644 index 000000000..74f340ab2 --- /dev/null +++ b/plugins/screenshot/ScreenshotManagementPage.qml @@ -0,0 +1,80 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.12 +import Veyon.Plugins.Screenshot 2.0 + +Page { + title: qsTr("Screenshots") + property bool canBeClosed: false + + Flipable { + id: flipable + property bool flipped: false + anchors.fill: parent + + transform: Rotation { + id: rotation + origin.x: flipable.width/2 + origin.y: flipable.height/2 + axis.x: 0; axis.y: 1; axis.z: 0 + angle: 0 + } + + states: State { + name: "back" + PropertyChanges { target: rotation; angle: 180 } + when: flipable.flipped + } + + transitions: Transition { + NumberAnimation { target: rotation; property: "angle"; duration: 250 } + } + + front: GridView { + id: gridView + anchors.fill: parent + model: ScreenshotListModel { } + cellWidth: 300 + cellHeight: cellWidth * 9 / 16 + 20 + + delegate: ColumnLayout { + spacing: 5 + width: gridView.cellWidth + height: gridView.cellHeight + Image { + Layout.margins: 2 + source: url + Layout.alignment: Qt.AlignHCenter + sourceSize.width: width//parent.width + sourceSize.height: height//parent.height - label.height + clip: true + asynchronous: true + Layout.fillHeight: true + MouseArea { + anchors.fill: parent + onClicked: { + screenshotView.source = url + flipable.flipped = !flipable.flipped + } + } + } + Label { + id: label + text: name + Layout.margins: 5 + elide: Label.ElideRight + Layout.fillWidth: true + } + } + } + + back: Image { + anchors.fill: parent + id: screenshotView + MouseArea { + anchors.fill: parent + onClicked: flipable.flipped = !flipable.flipped + } + } + } +} diff --git a/plugins/screenshot/camera-photo.png b/plugins/screenshot/camera-photo.png index f8ab91dbb..964a472cf 100644 Binary files a/plugins/screenshot/camera-photo.png and b/plugins/screenshot/camera-photo.png differ diff --git a/plugins/screenshot/screenshot.qrc b/plugins/screenshot/screenshot.qrc index 7d26b754b..8c4959466 100644 --- a/plugins/screenshot/screenshot.qrc +++ b/plugins/screenshot/screenshot.qrc @@ -1,5 +1,6 @@ - + camera-photo.png + ScreenshotManagementPage.qml diff --git a/plugins/servicecontrol/CMakeLists.txt b/plugins/servicecontrol/CMakeLists.txt deleted file mode 100644 index 84eb3b8b2..000000000 --- a/plugins/servicecontrol/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -INCLUDE(BuildPlugin) - -BUILD_PLUGIN(servicecontrol - ServiceControlPlugin.cpp - ServiceControlPlugin.h -) diff --git a/plugins/shell/CMakeLists.txt b/plugins/shell/CMakeLists.txt deleted file mode 100644 index 9b04dde83..000000000 --- a/plugins/shell/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -INCLUDE(BuildPlugin) - -BUILD_PLUGIN(shell ShellCommandLinePlugin.cpp ShellCommandLinePlugin.h) diff --git a/plugins/systemusergroups/CMakeLists.txt b/plugins/systemusergroups/CMakeLists.txt index f5116f2f0..c3b0c626f 100644 --- a/plugins/systemusergroups/CMakeLists.txt +++ b/plugins/systemusergroups/CMakeLists.txt @@ -1,6 +1,6 @@ -INCLUDE(BuildPlugin) +include(BuildVeyonPlugin) -BUILD_PLUGIN(systemusergroups +build_veyon_plugin(systemusergroups SystemUserGroupsPlugin.cpp SystemUserGroupsPlugin.h -) + ) diff --git a/plugins/systemusergroups/SystemUserGroupsPlugin.cpp b/plugins/systemusergroups/SystemUserGroupsPlugin.cpp index 7569c3a1c..f965d2504 100644 --- a/plugins/systemusergroups/SystemUserGroupsPlugin.cpp +++ b/plugins/systemusergroups/SystemUserGroupsPlugin.cpp @@ -1,7 +1,7 @@ /* * SystemUserGroupsPlugin.cpp - implementation of SystemUserGroupsPlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/plugins/systemusergroups/SystemUserGroupsPlugin.h b/plugins/systemusergroups/SystemUserGroupsPlugin.h index d5ef1b95c..b8912c5cc 100644 --- a/plugins/systemusergroups/SystemUserGroupsPlugin.h +++ b/plugins/systemusergroups/SystemUserGroupsPlugin.h @@ -1,7 +1,7 @@ /* * SystemUserGroupsPlugin.h - declaration of SystemUserGroupsPlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -37,7 +37,7 @@ class SystemUserGroupsPlugin : public QObject, PluginInterface, UserGroupsBacken Plugin::Uid uid() const override { - return QStringLiteral("2917cdeb-ac13-4099-8715-20368254a367"); + return Plugin::Uid{ QStringLiteral("2917cdeb-ac13-4099-8715-20368254a367") }; } QVersionNumber version() const override diff --git a/plugins/testing/CMakeLists.txt b/plugins/testing/CMakeLists.txt index 015c43678..562be4a63 100644 --- a/plugins/testing/CMakeLists.txt +++ b/plugins/testing/CMakeLists.txt @@ -1,5 +1,5 @@ -INCLUDE(BuildPlugin) +include(BuildVeyonPlugin) -IF(VEYON_DEBUG) -BUILD_PLUGIN(testing TestingCommandLinePlugin.cpp TestingCommandLinePlugin.h) -ENDIF() +if(VEYON_DEBUG) + build_veyon_plugin(testing TestingCommandLinePlugin.cpp TestingCommandLinePlugin.h) +endif() diff --git a/plugins/testing/TestingCommandLinePlugin.cpp b/plugins/testing/TestingCommandLinePlugin.cpp index 3bec5fd9b..481627d0e 100644 --- a/plugins/testing/TestingCommandLinePlugin.cpp +++ b/plugins/testing/TestingCommandLinePlugin.cpp @@ -1,7 +1,7 @@ /* * TestingCommandLinePlugin.cpp - implementation of TestingCommandLinePlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,15 +24,16 @@ #include "CommandLineIO.h" #include "AccessControlProvider.h" +#include "PlatformNetworkFunctions.h" #include "TestingCommandLinePlugin.h" TestingCommandLinePlugin::TestingCommandLinePlugin( QObject* parent ) : QObject( parent ), m_commands( { -{ QStringLiteral("checkaccess"), QStringLiteral( "check access with arguments [ACCESSING USER] [ACCESSING COMPUTER] [CONNECTED USER]" ) }, +{ QStringLiteral("checkaccess"), QStringLiteral( "check access with arguments [ACCESSING USER] [ACCESSING COMPUTER] [CONNECTED USER] [AUTH METHOD UID]" ) }, { QStringLiteral("authorizedgroups"), QStringLiteral( "check if specified user is in authorized groups [ACCESSING USER]" ) }, -{ QStringLiteral("accesscontrolrules"), QStringLiteral( "process access control rules with arguments [ACCESSING USER] [ACCESSING COMPUTER] [LOCAL USER] [LOCAL COMPUTER] [CONNECTED USER]" ) }, +{ QStringLiteral("accesscontrolrules"), QStringLiteral( "process access control rules with arguments [ACCESSING USER] [ACCESSING COMPUTER] [LOCAL USER] [LOCAL COMPUTER] [CONNECTED USER] [AUTH METHOD UID]" ) }, { QStringLiteral("isaccessdeniedbylocalstate"), QStringLiteral( "check if access would be denied by local state") }, } ) { @@ -57,7 +58,8 @@ QString TestingCommandLinePlugin::commandHelp( const QString& command ) const CommandLinePluginInterface::RunResult TestingCommandLinePlugin::handle_checkaccess( const QStringList& arguments ) { - switch( AccessControlProvider().checkAccess( arguments.value( 0 ), arguments.value( 1 ), { arguments.value( 2 ) } ) ) + switch (AccessControlProvider().checkAccess(arguments.value(0), arguments.value(1), {arguments.value(2)}, + Plugin::Uid{arguments.value(3)}).access) { case AccessControlProvider::Access::Allow: printf( "[TEST]: CheckAccess: ALLOW\n" ); return Successful; case AccessControlProvider::Access::Deny: printf( "[TEST]: CheckAccess: DENY\n" ); return Successful; @@ -87,9 +89,12 @@ CommandLinePluginInterface::RunResult TestingCommandLinePlugin::handle_authorize CommandLinePluginInterface::RunResult TestingCommandLinePlugin::handle_accesscontrolrules( const QStringList& arguments ) { - switch( AccessControlProvider().processAccessControlRules( arguments.value( 0 ), arguments.value( 1 ), - arguments.value( 2 ), arguments.value( 3 ), - QStringList( arguments.value( 4 ) ) ) ) + AccessControlProvider provider; + const auto rule = provider.processAccessControlRules(arguments.value(0), arguments.value(1), + arguments.value(2), arguments.value(3), + QStringList(arguments.value(4)), + Plugin::Uid{arguments.value(5)}); + switch(rule ? rule->action() : AccessControlRule::Action::None) { case AccessControlRule::Action::Allow: printf( "[TEST]: AccessControlRules: ALLOW\n" ); return Successful; case AccessControlRule::Action::Deny: printf( "[TEST]: AccessControlRules: DENY\n" ); return Successful; @@ -118,3 +123,15 @@ CommandLinePluginInterface::RunResult TestingCommandLinePlugin::handle_isaccessd return Successful; } + + + +CommandLinePluginInterface::RunResult TestingCommandLinePlugin::handle_ping( const QStringList& arguments ) +{ + if( arguments.count() < 1 ) + { + return NotEnoughArguments; + } + + return VeyonCore::platform().networkFunctions().ping( arguments.first() ) == PlatformNetworkFunctions::PingResult::ReplyReceived ? Successful : Failed; +} diff --git a/plugins/testing/TestingCommandLinePlugin.h b/plugins/testing/TestingCommandLinePlugin.h index adec0e905..f265415b0 100644 --- a/plugins/testing/TestingCommandLinePlugin.h +++ b/plugins/testing/TestingCommandLinePlugin.h @@ -1,7 +1,7 @@ /* * TestingCommandLinePlugin.h - declaration of TestingCommandLinePlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -38,7 +38,7 @@ class TestingCommandLinePlugin : public QObject, CommandLinePluginInterface, Plu Plugin::Uid uid() const override { - return QStringLiteral("a8a84654-40ca-4731-811e-7e05997ed081"); + return Plugin::Uid{ QStringLiteral("a8a84654-40ca-4731-811e-7e05997ed081") }; } QVersionNumber version() const override @@ -79,11 +79,12 @@ class TestingCommandLinePlugin : public QObject, CommandLinePluginInterface, Plu QStringList commands() const override; QString commandHelp( const QString& command ) const override; -public slots: +public Q_SLOTS: CommandLinePluginInterface::RunResult handle_checkaccess( const QStringList& arguments ); CommandLinePluginInterface::RunResult handle_authorizedgroups( const QStringList& arguments ); CommandLinePluginInterface::RunResult handle_accesscontrolrules( const QStringList& arguments ); CommandLinePluginInterface::RunResult handle_isaccessdeniedbylocalstate( const QStringList& arguments ); + CommandLinePluginInterface::RunResult handle_ping( const QStringList& arguments ); private: QMap m_commands; diff --git a/plugins/textmessage/CMakeLists.txt b/plugins/textmessage/CMakeLists.txt index 41291be78..964438667 100644 --- a/plugins/textmessage/CMakeLists.txt +++ b/plugins/textmessage/CMakeLists.txt @@ -1,11 +1,10 @@ -INCLUDE(BuildPlugin) +include(BuildVeyonPlugin) -BUILD_PLUGIN(textmessage +build_veyon_plugin(textmessage TextMessageFeaturePlugin.cpp TextMessageDialog.cpp TextMessageDialog.ui TextMessageFeaturePlugin.h TextMessageDialog.h textmessage.qrc -) - + ) diff --git a/plugins/textmessage/TextMessageDialog.cpp b/plugins/textmessage/TextMessageDialog.cpp index 3ef169d83..1abe5333d 100644 --- a/plugins/textmessage/TextMessageDialog.cpp +++ b/plugins/textmessage/TextMessageDialog.cpp @@ -1,7 +1,7 @@ /* * TextMessageDialog.cpp - implementation of text message dialog class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -51,6 +51,6 @@ TextMessageDialog::~TextMessageDialog() void TextMessageDialog::accept() { - m_msgStr = ui->textEdit->toPlainText(); + m_msgStr = ui->textEdit->toHtml(); QDialog::accept(); } diff --git a/plugins/textmessage/TextMessageDialog.h b/plugins/textmessage/TextMessageDialog.h index 43e6d161b..3fb507362 100644 --- a/plugins/textmessage/TextMessageDialog.h +++ b/plugins/textmessage/TextMessageDialog.h @@ -1,7 +1,7 @@ /* * TextMessageDialog.h - declaration of text message dialog class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -38,7 +38,7 @@ class TextMessageDialog : public QDialog TextMessageDialog( QString &msgStr, QWidget *parent ); ~TextMessageDialog() override; -private slots: +private Q_SLOTS: void accept() override; diff --git a/plugins/textmessage/TextMessageDialog.qml b/plugins/textmessage/TextMessageDialog.qml new file mode 100644 index 000000000..6cc3c0c6f --- /dev/null +++ b/plugins/textmessage/TextMessageDialog.qml @@ -0,0 +1,35 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.1 +import QtQuick.Dialogs 1.0 +import QtQuick.Layouts 1.0 + +Dialog { + title: qsTr("Send text message") + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + standardButtons: Dialog.Ok | Dialog.Cancel + visible: true + modal: true + + onAccepted: { + context.acceptTextMessage(textArea.text) + qmlCore.deleteLater(this) + } + onRejected: qmlCore.deleteLater(this) + + ColumnLayout { + anchors.fill: parent + Label { + text: qsTr("Please enter your message which send to all selected users.") + wrapMode: Label.WordWrap + Layout.fillWidth: true + } + + TextArea { + id: textArea + focus: true + Layout.fillWidth: true + Layout.fillHeight: true + } + } +} diff --git a/plugins/textmessage/TextMessageDialog.ui b/plugins/textmessage/TextMessageDialog.ui index 3e593624d..e13e685d3 100644 --- a/plugins/textmessage/TextMessageDialog.ui +++ b/plugins/textmessage/TextMessageDialog.ui @@ -14,7 +14,7 @@ - Use the field below to type your message which will be sent to all selected users. + Please enter your message which send to all selected users. true diff --git a/plugins/textmessage/TextMessageFeaturePlugin.cpp b/plugins/textmessage/TextMessageFeaturePlugin.cpp index 985ae6204..59ecbf0a1 100644 --- a/plugins/textmessage/TextMessageFeaturePlugin.cpp +++ b/plugins/textmessage/TextMessageFeaturePlugin.cpp @@ -1,7 +1,7 @@ /* * TextMessageFeaturePlugin.cpp - implementation of TextMessageFeaturePlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,11 +23,13 @@ */ #include +#include -#include "TextMessageFeaturePlugin.h" -#include "TextMessageDialog.h" -#include "FeatureWorkerManager.h" #include "ComputerControlInterface.h" +#include "FeatureWorkerManager.h" +#include "QmlCore.h" +#include "TextMessageDialog.h" +#include "TextMessageFeaturePlugin.h" #include "VeyonMasterInterface.h" #include "VeyonServerInterface.h" @@ -35,7 +37,7 @@ TextMessageFeaturePlugin::TextMessageFeaturePlugin( QObject* parent ) : QObject( parent ), m_textMessageFeature( Feature( QStringLiteral( "TextMessage" ), - Feature::Action | Feature::AllComponents, + Feature::Flag::Action | Feature::Flag::AllComponents, Feature::Uid( "e75ae9c8-ac17-4d00-8f0d-019348346208" ), Feature::Uid(), tr( "Text message" ), {}, @@ -55,56 +57,82 @@ const FeatureList &TextMessageFeaturePlugin::featureList() const -bool TextMessageFeaturePlugin::startFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) +bool TextMessageFeaturePlugin::controlFeature( Feature::Uid featureUid, + Operation operation, + const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) { - if( feature.uid() != m_textMessageFeature.uid() ) + if( operation != Operation::Start ) { return false; } - QString textMessage; - - TextMessageDialog( textMessage, master.mainWindow() ).exec(); - - if( textMessage.isEmpty() == false ) + if( featureUid == m_textMessageFeature.uid() ) { - FeatureMessage featureMessage( m_textMessageFeature.uid(), ShowTextMessage ); - featureMessage.addArgument( MessageTextArgument, textMessage ); - featureMessage.addArgument( MessageIcon, QMessageBox::Information ); + const auto text = arguments.value( argToString(Argument::Text) ).toString(); + const auto icon = arguments.value( argToString(Argument::Icon) ).toInt(); + + sendFeatureMessage( FeatureMessage{ featureUid, ShowTextMessage } + .addArgument( Argument::Text, text ) + .addArgument( Argument::Icon, icon ), computerControlInterfaces ); - sendFeatureMessage( featureMessage, computerControlInterfaces ); + return true; } - return true; + return false; } -bool TextMessageFeaturePlugin::stopFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) +bool TextMessageFeaturePlugin::startFeature( VeyonMasterInterface& master, const Feature& feature, + const ComputerControlInterfaceList& computerControlInterfaces ) { - Q_UNUSED(master); - Q_UNUSED(feature); - Q_UNUSED(computerControlInterfaces); + if( feature.uid() != m_textMessageFeature.uid() ) + { + return false; + } - return false; -} + if( master.appWindow() ) + { + auto dialog = VeyonCore::qmlCore().createObjectFromFile( QStringLiteral("qrc:/textmessage/TextMessageDialog.qml"), + master.appWindow(), + this ); + connect( this, &TextMessageFeaturePlugin::acceptTextMessage, dialog, // clazy:exclude=connect-non-signal + [this, computerControlInterfaces]( const QString& text ) { + if( text.isEmpty() == false ) + { + controlFeature( m_textMessageFeature.uid(), Operation::Start, + { + { argToString(Argument::Text), text }, + { argToString(Argument::Icon), QMessageBox::Information } + }, + computerControlInterfaces ); + } + } ); + + return true; + } + QString textMessage; + TextMessageDialog( textMessage, master.mainWindow() ).exec(); -bool TextMessageFeaturePlugin::handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) -{ - Q_UNUSED(master); - Q_UNUSED(message); - Q_UNUSED(computerControlInterface); + if( textMessage.isEmpty() == false ) + { + controlFeature( m_textMessageFeature.uid(), Operation::Start, + { + { argToString(Argument::Text), textMessage }, + { argToString(Argument::Icon), QMessageBox::Information } + }, + computerControlInterfaces ); + } - return false; + return true; } + bool TextMessageFeaturePlugin::handleFeatureMessage( VeyonServerInterface& server, const MessageContext& messageContext, const FeatureMessage& message ) @@ -114,11 +142,7 @@ bool TextMessageFeaturePlugin::handleFeatureMessage( VeyonServerInterface& serve if( m_textMessageFeature.uid() == message.featureUid() ) { // forward message to worker - if( server.featureWorkerManager().isWorkerRunning( m_textMessageFeature ) == false ) - { - server.featureWorkerManager().startWorker( m_textMessageFeature, FeatureWorkerManager::UnmanagedSessionProcess ); - } - server.featureWorkerManager().sendMessage( message ); + server.featureWorkerManager().sendMessageToUnmanagedSessionWorker( message ); return true; } @@ -130,13 +154,15 @@ bool TextMessageFeaturePlugin::handleFeatureMessage( VeyonServerInterface& serve bool TextMessageFeaturePlugin::handleFeatureMessage( VeyonWorkerInterface& worker, const FeatureMessage& message ) { - Q_UNUSED(worker); + Q_UNUSED(worker) if( message.featureUid() == m_textMessageFeature.uid() ) { - QMessageBox* messageBox = new QMessageBox( static_cast( message.argument( MessageIcon ).toInt() ), - tr( "Message from teacher" ), - message.argument( MessageTextArgument ).toString() ); + auto messageBox = new QMessageBox( static_cast( message.argument( Argument::Icon ).toInt() ), + tr( "Message from teacher" ), + message.argument( Argument::Text ).toString() ); + messageBox->setTextFormat( Qt::RichText ); + messageBox->setTextInteractionFlags( Qt::TextBrowserInteraction | Qt::TextSelectableByKeyboard ); messageBox->show(); connect( messageBox, &QMessageBox::accepted, messageBox, &QMessageBox::deleteLater ); @@ -146,3 +172,4 @@ bool TextMessageFeaturePlugin::handleFeatureMessage( VeyonWorkerInterface& worke return true; } + diff --git a/plugins/textmessage/TextMessageFeaturePlugin.h b/plugins/textmessage/TextMessageFeaturePlugin.h index 5bd2e121b..4d5da7086 100644 --- a/plugins/textmessage/TextMessageFeaturePlugin.h +++ b/plugins/textmessage/TextMessageFeaturePlugin.h @@ -1,7 +1,7 @@ /* * TextMessageFeaturePlugin.h - declaration of TextMessageFeature class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -33,12 +33,18 @@ class TextMessageFeaturePlugin : public QObject, FeatureProviderInterface, Plugi Q_PLUGIN_METADATA(IID "io.veyon.Veyon.Plugins.TextMessage") Q_INTERFACES(PluginInterface FeatureProviderInterface) public: + enum class Argument { + Text, + Icon + }; + Q_ENUM(Argument) + explicit TextMessageFeaturePlugin( QObject* parent = nullptr ); ~TextMessageFeaturePlugin() override = default; Plugin::Uid uid() const override { - return QStringLiteral("8ae6668b-9c12-4b29-9bfc-ff89f6604164"); + return Plugin::Uid{ QStringLiteral("8ae6668b-9c12-4b29-9bfc-ff89f6604164") }; } QVersionNumber version() const override @@ -68,32 +74,26 @@ class TextMessageFeaturePlugin : public QObject, FeatureProviderInterface, Plugi const FeatureList& featureList() const override; + bool controlFeature( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) override; + bool startFeature( VeyonMasterInterface& master, const Feature& feature, const ComputerControlInterfaceList& computerControlInterfaces ) override; - bool stopFeature( VeyonMasterInterface& master, const Feature& feature, - const ComputerControlInterfaceList& computerControlInterfaces ) override; - - bool handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) override; - bool handleFeatureMessage( VeyonServerInterface& server, const MessageContext& messageContext, const FeatureMessage& message ) override; bool handleFeatureMessage( VeyonWorkerInterface& worker, const FeatureMessage& message ) override; +Q_SIGNALS: + Q_INVOKABLE void acceptTextMessage( const QString& textMessage ); + private: enum Commands { ShowTextMessage }; - enum FeatureMessageArguments { - MessageTextArgument, - MessageIcon, - FeatureMessageArgumentCount - }; - const Feature m_textMessageFeature; const FeatureList m_features; diff --git a/plugins/textmessage/textmessage.qrc b/plugins/textmessage/textmessage.qrc index 93f64c521..71c08a0f1 100644 --- a/plugins/textmessage/textmessage.qrc +++ b/plugins/textmessage/textmessage.qrc @@ -1,5 +1,6 @@ - + dialog-information.png + TextMessageDialog.qml diff --git a/plugins/usersessioncontrol/CMakeLists.txt b/plugins/usersessioncontrol/CMakeLists.txt new file mode 100644 index 000000000..447203508 --- /dev/null +++ b/plugins/usersessioncontrol/CMakeLists.txt @@ -0,0 +1,10 @@ +include(BuildVeyonPlugin) + +build_veyon_plugin(usersessioncontrol + UserSessionControlPlugin.cpp + UserSessionControlPlugin.h + UserLoginDialog.cpp + UserLoginDialog.h + UserLoginDialog.ui + usersessioncontrol.qrc + ) diff --git a/plugins/usersessioncontrol/UserLoginDialog.cpp b/plugins/usersessioncontrol/UserLoginDialog.cpp new file mode 100644 index 000000000..bde5a7123 --- /dev/null +++ b/plugins/usersessioncontrol/UserLoginDialog.cpp @@ -0,0 +1,75 @@ +/* + * UserLoginDialog.cpp - dialog for querying logon credentials + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include + +#include "UserLoginDialog.h" + +#include "ui_UserLoginDialog.h" + + +UserLoginDialog::UserLoginDialog( QWidget *parent ) : + QDialog( parent ), + ui( new Ui::UserLoginDialog ) +{ + ui->setupUi( this ); + + if( ui->username->text().isEmpty() == false ) + { + ui->password->setFocus(); + } + + updateOkButton(); + + VeyonCore::enforceBranding( this ); +} + + + +UserLoginDialog::~UserLoginDialog() +{ + delete ui; +} + + + +QString UserLoginDialog::username() const +{ + return ui->username->text(); +} + + + +CryptoCore::PlaintextPassword UserLoginDialog::password() const +{ + return ui->password->text().toUtf8(); +} + + + +void UserLoginDialog::updateOkButton() +{ + ui->buttonBox->button( QDialogButtonBox::Ok )-> + setEnabled( !username().isEmpty() && !password().isEmpty() ); +} diff --git a/plugins/usersessioncontrol/UserLoginDialog.h b/plugins/usersessioncontrol/UserLoginDialog.h new file mode 100644 index 000000000..a3ca230f8 --- /dev/null +++ b/plugins/usersessioncontrol/UserLoginDialog.h @@ -0,0 +1,49 @@ +/* + * UserLoginDialog.h - dialog for querying logon credentials + * + * Copyright (c) 2019-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "CryptoCore.h" + +#include + +namespace Ui { class UserLoginDialog; } + +class UserLoginDialog : public QDialog +{ + Q_OBJECT +public: + explicit UserLoginDialog( QWidget *parent ); + ~UserLoginDialog() override; + + QString username() const; + CryptoCore::PlaintextPassword password() const; + +private Q_SLOTS: + void updateOkButton(); + +private: + Ui::UserLoginDialog *ui; + +} ; diff --git a/plugins/usersessioncontrol/UserLoginDialog.ui b/plugins/usersessioncontrol/UserLoginDialog.ui new file mode 100644 index 000000000..636b7f1fa --- /dev/null +++ b/plugins/usersessioncontrol/UserLoginDialog.ui @@ -0,0 +1,142 @@ + + + UserLoginDialog + + + User login + + + + :/usersessioncontrol/login-user.png:/usersessioncontrol/login-user.png + + + + + + Please enter a username and password for automatic login on all computers. + + + true + + + + + + + 16 + + + + + Username + + + + + + + + 350 + 0 + + + + + + + + Password + + + + + + + QLineEdit::Password + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + UserLoginDialog + accept() + + + 206 + 137 + + + 169 + 79 + + + + + buttonBox + rejected() + UserLoginDialog + reject() + + + 206 + 137 + + + 169 + 79 + + + + + password + textChanged(QString) + UserLoginDialog + updateOkButton() + + + 204 + 107 + + + 169 + 78 + + + + + username + textChanged(QString) + UserLoginDialog + updateOkButton() + + + 204 + 76 + + + 169 + 78 + + + + + + updateOkButton() + + diff --git a/plugins/usersessioncontrol/UserSessionControlPlugin.cpp b/plugins/usersessioncontrol/UserSessionControlPlugin.cpp new file mode 100644 index 000000000..65abc3a38 --- /dev/null +++ b/plugins/usersessioncontrol/UserSessionControlPlugin.cpp @@ -0,0 +1,179 @@ +/* + * UserSessionControlPlugin.cpp - implementation of UserSessionControlPlugin class + * + * Copyright (c) 2017-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include + +#include "PlatformSessionFunctions.h" +#include "PlatformUserFunctions.h" +#include "UserLoginDialog.h" +#include "UserSessionControlPlugin.h" +#include "VeyonConfiguration.h" +#include "VeyonMasterInterface.h" + + +UserSessionControlPlugin::UserSessionControlPlugin( QObject* parent ) : + QObject( parent ), + m_userLoginFeature( QStringLiteral( "UserLogin" ), + Feature::Flag::Action | Feature::Flag::Master | Feature::Flag::Service, + Feature::Uid( "7310707d-3918-460d-a949-65bd152cb958" ), + Feature::Uid(), + tr( "Log in" ), {}, + tr( "Click this button to log in a specific user on all computers." ), + QStringLiteral( ":/usersessioncontrol/login-user.png" ) ), + m_userLogoffFeature( QStringLiteral( "UserLogoff" ), + Feature::Flag::Action | Feature::Flag::Master | Feature::Flag::Service, + Feature::Uid( "7311d43d-ab53-439e-a03a-8cb25f7ed526" ), + Feature::Uid(), + tr( "Log off" ), {}, + tr( "Click this button to log off users from all computers." ), + QStringLiteral( ":/usersessioncontrol/logout-user.png" ) ), + m_features( { m_userLoginFeature, m_userLogoffFeature } ) +{ +} + + + +bool UserSessionControlPlugin::controlFeature( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) +{ + if( operation != Operation::Start ) + { + return false; + } + + if( featureUid == m_userLoginFeature.uid() ) + { + const auto username = arguments.value( argToString(Argument::Username) ).toString(); + const auto password = arguments.value( argToString(Argument::Password) ).toByteArray(); + if( username.isEmpty() ) + { + return false; + } + + sendFeatureMessage( FeatureMessage{ featureUid, FeatureMessage::DefaultCommand } + .addArgument( Argument::Username, username ) + .addArgument( Argument::Password, VeyonCore::cryptoCore().encryptPassword( password ) ), + computerControlInterfaces ); + + return true; + } + + if( featureUid == m_userLogoffFeature.uid() ) + { + sendFeatureMessage( FeatureMessage{ featureUid, FeatureMessage::DefaultCommand }, computerControlInterfaces ); + + return true; + } + + return false; +} + + + +bool UserSessionControlPlugin::startFeature( VeyonMasterInterface& master, const Feature& feature, + const ComputerControlInterfaceList& computerControlInterfaces ) +{ + Q_UNUSED(master) + + if( feature == m_userLoginFeature ) + { + UserLoginDialog loginDialog( master.mainWindow() ); + if( loginDialog.exec() ) + { + return controlFeature( feature.uid(), Operation::Start, + { + { argToString(Argument::Username), loginDialog.username() }, + { argToString(Argument::Password), loginDialog.password().toByteArray() } + }, + computerControlInterfaces ); + } + } + else if( feature == m_userLogoffFeature ) + { + const auto executeOnAllComputers = + computerControlInterfaces.size() >= master.filteredComputerControlInterfaces().size(); + + if (confirmFeatureExecution(feature, executeOnAllComputers, master.mainWindow()) == false) + { + return true; + } + + return controlFeature( feature.uid(), Operation::Start, {}, computerControlInterfaces ); + } + + return false; +} + + + +bool UserSessionControlPlugin::handleFeatureMessage( VeyonServerInterface& server, + const MessageContext& messageContext, + const FeatureMessage& message ) +{ + Q_UNUSED(server) + Q_UNUSED(messageContext) + + if( message.featureUid() == m_userLoginFeature.uid() ) + { + VeyonCore::platform().userFunctions().prepareLogon( message.argument( Argument::Username ).toString(), + VeyonCore::cryptoCore().decryptPassword( + message.argument( Argument::Password ).toString() ) ); + return true; + } + + if( message.featureUid() == m_userLogoffFeature.uid() ) + { + if( VeyonCore::platform().sessionFunctions().currentSessionHasUser() ) + { + VeyonCore::platform().userFunctions().logoff(); + } + else + { + vDebug() << "not logging off since not running in a user session"; + } + return true; + } + + return false; +} + + + +bool UserSessionControlPlugin::confirmFeatureExecution( const Feature& feature, bool all, QWidget* parent ) +{ + if( VeyonCore::config().confirmUnsafeActions() == false ) + { + return true; + } + + if( feature == m_userLogoffFeature ) + { + return QMessageBox::question( parent, tr( "Confirm user logoff" ), + all ? tr( "Do you really want to log off ALL users?" ) + : tr( "Do you really want to log off the selected users?" ) ) == + QMessageBox::Yes; + } + + return true; +} diff --git a/core/include/UserSessionControl.h b/plugins/usersessioncontrol/UserSessionControlPlugin.h similarity index 62% rename from core/include/UserSessionControl.h rename to plugins/usersessioncontrol/UserSessionControlPlugin.h index 33e5f3238..681c06271 100644 --- a/core/include/UserSessionControl.h +++ b/plugins/usersessioncontrol/UserSessionControlPlugin.h @@ -1,7 +1,7 @@ /* - * UserSessionControl.h - declaration of UserSessionControl class + * UserSessionControlPlugin.h - declaration of UserSessionControlPlugin class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,29 +26,32 @@ #include -#include "SimpleFeatureProvider.h" +#include "FeatureProviderInterface.h" -class QThread; -class QTimer; - -class VEYON_CORE_EXPORT UserSessionControl : public QObject, public SimpleFeatureProvider, public PluginInterface +class UserSessionControlPlugin : public QObject, public FeatureProviderInterface, public PluginInterface { Q_OBJECT + Q_PLUGIN_METADATA(IID "io.veyon.Veyon.Plugins.UserSessionControl") Q_INTERFACES(FeatureProviderInterface PluginInterface) public: - explicit UserSessionControl( QObject* parent = nullptr ); - ~UserSessionControl() override = default; + enum class Argument + { + Username, + Password + }; + Q_ENUM(Argument) - bool getUserSessionInfo( const ComputerControlInterfaceList& computerControlInterfaces ); + explicit UserSessionControlPlugin( QObject* parent = nullptr ); + ~UserSessionControlPlugin() override = default; Plugin::Uid uid() const override { - return QStringLiteral("80580500-2e59-4297-9e35-e53959b028cd"); + return Plugin::Uid{ QStringLiteral("80580500-2e59-4297-9e35-e53959b028cd") }; } QVersionNumber version() const override { - return QVersionNumber( 1, 1 ); + return QVersionNumber( 1, 2 ); } QString name() const override @@ -76,39 +79,21 @@ class VEYON_CORE_EXPORT UserSessionControl : public QObject, public SimpleFeatur return m_features; } + bool controlFeature( Feature::Uid featureUid, Operation operation, const QVariantMap& arguments, + const ComputerControlInterfaceList& computerControlInterfaces ) override; + bool startFeature( VeyonMasterInterface& master, const Feature& feature, const ComputerControlInterfaceList& computerControlInterfaces ) override; - bool handleFeatureMessage( VeyonMasterInterface& master, const FeatureMessage& message, - ComputerControlInterface::Pointer computerControlInterface ) override; - bool handleFeatureMessage( VeyonServerInterface& server, const MessageContext& messageContext, const FeatureMessage& message ) override; private: - enum Commands - { - GetInfo, - LogonUser, - LogoffUser - }; - - enum Arguments - { - UserLoginName, - UserFullName, - }; - - void queryUserInformation(); - bool confirmFeatureExecution( const Feature& feature, QWidget* parent ); + bool confirmFeatureExecution( const Feature& feature, bool all, QWidget* parent ); - const Feature m_userSessionInfoFeature; + const Feature m_userLoginFeature; const Feature m_userLogoffFeature; const FeatureList m_features; - QReadWriteLock m_userDataLock; - QString m_userLoginName; - QString m_userFullName; - }; diff --git a/plugins/usersessioncontrol/login-user.png b/plugins/usersessioncontrol/login-user.png new file mode 100644 index 000000000..0bfa1da07 Binary files /dev/null and b/plugins/usersessioncontrol/login-user.png differ diff --git a/plugins/usersessioncontrol/logout-user.png b/plugins/usersessioncontrol/logout-user.png new file mode 100644 index 000000000..982821f57 Binary files /dev/null and b/plugins/usersessioncontrol/logout-user.png differ diff --git a/plugins/usersessioncontrol/usersessioncontrol.qrc b/plugins/usersessioncontrol/usersessioncontrol.qrc new file mode 100644 index 000000000..73560fee9 --- /dev/null +++ b/plugins/usersessioncontrol/usersessioncontrol.qrc @@ -0,0 +1,6 @@ + + + login-user.png + logout-user.png + + diff --git a/plugins/vncserver/CMakeLists.txt b/plugins/vncserver/CMakeLists.txt index 619999323..239b7cee2 100644 --- a/plugins/vncserver/CMakeLists.txt +++ b/plugins/vncserver/CMakeLists.txt @@ -1,9 +1,10 @@ -IF(VEYON_BUILD_WIN32) -ADD_SUBDIRECTORY(ultravnc-builtin) -ENDIF() +if(VEYON_BUILD_WINDOWS) + add_subdirectory(ultravnc-builtin) +endif() -IF(VEYON_BUILD_LINUX) -ADD_SUBDIRECTORY(x11vnc-builtin) -ENDIF() +if(VEYON_BUILD_LINUX) + add_subdirectory(x11vnc-builtin) +endif() -ADD_SUBDIRECTORY(external) +add_subdirectory(external) +add_subdirectory(headless) diff --git a/plugins/vncserver/external/CMakeLists.txt b/plugins/vncserver/external/CMakeLists.txt index 907b3f1f9..552194aa2 100644 --- a/plugins/vncserver/external/CMakeLists.txt +++ b/plugins/vncserver/external/CMakeLists.txt @@ -1,11 +1,10 @@ -INCLUDE(BuildPlugin) +include(BuildVeyonPlugin) -BUILD_PLUGIN(external-vnc-server +build_veyon_plugin(external-vnc-server ExternalVncServer.cpp ExternalVncServerConfigurationWidget.cpp ExternalVncServerConfigurationWidget.ui ExternalVncServer.h ExternalVncServerConfiguration.h ExternalVncServerConfigurationWidget.h -) - + ) diff --git a/plugins/vncserver/external/ExternalVncServer.cpp b/plugins/vncserver/external/ExternalVncServer.cpp index 448ddce2a..6b515e0d8 100644 --- a/plugins/vncserver/external/ExternalVncServer.cpp +++ b/plugins/vncserver/external/ExternalVncServer.cpp @@ -1,7 +1,7 @@ /* * ExternalVncServer.cpp - implementation of ExternalVncServer class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -47,7 +47,7 @@ void ExternalVncServer::upgrade( const QVersionNumber& oldVersion ) if( rawPassword.size() < MaximumPlaintextPasswordLength ) { // setting it again will encrypt it - m_configuration.setPassword( Configuration::Password::fromPlainText( rawPassword ) ); + m_configuration.setPassword( Configuration::Password::fromPlainText( rawPassword.toUtf8() ) ); } } } @@ -67,12 +67,14 @@ void ExternalVncServer::prepareServer() -void ExternalVncServer::runServer( int serverPort, const QString& password ) +bool ExternalVncServer::runServer( int serverPort, const Password& password ) { - Q_UNUSED(serverPort); - Q_UNUSED(password); + Q_UNUSED(serverPort) + Q_UNUSED(password) QEventLoop().exec(); + + return true; } @@ -84,7 +86,7 @@ int ExternalVncServer::configuredServerPort() -QString ExternalVncServer::configuredPassword() +ExternalVncServer::Password ExternalVncServer::configuredPassword() { return m_configuration.password().plainText(); } diff --git a/plugins/vncserver/external/ExternalVncServer.h b/plugins/vncserver/external/ExternalVncServer.h index 5d28c3e93..024603fe9 100644 --- a/plugins/vncserver/external/ExternalVncServer.h +++ b/plugins/vncserver/external/ExternalVncServer.h @@ -1,7 +1,7 @@ /* * ExternalVncServer.h - declaration of ExternalVncServer class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -38,7 +38,7 @@ class ExternalVncServer : public QObject, VncServerPluginInterface, PluginInterf Plugin::Uid uid() const override { - return QStringLiteral("67dfc1c1-8f37-4539-a298-16e74e34fd8b"); + return Plugin::Uid{ QStringLiteral("67dfc1c1-8f37-4539-a298-16e74e34fd8b") }; } QVersionNumber version() const override @@ -71,17 +71,22 @@ class ExternalVncServer : public QObject, VncServerPluginInterface, PluginInterf return Plugin::NoFlags; } + QStringList supportedSessionTypes() const override + { + return {}; + } + void upgrade( const QVersionNumber& oldVersion ) override; QWidget* configurationWidget() override; void prepareServer() override; - void runServer( int serverPort, const QString& password ) override; + bool runServer( int serverPort, const Password& password ) override; int configuredServerPort() override; - QString configuredPassword() override; + Password configuredPassword() override; private: enum { diff --git a/plugins/vncserver/external/ExternalVncServerConfiguration.h b/plugins/vncserver/external/ExternalVncServerConfiguration.h index 915b70652..250544871 100644 --- a/plugins/vncserver/external/ExternalVncServerConfiguration.h +++ b/plugins/vncserver/external/ExternalVncServerConfiguration.h @@ -1,7 +1,7 @@ /* * ExternalVncServerConfiguration.h - configuration values for external VNC server * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -30,4 +30,6 @@ OP( ExternalVncServerConfiguration, m_configuration, int, serverPort, setServerPort, "ServerPort", "ExternalVncServer", 5900, Configuration::Property::Flag::Standard ) \ OP( ExternalVncServerConfiguration, m_configuration, Configuration::Password, password, setPassword, "Password", "ExternalVncServer", QString(), Configuration::Property::Flag::Standard ) +// clazy:excludeall=missing-qobject-macro + DECLARE_CONFIG_PROXY(ExternalVncServerConfiguration, FOREACH_EXTERNAL_VNC_SERVER_CONFIG_PROPERTY) diff --git a/plugins/vncserver/external/ExternalVncServerConfigurationWidget.cpp b/plugins/vncserver/external/ExternalVncServerConfigurationWidget.cpp index 1a4768d6c..7027d0214 100644 --- a/plugins/vncserver/external/ExternalVncServerConfigurationWidget.cpp +++ b/plugins/vncserver/external/ExternalVncServerConfigurationWidget.cpp @@ -1,7 +1,7 @@ /* * ExternalVncServerConfigurationWidget.h - implementation of the ExternalVncServerConfigurationWidget class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/plugins/vncserver/external/ExternalVncServerConfigurationWidget.h b/plugins/vncserver/external/ExternalVncServerConfigurationWidget.h index 91c149c5a..bdf0da7c1 100644 --- a/plugins/vncserver/external/ExternalVncServerConfigurationWidget.h +++ b/plugins/vncserver/external/ExternalVncServerConfigurationWidget.h @@ -1,7 +1,7 @@ /* * ExternalVncServerConfigurationWidget.h - header for the ExternalVncServerConfigurationWidget class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/plugins/vncserver/headless/CMakeLists.txt b/plugins/vncserver/headless/CMakeLists.txt new file mode 100644 index 000000000..ea6ed5151 --- /dev/null +++ b/plugins/vncserver/headless/CMakeLists.txt @@ -0,0 +1,20 @@ +include(BuildVeyonPlugin) + +get_property(HAVE_LIBVNCCLIENT GLOBAL PROPERTY HAVE_LIBVNCCLIENT) +if(HAVE_LIBVNCCLIENT) + find_package(LibVNCServer 0.9.8) +endif() + +if(LibVNCServer_FOUND) + + build_veyon_plugin(headless-vnc-server + HeadlessVncServer.cpp + HeadlessVncServer.h + HeadlessVncConfiguration.h + ) + + target_link_libraries(headless-vnc-server PRIVATE LibVNC::LibVNCServer) + + target_compile_options(headless-vnc-server PRIVATE -Wno-parentheses) + +endif() diff --git a/plugins/vncserver/headless/HeadlessVncConfiguration.h b/plugins/vncserver/headless/HeadlessVncConfiguration.h new file mode 100644 index 000000000..1038c4d15 --- /dev/null +++ b/plugins/vncserver/headless/HeadlessVncConfiguration.h @@ -0,0 +1,34 @@ +/* + * HeadlessVncConfiguration.h - headless VNC server specific configuration values + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +#include "Configuration/Proxy.h" + +#define FOREACH_HEADLESS_VNC_CONFIG_PROPERTY(OP) \ + OP( HeadlessVncConfiguration, m_configuration, QColor, backgroundColor, setBackgroundColor, "BackgroundColor", "HeadlessVncServer", QColor(QStringLiteral("#198cb3")), Configuration::Property::Flag::Advanced ) + +DECLARE_CONFIG_PROXY(HeadlessVncConfiguration, FOREACH_HEADLESS_VNC_CONFIG_PROPERTY) diff --git a/plugins/vncserver/headless/HeadlessVncServer.cpp b/plugins/vncserver/headless/HeadlessVncServer.cpp new file mode 100644 index 000000000..5cdc23a4d --- /dev/null +++ b/plugins/vncserver/headless/HeadlessVncServer.cpp @@ -0,0 +1,187 @@ +/* + * HeadlessVncServer.cpp - implementation of HeadlessVncServer class + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +extern "C" { +#include "rfb/rfb.h" +} + +#include + +#include + +#include "HeadlessVncServer.h" +#include "VeyonConfiguration.h" + + +struct HeadlessVncScreen +{ + ~HeadlessVncScreen() + { + delete[] passwords[0]; + } + + rfbScreenInfoPtr rfbScreen{nullptr}; + std::array passwords{}; + QImage framebuffer; + +}; + + +HeadlessVncServer::HeadlessVncServer( QObject* parent ) : + QObject( parent ), + m_configuration( &VeyonCore::config() ) +{ +} + + + +void HeadlessVncServer::prepareServer() +{ +} + + + +bool HeadlessVncServer::runServer( int serverPort, const Password& password ) +{ + if (VeyonCore::isDebugging()) + { + rfbLog = rfbLogDebug; + rfbErr = rfbLogDebug; + } + else + { + rfbLog = rfbLogNone; + rfbErr = rfbLogNone; + } + + HeadlessVncScreen screen; + + if( initScreen( &screen ) == false || + initVncServer( serverPort, password, &screen ) == false ) + { + return false; + } + + while( true ) + { + QThread::msleep( DefaultSleepTime ); + + rfbProcessEvents( screen.rfbScreen, 0 ); + } + + rfbShutdownServer( screen.rfbScreen, true ); + rfbScreenCleanup( screen.rfbScreen ); + + return true; +} + + + +bool HeadlessVncServer::initScreen( HeadlessVncScreen* screen ) +{ + screen->framebuffer = QImage( DefaultFramebufferWidth, DefaultFramebufferHeight, QImage::Format_RGB32 ); + screen->framebuffer.fill( m_configuration.backgroundColor() ); + + return true; +} + + + +bool HeadlessVncServer::initVncServer( int serverPort, const VncServerPluginInterface::Password& password, + HeadlessVncScreen* screen ) +{ + auto rfbScreen = rfbGetScreen( nullptr, nullptr, + screen->framebuffer.width(), screen->framebuffer.height(), + 8, 3, 4 ); + + if( rfbScreen == nullptr ) + { + return false; + } + + screen->passwords[0] = qstrdup( password.toByteArray().constData() ); + + rfbScreen->desktopName = "VeyonVNC"; + rfbScreen->frameBuffer = reinterpret_cast( screen->framebuffer.bits() ); + rfbScreen->port = serverPort; + rfbScreen->ipv6port = serverPort; + + rfbScreen->authPasswdData = screen->passwords.data(); + rfbScreen->passwordCheck = rfbCheckPasswordByList; + + rfbScreen->serverFormat.redShift = 16; + rfbScreen->serverFormat.greenShift = 8; + rfbScreen->serverFormat.blueShift = 0; + + rfbScreen->serverFormat.redMax = 255; + rfbScreen->serverFormat.greenMax = 255; + rfbScreen->serverFormat.blueMax = 255; + + rfbScreen->serverFormat.trueColour = true; + rfbScreen->serverFormat.bitsPerPixel = 32; + + rfbScreen->alwaysShared = true; + rfbScreen->handleEventsEagerly = true; + rfbScreen->deferUpdateTime = 5; + + rfbScreen->screenData = screen; + + rfbScreen->cursor = nullptr; + + rfbInitServer( rfbScreen ); + + rfbMarkRectAsModified( rfbScreen, 0, 0, rfbScreen->width, rfbScreen->height ); + + screen->rfbScreen = rfbScreen; + + return true; +} + + + +void HeadlessVncServer::rfbLogDebug(const char* format, ...) +{ + va_list args; + va_start(args, format); + + static constexpr int MaxMessageLength = 256; + char message[MaxMessageLength]; + + vsnprintf(message, sizeof(message), format, args); + message[MaxMessageLength-1] = 0; + + va_end(args); + + vDebug() << message; +} + + + +void HeadlessVncServer::rfbLogNone(const char* format, ...) +{ + Q_UNUSED(format); +} + + +IMPLEMENT_CONFIG_PROXY(HeadlessVncConfiguration) diff --git a/plugins/vncserver/headless/HeadlessVncServer.h b/plugins/vncserver/headless/HeadlessVncServer.h new file mode 100644 index 000000000..59d70bb9b --- /dev/null +++ b/plugins/vncserver/headless/HeadlessVncServer.h @@ -0,0 +1,116 @@ +/* + * HeadlessVncServer.h - declaration of HeadlessVncServer class + * + * Copyright (c) 2020-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include "PluginInterface.h" +#include "VncServerPluginInterface.h" +#include "HeadlessVncConfiguration.h" + +struct HeadlessVncScreen; + +class HeadlessVncServer : public QObject, VncServerPluginInterface, PluginInterface +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "io.veyon.Veyon.Plugins.HeadlessVncServer") + Q_INTERFACES(PluginInterface VncServerPluginInterface) +public: + explicit HeadlessVncServer( QObject* parent = nullptr ); + + Plugin::Uid uid() const override + { + return Plugin::Uid{ QStringLiteral("f626f759-7691-45c0-bd4a-37171d98d219") }; + } + + QVersionNumber version() const override + { + return QVersionNumber( 1, 0 ); + } + + QString name() const override + { + return QStringLiteral( "HeadlessVncServer" ); + } + + QString description() const override + { + return tr( "Headless VNC server" ); + } + + QString vendor() const override + { + return QStringLiteral( "Veyon Community" ); + } + + QString copyright() const override + { + return QStringLiteral( "Tobias Junghans" ); + } + + Plugin::Flags flags() const override + { + return Plugin::NoFlags; + } + + virtual QStringList supportedSessionTypes() const override + { + return {}; + } + + QWidget* configurationWidget() override + { + return nullptr; + } + + void prepareServer() override; + + bool runServer( int serverPort, const Password& password ) override; + + int configuredServerPort() override + { + return -1; + } + + Password configuredPassword() override + { + return {}; + } + +private: + static constexpr auto DefaultFramebufferWidth = 640; + static constexpr auto DefaultFramebufferHeight = 480; + static constexpr auto DefaultSleepTime = 25; + + bool initScreen( HeadlessVncScreen* screen ); + bool initVncServer( int serverPort, const VncServerPluginInterface::Password& password, + HeadlessVncScreen* screen ); + + bool handleScreenChanges( HeadlessVncScreen* screen ); + + static void rfbLogDebug(const char* format, ...); + static void rfbLogNone(const char* format, ...); + + HeadlessVncConfiguration m_configuration; + +}; diff --git a/plugins/vncserver/ultravnc-builtin/BuiltinUltraVncServer.cpp b/plugins/vncserver/ultravnc-builtin/BuiltinUltraVncServer.cpp index 36289611b..32e4810a8 100644 --- a/plugins/vncserver/ultravnc-builtin/BuiltinUltraVncServer.cpp +++ b/plugins/vncserver/ultravnc-builtin/BuiltinUltraVncServer.cpp @@ -1,7 +1,7 @@ /* * BuiltinUltraVncServer.cpp - implementation of BuiltinUltraVncServer class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -30,11 +30,11 @@ #include "UltraVncConfigurationWidget.h" #include "VeyonConfiguration.h" -extern int WinVNCAppMain(); +int WinVNCAppMain(); +void initUltraVncSettingsManager(); static BuiltinUltraVncServer* vncServerInstance = nullptr; -extern BOOL multi; extern HINSTANCE hAppInstance; extern DWORD mainthreadId; extern HINSTANCE hInstResDLL; @@ -42,11 +42,11 @@ extern HINSTANCE hInstResDLL; void ultravnc_veyon_load_password( char* out, int size ) { - const auto password = vncServerInstance->password().toUtf8(); + const auto password = vncServerInstance->password().toByteArray(); if( password.size() == size ) { - memcpy( out, password.constData(), size ); // Flawfinder: ignore + memcpy( out, password.constData(), static_cast( size ) ); // Flawfinder: ignore } else { @@ -56,7 +56,7 @@ void ultravnc_veyon_load_password( char* out, int size ) -BOOL ultravnc_veyon_load_int( LPCSTR valname, LONG *out ) +BOOL ultravnc_veyon_load_int( LPCSTR valname, int *out ) { if( strcmp( valname, "LoopbackOnly" ) == 0 ) { @@ -93,6 +93,11 @@ BOOL ultravnc_veyon_load_int( LPCSTR valname, LONG *out ) *out = vncServerInstance->configuration().ultraVncDeskDupEngineEnabled() ? 1 : 0; return true; } + if( strcmp( valname, "MaxCpu2" ) == 0 ) + { + *out = vncServerInstance->configuration().ultraVncMaxCpu(); + return true; + } if( strcmp( valname, "NewMSLogon" ) == 0 ) { *out = 0; @@ -195,33 +200,47 @@ void BuiltinUltraVncServer::prepareServer() -void BuiltinUltraVncServer::runServer( int serverPort, const QString& password ) +bool BuiltinUltraVncServer::runServer( int serverPort, const Password& password ) { m_serverPort = serverPort; m_password = password; - // only allow multiple instances when explicitely working with multiple - // service instances - if( VeyonCore::hasSessionId() ) + initUltraVncSettingsManager(); + + // run UltraVNC server + auto hUser32 = LoadLibrary( "user32.dll" ); + auto hSHCore = LoadLibrary( "SHCore.dll" ); + + using SetProcessDpiAwarenessFunc = HRESULT (WINAPI *)( DWORD ); + const auto setProcessDpiAwareness = + hSHCore ? SetProcessDpiAwarenessFunc( GetProcAddress( hSHCore, "SetProcessDpiAwareness" ) ) : nullptr; + + if( setProcessDpiAwareness ) { - multi = true; + static constexpr DWORD PROCESS_PER_MONITOR_DPI_AWARE = 2; + setProcessDpiAwareness( PROCESS_PER_MONITOR_DPI_AWARE ); } - - // run winvnc-server - HMODULE hUser32 = LoadLibrary( "user32.dll" ); - using SetProcessDPIAwareFunc = BOOL (*)(); - SetProcessDPIAwareFunc setDPIAware = nullptr; - if( hUser32 ) + else if( hUser32 ) { - setDPIAware = reinterpret_cast( GetProcAddress( hUser32, "SetProcessDPIAware" ) ); + using SetProcessDPIAwareFunc = BOOL (*)(); + const auto setDPIAware = SetProcessDPIAwareFunc( GetProcAddress( hUser32, "SetProcessDPIAware" ) ); if( setDPIAware ) { setDPIAware(); } + } + + if( hUser32 ) + { FreeLibrary( hUser32 ); } - WinVNCAppMain(); + if( hSHCore ) + { + FreeLibrary( hSHCore ); + } + + return WinVNCAppMain() == 1; } diff --git a/plugins/vncserver/ultravnc-builtin/BuiltinUltraVncServer.h b/plugins/vncserver/ultravnc-builtin/BuiltinUltraVncServer.h index 187c27c54..09d956515 100644 --- a/plugins/vncserver/ultravnc-builtin/BuiltinUltraVncServer.h +++ b/plugins/vncserver/ultravnc-builtin/BuiltinUltraVncServer.h @@ -1,7 +1,7 @@ /* * BuiltinUltraVncServer.h - declaration of BuiltinUltraVncServer class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -40,7 +40,7 @@ class BuiltinUltraVncServer : public QObject, VncServerPluginInterface, PluginIn Plugin::Uid uid() const override { - return QStringLiteral("39d7a07f-94db-4912-aa1a-c4df8aee3879"); + return Plugin::Uid{ QStringLiteral("39d7a07f-94db-4912-aa1a-c4df8aee3879") }; } QVersionNumber version() const override @@ -73,18 +73,23 @@ class BuiltinUltraVncServer : public QObject, VncServerPluginInterface, PluginIn return Plugin::ProvidesDefaultImplementation; } + QStringList supportedSessionTypes() const override + { + return { QStringLiteral("console"), QStringLiteral("rdp") }; + } + QWidget* configurationWidget() override; void prepareServer() override; - void runServer( int serverPort, const QString& password ) override; + bool runServer( int serverPort, const Password& password ) override; int configuredServerPort() override { return -1; } - QString configuredPassword() override + Password configuredPassword() override { return {}; } @@ -99,7 +104,7 @@ class BuiltinUltraVncServer : public QObject, VncServerPluginInterface, PluginIn return m_serverPort; } - const QString& password() const + const Password& password() const { return m_password; } @@ -110,7 +115,7 @@ class BuiltinUltraVncServer : public QObject, VncServerPluginInterface, PluginIn static constexpr auto DefaultServerPort = 5900; int m_serverPort; - QString m_password; + Password m_password; LogoffEventFilter* m_logoffEventFilter; diff --git a/plugins/vncserver/ultravnc-builtin/CMakeLists.txt b/plugins/vncserver/ultravnc-builtin/CMakeLists.txt index 5cd56dc05..4a212fc7e 100644 --- a/plugins/vncserver/ultravnc-builtin/CMakeLists.txt +++ b/plugins/vncserver/ultravnc-builtin/CMakeLists.txt @@ -1,90 +1,114 @@ -ADD_SUBDIRECTORY(vnchooks) +remove_definitions(-DUNICODE -D_UNICODE) -INCLUDE(BuildPlugin) +add_subdirectory(vnchooks) -INCLUDE_DIRECTORIES( - ${ultravnc_DIR} - ${ultravnc_DIR}/winvnc - ${ultravnc_DIR}/winvnc/omnithread - ${ultravnc_DIR}/winvnc/winvnc - ) +include(BuildVeyonPlugin) + +find_package(ZLIB REQUIRED) +find_package(JPEG REQUIRED) +find_package(LZO REQUIRED) -SET(ultravnc_SOURCES +set(ultravnc_CXX_SOURCES + ${ultravnc_DIR}/common/Clipboard.cpp + ${ultravnc_DIR}/common/inifile.cpp + ${ultravnc_DIR}/common/UltraVncZ.cpp + ${ultravnc_DIR}/common/win32_helpers.cpp + ${ultravnc_DIR}/rdr/ZlibInStream.cxx + ${ultravnc_DIR}/rdr/ZlibOutStream.cxx + ${ultravnc_DIR}/rfb/dh.cpp + ${ultravnc_DIR}/omnithread/nt.cpp + ${ultravnc_DIR}/winvnc/winvnc/benchmark.cpp + ${ultravnc_DIR}/winvnc/winvnc/buildtime.cpp + ${ultravnc_DIR}/winvnc/winvnc/CpuUsage.cpp + ${ultravnc_DIR}/winvnc/winvnc/credentials.cpp + ${ultravnc_DIR}/winvnc/winvnc/DeskdupEngine.cpp + ${ultravnc_DIR}/winvnc/winvnc/HelperFunctions.cpp ${ultravnc_DIR}/winvnc/winvnc/HideDesktop.cpp - ${ultravnc_DIR}/winvnc/winvnc/rfbRegion_win32.cpp - ${ultravnc_DIR}/winvnc/winvnc/vistahook.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncdesktopthread.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncdesktopsink.cpp ${ultravnc_DIR}/winvnc/winvnc/IPC.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncencoderre.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncdesktop.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncserver.cpp + ${ultravnc_DIR}/winvnc/winvnc/MouseSimulator.cpp + ${ultravnc_DIR}/winvnc/winvnc/rfbRegion_win32.cpp ${ultravnc_DIR}/winvnc/winvnc/rfbUpdateTracker.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncencodehext.cpp - ${ultravnc_DIR}/winvnc/winvnc/d3des.c - ${ultravnc_DIR}/winvnc/winvnc/vncproperties.cpp - ${ultravnc_DIR}/winvnc/winvnc/security.cpp - ${ultravnc_DIR}/winvnc/winvnc/buildtime.cpp + ${ultravnc_DIR}/winvnc/winvnc/ScreenCapture.cpp + ${ultravnc_DIR}/winvnc/winvnc/SettingsManager.cpp + ${ultravnc_DIR}/winvnc/winvnc/stdhdrs.cpp ${ultravnc_DIR}/winvnc/winvnc/Timer.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncencoderCursor.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncencoder.cpp - ${ultravnc_DIR}/winvnc/winvnc/vnclog.cpp ${ultravnc_DIR}/winvnc/winvnc/translate.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncencodecorre.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncencodezrle.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncEncodeTight.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncservice.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncMultiMonitor.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncbuffer.cpp + ${ultravnc_DIR}/winvnc/winvnc/uvncUiAccess.cpp ${ultravnc_DIR}/winvnc/winvnc/videodrivercheck.cpp ${ultravnc_DIR}/winvnc/winvnc/videodriver.cpp + ${ultravnc_DIR}/winvnc/winvnc/vistahook.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncbuffer.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncclient.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncdesktop.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncdesktopsink.cpp ${ultravnc_DIR}/winvnc/winvnc/vncDesktopSW.cpp - ${ultravnc_DIR}/winvnc/winvnc/vnckeymap.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncOSVersion.cpp - ${ultravnc_DIR}/winvnc/winvnc/winvnc.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncauth.c - ${ultravnc_DIR}/winvnc/winvnc/stdhdrs.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncEncodeUltra.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncdesktopthread.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncencodecorre.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncencodehext.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncencoder.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncencoderCursor.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncencoderre.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncEncodeTight.cpp ${ultravnc_DIR}/winvnc/winvnc/vncEncodeUltra2.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncsockconnect.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncinsthandler.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncEncodeUltra.cpp ${ultravnc_DIR}/winvnc/winvnc/vncEncodeZlib.cpp ${ultravnc_DIR}/winvnc/winvnc/vncEncodeZlibHex.cpp - ${ultravnc_DIR}/winvnc/winvnc/vncpropertiesPoll.cpp - ${ultravnc_DIR}/winvnc/winvnc/helpers.cpp - ${ultravnc_DIR}/winvnc/winvnc/CpuUsage.cpp - ${ultravnc_DIR}/winvnc/winvnc/uvncUiAccess.cpp - ${ultravnc_DIR}/winvnc/winvnc/ScreenCapture.cpp - ${ultravnc_DIR}/winvnc/winvnc/DeskdupEngine.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncencodezrle.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncinsthandler.cpp + ${ultravnc_DIR}/winvnc/winvnc/vnckeymap.cpp + ${ultravnc_DIR}/winvnc/winvnc/vnclog.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncMultiMonitor.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncOSVersion.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncserver.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncsetauth.cpp + ${ultravnc_DIR}/winvnc/winvnc/vncsockconnect.cpp ${ultravnc_DIR}/winvnc/winvnc/vsocket.cpp - ${ultravnc_DIR}/winvnc/omnithread/nt.cpp - ${ultravnc_DIR}/common/Clipboard.cpp - ${ultravnc_DIR}/common/win32_helpers.cpp - ${ultravnc_DIR}/rfb/dh.cpp - ${ultravnc_DIR}/rdr/ZlibOutStream.cxx - ${ultravnc_DIR}/rdr/ZlibInStream.cxx - ultravnc.cpp - vncntlm.cpp + ${ultravnc_DIR}/winvnc/winvnc/winvnc.cpp ) -ADD_DEFINITIONS(-DULTRAVNC_VEYON_SUPPORT -D_INTERNALLIB -D_WIN32_WINNT=0x0600) - -IF(VEYON_BUILD_WIN64) - ADD_DEFINITIONS(-D_X64) -ENDIF(VEYON_BUILD_WIN64) +set(ultravnc_C_SOURCES + ${ultravnc_DIR}/common/d3des.c + ${ultravnc_DIR}/winvnc/winvnc/vncauth.c + ) +set(WITH_PCH OFF) -BUILD_PLUGIN(builtin-ultravnc-server +build_veyon_plugin(builtin-ultravnc-server BuiltinUltraVncServer.cpp LogoffEventFilter.cpp UltraVncConfigurationWidget.cpp UltraVncConfigurationWidget.ui - ${ultravnc_SOURCES} + ${ultravnc_C_SOURCES} + ${ultravnc_CXX_SOURCES} BuiltinUltraVncServer.h LogoffEventFilter.h UltraVncConfigurationWidget.h UltraVncConfiguration.h + ) + +target_link_libraries(builtin-ultravnc-server PRIVATE -lws2_32 -luserenv -lole32 -lversion -lgdi32 -limm32 -lwinmm ${ZLIB_LIBRARIES} ${JPEG_LIBRARIES} ${LZO_LIBRARIES}) +target_include_directories(builtin-ultravnc-server PRIVATE + ${ultravnc_DIR} + ${ultravnc_DIR}/common + ${ultravnc_DIR}/omnithread + ${ultravnc_DIR}/winvnc + ${ultravnc_DIR}/winvnc/winvnc + ) + +target_compile_definitions(builtin-ultravnc-server PRIVATE + ULTRAVNC_VEYON_SUPPORT + _VCPKG + _INTERNALLIB + _USE_DESKTOPDUPLICATION ) -TARGET_LINK_LIBRARIES(builtin-ultravnc-server -luserenv -lole32 -lversion -lgdi32 -limm32 -lwinmm) -SET_SOURCE_FILES_PROPERTIES(${ultravnc_SOURCES} PROPERTIES COMPILE_FLAGS "-Wno-comments -Wno-attributes -Wno-terminate -Wno-write-strings -Wno-parentheses -Wno-misleading-indentation -Wno-unused-result -Wno-unused-label -Wno-unknown-pragmas -Wno-unused-variable -Wno-unused-but-set-variable -Wno-deprecated-declarations -Wno-conversion-null -Wno-format-zero-length -Wno-sign-compare -fexceptions") +if(VEYON_BUILD_WIN64) + target_compile_definitions(builtin-ultravnc-server PRIVATE _X64) +endif() + +qt6_disable_unicode_defines(builtin-ultravnc-server) + +set(ULTRAVNC_COMPILER_FLAGS "-Wno-comments -Wno-attributes -Wno-write-strings -Wno-parentheses -Wno-misleading-indentation -Wno-unused-result -Wno-unused-label -Wno-unknown-pragmas -Wno-unused-variable -Wno-unused-value -Wno-unused-but-set-variable -Wno-deprecated-declarations -Wno-format-zero-length -Wno-sign-compare -Wno-int-to-pointer-cast -fexceptions") + +set_source_files_properties(${ultravnc_C_SOURCES} PROPERTIES COMPILE_FLAGS "${ULTRAVNC_COMPILER_FLAGS}") +set_source_files_properties(${ultravnc_CXX_SOURCES} PROPERTIES COMPILE_FLAGS "${ULTRAVNC_COMPILER_FLAGS} -Wno-terminate -Wno-conversion-null") diff --git a/plugins/vncserver/ultravnc-builtin/LogoffEventFilter.cpp b/plugins/vncserver/ultravnc-builtin/LogoffEventFilter.cpp index 3e3aa7550..20f6fd5ad 100644 --- a/plugins/vncserver/ultravnc-builtin/LogoffEventFilter.cpp +++ b/plugins/vncserver/ultravnc-builtin/LogoffEventFilter.cpp @@ -1,7 +1,7 @@ /* * LogoffEventFilter.cpp - implementation of LogoffEventFilter class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -52,16 +52,21 @@ LogoffEventFilter::LogoffEventFilter() : -bool LogoffEventFilter::nativeEventFilter( const QByteArray& eventType, void* message, long* result ) +bool LogoffEventFilter::nativeEventFilter(const QByteArray& eventType, void* message, qintptr* result) { - Q_UNUSED(eventType); - Q_UNUSED(result); + Q_UNUSED(eventType) + Q_UNUSED(result) + + if (!message) + { + return false; + } const auto winMsg = reinterpret_cast( message )->message; - if( winMsg == WM_QUERYENDSESSION ) + if (winMsg == WM_ENDSESSION) { - vInfo() << "Got WM_QUERYENDSESSION - initiating server shutdown"; + vInfo() << "Got WM_ENDSESSION - initiating server shutdown"; // tell UltraVNC server to quit SetEvent( m_shutdownEventHandle ); diff --git a/plugins/vncserver/ultravnc-builtin/LogoffEventFilter.h b/plugins/vncserver/ultravnc-builtin/LogoffEventFilter.h index 98e863658..b5e8512c7 100644 --- a/plugins/vncserver/ultravnc-builtin/LogoffEventFilter.h +++ b/plugins/vncserver/ultravnc-builtin/LogoffEventFilter.h @@ -1,7 +1,7 @@ /* * LogoffEventFilter.h - declaration of LogoffEventFilter class * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -34,7 +34,7 @@ class LogoffEventFilter : public QAbstractNativeEventFilter public: LogoffEventFilter(); - bool nativeEventFilter( const QByteArray& eventType, void* message, long* result) override; + bool nativeEventFilter(const QByteArray& eventType, void* message, qintptr* result) override; private: HANDLE m_shutdownEventHandle; diff --git a/plugins/vncserver/ultravnc-builtin/UltraVncConfiguration.h b/plugins/vncserver/ultravnc-builtin/UltraVncConfiguration.h index 447a10897..93791d23f 100644 --- a/plugins/vncserver/ultravnc-builtin/UltraVncConfiguration.h +++ b/plugins/vncserver/ultravnc-builtin/UltraVncConfiguration.h @@ -1,7 +1,7 @@ /* * UltraVncConfiguration.h - UltraVNC-specific configuration values * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -32,6 +32,7 @@ OP( UltraVncConfiguration, m_configuration, bool, ultraVncPollFullScreen, setUltraVncPollFullScreen, "PollFullScreen", "UltraVNC", true, Configuration::Property::Flag::Advanced ) \ OP( UltraVncConfiguration, m_configuration, bool, ultraVncLowAccuracy, setUltraVncLowAccuracy, "LowAccuracy", "UltraVNC", true, Configuration::Property::Flag::Advanced ) \ OP( UltraVncConfiguration, m_configuration, bool, ultraVncDeskDupEngineEnabled, setUltraVncDeskDupEngineEnabled, "DeskDupEngine", "UltraVNC", true, Configuration::Property::Flag::Advanced ) \ + OP( UltraVncConfiguration, m_configuration, int, ultraVncMaxCpu, setUltraVncMaxCpu, "MaxCPU", "UltraVNC", 100, Configuration::Property::Flag::Advanced ) \ DECLARE_CONFIG_PROXY(UltraVncConfiguration, FOREACH_ULTRAVNC_CONFIG_PROPERTY) diff --git a/plugins/vncserver/ultravnc-builtin/UltraVncConfigurationWidget.cpp b/plugins/vncserver/ultravnc-builtin/UltraVncConfigurationWidget.cpp index b1eb03b1a..d0f191812 100644 --- a/plugins/vncserver/ultravnc-builtin/UltraVncConfigurationWidget.cpp +++ b/plugins/vncserver/ultravnc-builtin/UltraVncConfigurationWidget.cpp @@ -1,7 +1,7 @@ /* * UltraVncConfigurationWidget.h - implementation of the UltraVncConfigurationWidget class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -35,6 +35,9 @@ UltraVncConfigurationWidget::UltraVncConfigurationWidget( UltraVncConfiguration& { ui->setupUi( this ); + Configuration::UiMapping::setFlags( ui->ultraVncMaxCpu, Configuration::Property::Flag::Advanced ); + Configuration::UiMapping::setFlags( ui->ultraVncMaxCpuLabel, Configuration::Property::Flag::Advanced ); + FOREACH_ULTRAVNC_CONFIG_PROPERTY(INIT_WIDGET_FROM_PROPERTY); FOREACH_ULTRAVNC_CONFIG_PROPERTY(CONNECT_WIDGET_TO_PROPERTY); } diff --git a/plugins/vncserver/ultravnc-builtin/UltraVncConfigurationWidget.h b/plugins/vncserver/ultravnc-builtin/UltraVncConfigurationWidget.h index 562543b06..2110b023b 100644 --- a/plugins/vncserver/ultravnc-builtin/UltraVncConfigurationWidget.h +++ b/plugins/vncserver/ultravnc-builtin/UltraVncConfigurationWidget.h @@ -1,7 +1,7 @@ /* * UltraVncConfigurationWidget.h - header for the UltraVncConfigurationWidget class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/plugins/vncserver/ultravnc-builtin/UltraVncConfigurationWidget.ui b/plugins/vncserver/ultravnc-builtin/UltraVncConfigurationWidget.ui index a219d302c..c862e5fb0 100644 --- a/plugins/vncserver/ultravnc-builtin/UltraVncConfigurationWidget.ui +++ b/plugins/vncserver/ultravnc-builtin/UltraVncConfigurationWidget.ui @@ -18,41 +18,61 @@ 0 - - + + - Poll full screen (leave this enabled per default) + Maximum CPU usage - - - - Enable multi monitor support + + + + % + + + 10 + + + 100 - - + + - Enable capturing of layered (semi-transparent) windows + Low accuracy (turbo mode) - - + + - Low accuracy (turbo mode) + Poll full screen (leave this enabled per default) - + Enable Desktop Duplication Engine on Windows 8 and newer + + + + Enable multi monitor support + + + + + + + Enable capturing of layered (semi-transparent) windows + + + diff --git a/plugins/vncserver/ultravnc-builtin/ultravnc-rfbproto.h b/plugins/vncserver/ultravnc-builtin/ultravnc-rfbproto.h deleted file mode 100644 index 0d49db51f..000000000 --- a/plugins/vncserver/ultravnc-builtin/ultravnc-rfbproto.h +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once - -#define KEEPALIVE_HEADROOM 1 -#define KEEPALIVE_INTERVAL 5 -#define FT_RECV_TIMEOUT 30 - -// adzm 2010-08 -#define SOCKET_KEEPALIVE_TIMEOUT 10000 -#define SOCKET_KEEPALIVE_INTERVAL 1000 - -#define rfbEncodingUltra2 10 - -// adzm - 2010-07 - Extended clipboard support -// this struct is used as the data within an rfbServerCutTextMsg or rfbClientCutTextMsg. -typedef struct { - uint32_t flags; // see rfbExtendedClipboardDataFlags - - // followed by unsigned char data[(rfbServerCutTextMsg|rfbClientCutTextMsg).length - sz_rfbExtendedClipboardData] -} rfbExtendedClipboardData; - -#define sz_rfbExtendedClipboardData 4 - -typedef enum { - // formats - clipText = 0x00000001, // Unicode text (UTF-8 encoding) - clipRTF = 0x00000002, // Microsoft RTF format - clipHTML = 0x00000004, // Microsoft HTML clipboard format - clipDIB = 0x00000008, // Microsoft DIBv5 - // line endings are not touched and remain as \r\n for Windows machines. Terminating NULL characters are preserved. - - // Complex formats - // These formats should also have 3 more CARD32 values after rfbExtendedClipboardData.flags. This will allow them - // to set up more complex messages (such as preview) or subformats (such as lossless, png, jpeg, lossy) etc. - // The rest should follow the standard format of a 32-bit length of the uncompressed data, followed by the data. - // - // Please note none of these are implemented yet, but seem obvious enough that their values are reserved here - // for posterity. - clipFiles = 0x00000010, // probably also more than one file - clipFormatMask = 0x0000FFFF, - - // reserved - clipReservedMask= 0x00FF0000, // more than likely will be used for more formats, but may be used for more actions - // or remain unused for years to come. - - // actions - clipCaps = 0x01000000, // which formats are supported / desired. - // Message data should include limits on maximum automatic uncompressed data size for each format - // in 32-bit values (in order of enum value). If the data exceeds that value, it must be requested. - // This can be used to disable the clipboard entirely by setting no supported formats, or to - // only enable manual clipboard transfers by setting the maximum sizes to 0. - // can be combined with other actions to denote actions that are supported - // The server must send this to the client to notify that it understands the new clipboard format. - // The client may respond with its own clipCaps; otherwise the server should use the defaults. - // Currently, the defaults are the messages and formats defined in this initial implementation - // that are common to both server and viewer: - // clipCaps | clipRequest | clipProvide | (clipNotify if viewer, clipPeek if server) - // clipText | clipRTF | clipHTML | clipDIB - // (Note that clipNotify is only relevant from server->viewer, and clipPeek is only relevant - // from viewer->server. Therefore they are left out of the defaults but can be set with the - // rest of the caps if desired.) - // It is also strongly recommended to set up maximum sizes for the formats since currently - // the data is sent synchronously and cannot be interrupted. If data exceeds the maximum size, - // then the server should send the clipNotify so the client may send clipRequest. Current default - // limits were somewhat arbitrarily chosen as 2mb (10mb for text) and 0 for image - // Note that these limits are referring to the length of uncompressed data. - clipRequest = 0x02000000, // request clipboard data (should be combined with desired formats) - // Message should be empty - // Response should be a clipProvide message with appropriate formats. This should ignore any - // maximum size limitations specified in clipCaps. - clipPeek = 0x04000000, // Peek at what is currently available in the clipboard. - // Message should be empty - // Respond with clipNotify including all available formats in the flags - clipNotify = 0x08000000, // notify that the formats combined with the flags are available for transfer. - // Message should be empty - // When a clipProvide message is received, then all formats notified as being available are - // invalidated. Therefore, when implementing, ensure that clipProvide messages are sent before - // clipNotify messages, specifically when in response to a change in the clipboard - clipProvide = 0x10000000, // send clipboard data (should be combined with sent formats) - // All message data including the length is compressed by a single zlib stream. - // First is the 32-bit length of the uncompressed data, followed by the data itself - // Repeat for each format listed in order of enum value - // Invalidate any formats that were notified as being available. - clipActionMask = 0xFF000000, - - clipInvalid = 0xFFFFFFFF, - -} rfbExtendedClipboardDataFlags; - - diff --git a/plugins/vncserver/ultravnc-builtin/ultravnc.cpp b/plugins/vncserver/ultravnc-builtin/ultravnc.cpp deleted file mode 100644 index 628c5998a..000000000 --- a/plugins/vncserver/ultravnc-builtin/ultravnc.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "stdhdrs.h" - -#define rfbConnFailed 0 -#define rfbInvalidAuth 0 -#define rfbNoAuth 1 -#define rfbVncAuth 2 -#define rfbUltraVNC 17 - -#define rfbVncAuthOK 0 -#define rfbVncAuthFailed 1 - -// adzm 2010-09 - rfbUltraVNC or other auths may send this to restart authentication (perhaps over a now-secure channel) -#define rfbVncAuthContinue 0xFFFFFFFF - -#include "vncclient.cpp" - -extern bool G_USE_PIXEL; - -bool G_USE_PIXEL = false; diff --git a/plugins/vncserver/ultravnc-builtin/vnchooks/CMakeLists.txt b/plugins/vncserver/ultravnc-builtin/vnchooks/CMakeLists.txt index c7b9b92ef..5d08707f0 100644 --- a/plugins/vncserver/ultravnc-builtin/vnchooks/CMakeLists.txt +++ b/plugins/vncserver/ultravnc-builtin/vnchooks/CMakeLists.txt @@ -1,16 +1,14 @@ -SET(VH_WINRC "${CMAKE_CURRENT_BINARY_DIR}/vnchooksrc.obj") -ADD_CUSTOM_COMMAND(OUTPUT ${VH_WINRC} - COMMAND ${WINDRES} - -I${CMAKE_CURRENT_SOURCE_DIR} - -o${VH_WINRC} - -i${ultravnc_DIR}/winvnc/vnchooks/vnchooks.rc) +set(vnchooks_SOURCES + ${ultravnc_DIR}/winvnc/vnchooks/VNCHooks.cpp + ${ultravnc_DIR}/winvnc/vnchooks/SharedData.cpp + ${ultravnc_DIR}/winvnc/vnchooks/vnchooks.rc +) -ADD_LIBRARY(vnchooks MODULE - ${ultravnc_DIR}/winvnc/vnchooks/VNCHooks.cpp - ${ultravnc_DIR}/winvnc/vnchooks/SharedData.cpp - ${VH_WINRC}) -SET_TARGET_PROPERTIES(vnchooks PROPERTIES PREFIX "") -SET_TARGET_PROPERTIES(vnchooks PROPERTIES COMPILE_FLAGS "-Wno-write-strings -Wno-unused-variable -Wno-unknown-pragmas") -SET_TARGET_PROPERTIES(vnchooks PROPERTIES LINK_FLAGS -Wl,-export-all-symbols) -TARGET_LINK_LIBRARIES(vnchooks -ladvapi32) +add_library(vnchooks MODULE ${vnchooks_SOURCES}) +set_source_files_properties(${vnchooks_SOURCES} PROPERTIES SKIP_UNITY_BUILD_INCLUSION TRUE) +set_default_target_properties(vnchooks) +set_target_properties(vnchooks PROPERTIES PREFIX "") +set_target_properties(vnchooks PROPERTIES COMPILE_FLAGS "-Wno-write-strings -Wno-unused-variable -Wno-unknown-pragmas -Wno-int-to-pointer-cast") +set_target_properties(vnchooks PROPERTIES LINK_FLAGS -Wl,-export-all-symbols) +target_link_libraries(vnchooks PRIVATE -ladvapi32) diff --git a/plugins/vncserver/x11vnc-builtin/BuiltinX11VncServer.cpp b/plugins/vncserver/x11vnc-builtin/BuiltinX11VncServer.cpp index f0ba0150b..c8e585024 100644 --- a/plugins/vncserver/x11vnc-builtin/BuiltinX11VncServer.cpp +++ b/plugins/vncserver/x11vnc-builtin/BuiltinX11VncServer.cpp @@ -1,7 +1,7 @@ /* * BuiltinX11VncServer.cpp - implementation of BuiltinX11VncServer class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -32,6 +32,7 @@ #include "X11VncConfigurationWidget.h" extern "C" int x11vnc_main( int argc, char * * argv ); +extern "C" int hasWorkingXShm(); BuiltinX11VncServer::BuiltinX11VncServer( QObject* parent ) : @@ -55,7 +56,7 @@ void BuiltinX11VncServer::prepareServer() -void BuiltinX11VncServer::runServer( int serverPort, const QString& password ) +bool BuiltinX11VncServer::runServer( int serverPort, const Password& password ) { QStringList cmdline = { QStringLiteral("-localhost"), QStringLiteral("-nosel"), // do not exchange clipboard-contents @@ -72,23 +73,23 @@ void BuiltinX11VncServer::runServer( int serverPort, const QString& password ) cmdline.append( extraArguments.split( QLatin1Char(' ') ) ); } - if( m_configuration.isXDamageDisabled() ) +#ifndef VEYON_X11VNC_EXTERNAL + if( hasWorkingXShm() == false ) { - cmdline.append( QStringLiteral("-noxdamage") ); + vDebug() << "X shared memory extension not available - passing -noshm to x11vnc"; + cmdline.append( QStringLiteral("-noshm") ); } - else +#endif + + const auto systemEnv = QProcessEnvironment::systemEnvironment(); + + if( m_configuration.isXDamageDisabled() || + // workaround for x11vnc when running in a NX session or a Thin client LTSP session + systemEnv.contains( QStringLiteral("NXSESSIONID") ) || + systemEnv.contains( QStringLiteral("X2GO_SESSION") ) || + systemEnv.contains( QStringLiteral("LTSP_CLIENT_MAC") ) ) { - // workaround for x11vnc when running in an NX session or a Thin client LTSP session - const auto systemEnv = QProcess::systemEnvironment(); - for( const auto& s : systemEnv ) - { - if( s.startsWith( QStringLiteral("NXSESSIONID=") ) || - s.startsWith( QStringLiteral("X2GO_SESSION=") ) || - s.startsWith( QStringLiteral("LTSP_CLIENT_MAC=") ) ) - { - cmdline.append( QStringLiteral("-noxdamage") ); - } - } + cmdline.append( QStringLiteral("-noxdamage") ); } #ifdef VEYON_X11VNC_EXTERNAL @@ -96,9 +97,9 @@ void BuiltinX11VncServer::runServer( int serverPort, const QString& password ) if( tempFile.open() == false ) // Flawfinder: ignore { vCritical() << "Could not create temporary file!"; - return; + return false; } - tempFile.write( password.toLocal8Bit() ); + tempFile.write( password.toByteArray() ); tempFile.close(); cmdline.append( QStringLiteral("-passwdfile") ); @@ -115,14 +116,16 @@ void BuiltinX11VncServer::runServer( int serverPort, const QString& password ) { vCritical() << "Could not start external x11vnc:" << x11vnc.errorString(); vCritical() << "Please make sure x11vnc is installed and installation directory is in PATH!"; - QThread::msleep( 5000 ); + return false; } else { x11vnc.waitForFinished( -1 ); } + + return true; #else - cmdline.append( { QStringLiteral("-passwd"), password } ); + cmdline.append( { QStringLiteral("-passwd"), QString::fromUtf8( password.toByteArray() ) } ); // build new C-style command line array based on cmdline-QStringList const auto appArguments = QCoreApplication::arguments(); @@ -139,7 +142,7 @@ void BuiltinX11VncServer::runServer( int serverPort, const QString& password ) } // run x11vnc-server - x11vnc_main( argc, argv ); + const auto result = x11vnc_main( argc, argv ); for( int i = 0; i < argc; ++i ) { @@ -147,6 +150,8 @@ void BuiltinX11VncServer::runServer( int serverPort, const QString& password ) } delete[] argv; + + return result == 0; #endif } diff --git a/plugins/vncserver/x11vnc-builtin/BuiltinX11VncServer.h b/plugins/vncserver/x11vnc-builtin/BuiltinX11VncServer.h index c678cffdc..203824211 100644 --- a/plugins/vncserver/x11vnc-builtin/BuiltinX11VncServer.h +++ b/plugins/vncserver/x11vnc-builtin/BuiltinX11VncServer.h @@ -1,7 +1,7 @@ /* * BuiltinX11VncServer.h - declaration of BuiltinX11VncServer class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -38,7 +38,7 @@ class BuiltinX11VncServer : public QObject, VncServerPluginInterface, PluginInte Plugin::Uid uid() const override { - return QStringLiteral("39d7a07f-94db-4912-aa1a-c4df8aee3879"); + return Plugin::Uid{ QStringLiteral("39d7a07f-94db-4912-aa1a-c4df8aee3879") }; } QVersionNumber version() const override @@ -71,18 +71,23 @@ class BuiltinX11VncServer : public QObject, VncServerPluginInterface, PluginInte return Plugin::ProvidesDefaultImplementation; } + QStringList supportedSessionTypes() const override + { + return { QStringLiteral("x11") }; + } + QWidget* configurationWidget() override; void prepareServer() override; - void runServer( int serverPort, const QString& password ) override; + bool runServer( int serverPort, const Password& password ) override; int configuredServerPort() override { return -1; } - QString configuredPassword() override + Password configuredPassword() override { return {}; } diff --git a/plugins/vncserver/x11vnc-builtin/CMakeLists.txt b/plugins/vncserver/x11vnc-builtin/CMakeLists.txt index 660bc5e72..155ee80d9 100644 --- a/plugins/vncserver/x11vnc-builtin/CMakeLists.txt +++ b/plugins/vncserver/x11vnc-builtin/CMakeLists.txt @@ -1,247 +1,212 @@ -INCLUDE(BuildPlugin) - -IF(VEYON_X11VNC_EXTERNAL) - -ADD_DEFINITIONS(-DVEYON_X11VNC_EXTERNAL) - -ELSE() - -# check for pthreads and TLS support -SET(CMAKE_THREAD_PREFER_PTHREAD TRUE) -FIND_PACKAGE(Threads) -IF(CMAKE_USE_PTHREADS_INIT) - SET(LIBVNCSERVER_HAVE_LIBPTHREAD TRUE) -ENDIF(CMAKE_USE_PTHREADS_INIT) - -# check for libvncserver requirements - -# functions -SET(LIBVNCSERVER_FUNCS fork ftime gethostbyname gethostname gettimeofday inet_ntoa memmove memset mkfifo mmap select socket strchr strdup strerror strstr vfork vprintf) -FOREACH(_func ${LIBVNCSERVER_FUNCS}) - STRING(TOUPPER "${_func}" fuc) - CHECK_FUNCTION_EXISTS(${_func} LIBVNCSERVER_HAVE_${fuc}) -ENDFOREACH() - -# headers -SET(LIBVNCSERVER_HEADERS fcntl sys/endian sys/wait sys/uio vfork) -FOREACH(_header ${LIBVNCSERVER_HEADERS}) - STRING(TOUPPER "${_header}" _huc) - STRING(REPLACE "/" "_" _header_escaped "${_huc}") - CHECK_INCLUDE_FILES(${_header}.h LIBVNCSERVER_HAVE_${_header_escaped}_H) -ENDFOREACH() - -SET(LIBVNCSERVER_ALLOW24BPP TRUE) -SET(FULL_PACKAGE_NAME "Veyon") -SET(PACKAGE_VERSION "${VERSION_STRING}") -SET(VERSION_PATCHLEVEL "${VERSION_PATCH}") - -CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/3rdparty/libvncserver/rfb/rfbconfig.h.cmakein ${CMAKE_BINARY_DIR}/${VEYON_CORE_INCLUDE_DIR}/rfb/rfbconfig.h @ONLY) - -# check for x11vnc requirements -SET(FUNCS dup2 floor ftime geteuid gethostbyname gethostname getpwnam getpwuid getspnam gettimeofday getuid grantpt inet_ntoa initgroups memcmp memcpy memmove memset mkfifo mmap fork pow putenv select seteuid setegid setgid setpgrp setsid setuid setutxent shmat socket strchr strcspn strdup strerror strftime strpbrk strrchr strstr uname vfork vprintf waitpid) -FOREACH(_func ${FUNCS}) - STRING(TOUPPER "${_func}" fuc) - CHECK_FUNCTION_EXISTS(${_func} HAVE_${fuc}) -ENDFOREACH(_func ${FUNCS}) - -CHECK_C_SOURCE_COMPILES("static __thread int p = 0; int main() {}" HAVE_TLS) - -CHECK_INCLUDE_FILES(arpa/inet.h HAVE_ARPA_INET_H) -CHECK_INCLUDE_FILES(ctype.h HAVE_CTYPE_H) -CHECK_INCLUDE_FILES(dlfcn.h HAVE_DLFCN_H) -CHECK_INCLUDE_FILES(endian.h HAVE_ENDIAN_H) -CHECK_INCLUDE_FILES(errno.h HAVE_ERRNO_H) -CHECK_INCLUDE_FILES(fcntl.h HAVE_FCNTL_H) -CHECK_INCLUDE_FILES(inttypes.h HAVE_INTTYPES_H) -CHECK_INCLUDE_FILES(linux/fb.h HAVE_LINUX_FB_H) -CHECK_INCLUDE_FILES(linux/input.h HAVE_LINUX_INPUT_H) -CHECK_INCLUDE_FILES(linux/uinput.h HAVE_LINUX_UINPUT_H) -CHECK_INCLUDE_FILES(linux/videodev2.h HAVE_LINUX_VIDEODEV2_H) -CHECK_INCLUDE_FILES(linux/videodev.h HAVE_LINUX_VIDEODEV_H) -CHECK_INCLUDE_FILES(memory.h HAVE_MEMORY_H) -CHECK_INCLUDE_FILES(netdb.h HAVE_NETDB_H) -CHECK_INCLUDE_FILES(netinet/in.h HAVE_NETINET_IN_H) -CHECK_INCLUDE_FILES(process.h HAVE_PROCESS_H) -CHECK_INCLUDE_FILES(pthread.h HAVE_PTHREAD_H) -CHECK_INCLUDE_FILES(pwd.h HAVE_PWD_H) -CHECK_INCLUDE_FILES(signal.h HAVE_SIGNAL_H) -CHECK_INCLUDE_FILES(stdarg.h HAVE_STDARG_H) -CHECK_INCLUDE_FILES(stdbool.h HAVE_STDBOOL_H) -CHECK_INCLUDE_FILES(stdint.h HAVE_STDINT_H) -CHECK_INCLUDE_FILES(stdlib.h HAVE_STDLIB_H) -CHECK_INCLUDE_FILES(string.h HAVE_STRING_H) -CHECK_INCLUDE_FILES(strings.h HAVE_STRINGS_H) -CHECK_INCLUDE_FILES(sys/endian.h HAVE_SYS_ENDIAN_H) -CHECK_INCLUDE_FILES(sys/ioctl.h HAVE_SYS_IOCTL_H) -CHECK_INCLUDE_FILES(sys/ipc.h HAVE_SYS_IPC_H) -CHECK_INCLUDE_FILES(syslog.h HAVE_SYSLOG_H) -CHECK_INCLUDE_FILES(sys/shm.h HAVE_SYS_SHM_H) -CHECK_INCLUDE_FILES(sys/socket.h HAVE_SYS_SOCKET_H) -CHECK_INCLUDE_FILES(sys/stat.h HAVE_SYS_STAT_H) -CHECK_INCLUDE_FILES(sys/stropts.h HAVE_SYS_STROPTS_H) -CHECK_INCLUDE_FILES(sys/timeb.h HAVE_SYS_TIMEB_H) -CHECK_INCLUDE_FILES(sys/time.h HAVE_SYS_TIME_H) -CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H) -CHECK_INCLUDE_FILES(sys/wait.h HAVE_SYS_WAIT_H) -CHECK_INCLUDE_FILES(termios.h HAVE_TERMIOS_H) -CHECK_INCLUDE_FILES(time.h HAVE_TIME_H) -CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H) -CHECK_INCLUDE_FILES(utmpx.h HAVE_UTMPX_H) -CHECK_INCLUDE_FILES(vfork.h HAVE_VFORK_H) - -FIND_PACKAGE(X11 REQUIRED) - -IF(NOT X11_XTest_FOUND) - MESSAGE(FATAL_ERROR "XTest library or headers not found - please install libxtst-dev or libXtst-devel") -ENDIF() - -IF(NOT X11_Xrandr_FOUND) - MESSAGE(FATAL_ERROR "Xrandr library or headers not found - please install libxrandr-dev or libXrandr-devel") -ENDIF() - -IF(NOT X11_Xinerama_FOUND) - MESSAGE(FATAL_ERROR "Xinerama library or headers not found - please install libxinerama-dev or libXinerama-devel") -ENDIF() - -IF(NOT X11_Xdamage_FOUND) - MESSAGE(FATAL_ERROR "Xdamage library or headers not found - please install libxdamage-dev or libXdamage-devel") -ENDIF() - -IF(NOT X11_Xfixes_FOUND) - MESSAGE(FATAL_ERROR "Xfixes library or headers not found - please install libxfixes-dev or libXfixes-devel") -ENDIF() - -SET(HAVE_X11 TRUE) -SET(HAVE_XTEST TRUE) -SET(HAVE_LIBSSL TRUE) -SET(HAVE_LIBXINERAMA TRUE) -SET(HAVE_LIBXRANDR TRUE) -SET(HAVE_LIBXDAMAGE TRUE) -SET(HAVE_LIBXFIXES TRUE) - -IF(X11_XShm_FOUND) - SET(HAVE_XSHM TRUE) -ELSE() - MESSAGE("WARNING: XShm library or headers not found - building VNC server without XShm support") -ENDIF() - -IF(X11_Xinput_FOUND) - SET(HAVE_XI2 TRUE) -ELSE() - MESSAGE("WARNING: Xinput library or headers not found - building VNC server without Xinput support") -ENDIF() - -IF(X11_Xcomposite_FOUND) - SET(HAVE_LIBXCOMPOSITE TRUE) -ELSE() - MESSAGE("WARNING: Xcomposite library or headers not found - building VNC server without Xcomposite support") -ENDIF() - -IF(X11_Xcursor_FOUND) - SET(HAVE_LIBXCURSOR TRUE) -ELSE() - MESSAGE("WARNING: Xcursor library or headers not found - building VNC server without Xcursor support") -ENDIF() - -SET(CMAKE_REQUIRED_LIBRARIES ${X11_LIBRARIES} ${X11_XTest_LIB}) - -CHECK_FUNCTION_EXISTS(XReadScreen HAVE_SOLARIS_XREADSCREEN) -CHECK_FUNCTION_EXISTS(FBPMForceLevel HAVE_FBPM) -CHECK_FUNCTION_EXISTS(DPMSForceLevel HAVE_DPMS) -CHECK_FUNCTION_EXISTS(XTestGrabControl HAVE_XTESTGRABCONTROL) -CHECK_FUNCTION_EXISTS(XRecordEnableContextAsync HAVE_RECORD) -CHECK_INCLUDE_FILES(X11/extensions/readdisplay.h HAVE_IRIX_XREADDISPLAY) -CHECK_INCLUDE_FILES(X11/XKBlib.h HAVE_XKBLIB_H) -IF(HAVE_XKBLIB_H) - CHECK_FUNCTION_EXISTS(XkbSelectEvents HAVE_XKEYBOARD) -ENDIF(HAVE_XKBLIB_H) - -UNSET(CMAKE_REQUIRED_LIBRARIES) - -SET(X11VNC_CONFIG ${CMAKE_BINARY_DIR}/config.h) -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h @ONLY) - -ADD_DEFINITIONS(-DVNCSHARED -DFOREVER -DNOREPEAT=0 -DNOPW=1 -DREMOTE_CONTROL=0 -DEXTERNAL_COMMANDS=0 -DFILEXFER=0 -DNOGUI -DSMALL_FOOTPRINT) -INCLUDE_DIRECTORIES(${libvncserver_DIR}/libvncserver ${libvncserver_DIR}/common ${3rdparty_DIR} ${x11vnc_DIR}/src) - -SET(libvncserver_SOURCES - ${libvncserver_DIR}/libvncserver/auth.c - ${libvncserver_DIR}/libvncserver/cargs.c - ${libvncserver_DIR}/libvncserver/corre.c - ${libvncserver_DIR}/libvncserver/cursor.c - ${libvncserver_DIR}/libvncserver/cutpaste.c - ${libvncserver_DIR}/libvncserver/draw.c - ${libvncserver_DIR}/libvncserver/font.c - ${libvncserver_DIR}/libvncserver/hextile.c - ${libvncserver_DIR}/libvncserver/httpd.c - ${libvncserver_DIR}/libvncserver/main.c - ${libvncserver_DIR}/libvncserver/rfbregion.c - ${libvncserver_DIR}/libvncserver/rfbserver.c - ${libvncserver_DIR}/libvncserver/rre.c - ${libvncserver_DIR}/libvncserver/scale.c - ${libvncserver_DIR}/libvncserver/selbox.c - ${libvncserver_DIR}/libvncserver/sockets.c - ${libvncserver_DIR}/libvncserver/stats.c - ${libvncserver_DIR}/libvncserver/translate.c - ${libvncserver_DIR}/libvncserver/ultra.c - ${libvncserver_DIR}/libvncserver/zlib.c - ${libvncserver_DIR}/libvncserver/zrle.c - ${libvncserver_DIR}/libvncserver/zrleoutstream.c - ${libvncserver_DIR}/libvncserver/zrlepalettehelper.c - ${libvncserver_DIR}/libvncserver/tight.c - ${libvncserver_DIR}/common/d3des.c - ${libvncserver_DIR}/common/turbojpeg.c - ${libvncserver_DIR}/common/vncauth.c) - -SET(x11vnc_SOURCES x11vnc-veyon.c - ${x11vnc_DIR}/src/appshare.c - ${x11vnc_DIR}/src/avahi.c - ${x11vnc_DIR}/src/rates.c - ${x11vnc_DIR}/src/cleanup.c - ${x11vnc_DIR}/src/remote.c - ${x11vnc_DIR}/src/pointer.c - ${x11vnc_DIR}/src/userinput.c - ${x11vnc_DIR}/src/unixpw.c - ${x11vnc_DIR}/src/gui.c - ${x11vnc_DIR}/src/xkb_bell.c - ${x11vnc_DIR}/src/xinerama.c - ${x11vnc_DIR}/src/solid.c - ${x11vnc_DIR}/src/selection.c - ${x11vnc_DIR}/src/xrandr.c - ${x11vnc_DIR}/src/win_utils.c - ${x11vnc_DIR}/src/cursor.c - ${x11vnc_DIR}/src/screen.c - ${x11vnc_DIR}/src/xevents.c - ${x11vnc_DIR}/src/help.c - ${x11vnc_DIR}/src/inet.c - ${x11vnc_DIR}/src/sslcmds.c - ${x11vnc_DIR}/src/xwrappers.c - ${x11vnc_DIR}/src/scan.c - ${x11vnc_DIR}/src/options.c - ${x11vnc_DIR}/src/user.c - ${x11vnc_DIR}/src/util.c - ${x11vnc_DIR}/src/x11vnc_defs.c - ${x11vnc_DIR}/src/xrecord.c - ${x11vnc_DIR}/src/8to24.c - ${x11vnc_DIR}/src/xdamage.c - ${x11vnc_DIR}/src/keyboard.c - ${x11vnc_DIR}/src/connections.c - ${x11vnc_DIR}/src/sslhelper.c - ${x11vnc_DIR}/src/linuxfb.c - ${x11vnc_DIR}/src/v4l.c - ${x11vnc_DIR}/src/macosx.c - ${x11vnc_DIR}/src/macosxCG.c - ${x11vnc_DIR}/src/macosxCGP.c - ${x11vnc_DIR}/src/macosxCGS.c - ${x11vnc_DIR}/src/xi2_devices.c - ${x11vnc_DIR}/src/uinput.c -) - -ENDIF() - -SET_SOURCE_FILES_PROPERTIES(${x11vnc_SOURCES} ${libvncserver_SOURCES} PROPERTIES COMPILE_FLAGS "-Wno-unused-result -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable -Wno-misleading-indentation -Wno-deprecated-declarations -Wno-address -Wno-format -Wno-discarded-qualifiers" COTIRE_EXCLUDED TRUE) - -BUILD_PLUGIN(builtin-x11vnc-server +include(BuildVeyonPlugin) + +option(VEYON_X11VNC_EXTERNAL "Build with external x11vnc server" OFF) + +if(NOT VEYON_X11VNC_EXTERNAL) + + get_property(HAVE_LIBVNCCLIENT GLOBAL PROPERTY HAVE_LIBVNCCLIENT) + if(HAVE_LIBVNCCLIENT) + find_package(LibVNCClient) + find_package(LibVNCServer 0.9.8) + else() + message(WARNING "No suitable LibVNCClient library found therefore performing internal build of LibVNCServer as well to avoid binary compatibility issues") + endif() + + if(NOT LibVNCServer_FOUND) + include(LibVNCServerIntegration) + endif() + + set(FULL_PACKAGE_NAME "Veyon") + set(PACKAGE_VERSION "${VERSION_STRING}") + set(VERSION_PATCHLEVEL "${VERSION_PATCH}") + + # check for x11vnc requirements + set(FUNCS getpwnam getspnam getuid grantpt initgroups seteuid setegid setgid setsid setuid shmat waitpid) + foreach(_func ${FUNCS}) + string(TOUPPER "${_func}" fuc) + check_function_exists(${_func} HAVE_${fuc}) + endforeach() + + check_c_source_compiles("static __thread int p = 0; int main() {}" HAVE_TLS) + + # x11vnc header macros + check_include_files(linux/fb.h HAVE_LINUX_FB_H) + check_include_files(linux/input.h HAVE_LINUX_INPUT_H) + check_include_files(linux/uinput.h HAVE_LINUX_UINPUT_H) + check_include_files(linux/videodev.h HAVE_LINUX_VIDEODEV_H) + check_include_files(linux/videodev2.h HAVE_LINUX_VIDEODEV2_H) + check_include_files(netdb.h HAVE_NETDB_H) + check_include_files(netinet/in.h HAVE_NETINET_IN_H) + check_include_files(pwd.h HAVE_PWD_H) + check_include_files(sys/ioctl.h HAVE_SYS_IOCTL_H) + check_include_files(sys/stropts.h HAVE_SYS_STROPTS_H) + check_include_files(sys/wait.h HAVE_SYS_WAIT_H) + check_include_files(termios.h HAVE_TERMIOS_H) + check_include_files(utmpx.h HAVE_UTMPX_H) + + find_package(X11 REQUIRED) + + if(NOT X11_XTest_FOUND) + message(FATAL_ERROR "XTest library or headers not found - please install libxtst-dev or libXtst-devel") + endif() + + if(NOT X11_Xrandr_FOUND) + message(FATAL_ERROR "Xrandr library or headers not found - please install libxrandr-dev or libXrandr-devel") + endif() + + if(NOT X11_Xinerama_FOUND) + message(FATAL_ERROR "Xinerama library or headers not found - please install libxinerama-dev or libXinerama-devel") + endif() + + if(NOT X11_Xdamage_FOUND) + message(FATAL_ERROR "Xdamage library or headers not found - please install libxdamage-dev or libXdamage-devel") + endif() + + if(NOT X11_Xfixes_FOUND) + message(FATAL_ERROR "Xfixes library or headers not found - please install libxfixes-dev or libXfixes-devel") + endif() + + set(HAVE_X11 TRUE) + set(HAVE_XTEST TRUE) + set(HAVE_LIBSSL TRUE) + set(HAVE_LIBXINERAMA TRUE) + set(HAVE_LIBXRANDR TRUE) + set(HAVE_LIBXDAMAGE TRUE) + set(HAVE_LIBXFIXES TRUE) + + if(X11_XShm_FOUND) + set(HAVE_XSHM TRUE) + else() + message("WARNING: XShm library or headers not found - building VNC server without XShm support") + endif() + + if(X11_Xinput_FOUND) + set(HAVE_XI2 TRUE) + else() + message("WARNING: Xinput library or headers not found - building VNC server without Xinput support") + endif() + + if(X11_Xcomposite_FOUND) + set(HAVE_LIBXCOMPOSITE TRUE) + else() + message("WARNING: Xcomposite library or headers not found - building VNC server without Xcomposite support") + endif() + + if(X11_Xcursor_FOUND) + set(HAVE_LIBXCURSOR TRUE) + else() + message("WARNING: Xcursor library or headers not found - building VNC server without Xcursor support") + endif() + + set(CMAKE_REQUIRED_LIBRARIES ${X11_LIBRARIES} ${X11_XTest_LIB}) + + check_function_exists(XReadScreen HAVE_SOLARIS_XREADSCREEN) + check_function_exists(FBPMForceLevel HAVE_FBPM) + check_function_exists(DPMSForceLevel HAVE_DPMS) + check_function_exists(XTestGrabControl HAVE_XTESTGRABCONTROL) + check_function_exists(XRecordEnableContextAsync HAVE_RECORD) + check_include_files(X11/extensions/readdisplay.h HAVE_IRIX_XREADDISPLAY) + check_include_files(X11/XKBlib.h HAVE_XKBLIB_H) + if(HAVE_XKBLIB_H) + check_function_exists(XkbSelectEvents HAVE_XKEYBOARD) + endif() + + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES}) + check_function_exists(X509_print_ex_fp HAVE_X509_PRINT_EX_FP) + + unset(CMAKE_REQUIRED_LIBRARIES) + + set(X11VNC_CONFIG ${CMAKE_BINARY_DIR}/config.h) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h @ONLY) + if(NOT LibVNCServer_FOUND) + set(libvncserver_SOURCES + ${libvncserver_DIR}/src/libvncserver/auth.c + ${libvncserver_DIR}/src/libvncserver/cargs.c + ${libvncserver_DIR}/src/libvncserver/corre.c + ${libvncserver_DIR}/src/libvncserver/cursor.c + ${libvncserver_DIR}/src/libvncserver/cutpaste.c + ${libvncserver_DIR}/src/libvncserver/draw.c + ${libvncserver_DIR}/src/libvncserver/font.c + ${libvncserver_DIR}/src/libvncserver/hextile.c + ${libvncserver_DIR}/src/libvncserver/httpd.c + ${libvncserver_DIR}/src/libvncserver/main.c + ${libvncserver_DIR}/src/libvncserver/rfbregion.c + ${libvncserver_DIR}/src/libvncserver/rfbserver.c + ${libvncserver_DIR}/src/libvncserver/rre.c + ${libvncserver_DIR}/src/libvncserver/scale.c + ${libvncserver_DIR}/src/libvncserver/selbox.c + ${libvncserver_DIR}/src/libvncserver/sockets.c + ${libvncserver_DIR}/src/libvncserver/stats.c + ${libvncserver_DIR}/src/libvncserver/translate.c + ${libvncserver_DIR}/src/libvncserver/ultra.c + ${libvncserver_DIR}/src/libvncserver/zlib.c + ${libvncserver_DIR}/src/libvncserver/zrle.c + ${libvncserver_DIR}/src/libvncserver/zrleoutstream.c + ${libvncserver_DIR}/src/libvncserver/zrlepalettehelper.c + ${libvncserver_DIR}/src/libvncserver/tight.c + ${libvncserver_DIR}/src/common/d3des.c + ${libvncserver_DIR}/src/common/sockets.c + ${libvncserver_DIR}/src/common/turbojpeg.c + ${libvncserver_DIR}/src/common/vncauth.c) + endif() + + set(x11vnc_SOURCES x11vnc-veyon.c + ${x11vnc_DIR}/src/appshare.c + ${x11vnc_DIR}/src/avahi.c + ${x11vnc_DIR}/src/rates.c + ${x11vnc_DIR}/src/cleanup.c + ${x11vnc_DIR}/src/remote.c + ${x11vnc_DIR}/src/pointer.c + ${x11vnc_DIR}/src/userinput.c + ${x11vnc_DIR}/src/unixpw.c + ${x11vnc_DIR}/src/gui.c + ${x11vnc_DIR}/src/xkb_bell.c + ${x11vnc_DIR}/src/xinerama.c + ${x11vnc_DIR}/src/solid.c + ${x11vnc_DIR}/src/selection.c + ${x11vnc_DIR}/src/xrandr.c + ${x11vnc_DIR}/src/win_utils.c + ${x11vnc_DIR}/src/cursor.c + ${x11vnc_DIR}/src/screen.c + ${x11vnc_DIR}/src/xevents.c + ${x11vnc_DIR}/src/help.c + ${x11vnc_DIR}/src/inet.c + ${x11vnc_DIR}/src/sslcmds.c + ${x11vnc_DIR}/src/xwrappers.c + ${x11vnc_DIR}/src/scan.c + ${x11vnc_DIR}/src/options.c + ${x11vnc_DIR}/src/user.c + ${x11vnc_DIR}/src/util.c + ${x11vnc_DIR}/src/x11vnc_defs.c + ${x11vnc_DIR}/src/xrecord.c + ${x11vnc_DIR}/src/8to24.c + ${x11vnc_DIR}/src/xdamage.c + ${x11vnc_DIR}/src/keyboard.c + ${x11vnc_DIR}/src/connections.c + ${x11vnc_DIR}/src/sslhelper.c + ${x11vnc_DIR}/src/linuxfb.c + ${x11vnc_DIR}/src/v4l.c + ${x11vnc_DIR}/src/macosx.c + ${x11vnc_DIR}/src/macosxCG.c + ${x11vnc_DIR}/src/macosxCGP.c + ${x11vnc_DIR}/src/macosxCGS.c + ${x11vnc_DIR}/src/xi2_devices.c + ${x11vnc_DIR}/src/uinput.c + ) + + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(COMPILER_WARN_DISABLE_FLAGS "-Wno-unused-but-set-variable -Wno-address -Wno-discarded-qualifiers -Wno-strict-aliasing -Wno-restrict -Wno-multistatement-macros -Wno-stringop-truncation -Wno-stringop-overflow -Wno-format-overflow") + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(COMPILER_WARN_DISABLE_FLAGS "-Wno-sometimes-uninitialized -Wno-pointer-bool-conversion -Wno-tautological-pointer-compare -Wno-tautological-constant-out-of-range-compare -Wno-incompatible-pointer-types-discards-qualifiers") + endif() + + set_source_files_properties(${x11vnc_SOURCES} ${libvncserver_SOURCES} PROPERTIES + COMPILE_FLAGS "${COMPILER_WARN_DISABLE_FLAGS} -Wno-deprecated-declarations -Wno-unused-result -Wno-unused-function -Wno-unused-variable -Wno-misleading-indentation") +endif() + +set(WITH_PCH OFF) + +build_veyon_plugin(builtin-x11vnc-server BuiltinX11VncServer.cpp X11VncConfigurationWidget.cpp X11VncConfigurationWidget.ui @@ -250,35 +215,56 @@ BUILD_PLUGIN(builtin-x11vnc-server BuiltinX11VncServer.h X11VncConfigurationWidget.h X11VncConfiguration.h -) - -IF(NOT VEYON_X11VNC_EXTERNAL) -TARGET_LINK_LIBRARIES(builtin-x11vnc-server - Threads::Threads - ${X11_LIBRARIES} - ${X11_XTest_LIB} - ${X11_Xfixes_LIB} - ${X11_Xinerama_LIB} - ${X11_Xdamage_LIB} - ${X11_Xrandr_LIB} -) - -IF(X11_XShm_FOUND) -TARGET_LINK_LIBRARIES(builtin-x11vnc-server ${X11_XShm_LIB}) -ENDIF() - -IF(X11_Xcomposite_FOUND) -TARGET_LINK_LIBRARIES(builtin-x11vnc-server ${X11_Xcomposite_LIB}) -ENDIF() - -IF(X11_Xcursor_FOUND) -TARGET_LINK_LIBRARIES(builtin-x11vnc-server ${X11_Xcursor_LIB}) -ENDIF() - -IF(X11_Xinput_FOUND) -TARGET_LINK_LIBRARIES(builtin-x11vnc-server ${X11_Xinput_LIB}) -ENDIF() - -ENDIF() - - + ) + +if(VEYON_X11VNC_EXTERNAL) + + target_compile_definitions(builtin-x11vnc-server PRIVATE VEYON_X11VNC_EXTERNAL) + +else() + + target_compile_definitions(builtin-x11vnc-server PRIVATE VNCSHARED FOREVER NOREPEAT=0 NOPW=1 REMOTE_CONTROL=0 EXTERNAL_COMMANDS=0 FILEXFER=0 NOGUI SMALL_FOOTPRINT) + + target_include_directories(builtin-x11vnc-server PRIVATE ${x11vnc_DIR}/src) + + target_link_libraries(builtin-x11vnc-server PRIVATE + ${X11_LIBRARIES} + ${X11_XTest_LIB} + ${X11_Xfixes_LIB} + ${X11_Xinerama_LIB} + ${X11_Xdamage_LIB} + ${X11_Xrandr_LIB} + ) + + if(LibVNCServer_FOUND) + target_link_libraries(builtin-x11vnc-server PRIVATE + LibVNC::LibVNCClient + LibVNC::LibVNCServer) + else() + target_link_libraries(builtin-x11vnc-server PRIVATE + Threads::Threads + PNG::PNG + ${ZLIB_LIBRARIES} + ${JPEG_LIBRARIES} + ${LZO_LIBRARIES} + ) + target_include_directories(builtin-x11vnc-server PRIVATE ${libvncserver_DIR}/libvncserver ${libvncserver_DIR}/common) + endif() + + if(X11_XShm_FOUND) + target_link_libraries(builtin-x11vnc-server PRIVATE ${X11_XShm_LIB}) + endif() + + if(X11_Xcomposite_FOUND) + target_link_libraries(builtin-x11vnc-server PRIVATE ${X11_Xcomposite_LIB}) + endif() + + if(X11_Xcursor_FOUND) + target_link_libraries(builtin-x11vnc-server PRIVATE ${X11_Xcursor_LIB}) + endif() + + if(X11_Xinput_FOUND) + target_link_libraries(builtin-x11vnc-server PRIVATE ${X11_Xinput_LIB}) + endif() + +endif() diff --git a/plugins/vncserver/x11vnc-builtin/X11VncConfiguration.h b/plugins/vncserver/x11vnc-builtin/X11VncConfiguration.h index ee5f48966..e18423d6b 100644 --- a/plugins/vncserver/x11vnc-builtin/X11VncConfiguration.h +++ b/plugins/vncserver/x11vnc-builtin/X11VncConfiguration.h @@ -1,7 +1,7 @@ /* * X11VncConfiguration.h - x11vnc-specific configuration values * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -30,4 +30,6 @@ OP( X11VncConfiguration, m_configuration, bool, isXDamageDisabled, setXDamageDisabled, "XDamageDisabled", "X11Vnc", false, Configuration::Property::Flag::Advanced ) \ OP( X11VncConfiguration, m_configuration, QString, extraArguments, setExtraArguments, "ExtraArguments", "X11Vnc", QString(), Configuration::Property::Flag::Advanced ) +// clazy:excludeall=missing-qobject-macro + DECLARE_CONFIG_PROXY(X11VncConfiguration, FOREACH_X11VNC_CONFIG_PROPERTY) diff --git a/plugins/vncserver/x11vnc-builtin/X11VncConfigurationWidget.cpp b/plugins/vncserver/x11vnc-builtin/X11VncConfigurationWidget.cpp index 0a6a17f42..a308c6696 100644 --- a/plugins/vncserver/x11vnc-builtin/X11VncConfigurationWidget.cpp +++ b/plugins/vncserver/x11vnc-builtin/X11VncConfigurationWidget.cpp @@ -1,7 +1,7 @@ /* * X11VncConfigurationWidget.h - implementation of the X11VncConfigurationWidget class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/plugins/vncserver/x11vnc-builtin/X11VncConfigurationWidget.h b/plugins/vncserver/x11vnc-builtin/X11VncConfigurationWidget.h index 45a8867dd..018ea7ed5 100644 --- a/plugins/vncserver/x11vnc-builtin/X11VncConfigurationWidget.h +++ b/plugins/vncserver/x11vnc-builtin/X11VncConfigurationWidget.h @@ -1,7 +1,7 @@ /* * X11VncConfigurationWidget.h - header for the X11VncConfigurationWidget class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * diff --git a/plugins/vncserver/x11vnc-builtin/config.h.in b/plugins/vncserver/x11vnc-builtin/config.h.in index e977c64d6..6ab3f253a 100644 --- a/plugins/vncserver/x11vnc-builtin/config.h.in +++ b/plugins/vncserver/x11vnc-builtin/config.h.in @@ -1,8 +1,5 @@ /* config.h.in. Generated from configure.ac by autoheader. */ -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_ARPA_INET_H 1 - /* Avahi/mDNS client build environment present */ #cmakedefine HAVE_AVAHI 1 @@ -15,57 +12,24 @@ /* DPMS extension build environment present */ #cmakedefine HAVE_DPMS 1 -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_ENDIAN_H 1 - /* FBPM extension build environment present */ #cmakedefine HAVE_FBPM 1 -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_FCNTL_H 1 - -/* Define to 1 if you have the `fork' function. */ -#cmakedefine HAVE_FORK 1 - -/* Define to 1 if you have the `ftime' function. */ -#cmakedefine HAVE_FTIME 1 - -/* Define to 1 if you have the `geteuid' function. */ -#cmakedefine HAVE_GETEUID 1 - -/* Define to 1 if you have the `gethostbyname' function. */ -#cmakedefine HAVE_GETHOSTBYNAME 1 - -/* Define to 1 if you have the `gethostname' function. */ -#cmakedefine HAVE_GETHOSTNAME 1 - /* Define to 1 if you have the `getpwnam' function. */ #cmakedefine HAVE_GETPWNAM 1 -/* Define to 1 if you have the `getpwuid' function. */ -#cmakedefine HAVE_GETPWUID 1 - /* Define to 1 if you have the `getspnam' function. */ #cmakedefine HAVE_GETSPNAM 1 -/* Define to 1 if you have the `gettimeofday' function. */ -#cmakedefine HAVE_GETTIMEOFDAY 1 - /* Define to 1 if you have the `getuid' function. */ #cmakedefine HAVE_GETUID 1 /* Define to 1 if you have the `grantpt' function. */ #cmakedefine HAVE_GRANTPT 1 -/* Define to 1 if you have the `inet_ntoa' function. */ -#cmakedefine HAVE_INET_NTOA 1 - /* Define to 1 if you have the `initgroups' function. */ #cmakedefine HAVE_INITGROUPS 1 -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_INTTYPES_H 1 - /* IRIX XReadDisplay available */ #cmakedefine HAVE_IRIX_XREADDISPLAY 1 @@ -120,27 +84,15 @@ /* video4linux build environment present */ #cmakedefine HAVE_LINUX_VIDEODEV_H 1 +/* video4linux2 build environment present */ +#cmakedefine HAVE_LINUX_VIDEODEV2_H 1 + /* build MacOS X native display support */ #cmakedefine HAVE_MACOSX_NATIVE_DISPLAY 1 /* MacOS X OpenGL present */ #cmakedefine HAVE_MACOSX_OPENGL_H 1 -/* Define to 1 if you have the `memmove' function. */ -#cmakedefine HAVE_MEMMOVE 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `memset' function. */ -#cmakedefine HAVE_MEMSET 1 - -/* Define to 1 if you have the `mkfifo' function. */ -#cmakedefine HAVE_MKFIFO 1 - -/* Define to 1 if you have the `mmap' function. */ -#cmakedefine HAVE_MMAP 1 - /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETDB_H 1 @@ -153,9 +105,6 @@ /* RECORD extension build environment present */ #cmakedefine HAVE_RECORD 1 -/* Define to 1 if you have the `select' function. */ -#cmakedefine HAVE_SELECT 1 - /* Define to 1 if you have the `setegid' function. */ #cmakedefine HAVE_SETEGID 1 @@ -165,121 +114,36 @@ /* Define to 1 if you have the `setgid' function. */ #cmakedefine HAVE_SETGID 1 -/* Define to 1 if you have the `setpgrp' function. */ -#cmakedefine HAVE_SETPGRP 1 - /* Define to 1 if you have the `setsid' function. */ #cmakedefine HAVE_SETSID 1 /* Define to 1 if you have the `setuid' function. */ #cmakedefine HAVE_SETUID 1 -/* Define to 1 if you have the `setutxent' function. */ -#cmakedefine HAVE_SETUTXENT 1 - /* Define to 1 if you have the `shmat' function. */ #cmakedefine HAVE_SHMAT 1 -/* Define to 1 if you have the `socket' function. */ -#cmakedefine HAVE_SOCKET 1 - /* Solaris XReadScreen available */ #cmakedefine HAVE_SOLARIS_XREADSCREEN 1 -/* Define to 1 if `stat' has the bug that it succeeds when given the - zero-length file name argument. */ -#cmakedefine HAVE_STAT_EMPTY_STRING_BUG 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strchr' function. */ -#cmakedefine HAVE_STRCHR 1 - -/* Define to 1 if you have the `strcspn' function. */ -#cmakedefine HAVE_STRCSPN 1 - -/* Define to 1 if you have the `strdup' function. */ -#cmakedefine HAVE_STRDUP 1 - -/* Define to 1 if you have the `strerror' function. */ -#cmakedefine HAVE_STRERROR 1 - -/* Define to 1 if you have the `strftime' function. */ -#cmakedefine HAVE_STRFTIME 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_STRING_H 1 - -/* Define to 1 if you have the `strstr' function. */ -#cmakedefine HAVE_STRSTR 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYSLOG_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_ENDIAN_H 1 - /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_IOCTL_H 1 -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_STAT_H 1 - /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_STROPTS_H 1 -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_TIMEB_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_TYPES_H 1 - /* Define to 1 if you have that is POSIX.1 compatible. */ #cmakedefine HAVE_SYS_WAIT_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_TERMIOS_H 1 -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_UNISTD_H 1 - /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UTMPX_H 1 -/* Define to 1 if you have the `vfork' function. */ -#cmakedefine HAVE_VFORK 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_VFORK_H 1 - -/* Define to 1 if you have the `vprintf' function. */ -#cmakedefine HAVE_VPRINTF 1 - /* Define to 1 if you have the `waitpid' function. */ #cmakedefine HAVE_WAITPID 1 -/* Define to 1 if `fork' works. */ -#cmakedefine HAVE_WORKING_FORK 1 - -/* Define to 1 if `vfork' works. */ -#cmakedefine HAVE_WORKING_VFORK 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_WS2TCPIP_H 1 - /* X11 build environment present */ #cmakedefine HAVE_X11 1 diff --git a/plugins/vncserver/x11vnc-builtin/x11vnc-veyon.c b/plugins/vncserver/x11vnc-builtin/x11vnc-veyon.c index 449725eb3..6dbcd78a1 100644 --- a/plugins/vncserver/x11vnc-builtin/x11vnc-veyon.c +++ b/plugins/vncserver/x11vnc-builtin/x11vnc-veyon.c @@ -3,5 +3,136 @@ #include -#include "x11vnc/src/x11vnc.c" -#include "x11vnc/src/pm.c" +#include "x11vnc.c" +#include "pm.c" + +#ifdef HAVE_XSHM + +#include +#include + +static int xshmOpCode = 0; +static int shmErrorCount = 0; +static XErrorHandler defaultXErrorHandler = NULL; + +static int handleXError( Display* display, XErrorEvent* error ) +{ + if( xshmOpCode > 0 && error->request_code == xshmOpCode ) + { + shmErrorCount++; + return 0; + } + + return defaultXErrorHandler(display, error); +} + + + +static XImage* createXShmTestImage( Display* display, XShmSegmentInfo* shm ) +{ + shm->shmid = -1; + shm->shmaddr = (char *) -1; + + const int screen = DefaultScreen(display); + + XImage* xim = XShmCreateImage(display, DefaultVisual(display, screen), + DefaultDepth(display, screen), + ZPixmap, NULL, shm, 1, 1); + if( xim == NULL ) + { + shmErrorCount++; + return NULL; + } + + shm->shmid = shmget(IPC_PRIVATE, (size_t)xim->bytes_per_line * xim->height, IPC_CREAT | 0600); + + if( shm->shmid == -1 ) + { + shmErrorCount++; + return xim; + } + + shm->shmaddr = xim->data = (char *) shmat(shm->shmid, NULL, 0); + shm->readOnly = False; + + if( shm->shmaddr == (char *)-1 ) + { + shmErrorCount++; + return xim; + } + + if( XShmAttach(display, shm) ) + { + XSync(display, False); + XShmDetach(display, shm); + } + else + { + shmErrorCount++; + } + + XSync(display, False); + + return xim; +} + + + +int hasWorkingXShm() +{ + shmErrorCount = 0; + + Display* display = XOpenDisplay(NULL); + if( display == NULL ) + { + return 0; + } + + int op, ev, er; + if( XQueryExtension(display, "MIT-SHM", &op, &ev, &er) ) + { + xshmOpCode = op; + } + else + { + XCloseDisplay(display); + return 0; + } + + defaultXErrorHandler = XSetErrorHandler(handleXError); + + XShmSegmentInfo shm; + XImage* xim = createXShmTestImage(display, &shm); + + XSetErrorHandler(defaultXErrorHandler); + + if( xim ) + { + XDestroyImage(xim); + } + + if( shm.shmaddr != (char *) -1 ) + { + shmdt(shm.shmaddr); + } + + if( shm.shmid != -1 ) + { + shmctl(shm.shmid, IPC_RMID, 0); + } + + XSync(display, False); + + XCloseDisplay(display); + + return shmErrorCount == 0; +} + +#else + +int hasWorkingXShm() +{ + return 0; +} + +#endif diff --git a/project.yml b/project.yml index 569e6bbda..68d40f2b8 100644 --- a/project.yml +++ b/project.yml @@ -1,7 +1,7 @@ project: name: Veyon - version: 4.2.3 - copyright: 2004-2019 + version: 4.99.0 + copyright: 2004-2025 author: Tobias Junghans contact: Tobias Junghans contributors: diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index e15be3d8b..0581adb28 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -1,21 +1,36 @@ -INCLUDE(BuildApplication) -INCLUDE(WindowsBuildHelpers) +include(BuildVeyonApplication) +include(WindowsBuildHelpers) -FILE(GLOB server_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h) -FILE(GLOB server_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) - -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src) - -BUILD_APPLICATION(veyon-server ${server_SOURCES} ${server_INCLUDES}) -TARGET_LINK_LIBRARIES(veyon-server veyon-core) +build_veyon_application(veyon-server + src/ComputerControlClient.cpp + src/ComputerControlClient.h + src/ComputerControlServer.cpp + src/ComputerControlServer.h + src/main.cpp + src/ServerAccessControlManager.cpp + src/ServerAccessControlManager.h + src/ServerAuthenticationManager.cpp + src/ServerAuthenticationManager.h + src/TlsServer.cpp + src/TlsServer.h + src/VeyonServerProtocol.cpp + src/VeyonServerProtocol.h + src/VncProxyConnection.cpp + src/VncProxyConnectionFactory.h + src/VncProxyConnection.h + src/VncProxyServer.cpp + src/VncProxyServer.h + src/VncServer.cpp + src/VncServer.h + ) -ADD_WINDOWS_RESOURCE(veyon-server) -MAKE_GRAPHICAL_APP(veyon-server) +add_windows_resource(veyon-server) +make_graphical_app(veyon-server) -TARGET_LINK_LIBRARIES(veyon-server - Qt5::Gui - Qt5::Network - Qt5::Widgets - ) +if(VEYON_BUILD_ANDROID) + set(CMAKE_ANDROID_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") + androiddeployqt("veyon-server" "${ANDROID_ADDITIONAL_FIND_ROOT_PATH};${CMAKE_BINARY_DIR}/core;${ANDROID_INSTALL_DIR}") + set_target_properties(create-apk-veyon-server PROPERTIES ANDROID_APK_DIR "${CMAKE_ANDROID_DIR}") -COTIRE_VEYON(veyon-server) + add_dependencies(create-apk-veyon-server prepare-apk) +endif() diff --git a/android/AndroidManifest.xml b/server/android/AndroidManifest.xml similarity index 79% rename from android/AndroidManifest.xml rename to server/android/AndroidManifest.xml index 1548cb13d..6ca49efb8 100644 --- a/android/AndroidManifest.xml +++ b/server/android/AndroidManifest.xml @@ -1,6 +1,6 @@ - - + + - - - - - - - - - + @@ -84,9 +73,30 @@ --> - + + + + + - + + + + diff --git a/server/android/build.gradle b/server/android/build.gradle new file mode 120000 index 000000000..b8869a3b7 --- /dev/null +++ b/server/android/build.gradle @@ -0,0 +1 @@ +../../android/build.gradle \ No newline at end of file diff --git a/server/android/res/xml/veyon_accessibility_service_config.xml b/server/android/res/xml/veyon_accessibility_service_config.xml new file mode 100644 index 000000000..da8d1fa91 --- /dev/null +++ b/server/android/res/xml/veyon_accessibility_service_config.xml @@ -0,0 +1,8 @@ + + diff --git a/server/android/src/io/veyon/VeyonAccessibilityService.java b/server/android/src/io/veyon/VeyonAccessibilityService.java new file mode 100644 index 000000000..d595d902c --- /dev/null +++ b/server/android/src/io/veyon/VeyonAccessibilityService.java @@ -0,0 +1,66 @@ +package io.veyon.Veyon.Server; + +import android.accessibilityservice.AccessibilityService; +import android.accessibilityservice.GestureDescription; +import android.view.accessibility.AccessibilityEvent; +import android.view.ViewConfiguration; +import android.graphics.Path; + +public class VeyonAccessibilityService extends AccessibilityService { + + private static VeyonAccessibilityService instance; + + @Override + public void onAccessibilityEvent( AccessibilityEvent event ) { } + + @Override + public void onInterrupt() { } + + @Override + public void onCreate() + { + super.onCreate(); + instance = this; + } + + public static void tap( int x, int y ) + { + instance.dispatchGesture( createClick( x, y, ViewConfiguration.getTapTimeout() + 50 ), null, null ); + } + + public static void longPress( int x, int y ) + { + instance.dispatchGesture( createClick( x, y, ViewConfiguration.getLongPressTimeout() + 200 ), null, null ); + } + + public static void swipeDown( int x, int y ) + { + instance.dispatchGesture( createSwipe( x, y, x, y+100 ), null, null ); + } + + public static void swipeUp( int x, int y ) + { + instance.dispatchGesture( createSwipe( x, y, x, y-100 ), null, null ); + } + + private static GestureDescription createClick( int x, int y, int duration ) + { + Path clickPath = new Path(); + clickPath.moveTo( x, y ); + GestureDescription.StrokeDescription clickStroke = new GestureDescription.StrokeDescription( clickPath, 0, duration ); + GestureDescription.Builder clickBuilder = new GestureDescription.Builder(); + clickBuilder.addStroke( clickStroke ); + return clickBuilder.build(); + } + + private static GestureDescription createSwipe( int x1, int y1, int x2, int y2 ) + { + Path swipePath = new Path(); + swipePath.moveTo( x1, y1 ); + swipePath.moveTo( x2, y2 ); + GestureDescription.StrokeDescription swipeStroke = new GestureDescription.StrokeDescription( swipePath, 0, 100 ); + GestureDescription.Builder swipeBuilder = new GestureDescription.Builder(); + swipeBuilder.addStroke( swipeStroke ); + return swipeBuilder.build(); + } +} diff --git a/server/src/ComputerControlClient.cpp b/server/src/ComputerControlClient.cpp index 9bf579d2f..92f2dae78 100644 --- a/server/src/ComputerControlClient.cpp +++ b/server/src/ComputerControlClient.cpp @@ -1,7 +1,7 @@ /* * ComputerControlClient.cpp - implementation of the ComputerControlClient class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -32,19 +32,17 @@ ComputerControlClient::ComputerControlClient( ComputerControlServer* server, QTcpSocket* clientSocket, int vncServerPort, - const QString& vncServerPassword, + const Password& vncServerPassword, QObject* parent ) : VncProxyConnection( clientSocket, vncServerPort, parent ), m_server( server ), - m_serverClient(), m_serverProtocol( clientSocket, &m_serverClient, server->authenticationManager(), server->accessControlManager() ), m_clientProtocol( vncServerSocket(), vncServerPassword ) { - m_serverProtocol.start(); - m_clientProtocol.start(); + m_framebufferUpdateTimer.start(); } @@ -68,8 +66,38 @@ bool ComputerControlClient::receiveClientMessage() if( messageType == FeatureMessage::RfbMessageType ) { - return m_server->handleFeatureMessage( socket ); + return m_server->handleFeatureMessage(this); + } + + // filter framebuffer update requests when minimum framebuffer update interval is set + if (messageType == rfbFramebufferUpdateRequest && m_minimumFramebufferUpdateInterval > 0) + { + if (socket->bytesAvailable() < sz_rfbFramebufferUpdateRequestMsg) + { + return false; + } + + const auto messageData = socket->read(sz_rfbFramebufferUpdateRequestMsg); + const auto updateRequestMessage = reinterpret_cast(messageData.constData()); + + if (updateRequestMessage->incremental && + m_framebufferUpdateTimer.hasExpired(m_minimumFramebufferUpdateInterval) == false) + { + // discard update request + return true; + } + + // forward request to server + m_framebufferUpdateTimer.restart(); + return vncServerSocket()->write(messageData) == messageData.size(); } return VncProxyConnection::receiveClientMessage(); } + + + +void ComputerControlClient::setMinimumFramebufferUpdateInterval(int interval) +{ + m_minimumFramebufferUpdateInterval = interval; +} diff --git a/server/src/ComputerControlClient.h b/server/src/ComputerControlClient.h index a2dc24f3e..c0d0469e7 100644 --- a/server/src/ComputerControlClient.h +++ b/server/src/ComputerControlClient.h @@ -1,7 +1,7 @@ /* * ComputerControlClient.h - header file for the ComputerControlClient class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,6 +24,8 @@ #pragma once +#include + #include "VncClientProtocol.h" #include "VncProxyConnection.h" #include "VncServerClient.h" @@ -35,15 +37,24 @@ class ComputerControlClient : public VncProxyConnection { Q_OBJECT public: + using Password = CryptoCore::PlaintextPassword; + ComputerControlClient( ComputerControlServer* server, QTcpSocket* clientSocket, int vncServerPort, - const QString& vncServerPassword, + const Password& vncServerPassword, QObject* parent ); ~ComputerControlClient() override; bool receiveClientMessage() override; + VncServerClient* serverClient() + { + return &m_serverClient; + } + + void setMinimumFramebufferUpdateInterval(int interval); + protected: VncClientProtocol& clientProtocol() override { @@ -58,9 +69,12 @@ class ComputerControlClient : public VncProxyConnection private: ComputerControlServer* m_server; - VncServerClient m_serverClient; + VncServerClient m_serverClient{}; VeyonServerProtocol m_serverProtocol; VncClientProtocol m_clientProtocol; + int m_minimumFramebufferUpdateInterval{-1}; + QElapsedTimer m_framebufferUpdateTimer; + } ; diff --git a/server/src/ComputerControlServer.cpp b/server/src/ComputerControlServer.cpp index e861e5c63..da6b72d6c 100644 --- a/server/src/ComputerControlServer.cpp +++ b/server/src/ComputerControlServer.cpp @@ -1,7 +1,7 @@ /* * ComputerControlServer.cpp - implementation of ComputerControlServer * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -28,32 +28,26 @@ #include "BuiltinFeatures.h" #include "ComputerControlClient.h" #include "ComputerControlServer.h" +#include "FeatureManager.h" #include "FeatureMessage.h" #include "HostAddress.h" +#include "PlatformPluginInterface.h" #include "VeyonConfiguration.h" #include "SystemTrayIcon.h" ComputerControlServer::ComputerControlServer( QObject* parent ) : - QObject( parent ), - m_allowedIPs(), - m_failedAuthHosts(), - m_featureManager(), - m_featureWorkerManager( *this, m_featureManager ), + VeyonServerInterface(parent), + m_featureWorkerManager( *this ), m_serverAuthenticationManager( this ), m_serverAccessControlManager( m_featureWorkerManager, VeyonCore::builtinFeatures().desktopAccessDialog(), this ), - m_vncServer(), - m_vncProxyServer( VeyonCore::config().localConnectOnly() || AccessControlProvider().isAccessToLocalComputerDenied() ? + m_vncProxyServer( VeyonCore::config().localConnectOnly() || VeyonCore::builtinFeatures().accessControlProvider().isAccessToLocalComputerDenied() ? QHostAddress::LocalHost : QHostAddress::Any, - VeyonCore::config().primaryServicePort() + VeyonCore::sessionId(), + VeyonCore::config().veyonServerPort() + VeyonCore::sessionId(), this, this ) { - VeyonCore::builtinFeatures().systemTrayIcon().setToolTip( - tr( "%1 Service %2 at %3:%4" ).arg( VeyonCore::applicationName(), VeyonCore::version(), - HostAddress::localFQDN(), - QString::number( VeyonCore::config().primaryServicePort() + VeyonCore::sessionId() ) ), - m_featureWorkerManager ); + updateTrayIconToolTip(); // make app terminate once the VNC server thread has finished connect( &m_vncServer, &VncServer::finished, QCoreApplication::instance(), &QCoreApplication::quit ); @@ -63,6 +57,10 @@ ComputerControlServer::ComputerControlServer( QObject* parent ) : connect( &m_serverAccessControlManager, &ServerAccessControlManager::finished, this, &ComputerControlServer::showAccessControlMessage ); + + connect(&m_vncProxyServer, &VncProxyServer::serverMessageProcessed, + this, &ComputerControlServer::sendAsyncFeatureMessages, Qt::DirectConnection); + connect( &m_vncProxyServer, &VncProxyServer::connectionClosed, this, &ComputerControlServer::updateTrayIconToolTip ); } @@ -93,16 +91,24 @@ bool ComputerControlServer::start() VncProxyConnection* ComputerControlServer::createVncProxyConnection( QTcpSocket* clientSocket, int vncServerPort, - const QString& vncServerPassword, + const Password& vncServerPassword, QObject* parent ) { - return new ComputerControlClient( this, clientSocket, vncServerPort, vncServerPassword, parent ); + auto client = new ComputerControlClient( this, clientSocket, vncServerPort, vncServerPassword, parent ); + + connect( client, &ComputerControlClient::serverConnectionClosed, this, + [=]() { checkForIncompleteAuthentication( client->serverClient() ); }, + Qt::DirectConnection ); + + return client; } -bool ComputerControlServer::handleFeatureMessage( QTcpSocket* socket ) +bool ComputerControlServer::handleFeatureMessage(ComputerControlClient* client) { + auto socket = client->proxyClientSocket(); + char messageType; if( socket->getChar( &messageType ) == false ) { @@ -118,21 +124,54 @@ bool ComputerControlServer::handleFeatureMessage( QTcpSocket* socket ) return false; } - featureMessage.receive( socket ); + if (featureMessage.receive(socket) == false) + { + return false; + } - return m_featureManager.handleFeatureMessage( *this, MessageContext( socket ), featureMessage ); + VeyonCore::featureManager().handleFeatureMessage( *this, MessageContext{socket, client}, featureMessage ); + + return true; } bool ComputerControlServer::sendFeatureMessageReply( const MessageContext& context, const FeatureMessage& reply ) { - vDebug() << reply.featureUid() << reply.command() << reply.arguments(); + vDebug() << reply; + + if (context.ioDevice()) + { + return reply.sendAsRfbMessage(context.ioDevice()); + } + + return false; +} + + + +void ComputerControlServer::setMinimumFramebufferUpdateInterval(const MessageContext& context, int interval) +{ + auto client = qobject_cast(context.connection()); + if (client) + { + client->setMinimumFramebufferUpdateInterval(interval); + } +} + - char rfbMessageType = FeatureMessage::RfbMessageType; - context.ioDevice()->write( &rfbMessageType, sizeof(rfbMessageType) ); - return reply.send( context.ioDevice() ); +void ComputerControlServer::checkForIncompleteAuthentication( VncServerClient* client ) +{ + // connection to client closed during authentication? + if( client->protocolState() == VncServerProtocol::State::AuthenticationMethods || + client->protocolState() == VncServerProtocol::State::Authenticating ) + { + // then mark as failed authentication and report it + client->setAuthState( VncServerClient::AuthState::Failed ); + + showAuthenticationMessage( client ); + } } @@ -143,7 +182,8 @@ void ComputerControlServer::showAuthenticationMessage( VncServerClient* client ) { vWarning() << "Authentication failed for" << client->hostAddress() << client->username(); - if( VeyonCore::config().failedAuthenticationNotificationsEnabled() ) + if (VeyonCore::config().failedAuthenticationNotificationsEnabled() && + VeyonCore::platform().sessionFunctions().currentSessionHasUser()) { QMutexLocker l( &m_dataMutex ); @@ -167,11 +207,13 @@ void ComputerControlServer::showAuthenticationMessage( VncServerClient* client ) void ComputerControlServer::showAccessControlMessage( VncServerClient* client ) { - if( client->accessControlState() == VncServerClient::AccessControlState::Successful ) + if( client->accessControlState() == VncServerClient::AccessControlState::Successful && + client->protocolState() == VncServerProtocol::State::AccessControl ) { vInfo() << "Access control successful for" << client->hostAddress() << client->username(); - if( VeyonCore::config().remoteConnectionNotificationsEnabled() ) + if (VeyonCore::config().remoteConnectionNotificationsEnabled() && + VeyonCore::platform().sessionFunctions().currentSessionHasUser()) { const auto fqdn = HostAddress( client->hostAddress() ).tryConvert( HostAddress::Type::FullyQualifiedDomainName ); @@ -181,6 +223,8 @@ void ComputerControlServer::showAccessControlMessage( VncServerClient* client ) arg( client->username(), fqdn ), m_featureWorkerManager ); } + + updateTrayIconToolTip(); } else if( client->accessControlState() == VncServerClient::AccessControlState::Failed ) { @@ -206,3 +250,80 @@ void ComputerControlServer::showAccessControlMessage( VncServerClient* client ) } } } + + + +QFutureWatcher* ComputerControlServer::resolveFQDNs( const QStringList& hosts ) +{ + auto watcher = new QFutureWatcher(); + + watcher->setFuture( QtConcurrent::run( [this, hosts]() { + for( const auto& host : hosts ) + { + const auto fqdn = HostAddress( host ).tryConvert( HostAddress::Type::FullyQualifiedDomainName ); + + m_dataMutex.lock(); + m_resolvedHostNames[host] = fqdn; + m_dataMutex.unlock(); + } + } ) ); + + connect( watcher, &QFutureWatcher::finished, watcher, &QObject::deleteLater ); + + return watcher; +} + + + +void ComputerControlServer::sendAsyncFeatureMessages(VncProxyConnection* connection) +{ + VeyonCore::featureManager().sendAsyncFeatureMessages(*this, MessageContext{connection->proxyClientSocket()}); +} + + + +void ComputerControlServer::updateTrayIconToolTip() +{ + if (VeyonCore::platform().sessionFunctions().currentSessionHasUser() == false) + { + return; + } + + auto toolTip = tr( "%1 Service %2 at %3:%4" ).arg( VeyonCore::applicationName(), VeyonCore::versionString(), + HostAddress::localFQDN(), + QString::number( VeyonCore::config().veyonServerPort() + VeyonCore::sessionId() ) ); + + QMutexLocker locker( &m_dataMutex ); + + QStringList clients; + QStringList hostsToResolve; + clients.reserve( m_vncProxyServer.clients().size() ); + hostsToResolve.reserve( m_vncProxyServer.clients().size() ); + + for( const auto* client : m_vncProxyServer.clients() ) + { + const auto clientIpAddress = client->proxyClientSocket()->peerAddress().toString(); + if( m_resolvedHostNames.contains( clientIpAddress ) == false ) + { + hostsToResolve.append( clientIpAddress ); + clients.append( clientIpAddress ); + } + else + { + clients.append( m_resolvedHostNames[clientIpAddress] ); + } + } + + if( hostsToResolve.isEmpty() == false ) + { + auto watcher = resolveFQDNs( hostsToResolve ); + connect( watcher, &QFutureWatcher::finished, this, &ComputerControlServer::updateTrayIconToolTip ); + } + + if( clients.isEmpty() == false ) + { + toolTip += QLatin1Char('\n') + tr( "Active connections:") + QLatin1Char('\n') + clients.join( QLatin1Char('\n') ); + } + + VeyonCore::builtinFeatures().systemTrayIcon().setToolTip( toolTip, m_featureWorkerManager ); +} diff --git a/server/src/ComputerControlServer.h b/server/src/ComputerControlServer.h index 2f2fc5233..74fcdfb66 100644 --- a/server/src/ComputerControlServer.h +++ b/server/src/ComputerControlServer.h @@ -1,7 +1,7 @@ /* * ComputerControlServer.h - header file for ComputerControlServer * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,12 +24,10 @@ #pragma once -#include -#include +#include +#include -#include "FeatureManager.h" #include "FeatureWorkerManager.h" -#include "RfbVeyonAuth.h" #include "ServerAuthenticationManager.h" #include "ServerAccessControlManager.h" #include "VeyonServerInterface.h" @@ -37,7 +35,9 @@ #include "VncProxyConnectionFactory.h" #include "VncServer.h" -class ComputerControlServer : public QObject, VncProxyConnectionFactory, VeyonServerInterface +class ComputerControlClient; + +class ComputerControlServer : public VeyonServerInterface, VncProxyConnectionFactory { Q_OBJECT public: @@ -48,7 +48,7 @@ class ComputerControlServer : public QObject, VncProxyConnectionFactory, VeyonSe VncProxyConnection* createVncProxyConnection( QTcpSocket* clientSocket, int vncServerPort, - const QString& vncServerPassword, + const Password& vncServerPassword, QObject* parent ) override; ServerAuthenticationManager& authenticationManager() @@ -61,7 +61,7 @@ class ComputerControlServer : public QObject, VncProxyConnectionFactory, VeyonSe return m_serverAccessControlManager; } - bool handleFeatureMessage( QTcpSocket* socket ); + bool handleFeatureMessage(ComputerControlClient* client); bool sendFeatureMessageReply( const MessageContext& context, const FeatureMessage& reply ) override; @@ -70,24 +70,36 @@ class ComputerControlServer : public QObject, VncProxyConnectionFactory, VeyonSe return m_featureWorkerManager; } + int vncServerBasePort() const override + { + return m_vncServer.serverBasePort(); + } + + void setMinimumFramebufferUpdateInterval(const MessageContext& context, int interval) override; private: + void checkForIncompleteAuthentication( VncServerClient* client ); void showAuthenticationMessage( VncServerClient* client ); void showAccessControlMessage( VncServerClient* client ); + QFutureWatcher* resolveFQDNs( const QStringList& hosts ); + + void sendAsyncFeatureMessages(VncProxyConnection* connection); + void updateTrayIconToolTip(); + + QMutex m_dataMutex{}; + QStringList m_allowedIPs{}; - QMutex m_dataMutex; - QStringList m_allowedIPs; + QMap m_resolvedHostNames; - QStringList m_failedAuthHosts; - QStringList m_failedAccessControlHosts; + QStringList m_failedAuthHosts{}; + QStringList m_failedAccessControlHosts{}; - FeatureManager m_featureManager; FeatureWorkerManager m_featureWorkerManager; ServerAuthenticationManager m_serverAuthenticationManager; ServerAccessControlManager m_serverAccessControlManager; - VncServer m_vncServer; + VncServer m_vncServer{}; VncProxyServer m_vncProxyServer; } ; diff --git a/server/src/ServerAccessControlManager.cpp b/server/src/ServerAccessControlManager.cpp index f35e98710..308df349b 100644 --- a/server/src/ServerAccessControlManager.cpp +++ b/server/src/ServerAccessControlManager.cpp @@ -1,7 +1,7 @@ /* * ServerAccessControlManager.cpp - implementation of ServerAccessControlManager * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,13 +22,11 @@ * */ -#include "VeyonCore.h" - +#include "BuiltinFeatures.h" #include "ServerAccessControlManager.h" #include "AccessControlProvider.h" +#include "AuthenticationManager.h" #include "DesktopAccessDialog.h" -#include "VeyonConfiguration.h" -#include "VariantArrayMessage.h" ServerAccessControlManager::ServerAccessControlManager( FeatureWorkerManager& featureWorkerManager, @@ -36,9 +34,7 @@ ServerAccessControlManager::ServerAccessControlManager( FeatureWorkerManager& fe QObject* parent ) : QObject( parent ), m_featureWorkerManager( featureWorkerManager ), - m_desktopAccessDialog( desktopAccessDialog ), - m_clients(), - m_desktopAccessChoices() + m_desktopAccessDialog( desktopAccessDialog ) { } @@ -46,22 +42,22 @@ ServerAccessControlManager::ServerAccessControlManager( FeatureWorkerManager& fe void ServerAccessControlManager::addClient( VncServerClient* client ) { - switch( client->authType() ) + const auto plugins = VeyonCore::authenticationManager().plugins(); + if( plugins.contains( client->authMethodUid() ) ) + { + if( plugins[client->authMethodUid()]->requiresAccessControl() ) + { + performAccessControl( client ); + } + else + { + client->setAccessControlState( VncServerClient::AccessControlState::Successful ); + } + } + else { - case RfbVeyonAuth::KeyFile: - case RfbVeyonAuth::Logon: - performAccessControl( client ); - break; - - case RfbVeyonAuth::None: - case RfbVeyonAuth::Token: - client->setAccessControlState( VncServerClient::AccessControlState::Successful ); - break; - - default: - // reject unknown auth type client->setAccessControlState( VncServerClient::AccessControlState::Failed ); - break; + client->setAccessControlDetails(tr("Requested authentication method not available")); } if( client->accessControlState() == VncServerClient::AccessControlState::Successful ) @@ -77,21 +73,21 @@ void ServerAccessControlManager::removeClient( VncServerClient* client ) m_clients.removeAll( client ); // force all remaining clients to pass access control again as conditions might - // have changed (e.g. AccessControlRule::ConditionAccessFromAlreadyConnectedUser) + // have changed (e.g. AccessControlRule::Condition::AccessFromAlreadyConnectedUser) const VncServerClientList previousClients = m_clients; m_clients.clear(); - for( auto prevClient : qAsConst( previousClients ) ) + for( auto prevClient : std::as_const( previousClients ) ) { prevClient->setAccessControlState( VncServerClient::AccessControlState::Init ); addClient( prevClient ); if( prevClient->accessControlState() != VncServerClient::AccessControlState::Successful && - prevClient->accessControlState() != VncServerClient::AccessControlState::Pending ) + prevClient->accessControlState() != VncServerClient::AccessControlState::Pending ) { vDebug() << "closing connection as client does not pass access control any longer"; - prevClient->setProtocolState( VncServerProtocol::Close ); + prevClient->setProtocolState( VncServerProtocol::State::Close ); } } } @@ -118,15 +114,20 @@ void ServerAccessControlManager::performAccessControl( VncServerClient* client ) break; } - const auto accessResult = - AccessControlProvider().checkAccess( client->username(), - client->hostAddress(), - connectedUsers() ); + const auto checkResult = VeyonCore::builtinFeatures().accessControlProvider() + .checkAccess(client->username(), + client->hostAddress(), + connectedUsers(), + client->authMethodUid()); - switch( accessResult ) + switch (checkResult.access) { case AccessControlProvider::Access::Allow: client->setAccessControlState( VncServerClient::AccessControlState::Successful ); + if (checkResult.matchedRule) + { + client->setAccessControlDetails(tr("Access allowed by rule \"%1\"").arg(checkResult.matchedRule->name())); + } break; case AccessControlProvider::Access::ToBeConfirmed: @@ -135,11 +136,23 @@ void ServerAccessControlManager::performAccessControl( VncServerClient* client ) default: client->setAccessControlState( VncServerClient::AccessControlState::Failed ); - client->setProtocolState( VncServerProtocol::Close ); + client->setProtocolState( VncServerProtocol::State::Close ); + if (checkResult.reason == AccessControlProvider::Reason::AccessControlRuleMatched && checkResult.matchedRule) + { + client->setAccessControlDetails(tr("Access denied by rule \"%1\"").arg(checkResult.matchedRule->name())); + } + else if (checkResult.reason == AccessControlProvider::Reason::NoAccessControlRuleMatched) + { + client->setAccessControlDetails(tr("No rule allowed access")); + } + else if (checkResult.reason == AccessControlProvider::Reason::UserNotInAuthorizedUserGroups) + { + client->setAccessControlDetails(tr("Accessing user not member of an authorized user group")); + } break; } - emit finished( client ); + Q_EMIT finished( client ); } @@ -151,11 +164,12 @@ VncServerClient::AccessControlState ServerAccessControlManager::confirmDesktopAc // did we save a previous choice because user chose "always" or "never"? if( m_desktopAccessChoices.contains( hostUserPair ) ) { - if( qAsConst(m_desktopAccessChoices)[hostUserPair] == DesktopAccessDialog::ChoiceAlways ) + if( std::as_const(m_desktopAccessChoices)[hostUserPair] == DesktopAccessDialog::ChoiceAlways ) { return VncServerClient::AccessControlState::Successful; } + client->setAccessControlDetails(tr("User has denied access")); return VncServerClient::AccessControlState::Failed; } @@ -189,7 +203,7 @@ void ServerAccessControlManager::finishDesktopAccessConfirmation( VncServerClien { // break helper connections for asynchronous desktop access control operations if( m_desktopAccessDialog.disconnect( client ) == false || - client->disconnect( this ) == false ) + client->disconnect( this ) == false ) { vCritical() << "could not break object connections"; } @@ -206,12 +220,13 @@ void ServerAccessControlManager::finishDesktopAccessConfirmation( VncServerClien if( choice == DesktopAccessDialog::ChoiceYes || choice == DesktopAccessDialog::ChoiceAlways ) { client->setAccessControlState( VncServerClient::AccessControlState::Successful ); + client->setAccessControlDetails(tr("User confirmed access")); m_clients.append( client ); } else { client->setAccessControlState( VncServerClient::AccessControlState::Failed ); - client->setProtocolState( VncServerProtocol::Close ); + client->setAccessControlDetails(tr("User has denied access")); } } diff --git a/server/src/ServerAccessControlManager.h b/server/src/ServerAccessControlManager.h index c2fd86d79..a7e56d74d 100644 --- a/server/src/ServerAccessControlManager.h +++ b/server/src/ServerAccessControlManager.h @@ -1,7 +1,7 @@ /* * ServerAccessControlManager.h - header file for ServerAccessControlManager * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,7 +25,6 @@ #pragma once #include "DesktopAccessDialog.h" -#include "RfbVeyonAuth.h" #include "VncServerClient.h" class VariantArrayMessage; @@ -42,7 +41,7 @@ class ServerAccessControlManager : public QObject void removeClient( VncServerClient* client ); -signals: +Q_SIGNALS: void finished( VncServerClient* client ); private: @@ -57,11 +56,11 @@ class ServerAccessControlManager : public QObject FeatureWorkerManager& m_featureWorkerManager; DesktopAccessDialog& m_desktopAccessDialog; - VncServerClientList m_clients; + VncServerClientList m_clients{}; using HostUserPair = QPair; using DesktopAccessChoiceMap = QMap; - DesktopAccessChoiceMap m_desktopAccessChoices; + DesktopAccessChoiceMap m_desktopAccessChoices{}; } ; diff --git a/server/src/ServerAuthenticationManager.cpp b/server/src/ServerAuthenticationManager.cpp index d8e4c2c8c..8f70b2613 100644 --- a/server/src/ServerAuthenticationManager.cpp +++ b/server/src/ServerAuthenticationManager.cpp @@ -1,7 +1,7 @@ /* * ServerAuthenticationManager.cpp - implementation of ServerAuthenticationManager * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,12 +22,8 @@ * */ -#include "AuthenticationCredentials.h" +#include "AuthenticationManager.h" #include "ServerAuthenticationManager.h" -#include "CryptoCore.h" -#include "Filesystem.h" -#include "PlatformUserFunctions.h" -#include "VariantArrayMessage.h" #include "VeyonConfiguration.h" @@ -38,210 +34,33 @@ ServerAuthenticationManager::ServerAuthenticationManager( QObject* parent ) : -QVector ServerAuthenticationManager::supportedAuthTypes() const -{ - QVector authTypes; - - if( VeyonCore::config().authenticationMethod() == VeyonCore::AuthenticationMethod::KeyFileAuthentication ) - { - authTypes.append( RfbVeyonAuth::KeyFile ); - } - - if( VeyonCore::config().authenticationMethod() == VeyonCore::AuthenticationMethod::LogonAuthentication ) - { - authTypes.append( RfbVeyonAuth::Logon ); - } - - if( VeyonCore::authenticationCredentials().hasCredentials( AuthenticationCredentials::Type::Token ) ) - { - authTypes.append( RfbVeyonAuth::Token ); - } - - return authTypes; -} - - - void ServerAuthenticationManager::processAuthenticationMessage( VncServerClient* client, VariantArrayMessage& message ) { vDebug() << "state" << client->authState() - << "type" << client->authType() + << "plugin" << client->authMethodUid() << "host" << client->hostAddress() << "user" << client->username(); - switch( client->authType() ) - { - // no authentication - case RfbVeyonAuth::None: - client->setAuthState( VncServerClient::AuthState::Successful ); - break; - - // authentication via DSA-challenge/-response - case RfbVeyonAuth::KeyFile: - client->setAuthState( performKeyAuthentication( client, message ) ); - break; - - case RfbVeyonAuth::Logon: - client->setAuthState( performLogonAuthentication( client, message ) ); - break; - - case RfbVeyonAuth::Token: - client->setAuthState( performTokenAuthentication( client, message ) ); - break; - - default: - // unknown or unsupported auth type - client->setAuthState( VncServerClient::AuthState::Failed ); - break; - } + auto authPlugin = VeyonCore::authenticationManager().plugins().value( client->authMethodUid() ); - switch( client->authState() ) + if( authPlugin && + VeyonCore::authenticationManager().isEnabled( client->authMethodUid() ) ) { - case VncServerClient::AuthState::Failed: - case VncServerClient::AuthState::Successful: - emit finished( client ); - default: - break; + client->setAuthState( authPlugin->performAuthentication( client, message ) ); } -} - - - -VncServerClient::AuthState ServerAuthenticationManager::performKeyAuthentication( VncServerClient* client, - VariantArrayMessage& message ) -{ - switch( client->authState() ) + else { - case VncServerClient::AuthState::Init: - client->setChallenge( CryptoCore::generateChallenge() ); - if( VariantArrayMessage( message.ioDevice() ).write( client->challenge() ).send() == false ) - { - vWarning() << "failed to send challenge"; - return VncServerClient::AuthState::Failed; - } - return VncServerClient::AuthState::Challenge; - - case VncServerClient::AuthState::Challenge: - { - // get authentication key name - const auto authKeyName = message.read().toString(); // Flawfinder: ignore - - if( VeyonCore::isAuthenticationKeyNameValid( authKeyName ) == false ) - { - vDebug() << "invalid auth key name!"; - return VncServerClient::AuthState::Failed; - } - - // now try to verify received signed data using public key of the user - // under which the client claims to run - const auto signature = message.read().toByteArray(); // Flawfinder: ignore - - const auto publicKeyPath = VeyonCore::filesystem().publicKeyPath( authKeyName ); - - vDebug() << "loading public key" << publicKeyPath; - CryptoCore::PublicKey publicKey( publicKeyPath ); - - if( publicKey.isNull() || publicKey.isPublic() == false || - publicKey.verifyMessage( client->challenge(), signature, CryptoCore::DefaultSignatureAlgorithm ) == false ) - { - vWarning() << "FAIL"; - return VncServerClient::AuthState::Failed; - } - - vDebug() << "SUCCESS"; - return VncServerClient::AuthState::Successful; - } - - default: - break; + client->setAuthState( VncServerClient::AuthState::Failed ); } - return VncServerClient::AuthState::Failed; -} - - - -VncServerClient::AuthState ServerAuthenticationManager::performLogonAuthentication( VncServerClient* client, - VariantArrayMessage& message ) -{ switch( client->authState() ) { - case VncServerClient::AuthState::Init: - client->setPrivateKey( CryptoCore::KeyGenerator().createRSA( CryptoCore::RsaKeySize ) ); - - if( VariantArrayMessage( message.ioDevice() ).write( client->privateKey().toPublicKey().toPEM() ).send() ) - { - return VncServerClient::AuthState::Password; - } - - vDebug() << "failed to send public key"; - return VncServerClient::AuthState::Failed; - - case VncServerClient::AuthState::Password: - { - auto privateKey = client->privateKey(); - - CryptoCore::SecureArray encryptedPassword( message.read().toByteArray() ); // Flawfinder: ignore - - CryptoCore::SecureArray decryptedPassword; - - if( privateKey.decrypt( encryptedPassword, - &decryptedPassword, - CryptoCore::DefaultEncryptionAlgorithm ) == false ) - { - vWarning() << "failed to decrypt password"; - return VncServerClient::AuthState::Failed; - } - - vInfo() << "authenticating user" << client->username(); - - if( VeyonCore::platform().userFunctions().authenticate( client->username(), - QString::fromUtf8( decryptedPassword.toByteArray() ) ) ) - { - vDebug() << "SUCCESS"; - return VncServerClient::AuthState::Successful; - } - - vDebug() << "FAIL"; - return VncServerClient::AuthState::Failed; - } - - default: + case VncServerClient::AuthState::Failed: + case VncServerClient::AuthState::Successful: + Q_EMIT finished( client ); break; - } - - return VncServerClient::AuthState::Failed; -} - - - -VncServerClient::AuthState ServerAuthenticationManager::performTokenAuthentication( VncServerClient* client, - VariantArrayMessage& message ) -{ - switch( client->authState() ) - { - case VncServerClient::AuthState::Init: - return VncServerClient::AuthState::Token; - - case VncServerClient::AuthState::Token: - { - const auto token = message.read().toString(); // Flawfinder: ignore - - if( VeyonCore::authenticationCredentials().hasCredentials( AuthenticationCredentials::Type::Token ) && - token == VeyonCore::authenticationCredentials().token() ) - { - vDebug() << "SUCCESS"; - return VncServerClient::AuthState::Successful; - } - - vDebug() << "FAIL"; - return VncServerClient::AuthState::Failed; - } - default: break; } - - return VncServerClient::AuthState::Failed; } diff --git a/server/src/ServerAuthenticationManager.h b/server/src/ServerAuthenticationManager.h index a7860c20a..0b757be90 100644 --- a/server/src/ServerAuthenticationManager.h +++ b/server/src/ServerAuthenticationManager.h @@ -1,7 +1,7 @@ /* * ServerAuthenticationManager.h - header file for ServerAuthenticationManager * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,7 +27,6 @@ #include #include -#include "RfbVeyonAuth.h" #include "VncServerClient.h" class VariantArrayMessage; @@ -44,18 +43,11 @@ class ServerAuthenticationManager : public QObject explicit ServerAuthenticationManager( QObject* parent ); - QVector supportedAuthTypes() const; - void processAuthenticationMessage( VncServerClient* client, VariantArrayMessage& message ); -signals: +Q_SIGNALS: void finished( VncServerClient* client ); -private: - VncServerClient::AuthState performKeyAuthentication( VncServerClient* client, VariantArrayMessage& message ); - VncServerClient::AuthState performLogonAuthentication( VncServerClient* client, VariantArrayMessage& message ); - VncServerClient::AuthState performTokenAuthentication( VncServerClient* client, VariantArrayMessage& message ); - } ; diff --git a/server/src/TlsServer.cpp b/server/src/TlsServer.cpp new file mode 100644 index 000000000..fe721a3ab --- /dev/null +++ b/server/src/TlsServer.cpp @@ -0,0 +1,85 @@ +/* + * TlsServer.cpp - header file for TlsServer + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include +#include + +#include "TlsServer.h" + + +TlsServer::TlsServer( const VeyonCore::TlsConfiguration& tlsConfig, QObject* parent ) : + QTcpServer( parent ), + m_tlsConfig( tlsConfig ) +{ +} + + + +void TlsServer::incomingConnection( qintptr socketDescriptor ) +{ + if( m_tlsConfig.localCertificate().isNull() || m_tlsConfig.privateKey().isNull() ) + { + auto socket = new QTcpSocket; + if( socket->setSocketDescriptor(socketDescriptor) ) + { + vDebug() << "accepting unencrypted connection for socket" << socketDescriptor; + addPendingConnection( socket ); + } + else + { + vCritical() << "failed to set socket descriptor for incoming non-TLS connection"; + delete socket; + } + } + else + { + auto socket = new QSslSocket; + if( socket->setSocketDescriptor(socketDescriptor) ) + { + connect(socket, QOverload&>::of(&QSslSocket::sslErrors), + [this, socket]( const QList &errors) { + for( const auto& err : errors ) + { + vCritical() << "SSL error" << err; + } + + Q_EMIT tlsErrors( socket, errors ); + } ); + + connect(socket, &QSslSocket::encrypted, this, + []() { vDebug() << "connection encryption established"; } ); + + socket->setSslConfiguration( m_tlsConfig ); + socket->startServerEncryption(); + + vDebug() << "establishing TLS connection for socket" << socketDescriptor; + addPendingConnection( socket ); + } + else + { + vCritical() << "failed to set socket descriptor for incoming TLS connection"; + delete socket; + } + } +} diff --git a/server/src/TlsServer.h b/server/src/TlsServer.h new file mode 100644 index 000000000..eb77b08c2 --- /dev/null +++ b/server/src/TlsServer.h @@ -0,0 +1,48 @@ +/* + * TlsServer.h - header file for TlsServer + * + * Copyright (c) 2021-2025 Tobias Junghans + * + * This file is part of Veyon - https://veyon.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include +#include + +#include "VeyonCore.h" + +class TlsServer : public QTcpServer +{ + Q_OBJECT +public: + TlsServer( const VeyonCore::TlsConfiguration& tlsConfig, QObject* parent = nullptr ); + ~TlsServer() override = default; + +protected: + void incomingConnection( qintptr socketDescriptor ) override; + +private: + VeyonCore::TlsConfiguration m_tlsConfig; + +Q_SIGNALS: + void tlsErrors( QSslSocket* socket, const QList& errors ); + +} ; diff --git a/server/src/VeyonServerProtocol.cpp b/server/src/VeyonServerProtocol.cpp index b9dc01231..8c861610b 100644 --- a/server/src/VeyonServerProtocol.cpp +++ b/server/src/VeyonServerProtocol.cpp @@ -1,7 +1,7 @@ /* * VeyonServerProtocol.cpp - implementation of the VeyonServerProtocol class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,9 +22,13 @@ * */ +#include + +#include "AuthenticationManager.h" #include "ServerAuthenticationManager.h" #include "ServerAccessControlManager.h" #include "VeyonServerProtocol.h" +#include "VeyonConfiguration.h" VeyonServerProtocol::VeyonServerProtocol( QTcpSocket* socket, @@ -39,14 +43,27 @@ VeyonServerProtocol::VeyonServerProtocol( QTcpSocket* socket, -QVector VeyonServerProtocol::supportedAuthTypes() const +VeyonServerProtocol::AuthMethodUids VeyonServerProtocol::supportedAuthMethodUids() const { - return m_serverAuthenticationManager.supportedAuthTypes(); + const auto authPlugins = VeyonCore::authenticationManager().plugins(); + + AuthMethodUids authMethodUids; + authMethodUids.reserve( authPlugins.size() ); + + for( auto it = authPlugins.constBegin(), end = authPlugins.constEnd(); it != end; ++it ) + { + if( VeyonCore::authenticationManager().isEnabled( it.key() ) ) + { + authMethodUids.append( it.key() ); + } + } + + return authMethodUids; } -void VeyonServerProtocol::processAuthenticationMessage(VariantArrayMessage &message) +void VeyonServerProtocol::processAuthenticationMessage( VariantArrayMessage& message ) { m_serverAuthenticationManager.processAuthenticationMessage( client(), message ); } @@ -59,7 +76,7 @@ void VeyonServerProtocol::performAccessControl() // client just entered access control or is still waiting to be // processed (e.g. desktop access dialog already active for a different connection) if( client()->accessControlState() == VncServerClient::AccessControlState::Init || - client()->accessControlState() == VncServerClient::AccessControlState::Waiting ) + client()->accessControlState() == VncServerClient::AccessControlState::Waiting ) { m_serverAccessControlManager.addClient( client() ); } diff --git a/server/src/VeyonServerProtocol.h b/server/src/VeyonServerProtocol.h index 3ffe50e39..57fb24954 100644 --- a/server/src/VeyonServerProtocol.h +++ b/server/src/VeyonServerProtocol.h @@ -1,7 +1,7 @@ /* * VeyonServerProtocol.h - header file for the VeyonServerProtocol class * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -26,6 +26,8 @@ #include "VncServerProtocol.h" +class QTcpSocket; + class ServerAuthenticationManager; class ServerAccessControlManager; @@ -40,7 +42,7 @@ class VeyonServerProtocol : public VncServerProtocol ServerAccessControlManager& serverAccessControlManager ); protected: - QVector supportedAuthTypes() const override; + AuthMethodUids supportedAuthMethodUids() const override; void processAuthenticationMessage( VariantArrayMessage& message ) override; void performAccessControl() override; diff --git a/server/src/VncProxyConnection.cpp b/server/src/VncProxyConnection.cpp index 51375896e..cca7a3626 100644 --- a/server/src/VncProxyConnection.cpp +++ b/server/src/VncProxyConnection.cpp @@ -1,7 +1,7 @@ /* * VncProxyConnection.cpp - class representing a connection within VncProxyServer * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -35,23 +35,21 @@ VncProxyConnection::VncProxyConnection( QTcpSocket* clientSocket, int vncServerPort, QObject* parent ) : QObject( parent ), + m_vncServerPort( vncServerPort ), m_proxyClientSocket( clientSocket ), m_vncServerSocket( new QTcpSocket( this ) ), m_rfbClientToServerMessageSizes( { - std::pair( rfbSetPixelFormat, sz_rfbSetPixelFormatMsg ), - std::pair( rfbFramebufferUpdateRequest, sz_rfbFramebufferUpdateRequestMsg ), - std::pair( rfbKeyEvent, sz_rfbKeyEventMsg ), - std::pair( rfbPointerEvent, sz_rfbPointerEventMsg ), - std::pair( rfbXvp, sz_rfbXvpMsg ), - } ) + { rfbFramebufferUpdateRequest, sz_rfbFramebufferUpdateRequestMsg }, + { rfbKeyEvent, sz_rfbKeyEventMsg }, + { rfbPointerEvent, sz_rfbPointerEventMsg }, + { rfbXvp, sz_rfbXvpMsg }, + } ) { connect( m_proxyClientSocket, &QTcpSocket::readyRead, this, &VncProxyConnection::readFromClient ); connect( m_vncServerSocket, &QTcpSocket::readyRead, this, &VncProxyConnection::readFromServer ); connect( m_vncServerSocket, &QTcpSocket::disconnected, this, &VncProxyConnection::clientConnectionClosed ); connect( m_proxyClientSocket, &QTcpSocket::disconnected, this, &VncProxyConnection::serverConnectionClosed ); - - m_vncServerSocket->connectToHost( QHostAddress::LocalHost, static_cast( vncServerPort ) ); } @@ -68,9 +66,16 @@ VncProxyConnection::~VncProxyConnection() +void VncProxyConnection::start() +{ + serverProtocol().start(); +} + + + void VncProxyConnection::readFromClient() { - if( serverProtocol().state() != VncServerProtocol::Running ) + if( serverProtocol().state() != VncServerProtocol::State::Running ) { while( serverProtocol().read() ) // Flawfinder: ignore { @@ -81,7 +86,7 @@ void VncProxyConnection::readFromClient() // and already have RFB messages in receive queue readFromClientLater(); } - else if( clientProtocol().state() == VncClientProtocol::Running ) + else if( clientProtocol().state() == VncClientProtocol::State::Running ) { while( receiveClientMessage() ) { @@ -92,13 +97,21 @@ void VncProxyConnection::readFromClient() // try again as client connection is not yet ready and we can't forward data readFromClientLater(); } + + if( serverProtocol().state() == VncServerProtocol::State::FramebufferInit && + clientProtocol().state() == VncClientProtocol::State::Disconnected ) + { + m_vncServerSocket->connectToHost( QHostAddress::LocalHost, quint16(m_vncServerPort) ); + + clientProtocol().start(); + } } void VncProxyConnection::readFromServer() { - if( clientProtocol().state() != VncClientProtocol::Running ) + if( clientProtocol().state() != VncClientProtocol::State::Running ) { while( clientProtocol().read() ) // Flawfinder: ignore { @@ -107,7 +120,7 @@ void VncProxyConnection::readFromServer() // did we finish client protocol initialization? then we must not miss this // read signaĺ from server but process it as the server is still waiting // for our response - if( clientProtocol().state() == VncClientProtocol::Running ) + if( clientProtocol().state() == VncClientProtocol::State::Running ) { // if client protocol is running we have the server init message which // we can forward to the real client @@ -116,10 +129,11 @@ void VncProxyConnection::readFromServer() readFromServerLater(); } } - else if( serverProtocol().state() == VncServerProtocol::Running ) + else if( serverProtocol().state() == VncServerProtocol::State::Running ) { while( receiveServerMessage() ) { + Q_EMIT serverMessageProcessed(); } } else @@ -207,6 +221,23 @@ bool VncProxyConnection::receiveClientMessage() } break; + case rfbSetPixelFormat: + if (socket->bytesAvailable() >= sz_rfbSetPixelFormatMsg) + { + rfbSetPixelFormatMsg setPixelFormatMessage; + if (socket->peek(reinterpret_cast(&setPixelFormatMessage), sz_rfbSetPixelFormatMsg) == sz_rfbSetPixelFormatMsg) + { + auto format = setPixelFormatMessage.format; + format.redMax = qFromBigEndian(format.redMax); + format.greenMax = qFromBigEndian(format.greenMax); + format.blueMax = qFromBigEndian(format.blueMax); + clientProtocol().setPixelFormat(format); + + return forwardDataToServer(sz_rfbSetPixelFormatMsg); + } + } + break; + default: if( m_rfbClientToServerMessageSizes.contains( messageType ) == false ) { diff --git a/server/src/VncProxyConnection.h b/server/src/VncProxyConnection.h index f3840b9ee..6ab62feb0 100644 --- a/server/src/VncProxyConnection.h +++ b/server/src/VncProxyConnection.h @@ -1,7 +1,7 @@ /* * VncProxyConnection.h - class representing a connection within VncProxyServer * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,7 +24,7 @@ #pragma once -#include "VeyonCore.h" +#include class QBuffer; class QTcpSocket; @@ -36,24 +36,22 @@ class VncProxyConnection : public QObject { Q_OBJECT public: - enum { - ProtocolRetryTime = 250 - }; - VncProxyConnection( QTcpSocket* clientSocket, int vncServerPort, QObject* parent ); ~VncProxyConnection() override; - QTcpSocket* proxyClientSocket() + void start(); + + QTcpSocket* proxyClientSocket() const { return m_proxyClientSocket; } - QTcpSocket* vncServerSocket() + QTcpSocket* vncServerSocket() const { return m_vncServerSocket; } -protected slots: +protected Q_SLOTS: void readFromClient(); void readFromServer(); @@ -71,13 +69,18 @@ protected slots: virtual VncServerProtocol& serverProtocol() = 0; private: + static constexpr int ProtocolRetryTime = 250; + + const int m_vncServerPort; + QTcpSocket* m_proxyClientSocket; QTcpSocket* m_vncServerSocket; const QMap m_rfbClientToServerMessageSizes; -signals: +Q_SIGNALS: void clientConnectionClosed(); void serverConnectionClosed(); + void serverMessageProcessed(); } ; diff --git a/server/src/VncProxyConnectionFactory.h b/server/src/VncProxyConnectionFactory.h index 88b2327c6..b036f3d9f 100644 --- a/server/src/VncProxyConnectionFactory.h +++ b/server/src/VncProxyConnectionFactory.h @@ -1,7 +1,7 @@ /* * VncProxyConnectionFactory.h - abstract factory class for VncProxyConnectionFactory objects * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,7 +24,8 @@ #pragma once -class QObject; +#include "CryptoCore.h" + class QTcpSocket; class VncProxyConnection; @@ -33,9 +34,13 @@ class VncProxyConnection; class VncProxyConnectionFactory { public: + using Password = CryptoCore::PlaintextPassword; + + virtual ~VncProxyConnectionFactory() = default; + virtual VncProxyConnection* createVncProxyConnection( QTcpSocket* clientSocket, int vncServerPort, - const QString& vncServerPassword, + const Password& vncServerPassword, QObject* parent ) = 0; } ; diff --git a/server/src/VncProxyServer.cpp b/server/src/VncProxyServer.cpp index 0a792bbab..39a499aca 100644 --- a/server/src/VncProxyServer.cpp +++ b/server/src/VncProxyServer.cpp @@ -1,7 +1,7 @@ /* * VncProxyServer.cpp - a VNC proxy implementation for intercepting VNC connections * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,9 +22,9 @@ * */ -#include #include +#include "TlsServer.h" #include "VeyonCore.h" #include "VncProxyServer.h" #include "VncProxyConnection.h" @@ -36,14 +36,13 @@ VncProxyServer::VncProxyServer( const QHostAddress& listenAddress, VncProxyConnectionFactory* connectionFactory, QObject* parent ) : QObject( parent ), - m_vncServerPort( -1 ), - m_vncServerPassword(), m_listenAddress( listenAddress ), m_listenPort( listenPort ), - m_server( new QTcpServer( this ) ), + m_server( new TlsServer( VeyonCore::TlsConfiguration::defaultConfiguration(), this ) ), m_connectionFactory( connectionFactory ) { connect( m_server, &QTcpServer::newConnection, this, &VncProxyServer::acceptConnection ); + connect( m_server, &QTcpServer::acceptError, this, &VncProxyServer::handleAcceptError ); } @@ -55,7 +54,7 @@ VncProxyServer::~VncProxyServer() -bool VncProxyServer::start( int vncServerPort, const QString& vncServerPassword ) +bool VncProxyServer::start( int vncServerPort, const Password& vncServerPassword ) { m_vncServerPort = vncServerPort; m_vncServerPassword = vncServerPassword; @@ -72,9 +71,10 @@ bool VncProxyServer::start( int vncServerPort, const QString& vncServerPassword } + void VncProxyServer::stop() { - for( auto connection : qAsConst( m_connections ) ) + for( auto connection : std::as_const( m_connections ) ) { delete connection; } @@ -89,15 +89,26 @@ void VncProxyServer::stop() void VncProxyServer::acceptConnection() { - VncProxyConnection* connection = - m_connectionFactory->createVncProxyConnection( m_server->nextPendingConnection(), - m_vncServerPort, - m_vncServerPassword, - this ); + auto clientSocket = m_server->nextPendingConnection(); + if( clientSocket == nullptr ) + { + vCritical() << "ignoring invalid client socket"; + return; + } + + auto connection = m_connectionFactory->createVncProxyConnection( clientSocket, + m_vncServerPort, + m_vncServerPassword, + this ); + + connect(connection, &VncProxyConnection::serverMessageProcessed, this, + [=]() { Q_EMIT serverMessageProcessed(connection); }, Qt::DirectConnection ); connect( connection, &VncProxyConnection::clientConnectionClosed, this, [=]() { closeConnection( connection ); } ); connect( connection, &VncProxyConnection::serverConnectionClosed, this, [=]() { closeConnection( connection ); } ); + connection->start(); + m_connections += connection; } @@ -107,5 +118,14 @@ void VncProxyServer::closeConnection( VncProxyConnection* connection ) { m_connections.removeAll( connection ); + Q_EMIT connectionClosed( connection ); + connection->deleteLater(); } + + + +void VncProxyServer::handleAcceptError( QAbstractSocket::SocketError socketError ) +{ + vCritical() << "error while accepting connection" << socketError; +} diff --git a/server/src/VncProxyServer.h b/server/src/VncProxyServer.h index 29ab25bd4..5693cb57e 100644 --- a/server/src/VncProxyServer.h +++ b/server/src/VncProxyServer.h @@ -1,7 +1,7 @@ /* * VncProxyServer.h - a VNC proxy implementation for intercepting VNC connections * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,7 +27,9 @@ #include #include -class QTcpServer; +#include "CryptoCore.h" + +class TlsServer; class VncProxyConnection; class VncProxyConnectionFactory; @@ -35,6 +37,7 @@ class VncProxyServer : public QObject { Q_OBJECT public: + using Password = CryptoCore::PlaintextPassword; using VncProxyConnectionList = QVector; VncProxyServer( const QHostAddress& listenAddress, @@ -43,7 +46,7 @@ class VncProxyServer : public QObject QObject* parent = nullptr ); ~VncProxyServer() override; - bool start( int vncServerPort, const QString& vncServerPassword ); + bool start( int vncServerPort, const Password& vncServerPassword ); void stop(); const VncProxyConnectionList& clients() const @@ -51,15 +54,20 @@ class VncProxyServer : public QObject return m_connections; } +Q_SIGNALS: + void serverMessageProcessed(VncProxyConnection* connection); + void connectionClosed( VncProxyConnection* connection ); + private: void acceptConnection(); void closeConnection( VncProxyConnection* ); + void handleAcceptError( QAbstractSocket::SocketError socketError ); - int m_vncServerPort; - QString m_vncServerPassword; + int m_vncServerPort{-1}; + Password m_vncServerPassword{}; QHostAddress m_listenAddress; int m_listenPort; - QTcpServer* m_server; + TlsServer* m_server; VncProxyConnectionFactory* m_connectionFactory; VncProxyConnectionList m_connections; diff --git a/server/src/VncServer.cpp b/server/src/VncServer.cpp index 0e41f9472..a8dd36d52 100644 --- a/server/src/VncServer.cpp +++ b/server/src/VncServer.cpp @@ -2,7 +2,7 @@ * VncServer.cpp - implementation of VncServer, a VNC-server- * abstraction for platform independent VNC-server-usage * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -28,6 +28,8 @@ #include "AuthenticationCredentials.h" #include "CryptoCore.h" #include "VeyonConfiguration.h" +#include "PlatformPluginInterface.h" +#include "PlatformSessionFunctions.h" #include "PluginManager.h" #include "VncServer.h" #include "VncServerPluginInterface.h" @@ -37,18 +39,28 @@ VncServer::VncServer( QObject* parent ) : QThread( parent ), m_pluginInterface( nullptr ) { + const auto currentSessionType = VeyonCore::platform().sessionFunctions().currentSessionType(); + VeyonCore::authenticationCredentials().setInternalVncServerPassword( - QString::fromLatin1( CryptoCore::generateChallenge().toBase64().left( MAXPWLEN ) ) ); + CryptoCore::generateChallenge().toBase64().left( MAXPWLEN ) ); VncServerPluginInterfaceList defaultVncServerPlugins; - for( auto pluginObject : qAsConst( VeyonCore::pluginManager().pluginObjects() ) ) + for( auto pluginObject : std::as_const( VeyonCore::pluginManager().pluginObjects() ) ) { auto pluginInterface = qobject_cast( pluginObject ); auto vncServerPluginInterface = qobject_cast( pluginObject ); if( pluginInterface && vncServerPluginInterface ) { + // skip VNC server plugins which support certain session types only and do not support + // the current session type + if( vncServerPluginInterface->supportedSessionTypes().isEmpty() == false && + vncServerPluginInterface->supportedSessionTypes().contains( currentSessionType, Qt::CaseInsensitive ) == false ) + { + continue; + } + if( pluginInterface->uid() == VeyonCore::config().vncServerPlugin() ) { m_pluginInterface = vncServerPluginInterface; @@ -94,19 +106,27 @@ void VncServer::prepare() -int VncServer::serverPort() const +int VncServer::serverBasePort() const { + if( m_pluginInterface && m_pluginInterface->configuredServerPort() > 0 ) { - return m_pluginInterface->configuredServerPort() + VeyonCore::sessionId(); + return m_pluginInterface->configuredServerPort(); } - return VeyonCore::config().vncServerPort() + VeyonCore::sessionId(); + return VeyonCore::config().vncServerPort(); +} + + + +int VncServer::serverPort() const +{ + return serverBasePort() + VeyonCore::sessionId(); } -QString VncServer::password() const +VncServer::Password VncServer::password() const { if( m_pluginInterface && m_pluginInterface->configuredPassword().isEmpty() == false ) { @@ -134,7 +154,10 @@ void VncServer::run() VeyonCore::authenticationCredentials().setInternalVncServerPassword( m_pluginInterface->configuredPassword() ); } - m_pluginInterface->runServer( serverPort(), password() ); + if( m_pluginInterface->runServer( serverPort(), password() ) == false ) + { + vCritical() << "An error occurred while running the VNC server plugin"; + } vDebug() << "finished"; } diff --git a/server/src/VncServer.h b/server/src/VncServer.h index 472425ec7..0f4d105ef 100644 --- a/server/src/VncServer.h +++ b/server/src/VncServer.h @@ -2,7 +2,7 @@ * VncServer.h - class VncServer, a VNC server abstraction for * platform-independent VNC server usage * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -27,20 +27,25 @@ #include +#include "CryptoCore.h" + class VncServerPluginInterface; class VncServer : public QThread { Q_OBJECT public: + using Password = CryptoCore::PlaintextPassword; + explicit VncServer( QObject* parent = nullptr ); ~VncServer() override; void prepare(); + int serverBasePort() const; int serverPort() const; - QString password() const; + Password password() const; private: void run() override; diff --git a/server/src/main.cpp b/server/src/main.cpp index c4b81ea00..2349dbba1 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -1,7 +1,7 @@ /* * main.cpp - main file for Veyon Server * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -22,17 +22,21 @@ * */ -#include +#include #include "ComputerControlServer.h" -#include "VeyonConfiguration.h" int main( int argc, char **argv ) { - QCoreApplication app( argc, argv ); + VeyonCore::setupApplicationParameters(); - VeyonCore core( &app, QStringLiteral("Server") ); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QGuiApplication::setAttribute( Qt::AA_EnableHighDpiScaling ); +#endif + QGuiApplication app( argc, argv ); + + VeyonCore core( &app, VeyonCore::Component::Server, QStringLiteral("Server") ); ComputerControlServer server( &core ); if( server.start() == false ) diff --git a/server/veyon-server.rc.in b/server/veyon-server.rc.in index fe610a094..4eaaaad3f 100644 --- a/server/veyon-server.rc.in +++ b/server/veyon-server.rc.in @@ -1,10 +1,10 @@ #include -ID_MANIFEST RT_MANIFEST data/veyon-server.exe.manifest +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST data/veyon-server.exe.manifest VS_VERSION_INFO VERSIONINFO FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,@VERSION_BUILD@ - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGSMASK 0 FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_APP FILESUBTYPE VFT2_UNKNOWN @@ -16,12 +16,16 @@ BEGIN BEGIN VALUE "Comments", "Virtual Eye On Networks (https://veyon.io)\0" VALUE "CompanyName", "Veyon Solutions\0" + VALUE "ProductName", "Veyon\0" + VALUE "ProductVersion", "@VERSION_STRING@\0" VALUE "FileDescription", "Veyon Server\0" VALUE "FileVersion", "@VERSION_STRING@\0" - VALUE "LegalCopyright", "Copyright (c) 2004-2019 Tobias Junghans\0" + VALUE "LegalCopyright", "Copyright (c) 2017-2025 Veyon Solutions / Tobias Junghans\0" VALUE "OriginalFilename", "veyon-server.exe\0" - VALUE "ProductName", "Veyon\0" - VALUE "ProductVersion", "@VERSION_STRING@\0" END END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04E4 + END END diff --git a/service/CMakeLists.txt b/service/CMakeLists.txt index 83d66d551..57378e6f1 100644 --- a/service/CMakeLists.txt +++ b/service/CMakeLists.txt @@ -1,19 +1,15 @@ -INCLUDE(BuildApplication) -INCLUDE(WindowsBuildHelpers) +include(BuildVeyonApplication) +include(WindowsBuildHelpers) -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src) +build_veyon_application(veyon-service ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp) -BUILD_APPLICATION(veyon-service ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp) -TARGET_LINK_LIBRARIES(veyon-service veyon-core) - -ADD_WINDOWS_RESOURCE(veyon-service) -MAKE_GRAPHICAL_APP(veyon-service) - -IF(VEYON_BUILD_LINUX) - CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/veyon.service.in ${CMAKE_CURRENT_BINARY_DIR}/veyon.service @ONLY) - IF(NOT SYSTEMD_SERVICE_INSTALL_DIR) - SET(SYSTEMD_SERVICE_INSTALL_DIR /lib/systemd/system) - ENDIF() - INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/veyon.service DESTINATION ${SYSTEMD_SERVICE_INSTALL_DIR}) -ENDIF() +add_windows_resource(veyon-service) +make_graphical_app(veyon-service) +if(VEYON_BUILD_LINUX) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/veyon.service.in ${CMAKE_CURRENT_BINARY_DIR}/veyon.service @ONLY) + if(NOT SYSTEMD_SERVICE_INSTALL_DIR) + set(SYSTEMD_SERVICE_INSTALL_DIR /lib/systemd/system) + endif() + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/veyon.service DESTINATION ${SYSTEMD_SERVICE_INSTALL_DIR}) +endif() diff --git a/service/src/main.cpp b/service/src/main.cpp index fb87bd39d..f54999a59 100644 --- a/service/src/main.cpp +++ b/service/src/main.cpp @@ -1,7 +1,7 @@ /* * main.cpp - main file for Veyon Service * - * Copyright (c) 2006-2019 Tobias Junghans + * Copyright (c) 2006-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -29,13 +29,17 @@ int main( int argc, char** argv ) { + VeyonCore::setupApplicationParameters(); + QCoreApplication app( argc, argv ); - VeyonCore core( &app, QStringLiteral("Service") ); + VeyonCore core( &app, VeyonCore::Component::Service, QStringLiteral("Service") ); - auto& serviceFunctions = core.platform().serviceFunctions(); + auto& serviceFunctions = VeyonCore::platform().serviceFunctions(); - if( serviceFunctions.runAsService( VeyonServiceControl::name(), - [&]() { serviceFunctions.manageServerInstances(); } ) ) + if( serviceFunctions.runAsService( VeyonServiceControl::name(), [&]() { + Q_EMIT core.applicationLoaded(); + serviceFunctions.manageServerInstances(); + } ) ) { return 0; } diff --git a/service/veyon-service.rc.in b/service/veyon-service.rc.in index 3051b75f3..fca598e4c 100644 --- a/service/veyon-service.rc.in +++ b/service/veyon-service.rc.in @@ -1,10 +1,10 @@ #include -ID_MANIFEST RT_MANIFEST data/veyon-service.exe.manifest +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST data/veyon-service.exe.manifest VS_VERSION_INFO VERSIONINFO FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,@VERSION_BUILD@ - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGSMASK 0 FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_APP FILESUBTYPE VFT2_UNKNOWN @@ -16,12 +16,16 @@ BEGIN BEGIN VALUE "Comments", "Virtual Eye On Networks (https://veyon.io)\0" VALUE "CompanyName", "Veyon Solutions\0" + VALUE "ProductName", "Veyon\0" + VALUE "ProductVersion", "@VERSION_STRING@\0" VALUE "FileDescription", "Veyon Service\0" VALUE "FileVersion", "@VERSION_STRING@\0" - VALUE "LegalCopyright", "Copyright (c) 2004-2019 Tobias Junghans\0" + VALUE "LegalCopyright", "Copyright (c) 2017-2025 Veyon Solutions / Tobias Junghans\0" VALUE "OriginalFilename", "veyon-service.exe\0" - VALUE "ProductName", "Veyon\0" - VALUE "ProductVersion", "@VERSION_STRING@\0" END END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04E4 + END END diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 000000000..2337f4398 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,3 @@ +if(WITH_FUZZERS) + add_subdirectory(libfuzzer) +endif() diff --git a/tests/libfuzzer/CMakeLists.txt b/tests/libfuzzer/CMakeLists.txt new file mode 100644 index 000000000..ad6d4787c --- /dev/null +++ b/tests/libfuzzer/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(core) diff --git a/tests/libfuzzer/common/init.cpp b/tests/libfuzzer/common/init.cpp new file mode 100644 index 000000000..606106414 --- /dev/null +++ b/tests/libfuzzer/common/init.cpp @@ -0,0 +1,8 @@ +#include + +extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) +{ + auto app = new QCoreApplication(*argc, *argv); + new VeyonCore(app, VeyonCore::Component::CLI, QStringLiteral("Fuzzer")); + return 0; +} diff --git a/tests/libfuzzer/core/CMakeLists.txt b/tests/libfuzzer/core/CMakeLists.txt new file mode 100644 index 000000000..ff3eac443 --- /dev/null +++ b/tests/libfuzzer/core/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(variantarraymessage) +add_subdirectory(variantstream) +add_subdirectory(vncclientprotocol) +add_subdirectory(vncserverprotocol) diff --git a/tests/libfuzzer/core/variantarraymessage/CMakeLists.txt b/tests/libfuzzer/core/variantarraymessage/CMakeLists.txt new file mode 100644 index 000000000..ddc131013 --- /dev/null +++ b/tests/libfuzzer/core/variantarraymessage/CMakeLists.txt @@ -0,0 +1,3 @@ +include(BuildVeyonFuzzer) + +build_veyon_fuzzer(variantarraymessage main.cpp ../../common/init.cpp) diff --git a/tests/libfuzzer/core/variantarraymessage/main.cpp b/tests/libfuzzer/core/variantarraymessage/main.cpp new file mode 100644 index 000000000..7542b8048 --- /dev/null +++ b/tests/libfuzzer/core/variantarraymessage/main.cpp @@ -0,0 +1,15 @@ +#include + +#include "VariantArrayMessage.h" + +extern "C" int LLVMFuzzerTestOneInput(const char *data, size_t size) +{ + QBuffer buffer; + buffer.open(QIODevice::ReadWrite); + buffer.write(QByteArray::fromRawData(data, size)); + buffer.seek(0); + + VariantArrayMessage(&buffer).receive(); + + return 0; +} diff --git a/tests/libfuzzer/core/variantstream/CMakeLists.txt b/tests/libfuzzer/core/variantstream/CMakeLists.txt new file mode 100644 index 000000000..17eefb871 --- /dev/null +++ b/tests/libfuzzer/core/variantstream/CMakeLists.txt @@ -0,0 +1,3 @@ +include(BuildVeyonFuzzer) + +build_veyon_fuzzer(variantstream main.cpp ../../common/init.cpp) diff --git a/tests/libfuzzer/core/variantstream/main.cpp b/tests/libfuzzer/core/variantstream/main.cpp new file mode 100644 index 000000000..4111efd90 --- /dev/null +++ b/tests/libfuzzer/core/variantstream/main.cpp @@ -0,0 +1,15 @@ +#include + +#include "VariantStream.h" + +extern "C" int LLVMFuzzerTestOneInput(const char *data, size_t size) +{ + QBuffer buffer; + buffer.open(QIODevice::ReadWrite); + buffer.write(QByteArray::fromRawData(data, size)); + buffer.seek(0); + + VariantStream{&buffer}.read(); + + return 0; +} diff --git a/tests/libfuzzer/core/vncclientprotocol/CMakeLists.txt b/tests/libfuzzer/core/vncclientprotocol/CMakeLists.txt new file mode 100644 index 000000000..5b1c5a7cf --- /dev/null +++ b/tests/libfuzzer/core/vncclientprotocol/CMakeLists.txt @@ -0,0 +1,3 @@ +include(BuildVeyonFuzzer) + +build_veyon_fuzzer(vncclientprotocol main.cpp ../../common/init.cpp) diff --git a/tests/libfuzzer/core/vncclientprotocol/main.cpp b/tests/libfuzzer/core/vncclientprotocol/main.cpp new file mode 100644 index 000000000..b72182462 --- /dev/null +++ b/tests/libfuzzer/core/vncclientprotocol/main.cpp @@ -0,0 +1,51 @@ +#include + +#include "VncClientProtocol.h" + +class VncClientProtocolTest : public VncClientProtocol +{ +public: + VncClientProtocolTest(QIODevice* socket) : + VncClientProtocol(socket, {}) + { + } + + void init(char state) + { + setState(State(state)); + } + +}; + + +extern "C" int LLVMFuzzerTestOneInput(const char *data, size_t size) +{ + if (size < 3) + { + return 0; + } + + QBuffer buffer; + buffer.open(QIODevice::ReadWrite); + + VncClientProtocolTest protocol(&buffer); + + const auto mode = data[0]; + const auto state = data[1]; + + protocol.init(state); + + buffer.write(QByteArray::fromRawData(data+2, size-2)); + buffer.seek(0); + + if(mode) + { + protocol.read(); + } + else + { + protocol.receiveMessage(); + } + + return 0; +} diff --git a/tests/libfuzzer/core/vncserverprotocol/CMakeLists.txt b/tests/libfuzzer/core/vncserverprotocol/CMakeLists.txt new file mode 100644 index 000000000..e98bc93db --- /dev/null +++ b/tests/libfuzzer/core/vncserverprotocol/CMakeLists.txt @@ -0,0 +1,3 @@ +include(BuildVeyonFuzzer) + +build_veyon_fuzzer(vncserverprotocol main.cpp ../../common/init.cpp) diff --git a/tests/libfuzzer/core/vncserverprotocol/main.cpp b/tests/libfuzzer/core/vncserverprotocol/main.cpp new file mode 100644 index 000000000..9e1d1c47a --- /dev/null +++ b/tests/libfuzzer/core/vncserverprotocol/main.cpp @@ -0,0 +1,64 @@ +#include + +#include "VncServerClient.h" +#include "VncServerProtocol.h" + +class VncServerProtocolTest : public VncServerProtocol +{ +public: + VncServerProtocolTest(Plugin::Uid authMethod, QIODevice* socket, VncServerClient* client) : + VncServerProtocol(socket, client), + m_authMethod(authMethod) + { + } + + AuthMethodUids supportedAuthMethodUids() const override + { + return {m_authMethod}; + } + + void processAuthenticationMessage(VariantArrayMessage& message) override + { + Q_UNUSED(message) + } + + void performAccessControl() override + { + } + +private: + const Plugin::Uid m_authMethod; + +}; + + +extern "C" int LLVMFuzzerTestOneInput(const char *data, size_t size) +{ + if (size < 5) + { + return 0; + } + + QBuffer buffer; + buffer.open(QIODevice::ReadWrite); + + const VncServerProtocol::AuthMethodUids authMethodUids{ + Plugin::Uid{QByteArrayLiteral("63611f7c-b457-42c7-832e-67d0f9281085")}, + Plugin::Uid{QByteArrayLiteral("73430b14-ef69-4c75-a145-ba635d1cc676")}, + Plugin::Uid{QByteArrayLiteral("0c69b301-81b4-42d6-8fae-128cdd113314")} + }; + + VncServerClient client; + VncServerProtocolTest protocol(authMethodUids.value(data[0]), &buffer, &client); + + client.setProtocolState(VncServerProtocol::State(data[1])); + client.setAuthState(VncServerClient::AuthState(data[2])); + client.setAccessControlState(VncServerClient::AccessControlState(data[3])); + + buffer.write(QByteArray::fromRawData(data+4, size-4)); + buffer.seek(0); + + protocol.read(); + + return 0; +} diff --git a/translations/CMakeLists.txt b/translations/CMakeLists.txt index 7c50aad5a..ec4a94c1d 100644 --- a/translations/CMakeLists.txt +++ b/translations/CMakeLists.txt @@ -1,54 +1,10 @@ -# build translation files -FILE(GLOB veyon_LOCALES ${CMAKE_CURRENT_SOURCE_DIR}/*.ts) -SET(ts_targets "") -SET(qm_targets "") -FILE(GLOB_RECURSE veyon_SOURCES ${CMAKE_SOURCE_DIR}/*.cpp ${CMAKE_SOURCE_DIR}/*.h ${CMAKE_SOURCE_DIR}/*.ui) -STRING(REGEX REPLACE "${CMAKE_SOURCE_DIR}/3rdparty[^;]+;?" "" veyon_SOURCES "${veyon_SOURCES}") +include(CreateTranslations) +include(ImportQtTranslations) -FOREACH(ts_file ${veyon_LOCALES}) - STRING(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" ts_target "${ts_file}") - STRING(REPLACE ".ts" ".qm" qm_target "${ts_target}") - SET(qm_file "${CMAKE_CURRENT_BINARY_DIR}/${qm_target}") - ADD_CUSTOM_TARGET(${ts_target} COMMAND ${Qt5_LUPDATE_EXECUTABLE} -I${CMAKE_SOURCE_DIR}/core/include -locations none -no-obsolete ${veyon_SOURCES} -ts ${ts_file}) - # add command and target for generating/updating QM file if TS file is newer or no QM file exists yet - ADD_CUSTOM_COMMAND(OUTPUT ${qm_file} COMMAND ${Qt5_LRELEASE_EXECUTABLE} ${ts_file} -qm ${qm_file} DEPENDS ${ts_file}) - ADD_CUSTOM_TARGET(${qm_target} ALL DEPENDS ${qm_file}) +file(GLOB veyon_translations ${CMAKE_CURRENT_SOURCE_DIR}/*.ts) +file(GLOB_RECURSE veyon_sources ${CMAKE_SOURCE_DIR}/*.cpp ${CMAKE_SOURCE_DIR}/*.h ${CMAKE_SOURCE_DIR}/*.ui ${CMAKE_SOURCE_DIR}/*.qml) +string(REGEX REPLACE "${CMAKE_SOURCE_DIR}/3rdparty[^;]+;?" "" veyon_sources "${veyon_sources}") +string(REGEX REPLACE "${CMAKE_SOURCE_DIR}/addons[^;]+;?" "" veyon_sources "${veyon_sources}") - LIST(APPEND ts_targets "${ts_target}") - LIST(APPEND qm_targets "${qm_target}") - - INSTALL(FILES ${qm_file} DESTINATION ${VEYON_INSTALL_DATA_DIR}/translations) -ENDFOREACH() - -ADD_CUSTOM_TARGET(update-locales) -FOREACH(_item ${ts_targets}) - ADD_DEPENDENCIES(update-locales ${_item}) -ENDFOREACH(_item ${ts_targets}) - - -# find Qt's translation files -SET(QT_TRANSLATIONS_STAMP ${CMAKE_CURRENT_BINARY_DIR}/qttranslations.stamp) -IF(NOT EXISTS "${QT_TRANSLATIONS_STAMP}") - GET_TARGET_PROPERTY(QT_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION) - EXECUTE_PROCESS(COMMAND "${QT_QMAKE_EXECUTABLE}" -query QT_INSTALL_TRANSLATIONS - OUTPUT_STRIP_TRAILING_WHITESPACE - OUTPUT_VARIABLE QT_TRANSLATIONS_DIR) - FILE(WRITE "${QT_TRANSLATIONS_STAMP}" "1") - IF(VEYON_BUILD_WIN32) - FILE(GLOB QT_TRANSLATIONS "${QT_TRANSLATIONS_DIR}/qt_*.qm") - FOREACH(QT_TRANSLATION ${QT_TRANSLATIONS}) - IF(NOT QT_TRANSLATION MATCHES "help") - STRING(REPLACE "${QT_TRANSLATIONS_DIR}/" "" QT_TRANSLATION_FILE_NAME "${QT_TRANSLATION}") - STRING(REPLACE "qt_" "qtbase_" QTBASE_TRANSLATION_FILE_NAME "${QT_TRANSLATION_FILE_NAME}") - # is there qtbase-specific QM file? - IF(EXISTS "${QT_TRANSLATIONS_DIR}/${QTBASE_TRANSLATION_FILE_NAME}") - # then use it instead of (deprecated) QM file for all Qt modules - FILE(COPY "${QT_TRANSLATIONS_DIR}/${QTBASE_TRANSLATION_FILE_NAME}" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - FILE(RENAME "${CMAKE_CURRENT_BINARY_DIR}/${QTBASE_TRANSLATION_FILE_NAME}" "${CMAKE_CURRENT_BINARY_DIR}/${QT_TRANSLATION_FILE_NAME}") - ELSE() - FILE(COPY ${QT_TRANSLATION} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - ENDIF() - ENDIF() - ENDFOREACH() - ENDIF() -ENDIF() +create_translations(veyon "${veyon_translations}" "${veyon_sources}") +import_qt_translations() diff --git a/translations/ca_ES.ts b/translations/ca_ES.ts deleted file mode 100644 index 24692ca6e..000000000 --- a/translations/ca_ES.ts +++ /dev/null @@ -1,4167 +0,0 @@ - - - AboutDialog - - About - Quant a - - - Translation - Traducció - - - License - Llicència - - - About Veyon - - - - Contributors - - - - Version: - - - - Website: - - - - Current language not translated yet (or native English). - -If you're interested in translating Veyon into your local or another language or want to improve an existing translation, please contact a Veyon developer! - - - - About %1 %2 - - - - Support Veyon project with a donation - - - - - AccessControlPage - - Computer access control - - - - Grant access to every authenticated user (default) - - - - Test - Comprova - - - Process access control rules - - - - User groups authorized for computer access - - - - Please add the groups whose members should be authorized to access computers in your Veyon network. - - - - Authorized user groups - - - - All groups - Tots els grups - - - ... - ... - - - Access control rules - - - - Add access control rule - - - - Remove access control rule - - - - Move selected rule down - - - - Move selected rule up - - - - Edit selected rule - - - - Enter username - - - - Please enter a user login name whose access permissions to test: - - - - Access allowed - - - - The specified user is allowed to access computers with this configuration. - - - - Access denied - - - - The specified user is not allowed to access computers with this configuration. - - - - Enable usage of domain groups - - - - User groups backend: - - - - Missing user groups backend - - - - No default user groups plugin was found. Please check your installation! - - - - Restrict access to members of specific user groups - - - - - AccessControlRuleEditDialog - - Edit access control rule - - - - General - General - - - enter a short name for the rule here - - - - Rule name: - - - - enter a description for the rule here - - - - Rule description: - - - - Invert all conditions ("is/has" interpreted as "is/has not") - - - - Conditions - - - - is member of group - - - - Accessing computer is localhost - - - - Accessing user is logged on user - - - - Accessing user is already connected - - - - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. - - - - Action - - - - Allow access - - - - Deny access - - - - Ask logged on user for permission - - - - None (rule disabled) - - - - Accessing user - - - - Accessing computer - - - - Local (logged on) user - - - - Local computer - - - - Always process rule and ignore conditions - - - - No user logged on - - - - Accessing user has one or more groups in common with local (logged on) user - - - - Accessing computer and local computer are at the same location - - - - is located at - - - - - AccessControlRulesTestDialog - - Access control rules test - - - - Accessing user: - - - - Local computer: - - - - Accessing computer: - - - - Please enter the following user and computer information in order to test the configured ruleset. - - - - Local user: - - - - Connected users: - - - - The access in the given scenario is allowed. - - - - The access in the given scenario is denied. - - - - The access in the given scenario needs permission of the logged on user. - - - - ERROR: Unknown action - - - - Test result - - - - - AndroidPlatformConfigurationPage - - Android - - - - General - General - - - - AndroidPlatformPlugin - - Plugin implementing specific functions for the Android platform - - - - - AuthKeysConfigurationPage - - Authentication keys - - - - Introduction - - - - Key file directories - - - - Public key file base directory - Carpeta del fitxer de la clau pública - - - Private key file base directory - Carpeta del fitxer de la clau privada - - - ... - ... - - - Available authentication keys - - - - Create key pair - - - - Delete key - - - - Import key - - - - Export key - - - - Set access group - - - - Key files (*.pem) - - - - Authentication key name - - - - Please enter the name of the user group or role for which to create an authentication key pair: - - - - Do you really want to delete authentication key "%1/%2"? - - - - Please select a key to delete! - - - - Please enter the name of the user group or role for which to import the authentication key: - - - - Please select a key to export! - - - - Please select a user group which to grant access to key "%1": - - - - Please select a key which to set the access group for! - - - - Please perform the following steps to set up key file authentication: - - - - 1) Create a key pair on the master computer. - - - - 2) Set an access group whose members should be allowed to access other computers. - - - - 3) Export the public key and import it on all client computers with the same name. - - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - - - - - AuthKeysManager - - Please check your permissions. - - - - Key name contains invalid characters! - - - - Invalid key type specified! Please specify "%1" or "%2". - - - - Specified key does not exist! Please use the "list" command to list all installed keys. - - - - One or more key files already exist! Please delete them using the "delete" command. - - - - Creating new key pair for "%1" - - - - Failed to create public or private key! - - - - Newly created key pair has been saved to "%1" and "%2". - - - - Could not remove key file "%1"! - - - - Could not remove key file directory "%1"! - - - - Failed to create directory for output file. - - - - File "%1" already exists. - - - - Failed to write output file. - - - - Key "%1/%2" has been exported to "%3" successfully. - - - - Failed read input file. - - - - File "%1" does not contain a valid private key! - - - - File "%1" does not contain a valid public key! - - - - Failed to create directory for key file. - - - - Failed to write key file "%1". - - - - Failed to set permissions for key file "%1"! - - - - Key "%1/%2" has been imported successfully. Please check file permissions of "%3" in order to prevent unauthorized accesses. - - - - Failed to convert private key to public key - - - - Failed to create directory for private key file "%1". - - - - Failed to save private key in file "%1"! - - - - Failed to set permissions for private key file "%1"! - - - - Failed to create directory for public key file "%1". - - - - Failed to save public key in file "%1"! - - - - Failed to set permissions for public key file "%1"! - - - - Failed to set owner of key file "%1" to "%2". - - - - Failed to set permissions for key file "%1". - - - - Key "%1" is now accessible by user group "%2". - - - - <N/A> - - - - Failed to read key file. - - - - - AuthKeysPlugin - - Create new authentication key pair - - - - Delete authentication key - - - - List authentication keys - - - - Import public or private key - - - - Export public or private key - - - - Extract public key from existing private key - - - - Set user group allowed to access a key - - - - KEY - - - - ACCESS GROUP - - - - This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. - - - - NAME - - - - FILE - - - - This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - - - - This command imports the authentication key <KEY> from <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - - - - This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - - - - Please specify the command to display help for! - - - - TYPE - - - - PAIR ID - - - - Command line support for managing authentication keys - - - - Commands for managing authentication keys - - - - This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. - - - - This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. - - - - This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. - - - - - AuthKeysTableModel - - Name - Nom - - - Type - Tipus - - - Access group - - - - Pair ID - - - - - BuiltinDirectoryConfigurationPage - - Computers - - - - Name - Nom - - - Host address/IP - - - - MAC address - Adreça MAC - - - Add new computer - - - - Remove selected computer - - - - New computer - - - - Builtin directory - - - - Locations & computers - - - - Locations - - - - Add new location - - - - Remove selected location - - - - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - - - - New location - - - - - BuiltinDirectoryPlugin - - Show help for specific command - - - - Import objects from given file - - - - Export objects to given file - - - - Invalid type specified. Valid values are "%1" or "%2". - - - - Type - Tipus - - - Name - Nom - - - Host address - - - - MAC address - Adreça MAC - - - Specified object not found. - - - - File "%1" does not exist! - - - - Can't open file "%1" for reading! - - - - Unknown argument "%1". - - - - Computer "%1" (host address: "%2" MAC address: "%3") - - - - Unclassified object "%1" with ID "%2" - - - - None - - - - Computer - - - - Root - - - - Invalid - - - - Error while parsing line %1. - - - - Network object directory which stores objects in local configuration - - - - Commands for managing the builtin network object directory - - - - No format string or regular expression specified! - - - - Can't open file "%1" for writing! - - - - No format string specified! - - - - Object UUID - - - - Parent UUID - - - - Add a location or computer - - - - Clear all locations and computers - - - - Dump all or individual locations and computers - - - - List all locations and computers - - - - Remove a location or computer - - - - Location "%1" - - - - Builtin (computers and locations in local configuration) - - - - Location - - - - FILE - - - - LOCATION - - - - FORMAT-STRING-WITH-PLACEHOLDERS - - - - REGULAR-EXPRESSION-WITH-PLACEHOLDER - - - - Imports objects from the specified text file using the given format string or regular expression containing one or multiple placeholders. Valid placeholders are: %1 - - - - Import simple CSV file to a single room - - - - Import CSV file with location name in first column - - - - Import text file with with key/value pairs using regular expressions - - - - Import arbitrarily formatted data - - - - Exports objects to the specified text file using the given format string containing one or multiple placeholders. Valid placeholders are: %1 - - - - Export all objects to a CSV file - - - - Export all computers in a specific location to a CSV file - - - - TYPE - - - - NAME - - - - PARENT - - - - Adds an object where %1 can be one of "%2" or "%3". %4 can be specified by name or UUID. - - - - Add a room - - - - Add a computer to room %1 - - - - OBJECT - - - - Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. - - - - Remove a computer by name - - - - Remove an object by UUID - - - - "Room 01" - - - - "Computer 01" - - - - HOST ADDRESS - - - - MAC ADDRESS - - - - - BuiltinUltraVncServer - - Builtin VNC server (UltraVNC) - - - - - BuiltinX11VncServer - - Builtin VNC server (x11vnc) - - - - - ComputerControlListModel - - Host/IP address: %1 - - - - Active features: %1 - - - - Online and connected - - - - Establishing connection - - - - Computer offline or switched off - - - - Service unreachable or not running - - - - Authentication failed or access denied - - - - Disconnected - - - - No user logged on - - - - Logged on user: %1 - - - - Location: %1 - - - - - ComputerControlServer - - %1 Service %2 at %3:%4 - - - - Authentication error - Error d'autentificació - - - Remote access - - - - User "%1" at host "%2" is now accessing this computer. - - - - User "%1" at host "%2" attempted to access this computer but could not authenticate successfully. - - - - Access control error - - - - User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. - - - - - ComputerManager - - User - - - - Missing network object directory plugin - - - - No default network object directory plugin was found. Please check your installation or configure a different network object directory backend via %1 Configurator. - - - - Location detection failed - - - - Computer name;Hostname;User - - - - Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. - - - - - ComputerSelectPanel - - Computer management - - - - Computer search - - - - Add location - - - - Save computer/user list - - - - Select output filename - - - - CSV files (*.csv) - - - - File error - - - - Could not write the computer and users list to %1! Please check the file access permissions. - - - - - ConfigCommandLinePlugin - - Please specify an existing configuration file to import. - - - - Please specify a valid filename for the configuration export. - - - - Please specify a valid key. - - - - Specified key does not exist in current configuration! - - - - Please specify a valid value. - - - - Configure Veyon at command line - - - - Output file is not writable! - - - - Output directory is not writable! - - - - Configuration file is not readable! - - - - Clear system-wide Veyon configuration - - - - List all configuration keys and values - - - - Import configuration from given file - - - - Export configuration to given file - - - - Read and output configuration value for given key - - - - Write given value to given configuration key - - - - Unset (remove) given configuration key - - - - Commands for managing the configuration of Veyon - - - - Upgrade and save configuration of program and plugins - - - - - ConfigurationManager - - Could not modify the autostart property for the %1 Service. - - - - Could not configure the firewall configuration for the %1 Server. - - - - Could not configure the firewall configuration for the %1 Worker. - - - - Configuration is not writable. Please check your permissions! - - - - Could not apply platform-specific configuration settings. - - - - - DemoClient - - %1 Demo - - - - - DemoConfigurationPage - - Demo server - Servidor demo - - - Tunables - - - - ms - - - - Key frame interval - - - - Memory limit - - - - Use multithreading (experimental) - - - - MB - - - - Update interval - - - - s - - - - Slow down thumbnail updates while demo is running - - - - - DemoFeaturePlugin - - Fullscreen demo - Demo a pantalla completa - - - Stop demo - - - - Window demo - Demo en finestra - - - Give a demonstration by screen broadcasting - - - - Demo server - Servidor demo - - - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - - - - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - - - - - DesktopAccessDialog - - Desktop access dialog - - - - Confirm desktop access - Confirmeu l'accés a l'escriptori - - - Never for this session - Mai per a aquesta sessió - - - Always for this session - Sempre per a aquesta sessió - - - The user %1 at computer %2 wants to access your desktop. Do you want to grant access? - - - - - DesktopServicesConfigurationPage - - Programs & websites - - - - Predefined programs - - - - Name - Nom - - - Path - - - - Add new program - - - - Remove selected program - - - - Predefined websites - - - - Remove selected website - - - - URL - - - - New program - - - - New website - - - - - DesktopServicesFeaturePlugin - - Run program - - - - Open website - - - - Click this button to open a website on all computers. - - - - Start programs and services in user desktop - - - - Click this button to run a program on all computers. - - - - Run program "%1" - - - - Custom program - - - - Open website "%1" - - - - Custom website - - - - - DocumentationFigureCreator - - Teacher - Professor - - - Room %1 - - - - Please complete all tasks within the next 5 minutes. - - - - Custom website - - - - Open file manager - - - - Start learning tool - - - - Play tutorial video - - - - Custom program - - - - Handout - - - - Texts to read - - - - - ExternalVncServer - - External VNC server - - - - - ExternalVncServerConfigurationWidget - - External VNC server configuration - - - - Port: - - - - Password: - - - - - FeatureControl - - Feature control - - - - - FileTransferController - - Could not open file "%1" for reading! Please check your permissions! - - - - - FileTransferDialog - - File transfer - - - - Options - - - - Transfer only - - - - Transfer and open file(s) with associated program - - - - Transfer and open destination folder - - - - Files - - - - Start - - - - Overwrite existing files - - - - - FileTransferPlugin - - File transfer - - - - Click this button to transfer files from your computer to all computers. - - - - Select one or more files to transfer - - - - Transfer files to remote computer - - - - Received file "%1". - - - - Could not receive file "%1" as it already exists. - - - - Could not receive file "%1" as it could not be opened for writing! - - - - - GeneralConfigurationPage - - User interface - Interfície d'usuari - - - Language: - Llengua: - - - Use system language setting - - - - Veyon - - - - Logging - Registre - - - Log file directory - Carpeta dels fitxers de registre - - - ... - ... - - - Log level - Nivell de registre - - - Nothing - Res - - - Only critical messages - Només missatges crítics - - - Errors and critical messages - Errors i missatges crítics - - - Warnings and errors - Avisos i errors - - - Information, warnings and errors - Informació, avisos i errors - - - Debug messages and everything else - Missatges de depuració i tota la resta - - - Limit log file size - Límita la mida del fitxer de registre - - - Clear all log files - Buida tots els fitxers de registre - - - Log to standard error output - Registra en la sortida d'error estàndard - - - Network object directory - - - - Backend: - - - - Update interval: - - - - %1 service - - - - The %1 service needs to be stopped temporarily in order to remove the log files. Continue? - - - - Log files cleared - Fitxers de registre buidats - - - All log files were cleared successfully. - Tots els fitxers de registre s'han buidat amb èxit. - - - Error - Error - - - Could not remove all log files. - No s'han pogut buidar tots els fitxers de registre. - - - MB - - - - Rotate log files - - - - x - - - - seconds - segons - - - Write to logging system of operating system - - - - Authentication - Autentificació - - - Method: - - - - Logon authentication - Autentificació d'inici de sessió - - - Key file authentication - Autentificació amb fitxers de claus - - - Test - Comprova - - - Authentication is set up properly on this computer. - - - - Authentication keys are not set up properly on this computer. - - - - Authentication test - - - - - InternetAccessControlConfigurationPage - - Internet access control - - - - Backend: - - - - General settings - - - - Backend settings - - - - - InternetAccessControlPlugin - - Block access to the internet - - - - Allow access to the internet - - - - Show help about command - - - - Block internet - - - - Click this button to block access to the internet. - - - - Unblock internet - - - - Click this button to allow access to the internet. - - - - Control access to the internet - - - - Commands for controlling access to the internet - - - - - LdapBrowseDialog - - Browse LDAP - - - - - LdapClient - - LDAP error description: %1 - - - - - LdapConfigurationPage - - Basic settings - - - - General - General - - - LDAP server and port - - - - Bind DN - - - - Bind password - - - - Anonymous bind - - - - Use bind credentials - - - - Base DN - - - - Fixed base DN - - - - e.g. dc=example,dc=org - - - - Discover base DN by naming context - - - - e.g. namingContexts or defaultNamingContext - - - - Environment settings - - - - Object trees - - - - Computer tree - - - - e.g. OU=Groups - - - - User tree - - - - e.g. OU=Users - - - - e.g. OU=Computers - - - - Group tree - - - - Perform recursive search operations in object trees - - - - Object attributes - - - - e.g. hwAddress - - - - e.g. member or memberUid - - - - e.g. dNSHostName - - - - Computer MAC address attribute - - - - Group member attribute - - - - e.g. uid or sAMAccountName - - - - Advanced settings - - - - Optional object filters - - - - Filter for user groups - - - - Filter for users - - - - Filter for computer groups - - - - Group member identification - - - - Distinguished name (Samba/AD) - - - - List all groups of a user - - - - List all groups of a computer - - - - Get computer object by IP address - - - - LDAP connection failed - - - - LDAP bind failed - - - - LDAP bind successful - - - - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - - - - LDAP base DN test failed - - - - LDAP base DN test successful - - - - LDAP naming context test failed - - - - LDAP naming context test successful - - - - The LDAP naming context has been queried successfully. The following base DN was found: -%1 - - - - user tree - - - - group tree - - - - computer tree - - - - Enter username - - - - Please enter a user login name (wildcards allowed) which to query: - - - - user objects - - - - Enter group name - - - - Please enter a group name whose members to query: - - - - group members - - - - Group not found - - - - Could not find a group with the name "%1". Please check the group name or the group tree parameter. - - - - Enter computer name - - - - computer objects - - - - Enter computer DN - - - - Please enter the DN of a computer whose MAC address to query: - - - - computer MAC addresses - - - - users - - - - user groups - - - - computer groups - - - - Please enter a user login name whose group memberships to query: - - - - groups of user - - - - User not found - - - - groups of computer - - - - Computer not found - - - - Enter computer IP address - - - - Please enter a computer IP address which to resolve to an computer object: - - - - computers - - - - LDAP %1 test failed - - - - LDAP %1 test successful - - - - The %1 has been queried successfully and %2 entries were found. - - - - %1 %2 have been queried successfully: - -%3 - - - - LDAP filter test failed - - - - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 - - - - LDAP filter test successful - - - - %1 %2 have been queried successfully using the configured filter. - - - - (only if different from group tree) - - - - Computer group tree - - - - computer group tree - - - - Filter for computers - - - - e.g. room or computerLab - - - - Integration tests - - - - Computer groups - - - - e.g. name or description - - - - Filter for computer containers - - - - Computer containers or OUs - - - - Connection security - - - - TLS certificate verification - - - - System defaults - - - - Never (insecure!) - - - - Custom CA certificate file - - - - None - - - - TLS - - - - SSL - - - - e.g. (objectClass=computer) - - - - e.g. (objectClass=group) - - - - e.g. (objectClass=person) - - - - e.g. (objectClass=room) or (objectClass=computerLab) - - - - e.g. (objectClass=container) or (objectClass=organizationalUnit) - - - - Could not query the configured base DN. Please check the base DN parameter. - -%1 - - - - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - - - - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - - - - Certificate files (*.pem) - - - - Could not connect to the LDAP server. Please check the server parameters. - -%1 - - - - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - - - - Encryption protocol - - - - Computer location attribute - - - - Computer display name attribute - - - - Location name attribute - - - - e.g. cn or displayName - - - - Computer locations identification - - - - Identify computer locations (e.g. rooms) via: - - - - Location attribute in computer objects - - - - List all entries of a location - - - - List all locations - - - - Enter computer display name - - - - Please enter a computer display name to query: - - - - Enter computer location name - - - - Please enter the name of a computer location (wildcards allowed): - - - - computer locations - - - - Enter location name - - - - Please enter the name of a location whose entries to query: - - - - location entries - - - - LDAP test failed - - - - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - - - - and - - - - LDAP test successful - - - - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - - - - Browse - - - - Test - Comprova - - - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - - - - Computer hostname attribute - - - - Please enter a computer hostname to query: - - - - Invalid hostname - - - - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - - - - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - - - - Could not find a user with the name "%1". Please check the username or the user tree parameter. - - - - Enter hostname - - - - Please enter a computer hostname whose group memberships to query: - - - - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - - - - Hostname lookup failed - - - - Could not lookup hostname for IP address %1. Please check your DNS server settings. - - - - User login name attribute - - - - Configured attribute for user login name or computer hostname (OpenLDAP) - - - - computer containers - - - - - LdapPlugin - - Auto-configure the base DN via naming context - - - - Query objects from LDAP directory - - - - Show help about command - - - - Commands for configuring and testing LDAP/AD integration - - - - Basic LDAP/AD support for Veyon - - - - %1 (load computers and locations from LDAP/AD) - - - - %1 (load users and groups from LDAP/AD) - - - - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - - - - No naming context attribute name given - falling back to configured value. - - - - Could not query base DN. Please check your LDAP configuration. - - - - Configuring %1 as base DN and disabling naming context queries. - - - - - LdapProConfigurationPage - - LDAP Pro - - - - Instances - - - - Enter name - - - - Please enter a name for the instance (can't be changed later!): - - - - Remove instance - - - - Do you really want to remove instance "%1"? - - - - Configuration for instance "%1" - - - - - LdapProPlugin - - Professional LDAP/AD integration for Veyon - - - - %1 (load computers and locations from LDAP/AD) - - - - %1 (load users and groups from LDAP/AD) - - - - - LicensingConfigurationPage - - Licensing - - - - Installed licenses - - - - Add new network range - - - - Remove selected network range - - - - ID - - - - Feature - - - - Valid until - - - - Licensee - - - - Browse license file - - - - Veyon license files (*.vlf) - - - - Remove license - - - - Do you really want to remove the selected license? - - - - <N/A> - - - - Invalid license file - - - - Could not open the license file for reading! - - - - The selected license file does not contain valid data. - - - - The selected license file could not be verified. - - - - The selected license file is not valid for this installation. - - - - The selected license file is expired. - - - - The license is already installed. - - - - Information - - - - Installation ID - - - - Addons available for licensing - - - - Addon - - - - - LicensingPlugin - - Show help for specific command - - - - Show all installed licenses - - - - Add license file - - - - Remove installed license - - - - -USAGE - -%1 add <LICENSE FILE> - - - - - - -USAGE - -%1 remove <LICENSE ID> - - - - - - No certificate found with given ID - - - - <N/A> - - - - Licensing management - - - - Commands for managing license keys - - - - - LinuxPlatformConfigurationPage - - Linux - - - - Custom PAM service for user authentication - - - - User authentication - - - - Session management - - - - Display manager users - - - - - LinuxPlatformPlugin - - Plugin implementing abstract functions for the Linux platform - - - - Plugin implementing specific functions for the Linux platform - - - - - LocationDialog - - Select location - - - - enter search filter... - - - - - MainToolBar - - Configuration - - - - Disable balloon tooltips - - - - Show icons only - - - - - MainWindow - - MainWindow - Finestra principal - - - toolBar - Barra d'eines - - - General - General - - - &File - &Fitxer - - - &Help - &Ajuda - - - &Quit - &Surt - - - Ctrl+Q - Ctrl+Q - - - Ctrl+S - Ctrl+S - - - L&oad settings from file - &Carrega els ajustaments des d'un fitxer - - - Ctrl+O - Ctrl+O - - - About Qt - Quant a Qt - - - Authentication impossible - Autentificació impossible - - - Configuration not writable - La configuració no es pot escriure - - - Load settings from file - Carregar ajustaments des d'un fitxer - - - Save settings to file - Desa els ajustaments en un fitxer - - - Unsaved settings - Ajustaments no desats - - - There are unsaved settings. Quit anyway? - Hi ha ajustaments no desats. Voleu sortir de totes formes? - - - Veyon Configurator - - - - Service - - - - Master - - - - Access control - - - - About Veyon - - - - Auto - - - - About - Quant a - - - %1 Configurator %2 - - - - JSON files (*.json) - - - - The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - - - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - - - - Access denied - - - - According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. - - - - Screenshots - - - - Feature active - - - - The feature "%1" is still active. Please stop it before closing %2. - - - - Reset configuration - - - - Do you really want to reset the local configuration and revert all settings to their defaults? - - - - Search users and computers - - - - Adjust optimal size - - - - Align computers to grid - - - - %1 Configurator - - - - Insufficient privileges - - - - Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. - - - - Only show powered on computers - - - - &Save settings to file - - - - &View - - - - &Standard - - - - &Advanced - - - - Use custom computer arrangement - - - - Locations && computers - - - - - MasterConfigurationPage - - Directories - Carpetes - - - ... - ... - - - User configuration - - - - Feature on computer double click: - - - - Features - - - - All features - - - - Disabled features - - - - Screenshots - - - - <no feature> - - - - Basic settings - - - - Behaviour - - - - Enforce selected mode for client computers - - - - Hide local computer - - - - Hide computer filter field - - - - Actions such as rebooting or powering down computers - - - - User interface - Interfície d'usuari - - - Background color - - - - Thumbnail update interval - - - - ms - - - - Program start - - - - Modes and features - - - - User and computer name - - - - Only user name - - - - Only computer name - - - - Computer thumbnail caption - - - - Text color - - - - Sort order - - - - Computer and user name - - - - Computer locations - - - - Show current location only - - - - Allow adding hidden locations manually - - - - Hide empty locations - - - - Show confirmation dialog for potentially unsafe actions - - - - Perform access control - - - - Automatically select current location - - - - Automatically adjust computer thumbnail size - - - - Automatically open computer select panel - - - - - MonitoringMode - - Monitoring - - - - Builtin monitoring mode - - - - This mode allows you to monitor all computers at one or more locations. - - - - - NetworkDiscoveryConfigurationPage - - Network discovery - - - - Mode - - - - Scan network ranges - - - - e.g. 192.168.1.0/24 - - - - Scan all subnets of computer - - - - Scan custom subnet - - - - Scan sessions on local computer - - - - Test - Comprova - - - Network ranges - - - - Add new group - - - - Remove selected group - - - - Groups - - - - First address - - - - Last address - - - - Add new network range - - - - Remove selected network range - - - - Parallel scans - - - - Scan timeout - - - - ms - - - - Session scan limit - - - - Options - - - - Reverse lookup discovered IP addresses to host names - - - - New location - - - - - NetworkDiscoveryDirectory - - Scanning... - - - - Discovered computers - - - - - NetworkDiscoveryPlugin - - Show help for specific command - - - - Scan a subnet - - - - -USAGE - -%1 scan [<SUBNET>] - - - - - - Network object directory which automatically discovers computers in the network - - - - Network discovery (scan network for Veyon clients) - - - - Commands for managing the network discovery directory - - - - - NetworkObjectTreeModel - - Locations/Computers - - - - - OpenWebsiteDialog - - Open website - - - - e.g. Veyon - - - - Remember and add to website menu - - - - e.g. www.veyon.io - - - - Please enter the URL of the website to open: - - - - Name: - - - - - PasswordDialog - - Username - Nom d'usuari - - - Password - Clau d'accés - - - Veyon Logon - - - - Authentication error - Error d'autentificació - - - Logon failed with given username and password. Please try again! - - - - Please enter your username and password in order to access computers. - - - - - PowerControlFeaturePlugin - - Power on - Engega - - - Click this button to power on all computers. This way you do not have to power on each computer by hand. - - - - Reboot - Reinicia - - - Click this button to reboot all computers. - - - - Power down - Apaga - - - Click this button to power down all computers. This way you do not have to power down each computer by hand. - - - - Power on/down or reboot a computer - - - - Confirm reboot - - - - Confirm power down - - - - Do you really want to reboot the selected computers? - - - - Do you really want to power down the selected computer? - - - - Power on a computer via Wake-on-LAN (WOL) - - - - MAC ADDRESS - - - - This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. - - - - Please specify the command to display help for! - - - - Invalid MAC address specified! - - - - Commands for controlling power status of computers - - - - Power down now - - - - Install updates and power down - - - - Power down after user confirmation - - - - Power down after timeout - - - - The computer was remotely requested to power down. Do you want to power down the computer now? - - - - The computer will be powered down in %1 minutes, %2 seconds. - -Please save your work and close all programs. - - - - - PowerDownTimeInputDialog - - Power down - Apaga - - - Please specify a timeout for powering down the selected computers: - - - - minutes - - - - seconds - - - - - RemoteAccessFeaturePlugin - - Remote view - - - - Open a remote view for a computer without interaction. - - - - Remote control - Control remot - - - Open a remote control window for a computer. - - - - Remote access - - - - Remote view or control a computer - - - - Please enter the hostname or IP address of the computer to access: - - - - Show help about command - - - - - RemoteAccessWidget - - %1 - %2 Remote Access - - - - - RemoteAccessWidgetToolBar - - View only - Només veure - - - Remote control - Control remot - - - Send shortcut - - - - Fullscreen - Pantalla completa - - - Window - Finestra - - - Ctrl+Alt+Del - - - - Ctrl+Esc - - - - Alt+Tab - - - - Alt+F4 - - - - Win+Tab - - - - Win - - - - Menu - - - - Alt+Ctrl+F1 - - - - Connecting %1 - S'està connectant a %1 - - - Connected. - Connectat. - - - Screenshot - - - - Exit - - - - - Routing - - Control internet access by modifying routing table - - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - - - - Add custom route to block internet - - - - Destination - - - - Gateway - - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - - - - Run programs - - - - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - - - - Name: - - - - Remember and add to program menu - - - - e.g. VLC - - - - - ScreenLockFeaturePlugin - - Lock - - - - Unlock - - - - Lock screen and input devices of a computer - - - - To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. - - - - - Screenshot - - unknown - desconegut - - - Could not take a screenshot as directory %1 doesn't exist and couldn't be created. - - - - Screenshot - - - - - ScreenshotFeaturePlugin - - Screenshot - - - - Use this function to take a screenshot of selected computers. - - - - Screenshots taken - - - - Screenshot of %1 computer have been taken successfully. - - - - Take screenshots of computers and save them locally. - - - - - ScreenshotManagementPanel - - All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. - - - - User: - Usuari: - - - Computer: - - - - Date: - Data: - - - Time: - Hora: - - - Show - Mostra - - - Delete - Suprimeix - - - - ServiceConfigurationPage - - General - General - - - Autostart - Arranc automàtic - - - Hide tray icon - Ocultar icona de la barra del sistema - - - Start service - Inicia el servei - - - Stopped - Aturat - - - Stop service - Atura el servei - - - State: - Estat: - - - Network - Xarxa - - - Demo server port - Port del servidor demo - - - Enable firewall exception - Activar excepció en el tallafocs - - - Allow connections from localhost only - Permet connexions només des d'aquest equip - - - Internal VNC server port - - - - VNC server - - - - Plugin: - - - - Restart %1 Service - - - - All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - - - - Running - Funcionant - - - Feature manager port - - - - Primary service port - - - - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. - - - - Show notification on remote connection - - - - Multi session mode (for terminal and remote desktop servers) - - - - Show notification when an unauthorized access is blocked - - - - - ServiceControl - - Starting service %1 - - - - Stopping service %1 - - - - Registering service %1 - - - - Unregistering service %1 - - - - Service control - - - - - ServiceControlPlugin - - Service is running - - - - Service is not running - - - - Configure and control Veyon service - - - - Register Veyon Service - - - - Unregister Veyon Service - - - - Start Veyon Service - - - - Stop Veyon Service - - - - Restart Veyon Service - - - - Query status of Veyon Service - - - - Commands for configuring and controlling Veyon Service - - - - - ShellCommandLinePlugin - - Run command file - - - - File "%1" does not exist! - - - - Interactive shell and script execution for Veyon Control - - - - Commands for shell functionalities - - - - - SystemTrayIcon - - System tray icon - - - - - SystemUserGroupsPlugin - - User groups backend for system user groups - - - - Default (system user groups) - - - - - TestingCommandLinePlugin - - Test internal Veyon components and functions - - - - Commands for testing internal components and functions of Veyon - - - - - TextMessageDialog - - Send text message - Envia un missatge de text - - - Use the field below to type your message which will be sent to all selected users. - Utilitzeu el camp de sota per escriure el missatge que serà enviat als usuaris seleccionats. - - - - TextMessageFeaturePlugin - - Text message - Missatge de text - - - Use this function to send a text message to all users e.g. to assign them new tasks. - - - - Message from teacher - Missatge del professor - - - Send a message to a user - - - - - UltraVncConfigurationWidget - - Enable capturing of layered (semi-transparent) windows - Habilita la captura de finestres apilades (semitransparents) - - - Poll full screen (leave this enabled per default) - Monitora tota la pantalla (deixa activat per defecte) - - - Low accuracy (turbo mode) - Baixa precissió (mode turbo) - - - Builtin UltraVNC server configuration - - - - Enable multi monitor support - - - - Enable Desktop Duplication Engine on Windows 8 and newer - - - - - UserConfig - - No write access - Sense permís d'escriptura - - - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - - - - - UserSessionControl - - User session control - - - - Log off - - - - Click this button to log off users from all computers. - - - - Confirm user logoff - - - - Do you really want to log off the selected users? - - - - - VeyonCore - - [OK] - - - - [FAIL] - - - - Invalid command! - - - - Available commands: - - - - Invalid arguments given - - - - Not enough arguments given - use "%1 help" for more information - - - - Unknown result! - - - - Available modules: - - - - No module specified or module not found - available modules are: - - - - Plugin not licensed - - - - INFO - - - - ERROR - - - - licensed for - - - - USAGE - - - - DESCRIPTION - - - - EXAMPLES - - - - WARNING - - - - - VeyonServiceControl - - Veyon Service - - - - - VncView - - Establishing connection to %1 ... - S'està establint connexió amb %1 ... - - - - WindowsPlatformConfiguration - - Could not change the setting for SAS generation by software. Sending Ctrl+Alt+Del via remote control will not work! - - - - - WindowsPlatformConfigurationPage - - Windows - - - - General - General - - - Enable SAS generation by software (Ctrl+Alt+Del) - - - - Screen lock - - - - Hide taskbar - - - - Hide start menu - - - - Hide desktop - - - - User authentication - - - - Use alternative user authentication mechanism - - - - - WindowsPlatformPlugin - - Plugin implementing abstract functions for the Windows platform - - - - Plugin implementing specific functions for the Windows platform - - - - - WindowsServiceControl - - The service "%1" is already installed. - - - - The service "%1" could not be installed. - - - - The service "%1" has been installed successfully. - - - - The service "%1" could not be uninstalled. - - - - The service "%1" has been uninstalled successfully. - - - - The start type of service "%1" could not be changed. - - - - Service "%1" could not be found. - - - - - X11VncConfigurationWidget - - Builtin x11vnc server configuration - - - - Custom x11vnc parameters: - - - - Do not use X Damage extension - - - - \ No newline at end of file diff --git a/translations/sv.ts b/translations/sv.ts deleted file mode 100644 index 92b4d6ae1..000000000 --- a/translations/sv.ts +++ /dev/null @@ -1,4169 +0,0 @@ - - - AboutDialog - - About - Om - - - Translation - - - - License - - - - About Veyon - Om Veyon - - - Contributors - Medarbetare - - - Version: - Version: - - - Website: - Hemsida - - - Current language not translated yet (or native English). - -If you're interested in translating Veyon into your local or another language or want to improve an existing translation, please contact a Veyon developer! - Nuvarande språk ej översatt än (eller originalspråk Engelska). - -Om du är intresserad av att översätta Veyon till ditt lokala eller ett ett annat språk, vänligen kontakta en Veyon-utvecklare! - - - About %1 %2 - Om %1 %2 - - - Support Veyon project with a donation - Stöd Veyon-projektet med en donation - - - - AccessControlPage - - Computer access control - Datoråtkomstskontroll - - - Grant access to every authenticated user (default) - Bevilja åtkomst för alla autentiserade användare (standard) - - - Test - Test - - - Process access control rules - Processåtkomstkontroll-regler - - - User groups authorized for computer access - Användargrupper auktoriserade för datoråtkomst - - - Please add the groups whose members should be authorized to access computers in your Veyon network. - Vänligen lägg till grupperna vilkas medlemmar ska vara auktoriserade för att komma åt datorer i ditt Veyon-nätverk. - - - Authorized user groups - Auktoriserade användargrupper - - - All groups - Alla grupper - - - ... - ... - - - Access control rules - Åtkomstregler - - - Add access control rule - Lägg till åtkomstregel - - - Remove access control rule - Ta bort åtkomstregel - - - Move selected rule down - Flytta vald regel nedåt - - - Move selected rule up - Flytta vald regel uppåt - - - Edit selected rule - Redigera vald regel - - - Enter username - Skriv in användarnamn - - - Please enter a user login name whose access permissions to test: - Vänligen skriv in ett användarnamn vars åtkomstbehörigheter ska testas: - - - Access allowed - Åtkomst beviljad - - - The specified user is allowed to access computers with this configuration. - Den specificerade användaren är tillåten att komma åt datorer med den här konfigurationen. - - - Access denied - Åtkomst nekad - - - The specified user is not allowed to access computers with this configuration. - Den specificerade användaren är inte tillåten att komma åt datorer med den här konfigurationen. - - - Enable usage of domain groups - Aktivera användandet av domängrupper - - - User groups backend: - Backend för användargrupper: - - - Missing user groups backend - Saknad backend för användargrupper - - - No default user groups plugin was found. Please check your installation! - Inget standard användargrupp-plugin kunde hittas. Vänligen kontrollera din installation! - - - Restrict access to members of specific user groups - - - - - AccessControlRuleEditDialog - - Edit access control rule - Redigera åtkomstregel - - - General - Allmänt - - - enter a short name for the rule here - skriv in ett kort namn på regeln här - - - Rule name: - Regelnamn: - - - enter a description for the rule here - skriv in en beskrivning av regeln här - - - Rule description: - Regelbeskrivning: - - - Invert all conditions ("is/has" interpreted as "is/has not") - Invertera alla villkor ("är/har" tolkas som "är/har inte") - - - Conditions - Villkor - - - is member of group - är medlem av gruppen - - - Accessing computer is localhost - Åtkomstdator är localhost - - - Accessing user is logged on user - Åtkomstanvändare är inloggad användare - - - Accessing user is already connected - Åtkomstanvändare är redan ansluten - - - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. - Om fler än ett villkor aktiveras behöver varje villkor mötas för att regeln ska gälla (logiskt OCH). Om endast en av flera villkor behöver mötas (logiskt ELLER) vänligen skapa flera åtkomstregler. - - - Action - Åtgärd - - - Allow access - Bevilja åtkomst - - - Deny access - Neka åtkomst - - - Ask logged on user for permission - Fråga inloggad användare om tillstånd - - - None (rule disabled) - Inga (regel inaktiverad) - - - Accessing user - Åtkomstanvändare - - - Accessing computer - Åtkomstdator - - - Local (logged on) user - Lokal (inloggad) användare - - - Local computer - Lokal dator - - - Always process rule and ignore conditions - Bearbeta alltid regel- och ignoreringsvillkor - - - No user logged on - Ingen användare inloggad - - - Accessing user has one or more groups in common with local (logged on) user - Åtkomstanvändaren har en eller flera grupper gemensamt med lokal (inloggad) användare - - - Accessing computer and local computer are at the same location - - - - is located at - - - - - AccessControlRulesTestDialog - - Access control rules test - Åtkomstregel-test - - - Accessing user: - - - - Local computer: - - - - Accessing computer: - - - - Please enter the following user and computer information in order to test the configured ruleset. - - - - Local user: - - - - Connected users: - - - - The access in the given scenario is allowed. - - - - The access in the given scenario is denied. - - - - The access in the given scenario needs permission of the logged on user. - - - - ERROR: Unknown action - - - - Test result - - - - - AndroidPlatformConfigurationPage - - Android - - - - General - Allmänt - - - - AndroidPlatformPlugin - - Plugin implementing specific functions for the Android platform - - - - - AuthKeysConfigurationPage - - Authentication keys - - - - Introduction - - - - Key file directories - - - - Public key file base directory - - - - Private key file base directory - - - - ... - ... - - - Available authentication keys - - - - Create key pair - - - - Delete key - - - - Import key - - - - Export key - - - - Set access group - - - - Key files (*.pem) - - - - Authentication key name - - - - Please enter the name of the user group or role for which to create an authentication key pair: - - - - Do you really want to delete authentication key "%1/%2"? - - - - Please select a key to delete! - - - - Please enter the name of the user group or role for which to import the authentication key: - - - - Please select a key to export! - - - - Please select a user group which to grant access to key "%1": - - - - Please select a key which to set the access group for! - - - - Please perform the following steps to set up key file authentication: - - - - 1) Create a key pair on the master computer. - - - - 2) Set an access group whose members should be allowed to access other computers. - - - - 3) Export the public key and import it on all client computers with the same name. - - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - - - - - AuthKeysManager - - Please check your permissions. - - - - Key name contains invalid characters! - - - - Invalid key type specified! Please specify "%1" or "%2". - - - - Specified key does not exist! Please use the "list" command to list all installed keys. - - - - One or more key files already exist! Please delete them using the "delete" command. - - - - Creating new key pair for "%1" - - - - Failed to create public or private key! - - - - Newly created key pair has been saved to "%1" and "%2". - - - - Could not remove key file "%1"! - - - - Could not remove key file directory "%1"! - - - - Failed to create directory for output file. - - - - File "%1" already exists. - - - - Failed to write output file. - - - - Key "%1/%2" has been exported to "%3" successfully. - - - - Failed read input file. - - - - File "%1" does not contain a valid private key! - - - - File "%1" does not contain a valid public key! - - - - Failed to create directory for key file. - - - - Failed to write key file "%1". - - - - Failed to set permissions for key file "%1"! - - - - Key "%1/%2" has been imported successfully. Please check file permissions of "%3" in order to prevent unauthorized accesses. - - - - Failed to convert private key to public key - - - - Failed to create directory for private key file "%1". - - - - Failed to save private key in file "%1"! - - - - Failed to set permissions for private key file "%1"! - - - - Failed to create directory for public key file "%1". - - - - Failed to save public key in file "%1"! - - - - Failed to set permissions for public key file "%1"! - - - - Failed to set owner of key file "%1" to "%2". - - - - Failed to set permissions for key file "%1". - - - - Key "%1" is now accessible by user group "%2". - - - - <N/A> - - - - Failed to read key file. - - - - - AuthKeysPlugin - - Create new authentication key pair - - - - Delete authentication key - - - - List authentication keys - - - - Import public or private key - - - - Export public or private key - - - - Extract public key from existing private key - - - - Set user group allowed to access a key - - - - KEY - - - - ACCESS GROUP - - - - This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. - - - - NAME - - - - FILE - - - - This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - - - - This command imports the authentication key <KEY> from <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - - - - This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - - - - Please specify the command to display help for! - - - - TYPE - - - - PAIR ID - - - - Command line support for managing authentication keys - - - - Commands for managing authentication keys - - - - This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. - - - - This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. - - - - This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. - - - - - AuthKeysTableModel - - Name - - - - Type - - - - Access group - - - - Pair ID - - - - - BuiltinDirectoryConfigurationPage - - Computers - - - - Name - - - - Host address/IP - - - - MAC address - - - - Add new computer - - - - Remove selected computer - - - - New computer - - - - Builtin directory - - - - Locations & computers - - - - Locations - - - - Add new location - - - - Remove selected location - - - - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - - - - New location - - - - - BuiltinDirectoryPlugin - - Show help for specific command - - - - Import objects from given file - - - - Export objects to given file - - - - Invalid type specified. Valid values are "%1" or "%2". - - - - Type - - - - Name - - - - Host address - - - - MAC address - - - - Specified object not found. - - - - File "%1" does not exist! - - - - Can't open file "%1" for reading! - - - - Unknown argument "%1". - - - - Computer "%1" (host address: "%2" MAC address: "%3") - - - - Unclassified object "%1" with ID "%2" - - - - None - - - - Computer - - - - Root - - - - Invalid - - - - Error while parsing line %1. - - - - Network object directory which stores objects in local configuration - - - - Commands for managing the builtin network object directory - - - - No format string or regular expression specified! - - - - Can't open file "%1" for writing! - - - - No format string specified! - - - - Object UUID - - - - Parent UUID - - - - Add a location or computer - - - - Clear all locations and computers - - - - Dump all or individual locations and computers - - - - List all locations and computers - - - - Remove a location or computer - - - - Location "%1" - - - - Builtin (computers and locations in local configuration) - - - - Location - - - - FILE - - - - LOCATION - - - - FORMAT-STRING-WITH-PLACEHOLDERS - - - - REGULAR-EXPRESSION-WITH-PLACEHOLDER - - - - Imports objects from the specified text file using the given format string or regular expression containing one or multiple placeholders. Valid placeholders are: %1 - - - - Import simple CSV file to a single room - - - - Import CSV file with location name in first column - - - - Import text file with with key/value pairs using regular expressions - - - - Import arbitrarily formatted data - - - - Exports objects to the specified text file using the given format string containing one or multiple placeholders. Valid placeholders are: %1 - - - - Export all objects to a CSV file - - - - Export all computers in a specific location to a CSV file - - - - TYPE - - - - NAME - - - - PARENT - - - - Adds an object where %1 can be one of "%2" or "%3". %4 can be specified by name or UUID. - - - - Add a room - - - - Add a computer to room %1 - - - - OBJECT - - - - Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. - - - - Remove a computer by name - - - - Remove an object by UUID - - - - "Room 01" - - - - "Computer 01" - - - - HOST ADDRESS - - - - MAC ADDRESS - - - - - BuiltinUltraVncServer - - Builtin VNC server (UltraVNC) - - - - - BuiltinX11VncServer - - Builtin VNC server (x11vnc) - - - - - ComputerControlListModel - - Host/IP address: %1 - - - - Active features: %1 - - - - Online and connected - - - - Establishing connection - - - - Computer offline or switched off - - - - Service unreachable or not running - - - - Authentication failed or access denied - - - - Disconnected - - - - No user logged on - Ingen användare inloggad - - - Logged on user: %1 - - - - Location: %1 - - - - - ComputerControlServer - - %1 Service %2 at %3:%4 - - - - Authentication error - Autentiseringsfel - - - Remote access - - - - User "%1" at host "%2" is now accessing this computer. - - - - User "%1" at host "%2" attempted to access this computer but could not authenticate successfully. - - - - Access control error - - - - User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. - - - - - ComputerManager - - User - - - - Missing network object directory plugin - - - - No default network object directory plugin was found. Please check your installation or configure a different network object directory backend via %1 Configurator. - - - - Location detection failed - - - - Computer name;Hostname;User - - - - Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. - - - - - ComputerSelectPanel - - Computer management - - - - Computer search - - - - Add location - - - - Save computer/user list - - - - Select output filename - - - - CSV files (*.csv) - - - - File error - - - - Could not write the computer and users list to %1! Please check the file access permissions. - - - - - ConfigCommandLinePlugin - - Please specify an existing configuration file to import. - - - - Please specify a valid filename for the configuration export. - - - - Please specify a valid key. - - - - Specified key does not exist in current configuration! - - - - Please specify a valid value. - - - - Configure Veyon at command line - - - - Output file is not writable! - - - - Output directory is not writable! - - - - Configuration file is not readable! - - - - Clear system-wide Veyon configuration - - - - List all configuration keys and values - - - - Import configuration from given file - - - - Export configuration to given file - - - - Read and output configuration value for given key - - - - Write given value to given configuration key - - - - Unset (remove) given configuration key - - - - Commands for managing the configuration of Veyon - - - - Upgrade and save configuration of program and plugins - - - - - ConfigurationManager - - Could not modify the autostart property for the %1 Service. - - - - Could not configure the firewall configuration for the %1 Server. - - - - Could not configure the firewall configuration for the %1 Worker. - - - - Configuration is not writable. Please check your permissions! - - - - Could not apply platform-specific configuration settings. - - - - - DemoClient - - %1 Demo - - - - - DemoConfigurationPage - - Demo server - Demoserver - - - Tunables - - - - ms - - - - Key frame interval - - - - Memory limit - - - - Use multithreading (experimental) - - - - MB - - - - Update interval - - - - s - - - - Slow down thumbnail updates while demo is running - - - - - DemoFeaturePlugin - - Fullscreen demo - Demo i helskärm - - - Stop demo - - - - Window demo - Demo i fönster - - - Give a demonstration by screen broadcasting - - - - Demo server - Demoserver - - - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - - - - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - - - - - DesktopAccessDialog - - Desktop access dialog - - - - Confirm desktop access - - - - Never for this session - Aldrig för denna session - - - Always for this session - Alltid för denna session - - - The user %1 at computer %2 wants to access your desktop. Do you want to grant access? - - - - - DesktopServicesConfigurationPage - - Programs & websites - - - - Predefined programs - - - - Name - - - - Path - - - - Add new program - - - - Remove selected program - - - - Predefined websites - - - - Remove selected website - - - - URL - - - - New program - - - - New website - - - - - DesktopServicesFeaturePlugin - - Run program - - - - Open website - - - - Click this button to open a website on all computers. - - - - Start programs and services in user desktop - - - - Click this button to run a program on all computers. - - - - Run program "%1" - - - - Custom program - - - - Open website "%1" - - - - Custom website - - - - - DocumentationFigureCreator - - Teacher - Lärare - - - Room %1 - - - - Please complete all tasks within the next 5 minutes. - - - - Custom website - - - - Open file manager - - - - Start learning tool - - - - Play tutorial video - - - - Custom program - - - - Handout - - - - Texts to read - - - - - ExternalVncServer - - External VNC server - - - - - ExternalVncServerConfigurationWidget - - External VNC server configuration - - - - Port: - - - - Password: - - - - - FeatureControl - - Feature control - - - - - FileTransferController - - Could not open file "%1" for reading! Please check your permissions! - - - - - FileTransferDialog - - File transfer - - - - Options - - - - Transfer only - - - - Transfer and open file(s) with associated program - - - - Transfer and open destination folder - - - - Files - - - - Start - - - - Overwrite existing files - - - - - FileTransferPlugin - - File transfer - - - - Click this button to transfer files from your computer to all computers. - - - - Select one or more files to transfer - - - - Transfer files to remote computer - - - - Received file "%1". - - - - Could not receive file "%1" as it already exists. - - - - Could not receive file "%1" as it could not be opened for writing! - - - - - GeneralConfigurationPage - - User interface - Användargränssnitt - - - Language: - - - - Use system language setting - - - - Veyon - - - - Logging - Loggning - - - Log file directory - Loggfilskatalog - - - ... - ... - - - Log level - Loggnivå - - - Nothing - Ingenting - - - Only critical messages - Endast kritiska meddelanden - - - Errors and critical messages - Fel och kritiska meddelanden - - - Warnings and errors - Varningar och fel - - - Information, warnings and errors - Information, varningar och fel - - - Debug messages and everything else - Felsökningsmeddelanden och allting annat - - - Limit log file size - Begränsa storlek på loggfil - - - Clear all log files - Töm alla loggfiler - - - Log to standard error output - - - - Network object directory - - - - Backend: - - - - Update interval: - - - - %1 service - - - - The %1 service needs to be stopped temporarily in order to remove the log files. Continue? - - - - Log files cleared - - - - All log files were cleared successfully. - - - - Error - - - - Could not remove all log files. - - - - MB - - - - Rotate log files - - - - x - - - - seconds - sekunder - - - Write to logging system of operating system - - - - Authentication - Autentisering - - - Method: - - - - Logon authentication - - - - Key file authentication - - - - Test - Test - - - Authentication is set up properly on this computer. - - - - Authentication keys are not set up properly on this computer. - - - - Authentication test - - - - - InternetAccessControlConfigurationPage - - Internet access control - - - - Backend: - - - - General settings - - - - Backend settings - - - - - InternetAccessControlPlugin - - Block access to the internet - - - - Allow access to the internet - - - - Show help about command - - - - Block internet - - - - Click this button to block access to the internet. - - - - Unblock internet - - - - Click this button to allow access to the internet. - - - - Control access to the internet - - - - Commands for controlling access to the internet - - - - - LdapBrowseDialog - - Browse LDAP - - - - - LdapClient - - LDAP error description: %1 - - - - - LdapConfigurationPage - - Basic settings - - - - General - Allmänt - - - LDAP server and port - - - - Bind DN - - - - Bind password - - - - Anonymous bind - - - - Use bind credentials - - - - Base DN - - - - Fixed base DN - - - - e.g. dc=example,dc=org - - - - Discover base DN by naming context - - - - e.g. namingContexts or defaultNamingContext - - - - Environment settings - - - - Object trees - - - - Computer tree - - - - e.g. OU=Groups - - - - User tree - - - - e.g. OU=Users - - - - e.g. OU=Computers - - - - Group tree - - - - Perform recursive search operations in object trees - - - - Object attributes - - - - e.g. hwAddress - - - - e.g. member or memberUid - - - - e.g. dNSHostName - - - - Computer MAC address attribute - - - - Group member attribute - - - - e.g. uid or sAMAccountName - - - - Advanced settings - - - - Optional object filters - - - - Filter for user groups - - - - Filter for users - - - - Filter for computer groups - - - - Group member identification - - - - Distinguished name (Samba/AD) - - - - List all groups of a user - - - - List all groups of a computer - - - - Get computer object by IP address - - - - LDAP connection failed - - - - LDAP bind failed - - - - LDAP bind successful - - - - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - - - - LDAP base DN test failed - - - - LDAP base DN test successful - - - - LDAP naming context test failed - - - - LDAP naming context test successful - - - - The LDAP naming context has been queried successfully. The following base DN was found: -%1 - - - - user tree - - - - group tree - - - - computer tree - - - - Enter username - Skriv in användarnamn - - - Please enter a user login name (wildcards allowed) which to query: - - - - user objects - - - - Enter group name - - - - Please enter a group name whose members to query: - - - - group members - - - - Group not found - - - - Could not find a group with the name "%1". Please check the group name or the group tree parameter. - - - - Enter computer name - - - - computer objects - - - - Enter computer DN - - - - Please enter the DN of a computer whose MAC address to query: - - - - computer MAC addresses - - - - users - - - - user groups - - - - computer groups - - - - Please enter a user login name whose group memberships to query: - - - - groups of user - - - - User not found - - - - groups of computer - - - - Computer not found - - - - Enter computer IP address - - - - Please enter a computer IP address which to resolve to an computer object: - - - - computers - - - - LDAP %1 test failed - - - - LDAP %1 test successful - - - - The %1 has been queried successfully and %2 entries were found. - - - - %1 %2 have been queried successfully: - -%3 - - - - LDAP filter test failed - - - - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 - - - - LDAP filter test successful - - - - %1 %2 have been queried successfully using the configured filter. - - - - (only if different from group tree) - - - - Computer group tree - - - - computer group tree - - - - Filter for computers - - - - e.g. room or computerLab - - - - Integration tests - - - - Computer groups - - - - e.g. name or description - - - - Filter for computer containers - - - - Computer containers or OUs - - - - Connection security - - - - TLS certificate verification - - - - System defaults - - - - Never (insecure!) - - - - Custom CA certificate file - - - - None - - - - TLS - - - - SSL - - - - e.g. (objectClass=computer) - - - - e.g. (objectClass=group) - - - - e.g. (objectClass=person) - - - - e.g. (objectClass=room) or (objectClass=computerLab) - - - - e.g. (objectClass=container) or (objectClass=organizationalUnit) - - - - Could not query the configured base DN. Please check the base DN parameter. - -%1 - - - - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - - - - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - - - - Certificate files (*.pem) - - - - Could not connect to the LDAP server. Please check the server parameters. - -%1 - - - - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - - - - Encryption protocol - - - - Computer location attribute - - - - Computer display name attribute - - - - Location name attribute - - - - e.g. cn or displayName - - - - Computer locations identification - - - - Identify computer locations (e.g. rooms) via: - - - - Location attribute in computer objects - - - - List all entries of a location - - - - List all locations - - - - Enter computer display name - - - - Please enter a computer display name to query: - - - - Enter computer location name - - - - Please enter the name of a computer location (wildcards allowed): - - - - computer locations - - - - Enter location name - - - - Please enter the name of a location whose entries to query: - - - - location entries - - - - LDAP test failed - - - - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - - - - and - - - - LDAP test successful - - - - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - - - - Browse - - - - Test - Test - - - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - - - - Computer hostname attribute - - - - Please enter a computer hostname to query: - - - - Invalid hostname - - - - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - - - - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - - - - Could not find a user with the name "%1". Please check the username or the user tree parameter. - - - - Enter hostname - - - - Please enter a computer hostname whose group memberships to query: - - - - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - - - - Hostname lookup failed - - - - Could not lookup hostname for IP address %1. Please check your DNS server settings. - - - - User login name attribute - - - - Configured attribute for user login name or computer hostname (OpenLDAP) - - - - computer containers - - - - - LdapPlugin - - Auto-configure the base DN via naming context - - - - Query objects from LDAP directory - - - - Show help about command - - - - Commands for configuring and testing LDAP/AD integration - - - - Basic LDAP/AD support for Veyon - - - - %1 (load computers and locations from LDAP/AD) - - - - %1 (load users and groups from LDAP/AD) - - - - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - - - - No naming context attribute name given - falling back to configured value. - - - - Could not query base DN. Please check your LDAP configuration. - - - - Configuring %1 as base DN and disabling naming context queries. - - - - - LdapProConfigurationPage - - LDAP Pro - - - - Instances - - - - Enter name - - - - Please enter a name for the instance (can't be changed later!): - - - - Remove instance - - - - Do you really want to remove instance "%1"? - - - - Configuration for instance "%1" - - - - - LdapProPlugin - - Professional LDAP/AD integration for Veyon - - - - %1 (load computers and locations from LDAP/AD) - - - - %1 (load users and groups from LDAP/AD) - - - - - LicensingConfigurationPage - - Licensing - - - - Installed licenses - - - - Add new network range - - - - Remove selected network range - - - - ID - - - - Feature - - - - Valid until - - - - Licensee - - - - Browse license file - - - - Veyon license files (*.vlf) - - - - Remove license - - - - Do you really want to remove the selected license? - - - - <N/A> - - - - Invalid license file - - - - Could not open the license file for reading! - - - - The selected license file does not contain valid data. - - - - The selected license file could not be verified. - - - - The selected license file is not valid for this installation. - - - - The selected license file is expired. - - - - The license is already installed. - - - - Information - - - - Installation ID - - - - Addons available for licensing - - - - Addon - - - - - LicensingPlugin - - Show help for specific command - - - - Show all installed licenses - - - - Add license file - - - - Remove installed license - - - - -USAGE - -%1 add <LICENSE FILE> - - - - - - -USAGE - -%1 remove <LICENSE ID> - - - - - - No certificate found with given ID - - - - <N/A> - - - - Licensing management - - - - Commands for managing license keys - - - - - LinuxPlatformConfigurationPage - - Linux - - - - Custom PAM service for user authentication - - - - User authentication - - - - Session management - - - - Display manager users - - - - - LinuxPlatformPlugin - - Plugin implementing abstract functions for the Linux platform - - - - Plugin implementing specific functions for the Linux platform - - - - - LocationDialog - - Select location - - - - enter search filter... - - - - - MainToolBar - - Configuration - - - - Disable balloon tooltips - - - - Show icons only - - - - - MainWindow - - MainWindow - Huvudfönster - - - toolBar - verktygsrad - - - General - Allmänt - - - &File - &Arkiv - - - &Help - &Hjälp - - - &Quit - A&vsluta - - - Ctrl+Q - Ctrl+Q - - - Ctrl+S - Ctrl+S - - - L&oad settings from file - &Läs in inställningar från fil - - - Ctrl+O - Ctrl+O - - - About Qt - Om Qt - - - Authentication impossible - - - - Configuration not writable - Konfigurationen är inte skrivbar - - - Load settings from file - Läs in inställningar från fil - - - Save settings to file - Spara inställningar till fil - - - Unsaved settings - Osparade inställningar - - - There are unsaved settings. Quit anyway? - Det finns osparade inställningar. Avsluta ändå? - - - Veyon Configurator - - - - Service - - - - Master - - - - Access control - - - - About Veyon - Om Veyon - - - Auto - - - - About - Om - - - %1 Configurator %2 - - - - JSON files (*.json) - - - - The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - - - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - - - - Access denied - Åtkomst nekad - - - According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. - - - - Screenshots - - - - Feature active - - - - The feature "%1" is still active. Please stop it before closing %2. - - - - Reset configuration - - - - Do you really want to reset the local configuration and revert all settings to their defaults? - - - - Search users and computers - - - - Adjust optimal size - - - - Align computers to grid - - - - %1 Configurator - - - - Insufficient privileges - - - - Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. - - - - Only show powered on computers - - - - &Save settings to file - - - - &View - - - - &Standard - - - - &Advanced - - - - Use custom computer arrangement - - - - Locations && computers - - - - - MasterConfigurationPage - - Directories - - - - ... - ... - - - User configuration - - - - Feature on computer double click: - - - - Features - - - - All features - - - - Disabled features - - - - Screenshots - - - - <no feature> - - - - Basic settings - - - - Behaviour - - - - Enforce selected mode for client computers - - - - Hide local computer - - - - Hide computer filter field - - - - Actions such as rebooting or powering down computers - - - - User interface - Användargränssnitt - - - Background color - - - - Thumbnail update interval - - - - ms - - - - Program start - - - - Modes and features - - - - User and computer name - - - - Only user name - - - - Only computer name - - - - Computer thumbnail caption - - - - Text color - - - - Sort order - - - - Computer and user name - - - - Computer locations - - - - Show current location only - - - - Allow adding hidden locations manually - - - - Hide empty locations - - - - Show confirmation dialog for potentially unsafe actions - - - - Perform access control - - - - Automatically select current location - - - - Automatically adjust computer thumbnail size - - - - Automatically open computer select panel - - - - - MonitoringMode - - Monitoring - - - - Builtin monitoring mode - - - - This mode allows you to monitor all computers at one or more locations. - - - - - NetworkDiscoveryConfigurationPage - - Network discovery - - - - Mode - - - - Scan network ranges - - - - e.g. 192.168.1.0/24 - - - - Scan all subnets of computer - - - - Scan custom subnet - - - - Scan sessions on local computer - - - - Test - Test - - - Network ranges - - - - Add new group - - - - Remove selected group - - - - Groups - - - - First address - - - - Last address - - - - Add new network range - - - - Remove selected network range - - - - Parallel scans - - - - Scan timeout - - - - ms - - - - Session scan limit - - - - Options - - - - Reverse lookup discovered IP addresses to host names - - - - New location - - - - - NetworkDiscoveryDirectory - - Scanning... - - - - Discovered computers - - - - - NetworkDiscoveryPlugin - - Show help for specific command - - - - Scan a subnet - - - - -USAGE - -%1 scan [<SUBNET>] - - - - - - Network object directory which automatically discovers computers in the network - - - - Network discovery (scan network for Veyon clients) - - - - Commands for managing the network discovery directory - - - - - NetworkObjectTreeModel - - Locations/Computers - - - - - OpenWebsiteDialog - - Open website - - - - e.g. Veyon - - - - Remember and add to website menu - - - - e.g. www.veyon.io - - - - Please enter the URL of the website to open: - - - - Name: - - - - - PasswordDialog - - Username - Användarnamn - - - Password - Lösenord - - - Veyon Logon - - - - Authentication error - Autentiseringsfel - - - Logon failed with given username and password. Please try again! - - - - Please enter your username and password in order to access computers. - - - - - PowerControlFeaturePlugin - - Power on - Starta - - - Click this button to power on all computers. This way you do not have to power on each computer by hand. - - - - Reboot - Starta om - - - Click this button to reboot all computers. - - - - Power down - Stäng av - - - Click this button to power down all computers. This way you do not have to power down each computer by hand. - - - - Power on/down or reboot a computer - - - - Confirm reboot - - - - Confirm power down - - - - Do you really want to reboot the selected computers? - - - - Do you really want to power down the selected computer? - - - - Power on a computer via Wake-on-LAN (WOL) - - - - MAC ADDRESS - - - - This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. - - - - Please specify the command to display help for! - - - - Invalid MAC address specified! - - - - Commands for controlling power status of computers - - - - Power down now - - - - Install updates and power down - - - - Power down after user confirmation - - - - Power down after timeout - - - - The computer was remotely requested to power down. Do you want to power down the computer now? - - - - The computer will be powered down in %1 minutes, %2 seconds. - -Please save your work and close all programs. - - - - - PowerDownTimeInputDialog - - Power down - Stäng av - - - Please specify a timeout for powering down the selected computers: - - - - minutes - - - - seconds - - - - - RemoteAccessFeaturePlugin - - Remote view - - - - Open a remote view for a computer without interaction. - - - - Remote control - Fjärrstyrning - - - Open a remote control window for a computer. - - - - Remote access - - - - Remote view or control a computer - - - - Please enter the hostname or IP address of the computer to access: - - - - Show help about command - - - - - RemoteAccessWidget - - %1 - %2 Remote Access - - - - - RemoteAccessWidgetToolBar - - View only - Visa endast - - - Remote control - Fjärrstyrning - - - Send shortcut - - - - Fullscreen - Helskärm - - - Window - Fönster - - - Ctrl+Alt+Del - - - - Ctrl+Esc - - - - Alt+Tab - - - - Alt+F4 - - - - Win+Tab - - - - Win - - - - Menu - - - - Alt+Ctrl+F1 - - - - Connecting %1 - Ansluter %1 - - - Connected. - Ansluten. - - - Screenshot - - - - Exit - - - - - Routing - - Control internet access by modifying routing table - - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - - - - Add custom route to block internet - - - - Destination - - - - Gateway - - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - - - - Run programs - - - - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - - - - Name: - - - - Remember and add to program menu - - - - e.g. VLC - - - - - ScreenLockFeaturePlugin - - Lock - - - - Unlock - - - - Lock screen and input devices of a computer - - - - To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. - - - - - Screenshot - - unknown - okänd - - - Could not take a screenshot as directory %1 doesn't exist and couldn't be created. - - - - Screenshot - - - - - ScreenshotFeaturePlugin - - Screenshot - - - - Use this function to take a screenshot of selected computers. - - - - Screenshots taken - - - - Screenshot of %1 computer have been taken successfully. - - - - Take screenshots of computers and save them locally. - - - - - ScreenshotManagementPanel - - All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. - - - - User: - Användare: - - - Computer: - - - - Date: - Datum: - - - Time: - Tid: - - - Show - Visa - - - Delete - Ta bort - - - - ServiceConfigurationPage - - General - Allmänt - - - Autostart - Automatisk start - - - Hide tray icon - Dölj aktivitetsikonen - - - Start service - Starta tjänst - - - Stopped - Stoppad - - - Stop service - Stoppa tjänst - - - State: - Tillstånd: - - - Network - Nätverk - - - Demo server port - Serverport för demo - - - Enable firewall exception - Aktivera brandväggsundantag - - - Allow connections from localhost only - - - - Internal VNC server port - - - - VNC server - - - - Plugin: - - - - Restart %1 Service - - - - All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - - - - Running - Kör - - - Feature manager port - - - - Primary service port - - - - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. - - - - Show notification on remote connection - - - - Multi session mode (for terminal and remote desktop servers) - - - - Show notification when an unauthorized access is blocked - - - - - ServiceControl - - Starting service %1 - - - - Stopping service %1 - - - - Registering service %1 - - - - Unregistering service %1 - - - - Service control - - - - - ServiceControlPlugin - - Service is running - - - - Service is not running - - - - Configure and control Veyon service - - - - Register Veyon Service - - - - Unregister Veyon Service - - - - Start Veyon Service - - - - Stop Veyon Service - - - - Restart Veyon Service - - - - Query status of Veyon Service - - - - Commands for configuring and controlling Veyon Service - - - - - ShellCommandLinePlugin - - Run command file - - - - File "%1" does not exist! - - - - Interactive shell and script execution for Veyon Control - - - - Commands for shell functionalities - - - - - SystemTrayIcon - - System tray icon - - - - - SystemUserGroupsPlugin - - User groups backend for system user groups - - - - Default (system user groups) - - - - - TestingCommandLinePlugin - - Test internal Veyon components and functions - - - - Commands for testing internal components and functions of Veyon - - - - - TextMessageDialog - - Send text message - Skicka textmeddelande - - - Use the field below to type your message which will be sent to all selected users. - - - - - TextMessageFeaturePlugin - - Text message - Textmeddelande - - - Use this function to send a text message to all users e.g. to assign them new tasks. - - - - Message from teacher - - - - Send a message to a user - - - - - UltraVncConfigurationWidget - - Enable capturing of layered (semi-transparent) windows - Aktivera fångst av flerskiktade fönster (semi-transparant) - - - Poll full screen (leave this enabled per default) - - - - Low accuracy (turbo mode) - Låg precision (turboläge) - - - Builtin UltraVNC server configuration - - - - Enable multi monitor support - - - - Enable Desktop Duplication Engine on Windows 8 and newer - - - - - UserConfig - - No write access - Ingen skrivåtkomst - - - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - - - - - UserSessionControl - - User session control - - - - Log off - - - - Click this button to log off users from all computers. - - - - Confirm user logoff - - - - Do you really want to log off the selected users? - - - - - VeyonCore - - [OK] - - - - [FAIL] - - - - Invalid command! - - - - Available commands: - - - - Invalid arguments given - - - - Not enough arguments given - use "%1 help" for more information - - - - Unknown result! - - - - Available modules: - - - - No module specified or module not found - available modules are: - - - - Plugin not licensed - - - - INFO - - - - ERROR - - - - licensed for - - - - USAGE - - - - DESCRIPTION - - - - EXAMPLES - - - - WARNING - - - - - VeyonServiceControl - - Veyon Service - - - - - VncView - - Establishing connection to %1 ... - Etablerar anslutning till %1... - - - - WindowsPlatformConfiguration - - Could not change the setting for SAS generation by software. Sending Ctrl+Alt+Del via remote control will not work! - - - - - WindowsPlatformConfigurationPage - - Windows - - - - General - Allmänt - - - Enable SAS generation by software (Ctrl+Alt+Del) - - - - Screen lock - - - - Hide taskbar - - - - Hide start menu - - - - Hide desktop - - - - User authentication - - - - Use alternative user authentication mechanism - - - - - WindowsPlatformPlugin - - Plugin implementing abstract functions for the Windows platform - - - - Plugin implementing specific functions for the Windows platform - - - - - WindowsServiceControl - - The service "%1" is already installed. - - - - The service "%1" could not be installed. - - - - The service "%1" has been installed successfully. - - - - The service "%1" could not be uninstalled. - - - - The service "%1" has been uninstalled successfully. - - - - The start type of service "%1" could not be changed. - - - - Service "%1" could not be found. - - - - - X11VncConfigurationWidget - - Builtin x11vnc server configuration - - - - Custom x11vnc parameters: - - - - Do not use X Damage extension - - - - \ No newline at end of file diff --git a/translations/veyon.ts b/translations/veyon.ts index cce141530..4d7d892bc 100644 --- a/translations/veyon.ts +++ b/translations/veyon.ts @@ -80,10 +80,6 @@ If you're interested in translating Veyon into your local or another langua All groups - - ... - - Access control rules @@ -141,15 +137,14 @@ If you're interested in translating Veyon into your local or another langua - Missing user groups backend - - - - No default user groups plugin was found. Please check your installation! + Restrict access to members of specific user groups + + + AccessControlProvider - Restrict access to members of specific user groups + Provider for access control features @@ -180,87 +175,159 @@ If you're interested in translating Veyon into your local or another langua - Invert all conditions ("is/has" interpreted as "is/has not") + Conditions - Conditions + If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. - is member of group + Action - Accessing computer is localhost + Allow access - Accessing user is logged on user + Deny access - Accessing user is already connected + Ask logged on user for permission - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. + None (rule disabled) - Action + Accessing user - Allow access + Accessing computer - Deny access + Always process rule and ignore conditions - Ask logged on user for permission + Accessing computer and local computer - None (rule disabled) + User being accessed - Accessing user + is logged in locally - Accessing computer + is logged in remotely - Local (logged on) user + No user is logged in locally - Local computer + One or multiple users are logged in locally - Always process rule and ignore conditions + No user is logged in remotely - No user logged on + One or multiple users are logged in remotely - Accessing user has one or more groups in common with local (logged on) user + is located at - Accessing computer and local computer are at the same location + is not located at - is located at + are located at the same location + + + + are not located the same location + + + + is member of group + + + + is not member of group + + + + is authenticated via + + + + is not authenticated via + + + + has one or more groups in common with user being accessed + + + + has no groups in common with user being accessed + + + + equals user being accessed + + + + is different from user being accessed + + + + is already connected + + + + is not connected + + + + is local computer + + + + is not local computer + + + + Computer being accessed + + + + Session being accessed is a user session + + + + Session being accessed is a login screen + + + + Local computer is already being accessed + + + + Local computer is not yet being accessed @@ -307,40 +374,42 @@ If you're interested in translating Veyon into your local or another langua - ERROR: Unknown action + Test result + + + + Authentication method - Test result + There is no matching rule with a valid action. The access is therefore denied. - AndroidPlatformConfigurationPage + AuthKeysConfigurationWidget - Android + Introduction - General + Please perform the following steps to set up key file authentication: - - - AndroidPlatformPlugin - Plugin implementing specific functions for the Android platform + 1) Create a key pair on the master computer. - - - AuthKeysConfigurationPage - Authentication keys + 2) Set an access group whose members should be allowed to access other computers. - Introduction + 3) Export the public key and import it on all client computers with the same name. + + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. @@ -356,11 +425,14 @@ If you're interested in translating Veyon into your local or another langua - ... + Available authentication keys - Available authentication keys + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. @@ -403,10 +475,6 @@ If you're interested in translating Veyon into your local or another langua Please select a key to delete! - - Please enter the name of the user group or role for which to import the authentication key: - - Please select a key to export! @@ -420,30 +488,9 @@ If you're interested in translating Veyon into your local or another langua - Please perform the following steps to set up key file authentication: - - - - 1) Create a key pair on the master computer. - - - - 2) Set an access group whose members should be allowed to access other computers. - - - - 3) Export the public key and import it on all client computers with the same name. - - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. @@ -644,10 +691,6 @@ The public key is used on client computers to authenticate incoming connection r This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - - Please specify the command to display help for! - - TYPE @@ -656,10 +699,6 @@ The public key is used on client computers to authenticate incoming connection r PAIR ID - - Command line support for managing authentication keys - - Commands for managing authentication keys @@ -676,193 +715,360 @@ The public key is used on client computers to authenticate incoming connection r This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. - - - AuthKeysTableModel - Name + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. - Type + Key file authentication - Access group + Key file - Pair ID + Please specify the key name (e.g. "teacher/public") as the first argument. - - - BuiltinDirectoryConfigurationPage - Computers + Please specify the command to display help for. + + + + The specified command does not exist or no help is available for it. + + + AuthKeysTableModel Name - Host address/IP + Type - MAC address + Access group - Add new computer + Pair ID + + + AuthLdapConfigurationWidget - Remove selected computer + General - New computer + Username to bind DN mapping: - Builtin directory + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + AuthLdapDialog - Locations & computers + Veyon Logon - Locations + Please enter your domain/LDAP username and password in order to access computers. - Add new location + Username - Remove selected location + Password - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + Authentication error - New location + Logon failed with given username and password. Please try again! - BuiltinDirectoryPlugin + AuthLogonDialog - Show help for specific command + Veyon Logon - Import objects from given file + Please enter your username and password in order to access computers. - Export objects to given file + Username - Invalid type specified. Valid values are "%1" or "%2". + Password - Type + Authentication error - Name + Logon failed with given username and password. Please try again! + + + AuthLogonPlugin - Host address + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - MAC address + Logon authentication - Specified object not found. + Logon + + + AuthSimpleDialog - File "%1" does not exist! + Veyon Logon - Can't open file "%1" for reading! + Please enter the Veyon password: - Unknown argument "%1". + Authentication error - Computer "%1" (host address: "%2" MAC address: "%3") + Logon failed with given password. Please try again! + + + AuthSimplePlugin - Unclassified object "%1" with ID "%2" + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. - None + Simple password authentication - Computer + Simple password + + + AuthenticationPage - Root + Authentication is set up properly on this computer. + + + AuthenticationPageTab - Invalid + Enabled - Error while parsing line %1. + Test + + + BuiltinDirectoryConfiguration - Network object directory which stores objects in local configuration + Builtin directory + + + BuiltinDirectoryConfigurationPage - Commands for managing the builtin network object directory + Computers - No format string or regular expression specified! + Name - Can't open file "%1" for writing! + Host address/IP - No format string specified! + MAC address - Object UUID + Add new computer - Parent UUID + Remove selected computer - Add a location or computer + New computer + + + + Builtin directory + + + + Locations + + + + Add new location + + + + Remove selected location + + + + New location + + + + Directory name + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + + + + BuiltinDirectoryPlugin + + Show help for specific command + + + + Import objects from given file + + + + Export objects to given file + + + + Invalid type specified. Valid values are "%1" or "%2". + + + + Type + + + + Name + + + + Host address + + + + MAC address + + + + Specified object not found. + + + + File "%1" does not exist! + + + + Can't open file "%1" for reading! + + + + Unknown argument "%1". + + + + Computer "%1" (host address: "%2" MAC address: "%3") + + + + Unclassified object "%1" with ID "%2" + + + + None + + + + Computer + + + + Root + + + + Invalid + + + + Error while parsing line %1. + + + + Network object directory which stores objects in local configuration + + + + Commands for managing the builtin network object directory + + + + No format string or regular expression specified! + + + + Can't open file "%1" for writing! + + + + No format string specified! + + + + Object UUID + + + + Parent UUID + + + + Add a location or computer @@ -997,6 +1203,14 @@ The public key is used on client computers to authenticate incoming connection r MAC ADDRESS + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. + + BuiltinUltraVncServer @@ -1014,10 +1228,6 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - - Active features: %1 @@ -1034,10 +1244,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off - - Service unreachable or not running - - Authentication failed or access denied @@ -1058,6 +1264,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 + + [no user] + + + + Veyon Server unreachable or not running + + + + Name: %1 + + + + Hostname: %1 + + + + unknown + + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + ComputerControlServer @@ -1089,6 +1327,17 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + + Active connections: + + + + + ComputerGroupSelector + + Group %1 + + ComputerManager @@ -1116,13 +1365,48 @@ The public key is used on client computers to authenticate incoming connection r Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + + Logged in since + + + + %1 days + + + + 1 day + + - ComputerSelectPanel + ComputerMonitoring + + Computers + + + + Search users and computers + + + + Select all + + + + Unselect all + + + + Add to group + + - Computer management + Remove from group + + + ComputerSelectPanel Computer search @@ -1151,79 +1435,83 @@ The public key is used on client computers to authenticate incoming connection r Could not write the computer and users list to %1! Please check the file access permissions. + + Search computers + + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. + Clear system-wide Veyon configuration - Please specify a valid filename for the configuration export. + List all configuration keys and values - Please specify a valid key. + Import configuration from given file - Specified key does not exist in current configuration! + Export configuration to given file - Please specify a valid value. + Read and output configuration value for given key - Configure Veyon at command line + Write given value to given configuration key - Output file is not writable! + Unset (remove) given configuration key - Output directory is not writable! + Upgrade and save configuration of program and plugins - Configuration file is not readable! + Please specify an existing configuration file to import. - Clear system-wide Veyon configuration + Configuration file is not readable! - List all configuration keys and values + Please specify a valid filename for the configuration export. - Import configuration from given file + Output file is not writable! - Export configuration to given file + Output directory is not writable! - Read and output configuration value for given key + Please specify a valid key. - Write given value to given configuration key + Specified key does not exist in current configuration! - Unset (remove) given configuration key + Please specify a valid value. - Commands for managing the configuration of Veyon + Configure Veyon at command line - Upgrade and save configuration of program and plugins + Commands for managing the configuration of Veyon @@ -1249,6 +1537,10 @@ The public key is used on client computers to authenticate incoming connection r Could not apply platform-specific configuration settings. + + Could not configure the firewall configuration for the %1 Service. + + DemoClient @@ -1280,11 +1572,7 @@ The public key is used on client computers to authenticate incoming connection r - Use multithreading (experimental) - - - - MB + MB @@ -1299,13 +1587,17 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running - - - DemoFeaturePlugin - Fullscreen demo + Bandwidth limit + + MB/s + + + + + DemoFeaturePlugin Stop demo @@ -1319,15 +1611,59 @@ The public key is used on client computers to authenticate incoming connection r - Demo server + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. + Demo - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Share your screen or allow a user to share his screen with other users. + + + + Full screen demo + + + + Share your own screen in fullscreen mode + + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share your own screen in a window + + + + Share selected user's screen in fullscreen mode + + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share selected user's screen in a window + + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + + + + Please select only one user screen to share. + + + + All screens @@ -1357,86 +1693,90 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - Programs & websites + Name - Predefined programs + Path - Name + Predefined websites - Path + Remove selected website - Add new program + URL - Remove selected program + New website - Predefined websites + Applications & websites - Remove selected website + Predefined applications - URL + Add new application - New program + Remove selected application - New website + Add new website + + + + New application DesktopServicesFeaturePlugin - Run program + Open website - Open website + Click this button to open a website on all computers. - Click this button to open a website on all computers. + Open website "%1" - Start programs and services in user desktop + Custom website - Click this button to run a program on all computers. + Start application - Run program "%1" + Click this button to start an application on all computers. - Custom program + Start application "%1" - Open website "%1" + Custom application - Custom website + Start apps and open websites in user sessions @@ -1471,15 +1811,19 @@ The public key is used on client computers to authenticate incoming connection r - Custom program + Handout - Handout + Texts to read - Texts to read + generic-student-user + + + + Custom application @@ -1506,9 +1850,164 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands + + List names of all available features + + + + Show table with details of all available features + + + + Start a feature on a remote host + + + + Stop a feature on a remote host + + + + Please specify the command to display help for. + + + + Displays a list with the names of all available features. + + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + + + + HOST ADDRESS + + + + FEATURE + + + + ARGUMENTS + + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + + + + Lock the screen + + + + Display a text message + + + + Test message + + + + Start an application + + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + + + + Unlock the screen + + + + The specified command does not exist or no help is available for it. + + + + Name + + + + Description + + + + Master + + + + Service + + + + Worker + + + + UID + + + + Plugin + + + + Invalid feature name or UID specified + + + + Error parsing the JSON-encoded arguments: %1 + + + + Failed to initialize credentials + + + + Could not establish a connection to host %1 + + + + Failed to send feature control message to host %1 + + + + Feature-related CLI operations + + + + Commands for controlling features + + + + + FileTransferConfigurationPage + + File transfer + + + + Directories + + + + Destination directory + + - Feature control + Default source directory + + + + Options + + + + Remember last source directory + + + + Create destination directory if it does not exist @@ -1554,6 +2053,13 @@ The public key is used on client computers to authenticate incoming connection r + + FileTransferFileDialog + + Select one or more files to transfer + + + FileTransferPlugin @@ -1611,10 +2117,6 @@ The public key is used on client computers to authenticate incoming connection r Log file directory - - ... - - Log level @@ -1656,7 +2158,91 @@ The public key is used on client computers to authenticate incoming connection r - Network object directory + %1 service + + + + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + + + + Log files cleared + + + + All log files were cleared successfully. + + + + Error + + + + Could not remove all log files. + + + + MB + + + + Rotate log files + + + + x + + + + Write to logging system of operating system + + + + TLS configuration + + + + Use certificate authority for TLS connections + + + + CA certificate file + + + + ... + + + + Host certificate file + + + + Host private key file + + + + Style: + + + + Native + + + + Color scheme: + + + + Light + + + + Dark + + + + User groups @@ -1664,491 +2250,541 @@ The public key is used on client computers to authenticate incoming connection r - Update interval: + Include user groups from domain - %1 service + Missing user groups backend - The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + No user groups plugin was found. Please check your installation! + + + HeadlessVncServer - Log files cleared + Headless VNC server + + + LdapBrowseDialog - All log files were cleared successfully. + Browse LDAP + + + LdapClient - Error + LDAP error description: %1 + + + LdapConfiguration - Could not remove all log files. + LDAP connection failed - MB + Could not connect to the LDAP server. Please check the server parameters. + +%1 - Rotate log files + LDAP bind failed - x + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 - seconds + LDAP bind successful - Write to logging system of operating system + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + + + + LDAP base DN test failed + + + + Could not query the configured base DN. Please check the base DN parameter. + +%1 + + + + LDAP base DN test successful + + + + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + + + + LDAP naming context test failed + + + + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + + + + LDAP naming context test successful + + + + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + + + + user tree - Authentication + User tree - Method: + group tree - Logon authentication + Group tree - Key file authentication + computer tree - Test + Computer tree - Authentication is set up properly on this computer. + computer group tree - Authentication keys are not set up properly on this computer. + Computer group tree - Authentication test + user objects - - - InternetAccessControlConfigurationPage - Internet access control + User login name attribute - Backend: + group members - General settings + Group member attribute - Backend settings + Group not found - - - InternetAccessControlPlugin - Block access to the internet + Could not find a group with the name "%1". Please check the group name or the group tree parameter. - Allow access to the internet + computer objects - Show help about command + Computer display name attribute - Block internet + Invalid hostname - Click this button to block access to the internet. + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Unblock internet + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - Click this button to allow access to the internet. + Computer hostname attribute - Control access to the internet + computer MAC addresses - Commands for controlling access to the internet + Computer MAC address attribute - - - LdapBrowseDialog - Browse LDAP + computer locations - - - LdapClient - LDAP error description: %1 + Computer location attribute - - - LdapConfigurationPage - Basic settings + Location name attribute - General + users - LDAP server and port + user groups - Bind DN + computers - Bind password + computer groups - Anonymous bind + computer containers - Use bind credentials + groups of user - Base DN + User not found - Fixed base DN + Could not find a user with the name "%1". Please check the username or the user tree parameter. - e.g. dc=example,dc=org + groups of computer - Discover base DN by naming context + Computer not found - e.g. namingContexts or defaultNamingContext + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - Environment settings + Hostname lookup failed - Object trees + Could not lookup hostname for IP address %1. Please check your DNS server settings. - Computer tree + location entries - e.g. OU=Groups + Computer groups filter - User tree + Computer locations identification - e.g. OU=Users + Filter for computer groups - e.g. OU=Computers + Invalid test value - Group tree + An empty or invalid value has been supplied for this test. - Perform recursive search operations in object trees + LDAP %1 test failed - Object attributes + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 - e.g. hwAddress + LDAP %1 test successful - e.g. member or memberUid + The %1 has been queried successfully and %2 entries were found. - e.g. dNSHostName + LDAP test failed - Computer MAC address attribute + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 - Group member attribute + and - e.g. uid or sAMAccountName + LDAP test successful - Advanced settings + %1 %2 have been queried successfully: + +%3 - Optional object filters + LDAP filter test failed - Filter for user groups + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 - Filter for users + LDAP filter test successful - Filter for computer groups + %1 %2 have been queried successfully using the configured filter. - Group member identification + LDAP directory + + + LdapConfigurationPage - Distinguished name (Samba/AD) + Basic settings - List all groups of a user + General - List all groups of a computer + LDAP server and port - Get computer object by IP address + Bind DN - LDAP connection failed + Bind password - LDAP bind failed + Anonymous bind - LDAP bind successful + Use bind credentials - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Base DN - LDAP base DN test failed + Fixed base DN - LDAP base DN test successful + e.g. dc=example,dc=org - LDAP naming context test failed + Discover base DN by naming context - LDAP naming context test successful + e.g. namingContexts or defaultNamingContext - The LDAP naming context has been queried successfully. The following base DN was found: -%1 + Environment settings - user tree + Object trees - group tree + Computer tree - computer tree + e.g. OU=Groups - Enter username + User tree - Please enter a user login name (wildcards allowed) which to query: + e.g. OU=Users - user objects + e.g. OU=Computers - Enter group name + Group tree - Please enter a group name whose members to query: + Perform recursive search operations in object trees - group members + Object attributes - Group not found + e.g. hwAddress - Could not find a group with the name "%1". Please check the group name or the group tree parameter. + e.g. member or memberUid - Enter computer name + e.g. dNSHostName - computer objects + Computer MAC address attribute - Enter computer DN + Group member attribute - Please enter the DN of a computer whose MAC address to query: + e.g. uid or sAMAccountName - computer MAC addresses + Advanced settings - users + Optional object filters - user groups + Filter for user groups - computer groups + Filter for users - Please enter a user login name whose group memberships to query: + Filter for computer groups - groups of user + Group member identification - User not found + Distinguished name (Samba/AD) - groups of computer + List all groups of a user - Computer not found + List all groups of a computer - Enter computer IP address + Get computer object by IP address - Please enter a computer IP address which to resolve to an computer object: + Enter username - computers + Please enter a user login name (wildcards allowed) which to query: - LDAP %1 test failed + Enter group name - LDAP %1 test successful + Please enter a group name whose members to query: - The %1 has been queried successfully and %2 entries were found. + Enter computer name - %1 %2 have been queried successfully: - -%3 + Enter computer DN - LDAP filter test failed + Please enter the DN of a computer whose MAC address to query: - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 + Please enter a user login name whose group memberships to query: - LDAP filter test successful + Enter computer IP address - %1 %2 have been queried successfully using the configured filter. + Please enter a computer IP address which to resolve to an computer object: @@ -2159,10 +2795,6 @@ The public key is used on client computers to authenticate incoming connection r Computer group tree - - computer group tree - - Filter for computers @@ -2239,42 +2871,12 @@ The public key is used on client computers to authenticate incoming connection r e.g. (objectClass=room) or (objectClass=computerLab) - - e.g. (objectClass=container) or (objectClass=organizationalUnit) - - - - Could not query the configured base DN. Please check the base DN parameter. - -%1 - - - - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - - - - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - - - - Certificate files (*.pem) - - - - Could not connect to the LDAP server. Please check the server parameters. - -%1 + + e.g. (objectClass=container) or (objectClass=organizationalUnit) - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 + Certificate files (*.pem) @@ -2333,10 +2935,6 @@ The public key is used on client computers to authenticate incoming connection r Please enter the name of a computer location (wildcards allowed): - - computer locations - - Enter location name @@ -2345,34 +2943,6 @@ The public key is used on client computers to authenticate incoming connection r Please enter the name of a location whose entries to query: - - location entries - - - - LDAP test failed - - - - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - - - - and - - - - LDAP test successful - - - - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - - Browse @@ -2394,51 +2964,54 @@ The public key is used on client computers to authenticate incoming connection r - Invalid hostname + Enter hostname - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Please enter a computer hostname whose group memberships to query: - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + User login name attribute - Could not find a user with the name "%1". Please check the username or the user tree parameter. + Configured attribute for user login name or computer hostname (OpenLDAP) - Enter hostname + Directory name - Please enter a computer hostname whose group memberships to query: + Query options - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Query nested user groups (supported by AD only) - Hostname lookup failed + Query timeout - Could not lookup hostname for IP address %1. Please check your DNS server settings. + ms - User login name attribute + Map container/OU structure 1:1 to locations + + + LdapNetworkObjectDirectoryConfigurationPage - Configured attribute for user login name or computer hostname (OpenLDAP) + LDAP - computer containers + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. @@ -2488,1373 +3061,1444 @@ The public key is used on client computers to authenticate incoming connection r Configuring %1 as base DN and disabling naming context queries. + + Test binding to an LDAP server + + + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + + + + LDAP bind + + - LdapProConfigurationPage + LinuxPlatformConfigurationPage - LDAP Pro + Linux - Instances + Custom PAM service for user authentication - Enter name + User authentication - Please enter a name for the instance (can't be changed later!): + User sessions - Remove instance + Minimum session lifetime before server start - Do you really want to remove instance "%1"? + User login - Configuration for instance "%1" + Login key sequence - LdapProPlugin + LinuxPlatformPlugin - Professional LDAP/AD integration for Veyon + Plugin implementing abstract functions for the Linux platform + + + LocationDialog - %1 (load computers and locations from LDAP/AD) + Select location - %1 (load users and groups from LDAP/AD) + enter search filter... - LicensingConfigurationPage + MainToolBar - Licensing + Configuration - Installed licenses + Show icons only - Add new network range + Disable tooltips + + + MainWindow - Remove selected network range + MainWindow - ID + toolBar - Feature + General - Valid until + &File - Licensee + &Help - Browse license file + &Quit - Veyon license files (*.vlf) + Ctrl+Q - Remove license + Ctrl+S - Do you really want to remove the selected license? + L&oad settings from file - <N/A> + Ctrl+O - Invalid license file + About Qt - Could not open the license file for reading! + Configuration not writable - The selected license file does not contain valid data. + Load settings from file - The selected license file could not be verified. + Save settings to file - The selected license file is not valid for this installation. + Unsaved settings - The selected license file is expired. + There are unsaved settings. Quit anyway? - The license is already installed. + Veyon Configurator - Information + Service - Installation ID + Master - Addons available for licensing + Access control - Addon + About Veyon - - - LicensingPlugin - Show help for specific command + Auto - Show all installed licenses + About - Add license file + %1 Configurator %2 - Remove installed license + JSON files (*.json) - -USAGE - -%1 add <LICENSE FILE> - - + The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - -USAGE - -%1 remove <LICENSE ID> - - + Access denied - No certificate found with given ID + According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. - <N/A> + Screenshots - Licensing management + Feature active - Commands for managing license keys + The feature "%1" is still active. Please stop it before closing %2. - - - LinuxPlatformConfigurationPage - Linux + Reset configuration - Custom PAM service for user authentication + Do you really want to reset the local configuration and revert all settings to their defaults? - User authentication + Search users and computers - Session management + Align computers to grid - Display manager users + %1 Configurator - - - LinuxPlatformPlugin - Plugin implementing abstract functions for the Linux platform + Insufficient privileges - Plugin implementing specific functions for the Linux platform + Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. - - - LocationDialog - Select location + Only show powered on computers - enter search filter... + &Save settings to file - - - MainToolBar - Configuration + &View - Disable balloon tooltips + &Standard - Show icons only + &Advanced + + + + Use custom computer arrangement + + + + Locations && computers + + + + Authentication + + + + Adjust size of computer icons automatically + + + + Slideshow + + + + Spotlight + + + + Veyon Master + + + + Locations & computers + + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + + + + Load computer positions + + + + Save computer positions - MainWindow + MasterConfigurationPage - MainWindow + Directories - toolBar + User configuration - General + Feature on computer double click: - &File + Features - &Help + All features - &Quit + Disabled features - Ctrl+Q + Screenshots - Ctrl+S + <no feature> - L&oad settings from file + Basic settings - Ctrl+O + Behaviour - About Qt + Enforce selected mode for client computers - Authentication impossible + Hide local computer - Configuration not writable + Hide computer filter field - Load settings from file + Actions such as rebooting or powering down computers - Save settings to file + User interface - Unsaved settings + Background color - There are unsaved settings. Quit anyway? + Thumbnail update interval - Veyon Configurator + ms - Service + Program start - Master + Modes and features - Access control + User and computer name + + + + Only user name + + + + Only last part of user name + + + + Only computer name + + + + Computer thumbnail caption - About Veyon + Text color - Auto + Sort order - About + Computer and user name - %1 Configurator %2 + Computer locations - JSON files (*.json) + Show current location only - The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. + Allow adding hidden locations manually - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. + Hide empty locations - Access denied + Show confirmation dialog for potentially unsafe actions - According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. + Perform access control - Screenshots + Automatically select current location - Feature active + Automatically open computer select panel - The feature "%1" is still active. Please stop it before closing %2. + Use modern user interface (experimental) - Reset configuration + Thumbnail spacing - Do you really want to reset the local configuration and revert all settings to their defaults? + px - Search users and computers + Hide local session - Adjust optimal size + Auto - Align computers to grid + Thumbnail aspect ratio - %1 Configurator + Automatically adjust computer icon size - Insufficient privileges + Open feature windows on the same screen as the main window - Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + Configuration templates - Only show powered on computers + Image quality in monitoring mode - &Save settings to file + Highest - &View + High - &Standard + Medium - &Advanced + Low - Use custom computer arrangement + Lowest - Locations && computers + Remote access image quality - - - MasterConfigurationPage - Directories + Advanced - ... + Computer name source - User configuration + Default - Feature on computer double click: + Host address - Features + Session client address - All features + Session client name - Disabled features + Session host name - Screenshots + Session metadata - <no feature> + Full name of user - Basic settings + User login name - Behaviour + Computer UID role - Enforce selected mode for client computers + Session meta data hash - Hide local computer + Always expand all locations - Hide computer filter field + Image quality + + + MonitoringMode - Actions such as rebooting or powering down computers + Monitoring - User interface + Builtin monitoring mode - Background color + This mode allows you to monitor all computers at one or more locations. - Thumbnail update interval + Query application version of the server - ms + Query active features - Program start + Query properties of remotely available screens + + + NestedNetworkObjectDirectory - Modes and features + All directories + + + NetworkObjectDirectoryConfigurationPage - User and computer name + Update interval: - Only user name + seconds + + + NetworkObjectDirectoryConfigurationPageTab - Only computer name + Enabled + + + NetworkObjectTreeModel - Computer thumbnail caption + Locations/Computers + + + OpenWebsiteDialog - Text color + Open website - Sort order + e.g. Veyon - Computer and user name + Remember and add to website menu - Computer locations + e.g. www.veyon.io - Show current location only + Please enter the URL of the website to open: - Allow adding hidden locations manually + Name: - Hide empty locations + Website name + + + PluginCommands - Show confirmation dialog for potentially unsafe actions + List names of all installed plugins - Perform access control + Show table with details of all installed plugins - Automatically select current location + Name - Automatically adjust computer thumbnail size + Description - Automatically open computer select panel + Version - - - MonitoringMode - Monitoring + UID - Builtin monitoring mode + Plugin-related CLI operations - This mode allows you to monitor all computers at one or more locations. + Commands for managing plugins - NetworkDiscoveryConfigurationPage + PowerControlFeaturePlugin - Network discovery + Power on - Mode + Click this button to power on all computers. This way you do not have to power on each computer by hand. - Scan network ranges + Reboot - e.g. 192.168.1.0/24 + Click this button to reboot all computers. - Scan all subnets of computer + Power down - Scan custom subnet + Click this button to power down all computers. This way you do not have to power down each computer by hand. - Scan sessions on local computer + Power on/down or reboot a computer - Test + Confirm reboot - Network ranges + Confirm power down - Add new group + Do you really want to reboot the selected computers? - Remove selected group + Power on a computer via Wake-on-LAN (WOL) - Groups + MAC ADDRESS - First address + This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. - Last address + Please specify the command to display help for! - Add new network range + Invalid MAC address specified! - Remove selected network range + Commands for controlling power status of computers - Parallel scans + Power down now - Scan timeout + Install updates and power down - ms + Power down after user confirmation - Session scan limit + Power down after timeout - Options + The computer was remotely requested to power down. Do you want to power down the computer now? - Reverse lookup discovered IP addresses to host names + The computer will be powered down in %1 minutes, %2 seconds. + +Please save your work and close all programs. - New location + Do you really want to reboot <b>ALL</b> computers? - - - NetworkDiscoveryDirectory - Scanning... + Do you really want to power down <b>ALL</b> computers? - Discovered computers + Do you really want to power down the selected computers? - NetworkDiscoveryPlugin + PowerDownTimeInputDialog - Show help for specific command + Power down - Scan a subnet + Please specify a timeout for powering down the selected computers: - -USAGE - -%1 scan [<SUBNET>] - - + minutes - Network object directory which automatically discovers computers in the network + seconds + + + RemoteAccessFeaturePlugin - Network discovery (scan network for Veyon clients) + Remote view - Commands for managing the network discovery directory + Open a remote view for a computer without interaction. - - - NetworkObjectTreeModel - Locations/Computers + Remote control - - - OpenWebsiteDialog - Open website + Open a remote control window for a computer. - e.g. Veyon + Remote access - Remember and add to website menu + Remote view or control a computer - e.g. www.veyon.io + Show help about command - Please enter the URL of the website to open: + Exchange clipboard contents - Name: + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: - PasswordDialog + RemoteAccessPage - Username + Remote access: %1 + + + RemoteAccessWidget - Password + %1 - %2 Remote Access - Veyon Logon + %1 - %2 - %3 Remote Access + + + RemoteAccessWidgetToolBar - Authentication error + View only - Logon failed with given username and password. Please try again! + Remote control - Please enter your username and password in order to access computers. + Send shortcut - - - PowerControlFeaturePlugin - Power on + Fullscreen - Click this button to power on all computers. This way you do not have to power on each computer by hand. + Window - Reboot + Ctrl+Alt+Del - Click this button to reboot all computers. + Ctrl+Esc - Power down + Alt+Tab - Click this button to power down all computers. This way you do not have to power down each computer by hand. + Alt+F4 - Power on/down or reboot a computer + Win+Tab - Confirm reboot + Win - Confirm power down + Menu - Do you really want to reboot the selected computers? + Alt+Ctrl+F1 - Do you really want to power down the selected computer? + Connected. - Power on a computer via Wake-on-LAN (WOL) + Screenshot - MAC ADDRESS + Exit - This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. + Connecting... - Please specify the command to display help for! + Select screen - Invalid MAC address specified! + All screens + + + ScreenLockFeaturePlugin - Commands for controlling power status of computers + Lock - Power down now + Unlock - Install updates and power down + Lock screen and input devices of a computer - Power down after user confirmation + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. - Power down after timeout + Lock input devices - The computer was remotely requested to power down. Do you want to power down the computer now? + Unlock input devices - The computer will be powered down in %1 minutes, %2 seconds. - -Please save your work and close all programs. + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. - PowerDownTimeInputDialog + Screenshot - Power down + unknown - Please specify a timeout for powering down the selected computers: + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. - minutes + Screenshot + + + + Could not open screenshot file %1 for writing. + + + + + ScreenshotFeaturePlugin + + Screenshot - seconds + Use this function to take a screenshot of selected computers. - - - RemoteAccessFeaturePlugin - Remote view + Screenshots taken - Open a remote view for a computer without interaction. + Screenshot of %1 computer have been taken successfully. - Remote control + Take screenshots of computers and save them locally. + + + ScreenshotManagementPage - Open a remote control window for a computer. + Screenshots + + + ScreenshotManagementPanel - Remote access + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. - Remote view or control a computer + User: - Please enter the hostname or IP address of the computer to access: + Computer: - Show help about command + Date: - - - RemoteAccessWidget - %1 - %2 Remote Access + Time: - - - RemoteAccessWidgetToolBar - View only + Show - Remote control + Delete - Send shortcut + Screenshot - Fullscreen + Do you really want to delete all selected screenshots? + + + ServerAccessControlManager - Window + Requested authentication method not available - Ctrl+Alt+Del + Access allowed by rule "%1" - Ctrl+Esc + Access denied by rule "%1" - Alt+Tab + No rule allowed access - Alt+F4 + Accessing user not member of an authorized user group - Win+Tab + User has denied access - Win + User confirmed access + + + ServiceConfigurationPage - Menu + General - Alt+Ctrl+F1 + Autostart - Connecting %1 + Hide tray icon - Connected. + Start service - Screenshot + Stopped - Exit + Stop service - - - Routing - Control internet access by modifying routing table + State: - - - RoutingConfigurationWidget - Remove default routes to block internet access + Enable firewall exception - Add custom route to block internet + Allow connections from localhost only - Destination + VNC server - Gateway + Plugin: - - - RunProgramDialog - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. + Restart %1 Service - Run programs + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + Running - Name: + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. - Remember and add to program menu + Show notification on remote connection - e.g. VLC + Show notification when an unauthorized access is blocked - - - ScreenLockFeaturePlugin - Lock + Maximum session count - Unlock + Network port numbers - Lock screen and input devices of a computer + Veyon server - To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + Internal VNC server - - - Screenshot - unknown + Feature manager - Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + Demo server - Screenshot + Miscellaneous network settings - - - ScreenshotFeaturePlugin - Screenshot + Session mode - Use this function to take a screenshot of selected computers. + Local session mode (single server instance for primary local session) - Screenshots taken + Active session mode (single server instance for active local or remote session) - Screenshot of %1 computer have been taken successfully. + Multi session mode (distinct server instance for each local and remote desktop session) - Take screenshots of computers and save them locally. + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. - - - ScreenshotManagementPanel - All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + Miscellaneous settings - User: + Disable clipboard synchronization - Computer: + Session metadata - Date: + Content - Time: + None - Show + Value of an environment variable - Delete + Value of a registry key - - - ServiceConfigurationPage - General + Environment variable name: - Autostart + Registry key name: - Hide tray icon + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + + + ServiceControl - Start service + Service control - Stopped + Starting %1 - Stop service + Stopping %1 - State: + Restarting %1 - Network + Registering %1 - Demo server port + Unregistering %1 + + + ServiceControlCommands - Enable firewall exception + Register Veyon Service - Allow connections from localhost only + Unregister Veyon Service - Internal VNC server port + Start Veyon Service - VNC server + Stop Veyon Service - Plugin: + Restart Veyon Service - Restart %1 Service + Query status of Veyon Service - All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + Service is running - Running + Service is not running - Feature manager port + Configure and control Veyon service - Primary service port + Commands for configuring and controlling Veyon Service + + + ShellCommands - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. + Run command file - Show notification on remote connection + File "%1" does not exist! - Multi session mode (for terminal and remote desktop servers) + Interactive shell and script execution for Veyon CLI - Show notification when an unauthorized access is blocked + Commands for shell functionalities - ServiceControl + SlideshowPanel - Starting service %1 + Previous - Stopping service %1 + Start/pause - Registering service %1 + Next - Unregistering service %1 + Duration: - Service control + View in separate window - - - ServiceControlPlugin - Service is running + %1 Master – Slideshow + + + SpotlightPanel - Service is not running + Add selected computers - Configure and control Veyon service + Remove selected computers - Register Veyon Service + Update computers in realtime - Unregister Veyon Service + Spotlight - Start Veyon Service + Please select at least one computer to add. - Stop Veyon Service + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + StartAppDialog - Restart Veyon Service + Start application - Query status of Veyon Service + Please enter the applications to start on the selected computers. You can separate multiple applications by line. - Commands for configuring and controlling Veyon Service + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - - - ShellCommandLinePlugin - Run command file + Remember and add to application menu - File "%1" does not exist! + Application name - Interactive shell and script execution for Veyon Control + Name: - Commands for shell functionalities + e.g. VLC @@ -3894,7 +4538,7 @@ Typically this is required to support terminal servers. - Use the field below to type your message which will be sent to all selected users. + Please enter your message which send to all selected users. @@ -3943,22 +4587,38 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer + + Maximum CPU usage + + - UserConfig + UserLoginDialog - No write access + User login - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Please enter a username and password for automatic login on all computers. + + + + Username + + + + Password - UserSessionControl + UserSessionControlPlugin - User session control + Log in + + + + Click this button to log in a specific user on all computers. @@ -3977,6 +4637,14 @@ Typically this is required to support terminal servers. Do you really want to log off the selected users? + + User session control + + + + Do you really want to log off <b>ALL</b> users? + + VeyonCore @@ -4028,10 +4696,6 @@ Typically this is required to support terminal servers. ERROR - - licensed for - - USAGE @@ -4048,18 +4712,30 @@ Typically this is required to support terminal servers. WARNING + + Authentication test + + + + Screen %1 + + - VeyonServiceControl + VeyonMaster - Veyon Service + No write access + + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - VncView + VeyonServiceControl - Establishing connection to %1 ... + Veyon Service @@ -4108,6 +4784,30 @@ Typically this is required to support terminal servers. Use alternative user authentication mechanism + + User login + + + + Input start delay + + + + Simulated key presses interval + + + + Confirm legal notice (message displayed before user logs in) + + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4116,7 +4816,7 @@ Typically this is required to support terminal servers. - Plugin implementing specific functions for the Windows platform + Internal display @@ -4127,27 +4827,31 @@ Typically this is required to support terminal servers. - The service "%1" could not be installed. + The service "%1" has been installed successfully. + + + + The service "%1" has been uninstalled successfully. - The service "%1" has been installed successfully. + Service "%1" could not be found. - The service "%1" could not be uninstalled. + The service "%1" could not be installed (error %2). - The service "%1" has been uninstalled successfully. + Could not change the failure actions config for service "%1" (error %2). - The start type of service "%1" could not be changed. + The service "%1" could not be uninstalled (error %2). - Service "%1" could not be found. + The start type of service "%1" could not be changed (error %2). diff --git a/translations/ar.ts b/translations/veyon_ar.ts similarity index 78% rename from translations/ar.ts rename to translations/veyon_ar.ts index a627bc80f..8d5124d9e 100644 --- a/translations/ar.ts +++ b/translations/veyon_ar.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -78,10 +78,6 @@ If you're interested in translating Veyon into your local or another langua All groups جميع المجموعات - - ... - ... - Access control rules قواعد التحكم في الوصول @@ -139,15 +135,14 @@ If you're interested in translating Veyon into your local or another langua - Missing user groups backend - - - - No default user groups plugin was found. Please check your installation! + Restrict access to members of specific user groups + + + AccessControlProvider - Restrict access to members of specific user groups + Provider for access control features @@ -178,87 +173,159 @@ If you're interested in translating Veyon into your local or another langua - Invert all conditions ("is/has" interpreted as "is/has not") + Conditions + حالات + + + If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. - Conditions - حالات + Action + - is member of group - هو عضو في المجموعة + Allow access + - Accessing computer is localhost + Deny access - Accessing user is logged on user + Ask logged on user for permission - Accessing user is already connected + None (rule disabled) - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. + Accessing user - Action + Accessing computer - Allow access + Always process rule and ignore conditions - Deny access + Accessing computer and local computer - Ask logged on user for permission + User being accessed - None (rule disabled) + is logged in locally - Accessing user + is logged in remotely - Accessing computer + No user is logged in locally - Local (logged on) user + One or multiple users are logged in locally - Local computer + No user is logged in remotely - Always process rule and ignore conditions + One or multiple users are logged in remotely - No user logged on + is located at - Accessing user has one or more groups in common with local (logged on) user + is not located at - Accessing computer and local computer are at the same location + are located at the same location - is located at + are not located the same location + + + + is member of group + هو عضو في المجموعة + + + is not member of group + + + + is authenticated via + + + + is not authenticated via + + + + has one or more groups in common with user being accessed + + + + has no groups in common with user being accessed + + + + equals user being accessed + + + + is different from user being accessed + + + + is already connected + + + + is not connected + + + + is local computer + + + + is not local computer + + + + Computer being accessed + + + + Session being accessed is a user session + + + + Session being accessed is a login screen + + + + Local computer is already being accessed + + + + Local computer is not yet being accessed @@ -305,40 +372,42 @@ If you're interested in translating Veyon into your local or another langua - ERROR: Unknown action + Test result + + + + Authentication method - Test result + There is no matching rule with a valid action. The access is therefore denied. - AndroidPlatformConfigurationPage + AuthKeysConfigurationWidget - Android + Introduction - General - عام + Please perform the following steps to set up key file authentication: + - - - AndroidPlatformPlugin - Plugin implementing specific functions for the Android platform + 1) Create a key pair on the master computer. - - - AuthKeysConfigurationPage - Authentication keys + 2) Set an access group whose members should be allowed to access other computers. - Introduction + 3) Export the public key and import it on all client computers with the same name. + + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. @@ -354,11 +423,14 @@ If you're interested in translating Veyon into your local or another langua دليل ملفات المفاتيح الخاصة الأساسي - ... - ... + Available authentication keys + - Available authentication keys + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. @@ -401,10 +473,6 @@ If you're interested in translating Veyon into your local or another langua Please select a key to delete! - - Please enter the name of the user group or role for which to import the authentication key: - - Please select a key to export! @@ -418,30 +486,9 @@ If you're interested in translating Veyon into your local or another langua - Please perform the following steps to set up key file authentication: - - - - 1) Create a key pair on the master computer. - - - - 2) Set an access group whose members should be allowed to access other computers. - - - - 3) Export the public key and import it on all client computers with the same name. - - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. @@ -642,10 +689,6 @@ The public key is used on client computers to authenticate incoming connection r This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - - Please specify the command to display help for! - - TYPE @@ -654,10 +697,6 @@ The public key is used on client computers to authenticate incoming connection r PAIR ID - - Command line support for managing authentication keys - - Commands for managing authentication keys @@ -674,6 +713,30 @@ The public key is used on client computers to authenticate incoming connection r This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + + + + Key file authentication + توثيق ملف المفاتيح + + + Key file + + + + Please specify the key name (e.g. "teacher/public") as the first argument. + + + + Please specify the command to display help for. + + + + The specified command does not exist or no help is available for it. + + AuthKeysTableModel @@ -695,100 +758,243 @@ The public key is used on client computers to authenticate incoming connection r - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - + General + عام - Name - الاسم + Username to bind DN mapping: + - Host address/IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + AuthLdapDialog - MAC address - IPعنوان + Veyon Logon + - Add new computer + Please enter your domain/LDAP username and password in order to access computers. - Remove selected computer - + Username + اسم المستخدم - New computer - + Password + كلمة السر - Builtin directory - + Authentication error + خطأ في عملية التوثيق - Locations & computers + Logon failed with given username and password. Please try again! + + + AuthLogonDialog - Locations + Veyon Logon - Add new location - + Please enter your username and password in order to access computers. + يرجى إدخال اسم المستخدم وكلمة المرور من أجل الوصول إلى الحواسيب. - Remove selected location - + Username + اسم المستخدم - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - + Password + كلمة السر - New location + Authentication error + خطأ في عملية التوثيق + + + Logon failed with given username and password. Please try again! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Import objects from given file - + Logon authentication + توثيق الدخول - Export objects to given file + Logon + + + AuthSimpleDialog - Invalid type specified. Valid values are "%1" or "%2". + Veyon Logon - Type - النوع + Please enter the Veyon password: + - Name - الاسم + Authentication error + خطأ في عملية التوثيق - Host address + Logon failed with given password. Please try again! + + + AuthSimplePlugin - MAC address - IPعنوان + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + - Specified object not found. + Simple password authentication + + + + Simple password + + + + + AuthenticationPage + + Authentication is set up properly on this computer. + + + + + AuthenticationPageTab + + Enabled + + + + Test + إختبار + + + + BuiltinDirectoryConfiguration + + Builtin directory + + + + + BuiltinDirectoryConfigurationPage + + Computers + + + + Name + الاسم + + + Host address/IP + + + + MAC address + IPعنوان + + + Add new computer + + + + Remove selected computer + + + + New computer + + + + Builtin directory + + + + Locations + العناوين + + + Add new location + + + + Remove selected location + + + + New location + + + + Directory name + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + + + + BuiltinDirectoryPlugin + + Show help for specific command + + + + Import objects from given file + + + + Export objects to given file + + + + Invalid type specified. Valid values are "%1" or "%2". + + + + Type + النوع + + + Name + الاسم + + + Host address + عنوان المضيف + + + MAC address + IPعنوان + + + Specified object not found. @@ -995,6 +1201,14 @@ The public key is used on client computers to authenticate incoming connection r MAC ADDRESS + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. + + BuiltinUltraVncServer @@ -1012,10 +1226,6 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - - Active features: %1 @@ -1032,10 +1242,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off - - Service unreachable or not running - - Authentication failed or access denied @@ -1056,6 +1262,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 + + [no user] + + + + Veyon Server unreachable or not running + + + + Name: %1 + + + + Hostname: %1 + + + + unknown + غير معروف + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + ComputerControlServer @@ -1087,6 +1325,17 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + + Active connections: + + + + + ComputerGroupSelector + + Group %1 + + ComputerManager @@ -1114,13 +1363,48 @@ The public key is used on client computers to authenticate incoming connection r Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + + Logged in since + + + + %1 days + + + + 1 day + + - ComputerSelectPanel + ComputerMonitoring + + Computers + + + + Search users and computers + + + + Select all + + - Computer management + Unselect all + + Add to group + + + + Remove from group + + + + + ComputerSelectPanel Computer search @@ -1149,79 +1433,83 @@ The public key is used on client computers to authenticate incoming connection r Could not write the computer and users list to %1! Please check the file access permissions. + + Search computers + + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. + Clear system-wide Veyon configuration - Please specify a valid filename for the configuration export. + List all configuration keys and values - Please specify a valid key. + Import configuration from given file - Specified key does not exist in current configuration! + Export configuration to given file - Please specify a valid value. + Read and output configuration value for given key - Configure Veyon at command line + Write given value to given configuration key - Output file is not writable! + Unset (remove) given configuration key - Output directory is not writable! + Upgrade and save configuration of program and plugins - Configuration file is not readable! + Please specify an existing configuration file to import. - Clear system-wide Veyon configuration + Configuration file is not readable! - List all configuration keys and values + Please specify a valid filename for the configuration export. - Import configuration from given file + Output file is not writable! - Export configuration to given file + Output directory is not writable! - Read and output configuration value for given key + Please specify a valid key. - Write given value to given configuration key + Specified key does not exist in current configuration! - Unset (remove) given configuration key + Please specify a valid value. - Commands for managing the configuration of Veyon + Configure Veyon at command line - Upgrade and save configuration of program and plugins + Commands for managing the configuration of Veyon @@ -1247,6 +1535,10 @@ The public key is used on client computers to authenticate incoming connection r Could not apply platform-specific configuration settings. + + Could not configure the firewall configuration for the %1 Service. + + DemoClient @@ -1277,10 +1569,6 @@ The public key is used on client computers to authenticate incoming connection r Memory limit - - Use multithreading (experimental) - - MB @@ -1297,13 +1585,17 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running + + Bandwidth limit + + + + MB/s + + DemoFeaturePlugin - - Fullscreen demo - عرض على كامل الشاشة - Stop demo @@ -1317,26 +1609,70 @@ The public key is used on client computers to authenticate incoming connection r - Demo server - خادم العرض + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. + Demo - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Share your screen or allow a user to share his screen with other users. - - - DesktopAccessDialog - Desktop access dialog + Full screen demo - Confirm desktop access + Share your own screen in fullscreen mode + + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share your own screen in a window + + + + Share selected user's screen in fullscreen mode + + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share selected user's screen in a window + + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + + + + Please select only one user screen to share. + + + + All screens + + + + + DesktopAccessDialog + + Desktop access dialog + + + + Confirm desktop access تأكيد أمكانية الوصول لسطح المكتب @@ -1355,86 +1691,90 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - Programs & websites + Name + الاسم + + + Path - Predefined programs + Predefined websites - Name - الاسم + Remove selected website + - Path + URL - Add new program + New website - Remove selected program + Applications & websites - Predefined websites + Predefined applications - Remove selected website + Add new application - URL + Remove selected application - New program + Add new website - New website + New application DesktopServicesFeaturePlugin - Run program + Open website - Open website + Click this button to open a website on all computers. - Click this button to open a website on all computers. + Open website "%1" - Start programs and services in user desktop + Custom website - Click this button to run a program on all computers. + Start application - Run program "%1" + Click this button to start an application on all computers. - Custom program + Start application "%1" - Open website "%1" + Custom application - Custom website + Start apps and open websites in user sessions @@ -1469,15 +1809,19 @@ The public key is used on client computers to authenticate incoming connection r - Custom program + Handout + + + + Texts to read - Handout + generic-student-user - Texts to read + Custom application @@ -1504,9 +1848,164 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands + + List names of all available features + + + + Show table with details of all available features + + + + Start a feature on a remote host + + + + Stop a feature on a remote host + + + + Please specify the command to display help for. + + + + Displays a list with the names of all available features. + + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + + + + HOST ADDRESS + + + + FEATURE + + + + ARGUMENTS + + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + + + + Lock the screen + + + + Display a text message + + + + Test message + + + + Start an application + + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + + + + Unlock the screen + + + + The specified command does not exist or no help is available for it. + + + + Name + الاسم + + + Description + + + + Master + + + + Service + + + + Worker + + + + UID + + + + Plugin + + + + Invalid feature name or UID specified + + + + Error parsing the JSON-encoded arguments: %1 + + + + Failed to initialize credentials + + + + Could not establish a connection to host %1 + + + + Failed to send feature control message to host %1 + + + + Feature-related CLI operations + + + + Commands for controlling features + + + + + FileTransferConfigurationPage + + File transfer + + + + Directories + أدلة + + + Destination directory + + + + Default source directory + + + + Options + + + + Remember last source directory + + - Feature control + Create destination directory if it does not exist @@ -1552,6 +2051,13 @@ The public key is used on client computers to authenticate incoming connection r + + FileTransferFileDialog + + Select one or more files to transfer + + + FileTransferPlugin @@ -1609,10 +2115,6 @@ The public key is used on client computers to authenticate incoming connection r Log file directory دليل ملف الدخول - - ... - ... - Log level مستوى الدخول @@ -1653,18 +2155,6 @@ The public key is used on client computers to authenticate incoming connection r Log to standard error output الدخول إلى خرج الاخطاء القياسية - - Network object directory - - - - Backend: - - - - Update interval: - - %1 service @@ -1701,102 +2191,79 @@ The public key is used on client computers to authenticate incoming connection r x - - seconds - ثواني - Write to logging system of operating system - Authentication - توثيق - - - Method: + TLS configuration - Logon authentication - توثيق الدخول - - - Key file authentication - توثيق ملف المفاتيح - - - Test - إختبار - - - Authentication is set up properly on this computer. + Use certificate authority for TLS connections - Authentication keys are not set up properly on this computer. + CA certificate file - Authentication test - + ... + ... - - - InternetAccessControlConfigurationPage - Internet access control + Host certificate file - Backend: + Host private key file - General settings + Style: - Backend settings + Native - - - InternetAccessControlPlugin - Block access to the internet + Color scheme: - Allow access to the internet + Light - Show help about command - عرض المساعدة حول الأمر + Dark + - Block internet - + User groups + مجموعات المستخدم - Click this button to block access to the internet. + Backend: - Unblock internet + Include user groups from domain - Click this button to allow access to the internet. + Missing user groups backend - Control access to the internet + No user groups plugin was found. Please check your installation! + + + HeadlessVncServer - Commands for controlling access to the internet + Headless VNC server @@ -1815,69 +2282,76 @@ The public key is used on client computers to authenticate incoming connection r - LdapConfigurationPage + LdapConfiguration - Basic settings + LDAP connection failed - General - عام - - - LDAP server and port + Could not connect to the LDAP server. Please check the server parameters. + +%1 - Bind DN + LDAP bind failed - Bind password + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 - Anonymous bind + LDAP bind successful - Use bind credentials + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - Base DN + LDAP base DN test failed - Fixed base DN + Could not query the configured base DN. Please check the base DN parameter. + +%1 - e.g. dc=example,dc=org + LDAP base DN test successful - Discover base DN by naming context + The LDAP base DN has been queried successfully. The following entries were found: + +%1 - e.g. namingContexts or defaultNamingContext + LDAP naming context test failed - Environment settings + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 - Object trees + LDAP naming context test successful - Computer tree + The LDAP naming context has been queried successfully. The following base DN was found: +%1 - e.g. OU=Groups + user tree @@ -1885,39 +2359,39 @@ The public key is used on client computers to authenticate incoming connection r - e.g. OU=Users + group tree - e.g. OU=Computers + Group tree - Group tree + computer tree - Perform recursive search operations in object trees + Computer tree - Object attributes + computer group tree - e.g. hwAddress + Computer group tree - e.g. member or memberUid + user objects - e.g. dNSHostName + User login name attribute - Computer MAC address attribute + group members @@ -1925,786 +2399,703 @@ The public key is used on client computers to authenticate incoming connection r - e.g. uid or sAMAccountName + Group not found - Advanced settings + Could not find a group with the name "%1". Please check the group name or the group tree parameter. - Optional object filters + computer objects - Filter for user groups + Computer display name attribute - Filter for users + Invalid hostname - Filter for computer groups + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Group member identification + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - Distinguished name (Samba/AD) + Computer hostname attribute - List all groups of a user + computer MAC addresses - List all groups of a computer + Computer MAC address attribute - Get computer object by IP address + computer locations - LDAP connection failed + Computer location attribute - LDAP bind failed + Location name attribute - LDAP bind successful + users - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + user groups - LDAP base DN test failed + computers - LDAP base DN test successful + computer groups - LDAP naming context test failed + computer containers - LDAP naming context test successful + groups of user - The LDAP naming context has been queried successfully. The following base DN was found: -%1 + User not found - user tree + Could not find a user with the name "%1". Please check the username or the user tree parameter. - group tree + groups of computer - computer tree + Computer not found - Enter username - أدخل اسم المستخدم - - - Please enter a user login name (wildcards allowed) which to query: + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - user objects + Hostname lookup failed - Enter group name + Could not lookup hostname for IP address %1. Please check your DNS server settings. - Please enter a group name whose members to query: + location entries - group members + Computer groups filter - Group not found + Computer locations identification - Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Filter for computer groups - Enter computer name + Invalid test value - computer objects + An empty or invalid value has been supplied for this test. - Enter computer DN + LDAP %1 test failed - Please enter the DN of a computer whose MAC address to query: + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 - computer MAC addresses + LDAP %1 test successful - users + The %1 has been queried successfully and %2 entries were found. - user groups + LDAP test failed - computer groups + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 - Please enter a user login name whose group memberships to query: + and - groups of user + LDAP test successful - User not found + %1 %2 have been queried successfully: + +%3 - groups of computer + LDAP filter test failed - Computer not found + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 - Enter computer IP address + LDAP filter test successful - Please enter a computer IP address which to resolve to an computer object: + %1 %2 have been queried successfully using the configured filter. - computers + LDAP directory + + + LdapConfigurationPage - LDAP %1 test failed + Basic settings - LDAP %1 test successful - + General + عام - The %1 has been queried successfully and %2 entries were found. + LDAP server and port - %1 %2 have been queried successfully: - -%3 + Bind DN - LDAP filter test failed + Bind password - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 + Anonymous bind - LDAP filter test successful + Use bind credentials - %1 %2 have been queried successfully using the configured filter. + Base DN - (only if different from group tree) + Fixed base DN - Computer group tree + e.g. dc=example,dc=org - computer group tree + Discover base DN by naming context - Filter for computers + e.g. namingContexts or defaultNamingContext - e.g. room or computerLab + Environment settings - Integration tests + Object trees - Computer groups + Computer tree - e.g. name or description + e.g. OU=Groups - Filter for computer containers + User tree - Computer containers or OUs + e.g. OU=Users - Connection security + e.g. OU=Computers - TLS certificate verification + Group tree - System defaults + Perform recursive search operations in object trees - Never (insecure!) + Object attributes - Custom CA certificate file + e.g. hwAddress - None + e.g. member or memberUid - TLS + e.g. dNSHostName - SSL + Computer MAC address attribute - e.g. (objectClass=computer) + Group member attribute - e.g. (objectClass=group) + e.g. uid or sAMAccountName - e.g. (objectClass=person) + Advanced settings - e.g. (objectClass=room) or (objectClass=computerLab) + Optional object filters - e.g. (objectClass=container) or (objectClass=organizationalUnit) + Filter for user groups - Could not query the configured base DN. Please check the base DN parameter. - -%1 + Filter for users - The LDAP base DN has been queried successfully. The following entries were found: - -%1 + Filter for computer groups - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 + Group member identification - Certificate files (*.pem) + Distinguished name (Samba/AD) - Could not connect to the LDAP server. Please check the server parameters. - -%1 + List all groups of a user - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 + List all groups of a computer - Encryption protocol + Get computer object by IP address - Computer location attribute - - - - Computer display name attribute - - - - Location name attribute - - - - e.g. cn or displayName - + Enter username + أدخل اسم المستخدم - Computer locations identification + Please enter a user login name (wildcards allowed) which to query: - Identify computer locations (e.g. rooms) via: + Enter group name - Location attribute in computer objects + Please enter a group name whose members to query: - List all entries of a location + Enter computer name - List all locations + Enter computer DN - Enter computer display name + Please enter the DN of a computer whose MAC address to query: - Please enter a computer display name to query: + Please enter a user login name whose group memberships to query: - Enter computer location name + Enter computer IP address - Please enter the name of a computer location (wildcards allowed): + Please enter a computer IP address which to resolve to an computer object: - computer locations + (only if different from group tree) - Enter location name + Computer group tree - Please enter the name of a location whose entries to query: + Filter for computers - location entries + e.g. room or computerLab - LDAP test failed + Integration tests - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 + Computer groups - and + e.g. name or description - LDAP test successful + Filter for computer containers - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 + Computer containers or OUs - Browse + Connection security - Test - إختبار - - - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + TLS certificate verification - Computer hostname attribute + System defaults - Please enter a computer hostname to query: + Never (insecure!) - Invalid hostname + Custom CA certificate file - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + None - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + TLS - Could not find a user with the name "%1". Please check the username or the user tree parameter. + SSL - Enter hostname + e.g. (objectClass=computer) - Please enter a computer hostname whose group memberships to query: + e.g. (objectClass=group) - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + e.g. (objectClass=person) - Hostname lookup failed + e.g. (objectClass=room) or (objectClass=computerLab) - Could not lookup hostname for IP address %1. Please check your DNS server settings. + e.g. (objectClass=container) or (objectClass=organizationalUnit) - User login name attribute + Certificate files (*.pem) - Configured attribute for user login name or computer hostname (OpenLDAP) + Encryption protocol - computer containers + Computer location attribute - - - LdapPlugin - Auto-configure the base DN via naming context + Computer display name attribute - Query objects from LDAP directory + Location name attribute - Show help about command - عرض المساعدة حول الأمر - - - Commands for configuring and testing LDAP/AD integration + e.g. cn or displayName - Basic LDAP/AD support for Veyon + Computer locations identification - %1 (load computers and locations from LDAP/AD) + Identify computer locations (e.g. rooms) via: - %1 (load users and groups from LDAP/AD) + Location attribute in computer objects - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + List all entries of a location - No naming context attribute name given - falling back to configured value. + List all locations - Could not query base DN. Please check your LDAP configuration. + Enter computer display name - Configuring %1 as base DN and disabling naming context queries. + Please enter a computer display name to query: - - - LdapProConfigurationPage - LDAP Pro + Enter computer location name - Instances + Please enter the name of a computer location (wildcards allowed): - Enter name + Enter location name - Please enter a name for the instance (can't be changed later!): + Please enter the name of a location whose entries to query: - Remove instance + Browse - Do you really want to remove instance "%1"? - + Test + إختبار - Configuration for instance "%1" + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - - - LdapProPlugin - Professional LDAP/AD integration for Veyon + Computer hostname attribute - %1 (load computers and locations from LDAP/AD) + Please enter a computer hostname to query: - %1 (load users and groups from LDAP/AD) + Enter hostname - - - LicensingConfigurationPage - Licensing + Please enter a computer hostname whose group memberships to query: - Installed licenses + User login name attribute - Add new network range + Configured attribute for user login name or computer hostname (OpenLDAP) - Remove selected network range + Directory name - ID + Query options - Feature + Query nested user groups (supported by AD only) - Valid until + Query timeout - Licensee + ms + + + LdapNetworkObjectDirectoryConfigurationPage - Browse license file + LDAP - Veyon license files (*.vlf) + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + LdapPlugin - Remove license + Auto-configure the base DN via naming context - Do you really want to remove the selected license? + Query objects from LDAP directory - <N/A> - + Show help about command + عرض المساعدة حول الأمر - Invalid license file + Commands for configuring and testing LDAP/AD integration - Could not open the license file for reading! + Basic LDAP/AD support for Veyon - The selected license file does not contain valid data. + %1 (load computers and locations from LDAP/AD) - The selected license file could not be verified. + %1 (load users and groups from LDAP/AD) - The selected license file is not valid for this installation. + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - The selected license file is expired. + No naming context attribute name given - falling back to configured value. - The license is already installed. + Could not query base DN. Please check your LDAP configuration. - Information + Configuring %1 as base DN and disabling naming context queries. - Installation ID + Test binding to an LDAP server - Addons available for licensing + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Addon + LDAP bind - LicensingPlugin - - Show help for specific command - - - - Show all installed licenses - - - - Add license file - - - - Remove installed license - - - - -USAGE - -%1 add <LICENSE FILE> - - - - - - -USAGE - -%1 remove <LICENSE ID> - - - - - - No certificate found with given ID - - - - <N/A> - - + LinuxPlatformConfigurationPage - Licensing management + Linux - Commands for managing license keys + Custom PAM service for user authentication - - - LinuxPlatformConfigurationPage - Linux + User authentication - Custom PAM service for user authentication + User sessions - User authentication + Minimum session lifetime before server start - Session management + User login - Display manager users + Login key sequence @@ -2714,10 +3105,6 @@ USAGE Plugin implementing abstract functions for the Linux platform - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2737,11 +3124,11 @@ USAGE - Disable balloon tooltips + Show icons only - Show icons only + Disable tooltips @@ -2791,10 +3178,6 @@ USAGE About Qt حول"كيو تي" - - Authentication impossible - يتعذر التوثيق - Configuration not writable تعيئة غير قابلة للكتابة @@ -2855,10 +3238,6 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - - Access denied حق الوصول ممنوع @@ -2891,10 +3270,6 @@ USAGE Search users and computers - - Adjust optimal size - - Align computers to grid @@ -2939,6 +3314,48 @@ USAGE Locations && computers + + Authentication + توثيق + + + Adjust size of computer icons automatically + + + + Slideshow + + + + Spotlight + + + + Veyon Master + + + + Locations & computers + + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + + + + Load computer positions + + + + Save computer positions + + MasterConfigurationPage @@ -2946,10 +3363,6 @@ USAGE Directories أدلة - - ... - ... - User configuration @@ -3034,6 +3447,10 @@ USAGE Only user name + + Only last part of user name + + Only computer name @@ -3083,164 +3500,179 @@ USAGE - Automatically adjust computer thumbnail size + Automatically open computer select panel - Automatically open computer select panel + Use modern user interface (experimental) - - - MonitoringMode - Monitoring + Thumbnail spacing - Builtin monitoring mode + px - This mode allows you to monitor all computers at one or more locations. + Hide local session - - - NetworkDiscoveryConfigurationPage - Network discovery + Auto - Mode + Thumbnail aspect ratio - Scan network ranges + Automatically adjust computer icon size - e.g. 192.168.1.0/24 + Open feature windows on the same screen as the main window - Scan all subnets of computer + Configuration templates - Scan custom subnet + Image quality in monitoring mode - Scan sessions on local computer + Highest - Test - إختبار + High + - Network ranges + Medium - Add new group + Low - Remove selected group + Lowest - Groups + Remote access image quality - First address + Advanced - Last address + Computer name source - Add new network range + Default - Remove selected network range + Host address + عنوان المضيف + + + Session client address - Parallel scans + Session client name - Scan timeout + Session host name - ms + Session metadata - Session scan limit + Full name of user - Options + User login name - Reverse lookup discovered IP addresses to host names + Computer UID role - New location + Session meta data hash - - - NetworkDiscoveryDirectory - Scanning... + Always expand all locations - Discovered computers + Image quality - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command + Monitoring - Scan a subnet + Builtin monitoring mode - -USAGE - -%1 scan [<SUBNET>] - - + This mode allows you to monitor all computers at one or more locations. + + + + Query application version of the server + + + + Query active features + + + + Query properties of remotely available screens + + + NestedNetworkObjectDirectory - Network object directory which automatically discovers computers in the network + All directories + + + NetworkObjectDirectoryConfigurationPage - Network discovery (scan network for Veyon clients) + Update interval: - Commands for managing the network discovery directory + seconds + ثواني + + + + NetworkObjectDirectoryConfigurationPageTab + + Enabled @@ -3277,32 +3709,44 @@ USAGE Name: + + Website name + + - PasswordDialog + PluginCommands - Username - اسم المستخدم + List names of all installed plugins + - Password - كلمة السر + Show table with details of all installed plugins + - Veyon Logon + Name + الاسم + + + Description - Authentication error - خطأ في عملية التوثيق + Version + - Logon failed with given username and password. Please try again! + UID - Please enter your username and password in order to access computers. - يرجى إدخال اسم المستخدم وكلمة المرور من أجل الوصول إلى الحواسيب. + Plugin-related CLI operations + + + + Commands for managing plugins + @@ -3347,10 +3791,6 @@ USAGE Do you really want to reboot the selected computers? هل تريد حقًا إعادة تشغيل الحاسوب المحدد؟ - - Do you really want to power down the selected computer? - هل تريد حقًا إيقاف تشغيل الحاسوب المحدد؟ - Power on a computer via Wake-on-LAN (WOL) @@ -3401,6 +3841,18 @@ USAGE Please save your work and close all programs. + + Do you really want to reboot <b>ALL</b> computers? + + + + Do you really want to power down <b>ALL</b> computers? + + + + Do you really want to power down the selected computers? + + PowerDownTimeInputDialog @@ -3448,12 +3900,23 @@ Please save your work and close all programs. عرض عن بعد أو التحكم في الحاسوب - Please enter the hostname or IP address of the computer to access: + Show help about command + عرض المساعدة حول الأمر + + + Exchange clipboard contents - Show help about command - عرض المساعدة حول الأمر + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + + + RemoteAccessPage + + Remote access: %1 + @@ -3462,6 +3925,10 @@ Please save your work and close all programs. %1 - %2 Remote Access + + %1 - %2 - %3 Remote Access + + RemoteAccessWidgetToolBar @@ -3518,341 +3985,514 @@ Please save your work and close all programs. - Connecting %1 - توصيل 1%‏ + Connected. + متصل + + + Screenshot + لقطة شاشة + + + Exit + + + + Connecting... + + + + Select screen + + + + All screens + + + + + ScreenLockFeaturePlugin + + Lock + + + + Unlock + + + + Lock screen and input devices of a computer + + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + + + + Lock input devices + + + + Unlock input devices + + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + + + + Screenshot + + unknown + غير معروف + + + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + + + + Screenshot + لقطة شاشة + + + Could not open screenshot file %1 for writing. + + + + + ScreenshotFeaturePlugin + + Screenshot + لقطة شاشة + + + Use this function to take a screenshot of selected computers. + + + + Screenshots taken + + + + Screenshot of %1 computer have been taken successfully. + + + + Take screenshots of computers and save them locally. + + + + + ScreenshotManagementPage + + Screenshots + + + + + ScreenshotManagementPanel + + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + + + + User: + المستخدم + + + Computer: + + + + Date: + التاريخ + + + Time: + الزمن + + + Show + عرض + + + Delete + حذف + + + Screenshot + لقطة شاشة + + + Do you really want to delete all selected screenshots? + + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + + + + User has denied access + + + + User confirmed access + + + + + ServiceConfigurationPage + + General + عام + + + Autostart + التشغيل آليا + + + Hide tray icon + إخفاء أيقونة الصينية + + + Start service + بدء الخدمة + + + Stopped + توقف + + + Stop service + إيقاف الخدمة - Connected. - متصل + State: + بيان:‏ - Screenshot - لقطة شاشة + Enable firewall exception + تمكين إستثناء الجدار الناري - Exit - + Allow connections from localhost only + السماح بالتوصيل من المضيف المحلي فقط - - - Routing - Control internet access by modifying routing table + VNC server - - - RoutingConfigurationWidget - Remove default routes to block internet access + Plugin: - Add custom route to block internet + Restart %1 Service - Destination + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - Gateway - + Running + تشغيل - - - RunProgramDialog - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - الرجاء إدخال برامج أو أوامر لتشغيلها على الحاسوب (الحواسيب) المحددة. يمكنك فصل العديد من البرامج / الأوامر بواسطة سطر. + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. + - Run programs + Show notification on remote connection - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + Show notification when an unauthorized access is blocked - Name: + Maximum session count - Remember and add to program menu + Network port numbers - e.g. VLC + Veyon server - - - ScreenLockFeaturePlugin - Lock + Internal VNC server - Unlock + Feature manager - Lock screen and input devices of a computer - + Demo server + خادم العرض - To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + Miscellaneous network settings - - - Screenshot - unknown - غير معروف + Session mode + - Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + Local session mode (single server instance for primary local session) - Screenshot - لقطة شاشة + Active session mode (single server instance for active local or remote session) + - - - ScreenshotFeaturePlugin - Screenshot - لقطة شاشة + Multi session mode (distinct server instance for each local and remote desktop session) + - Use this function to take a screenshot of selected computers. + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. - Screenshots taken + Miscellaneous settings - Screenshot of %1 computer have been taken successfully. + Disable clipboard synchronization - Take screenshots of computers and save them locally. + Session metadata - - - ScreenshotManagementPanel - All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + Content - User: - المستخدم + None + - Computer: + Value of an environment variable - Date: - التاريخ + Value of a registry key + - Time: - الزمن + Environment variable name: + - Show - عرض + Registry key name: + - Delete - حذف + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + - ServiceConfigurationPage - - General - عام - - - Autostart - التشغيل آليا - - - Hide tray icon - إخفاء أيقونة الصينية - + ServiceControl - Start service - بدء الخدمة + Service control + - Stopped - توقف + Starting %1 + - Stop service - إيقاف الخدمة + Stopping %1 + - State: - بيان:‏ + Restarting %1 + - Network - شبكة + Registering %1 + - Demo server port - منفذ خادم العرض + Unregistering %1 + + + + ServiceControlCommands - Enable firewall exception - تمكين إستثناء الجدار الناري + Register Veyon Service + - Allow connections from localhost only - السماح بالتوصيل من المضيف المحلي فقط + Unregister Veyon Service + - Internal VNC server port + Start Veyon Service - VNC server + Stop Veyon Service - Plugin: + Restart Veyon Service - Restart %1 Service + Query status of Veyon Service - All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + Service is running - Running - تشغيل + Service is not running + - Feature manager port + Configure and control Veyon service - Primary service port + Commands for configuring and controlling Veyon Service + + + ShellCommands - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. + Run command file - Show notification on remote connection + File "%1" does not exist! - Multi session mode (for terminal and remote desktop servers) + Interactive shell and script execution for Veyon CLI - Show notification when an unauthorized access is blocked + Commands for shell functionalities - ServiceControl + SlideshowPanel - Starting service %1 + Previous - Stopping service %1 + Start/pause - Registering service %1 + Next - Unregistering service %1 + Duration: - Service control + View in separate window - - - ServiceControlPlugin - Service is running + %1 Master – Slideshow + + + SpotlightPanel - Service is not running + Add selected computers - Configure and control Veyon service + Remove selected computers - Register Veyon Service + Update computers in realtime - Unregister Veyon Service + Spotlight - Start Veyon Service + Please select at least one computer to add. - Stop Veyon Service + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + StartAppDialog - Restart Veyon Service + Start application - Query status of Veyon Service + Please enter the applications to start on the selected computers. You can separate multiple applications by line. - Commands for configuring and controlling Veyon Service + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - - - ShellCommandLinePlugin - Run command file + Remember and add to application menu - File "%1" does not exist! + Application name - Interactive shell and script execution for Veyon Control + Name: - Commands for shell functionalities + e.g. VLC @@ -3892,8 +4532,8 @@ Typically this is required to support terminal servers. إرسال رسالة نصية - Use the field below to type your message which will be sent to all selected users. - استخدم الحقل أدناه لطباعة رسالتك التي سيتم ارسالها الى كافة المستخدمين المختارين + Please enter your message which send to all selected users. + @@ -3941,23 +4581,39 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer + + Maximum CPU usage + + - UserConfig + UserLoginDialog - No write access - لا يوجد وصول للكتابة + User login + - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - تعذر حفظ إعداداتك الشخصية! الرجاء التحقق من مسار ملف ضبط المستخدم باستخدام٪ 1 مكون. + Please enter a username and password for automatic login on all computers. + + + + Username + اسم المستخدم + + + Password + كلمة السر - UserSessionControl + UserSessionControlPlugin - User session control - التحكم في جلسة عمل المستخدم + Log in + + + + Click this button to log in a specific user on all computers. + Log off @@ -3975,6 +4631,14 @@ Typically this is required to support terminal servers. Do you really want to log off the selected users? + + User session control + التحكم في جلسة عمل المستخدم + + + Do you really want to log off <b>ALL</b> users? + + VeyonCore @@ -4026,10 +4690,6 @@ Typically this is required to support terminal servers. ERROR - - licensed for - - USAGE @@ -4046,19 +4706,31 @@ Typically this is required to support terminal servers. WARNING + + Authentication test + + + + Screen %1 + + - VeyonServiceControl + VeyonMaster - Veyon Service - + No write access + لا يوجد وصول للكتابة + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + تعذر حفظ إعداداتك الشخصية! الرجاء التحقق من مسار ملف ضبط المستخدم باستخدام٪ 1 مكون. - VncView + VeyonServiceControl - Establishing connection to %1 ... - انشاء اتصال بـ 1% + Veyon Service + @@ -4106,6 +4778,30 @@ Typically this is required to support terminal servers. Use alternative user authentication mechanism + + User login + + + + Input start delay + + + + Simulated key presses interval + + + + Confirm legal notice (message displayed before user logs in) + + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4114,7 +4810,7 @@ Typically this is required to support terminal servers. - Plugin implementing specific functions for the Windows platform + Internal display @@ -4125,27 +4821,31 @@ Typically this is required to support terminal servers. - The service "%1" could not be installed. + The service "%1" has been installed successfully. + + + + The service "%1" has been uninstalled successfully. - The service "%1" has been installed successfully. + Service "%1" could not be found. - The service "%1" could not be uninstalled. + The service "%1" could not be installed (error %2). - The service "%1" has been uninstalled successfully. + Could not change the failure actions config for service "%1" (error %2). - The start type of service "%1" could not be changed. + The service "%1" could not be uninstalled (error %2). - Service "%1" could not be found. + The start type of service "%1" could not be changed (error %2). diff --git a/translations/veyon_bg.ts b/translations/veyon_bg.ts new file mode 100644 index 000000000..d89c6e751 --- /dev/null +++ b/translations/veyon_bg.ts @@ -0,0 +1,4894 @@ + + + AboutDialog + + About + За програмата + + + Translation + Превод + + + License + Лиценз + + + About Veyon + За Veyron + + + Contributors + Автори + + + Version: + Версия: + + + Website: + Уебсайт: + + + Current language not translated yet (or native English). + +If you're interested in translating Veyon into your local or another language or want to improve an existing translation, please contact a Veyon developer! + Настоящият език все още не е преведен (или местен английски). + + Ако се интересувате от превода на Veyon на вашия местен или друг език или искате да подобрите съществуващ превод, моля, свържете се с разработчик на Veyon! + + + About %1 %2 + Относно %1 %2 + + + Support Veyon project with a donation + Подкрепете проект Veyon с дарение + + + + AccessControlPage + + Computer access control + Контрол на достъпа на компютъра + + + Grant access to every authenticated user (default) + Дайте достъп на всеки удостоверен потребител (по подразбиране) + + + Test + Тест + + + Process access control rules + Обработвайте правила за контрол на достъпа + + + User groups authorized for computer access + Потребителски групи, оторизирани за достъп до компютър + + + Please add the groups whose members should be authorized to access computers in your Veyon network. + Моля, добавете групите, чиито членове трябва да бъдат упълномощени за достъп до компютри във вашата Veyon мрежа. + + + Authorized user groups + Оторизирани потребителски групи + + + All groups + Всички групи + + + Access control rules + Правила за контрол на достъпа + + + Add access control rule + Добави правило за контрол на достъпа + + + Remove access control rule + Премахни правило за контрол на достъпа + + + Move selected rule down + Премести надолу + + + Move selected rule up + Премести нагоре + + + Edit selected rule + Промени + + + Enter username + Въведи потребителско име + + + Please enter a user login name whose access permissions to test: + Моля, въведете потребителско име за вход, чиито разрешения за достъп да тествате: + + + Access allowed + Достъпът е разрешен + + + The specified user is allowed to access computers with this configuration. + На посочения потребител е разрешен достъпа до компютри с тази конфигурация. + + + Access denied + Достъпът е отказан + + + The specified user is not allowed to access computers with this configuration. + Посоченият потребител няма право да получава достъп до компютри с тази конфигурация. + + + Enable usage of domain groups + Активиране на използването на групи от домейни + + + User groups backend: + Потребителски групи: + + + Restrict access to members of specific user groups + Ограничете достъпа до членове на определени потребителски групи + + + + AccessControlProvider + + Provider for access control features + + + + + AccessControlRuleEditDialog + + Edit access control rule + Промени + + + General + Общи настройки + + + enter a short name for the rule here + въведете кратко име за правилото + + + Rule name: + Име на правило: + + + enter a description for the rule here + въведете описание на правилото + + + Rule description: + Описание на правилото: + + + Conditions + Условия + + + If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. + If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. + + + Action + Действие + + + Allow access + Позволи достъп + + + Deny access + Забрани достъп + + + Ask logged on user for permission + Попитайте влезлия потребител за разрешение + + + None (rule disabled) + Няма (правилото е деактивирано) + + + Accessing user + Достъп до потребител + + + Accessing computer + Достъп до компютър + + + Always process rule and ignore conditions + Винаги използвай правилото и игнорирай условията + + + Accessing computer and local computer + + + + User being accessed + + + + is logged in locally + + + + is logged in remotely + + + + No user is logged in locally + + + + One or multiple users are logged in locally + + + + No user is logged in remotely + + + + One or multiple users are logged in remotely + + + + is located at + is located at + + + is not located at + + + + are located at the same location + + + + are not located the same location + + + + is member of group + е член на групата + + + is not member of group + + + + is authenticated via + + + + is not authenticated via + + + + has one or more groups in common with user being accessed + + + + has no groups in common with user being accessed + + + + equals user being accessed + + + + is different from user being accessed + + + + is already connected + + + + is not connected + + + + is local computer + + + + is not local computer + + + + Computer being accessed + + + + Session being accessed is a user session + + + + Session being accessed is a login screen + + + + Local computer is already being accessed + + + + Local computer is not yet being accessed + + + + + AccessControlRulesTestDialog + + Access control rules test + Access control rules test + + + Accessing user: + Accessing user: + + + Local computer: + Local computer: + + + Accessing computer: + Accessing computer: + + + Please enter the following user and computer information in order to test the configured ruleset. + Please enter the following user and computer information in order to test the configured ruleset. + + + Local user: + Local user: + + + Connected users: + Connected users: + + + The access in the given scenario is allowed. + The access in the given scenario is allowed. + + + The access in the given scenario is denied. + The access in the given scenario is denied. + + + The access in the given scenario needs permission of the logged on user. + The access in the given scenario needs permission of the logged on user. + + + Test result + Test result + + + Authentication method + + + + There is no matching rule with a valid action. The access is therefore denied. + + + + + AuthKeysConfigurationWidget + + Introduction + Introduction + + + Please perform the following steps to set up key file authentication: + Please perform the following steps to set up key file authentication: + + + 1) Create a key pair on the master computer. + 1) Create a key pair on the master computer. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Set an access group whose members should be allowed to access other computers. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Export the public key and import it on all client computers with the same name. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + + + Key file directories + Key file directories + + + Public key file base directory + Public key file base directory + + + Private key file base directory + Private key file base directory + + + Available authentication keys + Available authentication keys + + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + + + Create key pair + Create key pair + + + Delete key + Delete key + + + Import key + Import key + + + Export key + Export key + + + Set access group + Set access group + + + Key files (*.pem) + Key files (*.pem) + + + Authentication key name + Authentication key name + + + Please enter the name of the user group or role for which to create an authentication key pair: + Please enter the name of the user group or role for which to create an authentication key pair: + + + Do you really want to delete authentication key "%1/%2"? + Do you really want to delete authentication key "%1/%2"? + + + Please select a key to delete! + Please select a key to delete! + + + Please select a key to export! + Please select a key to export! + + + Please select a user group which to grant access to key "%1": + Please select a user group which to grant access to key "%1": + + + Please select a key which to set the access group for! + Please select a key which to set the access group for! + + + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + + + + + AuthKeysManager + + Please check your permissions. + Please check your permissions. + + + Key name contains invalid characters! + Key name contains invalid characters! + + + Invalid key type specified! Please specify "%1" or "%2". + Invalid key type specified! Please specify "%1" or "%2". + + + Specified key does not exist! Please use the "list" command to list all installed keys. + Specified key does not exist! Please use the "list" command to list all installed keys. + + + One or more key files already exist! Please delete them using the "delete" command. + One or more key files already exist! Please delete them using the "delete" command. + + + Creating new key pair for "%1" + Creating new key pair for "%1" + + + Failed to create public or private key! + Failed to create public or private key! + + + Newly created key pair has been saved to "%1" and "%2". + Newly created key pair has been saved to "%1" and "%2". + + + Could not remove key file "%1"! + Could not remove key file "%1"! + + + Could not remove key file directory "%1"! + Could not remove key file directory "%1"! + + + Failed to create directory for output file. + Failed to create directory for output file. + + + File "%1" already exists. + File "%1" already exists. + + + Failed to write output file. + Failed to write output file. + + + Key "%1/%2" has been exported to "%3" successfully. + Key "%1/%2" has been exported to "%3" successfully. + + + Failed read input file. + Failed read input file. + + + File "%1" does not contain a valid private key! + File "%1" does not contain a valid private key! + + + File "%1" does not contain a valid public key! + File "%1" does not contain a valid public key! + + + Failed to create directory for key file. + Failed to create directory for key file. + + + Failed to write key file "%1". + Failed to write key file "%1". + + + Failed to set permissions for key file "%1"! + Failed to set permissions for key file "%1"! + + + Key "%1/%2" has been imported successfully. Please check file permissions of "%3" in order to prevent unauthorized accesses. + Key "%1/%2" has been imported successfully. Please check file permissions of "%3" in order to prevent unauthorized accesses. + + + Failed to convert private key to public key + Failed to convert private key to public key + + + Failed to create directory for private key file "%1". + Failed to create directory for private key file "%1". + + + Failed to save private key in file "%1"! + Failed to save private key in file "%1"! + + + Failed to set permissions for private key file "%1"! + Failed to set permissions for private key file "%1"! + + + Failed to create directory for public key file "%1". + Failed to create directory for public key file "%1". + + + Failed to save public key in file "%1"! + Failed to save public key in file "%1"! + + + Failed to set permissions for public key file "%1"! + Failed to set permissions for public key file "%1"! + + + Failed to set owner of key file "%1" to "%2". + Failed to set owner of key file "%1" to "%2". + + + Failed to set permissions for key file "%1". + Failed to set permissions for key file "%1". + + + Key "%1" is now accessible by user group "%2". + Key "%1" is now accessible by user group "%2". + + + <N/A> + <N/A> + + + Failed to read key file. + Failed to read key file. + + + + AuthKeysPlugin + + Create new authentication key pair + Create new authentication key pair + + + Delete authentication key + Delete authentication key + + + List authentication keys + List authentication keys + + + Import public or private key + Import public or private key + + + Export public or private key + Export public or private key + + + Extract public key from existing private key + Extract public key from existing private key + + + Set user group allowed to access a key + Set user group allowed to access a key + + + KEY + KEY + + + ACCESS GROUP + ACCESS GROUP + + + This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. + This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. + + + NAME + NAME + + + FILE + FILE + + + This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. + This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. + + + This command imports the authentication key <KEY> from <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. + This command imports the authentication key <KEY> from <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. + + + This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. + This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. + + + TYPE + TYPE + + + PAIR ID + PAIR ID + + + Commands for managing authentication keys + Commands for managing authentication keys + + + This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. + This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. + + + This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. + This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. + + + This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + + + + Key file authentication + Key file authentication + + + Key file + + + + Please specify the key name (e.g. "teacher/public") as the first argument. + + + + Please specify the command to display help for. + + + + The specified command does not exist or no help is available for it. + + + + + AuthKeysTableModel + + Name + Name + + + Type + Type + + + Access group + Access group + + + Pair ID + Pair ID + + + + AuthLdapConfigurationWidget + + General + Общи настройки + + + Username to bind DN mapping: + + + + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + + + AuthLdapDialog + + Veyon Logon + Veyon Logon + + + Please enter your domain/LDAP username and password in order to access computers. + + + + Username + Username + + + Password + Password + + + Authentication error + Authentication error + + + Logon failed with given username and password. Please try again! + Logon failed with given username and password. Please try again! + + + + AuthLogonDialog + + Veyon Logon + Veyon Logon + + + Please enter your username and password in order to access computers. + Please enter your username and password in order to access computers. + + + Username + Username + + + Password + Password + + + Authentication error + Authentication error + + + Logon failed with given username and password. Please try again! + Logon failed with given username and password. Please try again! + + + + AuthLogonPlugin + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + + + + Logon authentication + Logon authentication + + + Logon + + + + + AuthSimpleDialog + + Veyon Logon + Veyon Logon + + + Please enter the Veyon password: + + + + Authentication error + Authentication error + + + Logon failed with given password. Please try again! + + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + + + + Simple password authentication + + + + Simple password + + + + + AuthenticationPage + + Authentication is set up properly on this computer. + Authentication is set up properly on this computer. + + + + AuthenticationPageTab + + Enabled + + + + Test + Тест + + + + BuiltinDirectoryConfiguration + + Builtin directory + Builtin directory + + + + BuiltinDirectoryConfigurationPage + + Computers + Computers + + + Name + Name + + + Host address/IP + Host address/IP + + + MAC address + MAC address + + + Add new computer + Add new computer + + + Remove selected computer + Remove selected computer + + + New computer + New computer + + + Builtin directory + Builtin directory + + + Locations + Locations + + + Add new location + Add new location + + + Remove selected location + Remove selected location + + + New location + New location + + + Directory name + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + + + + BuiltinDirectoryPlugin + + Show help for specific command + Show help for specific command + + + Import objects from given file + Import objects from given file + + + Export objects to given file + Export objects to given file + + + Invalid type specified. Valid values are "%1" or "%2". + Invalid type specified. Valid values are "%1" or "%2". + + + Type + Type + + + Name + Name + + + Host address + Host address + + + MAC address + MAC address + + + Specified object not found. + Specified object not found. + + + File "%1" does not exist! + File "%1" does not exist! + + + Can't open file "%1" for reading! + Can't open file "%1" for reading! + + + Unknown argument "%1". + Unknown argument "%1". + + + Computer "%1" (host address: "%2" MAC address: "%3") + Computer "%1" (host address: "%2" MAC address: "%3") + + + Unclassified object "%1" with ID "%2" + Unclassified object "%1" with ID "%2" + + + None + None + + + Computer + Computer + + + Root + Root + + + Invalid + Invalid + + + Error while parsing line %1. + Error while parsing line %1. + + + Network object directory which stores objects in local configuration + Network object directory which stores objects in local configuration + + + Commands for managing the builtin network object directory + Commands for managing the builtin network object directory + + + No format string or regular expression specified! + No format string or regular expression specified! + + + Can't open file "%1" for writing! + Can't open file "%1" for writing! + + + No format string specified! + No format string specified! + + + Object UUID + Object UUID + + + Parent UUID + Parent UUID + + + Add a location or computer + Add a location or computer + + + Clear all locations and computers + Clear all locations and computers + + + Dump all or individual locations and computers + Dump all or individual locations and computers + + + List all locations and computers + List all locations and computers + + + Remove a location or computer + Remove a location or computer + + + Location "%1" + Location "%1" + + + Builtin (computers and locations in local configuration) + Builtin (computers and locations in local configuration) + + + Location + Location + + + FILE + FILE + + + LOCATION + LOCATION + + + FORMAT-STRING-WITH-PLACEHOLDERS + FORMAT-STRING-WITH-PLACEHOLDERS + + + REGULAR-EXPRESSION-WITH-PLACEHOLDER + REGULAR-EXPRESSION-WITH-PLACEHOLDER + + + Imports objects from the specified text file using the given format string or regular expression containing one or multiple placeholders. Valid placeholders are: %1 + Imports objects from the specified text file using the given format string or regular expression containing one or multiple placeholders. Valid placeholders are: %1 + + + Import simple CSV file to a single room + Import simple CSV file to a single room + + + Import CSV file with location name in first column + Import CSV file with location name in first column + + + Import text file with with key/value pairs using regular expressions + Import text file with with key/value pairs using regular expressions + + + Import arbitrarily formatted data + Import arbitrarily formatted data + + + Exports objects to the specified text file using the given format string containing one or multiple placeholders. Valid placeholders are: %1 + Exports objects to the specified text file using the given format string containing one or multiple placeholders. Valid placeholders are: %1 + + + Export all objects to a CSV file + Export all objects to a CSV file + + + Export all computers in a specific location to a CSV file + Export all computers in a specific location to a CSV file + + + TYPE + TYPE + + + NAME + NAME + + + PARENT + PARENT + + + Adds an object where %1 can be one of "%2" or "%3". %4 can be specified by name or UUID. + Adds an object where %1 can be one of "%2" or "%3". %4 can be specified by name or UUID. + + + Add a room + Add a room + + + Add a computer to room %1 + Add a computer to room %1 + + + OBJECT + OBJECT + + + Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. + Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. + + + Remove a computer by name + Remove a computer by name + + + Remove an object by UUID + Remove an object by UUID + + + "Room 01" + "Room 01" + + + "Computer 01" + "Computer 01" + + + HOST ADDRESS + HOST ADDRESS + + + MAC ADDRESS + MAC ADDRESS + + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. + + + + + BuiltinUltraVncServer + + Builtin VNC server (UltraVNC) + Builtin VNC server (UltraVNC) + + + + BuiltinX11VncServer + + Builtin VNC server (x11vnc) + Builtin VNC server (x11vnc) + + + + ComputerControlListModel + + Active features: %1 + Active features: %1 + + + Online and connected + Online and connected + + + Establishing connection + Establishing connection + + + Computer offline or switched off + Computer offline or switched off + + + Authentication failed or access denied + Authentication failed or access denied + + + Disconnected + Disconnected + + + No user logged on + Няма потребител + + + Logged on user: %1 + Logged on user: %1 + + + Location: %1 + Location: %1 + + + [no user] + + + + Veyon Server unreachable or not running + + + + Name: %1 + + + + Hostname: %1 + + + + unknown + unknown + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + + + + ComputerControlServer + + %1 Service %2 at %3:%4 + %1 Service %2 at %3:%4 + + + Authentication error + Authentication error + + + Remote access + Remote access + + + User "%1" at host "%2" is now accessing this computer. + User "%1" at host "%2" is now accessing this computer. + + + User "%1" at host "%2" attempted to access this computer but could not authenticate successfully. + User "%1" at host "%2" attempted to access this computer but could not authenticate successfully. + + + Access control error + Access control error + + + User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + + + Active connections: + + + + + ComputerGroupSelector + + Group %1 + + + + + ComputerManager + + User + User + + + Missing network object directory plugin + Missing network object directory plugin + + + No default network object directory plugin was found. Please check your installation or configure a different network object directory backend via %1 Configurator. + No default network object directory plugin was found. Please check your installation or configure a different network object directory backend via %1 Configurator. + + + Location detection failed + Location detection failed + + + Computer name;Hostname;User + Computer name;Hostname;User + + + Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + + + Logged in since + + + + %1 days + + + + 1 day + + + + + ComputerMonitoring + + Computers + Computers + + + Search users and computers + Search users and computers + + + Select all + + + + Unselect all + + + + Add to group + + + + Remove from group + + + + + ComputerSelectPanel + + Computer search + Computer search + + + Add location + Add location + + + Save computer/user list + Save computer/user list + + + Select output filename + Select output filename + + + CSV files (*.csv) + CSV files (*.csv) + + + File error + File error + + + Could not write the computer and users list to %1! Please check the file access permissions. + Could not write the computer and users list to %1! Please check the file access permissions. + + + Search computers + + + + + ConfigCommands + + Clear system-wide Veyon configuration + Clear system-wide Veyon configuration + + + List all configuration keys and values + List all configuration keys and values + + + Import configuration from given file + Import configuration from given file + + + Export configuration to given file + Export configuration to given file + + + Read and output configuration value for given key + Read and output configuration value for given key + + + Write given value to given configuration key + Write given value to given configuration key + + + Unset (remove) given configuration key + Unset (remove) given configuration key + + + Upgrade and save configuration of program and plugins + Upgrade and save configuration of program and plugins + + + Please specify an existing configuration file to import. + Please specify an existing configuration file to import. + + + Configuration file is not readable! + Configuration file is not readable! + + + Please specify a valid filename for the configuration export. + Please specify a valid filename for the configuration export. + + + Output file is not writable! + Output file is not writable! + + + Output directory is not writable! + Output directory is not writable! + + + Please specify a valid key. + Please specify a valid key. + + + Specified key does not exist in current configuration! + Specified key does not exist in current configuration! + + + Please specify a valid value. + Please specify a valid value. + + + Configure Veyon at command line + Configure Veyon at command line + + + Commands for managing the configuration of Veyon + Commands for managing the configuration of Veyon + + + + ConfigurationManager + + Could not modify the autostart property for the %1 Service. + Could not modify the autostart property for the %1 Service. + + + Could not configure the firewall configuration for the %1 Server. + Could not configure the firewall configuration for the %1 Server. + + + Could not configure the firewall configuration for the %1 Worker. + Could not configure the firewall configuration for the %1 Worker. + + + Configuration is not writable. Please check your permissions! + Configuration is not writable. Please check your permissions! + + + Could not apply platform-specific configuration settings. + Could not apply platform-specific configuration settings. + + + Could not configure the firewall configuration for the %1 Service. + + + + + DemoClient + + %1 Demo + %1 Demo + + + + DemoConfigurationPage + + Demo server + Demo server + + + Tunables + Tunables + + + ms + ms + + + Key frame interval + Key frame interval + + + Memory limit + Memory limit + + + MB + MB + + + Update interval + Update interval + + + s + s + + + Slow down thumbnail updates while demo is running + Slow down thumbnail updates while demo is running + + + Bandwidth limit + + + + MB/s + + + + + DemoFeaturePlugin + + Stop demo + Stop demo + + + Window demo + Window demo + + + Give a demonstration by screen broadcasting + Give a demonstration by screen broadcasting + + + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + Demo + + + + Share your screen or allow a user to share his screen with other users. + + + + Full screen demo + + + + Share your own screen in fullscreen mode + + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share your own screen in a window + + + + Share selected user's screen in fullscreen mode + + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share selected user's screen in a window + + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + + + + Please select only one user screen to share. + + + + All screens + + + + + DesktopAccessDialog + + Desktop access dialog + Desktop access dialog + + + Confirm desktop access + Confirm desktop access + + + Never for this session + Never for this session + + + Always for this session + Always for this session + + + The user %1 at computer %2 wants to access your desktop. Do you want to grant access? + The user %1 at computer %2 wants to access your desktop. Do you want to grant access? + + + + DesktopServicesConfigurationPage + + Name + Name + + + Path + Path + + + Predefined websites + Predefined websites + + + Remove selected website + Remove selected website + + + URL + URL + + + New website + New website + + + Applications & websites + + + + Predefined applications + + + + Add new application + + + + Remove selected application + + + + Add new website + + + + New application + + + + + DesktopServicesFeaturePlugin + + Open website + Open website + + + Click this button to open a website on all computers. + Click this button to open a website on all computers. + + + Open website "%1" + Open website "%1" + + + Custom website + Custom website + + + Start application + + + + Click this button to start an application on all computers. + + + + Start application "%1" + + + + Custom application + + + + Start apps and open websites in user sessions + + + + + DocumentationFigureCreator + + Teacher + Teacher + + + Room %1 + Room %1 + + + Please complete all tasks within the next 5 minutes. + Please complete all tasks within the next 5 minutes. + + + Custom website + Custom website + + + Open file manager + Open file manager + + + Start learning tool + Start learning tool + + + Play tutorial video + Play tutorial video + + + Handout + Handout + + + Texts to read + Texts to read + + + generic-student-user + generic-student-user + + + Custom application + + + + + ExternalVncServer + + External VNC server + External VNC server + + + + ExternalVncServerConfigurationWidget + + External VNC server configuration + External VNC server configuration + + + Port: + Port: + + + Password: + Password: + + + + FeatureCommands + + List names of all available features + + + + Show table with details of all available features + + + + Start a feature on a remote host + + + + Stop a feature on a remote host + + + + Please specify the command to display help for. + + + + Displays a list with the names of all available features. + + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + + + + HOST ADDRESS + HOST ADDRESS + + + FEATURE + + + + ARGUMENTS + + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + + + + Lock the screen + + + + Display a text message + + + + Test message + + + + Start an application + + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + + + + Unlock the screen + + + + The specified command does not exist or no help is available for it. + + + + Name + Name + + + Description + + + + Master + Master + + + Service + Service + + + Worker + + + + UID + + + + Plugin + + + + Invalid feature name or UID specified + + + + Error parsing the JSON-encoded arguments: %1 + + + + Failed to initialize credentials + + + + Could not establish a connection to host %1 + + + + Failed to send feature control message to host %1 + + + + Feature-related CLI operations + + + + Commands for controlling features + + + + + FileTransferConfigurationPage + + File transfer + File transfer + + + Directories + Directories + + + Destination directory + + + + Default source directory + + + + Options + Options + + + Remember last source directory + + + + Create destination directory if it does not exist + + + + + FileTransferController + + Could not open file "%1" for reading! Please check your permissions! + Could not open file "%1" for reading! Please check your permissions! + + + + FileTransferDialog + + File transfer + File transfer + + + Options + Options + + + Transfer only + Transfer only + + + Transfer and open file(s) with associated program + Transfer and open file(s) with associated program + + + Transfer and open destination folder + Transfer and open destination folder + + + Files + Files + + + Start + Start + + + Overwrite existing files + Overwrite existing files + + + + FileTransferFileDialog + + Select one or more files to transfer + Select one or more files to transfer + + + + FileTransferPlugin + + File transfer + File transfer + + + Click this button to transfer files from your computer to all computers. + Click this button to transfer files from your computer to all computers. + + + Select one or more files to transfer + Select one or more files to transfer + + + Transfer files to remote computer + Transfer files to remote computer + + + Received file "%1". + Received file "%1". + + + Could not receive file "%1" as it already exists. + Could not receive file "%1" as it already exists. + + + Could not receive file "%1" as it could not be opened for writing! + Could not receive file "%1" as it could not be opened for writing! + + + + GeneralConfigurationPage + + User interface + User interface + + + Language: + Language: + + + Use system language setting + Use system language setting + + + Veyon + Veyon + + + Logging + Logging + + + Log file directory + Log file directory + + + Log level + Log level + + + Nothing + Nothing + + + Only critical messages + Only critical messages + + + Errors and critical messages + Errors and critical messages + + + Warnings and errors + Warnings and errors + + + Information, warnings and errors + Information, warnings and errors + + + Debug messages and everything else + Debug messages and everything else + + + Limit log file size + Limit log file size + + + Clear all log files + Clear all log files + + + Log to standard error output + Log to standard error output + + + %1 service + %1 service + + + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + + + Log files cleared + Log files cleared + + + All log files were cleared successfully. + All log files were cleared successfully. + + + Error + Error + + + Could not remove all log files. + Could not remove all log files. + + + MB + MB + + + Rotate log files + Rotate log files + + + x + x + + + Write to logging system of operating system + Write to logging system of operating system + + + TLS configuration + + + + Use certificate authority for TLS connections + + + + CA certificate file + + + + ... + ... + + + Host certificate file + + + + Host private key file + + + + Style: + + + + Native + + + + Color scheme: + + + + Light + + + + Dark + + + + User groups + + + + Backend: + Backend: + + + Include user groups from domain + + + + Missing user groups backend + Липсват потребителски групи + + + No user groups plugin was found. Please check your installation! + + + + + HeadlessVncServer + + Headless VNC server + + + + + LdapBrowseDialog + + Browse LDAP + Browse LDAP + + + + LdapClient + + LDAP error description: %1 + LDAP error description: %1 + + + + LdapConfiguration + + LDAP connection failed + LDAP connection failed + + + Could not connect to the LDAP server. Please check the server parameters. + +%1 + Could not connect to the LDAP server. Please check the server parameters. + +%1 + + + LDAP bind failed + LDAP bind failed + + + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + + + LDAP bind successful + LDAP bind successful + + + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + + + LDAP base DN test failed + LDAP base DN test failed + + + Could not query the configured base DN. Please check the base DN parameter. + +%1 + Could not query the configured base DN. Please check the base DN parameter. + +%1 + + + LDAP base DN test successful + LDAP base DN test successful + + + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + + + LDAP naming context test failed + LDAP naming context test failed + + + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + + + LDAP naming context test successful + LDAP naming context test successful + + + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + + + user tree + user tree + + + User tree + User tree + + + group tree + group tree + + + Group tree + Group tree + + + computer tree + computer tree + + + Computer tree + Computer tree + + + computer group tree + computer group tree + + + Computer group tree + Computer group tree + + + user objects + user objects + + + User login name attribute + User login name attribute + + + group members + group members + + + Group member attribute + Group member attribute + + + Group not found + Group not found + + + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + + + computer objects + computer objects + + + Computer display name attribute + Computer display name attribute + + + Invalid hostname + Invalid hostname + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + + + Computer hostname attribute + Computer hostname attribute + + + computer MAC addresses + computer MAC addresses + + + Computer MAC address attribute + Computer MAC address attribute + + + computer locations + computer locations + + + Computer location attribute + Computer location attribute + + + Location name attribute + Location name attribute + + + users + users + + + user groups + user groups + + + computers + computers + + + computer groups + computer groups + + + computer containers + computer containers + + + groups of user + groups of user + + + User not found + User not found + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + Could not find a user with the name "%1". Please check the username or the user tree parameter. + + + groups of computer + groups of computer + + + Computer not found + Computer not found + + + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + + + Hostname lookup failed + Hostname lookup failed + + + Could not lookup hostname for IP address %1. Please check your DNS server settings. + Could not lookup hostname for IP address %1. Please check your DNS server settings. + + + location entries + location entries + + + Computer groups filter + + + + Computer locations identification + Computer locations identification + + + Filter for computer groups + Filter for computer groups + + + Invalid test value + + + + An empty or invalid value has been supplied for this test. + + + + LDAP %1 test failed + LDAP %1 test failed + + + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + + + LDAP %1 test successful + LDAP %1 test successful + + + The %1 has been queried successfully and %2 entries were found. + The %1 has been queried successfully and %2 entries were found. + + + LDAP test failed + LDAP test failed + + + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + + + and + and + + + LDAP test successful + LDAP test successful + + + %1 %2 have been queried successfully: + +%3 + %1 %2 have been queried successfully: + +%3 + + + LDAP filter test failed + LDAP filter test failed + + + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 + + + LDAP filter test successful + LDAP filter test successful + + + %1 %2 have been queried successfully using the configured filter. + %1 %2 have been queried successfully using the configured filter. + + + LDAP directory + + + + + LdapConfigurationPage + + Basic settings + Basic settings + + + General + Общи настройки + + + LDAP server and port + LDAP server and port + + + Bind DN + Bind DN + + + Bind password + Bind password + + + Anonymous bind + Anonymous bind + + + Use bind credentials + Use bind credentials + + + Base DN + Base DN + + + Fixed base DN + Fixed base DN + + + e.g. dc=example,dc=org + e.g. dc=example,dc=org + + + Discover base DN by naming context + Discover base DN by naming context + + + e.g. namingContexts or defaultNamingContext + e.g. namingContexts or defaultNamingContext + + + Environment settings + Environment settings + + + Object trees + Object trees + + + Computer tree + Computer tree + + + e.g. OU=Groups + e.g. OU=Groups + + + User tree + User tree + + + e.g. OU=Users + e.g. OU=Users + + + e.g. OU=Computers + e.g. OU=Computers + + + Group tree + Group tree + + + Perform recursive search operations in object trees + Perform recursive search operations in object trees + + + Object attributes + Object attributes + + + e.g. hwAddress + e.g. hwAddress + + + e.g. member or memberUid + e.g. member or memberUid + + + e.g. dNSHostName + e.g. dNSHostName + + + Computer MAC address attribute + Computer MAC address attribute + + + Group member attribute + Group member attribute + + + e.g. uid or sAMAccountName + e.g. uid or sAMAccountName + + + Advanced settings + Advanced settings + + + Optional object filters + Optional object filters + + + Filter for user groups + Filter for user groups + + + Filter for users + Filter for users + + + Filter for computer groups + Filter for computer groups + + + Group member identification + Group member identification + + + Distinguished name (Samba/AD) + Distinguished name (Samba/AD) + + + List all groups of a user + List all groups of a user + + + List all groups of a computer + List all groups of a computer + + + Get computer object by IP address + Get computer object by IP address + + + Enter username + Въведи потребителско име + + + Please enter a user login name (wildcards allowed) which to query: + Please enter a user login name (wildcards allowed) which to query: + + + Enter group name + Enter group name + + + Please enter a group name whose members to query: + Please enter a group name whose members to query: + + + Enter computer name + Enter computer name + + + Enter computer DN + Enter computer DN + + + Please enter the DN of a computer whose MAC address to query: + Please enter the DN of a computer whose MAC address to query: + + + Please enter a user login name whose group memberships to query: + Please enter a user login name whose group memberships to query: + + + Enter computer IP address + Enter computer IP address + + + Please enter a computer IP address which to resolve to an computer object: + Please enter a computer IP address which to resolve to an computer object: + + + (only if different from group tree) + (only if different from group tree) + + + Computer group tree + Computer group tree + + + Filter for computers + Filter for computers + + + e.g. room or computerLab + e.g. room or computerLab + + + Integration tests + Integration tests + + + Computer groups + Computer groups + + + e.g. name or description + e.g. name or description + + + Filter for computer containers + Filter for computer containers + + + Computer containers or OUs + Computer containers or OUs + + + Connection security + Connection security + + + TLS certificate verification + TLS certificate verification + + + System defaults + System defaults + + + Never (insecure!) + Never (insecure!) + + + Custom CA certificate file + Custom CA certificate file + + + None + None + + + TLS + TLS + + + SSL + SSL + + + e.g. (objectClass=computer) + e.g. (objectClass=computer) + + + e.g. (objectClass=group) + e.g. (objectClass=group) + + + e.g. (objectClass=person) + e.g. (objectClass=person) + + + e.g. (objectClass=room) or (objectClass=computerLab) + e.g. (objectClass=room) or (objectClass=computerLab) + + + e.g. (objectClass=container) or (objectClass=organizationalUnit) + e.g. (objectClass=container) or (objectClass=organizationalUnit) + + + Certificate files (*.pem) + Certificate files (*.pem) + + + Encryption protocol + Encryption protocol + + + Computer location attribute + Computer location attribute + + + Computer display name attribute + Computer display name attribute + + + Location name attribute + Location name attribute + + + e.g. cn or displayName + e.g. cn or displayName + + + Computer locations identification + Computer locations identification + + + Identify computer locations (e.g. rooms) via: + Identify computer locations (e.g. rooms) via: + + + Location attribute in computer objects + Location attribute in computer objects + + + List all entries of a location + List all entries of a location + + + List all locations + List all locations + + + Enter computer display name + Enter computer display name + + + Please enter a computer display name to query: + Please enter a computer display name to query: + + + Enter computer location name + Enter computer location name + + + Please enter the name of a computer location (wildcards allowed): + Please enter the name of a computer location (wildcards allowed): + + + Enter location name + Enter location name + + + Please enter the name of a location whose entries to query: + Please enter the name of a location whose entries to query: + + + Browse + Browse + + + Test + Тест + + + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + + + Computer hostname attribute + Computer hostname attribute + + + Please enter a computer hostname to query: + Please enter a computer hostname to query: + + + Enter hostname + Enter hostname + + + Please enter a computer hostname whose group memberships to query: + Please enter a computer hostname whose group memberships to query: + + + User login name attribute + User login name attribute + + + Configured attribute for user login name or computer hostname (OpenLDAP) + Configured attribute for user login name or computer hostname (OpenLDAP) + + + Directory name + + + + Query options + + + + Query nested user groups (supported by AD only) + + + + Query timeout + + + + ms + ms + + + + LdapNetworkObjectDirectoryConfigurationPage + + LDAP + + + + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + + + LdapPlugin + + Auto-configure the base DN via naming context + Auto-configure the base DN via naming context + + + Query objects from LDAP directory + Query objects from LDAP directory + + + Show help about command + Show help about command + + + Commands for configuring and testing LDAP/AD integration + Commands for configuring and testing LDAP/AD integration + + + Basic LDAP/AD support for Veyon + Basic LDAP/AD support for Veyon + + + %1 (load computers and locations from LDAP/AD) + %1 (load computers and locations from LDAP/AD) + + + %1 (load users and groups from LDAP/AD) + %1 (load users and groups from LDAP/AD) + + + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + + + No naming context attribute name given - falling back to configured value. + No naming context attribute name given - falling back to configured value. + + + Could not query base DN. Please check your LDAP configuration. + Could not query base DN. Please check your LDAP configuration. + + + Configuring %1 as base DN and disabling naming context queries. + Configuring %1 as base DN and disabling naming context queries. + + + Test binding to an LDAP server + + + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + + + + LDAP bind + + + + + LinuxPlatformConfigurationPage + + Linux + Linux + + + Custom PAM service for user authentication + Custom PAM service for user authentication + + + User authentication + User authentication + + + User sessions + + + + Minimum session lifetime before server start + + + + User login + User login + + + Login key sequence + + + + + LinuxPlatformPlugin + + Plugin implementing abstract functions for the Linux platform + Plugin implementing abstract functions for the Linux platform + + + + LocationDialog + + Select location + Select location + + + enter search filter... + enter search filter... + + + + MainToolBar + + Configuration + Configuration + + + Show icons only + Show icons only + + + Disable tooltips + + + + + MainWindow + + MainWindow + MainWindow + + + toolBar + toolBar + + + General + Общи настройки + + + &File + &File + + + &Help + &Help + + + &Quit + &Quit + + + Ctrl+Q + Ctrl+Q + + + Ctrl+S + Ctrl+S + + + L&oad settings from file + L&oad settings from file + + + Ctrl+O + Ctrl+O + + + About Qt + About Qt + + + Configuration not writable + Configuration not writable + + + Load settings from file + Load settings from file + + + Save settings to file + Save settings to file + + + Unsaved settings + Unsaved settings + + + There are unsaved settings. Quit anyway? + There are unsaved settings. Quit anyway? + + + Veyon Configurator + Veyon Configurator + + + Service + Service + + + Master + Master + + + Access control + Access control + + + About Veyon + За Veyron + + + Auto + Auto + + + About + За програмата + + + %1 Configurator %2 + %1 Configurator %2 + + + JSON files (*.json) + JSON files (*.json) + + + The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. + The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. + + + Access denied + Достъпът е отказан + + + According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. + According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. + + + Screenshots + Screenshots + + + Feature active + Feature active + + + The feature "%1" is still active. Please stop it before closing %2. + The feature "%1" is still active. Please stop it before closing %2. + + + Reset configuration + Reset configuration + + + Do you really want to reset the local configuration and revert all settings to their defaults? + Do you really want to reset the local configuration and revert all settings to their defaults? + + + Search users and computers + Search users and computers + + + Align computers to grid + Align computers to grid + + + %1 Configurator + %1 Configurator + + + Insufficient privileges + Insufficient privileges + + + Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + + + Only show powered on computers + Only show powered on computers + + + &Save settings to file + &Save settings to file + + + &View + &View + + + &Standard + &Standard + + + &Advanced + &Advanced + + + Use custom computer arrangement + Use custom computer arrangement + + + Locations && computers + Locations && computers + + + Authentication + Authentication + + + Adjust size of computer icons automatically + + + + Slideshow + + + + Spotlight + + + + Veyon Master + + + + Locations & computers + Locations & computers + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + + + + Load computer positions + + + + Save computer positions + + + + + MasterConfigurationPage + + Directories + Directories + + + User configuration + User configuration + + + Feature on computer double click: + Feature on computer double click: + + + Features + Features + + + All features + All features + + + Disabled features + Disabled features + + + Screenshots + Screenshots + + + <no feature> + <no feature> + + + Basic settings + Basic settings + + + Behaviour + Behaviour + + + Enforce selected mode for client computers + Enforce selected mode for client computers + + + Hide local computer + Hide local computer + + + Hide computer filter field + Hide computer filter field + + + Actions such as rebooting or powering down computers + Actions such as rebooting or powering down computers + + + User interface + User interface + + + Background color + Background color + + + Thumbnail update interval + Thumbnail update interval + + + ms + ms + + + Program start + Program start + + + Modes and features + Modes and features + + + User and computer name + User and computer name + + + Only user name + Only user name + + + Only last part of user name + + + + Only computer name + Only computer name + + + Computer thumbnail caption + Computer thumbnail caption + + + Text color + Text color + + + Sort order + Sort order + + + Computer and user name + Computer and user name + + + Computer locations + Computer locations + + + Show current location only + Show current location only + + + Allow adding hidden locations manually + Allow adding hidden locations manually + + + Hide empty locations + Hide empty locations + + + Show confirmation dialog for potentially unsafe actions + Show confirmation dialog for potentially unsafe actions + + + Perform access control + Perform access control + + + Automatically select current location + Automatically select current location + + + Automatically open computer select panel + Automatically open computer select panel + + + Use modern user interface (experimental) + + + + Thumbnail spacing + + + + px + + + + Hide local session + + + + Auto + Auto + + + Thumbnail aspect ratio + + + + Automatically adjust computer icon size + + + + Open feature windows on the same screen as the main window + + + + Configuration templates + + + + Image quality in monitoring mode + + + + Highest + + + + High + + + + Medium + + + + Low + + + + Lowest + + + + Remote access image quality + + + + Advanced + + + + Computer name source + + + + Default + + + + Host address + Host address + + + Session client address + + + + Session client name + + + + Session host name + + + + Session metadata + + + + Full name of user + + + + User login name + + + + Computer UID role + + + + Session meta data hash + + + + Always expand all locations + + + + Image quality + + + + + MonitoringMode + + Monitoring + Monitoring + + + Builtin monitoring mode + Builtin monitoring mode + + + This mode allows you to monitor all computers at one or more locations. + This mode allows you to monitor all computers at one or more locations. + + + Query application version of the server + + + + Query active features + + + + Query properties of remotely available screens + + + + + NestedNetworkObjectDirectory + + All directories + + + + + NetworkObjectDirectoryConfigurationPage + + Update interval: + Update interval: + + + seconds + seconds + + + + NetworkObjectDirectoryConfigurationPageTab + + Enabled + + + + + NetworkObjectTreeModel + + Locations/Computers + Locations/Computers + + + + OpenWebsiteDialog + + Open website + Open website + + + e.g. Veyon + e.g. Veyon + + + Remember and add to website menu + Remember and add to website menu + + + e.g. www.veyon.io + e.g. www.veyon.io + + + Please enter the URL of the website to open: + Please enter the URL of the website to open: + + + Name: + Name: + + + Website name + + + + + PluginCommands + + List names of all installed plugins + + + + Show table with details of all installed plugins + + + + Name + Name + + + Description + + + + Version + + + + UID + + + + Plugin-related CLI operations + + + + Commands for managing plugins + + + + + PowerControlFeaturePlugin + + Power on + Power on + + + Click this button to power on all computers. This way you do not have to power on each computer by hand. + Click this button to power on all computers. This way you do not have to power on each computer by hand. + + + Reboot + Reboot + + + Click this button to reboot all computers. + Click this button to reboot all computers. + + + Power down + Power down + + + Click this button to power down all computers. This way you do not have to power down each computer by hand. + Click this button to power down all computers. This way you do not have to power down each computer by hand. + + + Power on/down or reboot a computer + Power on/down or reboot a computer + + + Confirm reboot + Confirm reboot + + + Confirm power down + Confirm power down + + + Do you really want to reboot the selected computers? + Do you really want to reboot the selected computers? + + + Power on a computer via Wake-on-LAN (WOL) + Power on a computer via Wake-on-LAN (WOL) + + + MAC ADDRESS + MAC ADDRESS + + + This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. + This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. + + + Please specify the command to display help for! + Please specify the command to display help for! + + + Invalid MAC address specified! + Invalid MAC address specified! + + + Commands for controlling power status of computers + Commands for controlling power status of computers + + + Power down now + Power down now + + + Install updates and power down + Install updates and power down + + + Power down after user confirmation + Power down after user confirmation + + + Power down after timeout + Power down after timeout + + + The computer was remotely requested to power down. Do you want to power down the computer now? + The computer was remotely requested to power down. Do you want to power down the computer now? + + + The computer will be powered down in %1 minutes, %2 seconds. + +Please save your work and close all programs. + The computer will be powered down in %1 minutes, %2 seconds. + +Please save your work and close all programs. + + + Do you really want to reboot <b>ALL</b> computers? + + + + Do you really want to power down <b>ALL</b> computers? + + + + Do you really want to power down the selected computers? + + + + + PowerDownTimeInputDialog + + Power down + Power down + + + Please specify a timeout for powering down the selected computers: + Please specify a timeout for powering down the selected computers: + + + minutes + minutes + + + seconds + seconds + + + + RemoteAccessFeaturePlugin + + Remote view + Remote view + + + Open a remote view for a computer without interaction. + Open a remote view for a computer without interaction. + + + Remote control + Remote control + + + Open a remote control window for a computer. + Open a remote control window for a computer. + + + Remote access + Remote access + + + Remote view or control a computer + Remote view or control a computer + + + Show help about command + Show help about command + + + Exchange clipboard contents + + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + + + RemoteAccessPage + + Remote access: %1 + + + + + RemoteAccessWidget + + %1 - %2 Remote Access + %1 - %2 Remote Access + + + %1 - %2 - %3 Remote Access + + + + + RemoteAccessWidgetToolBar + + View only + View only + + + Remote control + Remote control + + + Send shortcut + Send shortcut + + + Fullscreen + Fullscreen + + + Window + Window + + + Ctrl+Alt+Del + Ctrl+Alt+Del + + + Ctrl+Esc + Ctrl+Esc + + + Alt+Tab + Alt+Tab + + + Alt+F4 + Alt+F4 + + + Win+Tab + Win+Tab + + + Win + Win + + + Menu + Menu + + + Alt+Ctrl+F1 + Alt+Ctrl+F1 + + + Connected. + Connected. + + + Screenshot + Screenshot + + + Exit + Exit + + + Connecting... + + + + Select screen + + + + All screens + + + + + ScreenLockFeaturePlugin + + Lock + Lock + + + Unlock + Unlock + + + Lock screen and input devices of a computer + Lock screen and input devices of a computer + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + + + Lock input devices + + + + Unlock input devices + + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + + + + Screenshot + + unknown + unknown + + + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + + + Screenshot + Screenshot + + + Could not open screenshot file %1 for writing. + + + + + ScreenshotFeaturePlugin + + Screenshot + Screenshot + + + Use this function to take a screenshot of selected computers. + Use this function to take a screenshot of selected computers. + + + Screenshots taken + Screenshots taken + + + Screenshot of %1 computer have been taken successfully. + Screenshot of %1 computer have been taken successfully. + + + Take screenshots of computers and save them locally. + Take screenshots of computers and save them locally. + + + + ScreenshotManagementPage + + Screenshots + Screenshots + + + + ScreenshotManagementPanel + + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + + + User: + User: + + + Computer: + Computer: + + + Date: + Date: + + + Time: + Time: + + + Show + Show + + + Delete + Delete + + + Screenshot + Screenshot + + + Do you really want to delete all selected screenshots? + + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + + + + User has denied access + + + + User confirmed access + + + + + ServiceConfigurationPage + + General + Общи настройки + + + Autostart + Autostart + + + Hide tray icon + Hide tray icon + + + Start service + Start service + + + Stopped + Stopped + + + Stop service + Stop service + + + State: + State: + + + Enable firewall exception + Enable firewall exception + + + Allow connections from localhost only + Allow connections from localhost only + + + VNC server + VNC server + + + Plugin: + Plugin: + + + Restart %1 Service + Restart %1 Service + + + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + + + Running + Running + + + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. + + + Show notification on remote connection + Show notification on remote connection + + + Show notification when an unauthorized access is blocked + Show notification when an unauthorized access is blocked + + + Maximum session count + + + + Network port numbers + + + + Veyon server + + + + Internal VNC server + + + + Feature manager + + + + Demo server + Demo server + + + Miscellaneous network settings + + + + Session mode + + + + Local session mode (single server instance for primary local session) + + + + Active session mode (single server instance for active local or remote session) + + + + Multi session mode (distinct server instance for each local and remote desktop session) + + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + + + + Miscellaneous settings + + + + Disable clipboard synchronization + + + + Session metadata + + + + Content + + + + None + None + + + Value of an environment variable + + + + Value of a registry key + + + + Environment variable name: + + + + Registry key name: + + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + + + + + ServiceControl + + Service control + Service control + + + Starting %1 + + + + Stopping %1 + + + + Restarting %1 + + + + Registering %1 + + + + Unregistering %1 + + + + + ServiceControlCommands + + Register Veyon Service + Register Veyon Service + + + Unregister Veyon Service + Unregister Veyon Service + + + Start Veyon Service + Start Veyon Service + + + Stop Veyon Service + Stop Veyon Service + + + Restart Veyon Service + Restart Veyon Service + + + Query status of Veyon Service + Query status of Veyon Service + + + Service is running + Service is running + + + Service is not running + Service is not running + + + Configure and control Veyon service + Configure and control Veyon service + + + Commands for configuring and controlling Veyon Service + Commands for configuring and controlling Veyon Service + + + + ShellCommands + + Run command file + Run command file + + + File "%1" does not exist! + File "%1" does not exist! + + + Interactive shell and script execution for Veyon CLI + + + + Commands for shell functionalities + Commands for shell functionalities + + + + SlideshowPanel + + Previous + + + + Start/pause + + + + Next + + + + Duration: + + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + + + + Remove selected computers + + + + Update computers in realtime + + + + Spotlight + + + + Please select at least one computer to add. + + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + + + StartAppDialog + + Start application + + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + + + + Application name + + + + Name: + Name: + + + e.g. VLC + e.g. VLC + + + + SystemTrayIcon + + System tray icon + System tray icon + + + + SystemUserGroupsPlugin + + User groups backend for system user groups + User groups backend for system user groups + + + Default (system user groups) + Default (system user groups) + + + + TestingCommandLinePlugin + + Test internal Veyon components and functions + Test internal Veyon components and functions + + + Commands for testing internal components and functions of Veyon + Commands for testing internal components and functions of Veyon + + + + TextMessageDialog + + Send text message + Send text message + + + Please enter your message which send to all selected users. + + + + + TextMessageFeaturePlugin + + Text message + Text message + + + Use this function to send a text message to all users e.g. to assign them new tasks. + Use this function to send a text message to all users e.g. to assign them new tasks. + + + Message from teacher + Message from teacher + + + Send a message to a user + Send a message to a user + + + + UltraVncConfigurationWidget + + Enable capturing of layered (semi-transparent) windows + Enable capturing of layered (semi-transparent) windows + + + Poll full screen (leave this enabled per default) + Poll full screen (leave this enabled per default) + + + Low accuracy (turbo mode) + Low accuracy (turbo mode) + + + Builtin UltraVNC server configuration + Builtin UltraVNC server configuration + + + Enable multi monitor support + Enable multi monitor support + + + Enable Desktop Duplication Engine on Windows 8 and newer + Enable Desktop Duplication Engine on Windows 8 and newer + + + Maximum CPU usage + + + + + UserLoginDialog + + User login + User login + + + Please enter a username and password for automatic login on all computers. + Please enter a username and password for automatic login on all computers. + + + Username + Username + + + Password + Password + + + + UserSessionControlPlugin + + Log in + Log in + + + Click this button to log in a specific user on all computers. + Click this button to log in a specific user on all computers. + + + Log off + Log off + + + Click this button to log off users from all computers. + Click this button to log off users from all computers. + + + Confirm user logoff + Confirm user logoff + + + Do you really want to log off the selected users? + Do you really want to log off the selected users? + + + User session control + User session control + + + Do you really want to log off <b>ALL</b> users? + + + + + VeyonCore + + [OK] + [OK] + + + [FAIL] + [FAIL] + + + Invalid command! + Invalid command! + + + Available commands: + Available commands: + + + Invalid arguments given + Invalid arguments given + + + Not enough arguments given - use "%1 help" for more information + Not enough arguments given - use "%1 help" for more information + + + Unknown result! + Unknown result! + + + Available modules: + Available modules: + + + No module specified or module not found - available modules are: + No module specified or module not found - available modules are: + + + Plugin not licensed + Plugin not licensed + + + INFO + INFO + + + ERROR + ERROR + + + USAGE + USAGE + + + DESCRIPTION + DESCRIPTION + + + EXAMPLES + EXAMPLES + + + WARNING + WARNING + + + Authentication test + Authentication test + + + Screen %1 + + + + + VeyonMaster + + No write access + No write access + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + + + + VeyonServiceControl + + Veyon Service + Veyon Service + + + + WindowsPlatformConfiguration + + Could not change the setting for SAS generation by software. Sending Ctrl+Alt+Del via remote control will not work! + Could not change the setting for SAS generation by software. Sending Ctrl+Alt+Del via remote control will not work! + + + + WindowsPlatformConfigurationPage + + Windows + Windows + + + General + Общи настройки + + + Enable SAS generation by software (Ctrl+Alt+Del) + Enable SAS generation by software (Ctrl+Alt+Del) + + + Screen lock + Screen lock + + + Hide taskbar + Hide taskbar + + + Hide start menu + Hide start menu + + + Hide desktop + Hide desktop + + + User authentication + User authentication + + + Use alternative user authentication mechanism + Use alternative user authentication mechanism + + + User login + User login + + + Input start delay + Input start delay + + + Simulated key presses interval + Simulated key presses interval + + + Confirm legal notice (message displayed before user logs in) + Confirm legal notice (message displayed before user logs in) + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + + + + WindowsPlatformPlugin + + Plugin implementing abstract functions for the Windows platform + Plugin implementing abstract functions for the Windows platform + + + Internal display + + + + + WindowsServiceControl + + The service "%1" is already installed. + The service "%1" is already installed. + + + The service "%1" has been installed successfully. + The service "%1" has been installed successfully. + + + The service "%1" has been uninstalled successfully. + The service "%1" has been uninstalled successfully. + + + Service "%1" could not be found. + Service "%1" could not be found. + + + The service "%1" could not be installed (error %2). + + + + Could not change the failure actions config for service "%1" (error %2). + + + + The service "%1" could not be uninstalled (error %2). + + + + The start type of service "%1" could not be changed (error %2). + + + + + X11VncConfigurationWidget + + Builtin x11vnc server configuration + Builtin x11vnc server configuration + + + Custom x11vnc parameters: + Custom x11vnc parameters: + + + Do not use X Damage extension + Do not use X Damage extension + + + \ No newline at end of file diff --git a/translations/veyon_ca_ES.ts b/translations/veyon_ca_ES.ts new file mode 100644 index 000000000..ba7cca52b --- /dev/null +++ b/translations/veyon_ca_ES.ts @@ -0,0 +1,4895 @@ + + + AboutDialog + + About + Quant a + + + Translation + Traducció + + + License + Llicència + + + About Veyon + Quant al Veyon + + + Contributors + Col·laboradors + + + Version: + Versió: + + + Website: + Lloc web: + + + Current language not translated yet (or native English). + +If you're interested in translating Veyon into your local or another language or want to improve an existing translation, please contact a Veyon developer! + La llengua actual encara no s'ha traduït (o anglès natiu). + +Si esteu interessat a traduir el Veyon al vostre idioma local o a un altre o voleu millorar una traducció existent, poseu-vos en contacte amb un desenvolupador del Veyon! + + + About %1 %2 + Quant a %1 %2 + + + Support Veyon project with a donation + Doneu suport al projecte Veyon amb una donació + + + + AccessControlPage + + Computer access control + Control d'accés a l'ordinador + + + Grant access to every authenticated user (default) + Concedeix accés a cada usuari autenticat (per defecte) + + + Test + Prova + + + Process access control rules + Processa les regles de control d'accés + + + User groups authorized for computer access + Grups d'usuaris autoritzats per a accedir a l'ordinador + + + Please add the groups whose members should be authorized to access computers in your Veyon network. + Afegiu els grups els membres dels quals haurien d'estar autoritzats per a accedir als ordinadors de la vostra xarxa Veyon. + + + Authorized user groups + Grups d'usuaris autoritzats + + + All groups + Tots els grups + + + Access control rules + Regles de control d'accés + + + Add access control rule + Afegeix una regla de control d'accés + + + Remove access control rule + Suprimeix la regla de control d'accés + + + Move selected rule down + Mou avall la regla seleccionada + + + Move selected rule up + Mou amunt la regla seleccionada + + + Edit selected rule + Edita la regla seleccionada + + + Enter username + Introduïu el nom d'usuari + + + Please enter a user login name whose access permissions to test: + Introduïu un nom d'usuari d'inici de sessió amb els permisos d'accés per provar: + + + Access allowed + Accés permès + + + The specified user is allowed to access computers with this configuration. + L'usuari especificat té permís per a accedir als ordinadors amb aquesta configuració. + + + Access denied + Accés denegat + + + The specified user is not allowed to access computers with this configuration. + L'usuari especificat no té permís per a accedir als ordinadors amb aquesta configuració. + + + Enable usage of domain groups + Habilita l'ús de grups de domini + + + User groups backend: + Rerefons dels grups d'usuaris: + + + Restrict access to members of specific user groups + Restringeix l'accés als membres de grups d'usuaris específics + + + + AccessControlProvider + + Provider for access control features + + + + + AccessControlRuleEditDialog + + Edit access control rule + Edita la regla de control d'accés + + + General + General + + + enter a short name for the rule here + introduïu aquí un nom curt per a la regla + + + Rule name: + Nom de la regla: + + + enter a description for the rule here + introduïu aquí una descripció per a la regla + + + Rule description: + Descripció de la regla: + + + Conditions + Condicions + + + If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. + Si s'activa més d'una condició cada condició s'ha de complir per tal que s'apliqui la regla (I lògic). Si només s'ha de complir una de les múltiples condicions (O lògic) creeu regles de control d'accés múltiples. + + + Action + Acció + + + Allow access + Permet l'accés + + + Deny access + Denega l'accés + + + Ask logged on user for permission + Demana permís a l'usuari + + + None (rule disabled) + Cap (regla inhabilitada) + + + Accessing user + S'està accedint a l'usuari + + + Accessing computer + S'està accedint a l'ordinador + + + Always process rule and ignore conditions + Processa sempre la regla i ignora les condicions + + + Accessing computer and local computer + Accés a l'ordinador i a l'ordinador local + + + User being accessed + S'està accedint a l'usuari + + + is logged in locally + està connectat localment + + + is logged in remotely + està connectat remotament + + + No user is logged in locally + No hi ha cap usuari connectat localment + + + One or multiple users are logged in locally + Un o diversos usuaris han iniciat la sessió local + + + No user is logged in remotely + No hi ha cap usuari connectat remotament + + + One or multiple users are logged in remotely + Un o diversos usuaris han iniciat sessió remotament + + + is located at + està situat a + + + is not located at + no està situat a + + + are located at the same location + es troben a la mateixa ubicació + + + are not located the same location + no es troben a la mateixa ubicació + + + is member of group + és membre del grup + + + is not member of group + no és membre del grup + + + is authenticated via + s'ha autenticat via + + + is not authenticated via + no s'ha autenticat via + + + has one or more groups in common with user being accessed + té un o més grups en comú amb l'usuari que s'està accedint + + + has no groups in common with user being accessed + no té grups en comú amb l'usuari que s'està accedint + + + equals user being accessed + és igual que l'usuari que s'està accedint + + + is different from user being accessed + és diferent que l'usuari que s'està accedint + + + is already connected + ja està connectat + + + is not connected + no està connectat + + + is local computer + és un ordinador local + + + is not local computer + no és un ordinador local + + + Computer being accessed + S'està accedint a l'ordinador + + + Session being accessed is a user session + La sessió que s'està accedint és una sessió d'usuari + + + Session being accessed is a login screen + La sessió que s'està accedint és una pantalla d'inici de sessió + + + Local computer is already being accessed + + + + Local computer is not yet being accessed + + + + + AccessControlRulesTestDialog + + Access control rules test + Prova de regles de control d'accés + + + Accessing user: + Accés a l'usuari: + + + Local computer: + Ordinador local: + + + Accessing computer: + Accés a l'ordinador: + + + Please enter the following user and computer information in order to test the configured ruleset. + Introduïu la següent informació de l'usuari i de l'ordinador per a provar el conjunt de regles configurat. + + + Local user: + Usuari local: + + + Connected users: + Usuaris connectats: + + + The access in the given scenario is allowed. + Es permet l'accés a l'escenari indicat. + + + The access in the given scenario is denied. + Es denega l'accés a l'escenari indicat. + + + The access in the given scenario needs permission of the logged on user. + L'accés a l'escenari indicat necessita el permís de l'usuari connectat. + + + Test result + Resultat de la prova + + + Authentication method + Mètode d'autenticació + + + There is no matching rule with a valid action. The access is therefore denied. + + + + + AuthKeysConfigurationWidget + + Introduction + Introducció + + + Please perform the following steps to set up key file authentication: + Realitzeu els passos següents per a configurar l'autenticació del fitxer de claus: + + + 1) Create a key pair on the master computer. + 1) Creeu un parell de claus a l'ordinador principal. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Establiu un grup d'accés els membres del qual han de tenir permís per accedir a altres ordinadors. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Exporteu la clau pública i importeu en tots els ordinadors de client amb el mateix nom. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Consulteu <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Manual de l'administrador del Veyon</a> per a més informació. + + + Key file directories + Directoris de fitxers de claus + + + Public key file base directory + Carpeta del fitxer de la clau pública + + + Private key file base directory + Carpeta del fitxer de la clau privada + + + Available authentication keys + Claus d'autenticació disponibles + + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Un parell de claus d'autenticació consisteix en dues claus criptogràfiques acoblades, una clau privada i una de pública. +Una clau privada permet als usuaris de l'ordinador mestre accedir als ordinadors de client. +És important que només els usuaris autoritzats tinguin accés a la clau privada. +La clau pública s'utilitza en ordinadors de client per autenticar la sol·licitud de connexió entrant. + + + Create key pair + Crea un parell de claus + + + Delete key + Suprimeix la clau + + + Import key + Importa la clau + + + Export key + Exporta la clau + + + Set access group + Estableix el grup d'accés + + + Key files (*.pem) + Fitxers de claus (*.perm) + + + Authentication key name + Nom de la clau d'autenticació + + + Please enter the name of the user group or role for which to create an authentication key pair: + Introduïu el nom del grup d'usuaris o el rol per al qual crear un parell de claus d'autenticació: + + + Do you really want to delete authentication key "%1/%2"? + Esteu segur que voleu suprimir la clau d'autenticació «%1/%2»? + + + Please select a key to delete! + Seleccioneu una clau per suprimir! + + + Please select a key to export! + Seleccioneu una clau per exportar! + + + Please select a user group which to grant access to key "%1": + Seleccioneu un grup d'usuaris que puguin accedir a la clau "%1": + + + Please select a key which to set the access group for! + Seleccioneu una clau per a la qual establir el grup d'accés! + + + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + + + + + AuthKeysManager + + Please check your permissions. + Comproveu els permisos. + + + Key name contains invalid characters! + El nom de la clau conté caràcters no vàlids! + + + Invalid key type specified! Please specify "%1" or "%2". + S'ha especificat un tipus de clau no vàlid! Especifiqueu "%1" o "%2". + + + Specified key does not exist! Please use the "list" command to list all installed keys. + La clau especificada no existeix! Utilitzeu l'ordre «list» per a llistar totes les claus instal·lades. + + + One or more key files already exist! Please delete them using the "delete" command. + Ja existeix un o més fitxers de claus! Suprimiu-les utilitzant l'ordre «delete». + + + Creating new key pair for "%1" + S'està creant un parell de claus nou per a «%1» + + + Failed to create public or private key! + No s'ha pogut crear la clau pública o privada! + + + Newly created key pair has been saved to "%1" and "%2". + La parella de claus creada recentment s'ha desat a «%1» i «%2». + + + Could not remove key file "%1"! + No s'ha pogut suprimir el fitxer de claus «%1»! + + + Could not remove key file directory "%1"! + No s'ha pogut eliminar el directori de fitxers de claus «%1»! + + + Failed to create directory for output file. + No s'ha pogut crear el directori per al fitxer de sortida. + + + File "%1" already exists. + El fitxer «%1» ja existeix. + + + Failed to write output file. + No s'ha pogut escriure el fitxer de sortida. + + + Key "%1/%2" has been exported to "%3" successfully. + La clau "%1/%2" s'ha exportat a «%3» amb èxit. + + + Failed read input file. + Ha fallat la lectura del fitxer d'entrada. + + + File "%1" does not contain a valid private key! + El fitxer «%1» no conté una clau privada vàlida! + + + File "%1" does not contain a valid public key! + El fitxer «%1» no conté una clau pública vàlida! + + + Failed to create directory for key file. + No s'ha pogut crear el directori per al fitxer de claus. + + + Failed to write key file "%1". + No s'ha pogut escriure el fitxer de claus «%1». + + + Failed to set permissions for key file "%1"! + No s'han pogut establir els permisos del fitxer de claus «%1»! + + + Key "%1/%2" has been imported successfully. Please check file permissions of "%3" in order to prevent unauthorized accesses. + La clau «%1/%2» s'ha importat correctament. Comproveu els permisos del fitxer de «%3» per a evitar els accessos no autoritzats. + + + Failed to convert private key to public key + No s'ha pogut convertir la clau privada a la clau pública + + + Failed to create directory for private key file "%1". + No s'ha pogut crear el directori per al fitxer de claus privades «%1». + + + Failed to save private key in file "%1"! + No s'ha pogut desar la clau privada al fitxer «%1»! + + + Failed to set permissions for private key file "%1"! + No s'han pogut establir els permisos del fitxer de claus privades «%1»! + + + Failed to create directory for public key file "%1". + No s'ha pogut crear el directori per al fitxer de claus públiques «%1». + + + Failed to save public key in file "%1"! + No s'ha pogut desar la clau pública al fitxer «%1»! + + + Failed to set permissions for public key file "%1"! + No s'han pogut establir els permisos del fitxer de claus públiques «%1»! + + + Failed to set owner of key file "%1" to "%2". + No s'ha pogut establir el propietari del fitxer de claus «%1» a «%2». + + + Failed to set permissions for key file "%1". + No s'han pogut establir els permisos del fitxer de claus «%1». + + + Key "%1" is now accessible by user group "%2". + La clau «%1» ara és accessible per al grup d'usuaris «%2». + + + <N/A> + <N/D> + + + Failed to read key file. + No s'ha pogut llegir el fitxer de claus. + + + + AuthKeysPlugin + + Create new authentication key pair + Crea un parell de claus d'autenticació nou + + + Delete authentication key + Suprimeix la clau d'autenticació + + + List authentication keys + Llista les claus d'autenticació + + + Import public or private key + Importa una clau pública o privada + + + Export public or private key + Exporta la clau pública o privada + + + Extract public key from existing private key + Extreu la clau pública de la clau privada existent + + + Set user group allowed to access a key + Estableix el grup d'usuaris permesos per a accedir a una clau + + + KEY + CLAU + + + ACCESS GROUP + GRUP D'ACCÉS + + + This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. + Aquesta ordre ajusta els permisos d'accés als fitxers <KEY>de manera que només el grup d'usuaris<ACCESS GROUP> hi té permís de lectura. + + + NAME + NOM + + + FILE + FITXER + + + This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. + Aquesta ordre exporta la clau d'autenticació <KEY> a <FILE>. Si no s'especifica <FILE>, es construirà un nom a partir del nom i el tipus de <KEY>. + + + This command imports the authentication key <KEY> from <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. + Aquesta ordre importa la clau d'autenticació <KEY> de <FILE>. Si no s'especifica <FILE>,. es construirà un nom a partir del nom i el tipus de <KEY>. + + + This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. + Aquesta ordre llista totes les claus d'autenticació disponibles al directori de claus configurat. Si s'especifica l'opció «%1» es mostrarà una taula amb els detalls de la clau. Pot ser que faltin alguns detalls si una clau no és accessible p. ex. a causa de la manca de permisos de lectura. + + + TYPE + TIPUS + + + PAIR ID + ID DEL PARELL + + + Commands for managing authentication keys + Ordres per gestionar les claus d'autenticació + + + This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. + Aquesta ordre crea un nou parell de claus d'autenticació amb el nom <NAME> i desa la clau privada i pública als directoris de claus configurats. El paràmetre ha de ser un nom per a la clau, que només pot contenir lletres. + + + This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. + Aquesta ordre elimina la clau d'autenticació <KEY> del directori de claus configurat. Tingueu en compte que una clau no es pot recuperar una vegada s'ha eliminat. + + + This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + Aquesta ordre extreu la part de la clau pública de la clau privada <KEY> i la desa com a clau pública corresponent. Per tant, quan es crea un altre ordinador mestre, n'hi ha prou amb transferir la clau privada només. Llavors es pot extreure la clau pública. + + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + Els fitxers de claus d'autenticació no s'han configurat correctament en aquest ordinador. Creeu fitxers de claus nous o canvieu a un mètode d'autenticació diferent utilitzant el configurador de Veyon. + + + Key file authentication + Autentificació amb fitxers de claus + + + Key file + Fitxer de claus + + + Please specify the key name (e.g. "teacher/public") as the first argument. + Indiqueu el nom de la clau (p. ex. «professor/públic») com a primer argument. + + + Please specify the command to display help for. + Indiqueu l'ordre per a la qual es mostrarà l'ajuda. + + + The specified command does not exist or no help is available for it. + L'ordre indicada no existeix o no hi ha cap ajuda disponible per a ella. + + + + AuthKeysTableModel + + Name + Nom + + + Type + Tipus + + + Access group + Grup d'accés + + + Pair ID + ID del parell + + + + AuthLdapConfigurationWidget + + General + General + + + Username to bind DN mapping: + Nom d'usuari per vincular el mapatge DN: + + + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + per exemple %username%MAINDOMAIN o cn=%username%,ou=usuaris,dc=example,dc=org + + + + AuthLdapDialog + + Veyon Logon + Inici de sessió Veyon + + + Please enter your domain/LDAP username and password in order to access computers. + Introduïu el vostre nom d'usuari i contrasenya de domini/LDAP per a accedir als ordinadors. + + + Username + Nom d'usuari + + + Password + Contrasenya + + + Authentication error + Error d'autentificació + + + Logon failed with given username and password. Please try again! + L'inici de sessió ha fallat amb el nom d'usuari i la contrasenya indicats. Torneu-ho a provar! + + + + AuthLogonDialog + + Veyon Logon + Inici de sessió Veyon + + + Please enter your username and password in order to access computers. + Introduïu el vostre nom d'usuari i contrasenya per a accedir als ordinadors. + + + Username + Nom d'usuari + + + Password + Contrasenya + + + Authentication error + Error d'autentificació + + + Logon failed with given username and password. Please try again! + L'inici de sessió ha fallat amb el nom d'usuari i la contrasenya indicats. Torneu-ho a provar! + + + + AuthLogonPlugin + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + El nom d'usuari o la contrasenya indicats no són correctes. Introduïu unes credencials vàlides o canvieu a un mètode d'autenticació diferent utilitzant el Configurador de Veyon. + + + Logon authentication + Autentificació d'inici de sessió + + + Logon + Inici de sessió + + + + AuthSimpleDialog + + Veyon Logon + Inici de sessió Veyon + + + Please enter the Veyon password: + Introduïu la contrasenya de Veyon: + + + Authentication error + Error d'autentificació + + + Logon failed with given password. Please try again! + L'inici de sessió ha fallat amb la contrasenya indicada. Torneu-ho a provar! + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + La contrasenya proporcionada és incorrecta. Introduïu la contrasenya correcta o canvieu a un mètode d'autenticació diferent utilitzant el Configurador de Veyon. + + + Simple password authentication + Autenticació de contrasenya simple + + + Simple password + Contrasenya simple + + + + AuthenticationPage + + Authentication is set up properly on this computer. + L'autenticació s'ha configurat correctament en aquest ordinador. + + + + AuthenticationPageTab + + Enabled + Activat + + + Test + Prova + + + + BuiltinDirectoryConfiguration + + Builtin directory + Directori integrat + + + + BuiltinDirectoryConfigurationPage + + Computers + Ordinadors + + + Name + Nom + + + Host address/IP + Adreça/IP de l'amfitrió + + + MAC address + Adreça MAC + + + Add new computer + Afegeix un ordinador nou + + + Remove selected computer + Suprimeix l'ordinador seleccionat + + + New computer + Ordinador nou + + + Builtin directory + Directori integrat + + + Locations + Ubicacions + + + Add new location + Afegeix una ubicació nova + + + Remove selected location + Suprimeix la ubicació seleccionada + + + New location + Ubicació nova + + + Directory name + Nom del directori + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + La importació de fitxers CSV és possible a través de la interfície de la línia d'ordres. Per a més informació, vegeu la .<a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">documentació en línia</a>. + + + + BuiltinDirectoryPlugin + + Show help for specific command + Mostra l'ajuda per a una ordre específica + + + Import objects from given file + Importa objectes des d'un fitxer donat + + + Export objects to given file + Exporta objectes a un fitxer donat + + + Invalid type specified. Valid values are "%1" or "%2". + S'ha especificat un tipus no vàlid. Els valors vàlids són «%1» o «%2». + + + Type + Tipus + + + Name + Nom + + + Host address + Adreça de l'amfitrió + + + MAC address + Adreça MAC + + + Specified object not found. + No s'ha trobat l'objecte especificat. + + + File "%1" does not exist! + El fitxer «%1» no existeix! + + + Can't open file "%1" for reading! + No es pot obrir el fitxer «%1» per a la lectura! + + + Unknown argument "%1". + Argument desconegut «%1». + + + Computer "%1" (host address: "%2" MAC address: "%3") + Ordinador "%1" (adreça host: "%2" adreça MAC: "%3") + + + Unclassified object "%1" with ID "%2" + Objecte no classificat «%1» amb ID «%2» + + + None + Cap + + + Computer + Ordinador + + + Root + Arrel + + + Invalid + No vàlid + + + Error while parsing line %1. + S'ha produït un error en analitzar la línia %1. + + + Network object directory which stores objects in local configuration + Directori d'objectes de xarxa que emmagatzema objectes en la configuració local + + + Commands for managing the builtin network object directory + Ordres per a gestionar el directori d'objectes de xarxa integrat + + + No format string or regular expression specified! + No s'ha especificat cap cadena de format o expressió regular! + + + Can't open file "%1" for writing! + No es pot obrir el fitxer «%1» per escriure! + + + No format string specified! + No s'ha especificat cap cadena de format! + + + Object UUID + UUID de l'objecte + + + Parent UUID + UUID pare + + + Add a location or computer + Afegeix una ubicació o un ordinador + + + Clear all locations and computers + Neteja totes les ubicacions i ordinadors + + + Dump all or individual locations and computers + Bolca totes les ubicacions o ordinadors individuals + + + List all locations and computers + Llista totes les ubicacions i ordinadors + + + Remove a location or computer + Elimina una ubicació o un ordinador + + + Location "%1" + Ubicació «%1» + + + Builtin (computers and locations in local configuration) + Integrat (ordinadors i ubicacions en la configuració local) + + + Location + Ubicació + + + FILE + FITXER + + + LOCATION + UBICACIÓ + + + FORMAT-STRING-WITH-PLACEHOLDERS + FORMAT-CADENA-AMB-MARCADORS-DE-POSICIÓ + + + REGULAR-EXPRESSION-WITH-PLACEHOLDER + EXPRESSIÓ-REGULAR-AMB-MARCADORS-DE-POSICIÓ + + + Imports objects from the specified text file using the given format string or regular expression containing one or multiple placeholders. Valid placeholders are: %1 + Importa objectes del fitxer de text indicat utilitzant el format indicat cadena o expressió regular que conté un o diversos espais reservats. Els marcadors de posició vàlids són: %1 + + + Import simple CSV file to a single room + Importa un fitxer CSV senzill a una única sala + + + Import CSV file with location name in first column + Importa un fitxer CSV amb el nom de la ubicació a la primera columna + + + Import text file with with key/value pairs using regular expressions + Importa un fitxer de text amb parells clau/valor utilitzant expressions regulars + + + Import arbitrarily formatted data + Importa dades amb format arbitrari + + + Exports objects to the specified text file using the given format string containing one or multiple placeholders. Valid placeholders are: %1 + Exporta objectes al fitxer de text especificat utilitzant la cadena de format indicat que conté un o diversos espais reservats. Els marcadors de posició vàlids són: %1 + + + Export all objects to a CSV file + Exporta tots els objectes a un fitxer CSV + + + Export all computers in a specific location to a CSV file + Exporta tots els ordinadors en una ubicació específica a un fitxer CSV + + + TYPE + TIPUS + + + NAME + NOM + + + PARENT + PARE + + + Adds an object where %1 can be one of "%2" or "%3". %4 can be specified by name or UUID. + Afegeix un objecte on %1 pot ser un de «%2» o «%3». %4 es pot especificar per nom o UUID. + + + Add a room + Afegeix una sala + + + Add a computer to room %1 + Afegeix un ordinador a la sala %1 + + + OBJECT + OBJECTE + + + Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. + Elimina l'objecte especificat del directori. Es pot especificar %1 per nom o UUID. Eliminar una ubicació també eliminarà tots els ordinadors relacionats. + + + Remove a computer by name + Suprimeix un ordinador per nom + + + Remove an object by UUID + Suprimeix un objecte per UUID + + + "Room 01" + «Sala 01» + + + "Computer 01" + «Ordinadors 01» + + + HOST ADDRESS + ADREÇA DE L'AMFITRIÓ + + + MAC ADDRESS + ADREÇA MAC + + + The specified command does not exist or no help is available for it. + L'ordre indicada no existeix o no hi ha cap ajuda disponible per a ella. + + + Location "%1" not found. + + + + + BuiltinUltraVncServer + + Builtin VNC server (UltraVNC) + Servidor VNC integrat (UltraVNC) + + + + BuiltinX11VncServer + + Builtin VNC server (x11vnc) + Servidor VNC integrat (x11vnc) + + + + ComputerControlListModel + + Active features: %1 + Característiques actives: %1 + + + Online and connected + En línia i connectat + + + Establishing connection + S'està establint la connexió + + + Computer offline or switched off + Ordinador desconnectat o desactivat + + + Authentication failed or access denied + Ha fallat l'autenticació o s'ha denegat l'accés + + + Disconnected + Desconnectat + + + No user logged on + No hi ha cap usuari connectat + + + Logged on user: %1 + Usuari connectat: %1 + + + Location: %1 + Ubicació: %1 + + + [no user] + [cap usuari] + + + Veyon Server unreachable or not running + No es pot accedir al servidor Veyon o no s'està executant + + + Name: %1 + Nom: %1 + + + Hostname: %1 + + + + unknown + desconegut + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + + + + ComputerControlServer + + %1 Service %2 at %3:%4 + %1 servei %2 a les %3:%4 + + + Authentication error + Error d'autentificació + + + Remote access + Accés remot + + + User "%1" at host "%2" is now accessing this computer. + L'usuari «%1» a l'amfitrió «%2» ara està accedint a aquest ordinador. + + + User "%1" at host "%2" attempted to access this computer but could not authenticate successfully. + L'usuari «%1» a l'amfitrió «%2» ha intentat accedir a aquest ordinador, però no s'ha pogut autenticar correctament. + + + Access control error + Error de control d'accés + + + User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + L'usuari «%1» a l'amfitrió «%2» ha intentat accedir a aquest ordinador, però s'ha blocat a causa de la configuració del control d'accés. + + + Active connections: + Connexions actives: + + + + ComputerGroupSelector + + Group %1 + + + + + ComputerManager + + User + Usuari + + + Missing network object directory plugin + Falta el connector de directori d'objectes de xarxa + + + No default network object directory plugin was found. Please check your installation or configure a different network object directory backend via %1 Configurator. + No s'ha trobat cap connector de directori d'objectes de xarxa per defecte. Comproveu la instal·lació o configureu un rerefons de directoris d'objectes de xarxa diferent a través del configurador de %1. + + + Location detection failed + Ha fallat la detecció de la ubicació + + + Computer name;Hostname;User + Nom de l'ordinador;Nom de l'ordinador;Usuari + + + Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + No s'ha pogut determinar la ubicació d'aquest ordinador. Això indica un problema amb la configuració del sistema. Totes les ubicacions es mostraran al plafó de selecció de l'ordinador. + + + Logged in since + + + + %1 days + + + + 1 day + + + + + ComputerMonitoring + + Computers + Ordinadors + + + Search users and computers + Cerca usuaris i ordinadors + + + Select all + + + + Unselect all + + + + Add to group + + + + Remove from group + + + + + ComputerSelectPanel + + Computer search + Cerca per ordinador + + + Add location + Afegeix una ubicació + + + Save computer/user list + Desa la llista d'ordinadors o usuaris + + + Select output filename + Selecciona el nom del fitxer de sortida + + + CSV files (*.csv) + Fitxers CSV (*.csv) + + + File error + Error de fitxer + + + Could not write the computer and users list to %1! Please check the file access permissions. + No s'ha pogut escriure la llista d'ordinadors i usuaris a %1! Comproveu els permisos d'accés als fitxers. + + + Search computers + + + + + ConfigCommands + + Clear system-wide Veyon configuration + Neteja la configuració de Veyon a tot el sistema + + + List all configuration keys and values + Llista totes les claus i valors de configuració + + + Import configuration from given file + Importa la configuració des d'un fitxer donat + + + Export configuration to given file + Exporta la configuració al fitxer indicat + + + Read and output configuration value for given key + Valor de configuració de lectura i sortida per a la clau donada + + + Write given value to given configuration key + Escriu el valor donat a la clau de configuració donada + + + Unset (remove) given configuration key + Desfa (suprimeix) la clau de configuració donada + + + Upgrade and save configuration of program and plugins + Actualitza i desa la configuració del programa i els connectors + + + Please specify an existing configuration file to import. + Indiqueu un fitxer de configuració existent per importar. + + + Configuration file is not readable! + El fitxer de configuració no es pot llegir! + + + Please specify a valid filename for the configuration export. + Indiqueu un nom de fitxer vàlid per a l'exportació de la configuració. + + + Output file is not writable! + No es pot escriure el fitxer de sortida! + + + Output directory is not writable! + No es pot escriure en el directori de sortida! + + + Please specify a valid key. + Indiqueu una clau vàlida. + + + Specified key does not exist in current configuration! + La clau indicada no existeix a la configuració actual! + + + Please specify a valid value. + Indiqueu un valor vàlid. + + + Configure Veyon at command line + Configura Veyon a la línia d'ordres + + + Commands for managing the configuration of Veyon + Ordres per a gestionar la configuració de Veyon + + + + ConfigurationManager + + Could not modify the autostart property for the %1 Service. + No s'ha pogut modificar la propietat d'inici automàtic per al servei %1. + + + Could not configure the firewall configuration for the %1 Server. + No s'ha pogut configurar la configuració del tallafoc per al servidor %1. + + + Could not configure the firewall configuration for the %1 Worker. + No s'ha pogut configurar la configuració del tallafoc per a l'operador de treball %1. + + + Configuration is not writable. Please check your permissions! + No es pot escriure la configuració. Comproveu-ne els permisos! + + + Could not apply platform-specific configuration settings. + No s'han pogut aplicar els paràmetres de configuració específics de la plataforma. + + + Could not configure the firewall configuration for the %1 Service. + No s'ha pogut configurar la configuració del tallafoc per al servei %1. + + + + DemoClient + + %1 Demo + Demostració %1 + + + + DemoConfigurationPage + + Demo server + Servidor de demostració + + + Tunables + Tunables + + + ms + ms + + + Key frame interval + Interval del marc de la clau + + + Memory limit + Límit de memòria + + + MB + MB + + + Update interval + Interval d'actualització + + + s + s + + + Slow down thumbnail updates while demo is running + Alenteix les actualitzacions de miniatures mentre s'està executant la demostració + + + Bandwidth limit + + + + MB/s + + + + + DemoFeaturePlugin + + Stop demo + Atura la demostració + + + Window demo + Demostració en finestra + + + Give a demonstration by screen broadcasting + Fa una demostració per emissió de pantalla + + + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + En aquest mode la pantalla es mostra en una finestra de tots els ordinadors. Els usuaris poden canviar a altres finestres segons sigui necessari. + + + Demo + Demostració + + + Share your screen or allow a user to share his screen with other users. + Comparteix la pantalla o permet que un usuari comparteixi la seva pantalla amb altres usuaris. + + + Full screen demo + Demostració en pantalla completa + + + Share your own screen in fullscreen mode + Compartiu la vostra pantalla en mode de pantalla completa + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + En aquest mode la pantalla es mostra en mode de pantalla completa en tots els ordinadors mentre que els dispositius d'entrada dels usuaris estan blocats. + + + Share your own screen in a window + Compartiu la vostra pantalla en una finestra + + + Share selected user's screen in fullscreen mode + Comparteix la pantalla de l'usuari seleccionat en mode de pantalla completa + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + En aquest mode la pantalla de l'usuari seleccionat es mostra en mode de pantalla completa en tots els ordinadors mentre que els dispositius d'entrada dels usuaris estan blocats. + + + Share selected user's screen in a window + Comparteix la pantalla de l'usuari seleccionat en una finestra + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + En aquest mode la pantalla de l'usuari seleccionat es mostra en una finestra de tots els ordinadors. Els usuaris poden canviar a altres finestres segons sigui necessari. + + + Please select a user screen to share. + Seleccioneu una pantalla d'usuari per a compartir. + + + Please select only one user screen to share. + Seleccioneu només una pantalla d'usuari per a compartir. + + + All screens + Totes les pantalles + + + + DesktopAccessDialog + + Desktop access dialog + Diàleg d'accés a l'escriptori + + + Confirm desktop access + Confirmeu l'accés a l'escriptori + + + Never for this session + Mai per a aquesta sessió + + + Always for this session + Sempre per a aquesta sessió + + + The user %1 at computer %2 wants to access your desktop. Do you want to grant access? + L'usuari %1 de l'ordinador %2 vol accedir a l'escriptori. Voleu concedir-hi accés? + + + + DesktopServicesConfigurationPage + + Name + Nom + + + Path + Camí + + + Predefined websites + Llocs web predefinits + + + Remove selected website + Elimina el lloc web seleccionat + + + URL + URL + + + New website + Lloc web nou + + + Applications & websites + Aplicacions i llocs web + + + Predefined applications + Aplicacions predefinides + + + Add new application + Afegeix una aplicació nova + + + Remove selected application + Suprimeix l'aplicació seleccionada + + + Add new website + Afegeix un lloc web nou + + + New application + Aplicació nova + + + + DesktopServicesFeaturePlugin + + Open website + Obre el lloc web + + + Click this button to open a website on all computers. + Feu clic en aquest botó per a obrir un lloc web en tots els ordinadors. + + + Open website "%1" + Obre el lloc web «%1» + + + Custom website + Lloc web personalitzat + + + Start application + Inicia l'aplicació + + + Click this button to start an application on all computers. + Feu clic en aquest botó per a iniciar una aplicació en tots els ordinadors. + + + Start application "%1" + Inicia l'aplicació «%1» + + + Custom application + Aplicació personalitzada + + + Start apps and open websites in user sessions + Inicia aplicacions i obre llocs web en sessions d'usuari + + + + DocumentationFigureCreator + + Teacher + Professor + + + Room %1 + Sala %1 + + + Please complete all tasks within the next 5 minutes. + Completeu totes les tasques en els pròxims 5 minuts. + + + Custom website + Lloc web personalitzat + + + Open file manager + Obre el gestor de fitxers + + + Start learning tool + Inicia l'eina d'aprenentatge + + + Play tutorial video + Reprodueix un vídeo d'aprenentatge + + + Handout + Gestió + + + Texts to read + Textos per llegir + + + generic-student-user + usuari-estudiant-genèric + + + Custom application + Aplicació personalitzada + + + + ExternalVncServer + + External VNC server + Servidor VNC extern + + + + ExternalVncServerConfigurationWidget + + External VNC server configuration + Configuració externa del servidor VNC + + + Port: + Port: + + + Password: + Contrasenya: + + + + FeatureCommands + + List names of all available features + Llista els noms de totes les característiques disponibles + + + Show table with details of all available features + Mostra la taula amb els detalls de totes les característiques disponibles + + + Start a feature on a remote host + Inicia una característica en un amfitrió remot + + + Stop a feature on a remote host + Atura una característica en un amfitrió remot + + + Please specify the command to display help for. + Indiqueu l'ordre per a la qual es mostrarà l'ajuda. + + + Displays a list with the names of all available features. + Mostra una llista amb els noms de totes les característiques disponibles. + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + Mostra una taula amb informació detallada sobre totes les característiques disponibles. Aquesta informació inclou una descripció, l'UID, el nom del connector que proporciona la característica respectiva i alguns altres detalls relacionats amb la implementació. + + + HOST ADDRESS + ADREÇA DE L'AMFITRIÓ + + + FEATURE + CARACTERÍSTICA + + + ARGUMENTS + ARGUMENTS + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + Inicia la característica especificada a l'amfitrió especificat connectant-se al servidor Veyon que s'executa remotament. La característica es pot especificar per nom o UID. Utilitzeu l'ordre «show» per a veure totes les característiques disponibles. Depenent de la característica, s'han d'especificar arguments addicionals (com el missatge de text a mostrar) codificats com una cadena JSON única. Consulteu la documentació del desenvolupador per a més informació + + + Lock the screen + Bloca la pantalla + + + Display a text message + Mostra un missatge de text + + + Test message + Missatge de prova + + + Start an application + Inicia una aplicació + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + Atura la característica especificada a l'amfitrió especificat connectant-se al servidor Veyon que s'exectua remotament. La característica es pot especificar per nom o UID. Utilitzeu l'ordre «show» per a veure totes les característiques disponibles. + + + Unlock the screen + Desbloca la pantalla + + + The specified command does not exist or no help is available for it. + L'ordre indicada no existeix o no hi ha cap ajuda disponible per a ella. + + + Name + Nom + + + Description + Descripció + + + Master + Mestre + + + Service + Servei + + + Worker + Treballador + + + UID + UID + + + Plugin + Connector + + + Invalid feature name or UID specified + El nom o l'UID de l'objecte no és vàlid + + + Error parsing the JSON-encoded arguments: %1 + S'ha produït un error en analitzar els arguments codificats per JSON: %1 + + + Failed to initialize credentials + No s'han pogut inicialitzar les credencials + + + Could not establish a connection to host %1 + No s'ha pogut establir una connexió a l'amfitrió %1 + + + Failed to send feature control message to host %1 + No s'ha pogut enviar el missatge de control de característiques a l'amfitrió %1 + + + Feature-related CLI operations + Operacions CLI relacionades amb les característiques + + + Commands for controlling features + Ordres per a les funcions de control + + + + FileTransferConfigurationPage + + File transfer + Transferència de fitxers + + + Directories + Directoris + + + Destination directory + Directori de destinació + + + Default source directory + Directori font per defecte + + + Options + Opcions + + + Remember last source directory + Recorda l'últim directori font + + + Create destination directory if it does not exist + Crea un directori de destinació si no existeix + + + + FileTransferController + + Could not open file "%1" for reading! Please check your permissions! + No s'ha pogut obrir el fitxer «%1» per a la lectura! Comproveu-ne els permisos! + + + + FileTransferDialog + + File transfer + Transferència de fitxers + + + Options + Opcions + + + Transfer only + Només la transferència + + + Transfer and open file(s) with associated program + Transfereix i obre fitxers amb el programa associat + + + Transfer and open destination folder + Transfereix i obre la carpeta de destinació + + + Files + Fitxers + + + Start + Inici + + + Overwrite existing files + Sobreescriu els fitxers existents + + + + FileTransferFileDialog + + Select one or more files to transfer + Seleccioneu un o més fitxers a transferir + + + + FileTransferPlugin + + File transfer + Transferència de fitxers + + + Click this button to transfer files from your computer to all computers. + Feu clic en aquest botó per a transferir fitxers des del vostre ordinador a tots els ordinadors. + + + Select one or more files to transfer + Seleccioneu un o més fitxers a transferir + + + Transfer files to remote computer + Transfereix els fitxers a l'ordinador remot + + + Received file "%1". + Fitxer «%1» rebut. + + + Could not receive file "%1" as it already exists. + No s'ha pogut rebre el fitxer «%1» perquè ja existeix. + + + Could not receive file "%1" as it could not be opened for writing! + No s'ha pogut rebre el fitxer «%1» perquè no s'ha pogut obrir per escriure! + + + + GeneralConfigurationPage + + User interface + Interfície d'usuari + + + Language: + Llengua: + + + Use system language setting + Utilitza la configuració de llengua del sistema + + + Veyon + Veyon + + + Logging + Registre + + + Log file directory + Carpeta dels fitxers de registre + + + Log level + Nivell de registre + + + Nothing + Res + + + Only critical messages + Només missatges crítics + + + Errors and critical messages + Errors i missatges crítics + + + Warnings and errors + Avisos i errors + + + Information, warnings and errors + Informació, avisos i errors + + + Debug messages and everything else + Missatges de depuració i tota la resta + + + Limit log file size + Limita la mida del fitxer de registre + + + Clear all log files + Buida tots els fitxers de registre + + + Log to standard error output + Registra cap a la sortida d'error estàndard + + + %1 service + Servei %1 + + + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + Cal parar temporalment el servei %1 per a eliminar els fitxers de registre. Voleu continuar? + + + Log files cleared + Fitxers de registre buidats + + + All log files were cleared successfully. + Tots els fitxers de registre s'han buidat amb èxit. + + + Error + Error + + + Could not remove all log files. + No s'han pogut buidar tots els fitxers de registre. + + + MB + MB + + + Rotate log files + Fes rotació dels fitxers de registre + + + x + x + + + Write to logging system of operating system + Escriu al sistema de registre del sistema operatiu + + + TLS configuration + Configuració TLS + + + Use certificate authority for TLS connections + Utilitza l'autoritat de certificació per a les connexions TLS + + + CA certificate file + Fitxer de certificat CA + + + ... + ... + + + Host certificate file + Fitxer de certificat de l'amfitrió + + + Host private key file + Fitxer de clau privada de l'amfitrió + + + Style: + + + + Native + + + + Color scheme: + + + + Light + + + + Dark + + + + User groups + + + + Backend: + Dorsal: + + + Include user groups from domain + + + + Missing user groups backend + Falta el rerefonss de grups d'usuaris + + + No user groups plugin was found. Please check your installation! + + + + + HeadlessVncServer + + Headless VNC server + Servidor VNC sense cap + + + + LdapBrowseDialog + + Browse LDAP + Navega per l'LDAP + + + + LdapClient + + LDAP error description: %1 + Descripció de l'error LDAP: %1 + + + + LdapConfiguration + + LDAP connection failed + Ha fallat la connexió LDAP + + + Could not connect to the LDAP server. Please check the server parameters. + +%1 + No s'ha pogut connectar al servidor LDAP. Comproveu els paràmetres del servidor. + +%1 + + + LDAP bind failed + Ha fallat el vincle LDAP + + + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + No s'ha pogut vincular al servidor LDAP. Comproveu els paràmetres del servidor i vinculeu-ne les credencials. + +%1 + + + LDAP bind successful + Enllaç LDAP correcte + + + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + S'ha connectat correctament al servidor LDAP i s'ha realitzat un enllaç LDAP. Els paràmetres bàsics LDAP estan configurats correctament. + + + LDAP base DN test failed + Ha fallat la prova DN base de l'LDAP + + + Could not query the configured base DN. Please check the base DN parameter. + +%1 + No s'ha pogut consultar el DN base configurat. Comproveu el paràmetre base DN. + +%1 + + + LDAP base DN test successful + Prova DN base LDAP correcta + + + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + El DN base LDAP s'ha consultat correctament. Es van trobar les següents entrades: + +%1 + + + LDAP naming context test failed + Ha fallat la prova de context de nomenclatura LDAP + + + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + No s'ha pogut consultar el DN base mitjançant contexts de nomenclatura. Comproveu el paràmetre de l'atribut de context de noms. + +%1 + + + LDAP naming context test successful + Prova de context de nomenclatura LDAP correcta + + + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + El context de nomenclatura LDAP s'ha consultat correctament. Es va trobar la base DN següent: +%1 + + + user tree + arbre d'usuari + + + User tree + Arbre d'usuari + + + group tree + arbre del grup + + + Group tree + Arbre de grups + + + computer tree + arbre de l'ordinador + + + Computer tree + Arbre de l'ordinador + + + computer group tree + arbre de grups d'ordinador + + + Computer group tree + Arbre de grups de l'ordinador + + + user objects + objectes d'usuari + + + User login name attribute + L'atribut de nom d'inici de sessió d'usuari + + + group members + membres del grup + + + Group member attribute + Atribut del membre del grup + + + Group not found + No s'ha trobat el grup + + + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + No s'ha pogut trobar un grup amb el nom «%1». Comproveu el nom del grup o el paràmetre de l'arbre de grups. + + + computer objects + objectes d'ordinador + + + Computer display name attribute + L'atribut nom de la pantalla de l'ordinador + + + Invalid hostname + El nom d'amfitrió no és vàlid + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Heu configurat els noms d'amfitrió de l'ordinador perquè s'emmagatzemin com a noms de domini plenament qualificats (FQDN) però heu introduït un nom d'amfitrió sense domini. + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Heu configurat els noms de host de l'ordinador perquè s'emmagatzemin com a noms d'amfitrió senzills sense un nom de domini, però heu introduït un nom d'amfitrió amb una part del nom de domini. + + + Computer hostname attribute + L'atribut de nom de l'ordinador + + + computer MAC addresses + adreces MAC de l'ordinador + + + Computer MAC address attribute + L'atribut d'adreça MAC de l'ordinador + + + computer locations + ubicacions de l'ordinador + + + Computer location attribute + Atribut de la ubicació de l'ordinador + + + Location name attribute + Atribut del nom de la ubicació + + + users + usuaris + + + user groups + grups d'usuaris + + + computers + ordinadors + + + computer groups + grups d'ordinador + + + computer containers + contenidors d'ordinador + + + groups of user + grups d'usuari + + + User not found + No s'ha trobat l'usuari + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + No s'ha pogut trobar un usuari amb el nom «%1». Comproveu el nom d'usuari o el paràmetre de l'arbre d'usuaris. + + + groups of computer + grups d'ordinador + + + Computer not found + No s'ha trobat l'ordinador + + + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + No s'ha pogut trobar un ordinador amb el nom d'amfitrió «%1». Comproveu el nom del servidor o el paràmetre de l'arbre de l'ordinador. + + + Hostname lookup failed + Ha fallat la cerca del nom d'amfitrió + + + Could not lookup hostname for IP address %1. Please check your DNS server settings. + No s'ha pogut cercar el nom de l'amfitrió per a l'adreça IP per cent1. Comproveu la configuració del servidor DNS. + + + location entries + entrades de la ubicació + + + Computer groups filter + Filtre de grups d'ordinador + + + Computer locations identification + Identificació de les ubicacions de l'ordinador + + + Filter for computer groups + Filtra per grups d'ordinador + + + Invalid test value + Valor de prova no vàlid + + + An empty or invalid value has been supplied for this test. + S'ha proporcionat un valor buit o no vàlid per a aquesta prova. + + + LDAP %1 test failed + Ha fallat la prova LDAP %1 + + + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + No s'ha pogut consultar cap entrada a la configuració %1. Comproveu el paràmetre «%2». + +3% + + + LDAP %1 test successful + Prova LDAP %1 correcta + + + The %1 has been queried successfully and %2 entries were found. + S'ha consultat amb èxit %1 i s'han trobat %2 entrades. + + + LDAP test failed + Ha fallat la prova LDAP + + + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + No s'ha pogut consultar cap %1. Comproveu els paràmetres %2 i introduïu el nom d'un objecte existent. + +3% + + + and + i + + + LDAP test successful + Prova LDAP correcta + + + %1 %2 have been queried successfully: + +%3 + S'ha preguntat amb èxit %1 %2: + +3% + + + LDAP filter test failed + Ha fallat la prova del filtre LDAP + + + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 + No s'ha pogut consultar %1 utilitzant el filtre configurat. Comproveu el filtre LDAP per a %1. + +2% + + + LDAP filter test successful + Prova de filtre LDAP correcta + + + %1 %2 have been queried successfully using the configured filter. + S'ha consultat correctament 1% 2% utilitzant el filtre configurat. + + + LDAP directory + Directori LDAP + + + + LdapConfigurationPage + + Basic settings + Paràmetres bàsics + + + General + General + + + LDAP server and port + Servidor LDAP i port + + + Bind DN + Enllaça DN + + + Bind password + Contrasenya d'enllaç + + + Anonymous bind + Anònim + + + Use bind credentials + Utilitza les credencials d'enllaç + + + Base DN + DN base + + + Fixed base DN + DN base fixa + + + e.g. dc=example,dc=org + p. ex. dc=example,dc=org + + + Discover base DN by naming context + DN base del Discover nomenant context + + + e.g. namingContexts or defaultNamingContext + p. ex. nomsContexts o defaultNamingContext + + + Environment settings + Configuració de l'entorn + + + Object trees + Objectes + + + Computer tree + Arbre de l'ordinador + + + e.g. OU=Groups + p. ex. OU=Groups + + + User tree + Arbre d'usuari + + + e.g. OU=Users + p. ex. OU=Users + + + e.g. OU=Computers + p. ex. OU=Computers + + + Group tree + Arbre de grups + + + Perform recursive search operations in object trees + Realitza operacions de cerca recursiva en arbres d'objectes + + + Object attributes + Atributs de l'objecte + + + e.g. hwAddress + p. ex. hwAddress + + + e.g. member or memberUid + p. ex. membre o membreUid + + + e.g. dNSHostName + p. ex. dNSHostName + + + Computer MAC address attribute + L'atribut d'adreça MAC de l'ordinador + + + Group member attribute + Atribut del membre del grup + + + e.g. uid or sAMAccountName + p. ex. uid o sAMAccountName + + + Advanced settings + Paràmetres avançats + + + Optional object filters + Filtres d'objectes opcionals + + + Filter for user groups + Filtra per grups d'usuaris + + + Filter for users + Filtra per usuaris + + + Filter for computer groups + Filtra per grups d'ordinador + + + Group member identification + Identificació dels membres del grup + + + Distinguished name (Samba/AD) + Nom distingit (Samba/AD) + + + List all groups of a user + Llista tots els grups d'un usuari + + + List all groups of a computer + Llista tots els grups d'un ordinador + + + Get computer object by IP address + Obté l'objecte d'ordinador per adreça IP + + + Enter username + Introduïu el nom d'usuari + + + Please enter a user login name (wildcards allowed) which to query: + Introduïu un nom d'usuari (es permeten els comodins) que voleu consultar: + + + Enter group name + Introduïu el nom del grup + + + Please enter a group name whose members to query: + Introduïu un nom de grup els membres del qual han de consultar: + + + Enter computer name + Introduïu el nom de l'ordinador + + + Enter computer DN + Introduïu el DN de l'ordinador + + + Please enter the DN of a computer whose MAC address to query: + Introduïu el DN d'un ordinador l'adreça MAC del qual s'ha de consultar: + + + Please enter a user login name whose group memberships to query: + Introduïu un nom d'usuari d'inici de sessió els membres del grup del qual consultaran: + + + Enter computer IP address + Introduïu l'adreça IP de l'ordinador + + + Please enter a computer IP address which to resolve to an computer object: + Introduïu una adreça IP de l'ordinador que s'ha de resoldre a un objecte de l'ordinador: + + + (only if different from group tree) + (només si és diferent de l'arbre de grups) + + + Computer group tree + Arbre de grups de l'ordinador + + + Filter for computers + Filtra per ordinadors + + + e.g. room or computerLab + p. ex. sala o ordinadorLab + + + Integration tests + Proves d'integració + + + Computer groups + Grups d'ordinador + + + e.g. name or description + p. ex. nom o descripció + + + Filter for computer containers + Filtra per contenidors d'ordinador + + + Computer containers or OUs + Contenidors d'ordinador o OU + + + Connection security + Seguretat de la connexió + + + TLS certificate verification + Verificació del certificat TLS + + + System defaults + Valors predeterminats del sistema + + + Never (insecure!) + Mai (insegur!) + + + Custom CA certificate file + Fitxer de certificat CA personalitzat + + + None + Cap + + + TLS + TLS + + + SSL + SSL + + + e.g. (objectClass=computer) + p. ex. (objectClass=computer) + + + e.g. (objectClass=group) + p. ex. (objectClass=group) + + + e.g. (objectClass=person) + p. ex. (objectClass=persona) + + + e.g. (objectClass=room) or (objectClass=computerLab) + p. ex. (objectClass=room) o (objectClass=computerLab) + + + e.g. (objectClass=container) or (objectClass=organizationalUnit) + p. ex. (objectClass=container) o (objectClass=organizationalUnit) + + + Certificate files (*.pem) + Fitxers de certificat (*.pem) + + + Encryption protocol + Protocol de xifratge + + + Computer location attribute + Atribut de la ubicació de l'ordinador + + + Computer display name attribute + L'atribut nom de la pantalla de l'ordinador + + + Location name attribute + Atribut del nom de la ubicació + + + e.g. cn or displayName + p. ex. cn o displayName + + + Computer locations identification + Identificació de les ubicacions de l'ordinador + + + Identify computer locations (e.g. rooms) via: + Identifica les ubicacions dels ordinadors (per exemple, les sales) a través de: + + + Location attribute in computer objects + L'atribut de localització en objectes d'ordinador + + + List all entries of a location + Llista totes les entrades d'una ubicació + + + List all locations + Llista totes les ubicacions + + + Enter computer display name + Introduïu el nom de la pantalla de l'ordinador + + + Please enter a computer display name to query: + Introduïu un nom per a la visualització de l'ordinador a consultar: + + + Enter computer location name + Introduïu el nom de la ubicació de l'ordinador + + + Please enter the name of a computer location (wildcards allowed): + Introduïu el nom d'una ubicació de l'ordinador (es permeten comodins): + + + Enter location name + Introduïu el nom de la ubicació + + + Please enter the name of a location whose entries to query: + Introduïu el nom d'una ubicació les entrades de la qual s'han de consultar: + + + Browse + Navega + + + Test + Comprova + + + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Noms d'amfitrió emmagatzemats com a noms de domini plenament qualificats (FQDN, p. ex. myhost.example.org) + + + Computer hostname attribute + L'atribut de nom de l'ordinador + + + Please enter a computer hostname to query: + Introduïu un nom d'amfitrió per a consultar: + + + Enter hostname + Introduïu el nom de l'amfitrió + + + Please enter a computer hostname whose group memberships to query: + Introduïu un nom d'amfitrió de l'ordinador les afiliacions del grup del qual consultar: + + + User login name attribute + L'atribut nom d'usuari + + + Configured attribute for user login name or computer hostname (OpenLDAP) + Atribut configurat per a l'usuari nom d'usuari o nom de l'ordinador (OpenLDAP) + + + Directory name + Nom del directori + + + Query options + Opcions de consulta + + + Query nested user groups (supported by AD only) + Consulta els grups d'usuaris imbricats (disponible només AD) + + + Query timeout + + + + ms + ms + + + + LdapNetworkObjectDirectoryConfigurationPage + + LDAP + LDAP + + + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + Utilitzeu la pàgina de configuració global LDAP per a configurar com recuperar ubicacions i ordinadors del servei de directori basat en LDAP. + + + + LdapPlugin + + Auto-configure the base DN via naming context + Configura automàticament el DN base mitjançant el context de nomenclatura + + + Query objects from LDAP directory + Consulta objectes del directori LDAP + + + Show help about command + Mostra l'ajuda sobre l'ordre + + + Commands for configuring and testing LDAP/AD integration + Ordres per a configurar i provar la integració LDAP/AD + + + Basic LDAP/AD support for Veyon + Suport bàsic LDAP/AD per a Veyon + + + %1 (load computers and locations from LDAP/AD) + %1 (carrega els ordinadors i les ubicacions des de LDAP/AD) + + + %1 (load users and groups from LDAP/AD) + %1 (carrega usuaris i grups des de LDAP/AD) + + + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Indiqueu un URL LDAP vàlid seguint l'esquema «ldap[s]://[usuar[:contrassenya]@nomamfitrió[:port]» + + + No naming context attribute name given - falling back to configured value. + No s'ha indicat el nom de l'atribut de context de noms - es retorna al valor configurat. + + + Could not query base DN. Please check your LDAP configuration. + No s'ha pogut consultar la base DN. Comproveu la configuració LDAP. + + + Configuring %1 as base DN and disabling naming context queries. + S'està configurant 1% com a base DN i s'estan inhabilitant les consultes de context de nomenclatura. + + + Test binding to an LDAP server + Prova la vinculació a un servidor LDAP + + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + El nom d'usuari o la contrasenya indicats no són correctes. Introduïu credencials vàlides o canvieu a un mètode d'autenticació diferent utilitzant el Configurador de Veyon. + + + LDAP bind + Enllaç LDAP + + + + LinuxPlatformConfigurationPage + + Linux + Linux + + + Custom PAM service for user authentication + Servei PAM personalitzat per a l'autenticació de l'usuari + + + User authentication + Autenticació de l'usuari + + + User sessions + Sessions d'usuari + + + Minimum session lifetime before server start + Durada mínima de la sessió abans de l'inici del servidor + + + User login + Usuari + + + Login key sequence + Seqüència de la clau d'inici de sessió + + + + LinuxPlatformPlugin + + Plugin implementing abstract functions for the Linux platform + Connector implementant funcions abstractes per a la plataforma Linux + + + + LocationDialog + + Select location + Selecciona la ubicació + + + enter search filter... + introduïu un filtre de cerca... + + + + MainToolBar + + Configuration + Configuració + + + Show icons only + Mostra només les icones + + + Disable tooltips + + + + + MainWindow + + MainWindow + Finestra principal + + + toolBar + Barra d'eines + + + General + General + + + &File + &Fitxer + + + &Help + &Ajuda + + + &Quit + &Surt + + + Ctrl+Q + Ctrl+Q + + + Ctrl+S + Ctrl+S + + + L&oad settings from file + &Carrega els ajustaments des d'un fitxer + + + Ctrl+O + Ctrl+O + + + About Qt + Quant a Qt + + + Configuration not writable + No es pot escriure la configuració + + + Load settings from file + Carrega ajustaments des d'un fitxer + + + Save settings to file + Desa els ajustaments en un fitxer + + + Unsaved settings + Ajustaments no desats + + + There are unsaved settings. Quit anyway? + Hi ha ajustaments sense desar. Voleu sortir de totes formes? + + + Veyon Configurator + Configurador de Veyon + + + Service + Servei + + + Master + Mestre + + + Access control + Control d'accés + + + About Veyon + Quant a Veyon + + + Auto + Automàtic + + + About + Quant a + + + %1 Configurator %2 + %1 Configurador 2% + + + JSON files (*.json) + Fitxers JSON (*.json) + + + The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. + El rerefons de configuració local ha informat que no es pot escriure la configuració! Executeu el configurador de %1 amb privilegis més alts. + + + Access denied + Accés denegat + + + According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. + D'acord amb la configuració local, no teniu permís per a accedir als ordinadors de la xarxa. Inicieu sessió amb un compte diferent o deixeu que l'administrador del sistema comprovi la configuració local. + + + Screenshots + Captures de pantalla + + + Feature active + Funció activa + + + The feature "%1" is still active. Please stop it before closing %2. + La característica «%1» encara està activa. Atureu-la abans de tancar %2. + + + Reset configuration + Reinicia la configuració + + + Do you really want to reset the local configuration and revert all settings to their defaults? + Esteu segur que voleu restablir la configuració local i revertir tots els ajustaments als seus valors predeterminats? + + + Search users and computers + Cerca usuaris i ordinadors + + + Align computers to grid + Alinea els ordinadors a la graella + + + %1 Configurator + Configurador %1 + + + Insufficient privileges + Privilegis insuficients + + + Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + No s'ha pogut iniciar amb els privilegis administratius. Assegureu-vos que hi ha instal·lat un programa semblant a sudo per al vostre entorn d'escriptori! El programa s'executarà amb privilegis d'usuari normals. + + + Only show powered on computers + Mostra només els ordinadors engegats + + + &Save settings to file + De&sa els ajustaments al fitxer + + + &View + &Visualitza + + + &Standard + E&stàndard + + + &Advanced + &Avançat + + + Use custom computer arrangement + Utilitza l'arranjament personalitzat de l'ordinador + + + Locations && computers + Ubicacions i ordinadors + + + Authentication + Autentificació + + + Adjust size of computer icons automatically + Ajusta la mida de les icones de l'ordinador automàticament + + + Slideshow + Presentació + + + Spotlight + Focus + + + Veyon Master + + + + Locations & computers + Ubicacions i ordinadors + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + Mostra només els ordinadors amb usuaris connectats + + + Load computer positions + + + + Save computer positions + + + + + MasterConfigurationPage + + Directories + Directoris + + + User configuration + Configuració de l'usuari + + + Feature on computer double click: + Característica en fer doble clic a l'ordinador: + + + Features + Característiques + + + All features + Totes les característiques + + + Disabled features + Característiques desactivades + + + Screenshots + Captures de pantalla + + + <no feature> + <no feature> + + + Basic settings + Paràmetres bàsics + + + Behaviour + Comportament + + + Enforce selected mode for client computers + Força el mode seleccionat per als ordinadors de client + + + Hide local computer + Oculta l'ordinador local + + + Hide computer filter field + Oculta el camp de filtre de l'ordinador + + + Actions such as rebooting or powering down computers + Accions com ara reiniciar o apagar ordinadors + + + User interface + Interfície d'usuari + + + Background color + Color del fons + + + Thumbnail update interval + Interval d'actualització de les miniatures + + + ms + ms + + + Program start + Inici del programa + + + Modes and features + Modes i característiques + + + User and computer name + Nom d'usuari i ordinador + + + Only user name + Només nom d'usuari + + + Only last part of user name + + + + Only computer name + Només nom de l'ordinador + + + Computer thumbnail caption + Títol de la miniatura de l'ordinador + + + Text color + Color del text + + + Sort order + Ordenació + + + Computer and user name + Nom de l'ordinador i l'usuari + + + Computer locations + Ubicacions de l'ordinador + + + Show current location only + Mostra només la ubicació actual + + + Allow adding hidden locations manually + Permet afegir ubicacions ocultes manualment + + + Hide empty locations + Oculta les ubicacions buides + + + Show confirmation dialog for potentially unsafe actions + Mostra el diàleg de confirmació per a accions potencialment insegures + + + Perform access control + Control d'accés + + + Automatically select current location + Selecciona automàticament la ubicació actual + + + Automatically open computer select panel + Obre automàticament el tauler de selecció de l'ordinador + + + Use modern user interface (experimental) + Utilitza la interfície d'usuari moderna (experimental) + + + Thumbnail spacing + Espaiat de les miniatures + + + px + px + + + Hide local session + Oculta la sessió local + + + Auto + Automàtic + + + Thumbnail aspect ratio + Relació d'aspecte de la miniatura + + + Automatically adjust computer icon size + Ajusta automàticament la mida de la icona de l'ordinador + + + Open feature windows on the same screen as the main window + Obre les finestres de les característiques a la mateixa pantalla que la finestra principal + + + Configuration templates + + + + Image quality in monitoring mode + + + + Highest + + + + High + + + + Medium + + + + Low + + + + Lowest + + + + Remote access image quality + + + + Advanced + + + + Computer name source + + + + Default + + + + Host address + Adreça de l'amfitrió + + + Session client address + + + + Session client name + + + + Session host name + + + + Session metadata + + + + Full name of user + + + + User login name + + + + Computer UID role + + + + Session meta data hash + + + + Always expand all locations + + + + Image quality + + + + + MonitoringMode + + Monitoring + Monitoratge + + + Builtin monitoring mode + Mode de monitoratge integrat + + + This mode allows you to monitor all computers at one or more locations. + Aquest mode us permet controlar tots els ordinadors en una o més ubicacions. + + + Query application version of the server + + + + Query active features + + + + Query properties of remotely available screens + + + + + NestedNetworkObjectDirectory + + All directories + Tots els directoris + + + + NetworkObjectDirectoryConfigurationPage + + Update interval: + Interval d'actualització: + + + seconds + segonds + + + + NetworkObjectDirectoryConfigurationPageTab + + Enabled + Activat + + + + NetworkObjectTreeModel + + Locations/Computers + Ubicacions/ordinadors + + + + OpenWebsiteDialog + + Open website + Obre el lloc web + + + e.g. Veyon + p. ex. Veyon + + + Remember and add to website menu + Recorda i afegeix al menú del lloc web + + + e.g. www.veyon.io + p. ex. www.veyon.io + + + Please enter the URL of the website to open: + Introduïu l'URL del lloc web a obrir: + + + Name: + Nom: + + + Website name + + + + + PluginCommands + + List names of all installed plugins + Llista els noms de tots els connectors instal·lats + + + Show table with details of all installed plugins + Mostra la taula amb els detalls de tots els connectors instal·lats + + + Name + Nom + + + Description + Descripció + + + Version + Versió + + + UID + UID + + + Plugin-related CLI operations + Operacions de l'CLI relacionades amb els connectors + + + Commands for managing plugins + Ordres per a gestionar connectors + + + + PowerControlFeaturePlugin + + Power on + Engega + + + Click this button to power on all computers. This way you do not have to power on each computer by hand. + Feu clic en aquest botó per a activar tots els ordinadors. D'aquesta manera no cal engegar cada ordinador a mà. + + + Reboot + Reinicia + + + Click this button to reboot all computers. + Feu clic en aquest botó per a reiniciar tots els ordinadors. + + + Power down + Apaga + + + Click this button to power down all computers. This way you do not have to power down each computer by hand. + Feu clic en aquest botó per activar tots els ordinadors. D'aquesta manera no cal apagar cada ordinador a mà. + + + Power on/down or reboot a computer + Engega, apaga o reinicia un ordinador + + + Confirm reboot + Confirma el reinici + + + Confirm power down + Confirma l'apagada + + + Do you really want to reboot the selected computers? + Esteu segur que voleu reiniciar els ordinadors seleccionats? + + + Power on a computer via Wake-on-LAN (WOL) + Engega un ordinador via Wake-on-LAN (WOL) + + + MAC ADDRESS + ADREÇA MAC + + + This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. + Aquesta ordre emet un paquet Wake-on-LAN (WOL) a la xarxa per tal d'engegar l'ordinador amb l'adreça MAC indicada. + + + Please specify the command to display help for! + Indiqueu l'ordre per a la qual es mostrarà l'ajuda! + + + Invalid MAC address specified! + S'ha indicat una adreça MAC no vàlida! + + + Commands for controlling power status of computers + Ordres per a controlar l'estat d'energia dels ordinadors + + + Power down now + Apaga ara + + + Install updates and power down + Instal·la les actualitzacions i apaga + + + Power down after user confirmation + Apaga després de la confirmació de l'usuari + + + Power down after timeout + Apaga després del temps d'espera + + + The computer was remotely requested to power down. Do you want to power down the computer now? + Ja s'ha demanat a l'ordinador que s'apagui remotament. Voleu apagar l'ordinador ara? + + + The computer will be powered down in %1 minutes, %2 seconds. + +Please save your work and close all programs. + L'ordinador s'apagarà en %1 minuts, %2 segons. + +Deseu el vostre treball i tanqueu tots els programes. + + + Do you really want to reboot <b>ALL</b> computers? + Esteu segur que voleu reiniciar <b>TOTS</b> els ordinadors? + + + Do you really want to power down <b>ALL</b> computers? + Esteu segur que voleu engegar <b>TOTS</b> els ordinadors? + + + Do you really want to power down the selected computers? + Esteu segur que voleu apagar els ordinadors seleccionats? + + + + PowerDownTimeInputDialog + + Power down + Apaga + + + Please specify a timeout for powering down the selected computers: + Indiqueu un temps d'espera per a apagar els ordinadors seleccionats: + + + minutes + minuts + + + seconds + segons + + + + RemoteAccessFeaturePlugin + + Remote view + Visualització remota + + + Open a remote view for a computer without interaction. + Obre una visualització remota per a un ordinador sense interacció. + + + Remote control + Control remot + + + Open a remote control window for a computer. + Obre una finestra de control remot per a un ordinador. + + + Remote access + Accés remot + + + Remote view or control a computer + Visualització remota o control remot a un ordinador + + + Show help about command + Mostra l'ajuda sobre l'ordre + + + Exchange clipboard contents + + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + + + RemoteAccessPage + + Remote access: %1 + + + + + RemoteAccessWidget + + %1 - %2 Remote Access + Accés remot %1 -%2 + + + %1 - %2 - %3 Remote Access + Accés remot %1 -%2 - 3% + + + + RemoteAccessWidgetToolBar + + View only + Només veure + + + Remote control + Control remot + + + Send shortcut + Envia la drecera + + + Fullscreen + Pantalla completa + + + Window + Finestra + + + Ctrl+Alt+Del + Ctrl+Alt+Supr + + + Ctrl+Esc + Ctrl+Esc + + + Alt+Tab + Alt+Tab + + + Alt+F4 + Alt+F4 + + + Win+Tab + Win+Tab + + + Win + Win + + + Menu + Menú + + + Alt+Ctrl+F1 + Alt+Ctrl+F1 + + + Connected. + Connectat. + + + Screenshot + Captura + + + Exit + Surt + + + Connecting... + S'està connectant... + + + Select screen + + + + All screens + Totes les pantalles + + + + ScreenLockFeaturePlugin + + Lock + Bloca + + + Unlock + Desbloca + + + Lock screen and input devices of a computer + Bloca la pantalla i els dispositius d'entrada d'un ordinador + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + Per a reclamar tota l'atenció de l'usuari podeu blocar-li els ordinadors utilitzant aquest botó. En aquest mode es bloquen tots els dispositius d'entrada i les pantalles es posen en negre. + + + Lock input devices + Bloca els dispositius d'entrada + + + Unlock input devices + Desbloca els dispositius d'entrada + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + Per a reclamar tota l'atenció de l'usuari podeu blocar-li els ordinadors utilitzant aquest botó. En aquest mode es bloquen tots els dispositius d'entrada mentre l'escriptori encara és visible. + + + + Screenshot + + unknown + desconegut + + + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + No s'ha pogut prendre una captura de pantalla, ja que el directori %1 no existeix i no s'ha pogut crear. + + + Screenshot + Captura + + + Could not open screenshot file %1 for writing. + No s'ha pogut obrir el fitxer de captura de pantalla %1 en mode l'escriptura. + + + + ScreenshotFeaturePlugin + + Screenshot + Captura + + + Use this function to take a screenshot of selected computers. + Utilitzeu aquesta funció per a fer una captura de pantalla dels ordinadors seleccionats. + + + Screenshots taken + Captures de pantalla + + + Screenshot of %1 computer have been taken successfully. + La captura de pantalla de l'ordinador %1 s'ha fet correctament. + + + Take screenshots of computers and save them locally. + Fa captures de pantalla dels ordinadors i les desa localment. + + + + ScreenshotManagementPage + + Screenshots + Captures de pantalla + + + + ScreenshotManagementPanel + + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + Aquí es llisten totes les captures de pantalla que heu fet. Podeu fer captures de pantalla fent clic a l'element «Captura de pantalla» del menú contextual d'un ordinador. Les captures de pantalla es poden gestionar utilitzant els botons següents. + + + User: + Usuari: + + + Computer: + Ordinador: + + + Date: + Data: + + + Time: + Hora: + + + Show + Mostra + + + Delete + Suprimeix + + + Screenshot + Captura + + + Do you really want to delete all selected screenshots? + Esteu segur que voleu suprimir totes les captures de pantalla seleccionades? + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + + + + User has denied access + + + + User confirmed access + + + + + ServiceConfigurationPage + + General + General + + + Autostart + Inici automàtic + + + Hide tray icon + Oculta la icona de la barra del sistema + + + Start service + Inicia el servei + + + Stopped + Aturat + + + Stop service + Atura el servei + + + State: + Estat: + + + Enable firewall exception + Activa una excepció en el tallafocs + + + Allow connections from localhost only + Permet connexions només des d'aquest equip + + + VNC server + Servidor VNC + + + Plugin: + Connector: + + + Restart %1 Service + Reinicia el servei %1 + + + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + Tots els ajustaments s'han desat correctament. Per a poder fer-ho efectiu, cal reiniciar el servei %1. Voleu reiniciar-la ara? + + + Running + Funcionant + + + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. + Si activeu aquesta opció, el servei iniciarà un procés de servidor per a cada sessió interactiva en un ordinador. +Normalment es requereix per a donar suport als servidors de terminals. + + + Show notification on remote connection + Mostra la notificació a la connexió remota + + + Show notification when an unauthorized access is blocked + Mostra la notificació quan es bloca un accés no autoritzat + + + Maximum session count + Nombre màxim de sessions + + + Network port numbers + Números del port de la xarxa + + + Veyon server + Servidor Veyon + + + Internal VNC server + Servidor VNC intern + + + Feature manager + Gestor de característiques + + + Demo server + Servidor de demostració + + + Miscellaneous network settings + Paràmetres de xarxa diversos + + + Session mode + Mode de sessió + + + Local session mode (single server instance for primary local session) + Mode de sessió local (instància única del servidor per a la sessió local primària) + + + Active session mode (single server instance for active local or remote session) + Mode de sessió activa (instància única del servidor per a la sessió activa local o remota) + + + Multi session mode (distinct server instance for each local and remote desktop session) + Mode de sessió múltiple (instàncies del servidor diferents per a cada sessió d'escriptori local i remot) + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + + + + Miscellaneous settings + + + + Disable clipboard synchronization + + + + Session metadata + + + + Content + + + + None + Cap + + + Value of an environment variable + + + + Value of a registry key + + + + Environment variable name: + + + + Registry key name: + + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + + + + + ServiceControl + + Service control + Control del servei + + + Starting %1 + + + + Stopping %1 + + + + Restarting %1 + + + + Registering %1 + + + + Unregistering %1 + + + + + ServiceControlCommands + + Register Veyon Service + Registre del servei Veyon + + + Unregister Veyon Service + Desregistrament del servei Veyon + + + Start Veyon Service + Inicia el servei Veyon + + + Stop Veyon Service + Atura el servei Veyon + + + Restart Veyon Service + Reinicia el servei Veyon + + + Query status of Veyon Service + Consulta l'estat del servei Veyon + + + Service is running + El servei s'està executant + + + Service is not running + El servei no s'està executant + + + Configure and control Veyon service + Configura i controla el servei Veyon + + + Commands for configuring and controlling Veyon Service + Ordres per a configurar i controlar el servei Veyon + + + + ShellCommands + + Run command file + Executa el fitxer d'ordres + + + File "%1" does not exist! + El fitxer «%1» no existeix! + + + Interactive shell and script execution for Veyon CLI + Execució interactiva de shell i script per a Veyon CLI + + + Commands for shell functionalities + Ordres per a les funcionalitats del shell + + + + SlideshowPanel + + Previous + Anterior + + + Start/pause + Inicia/pausa + + + Next + Endavant + + + Duration: + Duració: + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + Afegeix els ordinadors seleccionats + + + Remove selected computers + Suprimeix els ordinadors seleccionats + + + Update computers in realtime + Actualitza els ordinadors en temps real + + + Spotlight + Focus + + + Please select at least one computer to add. + Seleccioneu almenys un ordinador per a afegir-lo. + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + Afegiu ordinadors fent clic amb el botó central del ratolí o fent clic al primer botó de sota. +El segon botó elimina l'ordinador seleccionat o l'últim. + + + + StartAppDialog + + Start application + Inicia l'aplicació + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + Introduïu les aplicacions que voleu iniciar en els ordinadors seleccionats. Podeu separar múltiples aplicacions per línies. + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + p. ex. «C:\Program Files\VideoLAN\VLC\vlc.exe» + + + Remember and add to application menu + Recorda i afegeix al menú de l'aplicació + + + Application name + + + + Name: + Nom: + + + e.g. VLC + p. ex. VLC + + + + SystemTrayIcon + + System tray icon + Icona de la safata del sistema + + + + SystemUserGroupsPlugin + + User groups backend for system user groups + Rerefons de grups d'usuari per a grups d'usuaris del sistema + + + Default (system user groups) + Per defecte (grups d'usuaris del sistema) + + + + TestingCommandLinePlugin + + Test internal Veyon components and functions + Prova els components i funcions interns de Veyon + + + Commands for testing internal components and functions of Veyon + Ordres per a provar components i funcions interns de Veyon + + + + TextMessageDialog + + Send text message + Envia un missatge de text + + + Please enter your message which send to all selected users. + Introduïu el missatge que s'enviarà a tots els usuaris seleccionats. + + + + TextMessageFeaturePlugin + + Text message + Missatge de text + + + Use this function to send a text message to all users e.g. to assign them new tasks. + Utilitzeu aquesta funció per a enviar un missatge de text a tots els usuaris p. ex. per assignar-los tasques noves. + + + Message from teacher + Missatge del professor + + + Send a message to a user + Envia un missatge a un usuari + + + + UltraVncConfigurationWidget + + Enable capturing of layered (semi-transparent) windows + Habilita la captura de finestres apilades (semitransparents) + + + Poll full screen (leave this enabled per default) + Monitora tota la pantalla (deixa activat per defecte) + + + Low accuracy (turbo mode) + Baixa precisió (mode turbo) + + + Builtin UltraVNC server configuration + Configuració del servidor UltraVNC integrat + + + Enable multi monitor support + Habilita el suport per a monitors múltiples + + + Enable Desktop Duplication Engine on Windows 8 and newer + Habilita el motor de duplicació de l'escriptori al Windows 8 i posterior + + + Maximum CPU usage + Ús màxim de la CPU + + + + UserLoginDialog + + User login + Inici de sessió de l'usuari + + + Please enter a username and password for automatic login on all computers. + Introduïu un nom d'usuari i una contrasenya per a l'inici de sessió automàtic en tots els ordinadors. + + + Username + Nom d'usuari + + + Password + Contrasenya + + + + UserSessionControlPlugin + + Log in + Inicia la sessió + + + Click this button to log in a specific user on all computers. + Feu clic en aquest botó per a iniciar sessió en un usuari específic de tots els ordinadors. + + + Log off + Tanca la sessió + + + Click this button to log off users from all computers. + Feu clic en aquest botó per a tancar la sessió als usuaris de tots els ordinadors. + + + Confirm user logoff + Confirma la sortida de l'usuari + + + Do you really want to log off the selected users? + Esteu segur que voleu tancar la sessió als usuaris seleccionats? + + + User session control + Control de sessió d'usuari + + + Do you really want to log off <b>ALL</b> users? + Esteu segur que voleu tancar la sessió a <b>TOTS</b> els usuaris? + + + + VeyonCore + + [OK] + [OK] + + + [FAIL] + [FALLADA] + + + Invalid command! + L'ordre no és vàlida! + + + Available commands: + Ordres disponibles: + + + Invalid arguments given + S'han donat arguments no vàlids + + + Not enough arguments given - use "%1 help" for more information + No s'han donat prou arguments - useu «%1 help» per a més informació + + + Unknown result! + Resultat desconegut! + + + Available modules: + Mòduls disponibles: + + + No module specified or module not found - available modules are: + No s'ha indicat cap mòdul o no s'ha trobat - els mòduls disponibles són: + + + Plugin not licensed + Connector sense llicència + + + INFO + INFORMACIÓ + + + ERROR + ERROR + + + USAGE + ÚS + + + DESCRIPTION + DESCRIPCIÓ + + + EXAMPLES + EXEMPLES + + + WARNING + AVÍS + + + Authentication test + Prova d'autenticació + + + Screen %1 + + + + + VeyonMaster + + No write access + Sense permís d'escriptura + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + No s'ha pogut desar la vostra configuració personal! Comproveu el camí del fitxer de configuració de l'usuari utilitzant el configurador de %1. + + + + VeyonServiceControl + + Veyon Service + Servei Veyon + + + + WindowsPlatformConfiguration + + Could not change the setting for SAS generation by software. Sending Ctrl+Alt+Del via remote control will not work! + No s'ha pogut canviar la configuració de la generació SAS per programari. L'enviament de Ctrl+Alt+Supr a través del control remot no funcionarà! + + + + WindowsPlatformConfigurationPage + + Windows + Windows + + + General + General + + + Enable SAS generation by software (Ctrl+Alt+Del) + Habilita la generació de SAS per programari (Ctrl+Alt+Del) + + + Screen lock + Bloqueig de la pantalla + + + Hide taskbar + Oculta la barra de tasques + + + Hide start menu + Oculta el menú d'inici + + + Hide desktop + Oculta l'escriptori + + + User authentication + Autenticació de l'usuari + + + Use alternative user authentication mechanism + Usa un mecanisme alternatiu d'autenticació d'usuari + + + User login + Inici de sesisó de l'usuari + + + Input start delay + Retard d'inici de l'entrada + + + Simulated key presses interval + Interval de pulsació de tecles simulades + + + Confirm legal notice (message displayed before user logs in) + Avís legal de confirmació (missatge que es mostra abans que l'usuari iniciï sessió) + + + Use input device interception driver + Utilitza el controlador d'intercepció del dispositiu d'entrada + + + Use custom power scheme with disabled power button + + + + + WindowsPlatformPlugin + + Plugin implementing abstract functions for the Windows platform + Connector implementant funcions abstractes per a la plataforma Windows + + + Internal display + + + + + WindowsServiceControl + + The service "%1" is already installed. + El servei «%1» ja està instal·lat. + + + The service "%1" has been installed successfully. + El servei «%1» s'ha instal·lat correctament. + + + The service "%1" has been uninstalled successfully. + El servei «%1» s'ha desinstal·lat correctament. + + + Service "%1" could not be found. + No s'ha trobat el servei «%1». + + + The service "%1" could not be installed (error %2). + No s'ha pogut instal·lar el servei «%1» (error %2). + + + Could not change the failure actions config for service "%1" (error %2). + No s'ha pogut canviar la configuració de les accions de fallada del servei «%1» (error %2). + + + The service "%1" could not be uninstalled (error %2). + No s'ha pogut desintal·lar el servei «%1» (error%2). + + + The start type of service "%1" could not be changed (error %2). + No s'ha pogut canviar el tipus d'inici del servei «%1» (error %2). + + + + X11VncConfigurationWidget + + Builtin x11vnc server configuration + Configuració del servidor x11vnc integrat + + + Custom x11vnc parameters: + Paràmetres personalitzats de x11vnc: + + + Do not use X Damage extension + No utilitzis l'extensió X Damage + + + \ No newline at end of file diff --git a/translations/cs.ts b/translations/veyon_cs.ts similarity index 77% rename from translations/cs.ts rename to translations/veyon_cs.ts index 17c722de8..e0d6138f2 100644 --- a/translations/cs.ts +++ b/translations/veyon_cs.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -80,10 +80,6 @@ Pokud ale překlad není kompletní a nebo by potřeboval vylepšit, případně All groups Všechny skupiny - - ... - - Access control rules Pravidla řízení přístupu @@ -140,19 +136,18 @@ Pokud ale překlad není kompletní a nebo by potřeboval vylepšit, případně User groups backend: Podpůrná vrstva uživatelských skupin: - - Missing user groups backend - Chybí podpůrná vrstva uživatelských skupin - - - No default user groups plugin was found. Please check your installation! - Nebyl nalezen žádný výchozí zásuvný modul uživatelských skupin. Zkontrolujte svou instalaci! - Restrict access to members of specific user groups Omezit přístup na členy konkrétních skupin uživatelů + + AccessControlProvider + + Provider for access control features + + + AccessControlRuleEditDialog @@ -179,30 +174,10 @@ Pokud ale překlad není kompletní a nebo by potřeboval vylepšit, případně Rule description: Popis pravidla: - - Invert all conditions ("is/has" interpreted as "is/has not") - Převrátit všechny podmínky („je/má“ si vykládat jako není/nemá) - Conditions Podmínky - - is member of group - je členem skupiny - - - Accessing computer is localhost - Přistupující počítač přistupuje sám na sebe - - - Accessing user is logged on user - Přistupující uživatel přistupuje sám na sebe - - - Accessing user is already connected - Přistupující uživatel je už připojený - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. Pokud je zapnutá více než jedna, pak aby se pravidlo uplatnilo je třeba, aby byly splněné všechny podmínky (logické A). Pokud postačí splnit pouze jednu z daných podmínek (logické NEBO) vytvořte pravidlo řízení přístupu pro každou zvlášť. @@ -236,33 +211,125 @@ Pokud ale překlad není kompletní a nebo by potřeboval vylepšit, případně Přistupující počítač - Local (logged on) user - Uživatel na tomto počítači (právě přihlášený) + Always process rule and ignore conditions + Ignorovat podmínky a pravidlo zpracovat vždy - Local computer - Tento počítač + Accessing computer and local computer + - Always process rule and ignore conditions - Ignorovat podmínky a pravidlo zpracovat vždy + User being accessed + - No user logged on - Není přihlášený žádný uživatel + is logged in locally + + + + is logged in remotely + + + + No user is logged in locally + + + + One or multiple users are logged in locally + - Accessing user has one or more groups in common with local (logged on) user - Přistupující uživatel má jednu nebo více skupin společných s uživatelem, který je právě přihlášený k počítači + No user is logged in remotely + - Accessing computer and local computer are at the same location - Přistupující počítač a tento počítač se nacházejí ve stejném umístění + One or multiple users are logged in remotely + is located at se nachází v + + is not located at + + + + are located at the same location + + + + are not located the same location + + + + is member of group + je členem skupiny + + + is not member of group + + + + is authenticated via + + + + is not authenticated via + + + + has one or more groups in common with user being accessed + + + + has no groups in common with user being accessed + + + + equals user being accessed + + + + is different from user being accessed + + + + is already connected + + + + is not connected + + + + is local computer + + + + is not local computer + + + + Computer being accessed + + + + Session being accessed is a user session + + + + Session being accessed is a login screen + + + + Local computer is already being accessed + + + + Local computer is not yet being accessed + + AccessControlRulesTestDialog @@ -306,42 +373,44 @@ Pokud ale překlad není kompletní a nebo by potřeboval vylepšit, případně The access in the given scenario needs permission of the logged on user. Přístup v zadaném scénáři vyžaduje svolení od přihlášeného uživatele. - - ERROR: Unknown action - CHYBA: neznámá akce - Test result Výsledek zkoušky fungování - - - AndroidPlatformConfigurationPage - Android + Authentication method - General - Obecné + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + Úvod - - - AuthKeysConfigurationPage - Authentication keys - Ověřovací klíče + Please perform the following steps to set up key file authentication: + Pro nastavení ověřování souborem s klíčem proveďte následující kroky: - Introduction - Úvod + 1) Create a key pair on the master computer. + 1) Vytvořte dvojici klíčů na řídícím počítači. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Nastavte přístupovou skupinu jejíž členům by mělo být umožněno přistupovat k ostatním počítačům. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Exportujte veřejnou část klíče a importujte ji na všechny klientské počítače pod stejným názvem. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Nahlédněte do <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Příručky správy Veyon</a> pro další informace. Key file directories @@ -355,14 +424,20 @@ Pokud ale překlad není kompletní a nebo by potřeboval vylepšit, případně Private key file base directory Základní složka pro soukromou část klíče - - ... - - Available authentication keys Ověřovací klíče k dispozici + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Dvojice ověřovacích klíčů je tvořena propojovacími šifrovacími klíči, soukromým a veřejným. +Soukromá část umožňuje uživatelům na hlavním počítači přistupovat ke klientským počítačům. +Je důležité aby pouze pověření uživatelé mohli číst soubor se soukromou částí klíče. +Veřejná část je použita na klientských počítačích pro ověření příchozího požadavku na připojení. + Create key pair Vytvořit dvojici klíčů @@ -403,10 +478,6 @@ Pokud ale překlad není kompletní a nebo by potřeboval vylepšit, případně Please select a key to delete! Vyberte klíč, který chcete smazat! - - Please enter the name of the user group or role for which to import the authentication key: - Zadejte název uživatelské skupiny nebo role pro kterou chcete importovat ověřovací klíč: - Please select a key to export! Vyberte klíč který chcete exportovat! @@ -420,34 +491,10 @@ Pokud ale překlad není kompletní a nebo by potřeboval vylepšit, případně Vyberte klíč pro který nastavit přístupovou skupinu! - Please perform the following steps to set up key file authentication: - Pro nastavení ověřování souborem s klíčem proveďte následující kroky: - - - 1) Create a key pair on the master computer. - 1) Vytvořte dvojici klíčů na řídícím počítači. - - - 2) Set an access group whose members should be allowed to access other computers. - 2( Nastavte přístupovou skupinu jejíž členům by mělo být umožněno přistupovat k ostatním počítačům. - - - 3) Export the public key and import it on all client computers with the same name. - 3) Exportujte veřejnou část klíče a importujte ji na všechny klientské počítače pod stejným názvem. - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - Nahlédněte do <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Příručky správy Veyon</a> pro další informace. - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - Dvojice ověřovacích klíčů je tvořena propojovacími šifrovacími klíči, soukromým a veřejným. -Soukromá část umožňuje uživatelům na hlavním počítači přistupovat ke klientským počítačům. -Je důležité aby pouze pověření uživatelé mohli číst soubor se soukromou částí klíče. -Veřejná část je použita na klientských počítačích pro ověření příchozího požadavku na připojení. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + @@ -647,10 +694,6 @@ Veřejná část je použita na klientských počítačích pro ověření pří This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. Tento příkaz vypíše všechny dostupné ověřovací klíče v nastavené složce s klíči. Pokud je zadaná volba „%1“, bude namísto toho zobrazena tabulka s podrobnostmi o klíči. Některé podrobnosti mohou chybět pokud klíč není dostupný například kvůli chybějícím právům na čtení. - - Please specify the command to display help for! - Zadejte příkaz pro který chcete zobrazit nápovědu! - TYPE TYP @@ -659,10 +702,6 @@ Veřejná část je použita na klientských počítačích pro ověření pří PAIR ID IDENTIFIKÁTOR DVOJICE - - Command line support for managing authentication keys - Podpora pro správu ověřovacích klíčů z příkazového řádku - Commands for managing authentication keys Příkazy pro zprávu ověřovacích klíčů @@ -679,6 +718,30 @@ Veřejná část je použita na klientských počítačích pro ověření pří This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. Tento příkaz vytáhne veřejnou část klíče ze soukromého klíče <KEY> a uloží jí do odpovídajícího veřejného klíče. Při nastavování jiného řídícího počítače proto stačí přenést pouze soukromou část klíče. Tu veřejnou z něj lze vytáhnout. + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + Na tomto počítači nejsou správně nastavené klíče s ověřovacími klíči. Vytvořte nové soubory nebo pomocí nastavení Veyon přepněte na jinou metodu ověřování. + + + Key file authentication + Ověření pomocí souboru s klíčem + + + Key file + + + + Please specify the key name (e.g. "teacher/public") as the first argument. + + + + Please specify the command to display help for. + + + + The specified command does not exist or no help is available for it. + + AuthKeysTableModel @@ -700,63 +763,206 @@ Veřejná část je použita na klientských počítačích pro ověření pří - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - Počítače + General + Obecné - Name - Název + Username to bind DN mapping: + - Host address/IP - Adresa IP/stroje + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + + AuthLdapDialog - MAC address - Fyzická (MAC) adresa + Veyon Logon + Veyon přihlášení - Add new computer - Přidat nový počítač + Please enter your domain/LDAP username and password in order to access computers. + - Remove selected computer - Odebrat označený počítač + Username + Uživatelské jméno - New computer - Nový počítač + Password + Heslo - Builtin directory - Vestavěný adresář + Authentication error + Chyba ověření - Locations & computers - Umístění a počítače + Logon failed with given username and password. Please try again! + Přihlášení daným uživatelským jménem a heslem se nezdařilo. Zkuste to znovu! + + + AuthLogonDialog - Locations - Umístění + Veyon Logon + Veyon přihlášení - Add new location - Přidat nové umístění + Please enter your username and password in order to access computers. + Zadejte své uživatelské jméno a heslo pro přístup k počítačům. - Remove selected location - Odebrat označené umístění + Username + Uživatelské jméno - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - Import CSV souborů je možný prostřednictvím rozhraní pro příkazový řádek. Další informace jsou k dispozici v <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">dokumentaci na webu</a>. + Password + Heslo + + + Authentication error + Chyba ověření + + + Logon failed with given username and password. Please try again! + Přihlášení daným uživatelským jménem a heslem se nezdařilo. Zkuste to znovu! + + + + AuthLogonPlugin + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Zadané uživatelské jméno nebo heslo není správné. Zadejte platné přihlašovací údaje nebo pomocí nastavení Veyon přepněte na jinou metodu ověřování. + + + Logon authentication + Ověření přihlášením se + + + Logon + + + + + AuthSimpleDialog + + Veyon Logon + Veyon přihlášení + + + Please enter the Veyon password: + Zadejte Veyon heslo: + + + Authentication error + Chyba ověření + + + Logon failed with given password. Please try again! + Přihlášení se zadaným heslem se nezdařilo. Zkuste to prosím znovu! + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + Zadané heslo není správné. Zadejte platné heslo pomocí nastavení Veyon přepněte na jinou metodu ověřování. + + + Simple password authentication + Jednoduché ověřování se heslem + + + Simple password + + + + + AuthenticationPage + + Authentication is set up properly on this computer. + Ověřování je na tomto počítači nastaveno správně + + + + AuthenticationPageTab + + Enabled + + + + Test + Vyzkoušet funkčnost + + + + BuiltinDirectoryConfiguration + + Builtin directory + Vestavěný adresář + + + + BuiltinDirectoryConfigurationPage + + Computers + Počítače + + + Name + Název + + + Host address/IP + Adresa IP/stroje + + + MAC address + Fyzická (MAC) adresa + + + Add new computer + Přidat nový počítač + + + Remove selected computer + Odebrat označený počítač + + + New computer + Nový počítač + + + Builtin directory + Vestavěný adresář + + + Locations + Umístění + + + Add new location + Přidat nové umístění + + + Remove selected location + Odebrat označené umístění New location Nové umístění + + Directory name + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + BuiltinDirectoryPlugin @@ -1000,6 +1206,14 @@ Veřejná část je použita na klientských počítačích pro ověření pří MAC ADDRESS MAC ADRESA + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. + + BuiltinUltraVncServer @@ -1017,10 +1231,6 @@ Veřejná část je použita na klientských počítačích pro ověření pří ComputerControlListModel - - Host/IP address: %1 - Stroj / IP adresa: %1 - Active features: %1 Aktivní funkce: %1 @@ -1037,10 +1247,6 @@ Veřejná část je použita na klientských počítačích pro ověření pří Computer offline or switched off Počítač není dostupný na síti nebo je vypnutý - - Service unreachable or not running - Služba není dosažitelná nebo není spuštěná - Authentication failed or access denied Ověření se nezdařilo nebo odepřen přístup @@ -1061,6 +1267,38 @@ Veřejná část je použita na klientských počítačích pro ověření pří Location: %1 Umístění: %1 + + [no user] + + + + Veyon Server unreachable or not running + + + + Name: %1 + + + + Hostname: %1 + + + + unknown + Neznámé + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + ComputerControlServer @@ -1092,6 +1330,17 @@ Veřejná část je použita na klientských počítačích pro ověření pří User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. Uživatel „%1“ na stroji „%2“ se pokusil přistoupit k tomuto počítači, ale byl zablokován dle nastavení řízení přístupu. + + Active connections: + Aktivní spojení: + + + + ComputerGroupSelector + + Group %1 + Skupina %1 + ComputerManager @@ -1119,80 +1368,83 @@ Veřejná část je použita na klientských počítačích pro ověření pří Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. Umístění počítače se nedaří zjistit. To značí problém s nastavením systému. Náhradně budou v panelu výběru počítačů zobrazena všechna umístění. - - - ComputerSelectPanel - Computer management - Správa počítače + Logged in since + - Computer search - Vyhledání počítače + %1 days + - Add location - Přidat umístění + 1 day + + + + ComputerMonitoring - Save computer/user list - Uložit seznam počítačů/uživatelů + Computers + Počítače - Select output filename - Vyberte výstupní soubor + Search users and computers + Hledání uživatelů a počítačů - CSV files (*.csv) - CSV soubory (*.csv) + Select all + Vybrat vše - File error - Chyba souboru + Unselect all + Odznačit vše - Could not write the computer and users list to %1! Please check the file access permissions. - Nedaří se zapsat seznam počítačů a uživatelů do %1! Zkontrolujte přístupová práva souboru. + Add to group + Přidat do skupiny - - - ConfigCommandLinePlugin - Please specify an existing configuration file to import. - Zadejte existující soubor s nastaveními, který importovat. + Remove from group + Odebrat ze skupiny + + + ComputerSelectPanel - Please specify a valid filename for the configuration export. - Zadejte platný název souboru pro export nastavení. + Computer search + Vyhledání počítače - Please specify a valid key. - Zadejte platný klíč. + Add location + Přidat umístění - Specified key does not exist in current configuration! - Zadaný klíč ve stávajícím nastavení neexistuje! + Save computer/user list + Uložit seznam počítačů/uživatelů - Please specify a valid value. - Zadejte platnou hodnotu. + Select output filename + Vyberte výstupní soubor - Configure Veyon at command line - Nastavit Veyon na příkazovém řádku + CSV files (*.csv) + CSV soubory (*.csv) - Output file is not writable! - Výstupní soubor není přístupný pro zápis! + File error + Chyba souboru - Output directory is not writable! - Výstupní složka není přístupná pro zápis! + Could not write the computer and users list to %1! Please check the file access permissions. + Nedaří se zapsat seznam počítačů a uživatelů do %1! Zkontrolujte přístupová práva souboru. - Configuration file is not readable! - Soubor s nastaveními není přístupný pro čtení! + Search computers + + + + ConfigCommands Clear system-wide Veyon configuration Vyčistit nastavení Veyon týkající se celého systému @@ -1221,42 +1473,82 @@ Veřejná část je použita na klientských počítačích pro ověření pří Unset (remove) given configuration key Zrušit nastavení (odebrat ze) zadané položky nastavení - - Commands for managing the configuration of Veyon - Příkazy pro správu nastavení Veyon - Upgrade and save configuration of program and plugins Přejít na novější verzi a uložit nastavení aplikace a zásuvných modulů - - - ConfigurationManager - Could not modify the autostart property for the %1 Service. - Nedaří se nastavit automatické spouštění služby %1. + Please specify an existing configuration file to import. + Zadejte existující soubor s nastaveními, který importovat. - Could not configure the firewall configuration for the %1 Server. - Nedaří se nastavit nastavení brány firewall pro server %1. + Configuration file is not readable! + Soubor s nastaveními není přístupný pro čtení! - Could not configure the firewall configuration for the %1 Worker. - Nedaří se nastavit bránu firewall pro worker %1. + Please specify a valid filename for the configuration export. + Zadejte platný název souboru pro export nastavení. - Configuration is not writable. Please check your permissions! - Nastavení nejsou přístupná pro zápis. Zkontrolujte svá oprávnění! + Output file is not writable! + Výstupní soubor není přístupný pro zápis! - Could not apply platform-specific configuration settings. - Nedaří se uplatnit změny nastavení pro konkrétní platformu. + Output directory is not writable! + Výstupní složka není přístupná pro zápis! - - - DemoClient - %1 Demo + Please specify a valid key. + Zadejte platný klíč. + + + Specified key does not exist in current configuration! + Zadaný klíč ve stávajícím nastavení neexistuje! + + + Please specify a valid value. + Zadejte platnou hodnotu. + + + Configure Veyon at command line + Nastavit Veyon na příkazovém řádku + + + Commands for managing the configuration of Veyon + Příkazy pro správu nastavení Veyon + + + + ConfigurationManager + + Could not modify the autostart property for the %1 Service. + Nedaří se nastavit automatické spouštění služby %1. + + + Could not configure the firewall configuration for the %1 Server. + Nedaří se nastavit nastavení brány firewall pro server %1. + + + Could not configure the firewall configuration for the %1 Worker. + Nedaří se nastavit bránu firewall pro worker %1. + + + Configuration is not writable. Please check your permissions! + Nastavení nejsou přístupná pro zápis. Zkontrolujte svá oprávnění! + + + Could not apply platform-specific configuration settings. + Nedaří se uplatnit změny nastavení pro konkrétní platformu. + + + Could not configure the firewall configuration for the %1 Service. + + + + + DemoClient + + %1 Demo Ukázka %1 @@ -1282,10 +1574,6 @@ Veřejná část je použita na klientských počítačích pro ověření pří Memory limit Paměťový limit - - Use multithreading (experimental) - Provozovat vícevláknově (experimentální) - MB MB @@ -1302,13 +1590,17 @@ Veřejná část je použita na klientských počítačích pro ověření pří Slow down thumbnail updates while demo is running Zpomalit aktualizace náhledů při běhu ukázky + + Bandwidth limit + + + + MB/s + + DemoFeaturePlugin - - Fullscreen demo - Ukázka na celou obrazovku - Stop demo Zastavit ukázku @@ -1322,16 +1614,60 @@ Veřejná část je použita na klientských počítačích pro ověření pří Předvést ostatním vysíláním obsahu obrazovky - Demo server - Ukázkový server + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + V tomto režimu bude vaše obrazovka zobrazována v okně na všech počítačích. Uživatelé přitom budou moci v případě potřeby přepínat na další okna. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - V tomto režimu bude vaše obrazovka zobrazována v celoobrazovkovém režimu na všech počítačích a jejich vstupní zařízení budou uzamčena. + Demo + - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - V tomto režimu bude vaše obrazovka zobrazována v okně na všech počítačích. Uživatelé přitom budou moci v případě potřeby přepínat na další okna. + Share your screen or allow a user to share his screen with other users. + + + + Full screen demo + + + + Share your own screen in fullscreen mode + + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share your own screen in a window + + + + Share selected user's screen in fullscreen mode + + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share selected user's screen in a window + + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + + + + Please select only one user screen to share. + + + + All screens + @@ -1359,14 +1695,6 @@ Veřejná část je použita na klientských počítačích pro ověření pří DesktopServicesConfigurationPage - - Programs & websites - Programy a webové stránky - - - Predefined programs - Přednastavené aplikace - Name Název @@ -1375,14 +1703,6 @@ Veřejná část je použita na klientských počítačích pro ověření pří Path Umístění - - Add new program - Přidat novou aplikaci - - - Remove selected program - Odebrat označenou aplikaci - Predefined websites Přednastavené webové stránky @@ -1395,21 +1715,37 @@ Veřejná část je použita na klientských počítačích pro ověření pří URL URL - - New program - Nová aplikace - New website Nová webová stránka + + Applications & websites + + + + Predefined applications + + + + Add new application + + + + Remove selected application + + + + Add new website + + + + New application + + DesktopServicesFeaturePlugin - - Run program - Spustit aplikaci - Open website Otevřít webovou stránku @@ -1419,28 +1755,32 @@ Veřejná část je použita na klientských počítačích pro ověření pří Kliknutím na toto tlačítko otevřete webovou stránku na všech počítačích. - Start programs and services in user desktop - Spustit aplikace a služby na počítači uživatele + Open website "%1" + Otevřít webovou stránku „%1“ - Click this button to run a program on all computers. - Kliknutím na toto tlačítko spustíte aplikaci na všech počítačích. + Custom website + Uživatelsky určené webová stránka - Run program "%1" - Spustit aplikaci „%1“ + Start application + - Custom program - Uživatelem určená aplikace + Click this button to start an application on all computers. + - Open website "%1" - Otevřít webovou stránku „%1“ + Start application "%1" + - Custom website - Uživatelsky určené webová stránka + Custom application + + + + Start apps and open websites in user sessions + @@ -1473,16 +1813,20 @@ Veřejná část je použita na klientských počítačích pro ověření pří Play tutorial video Přehrát výukové video - - Custom program - Uživatelem určená aplikace - Handout - + Předání Texts to read + Text ke čtení + + + generic-student-user + obecný student-uživatel + + + Custom application @@ -1509,478 +1853,463 @@ Veřejná část je použita na klientských počítačích pro ověření pří - FeatureControl + FeatureCommands - Feature control - Ovládání funkce + List names of all available features + - - - FileTransferController - Could not open file "%1" for reading! Please check your permissions! - Soubor „%1“ se nedaří otevřít pro čtení! Zkontrolujte svá oprávnění! + Show table with details of all available features + - - - FileTransferDialog - File transfer - Přenos souboru + Start a feature on a remote host + - Options - Volby + Stop a feature on a remote host + - Transfer only - Pouze přenos + Please specify the command to display help for. + - Transfer and open file(s) with associated program - Přenést a otevřít soubory pomocí přiřazeného programu + Displays a list with the names of all available features. + - Transfer and open destination folder - Přenést a otevřít cílovou složku + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + - Files - Soubory + HOST ADDRESS + ADRESA STROJE - Start - Spustit + FEATURE + - Overwrite existing files - Přepsat existující soubory + ARGUMENTS + - - - FileTransferPlugin - File transfer - Přenos souboru + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + - Click this button to transfer files from your computer to all computers. - Kliknutím na toto tlačítko zkopírujete soubory ze svého počítače na všechny ostatní. + Lock the screen + - Select one or more files to transfer - Vyberte jeden nebo více souborů k přenosu + Display a text message + - Transfer files to remote computer - Přenést soubory na vzdálený počítač + Test message + - Received file "%1". - Obdržen soubor „%1“. + Start an application + - Could not receive file "%1" as it already exists. - Není možné přijmout soubor „%1“, protože už existuje. + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + - Could not receive file "%1" as it could not be opened for writing! - Není možné přijmout soubor „%1“, protože by ho nebylo možné otevřít pro zápis! + Unlock the screen + - - - GeneralConfigurationPage - User interface - Uživatelské rozhraní + The specified command does not exist or no help is available for it. + - Language: - Jazyk: + Name + Název - Use system language setting - Použit jazyková nastavení systému + Description + Popis - Veyon - Veyon + Master + Řídící - Logging - Pořizování záznamů událostí + Service + Služba - Log file directory - Složka pro soubor se záznamy událostí + Worker + - ... - + UID + - Log level - Úroveň podrobností záznamu událostí + Plugin + Zásuvný modul - Nothing - Nic + Invalid feature name or UID specified + - Only critical messages - Pouze kritické zprávy + Error parsing the JSON-encoded arguments: %1 + - Errors and critical messages - Chyby a kritické zprávy + Failed to initialize credentials + - Warnings and errors - Varování a chyby + Could not establish a connection to host %1 + - Information, warnings and errors - Informace, varování a chyby + Failed to send feature control message to host %1 + - Debug messages and everything else - Ladící zprávy a vše ostatní + Feature-related CLI operations + - Limit log file size - Omezit velikost souboru se záznamy událostí + Commands for controlling features + + + + FileTransferConfigurationPage - Clear all log files - Vymazat všechny soubory se záznamy událostí + File transfer + Přenos souboru - Log to standard error output - Zaznamenávat na standardní chybový výstup + Directories + Složky - Network object directory - Adresář síťových objektů + Destination directory + - Backend: - Podpůrná vrstva (backend): + Default source directory + - Update interval: - Interval aktualizace: + Options + Volby - %1 service - služba %1 + Remember last source directory + - The %1 service needs to be stopped temporarily in order to remove the log files. Continue? - Pro smazání souborů se záznamy událostí je třeba dočasně zastavit službu %1 – pokračovat? + Create destination directory if it does not exist + + + + FileTransferController - Log files cleared - Soubory se záznamy událostí byly smazány + Could not open file "%1" for reading! Please check your permissions! + Soubor „%1“ se nedaří otevřít pro čtení! Zkontrolujte svá oprávnění! + + + FileTransferDialog - All log files were cleared successfully. - Všechny soubory se záznamy událostí byly úspěšně smazány. + File transfer + Přenos souboru - Error - Chyba + Options + Volby - Could not remove all log files. - Nedaří se smazat soubory se záznamy událostí. + Transfer only + Pouze přenos - MB - MB + Transfer and open file(s) with associated program + Přenést a otevřít soubory pomocí přiřazeného programu - Rotate log files - Rotovat soubory se záznamem událostí + Transfer and open destination folder + Přenést a otevřít cílovou složku - x - x + Files + Soubory - seconds - sekund + Start + Spustit - Write to logging system of operating system - Zapisovat do systému záznamu událostí operačního systému + Overwrite existing files + Přepsat existující soubory + + + FileTransferFileDialog - Authentication - Ověření + Select one or more files to transfer + Vyberte jeden nebo více souborů k přenosu + + + FileTransferPlugin - Method: - Metoda: + File transfer + Přenos souboru - Logon authentication - Ověření přihlášením se + Click this button to transfer files from your computer to all computers. + Kliknutím na toto tlačítko zkopírujete soubory ze svého počítače na všechny ostatní. - Key file authentication - Ověření pomocí souboru s klíčem + Select one or more files to transfer + Vyberte jeden nebo více souborů k přenosu - Test - Vyzkoušet funkčnost + Transfer files to remote computer + Přenést soubory na vzdálený počítač - Authentication is set up properly on this computer. - Ověřování je na tomto počítači nastaveno správně + Received file "%1". + Obdržen soubor „%1“. - Authentication keys are not set up properly on this computer. - Ověřování není na tomto počítači nastaveno správně + Could not receive file "%1" as it already exists. + Není možné přijmout soubor „%1“, protože už existuje. - Authentication test - Vyzkoušení ověřování + Could not receive file "%1" as it could not be opened for writing! + Není možné přijmout soubor „%1“, protože by ho nebylo možné otevřít pro zápis! - InternetAccessControlConfigurationPage + GeneralConfigurationPage - Internet access control - Řízení přístupu k Internetu + User interface + Uživatelské rozhraní - Backend: - Podpůrná vrstva (backend): + Language: + Jazyk: - General settings - Obecná nastavení + Use system language setting + Použit jazyková nastavení systému - Backend settings - Nastavení podpůrné vrstvy + Veyon + Veyon - - - InternetAccessControlPlugin - Block access to the internet - Blokovat přístup k Internetu + Logging + Pořizování záznamů událostí - Allow access to the internet - Umožnit přístup k Internetu + Log file directory + Složka pro soubor se záznamy událostí - Show help about command - Zobrazit nápovědu k příkazu + Log level + Úroveň podrobností záznamu událostí - Block internet - Blokovat Internet + Nothing + Nic - Click this button to block access to the internet. - Kliknutím na toto tlačítko zablokujete přístup k Internetu. + Only critical messages + Pouze kritické zprávy - Unblock internet - Odblokovat Internet + Errors and critical messages + Chyby a kritické zprávy - Click this button to allow access to the internet. - Kliknutím na toto tlačítko umožníte přístup k Internetu. + Warnings and errors + Varování a chyby - Control access to the internet - Ovládat přístup k Internetu + Information, warnings and errors + Informace, varování a chyby - Commands for controlling access to the internet - Příkazy pro ovládání přístup k Internetu + Debug messages and everything else + Ladící zprávy a vše ostatní - - - LdapBrowseDialog - Browse LDAP - Procházet LDAP + Limit log file size + Omezit velikost souboru se záznamy událostí - - - LdapClient - LDAP error description: %1 - Popis LDAP chyby: %1 + Clear all log files + Vymazat všechny soubory se záznamy událostí - - - LdapConfigurationPage - Basic settings - Základní nastavení + Log to standard error output + Zaznamenávat na standardní chybový výstup - General - Obecné + %1 service + služba %1 - LDAP server and port - LDAP server a port + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + Pro smazání souborů se záznamy událostí je třeba dočasně zastavit službu %1 – pokračovat? - Bind DN - Spojovací rozlišený název (DN) + Log files cleared + Soubory se záznamy událostí byly smazány - Bind password - Spojovací heslo + All log files were cleared successfully. + Všechny soubory se záznamy událostí byly úspěšně smazány. - Anonymous bind - Anonymní spojení + Error + Chyba - Use bind credentials - Použít spojovací přihlašovací údaje + Could not remove all log files. + Nedaří se smazat soubory se záznamy událostí. - Base DN - Základ rozlišeného názvu (DN) + MB + MB - Fixed base DN - Neměnný základ rozlišeného názvu (DN) + Rotate log files + Rotovat soubory se záznamem událostí - e.g. dc=example,dc=org - např. dc=example,dc=org + x + x - Discover base DN by naming context - Zjistit základ rozlišeného názvu (DN) pomocí kontextu pojmenování + Write to logging system of operating system + Zapisovat do systému záznamu událostí operačního systému - e.g. namingContexts or defaultNamingContext - např. namingContexts nebo defaultNamingContext + TLS configuration + - Environment settings - Nastavení prostředí + Use certificate authority for TLS connections + - Object trees - Stromy objektů + CA certificate file + - Computer tree - Strom počítačů + ... + - e.g. OU=Groups - např. OU=Groups + Host certificate file + - User tree - Strom uživatelů + Host private key file + - e.g. OU=Users - např. OU=Users + Style: + - e.g. OU=Computers - např. OU=Computers + Native + - Group tree - Strom skupin + Color scheme: + - Perform recursive search operations in object trees - Hledat i ve vnořených úrovních stromů objektu + Light + - Object attributes - Atributy objektu + Dark + - e.g. hwAddress - např. hwAdress + User groups + - e.g. member or memberUid - Např. member nebo memberUid + Backend: + Podpůrná vrstva (backend): - e.g. dNSHostName - Např. dNSHostName + Include user groups from domain + - Computer MAC address attribute - Atribut fyzická (MAC) adresa počítače + Missing user groups backend + Chybí podpůrná vrstva uživatelských skupin - Group member attribute - Atribut členství ve skupinách + No user groups plugin was found. Please check your installation! + + + + HeadlessVncServer - e.g. uid or sAMAccountName - např. uid nebo sAMAccountName - - - Advanced settings - Pokročilá nastavení - - - Optional object filters - Volitelné filtry objektů - - - Filter for user groups - Filtrovat dle skupin uživatele - - - Filter for users - Filtrovat dle uživatelů - - - Filter for computer groups - Filtrovat dle skupin počítačů - - - Group member identification - Identifikace člena skupiny - - - Distinguished name (Samba/AD) - Rozlišený název (Samba/AD) - - - List all groups of a user - Vypsat veškeré skupiny kterých je uživatel členem + Headless VNC server + + + + LdapBrowseDialog - List all groups of a computer - Vypsat veškeré skupiny počítačů + Browse LDAP + Procházet LDAP + + + LdapClient - Get computer object by IP address - Získat objekt počítače pomocí IP adresy + LDAP error description: %1 + Popis LDAP chyby: %1 + + + LdapConfiguration LDAP connection failed Nepodařilo se připojit do LDAP + + Could not connect to the LDAP server. Please check the server parameters. + +%1 + Nedaří se připojit na LDAP server. Zkontrolujte parametry serveru. + +%1 + LDAP bind failed Spojení s LDAP se nezdařilo + + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + Nedaří se přihlásit k LDAP serveru. Zkontrolujte parametry serveru a přihlašovací údaje. + LDAP bind successful Spojení do LDAP úspěšně navázáno @@ -1993,14 +2322,36 @@ Veřejná část je použita na klientských počítačích pro ověření pří LDAP base DN test failed Test základu LDAP rozliš. (DN) názvu se nezdařil + + Could not query the configured base DN. Please check the base DN parameter. + +%1 + Nedaří se dotázat na nastavený základ rozlišeného názvu. Zkontrolujte parametr základu DN. + +%1 + LDAP base DN test successful Test základu LDAP rozliš. názvu úspěšný + + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + Základ LDAP DN byl úspěšně dotázán. Byly nalezeny následující položky: + +%1 + LDAP naming context test failed Test LDAP kontextu názvů se nezdařil + + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + Nedaří se dotázat na základ rozlišeného názvu prostřednictvím názvového kontextu. Zkontrolujte parametr atributu kontextu názvů. + LDAP naming context test successful Test LDAP kontextu názvů úspěšný @@ -2015,38 +2366,50 @@ Veřejná část je použita na klientských počítačích pro ověření pří user tree strom uživatelů + + User tree + Strom uživatelů + group tree strom skupin + + Group tree + Strom skupin + computer tree strom počítačů - Enter username - Zadejte uživatelské jméno + Computer tree + Strom počítačů - Please enter a user login name (wildcards allowed) which to query: - Zadejte přihlašovací jméno uživatele (je možné použít i zástupné znaky) na které se dotázat: + computer group tree + Strom skupin uživatelů - user objects - objekty uživatele + Computer group tree + Strom skupin počítačů - Enter group name - Zadejte název skupiny + user objects + objekty uživatele - Please enter a group name whose members to query: - Zadejte název skupiny na jejíž členy se dotázat: + User login name attribute + Atribut obsahující přihlašovací jméno uživatele group members členové skupiny + + Group member attribute + Atribut členství ve skupinách + Group not found Skupina nenalezena @@ -2055,26 +2418,50 @@ Veřejná část je použita na klientských počítačích pro ověření pří Could not find a group with the name "%1". Please check the group name or the group tree parameter. Nedaří se nalézt skupinu s názvem „%1“. Zkontrolujte název skupiny a parametr „strom skupin“. - - Enter computer name - Zadejte název počítače - computer objects objekty počítačů - Enter computer DN - Zadejte rozlišený název (DN) počítače + Computer display name attribute + Atribut zobrazovaného názvu počítače - Please enter the DN of a computer whose MAC address to query: - Zadejte rozlišený název (DN) počítače na jehož MAC adresu se dotázat: + Invalid hostname + Neplatný název stroje + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Nastavili jste, že názvy strojů mají být ukládány v podobě úplných doménových názvů (FQDN), ale nyní jste zadali pouze název stroje bez domény. + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Nastavili jste, že názvy strojů mají být ukládány v podobě krátkých názvů bez doménové části, ale nyní jste zadali název stroje včetně domény. + + + Computer hostname attribute + Atribut název počítače computer MAC addresses Fyzické (MAC) adresy sítových rozhraní počítačů + + Computer MAC address attribute + Atribut fyzická (MAC) adresa počítače + + + computer locations + umístění počítačů + + + Computer location attribute + Atribut umístění počítače + + + Location name attribute + Atribut názvu umístění + users uživatelé @@ -2083,13 +2470,17 @@ Veřejná část je použita na klientských počítačích pro ověření pří user groups skupiny uživatelů + + computers + počítače + computer groups skupiny počítačů - Please enter a user login name whose group memberships to query: - Zadejte přihlašovací jméno uživatele na jehož členství ve skupinách se dotázat: + computer containers + kontejnery s počítači groups of user @@ -2099,6 +2490,10 @@ Veřejná část je použita na klientských počítačích pro ověření pří User not found Uživatel nebyl nalezen + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + Nedaří se nalézt uživatele se jménem „%1“. Zkontrolujte uživatelské jméno nebo parametr strom uživatelů. + groups of computer skupiny počítačů @@ -2108,21 +2503,53 @@ Veřejná část je použita na klientských počítačích pro ověření pří Počítač nenalezen - Enter computer IP address - Zadejte IP adresu počítače + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Nedaří se nalézt počítač nazvaný „%1“. Zkontrolujte název stroje nebo parametr strom počítačů. - Please enter a computer IP address which to resolve to an computer object: - Zadejte IP adresu počítače kterou přeložit na objekt počítače: + Hostname lookup failed + Vyhledání názvu stroje se nezdařilo - computers - počítače + Could not lookup hostname for IP address %1. Please check your DNS server settings. + Nedaří se zjistit název stroje pro IP adresu %1. Zkontrolujte nastavení pro DNS server. + + + location entries + položky umístění + + + Computer groups filter + Filtr skupin počítačů + + + Computer locations identification + Identifikace umístění počítače + + + Filter for computer groups + Filtrovat dle skupin počítačů + + + Invalid test value + Neplatná hodnota testu + + + An empty or invalid value has been supplied for this test. + Pro tento test zadána prázdná nebo neplatná hodnota. LDAP %1 test failed Test LDAP %1 se nezdařil + + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + Nedaří se dotázat na žádné položky v nastaveném %1. Zkontrolujte parametr „%2“. + +%3 + LDAP %1 test successful Test LDAP %1 úspěšný @@ -2131,6 +2558,26 @@ Veřejná část je použita na klientských počítačích pro ověření pří The %1 has been queried successfully and %2 entries were found. Úspěšně dotázáno na %1 a nalezeno %2 položek. + + LDAP test failed + Zkouška LDAP neúspěšná + + + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + Nedaří se dotázat na žádné %1. Zkontrolujte parametr(y) %2 a zadejte název existujícího objektu. + +%3 + + + and + a + + + LDAP test successful + Zkouška LDAP úspěšná + %1 %2 have been queried successfully: @@ -2160,566 +2607,492 @@ Veřejná část je použita na klientských počítačích pro ověření pří S nastaveným filtrem úspěšně dotázáno na %1 %2. - (only if different from group tree) - (pouze pokud se liší od stromu skupin) + LDAP directory + + + + LdapConfigurationPage - Computer group tree - Strom skupin počítačů + Basic settings + Základní nastavení - computer group tree - Strom skupin uživatelů + General + Obecné - Filter for computers - Filtrovat dle počítačů + LDAP server and port + LDAP server a port - e.g. room or computerLab - např. room (místnost) nebo computerLab (počítačová laboratoř) + Bind DN + Spojovací rozlišený název (DN) - Integration tests - Integrační testy + Bind password + Spojovací heslo - Computer groups - Skupiny počítačů + Anonymous bind + Anonymní spojení - e.g. name or description - např. název nebo popis - - - Filter for computer containers - Filtrovat dle kontejnerů s počítači - - - Computer containers or OUs - Kontejnery s počítači nebo organizační jednotky - - - Connection security - Zabezpečení připojení - - - TLS certificate verification - Ověření TLS certifikátu - - - System defaults - Výchozí systémové - - - Never (insecure!) - Nikdy (nezabezpečené!) + Use bind credentials + Použít spojovací přihlašovací údaje - Custom CA certificate file - Uživatelsky určený soubor s certifikátem cert. autority + Base DN + Základ rozlišeného názvu (DN) - None - Žádné + Fixed base DN + Neměnný základ rozlišeného názvu (DN) - TLS - TLS + e.g. dc=example,dc=org + např. dc=example,dc=org - SSL - SSL + Discover base DN by naming context + Zjistit základ rozlišeného názvu (DN) pomocí kontextu pojmenování - e.g. (objectClass=computer) - např. (objectClass=computer) + e.g. namingContexts or defaultNamingContext + např. namingContexts nebo defaultNamingContext - e.g. (objectClass=group) - např. (objectClass=group) + Environment settings + Nastavení prostředí - e.g. (objectClass=person) - např. (objectClass=person) + Object trees + Stromy objektů - e.g. (objectClass=room) or (objectClass=computerLab) - např. (objectClass=room) nebo (objectClass=computerLab) + Computer tree + Strom počítačů - e.g. (objectClass=container) or (objectClass=organizationalUnit) - např. (objectClass=container) nebo (objectClass=organizationalUnit) + e.g. OU=Groups + např. OU=Groups - Could not query the configured base DN. Please check the base DN parameter. - -%1 - Nedaří se dotázat na nastavený základ rozlišeného názvu. Zkontrolujte parametr základu DN. - -%1 + User tree + Strom uživatelů - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - Základ LDAP DN byl úspěšně dotázán. Byly nalezeny následující položky: - -%1 + e.g. OU=Users + např. OU=Users - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - Nedaří se dotázat na základ rozlišeného názvu prostřednictvím názvového kontextu. Zkontrolujte parametr atributu kontextu názvů. + e.g. OU=Computers + např. OU=Computers - Certificate files (*.pem) - Soubory certifikátů (*.pem) + Group tree + Strom skupin - Could not connect to the LDAP server. Please check the server parameters. - -%1 - Nedaří se připojit na LDAP server. Zkontrolujte parametry serveru. - -%1 + Perform recursive search operations in object trees + Hledat i ve vnořených úrovních stromů objektu - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - Nedaří se přihlásit k LDAP serveru. Zkontrolujte parametry serveru a přihlašovací údaje. + Object attributes + Atributy objektu - Encryption protocol - Šifrovací protokol + e.g. hwAddress + např. hwAdress - Computer location attribute - Atribut umístění počítače + e.g. member or memberUid + Např. member nebo memberUid - Computer display name attribute - Atribut zobrazovaného názvu počítače + e.g. dNSHostName + Např. dNSHostName - Location name attribute - Atribut názvu umístění + Computer MAC address attribute + Atribut fyzická (MAC) adresa počítače - e.g. cn or displayName - např. cn nebo displayName + Group member attribute + Atribut členství ve skupinách - Computer locations identification - Identifikace umístění počítače + e.g. uid or sAMAccountName + např. uid nebo sAMAccountName - Identify computer locations (e.g. rooms) via: - Identifikuje umístění počítačů (např. místnosti) prostřednictvím: + Advanced settings + Pokročilá nastavení - Location attribute in computer objects - Atribut umístění v objektu počítače + Optional object filters + Volitelné filtry objektů - List all entries of a location - Vypsat všechny položky v daném umístění + Filter for user groups + Filtrovat dle skupin uživatele - List all locations - Vypsat všechna umístění + Filter for users + Filtrovat dle uživatelů - Enter computer display name - Zadejte zobrazovaný název počítače + Filter for computer groups + Filtrovat dle skupin počítačů - Please enter a computer display name to query: - Zadejte zobrazovaný název počítače na se který dotázat: + Group member identification + Identifikace člena skupiny - Enter computer location name - Zadejte název umístění počítače + Distinguished name (Samba/AD) + Rozlišený název (Samba/AD) - Please enter the name of a computer location (wildcards allowed): - Zadejte název umístění počítače (je možné použít i zástupné znaky): + List all groups of a user + Vypsat veškeré skupiny kterých je uživatel členem - computer locations - umístění počítačů + List all groups of a computer + Vypsat veškeré skupiny počítačů - Enter location name - Zadejte název umístění + Get computer object by IP address + Získat objekt počítače pomocí IP adresy - Please enter the name of a location whose entries to query: - Zadejte název umístění na jejíž členy se chcete dotázat: + Enter username + Zadejte uživatelské jméno - location entries - položky umístění + Please enter a user login name (wildcards allowed) which to query: + Zadejte přihlašovací jméno uživatele (je možné použít i zástupné znaky) na které se dotázat: - LDAP test failed - Zkouška LDAP neúspěšná + Enter group name + Zadejte název skupiny - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - Nedaří se dotázat na žádné %1. Zkontrolujte parametr(y) %2 a zadejte název existujícího objektu. - -%3 + Please enter a group name whose members to query: + Zadejte název skupiny na jejíž členy se dotázat: - and - a + Enter computer name + Zadejte název počítače - LDAP test successful - Zkouška LDAP úspěšná + Enter computer DN + Zadejte rozlišený název (DN) počítače - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - Nedaří se dotázat na žádné položky v nastaveném %1. Zkontrolujte parametr „%2“. - -%3 + Please enter the DN of a computer whose MAC address to query: + Zadejte rozlišený název (DN) počítače na jehož MAC adresu se dotázat: - Browse - Procházet + Please enter a user login name whose group memberships to query: + Zadejte přihlašovací jméno uživatele na jehož členství ve skupinách se dotázat: - Test - Vyzkoušet funkčnost + Enter computer IP address + Zadejte IP adresu počítače - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - Názvy strojů ukládané jako úplné doménové názvy (FQDN), např. mujstroj.example.org + Please enter a computer IP address which to resolve to an computer object: + Zadejte IP adresu počítače kterou přeložit na objekt počítače: - Computer hostname attribute - Atribut název počítače + (only if different from group tree) + (pouze pokud se liší od stromu skupin) - Please enter a computer hostname to query: - Zadejte název počítače na se který dotázat: + Computer group tree + Strom skupin počítačů - Invalid hostname - Neplatný název stroje + Filter for computers + Filtrovat dle počítačů - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Nastavili jste, že názvy strojů mají být ukládány v podobě úplných doménových názvů (FQDN), ale nyní jste zadali pouze název stroje bez domény. + e.g. room or computerLab + např. room (místnost) nebo computerLab (počítačová laboratoř) - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - Nastavili jste, že názvy strojů mají být ukládány v podobě krátkých názvů bez doménové části, ale nyní jste zadali název stroje včetně domény. + Integration tests + Integrační testy - Could not find a user with the name "%1". Please check the username or the user tree parameter. - Nedaří se nalézt uživatele se jménem „%1“. Zkontrolujte uživatelské jméno nebo parametr strom uživatelů. + Computer groups + Skupiny počítačů - Enter hostname - Zadejte název stroje + e.g. name or description + např. název nebo popis - Please enter a computer hostname whose group memberships to query: - Zadejte název počítače na jehož členství ve skupinách se dotázat: + Filter for computer containers + Filtrovat dle kontejnerů s počítači - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - Nedaří se nalézt počítač nazvaný „%1“. Zkontrolujte název stroje nebo parametr strom počítačů. + Computer containers or OUs + Kontejnery s počítači nebo organizační jednotky - Hostname lookup failed - Vyhledání názvu stroje se nezdařilo + Connection security + Zabezpečení připojení - Could not lookup hostname for IP address %1. Please check your DNS server settings. - Nedaří se zjistit název stroje pro IP adresu %1. Zkontrolujte nastavení pro DNS server. + TLS certificate verification + Ověření TLS certifikátu - User login name attribute - Atribut obsahující přihlašovací jméno uživatele + System defaults + Výchozí systémové - Configured attribute for user login name or computer hostname (OpenLDAP) - Nastavený atribut pro uživatelské jméno nebo název počítače (OpenLDAP) + Never (insecure!) + Nikdy (nezabezpečené!) - computer containers - kontejnery s počítači + Custom CA certificate file + Uživatelsky určený soubor s certifikátem cert. autority - - - LdapPlugin - Auto-configure the base DN via naming context - Automaticky nastavit základ rozliš. názvu (DN) prostřednictvím kontextu pojmenování + None + Žádné - Query objects from LDAP directory - Dotazovat se na objekty z LDAP adresáře + TLS + TLS - Show help about command - Zobrazit nápovědu k příkazu + SSL + SSL - Commands for configuring and testing LDAP/AD integration - Příkazy pro nastavování a testování napojení na LDAP/AD + e.g. (objectClass=computer) + např. (objectClass=computer) - Basic LDAP/AD support for Veyon - Základní podpora pro LDAP/AD ve Veyon + e.g. (objectClass=group) + např. (objectClass=group) - %1 (load computers and locations from LDAP/AD) - %1 (načíst počítače a umístění z LDAP/AD) + e.g. (objectClass=person) + např. (objectClass=person) - %1 (load users and groups from LDAP/AD) - %1 (načíst uživatele a skupiny z LDAP/AD) + e.g. (objectClass=room) or (objectClass=computerLab) + např. (objectClass=room) nebo (objectClass=computerLab) - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - Zadejte platnou LDAP url následující toto schéma „ldap[s]://[uzivatel[:heslo]@]stroj[:port]" + e.g. (objectClass=container) or (objectClass=organizationalUnit) + např. (objectClass=container) nebo (objectClass=organizationalUnit) - No naming context attribute name given - falling back to configured value. - Nebyl zadán žádný název pro atribut jmenného kontextu – náhradně bude použita nastavená hodnota. + Certificate files (*.pem) + Soubory certifikátů (*.pem) - Could not query base DN. Please check your LDAP configuration. - Nedaří se dotázat na nastavený základ rozlišeného názvu. Zkontrolujte nastavení svého LDAP. + Encryption protocol + Šifrovací protokol - Configuring %1 as base DN and disabling naming context queries. - %1 je nastavováno jako základ rozlišeného názvu a vypínají se dotazy na jmenný kontext. + Computer location attribute + Atribut umístění počítače - - - LdapProConfigurationPage - LDAP Pro - LDAP Pro + Computer display name attribute + Atribut zobrazovaného názvu počítače - Instances - Instance + Location name attribute + Atribut názvu umístění - Enter name - Zadejte název + e.g. cn or displayName + např. cn nebo displayName - Please enter a name for the instance (can't be changed later!): - Zadejte název instance (později už nepůjde změnit!): + Computer locations identification + Identifikace umístění počítače - Remove instance - Odebrat instanci + Identify computer locations (e.g. rooms) via: + Identifikuje umístění počítačů (např. místnosti) prostřednictvím: - Do you really want to remove instance "%1"? - Opravdu chcete odebrat instanci „%1“? + Location attribute in computer objects + Atribut umístění v objektu počítače - Configuration for instance "%1" - Nastavení pro instanci „%1“ + List all entries of a location + Vypsat všechny položky v daném umístění - - - LdapProPlugin - Professional LDAP/AD integration for Veyon - Profesionální začlenění LDAP/AD pro Veyon + List all locations + Vypsat všechna umístění - %1 (load computers and locations from LDAP/AD) - %1 (načíst počítače a umístění z LDAP/AD) + Enter computer display name + Zadejte zobrazovaný název počítače - %1 (load users and groups from LDAP/AD) - %1 (načíst uživatele a skupiny z LDAP/AD) + Please enter a computer display name to query: + Zadejte zobrazovaný název počítače na se který dotázat: - - - LicensingConfigurationPage - Licensing - Licencování + Enter computer location name + Zadejte název umístění počítače - Installed licenses - Nainstalované licence + Please enter the name of a computer location (wildcards allowed): + Zadejte název umístění počítače (je možné použít i zástupné znaky): - Add new network range - Přidat nový síťový rozsah + Enter location name + Zadejte název umístění - Remove selected network range - Odebrat označený síťový rozsah + Please enter the name of a location whose entries to query: + Zadejte název umístění na jejíž členy se chcete dotázat: - ID - Identif. + Browse + Procházet - Feature - Funkce + Test + Vyzkoušet funkčnost - Valid until - Platné do + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Názvy strojů ukládané jako úplné doménové názvy (FQDN), např. mujstroj.example.org - Licensee - Držitel licence + Computer hostname attribute + Atribut název počítače - Browse license file - Nalistovat soubor s licencí + Please enter a computer hostname to query: + Zadejte název počítače na se který dotázat: - Veyon license files (*.vlf) - Soubory s licencí pro Veyon (*.vlf) + Enter hostname + Zadejte název stroje - Remove license - Odebrat licenci + Please enter a computer hostname whose group memberships to query: + Zadejte název počítače na jehož členství ve skupinách se dotázat: - Do you really want to remove the selected license? - Opravdu chcete odebrat vybranou licenci? + User login name attribute + Atribut obsahující přihlašovací jméno uživatele - <N/A> - <N/A> + Configured attribute for user login name or computer hostname (OpenLDAP) + Nastavený atribut pro uživatelské jméno nebo název počítače (OpenLDAP) - Invalid license file - Neplatný soubor s licencí + Directory name + - Could not open the license file for reading! - Nedaří se otevřít soubor s licencí pro čtení! + Query options + - The selected license file does not contain valid data. - Zvolený soubor s licencí neobsahuje platná data. + Query nested user groups (supported by AD only) + - The selected license file could not be verified. - Zvolený soubor s licencí se nepodařilo ověřit. + Query timeout + - The selected license file is not valid for this installation. - Zvolený soubor s licencí není platný pro tuto instalaci. + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. - Platnost zvoleného souboru s licencí skončila. + LDAP + LDAP - The license is already installed. - Tato licence už je nainstalována. + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + + LdapPlugin - Information - Informace + Auto-configure the base DN via naming context + Automaticky nastavit základ rozliš. názvu (DN) prostřednictvím kontextu pojmenování - Installation ID - Identifikátor instalace + Query objects from LDAP directory + Dotazovat se na objekty z LDAP adresáře - Addons available for licensing - Doplňky které je možné si licencovat + Show help about command + Zobrazit nápovědu k příkazu - Addon - Doplněk + Commands for configuring and testing LDAP/AD integration + Příkazy pro nastavování a testování napojení na LDAP/AD - - - LicensingPlugin - Show help for specific command - Zobrazit nápovědu pro konkrétní příkaz + Basic LDAP/AD support for Veyon + Základní podpora pro LDAP/AD ve Veyon - Show all installed licenses - Zobrazit všechny nainstalované licence + %1 (load computers and locations from LDAP/AD) + %1 (načíst počítače a umístění z LDAP/AD) - Add license file - Přidat licenční soubor + %1 (load users and groups from LDAP/AD) + %1 (načíst uživatele a skupiny z LDAP/AD) - Remove installed license - Odebrat nainstalovanou licenci + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Zadejte platnou LDAP url následující toto schéma „ldap[s]://[uzivatel[:heslo]@]stroj[:port]" - -USAGE - -%1 add <LICENSE FILE> - - - -POUŽITÍ - -%1 add <LICENSE FILE> - - + No naming context attribute name given - falling back to configured value. + Nebyl zadán žádný název pro atribut jmenného kontextu – náhradně bude použita nastavená hodnota. - -USAGE - -%1 remove <LICENSE ID> - - - -POUŽITÍ - -%1 remove <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. + Nedaří se dotázat na nastavený základ rozlišeného názvu. Zkontrolujte nastavení svého LDAP. - No certificate found with given ID - U daného identif. nenalezen certifikát + Configuring %1 as base DN and disabling naming context queries. + %1 je nastavováno jako základ rozlišeného názvu a vypínají se dotazy na jmenný kontext. - <N/A> - <N/A> + Test binding to an LDAP server + Vyzkoušet napojení na LDAP server - Licensing management - Správa licencí + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Zadané uživatelské jméno nebo heslo není správné. Zadejte platné přihlašovací údaje nebo pomocí nastavení Veyon přepněte na jinou metodu ověřování. - Commands for managing license keys - Příkazy pro správu licenčních klíčů + LDAP bind + LinuxPlatformConfigurationPage Linux - GNU/Linux + Linux Custom PAM service for user authentication @@ -2730,12 +3103,20 @@ POUŽITÍ Ověření uživatele - Session management - Správa relace + User sessions + + + + Minimum session lifetime before server start + + + + User login + Přihlášení uživatele - Display manager users - Zobrazit uživatele-správce + Login key sequence + @@ -2744,10 +3125,6 @@ POUŽITÍ Plugin implementing abstract functions for the Linux platform Zásuvný modul implementující abstrahující funkce pro Linuxovou platformu - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2766,14 +3143,14 @@ POUŽITÍ Configuration Nastavení - - Disable balloon tooltips - Nezobrazovat popisky nástrojů - Show icons only Zobrazovat pouze ikony + + Disable tooltips + + MainWindow @@ -2821,10 +3198,6 @@ POUŽITÍ About Qt O aplikačním rámci (framework) Qt - - Authentication impossible - Ověření není možné - Configuration not writable Nastavení není přístupné pro zápis @@ -2885,10 +3258,6 @@ POUŽITÍ The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. Podpůrná vrstva (backend) nastavení na tomto počítači hlásí, že do nastavení nelze zapisovat! Spusťte konzolu pro správu %1 s vyššími oprávněními. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - Nebyly nalezeny žádné ověřovací klíče nebo jsou ty vámi právě používané zastaralé. Vytvořte nové soubory s klíči pomocí konzole pro správu %1. Případně můžete v konzoli pro správu %1 nastavit ověřování přihlášením. Pokud tak neučiníte, nebudete moci přistupovat k počítačům pomocí %1. - Access denied Přístup odepřen @@ -2921,10 +3290,6 @@ POUŽITÍ Search users and computers Hledání uživatelů a počítačů - - Adjust optimal size - Upravit optimální velikost - Align computers to grid Zarovnat počítače do mřížky @@ -2969,6 +3334,48 @@ POUŽITÍ Locations && computers Umístění && počítače + + Authentication + Ověření + + + Adjust size of computer icons automatically + + + + Slideshow + + + + Spotlight + + + + Veyon Master + Veyon – hlavní + + + Locations & computers + Umístění a počítače + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + + + + Load computer positions + + + + Save computer positions + + MasterConfigurationPage @@ -2976,10 +3383,6 @@ POUŽITÍ Directories Složky - - ... - - User configuration Nastavení uživatele @@ -3064,6 +3467,10 @@ POUŽITÍ Only user name Pouze uživatelské jméno + + Only last part of user name + + Only computer name Pouze název počítače @@ -3112,171 +3519,181 @@ POUŽITÍ Automatically select current location Automaticky vybrat stávající umístění - - Automatically adjust computer thumbnail size - Automaticky přizpůsobit velikost náhledu počítače - Automatically open computer select panel Automaticky otevřít panel výběru počítače - - - MonitoringMode - Monitoring - Dohledování + Use modern user interface (experimental) + Použít moderní uživatelské rozhraní (experimentální) - Builtin monitoring mode - Režim vestavěného dohledování + Thumbnail spacing + - This mode allows you to monitor all computers at one or more locations. - Tento režim umožňuje monitorovat veškeré počítače v jednom a více umístěních. + px + + + + Hide local session + + + + Auto + Automaticky + + + Thumbnail aspect ratio + + + + Automatically adjust computer icon size + + + + Open feature windows on the same screen as the main window + - - - NetworkDiscoveryConfigurationPage - Network discovery - Prozkoumávání sítě + Configuration templates + + + + Image quality in monitoring mode + - Mode - Režim + Highest + - Scan network ranges - Skenovat síťové rozsahy + High + - e.g. 192.168.1.0/24 - např. 192.168.1.0/24 + Medium + - Scan all subnets of computer - Skenovat všechny podsítě počítače + Low + - Scan custom subnet - Skenovat uživatelsky určenou podsíť + Lowest + - Scan sessions on local computer - Skenovací relace na tomto počítači + Remote access image quality + - Test - Vyzkoušet funkčnost + Advanced + - Network ranges - Síťové rozsahy + Computer name source + - Add new group - Přidat novou skupinu + Default + - Remove selected group - Odebrat označenou skupinu + Host address + Adresa stroje - Groups - Skupiny + Session client address + - First address - První adresa + Session client name + - Last address - Poslední adresa + Session host name + - Add new network range - Přidat nový síťový rozsah + Session metadata + - Remove selected network range - Odebrat označený síťový rozsah + Full name of user + - Parallel scans - Souběžné skeny + User login name + - Scan timeout - Časový limit skenování + Computer UID role + - ms - ms + Session meta data hash + - Session scan limit - Limit skenu relace + Always expand all locations + - Options - Volby + Image quality + + + + MonitoringMode - Reverse lookup discovered IP addresses to host names - Překládat objevené IP adresy na názvy strojů + Monitoring + Dohledování - New location - Nové umístění + Builtin monitoring mode + Režim vestavěného dohledování - - - NetworkDiscoveryDirectory - Scanning... - Skenování… + This mode allows you to monitor all computers at one or more locations. + Tento režim umožňuje monitorovat veškeré počítače v jednom a více umístěních. - Discovered computers - Objevené počítače + Query application version of the server + - - - NetworkDiscoveryPlugin - Show help for specific command - Zobrazit nápovědu pro konkrétní příkaz + Query active features + - Scan a subnet - Skenovat podsíť + Query properties of remotely available screens + + + + NestedNetworkObjectDirectory - -USAGE - -%1 scan [<SUBNET>] - - - -POUŽITÍ - -%1 scan [<SUBNET>] - - + All directories + + + + NetworkObjectDirectoryConfigurationPage - Network object directory which automatically discovers computers in the network - Adresář síťových objektů který automaticky objevuje počítače v síti + Update interval: + Interval aktualizace: - Network discovery (scan network for Veyon clients) - Průzkum sítě (skenuje přítomnost Veyon klientů na síti) + seconds + sekund + + + NetworkObjectDirectoryConfigurationPageTab - Commands for managing the network discovery directory - Příkazy pro správu adresáře průzkumu sítě + Enabled + @@ -3312,32 +3729,44 @@ POUŽITÍ Name: Název: + + Website name + + - PasswordDialog + PluginCommands - Username - Uživatelské jméno + List names of all installed plugins + Vypsat názvy všech nainstalovaných zásuvných modulů - Password - Heslo + Show table with details of all installed plugins + Zobrazit tabulku s podrobnostmi o všech nainstalovaných zásuvných modulech - Veyon Logon - Veyon přihlášení + Name + Název - Authentication error - Chyba ověření + Description + Popis - Logon failed with given username and password. Please try again! - Přihlášení daným uživatelským jménem a heslem se nezdařilo. Zkuste to znovu! + Version + Verze - Please enter your username and password in order to access computers. - Zadejte své uživatelské jméno a heslo pro přístup k počítačům. + UID + + + + Plugin-related CLI operations + Operace v příkazovém řádku související se zásuvným modulem + + + Commands for managing plugins + Příkazy pro správu zásuvných modulů @@ -3382,10 +3811,6 @@ POUŽITÍ Do you really want to reboot the selected computers? Opravdu chcete vybrané počítače restartovat? - - Do you really want to power down the selected computer? - Opravdu chcete vybrané počítače vypnout? - Power on a computer via Wake-on-LAN (WOL) Zapnout počítač prostřednictvím probouzení po síti (WoL) @@ -3438,6 +3863,18 @@ Please save your work and close all programs. Uložte si rozdělanou práci a ukončete všechny aplikace. + + Do you really want to reboot <b>ALL</b> computers? + + + + Do you really want to power down <b>ALL</b> computers? + + + + Do you really want to power down the selected computers? + + PowerDownTimeInputDialog @@ -3484,14 +3921,25 @@ Uložte si rozdělanou práci a ukončete všechny aplikace. Remote view or control a computer Pohled na nebo ovládání počítače na dálku - - Please enter the hostname or IP address of the computer to access: - Zadejte název nebo IP adresu počítače ke kterému přistoupit: - Show help about command Zobrazit nápovědu k příkazu + + Exchange clipboard contents + + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + + + RemoteAccessPage + + Remote access: %1 + Přístup na dálku: %1 + RemoteAccessWidget @@ -3499,6 +3947,10 @@ Uložte si rozdělanou práci a ukončete všechny aplikace. %1 - %2 Remote Access %1 – %2 vzdálený přístup + + %1 - %2 - %3 Remote Access + + RemoteAccessWidgetToolBar @@ -3554,10 +4006,6 @@ Uložte si rozdělanou práci a ukončete všechny aplikace. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - Připojování k %1… - Connected. Připojeno. @@ -3570,58 +4018,17 @@ Uložte si rozdělanou práci a ukončete všechny aplikace. Exit Ukončit - - - Routing - - Control internet access by modifying routing table - Ovládá přístup k Internetu prostřednictvím upravování směrovacích tabulek - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - Odebrat výchozí trasy pro blokování přístupu k Internetu - - - Add custom route to block internet - Přidat uživatelsky určenou trasu pro blokování přístupu k Internetu - - - Destination - Cíl - - - Gateway - Brána - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - Zadejte aplikace nebo příkazy které mají být spuštěné na označených počítačích. Každou z aplikací/příkazů uvádějte na samostatný řádek - - - Run programs - Spustit aplikace - - - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - např.: "C:\Program Files\VideoLAN\VLC\vlc.exe" - - Name: - Název: + Connecting... + - Remember and add to program menu - Zapamatovat a přidat do nabídky programů + Select screen + - e.g. VLC - např. VLC + All screens + @@ -3642,6 +4049,18 @@ Uložte si rozdělanou práci a ukončete všechny aplikace. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. Abyste upoutali plnou pozornost všech uživatelů, můžete jim pomocí tohoto tlačítka uzamknout jejich počítače. Ty v tomto režimu nebudou reagovat na klávesnici a myš a jejich obrazovky potemní. + + Lock input devices + Uzamknout vstupní zařízení + + + Unlock input devices + + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + Screenshot @@ -3657,6 +4076,10 @@ Uložte si rozdělanou práci a ukončete všechny aplikace. Screenshot Snímek obrazovky + + Could not open screenshot file %1 for writing. + + ScreenshotFeaturePlugin @@ -3681,6 +4104,13 @@ Uložte si rozdělanou práci a ukončete všechny aplikace. Pořizovat snímky obrazovek počítačů a ukládat je místně. + + ScreenshotManagementPage + + Screenshots + Snímky obrazovky + + ScreenshotManagementPanel @@ -3708,144 +4138,241 @@ Uložte si rozdělanou práci a ukončete všechny aplikace. Zobrazit - Delete - Smazat + Delete + Smazat + + + Screenshot + Snímek obrazovky + + + Do you really want to delete all selected screenshots? + + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + + + + User has denied access + + + + User confirmed access + + + + + ServiceConfigurationPage + + General + Obecné + + + Autostart + Spouštět automaticky + + + Hide tray icon + Skrýt ikonu v oznamovací oblasti + + + Start service + Spustit službu + + + Stopped + Zastaveno + + + Stop service + Zastavit službu + + + State: + Stav: + + + Enable firewall exception + Vytvořit výjimku na bráně firewall + + + Allow connections from localhost only + Umožnit připojení pouze v rámci tohoto počítače (localhost) + + + VNC server + VNC server + + + Plugin: + Zásuvný modul: + + + Restart %1 Service + Restartovat službu %1 + + + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + Všechna nastavení byla úspěšně uložena. Aby se změny projevily, je třeba restartovat službu %1 – provést nyní? + + + Running + Spuštěné + + + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. + Zapnutím této volby bude serverový proces spouštěn pro každé z interaktivních sezení na počítači. +Typicky je toto třeba na terminálových serverech. + + + Show notification on remote connection + Zobrazovat upozornění na připojení na dálku - - - ServiceConfigurationPage - General - Obecné + Show notification when an unauthorized access is blocked + Zobrazit oznámení když je zablokován nepověřený přístup - Autostart - Spouštět automaticky + Maximum session count + - Hide tray icon - Skrýt ikonu v oznamovací oblasti + Network port numbers + - Start service - Spustit službu + Veyon server + - Stopped - Zastaveno + Internal VNC server + - Stop service - Zastavit službu + Feature manager + - State: - Stav: + Demo server + Ukázkový server - Network - Síť + Miscellaneous network settings + - Demo server port - Port ukázkového serveru + Session mode + - Enable firewall exception - Vytvořit výjimku na bráně firewall + Local session mode (single server instance for primary local session) + - Allow connections from localhost only - Umožnit připojení pouze v rámci tohoto počítače (localhost) + Active session mode (single server instance for active local or remote session) + - Internal VNC server port - Port vnitřního VNC serveru + Multi session mode (distinct server instance for each local and remote desktop session) + - VNC server - VNC server + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + - Plugin: - Zásuvný modul: + Miscellaneous settings + - Restart %1 Service - Restartovat službu %1 + Disable clipboard synchronization + - All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - Všechna nastavení byla úspěšně uložena. Aby se změny projevily, je třeba restartovat službu %1 – provést nyní? + Session metadata + - Running - Spuštěné + Content + - Feature manager port - Port správce funkce + None + Žádné - Primary service port - Port hlavní služby + Value of an environment variable + - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. - Zapnutím této volby bude serverový proces spouštěn pro každé z interaktivních sezení na počítači. -Typicky je toto třeba na terminálových serverech. + Value of a registry key + - Show notification on remote connection - Zobrazovat upozornění na připojení na dálku + Environment variable name: + - Multi session mode (for terminal and remote desktop servers) - Režim vícero relací (pro terminály a servery pro vzdálenou plochu) + Registry key name: + - Show notification when an unauthorized access is blocked - Zobrazit oznámení když je zablokován nepověřený přístup + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + ServiceControl - Starting service %1 - Spouštění služby %1 - - - Stopping service %1 - Zastavování služby %1 - - - Registering service %1 - Registrace služby %1 + Service control + Řízení služby - Unregistering service %1 - Rušení registrace služby %1 + Starting %1 + - Service control - Řízení služby + Stopping %1 + - - - ServiceControlPlugin - Service is running - Služba je spuštěná + Restarting %1 + - Service is not running - Služba není spuštěná + Registering %1 + - Configure and control Veyon service - Nastavit a ovládat službu Veyon + Unregistering %1 + + + + ServiceControlCommands Register Veyon Service Zaregistrovat službu Veyon @@ -3870,13 +4397,25 @@ Typicky je toto třeba na terminálových serverech. Query status of Veyon Service Dotázat se na stav služby Veyon + + Service is running + Služba je spuštěná + + + Service is not running + Služba není spuštěná + + + Configure and control Veyon service + Nastavit a ovládat službu Veyon + Commands for configuring and controlling Veyon Service Přikazy pro nastavování a ovládání služby Veyon - ShellCommandLinePlugin + ShellCommands Run command file Spustit příkazový soubor @@ -3886,14 +4425,100 @@ Typicky je toto třeba na terminálových serverech. Soubor „%1“ neexistuje! - Interactive shell and script execution for Veyon Control - Interaktivní vykonávání shellu a skriptu pro ovládání Veyon + Interactive shell and script execution for Veyon CLI + Commands for shell functionalities Příkazy pro shellové funkce + + SlideshowPanel + + Previous + + + + Start/pause + + + + Next + + + + Duration: + + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + + + + Remove selected computers + + + + Update computers in realtime + + + + Spotlight + + + + Please select at least one computer to add. + + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + + + StartAppDialog + + Start application + + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + např.: "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + + + + Application name + + + + Name: + Název: + + + e.g. VLC + např. VLC + + SystemTrayIcon @@ -3930,8 +4555,8 @@ Typicky je toto třeba na terminálových serverech. Poslat textovou zprávu - Use the field below to type your message which will be sent to all selected users. - Do kolonky níže zadejte svou zprávu, určenou všem označeným uživatelům. + Please enter your message which send to all selected users. + @@ -3979,23 +4604,39 @@ Typicky je toto třeba na terminálových serverech. Enable Desktop Duplication Engine on Windows 8 and newer Zapnout Desktop Duplication Engine na Windows 8 a novějších + + Maximum CPU usage + + - UserConfig + UserLoginDialog - No write access - Do daného umístění nelze zapisovat + User login + Přihlášení uživatele - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - Nedaří se uložit vaše osobní nastavení! Zkontrolujte popis umístění souboru s uživatelskými nastaveními v nastavení %1. + Please enter a username and password for automatic login on all computers. + Zadejte uživatelské jméno a heslo pro automatické přihlášení na všechny počítače. + + + Username + Uživatelské jméno + + + Password + Heslo - UserSessionControl + UserSessionControlPlugin - User session control - Ovládání relace uživatele + Log in + Přihlásit + + + Click this button to log in a specific user on all computers. + Kliknutím na toto tlačítko se přihlásíte jako konkrétní uživatel na všechny počítače. Log off @@ -4013,6 +4654,14 @@ Typicky je toto třeba na terminálových serverech. Do you really want to log off the selected users? Opravdu chcete označené uživatele odhlásit? + + User session control + Ovládání relace uživatele + + + Do you really want to log off <b>ALL</b> users? + + VeyonCore @@ -4064,10 +4713,6 @@ Typicky je toto třeba na terminálových serverech. ERROR CHYBA - - licensed for - licencováno pro - USAGE POUŽITÍ @@ -4084,19 +4729,31 @@ Typicky je toto třeba na terminálových serverech. WARNING VAROVÁNÍ + + Authentication test + Vyzkoušení ověřování + + + Screen %1 + + - VeyonServiceControl + VeyonMaster - Veyon Service - Služba Veyon + No write access + Do daného umístění nelze zapisovat + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Nedaří se uložit vaše osobní nastavení! Zkontrolujte popis umístění souboru s uživatelskými nastaveními v nastavení %1. - VncView + VeyonServiceControl - Establishing connection to %1 ... - Připojování k %1… + Veyon Service + Služba Veyon @@ -4144,6 +4801,30 @@ Typicky je toto třeba na terminálových serverech. Use alternative user authentication mechanism Použít alternativní mechanizmus ověřování uživatelů + + User login + Přihlášení uživatele + + + Input start delay + Prodleva začátku vstupu + + + Simulated key presses interval + Interval simulovaných stisků kláves + + + Confirm legal notice (message displayed before user logs in) + Potvrďte právní upozornění (zprávu zobrazovanou před tím, než se uživatel přihlásí) + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4152,7 +4833,7 @@ Typicky je toto třeba na terminálových serverech. Zásuvný modul implementující abstrahující funkce pro platformu Windows - Plugin implementing specific functions for the Windows platform + Internal display @@ -4162,30 +4843,34 @@ Typicky je toto třeba na terminálových serverech. The service "%1" is already installed. Služba „%1“ je už nainstalovaná. - - The service "%1" could not be installed. - Službu „%1“ se nepodařilo nainstalovat - The service "%1" has been installed successfully. Služba „%1“ byla úspěšně nainstalována. - - The service "%1" could not be uninstalled. - Službu „%1“ se nepodařilo odinstalovat. - The service "%1" has been uninstalled successfully. Služba „%1“ byla úspěšně odinstalována. - - The start type of service "%1" could not be changed. - Typ spouštění služby „%1“ nemůže být změněn. - Service "%1" could not be found. Službu „%1“ se nedaří najít. + + The service "%1" could not be installed (error %2). + + + + Could not change the failure actions config for service "%1" (error %2). + + + + The service "%1" could not be uninstalled (error %2). + + + + The start type of service "%1" could not be changed (error %2). + + X11VncConfigurationWidget diff --git a/translations/de.ts b/translations/veyon_de.ts similarity index 73% rename from translations/de.ts rename to translations/veyon_de.ts index 8d7633fd3..b977405ce 100644 --- a/translations/de.ts +++ b/translations/veyon_de.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -78,10 +78,6 @@ If you're interested in translating Veyon into your local or another langua All groups Alle Gruppen - - ... - ... - Access control rules Zugriffskontrollregeln @@ -138,19 +134,18 @@ If you're interested in translating Veyon into your local or another langua User groups backend: Benutzergruppen-Backend: - - Missing user groups backend - Fehlendes Benutzergruppen-Backend - - - No default user groups plugin was found. Please check your installation! - Es wurde kein Benutzergruppen-Plugin gefunden. Bitte überprüfen Sie Ihre Installation! - Restrict access to members of specific user groups Zugriff auf Mitglieder bestimmter Benutzergruppen einschränken + + AccessControlProvider + + Provider for access control features + Anbieter für Zugriffskontrollfunktionen + + AccessControlRuleEditDialog @@ -177,30 +172,10 @@ If you're interested in translating Veyon into your local or another langua Rule description: Regelbeschreibung: - - Invert all conditions ("is/has" interpreted as "is/has not") - Alle Bedingungen umkehren ("ist/hat" wird als "ist/hat nicht" interpretiert) - Conditions Bedingungen - - is member of group - ist Mitglied von Gruppe - - - Accessing computer is localhost - Zugreifender Computer ist localhost - - - Accessing user is logged on user - Zugreifender Benutzer ist angemeldeter Benutzer - - - Accessing user is already connected - Zugreifender Benutzer ist bereits verbunden - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. Wenn mehr als eine Bedingung aktiviert wird muss jede Bedingung zutreffen, damit die Regel angewendet wird (logisches UND). Wenn nur eine von mehreren Regeln zutreffen soll (logisches ODER) erstellen Sie bitte mehrere Zugriffskontrollregeln. @@ -234,33 +209,125 @@ If you're interested in translating Veyon into your local or another langua Zugreifender Computer - Local (logged on) user - Lokaler (angemeldeter) Benutzer + Always process rule and ignore conditions + Regel immer verarbeiten und Bedingungen ignorieren - Local computer - Lokaler Computer + Accessing computer and local computer + Zugreifender und lokaler Computer - Always process rule and ignore conditions - Regel immer verarbeiten und Bedingungen ignorieren + User being accessed + Benutzer, auf den zugegriffen wird - No user logged on - Kein Benutzer angemeldet + is logged in locally + ist lokal angemeldet - Accessing user has one or more groups in common with local (logged on) user - Zugreifender Benutzer hat eine oder mehrere gemeinsame Gruppen mit lokalem (angemeldeten) Benutzer + is logged in remotely + ist aus der Ferne angemeldet - Accessing computer and local computer are at the same location - Zugreifender Computer und lokaler Computer befinden sich am selben Standort + No user is logged in locally + Kein Benutzer ist lokal angemeldet + + + One or multiple users are logged in locally + Ein oder mehrere Benutzer sind lokal angemeldet + + + No user is logged in remotely + Kein Benutzer ist aus der Ferne angemeldet + + + One or multiple users are logged in remotely + Ein oder mehrere Benutzer sind aus der Ferne angemeldet is located at befindet sich in + + is not located at + befindet sich nicht in + + + are located at the same location + befinden sich am selben Standort + + + are not located the same location + befinden sich nicht am selben Standort + + + is member of group + ist Mitglied der Gruppe + + + is not member of group + ist nicht Mitglied der Gruppe + + + is authenticated via + ist authentifiziert über + + + is not authenticated via + ist nicht authentifiziert über + + + has one or more groups in common with user being accessed + hat gemeinsame Gruppen mit dem Benutzer, auf den zugegriffen wird + + + has no groups in common with user being accessed + hat keine gemeinsame Gruppen mit dem Benutzer, auf den zugegriffen wird + + + equals user being accessed + entspricht Benutzer, auf den zugegriffen wird + + + is different from user being accessed + unterscheidet sich von Benutzer, auf den zugegriffen wird + + + is already connected + ist bereits verbunden + + + is not connected + ist nicht verbunden + + + is local computer + ist lokaler Computer + + + is not local computer + ist nicht lokaler Computer + + + Computer being accessed + Computer, auf den zugegriffen wird + + + Session being accessed is a user session + Sitzung, auf die zugegriffen wird, ist eine Benutzersitzung + + + Session being accessed is a login screen + Sitzung, auf die zugegriffen wird, ist ein Anmeldebildschirm + + + Local computer is already being accessed + Auf den lokalen Computer wird bereits zugegriffen + + + Local computer is not yet being accessed + Auf den lokalen Computer wird noch nicht zugegriffen + AccessControlRulesTestDialog @@ -304,42 +371,44 @@ If you're interested in translating Veyon into your local or another langua The access in the given scenario needs permission of the logged on user. Der Zugriff benötigt im angegebenen Szenario die Erlaubnis des angemeldeten Benutzers. - - ERROR: Unknown action - FEHLER: Unbekannte Aktion - Test result Testergebnis - - - AndroidPlatformConfigurationPage - Android - Android + Authentication method + Authentifizierungsmethode - General - Allgemein + There is no matching rule with a valid action. The access is therefore denied. + Es gibt keine zutreffende Regel mit einer gültigen Aktion. Der Zugriff wird daher verweigert. - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - Plugin zur Implementierung spezifischer Funktionen für die Android-Plattform + Introduction + Einführung - - - AuthKeysConfigurationPage - Authentication keys - Authentifizierungsschlüssel + Please perform the following steps to set up key file authentication: + Bitte führen Sie die folgenden Schritte durch, um die Schlüsseldatei-Authentifizierung einzurichten: - Introduction - Einführung + 1) Create a key pair on the master computer. + 1) Schlüsselpaar auf dem Master-Computer erzeugen. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Zugriffsgruppe festlegen, deren Mitgliedern der Zugriff auf andere Computer erlaubt werden soll. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Öffentlichen Schlüssel exportieren und auf allen Client-Computern mit dem selben Namen importieren. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Weitere Informationen entnehmen Sie bitte dem <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon-Administrationshandbuch</a>. Key file directories @@ -347,20 +416,25 @@ If you're interested in translating Veyon into your local or another langua Public key file base directory - Basisverzeichnis für öffentliche Schlüsseldateien + Basisverzeichnis der öffentlichen Schlüsseldatei Private key file base directory - Basisverzeichnis für private Schlüsseldateien - - - ... - ... + Basisverzeichnis der privaten Schlüsseldatei Available authentication keys Verfügbare Authentifizierungsschlüssel + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Ein Authentifizierungsschlüsselpaar besteht aus zwei zueinander gehörigen Teilen, einem privaten und einem öffentlichen Schlüsselteil. +Mit Hilfe des privaten Schlüssels können Nutzer auf dem Mastercomputer auf Clientcomputer zugreifen. Es ist wichtig, dass nur autorisierte Nutzer Lesezugriff auf die private Schlüsseldatei besitzen. +Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede eingehende Verbindungsanfrage zu prüfen, ob diese autorisiert ist. + Create key pair Schlüsselpaar erzeugen @@ -401,10 +475,6 @@ If you're interested in translating Veyon into your local or another langua Please select a key to delete! Bitte wählen Sie den zu löschenden Schlüssel! - - Please enter the name of the user group or role for which to import the authentication key: - Bitte geben Sie den Namen der Benutzergruppe oder -rolle ein, für die ein Authentifizierungsschlüssel importiert werden soll: - Please select a key to export! Bitte wählen Sie den zu exportierenden Schlüssel! @@ -418,33 +488,12 @@ If you're interested in translating Veyon into your local or another langua Bitte wählen Sie den Schlüssel, für den die Zugriffsgruppe gesetzt werden soll! - Please perform the following steps to set up key file authentication: - Bitte führen Sie die folgenden Schritte durch, um die Schlüsseldatei-Authentifizierung einzurichten: - - - 1) Create a key pair on the master computer. - 1) Schlüsselpaar auf dem Master-Computer erzeugen. - - - 2) Set an access group whose members should be allowed to access other computers. - 2) Zugriffsgruppe festlegen, deren Mitgliedern der Zugriff auf andere Computer erlaubt werden soll. - - - 3) Export the public key and import it on all client computers with the same name. - 3) Öffentlichen Schlüssel exportieren und auf allen Client-Computern mit dem selben Namen importieren. - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - Weitere Informationen entnehmen Sie bitte dem <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon-Administrationshandbuch</a>. - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - Ein Authentifizierungsschlüsselpaar besteht aus zwei zueinander gehörigen Teilen, einem privaten und einem öffentlichen Schlüsselteil. -Mit Hilfe des privaten Schlüssels können Nutzer auf dem Mastercomputer auf Clientcomputer zugreifen. Es ist wichtig, dass nur autorisierte Nutzer Lesezugriff auf die private Schlüsseldatei besitzen. -Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede eingehende Verbindungsanfrage zu prüfen, ob diese autorisiert ist. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + Bitte geben Sie den Namen der Benutzergruppe oder -rolle an, für die der Authentifizierungsschlüssel importiert werden soll. + +Achten Sie darauf, dass die Namen der zueinander gehörenden Schlüssel auf allen Computern identisch sind. @@ -644,10 +693,6 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. Dieser Befehl listet alle verfügbaren Authentifizierungsschlüssel im konfigurierten Schlüsselverzeichnis auf. Wenn die Option "%1" angegeben wird, wird stattdessen eine Tabelle mit Schlüsseldetails ausgegeben. Einige Details können fehlen, wenn auf einen Schlüssel nicht zugegriffen werden kann, z.B. aufgrund fehlender Leserechte. - - Please specify the command to display help for! - Bitte geben Sie den Befehl an, für den Hilfe angezeigt werden soll! - TYPE TYP @@ -656,10 +701,6 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e PAIR ID PAAR-ID - - Command line support for managing authentication keys - Kommandozeilenunterstützung zur Verwaltung von Authentifizierungsschlüsseln - Commands for managing authentication keys Befehle zur Verwaltung von Authentifizierungsschlüsseln @@ -676,6 +717,30 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. Dieser Befehl extrahiert den öffentlichen Schlüsselteil aus dem privaten Schlüssel ``<SCHLÜSSEL>`` und speichert ihn als den zugehörigen öffentlichen Schlüssel. Bei der Einrichtung eines weiteren Mastercomputers genügt somit die Übertragung des privaten Schlüssels. Anschließend kann der öffentliche Schlüssel extrahiert werden. + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + Authentifizierungsschlüssel sind auf diesem Computer nicht ordnungsgemäß eingerichtet. Bitte erstellen Sie neue Schlüsseldateien oder wechseln zu einer anderen Authentifizierungsmethode mit Hilfe des Veyon Configurators. + + + Key file authentication + Schlüsseldatei-Authentifizierung + + + Key file + Schlüsseldatei + + + Please specify the key name (e.g. "teacher/public") as the first argument. + Bitte geben Sie den Schlüsselname (z.B. "teacher/public") als erstes Argument an. + + + Please specify the command to display help for. + Bitte geben Sie den Befehl an, für den Hilfe angezeigt werden soll. + + + The specified command does not exist or no help is available for it. + Der angegebene Befehl existiert nicht oder es ist keine Hilfe für ihn verfügbar. + AuthKeysTableModel @@ -697,97 +762,240 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - Computer + General + Allgemein - Name - Name + Username to bind DN mapping: + Zuordnung Benutzername zu Bind-DN: - Host address/IP - Hostadresse/IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + z.B. %username%@DOMAIN oder cn=%username%,ou=users,dc=example,dc=org + + + AuthLdapDialog - MAC address - MAC-Adresse + Veyon Logon + Veyon-Anmeldung - Add new computer - Neuen Computer hinzufügen + Please enter your domain/LDAP username and password in order to access computers. + Bitte geben Sie Ihren Domain/LDAP-Benutzernamen und Passwort ein, um auf Computer zuzugreifen. - Remove selected computer - Gewählten Computer entfernen + Username + Benutzername - New computer - Neuer Computer + Password + Passwort - Builtin directory - Integriertes Verzeichnis + Authentication error + Authentifizierungsfehler - Locations & computers - Standorte & Computer + Logon failed with given username and password. Please try again! + Die Anmeldung mit dem angegebenen Benutzername und Passwort ist fehlgeschlagen. Bitte versuchen Sie es erneut! + + + AuthLogonDialog - Locations - Standorte + Veyon Logon + Veyon-Anmeldung - Add new location - Neuen Standort hinzufügen + Please enter your username and password in order to access computers. + Bitte geben Sie Ihren Benutzernamen und Passwort ein, um auf Computer zuzugreifen. - Remove selected location - Gewählten Standort entfernen + Username + Benutzername - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - Der Import von CSV-Dateien ist über die Kommandozeilenschnittstelle möglich. Weitere Informationen finden Sie in der <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">Online-Dokumentation</a>. + Password + Passwort - New location - Neuer Standort + Authentication error + Authentifizierungsfehler + + + Logon failed with given username and password. Please try again! + Die Anmeldung mit dem angegebenen Benutzername und Passwort ist fehlgeschlagen. Bitte versuchen Sie es erneut! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command - Hilfe für bestimmten Befehl anzeigen + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Der angegebene Benutzername oder das Passwort ist falsch. Bitte geben Sie gültige Zugangsdaten ein oder wechseln zu einer anderen Authentifizierungsmethode mit Hilfe des Veyon Configurators. - Import objects from given file - Objekte aus angegebener Datei importieren + Logon authentication + Anmelde-Authentifizierung - Export objects to given file - Objekte in angegebene Datei exportieren + Logon + Anmeldung + + + AuthSimpleDialog - Invalid type specified. Valid values are "%1" or "%2". - Ungültiger Typ angegeben. Gültige Werte sind "%1" oder "%2". + Veyon Logon + Veyon-Anmeldung - Type - Typ + Please enter the Veyon password: + Bitte geben Sie das Veyon-Passwort ein: - Name - Name + Authentication error + Authentifizierungsfehler - Host address - Hostadresse + Logon failed with given password. Please try again! + Anmeldung mit dem angegebenen Passwort fehlgeschlagen. Bitte versuchen Sie es erneut! + + + AuthSimplePlugin - MAC address - MAC-Adresse + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + Das angegebene Passwort ist falsch. Bitte geben Sie das richtige Passwort ein oder wechseln zu einer anderen Authentifizierungsmethode mit Hilfe des Veyon Configurators. + + + Simple password authentication + Einfache Passwortauthentifizierung + + + Simple password + Einfaches Passwort + + + + AuthenticationPage + + Authentication is set up properly on this computer. + Authentifizierung ist auf diesem Computer ordnungsgemäß eingerichtet. + + + + AuthenticationPageTab + + Enabled + Aktiviert + + + Test + Testen + + + + BuiltinDirectoryConfiguration + + Builtin directory + Integriertes Verzeichnis + + + + BuiltinDirectoryConfigurationPage + + Computers + Computer + + + Name + Name + + + Host address/IP + Hostadresse/IP + + + MAC address + MAC-Adresse + + + Add new computer + Neuen Computer hinzufügen + + + Remove selected computer + Gewählten Computer entfernen + + + New computer + Neuer Computer + + + Builtin directory + Integriertes Verzeichnis + + + Locations + Standorte + + + Add new location + Neuen Standort hinzufügen + + + Remove selected location + Gewählten Standort entfernen + + + New location + Neuer Standort + + + Directory name + Verzeichnisname + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + Der Import von CSV-Dateien ist über die Kommandozeilenschnittstelle möglich. Weitere Informationen finden Sie in der <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">Online-Dokumentation</a>. + + + + BuiltinDirectoryPlugin + + Show help for specific command + Hilfe für bestimmten Befehl anzeigen + + + Import objects from given file + Objekte aus angegebener Datei importieren + + + Export objects to given file + Objekte in angegebene Datei exportieren + + + Invalid type specified. Valid values are "%1" or "%2". + Ungültiger Typ angegeben. Gültige Werte sind "%1" oder "%2". + + + Type + Typ + + + Name + Name + + + Host address + Hostadresse + + + MAC address + MAC-Adresse Specified object not found. @@ -997,6 +1205,14 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e MAC ADDRESS MAC-ADRESSE + + The specified command does not exist or no help is available for it. + Der angegebene Befehl existiert nicht oder es ist keine Hilfe für ihn verfügbar. + + + Location "%1" not found. + Standort "%1" nicht gefunden. + BuiltinUltraVncServer @@ -1014,10 +1230,6 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e ComputerControlListModel - - Host/IP address: %1 - Host-/IP-Adresse: %1 - Active features: %1 Aktive Funktionen: %1 @@ -1034,10 +1246,6 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Computer offline or switched off Computer offline oder ausgeschalten - - Service unreachable or not running - Dienst nicht erreichbar oder läuft nicht - Authentication failed or access denied Authentifizierung fehgeschlagen oder Zugriff verweigert @@ -1058,6 +1266,38 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Location: %1 Standort: %1 + + [no user] + [Kein Benutzer] + + + Veyon Server unreachable or not running + Veyon-Server nicht erreichbar oder läuft nicht + + + Name: %1 + Name: %1 + + + Hostname: %1 + Hostname: %1 + + + unknown + unbekannt + + + IP address: %1 + IP-Adresse: %1 + + + Hostname could not be resolved + Hostname konnte nicht aufgelöst werden + + + No features active + Keine Funktionen aktiv + ComputerControlServer @@ -1089,6 +1329,17 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. Der Benutzer "%1" am Computer "%2" hat versucht, auf diesen Computer zuzugreifen, wurde aber aufgrund von Zugriffskontrolleneinstellungen blockiert. + + Active connections: + Aktive Verbindungen: + + + + ComputerGroupSelector + + Group %1 + Gruppe %1 + ComputerManager @@ -1116,13 +1367,48 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. Der Standort dieses Computers konnte nicht ermittelt werden. Das deutet auf ein Problem mit der Systemkonfiguration hin. Stattdessen werden alle Standorte im Computerauswahlbedienfeld angezeigt. + + Logged in since + Angemeldet seit + + + %1 days + %1 Tage + + + 1 day + 1 Tag + - ComputerSelectPanel + ComputerMonitoring + + Computers + Computer + + + Search users and computers + Benutzer und Computer suchen + + + Select all + Alle auswählen + + + Unselect all + Alle abwählen + + + Add to group + Zu Gruppe hinzufügen + - Computer management - Computerverwaltung + Remove from group + Aus Gruppe entfernen + + + ComputerSelectPanel Computer search Computersuche @@ -1151,81 +1437,85 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Could not write the computer and users list to %1! Please check the file access permissions. Die Computer- und Benutzerliste konnte nicht in die Datei %1 geschrieben werden. Bitte überprüfen Sie die Dateizugriffsrechte. + + Search computers + Computer suchen + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. - Bitte geben Sie eine existierende Konfigurationsdatei für den Import an. + Clear system-wide Veyon configuration + Systemweite Veyon-Konfiguration löschen - Please specify a valid filename for the configuration export. - Bitte geben Sie einen gültigen Dateinamen für den Konfigurationsexport an. + List all configuration keys and values + Alle Konfigurationsschlüssel und -werte auflisten - Please specify a valid key. - Bitte geben Sie einen gültigen Schlüssel ein. + Import configuration from given file + Konfiguration aus angegebener Datei importieren - Specified key does not exist in current configuration! - Der angegebene Schlüssel existiert in der derzeitigen Konfiguration nicht! + Export configuration to given file + Konfiguration in angegebene Datei exportieren - Please specify a valid value. - Bitte geben Sie einen gültigen Wert ein. + Read and output configuration value for given key + Konfigurationswert für gegebenen Schlüssel lesen und ausgeben - Configure Veyon at command line - Veyon auf der Kommandozeile konfigurieren + Write given value to given configuration key + Angegebenen Wert in angegebenen Konfigurationsschlüssel schreiben - Output file is not writable! - Ausgabedatei ist nicht schreibbar! + Unset (remove) given configuration key + Angegebenen Konfigurationsschlüssel zurücksetzen (löschen) - Output directory is not writable! - Ausgabeverzeichnis ist nicht schreibbar! + Upgrade and save configuration of program and plugins + Konfiguration von Programm und Plugins aktualisieren und speichern + + + Please specify an existing configuration file to import. + Bitte geben Sie eine existierende Konfigurationsdatei für den Import an. Configuration file is not readable! Konfigurationsdatei ist nicht lesbar! - Clear system-wide Veyon configuration - Systemweite Veyon-Konfiguration löschen + Please specify a valid filename for the configuration export. + Bitte geben Sie einen gültigen Dateinamen für den Konfigurationsexport an. - List all configuration keys and values - Alle Konfigurationsschlüssel und -werte auflisten + Output file is not writable! + Ausgabedatei ist nicht schreibbar! - Import configuration from given file - Konfiguration aus angegebener Datei importieren + Output directory is not writable! + Ausgabeverzeichnis ist nicht schreibbar! - Export configuration to given file - Konfiguration in angegebene Datei exportieren + Please specify a valid key. + Bitte geben Sie einen gültigen Schlüssel ein. - Read and output configuration value for given key - Konfigurationswert für gegebenen Schlüssel lesen und ausgeben + Specified key does not exist in current configuration! + Der angegebene Schlüssel existiert in der derzeitigen Konfiguration nicht! - Write given value to given configuration key - Angegebenen Wert in angegebenen Konfigurationsschlüssel schreiben + Please specify a valid value. + Bitte geben Sie einen gültigen Wert ein. - Unset (remove) given configuration key - Angegebenen Konfigurationsschlüssel zurücksetzen (löschen) + Configure Veyon at command line + Veyon auf der Kommandozeile konfigurieren Commands for managing the configuration of Veyon Befehle zur Verwaltung der Veyon-Konfiguration - - Upgrade and save configuration of program and plugins - Konfiguration von Programm und Plugins aktualisieren und speichern - ConfigurationManager @@ -1249,6 +1539,10 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Could not apply platform-specific configuration settings. Die plattformspezifischen Konfigurationseinstellungen konnten nicht angewendet werden. + + Could not configure the firewall configuration for the %1 Service. + Die Firewall-Einstellungen für den %1 Service konnten nicht geändert werden. + DemoClient @@ -1279,10 +1573,6 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Memory limit Speicherlimit - - Use multithreading (experimental) - Multithreading benutzen (experimentell) - MB MB @@ -1299,13 +1589,17 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Slow down thumbnail updates while demo is running Miniaturbildaktualisierungen während laufender Demo verlangsamen + + Bandwidth limit + Bandbreitenbeschränkung + + + MB/s + MB/s + DemoFeaturePlugin - - Fullscreen demo - Vollbild-Demo - Stop demo Demo beenden @@ -1319,16 +1613,60 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Eine Präsentation durch Bildschirmübertragung - Demo server - Demo-Server + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + In diesem Modus wird Ihr Bildschirm in einem Fenster auf allen Computern angezeigt. Die Benutzer können bei Bedarf zu anderen Fenstern wechseln. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - In diesem Modus wird Ihr Bildschirm als Vollbild auf allen Computern angezeigt während die Eingabegeräte der Benutzer gesperrt werden. + Demo + Demo - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - In diesem Modus wird Ihr Bildschirm in einem Fenster auf allen Computern angezeigt. Die Benutzer können bei Bedarf zu anderen Fenstern wechseln. + Share your screen or allow a user to share his screen with other users. + Eigenen Bildschirm teilen oder einem Benutzer erlauben, seinen Bildschirm mit anderen Benutzern zu teilen. + + + Full screen demo + Vollbild-Demo + + + Share your own screen in fullscreen mode + Eigenen Bildschirm im Vollbildmodus teilen + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + In diesem Modus wird Ihr Bildschirm im Vollbild auf allen Computern angezeigt, während die Eingabegeräte der Benutzer gesperrt werden. + + + Share your own screen in a window + Eigenen Bildschirm in einem Fenster teilen + + + Share selected user's screen in fullscreen mode + Bildschirm des ausgewählten Benutzers im Vollbild teilen + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + In diesem Modus wird der Bildschirm des gewählten Benutzers im Vollbild auf allen Computern angezeigt, während die Eingabegeräte der Benutzer gesperrt werden. + + + Share selected user's screen in a window + Bildschirm des ausgewählten Benutzers in einem Fenster teilen + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + In diesem Modus wird der Bildschirm des gewählten Benutzers in einem Fenster auf allen Computern angezeigt. Die Benutzer können bei Bedarf zu anderen Fenstern wechseln. + + + Please select a user screen to share. + Bitte wählen Sie einen Benutzer, dessen Bildschirm geteilt werden soll. + + + Please select only one user screen to share. + Bitte wählen Sie nur einen Benutzer-Bildschirm zum Teilen. + + + All screens + Alle Bildschirme @@ -1356,14 +1694,6 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e DesktopServicesConfigurationPage - - Programs & websites - Programme & Webseiten - - - Predefined programs - Vordefinierte Programme - Name Name @@ -1372,41 +1702,49 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Path Pfad - - Add new program - Neues Programm hinzufügen - - - Remove selected program - Ausgewähltes Programm entfernen - Predefined websites Vordefinierte Webseiten Remove selected website - Ausgewählte Webseite entfernen + Ausgewählte Webseiten entfernen URL URL - - New program - Neues Programm - New website Neue Webseite + + Applications & websites + Anwendungen & Webseiten + + + Predefined applications + Vordefinierte Anwendungen + + + Add new application + Neue Anwendung hinzufügen + + + Remove selected application + Gewählte Anwendung entfernen + + + Add new website + Neue Website hinzufügen + + + New application + Neue Anwendung + DesktopServicesFeaturePlugin - - Run program - Programm starten - Open website Webseite öffnen @@ -1416,28 +1754,32 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Klicken Sie auf diesen Button, um eine Webseite auf allen Computern zu öffnen. - Start programs and services in user desktop - Programme und Dienste im Benutzerdesktop starten + Open website "%1" + Webseite "%1" öffnen - Click this button to run a program on all computers. - Klicken Sie auf diesen Button, um Programme auf allen Computern zu starten. + Custom website + Benutzerdefinierte Webseite - Run program "%1" - Programm "%1" ausführen + Start application + Anwendung starten - Custom program - Benutzerdefiniertes Programm + Click this button to start an application on all computers. + Klicken Sie auf diesen Button, um eine Anwendung auf allen Computern zu starten. - Open website "%1" - Webseite "%1" öffnen + Start application "%1" + Anwendung "%1" ausführen - Custom website - Benutzerdefinierte Webseite + Custom application + Benutzerdefinierte Anwendung + + + Start apps and open websites in user sessions + Anwendungen starten und Webseiten öffnen in Benutzersitzungen @@ -1470,10 +1812,6 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Play tutorial video Tutorial-Video abspielen - - Custom program - Benutzerdefiniertes Programm - Handout Arbeitsblatt @@ -1482,6 +1820,14 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Texts to read Texte zum Lesen + + generic-student-user + allgemeiner-schueler-benutzer + + + Custom application + Benutzerdefinierte Anwendung + ExternalVncServer @@ -1506,10 +1852,165 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e - FeatureControl + FeatureCommands + + List names of all available features + Namen aller verfügbaren Funktionen auflisten + + + Show table with details of all available features + Tabelle mit Details zu allen verfügbaren Funktionen anzeigen + + + Start a feature on a remote host + Eine Funktion auf einem entfernten Computer starten + + + Stop a feature on a remote host + Eine Funktion auf einem entfernten Computer stoppen + + + Please specify the command to display help for. + Bitte geben Sie den Befehl an, für den Hilfe angezeigt werden soll. + + + Displays a list with the names of all available features. + Zeigt eine Liste mit den Namen aller verfügbaren Funktionen an. + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + Zeigt eine Tabelle mit detaillierten Informationen über alle verfügbaren Funktionen an. Diese Informationen umfassen eine Beschreibung, die UID, den Namen des Plugins, das die jeweilige Funktion bereitstellt, sowie einige andere implementierungsbezogene Details. + + + HOST ADDRESS + HOST-ADRESSE + + + FEATURE + FUNKTION + + + ARGUMENTS + ARGUMENTE + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + Startet die angegebene Funktion auf dem angegebenen Computer, indem eine Verbindung zum entfernt laufenden Veyon Server hergestellt wird. Die Funktion kann mittels Name oder UID angegeben werden. Benutzen Sie den ``show``-Befehl, um alle verfügbaren Funktionen zu sehen. Abhängig von der Funktion müssen zusätzliche Argumente (wie z.B. die anzuzeigende Textnachricht), kodiert als einzelne JSON-String, angegeben werden. Weitere Informationen entnehmen Sie bitte der Entwicklerdokumentation. + + + Lock the screen + Den Bildschirm sperren + + + Display a text message + Eine Textnachricht anzeigen + + + Test message + Testnachricht + + + Start an application + Eine Anwendung starten + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + Stoppt die angegebene Funktion auf dem angegebenen Computer, indem eine Verbindung zum entfernt laufenden Veyon Server hergestellt wird. Die Funktion kann mittels Name oder UID angegeben werden. Verwenden Sie den Befehl ``show``, um alle verfügbaren Funktionen zu sehen. + + + Unlock the screen + Den Bildschirm entsperren + + + The specified command does not exist or no help is available for it. + Der angegebene Befehl existiert nicht oder es ist keine Hilfe für ihn verfügbar. + + + Name + Name + + + Description + Beschreibung + + + Master + Master + + + Service + Dienst + + + Worker + Worker + + + UID + UID + + + Plugin + Plugin + + + Invalid feature name or UID specified + Ungültiger Featurename oder -UID angegeben + + + Error parsing the JSON-encoded arguments: %1 + Fehler beim Parsen der JSON-kodierten Argumente: %1 + + + Failed to initialize credentials + Initialisierung der Zugangsdaten fehlgeschlagen + + + Could not establish a connection to host %1 + Es konnte keine Verbindung zum Computer %1 hergestellt werden + + + Failed to send feature control message to host %1 + Die Funktionskontrollnachricht konnte nicht an den Computer %1 gesendet werden. + + + Feature-related CLI operations + Funktionsbezogene CLI-Operationen + + + Commands for controlling features + Befehle zur Steuerung von Funktionen + + + + FileTransferConfigurationPage + + File transfer + Dateiübertragung + + + Directories + Verzeichnisse + + + Destination directory + Zielverzeichnis + + + Default source directory + Standardquellverzeichnis + + + Options + Optionen + + + Remember last source directory + Letztes Quellverzeichnis merken + - Feature control - Funktionssteuerung + Create destination directory if it does not exist + Zielverzeichnis erstellen, wenn es nicht existiert @@ -1554,6 +2055,13 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Bestehende Dateien überschreiben + + FileTransferFileDialog + + Select one or more files to transfer + Eine oder mehrere Dateien für die Übertragung auswählen + + FileTransferPlugin @@ -1611,10 +2119,6 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Log file directory Logdateiverzeichnis - - ... - ... - Log level Loglevel @@ -1655,18 +2159,6 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Log to standard error output Nach Standardfehlerausgabe loggen - - Network object directory - Netzwerkobjektverzeichnis - - - Backend: - Backend: - - - Update interval: - Aktualisierungsintervall: - %1 service %1-Dienst @@ -1703,103 +2195,80 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e x x - - seconds - Sekunden - Write to logging system of operating system In Ereignisprotokollierung des Betriebssystems schreiben - Authentication - Authentifizierung - - - Method: - Methode: - - - Logon authentication - Anmelde-Authentifizierung - - - Key file authentication - Schlüsseldatei-Authentifizierung - - - Test - Testen + TLS configuration + TLS-Konfiguration - Authentication is set up properly on this computer. - Authentifizierung ist auf diesem Computer ordnungsgemäß eingerichtet. + Use certificate authority for TLS connections + Zertifikatsautorität für TLS-Verbindungen verwenden - Authentication keys are not set up properly on this computer. - Authentifizierungsschlüssel sind auf diesem Computer nicht ordnungsgemäß eingerichtet. + CA certificate file + CA-Zertifikatsdatei - Authentication test - Authentifizierungstest + ... + ... - - - InternetAccessControlConfigurationPage - Internet access control - Internetzugriffskontrolle + Host certificate file + Host-Zertifikatsdatei - Backend: - Backend: + Host private key file + Private Host-Schlüsseldatei - General settings - Allgemeine Einstellungen + Style: + Stil: - Backend settings - Backend-Einstellungen + Native + Nativ - - - InternetAccessControlPlugin - Block access to the internet - Zugriff auf das Internet blockieren + Color scheme: + Farbschema: - Allow access to the internet - Zugriff auf das Internet erlauben + Light + Hell - Show help about command - Hilfe über Befehl anzeigen + Dark + Dunkel - Block internet - Internet sperren + User groups + Benutzergruppen - Click this button to block access to the internet. - Klicken Sie auf diesen Button, um den Zugriff auf das Internet zu sperren. + Backend: + Backend: - Unblock internet - Internet freigeben + Include user groups from domain + Benutzergruppen von Domain einbeziehen - Click this button to allow access to the internet. - Klicken Sie auf diesen Button, um den Zugriff auf das Internet wieder freizugeben. + Missing user groups backend + Fehlendes Benutzergruppen-Backend - Control access to the internet - Internetzugriff steuern + No user groups plugin was found. Please check your installation! + Es wurde kein Benutzergruppen-Plugin gefunden. Bitte überprüfen Sie Ihre Installation! + + + HeadlessVncServer - Commands for controlling access to the internet - Befehle zur Steuerung des Internetzugriffs + Headless VNC server + Headless VNC-Server @@ -1817,344 +2286,527 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e - LdapConfigurationPage + LdapConfiguration - Basic settings - Grundeinstellungen + LDAP connection failed + LDAP-Verbindung fehlgeschlagen - General - Allgemein + Could not connect to the LDAP server. Please check the server parameters. + +%1 + Verbindung zum LDAP-Server konnte nicht hergestellt werden. Bitte überprüfen Sie die Servereinstellungen. + +%1 - LDAP server and port - LDAP-Server und Port + LDAP bind failed + LDAP-Bind fehlgeschlagen - Bind DN - Bind-DN + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + Bind zum LDAP-Server fehlgeschlagen. Bitte überprüfen Sie die Serverparameter und Bind-Zugangsdaten. + +%1 - Bind password - Bind-Passwort + LDAP bind successful + LDAP-Bind erfolgreich - Anonymous bind - Anonymer Bind + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Der Verbindungsaufbau zum LDAP-Server und LDAP-Bind waren erfolgreich. Die grundlegenden LDAP-Einstellungen sind korrekt eingerichtet. - Use bind credentials - Bind-Zugangsdaten verwenden + LDAP base DN test failed + LDAP-Base-DN-Test fehlgeschlagen - Base DN - Base-DN + Could not query the configured base DN. Please check the base DN parameter. + +%1 + Die konfigurierte Base-DN konnte nicht abgefragt werden. Bitte überprüfen Sie den Base-DN-Parameter. + +%1 - Fixed base DN - Fester Base-DN + LDAP base DN test successful + LDAP-Base-DN-erfolgreich getestet - e.g. dc=example,dc=org - z.B. dc=example,dc=org + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + Die LDAP-Base-DN wurde erfolgreich abgefragt. Die folgenden Einträge wurden gefunden: + +%1 - Discover base DN by naming context - Base-DN über Naming-Context ermitteln + LDAP naming context test failed + LDAP-Naming-Context-Test fehlgeschlagen - e.g. namingContexts or defaultNamingContext - z.B. namingContexts oder defaultNamingContext + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + Die Base-DN konnte nicht mittels Naming-Contexts abgefragt werden. Bitte überprüfen Sie den Naming-Context-Attribut-Parameter. + +%1 - Environment settings - Umgebungseinstellungen + LDAP naming context test successful + LDAP-Naming-Context-erfolgreich getestet - Object trees - Objektbäume + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + Der LDAP-Naming-Context wurde erfolgreich abgefragt. Die folgende Base-DN wurde gefunden: +%1 + + + user tree + Benutzerbaum + + + User tree + Benutzerbaum + + + group tree + Gruppenbaum + + + Group tree + Gruppenbaum + + + computer tree + Computerbaum Computer tree Computerbaum - e.g. OU=Groups - z.B. OU=Groups + computer group tree + Computergruppenbaum - User tree - Benutzerbaum + Computer group tree + Computergruppenbaum - e.g. OU=Users - z.B. OU=Users + user objects + Benutzerobjekte - e.g. OU=Computers - z.B. OU=Computers + User login name attribute + Attribut Benutzeranmeldename - Group tree - Gruppenbaum + group members + Gruppenmitglieder - Perform recursive search operations in object trees - Rekursive Suchoperationen in Objektbäumen durchführen + Group member attribute + Attribut Gruppenmitglied - Object attributes - Objektattribute + Group not found + Gruppe nicht gefunden - e.g. hwAddress - z.B. hwAddress + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Es wurde keine Gruppe mit dem Name "%1" gefunden. Bitte überprüfen Sie den Gruppenname oder den Gruppenbaum-Parameter. - e.g. member or memberUid - z.B. member oder memberUid + computer objects + Computerobjekte - e.g. dNSHostName - z.B. dNSHostName + Computer display name attribute + Attribut Computeranzeigename + + + Invalid hostname + Ungültiger Hostname + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Sie haben eingestellt, dass Computerhostnamen als vollqualifizierte Domainnamen (FQDN) gespeichert sind, haben aber einen Hostnamen ohne Domain eingegeben. + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Sie haben eingestellt, dass Computerhostnamen als einfache Hostnamen ohne Domainnamen gespeichert sind, haben aber einen Hostnamen mit Domain eingegeben. + + + Computer hostname attribute + Attribut Computerhostname + + + computer MAC addresses + Computer-MAC-Adressen Computer MAC address attribute Attribut Computer-MAC-Adresse - Group member attribute - Attribut Gruppenmitglied + computer locations + Computerstandorte - e.g. uid or sAMAccountName - z.B. uid oder sAMAccountName + Computer location attribute + Attribut Computerstandort - Advanced settings - Erweiterte Einstellungen + Location name attribute + Attribut Standortname - Optional object filters - Optionale Objektfilter + users + Benutzer - Filter for user groups - Filter für Benutzergruppen + user groups + Benutzergruppen - Filter for users - Filter für Benutzer + computers + Computer + + + computer groups + Computergruppen + + + computer containers + Computercontainer + + + groups of user + Gruppen des Benutzers + + + User not found + Benutzer nicht gefunden + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + Es wurde kein Benutzer mit dem Name "%1" gefunden! Bitte überprüfen Sie den Benutzername oder den Benutzergruppenbaum-Parameter. + + + groups of computer + Gruppen des Computers + + + Computer not found + Computer nicht gefunden + + + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Es wurde kein Computer mit dem Hostname "%1" gefunden. Bitte überprüfen Sie den Hostnamen oder den Computerbaum-Parameter. + + + Hostname lookup failed + Hostname-Lookup fehlgeschlagen + + + Could not lookup hostname for IP address %1. Please check your DNS server settings. + Der Hostname für die IP-Adresse %1 konnte nicht ermittelt werden. Bitte überprüfen Sie Ihre DNS-Server-Einstellungen. + + + location entries + Standorteinträge + + + Computer groups filter + Computergruppenfilter + + + Computer locations identification + Identifizierung von Computerstandorten Filter for computer groups Filter für Computergruppen - Group member identification - Identifizierung von Gruppenmitgliedern + Invalid test value + Ungültiger Testwert - Distinguished name (Samba/AD) - Distinguished name (Samba/AD) + An empty or invalid value has been supplied for this test. + Ein leerer oder ungültiger Wert wurde für diesen Test angegeben. - List all groups of a user - Alle Gruppen eines Benutzers auflisten + LDAP %1 test failed + LDAP %1 Test fehlgeschlagen - List all groups of a computer - Alle Gruppen eines Computers auflisten + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + Es konnten keine Enträge im konfigurierten %1 abgefragt werden. Bitte überprüfen Sie den Parameter "%2". + +%3 - Get computer object by IP address - Computerobjekt über IP-Adresse ermitteln + LDAP %1 test successful + LDAP %1 Test erfolgreich - LDAP connection failed - LDAP-Verbindung fehlgeschlagen + The %1 has been queried successfully and %2 entries were found. + Der %1 wurde erfolgreich abgefragt und %2 Einträge wurden gefunden. - LDAP bind failed - LDAP-Bind fehlgeschlagen + LDAP test failed + LDAP-Test fehlgeschlagen - LDAP bind successful - LDAP-Bind erfolgreich + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + Es konnte keine %1 abgefragt werden. Bitte überprüfen Sie den/die Parameter %2 und geben Sie den Namen eines existierenden Objekts ein. + +%3 - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - Der Verbindungsaufbau zum LDAP-Server und LDAP-Bind waren erfolgreich. Die grundlegenden LDAP-Einstellungen sind korrekt eingerichtet. + and + und - LDAP base DN test failed - LDAP-Base-DN-Test fehlgeschlagen + LDAP test successful + LDAP-Test erfolgreich - LDAP base DN test successful - LDAP-Base-DN-erfolgreich getestet + %1 %2 have been queried successfully: + +%3 + %1 %2 wurden erfolgreich abgefragt: + +%3 - LDAP naming context test failed - LDAP-Naming-Context-Test fehlgeschlagen + LDAP filter test failed + LDAP-Filter-Test fehlgeschlagen - LDAP naming context test successful - LDAP-Naming-Context-erfolgreich getestet + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 + Es konnten keine %1 mit dem eingestellten Filter abfragen. Bitte überprüfen Sie den LDAP-Filter für %1. + +%2 - The LDAP naming context has been queried successfully. The following base DN was found: -%1 - Der LDAP-Naming-Context wurde erfolgreich abgefragt. Die folgende Base-DN wurde gefunden: -%1 + LDAP filter test successful + LDAP-Filter-Test erfolgreich - user tree - Benutzerbaum + %1 %2 have been queried successfully using the configured filter. + %1 %2 wurden mit dem konfigurierten Filter erfolgreich abgefragt. - group tree - Gruppenbaum + LDAP directory + LDAP-Verzeichnis + + + LdapConfigurationPage - computer tree + Basic settings + Grundeinstellungen + + + General + Allgemein + + + LDAP server and port + LDAP-Server und Port + + + Bind DN + Bind-DN + + + Bind password + Bind-Passwort + + + Anonymous bind + Anonymer Bind + + + Use bind credentials + Bind-Zugangsdaten verwenden + + + Base DN + Base-DN + + + Fixed base DN + Fester Base-DN + + + e.g. dc=example,dc=org + z.B. dc=example,dc=org + + + Discover base DN by naming context + Base-DN über Naming-Context ermitteln + + + e.g. namingContexts or defaultNamingContext + z.B. namingContexts oder defaultNamingContext + + + Environment settings + Umgebungseinstellungen + + + Object trees + Objektbäume + + + Computer tree Computerbaum - Enter username - Benutzername eingeben + e.g. OU=Groups + z.B. OU=Groups - Please enter a user login name (wildcards allowed) which to query: - Bitte geben Sie den abzufragenden Benutzername ein (Platzhalter erlaubt): + User tree + Benutzerbaum - user objects - Benutzerobjekte + e.g. OU=Users + z.B. OU=Users - Enter group name - Grupenname eingeben + e.g. OU=Computers + z.B. OU=Computers - Please enter a group name whose members to query: - Bitte geben Sie den Namen der Gruppe ein, deren Mitglieder abgefragt werden sollen: + Group tree + Gruppenbaum - group members - Gruppenmitglieder + Perform recursive search operations in object trees + Rekursive Suchoperationen in Objektbäumen durchführen - Group not found - Gruppe nicht gefunden + Object attributes + Objektattribute - Could not find a group with the name "%1". Please check the group name or the group tree parameter. - Es wurde keine Gruppe mit dem Name "%1" gefunden. Bitte überprüfen Sie den Gruppenname oder den Gruppenbaum-Parameter. + e.g. hwAddress + z.B. hwAddress - Enter computer name - Computername eingeben + e.g. member or memberUid + z.B. member oder memberUid - computer objects - Computerobjekte + e.g. dNSHostName + z.B. dNSHostName - Enter computer DN - Computer-DN eingeben + Computer MAC address attribute + Attribut Computer-MAC-Adresse - Please enter the DN of a computer whose MAC address to query: - Bitte geben Sie den DN von einem Computer ein, dessen MAC-Adresse abgefragt werden soll: + Group member attribute + Attribut Gruppenmitglied - computer MAC addresses - Computer-MAC-Adressen + e.g. uid or sAMAccountName + z.B. uid oder sAMAccountName - users - Benutzer + Advanced settings + Erweiterte Einstellungen - user groups - Benutzergruppen + Optional object filters + Optionale Objektfilter - computer groups - Computergruppen + Filter for user groups + Filter für Benutzergruppen - Please enter a user login name whose group memberships to query: - Bitte geben Sie den Benutzerlogin-Name ein, dessen Gruppenmitgliedschaften abgefragt werden sollen: + Filter for users + Filter für Benutzer - groups of user - Gruppen des Benutzers + Filter for computer groups + Filter für Computergruppen - User not found - Benutzer nicht gefunden + Group member identification + Identifizierung von Gruppenmitgliedern - groups of computer - Gruppen des Computers + Distinguished name (Samba/AD) + Distinguished name (Samba/AD) - Computer not found - Computer nicht gefunden + List all groups of a user + Alle Gruppen eines Benutzers auflisten - Enter computer IP address - Computer-IP-Adresse eingeben + List all groups of a computer + Alle Gruppen eines Computers auflisten - Please enter a computer IP address which to resolve to an computer object: - Bitte geben Sie eine Computer-IP-Adresse ein, die in ein Computerobjekt aufgelöst werden soll: + Get computer object by IP address + Computerobjekt über IP-Adresse ermitteln - computers - Computer + Enter username + Benutzername eingeben - LDAP %1 test failed - LDAP %1 Test fehlgeschlagen + Please enter a user login name (wildcards allowed) which to query: + Bitte geben Sie den abzufragenden Benutzername ein (Platzhalter erlaubt): - LDAP %1 test successful - LDAP %1 Test erfolgreich + Enter group name + Grupenname eingeben - The %1 has been queried successfully and %2 entries were found. - Der %1 wurde erfolgreich abgefragt und %2 Einträge wurden gefunden. + Please enter a group name whose members to query: + Bitte geben Sie den Namen der Gruppe ein, deren Mitglieder abgefragt werden sollen: - %1 %2 have been queried successfully: - -%3 - %1 %2 wurden erfolgreich abgefragt: - -%3 + Enter computer name + Computername eingeben - LDAP filter test failed - LDAP-Filter-Test fehlgeschlagen + Enter computer DN + Computer-DN eingeben + + + Please enter the DN of a computer whose MAC address to query: + Bitte geben Sie den DN von einem Computer ein, dessen MAC-Adresse abgefragt werden soll: - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 - Es konnten keine %1 mit dem eingestellten Filter abfragen. Bitte überprüfen Sie den LDAP-Filter für %1. - -%2 + Please enter a user login name whose group memberships to query: + Bitte geben Sie den Benutzerlogin-Name ein, dessen Gruppenmitgliedschaften abgefragt werden sollen: - LDAP filter test successful - LDAP-Filter-Test erfolgreich + Enter computer IP address + Computer-IP-Adresse eingeben - %1 %2 have been queried successfully using the configured filter. - %1 %2 wurden mit dem konfigurierten Filter erfolgreich abgefragt. + Please enter a computer IP address which to resolve to an computer object: + Bitte geben Sie eine Computer-IP-Adresse ein, die in ein Computerobjekt aufgelöst werden soll: (only if different from group tree) @@ -2164,10 +2816,6 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Computer group tree Computergruppenbaum - - computer group tree - Computergruppenbaum - Filter for computers Filter für Computer @@ -2248,50 +2896,10 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e e.g. (objectClass=container) or (objectClass=organizationalUnit) z.B. (objectClass=container) oder (objectClass=organizationalUnit) - - Could not query the configured base DN. Please check the base DN parameter. - -%1 - Die konfigurierte Base-DN konnte nicht abgefragt werden. Bitte überprüfen Sie den Base-DN-Parameter. - -%1 - - - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - Die LDAP-Base-DN wurde erfolgreich abgefragt. Die folgenden Einträge wurden gefunden: - -%1 - - - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - Die Base-DN konnte nicht mittels Naming-Contexts abgefragt werden. Bitte überprüfen Sie den Naming-Context-Attribut-Parameter. - -%1 - Certificate files (*.pem) Zertifikatsdateien (*.pem) - - Could not connect to the LDAP server. Please check the server parameters. - -%1 - Verbindung zum LDAP-Server konnte nicht hergestellt werden. Bitte überprüfen Sie die Servereinstellungen. - -%1 - - - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - Bind zum LDAP-Server fehlgeschlagen. Bitte überprüfen Sie die Serverparameter und Bind-Zugangsdaten. - -%1 - Encryption protocol Verschlüsselungsprotokoll @@ -2337,383 +2945,150 @@ Der öffentliche Schlüssel wird auf den Clientcomputern genutzt, um für jede e Computeranzeigename eingeben - Please enter a computer display name to query: - Bitte geben Sie den abzufragenden Computeranzeigename ein: - - - Enter computer location name - Computerstandortname eingeben - - - Please enter the name of a computer location (wildcards allowed): - Bitte geben Sie den Namen eines Computerstandortes ein (Platzhalter möglich): - - - computer locations - Computerstandorte - - - Enter location name - Standortname eingeben - - - Please enter the name of a location whose entries to query: - Bitte geben Sie den Namen eines Standortes ein, dessen Einträge abgefragt werden sollen: - - - location entries - Standorteinträge - - - LDAP test failed - LDAP-Test fehlgeschlagen - - - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - Es konnte keine %1 abgefragt werden. Bitte überprüfen Sie den/die Parameter %2 und geben Sie den Namen eines existierenden Objekts ein. - -%3 - - - and - und - - - LDAP test successful - LDAP-Test erfolgreich - - - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - Es konnten keine Enträge im konfigurierten %1 abgefragt werden. Bitte überprüfen Sie den Parameter "%2". - -%3 - - - Browse - Durchsuchen - - - Test - Testen - - - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - Hostnamen sind als vollqualifizierte Domainnamen gespeichert (FQDN, z.B. myhost.example.org) - - - Computer hostname attribute - Attribut Computerhostname - - - Please enter a computer hostname to query: - Bitte geben Sie den abzufragenden Computerhostnamen ein: - - - Invalid hostname - Ungültiger Hostname - - - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Sie haben eingestellt, dass Computerhostnamen als vollqualifizierte Domainnamen (FQDN) gespeichert sind, haben aber einen Hostnamen ohne Domain eingegeben. - - - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - Sie haben eingestellt, dass Computerhostnamen als einfache Hostnamen ohne Domainnamen gespeichert sind, haben aber einen Hostnamen mit Domain eingegeben. - - - Could not find a user with the name "%1". Please check the username or the user tree parameter. - Es wurde kein Benutzer mit dem Name "%1" gefunden! Bitte überprüfen Sie den Benutzername oder den Benutzergruppenbaum-Parameter. - - - Enter hostname - Hostname eingeben - - - Please enter a computer hostname whose group memberships to query: - Bitte geben Sie den Computerhostnamen ein, dessen Gruppenmitgliedschaften abgefragt werden sollen: - - - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - Es wurde kein Computer mit dem Hostname "%1" gefunden. Bitte überprüfen Sie den Hostnamen oder den Computerbaum-Parameter. - - - Hostname lookup failed - Hostname-Lookup fehlgeschlagen - - - Could not lookup hostname for IP address %1. Please check your DNS server settings. - Der Hostname für die IP-Adresse %1 konnte nicht ermittelt werden. Bitte überprüfen Sie Ihre DNS-Server-Einstellungen. - - - User login name attribute - Attribut Benutzeranmeldename - - - Configured attribute for user login name or computer hostname (OpenLDAP) - Konfiguriertes Attribut für Benutzeranmeldename oder Computerhostname (OpenLDAP) - - - computer containers - Computercontainer - - - - LdapPlugin - - Auto-configure the base DN via naming context - Basis-DN mittels Naming-Context automatisch konfigurieren - - - Query objects from LDAP directory - Objekte aus LDAP-Verzeichnis abfragen - - - Show help about command - Hilfe über Befehl anzeigen - - - Commands for configuring and testing LDAP/AD integration - Befehle zum Konfigurieren und Testen der LDAP-/AD-Integration - - - Basic LDAP/AD support for Veyon - Einfache LDAP/AD-Unterstützung für Veyon - - - %1 (load computers and locations from LDAP/AD) - %1 (Computer und Standorte aus LDAP/AD laden) - - - %1 (load users and groups from LDAP/AD) - %1 (Benutzer und Gruppen aus LDAP/AD laden) - - - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - Bitte geben Sie eine gültige LDAP-URL an, die dem Schema "ldap[s]://[Benutzer[:Passwort]@]Hostname[:Port]" folgt - - - No naming context attribute name given - falling back to configured value. - Es wurde kein Naming-Context-Attribut angegeben - falle auf konfigurierten Wert zurück. - - - Could not query base DN. Please check your LDAP configuration. - Base-DN konnte nicht abgefragt werden. Bitte überprüfen Sie Ihre LDAP-Konfiguration. - - - Configuring %1 as base DN and disabling naming context queries. - Konfiguriere %1 als Base-DN und deaktiviere Naming-Context-Abfragen. - - - - LdapProConfigurationPage - - LDAP Pro - LDAP Pro - - - Instances - Instanzen - - - Enter name - Name eingeben - - - Please enter a name for the instance (can't be changed later!): - Bitte geben Sie einen Namen für die Instanz (kann später nicht geändert werden!): - - - Remove instance - Instanz entfernen - - - Do you really want to remove instance "%1"? - Möchten Sie wirklich die Instanz "%1" entfernen? - - - Configuration for instance "%1" - Konfiguration für Instanz "%1" - - - - LdapProPlugin - - Professional LDAP/AD integration for Veyon - Professionelle LDAP/AD-Anbindung für Veyon - - - %1 (load computers and locations from LDAP/AD) - %1 (Computer und Standorte aus LDAP/AD laden) - - - %1 (load users and groups from LDAP/AD) - %1 (Benutzer und Gruppen aus LDAP/AD laden) + Please enter a computer display name to query: + Bitte geben Sie den abzufragenden Computeranzeigename ein: - - - LicensingConfigurationPage - Licensing - Lizenzierung + Enter computer location name + Computerstandortname eingeben - Installed licenses - Installierte Lizenzen + Please enter the name of a computer location (wildcards allowed): + Bitte geben Sie den Namen eines Computerstandortes ein (Platzhalter möglich): - Add new network range - Neuen Netzwerkbereich hinzufügen + Enter location name + Standortname eingeben - Remove selected network range - Gewählten Netzwerkbereich entfernen + Please enter the name of a location whose entries to query: + Bitte geben Sie den Namen eines Standortes ein, dessen Einträge abgefragt werden sollen: - ID - ID + Browse + Durchsuchen - Feature - Funktion + Test + Testen - Valid until - Gültig bis + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Hostnamen sind als vollqualifizierte Domainnamen gespeichert (FQDN, z.B. myhost.example.org) - Licensee - Lizenznehmer + Computer hostname attribute + Attribut Computerhostname - Browse license file - Lizenzfile auswählen + Please enter a computer hostname to query: + Bitte geben Sie den abzufragenden Computerhostnamen ein: - Veyon license files (*.vlf) - Veyon-Lizenz-Datei (*.vlf) + Enter hostname + Hostname eingeben - Remove license - Lizenz entfernen + Please enter a computer hostname whose group memberships to query: + Bitte geben Sie den Computerhostnamen ein, dessen Gruppenmitgliedschaften abgefragt werden sollen: - Do you really want to remove the selected license? - Möchten Sie wirklich die gewählte Lizenz entfernen? + User login name attribute + Attribut Benutzeranmeldename - <N/A> - <N/V> + Configured attribute for user login name or computer hostname (OpenLDAP) + Konfiguriertes Attribut für Benutzeranmeldename oder Computerhostname (OpenLDAP) - Invalid license file - Ungültige Lizenzdatei + Directory name + Verzeichnisname - Could not open the license file for reading! - Die Lizenzdatei konnte nicht zum Lesen geöffnet werden! + Query options + Abfrageoptionen - The selected license file does not contain valid data. - Die gewählte Lizenzdatei enthält keine gültigen Daten. + Query nested user groups (supported by AD only) + Verschachtelte Benutzergruppen abfragen (nur von AD unterstützt) - The selected license file could not be verified. - Die gewählte Lizenzdatei konnte nicht verifiziert werden. + Query timeout + Abfrage-Timeout - The selected license file is not valid for this installation. - Die gewählte Lizenzdatei ist nicht gültig für diese Installation. + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. - Die gewählte Lizenzdatei ist abgelaufen. + LDAP + LDAP - The license is already installed. - Die Lizenz ist bereits installiert. + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + Bitte verwenden Sie die globale LDAP-Konfigurationsseite, um festzulegen, wie Standorte und Computer von Ihrem LDAP-basierten Verzeichnisdienst abgefragt werden sollen. + + + LdapPlugin - Information - Informationen + Auto-configure the base DN via naming context + Basis-DN mittels Naming-Context automatisch konfigurieren - Installation ID - Installations-ID + Query objects from LDAP directory + Objekte aus LDAP-Verzeichnis abfragen - Addons available for licensing - Lizenzierbare Erweiterungen + Show help about command + Hilfe über Befehl anzeigen - Addon - Erweiterung + Commands for configuring and testing LDAP/AD integration + Befehle zum Konfigurieren und Testen der LDAP-/AD-Integration - - - LicensingPlugin - Show help for specific command - Hilfe für bestimmten Befehl anzeigen + Basic LDAP/AD support for Veyon + Einfache LDAP/AD-Unterstützung für Veyon - Show all installed licenses - Alle installierten Lizenzen anzeigen + %1 (load computers and locations from LDAP/AD) + %1 (Computer und Standorte aus LDAP/AD laden) - Add license file - Lizenzdatei hinzufügen + %1 (load users and groups from LDAP/AD) + %1 (Benutzer und Gruppen aus LDAP/AD laden) - Remove installed license - Installierte Lizenz entfernen + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Bitte geben Sie eine gültige LDAP-URL an, die dem Schema "ldap[s]://[Benutzer[:Passwort]@]Hostname[:Port]" folgt - -USAGE - -%1 add <LICENSE FILE> - - - -VERWENDUNG - -%1 add <LICENSE FILE> - - + No naming context attribute name given - falling back to configured value. + Es wurde kein Naming-Context-Attribut angegeben - falle auf konfigurierten Wert zurück. - -USAGE - -%1 remove <LICENSE ID> - - - -VERWENDUNG - -%1 remove <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. + Base-DN konnte nicht abgefragt werden. Bitte überprüfen Sie Ihre LDAP-Konfiguration. - No certificate found with given ID - Kein Zertifikat mit angegebener ID gefunden + Configuring %1 as base DN and disabling naming context queries. + Konfiguriere %1 als Base-DN und deaktiviere Naming-Context-Abfragen. - <N/A> - <N/V> + Test binding to an LDAP server + Bind zu einem LDAP-Server testen - Licensing management - Lizenzverwaltung + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Der angegebene Benutzername oder das Passwort ist falsch. Bitte geben Sie gültige Zugangsdaten ein oder wechseln zu einer anderen Authentifizierungsmethode mit Hilfe des Veyon Configurators. - Commands for managing license keys - Befehle zum Verwalten von Lizenzschlüsseln + LDAP bind + LDAP-Bind @@ -2731,12 +3106,20 @@ VERWENDUNG Benutzerauthentifizierung - Session management - Sitzungsverwaltung + User sessions + Benutzersitzungen + + + Minimum session lifetime before server start + Minimale Sitzungsdauer vor Serverstart + + + User login + Benutzeranmeldung - Display manager users - Displaymanager-Benutzer + Login key sequence + Tastensequenz zum Anmelden @@ -2745,10 +3128,6 @@ VERWENDUNG Plugin implementing abstract functions for the Linux platform Plugin zur Implementierung abstrakter Funktionen für die Linux-Plattform - - Plugin implementing specific functions for the Linux platform - Plugin zur Implementierung spezifischer Funktionen für die Linux-Plattform - LocationDialog @@ -2767,14 +3146,14 @@ VERWENDUNG Configuration Konfiguration - - Disable balloon tooltips - Balloon-Tooltips deaktivieren - Show icons only Nur Icons anzeigen + + Disable tooltips + Tooltips deaktivieren + MainWindow @@ -2822,10 +3201,6 @@ VERWENDUNG About Qt Über Qt - - Authentication impossible - Authentifizierung nicht möglich - Configuration not writable Konfiguration nicht schreibbar @@ -2886,10 +3261,6 @@ VERWENDUNG The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. Das Backend für die lokale Konfiguration hat gemeldet, dass die Konfiguration nicht beschreibbar ist. Bitte führen Sie den %1 Configurator mit höheren Privilegien aus. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - Es wurden keine Authentifizierungsschlüsseldateien gefunden oder sie sind nicht mehr aktuell. Bitte erzeugen Sie neue Schlüsseldateien mit Hilfe des %1 Configurators. Alternativ können Sie die Anmelde-Authentifizierung mit Hilfe des %1 Configurators einrichten. Andernfalls werden Sie nicht in der Lage sein, mit %1 auf Computer zuzugreifen. - Access denied Zugriff verweigert @@ -2922,10 +3293,6 @@ VERWENDUNG Search users and computers Benutzer und Computer suchen - - Adjust optimal size - Optimale Größe einstellen - Align computers to grid Computer an Gitter ausrichten @@ -2970,6 +3337,50 @@ VERWENDUNG Locations && computers Standorte && Computer + + Authentication + Authentifizierung + + + Adjust size of computer icons automatically + Größe der Computer-Icons automatisch anpassen + + + Slideshow + Diashow + + + Spotlight + Scheinwerfer + + + Veyon Master + Veyon Master + + + Locations & computers + Standorte & Computer + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + Benutzerdefinierte Computeranordnung verwenden. + +Gedrückt halten, um die Anordnung aus einer Datei zu laden oder die aktuelle Anordnung in einer Datei zu speichern. + + + Only show computers with logged on users + Nur Computer mit angemeldeten Benutzern anzeigen + + + Load computer positions + Computerpositionen laden + + + Save computer positions + Computerpositionen speichern + MasterConfigurationPage @@ -2977,10 +3388,6 @@ VERWENDUNG Directories Verzeichnisse - - ... - ... - User configuration Benutzerkonfiguration @@ -3031,7 +3438,7 @@ VERWENDUNG Actions such as rebooting or powering down computers - Aktionen wie Computer neustarten oder ausschalten + Aktionen wie Computer neu starten oder ausschalten User interface @@ -3043,7 +3450,7 @@ VERWENDUNG Thumbnail update interval - Aktualisierungsintervall Vorschaubilder + Aktualisierungsintervall Miniaturbilder ms @@ -3065,6 +3472,10 @@ VERWENDUNG Only user name Nur Benutzername + + Only last part of user name + Nur letzter Teil des Benutzernamens + Only computer name Nur Computername @@ -3113,170 +3524,181 @@ VERWENDUNG Automatically select current location Automatisch aktuellen Standort auswählen - - Automatically adjust computer thumbnail size - Automatisch die Größe der Computer-Miniaturansichten anpassen - Automatically open computer select panel Automatisch Computerauswahlbedienfeld öffnen - - - MonitoringMode - Monitoring - Beobachten + Use modern user interface (experimental) + Moderne Benutzeroberfläche nutzen (experimentell) - Builtin monitoring mode - Eingebauter Beobachtungsmodus + Thumbnail spacing + Abstand Miniaturbilder - This mode allows you to monitor all computers at one or more locations. - Dieser Modus erlaubt es Ihnen, alle Computer an einem oder mehreren Standorten zu beobachten. + px + px + + + Hide local session + Lokale Sitzung ausblenden - - - NetworkDiscoveryConfigurationPage - Network discovery - Netzwerkerkennung + Auto + Auto - Mode - Modus + Thumbnail aspect ratio + Seitenverhältnis Miniaturbilder - Scan network ranges - Netzwerkbereiche scannen + Automatically adjust computer icon size + Automatisch die Größe der Computer-Icons anpassen - e.g. 192.168.1.0/24 - z.B. 192.168.1.0/24 + Open feature windows on the same screen as the main window + Funktionsfenster auf dem gleichen Bildschirm wie der des Hauptfensters öffnen - Scan all subnets of computer - Alle Subnetze des Computers scannen + Configuration templates + Konfigurationsvorlagen - Scan custom subnet - Benutzerdefiniertes Subnetz scannen + Image quality in monitoring mode + Bildqualität im Beobachtungsmodus - Scan sessions on local computer - Sitzungen auf lokalem Computer scannen + Highest + Höchste - Test - Testen + High + Hoch - Network ranges - Netzwerkbereiche + Medium + Mittel - Add new group - Neue Gruppe hinzufügen + Low + Niedrig - Remove selected group - Gewählte Gruppe entfernen + Lowest + Niedrigste - Groups - Gruppen + Remote access image quality + Bildqualität beim Fernzugriff - First address - Erste Adresse + Advanced + Erweitert - Last address - Letzte Adresse + Computer name source + Quelle für Computernamen - Add new network range - Neuen Netzwerkbereich hinzufügen + Default + Standard - Remove selected network range - Gewählten Netzwerkbereich entfernen + Host address + Hostadresse - Parallel scans - Parallele Scans + Session client address + Adresse des Sitzungsclients - Scan timeout - Scan-Timeout + Session client name + Name des Sitzungsclients - ms - ms + Session host name + Sitzungshostname - Session scan limit - Limit für Sitzungsscan + Session metadata + Sitzungsmetadaten - Options - Optionen + Full name of user + Voller Name des Benutzers - Reverse lookup discovered IP addresses to host names - Gefundene IP-Adressen in Hostnamen rückwärts auflösen + User login name + Benutzeranmeldename - New location - Neuer Standort + Computer UID role + Computer-UID-Rolle + + + Session meta data hash + Hash über Sitzungsmetadaten - - - NetworkDiscoveryDirectory - Scanning... - Scanne... + Always expand all locations + Immer alle Standorte ausklappen - Discovered computers - Gefundene Computer + Image quality + Bildqualität - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command - Hilfe für bestimmten Befehl anzeigen + Monitoring + Beobachten - Scan a subnet - Ein Subnetz scannen + Builtin monitoring mode + Eingebauter Beobachtungsmodus - -USAGE - -%1 scan [<SUBNET>] - - - -VERWENDUNG - -%1 scan [<SUBNETZ>] - + This mode allows you to monitor all computers at one or more locations. + Dieser Modus erlaubt es Ihnen, alle Computer an einem oder mehreren Standorten zu beobachten. + + + Query application version of the server + Anwendungsversion des Servers abfragen + + + Query active features + Aktive Funktionen abfragen + + + Query properties of remotely available screens + Eigenschaften entfernt verfügbarer Bildschirme abfragen + + + + NestedNetworkObjectDirectory + + All directories + Alle Verzeichnisse + + + NetworkObjectDirectoryConfigurationPage - Network object directory which automatically discovers computers in the network - Netzwerkobjektverzeichnis, das automatisch Computer im Netzwerk erkennt + Update interval: + Aktualisierungsintervall: - Network discovery (scan network for Veyon clients) - Netzwerkerkennung (Veyon-Clients im Netzwerk suchen) + seconds + Sekunden + + + NetworkObjectDirectoryConfigurationPageTab - Commands for managing the network discovery directory - Befehle zur Verwaltung des Netzwerkobjektverzeichnisses + Enabled + Aktiviert @@ -3312,32 +3734,44 @@ VERWENDUNG Name: Name: + + Website name + Webseitenname + - PasswordDialog + PluginCommands - Username - Benutzername + List names of all installed plugins + Namen aller installierter Plugins auflisten - Password - Passwort + Show table with details of all installed plugins + Tabelle mit Details zu allen installierten Plugins anzeigen - Veyon Logon - Veyon-Anmeldung + Name + Name - Authentication error - Authentifizierungsfehler + Description + Beschreibung - Logon failed with given username and password. Please try again! - Die Anmeldung mit dem angegebenen Benutzername und Passwort ist fehlgeschlagen. Bitte versuchen Sie es erneut! + Version + Version - Please enter your username and password in order to access computers. - Bitte geben Sie Ihren Benutzernamen und Passwort ein, um auf Computer zuzugreifen. + UID + UID + + + Plugin-related CLI operations + Plugin-bezogene CLI-Operationen + + + Commands for managing plugins + Befehle zur Verwaltung von Plugins @@ -3352,7 +3786,7 @@ VERWENDUNG Reboot - Neustarten + Neustart Click this button to reboot all computers. @@ -3368,7 +3802,7 @@ VERWENDUNG Power on/down or reboot a computer - Computer ein-/ausschalten oder neustarten + Computer ein-/ausschalten oder neu starten Confirm reboot @@ -3380,11 +3814,7 @@ VERWENDUNG Do you really want to reboot the selected computers? - Möchten Sie wirklich die gewählten Computer neustarten? - - - Do you really want to power down the selected computer? - Möchten Sie wirklich die gewählten Computer herunterfahren? + Möchten Sie wirklich die gewählten Computer neu starten? Power on a computer via Wake-on-LAN (WOL) @@ -3438,6 +3868,18 @@ Please save your work and close all programs. Bitte speichern Sie Ihre Arbeiten und schließen alle Programme. + + Do you really want to reboot <b>ALL</b> computers? + Möchten Sie wirklich <b>ALLE</b> Computer neu starten? + + + Do you really want to power down <b>ALL</b> computers? + Möchten Sie wirklich <b>ALLE</b> Computer herunterfahren? + + + Do you really want to power down the selected computers? + Möchten Sie wirklich die gewählten Computer herunterfahren? + PowerDownTimeInputDialog @@ -3484,14 +3926,25 @@ Bitte speichern Sie Ihre Arbeiten und schließen alle Programme. Remote view or control a computer Fernansicht oder -Steuerung eines Computers - - Please enter the hostname or IP address of the computer to access: - Bitte geben Sie den Hostnamen oder IP-Adresse des Computers ein, auf den Sie zugreifen möchten: - Show help about command Hilfe über Befehl anzeigen + + Exchange clipboard contents + Inhalt der Zwischenablage austauschen + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + Da kein Computer ausgewählt wurde, können Sie einen Hostnamen oder eine IP-Adresse eines Computers für den manuellen Zugriff eingeben: + + + + RemoteAccessPage + + Remote access: %1 + Fernzugriff: %1 + RemoteAccessWidget @@ -3499,6 +3952,10 @@ Bitte speichern Sie Ihre Arbeiten und schließen alle Programme. %1 - %2 Remote Access %1 - %2 Fernzugriff + + %1 - %2 - %3 Remote Access + %1 - %2 - %3 Fernzugriff + RemoteAccessWidgetToolBar @@ -3552,76 +4009,31 @@ Bitte speichern Sie Ihre Arbeiten und schließen alle Programme. Alt+Ctrl+F1 - Alt+Strg+F1 - - - Connecting %1 - Verbindung wird hergestellt %1 - - - Connected. - Verbindung hergestellt. - - - Screenshot - Bildschirmfoto - - - Exit - Beenden - - - - Routing - - Control internet access by modifying routing table - Internetzugriff durch Modifizierung der Routingtabelle - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - Defaultroute entfernen um Internetzugriff zu sperren - - - Add custom route to block internet - Benutzerdefinierte Route hinzufügen um Internetzugriff zu sperren - - - Destination - Ziel - - - Gateway - Gateway + Alt+Strg+F1 - - - RunProgramDialog - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - Bitte geben Sie die Programme oder die Befehle ein, die auf den gewählten Computern gestartet werden sollen. Sie können mehrere Programme/Befehle über einzelne Zeilen angeben. + Connected. + Verbunden. - Run programs - Programme starten + Screenshot + Bildschirmfoto - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - z.B. "C:\Programme\VideoLAN\VLC\vlc.exe" + Exit + Beenden - Name: - Name: + Connecting... + Verbinde... - Remember and add to program menu - Merken und zum Programmmenü hinzufügen + Select screen + Bildschirm auswählen - e.g. VLC - z.B. VLC + All screens + Alle Bildschirme @@ -3642,6 +4054,18 @@ Bitte speichern Sie Ihre Arbeiten und schließen alle Programme. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. Mit diesem Button können Sie alle Computer sperren und die volle Aufmerksamkeit der Benutzer zurückerhalten. In diesem Modus werden alle Eingabegeräte gesperrt und die Bildschirme der Benutzer schwarz eingefärbt. + + Lock input devices + Eingabegeräte sperren + + + Unlock input devices + Eingabegeräte entsperren + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + Mit diesem Button können Sie alle Computer sperren und die volle Aufmerksamkeit der Benutzer zurückerhalten. In diesem Modus werden alle Eingabegeräte gesperrt, während der Desktop sichtbar bleibt. + Screenshot @@ -3657,6 +4081,10 @@ Bitte speichern Sie Ihre Arbeiten und schließen alle Programme. Screenshot Bildschirmfoto + + Could not open screenshot file %1 for writing. + Die Bildschirmfotodatei %1 konnte nicht zum Schreiben geöffnet werden. + ScreenshotFeaturePlugin @@ -3681,6 +4109,13 @@ Bitte speichern Sie Ihre Arbeiten und schließen alle Programme. Bildschirmfotos von Computern aufnehmen und lokal speichern. + + ScreenshotManagementPage + + Screenshots + Bildschirmfotos + + ScreenshotManagementPanel @@ -3711,6 +4146,45 @@ Bitte speichern Sie Ihre Arbeiten und schließen alle Programme. Delete Löschen + + Screenshot + Bildschirmfoto + + + Do you really want to delete all selected screenshots? + Möchten Sie wirklich alle ausgewählten Screenshots löschen? + + + + ServerAccessControlManager + + Requested authentication method not available + Angeforderte Authentifizierungsmethode nicht verfügbar + + + Access allowed by rule "%1" + Zugriff erlaubt durch Regel "%1" + + + Access denied by rule "%1" + Zugriff verweigert durch Regel "%1" + + + No rule allowed access + Keine Regel erlaubt Zugriff + + + Accessing user not member of an authorized user group + Zugreifender Benutzer ist nicht Mitglied einer autorisierten Benutzergruppe + + + User has denied access + Benutzer hat den Zugriff abgelehnt + + + User confirmed access + Benutzer hat den Zugriff bestätigt + ServiceConfigurationPage @@ -3742,14 +4216,6 @@ Bitte speichern Sie Ihre Arbeiten und schließen alle Programme. State: Status: - - Network - Netzwerk - - - Demo server port - Demoserver-Port - Enable firewall exception Firewall-Ausnahme aktivieren @@ -3758,10 +4224,6 @@ Bitte speichern Sie Ihre Arbeiten und schließen alle Programme. Allow connections from localhost only Nur Verbindungen vom lokalen Computer erlauben - - Internal VNC server port - Port des internen VNC-Servers - VNC server VNC-Server @@ -3772,24 +4234,16 @@ Bitte speichern Sie Ihre Arbeiten und schließen alle Programme. Restart %1 Service - %1 Dienst neustarten + %1 Dienst neu starten All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - Alle Einstellungen wurden erfolgreich gespeichert. Damit die Einstellungen wirksam werden, muss der %1-Dienst neugestartet werden. Jetzt neustarten? + Alle Einstellungen wurden erfolgreich gespeichert. Damit die Einstellungen wirksam werden, muss der %1-Dienst neu gestartet werden. Jetzt neu starten? Running Läuft - - Feature manager port - Funktionsverwalter-Port - - - Primary service port - Primärer Dienst-Port - Enabling this option will make the service launch a server process for every interactive session on a computer. Typically this is required to support terminal servers. @@ -3800,52 +4254,132 @@ Normalerweise ist dies erforderlich, um Terminalserver zu unterstützen.Show notification on remote connection Benachrichtigung bei Fernzugriff anzeigen - - Multi session mode (for terminal and remote desktop servers) - Mehrfachsitzungsmodus (für Terminal- und Remote-Desktop-Server) - Show notification when an unauthorized access is blocked Benachrichtigung bei unerlaubtem Zugriff anzeigen - - - ServiceControl - Starting service %1 - Starte Dienst %1 + Maximum session count + Maximale Sitzungsanzahl - Stopping service %1 - Beende Dienst %1 + Network port numbers + Netzwerk-Portnummern - Registering service %1 - Registriere Dienst %1 + Veyon server + Veyon-Server - Unregistering service %1 - Deregistriere Dienst %1 + Internal VNC server + Interner VNC-Server - Service control - Dienststeuerung + Feature manager + Funktionsverwalter + + + Demo server + Demo-Server + + + Miscellaneous network settings + Diverse Netzwerkeinstellungen + + + Session mode + Sitzungsmodus + + + Local session mode (single server instance for primary local session) + Lokaler Sitzungsmodus (einzelne Serverinstanz für primäre lokale Sitzung) + + + Active session mode (single server instance for active local or remote session) + Aktiver Sitzungsmodus (einzelne Serverinstanz für aktive lokale oder entfernte Sitzung) + + + Multi session mode (distinct server instance for each local and remote desktop session) + Mehrsitzungsmodus (eigene Serverinstanz für jede lokale und entfernte Desktop-Sitzung) + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + Aktivieren, wenn eine einzelne Veyon Server-Instanz für die gerade aktive Sitzung gestartet werden soll, egal ob lokal oder remote. + + + Miscellaneous settings + Sonstige Einstellungen + + + Disable clipboard synchronization + Synchronisierung der Zwischenablage deaktivieren + + + Session metadata + Sitzungsmetadaten + + + Content + Inhalt + + + None + Keine + + + Value of an environment variable + Wert einer Umgebungsvariable + + + Value of a registry key + Wert eines Registryschlüssels + + + Environment variable name: + Name der Umgebungsvariable: + + + Registry key name: + Name des Registryschlüssels: + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + Geben Sie optional einen regulären Ausdruck mit einem Capture ein, um einen Teil des Computernamens zu extrahieren und ihn als Anzeigenamen für den Computer zu verwenden. + +Beispiel: [^-]*-(PC[0-9]*) - ServiceControlPlugin + ServiceControl - Service is running - Dienst läuft + Service control + Dienststeuerung - Service is not running - Dienst läuft nicht + Starting %1 + Starte %1 - Configure and control Veyon service - Veyon-Dienst konfigurieren und steuern + Stopping %1 + Beende %1 + + + Restarting %1 + Starte %1 neu + + + Registering %1 + Registriere %1 + + Unregistering %1 + Deregistriere %1 + + + + ServiceControlCommands Register Veyon Service Veyon-Dienst registrieren @@ -3864,19 +4398,31 @@ Normalerweise ist dies erforderlich, um Terminalserver zu unterstützen. Restart Veyon Service - Veyon-Dienst neustarten + Veyon-Dienst neu starten Query status of Veyon Service Status des Veyon-Diensts abfragen + + Service is running + Dienst läuft + + + Service is not running + Dienst läuft nicht + + + Configure and control Veyon service + Veyon-Dienst konfigurieren und steuern + Commands for configuring and controlling Veyon Service Befehle zur Konfiguration und Steuerung des Veyon-Diensts - ShellCommandLinePlugin + ShellCommands Run command file Befehlsdatei ausführen @@ -3886,14 +4432,101 @@ Normalerweise ist dies erforderlich, um Terminalserver zu unterstützen.Datei "%1 existiert nicht! - Interactive shell and script execution for Veyon Control - Interaktive Shell und Scriptausführung für Veyon Control + Interactive shell and script execution for Veyon CLI + Interaktive Shell und Scriptausführung für Veyon CLI Commands for shell functionalities Befehle für Shellfunktionalitäten + + SlideshowPanel + + Previous + Zurück + + + Start/pause + Starten/pausieren + + + Next + Weiter + + + Duration: + Dauer: + + + View in separate window + Ansicht in separatem Fenster + + + %1 Master – Slideshow + %1 Master – Diashow + + + + SpotlightPanel + + Add selected computers + Gewählte Computer hinzufügen + + + Remove selected computers + Gewählte Computer entfernen + + + Update computers in realtime + Computer in Echtzeit aktualisieren + + + Spotlight + Scheinwerfer + + + Please select at least one computer to add. + Bitte wählen Sie mindestens einen hinzuzufügenden Computer aus. + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + Computer durch Klick mit der mittleren Maustaste oder mit Hilfe des ersten Buttons hinzufügen. +Der zweite Button entfernt den gewählten oder letzten Computer. + + + + StartAppDialog + + Start application + Anwendung starten + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + Bitte geben Sie die Anwendungen ein, die auf den gewählten Computern gestartet werden sollen. Sie können mehrere Anwendungen über einzelne Zeilen angeben. + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + z.B. "C:\Programme\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + Merken und zum Anwendungsmenü hinzufügen + + + Application name + Anwendungsname + + + Name: + Name: + + + e.g. VLC + z.B. VLC + + SystemTrayIcon @@ -3930,8 +4563,8 @@ Normalerweise ist dies erforderlich, um Terminalserver zu unterstützen.Textnachricht übermitteln - Use the field below to type your message which will be sent to all selected users. - Nutzen Sie das Feld unterhalb, um Ihre Nachricht zu tippen, die an alle Benutzer übermittelt wird. + Please enter your message which send to all selected users. + Bitte geben Sie die Nachricht ein, die an alle gewählten Benutzer übermittelt werden soll. @@ -3979,23 +4612,39 @@ Normalerweise ist dies erforderlich, um Terminalserver zu unterstützen.Enable Desktop Duplication Engine on Windows 8 and newer Desktop-Duplication-Engine unter Windows 8 und neuer aktivieren + + Maximum CPU usage + Maximale CPU-Auslastung + - UserConfig + UserLoginDialog - No write access - Kein Schreibzugriff + User login + Benutzeranmeldung - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - Ihre persönlichen Einstellungen konnten nicht gespeichert werden! Bitte überprüfen Sie den Pfad für die Benutzerkonfiguration mit Hilfe des %1 Configurators. + Please enter a username and password for automatic login on all computers. + Bitte geben Sie einen Benutzernamen und ein Passwort zur automatischen Anmeldung auf allen Computern ein. + + + Username + Benutzername + + + Password + Passwort - UserSessionControl + UserSessionControlPlugin - User session control - Benutzersitzungssteuerung + Log in + Anmelden + + + Click this button to log in a specific user on all computers. + Klicken Sie auf diesen Button, um einen bestimmten Benutzer auf allen Computern anzumelden. Log off @@ -4013,6 +4662,14 @@ Normalerweise ist dies erforderlich, um Terminalserver zu unterstützen.Do you really want to log off the selected users? Möchten Sie wirklich die gewählten Benutzer abmelden? + + User session control + Benutzersitzungssteuerung + + + Do you really want to log off <b>ALL</b> users? + Möchten Sie wirklich <b>ALLE</b> Benutzer abmelden? + VeyonCore @@ -4064,10 +4721,6 @@ Normalerweise ist dies erforderlich, um Terminalserver zu unterstützen.ERROR FEHLER - - licensed for - lizenziert für - USAGE VERWENDUNG @@ -4084,19 +4737,31 @@ Normalerweise ist dies erforderlich, um Terminalserver zu unterstützen.WARNING WARNUNG + + Authentication test + Authentifizierungstest + + + Screen %1 + Bildschirm %1 + - VeyonServiceControl + VeyonMaster - Veyon Service - Veyon-Dienst + No write access + Kein Schreibzugriff + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Ihre persönlichen Einstellungen konnten nicht gespeichert werden! Bitte überprüfen Sie den Pfad für die Benutzerkonfiguration mit Hilfe des %1 Configurators. - VncView + VeyonServiceControl - Establishing connection to %1 ... - Verbindung zu %1 wird hergestellt ... + Veyon Service + Veyon-Dienst @@ -4144,6 +4809,30 @@ Normalerweise ist dies erforderlich, um Terminalserver zu unterstützen.Use alternative user authentication mechanism Alternativen Mechanismus zur Benutzerauthentifizierung verwenden + + User login + Benutzeranmeldung + + + Input start delay + Verzögerung vor Eingabebeginn + + + Simulated key presses interval + Intervall zwischen simulierten Tastendrücken + + + Confirm legal notice (message displayed before user logs in) + Rechtshinweis bestätigen (Nachricht, die vor Benutzeranmeldung angezeigt wird) + + + Use input device interception driver + Eingabegeräte-Interception-Treiber verwenden + + + Use custom power scheme with disabled power button + Benutzerdefiniertes Energieschema mit deaktiviertem Ein-/Ausschaltknopf verwenden + WindowsPlatformPlugin @@ -4152,8 +4841,8 @@ Normalerweise ist dies erforderlich, um Terminalserver zu unterstützen.Plugin zur Implementierung abstrakter Funktionen für die Windows-Plattform - Plugin implementing specific functions for the Windows platform - Plugin zur Implementierung spezifischer Funktionen für die Windows-Plattform + Internal display + Interne Anzeige @@ -4162,30 +4851,34 @@ Normalerweise ist dies erforderlich, um Terminalserver zu unterstützen.The service "%1" is already installed. Der Dienst "%1" ist bereits installiert. - - The service "%1" could not be installed. - Der Dienst "%1" konnte nicht installiert werden. - The service "%1" has been installed successfully. Der Dienst "%1" wurde erfolgreich installiert. - - The service "%1" could not be uninstalled. - Der Dienst "%1" konnte nicht deinstalliert werden. - The service "%1" has been uninstalled successfully. Der Dienst "%1" wurde erfolgreich deinstalliert. - - The start type of service "%1" could not be changed. - Der Starttyp des Diensts "%1" konnte nicht geändert werden. - Service "%1" could not be found. Der Dienst "%1" wurde nicht gefunden. + + The service "%1" could not be installed (error %2). + Der Dienst "%1" konnte nicht installiert werden (Fehler %2). + + + Could not change the failure actions config for service "%1" (error %2). + Die Konfiguration der Fehlermaßnahmen für den Dienst "%1" konnte nicht geändert werden (%2). + + + The service "%1" could not be uninstalled (error %2). + Der Dienst "%1" konnte nicht deinstalliert werden (Fehler %2). + + + The start type of service "%1" could not be changed (error %2). + Der Starttyp des Diensts "%1" konnte nicht geändert werden (Fehler %2). + X11VncConfigurationWidget diff --git a/translations/el.ts b/translations/veyon_el.ts similarity index 73% rename from translations/el.ts rename to translations/veyon_el.ts index 8884bc7e5..165e8eb72 100644 --- a/translations/el.ts +++ b/translations/veyon_el.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -11,7 +11,7 @@ License - Άδεια + Άδεια χρήσης About Veyon @@ -33,26 +33,28 @@ Current language not translated yet (or native English). If you're interested in translating Veyon into your local or another language or want to improve an existing translation, please contact a Veyon developer! - + Δεν υπάρχει μετάφραση σε αυτήν την γλώσσα ακόμα (ή Αγγλικά). + +Εάν ενδιαφέρεσται να μεταφράσετε το Veyon στην γλώσσα σας ή σε κάποια άλλη ή θέλεται να βελτιόσεται την παρούσα μετάφραση, πρακαλούμαι εποικοινωνίσται με κάποιον προγραμματιστή του Veyon! About %1 %2 - Σχετικά %1 %2 + Σχετικά με το %1 %2 Support Veyon project with a donation - Υποστήριξε το Veyon με μία δωρεά + Υποστήριξε το Veyon με μια δωρεά AccessControlPage Computer access control - + Έλεγχος πρόσβασης υπολογιστή Grant access to every authenticated user (default) - + Παραχώρηση πρόσβασης σε όλους τους πιστοποιημένους χρήστες (προεπιλογή) Test @@ -60,11 +62,11 @@ If you're interested in translating Veyon into your local or another langua Process access control rules - + Κανόνες ελέγχου πρόσβασης διεργασίας User groups authorized for computer access - Εξουσιοδοτημένα μέλη ομάδων με πρόσβαση στον υπολογιστή + Ομάδες χρηστών εξουσιοδοτημένες για πρόσβαση στον υπολογιστή Please add the groups whose members should be authorized to access computers in your Veyon network. @@ -72,35 +74,31 @@ If you're interested in translating Veyon into your local or another langua Authorized user groups - Εξουσιοδοτημένα μέλη ομάδων + Εξουσιοδοτημένες ομάδες χρηστών All groups Όλες οι ομάδες - - ... - ... - Access control rules - + Κανόνες ελέγχου πρόσβασης Add access control rule - + Προσθήκη κανόνα ελέγχου πρόσβασης Remove access control rule - + Αφαίρεση κανόνα ελέγχου πρόσβασης Move selected rule down - Μετακίνηση του κανόνα προς τα κάτω + Μετακίνηση επιλεγμένου κανόνα προς τα κάτω Move selected rule up - Μετακίνηση του κανόνα προς τα πάνω + Μετακίνηση επιλεγμένου κανόνα προς τα επάνω Edit selected rule @@ -108,7 +106,7 @@ If you're interested in translating Veyon into your local or another langua Enter username - Εισάγετε όνομα χρήστη + Εισαγωγή ονόματος χρήστη Please enter a user login name whose access permissions to test: @@ -120,7 +118,7 @@ If you're interested in translating Veyon into your local or another langua The specified user is allowed to access computers with this configuration. - Ο συγκεκριμένος χρήστης έχει δικαίωμα πρόσβασης σε υπολογιστή, με αυτή την διαμόρφωση. + Ο συγκεκριμένος χρήστης έχει δικαίωμα πρόσβασης σε υπολογιστές με αυτή τη διαμόρφωση. Access denied @@ -128,26 +126,25 @@ If you're interested in translating Veyon into your local or another langua The specified user is not allowed to access computers with this configuration. - Ο συγκεκριμένος χρήστης δεν έχει δικαίωμα πρόσβασης σε υπολογιστή, με αυτή την διαμόρφωση. + Ο συγκεκριμένος χρήστης δεν έχει δικαίωμα πρόσβασης σε υπολογιστές με αυτή τη διαμόρφωση. Enable usage of domain groups - + Ενεργοποιήση χρήσης ομάδων τομέων User groups backend: - - - - Missing user groups backend - + Υποστίρηξη ομάδων χρηστών - No default user groups plugin was found. Please check your installation! - + Restrict access to members of specific user groups + Περιορισμός πρόσβασης σε μέλη συγκεκριμένης ομάδας χρηστών + + + AccessControlProvider - Restrict access to members of specific user groups + Provider for access control features @@ -155,7 +152,7 @@ If you're interested in translating Veyon into your local or another langua AccessControlRuleEditDialog Edit access control rule - + Επεξεργασία κανόνα ελέγχου General @@ -177,33 +174,13 @@ If you're interested in translating Veyon into your local or another langua Rule description: Περιγραφή κανόνα: - - Invert all conditions ("is/has" interpreted as "is/has not") - Αντιστροφή όλων των συνθηκών ("είναι/έχει" θα είναι "δεν είναι/δεν έχει") - Conditions Συνθήκες - - is member of group - είναι μέλος της ομάδας - - - Accessing computer is localhost - - - - Accessing user is logged on user - - - - Accessing user is already connected - - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. - + Εάν παραπάνω από μία συνθήκη είναι ενεργή κάθε συνθήκη πρέπει να επαλυθεύετει για να εφαρμοστεί ο κανόνας (λογικό AND). Εάν πρέπει μόνο μία απο όλες τις συνθήκες να επαλυθευτεί (λογικό OR) παρακαλούμε διμιουργήσται πολλαπλούς κανόνες πρόσβασης. Action @@ -219,7 +196,7 @@ If you're interested in translating Veyon into your local or another langua Ask logged on user for permission - + Ζήτησε άδεια από τον συνδεδεμένο χρήστη None (rule disabled) @@ -227,38 +204,130 @@ If you're interested in translating Veyon into your local or another langua Accessing user - + Πρόσβαση χρήστη Accessing computer + Πρόσβαση υπολογιστή + + + Always process rule and ignore conditions - Local (logged on) user + Accessing computer and local computer - Local computer - Τοπικός υπολογιστής + User being accessed + - Always process rule and ignore conditions + is logged in locally + είναι τοπικά συνδεδεμένος + + + is logged in remotely + είναι απομακρισμένα συνδεδεμένος + + + No user is logged in locally + Κανένας χρήστης δεν είναι τοπικά συνδεδεμένος + + + One or multiple users are logged in locally + Ένας ή παραπάνω χρήστες είναι τοπικά συνδεδεμένοι + + + No user is logged in remotely + Κανένας χρήστης δεν είναι απομακρισμένα συνδεδεμένος + + + One or multiple users are logged in remotely + Ένας ή παραπάνω χρήστες είναι απομακρισμένα συνδεδεμένοι + + + is located at + βρίσκεται στο + + + is not located at + δεν βρίσκεται στο + + + are located at the same location + βρίσκονται στην ίδια τοποθεσία + + + are not located the same location + δεν βρίσκονται στην ίδια τοποθεσία + + + is member of group + είναι μέλος της ομάδας + + + is not member of group + δεν είναι μέρος κάποιας ομάδας + + + is authenticated via + είναι πιστοποιημένος μέσω + + + is not authenticated via + δεν είναι πιστοποιημένος μέσω + + + has one or more groups in common with user being accessed - No user logged on + has no groups in common with user being accessed - Accessing user has one or more groups in common with local (logged on) user + equals user being accessed - Accessing computer and local computer are at the same location + is different from user being accessed - is located at + is already connected + έχει ήδη συνδεθεί + + + is not connected + δεν έχει συνδεθεί + + + is local computer + είναι τοπικός υπολογιστής + + + is not local computer + δεν είναι τοπικός υπολογιστής + + + Computer being accessed + + + + Session being accessed is a user session + + + + Session being accessed is a login screen + + + + Local computer is already being accessed + + + + Local computer is not yet being accessed @@ -278,7 +347,7 @@ If you're interested in translating Veyon into your local or another langua Accessing computer: - + Πρόσβαση στον υπολογιστή: Please enter the following user and computer information in order to test the configured ruleset. @@ -294,52 +363,54 @@ If you're interested in translating Veyon into your local or another langua The access in the given scenario is allowed. - + Επιτρέπεται η πρόσβαση στο δεδομένο σενάριο. The access in the given scenario is denied. - + Η πρόσβαση στο δεδομένο σενάριο δεν επιτρέπεται. The access in the given scenario needs permission of the logged on user. - + Η πρόσβαση στο δεδομένο σενάριο χρειάζεται άδεια από τον συνδεδεμένο χρήστη. + + + Test result + Αποτέλεσμα δοκιμής - ERROR: Unknown action + Authentication method - Test result - Αποτέλεσμα δοκιμής + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformConfigurationPage + AuthKeysConfigurationWidget - Android + Introduction + Εισαγωγή + + + Please perform the following steps to set up key file authentication: - General - Γενικά + 1) Create a key pair on the master computer. + - - - AndroidPlatformPlugin - Plugin implementing specific functions for the Android platform + 2) Set an access group whose members should be allowed to access other computers. - - - AuthKeysConfigurationPage - Authentication keys + 3) Export the public key and import it on all client computers with the same name. - Introduction - Εισαγωγή + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Key file directories @@ -354,11 +425,14 @@ If you're interested in translating Veyon into your local or another langua - ... - ... + Available authentication keys + - Available authentication keys + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. @@ -387,7 +461,7 @@ If you're interested in translating Veyon into your local or another langua Authentication key name - + Όνομα κλειδιού ελέγχου ταυτότητας Please enter the name of the user group or role for which to create an authentication key pair: @@ -401,10 +475,6 @@ If you're interested in translating Veyon into your local or another langua Please select a key to delete! Επιλέξτε ένα κλειδί για διαγραφή! - - Please enter the name of the user group or role for which to import the authentication key: - - Please select a key to export! Επιλέξτε ένα κλειδί για εξαγωγή! @@ -418,30 +488,9 @@ If you're interested in translating Veyon into your local or another langua - Please perform the following steps to set up key file authentication: - - - - 1) Create a key pair on the master computer. - - - - 2) Set an access group whose members should be allowed to access other computers. - - - - 3) Export the public key and import it on all client computers with the same name. - - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. @@ -573,7 +622,7 @@ The public key is used on client computers to authenticate incoming connection r <N/A> - + <N/A> Failed to read key file. @@ -612,7 +661,7 @@ The public key is used on client computers to authenticate incoming connection r KEY - + ΚΛΕΙΔΙ ACCESS GROUP @@ -624,11 +673,11 @@ The public key is used on client computers to authenticate incoming connection r NAME - + ΟΝΟΜΑ FILE - + ΑΡΧΕΙΟ This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. @@ -643,35 +692,51 @@ The public key is used on client computers to authenticate incoming connection r - Please specify the command to display help for! + TYPE + ΤΥΠΟΣ + + + PAIR ID - TYPE + Commands for managing authentication keys - PAIR ID + This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. - Command line support for managing authentication keys + This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. - Commands for managing authentication keys + This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. - This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. - This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. + Key file authentication - This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + Key file + + + + Please specify the key name (e.g. "teacher/public") as the first argument. + + + + Please specify the command to display help for. + + + + The specified command does not exist or no help is available for it. @@ -683,7 +748,7 @@ The public key is used on client computers to authenticate incoming connection r Type - + Τύπος Access group @@ -695,94 +760,237 @@ The public key is used on client computers to authenticate incoming connection r - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - Υπολογιστές + General + Γενικά - Name - Όνομα + Username to bind DN mapping: + - Host address/IP - Διεύθυνση ΙΡ + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + π.χ. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + AuthLdapDialog - MAC address - Διεύθυνση MAC + Veyon Logon + - Add new computer - Προσθήκη υπολογιστή + Please enter your domain/LDAP username and password in order to access computers. + - Remove selected computer - Διαγραφή του επιλεγμένου υπολογιστή + Username + Όνομα χρήστη - New computer - Καινούριος υπολογιστής + Password + Κωδικός πρόσβασης - Builtin directory - + Authentication error + Σφάλμα ελέγχου ταυτότητας - Locations & computers + Logon failed with given username and password. Please try again! + + + AuthLogonDialog - Locations + Veyon Logon - Add new location + Please enter your username and password in order to access computers. - Remove selected location - + Username + Όνομα χρήστη - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - + Password + Κωδικός πρόσβασης - New location + Authentication error + Σφάλμα ελέγχου ταυτότητας + + + Logon failed with given username and password. Please try again! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Import objects from given file + Logon authentication - Export objects to given file - + Logon + Σύνδεση + + + AuthSimpleDialog - Invalid type specified. Valid values are "%1" or "%2". + Veyon Logon - Type + Please enter the Veyon password: + + + + Authentication error + Σφάλμα ελέγχου ταυτότητας + + + Logon failed with given password. Please try again! + + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + + + + Simple password authentication + + + + Simple password + + + + + AuthenticationPage + + Authentication is set up properly on this computer. + + + + + AuthenticationPageTab + + Enabled + + + + Test + Δοκιμή + + + + BuiltinDirectoryConfiguration + + Builtin directory + + + BuiltinDirectoryConfigurationPage + + Computers + Υπολογιστές + Name Όνομα - Host address + Host address/IP + Διεύθυνση/ΙΡ κεντρικού υπολογιστή + + + MAC address + Διεύθυνση MAC + + + Add new computer + Προσθήκη νέου υπολογιστή + + + Remove selected computer + Διαγραφή του επιλεγμένου υπολογιστή + + + New computer + Νέος υπολογιστής + + + Builtin directory + + + + Locations + Τοποθεσίες + + + Add new location + Προσθήκη νέας τοποθεσίας + + + Remove selected location + Αφαίρεση της επιλεγεμένης τοποθεσίας + + + New location + Νέα τοποθεσία + + + Directory name + Όνομα καταλόγου + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + + + + BuiltinDirectoryPlugin + + Show help for specific command + + + + Import objects from given file + + + + Export objects to given file + + + + Invalid type specified. Valid values are "%1" or "%2". + + Type + Τύπος + + + Name + Όνομα + + + Host address + Διεύθυνση υπολογιστή + MAC address Διεύθυνση MAC @@ -793,7 +1001,7 @@ The public key is used on client computers to authenticate incoming connection r File "%1" does not exist! - + Το αρχείο "%1" δεν υπάρχει! Can't open file "%1" for reading! @@ -817,7 +1025,7 @@ The public key is used on client computers to authenticate incoming connection r Computer - + Υπολογιστής Root @@ -861,11 +1069,11 @@ The public key is used on client computers to authenticate incoming connection r Add a location or computer - + Προσθέστε μια τοποθεσία ή υπολογιστή Clear all locations and computers - + Εκκαθάριση όλων των τοποθεσιών και υπολογιστών Dump all or individual locations and computers @@ -877,11 +1085,11 @@ The public key is used on client computers to authenticate incoming connection r Remove a location or computer - + Αφαιρέστε μια τοποθεσία ή υπολογιστή Location "%1" - + Τοποθεσία "%1" Builtin (computers and locations in local configuration) @@ -889,15 +1097,15 @@ The public key is used on client computers to authenticate incoming connection r Location - + Τοποθεσία FILE - + ΑΡΧΕΙΟ LOCATION - + ΤΟΠΟΘΕΣΙΑ FORMAT-STRING-WITH-PLACEHOLDERS @@ -941,11 +1149,11 @@ The public key is used on client computers to authenticate incoming connection r TYPE - + ΤΥΠΟΣ NAME - + ΟΝΟΜΑ PARENT @@ -965,7 +1173,7 @@ The public key is used on client computers to authenticate incoming connection r OBJECT - + ΑΝΤΙΚΕΙΜΕΝΟ Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. @@ -993,6 +1201,14 @@ The public key is used on client computers to authenticate incoming connection r MAC ADDRESS + ΔΙΕΥΘΥΝΣΗ MAC + + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. @@ -1012,10 +1228,6 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - - Active features: %1 @@ -1032,10 +1244,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off - - Service unreachable or not running - - Authentication failed or access denied @@ -1046,7 +1254,7 @@ The public key is used on client computers to authenticate incoming connection r No user logged on - + Κανένας χρήστης σε σύνδεση Logged on user: %1 @@ -1056,6 +1264,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 + + [no user] + + + + Veyon Server unreachable or not running + + + + Name: %1 + Όνομα: %1 + + + Hostname: %1 + + + + unknown + άγνωστο + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + ComputerControlServer @@ -1065,7 +1305,7 @@ The public key is used on client computers to authenticate incoming connection r Authentication error - + Σφάλμα ελέγχου ταυτότητας Remote access @@ -1087,6 +1327,17 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + + Active connections: + Ενεργές συνδέσεις: + + + + ComputerGroupSelector + + Group %1 + + ComputerManager @@ -1108,26 +1359,61 @@ The public key is used on client computers to authenticate incoming connection r Computer name;Hostname;User - + Όνομα υπολογιστή;Κεντρικός υπολογιστής;Χρήστης Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + + Logged in since + + + + %1 days + + + + 1 day + + - ComputerSelectPanel + ComputerMonitoring + + Computers + Υπολογιστές + + + Search users and computers + Αναζήτηση χρηστών και υπολογιστών + + + Select all + Επιλογή όλων + + + Unselect all + Αποεπιλογή όλων + + + Add to group + + - Computer management - Διαχείριση υπολογιστή + Remove from group + + + + ComputerSelectPanel Computer search Αναζήτηση υπολογιστή Add location - + Προσθήκη τοποθεσίας Save computer/user list @@ -1139,7 +1425,7 @@ The public key is used on client computers to authenticate incoming connection r CSV files (*.csv) - + Αρχεία CSV (*.csv) File error @@ -1149,79 +1435,83 @@ The public key is used on client computers to authenticate incoming connection r Could not write the computer and users list to %1! Please check the file access permissions. + + Search computers + + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. + Clear system-wide Veyon configuration - Please specify a valid filename for the configuration export. + List all configuration keys and values - Please specify a valid key. + Import configuration from given file - Specified key does not exist in current configuration! + Export configuration to given file - Please specify a valid value. + Read and output configuration value for given key - Configure Veyon at command line + Write given value to given configuration key - Output file is not writable! + Unset (remove) given configuration key - Output directory is not writable! + Upgrade and save configuration of program and plugins - Configuration file is not readable! + Please specify an existing configuration file to import. - Clear system-wide Veyon configuration + Configuration file is not readable! - List all configuration keys and values + Please specify a valid filename for the configuration export. - Import configuration from given file + Output file is not writable! - Export configuration to given file + Output directory is not writable! - Read and output configuration value for given key + Please specify a valid key. - Write given value to given configuration key + Specified key does not exist in current configuration! - Unset (remove) given configuration key + Please specify a valid value. - Commands for managing the configuration of Veyon + Configure Veyon at command line - Upgrade and save configuration of program and plugins + Commands for managing the configuration of Veyon @@ -1247,6 +1537,10 @@ The public key is used on client computers to authenticate incoming connection r Could not apply platform-specific configuration settings. + + Could not configure the firewall configuration for the %1 Service. + + DemoClient @@ -1259,7 +1553,7 @@ The public key is used on client computers to authenticate incoming connection r DemoConfigurationPage Demo server - + Διακομιστής επίδειξης Tunables @@ -1277,10 +1571,6 @@ The public key is used on client computers to authenticate incoming connection r Memory limit - - Use multithreading (experimental) - - MB ΜΒ @@ -1297,13 +1587,17 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running + + Bandwidth limit + + + + MB/s + + DemoFeaturePlugin - - Fullscreen demo - Παρουσίαση σε πλήρη οθόνη - Stop demo Διακοπή παρουσίασης @@ -1317,18 +1611,62 @@ The public key is used on client computers to authenticate incoming connection r Κάντε μια παρουσίαση μεταδίδοντας το περιεχόμενο της οθόνης σας - Demo server + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. + Demo - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Share your screen or allow a user to share his screen with other users. - + + Full screen demo + + + + Share your own screen in fullscreen mode + + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share your own screen in a window + + + + Share selected user's screen in fullscreen mode + + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share selected user's screen in a window + + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + + + + Please select only one user screen to share. + + + + All screens + Όλες οι οθόνες + + DesktopAccessDialog @@ -1354,14 +1692,6 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - - Programs & websites - - - - Predefined programs - - Name Όνομα @@ -1371,40 +1701,48 @@ The public key is used on client computers to authenticate incoming connection r - Add new program + Predefined websites - Remove selected program + Remove selected website - Predefined websites - + URL + URL - Remove selected website + New website - URL + Applications & websites + Εφαρμογές και ιστότοποι + + + Predefined applications - New program + Add new application - New website + Remove selected application + + Add new website + Προσθήκη νέου ιστότοπου + + + New application + Νέα εφαρμογή + DesktopServicesFeaturePlugin - - Run program - Εκτέλεση προγράμματος - Open website Άνοιγμα ιστοχώρου @@ -1414,27 +1752,31 @@ The public key is used on client computers to authenticate incoming connection r Πατήστε το κουμπί για να ανοίξετε έναν ιστοχώρο σε όλους τους υπολογιστές. - Start programs and services in user desktop + Open website "%1" - Click this button to run a program on all computers. + Custom website - Run program "%1" + Start application + Έναρξη εφαρμογής + + + Click this button to start an application on all computers. - Custom program + Start application "%1" - Open website "%1" + Custom application - Custom website + Start apps and open websites in user sessions @@ -1469,15 +1811,19 @@ The public key is used on client computers to authenticate incoming connection r - Custom program + Handout - Handout + Texts to read - Texts to read + generic-student-user + + + + Custom application @@ -1504,9 +1850,164 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands + + List names of all available features + + + + Show table with details of all available features + + + + Start a feature on a remote host + + + + Stop a feature on a remote host + + + + Please specify the command to display help for. + + + + Displays a list with the names of all available features. + + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + + + + HOST ADDRESS + + + + FEATURE + + + + ARGUMENTS + + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + + + + Lock the screen + Κλείδωμα οθόνης + + + Display a text message + + + + Test message + + + + Start an application + + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + + + + Unlock the screen + + + + The specified command does not exist or no help is available for it. + + + + Name + Όνομα + + + Description + + + + Master + + + + Service + Υπηρεσία + + + Worker + + + + UID + + + + Plugin + + + + Invalid feature name or UID specified + + + + Error parsing the JSON-encoded arguments: %1 + + + + Failed to initialize credentials + + + + Could not establish a connection to host %1 + + + + Failed to send feature control message to host %1 + + + + Feature-related CLI operations + + + + Commands for controlling features + + + + + FileTransferConfigurationPage + + File transfer + Μεταφορά αρχείων + + + Directories + Φάκελοι + + + Destination directory + + + + Default source directory + + + + Options + Επιλογές + + + Remember last source directory + + - Feature control + Create destination directory if it does not exist @@ -1521,11 +2022,11 @@ The public key is used on client computers to authenticate incoming connection r FileTransferDialog File transfer - + Μεταφορά αρχείων Options - + Επιλογές Transfer only @@ -1541,22 +2042,29 @@ The public key is used on client computers to authenticate incoming connection r Files - + Αρχεία Start - + Εκκίνηση Overwrite existing files + + FileTransferFileDialog + + Select one or more files to transfer + Επιλέξτε ένα ή περισσότερα αρχεία για μεταφορά + + FileTransferPlugin File transfer - + Μεταφορά αρχείων Click this button to transfer files from your computer to all computers. @@ -1564,7 +2072,7 @@ The public key is used on client computers to authenticate incoming connection r Select one or more files to transfer - + Επιλέξτε ένα ή περισσότερα αρχεία για μεταφορά Transfer files to remote computer @@ -1609,10 +2117,6 @@ The public key is used on client computers to authenticate incoming connection r Log file directory Φάκελος αρχείου καταγραφής - - ... - ... - Log level Λεπτομέρεια αρχείου καταγραφής @@ -1653,18 +2157,6 @@ The public key is used on client computers to authenticate incoming connection r Log to standard error output - - Network object directory - - - - Backend: - - - - Update interval: - Ρυθμός ανανέωσης: - %1 service υπηρεσία %1 @@ -1701,102 +2193,79 @@ The public key is used on client computers to authenticate incoming connection r x x - - seconds - δευτερόλεπτα - Write to logging system of operating system - Authentication - - - - Method: - - - - Logon authentication + TLS configuration - Key file authentication + Use certificate authority for TLS connections - Test - Δοκιμή - - - Authentication is set up properly on this computer. + CA certificate file - Authentication keys are not set up properly on this computer. - + ... + ... - Authentication test + Host certificate file - - - InternetAccessControlConfigurationPage - Internet access control + Host private key file - Backend: + Style: - General settings + Native - Backend settings + Color scheme: - - - InternetAccessControlPlugin - Block access to the internet + Light - Allow access to the internet + Dark - Show help about command - Εμφάνιση βοήθειας για την εντολή - - - Block internet - + User groups + Ομάδες χρηστών - Click this button to block access to the internet. + Backend: - Unblock internet + Include user groups from domain - Click this button to allow access to the internet. - + Missing user groups backend + Έλλειψη υποστίριξης ομαδών χρηστών - Control access to the internet + No user groups plugin was found. Please check your installation! + + + HeadlessVncServer - Commands for controlling access to the internet + Headless VNC server @@ -1815,314 +2284,284 @@ The public key is used on client computers to authenticate incoming connection r - LdapConfigurationPage + LdapConfiguration - Basic settings - Βασικές ρυθμίσεις - - - General - Γενικά - - - LDAP server and port - Διακομιστής και πόρτα LDAP - - - Bind DN - - - - Bind password - - - - Anonymous bind + LDAP connection failed - Use bind credentials + Could not connect to the LDAP server. Please check the server parameters. + +%1 - Base DN + LDAP bind failed - Fixed base DN + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 - e.g. dc=example,dc=org + LDAP bind successful - Discover base DN by naming context + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - e.g. namingContexts or defaultNamingContext + LDAP base DN test failed - Environment settings + Could not query the configured base DN. Please check the base DN parameter. + +%1 - Object trees + LDAP base DN test successful - Computer tree + The LDAP base DN has been queried successfully. The following entries were found: + +%1 - e.g. OU=Groups + LDAP naming context test failed - User tree + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 - e.g. OU=Users + LDAP naming context test successful - e.g. OU=Computers + The LDAP naming context has been queried successfully. The following base DN was found: +%1 - Group tree + user tree - Perform recursive search operations in object trees + User tree - Object attributes + group tree - e.g. hwAddress + Group tree - e.g. member or memberUid + computer tree - e.g. dNSHostName + Computer tree - Computer MAC address attribute + computer group tree - Group member attribute + Computer group tree - e.g. uid or sAMAccountName + user objects - Advanced settings + User login name attribute - Optional object filters - + group members + μέλη ομάδας - Filter for user groups + Group member attribute - Filter for users - + Group not found + Δεν βρέθηκε η ομάδα - Filter for computer groups + Could not find a group with the name "%1". Please check the group name or the group tree parameter. - Group member identification + computer objects - Distinguished name (Samba/AD) + Computer display name attribute - List all groups of a user + Invalid hostname - List all groups of a computer + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Get computer object by IP address + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - LDAP connection failed + Computer hostname attribute - LDAP bind failed + computer MAC addresses - LDAP bind successful + Computer MAC address attribute - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + computer locations - LDAP base DN test failed + Computer location attribute - LDAP base DN test successful + Location name attribute - LDAP naming context test failed - + users + χρήστες - LDAP naming context test successful - + user groups + ομάδες χρηστών - The LDAP naming context has been queried successfully. The following base DN was found: -%1 - + computers + υπολογιστές - user tree - + computer groups + ομάδες υπολογιστών - group tree + computer containers - computer tree + groups of user - Enter username - Εισάγετε όνομα χρήστη + User not found + Δεν βρέθηκε ο χρήστης - Please enter a user login name (wildcards allowed) which to query: + Could not find a user with the name "%1". Please check the username or the user tree parameter. - user objects + groups of computer - Enter group name + Computer not found - Please enter a group name whose members to query: + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - group members - μέλη ομάδας - - - Group not found - Δεν βρέθηκε η ομάδα - - - Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Hostname lookup failed - Enter computer name + Could not lookup hostname for IP address %1. Please check your DNS server settings. - computer objects + location entries - Enter computer DN + Computer groups filter - Please enter the DN of a computer whose MAC address to query: + Computer locations identification - computer MAC addresses + Filter for computer groups - users - χρήστες - - - user groups - ομάδες χρηστών - - - computer groups - ομάδες υπολογιστών - - - Please enter a user login name whose group memberships to query: + Invalid test value - groups of user + An empty or invalid value has been supplied for this test. - User not found + LDAP %1 test failed - groups of computer + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 - Computer not found + LDAP %1 test successful - Enter computer IP address + The %1 has been queried successfully and %2 entries were found. - Please enter a computer IP address which to resolve to an computer object: + LDAP test failed - computers - υπολογιστές - - - LDAP %1 test failed + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 - LDAP %1 test successful + and - The %1 has been queried successfully and %2 entries were found. + LDAP test successful @@ -2150,538 +2589,484 @@ The public key is used on client computers to authenticate incoming connection r - (only if different from group tree) - - - - Computer group tree - - - - computer group tree - - - - Filter for computers - - - - e.g. room or computerLab - - - - Integration tests - - - - Computer groups + LDAP directory + + + LdapConfigurationPage - e.g. name or description - + Basic settings + Βασικές ρυθμίσεις - Filter for computer containers - + General + Γενικά - Computer containers or OUs - + LDAP server and port + Διακομιστής και πόρτα LDAP - Connection security + Bind DN - TLS certificate verification + Bind password - System defaults + Anonymous bind - Never (insecure!) + Use bind credentials - Custom CA certificate file + Base DN - None + Fixed base DN - TLS + e.g. dc=example,dc=org - SSL + Discover base DN by naming context - e.g. (objectClass=computer) + e.g. namingContexts or defaultNamingContext - e.g. (objectClass=group) + Environment settings - e.g. (objectClass=person) + Object trees - e.g. (objectClass=room) or (objectClass=computerLab) + Computer tree - e.g. (objectClass=container) or (objectClass=organizationalUnit) + e.g. OU=Groups - Could not query the configured base DN. Please check the base DN parameter. - -%1 + User tree - The LDAP base DN has been queried successfully. The following entries were found: - -%1 + e.g. OU=Users - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 + e.g. OU=Computers - Certificate files (*.pem) + Group tree - Could not connect to the LDAP server. Please check the server parameters. - -%1 + Perform recursive search operations in object trees - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 + Object attributes - Encryption protocol + e.g. hwAddress - Computer location attribute + e.g. member or memberUid - Computer display name attribute + e.g. dNSHostName - Location name attribute + Computer MAC address attribute - e.g. cn or displayName + Group member attribute - Computer locations identification + e.g. uid or sAMAccountName - Identify computer locations (e.g. rooms) via: + Advanced settings - Location attribute in computer objects + Optional object filters - List all entries of a location + Filter for user groups - List all locations + Filter for users - Enter computer display name + Filter for computer groups - Please enter a computer display name to query: + Group member identification - Enter computer location name + Distinguished name (Samba/AD) - Please enter the name of a computer location (wildcards allowed): + List all groups of a user - computer locations + List all groups of a computer - Enter location name + Get computer object by IP address - Please enter the name of a location whose entries to query: - + Enter username + Εισάγετε όνομα χρήστη - location entries + Please enter a user login name (wildcards allowed) which to query: - LDAP test failed + Enter group name - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 + Please enter a group name whose members to query: - and - + Enter computer name + Εισαγωγή ονόματος υπολογιστή - LDAP test successful + Enter computer DN - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 + Please enter the DN of a computer whose MAC address to query: - Browse + Please enter a user login name whose group memberships to query: - Test - Δοκιμή + Enter computer IP address + Εισαγωγή διεύθυνσης IP υπολογιστή - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Please enter a computer IP address which to resolve to an computer object: - Computer hostname attribute + (only if different from group tree) - Please enter a computer hostname to query: + Computer group tree - Invalid hostname + Filter for computers - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + e.g. room or computerLab - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Integration tests - Could not find a user with the name "%1". Please check the username or the user tree parameter. + Computer groups - Enter hostname + e.g. name or description - Please enter a computer hostname whose group memberships to query: + Filter for computer containers - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Computer containers or OUs - Hostname lookup failed + Connection security - Could not lookup hostname for IP address %1. Please check your DNS server settings. + TLS certificate verification - User login name attribute + System defaults - Configured attribute for user login name or computer hostname (OpenLDAP) + Never (insecure!) - computer containers + Custom CA certificate file - - - LdapPlugin - Auto-configure the base DN via naming context + None - Query objects from LDAP directory - + TLS + TLS - Show help about command - Εμφάνιση βοήθειας για την εντολή + SSL + SSL - Commands for configuring and testing LDAP/AD integration + e.g. (objectClass=computer) - Basic LDAP/AD support for Veyon + e.g. (objectClass=group) - %1 (load computers and locations from LDAP/AD) + e.g. (objectClass=person) - %1 (load users and groups from LDAP/AD) + e.g. (objectClass=room) or (objectClass=computerLab) - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + e.g. (objectClass=container) or (objectClass=organizationalUnit) - No naming context attribute name given - falling back to configured value. + Certificate files (*.pem) - Could not query base DN. Please check your LDAP configuration. + Encryption protocol - Configuring %1 as base DN and disabling naming context queries. + Computer location attribute - - - LdapProConfigurationPage - LDAP Pro + Computer display name attribute - Instances + Location name attribute - Enter name + e.g. cn or displayName - Please enter a name for the instance (can't be changed later!): + Computer locations identification - Remove instance + Identify computer locations (e.g. rooms) via: - Do you really want to remove instance "%1"? + Location attribute in computer objects - Configuration for instance "%1" + List all entries of a location - - - LdapProPlugin - Professional LDAP/AD integration for Veyon + List all locations - %1 (load computers and locations from LDAP/AD) + Enter computer display name - %1 (load users and groups from LDAP/AD) + Please enter a computer display name to query: - - - LicensingConfigurationPage - Licensing + Enter computer location name - Installed licenses + Please enter the name of a computer location (wildcards allowed): - Add new network range + Enter location name - Remove selected network range + Please enter the name of a location whose entries to query: - ID + Browse - Feature - + Test + Δοκιμή - Valid until + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - Licensee + Computer hostname attribute - Browse license file + Please enter a computer hostname to query: - Veyon license files (*.vlf) + Enter hostname - Remove license + Please enter a computer hostname whose group memberships to query: - Do you really want to remove the selected license? + User login name attribute - <N/A> + Configured attribute for user login name or computer hostname (OpenLDAP) - Invalid license file - + Directory name + Όνομα καταλόγου - Could not open the license file for reading! + Query options - The selected license file does not contain valid data. + Query nested user groups (supported by AD only) - The selected license file could not be verified. + Query timeout - The selected license file is not valid for this installation. - + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. - + LDAP + LDAP - The license is already installed. + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + LdapPlugin - Information + Auto-configure the base DN via naming context - Installation ID + Query objects from LDAP directory - Addons available for licensing - + Show help about command + Εμφάνιση βοήθειας για την εντολή - Addon + Commands for configuring and testing LDAP/AD integration - - - LicensingPlugin - Show help for specific command + Basic LDAP/AD support for Veyon - Show all installed licenses + %1 (load computers and locations from LDAP/AD) - Add license file + %1 (load users and groups from LDAP/AD) - Remove installed license + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - -USAGE - -%1 add <LICENSE FILE> - - + No naming context attribute name given - falling back to configured value. - -USAGE - -%1 remove <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. - No certificate found with given ID + Configuring %1 as base DN and disabling naming context queries. - <N/A> + Test binding to an LDAP server - Licensing management + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Commands for managing license keys + LDAP bind @@ -2689,7 +3074,7 @@ USAGE LinuxPlatformConfigurationPage Linux - + Linux Custom PAM service for user authentication @@ -2697,14 +3082,22 @@ USAGE User authentication + Έλεγχος ταυτότητας χρήστη + + + User sessions - Session management + Minimum session lifetime before server start - Display manager users + User login + Σύνδεση χρήστη + + + Login key sequence @@ -2714,16 +3107,12 @@ USAGE Plugin implementing abstract functions for the Linux platform - - Plugin implementing specific functions for the Linux platform - - LocationDialog Select location - + Επιλογή τοποθεσίας enter search filter... @@ -2736,14 +3125,14 @@ USAGE Configuration Ρυθμίσεις - - Disable balloon tooltips - - Show icons only Προβολή μόνο των εικονιδίων + + Disable tooltips + + MainWindow @@ -2781,7 +3170,7 @@ USAGE L&oad settings from file - + Φ&όρτωση ρυθμίσεων από αρχείο Ctrl+O @@ -2791,17 +3180,13 @@ USAGE About Qt Σχετικά με το Qt - - Authentication impossible - - Configuration not writable Load settings from file - + Φόρτωση ρυθμίσεων από αρχείο Save settings to file @@ -2849,16 +3234,12 @@ USAGE JSON files (*.json) - + Αρχεία JSON (*.json) The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - - Access denied Δεν επιτρέπεται η πρόσβαση @@ -2889,11 +3270,7 @@ USAGE Search users and computers - - - - Adjust optimal size - + Αναζήτηση χρηστών και υπολογιστών Align computers to grid @@ -2917,11 +3294,11 @@ USAGE &Save settings to file - + &Αποθήκευση ρυθμίσεων σε αρχείο &View - + &Προβολή &Standard @@ -2937,6 +3314,48 @@ USAGE Locations && computers + Τοποθεσίες && υπολογιστές + + + Authentication + Αυθεντικοποίηση + + + Adjust size of computer icons automatically + + + + Slideshow + + + + Spotlight + + + + Veyon Master + + + + Locations & computers + Τοποθεσίες & υπολογιστές + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + + + + Load computer positions + + + + Save computer positions @@ -2946,10 +3365,6 @@ USAGE Directories Φάκελοι - - ... - ... - User configuration @@ -3032,11 +3447,15 @@ USAGE Only user name + Μόνο όνομα χρήστη + + + Only last part of user name Only computer name - + Μόνο όνομα υπολογιστή Computer thumbnail caption @@ -3044,7 +3463,7 @@ USAGE Text color - + Χρώμα κειμένου Sort order @@ -3068,7 +3487,7 @@ USAGE Hide empty locations - + Απόκρυψη άδειων τοποθεσιών Show confirmation dialog for potentially unsafe actions @@ -3083,164 +3502,179 @@ USAGE - Automatically adjust computer thumbnail size + Automatically open computer select panel - Automatically open computer select panel + Use modern user interface (experimental) - - - MonitoringMode - Monitoring + Thumbnail spacing - Builtin monitoring mode + px - This mode allows you to monitor all computers at one or more locations. + Hide local session - - - NetworkDiscoveryConfigurationPage - Network discovery + Auto + Αυτόματα + + + Thumbnail aspect ratio - Mode + Automatically adjust computer icon size - Scan network ranges + Open feature windows on the same screen as the main window - e.g. 192.168.1.0/24 + Configuration templates - Scan all subnets of computer + Image quality in monitoring mode - Scan custom subnet + Highest - Scan sessions on local computer + High - Test - Δοκιμή + Medium + + + + Low + - Network ranges + Lowest - Add new group + Remote access image quality - Remove selected group + Advanced - Groups + Computer name source - First address + Default - Last address + Host address + Διεύθυνση κεντρικού υπολογιστή + + + Session client address - Add new network range + Session client name - Remove selected network range + Session host name - Parallel scans + Session metadata - Scan timeout + Full name of user - ms - ms + User login name + - Session scan limit + Computer UID role - Options + Session meta data hash - Reverse lookup discovered IP addresses to host names + Always expand all locations - New location + Image quality - NetworkDiscoveryDirectory + MonitoringMode - Scanning... + Monitoring - Discovered computers + Builtin monitoring mode - - - NetworkDiscoveryPlugin - Show help for specific command + This mode allows you to monitor all computers at one or more locations. - Scan a subnet + Query application version of the server - -USAGE - -%1 scan [<SUBNET>] - - + Query active features - Network object directory which automatically discovers computers in the network + Query properties of remotely available screens + + + NestedNetworkObjectDirectory - Network discovery (scan network for Veyon clients) + All directories + + + NetworkObjectDirectoryConfigurationPage + + Update interval: + Ρυθμός ανανέωσης: + + + seconds + δευτερόλεπτα + + + + NetworkObjectDirectoryConfigurationPageTab - Commands for managing the network discovery directory + Enabled @@ -3275,33 +3709,45 @@ USAGE Name: + Όνομα: + + + Website name - PasswordDialog + PluginCommands - Username - Όνομα χρήστη + List names of all installed plugins + - Password - Κωδικός πρόσβασης + Show table with details of all installed plugins + - Veyon Logon + Name + Όνομα + + + Description - Authentication error + Version - Logon failed with given username and password. Please try again! + UID - Please enter your username and password in order to access computers. + Plugin-related CLI operations + + + + Commands for managing plugins @@ -3325,7 +3771,7 @@ USAGE Power down - + Τερματισμός λειτουργίας Click this button to power down all computers. This way you do not have to power down each computer by hand. @@ -3347,17 +3793,13 @@ USAGE Do you really want to reboot the selected computers? - - Do you really want to power down the selected computer? - - Power on a computer via Wake-on-LAN (WOL) MAC ADDRESS - + ΔΙΕΥΘΥΝΣΗ MAC This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. @@ -3377,19 +3819,19 @@ USAGE Power down now - + Τερματισμός λειτουργίας τώρα Install updates and power down - + Εγκατάσταση ενημερώσεων και τερματισμός λειτουργίας Power down after user confirmation - + Τερματισμός λειτουργίας μετά από επιβεβαίωση χρήστη Power down after timeout - + Τερματισμός λειτουργίας μετά από λήξη χρονικού ορίου The computer was remotely requested to power down. Do you want to power down the computer now? @@ -3401,12 +3843,24 @@ USAGE Please save your work and close all programs. + + Do you really want to reboot <b>ALL</b> computers? + + + + Do you really want to power down <b>ALL</b> computers? + + + + Do you really want to power down the selected computers? + + PowerDownTimeInputDialog Power down - + Τερματισμός λειτουργίας Please specify a timeout for powering down the selected computers: @@ -3414,18 +3868,18 @@ Please save your work and close all programs. minutes - + λεπτά seconds - + δευτερόλεπτα RemoteAccessFeaturePlugin Remote view - + Απομακρυσμένη προβολή Open a remote view for a computer without interaction. @@ -3448,26 +3902,41 @@ Please save your work and close all programs. Απομακρυσμένος έλεγχος/προβολή ενός υπολογιστή - Please enter the hostname or IP address of the computer to access: + Show help about command + Εμφάνιση βοήθειας για την εντολή + + + Exchange clipboard contents - Show help about command - Εμφάνιση βοήθειας για την εντολή + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + + + RemoteAccessPage + + Remote access: %1 + Απομακρυσμένη πρόσβαση: %1 RemoteAccessWidget %1 - %2 Remote Access - + %1 - %2 Απομακρυσμένη πρόσβαση + + + %1 - %2 - %3 Remote Access + %1 - %2 - %3 Απομακρυσμένη πρόσβαση RemoteAccessWidgetToolBar View only - Προβολή μόνο + Μόνο προβολή Remote control @@ -3517,10 +3986,6 @@ Please save your work and close all programs. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - Σύνδεση σε %1 - Connected. Συνδεδεμένος @@ -3531,148 +3996,169 @@ Please save your work and close all programs. Exit - + Έξοδος - - - Routing - Control internet access by modifying routing table - + Connecting... + Σύνδεση... + + + Select screen + Επιλογή οθόνης + + + All screens + Όλες οι οθόνες - RoutingConfigurationWidget + ScreenLockFeaturePlugin - Remove default routes to block internet access - + Lock + Κλείδωμα - Add custom route to block internet - + Unlock + Ξεκλείδωμα - Destination + Lock screen and input devices of a computer - Gateway + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. - - - RunProgramDialog - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - + Lock input devices + Κλείδωμα συσκευών εισόδου - Run programs - Εκτέλεση προγραμμάτων + Unlock input devices + Ξεκλείδωμα συσκευών εισόδου - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + + Screenshot + + unknown + άγνωστο + - Name: + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. - Remember and add to program menu - + Screenshot + Στιγμιότυπο οθόνης - e.g. VLC + Could not open screenshot file %1 for writing. - ScreenLockFeaturePlugin + ScreenshotFeaturePlugin - Lock - Κλείδωμα + Screenshot + Στιγμιότυπο οθόνης - Unlock - Ξεκλείδωμα + Use this function to take a screenshot of selected computers. + - Lock screen and input devices of a computer + Screenshots taken - To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + Screenshot of %1 computer have been taken successfully. + + + + Take screenshots of computers and save them locally. - Screenshot + ScreenshotManagementPage - unknown - άγνωστο + Screenshots + Στιγμιότυπα οθόνης + + + ScreenshotManagementPanel - Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. - Screenshot - Στιγμιότυπο + User: + Χρήστης: - - - ScreenshotFeaturePlugin - Screenshot - Στιγμιότυπο + Computer: + Υπολογιστής: - Use this function to take a screenshot of selected computers. - + Date: + Ημερομηνία: - Screenshots taken - + Time: + Ώρα: - Screenshot of %1 computer have been taken successfully. - + Show + Εμφάνιση + + + Delete + Διαγραφή + + + Screenshot + Στιγμιότυπο οθόνης - Take screenshots of computers and save them locally. + Do you really want to delete all selected screenshots? - ScreenshotManagementPanel + ServerAccessControlManager - All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + Requested authentication method not available - User: - Χρήστης: + Access allowed by rule "%1" + - Computer: - Υπολογιστής: + Access denied by rule "%1" + - Date: - Ημερομηνία: + No rule allowed access + - Time: - Ώρα: + Accessing user not member of an authorized user group + - Show - Προβολή + User has denied access + - Delete - Διαγραφή + User confirmed access + @@ -3695,7 +4181,7 @@ Please save your work and close all programs. Stopped - Τερματισμένη + Τερματίστηκε Stop service @@ -3706,108 +4192,166 @@ Please save your work and close all programs. Κατάσταση: - Network - Δίκτυο + Enable firewall exception + - Demo server port + Allow connections from localhost only - Enable firewall exception + VNC server + Διακομιστής VNC + + + Plugin: + Προσθήκη: + + + Restart %1 Service + Επανεκκίνηση της υπηρεσίας %1 + + + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - Allow connections from localhost only + Running + Εκτελείται + + + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. - Internal VNC server port + Show notification on remote connection - VNC server + Show notification when an unauthorized access is blocked - Plugin: + Maximum session count - Restart %1 Service + Network port numbers - All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + Veyon server + Διακομιστής Veyon + + + Internal VNC server - Running - Εκτελείται + Feature manager + Διαχείριση δυνατοτήτων + + + Demo server + Διακομιστής επίδειξης - Feature manager port + Miscellaneous network settings - Primary service port + Session mode - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. + Local session mode (single server instance for primary local session) - Show notification on remote connection + Active session mode (single server instance for active local or remote session) - Multi session mode (for terminal and remote desktop servers) + Multi session mode (distinct server instance for each local and remote desktop session) - Show notification when an unauthorized access is blocked + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. - - - ServiceControl - Starting service %1 + Miscellaneous settings - Stopping service %1 + Disable clipboard synchronization - Registering service %1 + Session metadata - Unregistering service %1 + Content - Service control + None + + + + Value of an environment variable + + + + Value of a registry key + + + + Environment variable name: + + + + Registry key name: + + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) - ServiceControlPlugin + ServiceControl - Service is running - Η υπηρεσία εκτελείται + Service control + - Service is not running - Η υπηρεσία δεν εκτελείται + Starting %1 + - Configure and control Veyon service + Stopping %1 + + + + Restarting %1 + + + + Registering %1 + + Unregistering %1 + + + + + ServiceControlCommands Register Veyon Service @@ -3832,23 +4376,35 @@ Typically this is required to support terminal servers. Query status of Veyon Service + + Service is running + Η υπηρεσία εκτελείται + + + Service is not running + Η υπηρεσία δεν εκτελείται + + + Configure and control Veyon service + + Commands for configuring and controlling Veyon Service - ShellCommandLinePlugin + ShellCommands Run command file File "%1" does not exist! - + Το αρχείο "%1" δεν υπάρχει! - Interactive shell and script execution for Veyon Control + Interactive shell and script execution for Veyon CLI @@ -3856,6 +4412,92 @@ Typically this is required to support terminal servers. + + SlideshowPanel + + Previous + Προηγούμενο + + + Start/pause + Έναρξη/παύση + + + Next + Επόμενο + + + Duration: + Διάρκεια: + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + Προσθήκη επιλεγμένων υπολογιστών + + + Remove selected computers + Αφαίρεση επιλεγμένων υπολογιστών + + + Update computers in realtime + Ενημέρωση υπολογιστών σε πραγματικό χρόνο + + + Spotlight + + + + Please select at least one computer to add. + + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + + + StartAppDialog + + Start application + Έναρξη εφαρμογής + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + π.χ. "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + Απομνημόνευση και προσθήκη στο μενού εφαρμογών + + + Application name + Όνομα εφαρμογής + + + Name: + Όνομα: + + + e.g. VLC + π.χ. VLC + + SystemTrayIcon @@ -3889,10 +4531,10 @@ Typically this is required to support terminal servers. TextMessageDialog Send text message - Αποστολή μηνύματος + Αποστολή κειμένου μηνύματος - Use the field below to type your message which will be sent to all selected users. + Please enter your message which send to all selected users. @@ -3900,7 +4542,7 @@ Typically this is required to support terminal servers. TextMessageFeaturePlugin Text message - Μήνυμα + Κείμενο μηνύματος Use this function to send a text message to all users e.g. to assign them new tasks. @@ -3941,38 +4583,62 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer + + Maximum CPU usage + Μέγιστη χρήση CPU + - UserConfig + UserLoginDialog - No write access - + User login + Σύνδεση χρήστη - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - + Please enter a username and password for automatic login on all computers. + Παρακαλώ εισάγετε ένα όνομα χρήστη και κωδικό πρόσβασης για αυτόματη σύνδεση σε όλους τους υπολογιστές. + + + Username + Όνομα χρήστη + + + Password + Κωδικός πρόσβασης - UserSessionControl + UserSessionControlPlugin - User session control - + Log in + Σύνδεση + + + Click this button to log in a specific user on all computers. + Κάντε κλικ σε αυτό το κουμπί για να συνδεθείτε σε έναν συγκεκριμένο χρήστη σε όλους τους υπολογιστές. Log off - + Αποσύνδεση Click this button to log off users from all computers. - + Κάντε κλικ σε αυτό το κουμπί για να αποσυνδέσετε χρήστες από όλους τους υπολογιστές. Confirm user logoff - + Επιβεβαίωση αποσύνδεσης χρήστη Do you really want to log off the selected users? + Θέλετε πραγματικά να αποσυνδέσετε τους επιλεγμένους χρήστες; + + + User session control + + + + Do you really want to log off <b>ALL</b> users? @@ -3980,15 +4646,15 @@ Typically this is required to support terminal servers. VeyonCore [OK] - + [OK] [FAIL] - + [ΑΠΟΤΥΧΙΑ] Invalid command! - + Μη έγκυρη εντολή! Available commands: @@ -4004,7 +4670,7 @@ Typically this is required to support terminal servers. Unknown result! - + Άγνωστο αποτέλεσμα! Available modules: @@ -4020,45 +4686,53 @@ Typically this is required to support terminal servers. INFO - + ΠΛΗΡ. ERROR - - - - licensed for - + ΣΦΑΛΜΑ USAGE - + ΧΡΗΣΗ DESCRIPTION - + ΠΕΡΙΓΡΑΦΗ EXAMPLES - + ΠΑΡΑΔΕΙΓΜΑΤΑ WARNING + ΠΡΟΕΙΔΟΠΟΙΗΣΗ + + + Authentication test + + Screen %1 + Οθόνη %1 + - VeyonServiceControl + VeyonMaster - Veyon Service + No write access + Χωρίς πρόσβαση εγγραφής + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - VncView + VeyonServiceControl - Establishing connection to %1 ... - + Veyon Service + Υπηρεσία Veyon @@ -4084,28 +4758,52 @@ Typically this is required to support terminal servers. Screen lock - + Κλείδωμα οθόνης Hide taskbar - + Απόκρυψη γραμμής εργασιών Hide start menu - + Απόκρυψη μενού έναρξης Hide desktop - + Απόκρυψη επιφάνειας εργασίας User authentication - + Έλεγχος ταυτότητας χρήστη Use alternative user authentication mechanism + + User login + Σύνδεση χρήστη + + + Input start delay + + + + Simulated key presses interval + + + + Confirm legal notice (message displayed before user logs in) + + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4114,7 +4812,7 @@ Typically this is required to support terminal servers. - Plugin implementing specific functions for the Windows platform + Internal display @@ -4122,31 +4820,35 @@ Typically this is required to support terminal servers. WindowsServiceControl The service "%1" is already installed. - + Η υπηρεσία "%1" είναι ήδη εγκατεστημένη. - The service "%1" could not be installed. - + The service "%1" has been installed successfully. + Η υπηρεσία "%1" έχει εγκατασταθεί με επιτυχία. - The service "%1" has been installed successfully. - + The service "%1" has been uninstalled successfully. + Η υπηρεσία "%1" έχει απεγκατασταθεί με επιτυχία. - The service "%1" could not be uninstalled. - + Service "%1" could not be found. + Η υπηρεσία "%1" δεν ήταν δυνατό να βρεθεί. - The service "%1" has been uninstalled successfully. - + The service "%1" could not be installed (error %2). + Η υπηρεσία "%1" δεν ήταν δυνατό να εγκατασταθεί (σφάλμα %2). - The start type of service "%1" could not be changed. + Could not change the failure actions config for service "%1" (error %2). - Service "%1" could not be found. - + The service "%1" could not be uninstalled (error %2). + Η υπηρεσία "%1" δεν ήταν δυνατό να απεγκατασταθεί (σφάλμα %2). + + + The start type of service "%1" could not be changed (error %2). + Ο τύπος έναρξης της υπηρεσίας "%1" δεν μπόρεσε να αλλάξει (σφάλμα %2). diff --git a/translations/es_ES.ts b/translations/veyon_es_ES.ts similarity index 74% rename from translations/es_ES.ts rename to translations/veyon_es_ES.ts index 4050779dd..dd229d497 100644 --- a/translations/es_ES.ts +++ b/translations/veyon_es_ES.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -82,10 +82,6 @@ Si deseas mejorar la traducción actual, por favor, ¡contacta con un desarrolla All groups Todos los grupos - - ... - ... - Access control rules Reglas de control de acceso @@ -142,19 +138,18 @@ Si deseas mejorar la traducción actual, por favor, ¡contacta con un desarrolla User groups backend: Backend para grupos de usuarios: - - Missing user groups backend - Falta backend para grupos de usuarios - - - No default user groups plugin was found. Please check your installation! - No se encontró el plugin por defecto para grupos de usuarios. ¡Por favor, compruebe la instalación! - Restrict access to members of specific user groups Restringir el acceso a miembros de grupos de usuarios específicos + + AccessControlProvider + + Provider for access control features + + + AccessControlRuleEditDialog @@ -181,30 +176,10 @@ Si deseas mejorar la traducción actual, por favor, ¡contacta con un desarrolla Rule description: Descripción de regla: - - Invert all conditions ("is/has" interpreted as "is/has not") - Invertir todas las condiciones ("está/tiene" interpretado como "no está/no tiene") - Conditions Condiciones - - is member of group - es miembro del grupo - - - Accessing computer is localhost - El computador de acceso es localhost - - - Accessing user is logged on user - El usuario de acceso ha iniciado sesión - - - Accessing user is already connected - El usuario de acceso ya está conectado - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. Si se activa más de una condición, cada condición se tiene que cumplir para hacer que la regla se aplique (AND lógico). Si sólo una de las condiciones múltiples se tiene que cumplir (OR lógico) cree varias reglas de control de acceso. @@ -238,33 +213,125 @@ Si deseas mejorar la traducción actual, por favor, ¡contacta con un desarrolla Acceso al equipo - Local (logged on) user - Usuario local (conectado) + Always process rule and ignore conditions + Siempre procesar reglas e ignorar condiciones - Local computer - Equipo local + Accessing computer and local computer + Computadora de acceso y computadora local - Always process rule and ignore conditions - Siempre procesar reglas e ignorar condiciones + User being accessed + Usuario al que se accede - No user logged on - Ningún usuario ha iniciado sesión + is logged in locally + está conectado localmente + + + is logged in remotely + está conectado de forma remota + + + No user is logged in locally + Ningún usuario ha iniciado sesión localmente + + + One or multiple users are logged in locally + Uno o varios usuarios han iniciado sesión localmente - Accessing user has one or more groups in common with local (logged on) user - El acceso al usuario tiene uno o más grupos en común con el usuario local (conectado) + No user is logged in remotely + Ningún usuario está conectado remotamente - Accessing computer and local computer are at the same location - El acceso al equipo y el equipo local están en la misma ubicación + One or multiple users are logged in remotely + Uno o varios usuarios inician sesión de forma remota is located at se encuentra en + + is not located at + no se encuentra en + + + are located at the same location + se encuentran en la misma ubicación + + + are not located the same location + no se encuentran en la misma ubicación + + + is member of group + es miembro del grupo + + + is not member of group + no es miembro del grupo + + + is authenticated via + está autenticado a través de + + + is not authenticated via + no está autenticado a través de + + + has one or more groups in common with user being accessed + tiene uno o más grupos en común con el usuario al que se accede + + + has no groups in common with user being accessed + no tiene grupos en común con el usuario al que se accede + + + equals user being accessed + igual al usuario al que se accede + + + is different from user being accessed + es diferente al usuario al que se accede + + + is already connected + ya esta conectada + + + is not connected + no esta conectada + + + is local computer + es una computadora local + + + is not local computer + no es una computadora local + + + Computer being accessed + Se accede a la computadora + + + Session being accessed is a user session + La sesión a la que se accede es una sesión de usuario + + + Session being accessed is a login screen + La sesión a la que se accede es una pantalla de inicio de sesión + + + Local computer is already being accessed + + + + Local computer is not yet being accessed + + AccessControlRulesTestDialog @@ -308,42 +375,44 @@ Si deseas mejorar la traducción actual, por favor, ¡contacta con un desarrolla The access in the given scenario needs permission of the logged on user. El acceso en el escenario dado necesita permiso del usuario conectado. - - ERROR: Unknown action - ERROR: Acción desconocida - Test result Resultado de la prueba - - - AndroidPlatformConfigurationPage - Android - + Authentication method + Métodos de autenticación - General - General + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + Introducción - - - AuthKeysConfigurationPage - Authentication keys - Claves de autenticación + Please perform the following steps to set up key file authentication: + Realice los siguientes pasos para configurar la autenticación de archivos de claves: - Introduction - Introducción + 1) Create a key pair on the master computer. + 1) Crea un par de llaves en la computadora maestra. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Establezca un grupo con acceso cuyos miembros deberían tener acceso a otras computadoras. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Exporte la clave pública e impórtela en todas las computadoras cliente con el mismo nombre. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Consulte el <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Manual de Administrador de Veyon</a> para obtener más información. Key file directories @@ -357,14 +426,20 @@ Si deseas mejorar la traducción actual, por favor, ¡contacta con un desarrolla Private key file base directory Directorio base para archivo de clave privada - - ... - ... - Available authentication keys Claves de autenticación disponibles + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Un par de claves de autenticación consta de dos claves criptográficas acopladas, una privada y otra pública. +Una clave privada permite a los usuarios de la computadora maestra acceder a las computadoras cliente. +Es importante que solo los usuarios autorizados tengan acceso de lectura al archivo de clave privada. +La clave pública se usa en las computadoras cliente para autenticar la solicitud de conexión entrante. + Create key pair Crear par de claves @@ -405,10 +480,6 @@ Si deseas mejorar la traducción actual, por favor, ¡contacta con un desarrolla Please select a key to delete! Por favor, ¡seleccione clave a eliminar! - - Please enter the name of the user group or role for which to import the authentication key: - Introduzca el nombre del grupo de usuarios o rol para el cual importar la clave de autenticación: - Please select a key to export! Por favor, ¡seleccione una clave a exportar! @@ -422,34 +493,10 @@ Si deseas mejorar la traducción actual, por favor, ¡contacta con un desarrolla ¡Seleccione una clave para configurar el grupo que tenga acceso! - Please perform the following steps to set up key file authentication: - Realice los siguientes pasos para configurar la autenticación de archivos de claves: - - - 1) Create a key pair on the master computer. - 1) Crea un par de llaves en la computadora maestra. - - - 2) Set an access group whose members should be allowed to access other computers. - 2) Establezca un grupo con acceso cuyos miembros deberían tener acceso a otras computadoras. - - - 3) Export the public key and import it on all client computers with the same name. - 3) Exporte la clave pública e impórtela en todas las computadoras cliente con el mismo nombre. - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - Consulte el <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Manual de Administrador de Veyon</a> para obtener más información. - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - Un par de claves de autenticación consta de dos claves criptográficas acopladas, una privada y otra pública. -Una clave privada permite a los usuarios de la computadora maestra acceder a las computadoras cliente. -Es importante que solo los usuarios autorizados tengan acceso de lectura al archivo de clave privada. -La clave pública se usa en las computadoras cliente para autenticar la solicitud de conexión entrante. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + @@ -649,10 +696,6 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. Este comando enumera todas las claves de autenticación disponibles en el directorio de claves configurado. Si se especifica la opción "%1", se mostrará una tabla con los detalles de las claves. Es posible que falten algunos detalles si no se puede acceder a una clave, p. ej. debido a la falta de permisos de lectura. - - Please specify the command to display help for! - Por favor, ¡especifique el comando sobre el cual mostrar ayuda! - TYPE TIPO @@ -661,10 +704,6 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu PAIR ID ID PAR - - Command line support for managing authentication keys - Soporte de línea de comando para administrar claves de autenticación - Commands for managing authentication keys Comandos para administrar claves de autenticación @@ -681,6 +720,30 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. Este comando extrae la parte de la clave pública de la clave privada <KEY> y la guarda como la clave pública correspondiente. Al configurar otra computadora maestra, por lo tanto, es suficiente transferir la clave privada solamente. La clave pública puede entonces ser extraída. + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + Los archivos de clave de autenticación no están configurados correctamente en esta computadora. Cree nuevos archivos clave o cambie a un método de autenticación diferente utilizando el Configurador Veyon. + + + Key file authentication + Autenticación mediante archivo de clave + + + Key file + Archivo de clave + + + Please specify the key name (e.g. "teacher/public") as the first argument. + Especifique el nombre de la clave (p. ej., "teacher/public") como primer argumento. + + + Please specify the command to display help for. + Por favor, especifique el comando para mostrar ayuda de el. + + + The specified command does not exist or no help is available for it. + El comando especificado no existe o no hay ayuda sobre el. + AuthKeysTableModel @@ -702,89 +765,232 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - Equipos + General + General - Name - Nombre + Username to bind DN mapping: + Nombre de usuario para vincular la asignación de DN: - Host address/IP - Dirección de equipo/IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + p.ej. %username%@DOMAIN o cn=%username%,ou=users,dc=example,dc=org + + + AuthLdapDialog - MAC address - Dirección MAC + Veyon Logon + Inicio de sesión de Veyon - Add new computer - Añadir nuevo equipo + Please enter your domain/LDAP username and password in order to access computers. + Introduzca su nombre de usuario y contraseña de dominio/LDAP para acceder a las computadoras. - Remove selected computer - Eliminar equipo seleccionado + Username + Nombre de usuario - New computer - Nuevo equipo + Password + Contraseña - Builtin directory - Directorio incorporado + Authentication error + Error de autenticación - Locations & computers - Ubicaciones y equipos + Logon failed with given username and password. Please try again! + Error de inicio de sesión con el nombre de usuario y contraseña dados. Por favor, ¡inténtelo de nuevo! + + + AuthLogonDialog - Locations - Ubicaciones + Veyon Logon + Inicio de sesión de Veyon - Add new location - Añadir nueva ubicación + Please enter your username and password in order to access computers. + Introduzca su nombre de usuario y contraseña para acceder a los equipos. - Remove selected location - Eliminar ubicación seleccionada + Username + Nombre de usuario - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - La importación de archivos CSV es posible a través de la interfaz de línea de comandos. Para más información, consulte la <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">documentación en línea</a>. + Password + Contraseña - New location - Nueva ubicación + Authentication error + Error de autenticación + + + Logon failed with given username and password. Please try again! + Error de inicio de sesión con el nombre de usuario y contraseña dados. Por favor, ¡inténtelo de nuevo! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command - Mostrar ayuda para un comando específico + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + El nombre de usuario o la contraseña proporcionados son incorrectos. Ingrese credenciales válidas o cambie a un método de autenticación diferente utilizando Veyon Configurator. - Import objects from given file - Importar objetos desde un archivo + Logon authentication + Autenticación de inicio de sesión - Export objects to given file - Exportar objetos a un archivo + Logon + Inicio de sesión + + + AuthSimpleDialog - Invalid type specified. Valid values are "%1" or "%2". - Tipo inválido especificado. Los valores válidos son "%1" o "%2". + Veyon Logon + Inicio de sesión de Veyon - Type - Tipo + Please enter the Veyon password: + Por favor, introduzca la contraseña de Veyon: - Name - Nombre + Authentication error + Error de autenticación + + + Logon failed with given password. Please try again! + El inicio de sesión falló con la contraseña dada. ¡Inténtalo de nuevo! + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + La contraseña proporcionada es incorrecta. Ingrese la contraseña correcta o cambie a un método de autenticación diferente utilizando Veyon Configurator. + + + Simple password authentication + Autenticación de contraseña simple + + + Simple password + Contraseña simple + + + + AuthenticationPage + + Authentication is set up properly on this computer. + La autenticación está configurada correctamente en esta computadora. + + + + AuthenticationPageTab + + Enabled + Habilitado + + + Test + Comprobar + + + + BuiltinDirectoryConfiguration + + Builtin directory + Directorio incorporado + + + + BuiltinDirectoryConfigurationPage + + Computers + Equipos + + + Name + Nombre + + + Host address/IP + Dirección de equipo/IP + + + MAC address + Dirección MAC + + + Add new computer + Añadir nuevo equipo + + + Remove selected computer + Eliminar equipo seleccionado + + + New computer + Nuevo equipo + + + Builtin directory + Directorio incorporado + + + Locations + Ubicaciones + + + Add new location + Añadir nueva ubicación + + + Remove selected location + Eliminar ubicación seleccionada + + + New location + Nueva ubicación + + + Directory name + Nombre del directorio + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + Es posible importar archivos CSV a través de la interfaz de línea de comandos. Para obtener más información, consulte la <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">documentación en línea</a>. + + + + BuiltinDirectoryPlugin + + Show help for specific command + Mostrar ayuda para un comando específico + + + Import objects from given file + Importar objetos desde un archivo + + + Export objects to given file + Exportar objetos a un archivo + + + Invalid type specified. Valid values are "%1" or "%2". + Tipo inválido especificado. Los valores válidos son "%1" o "%2". + + + Type + Tipo + + + Name + Nombre Host address @@ -1002,6 +1208,14 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu MAC ADDRESS DIRECCIÓN MAC + + The specified command does not exist or no help is available for it. + El comando especificado no existe o no hay ayuda sobre el. + + + Location "%1" not found. + + BuiltinUltraVncServer @@ -1019,10 +1233,6 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu ComputerControlListModel - - Host/IP address: %1 - Equipo/Dirección IP: %1 - Active features: %1 Características activas: %1 @@ -1039,10 +1249,6 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Computer offline or switched off El equipo está desconectado o apagado - - Service unreachable or not running - Servicio inaccesible o no ejecutándose - Authentication failed or access denied Error de autenticación o acceso denegado @@ -1063,6 +1269,38 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Location: %1 Ubicación: %1 + + [no user] + [ningún usuario] + + + Veyon Server unreachable or not running + Veyon Server es inaccesible o no se está ejecutando + + + Name: %1 + Nombre: %1 + + + Hostname: %1 + + + + unknown + desconocido + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + ComputerControlServer @@ -1094,6 +1332,17 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. El usuario "%1" en "%2" intentó acceder a este equipo pero se ha bloqueado debido a la configuración de control de acceso. + + Active connections: + Conexiones activas: + + + + ComputerGroupSelector + + Group %1 + Grupo %1 + ComputerManager @@ -1121,13 +1370,48 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. No se pudo determinar la ubicación de este equipo. Esto indica un problema con la configuración del sistema. En su lugar, se mostrarán todas las ubicaciones en el panel de selección del equipo. + + Logged in since + Conectado desde + + + %1 days + %1 días + + + 1 day + 1 día + - ComputerSelectPanel + ComputerMonitoring + + Computers + Equipos + + + Search users and computers + Buscar usuarios y equipos + + + Select all + Seleccionar todo + - Computer management - Gestión de equipo + Unselect all + Deseleccionar todo + + Add to group + Añadir al grupo + + + Remove from group + Eliminar del grupo + + + + ComputerSelectPanel Computer search Búsqueda de equipos @@ -1156,81 +1440,85 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Could not write the computer and users list to %1! Please check the file access permissions. No se pudo escribir la lista de equipos y usuarios en %1. Por favor, compruebe los permisos de acceso al archivo. + + Search computers + Buscar equipos + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. - Especifique un archivo de configuración existente para importar. + Clear system-wide Veyon configuration + Borrar la configuración de Veyon del sistema - Please specify a valid filename for the configuration export. - Especifique un nombre de archivo válido para la exportación de configuración. + List all configuration keys and values + Listar todas las claves y valores de la configuración - Please specify a valid key. - Especifique una clave válida. + Import configuration from given file + Importar configuración de archivo - Specified key does not exist in current configuration! - ¡La clave especificada no existe en la configuración actual! + Export configuration to given file + Exportar la configuración a archivo - Please specify a valid value. - Especifique un valor válido. + Read and output configuration value for given key + Leer y mostrar valor de configuración para una clave - Configure Veyon at command line - Configurar Veyon en la línea de comandos + Write given value to given configuration key + Escribir un valor a una clave de configuración - Output file is not writable! - ¡El archivo de salida no puede escribirse! + Unset (remove) given configuration key + Desactivar (quitar) la clave de configuración - Output directory is not writable! - ¡El directorio de salida no puede escribirse! + Upgrade and save configuration of program and plugins + Actualizar y guardar la configuración del programa y los complementos + + + Please specify an existing configuration file to import. + Especifique un archivo de configuración existente para importar. Configuration file is not readable! ¡El archivo de configuración no puede leerse! - Clear system-wide Veyon configuration - Borrar la configuración de Veyon del sistema + Please specify a valid filename for the configuration export. + Especifique un nombre de archivo válido para la exportación de configuración. - List all configuration keys and values - Listar todas las claves y valores de la configuración + Output file is not writable! + ¡El archivo de salida no puede escribirse! - Import configuration from given file - Importar configuración de archivo + Output directory is not writable! + ¡El directorio de salida no puede escribirse! - Export configuration to given file - Exportar la configuración a archivo + Please specify a valid key. + Especifique una clave válida. - Read and output configuration value for given key - Leer y mostrar valor de configuración para una clave + Specified key does not exist in current configuration! + ¡La clave especificada no existe en la configuración actual! - Write given value to given configuration key - Escribir un valor a una clave de configuración + Please specify a valid value. + Especifique un valor válido. - Unset (remove) given configuration key - Desactivar (quitar) la clave de configuración + Configure Veyon at command line + Configurar Veyon en la línea de comandos Commands for managing the configuration of Veyon Comandos para gestionar la configuración de Veyon - - Upgrade and save configuration of program and plugins - Actualizar y guardar la configuración del programa y los complementos - ConfigurationManager @@ -1254,6 +1542,10 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Could not apply platform-specific configuration settings. No se pudieron aplicar los ajustes de configuración específicos de la plataforma. + + Could not configure the firewall configuration for the %1 Service. + No se pudo configurar la configuración del firewall para el servicio %1. + DemoClient @@ -1284,10 +1576,6 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Memory limit Límite de memoria - - Use multithreading (experimental) - Utilizar multithreading (experimental) - MB MB @@ -1304,13 +1592,17 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Slow down thumbnail updates while demo is running Ralentizar las actualizaciones de miniaturas mientras se ejecuta la demostración + + Bandwidth limit + Límite de ancho de banda + + + MB/s + MB/s + DemoFeaturePlugin - - Fullscreen demo - Demo a pantalla completa - Stop demo Detener demo @@ -1324,16 +1616,60 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Dar una demostración por difusión de pantalla - Demo server - Servidor demo + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + En este modo, la pantalla se mostrará en una ventana de todos los ordenadores. Los usuarios pueden cambiar a otras ventanas según sea necesario. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - En este modo, la pantalla se muestra en modo de pantalla completa en todos los equipos mientras los dispositivos de entrada de los usuarios están bloqueados. + Demo + Demo - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - En este modo, la pantalla se mostrará en una ventana de todos los ordenadores. Los usuarios pueden cambiar a otras ventanas según sea necesario. + Share your screen or allow a user to share his screen with other users. + Compartir tu pantalla o permitir que un usuario comparta su pantalla con otros usuarios. + + + Full screen demo + Demo a pantalla completa + + + Share your own screen in fullscreen mode + Compartir tu propia pantalla en modo de pantalla completa + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + En este modo, su pantalla se muestra en modo de pantalla completa en todas las computadoras mientras los dispositivos de entrada de los usuarios están bloqueados. + + + Share your own screen in a window + Compartir tu propia pantalla en una ventana + + + Share selected user's screen in fullscreen mode + Compartir la pantalla del usuario seleccionado en modo de pantalla completa + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + En este modo, la pantalla del usuario seleccionado se muestra en modo de pantalla completa en todas las computadoras mientras los dispositivos de entrada de los usuarios están bloqueados. + + + Share selected user's screen in a window + Compartir la pantalla del usuario seleccionado en una ventana + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + En este modo, la pantalla del usuario seleccionado se muestra en una ventana en todas las computadoras. Los usuarios pueden cambiar a otras ventanas según sea necesario. + + + Please select a user screen to share. + Seleccione una pantalla de usuario para compartir. + + + Please select only one user screen to share. + Seleccione solo una pantalla de usuario para compartir. + + + All screens + Todas las pantallas @@ -1361,14 +1697,6 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu DesktopServicesConfigurationPage - - Programs & websites - Programas y sitios web - - - Predefined programs - Programas predefinidos - Name Nombre @@ -1377,14 +1705,6 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Path Ruta - - Add new program - Añadir nuevo programa - - - Remove selected program - Eliminar el programa seleccionado - Predefined websites Sitios web predefinidos @@ -1397,21 +1717,37 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu URL URL - - New program - Nuevo programa - New website Nuevo sitio web + + Applications & websites + Aplicaciones y sitios web + + + Predefined applications + Aplicaciones predefinidas + + + Add new application + Añadir nueva aplicación + + + Remove selected application + Eliminar la aplicación seleccionada + + + Add new website + Añadir nuevo sitio web + + + New application + Nueva aplicación + DesktopServicesFeaturePlugin - - Run program - Ejecutar programa - Open website Abrir sitio web @@ -1421,28 +1757,32 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Haga clic en este botón para abrir un sitio web en todos los equipos. - Start programs and services in user desktop - Iniciar programas y servicios en el escritorio del usuario + Open website "%1" + Abrir sitio web "%1" + + + Custom website + Sitio web personalizado - Click this button to run a program on all computers. - Haga clic en este botón para ejecutar un programa en todos los equipos. + Start application + Iniciar aplicación - Run program "%1" - Ejecutar el programa "%1" + Click this button to start an application on all computers. + Haga clic en este botón para iniciar una aplicación en todas las computadoras. - Custom program - Programa personalizado + Start application "%1" + Iniciar aplicación "%1" - Open website "%1" - Abrir sitio web "%1" + Custom application + Aplicación personalizada - Custom website - Sitio web personalizado + Start apps and open websites in user sessions + Iniciar aplicaciones y abrir sitios web en sesiones de usuario @@ -1475,17 +1815,21 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Play tutorial video Reproducir video tutorial - - Custom program - Programa personalizado - Handout - + Folleto Texts to read - + Textos para leer + + + generic-student-user + usuario-estudiante-genérico + + + Custom application + Aplicación personalizada @@ -1511,10 +1855,165 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu - FeatureControl + FeatureCommands + + List names of all available features + Lista de nombres de todas las funciones disponibles + + + Show table with details of all available features + Mostrar tabla con detalles de todas las funciones disponibles + + + Start a feature on a remote host + Iniciar una función en un host remoto + + + Stop a feature on a remote host + Detener una función en un host remoto + + + Please specify the command to display help for. + Por favor, especifique el comando para mostrar ayuda de el. + + + Displays a list with the names of all available features. + Muestra una lista con los nombres de todas las funciones disponibles. + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + Muestra una tabla con información detallada sobre todas las funciones disponibles. Esta información incluye una descripción, el UID, el nombre del complemento que proporciona la función respectiva y algunos otros detalles relacionados con la implementación. + + + HOST ADDRESS + DIRECCIÓN DE EQUIPO + + + FEATURE + CARACTERÍSTICA + + + ARGUMENTS + ARGUMENTOS + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + Inicia la función especificada en el host especificado conectándose al Veyon Server que se ejecuta de forma remota. La función se puede especificar por nombre o UID. Utilice el comando ``show`` para ver todas las funciones disponibles. Dependiendo de la función, se deben especificar argumentos adicionales (como el mensaje de texto que se mostrará) codificados como una sola cadena JSON. Consulte la documentación para desarrolladores para obtener más información. + + + Lock the screen + Bloquear la pantalla + + + Display a text message + Mostrar un mensaje de texto + + + Test message + Mensaje de prueba + + + Start an application + Empezar una aplicación + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + Detiene la función especificada en el host especificado al conectarse al servidor Veyon que se ejecuta de forma remota. La función se puede especificar por nombre o UID. Utilice el comando ``show`` para ver todas las funciones disponibles. + + + Unlock the screen + Desbloquea la pantalla + + + The specified command does not exist or no help is available for it. + El comando especificado no existe o no hay ayuda sobre el. + + + Name + Nombre + + + Description + Descripción + + + Master + Maestro + + + Service + Servicio + + + Worker + Trabajador + + + UID + UID + + + Plugin + Complemento + + + Invalid feature name or UID specified + Se ha especificado un nombre de función o UID no válido + + + Error parsing the JSON-encoded arguments: %1 + Error al analizar los argumentos codificados en JSON: %1 + + + Failed to initialize credentials + Fallo al inicializar las credenciales + + + Could not establish a connection to host %1 + No se pudo establecer una conexión con el host %1 + + + Failed to send feature control message to host %1 + Error al enviar el mensaje de control de funciones al host %1 + + + Feature-related CLI operations + Operaciones de CLI relacionadas con funciones + + + Commands for controlling features + Comandos para controlar funciones + + + + FileTransferConfigurationPage + + File transfer + Transferir archivo + + + Directories + Directorios + + + Destination directory + Directorio de destino + + + Default source directory + Directorio de origen predeterminado + + + Options + Opciones + + + Remember last source directory + Recordar el último directorio de origen + - Feature control - Control de funciones + Create destination directory if it does not exist + Crear directorio de destino si no existe @@ -1559,6 +2058,13 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Sobrescribir archivos existentes + + FileTransferFileDialog + + Select one or more files to transfer + Seleccione uno o más archivos para transferir + + FileTransferPlugin @@ -1616,10 +2122,6 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Log file directory Directorio de registro - - ... - ... - Log level Nivel de registro @@ -1660,18 +2162,6 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Log to standard error output Registro a salida de errores estándar - - Network object directory - Directorio de objetos de red - - - Backend: - Backend: - - - Update interval: - Intervalo de actualización: - %1 service servicio %1 @@ -1708,103 +2198,80 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu x x - - seconds - segundos - Write to logging system of operating system Escribir en el sistema de registro del sistema operativo - Authentication - Autenticación - - - Method: - Método: + TLS configuration + Configuración de TLS - Logon authentication - Autenticación de inicio de sesión - - - Key file authentication - Autenticación mediante archivo de clave - - - Test - Comprobar - - - Authentication is set up properly on this computer. - La autenticación está configurada correctamente en esta computadora. + Use certificate authority for TLS connections + Utilizar la autoridad de certificación para las conexiones TLS - Authentication keys are not set up properly on this computer. - Las claves de autenticación no están configuradas correctamente en esta computadora. + CA certificate file + Archivo de certificado de CA - Authentication test - Prueba de autenticacion + ... + ... - - - InternetAccessControlConfigurationPage - Internet access control - Control de acceso a Internet + Host certificate file + Archivo de certificado de equipo - Backend: - Backend: + Host private key file + Archivo de clave privada de equipo - General settings - Configuración general + Style: + Estilo: - Backend settings - Configuración de backend + Native + Nativo - - - InternetAccessControlPlugin - Block access to the internet - Bloquear el acceso a internet + Color scheme: + - Allow access to the internet - Permitir el acceso a internet + Light + - Show help about command - Mostrar ayuda sobre el comando + Dark + - Block internet - Bloquear internet + User groups + Grupos de usuarios - Click this button to block access to the internet. - Haga clic en este botón para bloquear el acceso a internet. + Backend: + Backend: - Unblock internet - Desbloquear internet + Include user groups from domain + - Click this button to allow access to the internet. - Haga clic en este botón para permitir el acceso a internet. + Missing user groups backend + Falta backend para grupos de usuarios - Control access to the internet - Control de acceso a internet + No user groups plugin was found. Please check your installation! + + + + HeadlessVncServer - Commands for controlling access to the internet - Comandos para controlar el acceso a internet + Headless VNC server + Servidor VNC headless @@ -1822,344 +2289,527 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu - LdapConfigurationPage + LdapConfiguration - Basic settings - Configuración básica + LDAP connection failed + Conexión LDAP fallida - General - General + Could not connect to the LDAP server. Please check the server parameters. + +%1 + No se pudo conectar al servidor LDAP. Por favor, revise los parámetros del servidor. + +%1 - LDAP server and port - Servidor y puerto LDAP + LDAP bind failed + Enlace LDAP fallido - Bind DN - Enlace DN + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + No se pudo vincular al servidor LDAP. Verifique los parámetros del servidor y las credenciales de enlace. + +%1 - Bind password - Contraseña de enlace + LDAP bind successful + Enlace LDAP exitoso - Anonymous bind - Enlace anónimo + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Se conectó correctamente al servidor LDAP y se realizó un enlace LDAP. La configuración básica de LDAP está configurada correctamente. - Use bind credentials - Utilizar credenciales de enlace + LDAP base DN test failed + Comprobación fallida de DN base de LDAP - Base DN - DN base + Could not query the configured base DN. Please check the base DN parameter. + +%1 + No se pudo consultar el DN base configurado. Verifique el parámetro base DN. + +%1 - Fixed base DN - DN base fijo + LDAP base DN test successful + Comprobación correcta de DN base de LDAP - e.g. dc=example,dc=org - v.g. dc=example,dc=org + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + El DN base de LDAP se ha consultado con éxito. Se encontraron las siguientes entradas: + +%1 - Discover base DN by naming context - Descubrir el DN base mediante el contexto de nombres + LDAP naming context test failed + Comprobación fallida de contexto de nombres LDAP - e.g. namingContexts or defaultNamingContext - v.g. namingContexts o defaultNamingContext + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + No se pudo consultar el DN base a través de los contextos de nombres. Verifique el parámetro de atributo de contexto de nombres. + +%1 - Environment settings - Configuración del entorno + LDAP naming context test successful + Comprobación correcta de contexto de nombres LDAP - Object trees - Árboles de objetos + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + Consulta correcta al contexto de nombres LDAP. Se han encontrado los siguientes DN base: +%1 + + + user tree + árbol de usuarios + + + User tree + Árbol de usuarios + + + group tree + árbol de grupos + + + Group tree + Árbol de grupos + + + computer tree + árbol de equipos Computer tree Árbol de equipos - e.g. OU=Groups - v.g. OU=Groups + computer group tree + árbol de grupo de equipos - User tree - Árbol de usuarios + Computer group tree + Árbol de grupo de equipos - e.g. OU=Users - v.g. OU=Users + user objects + objetos de usuario - e.g. OU=Computers - v.g. OU=Computers + User login name attribute + Atributo de nombre de usuario - Group tree - Árbol de grupos + group members + miembros del grupo - Perform recursive search operations in object trees - Realizar operaciones de búsqueda recursiva en árboles de objetos + Group member attribute + Atributo de miembro del grupo - Object attributes - Atributos de objeto + Group not found + Grupo no encontrado - e.g. hwAddress - p. ej. hwAddress + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + No se pudo encontrar un grupo con el nombre "%1". Compruebe el nombre del grupo o el parámetro de árbol de grupo. - e.g. member or memberUid - v.g. member o memberUid + computer objects + Objetos de equipo - e.g. dNSHostName - v.g. dNSHostName + Computer display name attribute + Atributo de nombre mostrado de equipo + + + Invalid hostname + Nombre de host no válido + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Configuró los nombres de host de los equipos para que se almacenaran como nombres de dominio completos (FQDN) pero ingresó un nombre de host sin dominio. + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Configuró los nombres de host de los equipos para ser almacenados como nombres de host simples sin un nombre de dominio, pero ingresó un nombre de host con una parte de nombre de dominio. + + + Computer hostname attribute + Atributo de nombre de host del equipo + + + computer MAC addresses + direcciones MAC de equipo Computer MAC address attribute Atributo de dirección MAC del equipo - Group member attribute - Atributo de miembro del grupo + computer locations + ubicaciones de equipos - e.g. uid or sAMAccountName - v.g. uid o sAMAccountName + Computer location attribute + Atributo de ubicación del equipo - Advanced settings - Configuración avanzada + Location name attribute + Atributo de nombre de ubicación - Optional object filters - Filtros de objeto opcionales + users + usuarios - Filter for user groups - Filtro para grupos de usuarios + user groups + grupos de usuarios - Filter for users - Filtro para usuarios + computers + equipos + + + computer groups + grupos de equipos + + + computer containers + contenedores de computadoras + + + groups of user + grupos de usuarios + + + User not found + Usuario no encontrado + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + No se pudo encontrar un usuario con el nombre "%1". Por favor, compruebe el nombre de usuario o el parámetro del árbol de usuarios. + + + groups of computer + grupos de equipos + + + Computer not found + Equipo no encontrado + + + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + No se pudo encontrar un equipo con el nombre de host "%1". Por favor, compruebe el nombre de host o el parámetro del árbol de equipos. + + + Hostname lookup failed + Error al buscar el nombre de host + + + Could not lookup hostname for IP address %1. Please check your DNS server settings. + No se pudo buscar el nombre de host para la dirección IP %1. Por favor, compruebe la configuración de su servidor DNS. + + + location entries + entradas de ubicación + + + Computer groups filter + Filtro de grupos de computadoras + + + Computer locations identification + Identificación de ubicaciones de equipos Filter for computer groups - Filtro para grupos de ordenadores + Filtro para grupos de computadoras - Group member identification - Identificación del miembro del grupo + Invalid test value + Valor de prueba inválido - Distinguished name (Samba/AD) - Nombre distinguido (Samba/AD) + An empty or invalid value has been supplied for this test. + Se ha proporcionado un valor vacío o inválido para esta prueba. - List all groups of a user - Listar todos los grupos de un usuario + LDAP %1 test failed + Comprobación fallida de LDAP %1 - List all groups of a computer - Listar todos los grupos de un equipo + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + No se pudo consultar ninguna entrada en %1 configurado. Por favor, compruebe el parámetro "%2". + +%3 - Get computer object by IP address - Obtener objeto de equipo por dirección IP + LDAP %1 test successful + Comprobación correcta de LDAP %1 - LDAP connection failed - Conexión LDAP fallida + The %1 has been queried successfully and %2 entries were found. + El %1 se ha consultado correctamente y se han encontrado %2 entradas. - LDAP bind failed - Enlace LDAP fallido + LDAP test failed + La prueba LDAP falló - LDAP bind successful - Enlace LDAP exitoso + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + No se pudo consultar ningún %1. Verifique el parámetro(s) %2 e ingrese el nombre de un objeto existente. + +%3 - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - Se conectó correctamente al servidor LDAP y se realizó un enlace LDAP. La configuración básica de LDAP está configurada correctamente. + and + y - LDAP base DN test failed - Comprobación fallida de DN base de LDAP + LDAP test successful + La prueba LDAP fue exitosa - LDAP base DN test successful - Comprobación correcta de DN base de LDAP + %1 %2 have been queried successfully: + +%3 + %1 %2 ha sido consultado correctamente: + +%3 - LDAP naming context test failed - Comprobación fallida de contexto de nombres LDAP + LDAP filter test failed + Comprobación fallida de filtro LDAP - LDAP naming context test successful - Comprobación correcta de contexto de nombres LDAP + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 + No se pudo consultar ningún %1 con el filtro configurado. Compruebe el filtro LDAP para %1. + +%2 - The LDAP naming context has been queried successfully. The following base DN was found: -%1 - Consulta correcta al contexto de nombres LDAP. Se han encontrado los siguientes DN base: -%1 + LDAP filter test successful + Comprobación correcta de filtro LDAP - user tree - árbol de usuarios + %1 %2 have been queried successfully using the configured filter. + %1 %2 se han consultado correctamente con el filtro configurado. - group tree - árbol de grupos + LDAP directory + Directorio LDAP + + + LdapConfigurationPage - computer tree - árbol de equipos + Basic settings + Configuración básica - Enter username - Introduzca nombre de usuario + General + General - Please enter a user login name (wildcards allowed) which to query: - Por favor, introduzca un nombre de inicio de sesión (se permiten comodines) a consultar: + LDAP server and port + Servidor y puerto LDAP - user objects - objetos de usuario + Bind DN + Enlace DN - Enter group name - Introduzca nombre del grupo + Bind password + Contraseña de enlace - Please enter a group name whose members to query: - Por favor, introduzca un nombre de grupo para consultar sus miembros: + Anonymous bind + Enlace anónimo - group members - miembros del grupo + Use bind credentials + Utilizar credenciales de enlace - Group not found - Grupo no encontrado + Base DN + DN base - Could not find a group with the name "%1". Please check the group name or the group tree parameter. - No se pudo encontrar un grupo con el nombre "%1". Compruebe el nombre del grupo o el parámetro de árbol de grupo. + Fixed base DN + DN base fijo - Enter computer name - Introduzca nombre del equipo + e.g. dc=example,dc=org + v.g. dc=example,dc=org - computer objects - Objetos de equipo + Discover base DN by naming context + Descubrir el DN base mediante el contexto de nombres - Enter computer DN - Introduzca DN de equipo + e.g. namingContexts or defaultNamingContext + v.g. namingContexts o defaultNamingContext - Please enter the DN of a computer whose MAC address to query: - Por favor, introduzca el DN de un equipo para consultar su dirección MAC: + Environment settings + Configuración del entorno - computer MAC addresses - direcciones MAC de equipo + Object trees + Árboles de objetos - users - usuarios + Computer tree + Árbol de equipos - user groups - grupos de usuarios + e.g. OU=Groups + v.g. OU=Groups - computer groups - grupos de equipos + User tree + Árbol de usuarios - Please enter a user login name whose group memberships to query: - Por favor, introduzca nombre de inicio de sesión de usuario para consultar miembros del grupo: + e.g. OU=Users + v.g. OU=Users - groups of user - grupos de usuarios + e.g. OU=Computers + v.g. OU=Computers - User not found - Usuario no encontrado + Group tree + Árbol de grupos - groups of computer - grupos de equipos + Perform recursive search operations in object trees + Realizar operaciones de búsqueda recursiva en árboles de objetos - Computer not found - Equipo no encontrado + Object attributes + Atributos de objeto - Enter computer IP address - Introduzca la dirección IP del equipo + e.g. hwAddress + p. ej. hwAddress - Please enter a computer IP address which to resolve to an computer object: - Introduzca una dirección IP de equipo a resolver a un objeto de equipo: + e.g. member or memberUid + v.g. member o memberUid - computers - equipos + e.g. dNSHostName + v.g. dNSHostName - LDAP %1 test failed - Comprobación fallida de LDAP %1 + Computer MAC address attribute + Atributo de dirección MAC del equipo + + + Group member attribute + Atributo de miembro del grupo + + + e.g. uid or sAMAccountName + v.g. uid o sAMAccountName + + + Advanced settings + Configuración avanzada + + + Optional object filters + Filtros de objeto opcionales + + + Filter for user groups + Filtro para grupos de usuarios + + + Filter for users + Filtro para usuarios + + + Filter for computer groups + Filtro para grupos de computadoras + + + Group member identification + Identificación del miembro del grupo + + + Distinguished name (Samba/AD) + Nombre distinguido (Samba/AD) + + + List all groups of a user + Listar todos los grupos de un usuario + + + List all groups of a computer + Listar todos los grupos de un equipo + + + Get computer object by IP address + Obtener objeto de equipo por dirección IP + + + Enter username + Introduzca nombre de usuario + + + Please enter a user login name (wildcards allowed) which to query: + Por favor, introduzca un nombre de inicio de sesión (se permiten comodines) a consultar: + + + Enter group name + Introduzca nombre del grupo - LDAP %1 test successful - Comprobación correcta de LDAP %1 + Please enter a group name whose members to query: + Por favor, introduzca un nombre de grupo para consultar sus miembros: - The %1 has been queried successfully and %2 entries were found. - El %1 se ha consultado correctamente y se han encontrado %2 entradas. + Enter computer name + Introduzca nombre del equipo - %1 %2 have been queried successfully: - -%3 - %1 %2 ha sido consultado correctamente: - -%3 + Enter computer DN + Introduzca DN de equipo - LDAP filter test failed - Comprobación fallida de filtro LDAP + Please enter the DN of a computer whose MAC address to query: + Por favor, introduzca el DN de un equipo para consultar su dirección MAC: - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 - No se pudo consultar ningún %1 con el filtro configurado. Compruebe el filtro LDAP para %1. - -%2 + Please enter a user login name whose group memberships to query: + Por favor, introduzca nombre de inicio de sesión de usuario para consultar miembros del grupo: - LDAP filter test successful - Comprobación correcta de filtro LDAP + Enter computer IP address + Introduzca la dirección IP del equipo - %1 %2 have been queried successfully using the configured filter. - %1 %2 se han consultado correctamente con el filtro configurado. + Please enter a computer IP address which to resolve to an computer object: + Introduzca una dirección IP de equipo a resolver a un objeto de equipo: (only if different from group tree) @@ -2169,10 +2819,6 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Computer group tree Árbol de grupo de equipos - - computer group tree - árbol de grupo de equipos - Filter for computers Filtro para equipos @@ -2253,50 +2899,10 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu e.g. (objectClass=container) or (objectClass=organizationalUnit) ej. (objectClass=container) o (objectClass=organizationalUnit) - - Could not query the configured base DN. Please check the base DN parameter. - -%1 - No se pudo consultar el DN base configurado. Verifique el parámetro base DN. - -%1 - - - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - El DN base de LDAP se ha consultado con éxito. Se encontraron las siguientes entradas: - -%1 - - - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - No se pudo consultar el DN base a través de los contextos de nombres. Verifique el parámetro de atributo de contexto de nombres. - -%1 - Certificate files (*.pem) Archivos de certificado (*.pem) - - Could not connect to the LDAP server. Please check the server parameters. - -%1 - No se pudo conectar al servidor LDAP. Por favor, revise los parámetros del servidor. - -%1 - - - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - No se pudo vincular al servidor LDAP. Verifique los parámetros del servidor y las credenciales de enlace. - -%1 - Encryption protocol Protocolo de encriptación @@ -2353,10 +2959,6 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Please enter the name of a computer location (wildcards allowed): Por favor ingrese el nombre de una ubicación de equipo (comodines permitidos): - - computer locations - ubicaciones de equipos - Enter location name Introduzca el nombre de ubicación @@ -2365,38 +2967,6 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Please enter the name of a location whose entries to query: Por favor introduzca el nombre de ubicación cuyas entradas consultar: - - location entries - entradas de ubicación - - - LDAP test failed - La prueba LDAP falló - - - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - No se pudo consultar ningún %1. Verifique el parámetro(s) %2 e ingrese el nombre de un objeto existente. - -%3 - - - and - y - - - LDAP test successful - La prueba LDAP fue exitosa - - - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - No se pudo consultar ninguna entrada en %1 configurado. Por favor, compruebe el parámetro "%2". - -%3 - Browse Buscar @@ -2417,22 +2987,6 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Please enter a computer hostname to query: Por favor introduzca un nombre de host de equipo para consultar: - - Invalid hostname - Nombre de host no válido - - - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Configuró los nombres de host de los equipos para que se almacenaran como nombres de dominio completos (FQDN) pero ingresó un nombre de host sin dominio. - - - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - Configuró los nombres de host de los equipos para ser almacenados como nombres de host simples sin un nombre de dominio, pero ingresó un nombre de host con una parte de nombre de dominio. - - - Could not find a user with the name "%1". Please check the username or the user tree parameter. - No se pudo encontrar un usuario con el nombre "%1". Por favor, compruebe el nombre de usuario o el parámetro del árbol de usuarios. - Enter hostname Introduzca el nombre de host @@ -2442,283 +2996,102 @@ La clave pública se usa en las computadoras cliente para autenticar la solicitu Por favor introduzca un nombre de host de equipo cuyos miembros de grupo desee consultar: - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - No se pudo encontrar un equipo con el nombre de host "%1". Por favor, compruebe el nombre de host o el parámetro del árbol de equipos. - - - Hostname lookup failed - Error al buscar el nombre de host - - - Could not lookup hostname for IP address %1. Please check your DNS server settings. - No se pudo buscar el nombre de host para la dirección IP %1. Por favor, compruebe la configuración de su servidor DNS. - - - User login name attribute - Atributo de nombre de usuario - - - Configured attribute for user login name or computer hostname (OpenLDAP) - Atributo configurado para el nombre de inicio de sesión del usuario o el nombre de host de la computadora (OpenLDAP) - - - computer containers - contenedores de computadoras - - - - LdapPlugin - - Auto-configure the base DN via naming context - Configuración automática del DN base a través del contexto de nombres - - - Query objects from LDAP directory - Consultar objetos desde el directorio LDAP - - - Show help about command - Mostrar ayuda sobre el comando - - - Commands for configuring and testing LDAP/AD integration - Comandos para configurar y probar la integración LDAP/AD - - - Basic LDAP/AD support for Veyon - Soporte básico LDAP/AD para Veyon - - - %1 (load computers and locations from LDAP/AD) - %1 (cargar equipos y ubicaciones desde LDAP/AD) - - - %1 (load users and groups from LDAP/AD) - %1 (cargar usuarios y grupos desde LDAP/AD) - - - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - Por favor, especifique una url LDAP válida siguiendo el esquema "ldap[s]://[usuario[:contraseña]@]hostname[:puerto]" - - - No naming context attribute name given - falling back to configured value. - No se ha dado un nombre de atributo de contexto de nombres - volvemos al valor configurado. - - - Could not query base DN. Please check your LDAP configuration. - No se pudo consultar el DN base. Por favor, compruebe su configuración LDAP. - - - Configuring %1 as base DN and disabling naming context queries. - Configurando %1 como DN base y deshabilitando las consultas de contexto de nombres. - - - - LdapProConfigurationPage - - LDAP Pro - LDAP Pro - - - Instances - Instancias - - - Enter name - Introduzca nombre - - - Please enter a name for the instance (can't be changed later!): - Por favor, introduzca un nombre para la instancia (¡no se puede cambiar más adelante!): - - - Remove instance - Eliminar instancia - - - Do you really want to remove instance "%1"? - ¿Realmente quiere eliminar la instancia "%1"? - - - Configuration for instance "%1" - Configuración para instancia "%1" - - - - LdapProPlugin - - Professional LDAP/AD integration for Veyon - Integración profesional LDAP/AD para Veyon - - - %1 (load computers and locations from LDAP/AD) - %1 (cargar equipos y ubicaciones desde LDAP/AD) - - - %1 (load users and groups from LDAP/AD) - %1 (cargar usuarios y grupos desde LDAP/AD) - - - - LicensingConfigurationPage - - Licensing - Licencias - - - Installed licenses - Licencias instaladas - - - Add new network range - Añadir nuevo rango de red - - - Remove selected network range - Eliminar el rango de red seleccionado - - - ID - ID - - - Feature - Característica - - - Valid until - Válido hasta - - - Licensee - Licencia - - - Browse license file - Buscar archivo de licencia - - - Veyon license files (*.vlf) - Archivos de licencia de Veyon (*.vlf) - - - Remove license - Eliminar licencia - - - Do you really want to remove the selected license? - ¿Realmente desea eliminar la licencia seleccionada? + User login name attribute + Atributo de nombre de usuario - <N/A> - <N/A> + Configured attribute for user login name or computer hostname (OpenLDAP) + Atributo configurado para el nombre de inicio de sesión del usuario o el nombre de host de la computadora (OpenLDAP) - Invalid license file - Archivo de licencia no válido + Directory name + Nombre del directorio - Could not open the license file for reading! - ¡No se pudo abrir el archivo de licencia para su lectura! + Query options + Opciones de consulta - The selected license file does not contain valid data. - El archivo de licencia seleccionado no contiene datos válidos. + Query nested user groups (supported by AD only) + Consultar grupos de usuarios anidados (compatible solo con AD) - The selected license file could not be verified. - El archivo de licencia seleccionado no pudo ser verificado. + Query timeout + Tiempo vencido de consulta - The selected license file is not valid for this installation. - El archivo de licencia seleccionado no es válido para esta instalación. + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. - El archivo de licencia seleccionado ha expirado. + LDAP + LDAP - The license is already installed. - La licencia ya está instalada. + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + Utilice la página de configuración global de LDAP para configurar cómo recuperar ubicaciones y computadoras de su servicio de directorio basado en LDAP. + + + LdapPlugin - Information - Información + Auto-configure the base DN via naming context + Configuración automática del DN base a través del contexto de nombres - Installation ID - ID de instalación + Query objects from LDAP directory + Consultar objetos desde el directorio LDAP - Addons available for licensing - Complementos disponibles para licenciar + Show help about command + Mostrar ayuda sobre el comando - Addon - Complemento + Commands for configuring and testing LDAP/AD integration + Comandos para configurar y probar la integración LDAP/AD - - - LicensingPlugin - Show help for specific command - Mostrar ayuda para un comando específico + Basic LDAP/AD support for Veyon + Soporte básico LDAP/AD para Veyon - Show all installed licenses - Mostrar todas las licencias instaladas + %1 (load computers and locations from LDAP/AD) + %1 (cargar equipos y ubicaciones desde LDAP/AD) - Add license file - Añadir archivo de licencia + %1 (load users and groups from LDAP/AD) + %1 (cargar usuarios y grupos desde LDAP/AD) - Remove installed license - Eliminar licencia instalada + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Por favor, especifique una url LDAP válida siguiendo el esquema "ldap[s]://[usuario[:contraseña]@]hostname[:puerto]" - -USAGE - -%1 add <LICENSE FILE> - - - -USO - -Añadir %1 <LICENSE FILE> - - + No naming context attribute name given - falling back to configured value. + No se ha dado un nombre de atributo de contexto de nombres - volvemos al valor configurado. - -USAGE - -%1 remove <LICENSE ID> - - - -USO - -Eliminar %1 <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. + No se pudo consultar el DN base. Por favor, compruebe su configuración LDAP. - No certificate found with given ID - No se ha encontrado ningún certificado con un ID proporcionado + Configuring %1 as base DN and disabling naming context queries. + Configurando %1 como DN base y deshabilitando las consultas de contexto de nombres. - <N/A> - <N/A> + Test binding to an LDAP server + Prueba de enlace a un servidor LDAP - Licensing management - Administración de licencias + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + El nombre de usuario o la contraseña proporcionados son incorrectos. Ingrese credenciales válidas o cambie a un método de autenticación diferente utilizando Veyon Configurator. - Commands for managing license keys - Comandos para gestionar claves de licencia + LDAP bind + Enlace LDAP @@ -2736,12 +3109,20 @@ Eliminar %1 <LICENSE ID> Autenticacion de usuario - Session management - Gestión de sesiones + User sessions + Sesiones de usuario + + + Minimum session lifetime before server start + Duración mínima de la sesión antes del inicio del servidor - Display manager users - Usuarios del gestor de pantalla + User login + Inicio de sesión de usuario + + + Login key sequence + Secuencia de clave de inicio de sesión @@ -2750,10 +3131,6 @@ Eliminar %1 <LICENSE ID> Plugin implementing abstract functions for the Linux platform Plugin implementando funciones abstractas para la plataforma Linux - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2772,14 +3149,14 @@ Eliminar %1 <LICENSE ID> Configuration Configuración - - Disable balloon tooltips - Desactivar ayudas en globos - Show icons only Mostrar solo iconos + + Disable tooltips + Desactivar los tooltips + MainWindow @@ -2827,10 +3204,6 @@ Eliminar %1 <LICENSE ID> About Qt Acerca de Qt - - Authentication impossible - Autenticación imposible - Configuration not writable La configuración no se puede escribir @@ -2853,7 +3226,7 @@ Eliminar %1 <LICENSE ID> Veyon Configurator - Configurador de Veyon + Veyon Configurator Service @@ -2891,10 +3264,6 @@ Eliminar %1 <LICENSE ID> The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. ¡El backend de configuración local informó que la configuración no es escribible! Ejecute el Configurador de %1 con privilegios más altos. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - No se encontraron archivos de clave de autenticación o los actuales no están actualizados. Por favor, cree nuevos archivos de claves usando el Configurador de %1. También puede configurar la autenticación de inicio de sesión utilizando el Configurador de %1. De lo contrario, no podrá acceder a los equipos que utilizan %1. - Access denied Acceso denegado @@ -2927,10 +3296,6 @@ Eliminar %1 <LICENSE ID> Search users and computers Buscar usuarios y equipos - - Adjust optimal size - Ajustar el tamaño óptimo - Align computers to grid Alinear equipos a la rejilla @@ -2975,6 +3340,48 @@ Eliminar %1 <LICENSE ID> Locations && computers Ubicaciones && equipos + + Authentication + Autenticación + + + Adjust size of computer icons automatically + Ajustar el tamaño de los iconos de la computadora automáticamente + + + Slideshow + Diapositivas + + + Spotlight + Foco + + + Veyon Master + Veyon Master + + + Locations & computers + Ubicaciones y equipos + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + Mostrar solo equipos con usuarios registrados + + + Load computer positions + + + + Save computer positions + + MasterConfigurationPage @@ -2982,10 +3389,6 @@ Eliminar %1 <LICENSE ID> Directories Directorios - - ... - ... - User configuration Configuración de usuario @@ -3070,6 +3473,10 @@ Eliminar %1 <LICENSE ID> Only user name Sólo nombre del usuario + + Only last part of user name + + Only computer name Sólo nombre del equipo @@ -3118,171 +3525,181 @@ Eliminar %1 <LICENSE ID> Automatically select current location Seleccionar automáticamente la ubicación actual - - Automatically adjust computer thumbnail size - Ajustar automáticamente el tamaño de la miniatura del equipo - Automatically open computer select panel Abrir automáticamente el panel de selección de equipo - - - MonitoringMode - Monitoring - Monitorización + Use modern user interface (experimental) + Usar una interfaz de usuario moderna (experimental) - Builtin monitoring mode - Modo de monitorización incorporado + Thumbnail spacing + Espaciado de miniaturas - This mode allows you to monitor all computers at one or more locations. - Este modo le permite monitorear todos los equipos en una o más ubicaciones. + px + px - - - NetworkDiscoveryConfigurationPage - Network discovery - Detección de redes + Hide local session + Ocultar sesión local - Mode - Modo + Auto + Auto - Scan network ranges - Analizar rangos de red + Thumbnail aspect ratio + Relación de aspecto de la miniatura - e.g. 192.168.1.0/24 - ej. 192.168.1.0/24 + Automatically adjust computer icon size + Ajustar automáticamente el tamaño del icono de la computadora - Scan all subnets of computer - Analizar todas las subredes del equipo + Open feature windows on the same screen as the main window + Abrir ventanas de funciones en la misma pantalla que la ventana principal - Scan custom subnet - Analizar subred personalizada + Configuration templates + - Scan sessions on local computer - Analizar sesiones en un equipo local + Image quality in monitoring mode + Calidad de imagen en modo de monitoreo - Test - Comprobar + Highest + Más alto - Network ranges - Rangos de red + High + Alto - Add new group - Añadir nuevo grupo + Medium + Medio - Remove selected group - Eliminar grupo seleccionado + Low + Bajo - Groups - Grupos + Lowest + El más bajo - First address - Primera dirección + Remote access image quality + Calidad de imagen de acceso remoto - Last address - Última dirección + Advanced + - Add new network range - Añadir nuevo rango de red + Computer name source + - Remove selected network range - Eliminar el rango de red seleccionado + Default + - Parallel scans - Análisis paralelos + Host address + Dirección del equipo - Scan timeout - Tiempo de espera de análisis + Session client address + Dirección del cliente de la sesión - ms - ms + Session client name + Nombre del cliente de sesión + + + Session host name + - Session scan limit - Límite de análisis de sesión + Session metadata + - Options - Opciones + Full name of user + Nombre completo del usuario - Reverse lookup discovered IP addresses to host names - Búsqueda inversa de direcciones IP descubiertas a nombres de host + User login name + Nombre de inicio de sesión del usuario - New location - Nueva ubicación + Computer UID role + + + + Session meta data hash + - - - NetworkDiscoveryDirectory - Scanning... - Analizando... + Always expand all locations + - Discovered computers - Equipos detectados + Image quality + Calidad de imagen - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command - Mostrar ayuda para un comando específico + Monitoring + Monitorización - Scan a subnet - Analizar una subred + Builtin monitoring mode + Modo de monitorización incorporado - -USAGE - -%1 scan [<SUBNET>] - - - -USO - -%1 analizado [<SUBNET>] - - + This mode allows you to monitor all computers at one or more locations. + Este modo le permite monitorear todos los equipos en una o más ubicaciones. + + + Query application version of the server + Consultar la versión de la aplicación del servidor + + + Query active features + Consultar funciones activas + + + Query properties of remotely available screens + Consultar propiedades de pantallas disponibles de forma remota + + + + NestedNetworkObjectDirectory + + All directories + Todos los directorios + + + NetworkObjectDirectoryConfigurationPage - Network object directory which automatically discovers computers in the network - Directorio de objetos de red que detecta automáticamente los equipos en la red + Update interval: + Intervalo de actualización: - Network discovery (scan network for Veyon clients) - Detección de redes (analizar la red para clientes Veyon) + seconds + segundos + + + NetworkObjectDirectoryConfigurationPageTab - Commands for managing the network discovery directory - Comandos para administrar el directorio de detección de redes + Enabled + Habilitado @@ -3318,32 +3735,44 @@ USO Name: Nombre: + + Website name + Nombre del Sitio Web + - PasswordDialog + PluginCommands - Username - Nombre de usuario + List names of all installed plugins + Lista de nombres de todos los complementos instalados - Password - Contraseña + Show table with details of all installed plugins + Mostrar tabla con detalles de todos los complementos instalados - Veyon Logon - Inicio de sesión de Veyon + Name + Nombre - Authentication error - Error de autenticación + Description + Descripción - Logon failed with given username and password. Please try again! - Error de inicio de sesión con el nombre de usuario y contraseña dados. Por favor, ¡inténtelo de nuevo! + Version + Versión - Please enter your username and password in order to access computers. - Introduzca su nombre de usuario y contraseña para acceder a los equipos. + UID + UID + + + Plugin-related CLI operations + Operaciones CLI relacionadas con complementos + + + Commands for managing plugins + Comandos para administrar complementos @@ -3388,10 +3817,6 @@ USO Do you really want to reboot the selected computers? ¿Realmente desea reiniciar los equipos seleccionados? - - Do you really want to power down the selected computer? - ¿Realmente desea apagar el equipo seleccionado? - Power on a computer via Wake-on-LAN (WOL) Encienda un equipo a través de Wake-on-LAN (WOL) @@ -3444,6 +3869,18 @@ Please save your work and close all programs. Por favor guarde su trabajo y cierre todos los programas. + + Do you really want to reboot <b>ALL</b> computers? + ¿Realmente desea reiniciar <b>TODAS</b> las computadoras? + + + Do you really want to power down <b>ALL</b> computers? + ¿Realmente desea apagar <b>TODAS</b> las computadoras? + + + Do you really want to power down the selected computers? + ¿Realmente desea apagar las computadoras seleccionadas? + PowerDownTimeInputDialog @@ -3490,14 +3927,25 @@ Por favor guarde su trabajo y cierre todos los programas. Remote view or control a computer Vista remota o control de un equipo - - Please enter the hostname or IP address of the computer to access: - Por favor, introduzca el nombre o la dirección IP del equipo a acceder: - Show help about command Mostrar ayuda sobre el comando + + Exchange clipboard contents + Intercambiar contenido del portapapeles + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + No se ha seleccionado ninguna computadora, por lo que puede introducir un nombre de host o dirección IP de una computadora para acceso manual: + + + + RemoteAccessPage + + Remote access: %1 + Acceso remoto: %1 + RemoteAccessWidget @@ -3505,6 +3953,10 @@ Por favor guarde su trabajo y cierre todos los programas. %1 - %2 Remote Access %1 - %2 Acceso remoto + + %1 - %2 - %3 Remote Access + Acceso Remoto %1 - %2 - %3 + RemoteAccessWidgetToolBar @@ -3560,10 +4012,6 @@ Por favor guarde su trabajo y cierre todos los programas. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - Conectando %1 - Connected. Conectado. @@ -3576,58 +4024,17 @@ Por favor guarde su trabajo y cierre todos los programas. Exit Salir - - - Routing - - Control internet access by modifying routing table - Controlar el acceso a Internet modificando la tabla de enrutamiento - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - Eliminar las rutas predeterminadas para bloquear el acceso a Internet - - - Add custom route to block internet - Añadir una ruta personalizada para bloquear Internet - - - Destination - Destino - - - Gateway - Puerta de enlace - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - Introduzca los programas o comandos a ejecutar en el equipo/s seleccionado/s. Puede separar varios programas/comandos por línea. - - - Run programs - Ejecutar programas - - - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - v.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - - Name: - Nombre: + Connecting... + Conectando ... - Remember and add to program menu - Recordar y añadir al menú del programa + Select screen + Seleccionar pantalla - e.g. VLC - p.ej. VLC + All screens + Todas las pantallas @@ -3648,6 +4055,18 @@ Por favor guarde su trabajo y cierre todos los programas. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. Para recuperar toda la atención del usuario puede bloquear sus equipos con este botón. En este modo, todos los dispositivos de entrada están bloqueados y las pantallas son inhabilitadas . + + Lock input devices + Bloquear dispositivos de entrada + + + Unlock input devices + Desbloquear dispositivos de entrada + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + Para reclamar la atención de todos los usuarios, puede bloquear sus computadoras usando este botón. En este modo, todos los dispositivos de entrada están bloqueados mientras el escritorio aún está visible. + Screenshot @@ -3663,6 +4082,10 @@ Por favor guarde su trabajo y cierre todos los programas. Screenshot Captura + + Could not open screenshot file %1 for writing. + No se pudo abrir el archivo de captura de pantalla %1 para escribir. + ScreenshotFeaturePlugin @@ -3683,8 +4106,15 @@ Por favor guarde su trabajo y cierre todos los programas. La captura de pantalla del equipo %1 se ha realizado correctamente. - Take screenshots of computers and save them locally. - Tome capturas de pantalla de los equipos y guárdelas localmente. + Take screenshots of computers and save them locally. + Tome capturas de pantalla de los equipos y guárdelas localmente. + + + + ScreenshotManagementPage + + Screenshots + Capturas @@ -3717,6 +4147,45 @@ Por favor guarde su trabajo y cierre todos los programas. Delete Borrar + + Screenshot + Captura + + + Do you really want to delete all selected screenshots? + ¿Realmente desea eliminar todas las capturas de pantalla seleccionadas? + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + + + + User has denied access + + + + User confirmed access + + ServiceConfigurationPage @@ -3748,14 +4217,6 @@ Por favor guarde su trabajo y cierre todos los programas. State: Estado: - - Network - Red - - - Demo server port - Puerto de servidor demo - Enable firewall exception Habilitar excepción en el cortafuegos @@ -3764,10 +4225,6 @@ Por favor guarde su trabajo y cierre todos los programas. Allow connections from localhost only Solo permitir conexiones desde equipo local - - Internal VNC server port - Puerto del servidor VNC interno - VNC server Servidor VNC @@ -3788,14 +4245,6 @@ Por favor guarde su trabajo y cierre todos los programas. Running Funcionando - - Feature manager port - Puerto del administrador de funciones - - - Primary service port - Puerto de servicio principal - Enabling this option will make the service launch a server process for every interactive session on a computer. Typically this is required to support terminal servers. @@ -3806,52 +4255,130 @@ Por lo general, esto es necesario para admitir servidores de terminales.Show notification on remote connection Mostrar notificación en conexión remota - - Multi session mode (for terminal and remote desktop servers) - Modo de sesión múltiple (para servidores de terminales y de escritorio remoto) - Show notification when an unauthorized access is blocked Mostrar notificación cuando un acceso no autorizado está bloqueado - - - ServiceControl - Starting service %1 - Iniciando servicio %1 + Maximum session count + Número máximo de sesiones - Stopping service %1 - Deteniendo servicio %1 + Network port numbers + Números de puerto de red - Registering service %1 - Registrando servicio %1 + Veyon server + Servidor Veyon - Unregistering service %1 - Eliminando registro de servicio %1 + Internal VNC server + Servidor VNC interno - Service control - Control de servicio + Feature manager + Gerente de funciones + + + Demo server + Servidor demo + + + Miscellaneous network settings + Configuraciones de red diversas + + + Session mode + Modo de sesión + + + Local session mode (single server instance for primary local session) + Modo de sesión local (instancia de servidor único para sesión local principal) + + + Active session mode (single server instance for active local or remote session) + Modo de sesión activa (instancia de servidor único para sesión local o remota activa) + + + Multi session mode (distinct server instance for each local and remote desktop session) + Modo de sesión múltiple (instancia de servidor distinta para cada sesión de escritorio local y remota) + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + + + + Miscellaneous settings + + + + Disable clipboard synchronization + + + + Session metadata + + + + Content + + + + None + Ninguno + + + Value of an environment variable + + + + Value of a registry key + + + + Environment variable name: + + + + Registry key name: + + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + - ServiceControlPlugin + ServiceControl - Service is running - El servicio esta ejecutándose + Service control + Control de servicio - Service is not running - El servicio no está ejecutándose + Starting %1 + - Configure and control Veyon service - Configurar y controlar el Servicio de Veyon + Stopping %1 + + + + Restarting %1 + + + + Registering %1 + + + + Unregistering %1 + + + + ServiceControlCommands Register Veyon Service Registrar Servicio Veyon @@ -3876,13 +4403,25 @@ Por lo general, esto es necesario para admitir servidores de terminales.Query status of Veyon Service Consultar estado de Servicio Veyon + + Service is running + El servicio esta ejecutándose + + + Service is not running + El servicio no está ejecutándose + + + Configure and control Veyon service + Configurar y controlar el Servicio de Veyon + Commands for configuring and controlling Veyon Service Comandos para configurar y controlar el Servicio Veyon - ShellCommandLinePlugin + ShellCommands Run command file Ejecutar archivo de comandos @@ -3892,14 +4431,101 @@ Por lo general, esto es necesario para admitir servidores de terminales.¡El archivo "%1" no existe! - Interactive shell and script execution for Veyon Control - Ejecución interactiva de shell y script para el Control de Veyon + Interactive shell and script execution for Veyon CLI + Ejecución interactiva de shell y script para Veyon CLI Commands for shell functionalities Comandos para funcionalidades de shell + + SlideshowPanel + + Previous + Anterior + + + Start/pause + Inicio/pausa + + + Next + Siguiente + + + Duration: + Duración: + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + Añadir las computadoras seleccionadas + + + Remove selected computers + Eliminar las computadoras seleccionadas + + + Update computers in realtime + Actualizar computadoras en tiempo real + + + Spotlight + Foco + + + Please select at least one computer to add. + Seleccione al menos una computadora para añadir. + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + Agregue computadoras haciendo clic con el botón central del ratón o haciendo clic en el botón primario más abajo. +El botón secundario elimina el equipo seleccionado o el último. + + + + StartAppDialog + + Start application + Iniciar aplicación + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + Por favor, introduzca las aplicaciones para iniciar en las computadoras seleccionadas. Puede separar varias aplicaciones por línea. + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + v.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + Recordar y añadir al menú de la aplicación + + + Application name + Nombre de la aplicación + + + Name: + Nombre: + + + e.g. VLC + p.ej. VLC + + SystemTrayIcon @@ -3936,8 +4562,8 @@ Por lo general, esto es necesario para admitir servidores de terminales.Enviar mensaje de texto - Use the field below to type your message which will be sent to all selected users. - Use el campo de más abajo para escribir su mensaje que será enviado a todos los usuarios seleccionados. + Please enter your message which send to all selected users. + Por favor, introduzca el mensaje a enviar a todos los usuarios seleccionados. @@ -3985,23 +4611,39 @@ Por lo general, esto es necesario para admitir servidores de terminales.Enable Desktop Duplication Engine on Windows 8 and newer Habilitar duplicación de escritorio en Windows 8 y versiones posteriores + + Maximum CPU usage + Uso máximo de CPU + - UserConfig + UserLoginDialog - No write access - No hay acceso de escritura + User login + Inicio de sesión de usuario - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - No se pudo guardar su configuración personal. Compruebe la ruta del archivo de configuración del usuario utilizando el Configurador %1. + Please enter a username and password for automatic login on all computers. + Introduzca un nombre de usuario y contraseña para iniciar sesión automáticamente en todas las computadoras. + + + Username + Nombre de usuario + + + Password + Contraseña - UserSessionControl + UserSessionControlPlugin - User session control - Control de sesión de usuario + Log in + Iniciar sesión + + + Click this button to log in a specific user on all computers. + Haga clic en este botón para iniciar sesión en un usuario específico en todas las computadoras. Log off @@ -4019,6 +4661,14 @@ Por lo general, esto es necesario para admitir servidores de terminales.Do you really want to log off the selected users? ¿Realmente quieres desconectar a los usuarios seleccionados? + + User session control + Control de sesión de usuario + + + Do you really want to log off <b>ALL</b> users? + ¿Realmente quieres cerrar sesión a <b>TODOS</b> los usuarios? + VeyonCore @@ -4070,10 +4720,6 @@ Por lo general, esto es necesario para admitir servidores de terminales.ERROR ERROR - - licensed for - licenciado para - USAGE USO @@ -4090,19 +4736,31 @@ Por lo general, esto es necesario para admitir servidores de terminales.WARNING ADVERTENCIA + + Authentication test + Prueba de autenticacion + + + Screen %1 + Pantalla %1 + - VeyonServiceControl + VeyonMaster - Veyon Service - Servicio Veyon + No write access + No hay acceso de escritura + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + No se pudo guardar su configuración personal. Compruebe la ruta del archivo de configuración del usuario utilizando el Configurador %1. - VncView + VeyonServiceControl - Establishing connection to %1 ... - Estableciendo conexión con %1 ... + Veyon Service + Veyon Service @@ -4150,6 +4808,30 @@ Por lo general, esto es necesario para admitir servidores de terminales.Use alternative user authentication mechanism Utilizar mecanismo de autenticación de usuario alternativo + + User login + Inicio de sesión de usuario + + + Input start delay + Retardo de inicio de entrada + + + Simulated key presses interval + Intervalo de pulsaciones de teclas simuladas + + + Confirm legal notice (message displayed before user logs in) + Confirmar aviso legal (mensaje que se muestra antes de que el usuario inicie sesión) + + + Use input device interception driver + Utilice el controlador de interceptación del dispositivo de entrada + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4158,8 +4840,8 @@ Por lo general, esto es necesario para admitir servidores de terminales.Plugin implementando funciones abstractas para la plataforma Windows - Plugin implementing specific functions for the Windows platform - + Internal display + Pantalla interna @@ -4168,30 +4850,34 @@ Por lo general, esto es necesario para admitir servidores de terminales.The service "%1" is already installed. El servicio "%1" ya está instalado. - - The service "%1" could not be installed. - No se pudo instalar el servicio "%1". - The service "%1" has been installed successfully. El servicio "%1" se ha instalado correctamente. - - The service "%1" could not be uninstalled. - El servicio "%1" no se pudo desinstalar. - The service "%1" has been uninstalled successfully. El servicio "%1" se ha desinstalado correctamente. - - The start type of service "%1" could not be changed. - El tipo de inicio de servicio "%1" no se pudo cambiar. - Service "%1" could not be found. No se pudo encontrar el servicio "%1". + + The service "%1" could not be installed (error %2). + No se pudo instalar el servicio "%1" (error %2). + + + Could not change the failure actions config for service "%1" (error %2). + No se pudo cambiar la configuración de acciones de fallo para el servicio "%1" (error %2). + + + The service "%1" could not be uninstalled (error %2). + No se pudo desinstalar el servicio "%1" (error %2). + + + The start type of service "%1" could not be changed (error %2). + No se pudo cambiar el tipo de inicio del servicio "%1" (error %2). + X11VncConfigurationWidget diff --git a/translations/veyon_et.ts b/translations/veyon_et.ts new file mode 100644 index 000000000..caa02157d --- /dev/null +++ b/translations/veyon_et.ts @@ -0,0 +1,4899 @@ + + + AboutDialog + + About + Programmist + + + Translation + Tõlkimine + + + License + Litsents + + + About Veyon + Programmist Veyon + + + Contributors + Kaastöötajad + + + Version: + Versioon: + + + Website: + Koduleht: + + + Current language not translated yet (or native English). + +If you're interested in translating Veyon into your local or another language or want to improve an existing translation, please contact a Veyon developer! + Current language not translated yet (or native English). + +If you're interested in translating Veyon into your local or another language or want to improve an existing translation, please contact a Veyon developer! + + + About %1 %2 + Programmist %1 %2 + + + Support Veyon project with a donation + Toetage Veyon projekti annetusega + + + + AccessControlPage + + Computer access control + Arvuti juurdepääsu juhtimine + + + Grant access to every authenticated user (default) + Andke juurdepääs igale autentitud kasutajale (vaikimisi) + + + Test + Test + + + Process access control rules + Protsessi juurdepääsu juhtimise reeglid + + + User groups authorized for computer access + Kasutajarühmad, kellel on juurdepääs arvutile + + + Please add the groups whose members should be authorized to access computers in your Veyon network. + Palun lisage rühmad, mille liikmetel peaks olema õigus pääseda juurde teie Veyoni võrgu arvutitele. + + + Authorized user groups + Volitatud kasutajagrupid + + + All groups + Kõik grupid + + + Access control rules + Juurdepääsu reeglid + + + Add access control rule + Lisa juurdepääsu reegel + + + Remove access control rule + Eemalda juurdepääsu reegel + + + Move selected rule down + Teisalda valitud reegel alla + + + Move selected rule up + Teisalda valitud reegel üles + + + Edit selected rule + Muuda valitud reeglit + + + Enter username + Sisestage kasutajanimi + + + Please enter a user login name whose access permissions to test: + Sisestage kasutaja sisselogimisnimi, mille juurdepääsuluba testida: + + + Access allowed + Juurdepääs lubatud + + + The specified user is allowed to access computers with this configuration. + Valitud kasutajal on juurdepääs selle konfiguratsiooniga arvutitele. + + + Access denied + Juurdepääs keelatud + + + The specified user is not allowed to access computers with this configuration. + Määratud kasutajal pole lubatud selle konfiguratsiooniga arvutitele juurde pääseda. + + + Enable usage of domain groups + Domeeni gruppide juurdepääsu lubamine + + + User groups backend: + Kasutajarühmade taustaprogramm: + + + Restrict access to members of specific user groups + Määratud gruppide liikmete juurdepääsu keelamine + + + + AccessControlProvider + + Provider for access control features + + + + + AccessControlRuleEditDialog + + Edit access control rule + Redigeeri juurdepääsu reeglit + + + General + Üldine + + + enter a short name for the rule here + sisestage siia reegli lühinimi + + + Rule name: + Reegli nimi: + + + enter a description for the rule here + sisestage siia reegli kirjeldus + + + Rule description: + Reegli kirjeldus: + + + Conditions + Tingimused + + + If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. + Kui aktiveeritakse rohkem kui üks tingimus, peavad reegli rakendamiseks kõik tingimused vastama (loogiline JA). Kui peab vastama ainult üks mitmest tingimusest (loogiline VÕI), siis looge mitu juurdepääsu kontrollreeglit. + + + Action + Tegevus + + + Allow access + Luba juurdepääs + + + Deny access + Keela juurdepääs + + + Ask logged on user for permission + Küsige sisselogitud kasutajalt luba + + + None (rule disabled) + Puudub (reegel on keelatud) + + + Accessing user + Kasutajale juurdepääs + + + Accessing computer + Arvutile juurdepääs + + + Always process rule and ignore conditions + Kasutage reeglit alati ja eirake tingimusi + + + Accessing computer and local computer + Juurdepääs arvutile ja kohalikule arvutile + + + User being accessed + Juurdepääs kasutajale + + + is logged in locally + on sisse logitud kohapeal + + + is logged in remotely + on sisse logitud kaugjuhtimisega + + + No user is logged in locally + Ükski kasutaja pole kohapeal sisse logitud + + + One or multiple users are logged in locally + Üks või mitu kasutajat on kohalikult sisse logitud + + + No user is logged in remotely + Ükski kasutaja pole kaugjuhtimisega sisse logitud + + + One or multiple users are logged in remotely + Üks või mitu kasutajat on sisse logitud eemalt + + + is located at + on asukohas + + + is not located at + ei asu aadressil + + + are located at the same location + asuvad samal aadressil + + + are not located the same location + ei asu samal aadressil + + + is member of group + on rühma liige + + + is not member of group + ei ole grupi liige + + + is authenticated via + on autentitud + + + is not authenticated via + pole autentitud + + + has one or more groups in common with user being accessed + on juurdepääsetava kasutajaga üks või mitu ühist rühma + + + has no groups in common with user being accessed + ei oma kasutajaga ühiseid rühmi + + + equals user being accessed + võrdub juurdepääsuga kasutajale + + + is different from user being accessed + erineb juurdepääsetavast kasutajast + + + is already connected + on juba ühendatud + + + is not connected + ei ole ühendatud + + + is local computer + on kohalik arvuti + + + is not local computer + ei ole kohalik arvuti + + + Computer being accessed + Juurdepääs arvutile + + + Session being accessed is a user session + Seanss, millele pääseb juurde, on kasutaja seanss + + + Session being accessed is a login screen + Seanss, millele pääseb juurde, on sisselogimisekraan + + + Local computer is already being accessed + + + + Local computer is not yet being accessed + + + + + AccessControlRulesTestDialog + + Access control rules test + Juurdepääsu reeglite test + + + Accessing user: + Kasutajale juurdepääs: + + + Local computer: + Kohalik arvuti: + + + Accessing computer: + Arvutile juurdepääs: + + + Please enter the following user and computer information in order to test the configured ruleset. + Konfigureeritud reeglistiku testimiseks sisestage järgmine kasutaja ja arvuti teave. + + + Local user: + Kohalik kasutaja: + + + Connected users: + ühenduses kasutajad + + + The access in the given scenario is allowed. + Antud stsenaariumi korral on juurdepääs lubatud. + + + The access in the given scenario is denied. + Antud stsenaariumi korral on juurdepääs keelatud. + + + The access in the given scenario needs permission of the logged on user. + Antud stsenaariumi korral vajab juurdepääs sisseloginud kasutaja luba. + + + Test result + Testi tulemus + + + Authentication method + Autentimismeetod + + + There is no matching rule with a valid action. The access is therefore denied. + + + + + AuthKeysConfigurationWidget + + Introduction + Juhend + + + Please perform the following steps to set up key file authentication: + Võtmefaili autentimise seadistamiseks toimige järgmiselt: + + + 1) Create a key pair on the master computer. + 1) Looge põhiarvutis võtmepaar. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Määrake juurdepääsugrupp, mille liikmetel peaks olema juurdepääs teistele arvutitele. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Eksportige avalik võti ja importige see kõigisse samanimelistesse klientarvutitesse. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Kasutage <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon administraatori käsiraamatut</a> lisateabe saamiseks. + + + Key file directories + Võtmefailide kataloogid + + + Public key file base directory + Avaliku võtme failibaasi kataloog + + + Private key file base directory + Privaatvõtme failibaasi kataloog + + + Available authentication keys + Saadaval olevad autentimisvõtmed + + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Autentimisvõtmete paar koosneb kahest ühendatud krüptovõtmest, privaatsest ja avalikust võtmest. +Privaatvõti võimaldab peaarvuti kasutajatel pääseda juurde klientarvutitele. +On oluline, et ainult volitatud kasutajatel oleks juurdepääs privaatvõtme failile. +Avalikku võtit kasutatakse klientarvutites sissetuleva ühenduse päringu autentimiseks. + + + Create key pair + Loo võtmepaar + + + Delete key + Kustuta võti + + + Import key + Impordi võti + + + Export key + Ekspordi võti + + + Set access group + Määra juurdepääsugrupp + + + Key files (*.pem) + Võtmefailid (*.pem) + + + Authentication key name + Autentimisvõtme nimi + + + Please enter the name of the user group or role for which to create an authentication key pair: + Sisestage kasutajagrupi või rolli nimi, mille jaoks autentimisvõtmepaari luua: + + + Do you really want to delete authentication key "%1/%2"? + Kas soovite tõesti autentimisvõtme "%1/%2" kustutada? + + + Please select a key to delete! + Valige kustutamiseks võti! + + + Please select a key to export! + Valige eksportimiseks võti! + + + Please select a user group which to grant access to key "%1": + Valige võtmerühmale "%1" juurdepääsuks kasutajagrupp: + + + Please select a key which to set the access group for! + Valige võti, millele juurdepääsugrupp määrata! + + + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + Sisestage selle kasutajarühma või rolli nimi, mille autentimisvõti importida. + +Veenduge, et üksteisele kuuluvate võtmete nimed oleksid kõikides arvutites identsed. + + + + AuthKeysManager + + Please check your permissions. + Kontrollige oma õigusi. + + + Key name contains invalid characters! + Võtme nimi sisaldab valesid tähemärke! + + + Invalid key type specified! Please specify "%1" or "%2". + Määratud on vale võtmetüüp! Palun määrake "%1" või "%2". + + + Specified key does not exist! Please use the "list" command to list all installed keys. + Määratud võtit pole olemas! Kõigi installitud võtmete loetlemiseks kasutage käsku "nimekiri". + + + One or more key files already exist! Please delete them using the "delete" command. + Üks või mitu võtmefaili on juba olemas! Kustutage need käsuga "kustuta". + + + Creating new key pair for "%1" + "%1" jaoks uue võtmepaari loomine + + + Failed to create public or private key! + Avaliku või privaatse võtme loomine ebaõnnestus! + + + Newly created key pair has been saved to "%1" and "%2". + Äsja loodud võtmepaar on salvestatud kaustadesse "%1" ja "%2". + + + Could not remove key file "%1"! + Võtmefaili "%1" ei saanud eemaldada! + + + Could not remove key file directory "%1"! + Võtmefailide kataloogi "%1" ei saanud eemaldada! + + + Failed to create directory for output file. + Väljundfaili kataloogi loomine nurjus. + + + File "%1" already exists. + Fail "%1" on juba olemas + + + Failed to write output file. + Faili kirjutamine ebaõnnestus + + + Key "%1/%2" has been exported to "%3" successfully. + Võti "%1 /%2" on edukalt eksporditud kausta "%3". + + + Failed read input file. + Sisendfaili lugemine ei õnnestu. + + + File "%1" does not contain a valid private key! + Fail "%1" ei sisalda kehtivat privaatvõtit! + + + File "%1" does not contain a valid public key! + Fail "%1" ei sisalda kehtivat avalikku võtit! + + + Failed to create directory for key file. + Võtmefaili kataloogi loomine nurjus. + + + Failed to write key file "%1". + Võtmefaili "%1" kirjutamine nurjus. + + + Failed to set permissions for key file "%1"! + Võtmefaili "%1" õiguste seadistamine nurjus! + + + Key "%1/%2" has been imported successfully. Please check file permissions of "%3" in order to prevent unauthorized accesses. + Võtme "%1/%2" importimine õnnestus. Volitamata juurdepääsu vältimiseks kontrollige faili "%3" õigusi. + + + Failed to convert private key to public key + Privaatvõtme avalikuks võtmeks teisendamine nurjus + + + Failed to create directory for private key file "%1". + Kataloogi loomine privaatvõtme failile "%1" nurjus. + + + Failed to save private key in file "%1"! + Privaatvõtme salvestamine faili "%1" nurjus! + + + Failed to set permissions for private key file "%1"! + Privaatvõtme faili "%1" õiguste seadistamine nurjus! + + + Failed to create directory for public key file "%1". + Avaliku võtme faili "%1" kataloogi loomine nurjus. + + + Failed to save public key in file "%1"! + Faili "%1" avaliku võtme salvestamine ebaõnnestus! + + + Failed to set permissions for public key file "%1"! + Avaliku võtme faili "%1" lubade seadistamine nurjus! + + + Failed to set owner of key file "%1" to "%2". + Võtmefaili "%1" omaniku määramine väärtuseks "%2" nurjus. + + + Failed to set permissions for key file "%1". + Võtmefaili "%1" õiguste seadistamine nurjus. + + + Key "%1" is now accessible by user group "%2". + Võtmele "%1" pääseb nüüd kasutajarühm "%2". + + + <N/A> + <N/A> + + + Failed to read key file. + Võtmefaili lugemine nurjus. + + + + AuthKeysPlugin + + Create new authentication key pair + Looge uus autentimisvõtmepaar + + + Delete authentication key + Kustutage autentimisvõti + + + List authentication keys + Loendage autentimisvõtmed + + + Import public or private key + Importige avalik või privaatne võti + + + Export public or private key + Eksportige avalik või privaatne võti + + + Extract public key from existing private key + Eemaldage avalik võti olemasolevast privaatvõtmest + + + Set user group allowed to access a key + Määra kasutajagrupp, kellel on juurdepääs võtmele + + + KEY + VÕTI + + + ACCESS GROUP + JUURDEPÄÄSU GRUPP + + + This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. + See käsk reguleerib failile juurdepääsuõigused <KEY> selliseks, et ainult kasutajagrupil <ACCESS GROUP> on sellele lugemisõigus. + + + NAME + NIMI + + + FILE + FAIL + + + This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. + See käsk ekspordib autentimisvõtme <KEY> võtmeks <FILE>. Kui <FILE> pole täpsustatud, koostatakse nimi nime ja tüübi <KEY> järgi. + + + This command imports the authentication key <KEY> from <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. + See käsk impordib autentimisvõtme <KEY> kohast <FILE>. Kui <FILE>pole täpsustatud, koostatakse nimi nime ja tüübi <KEY> järgi. + + + This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. + See käsk loetleb kõik saadaolevad autentimisvõtmed konfigureeritud võtmete kataloogis. Kui määratakse suvand "%1", kuvatakse selle asemel võtme üksikasjadega tabel. Mõni detail võib puududa, kui võtmele pole juurdepääsu, nt. lugemisõiguste puudumise tõttu. + + + TYPE + TÜÜP + + + PAIR ID + PAARI ID + + + Commands for managing authentication keys + Käsud autentimisvõtmete haldamiseks + + + This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. + See käsk loob uue autentimisvõtmepaari nimega <NAME> ja salvestab privaatse ja avaliku võtme konfigureeritud võtmete kataloogidesse. Parameeter peab olema võtme nimi, mis võib sisaldada ainult tähti. + + + This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. + See käsk kustutab autentimisvõtme <KEY> konfigureeritud võtmete kataloogist. Pange tähele, et võtit ei saa pärast selle kustutamist taastada. + + + This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + See käsk eraldab avaliku võtme osa privaatvõtmest <KEY> ja salvestab selle vastava avaliku võtmena. Teise põhiarvuti seadistamisel piisab seetõttu ainult privaatvõtme edastamisest. Seejärel saab avaliku võtme välja tõmmata. + + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + Autentimisvõtme failid pole selles arvutis õigesti seadistatud. Looge Veyon Configuratori abil uued võtmefailid või lülituge teisele autentimismeetodile. + + + Key file authentication + Võtmefaili autentimine + + + Key file + Võtmefail + + + Please specify the key name (e.g. "teacher/public") as the first argument. + Palun määrake esimese argumendina võtme nimi (näiteks „õpetaja/avalik”). + + + Please specify the command to display help for. + Palun määrake käsk abi kuvamiseks. + + + The specified command does not exist or no help is available for it. + Määratud käsku pole olemas või selle jaoks pole abi saadaval. + + + + AuthKeysTableModel + + Name + Nimi + + + Type + Tüüp + + + Access group + Juurdepääsugrupp + + + Pair ID + Paari ID + + + + AuthLdapConfigurationWidget + + General + Üldine + + + Username to bind DN mapping: + DN-kaardistamise sidumiseks kasutajanimi: + + + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + näit. %username%@DOMAIN või cn=%username%,ou=users,dc=example,dc=org + + + + AuthLdapDialog + + Veyon Logon + Veyoni sisselogimine + + + Please enter your domain/LDAP username and password in order to access computers. + Arvutitele juurdepääsemiseks sisestage oma domeen/LDAP kasutajanimi ja parool. + + + Username + Kasutajanimi + + + Password + Parool + + + Authentication error + Autentimise viga + + + Logon failed with given username and password. Please try again! + Sisselogimine nurjus antud kasutajanime ja parooliga. Palun proovi uuesti! + + + + AuthLogonDialog + + Veyon Logon + Veyoni sisselogimine + + + Please enter your username and password in order to access computers. + Arvutitele juurdepääsu saamiseks sisestage oma kasutajanimi ja parool. + + + Username + Kasutajanimi + + + Password + Parool + + + Authentication error + Autentimise viga + + + Logon failed with given username and password. Please try again! + Sisselogimine nurjus antud kasutajanime ja parooliga. Palun proovi uuesti! + + + + AuthLogonPlugin + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Sisestatud kasutajanimi või parool on vale. Sisestage Veyon Configuratori abil kehtivad mandaadid või minge teisele autentimismeetodile. + + + Logon authentication + Sisselogimise autentimine + + + Logon + Välju + + + + AuthSimpleDialog + + Veyon Logon + Veyoni sisselogimine + + + Please enter the Veyon password: + Sisestage Veyoni parool: + + + Authentication error + Autentimise viga + + + Logon failed with given password. Please try again! + Sisselogimine nurjus antud parooliga. Palun proovi uuesti! + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + Komplektis olev parool on vale. Sisestage Veyon Configuratori abil õige parool või lülituge teisele autentimismeetodile. + + + Simple password authentication + Lihtne parooli autentimine + + + Simple password + Lihtne parool + + + + AuthenticationPage + + Authentication is set up properly on this computer. + Autentimine on selles arvutis õigesti seadistatud. + + + + AuthenticationPageTab + + Enabled + Lubatud + + + Test + Test + + + + BuiltinDirectoryConfiguration + + Builtin directory + Sisseehitatud kataloog + + + + BuiltinDirectoryConfigurationPage + + Computers + Arvutid + + + Name + Nimi + + + Host address/IP + Seadme aadress/IP + + + MAC address + MAC aadress + + + Add new computer + Lisa arvuti + + + Remove selected computer + Eemalda valitud arvutid + + + New computer + Uus arvuti + + + Builtin directory + Sisseehitatud kataloog + + + Locations + Asukohad + + + Add new location + Uus asukoht + + + Remove selected location + Eemalda valitud asukohad + + + New location + Uus asukoht + + + Directory name + Kataloogi nimi + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + CSV -failide importimine on võimalik käsurealiidese kaudu. Lisateabe saamiseks vaadake <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">veebipõhist dokumentatsiooni</a>. + + + + BuiltinDirectoryPlugin + + Show help for specific command + Näita valitud käsu abi + + + Import objects from given file + Objektide importimine antud failist + + + Export objects to given file + Objektide eksportimine antud failist + + + Invalid type specified. Valid values are "%1" or "%2". + Määratud kehtetu tüüp. Kehtivad väärtused on "%1" või "%2". + + + Type + Tüüp + + + Name + Nimi + + + Host address + Seadme aadress + + + MAC address + MAC aadress + + + Specified object not found. + Määratud objekti ei leia. + + + File "%1" does not exist! + Faili "%1" ei ole! + + + Can't open file "%1" for reading! + Ei saa avada faili "%1" lugemiseks! + + + Unknown argument "%1". + Tundmatu argument "%1". + + + Computer "%1" (host address: "%2" MAC address: "%3") + Arvuti "%1" (IP aadress: "%2" MAC aadress: "%3") + + + Unclassified object "%1" with ID "%2" + Klassifitseerimata objekt "%1" ID-ga "%2" + + + None + Puudub + + + Computer + Arvuti + + + Root + Juur + + + Invalid + Kehtetu + + + Error while parsing line %1. + Viga rea %1 lahendamisel. + + + Network object directory which stores objects in local configuration + Võrguobjektide kataloog, mis salvestab objekte kohalikus konfiguratsioonis + + + Commands for managing the builtin network object directory + Käsud sisseehitatud võrguobjektide kataloogi haldamiseks + + + No format string or regular expression specified! + Vormingustringi ega regulaaravaldist pole määratud! + + + Can't open file "%1" for writing! + Faili "%1" ei saa kirjutamiseks avada! + + + No format string specified! + Vormingustringi pole määratud! + + + Object UUID + Objekti UUID + + + Parent UUID + Vanema UUID + + + Add a location or computer + Lisage asukoht või arvuti + + + Clear all locations and computers + Kustutage kõik asukohad ja arvutid + + + Dump all or individual locations and computers + Kõigi või üksikute asukohtade ja arvutite ladustamine + + + List all locations and computers + Vaata kõiki asukohti ja arvuteid + + + Remove a location or computer + Eemaldage asukoht või arvuti + + + Location "%1" + Asukoht "%1" + + + Builtin (computers and locations in local configuration) + Sissemised (arvutid ja asukohad kohalikus konfiguratsioonis) + + + Location + Asukoht + + + FILE + FAIL + + + LOCATION + ASUKOHT + + + FORMAT-STRING-WITH-PLACEHOLDERS + VORMING-STRING-KOHALIKEGA + + + REGULAR-EXPRESSION-WITH-PLACEHOLDER + REGULAARAVALDISE kohatäide + + + Imports objects from the specified text file using the given format string or regular expression containing one or multiple placeholders. Valid placeholders are: %1 + Impordib objekte määratud tekstifailist, kasutades antud vormingu stringi või regulaaravaldist, mis sisaldab ühte või mitut kohahoidjat. Kehtivad kohatäited on: %1 + + + Import simple CSV file to a single room + Importige lihtne CSV-fail ühte ruumi + + + Import CSV file with location name in first column + Importige CSV-fail, mille esimeses veerus on asukoha nimi + + + Import text file with with key/value pairs using regular expressions + Tekstifaili import koos võtme / väärtuse paaridega, kasutades regulaaravaldisi + + + Import arbitrarily formatted data + Importige suvaliselt vormindatud andmeid + + + Exports objects to the specified text file using the given format string containing one or multiple placeholders. Valid placeholders are: %1 + Ekspordib objektid määratud tekstifaili, kasutades antud vormingustringi, mis sisaldab ühte või mitut kohahoidjat. Kehtivad kohatäited on: %1 + + + Export all objects to a CSV file + Eksportige kõik objektid CSV-faili + + + Export all computers in a specific location to a CSV file + Eksportige kõik kindlas asukohas olevad arvutid CSV-faili + + + TYPE + TÜÜP + + + NAME + NIMI + + + PARENT + VANEM + + + Adds an object where %1 can be one of "%2" or "%3". %4 can be specified by name or UUID. + Lisab objekti, kus %1 võib olla üks "%2" või "%3". %4 saab määrata nime või UUID-i järgi. + + + Add a room + Lisa ruum + + + Add a computer to room %1 + Lisa arvuti ruumi %1 + + + OBJECT + OBJEKT + + + Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. + Eemaldab määratud objekti kataloogist. %1 saab määrata nime või UUID-i järgi. Asukoha eemaldamine eemaldab ka kõik seotud arvutid. + + + Remove a computer by name + Eemaldage arvuti nime järgi + + + Remove an object by UUID + Eemaldage objekt UUID järgi + + + "Room 01" + "Ruum 01" + + + "Computer 01" + "Arvuti 01" + + + HOST ADDRESS + IP AADRESS + + + MAC ADDRESS + MAC AADRESS + + + The specified command does not exist or no help is available for it. + Määratud käsku pole olemas või selle jaoks pole abi saadaval. + + + Location "%1" not found. + Asukohta "%1" ei leitud. + + + + BuiltinUltraVncServer + + Builtin VNC server (UltraVNC) + Sisemine VNC server (UltraVNC) + + + + BuiltinX11VncServer + + Builtin VNC server (x11vnc) + Sisemine VNC server (x11vnc) + + + + ComputerControlListModel + + Active features: %1 + Aktiivsed funktsioonid: %1 + + + Online and connected + Veebis ja ühendatud + + + Establishing connection + Ühenduse loomine + + + Computer offline or switched off + Arvuti on võrguühenduseta või välja lülitatud + + + Authentication failed or access denied + Autentimine nurjus või juurdepääs keelati + + + Disconnected + Ühendus katkestatud + + + No user logged on + Ükski kasutaja pole sisse loginud + + + Logged on user: %1 + Sisseloginud kasutaja: %1 + + + Location: %1 + Asukoht: %1 + + + [no user] + [ükski kasutaja] + + + Veyon Server unreachable or not running + Veyon Server pole kättesaadav või ei tööta + + + Name: %1 + Nimi: %1 + + + Hostname: %1 + + + + unknown + tundmatu + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + + + + ComputerControlServer + + %1 Service %2 at %3:%4 + %1 Teenus %2 kohas %3:%4 + + + Authentication error + Autentimise viga + + + Remote access + Kaugjuurdepääs + + + User "%1" at host "%2" is now accessing this computer. + Kasutaja "%1" hostis "%2" pääseb nüüd sellele arvutile ligi. + + + User "%1" at host "%2" attempted to access this computer but could not authenticate successfully. + Kasutaja "%1" hostis "%2" üritas sellele arvutile juurde pääseda, kuid ei suutnud edukalt autentida. + + + Access control error + Juurdepääsu viga + + + User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + Kasutaja "%1" hostis "%2" üritas sellele arvutile juurde pääseda, kuid on juurdepääsu seadete tõttu blokeeritud. + + + Active connections: + Aktiivsed ühendused: + + + + ComputerGroupSelector + + Group %1 + Grupp %1 + + + + ComputerManager + + User + Kasutaja + + + Missing network object directory plugin + Võrguobjektide kataloogi pistikprogramm puudub + + + No default network object directory plugin was found. Please check your installation or configure a different network object directory backend via %1 Configurator. + Vaikevõrguobjektide kataloogi pistikprogrammi ei leitud. Kontrollige installimist või konfigureerige %1 konfiguraatori kaudu mõni muu võrguobjektide kataloogi taustaprogramm. + + + Location detection failed + Asukoha tuvastamine nurjus + + + Computer name;Hostname;User + Arvuti nimi;Hostinimi;Kasutaja + + + Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + Selle arvuti asukohta ei õnnestunud kindlaks teha. See viitab probleemile süsteemi konfiguratsioonis. Kõik asukohad kuvatakse selle asemel arvuti valimise paneelil. + + + Logged in since + Sisse logitud alates + + + %1 days + %1 päeva + + + 1 day + 1 päev + + + + ComputerMonitoring + + Computers + Arvutid + + + Search users and computers + Otsige kasutajaid ja arvuteid + + + Select all + Vali kõik + + + Unselect all + Tühista kõigi valik + + + Add to group + Lisa grupp + + + Remove from group + Eemalda grupist + + + + ComputerSelectPanel + + Computer search + Arvuti otsing + + + Add location + Lisa asukoht + + + Save computer/user list + Salvesta arvuti/kasutajate loend + + + Select output filename + Vali väljundfaili nimi + + + CSV files (*.csv) + CSV failid (*.csv) + + + File error + Vigane fail + + + Could not write the computer and users list to %1! Please check the file access permissions. + Arvutit ja kasutajate loendi %1 kirjutamine nurjus! Kontrollige failidele juurdepääsu õigusi. + + + Search computers + Otsige arvuteid + + + + ConfigCommands + + Clear system-wide Veyon configuration + Tühi kogu süsteemi hõlmav Veyoni konfiguratsioon + + + List all configuration keys and values + Loetlege kõik konfiguratsioonivõtmed ja väärtused + + + Import configuration from given file + Impordi konfiguratsioon antud failist + + + Export configuration to given file + Ekspordi konfiguratsioon antud faili + + + Read and output configuration value for given key + Loe ja väljasta antud võtme konfiguratsiooni väärtus + + + Write given value to given configuration key + Kirjutage etteantud väärtus antud konfiguratsioonivõtmele + + + Unset (remove) given configuration key + Tühjendage (eemaldage) antud konfiguratsioonivõti + + + Upgrade and save configuration of program and plugins + Uuendage ja salvestage programmi ja pistikprogrammide konfiguratsioon + + + Please specify an existing configuration file to import. + Palun määrake imporditav olemasolev konfiguratsioonifail. + + + Configuration file is not readable! + Konfiguratsioonifail pole loetav! + + + Please specify a valid filename for the configuration export. + Palun määrake konfiguratsiooni eksportimiseks kehtiv failinimi. + + + Output file is not writable! + Väljundfaili ei saa kirjutada! + + + Output directory is not writable! + Väljundkausta ei saa kirjutada! + + + Please specify a valid key. + Palun määrake kehtiv võti. + + + Specified key does not exist in current configuration! + Määratud võtit pole praeguses konfiguratsioonis olemas! + + + Please specify a valid value. + Palun määrake kehtiv väärtus. + + + Configure Veyon at command line + Seadistage Veyon käsureal + + + Commands for managing the configuration of Veyon + Käsud Veyoni konfiguratsiooni haldamiseks + + + + ConfigurationManager + + Could not modify the autostart property for the %1 Service. + %1 teenuse automaatse käivitamise atribuuti ei saanud muuta. + + + Could not configure the firewall configuration for the %1 Server. + %1 serveri tulemüüri konfiguratsiooni ei õnnestunud konfigureerida. + + + Could not configure the firewall configuration for the %1 Worker. + %1 töötaja tulemüüri konfiguratsiooni ei õnnestunud konfigureerida. + + + Configuration is not writable. Please check your permissions! + Konfiguratsiooni ei saa kirjutada. Palun kontrollige oma õigusi! + + + Could not apply platform-specific configuration settings. + Platvormispetsiifilisi konfiguratsiooniseadeid ei saanud rakendada. + + + Could not configure the firewall configuration for the %1 Service. + %1 teenuse tulemüüri konfiguratsiooni ei õnnestunud seadistada. + + + + DemoClient + + %1 Demo + %1 Demo + + + + DemoConfigurationPage + + Demo server + Demo server + + + Tunables + Häälestatavad + + + ms + ms + + + Key frame interval + Võtmekaadri intervall + + + Memory limit + Mälupiirang + + + MB + MB + + + Update interval + Värskendamise intervall + + + s + s + + + Slow down thumbnail updates while demo is running + Demo töötamise ajal pidurdage pisipiltide värskendusi + + + Bandwidth limit + Ribalaiuse piirang + + + MB/s + MB/s + + + + DemoFeaturePlugin + + Stop demo + Peata demo + + + Window demo + Akna demo + + + Give a demonstration by screen broadcasting + Andke juhiseid ekraanil edastamise kaudu + + + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Selles režiimis kuvatakse teie ekraan aknas kõigis arvutites. Kasutajad saavad vajadusel üle minna teistele akendele. + + + Demo + Demo + + + Share your screen or allow a user to share his screen with other users. + Jagage oma ekraani või lubage kasutajal oma ekraani teiste kasutajatega jagada. + + + Full screen demo + Täisekraaniga demo + + + Share your own screen in fullscreen mode + Jagage oma ekraani täisekraanirežiimis + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + Selles režiimis kuvatakse teie ekraani täisekraanirežiimis kõikides arvutites, kui kasutajate sisendseadmed on lukus. + + + Share your own screen in a window + Jagage oma ekraani aknas + + + Share selected user's screen in fullscreen mode + Jagage valitud kasutaja ekraani täisekraanrežiimis + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + Selles režiimis kuvatakse valitud kasutaja ekraan täisekraani režiimis kõigis arvutites, kui kasutajate sisendseadmed on lukus. + + + Share selected user's screen in a window + Jaga valitud kasutaja ekraani aknas + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + Selles režiimis kuvatakse valitud arvuti ekraan kõigi arvutite aknas. Kasutajad saavad vajadusel üle minna teistele akendele. + + + Please select a user screen to share. + Valige jagamiseks kasutajaekraan. + + + Please select only one user screen to share. + Valige jagamiseks ainult üks kasutajaekraan. + + + All screens + Kõik ekraanid + + + + DesktopAccessDialog + + Desktop access dialog + Töölaua juurdepääsu dialoog + + + Confirm desktop access + Kinnitage töölauale juurdepääs + + + Never for this session + Mitte kunagi selle seansi jaoks + + + Always for this session + Alati selle sessiooni jaoks + + + The user %1 at computer %2 wants to access your desktop. Do you want to grant access? + Kasutaja %1 arvutis%2 soovib teie töölauale juurde pääseda. Kas soovite lubada juurdepääsu? + + + + DesktopServicesConfigurationPage + + Name + Nimi + + + Path + Rada + + + Predefined websites + Eelmääratud veebilehed + + + Remove selected website + Eemalda valitud veebileht + + + URL + URL aadress + + + New website + Uus veebileht + + + Applications & websites + Rakendused ja veebisaidid + + + Predefined applications + Eelmääratud rakendused + + + Add new application + Lisa uus rakendus + + + Remove selected application + Eemalda valitud rakendus + + + Add new website + Lisage uus veebisait + + + New application + Uus rakendus + + + + DesktopServicesFeaturePlugin + + Open website + Weebilehe avamine + + + Click this button to open a website on all computers. + Kõigil arvutitel veebisaidi avamiseks klõpsake seda nuppu. + + + Open website "%1" + Avage veebileht "%1" + + + Custom website + Kohandatud veebileht + + + Start application + Käivita rakendus + + + Click this button to start an application on all computers. + Rakenduse käivitamiseks kõikides arvutites klõpsake seda nuppu. + + + Start application "%1" + Käivitage rakendus "%1" + + + Custom application + Kohandatud rakendus + + + Start apps and open websites in user sessions + Käivitage rakendusi ja avage veebisaite kasutajaseanssidel + + + + DocumentationFigureCreator + + Teacher + Õpetaja + + + Room %1 + Ruum %1 + + + Please complete all tasks within the next 5 minutes. + Palun lõpetage kõik ülesanded järgmise 5 minuti jooksul. + + + Custom website + Kohandatud veebileht + + + Open file manager + Avage failihaldur + + + Start learning tool + Käivitage õppevahend + + + Play tutorial video + Esitage õppevideot + + + Handout + Jaotusmaterjal + + + Texts to read + Loetavad tekstid + + + generic-student-user + üldine-õpilane-kasutaja + + + Custom application + Kohandatud rakendus + + + + ExternalVncServer + + External VNC server + Väline VNC-server + + + + ExternalVncServerConfigurationWidget + + External VNC server configuration + Välise VNC-serveri konfiguratsioon + + + Port: + Port: + + + Password: + Parool: + + + + FeatureCommands + + List names of all available features + Loetlege kõigi saadaolevate funktsioonide nimed + + + Show table with details of all available features + Kuva tabel kõigi saadaolevate funktsioonide üksikasjadega + + + Start a feature on a remote host + Käivitage funktsioon kaughostis + + + Stop a feature on a remote host + Funktsiooni peatamine kaughostis + + + Please specify the command to display help for. + Palun määrake käsk abi kuvamiseks. + + + Displays a list with the names of all available features. + Kuvab loendi kõigi saadaolevate funktsioonide nimedega. + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + Kuvab tabeli üksikasjaliku teabega kõigi saadaolevate funktsioonide kohta. See teave sisaldab kirjeldust, UID-d, vastavat funktsiooni pakkuva pistikprogrammi nime ja mõningaid muid juurutamisega seotud üksikasju. + + + HOST ADDRESS + IP AADRESS + + + FEATURE + Tunnusjoon + + + ARGUMENTS + ARGUMENTID + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + Käivitab määratud funktsiooni määratud hostis, luues ühenduse kaugtöötava Veyoni serveriga. Funktsiooni saab määrata nime või UID-ga. Kõigi saadaolevate funktsioonide vaatamiseks kasutage käsku ``show``. Olenevalt funktsioonist tuleb määrata täiendavad argumendid (nt kuvatav tekstsõnum), mis on kodeeritud ühe JSON-stringina. Lisateabe saamiseks vaadake arendaja dokumentatsiooni + + + Lock the screen + Lukustage ekraan + + + Display a text message + Tekstisõnumi kuvamine + + + Test message + Testsõnum + + + Start an application + Käivitage rakendus + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + Peatab määratud funktsiooni määratud hostis, luues ühenduse kaugtöötava Veyoni serveriga. Funktsiooni saab määrata nime või UID-ga. Kõigi saadaolevate funktsioonide vaatamiseks kasutage käsku ``show``. + + + Unlock the screen + Avage ekraan + + + The specified command does not exist or no help is available for it. + Määratud käsku pole olemas või selle jaoks pole abi saadaval. + + + Name + Nimi + + + Description + Kirjeldus + + + Master + Master + + + Service + Teenus + + + Worker + Tööline + + + UID + UID + + + Plugin + Pistikprogramm + + + Invalid feature name or UID specified + Määratud on kehtetu objekti nimi või UID + + + Error parsing the JSON-encoded arguments: %1 + Viga JSON-kodeeritud argumentide sõelumisel: %1 + + + Failed to initialize credentials + Mandaatide lähtestamine ebaõnnestus + + + Could not establish a connection to host %1 + Hostiga %1 ei õnnestunud ühendust luua + + + Failed to send feature control message to host %1 + Funktsiooni juhtsõnumi saatmine hostile %1 ebaõnnestus + + + Feature-related CLI operations + Funktsioonidega seotud CLI toimingud + + + Commands for controlling features + Funktsioonide juhtimise käsud + + + + FileTransferConfigurationPage + + File transfer + Faili edastamine + + + Directories + Kataloogid + + + Destination directory + Sihtkataloog + + + Default source directory + Vaikeallika kataloog + + + Options + Valikud + + + Remember last source directory + Pidage meeles viimane lähtekataloog + + + Create destination directory if it does not exist + Looge sihtkataloog, kui seda pole olemas + + + + FileTransferController + + Could not open file "%1" for reading! Please check your permissions! + Faili "%1" ei õnnestunud lugemiseks avada! Palun kontrollige oma õigusi! + + + + FileTransferDialog + + File transfer + Faili edastamine + + + Options + Valikud + + + Transfer only + Edasta vaid + + + Transfer and open file(s) with associated program + Faili(de) edastamine ja avamine seotud programmiga + + + Transfer and open destination folder + Sihtkausta teisaldamine ja avamine + + + Files + Failid + + + Start + Start + + + Overwrite existing files + Kirjutage olemasolevad failid üle + + + + FileTransferFileDialog + + Select one or more files to transfer + Valige üks või mitu edastatavat faili + + + + FileTransferPlugin + + File transfer + Faili edastamine + + + Click this button to transfer files from your computer to all computers. + Klõpsake seda nuppu, et faile arvutist kõikidesse arvutitesse edastada. + + + Select one or more files to transfer + Valige üks või mitu edastatavat faili + + + Transfer files to remote computer + Failide edastamine kaugarvutisse + + + Received file "%1". + Vastuvõetud fail "%1". + + + Could not receive file "%1" as it already exists. + Faili "%1" ei saanud vastu võtta, kuna see on juba olemas. + + + Could not receive file "%1" as it could not be opened for writing! + Faili "%1" ei saanud vastu võtta, kuna seda ei saanud kirjutamiseks avada! + + + + GeneralConfigurationPage + + User interface + Kasutajaliides + + + Language: + Keel: + + + Use system language setting + Kasutage süsteemi keele seadistust + + + Veyon + Veyon + + + Logging + Logimine + + + Log file directory + Logifailide kataloog + + + Log level + Logi tase + + + Nothing + Ei midagi + + + Only critical messages + Ainult kriitilised sõnumid + + + Errors and critical messages + Vead ja kriitilised teated + + + Warnings and errors + Hoiatused ja vead + + + Information, warnings and errors + Teave, hoiatused ja vead + + + Debug messages and everything else + Siluge sõnumeid ja kõike muud + + + Limit log file size + Logi faili suuruse piirang + + + Clear all log files + Kustutage kõik logifailid + + + Log to standard error output + Logige standardvea väljundisse + + + %1 service + %1 teenus + + + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + Logifailide eemaldamiseks tuleb teenus %1 ajutiselt peatada. Kas jätkata? + + + Log files cleared + Logifailid on kustutatud + + + All log files were cleared successfully. + Kõik logifailid kustutati edukalt. + + + Error + Viga + + + Could not remove all log files. + Kõiki logifaile ei saanud eemaldada. + + + MB + MB + + + Rotate log files + Rotate log files + + + x + x + + + Write to logging system of operating system + Kirjutage operatsioonisüsteemi logimissüsteemi + + + TLS configuration + TLS konfiguratsioon + + + Use certificate authority for TLS connections + Kasutage TLS -ühenduste jaoks sertifikaati + + + CA certificate file + CA sertifikaadi fail + + + ... + ... + + + Host certificate file + Hosti sertifikaadi fail + + + Host private key file + Hosti privaatvõtme fail + + + Style: + Stiil: + + + Native + Kohalik + + + Color scheme: + + + + Light + + + + Dark + + + + User groups + Kasutajagrupid + + + Backend: + Taustaprogramm: + + + Include user groups from domain + Kaasake domeeni kasutajarühmad + + + Missing user groups backend + Puuduvad kasutajagruppide taustaprogrammid + + + No user groups plugin was found. Please check your installation! + Ühtegi kasutajarühmade pistikprogrammi ei leitud. Palun kontrolli oma paigaldust! + + + + HeadlessVncServer + + Headless VNC server + Peata VNC-server + + + + LdapBrowseDialog + + Browse LDAP + Sirvige LDAP-d + + + + LdapClient + + LDAP error description: %1 + LDAP-tõrke kirjeldus: %1 + + + + LdapConfiguration + + LDAP connection failed + LDAP-ühendus ebaõnnestus + + + Could not connect to the LDAP server. Please check the server parameters. + +%1 + LDAP-serveriga ei saanud ühendust luua. Palun kontrollige serveri parameetreid. + +%1 + + + LDAP bind failed + LDAP-sidumine nurjus + + + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + LDAP-serveriga ei saanud siduda. Kontrollige serveri parameetreid ja siduge mandaadid. + +%1 + + + LDAP bind successful + LDAP-sidumine õnnestus + + + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + LDAP-serveriga ühenduse loomine ja LDAP-sidumine. LDAP põhiseaded on õigesti konfigureeritud. + + + LDAP base DN test failed + LDAP baasi DN test ebaõnnestus + + + Could not query the configured base DN. Please check the base DN parameter. + +%1 + Konfigureeritud baasi DN-i ei saanud pärida. Kontrollige põhiparameetrit DN. + +%1 + + + LDAP base DN test successful + LDAP baasi DN test õnnestus + + + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + LDAP-i baasi DN-i kohta on edukalt päringuid tehtud. Leiti järgmised kirjed: + +%1 + + + LDAP naming context test failed + LDAP-i nimetamise kontekstitest ebaõnnestus + + + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + Põhi-DN-i ei saanud päringukontekstide kaudu pärida. Palun kontrollige nimetamise konteksti atribuudi parameetrit. + +%1 + + + LDAP naming context test successful + LDAP-i nimetamise kontekstitest õnnestus + + + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + LDAP-i nimetamise kontekst on edukalt päritud. Leiti järgmine alus DN: +%1 + + + user tree + kasutajapuu + + + User tree + Kasutajapuu + + + group tree + grupipuu + + + Group tree + Grupipuu + + + computer tree + arvutipuu + + + Computer tree + Arvutipuu + + + computer group tree + arvuti grupipuu + + + Computer group tree + Arvuti grupipuu + + + user objects + kasutaja objektid + + + User login name attribute + Kasutaja sisselogimise nime atribuut + + + group members + grupi liikmed + + + Group member attribute + Grupi liikme atribuut + + + Group not found + Gruppi ei leidnud + + + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Gruppi nimega "%1" ei leitud. Kontrollige grupi nime või grupipuu parameetrit. + + + computer objects + arvuti objektid + + + Computer display name attribute + Arvuti kuvanime atribuut + + + Invalid hostname + Tundmatu hosti nimi + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Konfigureerisite arvuti hostinimed salvestamiseks täielikult kvalifitseeritud domeeninimedena (FQDN), kuid sisestasite hostinime ilma domeenita. + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Konfigureerisite arvuti hostinimed salvestamiseks lihtsate hostinimedena ilma domeeninimeta, kuid sisestasite hostinime koos domeeninime osaga. + + + Computer hostname attribute + Arvuti hosti nime atribuut + + + computer MAC addresses + arvuti MAC-aadressid + + + Computer MAC address attribute + Arvuti MAC-aadressi atribuut + + + computer locations + arvuti asukohad + + + Computer location attribute + Arvuti asukoha atribuut + + + Location name attribute + Asukoha nime atribuut + + + users + kasutajad + + + user groups + kasutaja grupid + + + computers + arvutid + + + computer groups + arvuti grupid + + + computer containers + arvutikonteinerid + + + groups of user + kasutaja grupid + + + User not found + Kasutajat ei leidnud + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + Kasutajat nimega "%1" ei leitud. Kontrollige kasutajanime või kasutajapuu parameetrit. + + + groups of computer + arvuti grupid + + + Computer not found + Arvutit ei leidnud + + + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Ei leidnud arvutit hostinimega "%1". Palun kontrolli hostinime või arvutipuu parameetrit. + + + Hostname lookup failed + Hostinime otsimine nurjus + + + Could not lookup hostname for IP address %1. Please check your DNS server settings. + IP-aadressi %1 hostinime otsimine nurjus. Palun kontrollige oma DNS-serveri seadeid. + + + location entries + asukohtade kirjed + + + Computer groups filter + Arvutirühmade filter + + + Computer locations identification + Asukoha nime atribuut + + + Filter for computer groups + Filter arvutigruppide jaoks + + + Invalid test value + Kehtetu testi väärtus + + + An empty or invalid value has been supplied for this test. + Selle testi jaoks on sisestatud tühi või vale väärtus. + + + LDAP %1 test failed + LDAP %1 test ebaõnnestus + + + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + Konfigureeritud %1. kirjeid ei saa pärida. Kontrollige parameetrit "%2". + +%3 + + + LDAP %1 test successful + LDAP %1 test õnnestus + + + The %1 has been queried successfully and %2 entries were found. + %1 on edukalt päritud ja leitud %2 kirjet. + + + LDAP test failed + LDAP-test ebaõnnestus + + + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + %1. päringu esitamine nurjus. Kontrollige parameetr(eid) %2 ja sisestage olemasoleva objekti nimi. + +%3 + + + and + ning + + + LDAP test successful + LDAP-test õnnestus + + + %1 %2 have been queried successfully: + +%3 + %1 %2 on edukalt päritud: + +%3 + + + LDAP filter test failed + LDAP-filtri test ebaõnnestus + + + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 + Konfigureeritud filtrit kasutades ei saa üheltki %1 päringut teha. Palun kontrollige, kas LDAP-filtris pole %1. + +%2 + + + LDAP filter test successful + LDAP-filtri test õnnestus + + + %1 %2 have been queried successfully using the configured filter. + %1 %2 on konfigureeritud filtri abil edukalt päritud. + + + LDAP directory + LDAP kataloog + + + + LdapConfigurationPage + + Basic settings + Üldised seaded + + + General + Üldine + + + LDAP server and port + LDAP server ja port + + + Bind DN + Siduv DN + + + Bind password + Siduge parool + + + Anonymous bind + Anonüümne side + + + Use bind credentials + Kasutage sidumismandaate + + + Base DN + Baas DN + + + Fixed base DN + Fikseeritud baas DN + + + e.g. dc=example,dc=org + näit. dc=example,dc=org + + + Discover base DN by naming context + Avastage baasi DN, nimetades konteksti + + + e.g. namingContexts or defaultNamingContext + näit. namingContexts või defaultNamingContext + + + Environment settings + Keskkonna seaded + + + Object trees + Objektipuud + + + Computer tree + Arvutipuu + + + e.g. OU=Groups + näit. OU=Grupid + + + User tree + Kasutajapuu + + + e.g. OU=Users + näit. OU=kasutajad + + + e.g. OU=Computers + näit. OU=arvutid + + + Group tree + Grupipuu + + + Perform recursive search operations in object trees + Tehke rekursiivsed otsinguoperatsioonid objektipuudes + + + Object attributes + Objekti atribuudid + + + e.g. hwAddress + näit. riistvara aadress + + + e.g. member or memberUid + näit. liige või liikmeUiD + + + e.g. dNSHostName + näit. dNSHostName + + + Computer MAC address attribute + Arvuti MAC-aadressi atribuut + + + Group member attribute + Grupi liikme atribuut + + + e.g. uid or sAMAccountName + näit. uid või sAMAccountName + + + Advanced settings + Täpsemad seaded + + + Optional object filters + Valikulised objektifiltrid + + + Filter for user groups + Filter kasutajagruppide jaoks + + + Filter for users + Kasutajatele mõeldud filter + + + Filter for computer groups + Filter arvutigruppide jaoks + + + Group member identification + Grupi liikme identifitseerimine + + + Distinguished name (Samba/AD) + Eraldatud nimi (Samba/AD) + + + List all groups of a user + Loetlege kõik kasutaja grupid + + + List all groups of a computer + Loetlege kõik arvuti grupid + + + Get computer object by IP address + Hankige arvutiobjekt IP-aadressi järgi + + + Enter username + Sisestage kasutajanimi + + + Please enter a user login name (wildcards allowed) which to query: + Sisestage päringuks kasutajanimi (lubatud on metamärgid): + + + Enter group name + Sisestage grupi nimi + + + Please enter a group name whose members to query: + Sisestage grupi nimi, mille liikmed päringuid teevad: + + + Enter computer name + Sisestage arvuti nimi + + + Enter computer DN + Sisestage arvuti DN + + + Please enter the DN of a computer whose MAC address to query: + Sisestage selle arvuti DN, mille MAC-aadress päringuks: + + + Please enter a user login name whose group memberships to query: + Sisestage sisselogimiseks kasutajanimi, kelle grupi liikmesused päringu esitamiseks: + + + Enter computer IP address + Sisestage arvuti IP aadress + + + Please enter a computer IP address which to resolve to an computer object: + Sisestage arvuti IP-aadress arvutiobjekti lahendamiseks: + + + (only if different from group tree) + (ainult siis, kui see erineb grupipuust) + + + Computer group tree + Arvuti grupipuu + + + Filter for computers + Filter arvutite jaoks + + + e.g. room or computerLab + näit. ruum või arvutiLab + + + Integration tests + integratsioonitestid + + + Computer groups + Arvutigrupid + + + e.g. name or description + näit. nimi või kirjeldus + + + Filter for computer containers + Filter arvutikonteinerite jaoks + + + Computer containers or OUs + Arvutikonteinerid või OU-d + + + Connection security + Ühenduse turvalisus + + + TLS certificate verification + TLS-sertifikaadi kontroll + + + System defaults + Süsteemi vaikesätted + + + Never (insecure!) + Mitte kunagi (ebakindel!) + + + Custom CA certificate file + Kohandatud CA-sertifikaadi fail + + + None + Puudub + + + TLS + TLS + + + SSL + SSL + + + e.g. (objectClass=computer) + näit. (objectClass=arvuti) + + + e.g. (objectClass=group) + näit. (objectClass=grupp) + + + e.g. (objectClass=person) + näit. (objectClass=person) + + + e.g. (objectClass=room) or (objectClass=computerLab) + näit. (objectClass=ruum) või (objectClass=arvutiLab) + + + e.g. (objectClass=container) or (objectClass=organizationalUnit) + näit. (objectClass=konteiner) või (objectClass=organizationalUnit) + + + Certificate files (*.pem) + Sertifikaadifailid (*.pem) + + + Encryption protocol + Krüptimisprotokoll + + + Computer location attribute + Arvuti asukoha atribuut + + + Computer display name attribute + Arvuti kuvanime atribuut + + + Location name attribute + Asukoha nime atribuut + + + e.g. cn or displayName + näit. cn või displayName + + + Computer locations identification + Asukoha nime atribuut + + + Identify computer locations (e.g. rooms) via: + Tehke kindlaks arvuti asukohad (nt ruumid): + + + Location attribute in computer objects + Asukoha atribuut arvutiobjektides + + + List all entries of a location + Loetlege kõik asukoha kirjed + + + List all locations + Loetlege kõik asukohad + + + Enter computer display name + Sisestage arvuti kuvatav nimi + + + Please enter a computer display name to query: + Sisestage arvuti kuvatav nimi + + + Enter computer location name + Sisestage arvuti asukoha nimi + + + Please enter the name of a computer location (wildcards allowed): + Sisestage arvuti asukoha nimi (metamärgid on lubatud): + + + Enter location name + Sisestage asukoha nimi + + + Please enter the name of a location whose entries to query: + Sisestage asukoha nimi, mille sisestuste kohta päringu teha: + + + Browse + Sirvi + + + Test + Test + + + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Hosti nimed, mis on salvestatud täielikult kvalifitseeritud domeeninimedena (FQDN, nt myhost.example.org) + + + Computer hostname attribute + Arvuti hosti nime atribuut + + + Please enter a computer hostname to query: + Sisestage päringuks arvuti hostinimi: + + + Enter hostname + Sisestage hosti nimi + + + Please enter a computer hostname whose group memberships to query: + Sisestage arvuti hostinimi, mille rühma liikmesused päringu esitamiseks: + + + User login name attribute + Kasutaja sisselogimise nime atribuut + + + Configured attribute for user login name or computer hostname (OpenLDAP) + Konfigureeritud atribuut kasutaja sisselogimisnimele või arvuti hostinimele (OpenLDAP) + + + Directory name + Kataloogi nimi + + + Query options + Päringu valikud + + + Query nested user groups (supported by AD only) + Pesastatud kasutajarühmade päring (toetab ainult AD) + + + Query timeout + Päringu ajalõpp + + + ms + ms + + + + LdapNetworkObjectDirectoryConfigurationPage + + LDAP + LDAP + + + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + Kasutage üldist LDAP-i konfiguratsioonilehte, et konfigureerida, kuidas LDAP-põhisest kataloogiteenusest asukohti ja arvuteid alla laadida. + + + + LdapPlugin + + Auto-configure the base DN via naming context + Alam-DN automaatne konfigureerimine nimekonteksti kaudu + + + Query objects from LDAP directory + Objektide pärimine LDAP-kataloogist + + + Show help about command + Näita abi käsu kohta + + + Commands for configuring and testing LDAP/AD integration + Käsud LDAP / AD integreerimise konfigureerimiseks ja testimiseks + + + Basic LDAP/AD support for Veyon + Põhiline LDAP/AD tugi Veyonile + + + %1 (load computers and locations from LDAP/AD) + %1 (laadige arvutid ja asukohad LDAP/AD-st) + + + %1 (load users and groups from LDAP/AD) + %1 (laadige kasutajad ja grupid LDAP/AD-st) + + + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Palun määrake kehtiv LDAP-URL järgides skeemi "ldap[s]://[user[:password]@]hostname[:port]" + + + No naming context attribute name given - falling back to configured value. + Nimetamise konteksti atribuudi nime pole antud - langeb tagasi konfigureeritud väärtuse juurde. + + + Could not query base DN. Please check your LDAP configuration. + DN-i päringu esitamine nurjus. Palun kontrollige oma LDAP konfiguratsiooni. + + + Configuring %1 as base DN and disabling naming context queries. + %1 konfigureerimine baas-DN-ks ja kontekstipäringute nimetamise keelamine. + + + Test binding to an LDAP server + Testi sidumine LDAP-serveriga + + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Sisestatud kasutajanimi või parool on vale. Sisestage Veyon Configuratori abil kehtivad mandaadid või minge teisele autentimismeetodile. + + + LDAP bind + LDAP sidumine + + + + LinuxPlatformConfigurationPage + + Linux + Linux + + + Custom PAM service for user authentication + Kasutaja autentimiseks kohandatud PAM-teenus + + + User authentication + Kasutaja autentimine + + + User sessions + Kasutaja seansid + + + Minimum session lifetime before server start + Minimaalne seansi eluiga enne serveri käivitamist + + + User login + Kasutaja sisselogimine + + + Login key sequence + Sisselogimisvõtmete järjestus + + + + LinuxPlatformPlugin + + Plugin implementing abstract functions for the Linux platform + Plugin, mis rakendab abstraktseid funktsioone Linuxi platvormile + + + + LocationDialog + + Select location + Vali asukoht + + + enter search filter... + sisesta otsingufilter ... + + + + MainToolBar + + Configuration + Konfiguratsioon + + + Show icons only + Kuva ainult ikoone + + + Disable tooltips + Keela tööriistavihjed + + + + MainWindow + + MainWindow + PeaAken + + + toolBar + Tööriistariba + + + General + Üldine + + + &File + &Fail + + + &Help + &Abi + + + &Quit + &Välju + + + Ctrl+Q + Ctrl+Q + + + Ctrl+S + Ctrl+S + + + L&oad settings from file + L&oe seaded failist + + + Ctrl+O + Ctrl+O + + + About Qt + Qt kohta + + + Configuration not writable + Konfiguratsiooni ei saa kirjutada + + + Load settings from file + Loe seaded failist + + + Save settings to file + Salvesta seaded faili + + + Unsaved settings + Salvestamata seaded + + + There are unsaved settings. Quit anyway? + Seal on salvestamata seadeid. Kas ikkagi lõpetada? + + + Veyon Configurator + Veyoni konfiguraator + + + Service + Teenus + + + Master + Master + + + Access control + Juurdepääsu juhtimine + + + About Veyon + Programmist Veyon + + + Auto + Auto + + + About + Programmist + + + %1 Configurator %2 + %1 Konfiguraator %2 + + + JSON files (*.json) + JSON failid (*.json) + + + The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. + Kohaliku konfiguratsiooni taustaprogramm teatas, et konfiguratsiooni ei saa kirjutada! Palun käivitage %1 konfiguraator suuremate õigustega. + + + Access denied + Juurdepääs keelatud + + + According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. + Kohaliku konfiguratsiooni kohaselt pole teil lubatud võrgus olevatele arvutitele juurde pääseda. Logige sisse teise kontoga või laske oma süsteemiadministraatoril kohalikku konfiguratsiooni kontrollida. + + + Screenshots + Ekraanipildid + + + Feature active + Funktsioon on aktiivne + + + The feature "%1" is still active. Please stop it before closing %2. + Funktsioon "%1" on endiselt aktiivne. Enne %2 sulgemist peatage see. + + + Reset configuration + Lähtesta konfiguratsioon + + + Do you really want to reset the local configuration and revert all settings to their defaults? + Kas soovite tõesti lähtestada kohaliku konfiguratsiooni ja taastada kõigi seadete vaikeväärtused? + + + Search users and computers + Otsige kasutajaid ja arvuteid + + + Align computers to grid + Joondage arvutid + + + %1 Configurator + %1 Konfiguraator + + + Insufficient privileges + Ebapiisavad privileegid + + + Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + Ei saanud alustada administraatoriõigustega. Veenduge, et teie töölaua keskkonda oleks installitud sudo-laadne programm! Programmi käivitatakse tavaliste kasutajaõigustega. + + + Only show powered on computers + Näita ainult töötavaid arvuteid + + + &Save settings to file + &Salvesta seaded faili + + + &View + &Vaade + + + &Standard + &Standard + + + &Advanced + &Edasijõudnud + + + Use custom computer arrangement + Kasutage kohandatud arvutikorraldust + + + Locations && computers + Asukohad && arvutid + + + Authentication + Autentimine + + + Adjust size of computer icons automatically + Kohandage arvuti ikoonide suurust automaatselt + + + Slideshow + Slaidiseanss + + + Spotlight + Tähelepanu keskpunktis + + + Veyon Master + Veyon Master + + + Locations & computers + Asukohad&arvutid + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + Kuva ainult arvutid, mille kasutajad on sisse logitud + + + Load computer positions + + + + Save computer positions + + + + + MasterConfigurationPage + + Directories + Kataloogid + + + User configuration + Kasutaja konfiguratsioon + + + Feature on computer double click: + Funktsioon arvutis topeltklõpsake: + + + Features + Funktsioonid + + + All features + Kõik funktsioonid + + + Disabled features + Keelatud funktsioonid + + + Screenshots + Ekraanipildid + + + <no feature> + <no feature> + + + Basic settings + Üldised seaded + + + Behaviour + Käitumine + + + Enforce selected mode for client computers + Valitud režiimi rakendamine klientarvutite jaoks + + + Hide local computer + Peida kohalik arvuti + + + Hide computer filter field + Peida arvuti filtri väli + + + Actions such as rebooting or powering down computers + Sellised toimingud nagu arvutite taaskäivitamine või väljalülitamine + + + User interface + Kasutajaliides + + + Background color + Taustavärv + + + Thumbnail update interval + Pisipiltide uuendamise sagedus + + + ms + ms + + + Program start + Käivita programm + + + Modes and features + Režiimid ja funktsioonid + + + User and computer name + Kasutaja ja arvuti nimi + + + Only user name + Vaid kasutaja nimi + + + Only last part of user name + + + + Only computer name + Vaid arvuti nimi + + + Computer thumbnail caption + Arvuti pisipiltide pealdis + + + Text color + Teksti värv + + + Sort order + Järjestamine + + + Computer and user name + Arvuti ja kasutajanimi + + + Computer locations + Arvuti asukoht + + + Show current location only + Kuva ainult praegune asukoht + + + Allow adding hidden locations manually + Luba peidetud asukohtade käsitsi lisamine + + + Hide empty locations + Peida tühjad asukohad + + + Show confirmation dialog for potentially unsafe actions + Kuva potentsiaalselt ohtlike toimingute kinnitusdialoog + + + Perform access control + Tehke juurdepääsu kontroll + + + Automatically select current location + Valige praegune asukoht automaatselt + + + Automatically open computer select panel + Avage arvuti valimispaneel automaatselt + + + Use modern user interface (experimental) + Kasuta kaasaegset kasutajaliidest (eksperimentaalne) + + + Thumbnail spacing + Pisipiltide vahe + + + px + px + + + Hide local session + Peida kohalik seanss + + + Auto + Auto + + + Thumbnail aspect ratio + Pisipildi kuvasuhe + + + Automatically adjust computer icon size + Reguleerige arvuti ikooni suurust automaatselt + + + Open feature windows on the same screen as the main window + Avage funktsiooniaknad peaaknaga samal ekraanil + + + Configuration templates + + + + Image quality in monitoring mode + Pildikvaliteet jälgimisrežiimis + + + Highest + Kõrgeim + + + High + Kõrge + + + Medium + Keskmine + + + Low + Madal + + + Lowest + Madalaim + + + Remote access image quality + Kaugjuurdepääsu pildikvaliteet + + + Advanced + + + + Computer name source + + + + Default + Vaikimisi + + + Host address + Seadme aadress + + + Session client address + Seansi kliendi aadress + + + Session client name + Seansi kliendi nimi + + + Session host name + + + + Session metadata + + + + Full name of user + Kasutaja täisnimi + + + User login name + Kasutaja sisselogimisnimi + + + Computer UID role + + + + Session meta data hash + + + + Always expand all locations + + + + Image quality + Pildikvaliteet + + + + MonitoringMode + + Monitoring + Jälgimine + + + Builtin monitoring mode + Sisemine jälgimisrežiim + + + This mode allows you to monitor all computers at one or more locations. + See režiim võimaldab teil jälgida kõiki arvuteid ühes või mitmes kohas. + + + Query application version of the server + Päring serveri rakenduse versioonist + + + Query active features + Aktiivsete funktsioonide päring + + + Query properties of remotely available screens + Pärige kaugkasutatavate ekraanide atribuute + + + + NestedNetworkObjectDirectory + + All directories + Kõik kataloogid + + + + NetworkObjectDirectoryConfigurationPage + + Update interval: + Värskenduse sagedus: + + + seconds + sekundit + + + + NetworkObjectDirectoryConfigurationPageTab + + Enabled + Lubatud + + + + NetworkObjectTreeModel + + Locations/Computers + Asukohad/Arvutid + + + + OpenWebsiteDialog + + Open website + Weebilehe avamine + + + e.g. Veyon + näit. Veyon + + + Remember and add to website menu + Pidage meeles ja lisage veebisaidi menüüsse + + + e.g. www.veyon.io + näit. www.veyon.io + + + Please enter the URL of the website to open: + Avamiseks sisestage palun veebisaidi URL: + + + Name: + Nimi: + + + Website name + Veebisaidi nimi + + + + PluginCommands + + List names of all installed plugins + Loetlege kõigi installitud pistikprogrammide nimed + + + Show table with details of all installed plugins + Kuva tabel kõigi installitud pistikprogrammide üksikasjadega + + + Name + Nimi + + + Description + Kirjeldus + + + Version + Versioon + + + UID + UID + + + Plugin-related CLI operations + Pistikprogrammidega seotud CLI-toimingud + + + Commands for managing plugins + Pistikprogrammide haldamise käsud + + + + PowerControlFeaturePlugin + + Power on + Lülita sisse + + + Click this button to power on all computers. This way you do not have to power on each computer by hand. + Kõigi arvutite sisselülitamiseks klõpsake seda nuppu. Nii ei pea te igat arvutit käsitsi sisse lülitama. + + + Reboot + Taaskäivitamine + + + Click this button to reboot all computers. + Kõigi arvutite taaskäivitamiseks klõpsake seda nuppu. + + + Power down + Lülita välja + + + Click this button to power down all computers. This way you do not have to power down each computer by hand. + Kõigi arvutite väljalülitamiseks klõpsake seda nuppu. Nii ei pea te iga arvutit käsitsi välja lülitama. + + + Power on/down or reboot a computer + Lülitage arvuti sisse / välja või taaskäivitage arvuti + + + Confirm reboot + Kinnitage taaskäivitamine + + + Confirm power down + Kinnitage väljalülitamine + + + Do you really want to reboot the selected computers? + Kas soovite tõesti valitud arvutid taaskäivitada? + + + Power on a computer via Wake-on-LAN (WOL) + Lülitage arvuti sisse Wake-on-LAN (WOL) kaudu + + + MAC ADDRESS + MAC AADRESS + + + This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. + See käsk edastab võrgus Wake-on-LAN (WOL) paketi, et antud MAC-aadressiga arvuti sisse lülitada. + + + Please specify the command to display help for! + Palun määrake käsk, mille jaoks abi kuvatakse! + + + Invalid MAC address specified! + Määratud on kehtetu MAC-aadress! + + + Commands for controlling power status of computers + Käsud arvutite toiteoleku kontrollimiseks + + + Power down now + Lülita kohe välja + + + Install updates and power down + Uuenda ja lülita välja + + + Power down after user confirmation + Lülita välja kasutaja nõustumisel + + + Power down after timeout + Lülita välja aja möödumisel + + + The computer was remotely requested to power down. Do you want to power down the computer now? + Arvuti paluti eemalt välja lülitada. Kas soovite arvuti kohe välja lülitada? + + + The computer will be powered down in %1 minutes, %2 seconds. + +Please save your work and close all programs. + Arvuti lülitatakse välja %1 minuti, %2 sekundi pärast. + +Salvestage oma töö ja sulgege kõik programmid. + + + Do you really want to reboot <b>ALL</b> computers? + Kas soovite tõesti taaskäivitada <b>KÕIK</b> arvutid? + + + Do you really want to power down <b>ALL</b> computers? + Kas soovite tõesti välja lülitada <b>KÕIK</b> arvutid? + + + Do you really want to power down the selected computers? + Kas soovite tõesti välja lülitada valitud arvutid? + + + + PowerDownTimeInputDialog + + Power down + Lülita välja + + + Please specify a timeout for powering down the selected computers: + Määrake valitud arvutite väljalülitamise aeg: + + + minutes + minutit + + + seconds + sekundit + + + + RemoteAccessFeaturePlugin + + Remote view + Kaugvaade + + + Open a remote view for a computer without interaction. + Avage arvuti kaugvaade ilma suhtlemiseta. + + + Remote control + Kaugjuurdepääs + + + Open a remote control window for a computer. + Avage arvuti kaughalduse aken. + + + Remote access + Kaugjuurdepääs + + + Remote view or control a computer + Kaugvaatamine või arvuti kaughaldus + + + Show help about command + Näita abi käsu kohta + + + Exchange clipboard contents + Vahetage lõikepuhvri sisu + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + Ühtegi arvutit pole valitud, nii et saate käsitsi juurdepääsuks sisestada arvuti hostinime või IP-aadressi: + + + + RemoteAccessPage + + Remote access: %1 + Kaugjuurdepääs: %1 + + + + RemoteAccessWidget + + %1 - %2 Remote Access + %1 - %2 Kaugjuurdepääs + + + %1 - %2 - %3 Remote Access + %1 - %2 - %3 Kaugjuurdepääs + + + + RemoteAccessWidgetToolBar + + View only + Ainult vaade + + + Remote control + Kaugjuurdepääs + + + Send shortcut + Saada otsetee + + + Fullscreen + Täisekraan + + + Window + Aken + + + Ctrl+Alt+Del + Ctrl+Alt+Del + + + Ctrl+Esc + Ctrl+Esc + + + Alt+Tab + Alt+Tab + + + Alt+F4 + Alt+F4 + + + Win+Tab + Win+Tab + + + Win + Win + + + Menu + Menüü + + + Alt+Ctrl+F1 + Alt+Ctrl+F1 + + + Connected. + Ühendatud + + + Screenshot + Ekraanipilt + + + Exit + Välju + + + Connecting... + Ühendamine... + + + Select screen + Valige ekraan + + + All screens + Kõik ekraanid + + + + ScreenLockFeaturePlugin + + Lock + Lukusta + + + Unlock + Lukusta lahti + + + Lock screen and input devices of a computer + Lukusta arvuti ekraan ja sisendseadmed + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + Kasutaja tähelepanu äratamiseks võite selle nupu abil tema arvutid lukustada. Selles režiimis on kõik sisendseadmed lukustatud ja ekraanid mustad. + + + Lock input devices + Lukusta sisendseadmed + + + Unlock input devices + Sisendseadmete avamine + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + Kasutaja tähelepanu äratamiseks võite selle nupu abil tema arvutid lukustada. Selles režiimis on kõik sisendseadmed lukustatud, kuid töölaud on endiselt nähtav. + + + + Screenshot + + unknown + tundmatu + + + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + Ekraanipilti ei õnnestunud teha, kuna kataloogi %1 pole olemas ja seda ei saa luua. + + + Screenshot + Ekraanipilt + + + Could not open screenshot file %1 for writing. + Ekraanipilti faili %1 ei saanud kirjutamiseks avada. + + + + ScreenshotFeaturePlugin + + Screenshot + Ekraanipilt + + + Use this function to take a screenshot of selected computers. + Selle funktsiooni abil saate valitud arvutitest ekraanipildi teha. + + + Screenshots taken + Tehtud ekraanipildid + + + Screenshot of %1 computer have been taken successfully. + %1 arvuti ekraanipilt on edukalt tehtud. + + + Take screenshots of computers and save them locally. + Tehke arvutitest ekraanipilte ja salvestage need lokaalselt. + + + + ScreenshotManagementPage + + Screenshots + Ekraanipildid + + + + ScreenshotManagementPanel + + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + Kõik teie tehtud ekraanipildid on loetletud siin. Ekraanipilte saate teha, klõpsates arvuti kontekstimenüüs üksusel „Ekraanipilt”. Ekraanipilte saab hallata allolevate nuppude abil. + + + User: + Kasutaja: + + + Computer: + Arvuti: + + + Date: + Kuupäev: + + + Time: + Kellaaeg: + + + Show + Näita + + + Delete + Kustuta + + + Screenshot + Ekraanipilt + + + Do you really want to delete all selected screenshots? + Kas soovite tõesti kõik valitud ekraanipildid kustutada? + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + + + + User has denied access + + + + User confirmed access + + + + + ServiceConfigurationPage + + General + Üldine + + + Autostart + Autostart + + + Hide tray icon + Peida salveikoon + + + Start service + Käivita teenus + + + Stopped + Peatatud + + + Stop service + Peata teenus + + + State: + Seisund: + + + Enable firewall exception + Luba tulemüüri erisused + + + Allow connections from localhost only + Luba ühendused ainult localhostilt + + + VNC server + VNC server + + + Plugin: + Pistikprogramm: + + + Restart %1 Service + Taaskäivita %1 teenus + + + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + Kõik seaded salvestati edukalt. Jõustumiseks tuleb %1 teenus taaskäivitada. Kas taaskäivitada see kohe? + + + Running + Käib + + + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. + Selle suvandi lubamine käivitab teenuse serveriprotsessi iga arvuti interaktiivse seansi jaoks. +Tavaliselt on see vajalik terminaliserverite toetamiseks. + + + Show notification on remote connection + Kuva teated kaugühenduse korral + + + Show notification when an unauthorized access is blocked + Kuva teade, kui volitamata juurdepääs on blokeeritud + + + Maximum session count + Maksimaalne seansside arv + + + Network port numbers + Võrgu pordi numbrid + + + Veyon server + Veyoni server + + + Internal VNC server + Sisemine VNC server + + + Feature manager + Funktsioonihaldur + + + Demo server + Demo server + + + Miscellaneous network settings + Mitmesugused võrguseaded + + + Session mode + Seansi režiim + + + Local session mode (single server instance for primary local session) + Kohaliku seansi režiim (ühe serveri eksemplar esmase kohaliku seansi jaoks) + + + Active session mode (single server instance for active local or remote session) + Aktiivne seansirežiim (ühe serveri eksemplar aktiivse kohaliku või kaugseansi jaoks) + + + Multi session mode (distinct server instance for each local and remote desktop session) + Mitme seansi režiim (iga kohaliku ja kaugtöölaua seansi jaoks eraldi serveri eksemplar) + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + + + + Miscellaneous settings + Mitmesugused seaded + + + Disable clipboard synchronization + Keela lõikelaua sünkroonimine + + + Session metadata + + + + Content + + + + None + Puudub + + + Value of an environment variable + + + + Value of a registry key + + + + Environment variable name: + Keskkonna muutuja nimi + + + Registry key name: + Registrivõtme nimi + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + Soovi korral sisestage fikseeritud regulaaravaldis, et eraldada osa arvuti nimest ja kasutada seda arvuti kuvanimena. + +Näide: [^-]*-(PC[0-9]*) + + + + ServiceControl + + Service control + Teenuse juhtimine + + + Starting %1 + + + + Stopping %1 + + + + Restarting %1 + + + + Registering %1 + + + + Unregistering %1 + + + + + ServiceControlCommands + + Register Veyon Service + Registreerige Veyoni teenus + + + Unregister Veyon Service + Tühistage Veyoni teenuse registreerimine + + + Start Veyon Service + Käivitage Veyoni teenus + + + Stop Veyon Service + Peatan Veyoni teenuse + + + Restart Veyon Service + Taaskäivitage Veyoni teenus + + + Query status of Veyon Service + Veyoni teenuse päringu olek + + + Service is running + Teenus töötab + + + Service is not running + Teenus on peatatud + + + Configure and control Veyon service + Veyoni teenuse konfigureerimine ja juhtimine + + + Commands for configuring and controlling Veyon Service + Käsud Veyon Service'i konfigureerimiseks ja juhtimiseks + + + + ShellCommands + + Run command file + Käivitage käsufail + + + File "%1" does not exist! + Faili "%1" ei ole! + + + Interactive shell and script execution for Veyon CLI + Interaktiivne kest ja skripti täitmine Veyon CLI jaoks + + + Commands for shell functionalities + Käsud kestade funktsionaalsuste jaoks + + + + SlideshowPanel + + Previous + Eelmine + + + Start/pause + Start/paus + + + Next + Järgmine + + + Duration: + Kestus: + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + Lisage valitud arvutid + + + Remove selected computers + Eemaldage valitud arvutid + + + Update computers in realtime + Värskendage arvuteid reaalajas + + + Spotlight + Tähelepanu keskpunktis + + + Please select at least one computer to add. + Valige lisamiseks vähemalt üks arvuti. + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + Arvutite lisamiseks klõpsake hiire keskmise nupuga või klõpsake esimest nuppu allpool. +Teine nupp eemaldab valitud või viimase arvuti. + + + + StartAppDialog + + Start application + Käivita rakendus + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + Palun sisestage valitud arvutites käivitamiseks vajalikud rakendused. Saate eraldada mitu rakendust eri ridades. + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + näit. "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + Pidage meeles ja lisage rakendus menüüsse + + + Application name + Rakenduse nimetus + + + Name: + Nimi: + + + e.g. VLC + näit. VLC + + + + SystemTrayIcon + + System tray icon + Süsteemse salve ikoon + + + + SystemUserGroupsPlugin + + User groups backend for system user groups + Kasutajarühmade taustaprogramm süsteemi kasutajagruppide jaoks + + + Default (system user groups) + Vaikimisi (süsteemi kasutajagrupid) + + + + TestingCommandLinePlugin + + Test internal Veyon components and functions + Testige Veyoni sisemisi komponente ja funktsioone + + + Commands for testing internal components and functions of Veyon + Käsud Veyoni sisemiste komponentide ja funktsioonide testimiseks + + + + TextMessageDialog + + Send text message + Saada tekstisõnum + + + Please enter your message which send to all selected users. + Sisestage oma sõnum, mis saadetakse kõigile valitud kasutajatele. + + + + TextMessageFeaturePlugin + + Text message + Tekstisõnum + + + Use this function to send a text message to all users e.g. to assign them new tasks. + Selle funktsiooni abil saate tekstisõnumi saata kõigile kasutajatele, näit. neile uusi ülesandeid määrata. + + + Message from teacher + Sõnum õpetajalt + + + Send a message to a user + Saada kasutajale sõnum + + + + UltraVncConfigurationWidget + + Enable capturing of layered (semi-transparent) windows + Luba kihiliste (poolläbipaistvate) akende hõivamine + + + Poll full screen (leave this enabled per default) + Küsitlus täisekraanil (jätke see vaikimisi lubatuks) + + + Low accuracy (turbo mode) + Madal täpsus (turborežiim) + + + Builtin UltraVNC server configuration + Sissemise UltraVNC serveri konfiguratsioon + + + Enable multi monitor support + Luba mitme kuvari tugi + + + Enable Desktop Duplication Engine on Windows 8 and newer + Luba töölaua laiendamismootor Windows 8 ja uuemates versioonides + + + Maximum CPU usage + Maksimaalne protsessori kasutamine + + + + UserLoginDialog + + User login + Kasutaja sisselogimine + + + Please enter a username and password for automatic login on all computers. + Kõigi arvutite automaatseks sisselogimiseks sisestage kasutajanimi ja parool. + + + Username + Kasutajanimi + + + Password + Parool + + + + UserSessionControlPlugin + + Log in + Logi sisse + + + Click this button to log in a specific user on all computers. + Kõigil arvutitel konkreetse kasutaja sisselogimiseks klõpsake seda nuppu. + + + Log off + Logi välja + + + Click this button to log off users from all computers. + Kasutajate kõigist arvutitest väljalogimiseks klõpsake seda nuppu. + + + Confirm user logoff + Kinnitage kasutaja väljalogimine + + + Do you really want to log off the selected users? + Kas soovite tõesti valitud kasutajad välja logida? + + + User session control + Kasutaja seansi juhtimine + + + Do you really want to log off <b>ALL</b> users? + Kas soovite tõesti välja logida <b>KÕIK</b> kasutajad? + + + + VeyonCore + + [OK] + [OK] + + + [FAIL] + [FAIL] + + + Invalid command! + Tundmatu käsk! + + + Available commands: + Saadaolevad käsud: + + + Invalid arguments given + Esitatud valed argumendid + + + Not enough arguments given - use "%1 help" for more information + Ei ole piisavalt argumente esitatud - lisateabe saamiseks kasutage "%1 abi" + + + Unknown result! + Tundmatu tulemus! + + + Available modules: + Saadaval olevad moodulid: + + + No module specified or module not found - available modules are: + Moodulit pole määratud või moodulit ei leitud - saadaval on: + + + Plugin not licensed + Pistikprogramm pole litsentsitud + + + INFO + INFO + + + ERROR + VIGA + + + USAGE + KASUTA + + + DESCRIPTION + KIRJELDUS + + + EXAMPLES + NÄITED + + + WARNING + HOIATUS + + + Authentication test + Autentimistest + + + Screen %1 + Ekraan %1 + + + + VeyonMaster + + No write access + Kirjutusjuurdepääs puudub + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Teie isiklikke seadeid ei õnnestunud salvestada! Kontrollige kasutaja konfiguratsioonifaili teed %1 Konfiguraatori abil + + + + VeyonServiceControl + + Veyon Service + Veyoni teenus + + + + WindowsPlatformConfiguration + + Could not change the setting for SAS generation by software. Sending Ctrl+Alt+Del via remote control will not work! + Tarkvara järgi ei saanud SAS-i genereerimise seadet muuta. Ctrl+Alt+Del saatmine kaughalduse kaudu ei toimi! + + + + WindowsPlatformConfigurationPage + + Windows + Windows + + + General + Üldine + + + Enable SAS generation by software (Ctrl+Alt+Del) + Luba tarkvara SAS genereerimine (Ctrl+Alt+Del) + + + Screen lock + Ekraanilukk + + + Hide taskbar + Peida tegumiriba + + + Hide start menu + Peida Start menüü + + + Hide desktop + Peida töölaud + + + User authentication + Kasutaja autentimine + + + Use alternative user authentication mechanism + Kasutage alternatiivset kasutaja autentimismehhanismi + + + User login + Kasutaja sisselogimine + + + Input start delay + Sisendi käivitamise viivitus + + + Simulated key presses interval + Simuleeritud klahvivajutuste intervall + + + Confirm legal notice (message displayed before user logs in) + Kinnitage juriidiline teade (teade kuvatakse enne kasutaja sisselogimist) + + + Use input device interception driver + Kasutage sisendseadme pealtkuulamise draiverit + + + Use custom power scheme with disabled power button + Kasutage kohandatud toiteskeemi koos keelatud toitenupuga + + + + WindowsPlatformPlugin + + Plugin implementing abstract functions for the Windows platform + Pistikprogramm, mis rakendab Windowsi platvormi jaoks abstraktseid funktsioone + + + Internal display + Sisemine ekraan + + + + WindowsServiceControl + + The service "%1" is already installed. + Teenus "%1" on juba installitud. + + + The service "%1" has been installed successfully. + Teenus "%1" installiti edukalt. + + + The service "%1" has been uninstalled successfully. + Teenuse "%1" desinstallimine õnnestus. + + + Service "%1" could not be found. + Teenust "%1" ei leitud. + + + The service "%1" could not be installed (error %2). + Teenust "%1" ei saanud installida (viga %2). + + + Could not change the failure actions config for service "%1" (error %2). + Teenuse "%1" tõrketoimingute konfiguratsiooni ei saanud muuta (viga %2). + + + The service "%1" could not be uninstalled (error %2). + Teenust "%1" ei saanud desinstallida (viga %2). + + + The start type of service "%1" could not be changed (error %2). + Teenuse algustüüpi "%1" ei saanud muuta (viga %2). + + + + X11VncConfigurationWidget + + Builtin x11vnc server configuration + Sisemise x11vnc serveri konfiguratsioon + + + Custom x11vnc parameters: + Kohandatud x11vnc parameetrid: + + + Do not use X Damage extension + Ärge kasutage laiendust X Damage + + + \ No newline at end of file diff --git a/translations/fa.ts b/translations/veyon_fa.ts similarity index 78% rename from translations/fa.ts rename to translations/veyon_fa.ts index 09dddb5a2..417085760 100644 --- a/translations/fa.ts +++ b/translations/veyon_fa.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -79,10 +79,6 @@ If you're interested in translating Veyon into your local or another langua All groups تمام گروه ها - - ... - ... - Access control rules قوانین کنترل دسترسی @@ -140,15 +136,14 @@ If you're interested in translating Veyon into your local or another langua گروه های کاربر: - Missing user groups backend - گروه های کاربری فاقد بخش مدیریت - - - No default user groups plugin was found. Please check your installation! - هیچ پلاگین گروه کاربر پیش فرض یافت نشد لطفا نصب خود را بررسی کنید! + Restrict access to members of specific user groups + + + + AccessControlProvider - Restrict access to members of specific user groups + Provider for access control features @@ -178,30 +173,10 @@ If you're interested in translating Veyon into your local or another langua Rule description: شرح قانون: - - Invert all conditions ("is/has" interpreted as "is/has not") - همه شرایط را غیرفعال کنید ("is / has" به عنوان "آیا / ندارد" تفسیر شده است) - Conditions شرایط - - is member of group - عضو گروه است - - - Accessing computer is localhost - دسترسی به کامپیوتر میزبان محلی است - - - Accessing user is logged on user - دسترسی به کاربر به کاربر وارد شده است - - - Accessing user is already connected - دسترسی به کاربر در حال حاضر اتصال است - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. اگر بیشتر از یک شرایط فعال شود، هر شرایط باید برای تطابق قوانین (منطقی AND) مطابقت داشته باشد. اگر فقط یکی از شرایط چندگانه برای برآورده شدن باشد (منطقی OR)، لطفا قوانین کنترل دسترسی چندگانه ایجاد کنید. @@ -235,33 +210,125 @@ If you're interested in translating Veyon into your local or another langua دسترسی به کامپیوتر - Local (logged on) user - محلی (وارد سیستم) کاربر + Always process rule and ignore conditions + همیشه قوانین را فراموش کنید و شرایط را نادیده بگیرید - Local computer - کامپیوتر محلی + Accessing computer and local computer + - Always process rule and ignore conditions - همیشه قوانین را فراموش کنید و شرایط را نادیده بگیرید + User being accessed + - No user logged on - هیچ کاربری وارد نشده است + is logged in locally + + + + is logged in remotely + + + + No user is logged in locally + - Accessing user has one or more groups in common with local (logged on) user - دسترسی به کاربر دارای یک یا چند گروه مشترک با کاربر محلی (وارد شده) است + One or multiple users are logged in locally + + + + No user is logged in remotely + - Accessing computer and local computer are at the same location + One or multiple users are logged in remotely is located at + + is not located at + + + + are located at the same location + + + + are not located the same location + + + + is member of group + عضو گروه است + + + is not member of group + + + + is authenticated via + + + + is not authenticated via + + + + has one or more groups in common with user being accessed + + + + has no groups in common with user being accessed + + + + equals user being accessed + + + + is different from user being accessed + + + + is already connected + + + + is not connected + + + + is local computer + + + + is not local computer + + + + Computer being accessed + + + + Session being accessed is a user session + + + + Session being accessed is a login screen + + + + Local computer is already being accessed + + + + Local computer is not yet being accessed + + AccessControlRulesTestDialog @@ -305,42 +372,44 @@ If you're interested in translating Veyon into your local or another langua The access in the given scenario needs permission of the logged on user. دسترسی به سناریو داده شده نیاز به اجازه ورود کاربر دارد. - - ERROR: Unknown action - خطا: اقدام ناشناخته - Test result نتیجه تست - - - AndroidPlatformConfigurationPage - Android + Authentication method - General - عمومی + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform + Introduction + معرفی + + + Please perform the following steps to set up key file authentication: + لطفا مراحل زیر را برای راه اندازی احراز هویت فایل کلید انجام دهید: + + + 1) Create a key pair on the master computer. - - - AuthKeysConfigurationPage - Authentication keys - کلیدهای احراز هویت + 2) Set an access group whose members should be allowed to access other computers. + - Introduction - معرفی + 3) Export the public key and import it on all client computers with the same name. + + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Key file directories @@ -354,14 +423,17 @@ If you're interested in translating Veyon into your local or another langua Private key file base directory فایل پایگاه داده فایل خصوصی - - ... - ... - Available authentication keys کلیدهای تأیید موجود + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + + Create key pair ایجاد جفت کلید @@ -402,10 +474,6 @@ If you're interested in translating Veyon into your local or another langua Please select a key to delete! لطفا یک کلید برای حذف انتخاب کنید! - - Please enter the name of the user group or role for which to import the authentication key: - لطفا نام گروه کاربری یا نقش را برای وارد کردن کلید تأیید اعتبار وارد کنید. - Please select a key to export! لطفا یک کلید برای صدورانتخاب کنید! @@ -419,30 +487,9 @@ If you're interested in translating Veyon into your local or another langua لطفا یک کلید را برای تنظیم گروه دسترسی برای انتخاب کنید! - Please perform the following steps to set up key file authentication: - لطفا مراحل زیر را برای راه اندازی احراز هویت فایل کلید انجام دهید: - - - 1) Create a key pair on the master computer. - - - - 2) Set an access group whose members should be allowed to access other computers. - - - - 3) Export the public key and import it on all client computers with the same name. - - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. @@ -643,10 +690,6 @@ The public key is used on client computers to authenticate incoming connection r This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - - Please specify the command to display help for! - - TYPE @@ -655,10 +698,6 @@ The public key is used on client computers to authenticate incoming connection r PAIR ID - - Command line support for managing authentication keys - - Commands for managing authentication keys @@ -675,124 +714,291 @@ The public key is used on client computers to authenticate incoming connection r This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. - - - AuthKeysTableModel - Name + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. - Type + Key file authentication + فایل کلید احراز هویت + + + Key file - Access group + Please specify the key name (e.g. "teacher/public") as the first argument. - Pair ID + Please specify the command to display help for. - - - BuiltinDirectoryConfigurationPage - Computers + The specified command does not exist or no help is available for it. + + + AuthKeysTableModel Name - Host address/IP + Type - MAC address + Access group - Add new computer + Pair ID + + + AuthLdapConfigurationWidget - Remove selected computer - + General + عمومی - New computer + Username to bind DN mapping: - Builtin directory + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + AuthLdapDialog - Locations & computers + Veyon Logon - Locations + Please enter your domain/LDAP username and password in order to access computers. - Add new location - + Username + نام کاربری - Remove selected location - + Password + رمز - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - + Authentication error + خطا احراز هویت - New location + Logon failed with given username and password. Please try again! - BuiltinDirectoryPlugin + AuthLogonDialog - Show help for specific command + Veyon Logon - Import objects from given file + Please enter your username and password in order to access computers. - Export objects to given file - + Username + نام کاربری - Invalid type specified. Valid values are "%1" or "%2". - + Password + رمز - Type - + Authentication error + خطا احراز هویت - Name + Logon failed with given username and password. Please try again! + + + AuthLogonPlugin - Host address + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - MAC address - + Logon authentication + ورود احراز هویت شده ها - Specified object not found. + Logon - + + + AuthSimpleDialog + + Veyon Logon + + + + Please enter the Veyon password: + + + + Authentication error + خطا احراز هویت + + + Logon failed with given password. Please try again! + + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + + + + Simple password authentication + + + + Simple password + + + + + AuthenticationPage + + Authentication is set up properly on this computer. + + + + + AuthenticationPageTab + + Enabled + + + + Test + تست + + + + BuiltinDirectoryConfiguration + + Builtin directory + + + + + BuiltinDirectoryConfigurationPage + + Computers + + + + Name + + + + Host address/IP + + + + MAC address + + + + Add new computer + + + + Remove selected computer + + + + New computer + + + + Builtin directory + + + + Locations + + + + Add new location + + + + Remove selected location + + + + New location + + + + Directory name + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + + + + BuiltinDirectoryPlugin + + Show help for specific command + + + + Import objects from given file + + + + Export objects to given file + + + + Invalid type specified. Valid values are "%1" or "%2". + + + + Type + + + + Name + + + + Host address + + + + MAC address + + + + Specified object not found. + + + File "%1" does not exist! @@ -996,6 +1202,14 @@ The public key is used on client computers to authenticate incoming connection r MAC ADDRESS + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. + + BuiltinUltraVncServer @@ -1013,10 +1227,6 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - میزبان / آدرس آی پی :٪ 1 - Active features: %1 ویژگی های فعال:٪ 1 @@ -1033,10 +1243,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off کامپیوتر آفلاین یا خاموش است - - Service unreachable or not running - سرویس غیر قابل دسترس یا در حال اجرا نیست - Authentication failed or access denied تأیید اعتبار ناموفق بود یا دسترسی به آن ممنوع شد @@ -1057,6 +1263,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 + + [no user] + + + + Veyon Server unreachable or not running + + + + Name: %1 + + + + Hostname: %1 + + + + unknown + + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + ComputerControlServer @@ -1088,6 +1326,17 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + + Active connections: + + + + + ComputerGroupSelector + + Group %1 + + ComputerManager @@ -1115,80 +1364,83 @@ The public key is used on client computers to authenticate incoming connection r Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. - - - ComputerSelectPanel - Computer management - مدیریت کامپیوتر + Logged in since + + + + %1 days + - Computer search - جستجوی رایانه + 1 day + + + + ComputerMonitoring - Add location + Computers - Save computer/user list - ذخیره لیست کامپیوتر / کاربران + Search users and computers + - Select output filename - انتخاب نام فایل خروجی + Select all + - CSV files (*.csv) - فایل های csv (*.csv) + Unselect all + - File error - فایل خطا + Add to group + - Could not write the computer and users list to %1! Please check the file access permissions. - لیست کامپیوتر و کاربران را به٪ 1 نمی توان نوشت! لطفا مجوز دسترسی به فایل را بررسی کنید. + Remove from group + - ConfigCommandLinePlugin - - Please specify an existing configuration file to import. - لطفا یک فایل پیکربندی موجود برای وارد کردن را مشخص کنید - + ComputerSelectPanel - Please specify a valid filename for the configuration export. - لطفا نام فایل معتبر را برای تنظیم پیکربندی مشخص کنید. + Computer search + جستجوی رایانه - Please specify a valid key. - لطفا یک کلید معتبر را مشخص کنید + Add location + - Specified key does not exist in current configuration! - کلید مشخص در پیکربندی فعلی وجود ندارد! + Save computer/user list + ذخیره لیست کامپیوتر / کاربران - Please specify a valid value. - لطفا یک مقدار معتبر را مشخص کنید. + Select output filename + انتخاب نام فایل خروجی - Configure Veyon at command line - پیکربندی Veyon در خط فرمان + CSV files (*.csv) + فایل های csv (*.csv) - Output file is not writable! - فایل خروجی قابل نوشتن نیست! + File error + فایل خطا - Output directory is not writable! - دایرکتوری خروجی قابل نوشتن نیست! + Could not write the computer and users list to %1! Please check the file access permissions. + لیست کامپیوتر و کاربران را به٪ 1 نمی توان نوشت! لطفا مجوز دسترسی به فایل را بررسی کنید. - Configuration file is not readable! - فایل پیکربندی قابل خواندن نیست! + Search computers + + + + ConfigCommands Clear system-wide Veyon configuration پاک کردن پیکربندی Veyon در سراسر سیستم @@ -1217,14 +1469,50 @@ The public key is used on client computers to authenticate incoming connection r Unset (remove) given configuration key رها کردن (حذف) کلید تنظیمات داده شده - - Commands for managing the configuration of Veyon - دستورات برای مدیریت پیکربندی Veyon - Upgrade and save configuration of program and plugins + + Please specify an existing configuration file to import. + لطفا یک فایل پیکربندی موجود برای وارد کردن را مشخص کنید + + + Configuration file is not readable! + فایل پیکربندی قابل خواندن نیست! + + + Please specify a valid filename for the configuration export. + لطفا نام فایل معتبر را برای تنظیم پیکربندی مشخص کنید. + + + Output file is not writable! + فایل خروجی قابل نوشتن نیست! + + + Output directory is not writable! + دایرکتوری خروجی قابل نوشتن نیست! + + + Please specify a valid key. + لطفا یک کلید معتبر را مشخص کنید + + + Specified key does not exist in current configuration! + کلید مشخص در پیکربندی فعلی وجود ندارد! + + + Please specify a valid value. + لطفا یک مقدار معتبر را مشخص کنید. + + + Configure Veyon at command line + پیکربندی Veyon در خط فرمان + + + Commands for managing the configuration of Veyon + دستورات برای مدیریت پیکربندی Veyon + ConfigurationManager @@ -1248,6 +1536,10 @@ The public key is used on client computers to authenticate incoming connection r Could not apply platform-specific configuration settings. + + Could not configure the firewall configuration for the %1 Service. + + DemoClient @@ -1278,10 +1570,6 @@ The public key is used on client computers to authenticate incoming connection r Memory limit محدودیت حافظه - - Use multithreading (experimental) - استفاده از Multithreading (تجربی) - MB مگابایت @@ -1298,13 +1586,17 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running + + Bandwidth limit + + + + MB/s + + DemoFeaturePlugin - - Fullscreen demo - نمایش تمام صفحه - Stop demo توقف نمایش تمام صفحه @@ -1318,16 +1610,60 @@ The public key is used on client computers to authenticate incoming connection r نمایش توسط پخش روی صفحه نمایش - Demo server - نمایش سرور + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + در این حالت صفحه شما در یک پنجره در همه رایانه ها نمایش داده می شود. کاربران می توانند در صورت نیاز به پنجره های دیگر تغییر دهند. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - در این حالت صفحه نمایش شما در حالت تمام صفحه در تمام رایانه ها نمایش داده می شود در حالی که دستگاه های ورودی کاربران قفل می شوند + Demo + - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - در این حالت صفحه شما در یک پنجره در همه رایانه ها نمایش داده می شود. کاربران می توانند در صورت نیاز به پنجره های دیگر تغییر دهند. + Share your screen or allow a user to share his screen with other users. + + + + Full screen demo + + + + Share your own screen in fullscreen mode + + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share your own screen in a window + + + + Share selected user's screen in fullscreen mode + + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share selected user's screen in a window + + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + + + + Please select only one user screen to share. + + + + All screens + @@ -1356,56 +1692,56 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - Programs & websites + Name - Predefined programs + Path - Name + Predefined websites - Path + Remove selected website - Add new program + URL - Remove selected program + New website - Predefined websites + Applications & websites - Remove selected website + Predefined applications - URL + Add new application - New program + Remove selected application - New website + Add new website + + + + New application DesktopServicesFeaturePlugin - - Run program - اجرای برنامه - Open website وبسایت را باز کنید @@ -1415,27 +1751,31 @@ The public key is used on client computers to authenticate incoming connection r برای باز کردن یک وب سایت روی تمام رایانه ها ، روی این دکمه کلیک کنید. - Start programs and services in user desktop - شروع برنامه ها و خدمات در دسکتاپ کاربر + Open website "%1" + - Click this button to run a program on all computers. - برای اجرای یک برنامه روی تمام رایانه ها روی این دکمه کلیک کنید. + Custom website + - Run program "%1" + Start application - Custom program + Click this button to start an application on all computers. - Open website "%1" + Start application "%1" - Custom website + Custom application + + + + Start apps and open websites in user sessions @@ -1470,15 +1810,19 @@ The public key is used on client computers to authenticate incoming connection r - Custom program + Handout - Handout + Texts to read - Texts to read + generic-student-user + + + + Custom application @@ -1505,498 +1849,499 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands - Feature control - کنترل ویژگی + List names of all available features + - - - FileTransferController - Could not open file "%1" for reading! Please check your permissions! + Show table with details of all available features - - - FileTransferDialog - File transfer + Start a feature on a remote host - Options + Stop a feature on a remote host - Transfer only + Please specify the command to display help for. - Transfer and open file(s) with associated program + Displays a list with the names of all available features. - Transfer and open destination folder + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. - Files + HOST ADDRESS - Start + FEATURE - Overwrite existing files + ARGUMENTS - - - FileTransferPlugin - File transfer + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information - Click this button to transfer files from your computer to all computers. + Lock the screen - Select one or more files to transfer + Display a text message - Transfer files to remote computer + Test message - Received file "%1". + Start an application - Could not receive file "%1" as it already exists. + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. - Could not receive file "%1" as it could not be opened for writing! + Unlock the screen - - - GeneralConfigurationPage - User interface - رابط کاربری + The specified command does not exist or no help is available for it. + - Language: - زبان + Name + - Use system language setting - از تنظیمات زبان سیستم استفاده کنید + Description + - Veyon - ویون + Master + - Logging - ورود به سیستم + Service + - Log file directory - دایرکتوری فایل ثبت فعالیت + Worker + - ... - ... + UID + - Log level - سطح ورود + Plugin + - Nothing - هیچ چی + Invalid feature name or UID specified + - Only critical messages - فقط پیام های بحرانی + Error parsing the JSON-encoded arguments: %1 + - Errors and critical messages - خطاها و پیام های بحرانی + Failed to initialize credentials + - Warnings and errors - هشدارها و خطاها + Could not establish a connection to host %1 + - Information, warnings and errors - اطلاعات، هشدارها و خطاها + Failed to send feature control message to host %1 + - Debug messages and everything else - پیام های اشکال زدایی و هر چیز دیگری + Feature-related CLI operations + - Limit log file size - محدود کردن اندازه فایل ورودی + Commands for controlling features + + + + FileTransferConfigurationPage - Clear all log files - پاک کردن تمام ثبت فعالیت + File transfer + - Log to standard error output - ثبت گزارش به خروجی استاندارد خطا + Directories + فهرست راهنما - Network object directory + Destination directory - Backend: + Default source directory - Update interval: + Options - %1 service + Remember last source directory - The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + Create destination directory if it does not exist + + + FileTransferController - Log files cleared + Could not open file "%1" for reading! Please check your permissions! + + + FileTransferDialog - All log files were cleared successfully. + File transfer - Error + Options - Could not remove all log files. + Transfer only - MB - مگابایت - - - Rotate log files + Transfer and open file(s) with associated program - x + Transfer and open destination folder - seconds + Files - Write to logging system of operating system + Start - Authentication + Overwrite existing files + + + FileTransferFileDialog - Method: + Select one or more files to transfer + + + FileTransferPlugin - Logon authentication - ورود احراز هویت شده ها - - - Key file authentication - فایل کلید احراز هویت - - - Test - تست - - - Authentication is set up properly on this computer. + File transfer - Authentication keys are not set up properly on this computer. + Click this button to transfer files from your computer to all computers. - Authentication test + Select one or more files to transfer - - - InternetAccessControlConfigurationPage - Internet access control + Transfer files to remote computer - Backend: + Received file "%1". - General settings + Could not receive file "%1" as it already exists. - Backend settings + Could not receive file "%1" as it could not be opened for writing! - InternetAccessControlPlugin + GeneralConfigurationPage - Block access to the internet - + User interface + رابط کاربری - Allow access to the internet - + Language: + زبان - Show help about command - نمایش راهنما در مورد این فرمان + Use system language setting + از تنظیمات زبان سیستم استفاده کنید - Block internet - + Veyon + ویون - Click this button to block access to the internet. - + Logging + ورود به سیستم - Unblock internet - + Log file directory + دایرکتوری فایل ثبت فعالیت - Click this button to allow access to the internet. - + Log level + سطح ورود - Control access to the internet - + Nothing + هیچ چی - Commands for controlling access to the internet - + Only critical messages + فقط پیام های بحرانی - - - LdapBrowseDialog - Browse LDAP - + Errors and critical messages + خطاها و پیام های بحرانی - - - LdapClient - LDAP error description: %1 - + Warnings and errors + هشدارها و خطاها - - - LdapConfigurationPage - Basic settings - + Information, warnings and errors + اطلاعات، هشدارها و خطاها - General - عمومی + Debug messages and everything else + پیام های اشکال زدایی و هر چیز دیگری - LDAP server and port - + Limit log file size + محدود کردن اندازه فایل ورودی - Bind DN - + Clear all log files + پاک کردن تمام ثبت فعالیت - Bind password - + Log to standard error output + ثبت گزارش به خروجی استاندارد خطا - Anonymous bind + %1 service - Use bind credentials + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? - Base DN + Log files cleared - Fixed base DN + All log files were cleared successfully. - e.g. dc=example,dc=org + Error - Discover base DN by naming context + Could not remove all log files. - e.g. namingContexts or defaultNamingContext - + MB + مگابایت - Environment settings + Rotate log files - Object trees + x - Computer tree + Write to logging system of operating system - e.g. OU=Groups + TLS configuration - User tree + Use certificate authority for TLS connections - e.g. OU=Users + CA certificate file - e.g. OU=Computers - + ... + ... - Group tree + Host certificate file - Perform recursive search operations in object trees + Host private key file - Object attributes + Style: - e.g. hwAddress + Native - e.g. member or memberUid + Color scheme: - e.g. dNSHostName + Light - Computer MAC address attribute + Dark - Group member attribute + User groups - e.g. uid or sAMAccountName + Backend: - Advanced settings + Include user groups from domain - Optional object filters - + Missing user groups backend + گروه های کاربری فاقد بخش مدیریت - Filter for user groups + No user groups plugin was found. Please check your installation! + + + HeadlessVncServer - Filter for users + Headless VNC server + + + LdapBrowseDialog - Filter for computer groups + Browse LDAP + + + LdapClient - Group member identification + LDAP error description: %1 + + + LdapConfiguration - Distinguished name (Samba/AD) + LDAP connection failed - List all groups of a user + Could not connect to the LDAP server. Please check the server parameters. + +%1 - List all groups of a computer + LDAP bind failed - Get computer object by IP address + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 - LDAP connection failed + LDAP bind successful - LDAP bind failed + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - LDAP bind successful + LDAP base DN test failed - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Could not query the configured base DN. Please check the base DN parameter. + +%1 - LDAP base DN test failed + LDAP base DN test successful - LDAP base DN test successful + The LDAP base DN has been queried successfully. The following entries were found: + +%1 LDAP naming context test failed + + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + + LDAP naming context test successful @@ -2010,38 +2355,50 @@ The public key is used on client computers to authenticate incoming connection r user tree + + User tree + + group tree + + Group tree + + computer tree - Enter username - نام کاربری را وارد کنید + Computer tree + - Please enter a user login name (wildcards allowed) which to query: + computer group tree - user objects + Computer group tree - Enter group name + user objects - Please enter a group name whose members to query: + User login name attribute group members + + Group member attribute + + Group not found @@ -2051,25 +2408,49 @@ The public key is used on client computers to authenticate incoming connection r - Enter computer name + computer objects - computer objects + Computer display name attribute - Enter computer DN + Invalid hostname - Please enter the DN of a computer whose MAC address to query: + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + + + + Computer hostname attribute computer MAC addresses + + Computer MAC address attribute + + + + computer locations + + + + Computer location attribute + + + + Location name attribute + + users @@ -2078,12 +2459,16 @@ The public key is used on client computers to authenticate incoming connection r user groups + + computers + + computer groups - Please enter a user login name whose group memberships to query: + computer containers @@ -2094,6 +2479,10 @@ The public key is used on client computers to authenticate incoming connection r User not found + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + + groups of computer @@ -2103,586 +2492,580 @@ The public key is used on client computers to authenticate incoming connection r - Enter computer IP address + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - Please enter a computer IP address which to resolve to an computer object: + Hostname lookup failed - computers + Could not lookup hostname for IP address %1. Please check your DNS server settings. - LDAP %1 test failed + location entries - LDAP %1 test successful + Computer groups filter - The %1 has been queried successfully and %2 entries were found. + Computer locations identification - %1 %2 have been queried successfully: + Filter for computer groups + + + + Invalid test value + + + + An empty or invalid value has been supplied for this test. + + + + LDAP %1 test failed + + + + Could not query any entries in configured %1. Please check the parameter "%2". %3 - LDAP filter test failed + LDAP %1 test successful - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 + The %1 has been queried successfully and %2 entries were found. - LDAP filter test successful + LDAP test failed - %1 %2 have been queried successfully using the configured filter. + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 - (only if different from group tree) + and - Computer group tree + LDAP test successful - computer group tree + %1 %2 have been queried successfully: + +%3 - Filter for computers + LDAP filter test failed - e.g. room or computerLab + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 - Integration tests + LDAP filter test successful - Computer groups + %1 %2 have been queried successfully using the configured filter. - e.g. name or description + LDAP directory + + + LdapConfigurationPage - Filter for computer containers + Basic settings - Computer containers or OUs + General + عمومی + + + LDAP server and port - Connection security + Bind DN - TLS certificate verification + Bind password - System defaults + Anonymous bind - Never (insecure!) + Use bind credentials - Custom CA certificate file + Base DN - None + Fixed base DN - TLS + e.g. dc=example,dc=org - SSL + Discover base DN by naming context - e.g. (objectClass=computer) + e.g. namingContexts or defaultNamingContext - e.g. (objectClass=group) + Environment settings - e.g. (objectClass=person) + Object trees - e.g. (objectClass=room) or (objectClass=computerLab) + Computer tree - e.g. (objectClass=container) or (objectClass=organizationalUnit) + e.g. OU=Groups - Could not query the configured base DN. Please check the base DN parameter. - -%1 + User tree - The LDAP base DN has been queried successfully. The following entries were found: - -%1 + e.g. OU=Users - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 + e.g. OU=Computers - Certificate files (*.pem) + Group tree - Could not connect to the LDAP server. Please check the server parameters. - -%1 + Perform recursive search operations in object trees - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 + Object attributes - Encryption protocol + e.g. hwAddress - Computer location attribute + e.g. member or memberUid - Computer display name attribute + e.g. dNSHostName - Location name attribute + Computer MAC address attribute - e.g. cn or displayName + Group member attribute - Computer locations identification + e.g. uid or sAMAccountName - Identify computer locations (e.g. rooms) via: + Advanced settings - Location attribute in computer objects + Optional object filters - List all entries of a location + Filter for user groups - List all locations + Filter for users - Enter computer display name + Filter for computer groups - Please enter a computer display name to query: + Group member identification - Enter computer location name + Distinguished name (Samba/AD) - Please enter the name of a computer location (wildcards allowed): + List all groups of a user - computer locations + List all groups of a computer - Enter location name + Get computer object by IP address - Please enter the name of a location whose entries to query: - + Enter username + نام کاربری را وارد کنید - location entries + Please enter a user login name (wildcards allowed) which to query: - LDAP test failed + Enter group name - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 + Please enter a group name whose members to query: - and + Enter computer name - LDAP test successful + Enter computer DN - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 + Please enter the DN of a computer whose MAC address to query: - Browse + Please enter a user login name whose group memberships to query: - Test - تست + Enter computer IP address + - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Please enter a computer IP address which to resolve to an computer object: - Computer hostname attribute + (only if different from group tree) - Please enter a computer hostname to query: + Computer group tree - Invalid hostname + Filter for computers - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + e.g. room or computerLab - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Integration tests - Could not find a user with the name "%1". Please check the username or the user tree parameter. + Computer groups - Enter hostname + e.g. name or description - Please enter a computer hostname whose group memberships to query: + Filter for computer containers - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Computer containers or OUs - Hostname lookup failed + Connection security - Could not lookup hostname for IP address %1. Please check your DNS server settings. + TLS certificate verification - User login name attribute + System defaults - Configured attribute for user login name or computer hostname (OpenLDAP) + Never (insecure!) - computer containers + Custom CA certificate file - - - LdapPlugin - Auto-configure the base DN via naming context + None - Query objects from LDAP directory + TLS - Show help about command - نمایش راهنما در مورد این فرمان + SSL + - Commands for configuring and testing LDAP/AD integration + e.g. (objectClass=computer) - Basic LDAP/AD support for Veyon + e.g. (objectClass=group) - %1 (load computers and locations from LDAP/AD) + e.g. (objectClass=person) - %1 (load users and groups from LDAP/AD) + e.g. (objectClass=room) or (objectClass=computerLab) - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + e.g. (objectClass=container) or (objectClass=organizationalUnit) - No naming context attribute name given - falling back to configured value. + Certificate files (*.pem) - Could not query base DN. Please check your LDAP configuration. + Encryption protocol - Configuring %1 as base DN and disabling naming context queries. + Computer location attribute - - - LdapProConfigurationPage - LDAP Pro + Computer display name attribute - Instances + Location name attribute - Enter name + e.g. cn or displayName - Please enter a name for the instance (can't be changed later!): + Computer locations identification - Remove instance + Identify computer locations (e.g. rooms) via: - Do you really want to remove instance "%1"? + Location attribute in computer objects - Configuration for instance "%1" + List all entries of a location - - - LdapProPlugin - Professional LDAP/AD integration for Veyon + List all locations - %1 (load computers and locations from LDAP/AD) + Enter computer display name - %1 (load users and groups from LDAP/AD) + Please enter a computer display name to query: - - - LicensingConfigurationPage - Licensing + Enter computer location name - Installed licenses + Please enter the name of a computer location (wildcards allowed): - Add new network range + Enter location name - Remove selected network range + Please enter the name of a location whose entries to query: - ID + Browse - Feature - + Test + تست - Valid until + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - Licensee + Computer hostname attribute - Browse license file + Please enter a computer hostname to query: - Veyon license files (*.vlf) + Enter hostname - Remove license + Please enter a computer hostname whose group memberships to query: - Do you really want to remove the selected license? + User login name attribute - <N/A> + Configured attribute for user login name or computer hostname (OpenLDAP) - Invalid license file + Directory name - Could not open the license file for reading! + Query options - The selected license file does not contain valid data. + Query nested user groups (supported by AD only) - The selected license file could not be verified. + Query timeout - The selected license file is not valid for this installation. - + ms + ام اس + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. + LDAP - The license is already installed. + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + LdapPlugin - Information + Auto-configure the base DN via naming context - Installation ID + Query objects from LDAP directory - Addons available for licensing - + Show help about command + نمایش راهنما در مورد این فرمان - Addon + Commands for configuring and testing LDAP/AD integration - - - LicensingPlugin - Show help for specific command + Basic LDAP/AD support for Veyon - Show all installed licenses + %1 (load computers and locations from LDAP/AD) - Add license file + %1 (load users and groups from LDAP/AD) - Remove installed license + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - -USAGE - -%1 add <LICENSE FILE> - - + No naming context attribute name given - falling back to configured value. - -USAGE - -%1 remove <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. - No certificate found with given ID + Configuring %1 as base DN and disabling naming context queries. - <N/A> + Test binding to an LDAP server - Licensing management + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Commands for managing license keys + LDAP bind @@ -2701,11 +3084,19 @@ USAGE - Session management + User sessions + + + + Minimum session lifetime before server start - Display manager users + User login + + + + Login key sequence @@ -2715,10 +3106,6 @@ USAGE Plugin implementing abstract functions for the Linux platform - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2738,11 +3125,11 @@ USAGE - Disable balloon tooltips + Show icons only - Show icons only + Disable tooltips @@ -2792,10 +3179,6 @@ USAGE About Qt - - Authentication impossible - - Configuration not writable @@ -2856,10 +3239,6 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - - Access denied دسترسی غیرمجاز است @@ -2892,10 +3271,6 @@ USAGE Search users and computers - - Adjust optimal size - - Align computers to grid @@ -2940,6 +3315,48 @@ USAGE Locations && computers + + Authentication + + + + Adjust size of computer icons automatically + + + + Slideshow + + + + Spotlight + + + + Veyon Master + + + + Locations & computers + + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + + + + Load computer positions + + + + Save computer positions + + MasterConfigurationPage @@ -2947,10 +3364,6 @@ USAGE Directories فهرست راهنما - - ... - ... - User configuration پیکربندی کاربران @@ -3035,6 +3448,10 @@ USAGE Only user name + + Only last part of user name + + Only computer name @@ -3084,164 +3501,179 @@ USAGE - Automatically adjust computer thumbnail size + Automatically open computer select panel - Automatically open computer select panel + Use modern user interface (experimental) - - - MonitoringMode - Monitoring + Thumbnail spacing - Builtin monitoring mode - ساخته شده در حالت نظارت + px + - This mode allows you to monitor all computers at one or more locations. + Hide local session - - - NetworkDiscoveryConfigurationPage - Network discovery + Auto - Mode + Thumbnail aspect ratio - Scan network ranges + Automatically adjust computer icon size - e.g. 192.168.1.0/24 + Open feature windows on the same screen as the main window - Scan all subnets of computer + Configuration templates - Scan custom subnet + Image quality in monitoring mode - Scan sessions on local computer + Highest - Test - تست + High + - Network ranges + Medium - Add new group + Low - Remove selected group + Lowest - Groups + Remote access image quality - First address + Advanced - Last address + Computer name source - Add new network range + Default - Remove selected network range + Host address - Parallel scans + Session client address - Scan timeout + Session client name - ms - ام اس + Session host name + - Session scan limit + Session metadata - Options + Full name of user - Reverse lookup discovered IP addresses to host names + User login name - New location + Computer UID role + + + + Session meta data hash + + + + Always expand all locations + + + + Image quality - NetworkDiscoveryDirectory + MonitoringMode + + Monitoring + + + + Builtin monitoring mode + ساخته شده در حالت نظارت + - Scanning... + This mode allows you to monitor all computers at one or more locations. - Discovered computers + Query application version of the server - - - NetworkDiscoveryPlugin - Show help for specific command + Query active features - Scan a subnet + Query properties of remotely available screens + + + NestedNetworkObjectDirectory - -USAGE - -%1 scan [<SUBNET>] - - + All directories + + + NetworkObjectDirectoryConfigurationPage - Network object directory which automatically discovers computers in the network + Update interval: - Network discovery (scan network for Veyon clients) + seconds + + + NetworkObjectDirectoryConfigurationPageTab - Commands for managing the network discovery directory + Enabled @@ -3278,31 +3710,43 @@ USAGE Name: + + Website name + + - PasswordDialog + PluginCommands - Username - نام کاربری + List names of all installed plugins + - Password - رمز + Show table with details of all installed plugins + - Veyon Logon + Name - Authentication error - خطا احراز هویت + Description + - Logon failed with given username and password. Please try again! + Version - Please enter your username and password in order to access computers. + UID + + + + Plugin-related CLI operations + + + + Commands for managing plugins @@ -3348,10 +3792,6 @@ USAGE Do you really want to reboot the selected computers? - - Do you really want to power down the selected computer? - - Power on a computer via Wake-on-LAN (WOL) @@ -3402,6 +3842,18 @@ USAGE Please save your work and close all programs. + + Do you really want to reboot <b>ALL</b> computers? + + + + Do you really want to power down <b>ALL</b> computers? + + + + Do you really want to power down the selected computers? + + PowerDownTimeInputDialog @@ -3448,14 +3900,25 @@ Please save your work and close all programs. Remote view or control a computer - - Please enter the hostname or IP address of the computer to access: - لطفا نام میزبان یا آدرس آی پی کامپیوتر را وارد کنید: - Show help about command نمایش راهنما در مورد این فرمان + + Exchange clipboard contents + + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + + + RemoteAccessPage + + Remote access: %1 + + RemoteAccessWidget @@ -3463,6 +3926,10 @@ Please save your work and close all programs. %1 - %2 Remote Access + + %1 - %2 - %3 Remote Access + + RemoteAccessWidgetToolBar @@ -3518,10 +3985,6 @@ Please save your work and close all programs. Alt+Ctrl+F1 - - Connecting %1 - اتصال٪ 1 - Connected. متصل شد. @@ -3534,326 +3997,503 @@ Please save your work and close all programs. Exit + + Connecting... + + + + Select screen + + + + All screens + + + + + ScreenLockFeaturePlugin + + Lock + قفل + + + Unlock + گشودن + + + Lock screen and input devices of a computer + + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + + + + Lock input devices + + + + Unlock input devices + + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + + + + Screenshot + + unknown + + + + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + + + + Screenshot + + + + Could not open screenshot file %1 for writing. + + + + + ScreenshotFeaturePlugin + + Screenshot + + + + Use this function to take a screenshot of selected computers. + + + + Screenshots taken + عکسبرداری از صفحه مانیتور + + + Screenshot of %1 computer have been taken successfully. + تصاویری از رایانه٪ 1 با موفقیت انجام شده است. + + + Take screenshots of computers and save them locally. + عکسبرداری از رایانه های شبکه و ذخیره آنها در محلی مناسب. + + + + ScreenshotManagementPage + + Screenshots + عکس های گرفته شده + - Routing + ScreenshotManagementPanel + + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + تمام عکسهای گرفته شده توسط شما در اینجا فهرست شده است. شما می توانید عکس ها را با کلیک روی آیتم "Screenshot" در منوی بالایی یک کامپیوتر بگیرید. تصاویر را می توان با استفاده از دکمه های زیر مدیریت کرد. + + + User: + کاربر + - Control internet access by modifying routing table + Computer: + کامپیوتر + + + Date: + تاریخ + + + Time: + زمان + + + Show + نمایش + + + Delete + حذف + + + Screenshot + + + + Do you really want to delete all selected screenshots? - RoutingConfigurationWidget + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + - Remove default routes to block internet access + No rule allowed access - Add custom route to block internet + Accessing user not member of an authorized user group - Destination + User has denied access - Gateway + User confirmed access - RunProgramDialog + ServiceConfigurationPage + + General + عمومی + + + Autostart + + + + Hide tray icon + + + + Start service + سرویس فعال شد + + + Stopped + متوقف شده + + + Stop service + سرویس متوقف شد + + + State: + + + + Enable firewall exception + اضافه کردن استثنا به دیوار آتش + + + Allow connections from localhost only + اجازه ارتباط فقط برای کامپیوتر محلی + + + VNC server + سرور vnc + + + Plugin: + پلاگین : + + + Restart %1 Service + راه اندازی مجدد٪ 1 سرویس + + + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + تمام تنظیمات با موفقیت ذخیره شدند. برای به تأخیر انداختن سرویس٪ 1 باید مجددا راه اندازی شود. دوباره راه اندازی کنید؟ + + + Running + در حال اجرا + + + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. + + - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. + Show notification on remote connection - Run programs + Show notification when an unauthorized access is blocked - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + Maximum session count - Name: + Network port numbers - Remember and add to program menu + Veyon server - e.g. VLC + Internal VNC server - - - ScreenLockFeaturePlugin - Lock - قفل + Feature manager + - Unlock - گشودن + Demo server + نمایش سرور - Lock screen and input devices of a computer + Miscellaneous network settings - To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + Session mode - - - Screenshot - unknown + Local session mode (single server instance for primary local session) - Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + Active session mode (single server instance for active local or remote session) - Screenshot + Multi session mode (distinct server instance for each local and remote desktop session) - - - ScreenshotFeaturePlugin - Screenshot + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. - Use this function to take a screenshot of selected computers. + Miscellaneous settings - Screenshots taken - عکسبرداری از صفحه مانیتور - - - Screenshot of %1 computer have been taken successfully. - تصاویری از رایانه٪ 1 با موفقیت انجام شده است. + Disable clipboard synchronization + - Take screenshots of computers and save them locally. - عکسبرداری از رایانه های شبکه و ذخیره آنها در محلی مناسب. + Session metadata + - - - ScreenshotManagementPanel - All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. - تمام عکسهای گرفته شده توسط شما در اینجا فهرست شده است. شما می توانید عکس ها را با کلیک روی آیتم "Screenshot" در منوی بالایی یک کامپیوتر بگیرید. تصاویر را می توان با استفاده از دکمه های زیر مدیریت کرد. + Content + - User: - کاربر + None + - Computer: - کامپیوتر + Value of an environment variable + - Date: - تاریخ + Value of a registry key + - Time: - زمان + Environment variable name: + - Show - نمایش + Registry key name: + - Delete - حذف + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + - ServiceConfigurationPage - - General - عمومی - + ServiceControl - Autostart + Service control - Hide tray icon + Starting %1 - Start service - سرویس فعال شد - - - Stopped - متوقف شده - - - Stop service - سرویس متوقف شد + Stopping %1 + - State: + Restarting %1 - Network - شبکه + Registering %1 + - Demo server port + Unregistering %1 + + + ServiceControlCommands - Enable firewall exception - اضافه کردن استثنا به دیوار آتش + Register Veyon Service + ثبت سرویس های ویون - Allow connections from localhost only - اجازه ارتباط فقط برای کامپیوتر محلی + Unregister Veyon Service + عدم ثبت سرویس های ویون - Internal VNC server port - پورت سرور VNC داخلی + Start Veyon Service + شروع سرویس ویون - VNC server - سرور vnc + Stop Veyon Service + توقف سرویس ویون - Plugin: - پلاگین : + Restart Veyon Service + راه اندازی مجدد سرویس ویون - Restart %1 Service - راه اندازی مجدد٪ 1 سرویس + Query status of Veyon Service + بررسی وضعیت سرویس ویون - All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - تمام تنظیمات با موفقیت ذخیره شدند. برای به تأخیر انداختن سرویس٪ 1 باید مجددا راه اندازی شود. دوباره راه اندازی کنید؟ + Service is running + سرویس در حال اجرا است - Running - در حال اجرا + Service is not running + سرویس اجرا نمی شود - Feature manager port - پورت مدیریت ویژگی + Configure and control Veyon service + پیکربندی و کنترل سرویس ویون - Primary service port - پورت خدمات اصلی + Commands for configuring and controlling Veyon Service + شامل فرمان هایی برای پیکربندی و کنترل سرویس ویون + + + ShellCommands - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. + Run command file - Show notification on remote connection + File "%1" does not exist! - Multi session mode (for terminal and remote desktop servers) + Interactive shell and script execution for Veyon CLI - Show notification when an unauthorized access is blocked + Commands for shell functionalities - ServiceControl + SlideshowPanel - Starting service %1 + Previous - Stopping service %1 + Start/pause - Registering service %1 + Next - Unregistering service %1 + Duration: - Service control + View in separate window - - - ServiceControlPlugin - Service is running - سرویس در حال اجرا است + %1 Master – Slideshow + + + + SpotlightPanel - Service is not running - سرویس اجرا نمی شود + Add selected computers + - Configure and control Veyon service - پیکربندی و کنترل سرویس ویون + Remove selected computers + - Register Veyon Service - ثبت سرویس های ویون + Update computers in realtime + - Unregister Veyon Service - عدم ثبت سرویس های ویون + Spotlight + - Start Veyon Service - شروع سرویس ویون + Please select at least one computer to add. + - Stop Veyon Service - توقف سرویس ویون + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + + StartAppDialog - Restart Veyon Service - راه اندازی مجدد سرویس ویون + Start application + - Query status of Veyon Service - بررسی وضعیت سرویس ویون + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + - Commands for configuring and controlling Veyon Service - شامل فرمان هایی برای پیکربندی و کنترل سرویس ویون + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + - - - ShellCommandLinePlugin - Run command file + Remember and add to application menu - File "%1" does not exist! + Application name - Interactive shell and script execution for Veyon Control + Name: - Commands for shell functionalities + e.g. VLC @@ -3893,8 +4533,8 @@ Typically this is required to support terminal servers. ارسال پیام متنی - Use the field below to type your message which will be sent to all selected users. - از فیلد زیر برای تایپ پیام خود استفاده کنید که به تمامی کاربران انتخاب شده ارسال می شود. + Please enter your message which send to all selected users. + @@ -3942,23 +4582,39 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer + + Maximum CPU usage + + - UserConfig + UserLoginDialog - No write access - عدم دسترسی نوشتن + User login + - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - تنظیمات شخصی شما ذخیره نشد لطفا مسیر پرونده پیکربندی کاربر را با استفاده از پیکربندی ٪ 1 بررسی کنید. + Please enter a username and password for automatic login on all computers. + + + + Username + نام کاربری + + + Password + رمز - UserSessionControl + UserSessionControlPlugin - User session control - کنترل جلسه کاربر + Log in + + + + Click this button to log in a specific user on all computers. + Log off @@ -3976,6 +4632,14 @@ Typically this is required to support terminal servers. Do you really want to log off the selected users? + + User session control + کنترل جلسه کاربر + + + Do you really want to log off <b>ALL</b> users? + + VeyonCore @@ -4027,10 +4691,6 @@ Typically this is required to support terminal servers. ERROR - - licensed for - - USAGE @@ -4047,19 +4707,31 @@ Typically this is required to support terminal servers. WARNING + + Authentication test + + + + Screen %1 + + - VeyonServiceControl + VeyonMaster - Veyon Service - + No write access + عدم دسترسی نوشتن + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + تنظیمات شخصی شما ذخیره نشد لطفا مسیر پرونده پیکربندی کاربر را با استفاده از پیکربندی ٪ 1 بررسی کنید. - VncView + VeyonServiceControl - Establishing connection to %1 ... - ایجاد اتصال به٪ 1 ... + Veyon Service + @@ -4107,6 +4779,30 @@ Typically this is required to support terminal servers. Use alternative user authentication mechanism + + User login + + + + Input start delay + + + + Simulated key presses interval + + + + Confirm legal notice (message displayed before user logs in) + + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4115,7 +4811,7 @@ Typically this is required to support terminal servers. پلاگین اجرای توابع انتزاعی برای پلت فرم ویندوز - Plugin implementing specific functions for the Windows platform + Internal display @@ -4126,27 +4822,31 @@ Typically this is required to support terminal servers. - The service "%1" could not be installed. + The service "%1" has been installed successfully. + + + + The service "%1" has been uninstalled successfully. - The service "%1" has been installed successfully. + Service "%1" could not be found. - The service "%1" could not be uninstalled. + The service "%1" could not be installed (error %2). - The service "%1" has been uninstalled successfully. + Could not change the failure actions config for service "%1" (error %2). - The start type of service "%1" could not be changed. + The service "%1" could not be uninstalled (error %2). - Service "%1" could not be found. + The start type of service "%1" could not be changed (error %2). diff --git a/translations/fr.ts b/translations/veyon_fr.ts similarity index 72% rename from translations/fr.ts rename to translations/veyon_fr.ts index badd3bcad..54202d966 100644 --- a/translations/fr.ts +++ b/translations/veyon_fr.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -23,11 +23,11 @@ Version: - Version: + Version : Website: - Site Internet: + Site Internet : Current language not translated yet (or native English). @@ -80,10 +80,6 @@ Cependant, si vous êtes intéressé pour traduire Veyon dans une autre langue, All groups Tous les groupes - - ... - ... - Access control rules Règles du contrôle d'accès @@ -114,7 +110,7 @@ Cependant, si vous êtes intéressé pour traduire Veyon dans une autre langue, Please enter a user login name whose access permissions to test: - Pour tester, veuillez entrer un identifiant qui possède des droits d'accès: + Pour tester, veuillez entrer un identifiant qui possède des droits d'accès : Access allowed @@ -138,21 +134,20 @@ Cependant, si vous êtes intéressé pour traduire Veyon dans une autre langue, User groups backend: - Groupes d'utilisateurs de processus d'arrière plan: - - - Missing user groups backend - Groupes d'utilisateurs de processus d'arrière plan manquants - - - No default user groups plugin was found. Please check your installation! - Aucun greffon par défaut pour les groupes d'utilisateurs n'a été trouvé. Veuillez vérifier votre installation! + Groupes d'utilisateurs de processus d'arrière plan : Restrict access to members of specific user groups Restreindre l'accès aux membres de groupes d'utilisateurs spécifiques + + AccessControlProvider + + Provider for access control features + + + AccessControlRuleEditDialog @@ -169,7 +164,7 @@ Cependant, si vous êtes intéressé pour traduire Veyon dans une autre langue, Rule name: - Nom de la règle: + Nom de la règle : enter a description for the rule here @@ -177,32 +172,12 @@ Cependant, si vous êtes intéressé pour traduire Veyon dans une autre langue, Rule description: - Description de la règle: - - - Invert all conditions ("is/has" interpreted as "is/has not") - Inverser toutes les conditions ("est" sera interprété par "n'est pas") + Description de la règle : Conditions Conditions - - is member of group - est membre du groupe - - - Accessing computer is localhost - L'ordinateur accédant est l'hôte local - - - Accessing user is logged on user - L'utilisateur accédant est identifié en utilisateur - - - Accessing user is already connected - L'utilisateur accédant est déjà connecté - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. Si plus d'une condition est validée, chaque condition doit être en adéquation avec les autres afin que la règle puisse s'appliquer (ET Logique). Si seulement une condition sur plusieurs est validée (OU Logique) optez plutôt pour la création de plusieurs règles de contrôle d'accès. @@ -236,33 +211,125 @@ Cependant, si vous êtes intéressé pour traduire Veyon dans une autre langue, L'ordinateur accédant - Local (logged on) user - L'utilisateur local (connecté) + Always process rule and ignore conditions + Toujours appliquer la règle et ignorer les conditions - Local computer - L'ordinateur local + Accessing computer and local computer + Accès à l'ordinateur et à l'ordinateur local - Always process rule and ignore conditions - Toujours appliquer la règle et ignorer les conditions + User being accessed + Utilisateur en accès - No user logged on - Aucun utilisateur connecté + is logged in locally + est connecté localement + + + is logged in remotely + est connecté à distance + + + No user is logged in locally + Aucun utilisateur n'est connecté localement + + + One or multiple users are logged in locally + Un ou plusieurs utilisateurs sont connectés localement - Accessing user has one or more groups in common with local (logged on) user - L'utilisateur accédant est membre d'un ou plusieurs groupes en commun avec l'utilisateur local (connecté) + No user is logged in remotely + Aucun utilisateur n'est connecté à distance - Accessing computer and local computer are at the same location - L'accès à l'ordinateur et l'ordinateur local se trouvent au même endroit + One or multiple users are logged in remotely + Un ou plusieurs utilisateurs sont connectés à distance is located at est situé à + + is not located at + n'est pas situé à + + + are located at the same location + sont situés au même endroit + + + are not located the same location + ne sont pas situés au même endroit + + + is member of group + est membre du groupe + + + is not member of group + n'est pas membre du groupe + + + is authenticated via + est authentifié via + + + is not authenticated via + n'est pas authentifié via + + + has one or more groups in common with user being accessed + a un ou plusieurs groupes en commun avec l'utilisateur auquel on accède + + + has no groups in common with user being accessed + n'a aucun groupe en commun avec l'utilisateur auquel on accède + + + equals user being accessed + équivaut à l'utilisateur auquel on accède + + + is different from user being accessed + est différent de l'utilisateur auquel on accède + + + is already connected + est déjà connecté + + + is not connected + n'est pas connecté + + + is local computer + est un ordinateur local + + + is not local computer + n'est pas un ordinateur local + + + Computer being accessed + Ordinateur en accès + + + Session being accessed is a user session + La session en cours d'accès est une session utilisateur + + + Session being accessed is a login screen + La session en cours d'accès est un écran de connexion + + + Local computer is already being accessed + + + + Local computer is not yet being accessed + + AccessControlRulesTestDialog @@ -272,15 +339,15 @@ Cependant, si vous êtes intéressé pour traduire Veyon dans une autre langue, Accessing user: - Utilisateur accédant: + Utilisateur accédant : Local computer: - Ordinateur local: + Ordinateur local : Accessing computer: - Ordinateur accédant: + Ordinateur accédant : Please enter the following user and computer information in order to test the configured ruleset. @@ -288,11 +355,11 @@ Cependant, si vous êtes intéressé pour traduire Veyon dans une autre langue, Local user: - Utilisateur local: + Utilisateur local : Connected users: - Utilisateurs connectés + Utilisateurs connectés : The access in the given scenario is allowed. @@ -306,42 +373,44 @@ Cependant, si vous êtes intéressé pour traduire Veyon dans une autre langue, The access in the given scenario needs permission of the logged on user. L'accès dans le scénario donné demande la permission à l'utilisateur connecté. - - ERROR: Unknown action - ERREUR: Action inconnue - Test result Résultat du test - - - AndroidPlatformConfigurationPage - Android - + Authentication method + Méthode d'authentification - General - Général + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + Introduction - - - AuthKeysConfigurationPage - Authentication keys - Clés d'authentification + Please perform the following steps to set up key file authentication: + Veuillez suivre les indications suivantes pour configurer la clé d'authentification : - Introduction - Introduction + 1) Create a key pair on the master computer. + 1) Créer une paire de clé sur l'ordinateur maître. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Définissez un groupe d'accès dont les membres sont autorisés pour accéder aux autres ordinateurs. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Exporter la clé publique et importer la avec le même nom sur tous les ordinateurs clients . + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Veuillez vous référer au <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Manuel Administrateur Veyon</a> pour plus d'informations. Key file directories @@ -355,14 +424,20 @@ Cependant, si vous êtes intéressé pour traduire Veyon dans une autre langue, Private key file base directory Répertoire de base des clés d'accès privées - - ... - ... - Available authentication keys Clés d'authentification disponibles + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Une paire de clé d'authentification, consiste en deux clés cryptographiques couplées, une clé privée et une autre publique. +La clé privée permet aux utilisateurs de l'ordinateur maitre d'accéder aux ordinateurs clients. +Il est important que seuls les utilisateurs autorisés aient l'accès en lecture sur la clé privée. +La clé publique est utilisée sur les ordinateurs clients pour l'authentification des demandes de connexions. + Create key pair Créer paire de clé @@ -393,7 +468,7 @@ Cependant, si vous êtes intéressé pour traduire Veyon dans une autre langue, Please enter the name of the user group or role for which to create an authentication key pair: - Entrer le nom du groupe d'utilisateurs ou du rôle pour lequel se fait la création de la paire de clé d'authentification: + Entrer le nom du groupe d'utilisateurs ou du rôle pour lequel se fait la création de la paire de clé d'authentification : Do you really want to delete authentication key "%1/%2"? @@ -403,51 +478,23 @@ Cependant, si vous êtes intéressé pour traduire Veyon dans une autre langue, Please select a key to delete! Veuillez sélectionner une clé à supprimer ! - - Please enter the name of the user group or role for which to import the authentication key: - Entrez le nom du groupe d'utilisateurs ou du rôle pour lequel se fait l'import de la clé d'authentification: - Please select a key to export! Veuillez sélectionner une clé à exporter ! Please select a user group which to grant access to key "%1": - Veuillez sélectionner un groupe d'utilisateur pour lequel vous accordez l'accès à la clé "%1": + Veuillez sélectionner un groupe d'utilisateur pour lequel vous accordez l'accès à la clé "%1" : Please select a key which to set the access group for! Veuillez sélectionner une clé pour accorder l'accès groupe ! - Please perform the following steps to set up key file authentication: - Veuillez suivre les indications suivantes pour configurer la clé d'authentification: - - - 1) Create a key pair on the master computer. - 1) Créer une paire de clé sur l'ordinateur maître. - - - 2) Set an access group whose members should be allowed to access other computers. - 2) Définissez un groupe d'accès dont les membres sont autorisés pour accéder aux autres ordinateurs. - - - 3) Export the public key and import it on all client computers with the same name. - 3) Exporter la clé publique et importer la avec le même nom sur tous les ordinateurs clients . - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - Veuillez vous référer au <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Manuel Administrateur Veyon</a> pour plus d'informations. - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - Une paire de clé d'authentification, consiste en deux clés cryptographiques couplées, une clé privée et une autre publique. -La clé privée permet aux utilisateurs de l'ordinateur maitre d'accéder aux ordinateurs clients. -Il est important que seuls les utilisateurs autorisés aient l'accès en lecture sur la clé privée. -La clé publique est utilisée sur les ordinateurs clients pour l'authentification des demandes de connexions. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + @@ -647,10 +694,6 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. Cette commande liste toutes les clés d'authentification disponibles dans le répertoire des clés configuré. Si l'option "%1" est spécifiée, un tableau avec les détails de la clé sera affiché à la place. Certaines informations peuvent être manquantes si une clé n'est pas accessible ex: en cas d'un manque de permission en lecture. - - Please specify the command to display help for! - Veuillez spécifier la commande pour afficher l'aide correspondante ! - TYPE TYPE @@ -659,10 +702,6 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif PAIR ID ID PAIRE - - Command line support for managing authentication keys - Prise en charge de la ligne de commande pour la gestion des clés d'authentification - Commands for managing authentication keys Commandes pour gérer les clés d'authentification @@ -679,6 +718,30 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. Cette commande extrait la partie clé publique à partir de la clé privée <KEY> et l'enregistre comme la clé publique correspondante. Lors de la configuration d'un autre ordinateur maître, il suffit simplement de ne transférer que la clé privée. La clé publique pourra par la suite être extraite. + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + Les fichiers de clé d'authentification ne sont pas configurés correctement sur cet ordinateur. Veuillez créer de nouveaux fichiers de clé ou passer à une méthode d’authentification différente à l’aide du configurateur Veyon. + + + Key file authentication + Authentification par un fichier clé + + + Key file + Fichier clé + + + Please specify the key name (e.g. "teacher/public") as the first argument. + Veuillez spécifier le nom de la clé (par exemple "enseignant/public") comme premier argument. + + + Please specify the command to display help for. + Veuillez spécifier la commande pour afficher l'aide correspondante. + + + The specified command does not exist or no help is available for it. + La commande demandée n'existe pas et il n'y a pas d'aide à son propos. + AuthKeysTableModel @@ -700,92 +763,235 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - Ordinateurs + General + Général - Name - Nom + Username to bind DN mapping: + Nom d'utilisateur à lier au mapping DN : - Host address/IP - Adresse hôte / IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + ex: %username%@DOMAIN ou cn=%username%,ou=users,dc=example,dc=org + + + AuthLdapDialog - MAC address - Adresse MAC + Veyon Logon + Connexion Veyon - Add new computer - Ajouter un nouvel ordinateur + Please enter your domain/LDAP username and password in order to access computers. + Veuillez entrer l'identifiant et le mot de passe de votre domaine/LDAP afin d'accéder aux ordinateurs. - Remove selected computer - Retirer l'ordinateur selectionné + Username + Identifiant - New computer - Nouvel ordinateur + Password + Mot de passe - Builtin directory - Répertoire intégré + Authentication error + Erreur d'authentification - Locations & computers - Emplacements & ordinateurs + Logon failed with given username and password. Please try again! + La connexion a échoué avec le nom d'utilisateur et le mot de passe donné. Veuillez réessayer! + + + AuthLogonDialog - Locations - Emplacements + Veyon Logon + Connexion Veyon - Add new location - Ajouter un nouvel emplacement + Please enter your username and password in order to access computers. + Veuillez entrer votre identifiant et votre mot de passe afin d'accéder aux ordinateurs. - Remove selected location - Retirer l'emplacement sélectionné + Username + Identifiant - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - L'import de fichiers CSV est possible à travers l'interface en ligne de commande. Pour plus d'informations, voir la <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">documentation en ligne</a>. + Password + Mot de passe - New location - Nouvel emplacement + Authentication error + Erreur d'authentification + + + Logon failed with given username and password. Please try again! + La connexion a échoué avec le nom d'utilisateur et le mot de passe donné. Veuillez réessayer! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command - Affiche l'aide pour une commande spécifique + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Le nom d'utilisateur ou le mot de passe fourni est incorrect. Veuillez entrer des informations d'identification valides ou passer par une méthode d'authentification différente à l'aide du configurateur Veyon. - Import objects from given file - Importer des objets d'un fichier donné + Logon authentication + Authentification par identifiant - Export objects to given file - Exporter des objets vers un fichier donné + Logon + Connexion + + + AuthSimpleDialog - Invalid type specified. Valid values are "%1" or "%2". - Le type spécifié est non valide! Les valeurs convenables sont "%1" ou "%2". + Veyon Logon + Connexion Veyon - Type - Type + Please enter the Veyon password: + Veuillez entrer le mot de passe Veyon : - Name - Nom + Authentication error + Erreur d'authentification - Host address + Logon failed with given password. Please try again! + La connexion a échoué avec le mot de passe donné. Veuillez réessayer! + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + Le mot de passe fourni est incorrect. Entrez un mot de passe valide ou passez à une méthode d'authentification différente à l'aide du configurateur Veyon. + + + Simple password authentication + Authentification par mot de passe simple + + + Simple password + Mot de passe simple + + + + AuthenticationPage + + Authentication is set up properly on this computer. + L'authentification est correctement configurée sur cet ordinateur. + + + + AuthenticationPageTab + + Enabled + Activé + + + Test + Test + + + + BuiltinDirectoryConfiguration + + Builtin directory + Répertoire intégré + + + + BuiltinDirectoryConfigurationPage + + Computers + Ordinateurs + + + Name + Nom + + + Host address/IP + Adresse hôte / IP + + + MAC address + Adresse MAC + + + Add new computer + Ajouter un nouvel ordinateur + + + Remove selected computer + Retirer l'ordinateur selectionné + + + New computer + Nouvel ordinateur + + + Builtin directory + Répertoire intégré + + + Locations + Emplacements + + + Add new location + Ajouter un nouvel emplacement + + + Remove selected location + Retirer l'emplacement sélectionné + + + New location + Nouvel emplacement + + + Directory name + Nom du répertoire + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + L'importation de fichiers CSV est possible via l'interface de ligne de commande. Pour plus d'informations, consultez la <a href="https://docs.veyon.io/fr/latest/admin/cli.html#network-object-directory">documentation en ligne</a>. + + + + BuiltinDirectoryPlugin + + Show help for specific command + Affiche l'aide pour une commande spécifique + + + Import objects from given file + Importer des objets d'un fichier donné + + + Export objects to given file + Exporter des objets vers un fichier donné + + + Invalid type specified. Valid values are "%1" or "%2". + Le type spécifié est non valide! Les valeurs convenables sont "%1" ou "%2". + + + Type + Type + + + Name + Nom + + + Host address Adresse hôte @@ -810,7 +1016,7 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Computer "%1" (host address: "%2" MAC address: "%3") - Ordinateur "%1" (adresse hôte: "%2" adresse MAC: "%3") + Ordinateur "%1" (adresse hôte : "%2" adresse MAC : "%3") Unclassified object "%1" with ID "%2" @@ -914,7 +1120,7 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Imports objects from the specified text file using the given format string or regular expression containing one or multiple placeholders. Valid placeholders are: %1 - Importe des objets à partir d'un fichier texte spécifique utilisant la chaîne de caractères donnée ou une expression régulière contenant un ou plusieurs jokers. Les jokers valides sont: %1 + Importe des objets à partir d'un fichier texte spécifique utilisant la chaîne de caractères donnée ou une expression régulière contenant un ou plusieurs jokers. Les jokers valides sont : %1 Import simple CSV file to a single room @@ -934,7 +1140,7 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Exports objects to the specified text file using the given format string containing one or multiple placeholders. Valid placeholders are: %1 - Exporte les objets vers un fichier texte spécifique utilisant la chaîne de caractères donnée contenant un ou plusieurs jokers. Les jokers valides sont: %1 + Exporte les objets vers un fichier texte spécifique utilisant la chaîne de caractères donnée contenant un ou plusieurs jokers. Les jokers valides sont : %1 Export all objects to a CSV file @@ -1000,6 +1206,14 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif MAC ADDRESS ADRESSE MAC + + The specified command does not exist or no help is available for it. + La commande demandée n'existe pas et il n'y a pas d'aide à son propos. + + + Location "%1" not found. + + BuiltinUltraVncServer @@ -1017,13 +1231,9 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif ComputerControlListModel - - Host/IP address: %1 - Adresse de l'hôte / IP: %1 - Active features: %1 - Fonctionnalités activées: %1 + Fonctionnalités activées : %1 Online and connected @@ -1037,10 +1247,6 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Computer offline or switched off Ordinateur hors ligne ou éteint - - Service unreachable or not running - Service injoignable ou inactif - Authentication failed or access denied L'authentification a échouée ou l'accès est refusé @@ -1055,18 +1261,50 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Logged on user: %1 - Connecté sur l'utilisateur: %1 + Connecté sur l'utilisateur : %1 Location: %1 - Emplacement: %1 + Emplacement : %1 + + + [no user] + [aucun utilisateur] + + + Veyon Server unreachable or not running + Serveur Veyon inaccessible ou ne fonctionne pas + + + Name: %1 + Nom : %1 + + + Hostname: %1 + + + + unknown + inconnu + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + ComputerControlServer %1 Service %2 at %3:%4 - Service %1 %2 sur %3:%4 + Service %1 %2 à %3:%4 Authentication error @@ -1092,6 +1330,17 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. L'utilisateur "%1" sur l'hôte "%2" a tenté d'accéder à cet ordinateur, mais a été bloqué en raison des paramétrages du contrôle d'accès. + + Active connections: + Connexions actives : + + + + ComputerGroupSelector + + Group %1 + Groupe %1 + ComputerManager @@ -1119,13 +1368,48 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. Impossible de déterminer l'emplacement de cet ordinateur. Cela indique un problème de configuration du système. A la place, tous les emplacements seront affichés dans le panneau de sélection de l'ordinateur. + + Logged in since + Connecté depuis + + + %1 days + %1 jours + + + 1 day + 1 jour + - ComputerSelectPanel + ComputerMonitoring + + Computers + Ordinateurs + + + Search users and computers + Chercher des utilisateurs et des ordinateurs + + + Select all + Tout sélectionner + + + Unselect all + Tout déselectionner + + + Add to group + Ajouter au groupe + - Computer management - Gestion ordinateur + Remove from group + Retirer du groupe + + + ComputerSelectPanel Computer search Recherche d'ordinateur @@ -1154,81 +1438,85 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Could not write the computer and users list to %1! Please check the file access permissions. Impossible d'écrire la liste des ordinateurs et des utilisateurs dans %1! Vérifiez le fichier des permissions d'accès. + + Search computers + Chercher des ordinateurs + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. - Veuillez spécifier un fichier de configuration existant à importer. + Clear system-wide Veyon configuration + Purger la configuration Veyon de tout le système - Please specify a valid filename for the configuration export. - Veuillez spécifier un nom de fichier valide pour l'export de la configuration. + List all configuration keys and values + Lister toutes les clés et paramètres de configuration - Please specify a valid key. - Veuillez spécifier une clé valide. + Import configuration from given file + Importer la configuration à partir d'un fichier - Specified key does not exist in current configuration! - La clé spécifiée n'existe pas dans la configuration courante! + Export configuration to given file + Exporter la configuration dans un fichier - Please specify a valid value. - Veuillez spécifier une valeur valide. + Read and output configuration value for given key + Lire et extraire la configuration pour une clé donnée - Configure Veyon at command line - Configurer Veyon en ligne de commande + Write given value to given configuration key + Écrire un paramètre dans une clé de configuration donnée - Output file is not writable! - Le fichier de sortie ne peut être écrit! + Unset (remove) given configuration key + Désactiver (retirer) une clé de configuration donnée - Output directory is not writable! - Le répertoire de sortie ne peut être écrit + Upgrade and save configuration of program and plugins + Mettre à niveau et enregistrer la configuration du programme et des greffons + + + Please specify an existing configuration file to import. + Veuillez spécifier un fichier de configuration existant à importer. Configuration file is not readable! Le fichier de configuration n'est pas lisible! - Clear system-wide Veyon configuration - Purger la configuration Veyon de tout le système + Please specify a valid filename for the configuration export. + Veuillez spécifier un nom de fichier valide pour l'export de la configuration. - List all configuration keys and values - Lister toutes les clés et paramètres de configuration + Output file is not writable! + Le fichier de sortie ne peut être écrit! - Import configuration from given file - Importer la configuration à partir d'un fichier + Output directory is not writable! + Le répertoire de sortie ne peut être écrit - Export configuration to given file - Exporter la configuration dans un fichier + Please specify a valid key. + Veuillez spécifier une clé valide. - Read and output configuration value for given key - Lire et extraire la configuration pour une clé donnée + Specified key does not exist in current configuration! + La clé spécifiée n'existe pas dans la configuration courante! - Write given value to given configuration key - Écrire un paramètre dans une clé de configuration donnée + Please specify a valid value. + Veuillez spécifier une valeur valide. - Unset (remove) given configuration key - Désactiver (retirer) une clé de configuration donnée + Configure Veyon at command line + Configurer Veyon en ligne de commande Commands for managing the configuration of Veyon Commandes pour la gestion de la configuration de Veyon - - Upgrade and save configuration of program and plugins - Mettre à niveau et enregistrer la configuration du programme et des greffons - ConfigurationManager @@ -1252,6 +1540,10 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Could not apply platform-specific configuration settings. Impossible d'appliquer les paramètres de configuration spécifiques à la plateforme. + + Could not configure the firewall configuration for the %1 Service. + Impossible de configurer la configuration du pare-feu pour le Service %1. + DemoClient @@ -1282,10 +1574,6 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Memory limit Limite de mémoire - - Use multithreading (experimental) - Utiliser le multithreading (expérimental) - MB MB @@ -1302,13 +1590,17 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Slow down thumbnail updates while demo is running Ralentir la mise à jour des vignettes lorsque qu'une démo est en cours d'exécution + + Bandwidth limit + Limite de bande passante + + + MB/s + Mo/s + DemoFeaturePlugin - - Fullscreen demo - Démo en plein écran - Stop demo Arrêter la démo @@ -1322,16 +1614,60 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Faire une démonstration par diffusion de l'écran - Demo server - Serveur de démo + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Dans ce mode votre écran est diffusé dans une fenêtre sur tous les autres ordinateurs. Les utilisateurs sont librement en mesure de changer de fenêtre comme ils le souhaitent. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - Dans ce mode votre écran sera affiché en plein écran sur tout les ordinateur, les périphériques d'entrée des utilisateurs seront verrouillés dans ce mode. + Demo + Démo - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - Dans ce mode votre écran est diffusé dans une fenêtre sur tous les autres ordinateurs. Les utilisateurs sont librement en mesure de changer de fenêtre comme ils le souhaitent. + Share your screen or allow a user to share his screen with other users. + Partagez votre écran ou autorisez un utilisateur à partager son écran avec d'autres utilisateurs. + + + Full screen demo + Démo en plein écran + + + Share your own screen in fullscreen mode + Partagez votre propre écran en mode plein écran + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + Dans ce mode, votre écran est affiché en mode plein écran sur tous les ordinateurs tandis que les périphériques d'entrée des utilisateurs sont verrouillés. + + + Share your own screen in a window + Partagez votre propre écran dans une fenêtre + + + Share selected user's screen in fullscreen mode + Partager l'écran de l'utilisateur sélectionné en mode plein écran + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + Dans ce mode, l'écran de l'utilisateur sélectionné est affiché en mode plein écran sur tous les ordinateurs tandis que les périphériques d'entrée des utilisateurs sont verrouillés. + + + Share selected user's screen in a window + Partager l'écran de l'utilisateur sélectionné dans une fenêtre + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + Dans ce mode, l'écran de l'utilisateur sélectionné est affiché dans une fenêtre sur tous les ordinateurs. Les utilisateurs peuvent consulter d'autres fenêtres selon leurs besoins. + + + Please select a user screen to share. + Veuillez sélectionner un écran d'utilisateur à partager. + + + Please select only one user screen to share. + Veuillez sélectionner un seul écran utilisateur à partager. + + + All screens + Tous les écrans @@ -1359,14 +1695,6 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif DesktopServicesConfigurationPage - - Programs & websites - Programmes et sites internet - - - Predefined programs - Programmes prédéfinis - Name Nom @@ -1375,14 +1703,6 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Path Chemin - - Add new program - Ajouter un nouveau programme - - - Remove selected program - Retirer le programme sélectionné - Predefined websites Sites internet prédéfinis @@ -1395,21 +1715,37 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif URL URL - - New program - Nouveau programme - New website Nouveau site internet + + Applications & websites + Applications & sites internet + + + Predefined applications + Applications prédéfinies + + + Add new application + Ajouter une nouvelle application + + + Remove selected application + Retirer l'application sélectionnée + + + Add new website + Ajouter un nouveau site internet + + + New application + Nouvelle application + DesktopServicesFeaturePlugin - - Run program - Exécuter un programme - Open website Ouvrir une page internet @@ -1419,28 +1755,32 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Cliquez sur ce bouton pour ouvrir un site internet sur tous les ordinateurs. - Start programs and services in user desktop - Démarrer les programmes et les services dans le bureau utilisateur + Open website "%1" + Ouvre le site internet "%1" + + + Custom website + Site internet personnalisé - Click this button to run a program on all computers. - Cliquez sur ce bouton pour exécuter un programme sur tous les ordinateurs. + Start application + Démarrer l'application - Run program "%1" - Lance le programme "%1" + Click this button to start an application on all computers. + Cliquez sur ce bouton pour exécuter une application sur tous les ordinateurs. - Custom program - Programme personnalisé + Start application "%1" + Démarrer l'application "%1" - Open website "%1" - Ouvre le site internet "%1" + Custom application + Application personnalisée - Custom website - Site internet personnalisé + Start apps and open websites in user sessions + Démarrez des applications et ouvrez des sites internet dans les sessions utilisateur @@ -1471,19 +1811,23 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Play tutorial video - Lire le didacticiel vidéo - - - Custom program - Programme personnalisé + Démarrer le didacticiel vidéo Handout - + don Texts to read - + Textes à lire + + + generic-student-user + utilisateur-élève-générique + + + Custom application + Application personnalisée @@ -1501,18 +1845,173 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Port: - Port: + Port : Password: - Mot de passe: + Mot de passe : + + + + FeatureCommands + + List names of all available features + Lister les noms de toutes les fonctionnalités disponibles + + + Show table with details of all available features + Afficher le tableau avec les détails de toutes les fonctionnalités disponibles + + + Start a feature on a remote host + Démarrer la fonctionnalité sur l'hôte distant + + + Stop a feature on a remote host + Arrêter la fonctionnalité sur un hôte distant + + + Please specify the command to display help for. + Veuillez spécifier la commande pour afficher l'aide correspondante. + + + Displays a list with the names of all available features. + Affiche une liste avec le nom de toutes les fonctionnalités disponibles. + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + Affiche un tableau avec des informations détaillées sur toutes les fonctionnalités disponibles. Ces informations incluent une description, l'UID, le nom du plugin fournissant la fonctionnalité respective et d'autres détails liés à l'implémentation. + + + HOST ADDRESS + ADRESSE HÔTE + + + FEATURE + FONCTIONNALITÉS + + + ARGUMENTS + ARGUMENTS + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + Démarre la fonctionnalité spécifiée sur l'hôte spécifié en se connectant au serveur Veyon exécuté à distance. La fonctionnalité peut être spécifiée par nom ou UID. Utilisez la commande ``show`` pour voir toutes les fonctionnalités disponibles. Selon la fonctionnalité, des arguments supplémentaires (tels que le message texte à afficher) codés sous la forme d'une chaîne JSON unique doivent être spécifiés. Veuillez vous référer à la documentation du développeur pour plus d'informations + + + Lock the screen + Verrouiller l'écran + + + Display a text message + Afficher un message + + + Test message + Message de test + + + Start an application + Démarrer une application + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + Arrête la fonctionnalité spécifiée sur l'hôte spécifié en se connectant au serveur Veyon exécuté à distance. La fonctionnalité peut être spécifiée par nom ou UID. Utilisez la commande ``show`` pour voir toutes les fonctionnalités disponibles. + + + Unlock the screen + Déverrouiller l'écran + + + The specified command does not exist or no help is available for it. + La commande demandée n'existe pas et il n'y a pas d'aide à son propos. + + + Name + Nom + + + Description + Description + + + Master + Maître + + + Service + Service + + + Worker + Travailleur + + + UID + UID + + + Plugin + Greffon + + + Invalid feature name or UID specified + Nom de fonction ou UID spécifié non valide + + + Error parsing the JSON-encoded arguments: %1 + Erreur lors de l'analyse des arguments encodés en JSON : %1 + + + Failed to initialize credentials + Échec de l'initialisation des informations d'identification + + + Could not establish a connection to host %1 + Impossible d'établir une connexion avec l'hôte %1 + + + Failed to send feature control message to host %1 + Échec de l'envoi du message de contrôle des fonctionnalités à l'hôte %1 + + + Feature-related CLI operations + Opérations CLI liées aux fonctionnalités + + + Commands for controlling features + Commandes pour contrôler les fonctionnalités - FeatureControl + FileTransferConfigurationPage + + File transfer + Transfert de fichier + + + Directories + Répertoires + + + Destination directory + Répertoire de destination + + + Default source directory + Répertoire source par défaut + + + Options + Options + - Feature control - Contrôle des fonctionnalités + Remember last source directory + Se souvenir du dernier répertoire source + + + Create destination directory if it does not exist + Créer un répertoire de destination s'il n'existe pas @@ -1557,6 +2056,13 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Écraser les fichiers existants + + FileTransferFileDialog + + Select one or more files to transfer + Sélectionner un ou plusieurs fichiers à transférer + + FileTransferPlugin @@ -1596,7 +2102,7 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Language: - Langue: + Langue : Use system language setting @@ -1614,10 +2120,6 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Log file directory Répertoire du fichier de journalisation - - ... - ... - Log level Niveau de journalisation @@ -1658,18 +2160,6 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Log to standard error output Journaliser via la sortie standard - - Network object directory - Répertoire objets réseau - - - Backend: - Méthode de fonctionnement: - - - Update interval: - Intervalle de rafraichissement: - %1 service Service %1 @@ -1706,103 +2196,80 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif x x - - seconds - secondes - Write to logging system of operating system Écrire dans le système de journalisation du système d'exploitation - Authentication - Authentification - - - Method: - Méthode: - - - Logon authentication - Authentification par un identifiant - - - Key file authentication - Authentification par un fichier clé - - - Test - Test + TLS configuration + Configuration TLS - Authentication is set up properly on this computer. - L'authentification est correctement configurée sur cet ordinateur. + Use certificate authority for TLS connections + Utiliser l'autorité de certification pour les connexions TLS - Authentication keys are not set up properly on this computer. - Les clés d'authentification ne sont pas configurées correctement sur cet ordinateur. + CA certificate file + Fichiers de certificat CA - Authentication test - Test d'authentification + ... + ... - - - InternetAccessControlConfigurationPage - Internet access control - Contrôle d'accès internet + Host certificate file + Fichier de certificat d'hôte - Backend: - Méthode de fonctionnement: + Host private key file + Fichier de clé privée de l'hôte - General settings - Paramètres généraux + Style: + Style: - Backend settings - Paramètres internes + Native + Natif - - - InternetAccessControlPlugin - Block access to the internet - Bloquer l'accès à internet + Color scheme: + - Allow access to the internet - Permettre l'accès à internet + Light + - Show help about command - Afficher la commande aide et à propos + Dark + - Block internet - Bloquer internet + User groups + Groupes d'utilisateurs - Click this button to block access to the internet. - Cliquez sur ce bouton pour bloquer l'accès à internet. + Backend: + Méthode de fonctionnement: - Unblock internet - Débloquer internet + Include user groups from domain + - Click this button to allow access to the internet. - Cliquez sur ce bouton pour permettre l'accès à internet. + Missing user groups backend + Groupes d'utilisateurs de processus d'arrière plan manquants - Control access to the internet - Contrôle l'accès à internet + No user groups plugin was found. Please check your installation! + + + + HeadlessVncServer - Commands for controlling access to the internet - Commandes pour contrôler l'accès à Internet + Headless VNC server + Serveur VNC sans périphériques @@ -1816,348 +2283,531 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif LdapClient LDAP error description: %1 - Description de l'erreur LDAP: %1 + Description de l'erreur LDAP : %1 - LdapConfigurationPage + LdapConfiguration - Basic settings - Paramètres généraux + LDAP connection failed + La connexion LDAP a échoué - General - Général + Could not connect to the LDAP server. Please check the server parameters. + +%1 + Impossible de se connecter au serveur LDAP. Veuillez vérifier les paramètres du serveur. + +%1 - LDAP server and port - Port et serveur LDAP + LDAP bind failed + Échec de la liaison LDAP - Bind DN - Authentification DN + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + Impossible de créer une liaison au serveur LDAP. Veuillez vérifier les paramètres du serveur et les informations d'identification. + +%1 - Bind password - Mot de passe d'authentification + LDAP bind successful + Liaison LDAP réussie - Anonymous bind - Authentification anonyme + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + La connexion au serveur LDAP ainsi que la liaison d'authentification LDAP ont été réussis. Les paramètres LDAP de base sont configurés convenablement. - Use bind credentials - Utiliser des informations d'identification + LDAP base DN test failed + Échec du test base LDAP DN - Base DN - Base DN + Could not query the configured base DN. Please check the base DN parameter. + +%1 + Impossible d'interroger la base DN ainsi configurée. Veuillez vérifier les paramètres de la base DN. + +%1 - Fixed base DN - Base DN Fixe + LDAP base DN test successful + Le test base LDAP DN à réussi - e.g. dc=example,dc=org - ex: dc=exemple, dc=org + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + La base LDAP DN a été interrogée avec succès. Les entrées suivantes ont été trouvées : + +%1 - Discover base DN by naming context - Explorer la base DN à partir d'un contexte de nommage + LDAP naming context test failed + Échec du test LDAP de nommage par contexte - e.g. namingContexts or defaultNamingContext - ex: ContextesNommés ou ContexteNomméParDéfaut + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + Impossible d'interroger la base DN via des contextes de nommage. Veuillez vérifier l'attribut du paramètre de contexte de nommage. + +%1 - Environment settings - Paramètres d'environnement + LDAP naming context test successful + Le test LDAP de nommage par contexte à réussi. - Object trees - Arborescence objet + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + Le contexte de nommage LDAP à été interrogé avec succès. La base DN suivante à été trouvée : +%1 + + + user tree + arborescence utilisateur + + + User tree + Arborescence utilisateur + + + group tree + arborescence groupe + + + Group tree + Arborescence groupe + + + computer tree + arborescence ordinateur Computer tree Arborescence ordinateur - e.g. OU=Groups - ex: OU=Groupes + computer group tree + arborescence groupe ordinateur - User tree - Arborescence utilisateur + Computer group tree + Arborescence groupe ordinateur - e.g. OU=Users - ex: OU=Utilisateurs + user objects + objets utilisateur - e.g. OU=Computers - ex: OU=Ordinateurs + User login name attribute + Attribut de l'identifiant utilisateur - Group tree - Arborescence groupe + group members + membres du groupe - Perform recursive search operations in object trees - Effectuer des recherches récursives dans les arborescences objet + Group member attribute + Attribut du groupe membre - Object attributes - Attributs d'objet + Group not found + Groupe introuvable - e.g. hwAddress - ex: Adressehw + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Impossible de trouver un groupe avec le nom "%1". Veuillez vérifier le nom du groupe ou le paramètre de l'arborescence du groupe. - e.g. member or memberUid - ex: membre ou surnom + computer objects + objets ordinateur - e.g. dNSHostName - ex: NomHotedNS + Computer display name attribute + Attribut de nom d'affichage d'ordinateur + + + Invalid hostname + Nom d'hôte invalide + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Vous avez choisi de stocker les noms d'ordinateurs hôtes comme des noms de domaine pleinement nommé (FQDN) mais vous avez saisi un nom d'hôte sans domaine. + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Vous avez choisi de stocker les noms d'ordinateurs hôtes comme de simple noms d'hôte sans nom de domaine, mais vous avez saisi un nom d'hôte dont une partie est un nom de domaine. + + + Computer hostname attribute + Attribut du nom d'hôte de l'ordinateur + + + computer MAC addresses + Adresse MAC de l'ordinateur Computer MAC address attribute Attribut de l'adresse MAC de l'ordinateur - Group member attribute - Attribut du groupe membre + computer locations + Emplacements d'ordinateur - e.g. uid or sAMAccountName - ex: uid ou sAMAccountName + Computer location attribute + Attribut d'emplacement d'ordinateur - Advanced settings - Paramétrages avancés + Location name attribute + Attribut de nom d'emplacement - Optional object filters - Filtres d'objet optionnel + users + utilisateurs - Filter for user groups - Filtre pour les groupes utilisateur + user groups + groupes d'utilisateurs - Filter for users - Filtre pour les utilisateurs + computers + ordinateurs + + + computer groups + groupes d'ordinateurs + + + computer containers + Conteneurs d'ordinateur + + + groups of user + groupes d'utilisateur + + + User not found + Utilisateur introuvable + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + Impossible de trouver un utilisateur dont le nom est "%1". Vérifiez le nom de l'utilisateur ou du paramètre d'arborescence utilisateur. + + + groups of computer + groupes d'ordinateur + + + Computer not found + Ordinateur introuvable + + + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Impossible de trouver un ordinateur dont le nom d'hôte est "%1". Vérifiez le nom d'hôte de l'ordinateur ou du paramètre d'arborescence ordinateur. + + + Hostname lookup failed + Échec de la recherche du nom d'hôte + + + Could not lookup hostname for IP address %1. Please check your DNS server settings. + Impossible de rechercher le nom d'hôte pour l'adresse IP %1. Veuillez vérifier le paramétrage de votre serveur DNS. + + + location entries + Entrées d'emplacement + + + Computer groups filter + Filtre des groupes d'ordinateurs + + + Computer locations identification + Identification des emplacements d'ordinateur Filter for computer groups Filtre pour les groupes d'ordinateurs - Group member identification - Identification du groupe membre + Invalid test value + Valeur test non valide - Distinguished name (Samba/AD) - Nom distinct (Samba/AD) + An empty or invalid value has been supplied for this test. + Une valeur vide ou invalide a été fournie pour ce test. - List all groups of a user - Lister tous les groupes d'un utilisateur + LDAP %1 test failed + Échec du test LDAP %1 - List all groups of a computer - Lister tous les groupes d'un ordinateur + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + Impossible d'interroger les entrées dans le "%1" configuré. Veuillez vérifier le paramètre "%2". + +%3 - Get computer object by IP address - Trouver un ordinateur par son adresse IP + LDAP %1 test successful + Le test LDAP %1 à réussi - LDAP connection failed - La connexion LDAP a échoué + The %1 has been queried successfully and %2 entries were found. + %1 a été interrogé avec succès et %2 entrée(s) ont été trouvée(s). - LDAP bind failed - Échec de l'authentification LDAP + LDAP test failed + Le test LDAP a échoué - LDAP bind successful - Authentification LDAP réussie + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + Impossible d'interroger les %1. Veuillez vérifier le(s) paramètre(s) %2 et entrez le nom d'un objet existant. + +%3 - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - La connexion au serveur LDAP ainsi que l'authentification LDAP ont été réussis. Les paramètres LDAP de base sont configurés convenablement. + and + et - LDAP base DN test failed - Échec du test base LDAP DN + LDAP test successful + Le test LDAP a réussi - LDAP base DN test successful - Le test base LDAP DN à réussi + %1 %2 have been queried successfully: + +%3 + %2 %1 a été interrogé avec succès : + +%3 - LDAP naming context test failed - Échec du test LDAP de nommage par contexte + LDAP filter test failed + Échec du test du filtre LDAP - LDAP naming context test successful - Le test LDAP de nommage par contexte à réussi. + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 + Impossible d'interroger %1 en utilisant le filtre configuré. Veuillez vérifier le filtre LDAP pour %1 + +%2 - The LDAP naming context has been queried successfully. The following base DN was found: -%1 - Le contexte de nommage LDAP à été interrogé avec succès. La base DN suivante à été trouvée: -%1 + LDAP filter test successful + Le test du filtre LDAP à réussi - user tree - arborescence utilisateur + %1 %2 have been queried successfully using the configured filter. + %2 %1 a été interrogé avec succès en appliquant le filtre. - group tree - arborescence groupe + LDAP directory + Annuaire LDAP + + + LdapConfigurationPage - computer tree - arborescence ordinateur + Basic settings + Paramètres généraux - Enter username - Entrer votre nom d'utilisateur + General + Général - Please enter a user login name (wildcards allowed) which to query: - Veuillez entrer un identifiant utilisateur (jokers autorisé ? *) à rechercher: + LDAP server and port + Port et serveur LDAP - user objects - objets utilisateur + Bind DN + Liaison DN - Enter group name - Entrer un nom de groupe + Bind password + Mot de passe lié - Please enter a group name whose members to query: - Veuillez entrer le nom d'un groupe dont vous recherchez les membres: + Anonymous bind + Liaison anonyme - group members - membres du groupe + Use bind credentials + Utiliser des informations d'identification par liaison - Group not found - Groupe introuvable + Base DN + Base DN - Could not find a group with the name "%1". Please check the group name or the group tree parameter. - Impossible de trouver un groupe avec le nom "%1". Veuillez vérifier le nom du groupe ou le paramètre de l'arborescence du groupe. + Fixed base DN + Base DN Fixe - Enter computer name - Entrer un nom d'ordinateur + e.g. dc=example,dc=org + ex: dc=exemple, dc=org - computer objects - objets ordinateur + Discover base DN by naming context + Explorer la base DN à partir d'un contexte de nommage - Enter computer DN - Entrer le DN de l'ordinateur + e.g. namingContexts or defaultNamingContext + ex: ContextesNommés ou ContexteNomméParDéfaut - Please enter the DN of a computer whose MAC address to query: - Veuillez entrer le DN d'un ordinateur dont vous recherchez l'adresse MAC: + Environment settings + Paramètres d'environnement - computer MAC addresses - Adresse MAC de l'ordinateur + Object trees + Arborescence objet - users - utilisateurs + Computer tree + Arborescence ordinateur - user groups - groupes d'utilisateurs + e.g. OU=Groups + ex: OU=Groupes - computer groups - groupes d'ordinateurs + User tree + Arborescence utilisateur - Please enter a user login name whose group memberships to query: - Veuillez entrer l'identifiant dont vous recherchez les groupes d'appartenance: + e.g. OU=Users + ex: OU=Utilisateurs - groups of user - groupes d'utilisateur + e.g. OU=Computers + ex: OU=Ordinateurs - User not found - Utilisateur introuvable + Group tree + Arborescence groupe - groups of computer - groupes d'ordinateur + Perform recursive search operations in object trees + Effectuer des recherches récursives dans les arborescences objet - Computer not found - Ordinateur introuvable + Object attributes + Attributs d'objet - Enter computer IP address - Entrer l'adresse IP de l'ordinateur + e.g. hwAddress + ex: Adressehw - Please enter a computer IP address which to resolve to an computer object: - Veuillez entrer une adresse IP pour trouver un ordinateur: + e.g. member or memberUid + ex: membre ou surnom - computers - ordinateurs + e.g. dNSHostName + ex: NomHotedNS - LDAP %1 test failed - Échec du test LDAP %1 + Computer MAC address attribute + Attribut de l'adresse MAC de l'ordinateur + + + Group member attribute + Attribut du groupe membre + + + e.g. uid or sAMAccountName + ex: uid ou sAMAccountName + + + Advanced settings + Paramétrages avancés + + + Optional object filters + Filtres d'objet optionnel + + + Filter for user groups + Filtre pour les groupes utilisateur + + + Filter for users + Filtre pour les utilisateurs + + + Filter for computer groups + Filtre pour les groupes d'ordinateurs + + + Group member identification + Identification du groupe membre + + + Distinguished name (Samba/AD) + Nom distinct (Samba/AD) + + + List all groups of a user + Lister tous les groupes d'un utilisateur + + + List all groups of a computer + Lister tous les groupes d'un ordinateur + + + Get computer object by IP address + Trouver un ordinateur par son adresse IP + + + Enter username + Entrer votre nom d'utilisateur + + + Please enter a user login name (wildcards allowed) which to query: + Veuillez entrer un identifiant utilisateur (jokers autorisé ? *) à rechercher : + + + Enter group name + Entrer un nom de groupe - LDAP %1 test successful - Le test LDAP %1 à réussi + Please enter a group name whose members to query: + Veuillez entrer le nom d'un groupe dont vous recherchez les membres : - The %1 has been queried successfully and %2 entries were found. - %1 a été interrogé avec succès et %2 entrée(s) ont été trouvée(s). + Enter computer name + Entrer un nom d'ordinateur - %1 %2 have been queried successfully: - -%3 - %2 %1 a été interrogé avec succès: - -%3 + Enter computer DN + Entrer le DN de l'ordinateur - LDAP filter test failed - Échec du test du filtre LDAP + Please enter the DN of a computer whose MAC address to query: + Veuillez entrer le DN d'un ordinateur dont vous recherchez l'adresse MAC : - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 - Impossible d'interroger %1 en utilisant le filtre configuré. Veuillez vérifier le filtre LDAP pour %1 - -%2 + Please enter a user login name whose group memberships to query: + Veuillez entrer l'identifiant dont vous recherchez les groupes d'appartenance : - LDAP filter test successful - Le test du filtre LDAP à réussi + Enter computer IP address + Entrer l'adresse IP de l'ordinateur - %1 %2 have been queried successfully using the configured filter. - %2 %1 a été interrogé avec succès en appliquant le filtre. + Please enter a computer IP address which to resolve to an computer object: + Veuillez entrer une adresse IP pour trouver un ordinateur : (only if different from group tree) @@ -2167,10 +2817,6 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Computer group tree Arborescence groupe ordinateur - - computer group tree - arborescence groupe ordinateur - Filter for computers Filtre pour les ordinateurs @@ -2251,50 +2897,10 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif e.g. (objectClass=container) or (objectClass=organizationalUnit) ex: (ClasseObjet=container) ou (ClasseObjet=Unité d'Organisation) - - Could not query the configured base DN. Please check the base DN parameter. - -%1 - Impossible d'interroger la base DN ainsi configurée. Veuillez vérifier les paramètres de la base DN. - -%1 - - - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - La base LDAP DN a été interrogée avec succès. Les entrées suivantes ont été trouvées: - -%1 - - - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - Impossible d'interroger la base DN via des contextes de nommage. Veuillez vérifier l'attribut du paramètre de contexte de nommage. - -%1 - Certificate files (*.pem) Fichiers de certificats (*.pem) - - Could not connect to the LDAP server. Please check the server parameters. - -%1 - Impossible de se connecter au serveur LDAP. Veuillez vérifier les paramètres du serveur. - -%1 - - - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - Authentification au serveur LDAP impossible. Veuillez vérifier les paramètres du serveur et les informations d'identification. - -%1 - Encryption protocol Protocole de cryptage @@ -2321,7 +2927,7 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Identify computer locations (e.g. rooms) via: - Identifier des emplacements ordinateur (ex salles) via: + Identifier des emplacements ordinateur (ex salles) via : Location attribute in computer objects @@ -2341,7 +2947,7 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Please enter a computer display name to query: - Veuillez entrer un nom d'affichage d'ordinateur à interroger: + Veuillez entrer un nom d'affichage d'ordinateur à interroger : Enter computer location name @@ -2349,11 +2955,7 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Please enter the name of a computer location (wildcards allowed): - Veuillez entrer le nom d'un emplacement d'ordinateur (jokers autorisés): - - - computer locations - Emplacements d'ordinateur + Veuillez entrer le nom d'un emplacement d'ordinateur (jokers autorisés) : Enter location name @@ -2361,39 +2963,7 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Please enter the name of a location whose entries to query: - Veuillez entrer le nom d'un emplacement dont les entrées sont à interroger. - - - location entries - Entrées d'emplacement - - - LDAP test failed - Le test LDAP a échoué - - - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - Impossible d'interroger les %1. Veuillez vérifier le(s) paramètre(s) %2 et entrez le nom d'un objet existant. - -%3 - - - and - et - - - LDAP test successful - Le test LDAP a réussi - - - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - Impossible d'interroger les entrées dans le "%1" configuré. Veuillez vérifier le paramètre "%2". - -%3 + Veuillez entrer le nom d'un emplacement dont les entrées sont à interroger : Browse @@ -2405,318 +2975,121 @@ La clé publique est utilisée sur les ordinateurs clients pour l'authentif Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - Noms d'hôtes enregistrés comme des noms de domaine pleinement nommé (FQDN, ex: monhote.exemple.org) - - - Computer hostname attribute - Attribut du nom d'hôte de l'ordinateur - - - Please enter a computer hostname to query: - Veuillez entrer un nom d'ordinateur hôte à rechercher: - - - Invalid hostname - Nom d'hôte invalide - - - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Vous avez choisi de stocker les noms d'ordinateurs hôtes comme des noms de domaine pleinement nommé (FQDN) mais vous avez saisi un nom d'hôte sans domaine. - - - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - Vous avez choisi de stocker les noms d'ordinateurs hôtes comme de simple noms d'hôte sans nom de domaine, mais vous avez saisi un nom d'hôte dont une partie est un nom de domaine. - - - Could not find a user with the name "%1". Please check the username or the user tree parameter. - Impossible de trouver un utilisateur dont le nom est "%1". Vérifiez le nom de l'utilisateur ou du paramètre d'arborescence utilisateur. - - - Enter hostname - Entrer nom d'hôte - - - Please enter a computer hostname whose group memberships to query: - Veuillez entrer un nom d’hôte pour l’ordinateur appartenant au groupe à interroger - - - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - Impossible de trouver un ordinateur dont le nom d'hôte est "%1". Vérifiez le nom d'hôte de l'ordinateur ou du paramètre d'arborescence ordinateur. - - - Hostname lookup failed - Échec de la recherche du nom d'hôte - - - Could not lookup hostname for IP address %1. Please check your DNS server settings. - Impossible de rechercher le nom d'hôte pour l'adresse IP %1. Veuillez vérifier le paramétrage de votre serveur DNS. - - - User login name attribute - Attribut de l'identifiant utilisateur - - - Configured attribute for user login name or computer hostname (OpenLDAP) - Attribut configuré pour l'identifiant utilisateur ou le nom d'hôte de l'ordinateur (OpenLDAP) - - - computer containers - Conteneurs d'ordinateur - - - - LdapPlugin - - Auto-configure the base DN via naming context - Auto configurer la base DN à partir d'un contexte de nommage - - - Query objects from LDAP directory - Requête d'objets depuis l'annuaire LDAP - - - Show help about command - Afficher la commande aide et à propos - - - Commands for configuring and testing LDAP/AD integration - Commandes pour configurer et tester l'intégration LDAP/AD - - - Basic LDAP/AD support for Veyon - Support LDAP/AD basique pour Veyon - - - %1 (load computers and locations from LDAP/AD) - %1 (charger les ordinateurs et les emplacements depuis LDAP/AD) - - - %1 (load users and groups from LDAP/AD) - %1 (charger les utilisateurs et les groupes depuis LDAP/AD) - - - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - Veuillez spécifier une url LDAP valide en suivant ce schéma "ldap[s]://[user[:password]@]hostname[:port]" - - - No naming context attribute name given - falling back to configured value. - Aucun attribut de nom de contexte de nommage n'a été donné - retour à la valeur configurée. - - - Could not query base DN. Please check your LDAP configuration. - Impossible d'interroger la base DN (Nom Domaine). Veuillez vérifier votre configuration LDAP. - - - Configuring %1 as base DN and disabling naming context queries. - Configuration de %1 en tant que base DN et désactivation des requêtes de contexte de dénomination. - - - - LdapProConfigurationPage - - LDAP Pro - LDAP Pro - - - Instances - Instances - - - Enter name - Entrer un nom - - - Please enter a name for the instance (can't be changed later!): - Veuillez entrer un nom pour l'instance (celui-ci ne pourra pas être changer plus tard!): - - - Remove instance - Retirer l'instance - - - Do you really want to remove instance "%1"? - Voulez-vous vraiment retirer l'instance "%1"? - - - Configuration for instance "%1" - Configuration pour l'instance "%1" - - - - LdapProPlugin - - Professional LDAP/AD integration for Veyon - Intégration LDAP/AD professionnelle pour Veyon - - - %1 (load computers and locations from LDAP/AD) - %1 (charger les ordinateurs et les emplacements depuis LDAP/AD) - - - %1 (load users and groups from LDAP/AD) - %1 (charger les utilisateurs et les groupes depuis LDAP/AD) - - - - LicensingConfigurationPage - - Licensing - Licence - - - Installed licenses - Licences installées - - - Add new network range - Ajouter une nouvelle plage réseau - - - Remove selected network range - Supprimer la plage réseau sélectionnée - - - ID - ID - - - Feature - Fonctionnalité - - - Valid until - Valable jusqu'à + Noms d'hôtes enregistrés comme des noms de domaine pleinement nommé (FQDN, ex: monhote.exemple.org) - Licensee - Licencié + Computer hostname attribute + Attribut du nom d'hôte de l'ordinateur - Browse license file - Parcourir fichier licence + Please enter a computer hostname to query: + Veuillez entrer un nom d'ordinateur hôte à rechercher : - Veyon license files (*.vlf) - Fichiers licence Veyon (*.vlf) + Enter hostname + Entrer nom d'hôte - Remove license - Retirer licence + Please enter a computer hostname whose group memberships to query: + Veuillez entrer un nom d’hôte pour l’ordinateur appartenant au groupe à interroger : - Do you really want to remove the selected license? - Voulez-vous réellement retirer la licence sélectionnée ? + User login name attribute + Attribut de l'identifiant utilisateur - <N/A> - < Sans Objet > + Configured attribute for user login name or computer hostname (OpenLDAP) + Attribut configuré pour l'identifiant utilisateur ou le nom d'hôte de l'ordinateur (OpenLDAP) - Invalid license file - Fichier licence invalide + Directory name + Nom du répertoire - Could not open the license file for reading! - Impossible d'ouvrir le fichier licence en lecture ! + Query options + Options de requête - The selected license file does not contain valid data. - Le fichier de licence sélectionné ne contient pas de données valides. + Query nested user groups (supported by AD only) + Interroger des groupes d'utilisateurs imbriqués (pris en charge par AD uniquement) - The selected license file could not be verified. - Le fichier de licence sélectionné n'a pas pu être vérifié. + Query timeout + Délai d'expiration de la requête - The selected license file is not valid for this installation. - Le fichier de licence sélectionné n'est pas valide pour cette installation. + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. - Le fichier de licence sélectionné a expiré. + LDAP + LDAP - The license is already installed. - La licence est déjà installée. + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + Veuillez utiliser la page de configuration LDAP globale pour configurer comment récupérer les emplacements et les ordinateurs de votre service d'annuaire LDAP. + + + LdapPlugin - Information - Information + Auto-configure the base DN via naming context + Auto configurer la base DN à partir d'un contexte de nommage - Installation ID - Identité installation + Query objects from LDAP directory + Requête d'objets depuis l'annuaire LDAP - Addons available for licensing - Extensions disponibles pour licence + Show help about command + Afficher la commande aide et à propos - Addon - Extension + Commands for configuring and testing LDAP/AD integration + Commandes pour configurer et tester l'intégration LDAP/AD - - - LicensingPlugin - Show help for specific command - Affiche l'aide pour une commande spécifique + Basic LDAP/AD support for Veyon + Support LDAP/AD basique pour Veyon - Show all installed licenses - Afficher toutes les licences installées + %1 (load computers and locations from LDAP/AD) + %1 (charger les ordinateurs et les emplacements depuis LDAP/AD) - Add license file - Ajouter un fichier de licence + %1 (load users and groups from LDAP/AD) + %1 (charger les utilisateurs et les groupes depuis LDAP/AD) - Remove installed license - Supprimer la licence installée + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Veuillez spécifier une url LDAP valide en suivant ce schéma "ldap[s]://[user[:password]@]hostname[:port]" - -USAGE - -%1 add <LICENSE FILE> - - - -USAGE - -%1 add <LICENSE FILE> - - + No naming context attribute name given - falling back to configured value. + Aucun attribut de nom de contexte de nommage n'a été donné - retour à la valeur configurée. - -USAGE - -%1 remove <LICENSE ID> - - - -USAGE - -%1 remove <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. + Impossible d'interroger la base DN (Nom Domaine). Veuillez vérifier votre configuration LDAP. - No certificate found with given ID - Aucun certificat trouvé avec l'ID donné + Configuring %1 as base DN and disabling naming context queries. + Configuration de %1 en tant que base DN et désactivation des requêtes de contexte de dénomination. - <N/A> - < Sans Objet > + Test binding to an LDAP server + Tester la liaison à un serveur LDAP - Licensing management - Gestion des licences + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Le nom d'utilisateur ou le mot de passe fourni est incorrect. Veuillez entrer des informations d'identification valides ou passer par une méthode d'authentification différente à l'aide du configurateur Veyon. - Commands for managing license keys - Commandes de gestion des clés de licence + LDAP bind + Liaison LDAP @@ -2734,12 +3107,20 @@ USAGE Authentification utilisateur - Session management - Gestion de session + User sessions + Sessions utilisateurs - Display manager users - Gestionnaire d'affichage utilisateurs + Minimum session lifetime before server start + Durée de vie minimale de la session avant le démarrage du serveur + + + User login + Identifiant utilisateur + + + Login key sequence + Séquence de touches de connexion @@ -2748,10 +3129,6 @@ USAGE Plugin implementing abstract functions for the Linux platform Extension implémentant les fonctions abstraites pour le système Linux - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2770,14 +3147,14 @@ USAGE Configuration Configuration - - Disable balloon tooltips - Désactiver les info-bulles - Show icons only Afficher seulement les icônes + + Disable tooltips + Désactiver les info-bulles + MainWindow @@ -2825,10 +3202,6 @@ USAGE About Qt À propos de QT - - Authentication impossible - Authentification impossible - Configuration not writable Impossible d'enregistrer la configuration @@ -2889,10 +3262,6 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. Le processus de configuration locale rapporte que le fichier de configuration ne peut pas s'enregistrer! Veuillez exécuter la console de gestion %1 avec des droits plus importants. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - Aucune clés d'authentification n'ont été trouvées ou bien les clés actuelles sont obsolètes. Veuillez créer de nouvelles clés en utilisant la Console de gestion %1. Sinon, vous pouvez paramétrer l'authentification par l'identifiant en utilisant également la Console de gestion %1. Sans cela, vous ne serez pas en mesure d'accéder aux ordinateurs en utilisant %1. - Access denied Accès refusé @@ -2915,20 +3284,16 @@ USAGE Reset configuration - Reset de la configuration + Réinitialisation de la configuration Do you really want to reset the local configuration and revert all settings to their defaults? - Voulez-vous vraiment reset la configuration locale et restaurer tous les paramètres à leurs valeurs par défaut ? + Souhaitez-vous vraiment réinitialiser la configuration locale et restaurer tous les paramètres à leurs valeurs par défaut ? Search users and computers Chercher des utilisateurs et des ordinateurs - - Adjust optimal size - Ajuster la taille optimale - Align computers to grid Aligner les ordinateurs sur la grille @@ -2973,6 +3338,48 @@ USAGE Locations && computers Emplacements && ordinateurs + + Authentication + Authentification + + + Adjust size of computer icons automatically + Ajuster automatiquement la taille des icônes d'ordinateur + + + Slideshow + Diaporama + + + Spotlight + Focalisation + + + Veyon Master + Veyon Maître + + + Locations & computers + Emplacements & ordinateurs + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + Afficher uniquement les ordinateurs avec des utilisateurs connectés + + + Load computer positions + + + + Save computer positions + + MasterConfigurationPage @@ -2980,17 +3387,13 @@ USAGE Directories Répertoires - - ... - ... - User configuration Configuration utilisateur Feature on computer double click: - Action au double clique sur un ordinateur: + Action au double clique sur un ordinateur : Features @@ -3042,7 +3445,7 @@ USAGE Background color - Couleur de fond + Couleur d'arrière plan Thumbnail update interval @@ -3058,7 +3461,7 @@ USAGE Modes and features - Modes et paramétrages + Modes et fonctionnalités User and computer name @@ -3066,7 +3469,11 @@ USAGE Only user name - Nom d'utilisateur seulement + Uniquement le nom d'utilisateur + + + Only last part of user name + Uniquement la dernière partie du nom d'utilisateur Only computer name @@ -3116,171 +3523,181 @@ USAGE Automatically select current location Sélectionner automatiquement la localisation courante - - Automatically adjust computer thumbnail size - Ajuster automatiquement la taille des prévues ordinateurs - Automatically open computer select panel Ouvrir automatiquement le panneau de sélection ordinateur - - - MonitoringMode - Monitoring - Surveiller + Use modern user interface (experimental) + Utiliser une interface utilisateur moderne (expérimentale) - Builtin monitoring mode - mode de surveillance intégré + Thumbnail spacing + Espacement des miniatures - This mode allows you to monitor all computers at one or more locations. - Ce mode vous permet de surveiller tous les ordinateurs d'un ou de plusieurs emplacements. + px + px - - - NetworkDiscoveryConfigurationPage - Network discovery - Découverte du réseau + Hide local session + Masquer la session locale - Mode - Mode + Auto + Auto - Scan network ranges - Scanner des plages réseau + Thumbnail aspect ratio + Rapport hauteur / largeur de la miniature - e.g. 192.168.1.0/24 - ex: 192.168.1.0/24 + Automatically adjust computer icon size + Ajuster automatiquement la taille de l'icône de l'ordinateur - Scan all subnets of computer - Scanner tous les sous-réseaux de l'ordinateur + Open feature windows on the same screen as the main window + Ouvrir les fenêtres de fonctionnalités sur le même écran que la fenêtre principale - Scan custom subnet - Scanner un sous-réseau personnalisé + Configuration templates + - Scan sessions on local computer - Scanner les sessions sur l'ordinateur local + Image quality in monitoring mode + Qualité d'image en mode surveillance - Test - Test + Highest + Supérieure + + + High + Élevée - Network ranges - Plages réseau + Medium + Moyenne - Add new group - Ajouter un nouveau groupe + Low + Basse - Remove selected group - Supprimer le groupe sélectionné + Lowest + La plus basse - Groups - Groupes + Remote access image quality + Qualité de l'image de l'accès à distance - First address - Première adresse + Advanced + - Last address - Dernière adresse + Computer name source + - Add new network range - Ajouter une nouvelle plage réseau + Default + - Remove selected network range - Supprimer la plage réseau sélectionnée + Host address + Adresse hôte - Parallel scans - Scans parallèles + Session client address + Adresse du client de la session - Scan timeout - Analyse temps mort + Session client name + Nom du client de la session - ms - ms + Session host name + - Session scan limit - Limite d'analyse de session + Session metadata + - Options - Options + Full name of user + Nom complet de l'utilisateur - Reverse lookup discovered IP addresses to host names - Recherche inversée des adresses IP découvertes en noms d'hôte + User login name + Identifiant utilisateur - New location - Nouvel emplacement + Computer UID role + + + + Session meta data hash + - - - NetworkDiscoveryDirectory - Scanning... - Scan... + Always expand all locations + - Discovered computers - Ordinateurs découverts + Image quality + Qualité d'image - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command - Affiche l'aide pour une commande spécifique + Monitoring + Surveiller - Scan a subnet - Scanner un sous-réseau + Builtin monitoring mode + mode de surveillance intégré - -USAGE - -%1 scan [<SUBNET>] - - - -USAGE - -%1 scan [<SUBNET>] - - + This mode allows you to monitor all computers at one or more locations. + Ce mode vous permet de surveiller tous les ordinateurs d'un ou de plusieurs emplacements. + + + Query application version of the server + Interroger la version de l'application du serveur + + + Query active features + Interroger les fonctionnalités actives + + + Query properties of remotely available screens + Interroger les propriétés des écrans distants disponibles + + + NestedNetworkObjectDirectory + + All directories + Tous les répertoires + + + + NetworkObjectDirectoryConfigurationPage - Network object directory which automatically discovers computers in the network - Répertoire d'objets réseau qui détecte automatiquement les ordinateurs du réseau + Update interval: + Intervalle de rafraichissement : - Network discovery (scan network for Veyon clients) - Découverte du réseau (analyse du réseau pour les clients Veyon) + seconds + secondes + + + NetworkObjectDirectoryConfigurationPageTab - Commands for managing the network discovery directory - Commandes de gestion de la découverte réseau + Enabled + Activé @@ -3310,38 +3727,50 @@ USAGE Please enter the URL of the website to open: - Veuillez entrer l'URL du site internet à ouvrir: + Veuillez entrer l'URL du site internet à ouvrir : Name: - Nom: + Nom : + + + Website name + Nom de site internet - PasswordDialog + PluginCommands - Username - Identifiant + List names of all installed plugins + Lister les noms de tous les greffons installés - Password - Mot de passe + Show table with details of all installed plugins + Afficher un tableau avec les détails de tous les plugins installés - Veyon Logon - Connexion Veyon + Name + Nom - Authentication error - Erreur d'authentification + Description + Description - Logon failed with given username and password. Please try again! - La connexion a échoué avec le nom d'utilisateur et le mot de passe donné. Veuillez réessayer! + Version + Version - Please enter your username and password in order to access computers. - Veuillez entrer votre identifiant et votre mot de passe afin d'accéder aux ordinateurs. + UID + UID + + + Plugin-related CLI operations + Greffons liés aux opérations CLI + + + Commands for managing plugins + Commandes pour gérer les greffons @@ -3386,10 +3815,6 @@ USAGE Do you really want to reboot the selected computers? Souhaitez-vous réellement redémarrer les ordinateurs sélectionnés ? - - Do you really want to power down the selected computer? - Souhaitez-vous réellement éteindre les ordinateurs sélectionnés ? - Power on a computer via Wake-on-LAN (WOL) Allumer un ordinateur via Wake-on-LAN (WOL) @@ -3442,6 +3867,18 @@ Please save your work and close all programs. Veuillez sauvegarder votre travail et fermer tous les programmes. + + Do you really want to reboot <b>ALL</b> computers? + Souhaitez-vous vraiment redémarrer <b>TOUS</b> les ordinateurs? + + + Do you really want to power down <b>ALL</b> computers? + Souhaitez-vous vraiment éteindre <b>TOUS</b> les ordinateurs? + + + Do you really want to power down the selected computers? + Souhaitez-vous vraiment éteindre les ordinateurs sélectionnés? + PowerDownTimeInputDialog @@ -3451,7 +3888,7 @@ Veuillez sauvegarder votre travail et fermer tous les programmes. Please specify a timeout for powering down the selected computers: - Veuillez spécifier un délai d'attente pour éteindre les ordinateurs sélectionnés: + Veuillez spécifier un délai d'attente pour éteindre les ordinateurs sélectionnés : minutes @@ -3488,14 +3925,25 @@ Veuillez sauvegarder votre travail et fermer tous les programmes. Remote view or control a computer Vue à distance ou contrôle de l'ordinateur - - Please enter the hostname or IP address of the computer to access: - Pour accéder, veuillez entrer le nom de l'hôte ou l'adresse IP de l'ordinateur: - Show help about command Afficher la commande aide et à propos + + Exchange clipboard contents + Échanger le contenu du presse-papiers + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + Aucun ordinateur n'a été sélectionné, vous pouvez donc saisir le nom d'hôte ou l'adresse IP d'un ordinateur pour un accès manuel : + + + + RemoteAccessPage + + Remote access: %1 + Accès à distance : %1 + RemoteAccessWidget @@ -3503,6 +3951,10 @@ Veuillez sauvegarder votre travail et fermer tous les programmes. %1 - %2 Remote Access %1 - %2 Accès distant + + %1 - %2 - %3 Remote Access + %1 - %2 - %3 Accès à distance + RemoteAccessWidgetToolBar @@ -3558,10 +4010,6 @@ Veuillez sauvegarder votre travail et fermer tous les programmes. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - Connexion à %1... - Connected. Connecté. @@ -3574,58 +4022,17 @@ Veuillez sauvegarder votre travail et fermer tous les programmes. Exit Quitter - - - Routing - - Control internet access by modifying routing table - Contrôle de l'accès internet par modification de la table de routage - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - Supprimer le routage par défaut pour bloquer internet - - - Add custom route to block internet - Ajouter un routage personnalisé pour bloquer internet - - - Destination - Destination - - - Gateway - Passerelle - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - Veuillez entrer les programmes ou les commandes à exécuter sur les ordinateurs sélectionnés. Vous pouvez séparer vos différents programmes/commandes ligne par ligne. - - - Run programs - Exécuter des programmes - - - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - ex: "C:\Program Files\VideoLAN\VLC\vlc.exe" - - Name: - Nom: + Connecting... + En cours de connexion - Remember and add to program menu - Mémoriser et ajouter au menu du programme + Select screen + Sélectionner l'écran - e.g. VLC - ex: VLC + All screens + Tous les écrans @@ -3643,8 +4050,20 @@ Veuillez sauvegarder votre travail et fermer tous les programmes. Verrouiller l'écran et les périphériques d'entrée d'un ordinateur - To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. - Pour attirer toute l'attention de tous les utilisateurs, vous pouvez verrouiller les ordinateurs en utilisant ce bouton. Dans ce mode, tous les périphériques d'entrée sont verrouillés et l'écran est noir. + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + Pour attirer toute l'attention de tous les utilisateurs, vous pouvez verrouiller les ordinateurs en utilisant ce bouton. Dans ce mode, tous les périphériques d'entrée sont verrouillés et l'écran est noir. + + + Lock input devices + Verrouiller les périphériques d'entrée + + + Unlock input devices + Déverrouiller les périphériques d'entrée + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + Pour conserver toute l'attention de tous les utilisateurs, vous pouvez verrouiller leurs ordinateurs à l'aide de ce bouton. Dans ce mode, tous les périphériques d'entrée sont verrouillés tandis que le bureau est toujours visible. @@ -3661,6 +4080,10 @@ Veuillez sauvegarder votre travail et fermer tous les programmes. Screenshot Capture d'écran + + Could not open screenshot file %1 for writing. + Impossible d'ouvrir le fichier de capture d'écran "%1" pour écrire! + ScreenshotFeaturePlugin @@ -3685,6 +4108,13 @@ Veuillez sauvegarder votre travail et fermer tous les programmes. Prend des captures d'écran des ordinateurs et les enregistre localement. + + ScreenshotManagementPage + + Screenshots + Captures d'écrans + + ScreenshotManagementPanel @@ -3693,19 +4123,19 @@ Veuillez sauvegarder votre travail et fermer tous les programmes. User: - Utilisateur: + Utilisateur : Computer: - Ordinateur: + Ordinateur : Date: - Date: + Date : Time: - Heure: + Heure : Show @@ -3715,6 +4145,45 @@ Veuillez sauvegarder votre travail et fermer tous les programmes. Delete Supprimer + + Screenshot + Capture d'écran + + + Do you really want to delete all selected screenshots? + Souhaitez-vous vraiment supprimer toutes les captures d'écran sélectionnées? + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + + + + User has denied access + + + + User confirmed access + + ServiceConfigurationPage @@ -3746,14 +4215,6 @@ Veuillez sauvegarder votre travail et fermer tous les programmes. State: État : - - Network - Réseau - - - Demo server port - Port du serveur de démonstration - Enable firewall exception Autoriser une exception pour le pare-feu @@ -3762,17 +4223,13 @@ Veuillez sauvegarder votre travail et fermer tous les programmes. Allow connections from localhost only Autoriser les connexions seulement à partir de l'hôte local - - Internal VNC server port - Port du serveur interne VNC - VNC server Serveur VNC Plugin: - Extension: + Extension : Restart %1 Service @@ -3784,15 +4241,7 @@ Veuillez sauvegarder votre travail et fermer tous les programmes. Running - En cours - - - Feature manager port - Port du gestionnaire de fonction - - - Primary service port - Port de service primaire + En cours d’exécution Enabling this option will make the service launch a server process for every interactive session on a computer. @@ -3804,52 +4253,130 @@ Généralement, ceci est nécessaire pour prendre en charge les serveurs de term Show notification on remote connection Afficher la notification sur la connexion à distance - - Multi session mode (for terminal and remote desktop servers) - Mode multi-session (pour les serveurs de bureau terminaux et distants) - Show notification when an unauthorized access is blocked Afficher une notification quand un accès non autorisé est bloqué - - - ServiceControl - Starting service %1 - Démarrage du service %1 + Maximum session count + Nombre maximum de sessions - Stopping service %1 - Arrêt du service %1 + Network port numbers + Numéros de port réseau - Registering service %1 - Inscription du service %1 + Veyon server + serveur Veyon - Unregistering service %1 - Déinscription du service %1 + Internal VNC server + Serveur VNC interne - Service control - Contrôle du service + Feature manager + Gestionnaire de fonctionnalités + + + Demo server + Serveur de démo + + + Miscellaneous network settings + Divers paramètres réseau + + + Session mode + Mode Session + + + Local session mode (single server instance for primary local session) + Mode session locale (instance de serveur unique pour la session locale principale) + + + Active session mode (single server instance for active local or remote session) + Mode session active (instance de serveur unique pour une session locale ou distante active) + + + Multi session mode (distinct server instance for each local and remote desktop session) + Mode multi-session (instance de serveur distincte pour chaque session de bureau local et distant) + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + + + + Miscellaneous settings + Paramètres divers + + + Disable clipboard synchronization + + + + Session metadata + + + + Content + + + + None + Aucun + + + Value of an environment variable + + + + Value of a registry key + + + + Environment variable name: + Nom de la variable d'environnement: + + + Registry key name: + + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + - ServiceControlPlugin + ServiceControl - Service is running - Le service fonctionne + Service control + Contrôle du service - Service is not running - Le service ne fonctionne pas + Starting %1 + - Configure and control Veyon service - Configure et contrôle le service Veyon + Stopping %1 + + + Restarting %1 + + + + Registering %1 + + + + Unregistering %1 + + + + + ServiceControlCommands Register Veyon Service Inscription du service Veyon @@ -3874,13 +4401,25 @@ Généralement, ceci est nécessaire pour prendre en charge les serveurs de term Query status of Veyon Service Interrogation du statut du service Veyon + + Service is running + Le service est en cours d’exécution + + + Service is not running + Le service n'est pas en fonctionnement + + + Configure and control Veyon service + Configure et contrôle le service Veyon + Commands for configuring and controlling Veyon Service Commandes pour configurer et contrôler le Service Veyon - ShellCommandLinePlugin + ShellCommands Run command file Lance un fichier de commande @@ -3890,14 +4429,101 @@ Généralement, ceci est nécessaire pour prendre en charge les serveurs de term Le fichier "%1" n'existe pas. - Interactive shell and script execution for Veyon Control - Terminal interactif et script d'exécution pour le Contrôle de Veyon + Interactive shell and script execution for Veyon CLI + Shell interactif et exécution de script pour Veyon CLI Commands for shell functionalities Commandes pour les fonctionnalités du terminal + + SlideshowPanel + + Previous + Précédent + + + Start/pause + Démarrage/pause + + + Next + Suivant + + + Duration: + Durée : + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + Ajouter les ordinateurs sélectionnés + + + Remove selected computers + Supprimer les ordinateurs sélectionnés + + + Update computers in realtime + Mettre à jour les ordinateurs en temps réel + + + Spotlight + Focalisation + + + Please select at least one computer to add. + Veuillez sélectionner au moins un ordinateur à ajouter. + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + Ajoutez des ordinateurs en cliquant avec le bouton central de la souris ou en cliquant sur le premier bouton ci-dessous. +Le deuxième bouton supprime l'ordinateur sélectionné ou le dernier ordinateur. + + + + StartAppDialog + + Start application + Démarrer l'application + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + Veuillez entrer les applications à démarrer sur les ordinateurs sélectionnés. Vous pouvez séparer plusieurs applications en les inscrivant sur chaque ligne. + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + ex: "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + Se souvenir et ajouter au menu de l'application + + + Application name + Nom d'application + + + Name: + Nom : + + + e.g. VLC + ex: VLC + + SystemTrayIcon @@ -3934,8 +4560,8 @@ Généralement, ceci est nécessaire pour prendre en charge les serveurs de term Envoyer un message écrit - Use the field below to type your message which will be sent to all selected users. - Utilisez le champ ci-dessous pour saisir votre message, il sera envoyé à tous les utilisateurs sélectionnés. + Please enter your message which send to all selected users. + Veuillez saisir votre message qui sera envoyé à tous les utilisateurs sélectionnés. @@ -3983,23 +4609,39 @@ Généralement, ceci est nécessaire pour prendre en charge les serveurs de term Enable Desktop Duplication Engine on Windows 8 and newer Activer le processus de duplication du bureau sur Windows 8 ou supérieur + + Maximum CPU usage + Utilisation maximale du processeur + - UserConfig + UserLoginDialog - No write access - Pas d'accès en écriture + User login + Identifiant utilisateur - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - Impossible de sauvegarder vos paramétrages! Veuillez vérifier le chemin du fichier de configuration utilisateur en utilisant la console de gestion %1 + Please enter a username and password for automatic login on all computers. + Saisissez ici votre identifiant utilisateur et votre mot de passe pour la connexion automatique à toutes les stations. + + + Username + Identifiant + + + Password + Mot de passe - UserSessionControl + UserSessionControlPlugin - User session control - Contrôle de session utilisateur + Log in + Connexion + + + Click this button to log in a specific user on all computers. + Cliquez sur ce bouton pour connecter un utilisateur spécifique sur toutes les stations. Log off @@ -4017,6 +4659,14 @@ Généralement, ceci est nécessaire pour prendre en charge les serveurs de term Do you really want to log off the selected users? Souhaitez-vous vraiment déconnecter l'utilisateur sélectionné ? + + User session control + Contrôle de session utilisateur + + + Do you really want to log off <b>ALL</b> users? + Souhaitez-vous vraiment déconnecter <b>TOUS</b> les utilisateurs? + VeyonCore @@ -4034,7 +4684,7 @@ Généralement, ceci est nécessaire pour prendre en charge les serveurs de term Available commands: - Commandes disponibles: + Commandes disponibles : Invalid arguments given @@ -4050,11 +4700,11 @@ Généralement, ceci est nécessaire pour prendre en charge les serveurs de term Available modules: - Modules disponibles: + Modules disponibles : No module specified or module not found - available modules are: - Aucun module spécifié ou module non trouvé - les modules disponibles sont: + Aucun module spécifié ou module non trouvé - les modules disponibles sont : Plugin not licensed @@ -4068,10 +4718,6 @@ Généralement, ceci est nécessaire pour prendre en charge les serveurs de term ERROR ERREUR - - licensed for - sous licence pour - USAGE USAGE @@ -4088,19 +4734,31 @@ Généralement, ceci est nécessaire pour prendre en charge les serveurs de term WARNING ATTENTION + + Authentication test + Test d'authentification + + + Screen %1 + Écran %1 + - VeyonServiceControl + VeyonMaster - Veyon Service - Service Veyon + No write access + Pas d'accès en écriture + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Impossible de sauvegarder vos paramétrages! Veuillez vérifier le chemin du fichier de configuration utilisateur en utilisant la console de gestion %1 - VncView + VeyonServiceControl - Establishing connection to %1 ... - Établissement de la connexion à %1 ... + Veyon Service + Service Veyon @@ -4148,6 +4806,30 @@ Généralement, ceci est nécessaire pour prendre en charge les serveurs de term Use alternative user authentication mechanism Utiliser une autre méthode pour l'authentification de l'utilisateur + + User login + Identifiant utilisateur + + + Input start delay + Délai de démarrage de l'entrée + + + Simulated key presses interval + intervalle entre simulations de saisie de touche + + + Confirm legal notice (message displayed before user logs in) + Confirmer les mentions légales (message affiché avant la connexion de l'utilisateur) + + + Use input device interception driver + Utiliser le pilote d'interception du périphérique d'entrée + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4156,8 +4838,8 @@ Généralement, ceci est nécessaire pour prendre en charge les serveurs de term Extension implémentant les fonctions abstraites pour le système Windows - Plugin implementing specific functions for the Windows platform - + Internal display + Affichage interne @@ -4166,30 +4848,34 @@ Généralement, ceci est nécessaire pour prendre en charge les serveurs de term The service "%1" is already installed. Le service "%1" est déjà installé. - - The service "%1" could not be installed. - Le service "%1" ne peut pas être installé. - The service "%1" has been installed successfully. Le service "%1" a été installé avec succès. - - The service "%1" could not be uninstalled. - Le service "%1" ne peut pas être désinstallé. - The service "%1" has been uninstalled successfully. Le service "%1" a été désinstallé avec succès. - - The start type of service "%1" could not be changed. - Le type de démarrage du service "%1" ne peut pas être changé. - Service "%1" could not be found. Service "%1" impossible à trouvé. + + The service "%1" could not be installed (error %2). + Le service "%1" n'a pas pu être installé (erreur %2). + + + Could not change the failure actions config for service "%1" (error %2). + Impossible de modifier la configuration des actions d'échec pour le service "%1" (erreur %2). + + + The service "%1" could not be uninstalled (error %2). + Le service "%1" n'a pas pu être désinstallé (erreur %2). + + + The start type of service "%1" could not be changed (error %2). + Le type de démarrage du service "%1" n'a pas pu être modifié (erreur %2). + X11VncConfigurationWidget @@ -4199,7 +4885,7 @@ Généralement, ceci est nécessaire pour prendre en charge les serveurs de term Custom x11vnc parameters: - Paramètres personnalisés x11vnc: + Paramètres personnalisés x11vnc : Do not use X Damage extension diff --git a/translations/he.ts b/translations/veyon_he.ts similarity index 72% rename from translations/he.ts rename to translations/veyon_he.ts index 59fc69c2a..5f3713a59 100644 --- a/translations/he.ts +++ b/translations/veyon_he.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -78,10 +78,6 @@ If you're interested in translating Veyon into your local or another langua All groups כל הקבוצות - - ... - ... - Access control rules כללי בקרת גישה @@ -136,18 +132,17 @@ If you're interested in translating Veyon into your local or another langua User groups backend: - - - - Missing user groups backend - + שרת קבוצות משתמשים: - No default user groups plugin was found. Please check your installation! - + Restrict access to members of specific user groups + הגבל הרשאה לחברי קבוצה מסוימת + + + AccessControlProvider - Restrict access to members of specific user groups + Provider for access control features @@ -178,87 +173,159 @@ If you're interested in translating Veyon into your local or another langua תיאור כלל: - Invert all conditions ("is/has" interpreted as "is/has not") + Conditions + תנאים + + + If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. + אם יותר מאחד התנאים מופעל, כל אחד מהתנאים צריך להתקיים על מנת לקיים את התנאי ("וגם" לוגי). אם רק אחד מהתנאים צריך להתקיים ("או" לוגי), יש ליצור מספר כללי גישה. + + + Action + פעולה + + + Allow access + אפשר גישה + + + Deny access + חסום גישה + + + Ask logged on user for permission + בקש אישור משתמש מחובר לגישה + + + None (rule disabled) + אין (כלל מושבת) + + + Accessing user + משתמש ניגש + + + Accessing computer + מחשב ניגש + + + Always process rule and ignore conditions + תמיד הפעל את החור והתעלם מהתנאים + + + Accessing computer and local computer - Conditions + User being accessed - is member of group + is logged in locally - Accessing computer is localhost + is logged in remotely - Accessing user is logged on user + No user is logged in locally - Accessing user is already connected + One or multiple users are logged in locally - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. + No user is logged in remotely - Action - פעולה + One or multiple users are logged in remotely + - Allow access - אפשר גישה + is located at + ממוקם ב - Deny access - חסום גישה + is not located at + - Ask logged on user for permission - בקש אישור משתמש מחובר לגישה + are located at the same location + - None (rule disabled) + are not located the same location - Accessing user + is member of group + חבר קבוצה + + + is not member of group - Accessing computer + is authenticated via - Local (logged on) user + is not authenticated via - Local computer - מחשב מקומי + has one or more groups in common with user being accessed + - Always process rule and ignore conditions + has no groups in common with user being accessed - No user logged on - אין אף משתמש מחובר + equals user being accessed + - Accessing user has one or more groups in common with local (logged on) user + is different from user being accessed - Accessing computer and local computer are at the same location + is already connected - is located at + is not connected + + + + is local computer + + + + is not local computer + + + + Computer being accessed + + + + Session being accessed is a user session + + + + Session being accessed is a login screen + + + + Local computer is already being accessed + + + + Local computer is not yet being accessed @@ -266,11 +333,11 @@ If you're interested in translating Veyon into your local or another langua AccessControlRulesTestDialog Access control rules test - + בדיקת כללי גישה Accessing user: - + משתמש ניגש: Local computer: @@ -282,7 +349,7 @@ If you're interested in translating Veyon into your local or another langua Please enter the following user and computer information in order to test the configured ruleset. - + אנא הזן את המשתמש הבא ואת המידע אודות המחשב על מנת לבדוק את קבוצת החוקים. Local user: @@ -294,154 +361,137 @@ If you're interested in translating Veyon into your local or another langua The access in the given scenario is allowed. - + הגישה במקרה הניתן מאופשרת. The access in the given scenario is denied. - + הגישה במקרה הניתן נדחית. The access in the given scenario needs permission of the logged on user. - + הגישה במקרה הניתן דורשת הרשאה מצד המשתמש המחובר. - ERROR: Unknown action - + Test result + תוצאות בדיקה - Test result + Authentication method + שיטת התחברות + + + There is no matching rule with a valid action. The access is therefore denied. - AndroidPlatformConfigurationPage + AuthKeysConfigurationWidget - Android - + Introduction + מבוא - General - כללי + Please perform the following steps to set up key file authentication: + יש לעקוב אחר הלשבים הבאים על מנת להגדיר התחברות באמצעות מפתחות: - - - AndroidPlatformPlugin - Plugin implementing specific functions for the Android platform - + 1) Create a key pair on the master computer. + 1) צור זוג מפתחות על מחשב המאסטר - - - AuthKeysConfigurationPage - Authentication keys - + 2) Set an access group whose members should be allowed to access other computers. + 2) הגדר קבוצת גישה אשר חבריה אמורים לגשת למחשבים אחרים. - Introduction - + 3) Export the public key and import it on all client computers with the same name. + 3) ייצא את המפתח הפומבי וייבא אותו בכל אחד ממחשבי הלקוחות עם שם זהה. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + אנה פנה אל <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">המדריך למנהל של Veyon</a> למידע נוסף. Key file directories - + נתיבים של קבצי מפתחות Public key file base directory - + נתיב בסיס למפתחות פומביים Private key file base directory - + נתיב בסיס למפתחות פרטיים - ... - ... + Available authentication keys + מפתחות התחברות זמינים - Available authentication keys - + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + זוג מפתחות אימות כולל זוג מפתחות קריפטוגרפיים, מפתח פרטי ומפתח פומבי. +מפתח פרט מאפשר למשתמשים על מחשב המאסטר לגשת לכל שאר מחשבי הלקוח. +זה חשוב שרק מחשבים מורשים יוכלו לקרוא את המפתח הפרטי. +המפתח הפומבי משמש במחשבי לקוח על מנת שיוכלו לאמת בקשות לחיבורים נכנסים. Create key pair - + יצירת זוג מפתחות Delete key - + מחק מפתח Import key - + ייבא מפתח Export key - + ייצא מפתח Set access group - + הגדר קבוצת גישה Key files (*.pem) - + קבצי מפתחות (*.pem) Authentication key name - + שם מפתח אימות Please enter the name of the user group or role for which to create an authentication key pair: - + אנא הכניסו את שם קבוצת המשתמשים או התפקיד עבורם יש ליצור את זוג המפתחות Do you really want to delete authentication key "%1/%2"? - + אתה בטוח שברצונך למחוק את המפתח "%1/%2"? Please select a key to delete! - - - - Please enter the name of the user group or role for which to import the authentication key: - + נא לבחור מפתח למחיקה! Please select a key to export! - + יש לבחור מפתח לייצוא! Please select a user group which to grant access to key "%1": - + נא לבחור קבוצת משתמשים עבורה יש לתת גישה למפתח "%1": Please select a key which to set the access group for! - - - - Please perform the following steps to set up key file authentication: - - - - 1) Create a key pair on the master computer. - - - - 2) Set an access group whose members should be allowed to access other computers. - - - - 3) Export the public key and import it on all client computers with the same name. - - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - + נא לבחור מפתח עבורו יש להגדיר את קבוצת הגישה! - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. @@ -449,95 +499,95 @@ The public key is used on client computers to authenticate incoming connection r AuthKeysManager Please check your permissions. - + בדוק את ההרשאות שלך. Key name contains invalid characters! - + שם מפתח כולל תווים לא חוקיים! Invalid key type specified! Please specify "%1" or "%2". - + סוג מפתח לא חוקי נבחר! נא לבחור "%1" או "%2". Specified key does not exist! Please use the "list" command to list all installed keys. - + המפתח שנבחר אינו קיים. אנא השתמש בפקודה "list" על מנת למנות את כל המפתחות המותקנים. One or more key files already exist! Please delete them using the "delete" command. - + אחד או יותר מהמפתחות כבר קיימים! השתמשו בפקודה "delete" ומחקו אותם ראשית. Creating new key pair for "%1" - + יוצר מפתח חדש עבור "%1" Failed to create public or private key! - + לא ניתן היה ליצור מפתח פומבי או פרטי! Newly created key pair has been saved to "%1" and "%2". - + זוג המפתחות שנוצרו נשמרו ל"%1" ול""%2". Could not remove key file "%1"! - + לא ניתן היה להסיר את קובץ המפתח "%1"! Could not remove key file directory "%1"! - + לא ניתן היה להסיר את נתיב המפתחות "%1"! Failed to create directory for output file. - + לא ניתן היה ליצור נתיב לקובץ הפלט. File "%1" already exists. - + הקובץ "%1" כבר קיים. Failed to write output file. - + לא ניתן היה לכתוב את קובץ הפלט. Key "%1/%2" has been exported to "%3" successfully. - + המפתח "%1/%2" יוצא בהצלחה ל"%3". Failed read input file. - + לא ניתן היה לקלוט את קובץ הקלט File "%1" does not contain a valid private key! - + הקובץ "%1" לא כולל מפתח פרטי תקין! File "%1" does not contain a valid public key! - + הקובץ "%1" לא כולל מפתח פומבי תקין! Failed to create directory for key file. - + לא ניתן היה ליצור נתיב לקובץ המפתח. Failed to write key file "%1". - + כתיבת קובץ המפתח "%1" נכשלה. Failed to set permissions for key file "%1"! - + הגדרת ההרשאות לקובץ המפתח "%1" נכשלה. Key "%1/%2" has been imported successfully. Please check file permissions of "%3" in order to prevent unauthorized accesses. - + המפתח "%1\%2" יובר בהצלחה. יש לבדוק את הרשאות הקובץ "%3" על מנת למנוע גישה לא מורשית. Failed to convert private key to public key - + לא ניתן היה להמיר מפתח פרטי למפתח פומבי. Failed to create directory for private key file "%1". - + יצירת הנתיב למפתח הפרטי "%1" נכשלה. Failed to save private key in file "%1"! @@ -573,7 +623,7 @@ The public key is used on client computers to authenticate incoming connection r <N/A> - + לא Failed to read key file. @@ -612,7 +662,7 @@ The public key is used on client computers to authenticate incoming connection r KEY - + מפתח ACCESS GROUP @@ -624,11 +674,11 @@ The public key is used on client computers to authenticate incoming connection r NAME - + שם FILE - + קובץ This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. @@ -643,35 +693,51 @@ The public key is used on client computers to authenticate incoming connection r - Please specify the command to display help for! + TYPE + סוג + + + PAIR ID - TYPE + Commands for managing authentication keys - PAIR ID + This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. - Command line support for managing authentication keys + This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. - Commands for managing authentication keys + This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. - This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. - This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. + Key file authentication - This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + Key file + קובץ מפתח + + + Please specify the key name (e.g. "teacher/public") as the first argument. + + + + Please specify the command to display help for. + + + + The specified command does not exist or no help is available for it. @@ -695,61 +761,204 @@ The public key is used on client computers to authenticate incoming connection r - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - מחשבים + General + כללי - Name - שם + Username to bind DN mapping: + - Host address/IP - שם מחשב / IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + + AuthLdapDialog - MAC address - כתובות MAC + Veyon Logon + - Add new computer - הוסף מחשב חדש + Please enter your domain/LDAP username and password in order to access computers. + - Remove selected computer - הסר מחשבים שנבחרו + Username + שם משתמש - New computer - מחשב חדש + Password + סיסמה - Builtin directory + Authentication error + שגיאה באימות + + + Logon failed with given username and password. Please try again! + + + AuthLogonDialog - Locations & computers + Veyon Logon - Locations + Please enter your username and password in order to access computers. - Add new location + Username + שם משתמש + + + Password + סיסמה + + + Authentication error + שגיאה באימות + + + Logon failed with given username and password. Please try again! + + + + + AuthLogonPlugin + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Remove selected location + Logon authentication + + + + Logon + התחברות + + + + AuthSimpleDialog + + Veyon Logon + + + + Please enter the Veyon password: + + + + Authentication error + שגיאה באימות + + + Logon failed with given password. Please try again! + + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + + + + Simple password authentication + + + + Simple password + + + + + AuthenticationPage + + Authentication is set up properly on this computer. + + + + + AuthenticationPageTab + + Enabled + מופעל + + + Test + בדיקה + + + + BuiltinDirectoryConfiguration + + Builtin directory + + + BuiltinDirectoryConfigurationPage + + Computers + מחשבים + + + Name + שם + + + Host address/IP + שם מחשב / IP + + + MAC address + כתובות MAC + + + Add new computer + הוסף מחשב חדש + + + Remove selected computer + הסר מחשבים שנבחרו + + + New computer + מחשב חדש + - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + Builtin directory + + Locations + מיקומים + + + Add new location + הוסף מיקום חדש + + + Remove selected location + הסר את המיקום שנבחר + New location + מיקום חדש + + + Directory name + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. @@ -813,7 +1022,7 @@ The public key is used on client computers to authenticate incoming connection r None - + כלום Computer @@ -825,7 +1034,7 @@ The public key is used on client computers to authenticate incoming connection r Invalid - + לא בתוקף Error while parsing line %1. @@ -861,7 +1070,7 @@ The public key is used on client computers to authenticate incoming connection r Add a location or computer - + הוסף מיקום או מחשב Clear all locations and computers @@ -877,7 +1086,7 @@ The public key is used on client computers to authenticate incoming connection r Remove a location or computer - + הסר מיקום או מחשב Location "%1" @@ -889,15 +1098,15 @@ The public key is used on client computers to authenticate incoming connection r Location - + מיקום FILE - + קובץ LOCATION - + מיקום FORMAT-STRING-WITH-PLACEHOLDERS @@ -941,15 +1150,15 @@ The public key is used on client computers to authenticate incoming connection r TYPE - + סוג NAME - + שם PARENT - + הורה Adds an object where %1 can be one of "%2" or "%3". %4 can be specified by name or UUID. @@ -957,7 +1166,7 @@ The public key is used on client computers to authenticate incoming connection r Add a room - + הוסף חדר Add a computer to room %1 @@ -965,7 +1174,7 @@ The public key is used on client computers to authenticate incoming connection r OBJECT - + חפץ Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. @@ -981,11 +1190,11 @@ The public key is used on client computers to authenticate incoming connection r "Room 01" - + "חדר 01" "Computer 01" - + "מחשב 01" HOST ADDRESS @@ -995,6 +1204,14 @@ The public key is used on client computers to authenticate incoming connection r MAC ADDRESS + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. + + BuiltinUltraVncServer @@ -1012,10 +1229,6 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - - Active features: %1 @@ -1032,10 +1245,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off - - Service unreachable or not running - - Authentication failed or access denied @@ -1054,6 +1263,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 + מיקום: %1 + + + [no user] + + + + Veyon Server unreachable or not running + + + + Name: %1 + + + + Hostname: %1 + + + + unknown + לא ידוע + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active @@ -1087,6 +1328,17 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + + Active connections: + + + + + ComputerGroupSelector + + Group %1 + + ComputerManager @@ -1114,80 +1366,83 @@ The public key is used on client computers to authenticate incoming connection r Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. - - - ComputerSelectPanel - Computer management + Logged in since - Computer search + %1 days - Add location + 1 day + + + ComputerMonitoring - Save computer/user list - שמור רשימת מחשבים / משתמשים + Computers + מחשבים - Select output filename - + Search users and computers + חפש משתמשים ומחשבים - CSV files (*.csv) - קובץ CSV (*.csv) + Select all + - File error + Unselect all - Could not write the computer and users list to %1! Please check the file access permissions. - + Add to group + הוסף לקבוצה - - - ConfigCommandLinePlugin - Please specify an existing configuration file to import. - + Remove from group + הסר מקבוצה + + + ComputerSelectPanel - Please specify a valid filename for the configuration export. - + Computer search + חיפוש מחשב - Please specify a valid key. - + Add location + הוסף מיקום - Specified key does not exist in current configuration! - + Save computer/user list + שמור רשימת מחשבים / משתמשים - Please specify a valid value. + Select output filename - Configure Veyon at command line - + CSV files (*.csv) + קובץ CSV (*.csv) - Output file is not writable! - + File error + שגיאת קובץ - Output directory is not writable! + Could not write the computer and users list to %1! Please check the file access permissions. - Configuration file is not readable! + Search computers + + + ConfigCommands Clear system-wide Veyon configuration @@ -1217,26 +1472,62 @@ The public key is used on client computers to authenticate incoming connection r - Commands for managing the configuration of Veyon + Upgrade and save configuration of program and plugins - Upgrade and save configuration of program and plugins + Please specify an existing configuration file to import. - - - ConfigurationManager - Could not modify the autostart property for the %1 Service. + Configuration file is not readable! - Could not configure the firewall configuration for the %1 Server. + Please specify a valid filename for the configuration export. - Could not configure the firewall configuration for the %1 Worker. + Output file is not writable! + + + + Output directory is not writable! + + + + Please specify a valid key. + + + + Specified key does not exist in current configuration! + + + + Please specify a valid value. + + + + Configure Veyon at command line + + + + Commands for managing the configuration of Veyon + + + + + ConfigurationManager + + Could not modify the autostart property for the %1 Service. + + + + Could not configure the firewall configuration for the %1 Server. + + + + Could not configure the firewall configuration for the %1 Worker. @@ -1247,6 +1538,10 @@ The public key is used on client computers to authenticate incoming connection r Could not apply platform-specific configuration settings. + + Could not configure the firewall configuration for the %1 Service. + + DemoClient @@ -1259,11 +1554,11 @@ The public key is used on client computers to authenticate incoming connection r DemoConfigurationPage Demo server - + שרת דוגמא Tunables - + מכוונים ms @@ -1275,11 +1570,7 @@ The public key is used on client computers to authenticate incoming connection r Memory limit - - - - Use multithreading (experimental) - + הגבלת זיכרון MB @@ -1297,16 +1588,20 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running + + Bandwidth limit + + + + MB/s + + DemoFeaturePlugin - - Fullscreen demo - הדגמה במסך מלא - Stop demo - + עצור הדגמה Window demo @@ -1317,27 +1612,72 @@ The public key is used on client computers to authenticate incoming connection r - Demo server + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. + Demo + הדגמה + + + Share your screen or allow a user to share his screen with other users. - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Full screen demo + הדגמה במסך מלא + + + Share your own screen in fullscreen mode + + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share your own screen in a window + שתף מסך שלך בחלון + + + Share selected user's screen in fullscreen mode + שתף את המסך של המשתמש שנבחר במצב מסך מלא + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share selected user's screen in a window + שתף את המסך של המשתמש שנבחר בחלון + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + + Please select only one user screen to share. + + + + All screens + כל המסכים + DesktopAccessDialog Desktop access dialog - + תיבת דו-שיח לגישה לשולחן העבודה + Confirm desktop access - + אשר גישה לשולחן העבודה Never for this session @@ -1355,56 +1695,56 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - Programs & websites - + Name + שם + + + Path + נתיב - Predefined programs + Predefined websites - Name - שם + Remove selected website + הסר את האתר הנבחר - Path - + URL + קישור - Add new program - + New website + אתר חדש - Remove selected program - + Applications & websites + אפליקציה ואתר - Predefined websites + Predefined applications - Remove selected website - + Add new application + הוסף אפליקציה חדשה - URL + Remove selected application - New program - + Add new website + הוסף אתר חדש - New website - + New application + אפליקציה חדשה DesktopServicesFeaturePlugin - - Run program - הפעל תוכנית - Open website פתח אתר אינטרנט @@ -1414,27 +1754,31 @@ The public key is used on client computers to authenticate incoming connection r - Start programs and services in user desktop + Open website "%1" - Click this button to run a program on all computers. - + Custom website + אתר מותאם אישית - Run program "%1" - + Start application + התחל אפליקציה - Custom program + Click this button to start an application on all computers. - Open website "%1" + Start application "%1" - Custom website + Custom application + אפליקציה מותאם אישית + + + Start apps and open websites in user sessions @@ -1442,11 +1786,11 @@ The public key is used on client computers to authenticate incoming connection r DocumentationFigureCreator Teacher - + מורה Room %1 - + חדר %1 Please complete all tasks within the next 5 minutes. @@ -1454,7 +1798,7 @@ The public key is used on client computers to authenticate incoming connection r Custom website - + אתר מותאם אישית Open file manager @@ -1469,17 +1813,21 @@ The public key is used on client computers to authenticate incoming connection r - Custom program - + Handout + למסור - Handout + Texts to read - Texts to read + generic-student-user + + Custom application + אפליקציה מותאם אישית + ExternalVncServer @@ -1504,569 +1852,606 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands - Feature control + List names of all available features - - - FileTransferController - Could not open file "%1" for reading! Please check your permissions! + Show table with details of all available features - - - FileTransferDialog - File transfer + Start a feature on a remote host - Options + Stop a feature on a remote host - Transfer only + Please specify the command to display help for. - Transfer and open file(s) with associated program + Displays a list with the names of all available features. - Transfer and open destination folder + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. - Files + HOST ADDRESS - Start + FEATURE - Overwrite existing files + ARGUMENTS - - - FileTransferPlugin - File transfer + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information - Click this button to transfer files from your computer to all computers. + Lock the screen - Select one or more files to transfer + Display a text message - Transfer files to remote computer + Test message - Received file "%1". + Start an application - Could not receive file "%1" as it already exists. + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. - Could not receive file "%1" as it could not be opened for writing! + Unlock the screen - - - GeneralConfigurationPage - User interface - ממשק משתמש + The specified command does not exist or no help is available for it. + - Language: - שפה: + Name + שם - Use system language setting - השתמש בשפת המערכת + Description + תאור - Veyon - + Master + מנהל - Logging - + Service + שרות - Log file directory - + Worker + עובד - ... - ... + UID + - Log level + Plugin - Nothing + Invalid feature name or UID specified - Only critical messages - רק הודעות קריטיות + Error parsing the JSON-encoded arguments: %1 + - Errors and critical messages + Failed to initialize credentials - Warnings and errors + Could not establish a connection to host %1 - Information, warnings and errors + Failed to send feature control message to host %1 - Debug messages and everything else + Feature-related CLI operations - Limit log file size + Commands for controlling features + + + FileTransferConfigurationPage - Clear all log files - + File transfer + העברת קבצים - Log to standard error output - + Directories + מדריכים - Network object directory + Destination directory - Backend: + Default source directory - Update interval: - + Options + אפשרויות - %1 service + Remember last source directory - The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + Create destination directory if it does not exist + + + FileTransferController - Log files cleared + Could not open file "%1" for reading! Please check your permissions! + + + FileTransferDialog - All log files were cleared successfully. - + File transfer + העברת קבצים - Error - + Options + אפשרויות - Could not remove all log files. + Transfer only - MB + Transfer and open file(s) with associated program - Rotate log files + Transfer and open destination folder - x - + Files + קובץ - seconds - שניות + Start + התחל - Write to logging system of operating system + Overwrite existing files + + + FileTransferFileDialog - Authentication + Select one or more files to transfer + + + FileTransferPlugin - Method: - + File transfer + העברת קבצים - Logon authentication + Click this button to transfer files from your computer to all computers. - Key file authentication + Select one or more files to transfer - Test - בדיקה + Transfer files to remote computer + - Authentication is set up properly on this computer. + Received file "%1". - Authentication keys are not set up properly on this computer. + Could not receive file "%1" as it already exists. - Authentication test + Could not receive file "%1" as it could not be opened for writing! - InternetAccessControlConfigurationPage + GeneralConfigurationPage - Internet access control - + User interface + ממשק משתמש - Backend: + Language: + שפה: + + + Use system language setting + השתמש בשפת המערכת + + + Veyon - General settings + Logging + רישום + + + Log file directory - Backend settings + Log level - - - InternetAccessControlPlugin - Block access to the internet - חסום גישה לאינטרנט + Nothing + כלום + + + Only critical messages + רק הודעות קריטיות - Allow access to the internet - אפשר גישה לאינטרנט + Errors and critical messages + - Show help about command + Warnings and errors - Block internet - חסום אינטרנט + Information, warnings and errors + - Click this button to block access to the internet. + Debug messages and everything else - Unblock internet + Limit log file size - Click this button to allow access to the internet. + Clear all log files - Control access to the internet + Log to standard error output - Commands for controlling access to the internet + %1 service - - - LdapBrowseDialog - Browse LDAP + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? - - - LdapClient - LDAP error description: %1 + Log files cleared - - - LdapConfigurationPage - Basic settings - הגדרות בסיסיות + All log files were cleared successfully. + - General - כללי + Error + שגיאה - LDAP server and port + Could not remove all log files. - Bind DN + MB - Bind password + Rotate log files - Anonymous bind + x - Use bind credentials + Write to logging system of operating system - Base DN + TLS configuration - Fixed base DN + Use certificate authority for TLS connections - e.g. dc=example,dc=org + CA certificate file - Discover base DN by naming context + ... + ... + + + Host certificate file - e.g. namingContexts or defaultNamingContext + Host private key file - Environment settings + Style: - Object trees + Native - Computer tree + Color scheme: - e.g. OU=Groups + Light - User tree + Dark - e.g. OU=Users + User groups - e.g. OU=Computers + Backend: - Group tree + Include user groups from domain - Perform recursive search operations in object trees + Missing user groups backend + חסר שרת קבוצות משתמשים + + + No user groups plugin was found. Please check your installation! + + + HeadlessVncServer - Object attributes + Headless VNC server + + + LdapBrowseDialog - e.g. hwAddress + Browse LDAP + + + LdapClient - e.g. member or memberUid + LDAP error description: %1 + + + LdapConfiguration - e.g. dNSHostName + LDAP connection failed - Computer MAC address attribute + Could not connect to the LDAP server. Please check the server parameters. + +%1 - Group member attribute + LDAP bind failed - e.g. uid or sAMAccountName + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 - Advanced settings - הגדרות מתקדמות + LDAP bind successful + - Optional object filters + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - Filter for user groups + LDAP base DN test failed - Filter for users + Could not query the configured base DN. Please check the base DN parameter. + +%1 - Filter for computer groups + LDAP base DN test successful - Group member identification + The LDAP base DN has been queried successfully. The following entries were found: + +%1 - Distinguished name (Samba/AD) + LDAP naming context test failed - List all groups of a user + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 - List all groups of a computer + LDAP naming context test successful - Get computer object by IP address + The LDAP naming context has been queried successfully. The following base DN was found: +%1 - LDAP connection failed + user tree - LDAP bind failed + User tree - LDAP bind successful + group tree - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Group tree - LDAP base DN test failed + computer tree - LDAP base DN test successful + Computer tree - LDAP naming context test failed + computer group tree - LDAP naming context test successful + Computer group tree - The LDAP naming context has been queried successfully. The following base DN was found: -%1 + user objects - user tree + User login name attribute - group tree + group members - computer tree + Group member attribute - Enter username - הכנס שם משתמש + Group not found + - Please enter a user login name (wildcards allowed) which to query: + Could not find a group with the name "%1". Please check the group name or the group tree parameter. - user objects + computer objects - Enter group name + Computer display name attribute - Please enter a group name whose members to query: + Invalid hostname - group members + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Group not found + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Computer hostname attribute - Enter computer name - הכנס שם מחשב + computer MAC addresses + - computer objects + Computer MAC address attribute - Enter computer DN + computer locations - Please enter the DN of a computer whose MAC address to query: + Computer location attribute - computer MAC addresses + Location name attribute @@ -2077,12 +2462,16 @@ The public key is used on client computers to authenticate incoming connection r user groups קבוצות משתמשים + + computers + מחשבים + computer groups קבוצות מחשבים - Please enter a user login name whose group memberships to query: + computer containers @@ -2093,6 +2482,10 @@ The public key is used on client computers to authenticate incoming connection r User not found משתמש לא נמצא + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + + groups of computer @@ -2102,586 +2495,580 @@ The public key is used on client computers to authenticate incoming connection r - Enter computer IP address + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - Please enter a computer IP address which to resolve to an computer object: + Hostname lookup failed - computers - מחשבים + Could not lookup hostname for IP address %1. Please check your DNS server settings. + - LDAP %1 test failed + location entries - LDAP %1 test successful + Computer groups filter - The %1 has been queried successfully and %2 entries were found. + Computer locations identification - %1 %2 have been queried successfully: - -%3 + Filter for computer groups - LDAP filter test failed + Invalid test value - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 + An empty or invalid value has been supplied for this test. - LDAP filter test successful + LDAP %1 test failed - %1 %2 have been queried successfully using the configured filter. + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 - (only if different from group tree) + LDAP %1 test successful - Computer group tree + The %1 has been queried successfully and %2 entries were found. - computer group tree + LDAP test failed - Filter for computers + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 - e.g. room or computerLab - + and + ו - Integration tests + LDAP test successful - Computer groups + %1 %2 have been queried successfully: + +%3 - e.g. name or description + LDAP filter test failed - Filter for computer containers + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 - Computer containers or OUs + LDAP filter test successful - Connection security + %1 %2 have been queried successfully using the configured filter. - TLS certificate verification + LDAP directory + + + LdapConfigurationPage - System defaults - + Basic settings + הגדרות בסיסיות - Never (insecure!) - + General + כללי - Custom CA certificate file + LDAP server and port - None + Bind DN - TLS - TLS + Bind password + - SSL - SSL + Anonymous bind + - e.g. (objectClass=computer) + Use bind credentials - e.g. (objectClass=group) + Base DN - e.g. (objectClass=person) + Fixed base DN - e.g. (objectClass=room) or (objectClass=computerLab) + e.g. dc=example,dc=org - e.g. (objectClass=container) or (objectClass=organizationalUnit) + Discover base DN by naming context - Could not query the configured base DN. Please check the base DN parameter. - -%1 + e.g. namingContexts or defaultNamingContext - The LDAP base DN has been queried successfully. The following entries were found: - -%1 + Environment settings - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 + Object trees - Certificate files (*.pem) + Computer tree - Could not connect to the LDAP server. Please check the server parameters. - -%1 + e.g. OU=Groups - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 + User tree - Encryption protocol + e.g. OU=Users - Computer location attribute + e.g. OU=Computers - Computer display name attribute + Group tree - Location name attribute + Perform recursive search operations in object trees - e.g. cn or displayName + Object attributes - Computer locations identification + e.g. hwAddress - Identify computer locations (e.g. rooms) via: + e.g. member or memberUid - Location attribute in computer objects + e.g. dNSHostName - List all entries of a location + Computer MAC address attribute - List all locations + Group member attribute - Enter computer display name + e.g. uid or sAMAccountName - Please enter a computer display name to query: - + Advanced settings + הגדרות מתקדמות - Enter computer location name + Optional object filters - Please enter the name of a computer location (wildcards allowed): + Filter for user groups - computer locations + Filter for users - Enter location name + Filter for computer groups - Please enter the name of a location whose entries to query: + Group member identification - location entries + Distinguished name (Samba/AD) - LDAP test failed + List all groups of a user - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 + List all groups of a computer - and + Get computer object by IP address - LDAP test successful + Enter username + הכנס שם משתמש + + + Please enter a user login name (wildcards allowed) which to query: - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 + Enter group name - Browse + Please enter a group name whose members to query: - Test - בדיקה + Enter computer name + הכנס שם מחשב - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Enter computer DN - Computer hostname attribute + Please enter the DN of a computer whose MAC address to query: - Please enter a computer hostname to query: + Please enter a user login name whose group memberships to query: - Invalid hostname + Enter computer IP address - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Please enter a computer IP address which to resolve to an computer object: - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + (only if different from group tree) - Could not find a user with the name "%1". Please check the username or the user tree parameter. + Computer group tree - Enter hostname + Filter for computers - Please enter a computer hostname whose group memberships to query: + e.g. room or computerLab - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Integration tests - Hostname lookup failed + Computer groups - Could not lookup hostname for IP address %1. Please check your DNS server settings. + e.g. name or description - User login name attribute + Filter for computer containers - Configured attribute for user login name or computer hostname (OpenLDAP) + Computer containers or OUs - computer containers + Connection security - - - LdapPlugin - Auto-configure the base DN via naming context + TLS certificate verification - Query objects from LDAP directory + System defaults - Show help about command + Never (insecure!) - Commands for configuring and testing LDAP/AD integration + Custom CA certificate file - Basic LDAP/AD support for Veyon - + None + כלום - %1 (load computers and locations from LDAP/AD) + TLS + TLS + + + SSL + SSL + + + e.g. (objectClass=computer) - %1 (load users and groups from LDAP/AD) + e.g. (objectClass=group) - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + e.g. (objectClass=person) - No naming context attribute name given - falling back to configured value. + e.g. (objectClass=room) or (objectClass=computerLab) - Could not query base DN. Please check your LDAP configuration. + e.g. (objectClass=container) or (objectClass=organizationalUnit) - Configuring %1 as base DN and disabling naming context queries. + Certificate files (*.pem) - - - LdapProConfigurationPage - LDAP Pro + Encryption protocol - Instances + Computer location attribute - Enter name + Computer display name attribute - Please enter a name for the instance (can't be changed later!): + Location name attribute - Remove instance + e.g. cn or displayName - Do you really want to remove instance "%1"? + Computer locations identification - Configuration for instance "%1" + Identify computer locations (e.g. rooms) via: - - - LdapProPlugin - Professional LDAP/AD integration for Veyon + Location attribute in computer objects - %1 (load computers and locations from LDAP/AD) + List all entries of a location - %1 (load users and groups from LDAP/AD) + List all locations - - - LicensingConfigurationPage - Licensing + Enter computer display name - Installed licenses + Please enter a computer display name to query: - Add new network range + Enter computer location name - Remove selected network range + Please enter the name of a computer location (wildcards allowed): - ID + Enter location name - Feature + Please enter the name of a location whose entries to query: - Valid until + Browse + לדפדף + + + Test + בדיקה + + + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - Licensee + Computer hostname attribute - Browse license file + Please enter a computer hostname to query: - Veyon license files (*.vlf) + Enter hostname - Remove license + Please enter a computer hostname whose group memberships to query: - Do you really want to remove the selected license? + User login name attribute - <N/A> + Configured attribute for user login name or computer hostname (OpenLDAP) - Invalid license file + Directory name - Could not open the license file for reading! + Query options - The selected license file does not contain valid data. + Query nested user groups (supported by AD only) - The selected license file could not be verified. + Query timeout - The selected license file is not valid for this installation. + ms + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. + LDAP - The license is already installed. + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + LdapPlugin - Information + Auto-configure the base DN via naming context - Installation ID + Query objects from LDAP directory - Addons available for licensing + Show help about command - Addon + Commands for configuring and testing LDAP/AD integration - - - LicensingPlugin - Show help for specific command - הצג עזרה עבור פקודה מסויימת + Basic LDAP/AD support for Veyon + - Show all installed licenses + %1 (load computers and locations from LDAP/AD) - Add license file + %1 (load users and groups from LDAP/AD) - Remove installed license + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - -USAGE - -%1 add <LICENSE FILE> - - + No naming context attribute name given - falling back to configured value. - -USAGE - -%1 remove <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. - No certificate found with given ID + Configuring %1 as base DN and disabling naming context queries. - <N/A> + Test binding to an LDAP server - Licensing management + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Commands for managing license keys + LDAP bind @@ -2697,14 +3084,22 @@ USAGE User authentication + אימות משתמש + + + User sessions - Session management + Minimum session lifetime before server start - Display manager users + User login + התחברות משתמש + + + Login key sequence @@ -2714,10 +3109,6 @@ USAGE Plugin implementing abstract functions for the Linux platform - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2737,11 +3128,11 @@ USAGE הגדרות - Disable balloon tooltips + Show icons only - Show icons only + Disable tooltips @@ -2753,7 +3144,7 @@ USAGE toolBar - + סרגל כלים General @@ -2761,11 +3152,11 @@ USAGE &File - + &קובץ &Help - + &עזרה &Quit @@ -2791,10 +3182,6 @@ USAGE About Qt - - Authentication impossible - - Configuration not writable @@ -2821,11 +3208,11 @@ USAGE Service - + שרות Master - + מנהל Access control @@ -2837,7 +3224,7 @@ USAGE Auto - + אוטומטי About @@ -2855,10 +3242,6 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - - Access denied גישה נדחתה @@ -2891,10 +3274,6 @@ USAGE Search users and computers חפש משתמשים ומחשבים - - Adjust optimal size - - Align computers to grid @@ -2925,7 +3304,7 @@ USAGE &Standard - + &רגיל &Advanced @@ -2939,16 +3318,54 @@ USAGE Locations && computers + + Authentication + אימות + + + Adjust size of computer icons automatically + + + + Slideshow + מצגת + + + Spotlight + זרקוֹר + + + Veyon Master + Veyon מאסטר + + + Locations & computers + + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + + + + Load computer positions + + + + Save computer positions + + MasterConfigurationPage Directories - - - - ... - ... + מדריכים User configuration @@ -2960,7 +3377,7 @@ USAGE Features - + תכונות All features @@ -2984,7 +3401,7 @@ USAGE Behaviour - + התנהגות Enforce selected mode for client computers @@ -3034,6 +3451,10 @@ USAGE Only user name + + Only last part of user name + + Only computer name @@ -3083,172 +3504,187 @@ USAGE - Automatically adjust computer thumbnail size + Automatically open computer select panel - Automatically open computer select panel + Use modern user interface (experimental) - - - MonitoringMode - Monitoring + Thumbnail spacing - Builtin monitoring mode + px - This mode allows you to monitor all computers at one or more locations. + Hide local session - - - NetworkDiscoveryConfigurationPage - Network discovery + Auto + אוטומטי + + + Thumbnail aspect ratio - Mode + Automatically adjust computer icon size - Scan network ranges + Open feature windows on the same screen as the main window - e.g. 192.168.1.0/24 + Configuration templates - Scan all subnets of computer + Image quality in monitoring mode - Scan custom subnet + Highest - Scan sessions on local computer + High - Test - בדיקה + Medium + - Network ranges + Low - Add new group + Lowest - Remove selected group + Remote access image quality - Groups + Advanced - First address + Computer name source - Last address + Default - Add new network range + Host address - Remove selected network range + Session client address - Parallel scans + Session client name - Scan timeout + Session host name - ms + Session metadata - Session scan limit + Full name of user - Options + User login name - Reverse lookup discovered IP addresses to host names + Computer UID role - New location + Session meta data hash - - - NetworkDiscoveryDirectory - Scanning... + Always expand all locations - Discovered computers + Image quality - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command - הצג עזרה עבור פקודה מסויימת + Monitoring + פיקוח - Scan a subnet + Builtin monitoring mode - -USAGE - -%1 scan [<SUBNET>] - - + This mode allows you to monitor all computers at one or more locations. + + + + Query application version of the server - Network object directory which automatically discovers computers in the network + Query active features - Network discovery (scan network for Veyon clients) + Query properties of remotely available screens + + + + + NestedNetworkObjectDirectory + + All directories + + + NetworkObjectDirectoryConfigurationPage - Commands for managing the network discovery directory + Update interval: + + seconds + שניות + + + + NetworkObjectDirectoryConfigurationPageTab + + Enabled + מופעל + NetworkObjectTreeModel Locations/Computers - + מיקומים/מחשבים @@ -3275,33 +3711,45 @@ USAGE Name: + שם: + + + Website name - PasswordDialog + PluginCommands - Username - שם משתמש + List names of all installed plugins + - Password - סיסמה + Show table with details of all installed plugins + - Veyon Logon - + Name + שם - Authentication error - שגיאה באימות + Description + תאור - Logon failed with given username and password. Please try again! + Version + גרסה + + + UID - Please enter your username and password in order to access computers. + Plugin-related CLI operations + + + + Commands for managing plugins @@ -3347,10 +3795,6 @@ USAGE Do you really want to reboot the selected computers? - - Do you really want to power down the selected computer? - - Power on a computer via Wake-on-LAN (WOL) @@ -3401,6 +3845,18 @@ USAGE Please save your work and close all programs. + + Do you really want to reboot <b>ALL</b> computers? + + + + Do you really want to power down <b>ALL</b> computers? + + + + Do you really want to power down the selected computers? + + PowerDownTimeInputDialog @@ -3414,11 +3870,11 @@ Please save your work and close all programs. minutes - + דקות seconds - + שניות @@ -3448,11 +3904,22 @@ Please save your work and close all programs. - Please enter the hostname or IP address of the computer to access: + Show help about command - Show help about command + Exchange clipboard contents + + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + + + RemoteAccessPage + + Remote access: %1 @@ -3462,6 +3929,10 @@ Please save your work and close all programs. %1 - %2 Remote Access + + %1 - %2 - %3 Remote Access + + RemoteAccessWidgetToolBar @@ -3511,16 +3982,12 @@ Please save your work and close all programs. Menu - + תפריט Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - - Connected. מחובר. @@ -3531,148 +3998,169 @@ Please save your work and close all programs. Exit - + יציאה + + + Connecting... + מתחבר... - - - Routing - Control internet access by modifying routing table + Select screen + + All screens + כל המסכים + - RoutingConfigurationWidget + ScreenLockFeaturePlugin - Remove default routes to block internet access - + Lock + נעילה - Add custom route to block internet - + Unlock + שחרור - Destination + Lock screen and input devices of a computer - Gateway + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. - - - RunProgramDialog - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - + Lock input devices + נעל מכשירי קלט - Run programs - + Unlock input devices + שחרר מכשירי קלט - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + + Screenshot + + unknown + לא ידוע + - Name: + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. - Remember and add to program menu - + Screenshot + צילום מסך - e.g. VLC + Could not open screenshot file %1 for writing. - ScreenLockFeaturePlugin + ScreenshotFeaturePlugin - Lock - + Screenshot + צילום מסך - Unlock + Use this function to take a screenshot of selected computers. - Lock screen and input devices of a computer + Screenshots taken + צילום מסך בוצע + + + Screenshot of %1 computer have been taken successfully. - To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + Take screenshots of computers and save them locally. - Screenshot + ScreenshotManagementPage - unknown - + Screenshots + צילומי מסך + + + ScreenshotManagementPanel - Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. - Screenshot - צילום מסך + User: + משתמש: - - - ScreenshotFeaturePlugin - Screenshot - צילום מסך + Computer: + מחשב: - Use this function to take a screenshot of selected computers. - + Date: + תאריך: - Screenshots taken - + Time: + זמן: - Screenshot of %1 computer have been taken successfully. - + Show + הצג + + + Delete + מחק + + + Screenshot + צילום מסך - Take screenshots of computers and save them locally. + Do you really want to delete all selected screenshots? - ScreenshotManagementPanel + ServerAccessControlManager - All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + Requested authentication method not available - User: - משתמש: + Access allowed by rule "%1" + - Computer: - מחשב: + Access denied by rule "%1" + - Date: - תאריך: + No rule allowed access + - Time: - זמן: + Accessing user not member of an authorized user group + - Show + User has denied access - Delete - מחק + User confirmed access + @@ -3683,11 +4171,11 @@ Please save your work and close all programs. Autostart - + הפעלה אוטומטית Hide tray icon - + הסתרת סמליל מגש Start service @@ -3695,7 +4183,7 @@ Please save your work and close all programs. Stopped - + נעצר Stop service @@ -3703,164 +4191,320 @@ Please save your work and close all programs. State: + מצב: + + + Enable firewall exception + הפעל חריגה בחומת אש + + + Allow connections from localhost only + אפשר חיבורים ממחשב מקומי בלבד + + + VNC server + שרת VNC + + + Plugin: + תוסף + + + Restart %1 Service + הפעל מחדש את השירות %1 + + + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - Network + Running + רץ + + + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. - Demo server port + Show notification on remote connection - Enable firewall exception + Show notification when an unauthorized access is blocked - Allow connections from localhost only + Maximum session count - Internal VNC server port + Network port numbers + מספרי מפתחים (פורטים) + + + Veyon server + שרת Veyon + + + Internal VNC server + שרת VNC פנימי + + + Feature manager + מנהל מאפיינים + + + Demo server + שרת דוגמא + + + Miscellaneous network settings - VNC server + Session mode - Plugin: + Local session mode (single server instance for primary local session) - Restart %1 Service + Active session mode (single server instance for active local or remote session) - All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + Multi session mode (distinct server instance for each local and remote desktop session) - Running + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. - Feature manager port + Miscellaneous settings - Primary service port + Disable clipboard synchronization - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. + Session metadata - Show notification on remote connection + Content - Multi session mode (for terminal and remote desktop servers) + None + כלום + + + Value of an environment variable - Show notification when an unauthorized access is blocked + Value of a registry key + + + + Environment variable name: + + + + Registry key name: + + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) ServiceControl - Starting service %1 + Service control + שליטה בשירות + + + Starting %1 - Stopping service %1 + Stopping %1 - Registering service %1 + Restarting %1 - Unregistering service %1 + Registering %1 - Service control + Unregistering %1 - ServiceControlPlugin + ServiceControlCommands + + Register Veyon Service + הוסף שירות Veyon + + + Unregister Veyon Service + מחק שירות Veyon + + + Start Veyon Service + הפעל שירות Veyon + + + Stop Veyon Service + עצור שירות Veyon + + + Restart Veyon Service + הפעל מחדש את שירות Veyon + + + Query status of Veyon Service + בדוק מצד של שירות Veyon + Service is running - + שירות רץ Service is not running - + שירות לא רץ Configure and control Veyon service + הגדר ושלוט בשירות Veyon + + + Commands for configuring and controlling Veyon Service + + + ShellCommands - Register Veyon Service + Run command file - Unregister Veyon Service + File "%1" does not exist! - Start Veyon Service + Interactive shell and script execution for Veyon CLI - Stop Veyon Service + Commands for shell functionalities + + + SlideshowPanel + + Previous + הקודם + - Restart Veyon Service + Start/pause + הפעל\השהה + + + Next + הבא + + + Duration: + משך זמן: + + + View in separate window - Query status of Veyon Service + %1 Master – Slideshow + + + SpotlightPanel + + Add selected computers + הוספצ מחשבים נבחרים + - Commands for configuring and controlling Veyon Service + Remove selected computers + הסרת מחשבים נבחרים + + + Update computers in realtime + עדכון מחשבים בזמן אמת + + + Spotlight + זרקוֹר + + + Please select at least one computer to add. + נא לבחור לפחות מחשב אחד להוספה. + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. - ShellCommandLinePlugin + StartAppDialog - Run command file + Start application + התחל אפליקציה + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. - File "%1" does not exist! + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - Interactive shell and script execution for Veyon Control + Remember and add to application menu - Commands for shell functionalities + Application name + + Name: + שם: + + + e.g. VLC + לדוגמה VLC + SystemTrayIcon System tray icon - + סמליל של מגש מערכת @@ -3871,18 +4515,18 @@ Typically this is required to support terminal servers. Default (system user groups) - + ברירת מחדל (קבוצות משתמשים של מערכת) TestingCommandLinePlugin Test internal Veyon components and functions - + בדוק רכיבים פנימיים ופונקציות פנימיות של Veyon Commands for testing internal components and functions of Veyon - + פקודות לבדיקת רכיבים פנימיים של Veyon @@ -3892,7 +4536,7 @@ Typically this is required to support terminal servers. שלחו הודעת טקסט - Use the field below to type your message which will be sent to all selected users. + Please enter your message which send to all selected users. @@ -3904,7 +4548,7 @@ Typically this is required to support terminal servers. Use this function to send a text message to all users e.g. to assign them new tasks. - + השתמש באפשרות זאת על מנת לשלוח הודעה לכל המשתמשים - לדוגמה, לתת משימה חדשה Message from teacher @@ -3919,7 +4563,7 @@ Typically this is required to support terminal servers. UltraVncConfigurationWidget Enable capturing of layered (semi-transparent) windows - + אפשר לכידה של חלונות בעלי שכבות (שקופים חלקית) Poll full screen (leave this enabled per default) @@ -3927,52 +4571,76 @@ Typically this is required to support terminal servers. Low accuracy (turbo mode) - + דיוק נמוך (מצב טורבו) Builtin UltraVNC server configuration - + הגדרות שרת UltraVNC בנוי Enable multi monitor support - + הפעל תמיכה במספר מסכים Enable Desktop Duplication Engine on Windows 8 and newer + הפעל מנוע שכפול שולחן עבודה על ווינדוס 8 ומעלה + + + Maximum CPU usage - UserConfig + UserLoginDialog - No write access - אין גישת כתיבה + User login + התחברות משתמש - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - + Please enter a username and password for automatic login on all computers. + נא להזין שם משתמש וסיסמה להתחברות אוטומטית בכל המחשבים + + + Username + שם משתמש + + + Password + סיסמה - UserSessionControl + UserSessionControlPlugin - User session control - + Log in + התחברות + + + Click this button to log in a specific user on all computers. + לחץ על כפתור זה על מנת לחבר משתמש מסוים Log off - + ניתוק Click this button to log off users from all computers. - + לחץ על כפתור זה על מנת לנתק את כל המשתמשים מכל המחשבים. Confirm user logoff - + וידוא ניתוק משתמש Do you really want to log off the selected users? + אתה באמת רוצה לנתק את המשתמשים הנבחרים? + + + User session control + + + + Do you really want to log off <b>ALL</b> users? @@ -3980,23 +4648,23 @@ Typically this is required to support terminal servers. VeyonCore [OK] - + [הצלחה] [FAIL] - + [כישלון] Invalid command! - + פקודה לא תקינה! Available commands: - + פקודות זמינות Invalid arguments given - + ארגומנט לא תקין ניתן Not enough arguments given - use "%1 help" for more information @@ -4004,7 +4672,7 @@ Typically this is required to support terminal servers. Unknown result! - + תוצאה לא ידועה! Available modules: @@ -4016,49 +4684,57 @@ Typically this is required to support terminal servers. Plugin not licensed - + תוסף אינו מורשה INFO - + מידע ERROR - - - - licensed for - + שגיאה USAGE - + שימוש DESCRIPTION - + הסבר EXAMPLES - + דוגמות WARNING + אזהרה + + + Authentication test + בדיקת התחברות + + + Screen %1 - VeyonServiceControl + VeyonMaster - Veyon Service + No write access + אין גישת כתיבה + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - VncView + VeyonServiceControl - Establishing connection to %1 ... - + Veyon Service + שירות Veyon @@ -4072,7 +4748,7 @@ Typically this is required to support terminal servers. WindowsPlatformConfigurationPage Windows - + ווינדוס General @@ -4084,26 +4760,50 @@ Typically this is required to support terminal servers. Screen lock - + נעילת מסך Hide taskbar - + הסתר את שורת המשימות Hide start menu - + הסתר תפריט "התחל" Hide desktop - + הסתר שולחן עבודה User authentication - + אימות משתמש Use alternative user authentication mechanism + השתמש במנגנון התחברות משתמש אלטרנטיבי + + + User login + התחברות משתמש + + + Input start delay + עיכוב התחלת הקלט + + + Simulated key presses interval + + + + Confirm legal notice (message displayed before user logs in) + וודא התראה משפטית (הודעה שקופצת לפני שמשתמש מתחבר) + + + Use input device interception driver + + + + Use custom power scheme with disabled power button @@ -4111,10 +4811,10 @@ Typically this is required to support terminal servers. WindowsPlatformPlugin Plugin implementing abstract functions for the Windows platform - + התוסף ממש פונקציות אבסטרקטיות של פלטפורמת Windows - Plugin implementing specific functions for the Windows platform + Internal display @@ -4122,30 +4822,34 @@ Typically this is required to support terminal servers. WindowsServiceControl The service "%1" is already installed. - + השירות "%1" כבר מותקן. - The service "%1" could not be installed. - + The service "%1" has been installed successfully. + השירות "%1" הותקן בהצלחה. - The service "%1" has been installed successfully. - + The service "%1" has been uninstalled successfully. + השירות "%1" נמחק בהצלחה. - The service "%1" could not be uninstalled. + Service "%1" could not be found. + השירות "%1" לא יכול היה להימצא. + + + The service "%1" could not be installed (error %2). - The service "%1" has been uninstalled successfully. + Could not change the failure actions config for service "%1" (error %2). - The start type of service "%1" could not be changed. + The service "%1" could not be uninstalled (error %2). - Service "%1" could not be found. + The start type of service "%1" could not be changed (error %2). @@ -4153,15 +4857,15 @@ Typically this is required to support terminal servers. X11VncConfigurationWidget Builtin x11vnc server configuration - + הגדרת שרת x11vnc המובנה Custom x11vnc parameters: - + פרמטרים מותאמים אישית של x11vnc: Do not use X Damage extension - + אין להשתמש בהרחבה X Damage \ No newline at end of file diff --git a/translations/hu.ts b/translations/veyon_hu.ts similarity index 74% rename from translations/hu.ts rename to translations/veyon_hu.ts index 99d1fb21c..66a17f05d 100644 --- a/translations/hu.ts +++ b/translations/veyon_hu.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -11,7 +11,7 @@ License - Licenc + Licensz About Veyon @@ -80,10 +80,6 @@ Ha érdekel a Veyon fordítása (saját vagy egyéb nyelvre), esetleg meglévő All groups Összes csoport - - ... - ... - Access control rules Hozzáférési szabályok @@ -140,19 +136,18 @@ Ha érdekel a Veyon fordítása (saját vagy egyéb nyelvre), esetleg meglévő User groups backend: Felhasználói csoportok háttere: - - Missing user groups backend - Hiányzik a felhasználói csoportok háttere - - - No default user groups plugin was found. Please check your installation! - Nincs alapértelmezett felhasználóicsoport-bővítmény. Kérem, ellenőrizd telepítésed! - Restrict access to members of specific user groups Hozzáférés tiltása meghatározott felhasználói csoport tagjainak + + AccessControlProvider + + Provider for access control features + + + AccessControlRuleEditDialog @@ -179,30 +174,10 @@ Ha érdekel a Veyon fordítása (saját vagy egyéb nyelvre), esetleg meglévő Rule description: Szabály leírása: - - Invert all conditions ("is/has" interpreted as "is/has not") - Feltételek megfordítása ("van/volt" cseréje: "nincs/nem volt") - Conditions Feltételek - - is member of group - tagja a csoportnak - - - Accessing computer is localhost - A hozzáférő számítógép a helyi számítógép - - - Accessing user is logged on user - A hozzáférő felhasználó már bejelentkezett - - - Accessing user is already connected - A hozzáférő felhasználó már csatlakozott - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. Ha egynél több feltétel aktív, az összes feltételnek teljesülnie kell, hogy a szabály életbe lépjen (logikai ÉS). Ha a szabályok közül csak egy teljesül (logikai VAGY), kérem, készíts több hozzáférés-vezérlési szabályt. @@ -236,33 +211,125 @@ Ha érdekel a Veyon fordítása (saját vagy egyéb nyelvre), esetleg meglévő Hozzáférő számítógép - Local (logged on) user - Helyi (bejelentkezett) felhasználó + Always process rule and ignore conditions + Mindig hassanak a szabályok és hagyja figyelmen kívül a feltételeket - Local computer - Helyi számítógép + Accessing computer and local computer + Hozzáférés a számítógéphez és a helyi számítógéphez - Always process rule and ignore conditions - Mindig hassanak a szabályok és hagyja figyelmen kívül a feltételeket + User being accessed + Elérendő felhasználó - No user logged on - Egy felhasználó sem jelentkezett be + is logged in locally + helyileg jelentkezett be + + + is logged in remotely + távolról jelentkezett be + + + No user is logged in locally + Senki sem jelentkezett be helyileg + + + One or multiple users are logged in locally + Egy több felhasználó helyileg jelentkezett be - Accessing user has one or more groups in common with local (logged on) user - A hozzáférő felhasználó egy vagy több csoport közös tagja a helyi (bejelentkezett) felhasználóval + No user is logged in remotely + Senki sem jelentkezett be távolról - Accessing computer and local computer are at the same location - A hozzáférő számítógép a helyi számítógéppel egy helyszínen van + One or multiple users are logged in remotely + Egy több felhasználó távolról jelentkezett be is located at helyezkedik el + + is not located at + nem helyezkedik el + + + are located at the same location + ugyanazon a helyen található + + + are not located the same location + nem ugyanazon a helyen található + + + is member of group + tagja a csoportnak + + + is not member of group + nem tagja a csoportnak + + + is authenticated via + hitelesítése + + + is not authenticated via + hitelesítése nem + + + has one or more groups in common with user being accessed + egy vagy több közös csoportja van az elérendő felhasználóval + + + has no groups in common with user being accessed + nincs közös csoportja van az elérendő felhasználóval + + + equals user being accessed + egyenlő az elérendő felhasználóval + + + is different from user being accessed + eltérő az elérendő felhasználótól + + + is already connected + már csatlakozott + + + is not connected + nem csatlakozott + + + is local computer + helyi számítógép + + + is not local computer + nem helyi számítógép + + + Computer being accessed + Elérendő számítógépek + + + Session being accessed is a user session + Az elérendő munkamenet egy felhasználói munkamenet + + + Session being accessed is a login screen + Az elérendő munkamenet egy bejelentkezési képernyő + + + Local computer is already being accessed + + + + Local computer is not yet being accessed + + AccessControlRulesTestDialog @@ -306,42 +373,44 @@ Ha érdekel a Veyon fordítása (saját vagy egyéb nyelvre), esetleg meglévő The access in the given scenario needs permission of the logged on user. Az adott esetben a hozzáféréshez a bejelentkezett felhasználó jogosultságára van szükség. - - ERROR: Unknown action - HIBA: Ismeretlen művelet - Test result Teszt eredménye: - - - AndroidPlatformConfigurationPage - Android - + Authentication method + Hitelesítési mód - General - Általános + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + Bevezetés - - - AuthKeysConfigurationPage - Authentication keys - Hitelesítési kulcs + Please perform the following steps to set up key file authentication: + Kérem, hajtsd végre a következő lépéseket a kulcsfájl-hitelesítés beállításához: - Introduction - Bevezetés + 1) Create a key pair on the master computer. + 1) Hozz létre egy kulcspárt a mesterszámítógépen. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Állíts be egy hozzáférési csoportot, amelynek tagjai hozzáférhetnek a többi számítógéphez. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Exportáld a nyilvános kulcsot , majd importáld ugyanazon a néven az összes számítógépre. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Kérem, további információkért olvassa le a <a href="https://veyon.readthedocs.io/en/latest/admin/index.html"> Veyon üzemeltetői leírást </a>. Key file directories @@ -355,14 +424,20 @@ Ha érdekel a Veyon fordítása (saját vagy egyéb nyelvre), esetleg meglévő Private key file base directory Privát kulcsfájl alapmappája - - ... - ... - Available authentication keys Elérhető hitelesítési kulcsok + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + A hitelesítési kulcspár kettő összetartozó kriptográfiai kulcsból áll, egy privát és egy publikus kulcsból. +A privát kulcs használatával a mester számítógép felhasználói hozzáférhetnek a kliens számítógépekhez. +Fontos, hogy csak hitelesített felhasználóknak legyen olvasási hozzáférése a privát kulcsfájlhoz. +A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcsolatkérések hitelesítéséhez. + Create key pair Kulcspár létrehozása @@ -403,10 +478,6 @@ Ha érdekel a Veyon fordítása (saját vagy egyéb nyelvre), esetleg meglévő Please select a key to delete! Kérem, válaszd ki a törlendő kulcsot! - - Please enter the name of the user group or role for which to import the authentication key: - Kérem, add meg a felhasználó csoport vagy szerep nevét, amely számára importálod a hitelesítési kulcsot: - Please select a key to export! Kérem, válaszd ki az importálandó kulcsot! @@ -420,34 +491,10 @@ Ha érdekel a Veyon fordítása (saját vagy egyéb nyelvre), esetleg meglévő Kérem, válassz egy kulcsot, amelyhez hozzáférési csoportot állítasz be! - Please perform the following steps to set up key file authentication: - Kérem, hajtsd végre a következő lépéseket a kulcsfájl-hitelesítés beállításához: - - - 1) Create a key pair on the master computer. - 1) Hozz létre egy kulcspárt a mesterszámítógépen. - - - 2) Set an access group whose members should be allowed to access other computers. - 2) Állíts be egy hozzáférési csoportot, amelynek tagjai hozzáférhetnek a többi számítógéphez. - - - 3) Export the public key and import it on all client computers with the same name. - 3) Exportáld a nyilvános kulcsot , majd importáld ugyanazon a néven az összes számítógépre. - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - Kérem, további információkért olvassa le a <a href="https://veyon.readthedocs.io/en/latest/admin/index.html"> Veyon üzemeltetői leírást </a>. - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - A hitelesítési kulcspár kettő összetartozó kriptográfiai kulcsból áll, egy privát és egy publikus kulcsból. -A privát kulcs használatával a mester számítógép felhasználói hozzáférhetnek a kliens számítógépekhez. -Fontos, hogy csak hitelesített felhasználóknak legyen olvasási hozzáférése a privát kulcsfájlhoz. -A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcsolatkérések hitelesítéséhez. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + @@ -647,10 +694,6 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. Ez a parancs a beállított kulcskönyvtárban lévő összes elérhető hitelesítési kulcsot felsorolja. Ha "%1" lehetőség meg van adva, egy, a kulcs részleteit tartalmazó táblázat fog megjelenni. Ha a kulcs nem érhető el, például olvasási jogosultságok hiánya miatt, néhány részlete hiányozhat. - - Please specify the command to display help for! - Kérem, válaszd ki az a parancsot, melynek súgóját megjelenítsük! - TYPE TÍPUS @@ -659,10 +702,6 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso PAIR ID PÁR ID - - Command line support for managing authentication keys - Parancssori támogatás a hitelesítési kulcsok kezeléséhez - Commands for managing authentication keys A hitelesítési kulcsokat kezelő parancsok @@ -679,6 +718,30 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. Ez a parancs kicsomagolja a nyilvános kulcsrészt <KEY> privát kulcsból és a megfelelő nyilvános kulcsként menti. Amikor egy másik mesterszámítógépet állítasz be, elegendő csak a privát kulcsot átmásolni. A publikus kulcs ebből már előállítható. + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + A hitelesítő kulcsfájlok nincsenek megfelelően beállítva ezen a számítógépen. Új kulcsfájlokat kell létrehozni vagy másik hitelesítési módszert kell választani a Veyon Konfigurátor használatával. + + + Key file authentication + Kulcsfájl hitelesítés + + + Key file + Kulcsfájl + + + Please specify the key name (e.g. "teacher/public") as the first argument. + Kérem, add meg a kulcsnevet (pl. tanár/publikus) az első argumentumként. + + + Please specify the command to display help for. + Kérem, válaszd ki az a parancsot, melynek súgóját megjelenítsük. + + + The specified command does not exist or no help is available for it. + A megadott parancs nem létezik vagy nincs hozzá segítség. + AuthKeysTableModel @@ -700,89 +763,232 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - Számítógépek + General + Általános - Name - Megnevezés + Username to bind DN mapping: + Felhasználónév a DN-leképezés kötéséhez : - Host address/IP - Kiszolgáló címe/IP-je + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + pl. %username%@DOMAIN or cn=%username%,ou=users,dc=pelda,dc=org + + + AuthLdapDialog - MAC address - Fizikai cím + Veyon Logon + Veyon bejelentkezés - Add new computer - Új számítógép hozzáadása + Please enter your domain/LDAP username and password in order to access computers. + Kérem, add meg domain/LDAP felhasználóneved és jelszavad a számítógépek eléréséhez. - Remove selected computer - Kiválasztott számítógép eltávolítása + Username + Felhasználónév - New computer - Új számítógép + Password + Jelszó - Builtin directory - Beépített mappa + Authentication error + Hitelesítési hiba - Locations & computers - Helyszínek és számítógépek + Logon failed with given username and password. Please try again! + A megadott felhasználónévvel és jelszóval a bejelentkezés sikertelen. Próbáld újra! + + + AuthLogonDialog - Locations - Helyszínek + Veyon Logon + Veyon bejelentkezés - Add new location - Új helyszín hozzáadása + Please enter your username and password in order to access computers. + Kérem, a számítógépek eléréséhez add meg felhasználóneved és jelszavad. - Remove selected location - Kiválasztott helyszín eltávolítása + Username + Felhasználónév - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - CSV fájlok importálása parancssori interfészen keresztül lehetséges. Bővebb információért látogassa meg az <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online dokumentációt</a>. + Password + Jelszó - New location - Új helyszín + Authentication error + Hitelesítési hiba + + + Logon failed with given username and password. Please try again! + A megadott felhasználónévvel és jelszóval a bejelentkezés sikertelen. Próbáld újra! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command - Konkrét parancsról segítség megjelenítése + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + A megadott felhasználónév és jelszó helytelen. Érvényes hitelesítő adatokat kell megadni vagy másik hitelesítési módszert kell választani a Veyon Konfigurátor használatával. - Import objects from given file - Objektumok importálása a megadott fájlból + Logon authentication + Bejelentkezési hitelesítés - Export objects to given file - Objektumok exportálása a megadott fájlba + Logon + Bejelentkezés + + + AuthSimpleDialog - Invalid type specified. Valid values are "%1" or "%2". - Érvénytelen típusmeghatározás. "%1" vagy "%2" lehetséges. + Veyon Logon + Veyon bejelentkezés - Type - Típus + Please enter the Veyon password: + A Veyon jelszó megadása: - Name - Megnevezés + Authentication error + Hitelesítési hiba + + + Logon failed with given password. Please try again! + A megadott jelszóval a bejelentkezés sikertelen. Próbáld újra! + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + A megadott jelszó helytelen. Meg kell adni a helyes jelszót vagy másik hitelesítési módszert kell választani a Veyon Konfigurátor használatával. + + + Simple password authentication + Egyszerű jelszavas hitelesítés + + + Simple password + Egyszerű jelszó + + + + AuthenticationPage + + Authentication is set up properly on this computer. + A hitelesítés megfelelően van beállítva ezen a számítógépen. + + + + AuthenticationPageTab + + Enabled + Bekapcsolva + + + Test + Tesztelés + + + + BuiltinDirectoryConfiguration + + Builtin directory + Beépített mappa + + + + BuiltinDirectoryConfigurationPage + + Computers + Számítógépek + + + Name + Megnevezés + + + Host address/IP + Kiszolgáló címe/IP-je + + + MAC address + Fizikai cím + + + Add new computer + Új számítógép hozzáadása + + + Remove selected computer + Kiválasztott számítógép eltávolítása + + + New computer + Új számítógép + + + Builtin directory + Beépített mappa + + + Locations + Helyszínek + + + Add new location + Új helyszín hozzáadása + + + Remove selected location + Kiválasztott helyszín eltávolítása + + + New location + Új helyszín + + + Directory name + Mappanév + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + CSV-fájlok importálása parancssori interfészen keresztül lehetséges. Bővebb információért látogasd meg az <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online dokumentációt</a>. + + + + BuiltinDirectoryPlugin + + Show help for specific command + Konkrét parancsról segítség megjelenítése + + + Import objects from given file + Objektumok importálása a megadott fájlból + + + Export objects to given file + Objektumok exportálása a megadott fájlba + + + Invalid type specified. Valid values are "%1" or "%2". + Érvénytelen típusmeghatározás. "%1" vagy "%2" lehetséges. + + + Type + Típus + + + Name + Megnevezés Host address @@ -1000,6 +1206,14 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso MAC ADDRESS FIZIKAI CÍM + + The specified command does not exist or no help is available for it. + A megadott parancs nem létezik vagy nincs hozzá segítség. + + + Location "%1" not found. + Helyszín "%1" nem található. + BuiltinUltraVncServer @@ -1017,17 +1231,13 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso ComputerControlListModel - - Host/IP address: %1 - Kiszolgáló/IP cím: %1 - Active features: %1 Aktív szolgáltatások: %1 Online and connected - Online és sikeren csatlakozott + Online és sikeresen csatlakozott Establishing connection @@ -1037,10 +1247,6 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Computer offline or switched off A számítógép nincs hálózaton vagy kikapcsolták - - Service unreachable or not running - A szolgáltatás nem érhető el vagy jelenleg nem fut - Authentication failed or access denied A hitelesítés sikertelen vagy a hozzáférés nem engedélyezett @@ -1061,6 +1267,38 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Location: %1 Helyszín: %1 + + [no user] + [nincs felhasználó] + + + Veyon Server unreachable or not running + Veyon szerver nem érhető el vagy nem fut + + + Name: %1 + Név: %1 + + + Hostname: %1 + + + + unknown + ismeretlen + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + ComputerControlServer @@ -1092,6 +1330,17 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. "%1%" felhasználó "%2" kiszolgálóról megpróbálta eléri ezt a számítógépet, de letiltottuk hozzáférés-hitelesítési beállítások miatt. + + Active connections: + Aktív kapcsolatok + + + + ComputerGroupSelector + + Group %1 + %1 csoport + ComputerManager @@ -1117,15 +1366,50 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. - Nem sikerült azt a helyszínt azonosítani, amelyikhez a számítógép tartozik. Ez a rendszer hibás konfigurálására utal. Ehelyett a számítógépkijelölés-panelen az összes helyszínt megjelentjük. + Nem sikerült azt a helyszínt azonosítani, amelyikhez a számítógép tartozik. Ez a rendszer hibás konfigurálására utal. Ehelyett a számítógépkijelölés-panelen az összes helyszínt megjelenítjük. + + + Logged in since + Bejelentkezve ekkortól + + + %1 days + %1 nap + + + 1 day + 1 nap - ComputerSelectPanel + ComputerMonitoring + + Computers + Számítógépek + + + Search users and computers + Felhasználók és számítógépek keresse + + + Select all + Mind kijelölése + + + Unselect all + Minden kijelölés törlése + + + Add to group + Hozzadás csoporthoz + - Computer management - Számítógép-kezelés + Remove from group + Eltávolítás csoportból + + + ComputerSelectPanel Computer search Számítógép keresése @@ -1154,81 +1438,85 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Could not write the computer and users list to %1! Please check the file access permissions. Nem sikerült a számítógép- és a felhasználólista kiírása ide: %1. Ellenőrizd a hozzáférési jogosultságaidat. + + Search computers + Számítógépek keresése + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. - Létező konfigurációs fájlt adj meg importáláshoz. + Clear system-wide Veyon configuration + Az egész rendszerre kiterjedő Veyon konfiguráció törlése - Please specify a valid filename for the configuration export. - Valós fájlnevet adj meg a konfiguráció exportálásához. + List all configuration keys and values + Összes konfigurációs kulcs és és értékének felsorolása - Please specify a valid key. - Valós kulcsot adj meg. + Import configuration from given file + Konfiguráció importálása adott fájlból - Specified key does not exist in current configuration! - A megadott kulcs nem létezik a jelenlegi konfigurációban! + Export configuration to given file + Konfiguráció exportálása adott fájlba - Please specify a valid value. - Kérem, valós értéket adj meg. + Read and output configuration value for given key + Adott kulcs konfigurációs értékének olvasása és kimenete - Configure Veyon at command line - Veyon konfigurálása parancssorból + Write given value to given configuration key + Adott érték írása adott konfigurációs kulcsba - Output file is not writable! - Kimeneti fájl nem írható! + Unset (remove) given configuration key + Adott konfigurációs kulcs kikapcsolása (eltávolítása) - Output directory is not writable! - Kimeneti könyvtár nem írható! + Upgrade and save configuration of program and plugins + A program és bővítmények frissítése és konfigurációjuk mentése + + + Please specify an existing configuration file to import. + Létező konfigurációs fájlt adj meg importáláshoz. Configuration file is not readable! Konfigurációs fájl nem olvasható! - Clear system-wide Veyon configuration - Az egész rendszerre kiterjedő Veyon konfiguráció törlése + Please specify a valid filename for the configuration export. + Valós fájlnevet adj meg a konfiguráció exportálásához. - List all configuration keys and values - Összes konfigurációs kulcs és és értékének felsorolása + Output file is not writable! + Kimeneti fájl nem írható! - Import configuration from given file - Konfiguráció importálása adott fájlból + Output directory is not writable! + Kimeneti könyvtár nem írható! - Export configuration to given file - Konfiguráció exportálása adott fájlba + Please specify a valid key. + Valós kulcsot adj meg. - Read and output configuration value for given key - Adott kulcs konfigurációs értékének olvasása és kimenete + Specified key does not exist in current configuration! + A megadott kulcs nem létezik a jelenlegi konfigurációban! - Write given value to given configuration key - Adott érték írása adott konfigurációs kulcsba + Please specify a valid value. + Kérem, valós értéket adj meg. - Unset (remove) given configuration key - Adott konfigurációs kulcs kikapcsolása (eltávolítása) + Configure Veyon at command line + Veyon konfigurálása parancssorból Commands for managing the configuration of Veyon Veyon konfigurálásához parancsok - - Upgrade and save configuration of program and plugins - A program és bővítmények frissítése és konfigurációjuk mentése - ConfigurationManager @@ -1252,6 +1540,10 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Could not apply platform-specific configuration settings. A platformfüggő konfigurációs beállítások nem alkalmazhatóak. + + Could not configure the firewall configuration for the %1 Service. + Nem módosíthatók %1 szolgáltatás tűzfalbeállításai. + DemoClient @@ -1282,10 +1574,6 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Memory limit Memóriakorlát - - Use multithreading (experimental) - Többszálúság használata (kísérleti) - MB MB @@ -1302,13 +1590,17 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Slow down thumbnail updates while demo is running Indexképek frissítésének lassítása a demó futása alatt. + + Bandwidth limit + Sávszélesség korlátozása + + + MB/s + MB/s + DemoFeaturePlugin - - Fullscreen demo - Teljes képernyős demó - Stop demo Demó leállítása @@ -1322,16 +1614,60 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Bemutató megjelenítése képernyőbroadcasttal - Demo server - Demószerver + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Ebben a módban a képernyőd az összes számítógépen ablakban jelenik meg. A felhasználók eközben ablakot tudnak váltani. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - Ebben a módban a képernyőd az összes számítógépén teljes képernyőn jelenik meg, ezalatt a felhasználók bemeneti eszközeit blokkoljuk. + Demo + Demo - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - Ebben a módban a képernyőd az összes számítógépen ablakban jelenik meg. A felhasználók eközben ablakot tudnak váltani. + Share your screen or allow a user to share his screen with other users. + Oszd meg a képernyődet vagy engedélyezd egy felhasználónak, hogy megossza a képernyőjét a többiekkel. + + + Full screen demo + Teljes képernyős demó + + + Share your own screen in fullscreen mode + Saját képernyőm megosztása teljes nézetben + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + Ebben a módban az összes számítógépen teljes képernyőn jelenik meg a képernyőd, egyúttal a felhasználók bemeneti eszközeit zároljuk. + + + Share your own screen in a window + Saját képernyőm megosztása ablakban + + + Share selected user's screen in fullscreen mode + Kiválasztott felhasználó képernyőjének megosztása teljes nézetben + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + Ebben a módban az összes számítógépen teljes képernyőn jelenik meg a kiválasztott felhasználó képernyőképe, egyúttal a felhasználók bemeneti eszközeit zároljuk. + + + Share selected user's screen in a window + Kiválasztott felhasználó képernyőjének megosztása ablakban + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + Ebben a módban az összes számítógépen ablakban jelenik meg a kiválasztott felhasználó képernyőképe. A felhasználók eközben ablakot tudnak váltani. + + + Please select a user screen to share. + Válaszd ki a megosztandó képernyőt. + + + Please select only one user screen to share. + Csak egy képernyőt válassz a megosztáshoz. + + + All screens + Összes képernyő @@ -1359,14 +1695,6 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso DesktopServicesConfigurationPage - - Programs & websites - Programok és weboldalak - - - Predefined programs - Előre definiált programok - Name Megnevezés @@ -1375,14 +1703,6 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Path Útvonal - - Add new program - Új program hozzáadása - - - Remove selected program - Kiválasztott program eltávolítása - Predefined websites Előre definiált weboldal @@ -1395,21 +1715,37 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso URL URL - - New program - Új program - New website Új weboldal + + Applications & websites + Alkalmazások & weboldalak + + + Predefined applications + Előre definiált alkalmazások + + + Add new application + Új alkalmazás hozzáadása + + + Remove selected application + Kiválasztott alkalmazás eltávolítása + + + Add new website + Új weboldal hozzáadása + + + New application + Új alkalmazás + DesktopServicesFeaturePlugin - - Run program - Program futtatása - Open website Weboldal megnyitása @@ -1419,28 +1755,32 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Kattints erre a gombra, hogy az összes számítógépen megnyíljon egy weboldal. - Start programs and services in user desktop - Programok és szolgáltatások indítása a felhasználó asztalon + Open website "%1" + "%1" weboldal megnyitása + + + Custom website + Egyéni weboldal - Click this button to run a program on all computers. - Kattints erre a gombra, hogy egy programot futtass az összes számítógépen. + Start application + Alkalmazás indítása - Run program "%1" - "%1" program futtatása + Click this button to start an application on all computers. + Kattints erre a gombra, hogy az összes számítógépen elinduljon egy alkalmazás. - Custom program - Egyéni program + Start application "%1" + "%1" alkalmazás indítása - Open website "%1" - "%1" weboldal megnyitása + Custom application + Egyéni alkalmazás - Custom website - Egyéni weboldal + Start apps and open websites in user sessions + Alkalmazások indítása és a weboldalak megnyitása felhasználói munkamenetekben @@ -1473,17 +1813,21 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Play tutorial video Bemutató videó lejátszása - - Custom program - Egyéni program - Handout - + Kiosztás Texts to read - + Olvasandó szövegek + + + generic-student-user + generic-student-user + + + Custom application + Egyéni alkalmazás @@ -1509,10 +1853,165 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso - FeatureControl + FeatureCommands - Feature control - Szolgáltatásvezérlés + List names of all available features + Az összes elérhető funkció nevének felsorolása + + + Show table with details of all available features + Az összes elérhető funkció adatainak táblázata + + + Start a feature on a remote host + Funkció indítása egy távoli kiszolgálón + + + Stop a feature on a remote host + Funkció leállítása egy távoli kiszolgálón + + + Please specify the command to display help for. + Kérem, válaszd ki az a parancsot, melynek súgóját megjelenítsük. + + + Displays a list with the names of all available features. + Megjelenít egy felsorolást az összes elérhető funkció nevével. + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + Megjelenít egy táblázatot az összes elérhető funkció adataival. Ez tartalmazza a leírást, az UID-t, a funkciót biztosító beépülő modul nevét és néhány egyéb megvalósítással kapcsolatos részletet. + + + HOST ADDRESS + HOST ADDRESS + + + FEATURE + TULAJDONSÁG + + + ARGUMENTS + ÉRVEK + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + Elindítja a megadott szolgáltatást a megadott kiszolgálón a távolról futó Veyon-szerverhez való csatlakozással. A szolgáltatás névvel vagy UID-vel adható meg. Az összes elérhető funkció megtekintéséhez használja a ``show`` parancsot. A szolgáltatástól függően további argumentumokat (például a megjelenítendő szöveges üzenetet) kell megadni egyetlen JSON-karakterláncként kódolva. További információért tekintse meg a fejlesztői dokumentációt + + + Lock the screen + Képernyő zárolása + + + Display a text message + Szöveges üzenet megjelenítése + + + Test message + Tesztüzenet + + + Start an application + Alkalmazás indítása + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + Leállítja a megadott szolgáltatást a megadott kiszolgálón a távoli Veyon-szerverhez való csatlakozással. A szolgáltatás névvel vagy UID-vel adható meg. Az összes elérhető funkció megtekintéséhez használja a ``show`` parancsot. + + + Unlock the screen + Képernyő zárolásának feloldása + + + The specified command does not exist or no help is available for it. + A megadott parancs nem létezik vagy nincs hozzá segítség. + + + Name + Megnevezés + + + Description + Leírás + + + Master + Mester + + + Service + Szolgáltatás + + + Worker + Dolgozó + + + UID + UID + + + Plugin + Bővítmény + + + Invalid feature name or UID specified + Érvénytelen tulajdonságnév vagy UID megadás + + + Error parsing the JSON-encoded arguments: %1 + Hiba a JSON-kódolású argumentumok elemzése során: %1 + + + Failed to initialize credentials + Nem sikerült inicializálni a hitelesítő adatokat + + + Could not establish a connection to host %1 + %1 kiszolgálóval nem sikerült kapcsolatot létesíteni. + + + Failed to send feature control message to host %1 + %1 kiszolgálóhoz nem sikerült elküldeni a funkcióvezérlő üzenetet. + + + Feature-related CLI operations + Funkciókhoz kapcsolódó CLI műveletek + + + Commands for controlling features + Funkcióvezérlés parancsai + + + + FileTransferConfigurationPage + + File transfer + Fájlátvitel + + + Directories + Mappák + + + Destination directory + Célmappa + + + Default source directory + Alapértelmezett forráskönyvtár + + + Options + Lehetőség + + + Remember last source directory + Emlékezz az utolsó forráskönyvtárra + + + Create destination directory if it does not exist + Célmappa létrehozása, ha nem létezik @@ -1557,6 +2056,13 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Fájlok felülírása + + FileTransferFileDialog + + Select one or more files to transfer + Válasszon ki egy vagy több fájlt az átvitelhez + + FileTransferPlugin @@ -1565,7 +2071,7 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Click this button to transfer files from your computer to all computers. - Kattints erre gombra, hogy számítógépedről fájlokat küld át az összes számítógépre. + Kattints erre gombra, hogy számítógépedről fájlokat küldj át az összes számítógépre. Select one or more files to transfer @@ -1614,10 +2120,6 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Log file directory Naplófájl mappája - - ... - ... - Log level Naplózás szintje @@ -1658,18 +2160,6 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Log to standard error output Naplózás standard hibakimenetre - - Network object directory - Hálózatobjektum-mappa - - - Backend: - Háttér: - - - Update interval: - Frissítési időköz: - %1 service %1 szolgáltatás @@ -1706,103 +2196,80 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso x x - - seconds - másodpercek - Write to logging system of operating system Írás az operációs rendszer naplózási rendszerébe - Authentication - Hitelesítés - - - Method: - Módszer: - - - Logon authentication - Bejelentkezési hitelesítés - - - Key file authentication - Kulcsfájl hitelesítés - - - Test - Tesztelés + TLS configuration + TLS konfiguráció - Authentication is set up properly on this computer. - A hitelesítés megfelelően van beállítva ezen a számítógépen. + Use certificate authority for TLS connections + Tanúsítványhitelesítő használata a TLS kapcsolatokhoz - Authentication keys are not set up properly on this computer. - A hitelesítési kulcsok nem megfelelően vannak beállítva ezen a számtógépen. + CA certificate file + CA tanúsítványfájl - Authentication test - Hitelesítési teszt + ... + ... - - - InternetAccessControlConfigurationPage - Internet access control - Internethozzáférés-vezérlés + Host certificate file + Kiszolgálótanúsítvány-fájl - Backend: - Háttér: + Host private key file + Kiszolgáló privát kulcs fájl - General settings - Általános beállítások + Style: + Stílus: - Backend settings - Háttér beállításai + Native + Natív - - - InternetAccessControlPlugin - Block access to the internet - Internet-hozzáférés blokkolása + Color scheme: + - Allow access to the internet - Internet-hozzáférés engedélyezése + Light + - Show help about command - Parancsról segítség megjelenítése + Dark + - Block internet - Internet blokkolása + User groups + Felhasználói csoportok - Click this button to block access to the internet. - Az internet-hozzáférés blokkolásához kattintson erre a gombra. + Backend: + Háttér: - Unblock internet - Internet blokkolásának feloldása + Include user groups from domain + - Click this button to allow access to the internet. - Az internet-hozzáférés engedélyezéséhez kattintson erre a gombra. + Missing user groups backend + Hiányzik a felhasználói csoportok háttere - Control access to the internet - Internethozzáférés-vezérlés + No user groups plugin was found. Please check your installation! + + + + HeadlessVncServer - Commands for controlling access to the internet - Internethozzáférés-vezérlés parancsai + Headless VNC server + Headless VNC szerver @@ -1820,25 +2287,354 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso - LdapConfigurationPage + LdapConfiguration - Basic settings - Alapbeállítások + LDAP connection failed + LDAP kapcsolat sikertelen - General - Általános + Could not connect to the LDAP server. Please check the server parameters. + +%1 + Nem sikerült kapcsolódni az LDAP szerverhez. Kérem, ellenőrizd a szerver paramétereit. + +%1 - LDAP server and port - LDAP szerver és port + LDAP bind failed + LDAP kötés sikertelen - Bind DN - Kötés DN-je + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + Nem sikerült kötést létrehozni a LDAP szerverrel. Kérem, ellenőrizd a szerver paramétereit és a kötést hitelesítő adatokat. + +%1 - Bind password + LDAP bind successful + LDAP kötés sikerült + + + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Sikeresen csatlakoztunk az LDAP szerverhez, és létrejött az LDAP kötés. Az LDAP alapszintű beállításai helyesek. + + + LDAP base DN test failed + LDAP alap DN teszt sikertelen + + + Could not query the configured base DN. Please check the base DN parameter. + +%1 + Nem sikerült lekérdezni az konfigurált alap DN-t. Kérem, ellenőrizd az alap DN paramétert. + +%1 + + + LDAP base DN test successful + LDAP alap DN teszt sikeres + + + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + Az LDAP alap DN-t sikeresen lekérdeztük. Az alábbi bejegyzéseket találtuk: + +%1 + + + LDAP naming context test failed + LDAP névkontextusteszt sikertelen + + + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + Nem sikerült elnevezési kontextusokból lekérdezni az alap DN-t. Kérem, ellenőrizd az elnevezési kontextusok attribútuma paramétert. + +%1 + + + LDAP naming context test successful + LDAP névkontextus-teszt sikerült + + + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + Az LDAP névmeghatározását sikeresen lekérdeztük. A következő alap DN-t találtuk: +%1 + + + user tree + felhasználófa + + + User tree + Felhasználófa + + + group tree + csoportfa + + + Group tree + Számítógépfa + + + computer tree + számítógépfa + + + Computer tree + Számítógépfák + + + computer group tree + számítógépcsoport-fa + + + Computer group tree + Számítógépcsoport-fa + + + user objects + felhasználói objektumok + + + User login name attribute + A felhasználó bejelentkezési nevének attribútuma + + + group members + csoporttagok + + + Group member attribute + Csoporttagság attribútumok + + + Group not found + Csoport nem találgató + + + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + "1%" nevű csoport nem található. Kérem, ellenőrizd a csoport nevét vagy a csoportfa paramétert. + + + computer objects + számítógép-objektumok + + + Computer display name attribute + Számítógép megjelenítési név attribútum + + + Invalid hostname + Érvénytelen kiszolgálónév + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Úgy konfiguráltad a rendszert, hogy az a számítógép kiszolgálónevét teljesen minősített domainnévként (FQDN) tárolja, de a kiszolgálónevet domain nélkül kell megadni. + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Úgy konfiguráltad a rendszert, hogy az a számítógép kiszolgálónevét domain nélküli egyszerű névként tárolja, de a kiszolgálónevet domain nélkül kell megadni. + + + Computer hostname attribute + Számítógép kiszolgálónév attribútuma + + + computer MAC addresses + számítógép fizikai címei + + + Computer MAC address attribute + Számítógép fizikai címének attribútuma + + + computer locations + számítógéphelyszínek + + + Computer location attribute + Számítógéphelyszín attribútum + + + Location name attribute + Helyszínnév attribútum + + + users + felhasználók + + + user groups + felhasználói csoportok + + + computers + számítógépek + + + computer groups + számítógépcsoportok + + + computer containers + számítógép tárolók + + + groups of user + felhasználó csoportjai + + + User not found + Felhasználó nem található + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + "%1" nevű felhasználó nem található. Kérem, ellenőrizd a felhasználónevet vagy a felhasználó-fa paramétert. + + + groups of computer + számítógép csoportjai + + + Computer not found + Számítógép nem található + + + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + "%1" nevű kiszolgálónevű számítógép nem található. Kérem, ellenőrizd a kiszolgálónevet vagy a számítógépfa paramétert. + + + Hostname lookup failed + Kiszolgálónév keresése sikertelen + + + Could not lookup hostname for IP address %1. Please check your DNS server settings. + %1 IP címhez nem sikerült lekérdezni a kiszolgálónevet. Kérem, ellenőrizd a DNS szerver beállításait. + + + location entries + Helyszín-bejegyzések + + + Computer groups filter + Számítógépcsoport-szűrő + + + Computer locations identification + Számítógéphelyszínek azonosítója + + + Filter for computer groups + Számítógépcsoportok szűrője + + + Invalid test value + Érvénytelen tesztérték + + + An empty or invalid value has been supplied for this test. + Egy üres vagy érvénytelen értéket adtál meg ehhez a teszthez. + + + LDAP %1 test failed + %1 LDAP teszt sikertelen + + + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + Egy bejegyzést sem sikerült lekérni %1 konfigurációban. Ellenőrizze a "%2" paramétert. + +%3 + + + LDAP %1 test successful + %1 LDAP teszt sikeres + + + The %1 has been queried successfully and %2 entries were found. + %1 objektum lekérdezése sikeres, %2 jegyezést találtunk. + + + LDAP test failed + LDAP tesztelése sikertelen + + + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + Egy %1 sem kérhető le. Ellenőrizze %2 paraméter(eke)t vagy adja meg a már létező objektum nevét. + +%3 + + + and + és + + + LDAP test successful + LDAP tesztelése sikeres + + + %1 %2 have been queried successfully: + +%3 + %1 %2 lekérdezés sikeres: + +%3 + + + LDAP filter test failed + LDAP szűrő teszt sikertelen + + + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 + A konfigurált szűrővel egy %1 objektumot sem sikerült lekérdezni. Kérem, ellenőrizd %1 LDAP szűrőt. + +%2 + + + LDAP filter test successful + LDAP szűrő teszt sikeres + + + %1 %2 have been queried successfully using the configured filter. + %1 %2-t sikeresen lekérdezted a a konfigurált szűrő használatával. + + + LDAP directory + LDAP könyvtár + + + + LdapConfigurationPage + + Basic settings + Alapbeállítások + + + General + Általános + + + LDAP server and port + LDAP szerver és port + + + Bind DN + Kötés DN-je + + + Bind password Kötés jelszava @@ -1973,56 +2769,6 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Get computer object by IP address Számítógép-objektumok előállítása IP címek alapján - - LDAP connection failed - LDAP kapcsolat sikertelen - - - LDAP bind failed - LDAP kötés sikertelen - - - LDAP bind successful - LDAP kötés sikerült - - - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - Sikeresen csatlakoztunk az LDAP szerverhez, és létrejött az LDAP kötés. Az LDAP alapszintű beállításai helyesek. - - - LDAP base DN test failed - LDAP alap DN teszt sikertelen - - - LDAP base DN test successful - LDAP alap DN teszt sikeres - - - LDAP naming context test failed - LDAP névkontextusteszt sikertelen - - - LDAP naming context test successful - LDAP névkontextus-teszt sikerült - - - The LDAP naming context has been queried successfully. The following base DN was found: -%1 - Az LDAP névmeghatározását sikeresen lekérdeztük. A következő alap DN-t találtuk: -%1 - - - user tree - felhasználófa - - - group tree - csoportfa - - - computer tree - számítógépfa - Enter username Add meg a felhasználónevet @@ -2031,10 +2777,6 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Please enter a user login name (wildcards allowed) which to query: Kérem, add meg a bejelentkezési felhasználónevet (helyettesítő karakterek megengedettek), melyeket lekérdezel: - - user objects - felhasználói objektumok - Enter group name Adja meg a csoport nevét @@ -2044,120 +2786,28 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Kérem, add meg a csoport nevét, amely tagjait lekérdezed: - group members - csoporttagok - - - Group not found - Csoport nem találgató - - - Could not find a group with the name "%1". Please check the group name or the group tree parameter. - "1%" nevű csoport nem található. Kérem, ellenőrizd a csoport nevét vagy a csoportfa paramétert. - - - Enter computer name - Add meg a számítógép nevét - - - computer objects - számítógép-objektumok - - - Enter computer DN - Add meg a számítógép DN-t - - - Please enter the DN of a computer whose MAC address to query: - Kérem, add meg a számítógép DN-jét, mely fizikai címét lekérdezed: - - - computer MAC addresses - számítógép fizikai címei - - - users - felhasználók - - - user groups - felhasználói csoportok - - - computer groups - számítógépcsoportok - - - Please enter a user login name whose group memberships to query: - Kérem, add meg a felhasználó bejelentkezési nevét, akinek csoporttagságait lekérdezed: - - - groups of user - felhasználó csoportjai - - - User not found - Felhasználó nem található - - - groups of computer - számítógép csoportjai - - - Computer not found - Számítógép nem található - - - Enter computer IP address - Add meg a számítógép IP címét - - - Please enter a computer IP address which to resolve to an computer object: - Kérem, add meg a számítógép IP címét, melyet számítógép-objektummá keressünk vissza: - - - computers - számítógépek - - - LDAP %1 test failed - %1 LDAP teszt sikertelen - - - LDAP %1 test successful - %1 LDAP teszt sikeres - - - The %1 has been queried successfully and %2 entries were found. - %1 objektum lekérdezése sikeres, %2 jegyezést találtunk. + Enter computer name + Add meg a számítógép nevét - %1 %2 have been queried successfully: - -%3 - %1 %2 lekérdezés sikeres: - -%3 + Enter computer DN + Add meg a számítógép DN-t - LDAP filter test failed - LDAP szűrő teszt sikertelen + Please enter the DN of a computer whose MAC address to query: + Kérem, add meg a számítógép DN-jét, mely fizikai címét lekérdezed: - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 - A konfigurált szűrővel egy %1 objektumot sem sikerült lekérdezni. Kérem, ellenőrizd %1 LDAP szűrőt. - -%2 + Please enter a user login name whose group memberships to query: + Kérem, add meg a felhasználó bejelentkezési nevét, akinek csoporttagságait lekérdezed: - LDAP filter test successful - LDAP szűrő teszt sikeres + Enter computer IP address + Add meg a számítógép IP címét - %1 %2 have been queried successfully using the configured filter. - %1 %2-t sikeresen lekérdezted a a konfigurált szűrő használatával. + Please enter a computer IP address which to resolve to an computer object: + Kérem, add meg a számítógép IP címét, melyet számítógép-objektummá keressünk vissza: (only if different from group tree) @@ -2167,10 +2817,6 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Computer group tree Számítógépcsoport-fa - - computer group tree - számítógépcsoport-fa - Filter for computers Számítógépek szűrője @@ -2251,50 +2897,10 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso e.g. (objectClass=container) or (objectClass=organizationalUnit) például (objectClass=container) vagy (objectClass=organizationalUnit) - - Could not query the configured base DN. Please check the base DN parameter. - -%1 - Nem sikerült lekérdezni az konfigurált alap DN-t. Kérem, ellenőrizd az alap DN paramétert. - -%1 - - - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - Az LDAP alap DN-t sikeresen lekérdeztük. Az alábbi bejegyzéseket találtuk: - -%1 - - - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - Nem sikerült elnevezési kontextusokból lekérdezni az alap DN-t. Kérem, ellenőrizd az elnevezési kontextusok attribútuma paramétert. - -%1 - Certificate files (*.pem) Tanúsítványfájlok (*.pem) - - Could not connect to the LDAP server. Please check the server parameters. - -%1 - Nem sikerült kapcsolódni az LDAP szerverhez. Kérem, ellenőrizd a szerver paramétereit. - -%1 - - - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - Nem sikerült kötést létrehozni a LDAP szerverrel. Kérem, ellenőrizd a szerver paramétereit és a kötést hitelesítő adatokat. - -%1 - Encryption protocol Titkosítási protokoll @@ -2351,10 +2957,6 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Please enter the name of a computer location (wildcards allowed): Adja meg egy számítógéphelyszín nevét (helyettesítő karakterek megengedettek): - - computer locations - számítógéphelyszínek - Enter location name Adja meg a helyszín nevét @@ -2363,38 +2965,6 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Please enter the name of a location whose entries to query: Adja meg azon helyszín nevét, amely bejegyzéseit le kívánja kérni: - - location entries - Helyszín-bejegyzések - - - LDAP test failed - LDAP tesztelése sikertelen - - - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - Egy %1 sem kérhető le. Ellenőrizze %2 paraméter(eke)t vagy adja meg a már létező objektum nevét. - -%3 - - - and - és - - - LDAP test successful - LDAP tesztelése sikeres - - - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - Egy bejegyzést sem sikerült lekérni %1 konfigurációban. Ellenőrizze a "%2" paramétert. - -%3 - Browse Tallózás @@ -2416,307 +2986,110 @@ A nyilvános kulcsrészt a kliens számítógépen használjuk a bejövő kapcso Kérem, add meg a számítógép kiszolgálónevét, melyet lekérdezel: - Invalid hostname - Érvénytelen kiszolgálónév - - - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Úgy konfiguráltad a rendszert, hogy az a számítógép kiszolgálónevét teljesen minősített domainnévként (FQDN) tárolja, de a kiszolgálónevet domain nélkül kell megadni. - - - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - Úgy konfiguráltad a rendszert, hogy az a számítógép kiszolgálónevét domain nélküli egyszerű névként tárolja, de a kiszolgálónevet domain nélkül kell megadni. - - - Could not find a user with the name "%1". Please check the username or the user tree parameter. - "%1" nevű felhasználó nem található. Kérem, ellenőrizd a felhasználónevet vagy a felhasználó-fa paramétert. - - - Enter hostname - Add meg a kiszolgálónevet - - - Please enter a computer hostname whose group memberships to query: - Kérem, add meg a számítógép kiszolgálónevét, melynek csoporttagságait lekérdezed: - - - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - "%1" nevű kiszolgálónevű számítógép nem található. Kérem, ellenőrizd a kiszolgálónevet vagy a számítógépfa paramétert. - - - Hostname lookup failed - Kiszolgálónév keresése sikertelen - - - Could not lookup hostname for IP address %1. Please check your DNS server settings. - %1 IP címhez nem sikerült lekérdezni a kiszolgálónevet. Kérem, ellenőrizd a DNS szerver beállításait. - - - User login name attribute - A felhasználó bejelentkezési nevének attribútuma - - - Configured attribute for user login name or computer hostname (OpenLDAP) - A felhasználó bejelentkezési nevéhez vagy a számítógép kiszolgálónevéhez beállított attribútum (OpenLDAP) - - - computer containers - számítógép tárolók - - - - LdapPlugin - - Auto-configure the base DN via naming context - Alap DN automatikus konfigurálása névmeghatározással - - - Query objects from LDAP directory - Objektumok lekérdezése LDAP könyvtárból - - - Show help about command - Parancsról segítség megjelenítése - - - Commands for configuring and testing LDAP/AD integration - LDAP/AD integráció konfigurálásának és tesztelésének parancsai - - - Basic LDAP/AD support for Veyon - Alapvető LDAP/AD támogatás a Veyon számára - - - %1 (load computers and locations from LDAP/AD) - %1 (számítógépek és helyszínek betöltése LDAP/AD-ból) - - - %1 (load users and groups from LDAP/AD) - %1 (felhasználók és csoportok betöltése LDAP/AD-ból) - - - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - Add meg a következő sémának megfelelő, érvényes LDAP url-t: "ldap[s]://[felhasználó[:jelszó]@]kiszolgáló[:port]" - - - No naming context attribute name given - falling back to configured value. - Hiányzik a névmeghatározás attribútum - visszaállunk a beállított értékekre. - - - Could not query base DN. Please check your LDAP configuration. - Nem sikerült az alap DN lekérdezése. Ellenőrizd az LDAP beállításait. - - - Configuring %1 as base DN and disabling naming context queries. - %1 beállítása alap DN-nek és a névmeghatározás-lekérdezések kikapcsolása. - - - - LdapProConfigurationPage - - LDAP Pro - LDAP Pro - - - Instances - Példányok - - - Enter name - Adja meg a nevet - - - Please enter a name for the instance (can't be changed later!): - Adja meg a példány nevét (később nem módosítható): - - - Remove instance - Példány eltávolítása - - - Do you really want to remove instance "%1"? - Biztos, hogy eltávolítja a "%1" példányt? - - - Configuration for instance "%1" - "%1" példány beállításai - - - - LdapProPlugin - - Professional LDAP/AD integration for Veyon - Professzionális LDAP/AD integráció a Veyon számára - - - %1 (load computers and locations from LDAP/AD) - %1 (számítógépek és helyszínek betöltése LDAP/AD-ból) - - - %1 (load users and groups from LDAP/AD) - %1 (felhasználók és csoportok betöltése LDAP/AD-ból) - - - - LicensingConfigurationPage - - Licensing - Licencelés - - - Installed licenses - Telepített licencek - - - Add new network range - Új hálózati tartomány hozzáadása - - - Remove selected network range - Kiválasztott hálózati tartomány eltávolítása - - - ID - ID - - - Feature - Szolgáltatás - - - Valid until - Érvényes eddig - - - Licensee - Licencelő - - - Browse license file - Licencfájlok böngészése - - - Veyon license files (*.vlf) - Veyon licencfájlok (*.vlf) + Enter hostname + Add meg a kiszolgálónevet - Remove license - Licenc eltávolítása + Please enter a computer hostname whose group memberships to query: + Kérem, add meg a számítógép kiszolgálónevét, melynek csoporttagságait lekérdezed: - Do you really want to remove the selected license? - Biztos, hogy eltávolítod a kiválasztott licenceket? + User login name attribute + A felhasználó bejelentkezési nevének attribútuma - <N/A> - <N/A> + Configured attribute for user login name or computer hostname (OpenLDAP) + A felhasználó bejelentkezési nevéhez vagy a számítógép kiszolgálónevéhez beállított attribútum (OpenLDAP) - Invalid license file - Érvénytelen licencfájlok + Directory name + Mappanév - Could not open the license file for reading! - A licencfájl nem nyitható meg olvasásra! + Query options + Lekérdezési lehetőségek - The selected license file does not contain valid data. - A kiválasztott licencfájl nem tartalmaz érvényes adatot. + Query nested user groups (supported by AD only) + Beágyazott felhasználói csoportok lekérdezése (csak az AD által támogatott) - The selected license file could not be verified. - A kiválasztott licencfájl nem ellenőrizhető. + Query timeout + Lekérdezési időtúllépés - The selected license file is not valid for this installation. - A kiválasztott licencfájl nem érvényes ehhez a telepítéshez. + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. - A kiválasztott licencfájl lejárt. + LDAP + LDAP - The license is already installed. - A licencet már telepítették. + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + Kérem, használd a globális LDAP konfigurációs oldalt a helyek és számítógépek LDAP-alapú címtárszolgáltatásából való lekérésének konfigurálásához. + + + LdapPlugin - Information - Információ + Auto-configure the base DN via naming context + Alap DN automatikus konfigurálása névmeghatározással - Installation ID - Telepítésazonosító + Query objects from LDAP directory + Objektumok lekérdezése LDAP könyvtárból - Addons available for licensing - Licencelhető + Show help about command + Parancsról segítség megjelenítése - Addon - Bővítmény + Commands for configuring and testing LDAP/AD integration + LDAP/AD integráció konfigurálásának és tesztelésének parancsai - - - LicensingPlugin - Show help for specific command - Konkrét parancsról segítség megjelenítése + Basic LDAP/AD support for Veyon + Alapvető LDAP/AD támogatás a Veyon számára - Show all installed licenses - Az összes telepített licenc megjelenítése + %1 (load computers and locations from LDAP/AD) + %1 (számítógépek és helyszínek betöltése LDAP/AD-ból) - Add license file - Licencfájlok hozzáadása + %1 (load users and groups from LDAP/AD) + %1 (felhasználók és csoportok betöltése LDAP/AD-ból) - Remove installed license - Telepített licencek eltávolítása + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Add meg a következő sémának megfelelő, érvényes LDAP url-t: "ldap[s]://[felhasználó[:jelszó]@]kiszolgáló[:port]" - -USAGE - -%1 add <LICENSE FILE> - - - -HASZNÁLAT - -%1 add <LICENSE FILE> - - + No naming context attribute name given - falling back to configured value. + Hiányzik a névmeghatározás attribútum - visszaállunk a beállított értékekre. - -USAGE - -%1 remove <LICENSE ID> - - - -HASZNÁLAT - -%1 remove <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. + Nem sikerült az alap DN lekérdezése. Ellenőrizd az LDAP beállításait. - No certificate found with given ID - A megadott ID-vel nem található tanúsítvány + Configuring %1 as base DN and disabling naming context queries. + %1 beállítása alap DN-nek és a névmeghatározás-lekérdezések kikapcsolása. - <N/A> - <N/A> + Test binding to an LDAP server + Tesztkötés egy LDAP-szerverhez - Licensing management - Licenckezelése + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + A megadott felhasználónév és jelszó helytelen. Érvényes hitelesítő adatokat kell megadni vagy másik hitelesítési módszert kell választani a Veyon Konfigurátor használatával. - Commands for managing license keys - Licenckulcs-kezelési parancsok + LDAP bind + LDAP kötés @@ -2734,12 +3107,20 @@ HASZNÁLAT Felhasználó hitelesítés - Session management - Munkamenet-kezelés + User sessions + Felhasználói munkamenetek + + + Minimum session lifetime before server start + A munkamenet minimális élettartama a szerver indítása előtt - Display manager users - Kezelő felhasználók megjelenítése + User login + Felhasználó bejelentkezése + + + Login key sequence + Bejelentkezési billentyűsorozat @@ -2748,10 +3129,6 @@ HASZNÁLAT Plugin implementing abstract functions for the Linux platform A bővítmény absztrakt függvényekkel egészíti ki a Linux platformot - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2770,14 +3147,14 @@ HASZNÁLAT Configuration Konfiguráció - - Disable balloon tooltips - Buborék-eszköztippek kikapcsolása - Show icons only Csak az ikonok megjelenítése + + Disable tooltips + Eszköztippek kikapcsolása + MainWindow @@ -2825,10 +3202,6 @@ HASZNÁLAT About Qt Qt névjegye - - Authentication impossible - Hitelesítés nem lehetséges - Configuration not writable Konfiguráció nem írható @@ -2889,10 +3262,6 @@ HASZNÁLAT The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. A helyi konfiguráció háttere azt jelzi, hogy a konfiguráció nem írható. Futtasd %1 Konfigurátort magasabb jogosultságokkal. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - Nincsenek hitelesítési kulcsok vagy a jelenlegi kulcsok elavultak. Kérem, készíts új kulcsfájlokat %1 Konfigurátorral. Másik megoldás lehet bejelentkezési hitelesítés beállítása %1 Konfigurátorral. Különben nem tudod majd elérni a számítógépeket %1 használatával. - Access denied Hozzáférés megtagadva @@ -2925,10 +3294,6 @@ HASZNÁLAT Search users and computers Felhasználók és számítógépek keresse - - Adjust optimal size - Optimális méretűre állítás - Align computers to grid Számítógépek rácsba illesztése @@ -2973,6 +3338,48 @@ HASZNÁLAT Locations && computers Helyszínek && számítógépek + + Authentication + Hitelesítés + + + Adjust size of computer icons automatically + Számítógépikonok automatikus méretezése + + + Slideshow + Diavetítés + + + Spotlight + Reflektorfény + + + Veyon Master + Veyon Master + + + Locations & computers + Helyszínek és számítógépek + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + Csak olyan számítógépeket megjelenítése, melyekre bejelentkezett felhasználó. + + + Load computer positions + + + + Save computer positions + + MasterConfigurationPage @@ -2980,10 +3387,6 @@ HASZNÁLAT Directories Mappák - - ... - ... - User configuration Felhasználói konfigurációk @@ -3068,6 +3471,10 @@ HASZNÁLAT Only user name Csak felhasználónév + + Only last part of user name + + Only computer name Csak számítógépnév @@ -3116,171 +3523,181 @@ HASZNÁLAT Automatically select current location Jelenlegi helyszín automatikus kiválasztása - - Automatically adjust computer thumbnail size - Számítógépek indexképének automatikus méretezése - Automatically open computer select panel Számítógépkiválasztási-panel automatikus megnyitása - - - MonitoringMode - Monitoring - Monitorozási + Use modern user interface (experimental) + Modern felhasználói felületet (kísérleti) - Builtin monitoring mode - Beépített monitorozási mód + Thumbnail spacing + Indexkép térköze - This mode allows you to monitor all computers at one or more locations. - Ez az alapértelmezett mód, ami lehetővé teszi, hogy monitorozd az egy vagy több helyszínen lévő összes számítógépet. + px + px + + + Hide local session + Helyi munkamenet elrejtése + + + Auto + Automatikus - - - NetworkDiscoveryConfigurationPage - Network discovery - Hálózat felderítése + Thumbnail aspect ratio + Indexkép méretaránya - Mode - Mód + Automatically adjust computer icon size + Számítógépikon automatikus méretezése - Scan network ranges - Hálózati tartományok átvizsgálása + Open feature windows on the same screen as the main window + A funkcióablakok megnyitása a főablakkal azonos képernyőn. - e.g. 192.168.1.0/24 - pl. 192.168.1.0/24 + Configuration templates + - Scan all subnets of computer - A számítógép összes alhálózatának átvizsgálása + Image quality in monitoring mode + Képminőség a monitorozási módban - Scan custom subnet - Egyéni alhálózat átvizsgálása + Highest + Legmagasabb - Scan sessions on local computer - A helyi számítógép munkameneteinek átvizsgálása + High + Magas - Test - Tesztelés + Medium + Közepes - Network ranges - Hálózati tartományok + Low + Alacsony - Add new group - Új csoport hozzáadása + Lowest + Legalacsonyabb - Remove selected group - Kiválasztott csoport eltávolítása + Remote access image quality + Távoli hozzáférés képminősége - Groups - Csoportok + Advanced + - First address - Első cím + Computer name source + - Last address - Utolsó cím + Default + Alap - Add new network range - Új hálózati tartomány hozzáadása + Host address + Kiszolgáló címe - Remove selected network range - Kiválasztott hálózati tartomány eltávolítása + Session client address + Munkamenet kliens címe - Parallel scans - Párhuzamos átvizsgálások + Session client name + Munkamenet ügyfél neve - Scan timeout - Átvizsgálási időtúllépés + Session host name + - ms - ms + Session metadata + - Session scan limit - Átvizsgálás munkamenetének korlátja + Full name of user + A felhasználók teljes neve - Options - Lehetőség + User login name + A felhasználó bejelentkezési neve - Reverse lookup discovered IP addresses to host names - A fordított keresés IP-címeket talált a kiszolgálónevekhez + Computer UID role + - New location - Új helyszín + Session meta data hash + - - - NetworkDiscoveryDirectory - Scanning... - Átvizsgálás... + Always expand all locations + - Discovered computers - Felderített számítógépek + Image quality + Képminőség - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command - Konkrét parancsról segítség megjelenítése + Monitoring + Monitorozási + + + Builtin monitoring mode + Beépített monitorozási mód - Scan a subnet - Egy alhálózat átvizsgálása + This mode allows you to monitor all computers at one or more locations. + Ez az alapértelmezett mód, ami lehetővé teszi, hogy monitorozd az egy vagy több helyszínen lévő összes számítógépet. - -USAGE - -%1 scan [<SUBNET>] - - - -HASZNÁLATA - -%1 scan [<SUBNET>] - - + Query application version of the server + A szerver alkalmazásverziójának lekérdezése - Network object directory which automatically discovers computers in the network - Hálózatobjektum-felderítő, ami automatikusan felderíti a hálózat számítógépeit + Query active features + Aktív funkciók lekérdezése - Network discovery (scan network for Veyon clients) - Hálózat felderítése (hálózat átvizsgálása Veyon kliens után) + Query properties of remotely available screens + A távolról elérhető képernyők tulajdonságainak lekérdezése + + + NestedNetworkObjectDirectory + + All directories + Összes mappa + + + + NetworkObjectDirectoryConfigurationPage + + Update interval: + Frissítési időköz: + + + seconds + másodpercek + + + + NetworkObjectDirectoryConfigurationPageTab - Commands for managing the network discovery directory - A hálózatfelderítő-mappát kezelő parancsok + Enabled + Bekapcsolva @@ -3316,32 +3733,44 @@ HASZNÁLATA Name: Név: + + Website name + Weboldal neve + - PasswordDialog + PluginCommands - Username - Felhasználónév + List names of all installed plugins + Az összes elérhető bővítmény nevének felsorolása - Password - Jelszó + Show table with details of all installed plugins + Az összes telepített bővítmény adatainak táblázata - Veyon Logon - Veyon bejelentkezés + Name + Megnevezés - Authentication error - Hitelesítési hiba + Description + Leírás - Logon failed with given username and password. Please try again! - A megadott felhasználónévvel és jelszóval a bejelentkezés sikertelen. Próbáld újra! + Version + Verzió - Please enter your username and password in order to access computers. - Kérem, a számítógépek eléréséhez add meg felhasználóneved és jelszavad. + UID + UID + + + Plugin-related CLI operations + Bővítményekhez kapcsolódó CLI műveletek + + + Commands for managing plugins + Parancsok a bővítmények kezeléséhez @@ -3386,10 +3815,6 @@ HASZNÁLATA Do you really want to reboot the selected computers? Biztos, hogy újraindítod a kiválasztott számítógépeket? - - Do you really want to power down the selected computer? - Biztos, hogy kikapcsolod a kiválasztott számítógépeket? - Power on a computer via Wake-on-LAN (WOL) Egy számítógép bekapcsolása hálózati ébresztéssel (WOL) @@ -3440,6 +3865,18 @@ HASZNÁLATA Please save your work and close all programs. A számítógép %1 perc %2 másodperc múlva automatikusan le fog állni. Kérjük, mentse el munkáját és zárja be az összes futó programot. + + Do you really want to reboot <b>ALL</b> computers? + Biztos, hogy újraindítod az <b>ÖSSZES</b> számítógépet? + + + Do you really want to power down <b>ALL</b> computers? + Biztos, hogy kikapcsolod az <b>ÖSSZES</b> számítógépet? + + + Do you really want to power down the selected computers? + Biztos, hogy kikapcsolod a kiválasztott számítógépeket? + PowerDownTimeInputDialog @@ -3486,14 +3923,25 @@ Please save your work and close all programs. Remote view or control a computer Egy számítógép távoli megtekintése vagy vezérlése - - Please enter the hostname or IP address of the computer to access: - Kérem, add meg az elérni kívánt gép nevét vagy IP címét: - Show help about command Parancsról segítség megjelenítése + + Exchange clipboard contents + Vágólap tartalmának cseréje + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + Nem választottál számítógépet, így beírhatsz egy kiszolgálónevet vagy IP-címet az eléréshez: + + + + RemoteAccessPage + + Remote access: %1 + Távoli elérés: %1 + RemoteAccessWidget @@ -3501,6 +3949,10 @@ Please save your work and close all programs. %1 - %2 Remote Access %1 - %2 távoli hozzáférés + + %1 - %2 - %3 Remote Access + %1 - %2 - %3 Távoli elérés + RemoteAccessWidgetToolBar @@ -3556,10 +4008,6 @@ Please save your work and close all programs. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - %1 csatlakozik - Connected. Sikeresen csatlakozott. @@ -3572,58 +4020,17 @@ Please save your work and close all programs. Exit Kilépés - - - Routing - - Control internet access by modifying routing table - Az internetelérés módosítása az útvonaltábla módosításával - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - Az alapértelmezett útvonalak eltávolítása az internetelérés blokkolásáért - - - Add custom route to block internet - Egyéni útvonal hozzáadása az internet blokkolásáért - - - Destination - Cél - - - Gateway - Átjáró - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - Kérem, add meg a kiválasztott számítógép(ek)en futtatandó programokat vagy parancsokat. Több programot/parancsot soronként adj meg. - - - Run programs - Programok futtatása - - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - például "C:\Program Files\VideoLAN\VLC\vlc.exe" - - - Name: - Név: + Connecting... + Csatlakozás... - Remember and add to program menu - Emlékezz és add a programmenühöz + Select screen + Képernyő kiválasztása - e.g. VLC - pl. VLC + All screens + Összes képernyő @@ -3642,7 +4049,19 @@ Please save your work and close all programs. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. - Az összes felhasználó figyelmének elnyerés érdekében evvel a gombbak zárolhatod számítógépüket. Ebben a módban az összes bemeneti eszközt zároljuk és a képernyő elfeketedik. + Az összes felhasználó figyelmének elnyerés érdekében evvel a gombbal zárolhatod számítógépüket. Ebben a módban az összes bemeneti eszközt zároljuk és a képernyő elfeketedik. + + + Lock input devices + Beviteli eszközök zárolása + + + Unlock input devices + Beviteli eszközök zárolásának feloldása + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + Az összes felhasználó figyelmének elnyerés érdekében evvel a gombbal zárolhatod számítógépüket. Ebben a módban az összes bemeneti eszközt zároljuk, a képernyők viszont továbbra is láthatók maradnak. @@ -3659,6 +4078,10 @@ Please save your work and close all programs. Screenshot Képernyőkép + + Could not open screenshot file %1 for writing. + %1 képernyőkép fájl nem nyitható meg írásra. + ScreenshotFeaturePlugin @@ -3683,6 +4106,13 @@ Please save your work and close all programs. Számítógépekről képernyőképek készítése és mentése a helyi gépre. + + ScreenshotManagementPage + + Screenshots + Képernyőképek + + ScreenshotManagementPanel @@ -3713,6 +4143,45 @@ Please save your work and close all programs. Delete Törlés + + Screenshot + Képernyőkép + + + Do you really want to delete all selected screenshots? + Biztos, hogy eltávolítod a kiválasztott képernyőképeket? + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + + + + User has denied access + + + + User confirmed access + + ServiceConfigurationPage @@ -3744,14 +4213,6 @@ Please save your work and close all programs. State: Állapot: - - Network - Hálózat - - - Demo server port - Demó szerver port - Enable firewall exception Fűzfal-kivétel bekapcsolása @@ -3760,10 +4221,6 @@ Please save your work and close all programs. Allow connections from localhost only Kapcsolatok engedélyezése csak a localhost-ból - - Internal VNC server port - Belső VNC szerver port - VNC server VNC szerver @@ -3778,20 +4235,12 @@ Please save your work and close all programs. All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - Az összes beállítást sikeresen mentette. A változások életbe lépéséhez %1 szolgáltatást új kell indítani. Újraindítod most? + Az összes beállítást sikeresen mentette. A változások életbe lépéséhez %1 szolgáltatást újra kell indítani. Újraindítod most? Running Jelenleg fut - - Feature manager port - Szolgáltatáskezelő port - - - Primary service port - Elsődleges szolgáltatási port - Enabling this option will make the service launch a server process for every interactive session on a computer. Typically this is required to support terminal servers. @@ -3801,52 +4250,132 @@ Typically this is required to support terminal servers. Show notification on remote connection Távoli csatlakozás esetén értesítés megjelenítése - - Multi session mode (for terminal and remote desktop servers) - Többmunka-menetes mód (terminál és távoli asztal szerverekhez) - Show notification when an unauthorized access is blocked Értesítés jelenjen meg amikor egy nem hitelesített hozzáférést blokkolunk. - - - ServiceControl - Starting service %1 - %1 szolgáltatás indítása + Maximum session count + Maximális munkamenetszám - Stopping service %1 - %1 szolgáltatás leállítása + Network port numbers + Hálózati portok száma - Registering service %1 - %1 szolgáltatás nyilvántartásban vétele + Veyon server + Veyon szerver - Unregistering service %1 - %1 szolgáltatás törlése a nyilvántartásból + Internal VNC server + Beépített VNC - Service control - Szolgáltatásvezérlés + Feature manager + Funkciókezelő + + + Demo server + Demószerver + + + Miscellaneous network settings + Egyéb hálózati beállítások + + + Session mode + Munkamenet mód + + + Local session mode (single server instance for primary local session) + Helyi munkamenet mód (egyetlen kiszolgálópéldány az elsődleges helyi munkamenethez) + + + Active session mode (single server instance for active local or remote session) + Aktív munkamenet mód (egyetlen kiszolgálópéldány az aktív hely vagy távoli munkamenethez) + + + Multi session mode (distinct server instance for each local and remote desktop session) + Többszörös munkamenet mód (különálló szerverpéldány minden helyi és távoli asztali munkamenethez) + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + + + + Miscellaneous settings + Egyéb beállítások + + + Disable clipboard synchronization + A vágólap szinkronizálásának kikapcsolása + + + Session metadata + + + + Content + + + + None + Egyik sem + + + Value of an environment variable + + + + Value of a registry key + + + + Environment variable name: + Környezeti változó neve: + + + Registry key name: + Rendszerleíró kulcs neve: + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + Opcionálisan írj egy reguláris kifejezést a számítógépnév egy részének kinyeréséhez, és használd ezt a számítógép megjelenített neveként. + +Példa: [^-]*-(PC[0-9]*) - ServiceControlPlugin + ServiceControl - Service is running - Veyon szolgáltatás jelenleg fut + Service control + Szolgáltatásvezérlés - Service is not running - Veyon szolgáltatás jelenleg nem fut + Starting %1 + - Configure and control Veyon service - Veyon szolgáltatás konfigurálása és felügyelete + Stopping %1 + + + + Restarting %1 + + + + Registering %1 + + + + Unregistering %1 + + + + ServiceControlCommands Register Veyon Service Regisztrált Veyon szolgáltatás @@ -3871,13 +4400,25 @@ Typically this is required to support terminal servers. Query status of Veyon Service Veyon Szolgáltatás állapotának lekérdezése + + Service is running + Veyon szolgáltatás jelenleg fut + + + Service is not running + Veyon szolgáltatás jelenleg nem fut + + + Configure and control Veyon service + Veyon szolgáltatás konfigurálása és felügyelete + Commands for configuring and controlling Veyon Service Veyon Szolgáltatás konfigurációs és felügyeleti parancsai - ShellCommandLinePlugin + ShellCommands Run command file Parancsfájl futtatása @@ -3887,14 +4428,101 @@ Typically this is required to support terminal servers. "%1" fájl nem létezik! - Interactive shell and script execution for Veyon Control - Interaktív héj és szkriptfuttatás a Veyon vezérlésből + Interactive shell and script execution for Veyon CLI + Interaktív shell- és szkript-végrehajtás a Veyon CLI-hez Commands for shell functionalities Parancsok héjfunkciókhoz + + SlideshowPanel + + Previous + Előző + + + Start/pause + Indítás/szünet + + + Next + Következő + + + Duration: + Időtartam: + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + Kiválasztott számítógép hozzáadása + + + Remove selected computers + Kiválasztott számítógép eltávolítása + + + Update computers in realtime + Számítógépek valósidejű frissítése + + + Spotlight + Reflektorfény + + + Please select at least one computer to add. + Kérjük, válassz legalább egy számítógépet hozzáadáshoz. + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + Számítógépek hozzáadásához kattints a középső egérgombbal vagy kattints a lenti első gombra. +A második gomb eltávolítja a kiválasztott vagy az utolsó számítógépet. + + + + StartAppDialog + + Start application + Alkalmazás indítása + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + Kérem, add meg a kiválasztott számítógépeken futtatandó alkalmazásokat. Több alkalmazást sorokkal válassz el. + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + például "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + Ne felejtsd el és add hozzá az alkalmazás menüjéhez + + + Application name + Alkalmazás neve + + + Name: + Név: + + + e.g. VLC + pl. VLC + + SystemTrayIcon @@ -3931,8 +4559,8 @@ Typically this is required to support terminal servers. Szöveges üzenet küldése - Use the field below to type your message which will be sent to all selected users. - Az alábbi mezőbe gépeld az összes kiválasztott felhasználóknak küldendő üzenetedet. + Please enter your message which send to all selected users. + Kérem, gépeld be az összes kiválasztott felhasználóknak küldendő üzenetedet. @@ -3980,23 +4608,39 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer Asztalduplikációs motor bekapcsolása Windows 8 vagy újabb rendszeren + + Maximum CPU usage + Maximális CPU használat + - UserConfig + UserLoginDialog - No write access - Nincs írási hozzáférés + User login + Felhasználó bejelentkezése - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - Személyes beállításait nem sikerült menteni! Kérem, ellenőrizd a felhasználói konfigurációs fájl útvonalát %1 Konfigurátorban. + Please enter a username and password for automatic login on all computers. + Kérem, adj meg egy felhasználónevet és egy jelszót az automatikus bejelentkezéshez az összes számítógépen. + + + Username + Felhasználónév + + + Password + Jelszó - UserSessionControl + UserSessionControlPlugin - User session control - Felhasználói munkamenet-vezérlés + Log in + Bejelentkezés + + + Click this button to log in a specific user on all computers. + Kattints erre a gombra, hogy egy megadott felhasználó bejelentkezzen az összes számítógépre. Log off @@ -4004,7 +4648,7 @@ Typically this is required to support terminal servers. Click this button to log off users from all computers. - Kattints erre a gombra, hogy felhasználókat kijelentkeztesd az össze számítógépről. + Kattints erre a gombra, hogy a felhasználókat kijelentkeztesd az összes számítógépről. Confirm user logoff @@ -4014,6 +4658,14 @@ Typically this is required to support terminal servers. Do you really want to log off the selected users? Biztos, hogy kijelentkezteted a kiválasztott felhasználókat? + + User session control + Felhasználói munkamenet-vezérlés + + + Do you really want to log off <b>ALL</b> users? + Biztos, hogy kijelentkezteted az <b>ÖSSZES</b> felhasználót? + VeyonCore @@ -4065,10 +4717,6 @@ Typically this is required to support terminal servers. ERROR HIBA - - licensed for - licencelt - USAGE HASZNÁLAT @@ -4085,19 +4733,31 @@ Typically this is required to support terminal servers. WARNING FIGYELMEZTETÉS + + Authentication test + Hitelesítési teszt + + + Screen %1 + %1 képernyő + - VeyonServiceControl + VeyonMaster - Veyon Service - Veyon szolgáltatás + No write access + Nincs írási hozzáférés + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Személyes beállításait nem sikerült menteni! Kérem, ellenőrizd a felhasználói konfigurációs fájl útvonalát %1 Konfigurátorban. - VncView + VeyonServiceControl - Establishing connection to %1 ... - Kapcsolat létrehozása: %1 ... + Veyon Service + Veyon szolgáltatás @@ -4145,6 +4805,30 @@ Typically this is required to support terminal servers. Use alternative user authentication mechanism Alternatív felhasználói hitelesítési mechanizmus használata + + User login + Felhasználó bejelentkezése + + + Input start delay + Add meg az indítási késleltetést + + + Simulated key presses interval + Billentyűlenyomási időköz szimulálása + + + Confirm legal notice (message displayed before user logs in) + Jogi értesítést erősítése (az üzenet a felhasználói bejelentkezés előtt jelenik meg) + + + Use input device interception driver + A beviteli eszköz elfogási illesztőprogramjának használata + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4153,8 +4837,8 @@ Typically this is required to support terminal servers. A bővítmény absztrakt függvényekkel egészíti ki a Windows platformot - Plugin implementing specific functions for the Windows platform - + Internal display + Belső képernyő @@ -4163,30 +4847,34 @@ Typically this is required to support terminal servers. The service "%1" is already installed. "%1" szolgáltatás már telepítve van. - - The service "%1" could not be installed. - "%1" szolgáltatás nem telepíthető. - The service "%1" has been installed successfully. "%1" szolgáltatást sikeresen telepítette. - - The service "%1" could not be uninstalled. - "%1" szolgáltatás nem távolítható el. - The service "%1" has been uninstalled successfully. "%1" szolgáltatást sikeresen eltávolította. - - The start type of service "%1" could not be changed. - "%1" szolgáltatás indítási típusa nem módosítható. - Service "%1" could not be found. "%1" szolgáltatás nem található. + + The service "%1" could not be installed (error %2). + "%1" szolgáltatás nem telepíthető (hiba: %2). + + + Could not change the failure actions config for service "%1" (error %2). + "%1" szolgáltatás hibaeseményeinek konfigurációja nem módosítható (hiba: %2). + + + The service "%1" could not be uninstalled (error %2). + "%1" szolgáltatás nem távolítható el (hiba: %2). + + + The start type of service "%1" could not be changed (error %2). + "%1" szolgáltatás indítási típusa nem módosítható (hiba: %2). + X11VncConfigurationWidget diff --git a/translations/id.ts b/translations/veyon_id.ts similarity index 75% rename from translations/id.ts rename to translations/veyon_id.ts index 377e3d1b2..1235e2e28 100644 --- a/translations/id.ts +++ b/translations/veyon_id.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -80,10 +80,6 @@ Jika anda tertarik menerjemahkan Veyon pada bahasa lokal Anda atau bahasa lain a All groups Semua grup - - ... - ... - Access control rules Aturan kontrol akses @@ -140,19 +136,18 @@ Jika anda tertarik menerjemahkan Veyon pada bahasa lokal Anda atau bahasa lain a User groups backend: Kelompok pengguna backend: - - Missing user groups backend - Backend grup pengguna tidak ada - - - No default user groups plugin was found. Please check your installation! - Tidak ditemukan pengaya grup pengguna bawaan. Sila cek instalasi Anda! - Restrict access to members of specific user groups Batasi akses ke pengguna dari grup pengguna tertentu + + AccessControlProvider + + Provider for access control features + + + AccessControlRuleEditDialog @@ -179,30 +174,10 @@ Jika anda tertarik menerjemahkan Veyon pada bahasa lokal Anda atau bahasa lain a Rule description: Penjelasan aturan: - - Invert all conditions ("is/has" interpreted as "is/has not") - Balikkan semua kondisi ("adalah/telah" diartikan sebagai "adalah/belum") - Conditions Kondisi - - is member of group - adalah anggota grup - - - Accessing computer is localhost - Mengakses komputer adalah localhost - - - Accessing user is logged on user - Pengguna yang mengakses dicatat sebagai pengguna - - - Accessing user is already connected - Mengakses pengguna sudah terhubung - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. Jika lebih dari satu kondisi diaktifkan, setiap kondisi harus dipenuhi untuk membuat aturan berlaku (logika AND). Jika hanya satu dari beberapa kondisi yang harus dipenuhi (OR logis), buat beberapa aturan kontrol akses. @@ -236,33 +211,125 @@ Jika anda tertarik menerjemahkan Veyon pada bahasa lokal Anda atau bahasa lain a Mengakses Komputer - Local (logged on) user - Pengguna lokal (masuk log) + Always process rule and ignore conditions + Selalu proses aturan dan abaikan kondisi - Local computer - Komputer lokal + Accessing computer and local computer + - Always process rule and ignore conditions - Selalu proses aturan dan abaikan kondisi + User being accessed + - No user logged on - Tidak ada pengguna masuk + is logged in locally + + + + is logged in remotely + - Accessing user has one or more groups in common with local (logged on) user - Pengguna yang mengakses memiliki satu atau beberapa grup yang sama dengan pengguna lokal (masuk) + No user is logged in locally + + + + One or multiple users are logged in locally + - Accessing computer and local computer are at the same location - Mengakses komputer dan komputer lokal berada di lokasi yang sama + No user is logged in remotely + + + + One or multiple users are logged in remotely + is located at berlokasi + + is not located at + + + + are located at the same location + + + + are not located the same location + + + + is member of group + adalah anggota grup + + + is not member of group + + + + is authenticated via + + + + is not authenticated via + + + + has one or more groups in common with user being accessed + + + + has no groups in common with user being accessed + + + + equals user being accessed + + + + is different from user being accessed + + + + is already connected + + + + is not connected + + + + is local computer + + + + is not local computer + bukan komputer lokal + + + Computer being accessed + komputer sedang diakses + + + Session being accessed is a user session + Sesi yang diakses adalah sesi pengguna + + + Session being accessed is a login screen + Sesi yang diakses adalah layar log masuk + + + Local computer is already being accessed + + + + Local computer is not yet being accessed + + AccessControlRulesTestDialog @@ -306,42 +373,44 @@ Jika anda tertarik menerjemahkan Veyon pada bahasa lokal Anda atau bahasa lain a The access in the given scenario needs permission of the logged on user. Akses dalam skenario yang diberikan membutuhkan izin dari pengguna yang masuk. - - ERROR: Unknown action - GALAT: Aksi tidak diketahui - Test result Hasil test - - - AndroidPlatformConfigurationPage - Android - + Authentication method + Metode autentikasi - General - Umum + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + Perkenalan + + + Please perform the following steps to set up key file authentication: + Silakan lakukan langkah-langkah berikut untuk mengatur otentikasi file utama: - - - AuthKeysConfigurationPage - Authentication keys - Kunci otentikasi + 1) Create a key pair on the master computer. + 1) Buat pasangan kunci di komputer master. - Introduction - Perkenalan + 2) Set an access group whose members should be allowed to access other computers. + 2) Tetapkan grup akses yang anggotanya harus diizinkan untuk mengakses komputer lain. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Ekspor kunci publik dan impor pada semua komputer klien dengan nama yang sama. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Silakan merujuk pada <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Manual Administrasi Veyon</a> untuk informasi lebih lanjut. Key file directories @@ -356,12 +425,18 @@ Jika anda tertarik menerjemahkan Veyon pada bahasa lokal Anda atau bahasa lain a Direktori basis file kunci pribadi - ... - ... + Available authentication keys + Kunci autentikasi tersedia - Available authentication keys - + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Sepasang kunci otentikasi terdiri dari dua kunci kriptografi yang digabungkan, kunci pribadi dan kunci publik. +Kunci privat memungkinkan pengguna pada komputer master untuk mengakses komputer klien. +Penting bahwa hanya pengguna yang berwenang yang memiliki akses baca ke file kunci pribadi. +Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan koneksi masuk. Create key pair @@ -403,52 +478,24 @@ Jika anda tertarik menerjemahkan Veyon pada bahasa lokal Anda atau bahasa lain a Please select a key to delete! Pilih kunci yang akan dihapus! - - Please enter the name of the user group or role for which to import the authentication key: - - Please select a key to export! Pilih kunci yang akan diekspor! Please select a user group which to grant access to key "%1": - + Silakan pilih grup pengguna yang akan diberikan akses ke kunci "%1": Please select a key which to set the access group for! - - - - Please perform the following steps to set up key file authentication: - Silakan lakukan langkah-langkah berikut untuk mengatur otentikasi file utama: - - - 1) Create a key pair on the master computer. - 1) Buat pasangan kunci di komputer master. - - - 2) Set an access group whose members should be allowed to access other computers. - 2) Tetapkan grup akses yang anggotanya harus diizinkan untuk mengakses komputer lain. - - - 3) Export the public key and import it on all client computers with the same name. - 3) Ekspor kunci publik dan impor pada semua komputer klien dengan nama yang sama. + Silakan pilih kunci untuk mengatur grup akses! - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - Sepasang kunci otentikasi terdiri dari dua kunci kriptografi yang digabungkan, kunci pribadi dan kunci publik. -Kunci privat memungkinkan pengguna pada komputer master untuk mengakses komputer klien. -Penting bahwa hanya pengguna yang berwenang yang memiliki akses baca ke file kunci pribadi. -Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan koneksi masuk. - AuthKeysManager @@ -462,19 +509,19 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Invalid key type specified! Please specify "%1" or "%2". - + Jenis kunci yang ditentukan tidak valid! Silakan tentukan "%1" atau "%2". Specified key does not exist! Please use the "list" command to list all installed keys. - + Kunci yang ditentukan tidak ada! Silakan gunakan perintah "daftar" untuk mendaftar semua kunci yang diinstal. One or more key files already exist! Please delete them using the "delete" command. - + Satu atau lebih file kunci sudah ada! Harap hapus dengan menggunakan perintah "hapus". Creating new key pair for "%1" - Membuat pasangan kunci baru untuk "% 1" + Membuat pasangan kunci baru untuk "%1" Failed to create public or private key! @@ -482,23 +529,23 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Newly created key pair has been saved to "%1" and "%2". - + Pasangan kunci yang baru dibuat telah disimpan ke "%1" dan "%2". Could not remove key file "%1"! - + Tidak dapat menghaps file kunci "%1"! Could not remove key file directory "%1"! - + Tidak dapat menghapus kunci file direktori "%1"! Failed to create directory for output file. - + Gagal dalam membuat direktori untuk output file. File "%1" already exists. - + File "%1" telah tersedia' Failed to write output file. @@ -506,7 +553,7 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Key "%1/%2" has been exported to "%3" successfully. - + Kunci "%1/%2" berhasil diekspor ke "%3". Failed read input file. @@ -514,11 +561,11 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone File "%1" does not contain a valid private key! - + Berkas "%1" tidak berisi kunci privat yang valid! File "%1" does not contain a valid public key! - + Berkas "%1" tidak berisi kunci publik yang valid! Failed to create directory for key file. @@ -526,70 +573,70 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Failed to write key file "%1". - + Gagal menulis berkas kunci "%1". Failed to set permissions for key file "%1"! - + Gagal menyetel izin untuk file kunci "%1"! Key "%1/%2" has been imported successfully. Please check file permissions of "%3" in order to prevent unauthorized accesses. - + Kunci "%1/%2" berhasil diimpor. Harap periksa izin file "%3" untuk mencegah akses tidak sah. Failed to convert private key to public key - + Gagal mengubah kunci privat menjadi kunci publik Failed to create directory for private key file "%1". - + Gagal membuat direktori untuk file kunci pribadi "%1". Failed to save private key in file "%1"! - + Gagal menyimpan kunci pribadi di file "%1"! Failed to set permissions for private key file "%1"! - + Gagal menyetel izin untuk file kunci pribadi "%1"! Failed to create directory for public key file "%1". - + Gagal membuat direktori untuk file kunci publik "%1". Failed to save public key in file "%1"! - + Gagal menyimpan kunci publik di berkas "%1"! Failed to set permissions for public key file "%1"! - + Gagal menyetel izin untuk file kunci publik "%1"! Failed to set owner of key file "%1" to "%2". - + Gagal menyetel pemilik untuk file kunci "%1" menjadi "%2". Failed to set permissions for key file "%1". - + Gagal menyetel izin untuk file kunci "%1". Key "%1" is now accessible by user group "%2". - + Kunci "%1" sekarang dapat diakses oleh grup pengguna "%2". <N/A> - + <Tidak Diketahui> Failed to read key file. - + Gagal membaca file kunci AuthKeysPlugin Create new authentication key pair - + Buat pasangan kunci autentikasi baru Delete authentication key @@ -625,7 +672,7 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. - + Perintah ini menyesuaikan izin akses file <KEY> sedemikian rupa sehingga hanya grup pengguna <ACCESS GROUP> yang memiliki akses baca ke sana. NAME @@ -645,11 +692,7 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - - - - Please specify the command to display help for! - + Perintah ini mencantumkan semua kunci autentikasi yang tersedia di direktori kunci yang dikonfigurasi. Jika opsi "%1" ditentukan sebagai gantinya, tabel dengan detail kunci akan ditampilkan. Beberapa detail mungkin hilang jika kunci tidak dapat diakses, mis. karena kurangnya izin membaca. TYPE @@ -659,13 +702,9 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone PAIR ID ID PASANGAN - - Command line support for managing authentication keys - - Commands for managing authentication keys - + Perintah untuk mengelola kunci autentikasi This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. @@ -679,6 +718,30 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + + + + Key file authentication + + + + Key file + + + + Please specify the key name (e.g. "teacher/public") as the first argument. + Silakan tentukan nama kunci (misalnya "guru/umum") sebagai argumen pertama. + + + Please specify the command to display help for. + Harap tentukan perintah untuk menampilkan bantuan. + + + The specified command does not exist or no help is available for it. + Perintah yang ditentukan tidak ada atau tidak ada bantuan yang tersedia untuk itu. + AuthKeysTableModel @@ -700,42 +763,181 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - Komputer + General + Umum - Name - Nama + Username to bind DN mapping: + - Host address/IP - Alamat host/IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + + AuthLdapDialog - MAC address - MAC address + Veyon Logon + Masuk Veyon - Add new computer - Tambah komputer baru + Please enter your domain/LDAP username and password in order to access computers. + - Remove selected computer - Hapus komputer terpilih + Username + Nama Pengguna - New computer - Komputer baru + Password + Kata sandi - Builtin directory + Authentication error + Otentikasi gagal + + + Logon failed with given username and password. Please try again! + + + AuthLogonDialog - Locations & computers - Lokasi & komputer + Veyon Logon + Masuk Veyon + + + Please enter your username and password in order to access computers. + + + + Username + Nama Pengguna + + + Password + Kata sandi + + + Authentication error + Otentikasi gagal + + + Logon failed with given username and password. Please try again! + + + + + AuthLogonPlugin + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + + + + Logon authentication + + + + Logon + + + + + AuthSimpleDialog + + Veyon Logon + Masuk Veyon + + + Please enter the Veyon password: + + + + Authentication error + Otentikasi gagal + + + Logon failed with given password. Please try again! + + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + + + + Simple password authentication + + + + Simple password + + + + + AuthenticationPage + + Authentication is set up properly on this computer. + + + + + AuthenticationPageTab + + Enabled + + + + Test + Tes + + + + BuiltinDirectoryConfiguration + + Builtin directory + Direktori bawaan + + + + BuiltinDirectoryConfigurationPage + + Computers + Komputer + + + Name + Nama + + + Host address/IP + Alamat host/IP + + + MAC address + MAC address + + + Add new computer + Tambah komputer baru + + + Remove selected computer + Hapus komputer terpilih + + + New computer + Komputer baru + + + Builtin directory + Direktori bawaan Locations @@ -749,14 +951,18 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Remove selected location Hapus lokasi terpilih - - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - Impor berkas CSV dimungkinkan melalui antarmuka baris perintah. Informasi lebih lanjut, lihat <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">dokumentasi daring</a>. - New location Lokasi baru + + Directory name + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + BuiltinDirectoryPlugin @@ -770,11 +976,11 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Export objects to given file - + Ekspor objek ke file yang diberikan Invalid type specified. Valid values are "%1" or "%2". - + Jenis yang ditentukan tidak valid. Nilai yang valid adalah "%1" atau "%2". Type @@ -814,7 +1020,7 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Unclassified object "%1" with ID "%2" - + Objek tidak terklasifikasi "%1" dengan ID "%2" None @@ -826,7 +1032,7 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Root - + Root Invalid @@ -834,7 +1040,7 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Error while parsing line %1. - + Terjadi kesalahan saat mengurai baris %1. Network object directory which stores objects in local configuration @@ -846,7 +1052,7 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone No format string or regular expression specified! - + Tidak ada string format atau ekspresi reguler yang ditentukan! Can't open file "%1" for writing! @@ -854,7 +1060,7 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone No format string specified! - + Tidak ada string format yang ditentukan! Object UUID @@ -874,7 +1080,7 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Dump all or individual locations and computers - + Buang semua atau lokasi individual dan komputer List all locations and computers @@ -902,35 +1108,35 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone LOCATION - + LOKASI FORMAT-STRING-WITH-PLACEHOLDERS - + FORMAT-STRING-WITH-PLACEHOLDERS REGULAR-EXPRESSION-WITH-PLACEHOLDER - + REGULAR-EXPRESSION-WITH-PLACEHOLDER Imports objects from the specified text file using the given format string or regular expression containing one or multiple placeholders. Valid placeholders are: %1 - + Mengimpor objek dari file teks yang ditentukan menggunakan string format yang diberikan atau ekspresi reguler yang berisi satu atau beberapa tempat penampung. Tempat penampung yang valid adalah: %1 Import simple CSV file to a single room - + Impor file CSV sederhana ke satu ruangan Import CSV file with location name in first column - + Impor file CSV dengan nama lokasi di kolom pertama Import text file with with key/value pairs using regular expressions - + Impor file teks dengan pasangan kunci/nilai menggunakan ekspresi reguler Import arbitrarily formatted data - + Impor data yang diformat secara sewenang-wenang Exports objects to the specified text file using the given format string containing one or multiple placeholders. Valid placeholders are: %1 @@ -938,7 +1144,7 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Export all objects to a CSV file - + Ekspor semua objek ke file CSV Export all computers in a specific location to a CSV file @@ -1000,6 +1206,14 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone MAC ADDRESS + + The specified command does not exist or no help is available for it. + Perintah yang ditentukan tidak ada atau tidak ada bantuan yang tersedia untuk itu. + + + Location "%1" not found. + + BuiltinUltraVncServer @@ -1017,10 +1231,6 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone ComputerControlListModel - - Host/IP address: %1 - Host/Alamat IP: %1 - Active features: %1 Fitur aktif: %1 @@ -1037,10 +1247,6 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Computer offline or switched off - - Service unreachable or not running - - Authentication failed or access denied @@ -1061,6 +1267,38 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Location: %1 + + [no user] + + + + Veyon Server unreachable or not running + + + + Name: %1 + + + + Hostname: %1 + + + + unknown + + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + ComputerControlServer @@ -1092,6 +1330,17 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + + Active connections: + + + + + ComputerGroupSelector + + Group %1 + + ComputerManager @@ -1119,80 +1368,83 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. Tidak dapat menentukan lokasi komputer ini. Ini menunjukkan masalah dengan konfigurasi sistem. Semua lokasi akan ditampilkan di panel pilih komputer sebagai gantinya. - - - ComputerSelectPanel - Computer management + Logged in since - Computer search + %1 days - Add location + 1 day + + + ComputerMonitoring - Save computer/user list - + Computers + Komputer - Select output filename + Search users and computers + Cari pengguna dan komputer + + + Select all - CSV files (*.csv) + Unselect all - File error + Add to group - Could not write the computer and users list to %1! Please check the file access permissions. + Remove from group - ConfigCommandLinePlugin - - Please specify an existing configuration file to import. - Silakan tentukan berkas konfigurasi yang ada untuk diimpor. - + ComputerSelectPanel - Please specify a valid filename for the configuration export. - Silakan tentukan nama berkas yang valid untuk ekspor konfigurasi. + Computer search + - Please specify a valid key. + Add location - Specified key does not exist in current configuration! - Kunci yang ditentukan tidak ada dalam konfigurasi saat ini! + Save computer/user list + - Please specify a valid value. + Select output filename - Configure Veyon at command line + CSV files (*.csv) - Output file is not writable! - Berkas keluaran tidak dapat ditulisi! + File error + - Output directory is not writable! - Direktori keluaran tidak dapat ditulisi! + Could not write the computer and users list to %1! Please check the file access permissions. + - Configuration file is not readable! - Berkas konfigurasi tidak terbaca! + Search computers + + + + ConfigCommands Clear system-wide Veyon configuration Hapus konfigurasi Veyon di seluruh sistem @@ -1221,16 +1473,52 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Unset (remove) given configuration key Batalkan (hapus) kunci konfigurasi yang diberikan - - Commands for managing the configuration of Veyon - Perintah untuk mengelola konfigurasi Veyon - Upgrade and save configuration of program and plugins Tingkatkan dan simpan konfigurasi program dan pengaya - - + + Please specify an existing configuration file to import. + Silakan tentukan berkas konfigurasi yang ada untuk diimpor. + + + Configuration file is not readable! + Berkas konfigurasi tidak terbaca! + + + Please specify a valid filename for the configuration export. + Silakan tentukan nama berkas yang valid untuk ekspor konfigurasi. + + + Output file is not writable! + Berkas keluaran tidak dapat ditulisi! + + + Output directory is not writable! + Direktori keluaran tidak dapat ditulisi! + + + Please specify a valid key. + + + + Specified key does not exist in current configuration! + Kunci yang ditentukan tidak ada dalam konfigurasi saat ini! + + + Please specify a valid value. + + + + Configure Veyon at command line + + + + Commands for managing the configuration of Veyon + Perintah untuk mengelola konfigurasi Veyon + + + ConfigurationManager Could not modify the autostart property for the %1 Service. @@ -1252,6 +1540,10 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Could not apply platform-specific configuration settings. + + Could not configure the firewall configuration for the %1 Service. + + DemoClient @@ -1282,10 +1574,6 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Memory limit - - Use multithreading (experimental) - - MB MB @@ -1302,13 +1590,17 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone Slow down thumbnail updates while demo is running - - - DemoFeaturePlugin - Fullscreen demo + Bandwidth limit + + + + MB/s + + + DemoFeaturePlugin Stop demo @@ -1322,15 +1614,59 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone - Demo server - Server demo + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. + Demo - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Share your screen or allow a user to share his screen with other users. + + + + Full screen demo + + + + Share your own screen in fullscreen mode + + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share your own screen in a window + + + + Share selected user's screen in fullscreen mode + + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share selected user's screen in a window + + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + + + + Please select only one user screen to share. + + + + All screens @@ -1360,86 +1696,90 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone DesktopServicesConfigurationPage - Programs & websites - + Name + Nama - Predefined programs + Path - Name - Nama + Predefined websites + - Path + Remove selected website - Add new program + URL + URL + + + New website - Remove selected program + Applications & websites - Predefined websites + Predefined applications - Remove selected website + Add new application - URL + Remove selected application - New program + Add new website - New website + New application DesktopServicesFeaturePlugin - Run program + Open website - Open website + Click this button to open a website on all computers. - Click this button to open a website on all computers. + Open website "%1" - Start programs and services in user desktop + Custom website - Click this button to run a program on all computers. + Start application - Run program "%1" + Click this button to start an application on all computers. - Custom program + Start application "%1" - Open website "%1" + Custom application - Custom website + Start apps and open websites in user sessions @@ -1474,15 +1814,19 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone - Custom program + Handout - Handout + Texts to read - Texts to read + generic-student-user + + + + Custom application @@ -1509,481 +1853,464 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone - FeatureControl + FeatureCommands - Feature control + List names of all available features - - - FileTransferController - Could not open file "%1" for reading! Please check your permissions! + Show table with details of all available features - - - FileTransferDialog - File transfer + Start a feature on a remote host - Options + Stop a feature on a remote host - Transfer only - + Please specify the command to display help for. + Harap tentukan perintah untuk menampilkan bantuan. - Transfer and open file(s) with associated program + Displays a list with the names of all available features. - Transfer and open destination folder + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. - Files + HOST ADDRESS - Start + FEATURE - Overwrite existing files + ARGUMENTS - - - FileTransferPlugin - File transfer + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information - Click this button to transfer files from your computer to all computers. + Lock the screen - Select one or more files to transfer + Display a text message - Transfer files to remote computer + Test message - Received file "%1". + Start an application - Could not receive file "%1" as it already exists. + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. - Could not receive file "%1" as it could not be opened for writing! + Unlock the screen - - - GeneralConfigurationPage - User interface - Antarmuka pengguna + The specified command does not exist or no help is available for it. + Perintah yang ditentukan tidak ada atau tidak ada bantuan yang tersedia untuk itu. - Language: - + Name + Nama - Use system language setting + Description - Veyon + Master - Logging - + Service + Layanan - Log file directory + Worker - ... - ... - - - Log level + UID - Nothing + Plugin - Only critical messages + Invalid feature name or UID specified - Errors and critical messages + Error parsing the JSON-encoded arguments: %1 - Warnings and errors + Failed to initialize credentials - Information, warnings and errors + Could not establish a connection to host %1 - Debug messages and everything else + Failed to send feature control message to host %1 - Limit log file size + Feature-related CLI operations - Clear all log files + Commands for controlling features + + + FileTransferConfigurationPage - Log to standard error output + File transfer - Network object directory - Direktori objek jaringan + Directories + Direktori - Backend: + Destination directory - Update interval: + Default source directory - %1 service - + Options + Opsi - The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + Remember last source directory - Log files cleared + Create destination directory if it does not exist + + + FileTransferController - All log files were cleared successfully. + Could not open file "%1" for reading! Please check your permissions! + + + FileTransferDialog - Error + File transfer - Could not remove all log files. + Options + Opsi + + + Transfer only - MB - MB + Transfer and open file(s) with associated program + - Rotate log files + Transfer and open destination folder - x + Files - seconds + Start - Write to logging system of operating system + Overwrite existing files + + + FileTransferFileDialog - Authentication + Select one or more files to transfer + + + FileTransferPlugin - Method: + File transfer - Logon authentication + Click this button to transfer files from your computer to all computers. - Key file authentication + Select one or more files to transfer - Test - Tes + Transfer files to remote computer + - Authentication is set up properly on this computer. + Received file "%1". - Authentication keys are not set up properly on this computer. + Could not receive file "%1" as it already exists. - Authentication test + Could not receive file "%1" as it could not be opened for writing! - InternetAccessControlConfigurationPage + GeneralConfigurationPage - Internet access control - + User interface + Antarmuka pengguna - Backend: + Language: - General settings + Use system language setting - Backend settings + Veyon - - - InternetAccessControlPlugin - Block access to the internet - - - - Allow access to the internet - - - - Show help about command - Tunjukkan bantuan tentang perintah - - - Block internet + Logging - Click this button to block access to the internet. + Log file directory - Unblock internet + Log level - Click this button to allow access to the internet. + Nothing - Control access to the internet + Only critical messages - Commands for controlling access to the internet + Errors and critical messages - - - LdapBrowseDialog - Browse LDAP + Warnings and errors - - - LdapClient - - LDAP error description: %1 - Deskripsi masalah LDAP: %1 - - - - LdapConfigurationPage - - Basic settings - Setelan dasar - - - General - Umum - - LDAP server and port + Information, warnings and errors - Bind DN + Debug messages and everything else - Bind password + Limit log file size - Anonymous bind + Clear all log files - Use bind credentials + Log to standard error output - Base DN + %1 service - Fixed base DN + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? - e.g. dc=example,dc=org + Log files cleared - Discover base DN by naming context + All log files were cleared successfully. - e.g. namingContexts or defaultNamingContext + Error - Environment settings + Could not remove all log files. - Object trees - + MB + MB - Computer tree + Rotate log files - e.g. OU=Groups + x - User tree + Write to logging system of operating system - e.g. OU=Users + TLS configuration - e.g. OU=Computers + Use certificate authority for TLS connections - Group tree + CA certificate file - Perform recursive search operations in object trees - + ... + ... - Object attributes + Host certificate file - e.g. hwAddress + Host private key file - e.g. member or memberUid + Style: - e.g. dNSHostName + Native - Computer MAC address attribute + Color scheme: - Group member attribute + Light - e.g. uid or sAMAccountName + Dark - Advanced settings + User groups - Optional object filters - + Backend: + Backend: - Filter for user groups + Include user groups from domain - Filter for users - + Missing user groups backend + Backend grup pengguna tidak ada - Filter for computer groups + No user groups plugin was found. Please check your installation! + + + HeadlessVncServer - Group member identification + Headless VNC server + + + LdapBrowseDialog - Distinguished name (Samba/AD) + Browse LDAP + + + LdapClient - List all groups of a user - + LDAP error description: %1 + Deskripsi masalah LDAP: %1 + + + LdapConfiguration - List all groups of a computer - + LDAP connection failed + Sambungan LDAP gagal - Get computer object by IP address + Could not connect to the LDAP server. Please check the server parameters. + +%1 - LDAP connection failed - + LDAP bind failed + Pengikatan LDAP gagal - LDAP bind failed + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 LDAP bind successful - + Pengikatan LDAP berhasil Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. @@ -1991,19 +2318,37 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone LDAP base DN test failed + Pengujian DN berdasarkan LDAP gagal + + + Could not query the configured base DN. Please check the base DN parameter. + +%1 LDAP base DN test successful + Pengujian DN berdasarkan LDAP berhasil + + + The LDAP base DN has been queried successfully. The following entries were found: + +%1 LDAP naming context test failed + Uji konteks penamaan LDAP gagal + + + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 LDAP naming context test successful - + Uji konteks penamaan LDAP berhasil The LDAP naming context has been queried successfully. The following base DN was found: @@ -2014,679 +2359,717 @@ Kunci publik digunakan pada komputer klien untuk mengautentikasi permintaan kone user tree + + User tree + + group tree - computer tree + Group tree - Enter username - Masukkan nama pengguna + computer tree + - Please enter a user login name (wildcards allowed) which to query: + Computer tree - user objects + computer group tree - Enter group name + Computer group tree - Please enter a group name whose members to query: + user objects + objek pengguna + + + User login name attribute group members + anggota kelompok + + + Group member attribute Group not found - + Grup tidak ditemukan Could not find a group with the name "%1". Please check the group name or the group tree parameter. - Enter computer name + computer objects + objek komputer + + + Computer display name attribute - computer objects + Invalid hostname - Enter computer DN + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Please enter the DN of a computer whose MAC address to query: + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + + + + Computer hostname attribute computer MAC addresses + Alamat MAC komputer + + + Computer MAC address attribute - users + computer locations + lokasi komputer + + + Computer location attribute + Atribut lokasi komputer + + + Location name attribute + + users + pengguna + user groups - + group pengguna + + + computers + komputer computer groups - + group komputer - Please enter a user login name whose group memberships to query: + computer containers groups of user - + kelompok pengguna User not found + Pengguna tidak ditemukan + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. groups of computer - + kelompok komputer Computer not found - + komputer tidak ditemukan - Enter computer IP address + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - Please enter a computer IP address which to resolve to an computer object: + Hostname lookup failed - computers + Could not lookup hostname for IP address %1. Please check your DNS server settings. - LDAP %1 test failed + location entries - LDAP %1 test successful + Computer groups filter - The %1 has been queried successfully and %2 entries were found. + Computer locations identification - %1 %2 have been queried successfully: - -%3 + Filter for computer groups - LDAP filter test failed + Invalid test value - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 + An empty or invalid value has been supplied for this test. - LDAP filter test successful - + LDAP %1 test failed + Tes LDAP %1 gagal - %1 %2 have been queried successfully using the configured filter. + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 - (only if different from group tree) - + LDAP %1 test successful + Tes LDAP %1 berhasil - Computer group tree - + The %1 has been queried successfully and %2 entries were found. + %1 telah berhasil dikueri dan %2 entri ditemukan. - computer group tree + LDAP test failed - Filter for computers + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 - e.g. room or computerLab + and - Integration tests + LDAP test successful - Computer groups - - - - e.g. name or description + %1 %2 have been queried successfully: + +%3 - Filter for computer containers - + LDAP filter test failed + Tes filter LDAP gagal - Computer containers or OUs + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 - Connection security - Keamanan Koneksi + LDAP filter test successful + Tes filter LDAP berhasil - TLS certificate verification - Verifikasi sertifikat TLS + %1 %2 have been queried successfully using the configured filter. + %1 %2 telah berhasil ditanyakan menggunakan filter yang dikonfigurasi. - System defaults + LDAP directory + + + LdapConfigurationPage - Never (insecure!) - + Basic settings + Setelan dasar - Custom CA certificate file - + General + Umum - None - Tidak ada + LDAP server and port + - TLS - TLS + Bind DN + - SSL - SSL + Bind password + - e.g. (objectClass=computer) + Anonymous bind - e.g. (objectClass=group) + Use bind credentials - e.g. (objectClass=person) + Base DN - e.g. (objectClass=room) or (objectClass=computerLab) + Fixed base DN - e.g. (objectClass=container) or (objectClass=organizationalUnit) + e.g. dc=example,dc=org - Could not query the configured base DN. Please check the base DN parameter. - -%1 + Discover base DN by naming context - The LDAP base DN has been queried successfully. The following entries were found: - -%1 + e.g. namingContexts or defaultNamingContext - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 + Environment settings - Certificate files (*.pem) - File sertifikat (*.pem) + Object trees + - Could not connect to the LDAP server. Please check the server parameters. - -%1 + Computer tree - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 + e.g. OU=Groups - Encryption protocol - Protokol enkripsi + User tree + - Computer location attribute + e.g. OU=Users - Computer display name attribute + e.g. OU=Computers - Location name attribute + Group tree - e.g. cn or displayName + Perform recursive search operations in object trees - Computer locations identification + Object attributes - Identify computer locations (e.g. rooms) via: + e.g. hwAddress - Location attribute in computer objects + e.g. member or memberUid - List all entries of a location - Tampilkan semua masukan lokasi + e.g. dNSHostName + - List all locations - Daftar semua lokasi + Computer MAC address attribute + - Enter computer display name + Group member attribute - Please enter a computer display name to query: + e.g. uid or sAMAccountName - Enter computer location name - Masukkan nama lokasi komputer + Advanced settings + - Please enter the name of a computer location (wildcards allowed): + Optional object filters - computer locations - lokasi komputer + Filter for user groups + - Enter location name - Masukkan nama lokasi + Filter for users + - Please enter the name of a location whose entries to query: + Filter for computer groups - location entries + Group member identification - LDAP test failed + Distinguished name (Samba/AD) - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 + List all groups of a user - and + List all groups of a computer - LDAP test successful - + Get computer object by IP address + Dapatkan objek komputer berdasarkan alamat IP - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - + Enter username + Masukkan nama pengguna - Browse - + Please enter a user login name (wildcards allowed) which to query: + Silakan masukkan nama login pengguna (bisa menggunakan wildcards) yang akan di query: - Test - Tes + Enter group name + Masukkan nama grup - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - + Please enter a group name whose members to query: + Harap masukkan nama grup yang anggotanya akan ditanyakan: - Computer hostname attribute - + Enter computer name + Masukkan nama komputer - Please enter a computer hostname to query: - + Enter computer DN + Masukkan DN komputer - Invalid hostname + Please enter the DN of a computer whose MAC address to query: - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - + Please enter a user login name whose group memberships to query: + Harap masukkan nama login pengguna yang keanggotaan grupnya akan ditanyakan: - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - + Enter computer IP address + masukan alamat IP komputer - Could not find a user with the name "%1". Please check the username or the user tree parameter. - + Please enter a computer IP address which to resolve to an computer object: + Silakan masukkan alamat IP komputer yang akan diselesaikan ke objek komputer: - Enter hostname - + (only if different from group tree) + (hanya jika berbeda dari pohon grup) - Please enter a computer hostname whose group memberships to query: + Computer group tree - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - + Filter for computers + Filter untuk komputer - Hostname lookup failed - + e.g. room or computerLab + misalnya ruangan atau "laboratorium komputer" - Could not lookup hostname for IP address %1. Please check your DNS server settings. - + Integration tests + Tes integrasi - User login name attribute - + Computer groups + Grup komputer - Configured attribute for user login name or computer hostname (OpenLDAP) - + e.g. name or description + misalnya nama atau deskripsi - computer containers - + Filter for computer containers + Filter untuk wadah komputer - - - LdapPlugin - Auto-configure the base DN via naming context - + Computer containers or OUs + Wadah komputer atau OU - Query objects from LDAP directory - + Connection security + Keamanan Koneksi - Show help about command - Tunjukkan bantuan tentang perintah + TLS certificate verification + Verifikasi sertifikat TLS - Commands for configuring and testing LDAP/AD integration - + System defaults + Default sistem - Basic LDAP/AD support for Veyon + Never (insecure!) - %1 (load computers and locations from LDAP/AD) + Custom CA certificate file - %1 (load users and groups from LDAP/AD) - + None + Tidak ada - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - + TLS + TLS - No naming context attribute name given - falling back to configured value. - + SSL + SSL - Could not query base DN. Please check your LDAP configuration. + e.g. (objectClass=computer) - Configuring %1 as base DN and disabling naming context queries. + e.g. (objectClass=group) - - - LdapProConfigurationPage - LDAP Pro + e.g. (objectClass=person) - Instances + e.g. (objectClass=room) or (objectClass=computerLab) - Enter name + e.g. (objectClass=container) or (objectClass=organizationalUnit) - Please enter a name for the instance (can't be changed later!): - + Certificate files (*.pem) + File sertifikat (*.pem) - Remove instance - + Encryption protocol + Protokol enkripsi - Do you really want to remove instance "%1"? - + Computer location attribute + Atribut lokasi komputer - Configuration for instance "%1" + Computer display name attribute - - - LdapProPlugin - Professional LDAP/AD integration for Veyon + Location name attribute - %1 (load computers and locations from LDAP/AD) + e.g. cn or displayName - %1 (load users and groups from LDAP/AD) + Computer locations identification - - - LicensingConfigurationPage - Licensing + Identify computer locations (e.g. rooms) via: - Installed licenses + Location attribute in computer objects - Add new network range - Tambahkan rentang jaringan baru + List all entries of a location + Tampilkan semua masukan lokasi - Remove selected network range - Hapus rentang jaringan terpilih + List all locations + Daftar semua lokasi - ID + Enter computer display name - Feature + Please enter a computer display name to query: - Valid until - + Enter computer location name + Masukkan nama lokasi komputer - Licensee + Please enter the name of a computer location (wildcards allowed): - Browse license file - + Enter location name + Masukkan nama lokasi - Veyon license files (*.vlf) + Please enter the name of a location whose entries to query: - Remove license + Browse - Do you really want to remove the selected license? + Test + Tes + + + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - <N/A> + Computer hostname attribute - Invalid license file + Please enter a computer hostname to query: - Could not open the license file for reading! + Enter hostname - The selected license file does not contain valid data. + Please enter a computer hostname whose group memberships to query: - The selected license file could not be verified. + User login name attribute - The selected license file is not valid for this installation. + Configured attribute for user login name or computer hostname (OpenLDAP) - The selected license file is expired. + Directory name - The license is already installed. + Query options - Information + Query nested user groups (supported by AD only) - Installation ID + Query timeout - Addons available for licensing + ms + ms + + + + LdapNetworkObjectDirectoryConfigurationPage + + LDAP - Addon + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. - LicensingPlugin + LdapPlugin - Show help for specific command - Tampilkan bantuan untuk perintah spesifik + Auto-configure the base DN via naming context + - Show all installed licenses + Query objects from LDAP directory - Add license file + Show help about command + Tunjukkan bantuan tentang perintah + + + Commands for configuring and testing LDAP/AD integration - Remove installed license + Basic LDAP/AD support for Veyon - -USAGE - -%1 add <LICENSE FILE> - - + %1 (load computers and locations from LDAP/AD) + %1 (memuat komputer dan lokasi untuk LDAP/AD) + + + %1 (load users and groups from LDAP/AD) + %1 (memuat pengguna dan group untuk LDAP/AD) + + + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - -USAGE - -%1 remove <LICENSE ID> - - + No naming context attribute name given - falling back to configured value. + + + + Could not query base DN. Please check your LDAP configuration. - No certificate found with given ID + Configuring %1 as base DN and disabling naming context queries. - <N/A> + Test binding to an LDAP server - Licensing management + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Commands for managing license keys + LDAP bind @@ -2705,11 +3088,19 @@ USAGE - Session management + User sessions - Display manager users + Minimum session lifetime before server start + + + + User login + + + + Login key sequence @@ -2719,10 +3110,6 @@ USAGE Plugin implementing abstract functions for the Linux platform Pengaya menerapkan fungsi abstrak untuk platform Linux - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2741,14 +3128,14 @@ USAGE Configuration Konfigurasi - - Disable balloon tooltips - Nonaktifkan tooltips balon - Show icons only Hanya tampilkan icon + + Disable tooltips + + MainWindow @@ -2796,10 +3183,6 @@ USAGE About Qt Tentang Qt - - Authentication impossible - Otentikasi tidak dimungkinkan - Configuration not writable Konfigurasi tidak dapat dirubah @@ -2860,10 +3243,6 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - - Access denied Akses ditolak @@ -2896,10 +3275,6 @@ USAGE Search users and computers Cari pengguna dan komputer - - Adjust optimal size - - Align computers to grid @@ -2944,6 +3319,48 @@ USAGE Locations && computers + + Authentication + + + + Adjust size of computer icons automatically + + + + Slideshow + + + + Spotlight + + + + Veyon Master + + + + Locations & computers + Lokasi & komputer + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + + + + Load computer positions + + + + Save computer positions + + MasterConfigurationPage @@ -2951,10 +3368,6 @@ USAGE Directories Direktori - - ... - ... - User configuration Konfigurasi pengguna @@ -3039,6 +3452,10 @@ USAGE Only user name Hanya nama pengguna + + Only last part of user name + + Only computer name Hanya nama komputer @@ -3088,165 +3505,180 @@ USAGE - Automatically adjust computer thumbnail size + Automatically open computer select panel - Automatically open computer select panel + Use modern user interface (experimental) - - - MonitoringMode - Monitoring + Thumbnail spacing - Builtin monitoring mode + px - This mode allows you to monitor all computers at one or more locations. + Hide local session + + + + Auto - - - NetworkDiscoveryConfigurationPage - Network discovery - Pendeteksian jaringan + Thumbnail aspect ratio + - Mode - Mode + Automatically adjust computer icon size + - Scan network ranges - Pindai rentang jaringan + Open feature windows on the same screen as the main window + - e.g. 192.168.1.0/24 - contoh: 192.168.1.0/24 + Configuration templates + - Scan all subnets of computer - Pindai semua subnet komputer + Image quality in monitoring mode + - Scan custom subnet - Pindai subnet tertentu + Highest + - Scan sessions on local computer - Pindai sesi pada komputer lokal + High + - Test - Tes + Medium + + + + Low + - Network ranges - Rentang jaringan + Lowest + - Add new group - Tambah grup baru + Remote access image quality + - Remove selected group - Hapus grup terpilih + Advanced + - Groups - Grup + Computer name source + - First address - Alamat pertama + Default + - Last address - Alamat terakhir + Host address + Alamat host - Add new network range - Tambahkan rentang jaringan baru + Session client address + - Remove selected network range - Hapus rentang jaringan terpilih + Session client name + - Parallel scans + Session host name - Scan timeout + Session metadata - ms - ms + Full name of user + - Session scan limit + User login name - Options + Computer UID role - Reverse lookup discovered IP addresses to host names + Session meta data hash - New location - Lokasi baru + Always expand all locations + + + + Image quality + - NetworkDiscoveryDirectory + MonitoringMode - Scanning... + Monitoring - Discovered computers + Builtin monitoring mode - - - NetworkDiscoveryPlugin - Show help for specific command - Tampilkan bantuan untuk perintah spesifik + This mode allows you to monitor all computers at one or more locations. + - Scan a subnet + Query application version of the server - -USAGE - -%1 scan [<SUBNET>] - - + Query active features + + + + Query properties of remotely available screens + + + + + NestedNetworkObjectDirectory + + All directories + + + NetworkObjectDirectoryConfigurationPage - Network object directory which automatically discovers computers in the network - Direktori objek jaringan yang secara otomatis menemukan komputer dalam jaringan + Update interval: + - Network discovery (scan network for Veyon clients) - Pendeteksian jaringan (memindai jaringan untuk klien Veyon) + seconds + + + + NetworkObjectDirectoryConfigurationPageTab - Commands for managing the network discovery directory - Perintah untuk mengelola direktori pendeteksian jaringan + Enabled + @@ -3282,31 +3714,43 @@ USAGE Name: + + Website name + + - PasswordDialog + PluginCommands + + List names of all installed plugins + + + + Show table with details of all installed plugins + + - Username - Nama Pengguna + Name + Nama - Password - Kata sandi + Description + - Veyon Logon - Masuk Veyon + Version + - Authentication error - Otentikasi gagal + UID + - Logon failed with given username and password. Please try again! + Plugin-related CLI operations - Please enter your username and password in order to access computers. + Commands for managing plugins @@ -3352,10 +3796,6 @@ USAGE Do you really want to reboot the selected computers? - - Do you really want to power down the selected computer? - - Power on a computer via Wake-on-LAN (WOL) @@ -3406,6 +3846,18 @@ USAGE Please save your work and close all programs. + + Do you really want to reboot <b>ALL</b> computers? + + + + Do you really want to power down <b>ALL</b> computers? + + + + Do you really want to power down the selected computers? + + PowerDownTimeInputDialog @@ -3453,12 +3905,23 @@ Please save your work and close all programs. - Please enter the hostname or IP address of the computer to access: + Show help about command + Tunjukkan bantuan tentang perintah + + + Exchange clipboard contents + + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + RemoteAccessPage - Show help about command - Tunjukkan bantuan tentang perintah + Remote access: %1 + @@ -3467,6 +3930,10 @@ Please save your work and close all programs. %1 - %2 Remote Access + + %1 - %2 - %3 Remote Access + + RemoteAccessWidgetToolBar @@ -3522,10 +3989,6 @@ Please save your work and close all programs. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - - Connected. Tersambung. @@ -3538,326 +4001,503 @@ Please save your work and close all programs. Exit + + Connecting... + + + + Select screen + + + + All screens + + + + + ScreenLockFeaturePlugin + + Lock + Kunci + + + Unlock + Buka kunci + + + Lock screen and input devices of a computer + + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + + + + Lock input devices + + + + Unlock input devices + + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + + + + Screenshot + + unknown + + + + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + + + + Screenshot + Tangkapan layar + + + Could not open screenshot file %1 for writing. + + + + + ScreenshotFeaturePlugin + + Screenshot + Tangkapan layar + + + Use this function to take a screenshot of selected computers. + + + + Screenshots taken + + + + Screenshot of %1 computer have been taken successfully. + + + + Take screenshots of computers and save them locally. + + + + + ScreenshotManagementPage + + Screenshots + Tangkapan layar + + + + ScreenshotManagementPanel + + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + + + + User: + Pengguna: + + + Computer: + Komputer: + + + Date: + Tanggal: + + + Time: + Waktu: + + + Show + Tampilkan + + + Delete + Hapus + + + Screenshot + Tangkapan layar + + + Do you really want to delete all selected screenshots? + + - Routing + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + + + + User has denied access + + - Control internet access by modifying routing table + User confirmed access - RoutingConfigurationWidget + ServiceConfigurationPage + + General + Umum + + + Autostart + Mulai otomatis + + + Hide tray icon + Sembunyikan ikon baki + + + Start service + Mulai layanan + + + Stopped + Dihentikan + + + Stop service + Hentikan layanan + + + State: + Status: + + + Enable firewall exception + Aktifkan pengecualian firewall + + + Allow connections from localhost only + + + + VNC server + + + + Plugin: + Pengaya: + + + Restart %1 Service + + + + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + + + + Running + Berjalan + + + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. + + + + Show notification on remote connection + + + + Show notification when an unauthorized access is blocked + + - Remove default routes to block internet access + Maximum session count - Add custom route to block internet + Network port numbers - Destination + Veyon server - Gateway + Internal VNC server - - - RunProgramDialog - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. + Feature manager - Run programs - Jalankan program + Demo server + Server demo - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + Miscellaneous network settings - Name: + Session mode - Remember and add to program menu + Local session mode (single server instance for primary local session) - e.g. VLC + Active session mode (single server instance for active local or remote session) - - - ScreenLockFeaturePlugin - Lock - Kunci + Multi session mode (distinct server instance for each local and remote desktop session) + - Unlock - Buka kunci + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + - Lock screen and input devices of a computer + Miscellaneous settings - To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + Disable clipboard synchronization - - - Screenshot - unknown + Session metadata - Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + Content - Screenshot - Tangkapan layar + None + Tidak ada - - - ScreenshotFeaturePlugin - Screenshot - Tangkapan layar + Value of an environment variable + - Use this function to take a screenshot of selected computers. + Value of a registry key - Screenshots taken + Environment variable name: - Screenshot of %1 computer have been taken successfully. + Registry key name: - Take screenshots of computers and save them locally. + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) - ScreenshotManagementPanel - - All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. - - + ServiceControl - User: - Pengguna: + Service control + Kontrol Layanan - Computer: - Komputer: + Starting %1 + - Date: - Tanggal: + Stopping %1 + - Time: - Waktu: + Restarting %1 + - Show - Tampilkan + Registering %1 + - Delete - Hapus + Unregistering %1 + - ServiceConfigurationPage + ServiceControlCommands - General - Umum - - - Autostart - Mulai otomatis - - - Hide tray icon - Sembunyikan ikon baki + Register Veyon Service + Daftarkan Layanan Veyon - Start service - Mulai layanan + Unregister Veyon Service + Batalkan Pendaftaran Layanan Veyon - Stopped - Dihentikan + Start Veyon Service + Mulai Layanan Veyon - Stop service - Hentikan layanan + Stop Veyon Service + Hentikan Layanan Veyon - State: - Status: + Restart Veyon Service + Restart Layanan Veyon - Network - Jaringan + Query status of Veyon Service + - Demo server port - + Service is running + Layanan berjalan - Enable firewall exception - Aktifkan pengecualian firewall + Service is not running + Layanan tidak berjalan - Allow connections from localhost only - + Configure and control Veyon service + Konfigurasi dan kontrol layanan Veyon - Internal VNC server port + Commands for configuring and controlling Veyon Service + + + ShellCommands - VNC server + Run command file - Plugin: - Pengaya: + File "%1" does not exist! + Berkas "%1" tidak ada! - Restart %1 Service + Interactive shell and script execution for Veyon CLI - All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + Commands for shell functionalities + + + SlideshowPanel - Running - Berjalan - - - Feature manager port + Previous - Primary service port + Start/pause - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. + Next - Show notification on remote connection + Duration: - Multi session mode (for terminal and remote desktop servers) + View in separate window - Show notification when an unauthorized access is blocked + %1 Master – Slideshow - ServiceControl - - Starting service %1 - Mulai layanan %1 - - - Stopping service %1 - Matikan layanan %1 - - - Registering service %1 - Daftarkan layanan %1 - - - Unregistering service %1 - Batalkan pendaftaran layanan %1 - - - Service control - Kontrol Layanan - - - - ServiceControlPlugin - - Service is running - Layanan berjalan - + SpotlightPanel - Service is not running - Layanan tidak berjalan + Add selected computers + - Configure and control Veyon service - Konfigurasi dan kontrol layanan Veyon + Remove selected computers + - Register Veyon Service - Daftarkan Layanan Veyon + Update computers in realtime + - Unregister Veyon Service - Batalkan Pendaftaran Layanan Veyon + Spotlight + - Start Veyon Service - Mulai Layanan Veyon + Please select at least one computer to add. + - Stop Veyon Service - Hentikan Layanan Veyon + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + + StartAppDialog - Restart Veyon Service - Restart Layanan Veyon + Start application + - Query status of Veyon Service + Please enter the applications to start on the selected computers. You can separate multiple applications by line. - Commands for configuring and controlling Veyon Service + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - - - ShellCommandLinePlugin - Run command file + Remember and add to application menu - File "%1" does not exist! - Berkas "%1" tidak ada! + Application name + - Interactive shell and script execution for Veyon Control + Name: - Commands for shell functionalities + e.g. VLC @@ -3897,7 +4537,7 @@ Typically this is required to support terminal servers. Kirim pesan teks - Use the field below to type your message which will be sent to all selected users. + Please enter your message which send to all selected users. @@ -3946,22 +4586,38 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer + + Maximum CPU usage + + - UserConfig + UserLoginDialog - No write access + User login - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Please enter a username and password for automatic login on all computers. + + Username + Nama Pengguna + + + Password + Kata sandi + - UserSessionControl + UserSessionControlPlugin - User session control + Log in + + + + Click this button to log in a specific user on all computers. @@ -3980,6 +4636,14 @@ Typically this is required to support terminal servers. Do you really want to log off the selected users? + + User session control + + + + Do you really want to log off <b>ALL</b> users? + + VeyonCore @@ -4031,10 +4695,6 @@ Typically this is required to support terminal servers. ERROR - - licensed for - - USAGE @@ -4051,19 +4711,31 @@ Typically this is required to support terminal servers. WARNING + + Authentication test + + + + Screen %1 + + - VeyonServiceControl + VeyonMaster - Veyon Service - Layanan Veyon + No write access + + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + - VncView + VeyonServiceControl - Establishing connection to %1 ... - + Veyon Service + Layanan Veyon @@ -4111,6 +4783,30 @@ Typically this is required to support terminal servers. Use alternative user authentication mechanism + + User login + + + + Input start delay + + + + Simulated key presses interval + + + + Confirm legal notice (message displayed before user logs in) + + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4119,7 +4815,7 @@ Typically this is required to support terminal servers. Pengaya menerapkan fungsi abstrak untuk platform Windows - Plugin implementing specific functions for the Windows platform + Internal display @@ -4130,27 +4826,31 @@ Typically this is required to support terminal servers. - The service "%1" could not be installed. + The service "%1" has been installed successfully. - The service "%1" has been installed successfully. + The service "%1" has been uninstalled successfully. - The service "%1" could not be uninstalled. - + Service "%1" could not be found. + Layanan "%1" tidak dapat ditemukan - The service "%1" has been uninstalled successfully. - + The service "%1" could not be installed (error %2). + Layanan "%1" tidak dapat dipasang (kesalahan %2). - The start type of service "%1" could not be changed. + Could not change the failure actions config for service "%1" (error %2). - Service "%1" could not be found. + The service "%1" could not be uninstalled (error %2). + Layanan "%1" tidak dapat dilepaskan (kesalahan %2). + + + The start type of service "%1" could not be changed (error %2). diff --git a/translations/it.ts b/translations/veyon_it.ts similarity index 72% rename from translations/it.ts rename to translations/veyon_it.ts index 246bfef1f..5e29b3fa9 100644 --- a/translations/it.ts +++ b/translations/veyon_it.ts @@ -1,9 +1,9 @@ - + AboutDialog About - Informazioni su + Informazioni Translation @@ -33,7 +33,7 @@ Current language not translated yet (or native English). If you're interested in translating Veyon into your local or another language or want to improve an existing translation, please contact a Veyon developer! - La lingua corrente non è ancora stata tradotta completamente (dall'inglese). + Lingua corrente tradotta da Albano Battistella (dall' inglese nativo) Se sei interessato alla traduzione di Veyon nella tua lingua locale o in qualche altra lingua o vuoi migliorare una traduzione esistente, contatta uno sviluppatore Veyon! @@ -80,10 +80,6 @@ Se sei interessato alla traduzione di Veyon nella tua lingua locale o in qualche All groups Tutti i gruppi - - ... - ... - Access control rules Regole di controllo d'accesso @@ -130,7 +126,7 @@ Se sei interessato alla traduzione di Veyon nella tua lingua locale o in qualche The specified user is not allowed to access computers with this configuration. - L'utente indicato non è abilitato ad accedere a computer con questa confiugurazione. + L'utente indicato non è abilitato ad accedere a computer con questa configurazione. Enable usage of domain groups @@ -140,19 +136,18 @@ Se sei interessato alla traduzione di Veyon nella tua lingua locale o in qualche User groups backend: Backend del gruppo utenti: - - Missing user groups backend - Backend dei gruppi utente non presente - - - No default user groups plugin was found. Please check your installation! - Non è stato trovato alcun plug-in predefinito per gruppi di utenti. Per favore controlla la tua installazione! - Restrict access to members of specific user groups Limita l'accesso a specifici membri di gruppi utenti + + AccessControlProvider + + Provider for access control features + Fornitore di funzionalità di controllo degli accessi + + AccessControlRuleEditDialog @@ -179,30 +174,10 @@ Se sei interessato alla traduzione di Veyon nella tua lingua locale o in qualche Rule description: Descrizione della regola: - - Invert all conditions ("is/has" interpreted as "is/has not") - Inverti tutte le condizioni ("è/ha" interpretato come "non è/ha") - Conditions Condizioni - - is member of group - è membro del gruppo - - - Accessing computer is localhost - Il computer in cui si sta entrando è localhost - - - Accessing user is logged on user - L'utente che sta entrando è registrato sull'utente - - - Accessing user is already connected - L'utente che sta entrando è già connesso - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. Se è attivata più di una condizione, ciascuna condizione deve essere soddisfatta affinchè la regola venga applicata (AND logico). Se invece solo una condizione è richiesta (OR logico), allora per favore creare regole multiple di controllo accesso. @@ -236,33 +211,125 @@ Se sei interessato alla traduzione di Veyon nella tua lingua locale o in qualche Il computer che sta entrando - Local (logged on) user - Utente locale (collegato) + Always process rule and ignore conditions + Elabora sempre la regola ed ignora le condizioni - Local computer - Computer locale + Accessing computer and local computer + Accesso al computer e al computer locale - Always process rule and ignore conditions - Elabora sempre la regola ed ignora le condizioni + User being accessed + Accesso all'utente - No user logged on - Nessun utente connesso + is logged in locally + è connesso localmente + + + is logged in remotely + è connesso in remoto + + + No user is logged in locally + Nessun utente è connesso localmente + + + One or multiple users are logged in locally + Uno o più utenti hanno effettuato l'accesso in locale - Accessing user has one or more groups in common with local (logged on) user - L'utente a cui si sta accedendo ha uno o più gruppi in comune con l'utente locale (l'utente ora loggato). + No user is logged in remotely + Nessun utente è connesso in remoto - Accessing computer and local computer are at the same location - L'accesso al computer e al computer locale si trovano nella stessa posizione + One or multiple users are logged in remotely + Uno o più utenti hanno effettuato l'accesso da remoto is located at si trova a + + is not located at + non si trova in + + + are located at the same location + si trovano nella stessa posizione + + + are not located the same location + non si trovano nella stessa posizione + + + is member of group + è membro del gruppo + + + is not member of group + non è membro del gruppo + + + is authenticated via + è autenticato tramite + + + is not authenticated via + non è autenticato tramite + + + has one or more groups in common with user being accessed + ha uno o più gruppi in comune con l'utente a cui si accede + + + has no groups in common with user being accessed + non ha gruppi in comune con l'utente a cui si accede + + + equals user being accessed + è uguale all'utente a cui ha avuto accesso + + + is different from user being accessed + è diverso dall'utente che ha avuto accesso + + + is already connected + è già connesso + + + is not connected + non è connesso + + + is local computer + è il computer locale + + + is not local computer + non è un computer locale + + + Computer being accessed + Computer a cui si accede + + + Session being accessed is a user session + La sessione a cui si accede è una sessione utente + + + Session being accessed is a login screen + La sessione a cui si accede è una schermata di accesso + + + Local computer is already being accessed + È già in corso l'accesso al computer locale + + + Local computer is not yet being accessed + Il computer locale non è ancora in fase di accesso + AccessControlRulesTestDialog @@ -306,42 +373,44 @@ Se sei interessato alla traduzione di Veyon nella tua lingua locale o in qualche The access in the given scenario needs permission of the logged on user. L'accesso allo scenario fornito richiede l'autorizzazione dell'utente connesso. - - ERROR: Unknown action - ERRORE: azione sconosciuta - Test result Risultati del test - - - AndroidPlatformConfigurationPage - Android - + Authentication method + Metodo di autenticazione - General - Generale + There is no matching rule with a valid action. The access is therefore denied. + Non esiste una regola corrispondente con un'azione valida. L'accesso è quindi negato. - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + Introduzione - - - AuthKeysConfigurationPage - Authentication keys - Chiavi di autenticazione + Please perform the following steps to set up key file authentication: + Effettuare le seguenti operazioni per configurare l'autenticazione del file chiave: - Introduction - Introduzione + 1) Create a key pair on the master computer. + 1) Creare una coppia di chiavi sul computer master. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Impostare un gruppo di accesso i cui membri dovrebbero poter accedere ad altri computer. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Esportare la chiave pubblica e importarla su tutti i computer client con lo stesso nome. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Per ulteriori informazioni, consultare il <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Manuale dell'amministratore di Veyon</a>. Key file directories @@ -355,14 +424,17 @@ Se sei interessato alla traduzione di Veyon nella tua lingua locale o in qualche Private key file base directory Cartella chiave Privata - - ... - ... - Available authentication keys Chiavi di autenticazione disponibili + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Una coppia di chiavi di autenticazione è composta da due chiavi crittografiche accoppiate, una privata e una chiave pubblica. Una chiave privata consente agli utenti del computer master di accedere ai computer client. È importante che solo gli utenti autorizzati abbiano accesso in lettura al file della chiave privata. La chiave pubblica viene utilizzata sui computer client per autenticare la richiesta di connessione in entrata. + Create key pair Crea una coppia di chiavi @@ -403,10 +475,6 @@ Se sei interessato alla traduzione di Veyon nella tua lingua locale o in qualche Please select a key to delete! Seleziona la chiave da eliminare! - - Please enter the name of the user group or role for which to import the authentication key: - Inserire il nome del gruppo o ruolo dell'utente per il quale importare la chiave di autenticazione: - Please select a key to export! Seleziona la chiave da esportare! @@ -420,31 +488,12 @@ Se sei interessato alla traduzione di Veyon nella tua lingua locale o in qualche Si prega di selezionare una chiave per impostare il gruppo di accesso! - Please perform the following steps to set up key file authentication: - Effettuare le seguenti operazioni per configurare l'autenticazione del file chiave: - - - 1) Create a key pair on the master computer. - 1) Creare una coppia di chiavi sul computer master. - - - 2) Set an access group whose members should be allowed to access other computers. - 2) Impostare un gruppo di accesso i cui membri dovrebbero poter accedere ad altri computer. - - - 3) Export the public key and import it on all client computers with the same name. - 3) Esportare la chiave pubblica e importarla su tutti i computer client con lo stesso nome. - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - Per ulteriori informazioni, consultare il <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Manuale dell'amministratore di Veyon</a>. - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - Una coppia di chiavi di autenticazione è composta da due chiavi crittografiche accoppiate, una privata e una chiave pubblica. Una chiave privata consente agli utenti del computer master di accedere ai computer client. È importante che solo gli utenti autorizzati abbiano accesso in lettura al file della chiave privata. La chiave pubblica viene utilizzata sui computer client per autenticare la richiesta di connessione in entrata. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + Inserisci il nome del gruppo di utenti o del ruolo per cui importare la chiave di autenticazione. + +Assicurati che i nomi delle chiavi che appartengono l'una all'altra siano identici su tutti i computer. @@ -644,10 +693,6 @@ The public key is used on client computers to authenticate incoming connection r This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. Questo comando elenca tutte le chiavi di autenticazione disponibili nella directory delle chiavi configurate. Se viene specificata l'opzione "%1", verrà visualizzata una tabella con i dettagli chiave. Alcuni dettagli potrebbero mancare se una chiave non è accessibile, ad es. a causa della mancanza di permessi di lettura. - - Please specify the command to display help for! - Si prega di specificare il comando per visualizzare la guida per! - TYPE TIPO @@ -656,10 +701,6 @@ The public key is used on client computers to authenticate incoming connection r PAIR ID COPPIA ID - - Command line support for managing authentication keys - Supporto da riga di comando per la gestione delle chiavi di autenticazione - Commands for managing authentication keys Comandi per la gestione delle chiavi di autenticazione @@ -676,6 +717,30 @@ The public key is used on client computers to authenticate incoming connection r This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. Questo comando estrae la parte della chiave pubblica dalla chiave privata <KEY> e lo salva come chiave pubblica corrispondente. Quando si configura un altro computer master, è quindi sufficiente trasferire solo la chiave privata. La chiave pubblica può quindi essere estratta. + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + I file delle chiavi di autenticazione non sono impostati correttamente su questo computer. Crea nuovi file di chiavi o passa a un altro metodo di autenticazione utilizzando Veyon Configurator. + + + Key file authentication + Autenticazione con File chiave + + + Key file + File chiave + + + Please specify the key name (e.g. "teacher/public") as the first argument. + Si prega di specificare il nome della chiave (ad es. "insegnante/pubblico") come primo argomento. + + + Please specify the command to display help for. + Specificare il comando per cui visualizzare la guida. + + + The specified command does not exist or no help is available for it. + Il comando specificato non esiste o non è disponibile alcun aiuto. + AuthKeysTableModel @@ -697,100 +762,243 @@ The public key is used on client computers to authenticate incoming connection r - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - Computer + General + Generale - Name - Nome + Username to bind DN mapping: + Nome utente per associare la mappatura DN: - Host address/IP - Indirizzo host/IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + es. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + AuthLdapDialog - MAC address - indirizzo MAC + Veyon Logon + Logon Veyon - Add new computer - Aggiungi un nuovo computer + Please enter your domain/LDAP username and password in order to access computers. + Inserisci il tuo dominio/LDAP nome utente e password per accedere ai computer. - Remove selected computer - Rimuovi il computer selezionato + Username + Nome Utente - New computer - Nuovo computer + Password + Password - Builtin directory - Directory incorporata + Authentication error + Errore di autenticazione - Locations & computers - Posizioni e computers + Logon failed with given username and password. Please try again! + Logon fallito con le credenziali fornite. Riprova! + + + AuthLogonDialog - Locations - Posizioni + Veyon Logon + Logon Veyon - Add new location - Aggiungi nuova posizione + Please enter your username and password in order to access computers. + Inserisci il tuo username e password per accedere ai computer - Remove selected location - Rimuovi la posizione selezionata + Username + Nome Utente - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - L'importazione di file CSV è possibile tramite l'interfaccia della riga di comando. Per ulteriori informazioni, consultare la documentazione online.<a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory"> + Password + Password - New location - Nuova posizione + Authentication error + Errore di autenticazione + + + Logon failed with given username and password. Please try again! + Logon fallito con le credenziali fornite. Riprova! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command - Mostra l'aiuto per un comando specifico + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Il nome utente o la password forniti sono errati. Inserisci credenziali valide o passa a un altro metodo di autenticazione utilizzando Veyon Configurator. - Import objects from given file - Importa oggetti dal file specificato + Logon authentication + Autenticazione di accesso (Logon) - Export objects to given file - Esportare oggetti nel file specificato + Logon + Accedere + + + AuthSimpleDialog - Invalid type specified. Valid values are "%1" or "%2". - Tipo non valido specificato. I valori validi sono "%1" o "%2". + Veyon Logon + Logon Veyon - Type - Tipo + Please enter the Veyon password: + Inserisci la password di Veyon: - Name - Nome + Authentication error + Errore di autenticazione - Host address - Indirizzo dell'host + Logon failed with given password. Please try again! + Accesso non riuscito con password specificata. Per favore riprova! + + + AuthSimplePlugin - MAC address - indirizzo MAC + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + La password fornita è errata. Inserisci la password corretta o passa a un altro metodo di autenticazione utilizzando Veyon Configurator. - Specified object not found. + Simple password authentication + La password fornita è errata. Inserisci la password corretta o passa un altro metodo di autenticazione usato Veyon Configurator. + + + Simple password + Password semplice + + + + AuthenticationPage + + Authentication is set up properly on this computer. + L'autenticazione è configurata correttamente su questo computer. + + + + AuthenticationPageTab + + Enabled + Abilitato + + + Test + Prova + + + + BuiltinDirectoryConfiguration + + Builtin directory + Directory incorporata + + + + BuiltinDirectoryConfigurationPage + + Computers + Computer + + + Name + Nome + + + Host address/IP + Indirizzo host/IP + + + MAC address + indirizzo MAC + + + Add new computer + Aggiungi un nuovo computer + + + Remove selected computer + Rimuovi il computer selezionato + + + New computer + Nuovo computer + + + Builtin directory + Directory incorporata + + + Locations + Posizioni + + + Add new location + Aggiungi nuova posizione + + + Remove selected location + Rimuovi la posizione selezionata + + + New location + Nuova posizione + + + Directory name + Nome Directory + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + Il'importazione di file CSV è possibile tramite l'interfaccia della riga di comando. Per ulteriori informazioni, vedere la<a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">documentazione in linea</a>. + + + + BuiltinDirectoryPlugin + + Show help for specific command + Mostra l'aiuto per un comando specifico + + + Import objects from given file + Importa oggetti dal file specificato + + + Export objects to given file + Esportare oggetti nel file specificato + + + Invalid type specified. Valid values are "%1" or "%2". + Tipo non valido specificato. I valori validi sono "%1" o "%2". + + + Type + Tipo + + + Name + Nome + + + Host address + Indirizzo dell'host + + + MAC address + indirizzo MAC + + + Specified object not found. Oggetto specificato non trovato. @@ -997,6 +1205,14 @@ The public key is used on client computers to authenticate incoming connection r MAC ADDRESS MAC ADDRESS + + The specified command does not exist or no help is available for it. + Il comando specificato non esiste o non è disponibile alcun aiuto. + + + Location "%1" not found. + Posizione "%1" non trovata. + BuiltinUltraVncServer @@ -1014,10 +1230,6 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - Host/indirizzo IP: %1 - Active features: %1 Funzioni attive: %1 @@ -1034,10 +1246,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off Computer disconnesso o spento - - Service unreachable or not running - Servizio irraggiungibile o non in esecuzione - Authentication failed or access denied Autenticazione fallita o accesso negato @@ -1058,6 +1266,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 Posizione: %1 + + [no user] + [nessun utente] + + + Veyon Server unreachable or not running + Veyon Server irraggiungibile o non in esecuzione + + + Name: %1 + Nome: %1 + + + Hostname: %1 + Nome host: %1 + + + unknown + sconosciuto + + + IP address: %1 + Indirizzo IP: %1 + + + Hostname could not be resolved + Il nome host non può essere risolto + + + No features active + Nessuna funzione attiva + ComputerControlServer @@ -1079,15 +1319,26 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" attempted to access this computer but could not authenticate successfully. - + L'utente "%1" presso l' host "%2" ha tentato di accedere a questo computer ma non è stato possibile eseguire l'autenticazione. Access control error - + Errore di controllo dell'accesso User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. - + L'utente "%1" presso l'host "%2" ha tentato di accedere a questo computer ma è stato bloccato a causa delle impostazioni di controllo dell'accesso. + + + Active connections: + Connessioni attive: + + + + ComputerGroupSelector + + Group %1 + Gruppo %1 @@ -1116,13 +1367,48 @@ The public key is used on client computers to authenticate incoming connection r Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. Impossibile determinare la posizione di questo computer. Questo indica un problema con la configurazione del sistema. Tutte le posizioni verranno visualizzate nel pannello di selezione del computer. + + Logged in since + Collegato dal + + + %1 days + %1 giorni + + + 1 day + 1 giorno + - ComputerSelectPanel + ComputerMonitoring + + Computers + Computer + + + Search users and computers + Cerca utenti e computer + + + Select all + Seleziona tutto + + + Unselect all + Deseleziona tutto + + + Add to group + Aggiungi al gruppo + - Computer management - Gestione del computer + Remove from group + Rimuovi dal gruppo + + + ComputerSelectPanel Computer search Ricerca computer @@ -1151,81 +1437,85 @@ The public key is used on client computers to authenticate incoming connection r Could not write the computer and users list to %1! Please check the file access permissions. Impossibile scrivere l'elenco computer e utenti su %1! Controllare i permessi di accesso al file. + + Search computers + Cerca computer + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. - Per favore indicare un file di configurazione esistente da importare. + Clear system-wide Veyon configuration + Eliminazione della configurazione di Veyon su tutto il sistema. - Please specify a valid filename for the configuration export. - Per favore indicare un nome di file valido per esportare la configurazione. + List all configuration keys and values + Lista di tutte le chiavi di configurazione e dei loro valori. - Please specify a valid key. - Per favore indicare una chiave valida. + Import configuration from given file + Importa una configurazione da file. - Specified key does not exist in current configuration! - La chiave indicata non esiste nella configurazione corrente! + Export configuration to given file + Esporta una configurazione su file. - Please specify a valid value. - Per favore indicare un valore valido. + Read and output configuration value for given key + Leggi e stampa i valori di configurazione delle chiavi date - Configure Veyon at command line - Non è possibile modificare gli argomenti passati a %1 + Write given value to given configuration key + Imposta il valore della chiave di configurazione - Output file is not writable! - Non si dispone dei permessi di scrittura per il file di destinazione. + Unset (remove) given configuration key + Dimentica (rimuovi) la chiave di configurazione data - Output directory is not writable! - Non si dispone dei permessi di scrittura nella cartella di destinazione + Upgrade and save configuration of program and plugins + Aggiorna e salva la configurazione del programma e dei plugin + + + Please specify an existing configuration file to import. + Per favore indicare un file di configurazione esistente da importare. Configuration file is not readable! Non è possibile leggere il file di configurazione! - Clear system-wide Veyon configuration - Eliminazione della configurazione di Veyon su tutto il sistema. + Please specify a valid filename for the configuration export. + Per favore indicare un nome di file valido per esportare la configurazione. - List all configuration keys and values - Lista di tutte le chiavi di configurazione e dei loro valori. + Output file is not writable! + Non si dispone dei permessi di scrittura per il file di destinazione. - Import configuration from given file - Importa una configurazione da file. + Output directory is not writable! + Non si dispone dei permessi di scrittura nella cartella di destinazione - Export configuration to given file - Esporta una configurazione su file. + Please specify a valid key. + Per favore indicare una chiave valida. - Read and output configuration value for given key - Leggi e stampa i valori di configurazione delle chiavi date + Specified key does not exist in current configuration! + La chiave indicata non esiste nella configurazione corrente! - Write given value to given configuration key - Imposta il valore della chiave di configurazione + Please specify a valid value. + Per favore indicare un valore valido. - Unset (remove) given configuration key - Dimentica (rimuovi) la chiave di configurazione data + Configure Veyon at command line + Non è possibile modificare gli argomenti passati a %1 Commands for managing the configuration of Veyon Comandi di configurazione - - Upgrade and save configuration of program and plugins - Aggiorna e salva la configurazione del programma e dei plugin - ConfigurationManager @@ -1249,6 +1539,10 @@ The public key is used on client computers to authenticate incoming connection r Could not apply platform-specific configuration settings. Impossibile applicare le impostazioni di configurazione specifiche della piattaforma. + + Could not configure the firewall configuration for the %1 Service. + Impossibile configurare la configurazione del firewall per il servizio %1. + DemoClient @@ -1279,10 +1573,6 @@ The public key is used on client computers to authenticate incoming connection r Memory limit Limite memoria - - Use multithreading (experimental) - Utilizzo multithreading (sperimentale) - MB MB @@ -1299,13 +1589,17 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running Rallenta gli aggiornamenti delle miniature mentre la demo è in esecuzione + + Bandwidth limit + Limite di larghezza di banda + + + MB/s + MB/s + DemoFeaturePlugin - - Fullscreen demo - Presenta su schermo intero - Stop demo Ferma Presentazione @@ -1319,16 +1613,60 @@ The public key is used on client computers to authenticate incoming connection r Esemplificare trasmettendo il proprio schermo - Demo server - Server per la modalità Presentazione + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + In questa modalità il tuo schermo sarà visualizzato in una finestra su tutti i computer client. Gli utenti, pertanto, potranno cambiare finestra e continuare il loro lavoro. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - In questa modalità il tuo schermo sarà visualizzato su tutti i computer client a tutto schermo. Inoltre gli utenti non saranno in grado di svolgere altre azioni, in quanto le periferiche di input saranno bloccate. + Demo + Demo - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - In questa modalità il tuo schermo sarà visualizzato in una finestra su tutti i computer client. Gli utenti, pertanto, potranno cambiare finestra e continuare il loro lavoro. + Share your screen or allow a user to share his screen with other users. + Condividi il tuo schermo o consenti a un utente di condividere il suo schermo con altri utenti. + + + Full screen demo + Demo a schermo intero + + + Share your own screen in fullscreen mode + Condividi il tuo schermo in modalità a schermo intero + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + In questa modalità lo schermo viene visualizzato in modalità a schermo intero su tutti i computer mentre i dispositivi di input degli utenti sono bloccati. + + + Share your own screen in a window + Condividi il tuo schermo in una finestra + + + Share selected user's screen in fullscreen mode + Condividi lo schermo dell'utente selezionato in modalità a schermo intero + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + In questa modalità lo schermo dell'utente selezionato viene visualizzato in modalità a schermo intero su tutti i computer mentre i dispositivi di input degli utenti sono bloccati. + + + Share selected user's screen in a window + Condividi lo schermo dell'utente selezionato in una finestra + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + In questa modalità lo schermo dell'utente selezionato viene visualizzato in una finestra su tutti i computer. Gli utenti possono passare ad altre finestre secondo necessità. + + + Please select a user screen to share. + Seleziona una schermata utente da condividere. + + + Please select only one user screen to share. + Seleziona solo uno schermo utente da condividere. + + + All screens + Tutti gli schermi @@ -1356,14 +1694,6 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - - Programs & websites - Programmi e siti Web - - - Predefined programs - Programmi predefiniti - Name Nome @@ -1372,14 +1702,6 @@ The public key is used on client computers to authenticate incoming connection r Path Percorso - - Add new program - Aggiungi un nuovo programma - - - Remove selected program - Rimuovi il programma selezionato - Predefined websites Siti Web predefiniti @@ -1392,44 +1714,44 @@ The public key is used on client computers to authenticate incoming connection r URL URL - - New program - Nuovo programma - New website Nuovo sito web - - - DesktopServicesFeaturePlugin - Run program - Apri un programma + Applications & websites + Applicazioni e siti web - Open website - Collegamento ad un sito internet + Predefined applications + Applicazioni predefinite - Click this button to open a website on all computers. - Clicca su questo pulsante per aprire un sito internet su tutti i PC. + Add new application + Aggiungi nuova applicazione + + + Remove selected application + Rimuovi l'applicazione selezionata - Start programs and services in user desktop - Attiva il programma sul PC remoto + Add new website + Aggiungi nuovo sito web - Click this button to run a program on all computers. - Clicca su questo pulsante per lanciare un programma su tutti i PC + New application + Nuova applicazione + + + DesktopServicesFeaturePlugin - Run program "%1" - Esegui il programma "%1" + Open website + Apri sito web - Custom program - Programma personalizzato + Click this button to open a website on all computers. + Clicca su questo pulsante per aprire un sito internet su tutti i PC. Open website "%1" @@ -1439,6 +1761,26 @@ The public key is used on client computers to authenticate incoming connection r Custom website Sito web personalizzato + + Start application + Avvia applicazione + + + Click this button to start an application on all computers. + Fare clic su questo pulsante per avviare un'applicazione su tutti i computer. + + + Start application "%1" + Avvia l'applicazione "%1" + + + Custom application + Applicazione personalizzata + + + Start apps and open websites in user sessions + Avvia app e apri siti web nelle sessioni utente + DocumentationFigureCreator @@ -1460,27 +1802,31 @@ The public key is used on client computers to authenticate incoming connection r Open file manager - + Apri il file manager Start learning tool - + Avvia strumento di apprendimento Play tutorial video - - - - Custom program - Programma personalizzato + Riproduci video tutorial Handout - + Volantino Texts to read - + Testi da leggere + + + generic-student-user + utente-generico-studente + + + Custom application + Applicazione personalizzata @@ -1506,10 +1852,165 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands + + List names of all available features + Elenca nomi di tutte le funzioni disponibili + + + Show table with details of all available features + Mostra tabella con i dettagli di tutte le funzionalità disponibili + + + Start a feature on a remote host + Avvia una funzione su un host remoto + + + Stop a feature on a remote host + Arresta una funzione su un host remoto + + + Please specify the command to display help for. + Specificare il comando per cui visualizzare la guida. + + + Displays a list with the names of all available features. + Visualizza un elenco con i nomi di tutte le funzioni disponibili. + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + Visualizza una tabella con informazioni dettagliate su tutte le funzioni disponibili. Queste informazioni includono una descrizione, l'UID, il nome del plug-in che fornisce la rispettiva funzione e alcuni altri dettagli relativi all'implementazione. + + + HOST ADDRESS + INDIRIZZO COMPUTER + + + FEATURE + CARATTERISTICA + + + ARGUMENTS + ARGOMENTI + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + Avvia la funzione specificata sull'host specificato connettendosi al server Veyon in esecuzione in remoto. La funzione può essere specificata per nome o UID. Usa il comando ``mostra`` per vedere tutte le funzionalità disponibili. A seconda della funzionalità, devono essere specificati argomenti aggiuntivi (come il messaggio di testo da visualizzare) codificati come una singola stringa JSON. Si prega di fare riferimento alla documentazione per gli sviluppatori per ulteriori informazioni + + + Lock the screen + Blocca lo schermo + + + Display a text message + Visualizza un messaggio di testo + + + Test message + Messaggio di prova + + + Start an application + Avvia un'applicazione + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + Arresta la funzione specificata sull'host specificato connettendosi al server Veyon in esecuzione in remoto. La funzione può essere specificata per nome o UID. Usa il comando ``mostra`` per vedere tutte le funzionalità disponibili. + + + Unlock the screen + Sblocca lo schermo + + + The specified command does not exist or no help is available for it. + Il comando specificato non esiste o non è disponibile alcun aiuto. + + + Name + Nome + + + Description + Descrizione + + + Master + Principale + + + Service + Servizio + + + Worker + Lavoratore + + + UID + UID + + + Plugin + Plugin + + + Invalid feature name or UID specified + Nome della funzione o UID specificato non valido + + + Error parsing the JSON-encoded arguments: %1 + Errore durante l'analisi degli argomenti con codifica JSON: %1 + + + Failed to initialize credentials + Impossibile inizializzare le credenziali + + + Could not establish a connection to host %1 + Impossibile stabilire una connessione all'host %1 + + + Failed to send feature control message to host %1 + Impossibile inviare il messaggio di controllo della funzionalità all'host %1 + + + Feature-related CLI operations + Operazioni CLI relative alle funzionalità + + + Commands for controlling features + Comandi per il controllo delle funzioni + + + + FileTransferConfigurationPage + + File transfer + Trasferimento di file + + + Directories + Cartelle + + + Destination directory + Directory di destinazione + + + Default source directory + Directory di origine predefinita + + + Options + Opzioni + + + Remember last source directory + Ricorda l'ultima directory di origine + - Feature control - Controllo delle opzioni + Create destination directory if it does not exist + Crea la directory di destinazione se non esiste @@ -1554,6 +2055,13 @@ The public key is used on client computers to authenticate incoming connection r Sovrascrivi i file esistenti + + FileTransferFileDialog + + Select one or more files to transfer + Seleziona uno o più file da trasferire + + FileTransferPlugin @@ -1611,10 +2119,6 @@ The public key is used on client computers to authenticate incoming connection r Log file directory Cartella per il Log file - - ... - ... - Log level Livello di Log @@ -1655,18 +2159,6 @@ The public key is used on client computers to authenticate incoming connection r Log to standard error output Log sullo standard error output - - Network object directory - Directory dell'oggetto di rete - - - Backend: - Backend: - - - Update interval: - Intervallo di aggiornamento: - %1 service Servizio %1 @@ -1703,103 +2195,80 @@ The public key is used on client computers to authenticate incoming connection r x x - - seconds - secondi - Write to logging system of operating system Scrivi nel sistema di log del sistema operativo - Authentication - Autenticazione - - - Method: - Metodo: - - - Logon authentication - Autenticazione di accesso (Logon) - - - Key file authentication - Autenticazione con File chiave - - - Test - Prova + TLS configuration + Configurazione TLS - Authentication is set up properly on this computer. - L'autenticazione è configurata correttamente su questo computer. + Use certificate authority for TLS connections + Usa l'autorità di certificazione per le connessioni TLS - Authentication keys are not set up properly on this computer. - Le chiavi di autenticazione non sono configurate correttamente su questo computer. + CA certificate file + File certificato CA - Authentication test - Test di autenticazione + ... + ... - - - InternetAccessControlConfigurationPage - Internet access control - Controllo dell'accesso a Internet + Host certificate file + File del certificato host - Backend: - Backend: + Host private key file + File della chiave privata dell'host - General settings - Impostazioni generali + Style: + Stile: - Backend settings - Impostazioni back-end + Native + Nativo - - - InternetAccessControlPlugin - Block access to the internet - Blocca l'accesso a Internet + Color scheme: + Schema di colori: - Allow access to the internet - Consentire l'accesso a Internet + Light + Leggero - Show help about command - Mostra aiuto per i comandi + Dark + Scuro - Block internet - Blocca internet + User groups + Gruppi utenti - Click this button to block access to the internet. - Fare clic su questo pulsante per bloccare l'accesso a Internet. + Backend: + Backend: - Unblock internet - Sblocca internet + Include user groups from domain + Includi gruppi di utenti dal dominio - Click this button to allow access to the internet. - Fare clic su questo pulsante per consentire l'accesso a Internet. + Missing user groups backend + Backend dei gruppi utente non presente - Control access to the internet - Controlla l'accesso a Internet + No user groups plugin was found. Please check your installation! + Nessun plugin per gruppi di utenti è stato trovato. Controlla la tua installazione! + + + HeadlessVncServer - Commands for controlling access to the internet - Comandi per il controllo dell'accesso a Internet + Headless VNC server + Server VNC headless @@ -1817,344 +2286,517 @@ The public key is used on client computers to authenticate incoming connection r - LdapConfigurationPage + LdapConfiguration - Basic settings - Impostazioni di base + LDAP connection failed + Connessione al server LDAP fallita - General - Generale + Could not connect to the LDAP server. Please check the server parameters. + +%1 + Impossibile connettersi al server LDAP. Controlla i parametri del server.%1 - LDAP server and port - Indirizzo e porta del server LDAP + LDAP bind failed + Il bind con il server LDAP è fallito. Verificare la sintassi delle credenziali - Bind DN - Bind DN + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + Impossibile collegarsi al server LDAP. Controlla i parametri del server e associa le credenziali.%1 - Bind password - Bind password + LDAP bind successful + Il bind con il server LDAP è riuscito. - Anonymous bind - Anonymous bind + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Collegato correttamente al server LDAP ed eseguito un binding LDAP. Le impostazioni LDAP di base sono configurate correttamente. - Use bind credentials - Use bind credentials + LDAP base DN test failed + Test LDAP base DN fallito - Base DN - Base DN + Could not query the configured base DN. Please check the base DN parameter. + +%1 + Impossibile interrogare il DN base configurato. Controlla il parametro DN di base.%1 - Fixed base DN - Fixed base DN + LDAP base DN test successful + Test LDAP base DN riuscito - e.g. dc=example,dc=org - e.g. dc=example,dc=org + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + Il DN base LDAP è stato interrogato correttamente. Sono state trovate le seguenti voci: %1 - Discover base DN by naming context - Discover base DN by naming context + LDAP naming context test failed + Test per contesto nominazione LDAP fallito - e.g. namingContexts or defaultNamingContext - e.g. namingContexts or defaultNamingContext + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + Impossibile interrogare il DN di base tramite i contesti di denominazione. Controlla il parametro dell'attributo del contesto di denominazione.%1 - Environment settings - Impostazioni ambiente + LDAP naming context test successful + Test di contesto di denominazione LDAP riuscito - Object trees - Alberatura oggetti + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + LDAP interrogato con successo. Il seguente base DN è stato trovato: +%1 + + + user tree + albero utenti + + + User tree + Alberatura utenti + + + group tree + albero gruppi + + + Group tree + Alberatura gruppi + + + computer tree + albero computer Computer tree Alberatura Pc - e.g. OU=Groups - e.g. OU=Groups + computer group tree + albero gruppo computer - User tree - Alberatura utenti + Computer group tree + Albero gruppo computer - e.g. OU=Users - e.g. OU=Users + user objects + user objects - e.g. OU=Computers - e.g. OU=Computers + User login name attribute + Attributo del nome di accesso dell'utente - Group tree - Alberatura gruppi + group members + Membri del gruppo - Perform recursive search operations in object trees - Ricerca anche nelle sottocartelle + Group member attribute + Attributo del gruppo del membro - Object attributes - Attributi degli oggetti + Group not found + Gruppo non trovato - e.g. hwAddress - e.g. hwAddress + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Non è possibile trovare il gruppo %1. Verificare il nome del gruppo inserito e i parametri LDAP dei gruppi. - e.g. member or memberUid - Per esempio membro o membroUid + computer objects + oggetti computer - e.g. dNSHostName - Per esempio dNSHostName + Computer display name attribute + Attributo del nome di visualizzazione del computer + + + Invalid hostname + Hostname non valido + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Hai configurato i nomi host dei computer da memorizzare come nomi di dominio completi (FQDN), ma hai inserito un nome host senza dominio. + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Hai configurato i nomi host dei computer da memorizzare come semplici nomi host senza un nome di dominio, ma hai inserito un nome host con una parte del nome di dominio. + + + Computer hostname attribute + Attributo hostname del computer + + + computer MAC addresses + indirizzi MAC computer Computer MAC address attribute Attributo dell'indirizzo MAC del computer - Group member attribute - Attributo del gruppo del membro + computer locations + posizioni del computer - e.g. uid or sAMAccountName - Per esempio uid o sAMAccountName + Computer location attribute + Attributo di posizione del computer - Advanced settings - Impostazioni avanzate + Location name attribute + Attributo del nome della posizione - Optional object filters - Filtro per oggetti opzionale + users + utenti - Filter for user groups - Filtro per gruppo utenti + user groups + gruppi di utenti - Filter for users - Filtro Users + computers + computer + + + computer groups + gruppi computer + + + computer containers + computer containers + + + groups of user + gruppi di utenti + + + User not found + Utente non trovato + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + Impossibile trovare un utente con il nome "%1". Si prega di controllare il nome utente o il parametro dell'albero utente. + + + groups of computer + gruppi di computer + + + Computer not found + Computer non trovato + + + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Impossibile trovare un computer con il nome host "%1". Si prega di controllare il nome host o il parametro dell'albero del computer. + + + Hostname lookup failed + Ricerca del nome host fallita + + + Could not lookup hostname for IP address %1. Please check your DNS server settings. + Impossibile cercare il nome host per l'indirizzo IP%1. Si prega di verificare le impostazioni del server DNS. + + + location entries + voci di posizione + + + Computer groups filter + Filtro gruppi di computer + + + Computer locations identification + Identificazione delle posizioni dei computers Filter for computer groups Filtro Gruppo computer - Group member identification - Identificazione membro del gruppo + Invalid test value + Valore di prova non valido - Distinguished name (Samba/AD) - Nome distinto (Samba/AD) + An empty or invalid value has been supplied for this test. + Un valore vuoto o non valido è stato fornito per questo test. - List all groups of a user - Visualizza i gruppi a cui appartiene un User + LDAP %1 test failed + Test %1 LDAP fallito - List all groups of a computer - Visualizza i gruppi a cui appartiene un computer + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + Impossibile interrogare le voci configurate %1. Si prega di controllare il parametro "%2". + +3% - Get computer object by IP address - Identifica il computer mediante indirizzo IP + LDAP %1 test successful + Test %1 LDAP completato con successo - LDAP connection failed - Connessione al server LDAP fallita + The %1 has been queried successfully and %2 entries were found. + Il %1 e' stato interrogato con successo e sono state trovate %2 voci. - LDAP bind failed - Il bind con il server LDAP è fallito. Verificare la sintassi delle credenziali + LDAP test failed + Test LDAP fallito - LDAP bind successful - Il bind con il server LDAP è riuscito. + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + Impossibile interrogare alcun%1. Controlla i parametro(i)%2 e inserisci il nome di un oggetto esistente. + +3% - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - Collegato correttamente al server LDAP ed eseguito un binding LDAP. Le impostazioni LDAP di base sono configurate correttamente. + and + e - LDAP base DN test failed - Test LDAP base DN fallito + LDAP test successful + Test LDAP riuscito - LDAP base DN test successful - Test LDAP base DN riuscito + %1 %2 have been queried successfully: + +%3 + %1 %2 sono stati interrogati con successo: + +%3 - LDAP naming context test failed - Test per contesto nominazione LDAP fallito + LDAP filter test failed + Test filtro LDAP falllito - LDAP naming context test successful - Test di contesto di denominazione LDAP riuscito + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 + Impossibile interrogare qualsiasi %1 usando il filtro configurato. Si prega di verificare il filtro LPAP per %1. + +%2 - The LDAP naming context has been queried successfully. The following base DN was found: -%1 - LDAP interrogato con successo. Il seguente base DN è stato trovato: -%1 + LDAP filter test successful + Test filtro LDAP completato con successo - user tree - albero utenti + %1 %2 have been queried successfully using the configured filter. + %1 %2 sono stati interrogati con successo usando il filtro configurato. - group tree - albero gruppi + LDAP directory + Directory LDAP + + + LdapConfigurationPage - computer tree - albero computer + Basic settings + Impostazioni di base - Enter username - Inserire il nome utente + General + Generale - Please enter a user login name (wildcards allowed) which to query: - Inserire un nome utente di login (caratteri speciali ammessi) per il quale effettuare la query + LDAP server and port + Indirizzo e porta del server LDAP - user objects - user objects + Bind DN + Bind DN - Enter group name - Inserire il nome del gruppo + Bind password + Bind password - Please enter a group name whose members to query: - Inserire il nome di un gruppo in cui ricercare i membri + Anonymous bind + Anonymous bind - group members - Membri del gruppo + Use bind credentials + Use bind credentials - Group not found - Gruppo non trovato + Base DN + Base DN - Could not find a group with the name "%1". Please check the group name or the group tree parameter. - Non è possibile trovare il gruppo %1. Verificare il nome del gruppo inserito e i parametri LDAP dei gruppi. + Fixed base DN + Fixed base DN - Enter computer name - Inserire il nome del computer + e.g. dc=example,dc=org + e.g. dc=example,dc=org - computer objects - oggetti computer + Discover base DN by naming context + Discover base DN by naming context - Enter computer DN - Inserisci il DN del computer + e.g. namingContexts or defaultNamingContext + e.g. namingContexts or defaultNamingContext - Please enter the DN of a computer whose MAC address to query: - Inserisci il DN di un computer il cui indirizzo MAC e' da ricercare + Environment settings + Impostazioni ambiente - computer MAC addresses - indirizzi MAC computer + Object trees + Alberatura oggetti - users - utenti + Computer tree + Alberatura Pc - user groups - gruppi di utenti + e.g. OU=Groups + e.g. OU=Groups - computer groups - gruppi computer + User tree + Alberatura utenti - Please enter a user login name whose group memberships to query: - Si prega di inserire un nome utente di accesso di appartenenza al gruppo da interrogare: + e.g. OU=Users + e.g. OU=Users - groups of user - gruppi di utenti + e.g. OU=Computers + e.g. OU=Computers - User not found - Utente non trovato + Group tree + Alberatura gruppi - groups of computer - gruppi di computer + Perform recursive search operations in object trees + Ricerca anche nelle sottocartelle - Computer not found - Computer non trovato + Object attributes + Attributi degli oggetti - Enter computer IP address - Inserisci indirizzo IP del computer + e.g. hwAddress + e.g. hwAddress - Please enter a computer IP address which to resolve to an computer object: - Si prega di inserire un indirizzo IP del computer da risolvere a un oggetto computer: + e.g. member or memberUid + Per esempio membro o membroUid - computers - computer + e.g. dNSHostName + Per esempio dNSHostName - LDAP %1 test failed - Test %1 LDAP fallito + Computer MAC address attribute + Attributo dell'indirizzo MAC del computer - LDAP %1 test successful - Test %1 LDAP completato con successo + Group member attribute + Attributo del gruppo del membro - The %1 has been queried successfully and %2 entries were found. - Il %1 e' stato interrogato con successo e sono state trovate %2 voci. + e.g. uid or sAMAccountName + Per esempio uid o sAMAccountName + + + Advanced settings + Impostazioni avanzate + + + Optional object filters + Filtro per oggetti opzionale + + + Filter for user groups + Filtro per gruppo utenti + + + Filter for users + Filtro Users + + + Filter for computer groups + Filtro Gruppo computer + + + Group member identification + Identificazione membro del gruppo + + + Distinguished name (Samba/AD) + Nome distinto (Samba/AD) + + + List all groups of a user + Visualizza i gruppi a cui appartiene un User + + + List all groups of a computer + Visualizza i gruppi a cui appartiene un computer + + + Get computer object by IP address + Identifica il computer mediante indirizzo IP + + + Enter username + Inserire il nome utente + + + Please enter a user login name (wildcards allowed) which to query: + Inserire un nome utente di login (caratteri speciali ammessi) per il quale effettuare la query + + + Enter group name + Inserire il nome del gruppo + + + Please enter a group name whose members to query: + Inserire il nome di un gruppo in cui ricercare i membri + + + Enter computer name + Inserire il nome del computer - %1 %2 have been queried successfully: - -%3 - %1 %2 sono stati interrogati con successo: - -%3 + Enter computer DN + Inserisci il DN del computer - LDAP filter test failed - Test filtro LDAP falllito + Please enter the DN of a computer whose MAC address to query: + Inserisci il DN di un computer il cui indirizzo MAC e' da ricercare - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 - Impossibile interrogare qualsiasi %1 usando il filtro configurato. Si prega di verificare il filtro LPAP per %1. - -%2 + Please enter a user login name whose group memberships to query: + Si prega di inserire un nome utente di accesso di appartenenza al gruppo da interrogare: - LDAP filter test successful - Test filtro LDAP completato con successo + Enter computer IP address + Inserisci indirizzo IP del computer - %1 %2 have been queried successfully using the configured filter. - %1 %2 sono stati interrogati con successo usando il filtro configurato. + Please enter a computer IP address which to resolve to an computer object: + Si prega di inserire un indirizzo IP del computer da risolvere a un oggetto computer: (only if different from group tree) @@ -2164,10 +2806,6 @@ The public key is used on client computers to authenticate incoming connection r Computer group tree Albero gruppo computer - - computer group tree - albero gruppo computer - Filter for computers Filtra per computer @@ -2248,40 +2886,10 @@ The public key is used on client computers to authenticate incoming connection r e.g. (objectClass=container) or (objectClass=organizationalUnit) per esempio (oggetto Classe=container) o (oggetto Classe=Unità Organizzativa) - - Could not query the configured base DN. Please check the base DN parameter. - -%1 - Impossibile interrogare il DN base configurato. Controlla il parametro DN di base.%1 - - - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - Il DN base LDAP è stato interrogato correttamente. Sono state trovate le seguenti voci: %1 - - - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - Impossibile interrogare il DN di base tramite i contesti di denominazione. Controlla il parametro dell'attributo del contesto di denominazione.%1 - Certificate files (*.pem) File di certificato (* .pem) - - Could not connect to the LDAP server. Please check the server parameters. - -%1 - Impossibile connettersi al server LDAP. Controlla i parametri del server.%1 - - - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - Impossibile collegarsi al server LDAP. Controlla i parametri del server e associa le credenziali.%1 - Encryption protocol Protocollo di crittografia @@ -2336,374 +2944,141 @@ The public key is used on client computers to authenticate incoming connection r Please enter the name of a computer location (wildcards allowed): - Si prega di inserire il nome di una posizione del computer (caratteri jolly consentiti): - - - computer locations - posizioni del computer - - - Enter location name - Inserisci il nome della posizione - - - Please enter the name of a location whose entries to query: - Si prega di inserire il nome di una posizione di cui voci per interrogare: - - - location entries - voci di posizione - - - LDAP test failed - Test LDAP fallito - - - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - Impossibile interrogare alcun%1. Controlla i parametro(i)%2 e inserisci il nome di un oggetto esistente. - -3% - - - and - e - - - LDAP test successful - Test LDAP riuscito - - - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - Impossibile interrogare le voci configurate %1. Si prega di controllare il parametro "%2". - -3% - - - Browse - Naviga - - - Test - Prova - - - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - Nomi host memorizzati come nomi di dominio completi (FQDN, ad es. Myhost.example.org) - - - Computer hostname attribute - Attributo hostname del computer - - - Please enter a computer hostname to query: - Inserire un nome host del computer da interrogare: - - - Invalid hostname - Hostname non valido - - - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Hai configurato i nomi host dei computer da memorizzare come nomi di dominio completi (FQDN), ma hai inserito un nome host senza dominio. - - - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - Hai configurato i nomi host dei computer da memorizzare come semplici nomi host senza un nome di dominio, ma hai inserito un nome host con una parte del nome di dominio. - - - Could not find a user with the name "%1". Please check the username or the user tree parameter. - Impossibile trovare un utente con il nome "%1". Si prega di controllare il nome utente o il parametro dell'albero utente. - - - Enter hostname - Inserisci il nome host - - - Please enter a computer hostname whose group memberships to query: - Immettere un nome host del computer di cui si desidera eseguire la ricerca per appartenenza al gruppo: - - - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - Impossibile trovare un computer con il nome host "%1". Si prega di controllare il nome host o il parametro dell'albero del computer. - - - Hostname lookup failed - Ricerca del nome host fallita - - - Could not lookup hostname for IP address %1. Please check your DNS server settings. - Impossibile cercare il nome host per l'indirizzo IP%1. Si prega di verificare le impostazioni del server DNS. - - - User login name attribute - Attributo del nome di accesso dell'utente - - - Configured attribute for user login name or computer hostname (OpenLDAP) - Attributo configurato per il nome di accesso dell'utente o il nome host del computer (OpenLDAP) - - - computer containers - computer containers - - - - LdapPlugin - - Auto-configure the base DN via naming context - Configura automaticamente la base DN tramite contesto di denominazione - - - Query objects from LDAP directory - Interrogare oggetti dalla directory LDAP - - - Show help about command - Mostra aiuto per i comandi - - - Commands for configuring and testing LDAP/AD integration - Comandi per la configurazione ed il testing dell'integrazione LDAP/AD - - - Basic LDAP/AD support for Veyon - Supporto LDAP / AD di base per Veyon - - - %1 (load computers and locations from LDAP/AD) - %1 (carica computer e posizioni da LDAP / AD) - - - %1 (load users and groups from LDAP/AD) - %1 (carica utenti e gruppi da LDAP / AD) - - - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - Specifica un URL LDAP valido seguendo lo schema "ldap [s]: ://[user[:password]@]hostname[:port]" - - - No naming context attribute name given - falling back to configured value. - Nessun nome attributo al contesto di denominazione assegnato, che ricade sul valore configurato. - - - Could not query base DN. Please check your LDAP configuration. - Impossibile interrogare il DN di base. Si prega di verificare la configurazione LDAP. - - - Configuring %1 as base DN and disabling naming context queries. - Configurazione di%1 come DN di base e disabilitazione delle query di contesto dei nomi. - - - - LdapProConfigurationPage - - LDAP Pro - LDAP Pro - - - Instances - Istanze - - - Enter name - Inserisci il nome - - - Please enter a name for the instance (can't be changed later!): - Si prega di inserire un nome per l'istanza (non può essere modificato in seguito!): - - - Remove instance - Rimuovi istanza - - - Do you really want to remove instance "%1"? - Vuoi veramente rimuovere l'istanza "%1"? - - - Configuration for instance "%1" - Configurazione per esempio "%1" - - - - LdapProPlugin - - Professional LDAP/AD integration for Veyon - Integrazione LDAP / AD professionale per Veyon - - - %1 (load computers and locations from LDAP/AD) - %1 (carica computer e posizioni da LDAP / AD) - - - %1 (load users and groups from LDAP/AD) - %1 (carica utenti e gruppi da LDAP / AD) - - - - LicensingConfigurationPage - - Licensing - Licenze - - - Installed licenses - Licenze installate + Si prega di inserire il nome di una posizione del computer (caratteri jolly consentiti): - Add new network range - Aggiungi un nuovo intervallo di rete + Enter location name + Inserisci il nome della posizione - Remove selected network range - Rimuovi l'intervallo di rete selezionato + Please enter the name of a location whose entries to query: + Si prega di inserire il nome di una posizione di cui voci per interrogare: - ID - ID + Browse + Naviga - Feature - Funzionalità + Test + Prova - Valid until - Valido fino a + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Nomi host memorizzati come nomi di dominio completi (FQDN, ad es. Myhost.example.org) - Licensee - Licenziatario + Computer hostname attribute + Attributo hostname del computer - Browse license file - Sfoglia il file di licenza + Please enter a computer hostname to query: + Inserire un nome host del computer da interrogare: - Veyon license files (*.vlf) - File di licenza Veyon (* .vlf) + Enter hostname + Inserisci il nome host - Remove license - Rimuovi la licenza + Please enter a computer hostname whose group memberships to query: + Immettere un nome host del computer di cui si desidera eseguire la ricerca per appartenenza al gruppo: - Do you really want to remove the selected license? - Vuoi veramente rimuovere la licenza selezionata? + User login name attribute + Attributo del nome di accesso dell'utente - <N/A> - <N/A> + Configured attribute for user login name or computer hostname (OpenLDAP) + Attributo configurato per il nome di accesso dell'utente o il nome host del computer (OpenLDAP) - Invalid license file - File di licenza non valido + Directory name + Nome Directory - Could not open the license file for reading! - Impossibile aprire il file di licenza per la lettura! + Query options + Opzioni di query - The selected license file does not contain valid data. - Il file di licenza selezionato non contiene dati validi. + Query nested user groups (supported by AD only) + Interroga gruppi di utenti annidati (supportato solo da AD) - The selected license file could not be verified. - Non è stato possibile verificare il file di licenza selezionato. + Query timeout + Timeout query - The selected license file is not valid for this installation. - Il file di licenza selezionato non è valido per questa installazione. + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. - Il file di licenza selezionato è scaduto. + LDAP + LDAP - The license is already installed. - La licenza è già installata. + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + Utilizza la pagina di configurazione LDAP globale per configurare come recuperare posizioni e computer dal servizio di directory basato su LDAP. + + + LdapPlugin - Information - + Auto-configure the base DN via naming context + Configura automaticamente la base DN tramite contesto di denominazione - Installation ID - + Query objects from LDAP directory + Interrogare oggetti dalla directory LDAP - Addons available for licensing - + Show help about command + Mostra aiuto per i comandi - Addon - + Commands for configuring and testing LDAP/AD integration + Comandi per la configurazione ed il testing dell'integrazione LDAP/AD - - - LicensingPlugin - Show help for specific command - Mostra l'aiuto per un comando specifico + Basic LDAP/AD support for Veyon + Supporto LDAP / AD di base per Veyon - Show all installed licenses - Mostra tutte le licenze installate + %1 (load computers and locations from LDAP/AD) + %1 (carica computer e posizioni da LDAP / AD) - Add license file - Aggiungi il file di licenza + %1 (load users and groups from LDAP/AD) + %1 (carica utenti e gruppi da LDAP / AD) - Remove installed license - Rimuovere la licenza installata + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Specifica un URL LDAP valido seguendo lo schema "ldap [s]: ://[user[:password]@]hostname[:port]" - -USAGE - -%1 add <LICENSE FILE> - - - -USO - - %1 aggiungi <LICENSE FILE> - - + No naming context attribute name given - falling back to configured value. + Nessun nome attributo al contesto di denominazione assegnato, che ricade sul valore configurato. - -USAGE - -%1 remove <LICENSE ID> - - - -USO - -%1 rimuovi <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. + Impossibile interrogare il DN di base. Si prega di verificare la configurazione LDAP. - No certificate found with given ID - Nessun certificato trovato con un dato ID + Configuring %1 as base DN and disabling naming context queries. + Configurazione di%1 come DN di base e disabilitazione delle query di contesto dei nomi. - <N/A> - <N/A> + Test binding to an LDAP server + Test dell'associazione a un server LDAP - Licensing management - Gestione delle licenze + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Il nome utente o la password forniti sono errati. Inserisci credenziali valide o passa a un altro metodo di autenticazione utilizzando Veyon Configurator. - Commands for managing license keys - Comandi per la gestione delle chiavi di licenza + LDAP bind + Bind LDAP @@ -2721,12 +3096,20 @@ USO Autenticazione utente - Session management - + User sessions + Sessioni utente - Display manager users - + Minimum session lifetime before server start + Durata minima della sessione prima dell'avvio del server + + + User login + Login utente + + + Login key sequence + Sequenza di tasti di accesso @@ -2735,10 +3118,6 @@ USO Plugin implementing abstract functions for the Linux platform Plugin che implementa funzioni astratte per la piattaforma Linux. - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2757,14 +3136,14 @@ USO Configuration Configurazione - - Disable balloon tooltips - Disabilita tooltip dei palloncini - Show icons only Mostra solamente le icone + + Disable tooltips + Disabilita i tooltip + MainWindow @@ -2812,10 +3191,6 @@ USO About Qt Informazioni su Qt - - Authentication impossible - Autenticazione impossibile - Configuration not writable Il file di configurazione non è scrivibile @@ -2876,10 +3251,6 @@ USO The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. La configurazione locale backend ha riportato che la configurazione non e' salvabile! Si prega di eseguire il configuratore %1 con privilegi maggiori. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - Nessun file di chiave di autenticazione e' stato trovato o i correnti sono antiquati. Si prega di creare un nuovi file di chiave usandi il Configuratore %1. In alternativa, imposta l'autenticazione di accesso usando il Configuratore %1. Altrimenti non sarai in grado ad accedere ai computer usando %1. - Access denied Accesso negato @@ -2912,10 +3283,6 @@ USO Search users and computers Cerca utenti e computer - - Adjust optimal size - Sistema dimensione ottimale - Align computers to grid Allinea i computer alla griglia @@ -2960,6 +3327,50 @@ USO Locations && computers Posizioni && computers + + Authentication + Autenticazione + + + Adjust size of computer icons automatically + Regola automaticamente la dimensione delle icone del computer + + + Slideshow + Presentazione + + + Spotlight + Spotlight + + + Veyon Master + Veyon Master + + + Locations & computers + Posizioni e computers + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + Utilizza la disposizione personalizzata del computer. + +Tieni premuto per caricare la disposizione da un file o salvare la disposizione corrente in un file. + + + Only show computers with logged on users + Mostra solo computer con utenti connessi + + + Load computer positions + Carica le posizioni del computer + + + Save computer positions + Salva le posizioni del computer + MasterConfigurationPage @@ -2967,10 +3378,6 @@ USO Directories Cartelle - - ... - ... - User configuration Configurazione utente @@ -3055,6 +3462,10 @@ USO Only user name Solo il nome utente + + Only last part of user name + + Only computer name Solo il nome del computer @@ -3103,171 +3514,181 @@ USO Automatically select current location Seleziona automaticamente la posizione corrente - - Automatically adjust computer thumbnail size - Regola automaticamente le dimensioni della miniatura del computer - Automatically open computer select panel Apri automaticamente il pannello di selezione del computer - - - MonitoringMode - Monitoring - Monitoraggio + Use modern user interface (experimental) + Usa l'interfaccia utente moderna (sperimentale) - Builtin monitoring mode - Modalita' di monitoraggio integrata + Thumbnail spacing + Spaziatura delle miniature - This mode allows you to monitor all computers at one or more locations. - Questa modalità consente di monitorare tutti i computer in una o più posizioni. + px + px - - - NetworkDiscoveryConfigurationPage - Network discovery - Individuazione della rete + Hide local session + Nascondi sessione locale - Mode - Modalità + Auto + Automatico - Scan network ranges - Scansione intervalli di rete + Thumbnail aspect ratio + Proporzioni delle miniature - e.g. 192.168.1.0/24 - per esempio: 192.168.1.0/24 + Automatically adjust computer icon size + Regola automaticamente la dimensione dell'icona del computer - Scan all subnets of computer - Analizza tutte le subnet del computer + Open feature windows on the same screen as the main window + Apri le finestre delle funzioni sulla stessa schermata della finestra principale - Scan custom subnet - Scansione subnet personalizzata + Configuration templates + Modelli di configurazione - Scan sessions on local computer - Scansione delle sessioni sul computer locale + Image quality in monitoring mode + Qualità dell'immagine in modalità di monitoraggio - Test - Prova + Highest + Più alto - Network ranges - Gamme di rete + High + Alta - Add new group - Aggiungi nuovo gruppo + Medium + Media - Remove selected group - Rimuovi il gruppo selezionato + Low + Bassa - Groups - Gruppi + Lowest + Minima - First address - Primo indirizzo + Remote access image quality + Qualità dell'immagine per l'accesso remoto - Last address - Ultimo indirizzo + Advanced + Avanzato - Add new network range - Aggiungi un nuovo intervallo di rete + Computer name source + Origine del nome del computer - Remove selected network range - Rimuovi l'intervallo di rete selezionato + Default + Predefinito - Parallel scans - Scansioni parallele + Host address + Indirizzo dell'host - Scan timeout - Scansione terminata + Session client address + Indirizzo del client di sessione - ms - ms + Session client name + Nome del cliente di sessione - Session scan limit - Limite di scansione di sessione + Session host name + Nome host della sessione - Options - Opzioni + Session metadata + Metadati di sessione - Reverse lookup discovered IP addresses to host names - La ricerca inversa ha scoperto gli indirizzi IP nei nomi host + Full name of user + Nome completo dell'utente - New location - Nuova posizione + User login name + Nome completo dell'utente + + + Computer UID role + Ruolo UID del computer + + + Session meta data hash + Hash dei metadati della sessione - - - NetworkDiscoveryDirectory - Scanning... - Scansione... + Always expand all locations + Espandi sempre tutte le posizioni - Discovered computers - Computers trovati + Image quality + Qualità dell'immagine - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command - Mostra l'aiuto per un comando specifico + Monitoring + Monitoraggio - Scan a subnet - Scansione di una sotto rete + Builtin monitoring mode + Modalita' di monitoraggio integrata - -USAGE - -%1 scan [<SUBNET>] - - - -USO - - %1 scansione[<SUBNET>] - - + This mode allows you to monitor all computers at one or more locations. + Questa modalità consente di monitorare tutti i computer in una o più posizioni. + + + Query application version of the server + Interroga la versione dell'applicazione del server + + + Query active features + Interroga le funzionalità attive + + + Query properties of remotely available screens + Interroga le proprietà delle schermate disponibili in remoto + + + + NestedNetworkObjectDirectory + + All directories + Tutte le directory + + + NetworkObjectDirectoryConfigurationPage - Network object directory which automatically discovers computers in the network - Directory dell'oggetto di rete che rileva automaticamente i computer nella rete + Update interval: + Intervallo di aggiornamento: - Network discovery (scan network for Veyon clients) - Ricerca della rete (rete di scansione per i client Veyon) + seconds + secondi + + + NetworkObjectDirectoryConfigurationPageTab - Commands for managing the network discovery directory - Comandi per la gestione della directory di ricerca della rete + Enabled + Abilitato @@ -3281,7 +3702,7 @@ USO OpenWebsiteDialog Open website - Collegamento ad un sito internet + Apri sito web e.g. Veyon @@ -3301,34 +3722,46 @@ USO Name: - Nome: + Nome + + + Website name + Nome del sito web - PasswordDialog + PluginCommands - Username - Nome Utente + List names of all installed plugins + Elenca i nomi di tutti i plugin installati - Password - Password + Show table with details of all installed plugins + Mostra la tabella con i dettagli di tutti i plugin installati - Veyon Logon - Logon Veyon + Name + Nome - Authentication error - Errore di autenticazione + Description + Descrizione - Logon failed with given username and password. Please try again! - Logon fallito con le credenziali fornite. Riprova! + Version + Versione - Please enter your username and password in order to access computers. - Inserisci il tuo username e password per accedere ai computer + UID + UID + + + Plugin-related CLI operations + Operazioni CLI relative al plug-in + + + Commands for managing plugins + Comandi per la gestione dei plugin @@ -3373,10 +3806,6 @@ USO Do you really want to reboot the selected computers? Vuoi veramente riavviare i computer selezionati? - - Do you really want to power down the selected computer? - Vuoi veramente spegnere il computer selezionato? - Power on a computer via Wake-on-LAN (WOL) Accendi un computer tramite Wake-on-LAN (WOL) @@ -3429,6 +3858,18 @@ Please save your work and close all programs. Si prega di salvare il lavoro e chiudere tutti i programmi. + + Do you really want to reboot <b>ALL</b> computers? + Vuoi davvero riavviare<b>TUTTI</b> i computer? + + + Do you really want to power down <b>ALL</b> computers? + Vuoi davvero spegnere <b>TUTTI</b> i computer? + + + Do you really want to power down the selected computers? + Vuoi davvero spegnere i computer selezionati? + PowerDownTimeInputDialog @@ -3475,20 +3916,35 @@ Si prega di salvare il lavoro e chiudere tutti i programmi. Remote view or control a computer Vista o controllo remoto di un computer - - Please enter the hostname or IP address of the computer to access: - Inserisci l'hostname o l'indirizzo IP del computer al quale vuoi accedere: - Show help about command Mostra aiuto per i comandi + + Exchange clipboard contents + Scambia il contenuto degli appunti + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + Nessun computer è stato selezionato, quindi puoi inserire un nome host o un indirizzo IP di un computer per l'accesso manuale: + + + + RemoteAccessPage + + Remote access: %1 + Accesso remoto: %1 + RemoteAccessWidget %1 - %2 Remote Access - %1 - %2 Accesso remoto + %1 -%2 Accesso remoto + + + %1 - %2 - %3 Remote Access + %1 - %2 - %3 Accesso Remoto @@ -3545,74 +4001,29 @@ Si prega di salvare il lavoro e chiudere tutti i programmi. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - Connessione con %1 - Connected. - Connesso. - - - Screenshot - Screenshot - - - Exit - Uscita - - - - Routing - - Control internet access by modifying routing table - Controlla l'accesso a Internet modificando la tabella di routing - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - Rimuovi percorsi predefiniti per bloccare l'accesso a Internet - - - Add custom route to block internet - Aggiungi un percorso personalizzato per bloccare Internet - - - Destination - Destinazione - - - Gateway - Gateway - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - Inserisci i programmi o i comandi da eseguire nei computer selezionati. Puoi separare programmi/comandi multipli andando a capo. + Connesso. - Run programs - Esegui programmi + Screenshot + Screenshot - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - es. "C:\Program Files\VideoLAN\VLC\vlc.exe" + Exit + Uscita - Name: - Nome + Connecting... + Connessione in corso... - Remember and add to program menu - Ricorda e aggiungi al menu del programma + Select screen + Seleziona lo schermo - e.g. VLC - per esempio, VLC + All screens + Tutti gli schermi @@ -3623,7 +4034,7 @@ Si prega di salvare il lavoro e chiudere tutti i programmi. Unlock - Sbloccca + Sblocca Lock screen and input devices of a computer @@ -3633,6 +4044,18 @@ Si prega di salvare il lavoro e chiudere tutti i programmi. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. Per richiamare la completa attenzione di tutti gli utenti, puoi bloccare i loro computer utilizzando questo pulsante. In questo modo tutti i dispositivi di input saranno bloccati e gli schermi saranno colorati di nero. + + Lock input devices + Blocca i dispositivi di input + + + Unlock input devices + Sblocca i dispositivi di input + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + Per recuperare la totale attenzione di tutti gli utenti, puoi bloccare i loro computer utilizzando questo pulsante. In questa modalità tutti i dispositivi di input sono bloccati mentre il desktop è ancora visibile. + Screenshot @@ -3648,6 +4071,10 @@ Si prega di salvare il lavoro e chiudere tutti i programmi. Screenshot Screenshot + + Could not open screenshot file %1 for writing. + Impossibile aprire il file screenshot %1 per la scrittura. + ScreenshotFeaturePlugin @@ -3672,6 +4099,13 @@ Si prega di salvare il lavoro e chiudere tutti i programmi. Effettua screenshot dei computer e salvali in locale. + + ScreenshotManagementPage + + Screenshots + Catture dello schermo + + ScreenshotManagementPanel @@ -3702,6 +4136,45 @@ Si prega di salvare il lavoro e chiudere tutti i programmi. Delete Elimina + + Screenshot + Screenshot + + + Do you really want to delete all selected screenshots? + Vuoi davvero eliminare tutti gli screenshot selezionati? + + + + ServerAccessControlManager + + Requested authentication method not available + Metodo di autenticazione richiesto non disponibile + + + Access allowed by rule "%1" + Accesso consentito dalla regola "%1" + + + Access denied by rule "%1" + Accesso negato dalla regola "%1" + + + No rule allowed access + Nessuna regola ha consentito l'accesso + + + Accessing user not member of an authorized user group + L'utente che accede non è membro di un gruppo di utenti autorizzati + + + User has denied access + L'utente ha rifiutato l'accesso + + + User confirmed access + L'utente ha confermato l'accesso + ServiceConfigurationPage @@ -3733,14 +4206,6 @@ Si prega di salvare il lavoro e chiudere tutti i programmi. State: Stato: - - Network - Rete - - - Demo server port - Porta per la modalità Presentazione - Enable firewall exception Abilita le eccezioni del firewall @@ -3749,10 +4214,6 @@ Si prega di salvare il lavoro e chiudere tutti i programmi. Allow connections from localhost only Consenti connessioni solo da questo computer 'localhost' - - Internal VNC server port - Porta interna server VNC - VNC server Server VNC @@ -3773,14 +4234,6 @@ Si prega di salvare il lavoro e chiudere tutti i programmi. Running In esecuzione - - Feature manager port - Porta manager funzionalita' - - - Primary service port - Porta servizio primario - Enabling this option will make the service launch a server process for every interactive session on a computer. Typically this is required to support terminal servers. @@ -3791,51 +4244,131 @@ Typically this is required to support terminal servers. Mostra notifica sulla connessione remota - Multi session mode (for terminal and remote desktop servers) - + Show notification when an unauthorized access is blocked + Mostra notifica quando viene bloccato un accesso non autorizzato - Show notification when an unauthorized access is blocked - + Maximum session count + Numero massimo di sessioni - - - ServiceControl - Starting service %1 - Avvio del servizio%1 + Network port numbers + Numeri di porta di rete - Stopping service %1 - Arresto del servizio%1 + Veyon server + Server Veyon - Registering service %1 - Registrazione del servizio%1 + Internal VNC server + Server VNC interno - Unregistering service %1 - Servizio di annullamento della registrazione%1 + Feature manager + Manager delle funzionalità - Service control - Controllo del servizio + Demo server + Server per la modalità Presentazione + + + Miscellaneous network settings + Impostazioni di rete varie + + + Session mode + Modalità sessione + + + Local session mode (single server instance for primary local session) + Modalità sessione locale (singola istanza del server per la sessione locale primaria) + + + Active session mode (single server instance for active local or remote session) + Modalità sessione attiva (istanza server singola per sessione attiva locale o remota) + + + Multi session mode (distinct server instance for each local and remote desktop session) + Modalità multisessione (istanza del server distinta per ogni sessione desktop locale e remota) + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + Abilita questa opzione se deve essere avviata una singola istanza di Veyon Server per la sessione attualmente attiva, indipendentemente dal fatto che sia locale o remota. + + + Miscellaneous settings + Impostazioni varie + + + Disable clipboard synchronization + Disabilita la sincronizzazione degli appunti + + + Session metadata + Metadati di sessione + + + Content + Contenuto + + + None + Nessuna + + + Value of an environment variable + Valore di una variabile d'ambiente + + + Value of a registry key + Valore di una chiave di registro + + + Environment variable name: + Nome della variabile d'ambiente: + + + Registry key name: + Nome della chiave di registro: + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + Facoltativamente, inserisci un'espressione regolare con un'acquisizione per estrarre una parte del nome del computer e utilizzarla come nome visualizzato per il computer. + +Esempio: [^-]*-(PC[0-9]*) - ServiceControlPlugin + ServiceControl - Service is running - Servizio in esecuzione + Service control + Controllo del servizio - Service is not running - Servizio non in esecuzione + Starting %1 + Avvio %1 - Configure and control Veyon service - Configura e controlla il servizio Veyon + Stopping %1 + Arresto %1 + + + Restarting %1 + Riavvio %1 + + + Registering %1 + Registrazione di %1 + + + Unregistering %1 + Disregistrazione di %1 + + + ServiceControlCommands Register Veyon Service Registra Servizio Veyon @@ -3860,13 +4393,25 @@ Typically this is required to support terminal servers. Query status of Veyon Service Stato del query del Servizio Veyon + + Service is running + Servizio in esecuzione + + + Service is not running + Servizio non in esecuzione + + + Configure and control Veyon service + Configura e controlla il servizio Veyon + Commands for configuring and controlling Veyon Service Comandi per configurare e controllare il Servizio Veyon - ShellCommandLinePlugin + ShellCommands Run command file Esegui il file di comando @@ -3876,14 +4421,101 @@ Typically this is required to support terminal servers. Il file "%1" non esiste! - Interactive shell and script execution for Veyon Control - Esecuzione interattiva di shell e script per controllo Veyon + Interactive shell and script execution for Veyon CLI + Shell interattiva ed esecuzione di script per Veyon CLI Commands for shell functionalities Comandi per le funzionalità della shell + + SlideshowPanel + + Previous + Precedente + + + Start/pause + Avvia/pausa + + + Next + Prossimo + + + Duration: + Durata: + + + View in separate window + Visualizzazione in finestra separata + + + %1 Master – Slideshow + %1 Master – Presentazione + + + + SpotlightPanel + + Add selected computers + Aggiungi computer selezionati + + + Remove selected computers + Rimuovi i computer selezionati + + + Update computers in realtime + Aggiorna i computer in tempo reale + + + Spotlight + Spotlight + + + Please select at least one computer to add. + Seleziona almeno un computer da aggiungere. + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + Aggiungi computer facendo clic con il pulsante centrale del mouse o facendo clic sul primo pulsante in basso. +Il secondo pulsante rimuove il computer selezionato o l'ultimo. + + + + StartAppDialog + + Start application + Avvia applicazione + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + Immettere le applicazioni da avviare sui computer selezionati. È possibile separare più applicazioni per riga. + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + es. "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + Ricorda e aggiungi al menu dell'applicazione + + + Application name + Nome dell'applicazione + + + Name: + Nome + + + e.g. VLC + per esempio, VLC + + SystemTrayIcon @@ -3906,11 +4538,11 @@ Typically this is required to support terminal servers. TestingCommandLinePlugin Test internal Veyon components and functions - + Testare componenti e funzioni interni di Veyon Commands for testing internal components and functions of Veyon - + Testare componenti e funzioni interne di Veyon @@ -3920,8 +4552,8 @@ Typically this is required to support terminal servers. Invia un messaggio di testo - Use the field below to type your message which will be sent to all selected users. - Utilizza il campo qui sotto per scrivere il messaggio che vuoi inviare agli utenti selezionati. + Please enter your message which send to all selected users. + Inserisci il messaggio che verrà inviato a tutti gli utenti selezionati. @@ -3969,23 +4601,39 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer Abilita motore di duplicazione Desktop su versioni di Windows 8 e successive + + Maximum CPU usage + Utilizzo massimo della CPU + - UserConfig + UserLoginDialog - No write access - Nessun accesso in scrittura + User login + Login utente - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - Impossibile salvare le tue impostazioni personali. Controlla il percorso file di configurazione utente utilizzando il Configuratore %1 + Please enter a username and password for automatic login on all computers. + Inserisci un nome utente e una password per l'accesso automatico su tutti i computer. + + + Username + Nome Utente + + + Password + Password - UserSessionControl + UserSessionControlPlugin - User session control - Controllo sessione utente + Log in + Log in + + + Click this button to log in a specific user on all computers. + Fare clic su questo pulsante per accedere a un utente specifico su tutti i computer. Log off @@ -4003,6 +4651,14 @@ Typically this is required to support terminal servers. Do you really want to log off the selected users? Vuoi veramente far fare logout agli utenti selezionati? + + User session control + Controllo sessione utente + + + Do you really want to log off <b>ALL</b> users? + Vuoi davvero disconnettere <b>TUTTI</b> gli utenti? + VeyonCore @@ -4054,10 +4710,6 @@ Typically this is required to support terminal servers. ERROR ERRORE - - licensed for - concesso in licenza per - USAGE USO @@ -4074,19 +4726,31 @@ Typically this is required to support terminal servers. WARNING ATTENZIONE + + Authentication test + Test di autenticazione + + + Screen %1 + Schermo %1 + - VeyonServiceControl + VeyonMaster - Veyon Service - Servizio Veyon + No write access + Nessun accesso in scrittura + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Impossibile salvare le tue impostazioni personali. Controlla il percorso file di configurazione utente utilizzando il Configuratore %1 - VncView + VeyonServiceControl - Establishing connection to %1 ... - Connessione a %1 ... + Veyon Service + Servizio Veyon @@ -4134,6 +4798,30 @@ Typically this is required to support terminal servers. Use alternative user authentication mechanism Utilizzare un meccanismo di autenticazione utente alternativo + + User login + Login utente + + + Input start delay + Ritardo inizio ingresso + + + Simulated key presses interval + Simulato l'intervallo di pressioni dei tasti + + + Confirm legal notice (message displayed before user logs in) + Conferma avviso legale (messaggio visualizzato prima dell'accesso dell'utente) + + + Use input device interception driver + Usa il driver di intercettazione del dispositivo di input + + + Use custom power scheme with disabled power button + Utilizza lo schema di alimentazione personalizzato con il pulsante di accensione disabilitato + WindowsPlatformPlugin @@ -4142,8 +4830,8 @@ Typically this is required to support terminal servers. Plugin che implementa funzioni astratte per la piattaforma Windows - Plugin implementing specific functions for the Windows platform - + Internal display + Schermo interno @@ -4152,30 +4840,34 @@ Typically this is required to support terminal servers. The service "%1" is already installed. Il servizio "%1" è già installato. - - The service "%1" could not be installed. - Il servizio "%1" non può essere installato. - The service "%1" has been installed successfully. Il servizio "%1" è stato installato correttamente. - - The service "%1" could not be uninstalled. - Il servizio "%1" non può essere disinstallato. - The service "%1" has been uninstalled successfully. Il servizio "%1" è stato disinstallato correttamente. - - The start type of service "%1" could not be changed. - Non è stato possibile modificare il tipo di avvio del servizio "%1". - Service "%1" could not be found. Il servizio "%1" non è stato trovato. + + The service "%1" could not be installed (error %2). + Il servizio "%1" non può essere installato (errore %2). + + + Could not change the failure actions config for service "%1" (error %2). + Impossibile modificare la configurazione delle azioni di errore per il servizio "%1" (errore %2). + + + The service "%1" could not be uninstalled (error %2). + Impossibile disinstallare il servizio "%1" (errore %2). + + + The start type of service "%1" could not be changed (error %2). + Impossibile modificare il tipo di avvio del servizio "%1" (errore %2). + X11VncConfigurationWidget diff --git a/translations/ja.ts b/translations/veyon_ja.ts similarity index 52% rename from translations/ja.ts rename to translations/veyon_ja.ts index e170388b7..eebc5cb1e 100644 --- a/translations/ja.ts +++ b/translations/veyon_ja.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -15,139 +15,136 @@ About Veyon - + Veyonについて Contributors - + 貢献者 Version: - + バージョン: Website: - + ウェブサイト: Current language not translated yet (or native English). If you're interested in translating Veyon into your local or another language or want to improve an existing translation, please contact a Veyon developer! - + 現在の言語(または現地の英語)は翻訳されていません。 + +この言語への翻訳や既存の翻訳の改善に興味がある方はVeyonの開発者に連絡してください。 About %1 %2 - + %1 %2について Support Veyon project with a donation - + 寄付してVeyonプロジェクトを支援する AccessControlPage Computer access control - + コンピューターアクセスコントロール Grant access to every authenticated user (default) - + すべての認証されたユーザーにアクセスを許可(デフォルト) Test - + テスト Process access control rules - + アクセスコントロールのルールを処理 User groups authorized for computer access - + コンピューターへのアクセスを許可されたユーザーグループ Please add the groups whose members should be authorized to access computers in your Veyon network. - + あなたのVeyonネットワーク上のコンピューターにアクセスすることを許可するメンバーのグループを追加してください。 Authorized user groups - + 認証されたユーザーグループ All groups すべてのグループ - - ... - ... - Access control rules - + アクセスコントロールルール Add access control rule - + アクセスコントロールルールを追加 Remove access control rule - + アクセスコントロールルールを削除 Move selected rule down - + 選択したルールを下げる Move selected rule up - + 選択したルールを上げる Edit selected rule - + 選択したルールを編集 Enter username - + ユーザー名を入力 Please enter a user login name whose access permissions to test: - + アクセス権限をテストするユーザー名を入力してください: Access allowed - + アクセス許可 The specified user is allowed to access computers with this configuration. - + このユーザーはこの設定でコンピューターにアクセス許可されています。 Access denied - + アクセス拒否 The specified user is not allowed to access computers with this configuration. - + このユーザーは設定によりコンピューターへのアクセスが拒否されました。 Enable usage of domain groups - + ドメイングループの使用を有効にする User groups backend: - - - - Missing user groups backend - + ユーザーグループのバックエンド - No default user groups plugin was found. Please check your installation! - + Restrict access to members of specific user groups + 特定のグループのメンバーのアクセスを制限する + + + AccessControlProvider - Restrict access to members of specific user groups + Provider for access control features @@ -155,7 +152,7 @@ If you're interested in translating Veyon into your local or another langua AccessControlRuleEditDialog Edit access control rule - + アクセスコントロールルールを編集 General @@ -163,102 +160,174 @@ If you're interested in translating Veyon into your local or another langua enter a short name for the rule here - + このルールの短い名前を入力 Rule name: - + ルール名: enter a description for the rule here - + このルールの説明を入力 Rule description: - + ルール説明: - Invert all conditions ("is/has" interpreted as "is/has not") - + Conditions + コンディション - Conditions - + If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. + もし1つ以上のコンディションが有効にされている場合、ルールが有効になるようそれぞれのコンディションを調整する必要があります。もし複数のコンディションを使用したい場合複数のコントロールルールを作ってください。 - is member of group - + Action + 実行 - Accessing computer is localhost - + Allow access + アクセス許可 - Accessing user is logged on user - + Deny access + アクセス拒否 - Accessing user is already connected - + Ask logged on user for permission + ログインしているユーザーに権限を確認 - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. - + None (rule disabled) + なし(ルール無効) - Action + Accessing user + ユーザーにアクセス中 + + + Accessing computer + コンピューターにアクセス中 + + + Always process rule and ignore conditions + 常にルールを有効にし、コンディションを無視する + + + Accessing computer and local computer - Allow access + User being accessed + アクセスされるユーザー + + + is logged in locally + はローカルでログインしています + + + is logged in remotely + はリモートでログインしています + + + No user is logged in locally + ローカルでログインしているユーザーはいません + + + One or multiple users are logged in locally + 一人、または複数のユーザーがローカルでログインしています + + + No user is logged in remotely + リモートでログインしているユーザーはいません + + + One or multiple users are logged in remotely + 一人、または複数のユーザーがリモートでログインしています + + + is located at + の場所 + + + is not located at - Deny access + are located at the same location - Ask logged on user for permission + are not located the same location - None (rule disabled) + is member of group + はグループのメンバーです + + + is not member of group + はグループのメンバーではありません + + + is authenticated via - Accessing user + is not authenticated via - Accessing computer + has one or more groups in common with user being accessed - Local (logged on) user + has no groups in common with user being accessed - Local computer + equals user being accessed - Always process rule and ignore conditions + is different from user being accessed - No user logged on + is already connected + すでに接続されています + + + is not connected + 接続されていません + + + is local computer + ローカルコンピュータです + + + is not local computer + ローカルコンピュータではありません + + + Computer being accessed + コンピューターへのアクセス + + + Session being accessed is a user session - Accessing user has one or more groups in common with local (logged on) user + Session being accessed is a login screen - Accessing computer and local computer are at the same location + Local computer is already being accessed - is located at + Local computer is not yet being accessed @@ -266,182 +335,165 @@ If you're interested in translating Veyon into your local or another langua AccessControlRulesTestDialog Access control rules test - + アクセスコントロールルールのテスト Accessing user: - + アクセス中のユーザー Local computer: - + ローカルコンピューター: Accessing computer: - + アクセス中のコンピューター: Please enter the following user and computer information in order to test the configured ruleset. - + 設定されたルールをテストするために以下のユーザーとコンピューター情報を入力してください。 Local user: - + ローカルユーザー: Connected users: - + 接続されたユーザー: The access in the given scenario is allowed. - + このシナリオでのアクセスが許可されています。 The access in the given scenario is denied. - + このシナリオでのアクセスが拒否されています。 The access in the given scenario needs permission of the logged on user. - + このシナリオでのアクセスにはログインしているユーザーの許可が必要です。 - ERROR: Unknown action - + Test result + テスト結果 - Test result + Authentication method + 認証方式 + + + There is no matching rule with a valid action. The access is therefore denied. - AndroidPlatformConfigurationPage + AuthKeysConfigurationWidget - Android - + Introduction + 紹介 - General - 一般 + Please perform the following steps to set up key file authentication: + キーファイル認証を設定するために以下の手順を追ってください - - - AndroidPlatformPlugin - Plugin implementing specific functions for the Android platform - + 1) Create a key pair on the master computer. + 1.マスターPCで認証キーを作成 - - - AuthKeysConfigurationPage - Authentication keys - + 2) Set an access group whose members should be allowed to access other computers. + 2.他のコンピューターへのアクセスを許可するメンバーのグループを設定 - Introduction - + 3) Export the public key and import it on all client computers with the same name. + 3.パブリックキーをエクスポートし、すべてのクライアントPCに同じ名前でインポートしてください。 + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + 詳細は<a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon管理者マニュアル</a>を確認してください。 Key file directories - + キーファイルの場所: Public key file base directory - + パブリックキーのファイルの場所 Private key file base directory - + プライベートキーのファイルの場所 - ... - ... + Available authentication keys + 使用可能な認証キー - Available authentication keys - + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + 1つの認証キーのペアは、プライベートキーとパブリックキーの2つの暗号キーで構成されています。 +プライベートキーを使用すると、マスターコンピューターのユーザーがクライアントPCにアクセスすることができます。 +許可されたユーザーのみがプライベートキーを読む権限があるようにしてください。 +パブリックキーはクライアントPCが他からのアクセス要求を認証するために使用します。 Create key pair - + キーを作成 Delete key - + キーを削除 Import key - + キーをインポート Export key - + キーをエクスポート Set access group - + アクセスグループを設定 Key files (*.pem) - + キーファイル(拡張子.pem) Authentication key name - + 認証キーの名前 Please enter the name of the user group or role for which to create an authentication key pair: - + 認証キーを作るユーザーグループかルールの名前を入力してください: Do you really want to delete authentication key "%1/%2"? - + 認証キー"%1/%2"を削除して良いですか? Please select a key to delete! - - - - Please enter the name of the user group or role for which to import the authentication key: - + 削除するキーを選択してください! Please select a key to export! - + エクスポートするキーを選択してください! Please select a user group which to grant access to key "%1": - + 認証キー:"%1"にアクセス許可するユーザーグループを選択してください: Please select a key which to set the access group for! - - - - Please perform the following steps to set up key file authentication: - - - - 1) Create a key pair on the master computer. - - - - 2) Set an access group whose members should be allowed to access other computers. - - - - 3) Export the public key and import it on all client computers with the same name. - - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - + アクセスグループに設定するキーを選択してください! - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. @@ -449,230 +501,246 @@ The public key is used on client computers to authenticate incoming connection r AuthKeysManager Please check your permissions. - + 権限を確認してください。 Key name contains invalid characters! - + キーの名前に使えない文字が入っています! Invalid key type specified! Please specify "%1" or "%2". - + 無効なキータイプが指定されました。"%1" か "%2"を指定してください。 Specified key does not exist! Please use the "list" command to list all installed keys. - + 指定したキーが見つかりませんでした。“list”コマンドを使用してキーをインストールしてください。 One or more key files already exist! Please delete them using the "delete" command. - + 1つ以上のキーが既に存在しています。“delete”コマンドを使用して削除してください。 Creating new key pair for "%1" - + "%1"に新しいキーペアを作成 Failed to create public or private key! - + パブリックキーかプライベートキーの作成に失敗しました! Newly created key pair has been saved to "%1" and "%2". - + 新しく作成されたキーは"%1" と "%2"に保存されました。 Could not remove key file "%1"! - + "%1"のキーファイルを削除できませんでした! Could not remove key file directory "%1"! - + "%1"キーの保存場所を削除できませんでした。 Failed to create directory for output file. - + 書き出しファイル用の保存場所の作成に失敗しました。 File "%1" already exists. - + ファイル "%1" が既に存在します。 Failed to write output file. - + 書き出しに失敗しました。 Key "%1/%2" has been exported to "%3" successfully. - + キー"%1/%2"を"%3"に書き出しました。 Failed read input file. - + ファイルの読み込みに失敗しました。 File "%1" does not contain a valid private key! - + ファイル( "%1")に有効なプライベートキーがありません。 File "%1" does not contain a valid public key! - + ファイル( "%1")に有効なパブリックキーがありません。 Failed to create directory for key file. - + キーファイル用のディレクトリーの作成に失敗しました。 Failed to write key file "%1". - + キーファイル"%1"の書き込みに失敗しました。 Failed to set permissions for key file "%1"! - + キーファイル"%1へのアクセス権限の設定に失敗しました。 Key "%1/%2" has been imported successfully. Please check file permissions of "%3" in order to prevent unauthorized accesses. - + キー"%1/%2"のインポートに成功しました。許可されていないアクセスを防ぐため、"%3"へのアクセス権限を確認してください。 Failed to convert private key to public key - + プライベートキーからパブリックキーへの変換に失敗しました。 Failed to create directory for private key file "%1". - + プライベートキーファイル"%1"のディレクトリーの作成に失敗しました。 Failed to save private key in file "%1"! - + "%1"へのプライベートキーの保存に失敗しました。 Failed to set permissions for private key file "%1"! - + プライベートキー"%1"へのアクセス権限の設定に失敗しました。 Failed to create directory for public key file "%1". - + パブリックキーのファイル"%1"のディレクトリーの作成に失敗しました。 Failed to save public key in file "%1"! - + "%1"のファイルへのパブリックキーの保存に失敗しました。 Failed to set permissions for public key file "%1"! - + パブリックキー"%1"へのアクセス権限の設定に失敗しました。 Failed to set owner of key file "%1" to "%2". - + キーファイル"%1" から "%2"への所有者の設定に失敗しました。 Failed to set permissions for key file "%1". - + キーファイル"%1"へのアクセス権限の設定に失敗しました。 Key "%1" is now accessible by user group "%2". - + キー"%1"はユーザーグループ"%2"によってアクセス可能になりました。 <N/A> - + <N/A> Failed to read key file. - + キーファイルの読み込みに失敗しました。 AuthKeysPlugin Create new authentication key pair - + 新しい認証キーキーペアの作成 Delete authentication key - + 認証キーを削除 List authentication keys - + 認証キーリスト Import public or private key - + パブリックまたはプライベートキーのインポート Export public or private key - + パブリックまたはプライベートキーのエクスポート Extract public key from existing private key - + 既存のプライベートキーからパブリックキーを作成 Set user group allowed to access a key - + ユーザーグループをキーにアクセス可能にする KEY - + キー ACCESS GROUP - + アクセスグループ This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. - + このコマンドはファイルのアクセス権限を、ユーザーグループ<ACCESS GROUP>がアクセスできるよう、<KEY>に設定します。 NAME - + 名前 FILE - + ファイル This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - + このコマンドは認証キー<KEY>を<FILE>にエクスポートします。<FILE>が指定されていない場合、<KEY>の名前とタイプから新しい名前が作成されます。 This command imports the authentication key <KEY> from <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - + このコマンドは認証キー<KEY>を<FILE>からインポートします。<FILE>が指定されていない場合、<KEY>の名前とタイプから新しい名前が作成されます。 This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - + このコマンドは設定されたキーディレクトリーにあるすべての有効な認証キーを一覧にします。"%1"が指定されていれば、キーの詳細が表で表示されます。キーにアクセス権限が無いなどキーにアクセスできなかった場合、いくつかの詳細が表示されない場合があります。 - Please specify the command to display help for! - - - - TYPE - + TYPE + タイプ PAIR ID - - - - Command line support for managing authentication keys - + ペアID Commands for managing authentication keys - + 認証キーを管理するコマンド This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. - + このコマンドは<NAME>という名前で認証キーペアを作成し、設定されたキーの保存ディレクトリーに保存されます。このパラメーターは文字だけを含む名前である必要があります。 This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. - + このコマンドは認証キー<KEY>を設定されたーディレクトリーから削除します。一度削除したキーは復元できないことに注意してください。 This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. - + このコマンドはプライベートキー<KEY>からパブリックキーを作成し、対応するパブリックキーとして保存します。別のマスターPCを設定する際はプライベートキーを転送すると便利です。パブリックキーが作成されます。 + + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + 認証キーファイルが正常にこのコンピューターに設定されていません。新しい認証キーファイルを作成するか、Veyon Configuratorを使って別の認証方法に切り替えてください。 + + + Key file authentication + キーファイル認証 + + + Key file + キーファイル + + + Please specify the key name (e.g. "teacher/public") as the first argument. + 第一引数にキー名(例:"teacher/public")を指定してください。 + + + Please specify the command to display help for. + ヘルプを表示するコマンドを指定してください。 + + + The specified command does not exist or no help is available for it. + 指定されたコマンドが存在しないか、そのコマンドに対するヘルプがありません。 @@ -687,18 +755,161 @@ The public key is used on client computers to authenticate incoming connection r Access group - + アクセスグループ Pair ID + ペアID + + + + AuthLdapConfigurationWidget + + General + 一般 + + + Username to bind DN mapping: + bindDNにマッピングするユーザー名: + + + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + 例:%username%@DOMAIN または cn=%username%,ou=users,dc=example,dc=org + + + + AuthLdapDialog + + Veyon Logon + Veyonログオン + + + Please enter your domain/LDAP username and password in order to access computers. + コンピューターにアクセスするためには、ドメイン/LDAPのユーザー名とパスワードを入力してください。 + + + Username + ユーザー名 + + + Password + パスワード + + + Authentication error + 認証エラー + + + Logon failed with given username and password. Please try again! + 入力したユーザー名とパスワードでログインに失敗しました。再試行してください! + + + + AuthLogonDialog + + Veyon Logon + Veyonログオン + + + Please enter your username and password in order to access computers. + アクセスするにはユーザー名とパスワードを入力してください。 + + + Username + ユーザー名 + + + Password + パスワード + + + Authentication error + 認証エラー + + + Logon failed with given username and password. Please try again! + 入力したユーザー名とパスワードでログインに失敗しました。再試行してください! + + + + AuthLogonPlugin + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + 入力されたユーザー名とパスワードが異なります。有効な資格情報を入力するか、Veyon Configuratorを使って別の認証方法に切り替えてください。 + + + Logon authentication + ログオン認証 + + + Logon + ログオン + + + + AuthSimpleDialog + + Veyon Logon + Veyonログオン + + + Please enter the Veyon password: + Veyonのパスワードを入力してください: + + + Authentication error + 認証エラー + + + Logon failed with given password. Please try again! + ログインに失敗しました。リトライしてください! + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + 入力されたユーザー名とパスワードが異なります。ただしいパスワードを入力するか、Veyon Configuratorを使って別の認証方法に切り替えてください。 + + + Simple password authentication + パスワード認証 + + + Simple password + + AuthenticationPage + + Authentication is set up properly on this computer. + このコンピューターでは認証が正しく設定されています。 + + + + AuthenticationPageTab + + Enabled + 有効 + + + Test + テスト + + + + BuiltinDirectoryConfiguration + + Builtin directory + ビルトインディクショナリー + + BuiltinDirectoryConfigurationPage Computers - + コンピューター Name @@ -706,7 +917,7 @@ The public key is used on client computers to authenticate incoming connection r Host address/IP - + ホストアドレス/IP MAC address @@ -714,62 +925,62 @@ The public key is used on client computers to authenticate incoming connection r Add new computer - + 新しいコンピューターを追加 Remove selected computer - + 選択したコンピューターを削除 New computer - + 新しいコンピューター Builtin directory - - - - Locations & computers - + ビルトインディクショナリー Locations - + 場所 Add new location - + 新しい場所を追加 Remove selected location - + 選択した場所を削除 - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - + New location + 新しい場所 - New location - + Directory name + ディレクトリ名 + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + CSVファイルのインポートは、コマンドライン・インターフェースで可能です。詳しくは、<a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">オンラインドキュメント</a>をご覧ください。 BuiltinDirectoryPlugin Show help for specific command - + 指定したコマンドのヘルプを表示 Import objects from given file - + ファイルからオブジェクトを追加 Export objects to given file - + ファイルへオブジェクトをエクスポート Invalid type specified. Valid values are "%1" or "%2". - + 無効なタイプが指定されました。有効な値は"%1" か "%2"です。 Type @@ -781,7 +992,7 @@ The public key is used on client computers to authenticate incoming connection r Host address - + ホストアドレス MAC address @@ -789,210 +1000,218 @@ The public key is used on client computers to authenticate incoming connection r Specified object not found. - + 指定したオブジェクトが見つかりませんでした。 File "%1" does not exist! - + ファイル"%1"が存在しません! Can't open file "%1" for reading! - + "%1"の読み込みに失敗 Unknown argument "%1". - + 不明な因数"%1" Computer "%1" (host address: "%2" MAC address: "%3") - + コンピューター"%1"(ホストアドレス:"%2" MACアドレス:"%3") Unclassified object "%1" with ID "%2" - + 未分類のオブジェクト"%1"、ID"%2" None - + なし Computer - + コンピューター Root - + ルート Invalid - + 無効 Error while parsing line %1. - + "%1"の解析中にエラーが発生しました。 Network object directory which stores objects in local configuration - + ローカル設定でオブジェクトを保管するネットワークオブジェクトの保存先 Commands for managing the builtin network object directory - + ビルトインのネットワークオブジェクト保存先を管理するためのコマンド No format string or regular expression specified! - + ストリングや一般の表現が指定されていません。 Can't open file "%1" for writing! - + "%1"に書き込むことができませんでした。 No format string specified! - + フォーマットが指定されていません! Object UUID - + オブジェクトUUID Parent UUID - + ペアレントUUID Add a location or computer - + 場所かコンピューターを追加 Clear all locations and computers - + 全ての場所とコンピューターを削除 Dump all or individual locations and computers - + 全てまたは個別の場所かコンピューターを削除 List all locations and computers - + 全てのコンピューターと場所の一覧 Remove a location or computer - + 場所かコンピューターを削除 Location "%1" - + 場所"%1" Builtin (computers and locations in local configuration) - + ビルトイン(ローカル設定内のコンピューターと場所) Location - + 場所 FILE - + ファイル LOCATION - + 場所 FORMAT-STRING-WITH-PLACEHOLDERS - + プレースホルダ付きフォーマット文字列 REGULAR-EXPRESSION-WITH-PLACEHOLDER - + プレースホルダ付き正規表現 Imports objects from the specified text file using the given format string or regular expression containing one or multiple placeholders. Valid placeholders are: %1 - + 指定されたフォーマット文字列か、1つまたは複数のプレースホルダーを含む正規表現を使用して、指定されたテキストファイルからオブジェクトをインポートします。 有効なプレースホルダーは次のとおりです:%1 Import simple CSV file to a single room - + CSVファイルを1つの部屋にインポート Import CSV file with location name in first column - + 最初の列に場所の名前があるCSVファイルをインポート Import text file with with key/value pairs using regular expressions - + 正規表現を使ってキーと値のペアを持つテキストファイルをインポート Import arbitrarily formatted data - + 任意のフォーマットのデータをインポート Exports objects to the specified text file using the given format string containing one or multiple placeholders. Valid placeholders are: %1 - + 1つまたは複数のプレースホルダーを含む指定のフォーマット文字列を使用して、オブジェクトを指定のテキストファイルにエクスポートします。有効なプレースホルダーは次のとおりです。%1 Export all objects to a CSV file - + すべてのオブジェクトをCSVファイルにエクスポート Export all computers in a specific location to a CSV file - + 特定の場所にあるすべてのコンピューターをCSVファイルにエクスポート TYPE - + タイプ NAME - + 名前 PARENT - + Adds an object where %1 can be one of "%2" or "%3". %4 can be specified by name or UUID. - + %1が「%2」または「%3」のいずれかになり得るオブジェクトを追加します。 %4は、名前またはUUIDで指定できます。 Add a room - + 部屋を追加 Add a computer to room %1 - + 新しいコンピューターを部屋"%1"に追加 OBJECT - + オブジェクト Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. - + 指定されたオブジェクトをディレクトリから削除します。%1 は名前または UUID で指定できます。場所を削除すると、関連するすべてのコンピュータも削除されます。 Remove a computer by name - + 名前を指定してコンピューターを削除 Remove an object by UUID - + UUIDを指定してオブジェクトを削除 "Room 01" - + "ルーム01" "Computer 01" - + "コンピューター01" HOST ADDRESS - + ホストアドレス MAC ADDRESS + MACアドレス + + + The specified command does not exist or no help is available for it. + 指定されたコマンドが存在しないか、そのコマンドに対するヘルプがありません。 + + + Location "%1" not found. @@ -1000,60 +1219,84 @@ The public key is used on client computers to authenticate incoming connection r BuiltinUltraVncServer Builtin VNC server (UltraVNC) - + ビルトインVNCサーバー(UltraVNC) BuiltinX11VncServer Builtin VNC server (x11vnc) - + ビルトインVNCサーバー(x11vnc) ComputerControlListModel - - Host/IP address: %1 - - Active features: %1 - + アクティブな機能: %1 Online and connected - + オンラインで接続 Establishing connection - + 接続の確立 Computer offline or switched off - + コンピューターがオフライン、または電源OFF - Service unreachable or not running - + Authentication failed or access denied + 認証失敗、またはアクセス拒否 - Authentication failed or access denied + Disconnected + 切断 + + + No user logged on + ログインユーザーなし + + + Logged on user: %1 + ログインしたユーザー: %1 + + + Location: %1 + 場所: %1 + + + [no user] + [ユーザー無し] + + + Veyon Server unreachable or not running + Veyonサーバーに到達できないか動作していない + + + Name: %1 + 名前: %1 + + + Hostname: %1 - Disconnected + unknown - No user logged on + IP address: %1 - Logged on user: %1 + Hostname could not be resolved - Location: %1 + No features active @@ -1069,160 +1312,210 @@ The public key is used on client computers to authenticate incoming connection r Remote access - + リモートアクセス User "%1" at host "%2" is now accessing this computer. - + 現在ホスト"%2"のユーザー"%1"がこのコンピューターにアクセスしています。 User "%1" at host "%2" attempted to access this computer but could not authenticate successfully. - + ホスト"%2"のユーザー"%1"がこのコンピューターにアクセスしようとしましたが、正常に認証できませんでした。 Access control error - + アクセスコントロールエラー User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. - + ホスト"%2"のユーザー"%1"がこのコンピューターにアクセスしようとしましたが、アクセスコントロール設定によりブロックされました。 + + + Active connections: + アクティブな接続: + + + + ComputerGroupSelector + + Group %1 + グループ %1 ComputerManager User - + ユーザー Missing network object directory plugin - + ネットワークオブジェクトプラグインが見つかりません No default network object directory plugin was found. Please check your installation or configure a different network object directory backend via %1 Configurator. - + 既定のネットワーク オブジェクト ディレクトリ プラグインが見つかりませんでした。インストールを確認するか、%1 Configurator で別のネットワーク オブジェクト ディレクトリ バックエンドを構成してください。 Location detection failed - + 場所の検出に失敗 Computer name;Hostname;User - + コンピュータ名;ホスト名;ユーザー Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + このコンピューターの場所を特定できませんでした。これは、システム構成に問題があることを示しています。 代わりに、すべての場所がコンピューターの選択パネルに表示されます。 + + + Logged in since + + + + %1 days + + + + 1 day - ComputerSelectPanel + ComputerMonitoring - Computer management - + Computers + コンピューター + + + Search users and computers + ユーザーとコンピューターを検索 + + + Select all + すべて選択 + + Unselect all + すべて選択解除 + + + Add to group + グループに追加 + + + Remove from group + グループから削除 + + + + ComputerSelectPanel Computer search - + コンピューターを検索 Add location - + 場所を追加 Save computer/user list - + コンピューター/ユーザーのリストを保存 Select output filename - + 出力先ファイル名を選択 CSV files (*.csv) - + CSVファイル(*.csv) File error - + ファイルエラー Could not write the computer and users list to %1! Please check the file access permissions. + コンピュータとユーザのリストを %1 に書き込めません! ファイルのアクセス許可を確認してください。 + + + Search computers - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. - + Clear system-wide Veyon configuration + システム全体のVeyon設定をクリア - Please specify a valid filename for the configuration export. - + List all configuration keys and values + すべての設定のキーと値の一覧を表示 - Please specify a valid key. - + Import configuration from given file + 設定をファイルからインポート - Specified key does not exist in current configuration! - + Export configuration to given file + 設定をファイルにエクスポート - Please specify a valid value. + Read and output configuration value for given key - Configure Veyon at command line + Write given value to given configuration key - Output file is not writable! + Unset (remove) given configuration key - Output directory is not writable! - + Upgrade and save configuration of program and plugins + プログラムおよびプラグインのアップグレードと設定の保存 - Configuration file is not readable! - + Please specify an existing configuration file to import. + インポートする既存の設定ファイルを指定してください。 - Clear system-wide Veyon configuration - + Configuration file is not readable! + 設定ファイルは読み込む事ができません! - List all configuration keys and values + Please specify a valid filename for the configuration export. - Import configuration from given file - + Output file is not writable! + 出力ファイルは書き込む事ができません! - Export configuration to given file - + Output directory is not writable! + 出力先ディレクトリは書き込むことができません! - Read and output configuration value for given key - + Please specify a valid key. + 有効なキーを指定してください。 - Write given value to given configuration key - + Specified key does not exist in current configuration! + 指定されたキーは現在の構成に存在しません! - Unset (remove) given configuration key - + Please specify a valid value. + 有効な値を指定してください。 - Commands for managing the configuration of Veyon - + Configure Veyon at command line + コマンドラインからVeynを設定する - Upgrade and save configuration of program and plugins - + Commands for managing the configuration of Veyon + Veyonの設定を管理するためのコマンド @@ -1247,6 +1540,10 @@ The public key is used on client computers to authenticate incoming connection r Could not apply platform-specific configuration settings. + + Could not configure the firewall configuration for the %1 Service. + + DemoClient @@ -1259,54 +1556,54 @@ The public key is used on client computers to authenticate incoming connection r DemoConfigurationPage Demo server - デモサーバー + デモサーバ Tunables - + チューニング ms - + ms Key frame interval - + キーフレーム間隔 Memory limit - - - - Use multithreading (experimental) - + メモリ制限 MB - + MB Update interval - + 更新間隔 s - + s Slow down thumbnail updates while demo is running + デモの実行中はサムネイルの更新を遅くする + + + Bandwidth limit + + + + MB/s DemoFeaturePlugin - - Fullscreen demo - フルスクリーンデモ - Stop demo - + デモ停止 Window demo @@ -1317,16 +1614,60 @@ The public key is used on client computers to authenticate incoming connection r - Demo server - デモサーバー + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + このモードでは、このPCの画面が全てのコンピューターの画面にウィンドウとして表示されます。全てのユーザーは必要に応じて他のウィンドウに切り替えることができます。 - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - + Demo + デモ - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - + Share your screen or allow a user to share his screen with other users. + 自分の画面、または選択したユーザーの画面を他のユーザーに共有します。 + + + Full screen demo + フルスクリーンデモ + + + Share your own screen in fullscreen mode + 自分のスクリーンをフルスクリーンモードで共有 + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + このモードでは、全てのコンピューターの入力を停止し、このコンピューターの画面をフルスクリーンで全てのPCに表示します。 + + + Share your own screen in a window + 自分のスクリーンをウィンドウモードで共有 + + + Share selected user's screen in fullscreen mode + 選択したユーザーのスクリーンをフルスクリーンモードで共有 + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + このモードでは、全てのコンピューターの入力を停止し、選択したユーザーの画面をフルスクリーンで全てのPCに表示します。 + + + Share selected user's screen in a window + 選択したユーザーの画面をウィンドウで共有 + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + このモードでは、選択したユーザーの画面が全てのコンピューターの画面にウィンドウとして表示されます。全てのユーザーは必要に応じて他のウィンドウに切り替えることができます。 + + + Please select a user screen to share. + 共有するユーザーの画面を選択してください。 + + + Please select only one user screen to share. + 共有するユーザーの画面を一つだけ選択してください。 + + + All screens + 全ての画面 @@ -1355,86 +1696,90 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - Programs & websites - + Name + 名前 - Predefined programs - + Path + パス - Name - 名前 + Predefined websites + 定義済みWebサイト - Path - + Remove selected website + 選択したWebサイトを削除 - Add new program - + URL + URL - Remove selected program - + New website + 新しいWebサイト - Predefined websites - + Applications & websites + アプリケーションとWebサイト - Remove selected website - + Predefined applications + 定義済みアプリケーション - URL - + Add new application + 新しいアプリケーションを追加 - New program - + Remove selected application + 選択したアプリケーションを削除 - New website - + Add new website + 新しいWebサイトを追加 + + + New application + 新しいアプリケーション DesktopServicesFeaturePlugin - - Run program - - Open website - + Webサイトを開く Click this button to open a website on all computers. - + 全てのコンピューターでWebサイトを開きます。 - Start programs and services in user desktop - + Open website "%1" + Webサイト "%1" を開く - Click this button to run a program on all computers. - + Custom website + カスタムWebサイト - Run program "%1" - + Start application + アプリケーションを開始 - Custom program - + Click this button to start an application on all computers. + 全てのコンピューターでアプリケーションを起動します - Open website "%1" - + Start application "%1" + アプリケーション "%1" を開始 - Custom website + Custom application + カスタムアプリケーション + + + Start apps and open websites in user sessions @@ -1442,11 +1787,12 @@ The public key is used on client computers to authenticate incoming connection r DocumentationFigureCreator Teacher - + 先生 Room %1 - + ルーム %1 + Please complete all tasks within the next 5 minutes. @@ -1454,11 +1800,11 @@ The public key is used on client computers to authenticate incoming connection r Custom website - + カスタムWebサイト Open file manager - + ファイルマネージャーを開く Start learning tool @@ -1466,563 +1812,580 @@ The public key is used on client computers to authenticate incoming connection r Play tutorial video - - - - Custom program - + チュートリアルビデオを再生 Handout - + 配布資料 Texts to read + テキストを読み上げる + + + generic-student-user + + Custom application + カスタムアプリケーション + ExternalVncServer External VNC server - + 外部VNCサーバー ExternalVncServerConfigurationWidget External VNC server configuration - + 外部VNCサーバー構成 Port: - + ポート: Password: - + パスワード: - FeatureControl + FeatureCommands - Feature control + List names of all available features - - - FileTransferController - Could not open file "%1" for reading! Please check your permissions! + Show table with details of all available features - - - FileTransferDialog - File transfer + Start a feature on a remote host - Options + Stop a feature on a remote host - Transfer only - + Please specify the command to display help for. + ヘルプを表示するコマンドを指定してください。 - Transfer and open file(s) with associated program + Displays a list with the names of all available features. - Transfer and open destination folder + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. - Files - + HOST ADDRESS + ホストアドレス - Start + FEATURE - Overwrite existing files + ARGUMENTS - - - FileTransferPlugin - File transfer + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information - Click this button to transfer files from your computer to all computers. + Lock the screen - Select one or more files to transfer - + Display a text message + テキストメッセージを表示する - Transfer files to remote computer + Test message - Received file "%1". + Start an application - Could not receive file "%1" as it already exists. + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. - Could not receive file "%1" as it could not be opened for writing! + Unlock the screen - - - GeneralConfigurationPage - User interface - ユーザーインターフェイス + The specified command does not exist or no help is available for it. + 指定されたコマンドが存在しないか、そのコマンドに対するヘルプがありません。 - Language: - + Name + 名前 - Use system language setting - + Description + 説明 - Veyon - + Master + マスター - Logging + Service + サービス + + + Worker - Log file directory - ログファイルのディレクトリ + UID + UID - ... - ... + Plugin + - Log level - ログレベル + Invalid feature name or UID specified + - Nothing - 無し + Error parsing the JSON-encoded arguments: %1 + - Only critical messages - 致命的なエラーのみ + Failed to initialize credentials + - Errors and critical messages - エラーと致命的なエラー + Could not establish a connection to host %1 + - Warnings and errors - 警告とエラー - - - Information, warnings and errors + Failed to send feature control message to host %1 - Debug messages and everything else + Feature-related CLI operations - Limit log file size + Commands for controlling features + + + FileTransferConfigurationPage - Clear all log files - + File transfer + ファイル転送 - Log to standard error output - + Directories + ディレクトリ - Network object directory - + Destination directory + 宛先ディレクトリ - Backend: - + Default source directory + デフォルトのソースディレクトリ - Update interval: - + Options + オプション - %1 service - + Remember last source directory + 最後に使用したソースディレクトリを記憶する - The %1 service needs to be stopped temporarily in order to remove the log files. Continue? - + Create destination directory if it does not exist + 宛先ディレクトリが存在しない場合は作成する + + + FileTransferController - Log files cleared + Could not open file "%1" for reading! Please check your permissions! + + + FileTransferDialog - All log files were cleared successfully. - + File transfer + ファイル転送 - Error - + Options + オプション - Could not remove all log files. - + Transfer only + 転送のみ - MB - + Transfer and open file(s) with associated program + 転送後、割り当てられているプログラムでファイルを開く - Rotate log files - + Transfer and open destination folder + 転送後、宛先フォルダを開く - x - + Files + ファイル - seconds - + Start + 開始 - Write to logging system of operating system - + Overwrite existing files + 既存のファイルを上書き + + + FileTransferFileDialog - Authentication - 認証 + Select one or more files to transfer + 一つ、または複数の配布ファイルを選択 + + + FileTransferPlugin - Method: - + File transfer + ファイル転送 - Logon authentication - + Click this button to transfer files from your computer to all computers. + 全てのコンピューターへファイルを転送します。 - Key file authentication - + Select one or more files to transfer + 一つ、または複数の配布ファイルを選択 - Test - + Transfer files to remote computer + コンピューターへファイルを転送 - Authentication is set up properly on this computer. + Received file "%1". - Authentication keys are not set up properly on this computer. + Could not receive file "%1" as it already exists. - Authentication test + Could not receive file "%1" as it could not be opened for writing! - InternetAccessControlConfigurationPage + GeneralConfigurationPage - Internet access control - + User interface + ユーザーインターフェイス - Backend: - + Language: + 言語: - General settings - + Use system language setting + システムの言語設定を使用する - Backend settings - + Veyon + Veyon - - - InternetAccessControlPlugin - Block access to the internet - + Logging + ロギング - Allow access to the internet - + Log file directory + ログファイルのディレクトリ - Show help about command - + Log level + ログレベル - Block internet - + Nothing + 無し - Click this button to block access to the internet. - + Only critical messages + 致命的なエラーのみ - Unblock internet - + Errors and critical messages + エラーと致命的なエラー - Click this button to allow access to the internet. - + Warnings and errors + 警告とエラー - Control access to the internet - + Information, warnings and errors + 情報、警告とエラー - Commands for controlling access to the internet + Debug messages and everything else - - - LdapBrowseDialog - Browse LDAP - + Limit log file size + ログファイルサイズ上限 - - - LdapClient - LDAP error description: %1 - + Clear all log files + すべてのログファイルをクリア - - - LdapConfigurationPage - Basic settings - + Log to standard error output + ログを標準エラー出力に出力する - General - 一般 + %1 service + %1 サービス - LDAP server and port - + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + ログファイルを削除するには %1 サービスを一時的に停止する必要があります。続行しますか? - Bind DN + Log files cleared - Bind password + All log files were cleared successfully. - Anonymous bind - + Error + エラー - Use bind credentials + Could not remove all log files. - Base DN - + MB + MB - Fixed base DN - + Rotate log files + ログファイルをローテーション - e.g. dc=example,dc=org + x - Discover base DN by naming context - + Write to logging system of operating system + OSのシステムログに書き込む - e.g. namingContexts or defaultNamingContext + TLS configuration - Environment settings + Use certificate authority for TLS connections - Object trees + CA certificate file - Computer tree - + ... + ... - e.g. OU=Groups + Host certificate file - User tree + Host private key file - e.g. OU=Users + Style: - e.g. OU=Computers + Native - Group tree + Color scheme: - Perform recursive search operations in object trees + Light - Object attributes + Dark - e.g. hwAddress - + User groups + ユーザーグループ - e.g. member or memberUid - + Backend: + バックエンド: - e.g. dNSHostName + Include user groups from domain - Computer MAC address attribute - + Missing user groups backend + ユーザーグループのバックエンドが不明 - Group member attribute + No user groups plugin was found. Please check your installation! + + + HeadlessVncServer - e.g. uid or sAMAccountName + Headless VNC server + + + LdapBrowseDialog - Advanced settings + Browse LDAP + + + LdapClient - Optional object filters + LDAP error description: %1 + + + LdapConfiguration - Filter for user groups - + LDAP connection failed + LDAP接続失敗 - Filter for users + Could not connect to the LDAP server. Please check the server parameters. + +%1 - Filter for computer groups - + LDAP bind failed + LDAPバインド失敗 - Group member identification + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 - Distinguished name (Samba/AD) - + LDAP bind successful + LDAPバインド成功 - List all groups of a user + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - List all groups of a computer + LDAP base DN test failed - Get computer object by IP address + Could not query the configured base DN. Please check the base DN parameter. + +%1 - LDAP connection failed + LDAP base DN test successful - LDAP bind failed + The LDAP base DN has been queried successfully. The following entries were found: + +%1 - LDAP bind successful + LDAP naming context test failed - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 - LDAP base DN test failed + LDAP naming context test successful - LDAP base DN test successful + The LDAP naming context has been queried successfully. The following base DN was found: +%1 - LDAP naming context test failed + user tree - LDAP naming context test successful + User tree - The LDAP naming context has been queried successfully. The following base DN was found: -%1 + group tree - user tree + Group tree - group tree + computer tree - computer tree + Computer tree - Enter username + computer group tree - Please enter a user login name (wildcards allowed) which to query: + Computer group tree @@ -2030,15 +2393,15 @@ The public key is used on client computers to authenticate incoming connection r - Enter group name + User login name attribute - Please enter a group name whose members to query: + group members - group members + Group member attribute @@ -2050,31 +2413,59 @@ The public key is used on client computers to authenticate incoming connection r - Enter computer name + computer objects - computer objects + Computer display name attribute - Enter computer DN + Invalid hostname + 無効なホスト名 + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Please enter the DN of a computer whose MAC address to query: + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + + + + Computer hostname attribute computer MAC addresses + コンピュータのMACアドレス + + + Computer MAC address attribute - users + computer locations + コンピューターの場所 + + + Computer location attribute + + Location name attribute + + + + users + ユーザー + user groups + ユーザーグループ + + + computers @@ -2082,7 +2473,7 @@ The public key is used on client computers to authenticate incoming connection r - Please enter a user login name whose group memberships to query: + computer containers @@ -2093,6 +2484,10 @@ The public key is used on client computers to authenticate incoming connection r User not found + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + + groups of computer @@ -2102,586 +2497,582 @@ The public key is used on client computers to authenticate incoming connection r - Enter computer IP address + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - Please enter a computer IP address which to resolve to an computer object: + Hostname lookup failed - computers + Could not lookup hostname for IP address %1. Please check your DNS server settings. - LDAP %1 test failed + location entries - LDAP %1 test successful + Computer groups filter - The %1 has been queried successfully and %2 entries were found. - + Computer locations identification + コンピューターの場所の識別 - %1 %2 have been queried successfully: - -%3 + Filter for computer groups - LDAP filter test failed + Invalid test value - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 + An empty or invalid value has been supplied for this test. - LDAP filter test successful + LDAP %1 test failed - %1 %2 have been queried successfully using the configured filter. + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 - (only if different from group tree) + LDAP %1 test successful - Computer group tree + The %1 has been queried successfully and %2 entries were found. - computer group tree + LDAP test failed - Filter for computers + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 - e.g. room or computerLab + and - Integration tests + LDAP test successful - Computer groups - + %1 %2 have been queried successfully: + +%3 + %1 %2 が正常にクエリされました: + +%3 - e.g. name or description + LDAP filter test failed - Filter for computer containers + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 - Computer containers or OUs + LDAP filter test successful - Connection security + %1 %2 have been queried successfully using the configured filter. - TLS certificate verification + LDAP directory + + + LdapConfigurationPage - System defaults - + Basic settings + 基本設定 - Never (insecure!) - + General + 一般 - Custom CA certificate file - + LDAP server and port + LDAPサーバとポート - None - + Bind DN + Bind DN - TLS + Bind password - SSL + Anonymous bind - e.g. (objectClass=computer) + Use bind credentials - e.g. (objectClass=group) + Base DN - e.g. (objectClass=person) + Fixed base DN - e.g. (objectClass=room) or (objectClass=computerLab) - + e.g. dc=example,dc=org + 例: dc=example,dc=org - e.g. (objectClass=container) or (objectClass=organizationalUnit) + Discover base DN by naming context - Could not query the configured base DN. Please check the base DN parameter. - -%1 + e.g. namingContexts or defaultNamingContext - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - + Environment settings + 環境設定 - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 + Object trees - Certificate files (*.pem) + Computer tree - Could not connect to the LDAP server. Please check the server parameters. - -%1 - + e.g. OU=Groups + 例:OU=Groups - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 + User tree - Encryption protocol - + e.g. OU=Users + 例:OU=Users - Computer location attribute - + e.g. OU=Computers + 例:OU=Computers - Computer display name attribute + Group tree - Location name attribute + Perform recursive search operations in object trees - e.g. cn or displayName + Object attributes - Computer locations identification + e.g. hwAddress + 例:hwAddress + + + e.g. member or memberUid + 例:member または memberUid + + + e.g. dNSHostName + 例:dNSHostName + + + Computer MAC address attribute - Identify computer locations (e.g. rooms) via: + Group member attribute - Location attribute in computer objects + e.g. uid or sAMAccountName + 例:uid または sAMAccountName + + + Advanced settings + 拡張設定 + + + Optional object filters - List all entries of a location + Filter for user groups - List all locations + Filter for users - Enter computer display name + Filter for computer groups - Please enter a computer display name to query: + Group member identification - Enter computer location name + Distinguished name (Samba/AD) - Please enter the name of a computer location (wildcards allowed): + List all groups of a user - computer locations + List all groups of a computer - Enter location name + Get computer object by IP address - Please enter the name of a location whose entries to query: - + Enter username + ユーザー名を入力 - location entries + Please enter a user login name (wildcards allowed) which to query: - LDAP test failed - + Enter group name + グループ名を入力 - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 + Please enter a group name whose members to query: - and - + Enter computer name + コンピューター名を入力 - LDAP test successful - + Enter computer DN + コンピューターDNを入力 - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 + Please enter the DN of a computer whose MAC address to query: - Browse + Please enter a user login name whose group memberships to query: - Test - + Enter computer IP address + コンピューターのIPアドレスを入力 - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Please enter a computer IP address which to resolve to an computer object: - Computer hostname attribute + (only if different from group tree) - Please enter a computer hostname to query: + Computer group tree - Invalid hostname + Filter for computers - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - + e.g. room or computerLab + 例:room または computerLab - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - + Integration tests + 統合テスト - Could not find a user with the name "%1". Please check the username or the user tree parameter. + Computer groups - Enter hostname - + e.g. name or description + 例:name または description - Please enter a computer hostname whose group memberships to query: + Filter for computer containers - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Computer containers or OUs - Hostname lookup failed - + Connection security + 接続の安全性 - Could not lookup hostname for IP address %1. Please check your DNS server settings. - + TLS certificate verification + TLS証明書の検証 - User login name attribute - + System defaults + システムの標準 - Configured attribute for user login name or computer hostname (OpenLDAP) - + Never (insecure!) + しない(安全ではありません!) - computer containers - + Custom CA certificate file + カスタムCA証明書ファイル - - - LdapPlugin - Auto-configure the base DN via naming context - + None + なし - Query objects from LDAP directory - + TLS + TLS - Show help about command - + SSL + SSL - Commands for configuring and testing LDAP/AD integration + e.g. (objectClass=computer) - Basic LDAP/AD support for Veyon + e.g. (objectClass=group) - %1 (load computers and locations from LDAP/AD) + e.g. (objectClass=person) - %1 (load users and groups from LDAP/AD) + e.g. (objectClass=room) or (objectClass=computerLab) - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + e.g. (objectClass=container) or (objectClass=organizationalUnit) - No naming context attribute name given - falling back to configured value. + Certificate files (*.pem) - Could not query base DN. Please check your LDAP configuration. - + Encryption protocol + 暗号化プロトコル - Configuring %1 as base DN and disabling naming context queries. + Computer location attribute - - - LdapProConfigurationPage - LDAP Pro + Computer display name attribute - Instances + Location name attribute - Enter name + e.g. cn or displayName - Please enter a name for the instance (can't be changed later!): - + Computer locations identification + コンピューターの場所の識別 - Remove instance + Identify computer locations (e.g. rooms) via: - Do you really want to remove instance "%1"? + Location attribute in computer objects - Configuration for instance "%1" + List all entries of a location - - - LdapProPlugin - Professional LDAP/AD integration for Veyon - + List all locations + すべての場所をリスト - %1 (load computers and locations from LDAP/AD) + Enter computer display name - %1 (load users and groups from LDAP/AD) + Please enter a computer display name to query: - - - LicensingConfigurationPage - Licensing + Enter computer location name - Installed licenses + Please enter the name of a computer location (wildcards allowed): - Add new network range - + Enter location name + 場所の名前を入力 - Remove selected network range + Please enter the name of a location whose entries to query: - ID - + Browse + 参照 - Feature - + Test + テスト - Valid until + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - Licensee + Computer hostname attribute - Browse license file + Please enter a computer hostname to query: - Veyon license files (*.vlf) + Enter hostname - Remove license + Please enter a computer hostname whose group memberships to query: - Do you really want to remove the selected license? + User login name attribute - <N/A> + Configured attribute for user login name or computer hostname (OpenLDAP) - Invalid license file - + Directory name + ディレクトリ名 - Could not open the license file for reading! + Query options - The selected license file does not contain valid data. + Query nested user groups (supported by AD only) - The selected license file could not be verified. + Query timeout - The selected license file is not valid for this installation. - + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. + LDAP - The license is already installed. + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + LdapPlugin - Information + Auto-configure the base DN via naming context - Installation ID + Query objects from LDAP directory - Addons available for licensing - + Show help about command + コマンドに関するヘルプを表示する - Addon + Commands for configuring and testing LDAP/AD integration - - - LicensingPlugin - Show help for specific command + Basic LDAP/AD support for Veyon - Show all installed licenses - + %1 (load computers and locations from LDAP/AD) + %1 (LDAP / ADからコンピューターとその場所を読み込む) - Add license file - + %1 (load users and groups from LDAP/AD) + %1 (LDAP/ADからユーザーとグループを読み込む) - Remove installed license + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - -USAGE - -%1 add <LICENSE FILE> - - + No naming context attribute name given - falling back to configured value. - -USAGE - -%1 remove <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. - No certificate found with given ID + Configuring %1 as base DN and disabling naming context queries. - <N/A> + Test binding to an LDAP server - Licensing management - + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + 入力されたユーザー名とパスワードが異なります。有効な資格情報を入力するか、Veyon Configuratorを使って別の認証方法に切り替えてください。 - Commands for managing license keys + LDAP bind @@ -2689,7 +3080,7 @@ USAGE LinuxPlatformConfigurationPage Linux - + Linux Custom PAM service for user authentication @@ -2697,14 +3088,22 @@ USAGE User authentication - + ユーザー認証 + + + User sessions + ユーザーセッション - Session management + Minimum session lifetime before server start - Display manager users + User login + ユーザーログイン + + + Login key sequence @@ -2714,34 +3113,30 @@ USAGE Plugin implementing abstract functions for the Linux platform - - Plugin implementing specific functions for the Linux platform - - LocationDialog Select location - + 場所を選択 enter search filter... - + 検索フィルターを入力... MainToolBar Configuration - + 構成 - Disable balloon tooltips - + Show icons only + アイコンのみ表示 - Show icons only + Disable tooltips @@ -2761,23 +3156,23 @@ USAGE &File - + &ファイル &Help - + &ヘルプ &Quit - + &終了 Ctrl+Q - + Ctrl+Q Ctrl+S - + Ctrl+S L&oad settings from file @@ -2785,15 +3180,11 @@ USAGE Ctrl+O - + Ctrl+O About Qt - - - - Authentication impossible - + Qtについて Configuration not writable @@ -2801,43 +3192,43 @@ USAGE Load settings from file - + 設定をファイルから読み込む Save settings to file - + 設定をファイルに保存する Unsaved settings - + 未保存の設定 There are unsaved settings. Quit anyway? - + 未保存の設定があります。終了しますか? Veyon Configurator - + Veyon構成 Service - + サービス Master - + マスター Access control - + アクセスコントロール About Veyon - + Veyonについて Auto - + 自動 About @@ -2849,19 +3240,15 @@ USAGE JSON files (*.json) - + JSON files (*.json) The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - - Access denied - + アクセス許可 According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. @@ -2869,7 +3256,7 @@ USAGE Screenshots - + スクリーンショット Feature active @@ -2881,23 +3268,19 @@ USAGE Reset configuration - + 構成のリセット Do you really want to reset the local configuration and revert all settings to their defaults? - + ローカル設定をリセットし、すべての設定をデフォルトに戻して良いですか? Search users and computers - - - - Adjust optimal size - + ユーザーとコンピューターを検索 Align computers to grid - + コンピューターをグリッドに揃える %1 Configurator @@ -2905,7 +3288,7 @@ USAGE Insufficient privileges - + 権限が不足 Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. @@ -2913,30 +3296,72 @@ USAGE Only show powered on computers - + 電源ONのコンピューターのみ表示 &Save settings to file - &View - + &View + &表示 + + + &Standard + 標準 + + + &Advanced + 拡張 + + + Use custom computer arrangement + コンピュータの自由配置を使用する + + + Locations && computers + 場所とコンピューター + + + Authentication + 認証 + + + Adjust size of computer icons automatically + コンピューターアイコンのサイズを自動で調整する + + + Slideshow + スライドショー + + + Spotlight + スポットライト + + + Veyon Master + Veyon Master + + + Locations & computers + 場所&コンピューター - &Standard + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. - &Advanced + Only show computers with logged on users - Use custom computer arrangement + Load computer positions - Locations && computers + Save computer positions @@ -2946,57 +3371,53 @@ USAGE Directories ディレクトリ - - ... - ... - User configuration - + ユーザー構成 Feature on computer double click: - + コンピューターをダブルクリックした時の機能: Features - + 機能 All features - + すべての機能 Disabled features - + 無効な機能 Screenshots - + スクリーンショット <no feature> - + 機能指定無し Basic settings - + 基本設定 Behaviour - + 動作 Enforce selected mode for client computers - + クライアントコンピューターに選択したモードを適用する Hide local computer - + ローカルコンピューターを隠す Hide computer filter field - + "コンピューターを検索"の欄を隠す Actions such as rebooting or powering down computers @@ -3008,332 +3429,363 @@ USAGE Background color - + 背景色 Thumbnail update interval - + サムネイル更新間隔 ms - + ms Program start - + 起動設定 Modes and features - + モードと機能 User and computer name - + ユーザー名とコンピューター名 Only user name + ユーザー名のみ + + + Only last part of user name Only computer name - + コンピューター名のみ Computer thumbnail caption - + コンピューターサムネイルの見出し Text color - + 文字色 Sort order - + ソート順 Computer and user name - + コンピューター名とユーザー名 Computer locations - + コンピューターの場所 Show current location only - + 現在の場所のみを表示 Allow adding hidden locations manually - + 非表示の場所を手動で追加することを許可する Hide empty locations - + 空の場所を隠す Show confirmation dialog for potentially unsafe actions - + 安全ではない可能性のあるアクションに対する確認ダイアログを表示する Perform access control - + アクセスコントロールの実行 Automatically select current location - + 自動的に現在の場所を選択する - Automatically adjust computer thumbnail size - + Automatically open computer select panel + 自動的にコンピューター選択パネルを開く - Automatically open computer select panel + Use modern user interface (experimental) - - - MonitoringMode - Monitoring - + Thumbnail spacing + サムネイル間隔 - Builtin monitoring mode - + px + px - This mode allows you to monitor all computers at one or more locations. - + Hide local session + ローカルセッションを隠す - - - NetworkDiscoveryConfigurationPage - Network discovery - + Auto + 自動 - Mode - + Thumbnail aspect ratio + サムネイルアスペクト比 - Scan network ranges - + Automatically adjust computer icon size + 自動的にコンピューターのアイコンサイズを調整する - e.g. 192.168.1.0/24 - + Open feature windows on the same screen as the main window + メインウィンドウと同じ画面で機能ウィンドウを開く - Scan all subnets of computer + Configuration templates - Scan custom subnet + Image quality in monitoring mode - Scan sessions on local computer + Highest - Test + High - Network ranges + Medium - Add new group + Low - Remove selected group + Lowest - Groups + Remote access image quality - First address + Advanced - Last address + Computer name source - Add new network range + Default - Remove selected network range - + Host address + ホストアドレス - Parallel scans + Session client address - Scan timeout + Session client name - ms + Session host name - Session scan limit + Session metadata - Options + Full name of user - Reverse lookup discovered IP addresses to host names + User login name - New location + Computer UID role - - - NetworkDiscoveryDirectory - Scanning... + Session meta data hash - Discovered computers + Always expand all locations + 常にすべてのロケーションを展開する + + + Image quality - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command - + Monitoring + モニタリング - Scan a subnet - + Builtin monitoring mode + 組み込み監視モード - -USAGE - -%1 scan [<SUBNET>] - - - + This mode allows you to monitor all computers at one or more locations. + このモードでは、全てのコンピューターを1つ以上の場所でモニターできるようになります。 - Network object directory which automatically discovers computers in the network - + Query application version of the server + サーバのアプリケーションバージョンを照会する - Network discovery (scan network for Veyon clients) - + Query active features + 有効な機能を照会する + + + Query properties of remotely available screens + リモートで利用可能な画面のプロパティを照会する + + + NestedNetworkObjectDirectory - Commands for managing the network discovery directory + All directories + + NetworkObjectDirectoryConfigurationPage + + Update interval: + 更新間隔: + + + seconds + + + + + NetworkObjectDirectoryConfigurationPageTab + + Enabled + 有効 + + NetworkObjectTreeModel Locations/Computers - + 場所/コンピューター OpenWebsiteDialog Open website - + Webサイトを開く e.g. Veyon - + 例:Veyon Remember and add to website menu - + Webサイトのメニューに追加・記録する e.g. www.veyon.io - + 例:www.veyon.io Please enter the URL of the website to open: - + 開くウェブサイトのURLを入力してください: Name: - + 例: + + + Website name + Webサイト名 - PasswordDialog + PluginCommands - Username - + List names of all installed plugins + インストールされているすべてのプラグインの名前を一覧表示 - Password - + Show table with details of all installed plugins + インストールされているすべてのプラグインの詳細を表で表示 - Veyon Logon - + Name + 名前 - Authentication error - 認証エラー + Description + 説明 - Logon failed with given username and password. Please try again! - + Version + バージョン - Please enter your username and password in order to access computers. - + UID + UID + + + Plugin-related CLI operations + プラグイン関連のCLI操作 + + + Commands for managing plugins + プラグインを管理するためのコマンド PowerControlFeaturePlugin Power on - + 電源オン Click this button to power on all computers. This way you do not have to power on each computer by hand. - + 全てのコンピューターの電源をオンにします。各コンピューターの電源を手動でオンにする必要はありません。 Reboot - + 再起動 Click this button to reboot all computers. - + 全てのコンピューターを再起動します。 Power down - + 電源オフ Click this button to power down all computers. This way you do not have to power down each computer by hand. - + 全てのコンピューターの電源をオフにします。各コンピューターの電源を手動でオフにする必要はありません。 Power on/down or reboot a computer - + 電源オン・オフ・再起動 Confirm reboot @@ -3341,23 +3793,19 @@ USAGE Confirm power down - + パワーダウンを確認 Do you really want to reboot the selected computers? - - - - Do you really want to power down the selected computer? - + 選択したコンピューターを再起動して良いですか? Power on a computer via Wake-on-LAN (WOL) - + Wake-on-LANでコンピュータの電源を入れる MAC ADDRESS - + MACアドレス This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. @@ -3365,7 +3813,7 @@ USAGE Please specify the command to display help for! - + ヘルプを表示するコマンドを指定してください! Invalid MAC address specified! @@ -3377,23 +3825,24 @@ USAGE Power down now - + 今すぐ電源オフ Install updates and power down - + 更新をインストールしてシャットダウン Power down after user confirmation - + ユーザーに確認後にシャットダウン Power down after timeout - + タイムアウト後にシャットダウン The computer was remotely requested to power down. Do you want to power down the computer now? - + このコンピューターは遠隔操作でシャットダウンが要求されました。 +コンピューターをシャットダウンして良いですか? The computer will be powered down in %1 minutes, %2 seconds. @@ -3401,35 +3850,47 @@ USAGE Please save your work and close all programs. + + Do you really want to reboot <b>ALL</b> computers? + 全てのコンピューターを再起動しても良いですか? + + + Do you really want to power down <b>ALL</b> computers? + 全てのコンピューターをシャットダウンしても良いですか? + + + Do you really want to power down the selected computers? + 選択したコンピューターをシャットダウンしても良いですか? + PowerDownTimeInputDialog Power down - + 電源オフ Please specify a timeout for powering down the selected computers: - + 選択されているコンピュータの電源を切るまでのタイムアウト時間を指定してください。 minutes - + seconds - + RemoteAccessFeaturePlugin Remote view - + リモートビュー Open a remote view for a computer without interaction. - + 通知なしにリモートビューを開始 Remote control @@ -3437,22 +3898,33 @@ Please save your work and close all programs. Open a remote control window for a computer. - + リモート操作ウィンドウを開きます Remote access - + リモートアクセス Remote view or control a computer - Please enter the hostname or IP address of the computer to access: + Show help about command + コマンドに関するヘルプを表示する + + + Exchange clipboard contents + + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + RemoteAccessPage - Show help about command + Remote access: %1 @@ -3462,6 +3934,10 @@ Please save your work and close all programs. %1 - %2 Remote Access + + %1 - %2 - %3 Remote Access + + RemoteAccessWidgetToolBar @@ -3487,7 +3963,7 @@ Please save your work and close all programs. Ctrl+Alt+Del - + Ctrl+Alt+Del Ctrl+Esc @@ -3517,161 +3993,178 @@ Please save your work and close all programs. Alt+Ctrl+F1 - - Connecting %1 - - Connected. Screenshot - + スクリーンショット Exit - - - Routing - Control internet access by modifying routing table + Connecting... + + Select screen + + + + All screens + 全ての画面 + - RoutingConfigurationWidget + ScreenLockFeaturePlugin - Remove default routes to block internet access - + Lock + ロック - Add custom route to block internet - + Unlock + ロック解除 - Destination - + Lock screen and input devices of a computer + コンピューターのスクリーンと入力機器をロック - Gateway - + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + ユーザーの注意をひくためには、このボタンを使用して全てのコンピューターの入力をロック・黒画面を表示し、PCをロックできます。 - - - RunProgramDialog - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. + Lock input devices - Run programs + Unlock input devices - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + + Screenshot - Name: + unknown - Remember and add to program menu + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. - e.g. VLC + Screenshot + スクリーンショット + + + Could not open screenshot file %1 for writing. - ScreenLockFeaturePlugin + ScreenshotFeaturePlugin - Lock - + Screenshot + スクリーンショット - Unlock - + Use this function to take a screenshot of selected computers. + 選択しているコンピューターのスクリーンショットを取得します。 - Lock screen and input devices of a computer - + Screenshots taken + スクリーンショット取得 - To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. - + Screenshot of %1 computer have been taken successfully. + %1 台のコンピューターのスクリーンショットを正常に取得しました + + + Take screenshots of computers and save them locally. + コンピューターのスクリーンショットを取得しローカルに保存しました - Screenshot + ScreenshotManagementPage - unknown - + Screenshots + スクリーンショット + + + ScreenshotManagementPanel - Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. - Screenshot - + User: + ユーザー: - - - ScreenshotFeaturePlugin - Screenshot - + Computer: + コンピューター: - Use this function to take a screenshot of selected computers. - + Date: + 日付: - Screenshots taken - + Time: + 時刻: + + + Show + 表示 + + + Delete + 削除 - Screenshot of %1 computer have been taken successfully. - + Screenshot + スクリーンショット - Take screenshots of computers and save them locally. - + Do you really want to delete all selected screenshots? + 選択したスクリーンショットを削除しても良いですか? - ScreenshotManagementPanel + ServerAccessControlManager - All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + Requested authentication method not available - User: + Access allowed by rule "%1" - Computer: + Access denied by rule "%1" - Date: + No rule allowed access - Time: + Accessing user not member of an authorized user group - Show + User has denied access - Delete + User confirmed access @@ -3705,37 +4198,25 @@ Please save your work and close all programs. State: 状態: - - Network - - - - Demo server port - デモサーバーのポート - Enable firewall exception - + ファイアウォールの例外を有効にする Allow connections from localhost only - - - - Internal VNC server port - + localhostからの接続のみ許可 VNC server - + VNCサーバー Plugin: - + プラグイン: Restart %1 Service - + サービス%1を再起動します All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? @@ -3743,112 +4224,194 @@ Please save your work and close all programs. Running - + 実行中 - Feature manager port + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. - Primary service port + Show notification on remote connection + リモート接続時、通知を表示 + + + Show notification when an unauthorized access is blocked + 許可されていないアクセスがブロックされた時、通知を表示 + + + Maximum session count + 最大セッション数 + + + Network port numbers + 通信ポート番号 + + + Veyon server + Veyonサーバ + + + Internal VNC server + 内部VNCサーバ + + + Feature manager + 機能マネージャー + + + Demo server + デモサーバ + + + Miscellaneous network settings + その他のネットワーク設定 + + + Session mode + セッションモード + + + Local session mode (single server instance for primary local session) + ローカルセッションモード(プライマリローカルセッション用の単一サーバーインスタンス) + + + Active session mode (single server instance for active local or remote session) + アクティブセッションモード(アクティブなローカルまたはリモートセッション用の単一サーバーインスタンス) + + + Multi session mode (distinct server instance for each local and remote desktop session) + マルチセッションモード(ローカルおよびリモートデスクトップセッションごとに異なるサーバーインスタンス) + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. + Miscellaneous settings - Show notification on remote connection + Disable clipboard synchronization - Multi session mode (for terminal and remote desktop servers) + Session metadata - Show notification when an unauthorized access is blocked + Content - - - ServiceControl - Starting service %1 + None + なし + + + Value of an environment variable - Stopping service %1 + Value of a registry key - Registering service %1 + Environment variable name: - Unregistering service %1 + Registry key name: - Service control + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) - ServiceControlPlugin + ServiceControl - Service is running + Service control + サービス制御 + + + Starting %1 - Service is not running + Stopping %1 - Configure and control Veyon service + Restarting %1 - Register Veyon Service + Registering %1 - Unregister Veyon Service + Unregistering %1 + + + ServiceControlCommands + + Register Veyon Service + Veyonサービスを登録 + + + Unregister Veyon Service + Veyonサービスの登録を解除 + Start Veyon Service - + Veyonサービスを開始 Stop Veyon Service - + Veyonサービスを停止 Restart Veyon Service - + Veyonサービスを再起動 Query status of Veyon Service + + Service is running + サービス実行中 + + + Service is not running + サービス停止中 + + + Configure and control Veyon service + Veyonサービスの構成と制御 + Commands for configuring and controlling Veyon Service - ShellCommandLinePlugin + ShellCommands Run command file File "%1" does not exist! - + ファイル"%1"が存在しません! - Interactive shell and script execution for Veyon Control + Interactive shell and script execution for Veyon CLI @@ -3856,55 +4419,143 @@ Typically this is required to support terminal servers. + + SlideshowPanel + + Previous + 前へ + + + Start/pause + 開始/一時停止 + + + Next + 次へ + + + Duration: + 期限: + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + 選択したコンピューターを追加 + + + Remove selected computers + 選択したコンピューターを削除 + + + Update computers in realtime + リアルタイムでコンピュータを更新 + + + Spotlight + スポットライト + + + Please select at least one computer to add. + 追加するコンピューターを少なくとも1台は選択してください + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + マウスの中ボタンでクリックするか、下の1番目のボタンをクリックすると、コンピュータが追加されます。 +2番目のボタンは、選択されたコンピュータまたは最後のコンピュータを削除します。 + + + + StartAppDialog + + Start application + アプリケーションを開始 + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + 選択したコンピューターで起動するアプリケーションを入力してください +複数のアプリケーションを行ごとに分けることができます + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + (例)"C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + アプリケーションのメニューに追加・記録する + + + Application name + アプリケーション名 + + + Name: + 例: + + + e.g. VLC + (例) VLC + + SystemTrayIcon System tray icon - + システムトレイアイコン SystemUserGroupsPlugin User groups backend for system user groups - + システムユーザグループのためのユーザグループバックエンド Default (system user groups) - + デフォルト(システムユーザーグループ) TestingCommandLinePlugin Test internal Veyon components and functions - + Veyonの内部コンポーネントや機能のテスト Commands for testing internal components and functions of Veyon - + 内部コンポーネントやVeyonの機能をテストするためのコマンド TextMessageDialog Send text message - + テキストメッセージを送信 - Use the field below to type your message which will be sent to all selected users. - + Please enter your message which send to all selected users. + 選択したすべてのユーザーに送信するメッセージを入力してください。 TextMessageFeaturePlugin Text message - + テキストメッセージ Use this function to send a text message to all users e.g. to assign them new tasks. - + 例えば新しい作業を指示するなど、この機能を使用してすべてのユーザーにテキストメッセージを送信できます Message from teacher @@ -3912,91 +4563,115 @@ Typically this is required to support terminal servers. Send a message to a user - + ユーザーへメッセージを送信 UltraVncConfigurationWidget Enable capturing of layered (semi-transparent) windows - + レイヤー(半透明)ウィンドウのキャプチャを可能にする Poll full screen (leave this enabled per default) - + フルスクリーンでポーリング(デフォルトで有効のまま) Low accuracy (turbo mode) - + 低精度(ターボモード) Builtin UltraVNC server configuration - + ビルトインUltraVNCサーバー構成 Enable multi monitor support - + マルチモニターサポートを有効 Enable Desktop Duplication Engine on Windows 8 and newer - + Windows 8以降でDesktop Duplication Engineを有効化する + + + Maximum CPU usage + CPUの最大使用率 - UserConfig + UserLoginDialog - No write access - + User login + ユーザーログイン - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - + Please enter a username and password for automatic login on all computers. + すべてのコンピュータで自動ログインする為にユーザー名とパスワードを入力してください。 + + + Username + ユーザー名 + + + Password + パスワード - UserSessionControl + UserSessionControlPlugin - User session control - + Log in + ログイン + + + Click this button to log in a specific user on all computers. + 全てのコンピューターに特定のユーザーでログインします。 Log off - + ログオフ Click this button to log off users from all computers. - + 全てのコンピューターをログオフします。 Confirm user logoff - + ユーザーログオフの確認 Do you really want to log off the selected users? - + 選択したユーザーをログオフしても良いですか? + + + User session control + ユーザーセッション制御 + + + Do you really want to log off <b>ALL</b> users? + 全てのユーザーをログオフしても良いですか? VeyonCore [OK] - + [OK] [FAIL] - + [失敗] Invalid command! - + 無効なコマンドです! Available commands: - + 使用可能なコマンド: Invalid arguments given - + 無効な引数が指定されました Not enough arguments given - use "%1 help" for more information @@ -4004,11 +4679,11 @@ Typically this is required to support terminal servers. Unknown result! - + 不明な結果! Available modules: - + 有効なモジュール: No module specified or module not found - available modules are: @@ -4016,63 +4691,71 @@ Typically this is required to support terminal servers. Plugin not licensed - + プラグインはライセンスされていません INFO - + ERROR - - - - licensed for - + エラー USAGE - + 使用法 DESCRIPTION - + 説明 EXAMPLES - + WARNING + 警告 + + + Authentication test + 認証テスト + + + Screen %1 - VeyonServiceControl + VeyonMaster - Veyon Service - + No write access + 書込不可 + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + 個人設定を保存できませんでした! %1 Configuratorを使ってユーザー設定ファイルのパスを確認してください。 - VncView + VeyonServiceControl - Establishing connection to %1 ... - + Veyon Service + Veyon サービス WindowsPlatformConfiguration Could not change the setting for SAS generation by software. Sending Ctrl+Alt+Del via remote control will not work! - + SAS生成の設定をソフトウェアで変更することができませんでした。リモコンでCtrl+Alt+Delを送っても動作しません! WindowsPlatformConfigurationPage Windows - + Windows General @@ -4080,30 +4763,54 @@ Typically this is required to support terminal servers. Enable SAS generation by software (Ctrl+Alt+Del) - + ソフトウェアによるSAS生成を有効にする(Ctrl + Alt + Del) Screen lock - + スクリーンロック Hide taskbar - + タスクバーを隠す Hide start menu - + スタートメニュー隠す Hide desktop - + デスクトップを隠す User authentication - + ユーザー認証 Use alternative user authentication mechanism + 代替のユーザー認証機構を使用する + + + User login + ユーザーログイン + + + Input start delay + 入力開始遅延 + + + Simulated key presses interval + キー押下シミュレート間隔 + + + Confirm legal notice (message displayed before user logs in) + 法的通知の確認(メッセージはユーザーがログインする前に表示されます) + + + Use input device interception driver + 入力デバイス遮断ドライバを使用する + + + Use custom power scheme with disabled power button @@ -4111,11 +4818,11 @@ Typically this is required to support terminal servers. WindowsPlatformPlugin Plugin implementing abstract functions for the Windows platform - + Windows環境用の抽象関数を実装したプラグイン - Plugin implementing specific functions for the Windows platform - + Internal display + 内蔵ディスプレイ @@ -4125,27 +4832,31 @@ Typically this is required to support terminal servers. - The service "%1" could not be installed. + The service "%1" has been installed successfully. - The service "%1" has been installed successfully. + The service "%1" has been uninstalled successfully. - The service "%1" could not be uninstalled. + Service "%1" could not be found. + サービス "%1"が見つかりませんでした。 + + + The service "%1" could not be installed (error %2). - The service "%1" has been uninstalled successfully. + Could not change the failure actions config for service "%1" (error %2). - The start type of service "%1" could not be changed. + The service "%1" could not be uninstalled (error %2). - Service "%1" could not be found. + The start type of service "%1" could not be changed (error %2). @@ -4153,15 +4864,15 @@ Typically this is required to support terminal servers. X11VncConfigurationWidget Builtin x11vnc server configuration - + ビルトインx11vncサーバー構成 Custom x11vnc parameters: - + カスタムx11vncパラメーター: Do not use X Damage extension - + X Damage extensionは使わないでください \ No newline at end of file diff --git a/translations/ko.ts b/translations/veyon_ko.ts similarity index 75% rename from translations/ko.ts rename to translations/veyon_ko.ts index 87641e8d5..9accf1c4f 100644 --- a/translations/ko.ts +++ b/translations/veyon_ko.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -80,10 +80,6 @@ Veyon 번역에 관심이 있거나 번역을 개선하실 의향이 있으신 All groups 모든 그룹 - - ... - ... - Access control rules 접근 제어 규칙 @@ -140,19 +136,18 @@ Veyon 번역에 관심이 있거나 번역을 개선하실 의향이 있으신 User groups backend: 유저그룹 백엔드: - - Missing user groups backend - 유저그룹 백엔드 없음 - - - No default user groups plugin was found. Please check your installation! - 디폴트 유저 그룹 플러그인이 없습니다. 설치상태를 확인하세요! - Restrict access to members of specific user groups 특정 그룹 사용자의 접근 제한 + + AccessControlProvider + + Provider for access control features + + + AccessControlRuleEditDialog @@ -179,30 +174,10 @@ Veyon 번역에 관심이 있거나 번역을 개선하실 의향이 있으신 Rule description: 규칙 설명: - - Invert all conditions ("is/has" interpreted as "is/has not") - 모든 조건 반대로 ("is/has" 는 "is/has not" 로 변경됨) - Conditions 조건 - - is member of group - 는 그룹의 멤버임 - - - Accessing computer is localhost - 연결하는 컴퓨터는 로컬 호스트입니다 - - - Accessing user is logged on user - 접속하는 사용자는 로그온되어 있습니다 - - - Accessing user is already connected - 접속하는 사용자는 이미 연결되어 있습니다 - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. 한개 이상의 조건이 활성화 될 경우 규칙이 적용되려면 각각의 조건이 일치해야 한다 (논리적 AND). 여러개 중에서 하나의 조건만 맞아야 할 경우에는(논리적 OR) 다수의 접근 제어 규칙을 생성하세요 . @@ -236,33 +211,125 @@ Veyon 번역에 관심이 있거나 번역을 개선하실 의향이 있으신 연결하는 컴퓨터 - Local (logged on) user - (로그온된)로컬 사용자 + Always process rule and ignore conditions + 조건 무시하고 항상 규칙 수행 - Local computer - 로컬 컴퓨터 + Accessing computer and local computer + - Always process rule and ignore conditions - 조건 무시하고 항상 규칙 수행 + User being accessed + - No user logged on - 로그온된 사용자 없음 + is logged in locally + + + + is logged in remotely + + + + No user is logged in locally + + + + One or multiple users are logged in locally + - Accessing user has one or more groups in common with local (logged on) user - 연결하는 사용자는 로컬 사용자(로그온됨)와 하나 또는 그이상의 공통 그룹을 갖고 있습니다 + No user is logged in remotely + - Accessing computer and local computer are at the same location - 같은 장소에 있는 다른 컴퓨터와 로컬 컴퓨터에 접근 + One or multiple users are logged in remotely + is located at 에 위치함 + + is not located at + + + + are located at the same location + + + + are not located the same location + + + + is member of group + 는 그룹의 멤버임 + + + is not member of group + + + + is authenticated via + + + + is not authenticated via + + + + has one or more groups in common with user being accessed + + + + has no groups in common with user being accessed + + + + equals user being accessed + + + + is different from user being accessed + + + + is already connected + + + + is not connected + + + + is local computer + + + + is not local computer + + + + Computer being accessed + + + + Session being accessed is a user session + + + + Session being accessed is a login screen + + + + Local computer is already being accessed + + + + Local computer is not yet being accessed + + AccessControlRulesTestDialog @@ -306,42 +373,44 @@ Veyon 번역에 관심이 있거나 번역을 개선하실 의향이 있으신 The access in the given scenario needs permission of the logged on user. 주어진 상황에 대한 접근은 로그온된 사용자의 허가가 필요함. - - ERROR: Unknown action - ERROR: 정의되지 않은 작업 - Test result 시험 결과 - - - AndroidPlatformConfigurationPage - Android + Authentication method - General - 일반사항 + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + 소개 - - - AuthKeysConfigurationPage - Authentication keys - 인증 키 + Please perform the following steps to set up key file authentication: + 키 파일 인증을 설정하기 위해 다음 단계들을 실행하세요: - Introduction - 소개 + 1) Create a key pair on the master computer. + 1) 마스터 컴퓨터에서 키페어를 생성하시오. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) 다른 컴퓨터에 접근을 허용할 멤버가 속한 그룹을 설정하세요. + + + 3) Export the public key and import it on all client computers with the same name. + 3) 공개키를 내보내고 그키를 같은 이름을 가진 모든 클라이언트 컴퓨터에서 읽어들이기. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + 더 자세한 정보는 <a href="https://veyon.readthedocs.io/en/latest/admin/index.html"> Veyon 관리자 매뉴얼을 참조하세요 </a> . Key file directories @@ -355,14 +424,20 @@ Veyon 번역에 관심이 있거나 번역을 개선하실 의향이 있으신 Private key file base directory 개인 키 화일 기본 폴더 - - ... - ... - Available authentication keys 사용 가능한 인증키들 + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + 인증 키는 두 부분으로 구성되어 있습니다, 공개 키 파트와 개인 키 파트. +개인 키를 사용하여 마스터 컴퓨터에서 클라이언트 컴퓨터에 접속할 수 있습니다. +오직 승인된 사용자만 개인 키 화일을 읽을 수 있도록 하는 것이 아주 중요합니다. +공개 키 파트는 클라이언트 컴퓨터에서 사용되며 들어오는 연결 요청이 허가된 것인지 검증하는데 사용됩니다. + Create key pair 키 페어 생성 @@ -403,10 +478,6 @@ Veyon 번역에 관심이 있거나 번역을 개선하실 의향이 있으신 Please select a key to delete! 삭제할 키를 선택하세요 - - Please enter the name of the user group or role for which to import the authentication key: - 접근 키를 불러올 사용자 그룹이나 역할의 이름을 입력하세요: - Please select a key to export! 내보낼 키를 선택하세요! @@ -420,34 +491,10 @@ Veyon 번역에 관심이 있거나 번역을 개선하실 의향이 있으신 이 접근 그룹에 설정할 키를 선택하세요! - Please perform the following steps to set up key file authentication: - 키 파일 인증을 설정하기 위해 다음 단계들을 실행하세요: - - - 1) Create a key pair on the master computer. - 1) 마스터 컴퓨터에서 키페어를 생성하시오. - - - 2) Set an access group whose members should be allowed to access other computers. - 2) 다른 컴퓨터에 접근을 허용할 멤버가 속한 그룹을 설정하세요. - - - 3) Export the public key and import it on all client computers with the same name. - 3) 공개키를 내보내고 그키를 같은 이름을 가진 모든 클라이언트 컴퓨터에서 읽어들이기. - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - 더 자세한 정보는 <a href="https://veyon.readthedocs.io/en/latest/admin/index.html"> Veyon 관리자 매뉴얼을 참조하세요 </a> . - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - 인증 키는 두 부분으로 구성되어 있습니다, 공개 키 파트와 개인 키 파트. -개인 키를 사용하여 마스터 컴퓨터에서 클라이언트 컴퓨터에 접속할 수 있습니다. -오직 승인된 사용자만 개인 키 화일을 읽을 수 있도록 하는 것이 아주 중요합니다. -공개 키 파트는 클라이언트 컴퓨터에서 사용되며 들어오는 연결 요청이 허가된 것인지 검증하는데 사용됩니다. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + @@ -647,10 +694,6 @@ The public key is used on client computers to authenticate incoming connection r This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. 이 명령어는 설정된 키폴더에 있는 모든 인증키를 리스트해 줍니다. 만일 옵션 "%1"가 지정되면 키 상세 테이블이 대신 표시됩니다. 키가 접근 불가할 경우엔 일부 내용이 누락될 수 있습니다. 즉 e.g. 읽기 권한이 없는 경우등. - - Please specify the command to display help for! - 도움말을 표시할 명령어를 지정하세요 - TYPE TYPE @@ -659,24 +702,44 @@ The public key is used on client computers to authenticate incoming connection r PAIR ID 페어 ID - - Command line support for managing authentication keys - 명령어 창에서 인증키 조작 지원 - Commands for managing authentication keys 인증키 조작 명령어들 This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. - + 이 명령어는 이름 <NAME> 를 가진 새로운 인증 키 페어를 생성하고 개인키와 공개키를 지정된 키 폴더에 저장합니다. 파라메터는 반드시 글자만을 포함하는 키 이름이어야 함. This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. - + 이 명령어는 키폴더에 설정된 인증키 <KEY> 를 삭제합니다. 이키를 삭제하면 다시 복구할 수 없습니다. This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + 이 명령어는 개인키 <KEY> 를 통해서 공개키 파트를 추출하여 개인키에 대한 공개키로 저장합니다. 다른 마스터 컴퓨터를 설정할 경우, 개인기만 전송하는 것으로 충분합니다. 공개키는 이때 추출될수 있습니다. + + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + 이컴퓨터에 인증키 화일이 정상적으로 설정되지 않았습니다. 새 키화일을 생성하시거나 또는 Veyon 설정기를 이용해서 다른 인증 방법을 사용하세요. + + + Key file authentication + 키 화일 인증 + + + Key file + 키 파일 + + + Please specify the key name (e.g. "teacher/public") as the first argument. + + + + Please specify the command to display help for. + + + + The specified command does not exist or no help is available for it. @@ -700,63 +763,206 @@ The public key is used on client computers to authenticate incoming connection r - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - 컴퓨터 + General + 일반사항 - Name - 이름 + Username to bind DN mapping: + - Host address/IP - 호스트주소/IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + + AuthLdapDialog - MAC address - MAC주소 + Veyon Logon + Veyon 로그온 - Add new computer - 새 컴퓨터 추가 + Please enter your domain/LDAP username and password in order to access computers. + - Remove selected computer - 선택된 컴퓨터 삭제 + Username + 사용자 이름 - New computer - 새 컴퓨터 + Password + 암호 - Builtin directory - 게시물 폴더 + Authentication error + 인증 에러 - Locations & computers - 위치 및 컴퓨터들 + Logon failed with given username and password. Please try again! + 입력한 사용자이름과 패스워드로 로그온 실패. 다시 시도하세요! + + + AuthLogonDialog - Locations - 위치 + Veyon Logon + Veyon 로그온 - Add new location - 새로운 위치 추가 + Please enter your username and password in order to access computers. + 컴퓨터에 접근 하려면 당신의 사용자이름과 패스워드를 입력하세요 - Remove selected location - 선택한 위치 삭제 + Username + 사용자 이름 + + + Password + 암호 + + + Authentication error + 인증 에러 + + + Logon failed with given username and password. Please try again! + 입력한 사용자이름과 패스워드로 로그온 실패. 다시 시도하세요! + + + + AuthLogonPlugin + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + 제공된 사용자 이름 또는 패스워드가 틀립니다. 유효한 사용자 명 또는 패스워드를 사용하시거나 Veyon 설정기를 이용하여 다른 인증방법을 사용하시기 바랍니다. + + + Logon authentication + 로그온 인증 + + + Logon + + + + + AuthSimpleDialog + + Veyon Logon + Veyon 로그온 + + + Please enter the Veyon password: + Veyon 패스워드를 입력하세요 + + + Authentication error + 인증 에러 + + + Logon failed with given password. Please try again! + 입력한 패스워드로 로그온 실패. 다시 시도하세요! + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + 제공된 패스워드가 틀립니다. 유효한 사용자 명 또는 패스워드를 사용하시거나 Veyon 설정기를 이용하여 다른 인증방법을 사용하시기 바랍니다. + + + Simple password authentication + 패스워드 간단 인증 + + + Simple password + + + + + AuthenticationPage + + Authentication is set up properly on this computer. + 이 컴퓨터에서 인증이 적절히 설정되었습니다. + + + + AuthenticationPageTab + + Enabled + + + + Test + 테스트 + + + + BuiltinDirectoryConfiguration + + Builtin directory + 게시물 폴더 + + + + BuiltinDirectoryConfigurationPage + + Computers + 컴퓨터 + + + Name + 이름 + + + Host address/IP + 호스트주소/IP + + + MAC address + MAC주소 + + + Add new computer + 새 컴퓨터 추가 + + + Remove selected computer + 선택된 컴퓨터 삭제 + + + New computer + 새 컴퓨터 + + + Builtin directory + 게시물 폴더 + + + Locations + 위치 + + + Add new location + 새로운 위치 추가 - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - CSV 화일 불러오기는 커맨드라인 인터페이스로 가능합니다. 자세한 정보는, 다음 참조 <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">온라인 문서</a>. + Remove selected location + 선택한 위치 삭제 New location 새로운 위치 + + Directory name + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + BuiltinDirectoryPlugin @@ -1000,6 +1206,14 @@ The public key is used on client computers to authenticate incoming connection r MAC ADDRESS 맥 어드레스 + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. + + BuiltinUltraVncServer @@ -1017,10 +1231,6 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - 호스트/IP 주소: %1 - Active features: %1 활성화된 기능들: %1 @@ -1037,10 +1247,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off 컴퓨터 오프라인 또는 전원 꺼짐 - - Service unreachable or not running - 서비스에 연결할 수 없거나 실행중이 아님 - Authentication failed or access denied 인증 실패 또는 접근 거부됨 @@ -1061,6 +1267,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 장소: %1 + + [no user] + + + + Veyon Server unreachable or not running + + + + Name: %1 + + + + Hostname: %1 + + + + unknown + 알수없음 + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + ComputerControlServer @@ -1082,7 +1320,7 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" attempted to access this computer but could not authenticate successfully. - + 호스트 "%2"의 사용자 "%1" 가 이 컴퓨터에 연결하려고 하였으나 인증에 성공하지 못했습니다. Access control error @@ -1090,6 +1328,17 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + 호스트 "%2"의 사용자 "%1" 가 이 컴퓨터에 연결하려고 하였으나 접근제어 설정에 의해 블럭되었습니다. + + + Active connections: + + + + + ComputerGroupSelector + + Group %1 @@ -1113,86 +1362,89 @@ The public key is used on client computers to authenticate incoming connection r Computer name;Hostname;User - + 컴퓨터 이름;호스트 이름;사용자 Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + 이 컴퓨터의 위치를 찾을 수 없음. 시스템 설정에 문제가 있어 보입니다. 대신 모든 위치는 컴퓨터 선정 패널에 표시됩니다. + + + Logged in since - - - ComputerSelectPanel - Computer management - 컴퓨터 관리 + %1 days + - Computer search - 컴퓨터 검색 + 1 day + + + + ComputerMonitoring - Add location - 위치 추가 + Computers + 컴퓨터 - Save computer/user list - 컴퓨터/사용자 리스트 저장 + Search users and computers + 사용자 또는 컴퓨터 검색 - Select output filename - 출력 화일이름 선택 + Select all + - CSV files (*.csv) - CSV files (*.csv) + Unselect all + - File error - 화일 에러 + Add to group + - Could not write the computer and users list to %1! Please check the file access permissions. - 컴퓨터와 사용자 리스트를 %1에 저장하지 못함. 접근 권한을 확인하세요. + Remove from group + - ConfigCommandLinePlugin - - Please specify an existing configuration file to import. - 읽어 올 기존 설정 화일을 선택하세요. - + ComputerSelectPanel - Please specify a valid filename for the configuration export. - 설정을 내보낼 유효한 화일 이름을 지정하세요. + Computer search + 컴퓨터 검색 - Please specify a valid key. - 유효한 키를 선택하세요. + Add location + 위치 추가 - Specified key does not exist in current configuration! - 현재 설정에 지정된 키가 존재하지 않습니다! + Save computer/user list + 컴퓨터/사용자 리스트 저장 - Please specify a valid value. - 유효한 값을 지정하세요 + Select output filename + 출력 화일이름 선택 - Configure Veyon at command line - 커맨드 라인에서 Veyon 설정 + CSV files (*.csv) + CSV files (*.csv) - Output file is not writable! - 출력 화일에 쓸수 없습니다! + File error + 화일 에러 - Output directory is not writable! - 출력 폴더에 저장할 수 없습니다! + Could not write the computer and users list to %1! Please check the file access permissions. + 컴퓨터와 사용자 리스트를 %1에 저장하지 못함. 접근 권한을 확인하세요. - Configuration file is not readable! - 설정화일을 읽을 수 없습니다! + Search computers + + + + ConfigCommands Clear system-wide Veyon configuration 시스템 상의 Veyon 설정 삭제 @@ -1221,35 +1473,75 @@ The public key is used on client computers to authenticate incoming connection r Unset (remove) given configuration key 해당 설정 키를 삭제(선택취소)함 - - Commands for managing the configuration of Veyon - Veyon 설정 관리 명령어들 - Upgrade and save configuration of program and plugins 프로그램과 플러그인의 설정을 업그레이드하고 저장 - - - ConfigurationManager - Could not modify the autostart property for the %1 Service. - %1 서비스에 대한 자동 시작 속성을 수정할 수 없습니다. + Please specify an existing configuration file to import. + 읽어 올 기존 설정 화일을 선택하세요. - Could not configure the firewall configuration for the %1 Server. - %1 서버용 방화벽 설정을 변경할 수 없습니다. + Configuration file is not readable! + 설정화일을 읽을 수 없습니다! - Could not configure the firewall configuration for the %1 Worker. - %1 워커용 방화벽 설정을 변경할 수 없습니다. + Please specify a valid filename for the configuration export. + 설정을 내보낼 유효한 화일 이름을 지정하세요. - Configuration is not writable. Please check your permissions! - 설정을 쓸수 없습니다. 권한을 점검하기 바랍니다! + Output file is not writable! + 출력 화일에 쓸수 없습니다! - Could not apply platform-specific configuration settings. + Output directory is not writable! + 출력 폴더에 저장할 수 없습니다! + + + Please specify a valid key. + 유효한 키를 선택하세요. + + + Specified key does not exist in current configuration! + 현재 설정에 지정된 키가 존재하지 않습니다! + + + Please specify a valid value. + 유효한 값을 지정하세요 + + + Configure Veyon at command line + 커맨드 라인에서 Veyon 설정 + + + Commands for managing the configuration of Veyon + Veyon 설정 관리 명령어들 + + + + ConfigurationManager + + Could not modify the autostart property for the %1 Service. + %1 서비스에 대한 자동 시작 속성을 수정할 수 없습니다. + + + Could not configure the firewall configuration for the %1 Server. + %1 서버용 방화벽 설정을 변경할 수 없습니다. + + + Could not configure the firewall configuration for the %1 Worker. + %1 워커용 방화벽 설정을 변경할 수 없습니다. + + + Configuration is not writable. Please check your permissions! + 설정을 쓸수 없습니다. 권한을 점검하기 바랍니다! + + + Could not apply platform-specific configuration settings. + 플랫폼 전용 설정 세팅을 적용할 수 없습니다. + + + Could not configure the firewall configuration for the %1 Service. @@ -1282,10 +1574,6 @@ The public key is used on client computers to authenticate incoming connection r Memory limit 메모리 한계 - - Use multithreading (experimental) - 멀티쓰레딩 사용(개발중임) - MB MB @@ -1300,15 +1588,19 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running + 데모가 실행중일 때 썸네일 업데이트 속도를 늦춤 + + + Bandwidth limit + + + + MB/s DemoFeaturePlugin - - Fullscreen demo - 전체화면 데모 - Stop demo 데모 중지 @@ -1322,17 +1614,60 @@ The public key is used on client computers to authenticate incoming connection r 화면 전송으로 데모를 보여 줍니다. - Demo server - 데모 서버 + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + 이 모드에서는 교사의 화면이 하나의 윈도우 창 으로 모든 컴퓨터에 표시됩니다. 필요할 경우 사용자들은 다른 윈도우 창으로 전환해서 자신의 작업을 계속 할 수 있습니다. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - 이 모드에서 교사의 화면이 모든 컴퓨터에 표시됩니다. -또한 입력장치가 잠기므로 사용자들은 다른 작업을 할 수 없습니다. + Demo + - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - 이 모드에서는 교사의 화면이 하나의 윈도우 창 으로 모든 컴퓨터에 표시됩니다. 필요할 경우 사용자들은 다른 윈도우 창으로 전환해서 자신의 작업을 계속 할 수 있습니다. + Share your screen or allow a user to share his screen with other users. + + + + Full screen demo + + + + Share your own screen in fullscreen mode + + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share your own screen in a window + + + + Share selected user's screen in fullscreen mode + + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share selected user's screen in a window + + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + + + + Please select only one user screen to share. + + + + All screens + @@ -1360,14 +1695,6 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - - Programs & websites - 프로그램과 웹사이트들 - - - Predefined programs - 미리 지정된 프로그램들 - Name 이름 @@ -1376,14 +1703,6 @@ The public key is used on client computers to authenticate incoming connection r Path 경로 - - Add new program - 새 프로그램 추가 - - - Remove selected program - 선택한 프로그램 삭제 - Predefined websites 미리 지정된 웹사이트들 @@ -1396,21 +1715,37 @@ The public key is used on client computers to authenticate incoming connection r URL URL - - New program - 새 프로그램 - New website 새 웹사이트 + + Applications & websites + + + + Predefined applications + + + + Add new application + + + + Remove selected application + + + + Add new website + + + + New application + + DesktopServicesFeaturePlugin - - Run program - 프로그램 실행 - Open website 웹사이트 열기 @@ -1420,28 +1755,32 @@ The public key is used on client computers to authenticate incoming connection r 클릭하면 모든 컴퓨터에서 같은 웹사이트를 오픈합니다. - Start programs and services in user desktop - 사용자 데스크탑에서 프로그램과 서비스를 시작 + Open website "%1" + 웹사이트 "%1" 열기 + + + Custom website + 사용자 지정 웹사이트 - Click this button to run a program on all computers. - 클릭하면 모든 컴퓨터에서 프로그램을 실행합니다. + Start application + - Run program "%1" - 프로그램 "%1" 실행 + Click this button to start an application on all computers. + - Custom program - 사용자 프로그램 + Start application "%1" + - Open website "%1" - 웹사이트 "%1" 열기 + Custom application + - Custom website - 사용자 지정 웹사이트 + Start apps and open websites in user sessions + @@ -1456,7 +1795,7 @@ The public key is used on client computers to authenticate incoming connection r Please complete all tasks within the next 5 minutes. - + 5분내로 모든 작업을 완료하시기 바랍니다. Custom website @@ -1468,22 +1807,26 @@ The public key is used on client computers to authenticate incoming connection r Start learning tool - + 학습툴 시작 Play tutorial video 튜토리얼 동영상 재생 - - Custom program - 사용자 프로그램 - Handout - + 자료 배포 핸드아웃 Texts to read + 읽을 글자들 + + + generic-student-user + 일반-학생-사용자 + + + Custom application @@ -1510,478 +1853,465 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands - Feature control - 기능제어 + List names of all available features + - - - FileTransferController - Could not open file "%1" for reading! Please check your permissions! - 화일 "%1"을 읽을 수 없습니다! 권한을 점검하기 바랍니다! + Show table with details of all available features + - - - FileTransferDialog - File transfer - 화일 전송 + Start a feature on a remote host + - Options - 옵션 + Stop a feature on a remote host + - Transfer only - 전송만 함 + Please specify the command to display help for. + - Transfer and open file(s) with associated program - 전송한 후 화일과 연결되어 있는 프로그램으로 화일(들) 열기 + Displays a list with the names of all available features. + - Transfer and open destination folder - 전송하고 도착 폴더를 열기 + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + - Files - 화일 + HOST ADDRESS + HOST ADDRESS - Start - 시작 + FEATURE + - Overwrite existing files - 기존 화일을 덮어 씀 + ARGUMENTS + - - - FileTransferPlugin - File transfer - 화일 전송 + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + - Click this button to transfer files from your computer to all computers. - 다른 모든 컴퓨터로 화일을 전송하려면 이버튼을 클릭하세요 + Lock the screen + - Select one or more files to transfer - 전송하려는 하나 또는 여러개의 화일을 선택하세요 + Display a text message + - Transfer files to remote computer - 원격 컴퓨터로 화일 전송 + Test message + - Received file "%1". - 받은 화일 "%1". + Start an application + - Could not receive file "%1" as it already exists. - 화일 "%1" 이 이미 존재하므로 덮어 쓸 수 없습니다. + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + - Could not receive file "%1" as it could not be opened for writing! - 화일 "%1" 이 쓸수 있도록 열리지 않아 화일을 받을 수 없습니다! + Unlock the screen + - - - GeneralConfigurationPage - User interface - 유저 인터페이스 + The specified command does not exist or no help is available for it. + - Language: - 언어: + Name + 이름 - Use system language setting - 시스템 언어 설정 사용 + Description + - Veyon - Veyon + Master + 마스터 - Logging - 로깅중 + Service + 서비스 - Log file directory - 로그 화일 폴더 + Worker + - ... - ... + UID + - Log level - 로그 수준 + Plugin + - Nothing - 로그 남기지 않음 + Invalid feature name or UID specified + - Only critical messages - 심각한 에러 메시지만 남김 + Error parsing the JSON-encoded arguments: %1 + - Errors and critical messages - 에러와 심각한 에러 메시지만 남김 + Failed to initialize credentials + - Warnings and errors - 경고와 에러 메시지 남김 + Could not establish a connection to host %1 + - Information, warnings and errors - 정보, 경고와 에러 메시지 남김 + Failed to send feature control message to host %1 + - Debug messages and everything else - 디버그 메시지와 기타 모든 메시지 남김 + Feature-related CLI operations + - Limit log file size - 로그 파일 최대 크기 + Commands for controlling features + + + + FileTransferConfigurationPage - Clear all log files - 모든 로그 파일 지우기 + File transfer + 화일 전송 - Log to standard error output - 표준 에러 출력장치에 기록 + Directories + 디렉토리 - Network object directory - 네트워크 개체 폴더 + Destination directory + - Backend: - 백엔드: + Default source directory + - Update interval: - 화면업데이트 간격: + Options + 옵션 - %1 service - %1 서비스 + Remember last source directory + - The %1 service needs to be stopped temporarily in order to remove the log files. Continue? - 로그 화일을 삭제하기 위해 %1 서비스를 잠시 중지합니다. 계속할까요 ? + Create destination directory if it does not exist + + + + FileTransferController - Log files cleared - 로그화일 삭제 + Could not open file "%1" for reading! Please check your permissions! + 화일 "%1"을 읽을 수 없습니다! 권한을 점검하기 바랍니다! + + + FileTransferDialog - All log files were cleared successfully. - 모든 로그화일 삭제 성공. + File transfer + 화일 전송 - Error - 에러 + Options + 옵션 - Could not remove all log files. - 모든 로그화일을 삭제하지 못함. + Transfer only + 전송만 함 - MB - MB + Transfer and open file(s) with associated program + 전송한 후 화일과 연결되어 있는 프로그램으로 화일(들) 열기 - Rotate log files - 로그화일 회전 + Transfer and open destination folder + 전송하고 도착 폴더를 열기 - x - x + Files + 화일 - seconds - + Start + 시작 - Write to logging system of operating system - 운영체계의 로깅시스템에 기록 + Overwrite existing files + 기존 화일을 덮어 씀 + + + FileTransferFileDialog - Authentication - 인증 + Select one or more files to transfer + 전송하려는 하나 또는 여러개의 화일을 선택하세요 + + + FileTransferPlugin - Method: - 방법: + File transfer + 화일 전송 - Logon authentication - 로그온 인증 + Click this button to transfer files from your computer to all computers. + 다른 모든 컴퓨터로 화일을 전송하려면 이버튼을 클릭하세요 - Key file authentication - 키 화일 인증 + Select one or more files to transfer + 전송하려는 하나 또는 여러개의 화일을 선택하세요 - Test - 테스트 + Transfer files to remote computer + 원격 컴퓨터로 화일 전송 - Authentication is set up properly on this computer. - + Received file "%1". + 받은 화일 "%1". - Authentication keys are not set up properly on this computer. - + Could not receive file "%1" as it already exists. + 화일 "%1" 이 이미 존재하므로 덮어 쓸 수 없습니다. - Authentication test - 인증 테스트 + Could not receive file "%1" as it could not be opened for writing! + 화일 "%1" 이 쓸수 있도록 열리지 않아 화일을 받을 수 없습니다! - InternetAccessControlConfigurationPage + GeneralConfigurationPage - Internet access control - 인터넷 연결 제어 + User interface + 유저 인터페이스 - Backend: - 백엔드: + Language: + 언어: - General settings - 일반 설정 + Use system language setting + 시스템 언어 설정 사용 - Backend settings - 백엔드 설정 + Veyon + Veyon - - - InternetAccessControlPlugin - Block access to the internet - 인터넷 접근 제한 + Logging + 로깅중 - Allow access to the internet - 인터넷 접근 허용 + Log file directory + 로그 화일 폴더 - Show help about command - 명령어에 대한 도움말 보여줌 + Log level + 로그 수준 - Block internet - 인터넷 연결제한 + Nothing + 로그 남기지 않음 - Click this button to block access to the internet. - 클릭하여 인터넷 접근을 제한 + Only critical messages + 심각한 에러 메시지만 남김 - Unblock internet - 인터넷 연결허용 + Errors and critical messages + 에러와 심각한 에러 메시지만 남김 - Click this button to allow access to the internet. - 클릭하여 인터넷 접근을 허용 + Warnings and errors + 경고와 에러 메시지 남김 - Control access to the internet - 인터넷 접근 제어 + Information, warnings and errors + 정보, 경고와 에러 메시지 남김 - Commands for controlling access to the internet - 인터넷 접근 제어용 명령어들 + Debug messages and everything else + 디버그 메시지와 기타 모든 메시지 남김 - - - LdapBrowseDialog - Browse LDAP - LDAP 찾아보기 + Limit log file size + 로그 파일 최대 크기 - - - LdapClient - LDAP error description: %1 - LDAP 에러 설명: %1 + Clear all log files + 모든 로그 파일 지우기 - - - LdapConfigurationPage - Basic settings - 기본 설정 + Log to standard error output + 표준 에러 출력장치에 기록 - General - 일반사항 + %1 service + %1 서비스 - LDAP server and port - LDAP 서버 및 포트 + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + 로그 화일을 삭제하기 위해 %1 서비스를 잠시 중지합니다. 계속할까요 ? - Bind DN - DN 결합 + Log files cleared + 로그화일 삭제 - Bind password - 패스워드 결합 + All log files were cleared successfully. + 모든 로그화일 삭제 성공. - Anonymous bind - 익명으로 결합 + Error + 에러 - Use bind credentials - 인증서 결합 사용 + Could not remove all log files. + 모든 로그화일을 삭제하지 못함. - Base DN - 기본 DN + MB + MB - Fixed base DN - 고정된 기본 DN + Rotate log files + 로그화일 회전 - e.g. dc=example,dc=org - 예. dc=example,dc=org + x + x - Discover base DN by naming context - 이름으로 기본 DN 탐색 + Write to logging system of operating system + 운영체계의 로깅시스템에 기록 - e.g. namingContexts or defaultNamingContext - 예. namingContexts or defaultNamingContext + TLS configuration + - Environment settings - 환경설정 + Use certificate authority for TLS connections + - Object trees - 개체 트리 + CA certificate file + - Computer tree - 컴퓨터 트리 + ... + ... - e.g. OU=Groups - 예. OU=Groups + Host certificate file + - User tree - 사용자 트리 + Host private key file + - e.g. OU=Users - 예. OU=Users + Style: + - e.g. OU=Computers - 예. OU=Computers + Native + - Group tree - 그룹 트리 + Color scheme: + - Perform recursive search operations in object trees - 개체 트리에서 재귀적 검색작업 수행 + Light + - Object attributes - 개체 특성 + Dark + - e.g. hwAddress - 예. hwAddress + User groups + - e.g. member or memberUid - 예. member or memberUid + Backend: + 백엔드: - e.g. dNSHostName - 예. dNSHostName + Include user groups from domain + - Computer MAC address attribute - 컴퓨터 MAC 주소 속성 + Missing user groups backend + 유저그룹 백엔드 없음 - Group member attribute - 그룹멤버 속성 + No user groups plugin was found. Please check your installation! + + + + HeadlessVncServer - e.g. uid or sAMAccountName - 예. uid or sAMAccountName - - - Advanced settings - 고급 설정 - - - Optional object filters - 선택적 개체필터 - - - Filter for user groups - 유저그룹 필터 - - - Filter for users - 유저필터 - - - Filter for computer groups - 컴퓨터 그룹 필터 - - - Group member identification - 그룹멤버 ID - - - Distinguished name (Samba/AD) - 식별이름 (Samba/AD) - - - List all groups of a user - 모든 유저그룹 표시 + Headless VNC server + + + + LdapBrowseDialog - List all groups of a computer - 모든 컴퓨터 그룹 표시 + Browse LDAP + LDAP 찾아보기 + + + LdapClient - Get computer object by IP address - IP주소로 컴퓨터 개체 가져오기 + LDAP error description: %1 + LDAP 에러 설명: %1 + + + LdapConfiguration LDAP connection failed LDAP 연결실패 + + Could not connect to the LDAP server. Please check the server parameters. + +%1 + LDAP 서버에 연결할 수 없음. 서버 파라메터를 점검하세요. + +%1 + LDAP bind failed LDAP 결합실패 + + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + LDAP서버와 결합 불가. 결합인자와 서버 파라메터를 점검하세요. + +%1 + LDAP bind successful LDAP 결합 성공 @@ -1994,14 +2324,36 @@ The public key is used on client computers to authenticate incoming connection r LDAP base DN test failed LDAP 기본 DN 시험 실패 + + Could not query the configured base DN. Please check the base DN parameter. + +%1 + 설정된 베이스 DN을 찾을 수 없습니다. 베이스 DN 파라메터를 점검하세요. + +%1 + LDAP base DN test successful LDAP 기본 DN 시험 성공 + + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + LDAP 베이스 DN 조회 성공. 다음 입력항목이 발견되었습니다: +%1 + LDAP naming context test failed LDAP naming context 시험실패 + + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + 명칭 내용을 통해 베이스 DN 조회를 할 수 없습니다. 명칭 속성 파라메터를 점검하세요. +%1 + LDAP naming context test successful LDAP naming context 시험 성공 @@ -2016,38 +2368,50 @@ The public key is used on client computers to authenticate incoming connection r user tree 사용자 트리 + + User tree + 사용자 트리 + group tree 그룹 트리 + + Group tree + 그룹 트리 + computer tree 컴퓨터 트리 - Enter username - 사용자 이름 입력 + Computer tree + 컴퓨터 트리 - Please enter a user login name (wildcards allowed) which to query: - 검색할 유저로그인 이름을 입력하세요 (와일드카드 허용됨): + computer group tree + 컴퓨터 그룹 트리 - user objects - 사용자 개체 + Computer group tree + 컴퓨터 그룹 트리 - Enter group name - 그룹이름 입력 + user objects + 사용자 개체 - Please enter a group name whose members to query: - 검색할 그룹 이름을 입력하세요: + User login name attribute + 사용자 로긴이름 속성 group members 그룹 멤버 + + Group member attribute + 그룹멤버 속성 + Group not found 그룹 검색되지 않음 @@ -2056,26 +2420,50 @@ The public key is used on client computers to authenticate incoming connection r Could not find a group with the name "%1". Please check the group name or the group tree parameter. 이름 "%1" 그룹 검색되지 않음. 그룹이름 또는 그룹 트리 파라메터를 확인하세요. - - Enter computer name - 그룹이름 입력 - computer objects 컴퓨터 개체 - Enter computer DN - 컴퓨터 DN 입력 + Computer display name attribute + 컴퓨터 표시 이름 속성 - Please enter the DN of a computer whose MAC address to query: - MAC 주소를 조회할 컴퓨터의 DN을 입력하세요 + Invalid hostname + 잘못된 호스트 이름 + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + 컴퓨터 호스트 이름을 완전히 인증된 도메인 이름으로 저장되도록 설정했으나 도메인(FQDN) 이 입력되지 않았음. + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + 컴퓨터 호스트 이름을 도메인 없는 단순 호스트 이름으로 저장되도록 설정하였으나 호스트 이름에 도메인 이름이 입력되있습니다. + + + Computer hostname attribute + 컴퓨터 호스트 이름 속성 computer MAC addresses 컴퓨터 MAC 주소 + + Computer MAC address attribute + 컴퓨터 MAC 주소 속성 + + + computer locations + 컴퓨터 위치 + + + Computer location attribute + 컴퓨터 위치 및 속성 + + + Location name attribute + 위치 이름 및 속성 + users 사용자 @@ -2084,13 +2472,17 @@ The public key is used on client computers to authenticate incoming connection r user groups 사용자 그룹 + + computers + 컴퓨터 + computer groups 컴퓨터 그룹 - Please enter a user login name whose group memberships to query: - 그룹 멤버 속성을 검색할 사용자 로그인 이름을 입력하세요 : + computer containers + 컴퓨터 컨테이너들 groups of user @@ -2100,6 +2492,10 @@ The public key is used on client computers to authenticate incoming connection r User not found 사용자 검색되지 않음 + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + 사용자 이름 "%1" 검색되지 않음. 사용자 이름 또는 사용자 트리 파라메터를 확인하세요. + groups of computer 컴퓨터 그룹 @@ -2109,21 +2505,53 @@ The public key is used on client computers to authenticate incoming connection r 컴퓨터 발견되지 않음 - Enter computer IP address - IP 주소를 입력하세요 + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + 호스트 이름 "%1"인 컴퓨터 가 검색되지 않음. 호스트 이름 또는 컴퓨터 트리 파라메터를 확인하세요. - Please enter a computer IP address which to resolve to an computer object: - 컴퓨터 개체로 변환할 컴퓨터 IP 주소를 입력하세요 + Hostname lookup failed + 호스트이름 검색 실패 - computers - 컴퓨터 + Could not lookup hostname for IP address %1. Please check your DNS server settings. + IP %1 에 대한 호스트 이름 검색 실패. DNS 서버 설정을 확인하세요 + + + location entries + 위치 엔트리 + + + Computer groups filter + + + + Computer locations identification + 컴퓨터 위치 ID + + + Filter for computer groups + 컴퓨터 그룹 필터 + + + Invalid test value + + + + An empty or invalid value has been supplied for this test. + LDAP %1 test failed LDAP %1 시험 실패 + + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + 설정된 %1에서 엔트리 값을 찾지 못함. "%2" 파라메터를 점검하세요. + +%3 + LDAP %1 test successful LDAP %1 시험 성공 @@ -2132,6 +2560,26 @@ The public key is used on client computers to authenticate incoming connection r The %1 has been queried successfully and %2 entries were found. %1 이 성공적으로 조회되고 %2 입력 값이 검색됨 + + LDAP test failed + LDAP 테스트 실패 + + + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + %1을 조회할 수 없음. %2 파라메터(들)을 점검하거나 또는 기존의 개체의 이름을 입력하세요 + +%3 + + + and + + + + LDAP test successful + LDAP 테스트 성공 + %1 %2 have been queried successfully: @@ -2161,561 +2609,485 @@ The public key is used on client computers to authenticate incoming connection r 컴퓨터 필터를 사용한 %1 %2 검색 조회 성공 - (only if different from group tree) - (그룹 트리가 다를 경우에만) + LDAP directory + + + + LdapConfigurationPage - Computer group tree - 컴퓨터 그룹 트리 + Basic settings + 기본 설정 - computer group tree - 컴퓨터 그룹 트리 + General + 일반사항 - Filter for computers - 컴퓨터 필터 + LDAP server and port + LDAP 서버 및 포트 - e.g. room or computerLab - 예. room or computerLab + Bind DN + DN 결합 - Integration tests - 결합 테스트 + Bind password + 패스워드 결합 - Computer groups - 컴퓨터 그룹 + Anonymous bind + 익명으로 결합 - e.g. name or description - 예. 이름 또는 설명 + Use bind credentials + 인증서 결합 사용 - Filter for computer containers - 컴퓨터 컨테이너 필터 - - - Computer containers or OUs - 컴퓨터 컨테이너 또는 OU - - - Connection security - 연결 보안 - - - TLS certificate verification - TLS 인증 검증 - - - System defaults - 시스템 디폴트 - - - Never (insecure!) - 거부(보안 안됨) - - - Custom CA certificate file - 사용자 CA 인증 화일 + Base DN + 기본 DN - None - 없음 + Fixed base DN + 고정된 기본 DN - TLS - TLS + e.g. dc=example,dc=org + 예. dc=example,dc=org - SSL - SSL + Discover base DN by naming context + 이름으로 기본 DN 탐색 - e.g. (objectClass=computer) - e.g. (objectClass=computer) + e.g. namingContexts or defaultNamingContext + 예. namingContexts or defaultNamingContext - e.g. (objectClass=group) - e.g. (objectClass=group) + Environment settings + 환경설정 - e.g. (objectClass=person) - 예. (objectClass=person) + Object trees + 개체 트리 - e.g. (objectClass=room) or (objectClass=computerLab) - e.g. (objectClass=room) or (objectClass=computerLab) + Computer tree + 컴퓨터 트리 - e.g. (objectClass=container) or (objectClass=organizationalUnit) - e.g. (objectClass=container) or (objectClass=organizationalUnit) + e.g. OU=Groups + 예. OU=Groups - Could not query the configured base DN. Please check the base DN parameter. - -%1 - 설정된 베이스 DN을 찾을 수 없습니다. 베이스 DN 파라메터를 점검하세요. - -%1 + User tree + 사용자 트리 - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - LDAP 베이스 DN 조회 성공. 다음 입력항목이 발견되었습니다: -%1 + e.g. OU=Users + 예. OU=Users - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - 명칭 내용을 통해 베이스 DN 조회를 할 수 없습니다. 명칭 속성 파라메터를 점검하세요. -%1 + e.g. OU=Computers + 예. OU=Computers - Certificate files (*.pem) - 인증화일 (*.pem) + Group tree + 그룹 트리 - Could not connect to the LDAP server. Please check the server parameters. - -%1 - LDAP 서버에 연결할 수 없음. 서버 파라메터를 점검하세요. - -%1 + Perform recursive search operations in object trees + 개체 트리에서 재귀적 검색작업 수행 - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - LDAP서버와 결합 불가. 결합인자와 서버 파라메터를 점검하세요. - -%1 + Object attributes + 개체 특성 - Encryption protocol - 암호화 프로토콜 + e.g. hwAddress + 예. hwAddress - Computer location attribute - 컴퓨터 위치 및 속성 + e.g. member or memberUid + 예. member or memberUid - Computer display name attribute - 컴퓨터 표시 이름 속성 + e.g. dNSHostName + 예. dNSHostName - Location name attribute - 위치 이름 및 속성 + Computer MAC address attribute + 컴퓨터 MAC 주소 속성 - e.g. cn or displayName - 예, cn 또는 displayName + Group member attribute + 그룹멤버 속성 - Computer locations identification - 컴퓨터 위치 ID + e.g. uid or sAMAccountName + 예. uid or sAMAccountName - Identify computer locations (e.g. rooms) via: - 를 통해서 컴퓨터 위치 확인하기( 예, rooms) : + Advanced settings + 고급 설정 - Location attribute in computer objects - 컴퓨터 오브젝트에서의 위치 속성 + Optional object filters + 선택적 개체필터 - List all entries of a location - 모든 위치의 엔트리 출력 + Filter for user groups + 유저그룹 필터 - List all locations - 모든 위치 출력 + Filter for users + 유저필터 - Enter computer display name - 컴퓨터 표시 이름 입력 + Filter for computer groups + 컴퓨터 그룹 필터 - Please enter a computer display name to query: - 검색할 컴퓨터 디스플레이 이름을 입력하세요: + Group member identification + 그룹멤버 ID - Enter computer location name - 컴퓨터 위치 이름 입력 + Distinguished name (Samba/AD) + 식별이름 (Samba/AD) - Please enter the name of a computer location (wildcards allowed): - 컴퓨터 위치의 이름을 입력하세요(와일드카드 허용됨): + List all groups of a user + 모든 유저그룹 표시 - computer locations - 컴퓨터 위치 + List all groups of a computer + 모든 컴퓨터 그룹 표시 - Enter location name - 위치 이름 입력 + Get computer object by IP address + IP주소로 컴퓨터 개체 가져오기 - Please enter the name of a location whose entries to query: - 조회할 위치 이름을 넣으세요: + Enter username + 사용자 이름 입력 - location entries - 위치 엔트리 + Please enter a user login name (wildcards allowed) which to query: + 검색할 유저로그인 이름을 입력하세요 (와일드카드 허용됨): - LDAP test failed - LDAP 테스트 실패 + Enter group name + 그룹이름 입력 - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - %1을 조회할 수 없음. %2 파라메터(들)을 점검하거나 또는 기존의 개체의 이름을 입력하세요 - -%3 + Please enter a group name whose members to query: + 검색할 그룹 이름을 입력하세요: - and - + Enter computer name + 그룹이름 입력 - LDAP test successful - LDAP 테스트 성공 + Enter computer DN + 컴퓨터 DN 입력 - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - 설정된 %1에서 엔트리 값을 찾지 못함. "%2" 파라메터를 점검하세요. - -%3 + Please enter the DN of a computer whose MAC address to query: + MAC 주소를 조회할 컴퓨터의 DN을 입력하세요 - Browse - 찾아보기 + Please enter a user login name whose group memberships to query: + 그룹 멤버 속성을 검색할 사용자 로그인 이름을 입력하세요 : - Test - 테스트 + Enter computer IP address + IP 주소를 입력하세요 - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - + Please enter a computer IP address which to resolve to an computer object: + 컴퓨터 개체로 변환할 컴퓨터 IP 주소를 입력하세요 - Computer hostname attribute - + (only if different from group tree) + (그룹 트리가 다를 경우에만) - Please enter a computer hostname to query: - + Computer group tree + 컴퓨터 그룹 트리 - Invalid hostname - 잘못된 호스트 이름 + Filter for computers + 컴퓨터 필터 - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - + e.g. room or computerLab + 예. room or computerLab - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - + Integration tests + 결합 테스트 - Could not find a user with the name "%1". Please check the username or the user tree parameter. - + Computer groups + 컴퓨터 그룹 - Enter hostname - 호스트 이름을 입력하세요 + e.g. name or description + 예. 이름 또는 설명 - Please enter a computer hostname whose group memberships to query: - + Filter for computer containers + 컴퓨터 컨테이너 필터 - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - + Computer containers or OUs + 컴퓨터 컨테이너 또는 OU - Hostname lookup failed - + Connection security + 연결 보안 - Could not lookup hostname for IP address %1. Please check your DNS server settings. - + TLS certificate verification + TLS 인증 검증 - User login name attribute - + System defaults + 시스템 디폴트 - Configured attribute for user login name or computer hostname (OpenLDAP) - + Never (insecure!) + 거부(보안 안됨) - computer containers - + Custom CA certificate file + 사용자 CA 인증 화일 - - - LdapPlugin - Auto-configure the base DN via naming context - 기본 DN 을 명칭 기반으로 자동 설정함 + None + 없음 - Query objects from LDAP directory - 개체를 LADP 폴더에서 조회 + TLS + TLS - Show help about command - 명령어에 대한 도움말 보여줌 + SSL + SSL - Commands for configuring and testing LDAP/AD integration - LDAP/AD 통합을 설정하거나 제어하는 명령어 + e.g. (objectClass=computer) + e.g. (objectClass=computer) - Basic LDAP/AD support for Veyon - Veyon 기본 LDAP/AD 지원 + e.g. (objectClass=group) + e.g. (objectClass=group) - %1 (load computers and locations from LDAP/AD) - %1 (LDAP/AD에서 컴퓨터와 위치를 가져옴) + e.g. (objectClass=person) + 예. (objectClass=person) - %1 (load users and groups from LDAP/AD) - %1 (LDAP/AD에서 사용자와 그룹을 가져옴) + e.g. (objectClass=room) or (objectClass=computerLab) + e.g. (objectClass=room) or (objectClass=computerLab) - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - + e.g. (objectClass=container) or (objectClass=organizationalUnit) + e.g. (objectClass=container) or (objectClass=organizationalUnit) - No naming context attribute name given - falling back to configured value. - + Certificate files (*.pem) + 인증화일 (*.pem) - Could not query base DN. Please check your LDAP configuration. - + Encryption protocol + 암호화 프로토콜 - Configuring %1 as base DN and disabling naming context queries. - + Computer location attribute + 컴퓨터 위치 및 속성 - - - LdapProConfigurationPage - LDAP Pro - LDAP Pro + Computer display name attribute + 컴퓨터 표시 이름 속성 - Instances - 개체 + Location name attribute + 위치 이름 및 속성 - Enter name - 이름 입력 + e.g. cn or displayName + 예, cn 또는 displayName - Please enter a name for the instance (can't be changed later!): - 개체의 이름을 입력하세요 (나중에 변경불가!): + Computer locations identification + 컴퓨터 위치 ID - Remove instance - 개체 삭제 + Identify computer locations (e.g. rooms) via: + 를 통해서 컴퓨터 위치 확인하기( 예, rooms) : - Do you really want to remove instance "%1"? - 정말로 "%1" 개체를 삭제하시겠습니까? + Location attribute in computer objects + 컴퓨터 오브젝트에서의 위치 속성 - Configuration for instance "%1" - "%1" 객체 설정 + List all entries of a location + 모든 위치의 엔트리 출력 - - - LdapProPlugin - Professional LDAP/AD integration for Veyon - Veyon용 프로페셔널 LDAP/AD 결합 + List all locations + 모든 위치 출력 - %1 (load computers and locations from LDAP/AD) - %1 (LDAP/AD에서 컴퓨터와 위치를 가져옴) + Enter computer display name + 컴퓨터 표시 이름 입력 - %1 (load users and groups from LDAP/AD) - %1 (LDAP/AD에서 사용자와 그룹을 가져옴) + Please enter a computer display name to query: + 검색할 컴퓨터 디스플레이 이름을 입력하세요: - - - LicensingConfigurationPage - Licensing - Licensing + Enter computer location name + 컴퓨터 위치 이름 입력 - Installed licenses - 설치된 라이센스 + Please enter the name of a computer location (wildcards allowed): + 컴퓨터 위치의 이름을 입력하세요(와일드카드 허용됨): - Add new network range - 새로운 네트워크 범위 추가 + Enter location name + 위치 이름 입력 - Remove selected network range - 선택된 네트워크 범위 삭제 + Please enter the name of a location whose entries to query: + 조회할 위치 이름을 넣으세요: - ID - ID + Browse + 찾아보기 - Feature - 기능 + Test + 테스트 - Valid until - 다음 기간동안 유효함 + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + 호스트 이름이 완전히 검증된 도메인 이름으로 저장되었음 (FQDN, 예 myhost.example.org) - Licensee - 사용권자 + Computer hostname attribute + 컴퓨터 호스트 이름 속성 - Browse license file - 라이센스 파일 찾아보기 + Please enter a computer hostname to query: + 검색할 컴퓨터 호스트 이름을 입력하세요: - Veyon license files (*.vlf) - Veyon 라이센스 파일 (*.vlf) + Enter hostname + 호스트 이름을 입력하세요 - Remove license - 라이센스 제거 + Please enter a computer hostname whose group memberships to query: + 멤버 속성을 검색할 컴퓨터 호스트 이름을 입력하세요: - Do you really want to remove the selected license? - 선택된 라이센스를 제거하시겠습니까 ? + User login name attribute + 사용자 로긴이름 속성 - <N/A> - <N/A> + Configured attribute for user login name or computer hostname (OpenLDAP) + 사용자 로그인 또는 컴퓨터 호스트 이름 (OpenLDAP)의 속성 설정됨 - Invalid license file - 유효하지 않은 라이센스 파일 + Directory name + - Could not open the license file for reading! - 라이센스 파일을 읽을 수 없습니다! + Query options + 조회 옵션 - The selected license file does not contain valid data. - 선택된 라이센스 파일에 유효한 데이터가 없습니다. + Query nested user groups (supported by AD only) + 유저 그룹 중첩 조회(AD에서만 사용 가능) - The selected license file could not be verified. - 선택한 라이센스 파일을 검증할 수 없습니다. + Query timeout + - The selected license file is not valid for this installation. - 선택된 라이센스 파일을 이번 설치에 사용할 수 없습니다. + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. - 선택된 라이센스 파일의 유효기간이 지났습니다. + LDAP + LDAP - The license is already installed. - 이 라이센스는 이미 설치 되었습니다. + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + + LdapPlugin - Information - 정보 + Auto-configure the base DN via naming context + 기본 DN 을 명칭 기반으로 자동 설정함 - Installation ID - 설치 ID + Query objects from LDAP directory + 개체를 LADP 폴더에서 조회 - Addons available for licensing - + Show help about command + 명령어에 대한 도움말 보여줌 - Addon - 애드온 + Commands for configuring and testing LDAP/AD integration + LDAP/AD 통합을 설정하거나 제어하는 명령어 - - - LicensingPlugin - Show help for specific command - 특정 명령어에 대한 도움말 보여줌 + Basic LDAP/AD support for Veyon + Veyon 기본 LDAP/AD 지원 - Show all installed licenses - 설치된 모든 라이센스를 보여주기 + %1 (load computers and locations from LDAP/AD) + %1 (LDAP/AD에서 컴퓨터와 위치를 가져옴) - Add license file - 라이센스 파일을 추가 + %1 (load users and groups from LDAP/AD) + %1 (LDAP/AD에서 사용자와 그룹을 가져옴) - Remove installed license - 설치된 라이센스 제거 + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + 다음 형식에 맞는 LDAP url을 입력하세요 "ldap[s]://[user[:password]@]hostname[:port]" - -USAGE - -%1 add <LICENSE FILE> - - - -사용법 - -%1 add <LICENSE FILE> - - + No naming context attribute name given - falling back to configured value. + 네이밍 컨텍스트 속성의 이름이 없습니다 - 이전에 설정된 값으로 되돌립니다 - -USAGE - -%1 remove <LICENSE ID> - - - -사용법 - -%1 remove <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. + 베이스 DN을 조회할 수 없습니다. LDAP 설정을 확인하세요. - No certificate found with given ID - 주어진 ID에 해당하는 인증서가 발견되지 않음 + Configuring %1 as base DN and disabling naming context queries. + %1 을 기본 DN 으로 설정하고 네이밍 컨텍스트 조회를 비활성화 함. - <N/A> - <N/A> + Test binding to an LDAP server + - Licensing management - 라이센스 관리 + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + 제공된 사용자 이름 또는 패스워드가 틀립니다. 유효한 사용자 명 또는 패스워드를 사용하시거나 Veyon 설정기를 이용하여 다른 인증방법을 사용하시기 바랍니다. - Commands for managing license keys - 라이센스 키 관리용 명령어들 + LDAP bind + @@ -2726,18 +3098,26 @@ USAGE Custom PAM service for user authentication - + 사용자 인증용 커스텀 PAM 서비스 User authentication 사용자 인증 - Session management - 세션 관리 + User sessions + + + + Minimum session lifetime before server start + + + + User login + 유저 로긴 - Display manager users + Login key sequence @@ -2747,10 +3127,6 @@ USAGE Plugin implementing abstract functions for the Linux platform 리눅스 플래폼용 플러그인 실행용 추상화 함수 - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2769,14 +3145,14 @@ USAGE Configuration 설정 - - Disable balloon tooltips - 풍선 툴팁기능 해제 - Show icons only 아이콘만 보여주기 + + Disable tooltips + + MainWindow @@ -2824,10 +3200,6 @@ USAGE About Qt Qt 정보 - - Authentication impossible - 인증 불가 - Configuration not writable 설정 저장 불가 @@ -2888,10 +3260,6 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. 설정을 저장할 수 없다는 로컬 설정 백엔드가 보고됨! %1 Configurator 를 관리자 권한으로 실행하세요. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - 인증 키 화일이 없거나 현재의 키 화일이 오래되었습니다. %1 Configurator 를 이용하여 새로운 키를 생성하세요. 다른 방법으로는 %1 Configurator 를 사용하여 로그온 인증을 설치하세요. 그렇지 않으면 %1을 사용하여 컴퓨터를 접속할 수 없습니다 - Access denied 접근 거부됨 @@ -2924,10 +3292,6 @@ USAGE Search users and computers 사용자 또는 컴퓨터 검색 - - Adjust optimal size - 최적 크기로 조정 - Align computers to grid 컴퓨터를 그리드에 맞춤 @@ -2966,12 +3330,54 @@ USAGE Use custom computer arrangement - + 사용자가 정의한 컴퓨터 배치를 사용 Locations && computers 위치 && 컴퓨터 + + Authentication + 인증 + + + Adjust size of computer icons automatically + + + + Slideshow + + + + Spotlight + + + + Veyon Master + + + + Locations & computers + 위치 및 컴퓨터들 + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + + + + Load computer positions + + + + Save computer positions + + MasterConfigurationPage @@ -2979,10 +3385,6 @@ USAGE Directories 디렉토리 - - ... - ... - User configuration 사용자 설정 @@ -3067,6 +3469,10 @@ USAGE Only user name 전용 사용자 이름 + + Only last part of user name + + Only computer name 전용 컴퓨터 이름 @@ -3097,7 +3503,7 @@ USAGE Allow adding hidden locations manually - + 수동으로 숨겨진 위치 추가를 허용 Hide empty locations @@ -3105,181 +3511,191 @@ USAGE Show confirmation dialog for potentially unsafe actions - + 안전하지 않은 작동에 대한 확인 대화 창 보여주기 Perform access control - + 접근제어 실행 Automatically select current location + 자동으로 현재 위치를 선택 + + + Automatically open computer select panel + 컴퓨터 선택 패너을 자동으로 열기 + + + Use modern user interface (experimental) - Automatically adjust computer thumbnail size + Thumbnail spacing - Automatically open computer select panel + px - - - MonitoringMode - Monitoring - 모니터링 + Hide local session + - Builtin monitoring mode - 게시판형 모니터링 모드 + Auto + 자동 - This mode allows you to monitor all computers at one or more locations. + Thumbnail aspect ratio + + + + Automatically adjust computer icon size + + + + Open feature windows on the same screen as the main window + + + + Configuration templates + + + + Image quality in monitoring mode + + + + Highest + + + + High - - - NetworkDiscoveryConfigurationPage - Network discovery - 네트워크 발견 + Medium + + + + Low + - Mode - 모드 + Lowest + - Scan network ranges - 네트워크 범위 검색 + Remote access image quality + - e.g. 192.168.1.0/24 - e.g. 192.168.1.0/24 + Advanced + - Scan all subnets of computer - 컴퓨터의 모든 서브넷 검색 + Computer name source + - Scan custom subnet - 사용자 서브넷 검색 + Default + - Scan sessions on local computer - 로컬 컴퓨터 스캔 세션 + Host address + 호스트 주소 - Test - 테스트 + Session client address + - Network ranges - 네트워크 범위 + Session client name + - Add new group - 새 그룹 추가 + Session host name + - Remove selected group - 선택된 그룹 삭제 + Session metadata + - Groups - 그룹 + Full name of user + - First address - 첫번째 주소 + User login name + - Last address - 마지막 주소 + Computer UID role + - Add new network range - 새로운 네트워크 범위 추가 + Session meta data hash + - Remove selected network range - 선택된 네트워크 범위 삭제 + Always expand all locations + - Parallel scans - 병행 스캔 + Image quality + + + + MonitoringMode - Scan timeout - 시간 시간 초과 + Monitoring + 모니터링 - ms - ms + Builtin monitoring mode + 게시판형 모니터링 모드 - Session scan limit - 세션 스캔 제한 + This mode allows you to monitor all computers at one or more locations. + 이모드는 하나 또는 많은 위치에 있는 모든 컴퓨터들의 모니터를 가능하게 합니다. - Options - 옵션 + Query application version of the server + - Reverse lookup discovered IP addresses to host names - 발견된 IP 주소를 호스트 이름으로 검색하기 + Query active features + - New location - 새로운 위치 + Query properties of remotely available screens + - NetworkDiscoveryDirectory + NestedNetworkObjectDirectory - Scanning... - 스캐닝... - - - Discovered computers - 검색된 컴퓨터들 + All directories + - NetworkDiscoveryPlugin - - Show help for specific command - 특정 명령어에 대한 도움말 보여줌 - - - Scan a subnet - 서브넷 스캔 - - - -USAGE - -%1 scan [<SUBNET>] - - - -사용법 - -%1 scan [<SUBNET>] - - - + NetworkObjectDirectoryConfigurationPage - Network object directory which automatically discovers computers in the network - 네트워크의 컴퓨터들을 자동으로 검색하기 위한 네트워크 오브젝트 폴더 + Update interval: + 화면업데이트 간격: - Network discovery (scan network for Veyon clients) - 네트워크 검색(Veyon 클라이언트용 네트워크 검색) + seconds + + + + NetworkObjectDirectoryConfigurationPageTab - Commands for managing the network discovery directory - 네트워크 검색 폴더를 제어하기 위한 명령어들 + Enabled + @@ -3315,32 +3731,44 @@ USAGE Name: 이름: + + Website name + + - PasswordDialog + PluginCommands - Username - 사용자 이름 + List names of all installed plugins + - Password - 암호 + Show table with details of all installed plugins + - Veyon Logon - Veyon 로그온 + Name + 이름 - Authentication error - 인증 에러 + Description + - Logon failed with given username and password. Please try again! - 입력한 사용자이름과 패스워드로 로그온 실패. 다시 시도하세요! + Version + - Please enter your username and password in order to access computers. - 컴퓨터에 접근 하려면 당신의 사용자이름과 패스워드를 입력하세요 + UID + + + + Plugin-related CLI operations + + + + Commands for managing plugins + @@ -3385,10 +3813,6 @@ USAGE Do you really want to reboot the selected computers? 선택된 컴퓨터를 리부팅하시겠습니까 ? - - Do you really want to power down the selected computer? - 선택된 컴퓨터 파워를 끄시겠습니까 ? - Power on a computer via Wake-on-LAN (WOL) Wake-on-LAN(WOL)을 사용하여 컴퓨터 파워를 켬 @@ -3437,6 +3861,20 @@ USAGE The computer will be powered down in %1 minutes, %2 seconds. Please save your work and close all programs. + 이컴퓨터는 %1 분, %2 초 후에 전원이 꺼집니다. + +작업을 저장하고 모든 프로그램을 닫기 바랍니다. + + + Do you really want to reboot <b>ALL</b> computers? + + + + Do you really want to power down <b>ALL</b> computers? + + + + Do you really want to power down the selected computers? @@ -3448,7 +3886,7 @@ Please save your work and close all programs. Please specify a timeout for powering down the selected computers: - + 선택된 컴퓨터의 전원을 끝때까지의 시간을 입력하세요. minutes @@ -3485,14 +3923,25 @@ Please save your work and close all programs. Remote view or control a computer 감시화면 또는 컴퓨터 제어 - - Please enter the hostname or IP address of the computer to access: - 연결할 컴퓨터의 호스트 이름 또는 IP를 입력하세요: - Show help about command 명령어에 대한 도움말 보여줌 + + Exchange clipboard contents + + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + + + RemoteAccessPage + + Remote access: %1 + + RemoteAccessWidget @@ -3500,6 +3949,10 @@ Please save your work and close all programs. %1 - %2 Remote Access %1 - %2 원격 접근 + + %1 - %2 - %3 Remote Access + + RemoteAccessWidgetToolBar @@ -3555,10 +4008,6 @@ Please save your work and close all programs. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - %1에 연결중 - Connected. 연결됨 @@ -3571,58 +4020,17 @@ Please save your work and close all programs. Exit 나가기 - - - Routing - - Control internet access by modifying routing table - 라우팅 테이블을 수정하여 인터넷 접속 제어 - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - 인터넷 접속을 제한하기 위해 기본 루트 제거 - - - Add custom route to block internet - 인터넷 접근 제한하려는 사용자 루트 추가 - - - Destination - 목적지 - - - Gateway - 게이트 웨이 - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - 선택된 컴퓨터(들)에서 실행할 명령어 또는 프로그램을 입력하세요. 각각의 라인으로 다수의 프로그램/명령어를 구분할 수 있습니다. - - - Run programs - 프로그램 실행 - - - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - 예. "C:\Program Files\VideoLAN\VLC\vlc.exe" - - Name: - 이름: + Connecting... + - Remember and add to program menu - 기억하고 프로그램 메뉴에 추가하기 + Select screen + - e.g. VLC - 예: VLC + All screens + @@ -3643,6 +4051,18 @@ Please save your work and close all programs. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. 사용자의 주의를 끌기 위해서 이버튼을 사용하여 사용자의 컴퓨터를 잠글수 있습니다. 이 모드에서 모든 입력 장치는 잠기며 화면은 검은색이 됩니다. + + Lock input devices + + + + Unlock input devices + + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + Screenshot @@ -3658,6 +4078,10 @@ Please save your work and close all programs. Screenshot 화면캡쳐 + + Could not open screenshot file %1 for writing. + + ScreenshotFeaturePlugin @@ -3682,6 +4106,13 @@ Please save your work and close all programs. 컴퓨터의 화면을 캡쳐하고 로컬에 저장함 + + ScreenshotManagementPage + + Screenshots + 화면캡쳐 + + ScreenshotManagementPanel @@ -3709,144 +4140,241 @@ Please save your work and close all programs. 보기 - Delete - 삭제 + Delete + 삭제 + + + Screenshot + 화면캡쳐 + + + Do you really want to delete all selected screenshots? + + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + + + + User has denied access + + + + User confirmed access + + + + + ServiceConfigurationPage + + General + 일반사항 + + + Autostart + 자동시작 + + + Hide tray icon + 트레이 아이콘 숨기기 + + + Start service + 서비스 시작 + + + Stopped + 멈춤 + + + Stop service + 서비스 중지 + + + State: + 상태: + + + Enable firewall exception + 방화벽 예외 적용 활성화 + + + Allow connections from localhost only + 로컬 호스트 연결만 허용함 + + + VNC server + VNC server + + + Plugin: + 플러그인: + + + Restart %1 Service + %1 서비스 재시작 + + + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + 모든 설정이 성공적으로 저장됨. %1 서비스가 작동하려면 재시작해야 합니다. 지금 재시작 할까요 ? + + + Running + 실행중 + + + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. + 이 옵션을 활성화 시키면 서비스가 컴퓨터의 모든 대화 세션용 서버 프로세스를 실행합니다. +일반적으로 터미널 서버를 지원하는데 필요합니다. + + + Show notification on remote connection + 원격 연결이면 알림 보이기 - - - ServiceConfigurationPage - General - 일반사항 + Show notification when an unauthorized access is blocked + 허가되지 않은 접속이 차단되었을때 알려줌 - Autostart - 자동시작 + Maximum session count + - Hide tray icon - 트레이 아이콘 숨기기 + Network port numbers + - Start service - 서비스 시작 + Veyon server + - Stopped - 멈춤 + Internal VNC server + - Stop service - 서비스 중지 + Feature manager + - State: - 상태: + Demo server + 데모 서버 - Network - 네트워크 + Miscellaneous network settings + - Demo server port - 데모 서버 포트 + Session mode + - Enable firewall exception - 방화벽 예외 적용 활성화 + Local session mode (single server instance for primary local session) + - Allow connections from localhost only - 로컬 호스트 연결만 허용함 + Active session mode (single server instance for active local or remote session) + - Internal VNC server port - 내부 VNC server 포트 + Multi session mode (distinct server instance for each local and remote desktop session) + - VNC server - VNC server + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + - Plugin: - 플러그인: + Miscellaneous settings + - Restart %1 Service - %1 서비스 재시작 + Disable clipboard synchronization + - All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - 모든 설정이 성공적으로 저장됨. %1 서비스가 작동하려면 재시작해야 합니다. 지금 재시작 할까요 ? + Session metadata + - Running - 실행중 + Content + - Feature manager port - 속성 관리 포트 + None + 없음 - Primary service port - 주 서비스 포트 + Value of an environment variable + - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. - 이 옵션을 활성화 시키면 서비스가 컴퓨터의 모든 대화 세션용 서버 프로세스를 실행합니다. -일반적으로 터미널 서버를 지원하는데 필요합니다. + Value of a registry key + - Show notification on remote connection - 원격 연결이면 알림 보이기 + Environment variable name: + - Multi session mode (for terminal and remote desktop servers) + Registry key name: - Show notification when an unauthorized access is blocked + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) ServiceControl - Starting service %1 - 서비스 %1 시작중 - - - Stopping service %1 - 서비스 %1 중지중 - - - Registering service %1 - 서비스 %1 를 등록중 + Service control + 서비스 제어 - Unregistering service %1 - 서비스 %1 를 등록 해제중 + Starting %1 + - Service control - 서비스 제어 + Stopping %1 + - - - ServiceControlPlugin - Service is running - 서비스 실행중 + Restarting %1 + - Service is not running - 서비스 실행중이 아님 + Registering %1 + - Configure and control Veyon service - Veyon 서비스 설정및 제어 + Unregistering %1 + + + + ServiceControlCommands Register Veyon Service Veyon 서비스 등록 @@ -3871,13 +4399,25 @@ Typically this is required to support terminal servers. Query status of Veyon Service Veyon 서비스 상태 조회 + + Service is running + 서비스 실행중 + + + Service is not running + 서비스 실행중이 아님 + + + Configure and control Veyon service + Veyon 서비스 설정및 제어 + Commands for configuring and controlling Veyon Service Veyon 서비스 설정 및 제어 명령어 - ShellCommandLinePlugin + ShellCommands Run command file 명령어행 실행 @@ -3887,14 +4427,100 @@ Typically this is required to support terminal servers. 화일 "%1" 이 없음! - Interactive shell and script execution for Veyon Control - Veyon 제어용 대화형 쉘과 스크립트 실행 + Interactive shell and script execution for Veyon CLI + Commands for shell functionalities 쉘 기능용 명령어들 + + SlideshowPanel + + Previous + + + + Start/pause + + + + Next + + + + Duration: + + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + + + + Remove selected computers + + + + Update computers in realtime + + + + Spotlight + + + + Please select at least one computer to add. + + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + + + StartAppDialog + + Start application + + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + 예. "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + + + + Application name + + + + Name: + 이름: + + + e.g. VLC + 예: VLC + + SystemTrayIcon @@ -3917,11 +4543,11 @@ Typically this is required to support terminal servers. TestingCommandLinePlugin Test internal Veyon components and functions - + 내부 Veyon 컴포넌트 및 기능을 시험 Commands for testing internal components and functions of Veyon - + Veyon의 내부 컴포넌트 및 기능을 시험하는 명령어들 @@ -3931,8 +4557,8 @@ Typically this is required to support terminal servers. 문자 메세지 보내기 - Use the field below to type your message which will be sent to all selected users. - 선택된 사용자에세 메세지를 보내려면 아래 빈칸에 내용을 입력하세요 + Please enter your message which send to all selected users. + @@ -3980,23 +4606,39 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer 윈도8 또는 상위버전에서 데스크탑 복제엔진 활성화 + + Maximum CPU usage + + - UserConfig + UserLoginDialog - No write access - 쓰기 권한 없음 + User login + 유저 로긴 - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - 개인 설정을 저장할 수 없음. %1 설정자를 이용하여 사용자 설정 화일을 경로를 확인하세요 + Please enter a username and password for automatic login on all computers. + 자동으로 모든 컴퓨터에 로긴하려면 유저명과 패스워드를 입력하세요 + + + Username + 사용자 이름 + + + Password + 암호 - UserSessionControl + UserSessionControlPlugin - User session control - 사용자 세션제어 + Log in + 로긴 + + + Click this button to log in a specific user on all computers. + 이 버튼을 클릭하여 모든 컴퓨터에 로긴 합니다 Log off @@ -4014,6 +4656,14 @@ Typically this is required to support terminal servers. Do you really want to log off the selected users? 선택한 유저를 로그오프 하시겠습니까? + + User session control + 사용자 세션제어 + + + Do you really want to log off <b>ALL</b> users? + + VeyonCore @@ -4065,10 +4715,6 @@ Typically this is required to support terminal servers. ERROR 에러 - - licensed for - 에게 사용허가 됨 - USAGE 사용법 @@ -4085,19 +4731,31 @@ Typically this is required to support terminal servers. WARNING 경고 + + Authentication test + 인증 테스트 + + + Screen %1 + + - VeyonServiceControl + VeyonMaster - Veyon Service - Veyon Service + No write access + 쓰기 권한 없음 + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + 개인 설정을 저장할 수 없음. %1 설정자를 이용하여 사용자 설정 화일을 경로를 확인하세요 - VncView + VeyonServiceControl - Establishing connection to %1 ... - ... %1 로 연결 중입니다 + Veyon Service + Veyon Service @@ -4135,16 +4793,40 @@ Typically this is required to support terminal servers. Hide desktop - + 데스크탑 숨김 User authentication - 사용자 인즘 + 사용자 인증 Use alternative user authentication mechanism 대체 사용자 인증 메커니즘 사용 + + User login + 유저 로긴 + + + Input start delay + 입력 시작 지연 + + + Simulated key presses interval + 시뮬레이션 키입력 간격 + + + Confirm legal notice (message displayed before user logs in) + + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4153,7 +4835,7 @@ Typically this is required to support terminal servers. 윈도우즈 플래폼용 플러그인 실행용 추상화 함수 - Plugin implementing specific functions for the Windows platform + Internal display @@ -4163,29 +4845,33 @@ Typically this is required to support terminal servers. The service "%1" is already installed. 서비스 "%1"은 이미 설치되어 있습니다. - - The service "%1" could not be installed. - 서비스 "%1"을 설치할 수 없습니다. - The service "%1" has been installed successfully. 서비스 "%1"을 성공적으로 설치했습니다. - - The service "%1" could not be uninstalled. - 서비스 "%1"을 제거할 수 없습니다. - The service "%1" has been uninstalled successfully. 서비스 "%1"을 성공적으로 제거했습니다. - The start type of service "%1" could not be changed. + Service "%1" could not be found. + 서비스 "%1"을 찾을 수 없습니다. + + + The service "%1" could not be installed (error %2). - Service "%1" could not be found. - 서비스 "%1"을 찾을 수 없습니다. + Could not change the failure actions config for service "%1" (error %2). + + + + The service "%1" could not be uninstalled (error %2). + + + + The start type of service "%1" could not be changed (error %2). + diff --git a/translations/lt.ts b/translations/veyon_lt.ts similarity index 57% rename from translations/lt.ts rename to translations/veyon_lt.ts index a90c42a59..0071a3e1d 100644 --- a/translations/lt.ts +++ b/translations/veyon_lt.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -15,44 +15,45 @@ About Veyon - + Apie Veyon Contributors - + Autoriai Version: - + Versija Website: - + Tinklalapis: Current language not translated yet (or native English). If you're interested in translating Veyon into your local or another language or want to improve an existing translation, please contact a Veyon developer! - + Dabartinė naudojama kalba dar neišversta (arba pagrindinė yra Anglų) +Jeigu domina Veyon programos vertimas į vietinę ar kitą kalbą, arba norite patobulinti esamą vertimą, susisiekite su Veyon kūrėjais About %1 %2 - + Apie %1 %2 Support Veyon project with a donation - + Paremti Veyon projektą AccessControlPage Computer access control - + Kompiuterio prieigos valdymas Grant access to every authenticated user (default) - + Suteikti prieigą kiekvienam prijungtam vartotojui (numatytasis) Test @@ -60,94 +61,89 @@ If you're interested in translating Veyon into your local or another langua Process access control rules - + Apdoroti prieigos valdymo taisykles User groups authorized for computer access - + Vartotojų grupės kurioms suteikta prieiga prie kompiuterio Please add the groups whose members should be authorized to access computers in your Veyon network. - + Pridėkite grupes kurių nariai kuriems turėtų būti leista prieiti prie kompiuterių esančių Veyon tinkle Authorized user groups - + Autorizuotų vartotojų grupė All groups Visos grupės - - ... - ... - Access control rules - + Prieigos valdymas Add access control rule - + Pridėti prieigos valdymo taisyklę Remove access control rule - + Pašalinti prieigos valdymo taisyklę Move selected rule down - + Pakelti pasirinktą taisyklę žemyn Move selected rule up - + Pakelti pasirinktą taisyklę aukštyn Edit selected rule - + Redaguoti pasirinktą taisyklę Enter username - + Įveskite vartotojo vardą Please enter a user login name whose access permissions to test: - + Įveskite vartotojo vardą kurio prieigos teises tikrinsite: Access allowed - + Prieiga leidžiama The specified user is allowed to access computers with this configuration. - + Pasirinktam vartotojui leidžiama prieiga prie kompiuteriu su šia konfiguracija. Access denied - + Prieiga uždrausta The specified user is not allowed to access computers with this configuration. - + Pasirinktam vartotojui neleidžiama prieiga prie kompiuteriu su šia konfiguracija. Enable usage of domain groups - + Įgalinti domenų grupių naudojimą User groups backend: - - - - Missing user groups backend - + Vartotojų grupių valdymas: - No default user groups plugin was found. Please check your installation! - + Restrict access to members of specific user groups + Apriboti prieigą speficinių grupių nariams + + + AccessControlProvider - Restrict access to members of specific user groups + Provider for access control features @@ -155,7 +151,7 @@ If you're interested in translating Veyon into your local or another langua AccessControlRuleEditDialog Edit access control rule - + Redaguoti prieigos valdymo taisyklę General @@ -163,102 +159,174 @@ If you're interested in translating Veyon into your local or another langua enter a short name for the rule here - + įveskite trumpą taisyklės pavadinimą Rule name: - + Taisyklės pavadinimas: enter a description for the rule here - + įveskite trumpą taisyklės aprašymą Rule description: + Taisyklės aprašymas + + + Conditions + Sąlygos + + + If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. + Jeigu daugiau negu viena sąlyga yra aktyvuota kiekviena sąlyga turi atitikti nustatytus kriterijus, kad taisyklė veiktų (loginis IR). Jeigu viena iš kelių salygų atitinka (loginis ARBA). Prašome sukurti kelias prieigos valdymo taisykles. + + + Action + Veiksmai + + + Allow access + Suteikti prieigą + + + Deny access + Nesuteikti prieigos + + + Ask logged on user for permission + Prašyti prisijungusio vartotojo leidimo + + + None (rule disabled) + Taisyklė išjungta + + + Accessing user + Prisijungiama prie vartotojo + + + Accessing computer + Prisijungiama prie kompiuterio + + + Always process rule and ignore conditions + Visados vykdyti šią taisyklę ir ignoruoti sąlygas + + + Accessing computer and local computer - Invert all conditions ("is/has" interpreted as "is/has not") + User being accessed - Conditions + is logged in locally - is member of group + is logged in remotely - Accessing computer is localhost + No user is logged in locally - Accessing user is logged on user + One or multiple users are logged in locally - Accessing user is already connected + No user is logged in remotely - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. + One or multiple users are logged in remotely - Action + is located at + yra šioje vietoje + + + is not located at - Allow access + are located at the same location - Deny access + are not located the same location - Ask logged on user for permission + is member of group + yra grupės narys + + + is not member of group - None (rule disabled) + is authenticated via - Accessing user + is not authenticated via - Accessing computer + has one or more groups in common with user being accessed - Local (logged on) user + has no groups in common with user being accessed - Local computer + equals user being accessed - Always process rule and ignore conditions + is different from user being accessed - No user logged on + is already connected - Accessing user has one or more groups in common with local (logged on) user + is not connected - Accessing computer and local computer are at the same location + is local computer - is located at + is not local computer + + + + Computer being accessed + + + + Session being accessed is a user session + + + + Session being accessed is a login screen + + + + Local computer is already being accessed + + + + Local computer is not yet being accessed @@ -266,84 +334,86 @@ If you're interested in translating Veyon into your local or another langua AccessControlRulesTestDialog Access control rules test - + Prieigos kontrolės taisyklių testavimas Accessing user: - + Prisijungiantis vartotojas: Local computer: - + Vietinis kompiuteris: Accessing computer: - + Prisijungiantis kompiuteris: Please enter the following user and computer information in order to test the configured ruleset. - + Įveskite vartotojo ir kompiuterio informaciją jeigu norite patikrinti sukonfigūruotą taisyklių rinkinį Local user: - + Vietinis vartotojas: Connected users: - + Prijungti vartotojai: The access in the given scenario is allowed. - + Prieiga šiomis salygomis yra leidžiama. The access in the given scenario is denied. - + Prieiga šiomis salygomis yra draudžiama The access in the given scenario needs permission of the logged on user. - + Prieiga šiomis salygomis reikalauja patvirtinimo iš prisijungusio vartotojo - ERROR: Unknown action - + Test result + Testo rezultatai - Test result + Authentication method + Autorizavimo metodas + + + There is no matching rule with a valid action. The access is therefore denied. - AndroidPlatformConfigurationPage + AuthKeysConfigurationWidget - Android - + Introduction + Įvadas - General - Pagrindinis + Please perform the following steps to set up key file authentication: + Atlikite šiuos veiksmus, kad nustatytumėte prieigą naudojant rakto failą - - - AndroidPlatformPlugin - Plugin implementing specific functions for the Android platform - + 1) Create a key pair on the master computer. + 1) Sukurkite raktų porą pagrindiniame kompiuteryje - - - AuthKeysConfigurationPage - Authentication keys - + 2) Set an access group whose members should be allowed to access other computers. + 2) Nustatykite prieigos grupę, kurios nariams bus leista pasiekti kitus kompiuterius. - Introduction - + 3) Export the public key and import it on all client computers with the same name. + 3) Eksportuokite viešajį raktą ir importuokite visuose klientų kompiuteriuose naudojant tą patį vardą. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Daugiau informacijos galite rasti <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administratoriaus Instrukcijoje</a> Key file directories - + Direktorija raktų failams Public key file base directory @@ -351,97 +421,78 @@ If you're interested in translating Veyon into your local or another langua Private key file base directory - Katalogas kuriame saugomas privatus raktas + Privataus rakto saugojimo direktorija - ... - ... + Available authentication keys + Galimi autorizavimo raktai - Available authentication keys - + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Autorizavimo raktų pora susideda iš dviejų kriptografinių raktų privataus ir viešojo. +Privatus raktas leidžia pagrindiniam kompiuteriui pasiekti klientų kompiuterius +Svarbu, kad tik autorizuoti naudotojai turėtų prieigą prie privataus rakto failo +Viešasis raktas skirtas kliento kompiuteriams patvirtinti įeinančio ryšio užklausą. Create key pair - + Sukurti raktų porą Delete key - + Ištrinti raktą Import key - + Importuoti raktą Export key - + Eksportuoti raktą Set access group - + Nustatyti prieigos grupę Key files (*.pem) - + Raktų failai (*.pem) Authentication key name - + Raktų failo vardas Please enter the name of the user group or role for which to create an authentication key pair: - + Įveskite naudotojų grupės vardą arba rolę kuriai bus kuriama raktų pora: Do you really want to delete authentication key "%1/%2"? - + Ar tikrai norite ištrinti prieigos raktą "%1/%2"? Please select a key to delete! - - - - Please enter the name of the user group or role for which to import the authentication key: - + Pasirinkite raktą kurį norite ištrinti! Please select a key to export! - + Pasirinkite raktą kurį norite eksportuoti Please select a user group which to grant access to key "%1": - + Pasirinkite naudotojų grupę kuriai bus suteikta prieiga prie rakto "%1": Please select a key which to set the access group for! - - - - Please perform the following steps to set up key file authentication: - - - - 1) Create a key pair on the master computer. - - - - 2) Set an access group whose members should be allowed to access other computers. - - - - 3) Export the public key and import it on all client computers with the same name. - - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - + Pasirinkite vartotojų grupę kuriai norite nustatyti prieigos grupę - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. @@ -449,230 +500,246 @@ The public key is used on client computers to authenticate incoming connection r AuthKeysManager Please check your permissions. - + Patikrinkite savo leidimus. Key name contains invalid characters! - + Rakto varde yra neleistinų simbolių. Invalid key type specified! Please specify "%1" or "%2". - + Pasirinktas negalimas rakto tipas! Pasirinkite "%1" arba "%2". Specified key does not exist! Please use the "list" command to list all installed keys. - + Nurodytas raktas neegzistuoja! Pasinaudokite komanda "list" , kad peržiūrėtumėte visus įdiegtus raktus One or more key files already exist! Please delete them using the "delete" command. - + Vienas ar daugiau raktų failai jau egzistuoja! Ištrinkite juos naudojantis "delete" komanda. Creating new key pair for "%1" - + Sukurkite naują raktų porą "%1" Failed to create public or private key! - + Nepavyko sukurti viešojo arba privataus rakto Newly created key pair has been saved to "%1" and "%2". - + Naujai sukurta raktų pora buvo išsaugota: "%1" ir "%2". Could not remove key file "%1"! - + Nepavyko ištrinti rakto failo "%1"! Could not remove key file directory "%1"! - + Nepavyko ištrinti rakto failo direktorijos "%1"! Failed to create directory for output file. - + Nepavyko sukurti direktorijos išvesties failams File "%1" already exists. - + Failas "%1" jau egzistuoja Failed to write output file. - + Nepavyko įrašyti į išvesties failą. Key "%1/%2" has been exported to "%3" successfully. - + Raktas "%1/%2" eksportuotas į "%3" sėkmingai. Failed read input file. - + Nepavyko nuskaityti įvesties failo File "%1" does not contain a valid private key! - + Failas "%1" neturi tinkamo privataus rakto File "%1" does not contain a valid public key! - + Failas "%1" neturi tinkamo viešo rakto Failed to create directory for key file. - + Nepavyko sukurti direktorijos raktų failams. Failed to write key file "%1". - + Nepavyko įrašyti į rakto failą "%1". Failed to set permissions for key file "%1"! - + Nepavyko nustatyti prieigos teisių rakto failui "%1"! Key "%1/%2" has been imported successfully. Please check file permissions of "%3" in order to prevent unauthorized accesses. - + Raktai "%1/%2" buvo sėkmingai importuoti. Patikrinkite failų teises "%3" , kad būtų apribota neleistina prieiga. Failed to convert private key to public key - + Nepavyko konvertuoti privataus rakto į viešajį. Failed to create directory for private key file "%1". - + Nepavyko sukurti direktorijos privataus rakto failui "%1". Failed to save private key in file "%1"! - + Nepavyko išsaugoti privataus rakto "%1". Failed to set permissions for private key file "%1"! - + Nepavyko nustatyti teisių privataus rakto failui "%1"! Failed to create directory for public key file "%1". - + Nepavyko sukurti direktorijos viešojo rakto failui "%1". Failed to save public key in file "%1"! - + Nepavyko išsaugoti viešojo rakto "%1". Failed to set permissions for public key file "%1"! - + Nepavyko nustatyti prieigos teisių viešojo rakto failui "%1"! Failed to set owner of key file "%1" to "%2". - + Nepavyko nustatyti rakto failo šeimininko "%1" to "%2". Failed to set permissions for key file "%1". - + Nepavyko nustatyti prieigos teisių rakto failui "%1"! Key "%1" is now accessible by user group "%2". - + Raktas "%1" dabar yra pasiekiamas vartotojų grupės: "%2". <N/A> - + <N/A> Failed to read key file. - + Nepavyko nuskaityti rakto failo AuthKeysPlugin Create new authentication key pair - + Sukurti naują prieigos raktų porą Delete authentication key - + Ištrinti prieigos raktą List authentication keys - + Atvaizduoti prieigos raktus Import public or private key - + Importuoti privatujį ar viešajį raktą Export public or private key - + Eksportuoti privatujį ar viešajį raktą Extract public key from existing private key - + Gauti viešajį raktą iš esamo privataus rakto Set user group allowed to access a key - + Nustatyta vartotojų grupė turi prieigą prie rakto. KEY - + RAKTAS ACCESS GROUP - + PRIEIGOS GRUPĖ This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. - + Ši komanda pakeičia failo prieigos teises į <KEY> tam, kad tik ši vartotojų grupė <ACCESS GROUP> turi skaitymo teises. NAME - + VARDAS FILE - + FAILAS This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - + Ši komanda eksportuoja prieigos raktą <KEY> į <FILE>. Jeigu <FILE> nėra nurodytas, vardas bus sukurtas iš vardo ir tipo <KEY>. This command imports the authentication key <KEY> from <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - + Ši komanda importuoja prieigos raktą <KEY> į <FILE>. Jeigu <FILE> nėra nurodytas, vardas bus sukurtas iš vardo ir tipo <KEY>. This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - - - - Please specify the command to display help for! - + Ši komanda parodo visus galimus prieigos raktus, kurie yra sukonfigūruoti raktų direktorijoje. Jeigu opcija "%1" yra užpildyta, lentelė su rakto duomenimis bus parodyta. Ne visos detalės gali būti rodomos jeigu raktas yra nepasiekiamas, pavyzdžiui dėl teisių trūkumo. TYPE - + TIPAS PAIR ID - - - - Command line support for managing authentication keys - + POROS ID Commands for managing authentication keys - + Komandos prieigos raktų valdymui This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. - + Ši komanda sukuria naują prieigos raktą su vardu <NAME> ir išsaugo privatų ir viešajį raktus į sukonfigūruotą raktų direktoriją. Parametras turi būti rakto vardas kuris gali būti sudarytas tik iš raidžių. This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. - + Ši komanda ištrina prieigos raktą <KEY> iš sukonfigūruotų raktų direktorijos. Pastaba: ištrynus raktą jis negali būti atkurtas. This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. - + Ši komanda sugeneruoja viešajį raktą iš privataus rakto <KEY> ir išsaugo kaip atitinkamą viešajį raktą. Kai bus nustatomas kitas pagrindinis kompiuteris, užtenka perkelti tik privatujį raktą. Viešasis raktas gali būti sugeneruotas iš privataus rakto. + + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + Prieigos raktų failai nėra tinkamai nustatyti šiame kompiuteryje. Sukurkite naujus raktų failus, arba pasirinkite kitą prieigos metodą naudojant Veyon Configurator + + + Key file authentication + Autorizuotis naudojant pasiekiamumo raktą + + + Key file + Rakto failas + + + Please specify the key name (e.g. "teacher/public") as the first argument. + + + + Please specify the command to display help for. + + + + The specified command does not exist or no help is available for it. + @@ -687,18 +754,161 @@ The public key is used on client computers to authenticate incoming connection r Access group - + Prieigos grupė Pair ID + Poros ID + + + + AuthLdapConfigurationWidget + + General + Pagrindinis + + + Username to bind DN mapping: + + + + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + AuthLdapDialog + + Veyon Logon + Veyon Prisijungimas + + + Please enter your domain/LDAP username and password in order to access computers. + Įveskite savo domeno/LDAP vartotojo vardą ir slaptažodį, kad pasiekti kompiuterius. + + + Username + Naudotojo vardas + + + Password + Slaptažodis + + + Authentication error + Autorizacijos klaida + + + Logon failed with given username and password. Please try again! + Nepavyko prisijungti su įvestu naudotojo vardu bei slaptažodžiu. Pabandykite dar kartą! + + + + AuthLogonDialog + + Veyon Logon + Veyon Prisijungimas + + + Please enter your username and password in order to access computers. + Įveskite savo vartotojo vardą ir slaptažodį, kad pasiektumėte kompiuterius + + + Username + Vartotojo vardas + + + Password + Slaptažodis + + + Authentication error + Autorizacijos klaida + + + Logon failed with given username and password. Please try again! + Nepavyko prisijungti naudojant įvestus vartotojo vardą ir slaptažodį. Pabandykite dar kartą + + + + AuthLogonPlugin + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Pateiktas vartotojo vardas ar slaptažodis yra neteisingas/i. Įveskite teisingus prisijungimo duomenis, arba perjunkite į kitą autorizavimo metodą naudojant Veyon Configurator + + + Logon authentication + Autorizacija prisijungiant į sistemą + + + Logon + Prisijungimas + + + + AuthSimpleDialog + + Veyon Logon + Veyon Prisijungimas + + + Please enter the Veyon password: + Įveskite Veyon slaptažodį + + + Authentication error + Autorizacijos klaida + + + Logon failed with given password. Please try again! + Prisijungimas su pateiktu slaptažodžiu nepavyko. Bandykite dar kartą + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + Įvestas slaptažodis yra neteisingas. Įveskite teisingą slaptažodį, arba pasirinkite kitą prieigos metodą, naudojant Veyon Configurator + + + Simple password authentication + Paprastas slaptažodio autorizavimas + + + Simple password + Slaptažodis + + + + AuthenticationPage + + Authentication is set up properly on this computer. + Autorizacija nustatyta tinkamai šiame kompiuteryje. + + + + AuthenticationPageTab + + Enabled + Įgalintas + + + Test + Testuoti + + + + BuiltinDirectoryConfiguration + + Builtin directory + Standartinė direktorija + + BuiltinDirectoryConfigurationPage Computers - + Kompiuteriai Name @@ -706,7 +916,7 @@ The public key is used on client computers to authenticate incoming connection r Host address/IP - + Tinklo adresas/IP MAC address @@ -714,42 +924,42 @@ The public key is used on client computers to authenticate incoming connection r Add new computer - + Pridėti naują kompiuterį Remove selected computer - + Ištrinti pažymėtą kompiuterį New computer - + Naujas kompiuteris Builtin directory - - - - Locations & computers - + Standartinė direktorija Locations - + Vietos Add new location - + Pridėti naują vietą Remove selected location - + Ištrinti pasirinktą vietą - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + New location + Nauja vieta + + + Directory name - New location + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. @@ -757,19 +967,19 @@ The public key is used on client computers to authenticate incoming connection r BuiltinDirectoryPlugin Show help for specific command - + Parodyti specifinės komandos pagalbą Import objects from given file - + Importuoti objektus iš failo Export objects to given file - + Eksportuoti pasirinktus objektus į failą Invalid type specified. Valid values are "%1" or "%2". - + Nurodytas neteisingas tipas. Tinkamos vertės yra"%1" ar "%2". Type @@ -781,7 +991,7 @@ The public key is used on client computers to authenticate incoming connection r Host address - + Kompiuterio adresas MAC address @@ -789,210 +999,218 @@ The public key is used on client computers to authenticate incoming connection r Specified object not found. - + Nurodytas objektas nerastas. File "%1" does not exist! - + Failas "%1" neegzistuoja! Can't open file "%1" for reading! - + Negaliu atidaryti failo "%1" skaitymui! Unknown argument "%1". - + Nežinomas argumentas "%1". Computer "%1" (host address: "%2" MAC address: "%3") - + Kompiuteris "%1" (tinklo adresas: "%2" MAC adresas: "%3") Unclassified object "%1" with ID "%2" - + Nesuklasifikuotas objektas "%1" su ID "%2" None - + Nėra Computer - + Kompiuteris Root - + Pagrindinis Invalid - + Neteisingas Error while parsing line %1. - + Klaida šifruojant eilutę %1. Network object directory which stores objects in local configuration - + Tinklo objektų direktorija kurioje saugomi objektai vietinėje konfigūracijoje Commands for managing the builtin network object directory - + Komandos skirtos valdyti tinklo objektų direktoriją No format string or regular expression specified! - + Nenurodytas formatas, ar regex Can't open file "%1" for writing! - + Negalima atidaryti failo "%1" įrašymui! No format string specified! - + Nenurodytas formatas! Object UUID - + Objekto UUID Parent UUID - + Tėvinis UUID Add a location or computer - + Pridėti vietą ar kompiuterį Clear all locations and computers - + Išvalyti visas vietas ar kompiuterius Dump all or individual locations and computers - + Išvalyti visas ar individualias vietas ir kompiuterius List all locations and computers - + Atvaizduoti visas vietas ir kompiuterius Remove a location or computer - + Ištrinti vietą ar kompiuterį Location "%1" - + Vieta "%1" Builtin (computers and locations in local configuration) - + Kompiuteriai ar vietos vietinėje konfigūracijoje Location - + Vieta FILE - + FAILAS LOCATION - + VIETA FORMAT-STRING-WITH-PLACEHOLDERS - + FORMATUOTI-TEKSTĄ-SU-ŠABLONAIS REGULAR-EXPRESSION-WITH-PLACEHOLDER - + REGULIARI-IŠRAIŠKA-SU-ŠABLONU Imports objects from the specified text file using the given format string or regular expression containing one or multiple placeholders. Valid placeholders are: %1 - + Importuoja objektus iš nurodyto tekstinio failo, naudojant numatytą formatą ar reguliarą formą kurioje yra viena ar daugiau užpildytų vietų. Tinkami šablonai yra: %1 Import simple CSV file to a single room - + Importuoti paprastą CSV failą į vieną kambarį Import CSV file with location name in first column - + Importuoti CSV failą su vietos pavadinimu pirmame stulpelyje Import text file with with key/value pairs using regular expressions - + Importuoti tekstinį failą su raktu/verčių poromis naudojant reguliarias išraiškas. Import arbitrarily formatted data - + Importuoti arbitruotai suformuotus duomenis Exports objects to the specified text file using the given format string containing one or multiple placeholders. Valid placeholders are: %1 - + Eksportuoja objektus į nurodytą tekstinį failą, naudojant numatytą formatą ar reguliarą išraišką kurioje yra viena ar daugiau užpildytų vietų. Tinkami šablonai yra: %1 Export all objects to a CSV file - + Eksportuoti visus objektus į CSV failą Export all computers in a specific location to a CSV file - + Eksportuoti kompiuterius iš nurodytos vietos į CSV failą TYPE - + TIPAS NAME - + VARDAS PARENT - + TĖVINIS Adds an object where %1 can be one of "%2" or "%3". %4 can be specified by name or UUID. - + Prideda objektą kur %1 gali būti vienas iš "%2" ar "%3". %4 gali būti nurodyta pagal vardą arba UUID. Add a room - + Pridėti kambarį Add a computer to room %1 - + Pridėti kompiuterį prie kambario %1 OBJECT - + OBJEKTAS Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. - + Pašalina nurodytą objektą iš direktorijos. %1 gali būti nurodytas pagal vardą ar UUID. Pašalinant vietą bus pašalinti visi susieti kompiuteriai. Remove a computer by name - + Ištrinti kompiuterį pagal vardą Remove an object by UUID - + Pašalinti objektą pagal UUID "Room 01" - + "Kambarys 01" "Computer 01" - + "Kompiuteris 01" HOST ADDRESS - + SERVERIO ADRESAS MAC ADDRESS + MAC ADRESAS + + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. @@ -1000,60 +1218,84 @@ The public key is used on client computers to authenticate incoming connection r BuiltinUltraVncServer Builtin VNC server (UltraVNC) - + Integruotas VNC serveris (UltraVNC) BuiltinX11VncServer Builtin VNC server (x11vnc) - + Integruotas VNC serveris (x11vnc) ComputerControlListModel - - Host/IP address: %1 - - Active features: %1 - + Aktyvios funkcijos: %1 Online and connected - + Įjungtas ir prisijungta Establishing connection - + Jungiamasi Computer offline or switched off - + Kompiuteris nepasiekiamas arba išjungtas - Service unreachable or not running - + Authentication failed or access denied + Autorizacija nepavyko arba prieiga negalima - Authentication failed or access denied + Disconnected + Atsijungta + + + No user logged on + Nėra prisijungusių vartotojų + + + Logged on user: %1 + Prisijungta su vartotoju: %1 + + + Location: %1 + Vieta: %1 + + + [no user] + [vartotojo nėra] + + + Veyon Server unreachable or not running + Veyon Serveris nepasiekiamas ar nepaleistas + + + Name: %1 - Disconnected + Hostname: %1 - No user logged on + unknown + Nežinomas + + + IP address: %1 - Logged on user: %1 + Hostname could not be resolved - Location: %1 + No features active @@ -1061,7 +1303,7 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlServer %1 Service %2 at %3:%4 - + %1 Servisas %2 vietoje %3:%4 Authentication error @@ -1069,190 +1311,244 @@ The public key is used on client computers to authenticate incoming connection r Remote access - + Nutolusi prieiga User "%1" at host "%2" is now accessing this computer. - + Vartotojas "%1" iš kompiuterio "%2" dabar jungiasi prie šio kompiuterio. User "%1" at host "%2" attempted to access this computer but could not authenticate successfully. - + Vartotojas "%1" iš kompiuterio "%2" bandė prisijungti prie šio kompiuterio, bet negalėjo autorizuotis tinkamai. Access control error - + Prieigos valdymo klaida User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. - + Vartotojas "%1" iš kompiuterio "%2" bandė prisijungti prie šio kompiuterio, bet negalėjo autorizuotis tinkamai. + + + Active connections: + Aktyvūs prisijungimai: + + + + ComputerGroupSelector + + Group %1 + Grupė %1 ComputerManager User - + Vartotojas Missing network object directory plugin - + Trūksta tinklo objektų direktorijos įskiepio No default network object directory plugin was found. Please check your installation or configure a different network object directory backend via %1 Configurator. - + Nerastas numatytasis tinklo objiektų plėtinys. Patikrinkite savo instaliaciją arba nustatykite kitą tinklo objektų katalogą panaudojant %1 konfigūratorių. Location detection failed - + Nepavyko aptikti vietos Computer name;Hostname;User - + Kompiuterio vardas;Serverio vardas;Vartotojas Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. - + Negalima nustatyti kompiuterio vietos. Tai galėjo įvykti dėl problemos su sistemos konfigūracija. Visos vietos bus nurodytos kompiuterio pasirinkimo lange. + + + Logged in since + + + + %1 days + + + + 1 day + - ComputerSelectPanel + ComputerMonitoring - Computer management - + Computers + Kompiuteriai + + + Search users and computers + Ieškoti naudotojų bei kompiuterių + + + Select all + Pasirinkti viską + + + Unselect all + Atžymėti visus + + + Add to group + Pridėti prie grupės + + + Remove from group + Pašalinti iš grupės + + + ComputerSelectPanel Computer search - + Kompiuterio paieška Add location - + Pridėti vietą Save computer/user list - + Išsaugoti kompiuterių/vartotojų sąrašą Select output filename - + Pasirinkti išvesties failo vardą CSV files (*.csv) - + CSV failas (*.csv) File error - + Failo klaida Could not write the computer and users list to %1! Please check the file access permissions. + Neįmanoma įrašyti kompiuterio ir vartotojų sąrašo į %1! Patikrinkite failo prieigos teises. + + + Search computers - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. - + Clear system-wide Veyon configuration + Išvalyti Veyon konfigūraciją sistemos lygmeniu. - Please specify a valid filename for the configuration export. - + List all configuration keys and values + Parodyti visus konfigūracijos parametrus. - Please specify a valid key. - + Import configuration from given file + Importuoti konfigūraciją iš nurodyto failo. - Specified key does not exist in current configuration! - + Export configuration to given file + Eksportuoti konfigūraciją į nurodytą failą - Please specify a valid value. - + Read and output configuration value for given key + Nuskaityti ir išvesti konfigūracijos vertę pasirinktam parametrui. - Configure Veyon at command line - + Write given value to given configuration key + Įrašyti nurodytą vertę pasirinktam parametrui. - Output file is not writable! - + Unset (remove) given configuration key + Atstatyti (pašalinti) pasirinktą parametrą. - Output directory is not writable! - + Upgrade and save configuration of program and plugins + Atnaujinti ir išsaugoti programos ir plėtinių konfigūraciją. - Configuration file is not readable! - + Please specify an existing configuration file to import. + Nurodytkite esamą konfigūraciją kurią norite importuoti. - Clear system-wide Veyon configuration - + Configuration file is not readable! + Neįmanoma nuskaityti konfigūracijos failo - List all configuration keys and values - + Please specify a valid filename for the configuration export. + Nurodykite tinkamą failo vardą eksportuojamai konfigūracijai. - Import configuration from given file - + Output file is not writable! + Neįmanoma rašyti į išvesties failą! - Export configuration to given file - + Output directory is not writable! + Neįmanoma rašyti į išvesties direktoriją - Read and output configuration value for given key - + Please specify a valid key. + Nurodykite tinkamą raktą - Write given value to given configuration key - + Specified key does not exist in current configuration! + Nurodyta vertė neegzistuoja esamoje konfigūracijoje - Unset (remove) given configuration key - + Please specify a valid value. + Nurodykite tinkamą vertę. - Commands for managing the configuration of Veyon - + Configure Veyon at command line + Konfigūruoti Veyon naudojant komandinę eilutę - Upgrade and save configuration of program and plugins - + Commands for managing the configuration of Veyon + Komandos skirtos valdyti Veyon konfigūraciją ConfigurationManager Could not modify the autostart property for the %1 Service. - + Nepavyko pakeisti automatinio paleidimo parametro servisui: %1 Could not configure the firewall configuration for the %1 Server. - + Nepavyko pakeisti ugniasienės konfigūracijos serveriui: %1 Could not configure the firewall configuration for the %1 Worker. - + Nepavyko pakeisti ugniasienės konfigūracijos darbuotojui: %1 Configuration is not writable. Please check your permissions! - + Konfigūracija nėra įrašoma. Patikrinkite konfigūracijos prieigos teises Could not apply platform-specific configuration settings. - + Nepavyko pritaikyti konfigūracijos parametrų specifinei platformai. + + + Could not configure the firewall configuration for the %1 Service. + Nepavyko sukonfigūruoti ugniasienės servisui: %1 DemoClient %1 Demo - + %1 prezentacija @@ -1263,50 +1559,50 @@ The public key is used on client computers to authenticate incoming connection r Tunables - + Derinamieji ms - + ms Key frame interval - + Pagrindinio kadro intervalas Memory limit - - - - Use multithreading (experimental) - + Atminties riba MB - + MB Update interval - + Atnaujinimo intervalas s - + s Slow down thumbnail updates while demo is running + Sulėtinti miniatūrų atnaujinimą, kol vyksta prezentacija + + + Bandwidth limit + + + + MB/s DemoFeaturePlugin - - Fullscreen demo - Pilno ekrano prezentacija - Stop demo - + Sustabdyti demonstraciją Window demo @@ -1314,26 +1610,70 @@ The public key is used on client computers to authenticate incoming connection r Give a demonstration by screen broadcasting - + Pateikite demonstraciją transliuodami ekraną - Demo server - Prezantacijų serveris + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Šiame rėžime jūsų ekranas bus demonstruojamas lange visiems kompiuteriams. Vartotojai gali perjungti langus pagal poreikį. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - + Demo + Demonstracija - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - + Share your screen or allow a user to share his screen with other users. + Dalintis savo ekranu, ar leisti vartotojui dalintis savo ekranu su kitais vartotojais. + + + Full screen demo + Pilno ekrano demonstracija. + + + Share your own screen in fullscreen mode + Dalintis savo ekranu pilno ekrano režime. + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + Šiame režime jūsų ekranas rodomas visiems kompiuteriams pilnojo ekrano režimu. Visuose kompiuteriuose įvesties įrenginiai yra užblokuoti. + + + Share your own screen in a window + Dalintis savo ekranu lange. + + + Share selected user's screen in fullscreen mode + Dalintis pasirinkto vartotojo ekranu pilnojo ekrano režime + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + Šiame režime bus rodomas pasirinkto vartotojo ekranas visiems vartotojams pilnojo ekrano režimu. Visuose kompiuteriuose įvesties įrenginiai yra užblokuoti. + + + Share selected user's screen in a window + Dalintis pasirinkto vartotojo ekranu lange. + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + Šiame režime bus rodomas pasirinkto vartotojo ekranas visiems vartotojams lange. Vartotojai gali perjungti į kitus langus pagal poreikį. + + + Please select a user screen to share. + Pasirinkite vartotoją kurio ekranu dalinsitės + + + Please select only one user screen to share. + Pasirinkite tik vieną vartotoją kurio ekranu dalinsitės + + + All screens + Visi ekranai DesktopAccessDialog Desktop access dialog - + Darbalaukio prieigos dialogas Confirm desktop access @@ -1349,92 +1689,96 @@ The public key is used on client computers to authenticate incoming connection r The user %1 at computer %2 wants to access your desktop. Do you want to grant access? - + Naudotojas %1 iš kompiuterio %2 nori prisijungti prie jūsų kompiuterio. Ar norite tai leisti? DesktopServicesConfigurationPage - Programs & websites - + Name + Vardas - Predefined programs - + Path + Kelias - Name - Vardas + Predefined websites + Numatytieji puslapiai - Path - + Remove selected website + Pašalinti pasirinktą puslapį - Add new program - + URL + URL + + + New website + Naujas puslapis - Remove selected program + Applications & websites - Predefined websites + Predefined applications - Remove selected website + Add new application - URL + Remove selected application - New program + Add new website - New website + New application DesktopServicesFeaturePlugin - - Run program - - Open website - + Atidaryti tinklalapį Click this button to open a website on all computers. - + Paspauskite šį mygtuką, kad atidarytumėte puslapį visuose kompiuteriuose. - Start programs and services in user desktop - + Open website "%1" + Atidaryti puslapį "%1" - Click this button to run a program on all computers. + Custom website + Pasirinktinis puslapis + + + Start application - Run program "%1" + Click this button to start an application on all computers. - Custom program + Start application "%1" - Open website "%1" + Custom application - Custom website + Start apps and open websites in user sessions @@ -1446,38 +1790,42 @@ The public key is used on client computers to authenticate incoming connection r Room %1 - + Kambarys %1 Please complete all tasks within the next 5 minutes. - + Prašome užbaigti visas užduotis per artimiausias 5 minutes. Custom website - + Pasirinktinis puslapis Open file manager - + Atidaryti failų tvarkyklę Start learning tool - + Paleisti mokymosi įrankį Play tutorial video - - - - Custom program - + Paleisti mokomajį vaizdo įrašą Handout - + Padalomoji medžiaga Texts to read + Medžiaga skaitymui + + + generic-student-user + bendrinis-besimokantysis-vartotojas + + + Custom application @@ -1485,1203 +1833,1243 @@ The public key is used on client computers to authenticate incoming connection r ExternalVncServer External VNC server - + Išorinis VNC serveris ExternalVncServerConfigurationWidget External VNC server configuration - + Išorinė VNC serverio konfigūracija Port: - + Prievadas: Password: - + Slaptažodis: - FeatureControl + FeatureCommands - Feature control + List names of all available features - - - FileTransferController - Could not open file "%1" for reading! Please check your permissions! + Show table with details of all available features - - - FileTransferDialog - File transfer + Start a feature on a remote host - Options + Stop a feature on a remote host - Transfer only + Please specify the command to display help for. - Transfer and open file(s) with associated program + Displays a list with the names of all available features. - Transfer and open destination folder + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. - Files - + HOST ADDRESS + SERVERIO ADRESAS - Start + FEATURE - Overwrite existing files + ARGUMENTS - - - FileTransferPlugin - File transfer + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information - Click this button to transfer files from your computer to all computers. + Lock the screen - Select one or more files to transfer + Display a text message - Transfer files to remote computer + Test message - Received file "%1". + Start an application - Could not receive file "%1" as it already exists. + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. - Could not receive file "%1" as it could not be opened for writing! + Unlock the screen - - - GeneralConfigurationPage - User interface - Vartotojo sąsaja + The specified command does not exist or no help is available for it. + - Language: - Kalba + Name + Vardas - Use system language setting + Description - Veyon + Master - Logging - Įvykių žurnalas + Service + Tarnyba - Log file directory - Įvykių žurnalo direktorija + Worker + - ... - ... + UID + - Log level - Įvykių žurnalo lygmuo + Plugin + Plėtinys - Nothing - Nevygdyti įvykių žurnalo + Invalid feature name or UID specified + - Only critical messages - Tik kritines klaidas + Error parsing the JSON-encoded arguments: %1 + - Errors and critical messages - Visas klaidas + Failed to initialize credentials + - Warnings and errors - Įspėjimai ir klaidos - - - Information, warnings and errors - Informaciniai įspėjimai ir klaidos - - - Debug messages and everything else - Patarimų žinutės ir visa kita - - - Limit log file size - Limituoti žurnalo failo dydį - - - Clear all log files - Išvalyti visus įvykių žurnalo failus - - - Log to standard error output - Persijungti į įvykių žurnalą - - - Network object directory - - - - Backend: + Could not establish a connection to host %1 - Update interval: + Failed to send feature control message to host %1 - %1 service + Feature-related CLI operations - The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + Commands for controlling features + + + FileTransferConfigurationPage - Log files cleared - Įvykio failai ištrinti + File transfer + Failų perkėlimas - All log files were cleared successfully. - Visi įvyko failai pašalinti sėkmingai. + Directories + Katalogai - Error - Klaida + Destination directory + Paskirties vieta - Could not remove all log files. - Nepavyko pašalinti visų įvykio failų. + Default source directory + Numatytoji pradinė failų vieta. - MB - + Options + Nustatymai - Rotate log files - + Remember last source directory + Atsiminti paskutinę pradinę direktoriją. - x - + Create destination directory if it does not exist + Sukurti paskirties direktoriją jeigu ji neegistuoja. + + + FileTransferController - seconds - Sekundės + Could not open file "%1" for reading! Please check your permissions! + Neįmanoma atidaryt failo "%1" skaitymui! Patikrinkite prieigos teises! + + + FileTransferDialog - Write to logging system of operating system - + File transfer + Failų perkėlimas - Authentication - Autorizavimas + Options + Nustatymai - Method: - + Transfer only + Tik perkelti - Logon authentication - Autorizacija prisijungiant į sistemą + Transfer and open file(s) with associated program + Perkelti ir atidaryti failą(-us) su numatytąja programa - Key file authentication - Autorizuotis naudojant pasiekiamumo raktą + Transfer and open destination folder + Perkelti ir atidaryti failo katalogą - Test - Testuoti + Files + Failai - Authentication is set up properly on this computer. - + Start + Pradėti - Authentication keys are not set up properly on this computer. - + Overwrite existing files + Perrašyti esamus failus + + + FileTransferFileDialog - Authentication test - + Select one or more files to transfer + Pasirinkite vieną ar daugiau failų perkėlimui - InternetAccessControlConfigurationPage + FileTransferPlugin - Internet access control - + File transfer + Failų perkėlimas - Backend: - + Click this button to transfer files from your computer to all computers. + Paspauskite šį mygtuką, kad perkelti failus iš Jūsų kompiuterio į visus kompiuterius - General settings - + Select one or more files to transfer + Pasirinkite vieną ar daugiau failų perkėlimui - Backend settings - + Transfer files to remote computer + Perkelti failus į nutolusį kompiuterį - - - InternetAccessControlPlugin - Block access to the internet - + Received file "%1". + Gautas failas "%1". - Allow access to the internet - + Could not receive file "%1" as it already exists. + Neįmanoma pasiekti failo "%1" kadangi failas jau egzistuoja. - Show help about command - + Could not receive file "%1" as it could not be opened for writing! + Negalima priimti failo "%1" nes jo negalima atidaryti rašymui! + + + GeneralConfigurationPage - Block internet - + User interface + Vartotojo sąsaja - Click this button to block access to the internet. - + Language: + Kalba - Unblock internet - + Use system language setting + Naudoti sistemos kalbos nustatymą - Click this button to allow access to the internet. - + Veyon + Veyon - Control access to the internet - + Logging + Įvykių žurnalas - Commands for controlling access to the internet - + Log file directory + Įvykių žurnalo direktorija - - - LdapBrowseDialog - Browse LDAP - + Log level + Įvykių žurnalo lygmuo - - - LdapClient - LDAP error description: %1 - + Nothing + Nevygdyti įvykių žurnalo - - - LdapConfigurationPage - Basic settings - + Only critical messages + Tik kritines klaidas - General - Pagrindinis + Errors and critical messages + Visas klaidas - LDAP server and port - + Warnings and errors + Įspėjimai ir klaidos - Bind DN - + Information, warnings and errors + Informaciniai įspėjimai ir klaidos - Bind password - + Debug messages and everything else + Patarimų žinutės ir visa kita - Anonymous bind - + Limit log file size + Limituoti žurnalo failo dydį - Use bind credentials - + Clear all log files + Išvalyti visus įvykių žurnalo failus - Base DN - + Log to standard error output + Persijungti į įvykių žurnalą - Fixed base DN - + %1 service + %1 servisas - e.g. dc=example,dc=org - + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + Servisas %1 turi būti sustabdytas laikinai, norint ištrinti įvykių žurnalo failus. Tęsti?? - Discover base DN by naming context - + Log files cleared + Įvykio failai ištrinti - e.g. namingContexts or defaultNamingContext - + All log files were cleared successfully. + Visi įvyko failai pašalinti sėkmingai. - Environment settings - + Error + Klaida - Object trees - + Could not remove all log files. + Nepavyko pašalinti visų įvykio failų. - Computer tree - + MB + MB - e.g. OU=Groups - + Rotate log files + Keisti įvykio žurnalo failus - User tree - + x + x - e.g. OU=Users - + Write to logging system of operating system + Įrašyti į operacinės sistemos įvykių žurnalą - e.g. OU=Computers + TLS configuration - Group tree + Use certificate authority for TLS connections - Perform recursive search operations in object trees + CA certificate file - Object attributes - + ... + ... - e.g. hwAddress + Host certificate file - e.g. member or memberUid + Host private key file - e.g. dNSHostName + Style: - Computer MAC address attribute + Native - Group member attribute + Color scheme: - e.g. uid or sAMAccountName + Light - Advanced settings + Dark - Optional object filters + User groups - Filter for user groups - + Backend: + Sisteminė konfigūracija - Filter for users + Include user groups from domain - Filter for computer groups - + Missing user groups backend + Naudotojų grupių valdymas nerastas - Group member identification + No user groups plugin was found. Please check your installation! + + + HeadlessVncServer - Distinguished name (Samba/AD) - + Headless VNC server + Nevaldomas VNC serveris. + + + LdapBrowseDialog - List all groups of a user - + Browse LDAP + Naršyti LDAP + + + LdapClient - List all groups of a computer - + LDAP error description: %1 + LDAP klaidos informacija: %1 + + + LdapConfiguration - Get computer object by IP address - + LDAP connection failed + Nepavyko prisijungti prie LDAP - LDAP connection failed + Could not connect to the LDAP server. Please check the server parameters. + +%1 LDAP bind failed + Nepavyko susieti su LDAP + + + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 LDAP bind successful - + Susiejimas su LDAP sėkmingas Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - + Sėkmingai prisijungta prie LDAP serverio ir atliktas LDAP susiejimas. Pagrindiniai LDAP parametrai yra tinkamai sukonfigūruoti. LDAP base DN test failed + Nepavyko atlikti LDAP bazinio DN testo + + + Could not query the configured base DN. Please check the base DN parameter. + +%1 LDAP base DN test successful + LDAP bazinis DN testas sėkmingas + + + The LDAP base DN has been queried successfully. The following entries were found: + +%1 LDAP naming context test failed + Nepavyko atlikti LDAP pavadinimo konteksto testo + + + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 LDAP naming context test successful - + LDAP įvardijimo konteksto testas sėkmingas The LDAP naming context has been queried successfully. The following base DN was found: %1 - + LDAP pavadinimų konteksto užklausa buvo sėkmingai pateikta. Rasta ši bazinė DN: +%1 user tree - + vartotojų medis + + + User tree + Vartotojų medis group tree - + grupės medis + + + Group tree + Grupių medis computer tree - + kompiuterių medis - Enter username - + Computer tree + Kompiuterių medis - Please enter a user login name (wildcards allowed) which to query: + computer group tree + + Computer group tree + Kompiuterių grupių medis + user objects - + vartotojų objektai - Enter group name - + User login name attribute + Prisijungimo vardo atributai - Please enter a group name whose members to query: + group members + grupės nariai + + + Group member attribute + Grupių narių atributai + + + Group not found + Grupė nerasta + + + Could not find a group with the name "%1". Please check the group name or the group tree parameter. - group members + computer objects + kompiuterių objektai + + + Computer display name attribute + Kompiuterio atvaizduojamo vardo atributai + + + Invalid hostname + Klaidingas kompiuterio vardas + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Group not found + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Computer hostname attribute - Enter computer name - + computer MAC addresses + kompiuterių MAC adresai - computer objects - + Computer MAC address attribute + Kompiuterio MAC adreso atributai - Enter computer DN + computer locations - Please enter the DN of a computer whose MAC address to query: - + Computer location attribute + Kompiuterio vietos atributai - computer MAC addresses - + Location name attribute + Vietos pavadinimo atributai users - + vartotojai user groups - + vartotojų grupės + + + computers + kompiuteriai computer groups - + kompiuterių grupės - Please enter a user login name whose group memberships to query: + computer containers groups of user - + vartotojo grupės User not found + Vartotojas nerastas + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. groups of computer - + kompiuterio grupės Computer not found - + Kompiuteris nerastas - Enter computer IP address + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - Please enter a computer IP address which to resolve to an computer object: - + Hostname lookup failed + Nepavyko ieškoti pagrindinio kompiuterio vardo - computers + Could not lookup hostname for IP address %1. Please check your DNS server settings. - LDAP %1 test failed + location entries - LDAP %1 test successful + Computer groups filter - The %1 has been queried successfully and %2 entries were found. + Computer locations identification - %1 %2 have been queried successfully: - -%3 + Filter for computer groups + Filtras kompiuterių grupėms + + + Invalid test value - LDAP filter test failed + An empty or invalid value has been supplied for this test. - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + LDAP %1 test failed + LDAP %1 testas nepavyko + + + Could not query any entries in configured %1. Please check the parameter "%2". -%2 +%3 - LDAP filter test successful - + LDAP %1 test successful + LDAP %1 testas pavyko - %1 %2 have been queried successfully using the configured filter. + The %1 has been queried successfully and %2 entries were found. - (only if different from group tree) + LDAP test failed - Computer group tree + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 - computer group tree - + and + ir - Filter for computers + LDAP test successful - e.g. room or computerLab + %1 %2 have been queried successfully: + +%3 - Integration tests + LDAP filter test failed - Computer groups + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 - e.g. name or description + LDAP filter test successful - Filter for computer containers + %1 %2 have been queried successfully using the configured filter. - Computer containers or OUs + LDAP directory + + + LdapConfigurationPage - Connection security - + Basic settings + Baziniai nustatymai - TLS certificate verification - + General + Pagrindinis - System defaults - + LDAP server and port + LDAP serverio adresas ir prievadas - Never (insecure!) - + Bind DN + Pririšti BN - Custom CA certificate file - + Bind password + Pririšti slaptažodį - None - + Anonymous bind + Anoniminis prisirišimas - TLS - + Use bind credentials + Naudoti prisirišimo duomenis - SSL - + Base DN + Bazinis DN - e.g. (objectClass=computer) - + Fixed base DN + Fiksuotas bazinis DN - e.g. (objectClass=group) - + e.g. dc=example,dc=org + pvz. dc=pavyzdys, dc=org - e.g. (objectClass=person) + Discover base DN by naming context - e.g. (objectClass=room) or (objectClass=computerLab) - + e.g. namingContexts or defaultNamingContext + pvz.: namingContexts arba defaultNamingContext - e.g. (objectClass=container) or (objectClass=organizationalUnit) - + Environment settings + Aplinkos nustatymai - Could not query the configured base DN. Please check the base DN parameter. - -%1 - + Object trees + Objektų medis - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - + Computer tree + Kompiuterių medis - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - + e.g. OU=Groups + pvz.: OU=Groups - Certificate files (*.pem) - + User tree + Vartotojų medis - Could not connect to the LDAP server. Please check the server parameters. - -%1 - + e.g. OU=Users + pvz.: OU=Users - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - + e.g. OU=Computers + pvz.: OU=Computers - Encryption protocol - + Group tree + Grupės medis - Computer location attribute - + Perform recursive search operations in object trees + Vykdyti rekursyvią paiešką objektų medyje - Computer display name attribute - + Object attributes + Objekto atributai - Location name attribute - + e.g. hwAddress + pvz.: hwAddress - e.g. cn or displayName + e.g. member or memberUid - Computer locations identification + e.g. dNSHostName - Identify computer locations (e.g. rooms) via: - + Computer MAC address attribute + Kompiuterio MAC adreso atributai - Location attribute in computer objects - + Group member attribute + Grupių narių atributai - List all entries of a location + e.g. uid or sAMAccountName - List all locations - + Advanced settings + Išplėstiniai nustatymai - Enter computer display name - + Optional object filters + Pasirinktiniai filtrai - Please enter a computer display name to query: - + Filter for user groups + Filtrai vartotojų grupėms - Enter computer location name - + Filter for users + Filtrai visiems vartotojams - Please enter the name of a computer location (wildcards allowed): - + Filter for computer groups + Filtras kompiuterių grupėms - computer locations - + Group member identification + Grupių vartotojų indentifikacija - Enter location name - + Distinguished name (Samba/AD) + Išskirtinis vardas (Samba/AD) - Please enter the name of a location whose entries to query: - + List all groups of a user + Atvaizduoti visas vartotojų grupes - location entries - + List all groups of a computer + Atvaizduoti visas grupes kompiuteriui - LDAP test failed - + Get computer object by IP address + Gaukite kompiuterio objektą pagal IP adresą - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - + Enter username + Įveskite vartotojo vardą - and + Please enter a user login name (wildcards allowed) which to query: - LDAP test successful - + Enter group name + Įveskite grupės pavadinimą - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - + Please enter a group name whose members to query: + Įveskite grupės pavadinimą, kurios narius užklausti: - Browse - + Enter computer name + Įveskite kompiuterio vardą - Test - Testuoti + Enter computer DN + Įveskite kompiuterio DN - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - + Please enter the DN of a computer whose MAC address to query: + Įveskite kompiuterio DN, kurio MAC adresą norite užklausti: - Computer hostname attribute + Please enter a user login name whose group memberships to query: - Please enter a computer hostname to query: - + Enter computer IP address + Įveskite kompiuterio IP adresą - Invalid hostname - + Please enter a computer IP address which to resolve to an computer object: + Įveskite kompiuterio IP adresą, kurį reikia naudoti kompiuterio objektui atskirti: - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + (only if different from group tree) - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - + Computer group tree + Kompiuterių grupių medis - Could not find a user with the name "%1". Please check the username or the user tree parameter. + Filter for computers + Filtrai kompiuteriams + + + e.g. room or computerLab - Enter hostname + Integration tests + Integraciniai testai + + + Computer groups + Kompiuterių grupės + + + e.g. name or description - Please enter a computer hostname whose group memberships to query: + Filter for computer containers - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Computer containers or OUs - Hostname lookup failed - + Connection security + Prisijungimo sauga - Could not lookup hostname for IP address %1. Please check your DNS server settings. - + TLS certificate verification + TLS sertifikato patvirtinimas - User login name attribute - + System defaults + Gamykliniai nustatymai - Configured attribute for user login name or computer hostname (OpenLDAP) - + Never (insecure!) + Niekada (nesaugu!) - computer containers - + Custom CA certificate file + Pasirinktinis CA sertifikato failas - - - LdapPlugin - Auto-configure the base DN via naming context - + None + Nėra - Query objects from LDAP directory - + TLS + TLS - Show help about command - + SSL + SSL - Commands for configuring and testing LDAP/AD integration + e.g. (objectClass=computer) - Basic LDAP/AD support for Veyon + e.g. (objectClass=group) - %1 (load computers and locations from LDAP/AD) + e.g. (objectClass=person) - %1 (load users and groups from LDAP/AD) + e.g. (objectClass=room) or (objectClass=computerLab) - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + e.g. (objectClass=container) or (objectClass=organizationalUnit) - No naming context attribute name given - falling back to configured value. - + Certificate files (*.pem) + Sertifikatų failai (*.pem) - Could not query base DN. Please check your LDAP configuration. - + Encryption protocol + Šifravimo protokolas - Configuring %1 as base DN and disabling naming context queries. - + Computer location attribute + Kompiuterio vietos atributai - - - LdapProConfigurationPage - LDAP Pro - + Computer display name attribute + Kompiuterio atvaizduojamo vardo atributai - Instances - + Location name attribute + Vietos pavadinimo atributai - Enter name - + e.g. cn or displayName + pvz.: cn arba displayName - Please enter a name for the instance (can't be changed later!): + Computer locations identification - Remove instance + Identify computer locations (e.g. rooms) via: - Do you really want to remove instance "%1"? + Location attribute in computer objects - Configuration for instance "%1" + List all entries of a location - - - LdapProPlugin - Professional LDAP/AD integration for Veyon - + List all locations + Rodyti visas vietas - %1 (load computers and locations from LDAP/AD) + Enter computer display name - %1 (load users and groups from LDAP/AD) + Please enter a computer display name to query: - - - LicensingConfigurationPage - Licensing + Enter computer location name - Installed licenses + Please enter the name of a computer location (wildcards allowed): - Add new network range - + Enter location name + Įveskite vietovės pavadinimą - Remove selected network range + Please enter the name of a location whose entries to query: - ID - + Browse + Naršyti - Feature - + Test + Testuoti - Valid until + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - Licensee + Computer hostname attribute - Browse license file + Please enter a computer hostname to query: - Veyon license files (*.vlf) - + Enter hostname + Įveskite kompiuterio vardą - Remove license + Please enter a computer hostname whose group memberships to query: - Do you really want to remove the selected license? - + User login name attribute + Prisijungimo vardo atributai - <N/A> + Configured attribute for user login name or computer hostname (OpenLDAP) - Invalid license file + Directory name - Could not open the license file for reading! + Query options - The selected license file does not contain valid data. + Query nested user groups (supported by AD only) - The selected license file could not be verified. + Query timeout - The selected license file is not valid for this installation. - + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. - + LDAP + LDAP - The license is already installed. + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + LdapPlugin - Information + Auto-configure the base DN via naming context - Installation ID + Query objects from LDAP directory - Addons available for licensing - + Show help about command + Parodyti pagalbos komandą - Addon + Commands for configuring and testing LDAP/AD integration - - - LicensingPlugin - Show help for specific command + Basic LDAP/AD support for Veyon - Show all installed licenses + %1 (load computers and locations from LDAP/AD) - Add license file + %1 (load users and groups from LDAP/AD) - Remove installed license + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - -USAGE - -%1 add <LICENSE FILE> - - + No naming context attribute name given - falling back to configured value. - -USAGE - -%1 remove <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. - No certificate found with given ID + Configuring %1 as base DN and disabling naming context queries. - <N/A> + Test binding to an LDAP server - Licensing management - + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Pateiktas vartotojo vardas ar slaptažodis yra neteisingas/i. Įveskite teisingus prisijungimo duomenis, arba perjunkite į kitą autorizavimo metodą naudojant Veyon Configurator - Commands for managing license keys + LDAP bind @@ -2689,7 +3077,7 @@ USAGE LinuxPlatformConfigurationPage Linux - + Linux Custom PAM service for user authentication @@ -2697,14 +3085,22 @@ USAGE User authentication + Vartotojo patvirtinimas + + + User sessions - Session management + Minimum session lifetime before server start - Display manager users + User login + Naudotojo prisijungimas + + + Login key sequence @@ -2714,16 +3110,12 @@ USAGE Plugin implementing abstract functions for the Linux platform - - Plugin implementing specific functions for the Linux platform - - LocationDialog Select location - + Pasirinkite vietą enter search filter... @@ -2734,14 +3126,14 @@ USAGE MainToolBar Configuration - + Konfigūracija - Disable balloon tooltips + Show icons only - Show icons only + Disable tooltips @@ -2791,10 +3183,6 @@ USAGE About Qt Apie Qt - - Authentication impossible - Autorizavimas neįmanomas - Configuration not writable Konfiguracinis failas negali būti įrašytas @@ -2817,11 +3205,11 @@ USAGE Veyon Configurator - + Veyon Configurator Service - + Paslauga Master @@ -2829,11 +3217,11 @@ USAGE Access control - + Prieigos valdymas About Veyon - + Apie Veyon Auto @@ -2855,13 +3243,9 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - - Access denied - + Prieiga uždrausta According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. @@ -2869,11 +3253,11 @@ USAGE Screenshots - + Ekrano nuotraukos Feature active - + Funkcija aktyvi The feature "%1" is still active. Please stop it before closing %2. @@ -2881,7 +3265,7 @@ USAGE Reset configuration - + Atstatyti numatytają konfigūraciją Do you really want to reset the local configuration and revert all settings to their defaults? @@ -2889,11 +3273,7 @@ USAGE Search users and computers - - - - Adjust optimal size - + Ieškoti naudotojų bei kompiuterių Align computers to grid @@ -2917,11 +3297,11 @@ USAGE &Save settings to file - + Į&rašyti nustatymus į failą &View - + &Rodyti &Standard @@ -2937,6 +3317,48 @@ USAGE Locations && computers + Vietos bei kompiuteriai + + + Authentication + Autorizavimas + + + Adjust size of computer icons automatically + + + + Slideshow + + + + Spotlight + + + + Veyon Master + Veyon Master + + + Locations & computers + Vietos ir kompiuteriai + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + + + + Load computer positions + + + + Save computer positions @@ -2946,13 +3368,9 @@ USAGE Directories Katalogai - - ... - ... - User configuration - + Naudotojo konfigūravimas Feature on computer double click: @@ -2960,19 +3378,19 @@ USAGE Features - + Galimybės All features - + Visos galimybės Disabled features - + Išjungtos galimybės Screenshots - + Ekrano nuotraukos <no feature> @@ -2980,15 +3398,15 @@ USAGE Basic settings - + Baziniai nustatymai Behaviour - + Elgsena Enforce selected mode for client computers - + Įgalinti pasirinktą rėžimą kliento kompiuteriuose Hide local computer @@ -3008,15 +3426,15 @@ USAGE Background color - + Fono spalva Thumbnail update interval - + Piktogramų atnaujinimo intervalas ms - + ms Program start @@ -3028,39 +3446,43 @@ USAGE User and computer name - + Naudotojo ir kompiuterio vardas Only user name + Tik naudotojo vardas + + + Only last part of user name Only computer name - + Tik kompiuterio vardas Computer thumbnail caption - + Kompiuterio piktogramos užrašas Text color - + Teksto spalva Sort order - + Rikiavimo tvarka Computer and user name - + Kompiuterio ir naudotojo vardas Computer locations - + Kompiuterių vietos Show current location only - + Parodyti dabartinę vietą Allow adding hidden locations manually @@ -3068,198 +3490,213 @@ USAGE Hide empty locations - + Slėpti tuščias vietas Show confirmation dialog for potentially unsafe actions - + Parodyti patvirtinimo langą galimai nesaugiems veiksmams Perform access control - + Atlikti prieigos kontrolę Automatically select current location - Automatically adjust computer thumbnail size + Automatically open computer select panel - Automatically open computer select panel + Use modern user interface (experimental) - - - MonitoringMode - Monitoring + Thumbnail spacing - Builtin monitoring mode + px - This mode allows you to monitor all computers at one or more locations. + Hide local session - - - NetworkDiscoveryConfigurationPage - Network discovery + Auto - Mode + Thumbnail aspect ratio - Scan network ranges + Automatically adjust computer icon size - e.g. 192.168.1.0/24 + Open feature windows on the same screen as the main window - Scan all subnets of computer + Configuration templates - Scan custom subnet + Image quality in monitoring mode - Scan sessions on local computer + Highest - Test - Testuoti + High + - Network ranges + Medium - Add new group + Low - Remove selected group + Lowest - Groups + Remote access image quality - First address + Advanced - Last address + Computer name source - Add new network range + Default - Remove selected network range + Host address + Kompiuterio adresas + + + Session client address - Parallel scans + Session client name - Scan timeout + Session host name - ms + Session metadata - Session scan limit + Full name of user - Options + User login name - Reverse lookup discovered IP addresses to host names + Computer UID role - New location + Session meta data hash - - - NetworkDiscoveryDirectory - Scanning... + Always expand all locations - Discovered computers + Image quality - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command + Monitoring + + + + Builtin monitoring mode - Scan a subnet + This mode allows you to monitor all computers at one or more locations. - -USAGE - -%1 scan [<SUBNET>] - - + Query application version of the server + + + + Query active features + + + + Query properties of remotely available screens + + + + + NestedNetworkObjectDirectory + + All directories + + + NetworkObjectDirectoryConfigurationPage - Network object directory which automatically discovers computers in the network - + Update interval: + Atnaujinimo intervalai: - Network discovery (scan network for Veyon clients) - + seconds + Sekundės + + + NetworkObjectDirectoryConfigurationPageTab - Commands for managing the network discovery directory - + Enabled + Įgalintas NetworkObjectTreeModel Locations/Computers - + Vietos/Kompiuteriai OpenWebsiteDialog Open website - + Atidaryti tinklalapį e.g. Veyon - + pvz.: Veyon Remember and add to website menu @@ -3267,7 +3704,7 @@ USAGE e.g. www.veyon.io - + pvz.: www.veyon.io Please enter the URL of the website to open: @@ -3275,33 +3712,45 @@ USAGE Name: + Vardas: + + + Website name - PasswordDialog + PluginCommands - Username - Vartotojo vardas + List names of all installed plugins + - Password - Slaptažodis + Show table with details of all installed plugins + - Veyon Logon + Name + Vardas + + + Description - Authentication error - Autorizacijos klaida + Version + - Logon failed with given username and password. Please try again! + UID - Please enter your username and password in order to access computers. + Plugin-related CLI operations + + + + Commands for managing plugins @@ -3321,7 +3770,7 @@ USAGE Click this button to reboot all computers. - + Paspauskite šį mygtuką, kad paleistumėte iš naujo visus kompiuterius. Power down @@ -3333,23 +3782,19 @@ USAGE Power on/down or reboot a computer - + Į(iš)jungti kompiuterį ar paleisti iš naujo Confirm reboot - + Patvirtinti kompiuterio paleidimą iš naujo Confirm power down - + Patvirtinti kompiuterio išjungimą Do you really want to reboot the selected computers? - - - - Do you really want to power down the selected computer? - + Ar tikrai norite paleisti iš naujo pasirinktus kompiuterius? Power on a computer via Wake-on-LAN (WOL) @@ -3357,15 +3802,15 @@ USAGE MAC ADDRESS - + MAC ADRESAS This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. - + Ši komanda persiunčia Wake-on-LAN(WOL) paketą tinklui, kad kompiuteris su nustatytu MAC adresu būtų įjungtas Please specify the command to display help for! - + Nurodykite komandą, kuriai norite peržiūrėti pagalbą! Invalid MAC address specified! @@ -3377,11 +3822,11 @@ USAGE Power down now - + Išjungti dabar Install updates and power down - + Įdiegti atnaujinimus ir išjungti Power down after user confirmation @@ -3401,6 +3846,18 @@ USAGE Please save your work and close all programs. + + Do you really want to reboot <b>ALL</b> computers? + + + + Do you really want to power down <b>ALL</b> computers? + + + + Do you really want to power down the selected computers? + + PowerDownTimeInputDialog @@ -3414,18 +3871,18 @@ Please save your work and close all programs. minutes - + minutės seconds - + sekundės RemoteAccessFeaturePlugin Remote view - + Nuotolinis rodymas Open a remote view for a computer without interaction. @@ -3441,18 +3898,29 @@ Please save your work and close all programs. Remote access - + Nutolusi prieiga Remote view or control a computer + Žiūrėti arba valdyti kompiuterį nuotoliniu būdu + + + Show help about command + Parodyti pagalbos komandą + + + Exchange clipboard contents - Please enter the hostname or IP address of the computer to access: + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + RemoteAccessPage - Show help about command + Remote access: %1 @@ -3462,6 +3930,10 @@ Please save your work and close all programs. %1 - %2 Remote Access + + %1 - %2 - %3 Remote Access + + RemoteAccessWidgetToolBar @@ -3487,380 +3959,553 @@ Please save your work and close all programs. Ctrl+Alt+Del - + Ctrl+Alt+Del Ctrl+Esc - + Ctrl+Esc Alt+Tab - + Alt+Tab Alt+F4 - + Alt+F4 Win+Tab - + Win+Tab Win - + Win Menu - + Meniu Alt+Ctrl+F1 + Alt+Ctrl+F1 + + + Connected. + Prisijungta. + + + Screenshot + Ekrano vaizdas + + + Exit + Išeiti + + + Connecting... - Connecting %1 - Jungiamasi su %1 + Select screen + - Connected. - Prisijungta. + All screens + Visi ekranai + + + + ScreenLockFeaturePlugin + + Lock + Užrakinti + + + Unlock + Atrakinti + + + Lock screen and input devices of a computer + Užrakinti ekraną ir įvesties įrenginius kompiuteryje + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + + + + Lock input devices + + + + Unlock input devices + + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + + + + Screenshot + + unknown + Nežinomas + + + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + + + + Screenshot + Ekrano vaizdas + + + Could not open screenshot file %1 for writing. + + + + ScreenshotFeaturePlugin Screenshot + Ekrano vaizdas + + + Use this function to take a screenshot of selected computers. - Exit + Screenshots taken + + + + Screenshot of %1 computer have been taken successfully. + + + + Take screenshots of computers and save them locally. - Routing + ScreenshotManagementPage + + Screenshots + Ekrano nuotraukos + + + + ScreenshotManagementPanel + + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + + + + User: + Vartotojas: + + + Computer: + Kompiuteris: + + + Date: + Data: + + + Time: + Laikas: + + + Show + Rodyti + + + Delete + Ištrinti + + + Screenshot + Ekrano nuotrauka + - Control internet access by modifying routing table + Do you really want to delete all selected screenshots? - RoutingConfigurationWidget + ServerAccessControlManager + + Requested authentication method not available + + - Remove default routes to block internet access + Access allowed by rule "%1" - Add custom route to block internet + Access denied by rule "%1" - Destination + No rule allowed access - Gateway + Accessing user not member of an authorized user group + + + + User has denied access + + + + User confirmed access - RunProgramDialog + ServiceConfigurationPage + + General + Pagrindinis + + + Autostart + Automatinė paleistis + + + Hide tray icon + Paslėpti piktogramas + + + Start service + Paleisti tarnybą + + + Stopped + Sustabdytas + + + Stop service + Sustabdyti tarnybą + + + State: + Būsena: + + + Enable firewall exception + Įjungti ugnesienės išimtį + + + Allow connections from localhost only + Leisti prisijungimus tik vietiniam tinkle + + + VNC server + VNC serveris + + + Plugin: + Įskiepis: + + + Restart %1 Service + Perkrauti %1 tarnybą + + + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + Visi nustatymai išsaugoti sėkmingai. Tam, kad pakeitimai taptų aktyvūs, %1 tarnyba turi būti paleista iš naujo. Paleisti iš naujo dabar? + + + Running + Veikia + - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. - Run programs - + Show notification on remote connection + Rodyti pranešimą nuotoliniame kompiuteryje + + + Show notification when an unauthorized access is blocked + Rodyti pranešimą, kai neautorizuota prieiga užblokuota - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + Maximum session count - Name: + Network port numbers - Remember and add to program menu + Veyon server - e.g. VLC - + Internal VNC server + Vidinis VNC serveris - - - ScreenLockFeaturePlugin - Lock - + Feature manager + Funkcijų valdymas - Unlock - + Demo server + Demonstracinis serveris - Lock screen and input devices of a computer + Miscellaneous network settings - To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + Session mode - - - Screenshot - - unknown - Nežinomas - - Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + Local session mode (single server instance for primary local session) - Screenshot + Active session mode (single server instance for active local or remote session) - - - ScreenshotFeaturePlugin - Screenshot + Multi session mode (distinct server instance for each local and remote desktop session) - Use this function to take a screenshot of selected computers. + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. - Screenshots taken + Miscellaneous settings - Screenshot of %1 computer have been taken successfully. + Disable clipboard synchronization - Take screenshots of computers and save them locally. + Session metadata - - - ScreenshotManagementPanel - All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + Content - User: - Vartotojas: + None + Nėra - Computer: + Value of an environment variable - Date: - Data: + Value of a registry key + - Time: - Laikas: + Environment variable name: + - Show - Rodyti + Registry key name: + - Delete - Ištrinti + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + - ServiceConfigurationPage - - General - Pagrindinis - - - Autostart - Automatinė paleistis - - - Hide tray icon - Paslėpti piktogramas - + ServiceControl - Start service - Paleisti tarnybą + Service control + Serviso valdymas - Stopped - Sustabdytas + Starting %1 + - Stop service - Sustabdyti tarnybą + Stopping %1 + - State: - Būsena: + Restarting %1 + - Network - Tinklas + Registering %1 + - Demo server port - Prezaentacinio serverio šliuzas + Unregistering %1 + + + + ServiceControlCommands - Enable firewall exception - Įjungti ugnesienės išimtį + Register Veyon Service + Užregistruoti Veyon tarnybą - Allow connections from localhost only - Leisti prisijungimus tik vietiniam tinkle + Unregister Veyon Service + Išregistruoti Veyon tarnybą - Internal VNC server port - + Start Veyon Service + Paleisti Veyon tarnybą - VNC server - + Stop Veyon Service + Sustabdyti Veyon tarnybą - Plugin: - + Restart Veyon Service + Perkrauti Veyon tarnybą - Restart %1 Service - + Query status of Veyon Service + Užklausti Veyon tarnybos statuso - All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - + Service is running + Tarnyba vykdoma - Running - Veikia + Service is not running + Tarnyba nevykdoma - Feature manager port - + Configure and control Veyon service + Konfigūruoti ir kontroliuoti Veyon tarnybą - Primary service port + Commands for configuring and controlling Veyon Service + + + ShellCommands - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. - + Run command file + Paleisti komandos failą - Show notification on remote connection - + File "%1" does not exist! + Failas "%1" neegzistuoja! - Multi session mode (for terminal and remote desktop servers) + Interactive shell and script execution for Veyon CLI - Show notification when an unauthorized access is blocked - + Commands for shell functionalities + Shell funkcijų komandos - ServiceControl + SlideshowPanel - Starting service %1 + Previous - Stopping service %1 + Start/pause - Registering service %1 + Next - Unregistering service %1 + Duration: - Service control + View in separate window - - - ServiceControlPlugin - Service is running + %1 Master – Slideshow + + + SpotlightPanel - Service is not running + Add selected computers - Configure and control Veyon service + Remove selected computers - Register Veyon Service + Update computers in realtime - Unregister Veyon Service + Spotlight - Start Veyon Service + Please select at least one computer to add. - Stop Veyon Service + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + StartAppDialog - Restart Veyon Service + Start application - Query status of Veyon Service + Please enter the applications to start on the selected computers. You can separate multiple applications by line. - Commands for configuring and controlling Veyon Service - + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + pvz.: "C:\Program Files\VideoLAN\VLC\vlc.exe" - - - ShellCommandLinePlugin - Run command file + Remember and add to application menu - File "%1" does not exist! + Application name - Interactive shell and script execution for Veyon Control - + Name: + Vardas: - Commands for shell functionalities - + e.g. VLC + pvz.: VLC SystemTrayIcon System tray icon - + Sistemos dėklo piktograma @@ -3871,18 +4516,18 @@ Typically this is required to support terminal servers. Default (system user groups) - + Numatytas (sistemos vartotojų grupės) TestingCommandLinePlugin Test internal Veyon components and functions - + Patikrinti vidinius Veyon komponentus ir funkcijas Commands for testing internal components and functions of Veyon - + Komandos naudojamos testavimui vidiniams komponentams ir funkcijoms Veyon programinėje įrangoje @@ -3892,8 +4537,8 @@ Typically this is required to support terminal servers. Nusiųsti tekstine žinutę - Use the field below to type your message which will be sent to all selected users. - Apačioje esančiame lange įveskite žinutę kuri bus išsiųsta visiems pasirinktiems vartotojams + Please enter your message which send to all selected users. + @@ -3904,7 +4549,7 @@ Typically this is required to support terminal servers. Use this function to send a text message to all users e.g. to assign them new tasks. - + Naudokite šią funkciją norėdami išsiųsti žinutę visiems vartotojams, pavyzdžiui, priskirti juos naujoms užduotims. Message from teacher @@ -3912,7 +4557,7 @@ Typically this is required to support terminal servers. Send a message to a user - + Nusiųsti žinutę vartotojui @@ -3931,48 +4576,72 @@ Typically this is required to support terminal servers. Builtin UltraVNC server configuration - + Integruoto UltraVNC serverio konfigūracija Enable multi monitor support - + Įgalinti daugiau nei vieno monitoriaus palaikymą Enable Desktop Duplication Engine on Windows 8 and newer + Įgalinti darbalaukio dubliavimo variklį Windows 8 ar naujesnėje versijoje + + + Maximum CPU usage - UserConfig + UserLoginDialog - No write access - Neturite leidimo įrašyti + User login + Vartotojo prisijungimas - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - + Please enter a username and password for automatic login on all computers. + Įveskite vartotojo vardą ir slaptažodį, kad galėtumėte automatiškai prisijungti visuose kompiuteriuose. + + + Username + Vartotojo vardas + + + Password + Slaptažodis - UserSessionControl + UserSessionControlPlugin - User session control + Log in + Prisijungti + + + Click this button to log in a specific user on all computers. Log off - + Atsijungti Click this button to log off users from all computers. - + Paspauskite šį mygtuką, kad atjungtumėte vartotojus visuose kompiuteriuose. Confirm user logoff - + Patvirtinti vartotojo atsijungimą Do you really want to log off the selected users? + Ar tikrai norite atjungti visus pasirinktus vartotojus? + + + User session control + Vartotojo sesijos valdymas + + + Do you really want to log off <b>ALL</b> users? @@ -3980,99 +4649,107 @@ Typically this is required to support terminal servers. VeyonCore [OK] - + [GERAI] [FAIL] - + [KLAIDA] Invalid command! - + Klaidinga komanda! Available commands: - + Galimos komandos: Invalid arguments given - + Gauti klaidingi argumentai Not enough arguments given - use "%1 help" for more information - + Per mažai argumentų - naudokite "%1 help", norėdami gauti daugiau informacijos Unknown result! - + Nežinomas rezultatas! Available modules: - + Galimi moduliai: No module specified or module not found - available modules are: - + Nenurodytas modulis arba modulis nerastas - galimi moduliai yra: Plugin not licensed - + Įskiepis neįdiegtas INFO - + INFORMACIJA ERROR - - - - licensed for - + KLAIDA USAGE - + VARTOJIMAS DESCRIPTION - + APIBŪDINIMAS EXAMPLES - + PAVYZDŽIAI WARNING + ĮSPĖJIMAS + + + Authentication test + Autentifikacijos testas + + + Screen %1 - VeyonServiceControl + VeyonMaster - Veyon Service - + No write access + Neturite leidimo įrašyti + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Neįmanoma išsaugoti asmeninių nustatymų! Prašome patikrinti naudotojo konfigūracijos failo vietą naudodami %1 konfigūratorių. - VncView + VeyonServiceControl - Establishing connection to %1 ... - Vykdomas sujungimas su %1 ... + Veyon Service + Veyon Service WindowsPlatformConfiguration Could not change the setting for SAS generation by software. Sending Ctrl+Alt+Del via remote control will not work! - + Neįmanoma išsaugoti SAS generavimo nustatymo programinėje įrangoje. Komandos Ctrl+Alt+Del siuntimas nuotoliniu valdymu neveiks! WindowsPlatformConfigurationPage Windows - + Windows General @@ -4080,30 +4757,54 @@ Typically this is required to support terminal servers. Enable SAS generation by software (Ctrl+Alt+Del) - + Įgalinti SAS generavimą programinėje įrangoje (Ctrl+Alt+Del) Screen lock - + Ekrano užraktas Hide taskbar - + Paslėpti užduočių juostą Hide start menu - + Paslėpti pradžios meniu Hide desktop - + Paslėpti darbalaukį User authentication - + Vartotojo patvirtinimas Use alternative user authentication mechanism + Naudoti alternatyvų vartotojo autentifikavimo mechanizmą + + + User login + Vartotojo prisijungimas + + + Input start delay + Įvesties vėlinimas + + + Simulated key presses interval + + + + Confirm legal notice (message displayed before user logs in) + + + + Use input device interception driver + + + + Use custom power scheme with disabled power button @@ -4111,10 +4812,10 @@ Typically this is required to support terminal servers. WindowsPlatformPlugin Plugin implementing abstract functions for the Windows platform - + Plėtinio įgyvendinimo abstrakčios funkcijos Windows platformai - Plugin implementing specific functions for the Windows platform + Internal display @@ -4122,30 +4823,34 @@ Typically this is required to support terminal servers. WindowsServiceControl The service "%1" is already installed. - + Tarnyba "%1" jau yra įdiegta. - The service "%1" could not be installed. - + The service "%1" has been installed successfully. + Tarnyba "%1" buvo sėkmingai įdiegta. - The service "%1" has been installed successfully. - + The service "%1" has been uninstalled successfully. + Tarnyba "%" buvo sėkmingai išdiegta. - The service "%1" could not be uninstalled. + Service "%1" could not be found. + Tarnyba "%1" nerasta. + + + The service "%1" could not be installed (error %2). - The service "%1" has been uninstalled successfully. + Could not change the failure actions config for service "%1" (error %2). - The start type of service "%1" could not be changed. + The service "%1" could not be uninstalled (error %2). - Service "%1" could not be found. + The start type of service "%1" could not be changed (error %2). @@ -4153,15 +4858,15 @@ Typically this is required to support terminal servers. X11VncConfigurationWidget Builtin x11vnc server configuration - + Integruoto x11vnc serverio konfigūracija Custom x11vnc parameters: - + Pasirinktiniai x11vnc parametrai: Do not use X Damage extension - + Nenaudokite X Damage papildinio. \ No newline at end of file diff --git a/translations/lv.ts b/translations/veyon_lv.ts similarity index 72% rename from translations/lv.ts rename to translations/veyon_lv.ts index 33bfe1a14..5f9d9a8f3 100644 --- a/translations/lv.ts +++ b/translations/veyon_lv.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -80,10 +80,6 @@ Ja esat ieinteresēti tulkot Veyon citā valodā vai uzlabot esošo tulkojumu, l All groups Visas grupas - - ... - ... - Access control rules Piekļuves kontroles noteikumi @@ -130,26 +126,25 @@ Ja esat ieinteresēti tulkot Veyon citā valodā vai uzlabot esošo tulkojumu, l The specified user is not allowed to access computers with this configuration. - + Norādītajam lietotājam nav piekļuve datoriem ar šo konfigurāciju. Enable usage of domain groups - + Iespējot domēnu grupas lietošanu User groups backend: - - - - Missing user groups backend - + Lietotāju grupas backends: - No default user groups plugin was found. Please check your installation! - + Restrict access to members of specific user groups + Ierobežot piekļuvi konkrētas grupas lietotājiem + + + AccessControlProvider - Restrict access to members of specific user groups + Provider for access control features @@ -179,33 +174,13 @@ Ja esat ieinteresēti tulkot Veyon citā valodā vai uzlabot esošo tulkojumu, l Rule description: Noteikuma apraksts: - - Invert all conditions ("is/has" interpreted as "is/has not") - - Conditions Nosacījumi - - is member of group - ir biedrs grupai - - - Accessing computer is localhost - - - - Accessing user is logged on user - - - - Accessing user is already connected - - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. - + Ja ir vairāk kā viens nosacījums aktivizēts, tad visiem nosacījumiem jāizpildās, lai izpildītos (loģiskais UN). Ja vienam vai vairākiem nosacījumiem jāizpildās (loģiskais VAI), lūdzu izveidojiet vairākus piekļuves kontroles noteikumus. Action @@ -236,31 +211,123 @@ Ja esat ieinteresēti tulkot Veyon citā valodā vai uzlabot esošo tulkojumu, l Piekļūstošais dators - Local (logged on) user - Vietējais (pieslēdzies) lietotājs + Always process rule and ignore conditions + Vienmēr apstrādāt noteikumus un ignorēt nosacījumus - Local computer - Vietējais dators + Accessing computer and local computer + Piekļūt datoram un lokālajam datoram - Always process rule and ignore conditions - + User being accessed + Piekļūt lietotājam - No user logged on - Nav lietotājs pieslēdzies + is logged in locally + ir pieslēdzies lokāli - Accessing user has one or more groups in common with local (logged on) user - + is logged in remotely + ir pieslēdzies attālināti - Accessing computer and local computer are at the same location - + No user is logged in locally + Neviens lietotājs nav pieteicies lokāli + + + One or multiple users are logged in locally + Neviens lietotājs nav pieteicies lokāli + + + No user is logged in remotely + Neviens lietotājs nav pieteicies + + + One or multiple users are logged in remotely + Viens vai vairāki lietotāji ir pieteikušies attālināti is located at + atrodas + + + is not located at + neatrodas + + + are located at the same location + atrodas vienā atrašanās vietā + + + are not located the same location + neatrodas vienā atrašanās vietā + + + is member of group + ir biedrs grupai + + + is not member of group + nav grupas dalībnieks + + + is authenticated via + ir autentificēts ar + + + is not authenticated via + nav autentificēts ar + + + has one or more groups in common with user being accessed + ir viena vai vairākas grupas, kas ir kopīgas lietotājam, kurām var piekļūt + + + has no groups in common with user being accessed + nav kopīgu grupu ar lietotāju, kuram var piekļūt + + + equals user being accessed + vienāds ar lietotāju, kuram piekļūst + + + is different from user being accessed + atšķiras no lietotāja, kuram tiek piekļūts + + + is already connected + jau ir izveidots savienojums + + + is not connected + nav savienots + + + is local computer + ir lokālais dators + + + is not local computer + nav lokālais dators + + + Computer being accessed + Dators, kuram piekļūst + + + Session being accessed is a user session + Sesija, kurai piekļūst, ir lietotāja sesija + + + Session being accessed is a login screen + Sesija, kurai piekļūst, ir pieteikšanās ekrāns + + + Local computer is already being accessed + + + + Local computer is not yet being accessed @@ -284,7 +351,7 @@ Ja esat ieinteresēti tulkot Veyon citā valodā vai uzlabot esošo tulkojumu, l Please enter the following user and computer information in order to test the configured ruleset. - + Lai pārbaudītu konfigurēto kārtulu kopu, lūdzu, ievadiet tālāk norādīto lietotāja un datora informāciju. Local user: @@ -304,44 +371,46 @@ Ja esat ieinteresēti tulkot Veyon citā valodā vai uzlabot esošo tulkojumu, l The access in the given scenario needs permission of the logged on user. - - - - ERROR: Unknown action - Errors: Nezināma darbība + Piekļuvei dotajā scenārijā ir nepieciešama no lietotāja, kurš šobrīd ir pierakstījies. Test result Testa rezultāti - - - AndroidPlatformConfigurationPage - Android - + Authentication method + Autentifikācijas metode - General - Vispārīgi + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + Ievads - - - AuthKeysConfigurationPage - Authentication keys - Autorizācijas atslēga + Please perform the following steps to set up key file authentication: + Lai iestatītu atslēgas faila autentifikāciju, veiciet šādas darbības: - Introduction - Ievads + 1) Create a key pair on the master computer. + 1) Izveido atslēgu pāri galvenajam datoram + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Izveido piekļuves grupu dalībniekiem kuru dalībniekiem atļauts piekļūt citu datoriem + + + 3) Export the public key and import it on all client computers with the same name. + 3) Izgul publisko atslēgu un iegul, ar vienādu vārdu, visos klientu datoros. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Lūdzu skaties <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon administratoru pamācību </a> vairāk informācijai Key file directories @@ -355,14 +424,20 @@ Ja esat ieinteresēti tulkot Veyon citā valodā vai uzlabot esošo tulkojumu, l Private key file base directory Privāto atslēgfailu atrašanās mape - - ... - ... - Available authentication keys Pieejamās autentifikācijas atslēgas + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Autentifikācijas atslēgu pāris sastāv no divām savienotām kriptogrāfiskām atslēgām - privātas un publiskas atslēgas. +Privātā atslēga ļauj lietotājiem galvenajā datorā piekļūt klientu datoriem. +Ir svarīgi, lai piekļuve privātās atslēgas failam būtu tikai autorizētiem lietotājiem. +Publiskā atslēga tiek izmantota klientu datoros, lai autentificētu ienākošā savienojuma pieprasījumu. + Create key pair Izveidot atslēgu @@ -393,57 +468,32 @@ Ja esat ieinteresēti tulkot Veyon citā valodā vai uzlabot esošo tulkojumu, l Please enter the name of the user group or role for which to create an authentication key pair: - + Lūdzu, ievadiet tās lietotāju grupas vai lomas nosaukumu, kurai jāizveido autentifikācijas atslēgu pāris: Do you really want to delete authentication key "%1/%2"? - + Vai tiešām izdzēst autentifikācijas atslēgu "%1/%2"? Please select a key to delete! Lūdzu, izvēlieties atslēgu kuru izdzēst! - - Please enter the name of the user group or role for which to import the authentication key: - - Please select a key to export! Lūdzu, izvēlieties atslēgfailu, kuru izvadīt! Please select a user group which to grant access to key "%1": - + Lūdzu, atlasiet lietotāju grupu, kurai piešķirt piekļuvi atslēgai “%1”: Please select a key which to set the access group for! - - - - Please perform the following steps to set up key file authentication: - - - - 1) Create a key pair on the master computer. - - - - 2) Set an access group whose members should be allowed to access other computers. - - - - 3) Export the public key and import it on all client computers with the same name. - - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - + Izvēlies atslēgu kuru piešķirt piekļuves grupai! - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. @@ -455,15 +505,15 @@ The public key is used on client computers to authenticate incoming connection r Key name contains invalid characters! - + Atslēga satur neatbilstošus simbolus! Invalid key type specified! Please specify "%1" or "%2". - + Norādīts nederīgs atslēgas tips! Lūdzu, norādiet “%1” vai “%2”. Specified key does not exist! Please use the "list" command to list all installed keys. - + Norādītā atslēga nepastāv! Lūdzu, izmantojiet komandu “list”, lai uzskaitītu visas instalētās atslēgas. One or more key files already exist! Please delete them using the "delete" command. @@ -471,7 +521,7 @@ The public key is used on client computers to authenticate incoming connection r Creating new key pair for "%1" - + Veido jaunu atslēgu pāri priekš "%1" Failed to create public or private key! @@ -483,7 +533,7 @@ The public key is used on client computers to authenticate incoming connection r Could not remove key file "%1"! - + Nevar noņemt atslēgas failu "%1"! Could not remove key file directory "%1"! @@ -586,7 +636,7 @@ The public key is used on client computers to authenticate incoming connection r AuthKeysPlugin Create new authentication key pair - + Izveidot jaunu autentificēšanās atslēgas pāri Delete authentication key @@ -594,15 +644,15 @@ The public key is used on client computers to authenticate incoming connection r List authentication keys - + Saraksts ar autentificēšanās atslēgām Import public or private key - + Importēt publisko vai privāto atslēgu Export public or private key - + Eksporēt publisko vai privāto atslēgu Extract public key from existing private key @@ -644,10 +694,6 @@ The public key is used on client computers to authenticate incoming connection r This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - - Please specify the command to display help for! - - TYPE TIPS @@ -656,10 +702,6 @@ The public key is used on client computers to authenticate incoming connection r PAIR ID Pāra ID - - Command line support for managing authentication keys - - Commands for managing authentication keys @@ -676,6 +718,30 @@ The public key is used on client computers to authenticate incoming connection r This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + + + + Key file authentication + + + + Key file + + + + Please specify the key name (e.g. "teacher/public") as the first argument. + + + + Please specify the command to display help for. + + + + The specified command does not exist or no help is available for it. + + AuthKeysTableModel @@ -697,80 +763,223 @@ The public key is used on client computers to authenticate incoming connection r - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - Datori + General + Vispārīgi - Name - Vārds + Username to bind DN mapping: + - Host address/IP - Dalībnieku adreses un IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + + AuthLdapDialog - MAC address - MAC adrese + Veyon Logon + - Add new computer - Pievienot jaunu datoru + Please enter your domain/LDAP username and password in order to access computers. + - Remove selected computer - Izdzēst izvēlēto datoru + Username + Lietotājvārds - New computer - Jauns dators + Password + Parole - Builtin directory - Iebūvētās mapes + Authentication error + Autentifikācijas kļūda - Locations & computers + Logon failed with given username and password. Please try again! + + + AuthLogonDialog - Locations + Veyon Logon - Add new location + Please enter your username and password in order to access computers. - Remove selected location - + Username + Lietotājvārds - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - + Password + Parole - New location + Authentication error + Autentifikācijas kļūda + + + Logon failed with given username and password. Please try again! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command - Parādīt palīdzību izvēlētajai komandai - - - Import objects from given file + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Export objects to given file + Logon authentication - Invalid type specified. Valid values are "%1" or "%2". + Logon + + + + + AuthSimpleDialog + + Veyon Logon + + + + Please enter the Veyon password: + + + + Authentication error + Autentifikācijas kļūda + + + Logon failed with given password. Please try again! + + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + + + + Simple password authentication + + + + Simple password + + + + + AuthenticationPage + + Authentication is set up properly on this computer. + + + + + AuthenticationPageTab + + Enabled + Iespējots + + + Test + Tests + + + + BuiltinDirectoryConfiguration + + Builtin directory + Iebūvētās mapes + + + + BuiltinDirectoryConfigurationPage + + Computers + Datori + + + Name + Vārds + + + Host address/IP + Dalībnieku adreses un IP + + + MAC address + MAC adrese + + + Add new computer + Pievienot jaunu datoru + + + Remove selected computer + Izdzēst izvēlēto datoru + + + New computer + Jauns dators + + + Builtin directory + Iebūvētās mapes + + + Locations + Vietas + + + Add new location + Pievienot jaunu vietu + + + Remove selected location + Noņemt izvēlēto vietu + + + New location + Jauna vieta + + + Directory name + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + + + + BuiltinDirectoryPlugin + + Show help for specific command + Parādīt palīdzību izvēlētajai komandai + + + Import objects from given file + + + + Export objects to given file + + + + Invalid type specified. Valid values are "%1" or "%2". @@ -799,11 +1008,11 @@ The public key is used on client computers to authenticate incoming connection r Can't open file "%1" for reading! - + Nevar atvērt failu "%1" lasīšanai! Unknown argument "%1". - + Nezināma arguments "%1". Computer "%1" (host address: "%2" MAC address: "%3") @@ -847,7 +1056,7 @@ The public key is used on client computers to authenticate incoming connection r Can't open file "%1" for writing! - + Nevar atvērt failu "%1" rakstīšanai! No format string specified! @@ -863,11 +1072,11 @@ The public key is used on client computers to authenticate incoming connection r Add a location or computer - + Pievienot vietu vai datoru Clear all locations and computers - + Notīrīt visas vietas un datorus Dump all or individual locations and computers @@ -875,15 +1084,15 @@ The public key is used on client computers to authenticate incoming connection r List all locations and computers - + Saraksts ar vietām un datoriem Remove a location or computer - + Noņemt vietu vai datoru Location "%1" - + Vieta "%1" Builtin (computers and locations in local configuration) @@ -891,7 +1100,7 @@ The public key is used on client computers to authenticate incoming connection r Location - + Vieta FILE @@ -899,7 +1108,7 @@ The public key is used on client computers to authenticate incoming connection r LOCATION - + VIETA FORMAT-STRING-WITH-PLACEHOLDERS @@ -959,7 +1168,7 @@ The public key is used on client computers to authenticate incoming connection r Add a room - + Pievienot istabu Add a computer to room %1 @@ -967,7 +1176,7 @@ The public key is used on client computers to authenticate incoming connection r OBJECT - + OBJEKTS Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. @@ -975,7 +1184,7 @@ The public key is used on client computers to authenticate incoming connection r Remove a computer by name - + Noņemt datorus ar vārdu Remove an object by UUID @@ -983,11 +1192,11 @@ The public key is used on client computers to authenticate incoming connection r "Room 01" - + "Istaba 01" "Computer 01" - + "Dators 01" HOST ADDRESS @@ -997,6 +1206,14 @@ The public key is used on client computers to authenticate incoming connection r MAC ADDRESS MAC adrese + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. + + BuiltinUltraVncServer @@ -1009,15 +1226,11 @@ The public key is used on client computers to authenticate incoming connection r BuiltinX11VncServer Builtin VNC server (x11vnc) - + Iebūvētais VNC serveris (x11vnc) ComputerControlListModel - - Host/IP address: %1 - Dalībnieku adreses/IP: %1 - Active features: %1 Aktīvās iespējas: %1 @@ -1032,11 +1245,7 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off - - - - Service unreachable or not running - + Dators nav tiešsaistē vai ir izslēgts Authentication failed or access denied @@ -1052,10 +1261,42 @@ The public key is used on client computers to authenticate incoming connection r Logged on user: %1 - + Ielogojies lietotajā: %1 Location: %1 + Vieta: %1 + + + [no user] + [nav lietotājs] + + + Veyon Server unreachable or not running + + + + Name: %1 + Vārds: %1 + + + Hostname: %1 + + + + unknown + nezināms + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active @@ -1083,12 +1324,23 @@ The public key is used on client computers to authenticate incoming connection r Access control error - + Piekļuves kontroles kļūda User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + + Active connections: + Aktīvās konekcijas: + + + + ComputerGroupSelector + + Group %1 + + ComputerManager @@ -1116,20 +1368,55 @@ The public key is used on client computers to authenticate incoming connection r Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + + Logged in since + Pieslēdzies kopš + + + %1 days + %1 days + + + 1 day + 1 diena + - ComputerSelectPanel + ComputerMonitoring + + Computers + Datori + + + Search users and computers + + + + Select all + + + + Unselect all + + + + Add to group + + - Computer management - Datora pārvaldība + Remove from group + + + + ComputerSelectPanel Computer search Datora meklēšana Add location - + Pievienot vietu Save computer/user list @@ -1151,79 +1438,83 @@ The public key is used on client computers to authenticate incoming connection r Could not write the computer and users list to %1! Please check the file access permissions. + + Search computers + Meklēt darorus + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. + Clear system-wide Veyon configuration - Please specify a valid filename for the configuration export. - + List all configuration keys and values + Saraksts ar konfigurācijas atslēgām un vērtībām - Please specify a valid key. + Import configuration from given file - Specified key does not exist in current configuration! + Export configuration to given file - Please specify a valid value. + Read and output configuration value for given key - Configure Veyon at command line + Write given value to given configuration key - Output file is not writable! + Unset (remove) given configuration key - Output directory is not writable! + Upgrade and save configuration of program and plugins - Configuration file is not readable! + Please specify an existing configuration file to import. - Clear system-wide Veyon configuration + Configuration file is not readable! - List all configuration keys and values + Please specify a valid filename for the configuration export. - Import configuration from given file - + Output file is not writable! + Izejas fails nav rakstāms! - Export configuration to given file - + Output directory is not writable! + Izejas mape nav rakstāma! - Read and output configuration value for given key - + Please specify a valid key. + Precizē derīgu atslēgu. - Write given value to given configuration key + Specified key does not exist in current configuration! - Unset (remove) given configuration key - + Please specify a valid value. + Lūdzu precizē derīgu vērtību. - Commands for managing the configuration of Veyon - + Configure Veyon at command line + Konfirugē Veyon komandrindā - Upgrade and save configuration of program and plugins + Commands for managing the configuration of Veyon @@ -1249,6 +1540,10 @@ The public key is used on client computers to authenticate incoming connection r Could not apply platform-specific configuration settings. + + Could not configure the firewall configuration for the %1 Service. + + DemoClient @@ -1279,10 +1574,6 @@ The public key is used on client computers to authenticate incoming connection r Memory limit Atmiņas limits - - Use multithreading (experimental) - - MB MB @@ -1299,13 +1590,17 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running + + Bandwidth limit + Joslas platuma limits + + + MB/s + MB/s + DemoFeaturePlugin - - Fullscreen demo - Pilnekrāna demonstrējums - Stop demo Apturēt demonstrējumu @@ -1319,51 +1614,87 @@ The public key is used on client computers to authenticate incoming connection r Dot demonstrējumu caur ekrāna raidīšanu - Demo server - Demonstrējuma serveris + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Demo + Demo - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. + Share your screen or allow a user to share his screen with other users. - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Full screen demo + Pilna ekrāna priekšskatījums + + + Share your own screen in fullscreen mode + Dalies ar savu ekrānu pilnekrāna veidā + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. - - - DesktopAccessDialog - Desktop access dialog + Share your own screen in a window + Dalies ar savu ekrānu logā + + + Share selected user's screen in fullscreen mode - Confirm desktop access + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. - Never for this session + Share selected user's screen in a window - Always for this session + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. - The user %1 at computer %2 wants to access your desktop. Do you want to grant access? + Please select a user screen to share. + + Please select only one user screen to share. + + + + All screens + Visi ekrāni + - DesktopServicesConfigurationPage + DesktopAccessDialog - Programs & websites + Desktop access dialog - Predefined programs + Confirm desktop access + Apstiprini darba virsmas piekļuvi + + + Never for this session + Nekad šai sesijai + + + Always for this session + Vienmēr šai sesijai + + + The user %1 at computer %2 wants to access your desktop. Do you want to grant access? + + + DesktopServicesConfigurationPage Name Vārds @@ -1372,71 +1703,83 @@ The public key is used on client computers to authenticate incoming connection r Path Ceļš - - Add new program - Pievienot jaunu programmu - - - Remove selected program - Noņemt izvēlēto programmu - Predefined websites - + Iepriekšdefinētas web lapas Remove selected website - + Noņemt izvēlēto web adresi URL URL - New program - + New website + Jauna web adrese - New website + Applications & websites + Lietotnes un web adreses + + + Predefined applications + + Add new application + Pievienot jaunu lietotni + + + Remove selected application + Noņemt izvēlēto lietotni + + + Add new website + Pievienot jaunu web adresi + + + New application + Jauna lietotne + DesktopServicesFeaturePlugin - - Run program - - Open website Atvērt vietni Click this button to open a website on all computers. - + Spied šo pogu lai atvērtu web adresi visos datoros. - Start programs and services in user desktop - + Open website "%1" + Atvērt web adresi "1%" - Click this button to run a program on all computers. - + Custom website + Pielāgota web adrese - Run program "%1" - Palaist programmu "%1" + Start application + Palaist lietotni - Custom program - + Click this button to start an application on all computers. + Spied šo pogu lai palaistu lietotni visos datoros. - Open website "%1" - + Start application "%1" + Palaist lietotni "%1" - Custom website + Custom application + Pielāgota lietotne + + + Start apps and open websites in user sessions @@ -1444,11 +1787,11 @@ The public key is used on client computers to authenticate incoming connection r DocumentationFigureCreator Teacher - + Skolotājs Room %1 - + Istaba %1 Please complete all tasks within the next 5 minutes. @@ -1456,38 +1799,42 @@ The public key is used on client computers to authenticate incoming connection r Custom website - + Pielāgota web adrese Open file manager - + Atvērt failu pārvaldnieku Start learning tool - + Sākt mācīšanās rīku Play tutorial video - - - - Custom program - + Atskaņot pamācību video Handout - + Izdale Texts to read + Teksts lasīšanai + + + generic-student-user + + Custom application + Pielāgota lietotne + ExternalVncServer External VNC server - + Ārējais VNC serveris @@ -1498,7 +1845,7 @@ The public key is used on client computers to authenticate incoming connection r Port: - + Ports: Password: @@ -1506,9 +1853,164 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands + + List names of all available features + Saraksts ar visām pieejām iespējām + + + Show table with details of all available features + + + + Start a feature on a remote host + + + + Stop a feature on a remote host + + + + Please specify the command to display help for. + + + + Displays a list with the names of all available features. + + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + + + + HOST ADDRESS + + + + FEATURE + + + + ARGUMENTS + ARGUMENTI + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + + + + Lock the screen + Aizslēgt ekrānu + + + Display a text message + Parādīt teksta ziņojumu + + + Test message + Testa ziņojums + + + Start an application + Palaist lietotni + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + + + + Unlock the screen + Ieslēgt ekrānu + + + The specified command does not exist or no help is available for it. + + + + Name + Vārds + + + Description + Apraksts + + + Master + Galvenais + + + Service + Pakalpojums + + + Worker + Darbinieks + + + UID + UID + + + Plugin + Spraudnis + + + Invalid feature name or UID specified + + + + Error parsing the JSON-encoded arguments: %1 + + + + Failed to initialize credentials + + + + Could not establish a connection to host %1 + + + + Failed to send feature control message to host %1 + + + + Feature-related CLI operations + + + + Commands for controlling features + + + + + FileTransferConfigurationPage + + File transfer + Faila pārsūtīšana + + + Directories + Mapes + + + Destination directory + Mērķa mape + + + Default source directory + Noklusējuma avota mape + + + Options + Iespējas + + + Remember last source directory + + - Feature control + Create destination directory if it does not exist @@ -1523,7 +2025,7 @@ The public key is used on client computers to authenticate incoming connection r FileTransferDialog File transfer - + Faila pārsūtīšana Options @@ -1531,7 +2033,7 @@ The public key is used on client computers to authenticate incoming connection r Transfer only - + Pārsūtīšana tikai Transfer and open file(s) with associated program @@ -1543,14 +2045,21 @@ The public key is used on client computers to authenticate incoming connection r Files - + Faili Start - + Sākt Overwrite existing files + Pārrakstīt esošos failus + + + + FileTransferFileDialog + + Select one or more files to transfer @@ -1558,7 +2067,7 @@ The public key is used on client computers to authenticate incoming connection r FileTransferPlugin File transfer - + Faila pārsūtīšana Click this button to transfer files from your computer to all computers. @@ -1574,7 +2083,7 @@ The public key is used on client computers to authenticate incoming connection r Received file "%1". - + Saņemts fails "%1" Could not receive file "%1" as it already exists. @@ -1589,7 +2098,7 @@ The public key is used on client computers to authenticate incoming connection r GeneralConfigurationPage User interface - + Lietotāja saskarne Language: @@ -1611,17 +2120,13 @@ The public key is used on client computers to authenticate incoming connection r Log file directory Žurnālfaila mape - - ... - ... - Log level Nothing - + Nekas Only critical messages @@ -1629,11 +2134,11 @@ The public key is used on client computers to authenticate incoming connection r Errors and critical messages - + Kļūdas un kritisko kļūdu ziņojumi Warnings and errors - + Brīdinājumi un kļūdas Information, warnings and errors @@ -1649,24 +2154,12 @@ The public key is used on client computers to authenticate incoming connection r Clear all log files - + Noņemt visus ziņojumu failus Log to standard error output - - Network object directory - - - - Backend: - - - - Update interval: - - %1 service %1 pakalpojums @@ -1703,102 +2196,79 @@ The public key is used on client computers to authenticate incoming connection r x x - - seconds - sekundes - Write to logging system of operating system - Authentication - Autentifikācija - - - Method: + TLS configuration - Logon authentication + Use certificate authority for TLS connections - Key file authentication + CA certificate file - Test - Tests + ... + ... - Authentication is set up properly on this computer. + Host certificate file - Authentication keys are not set up properly on this computer. + Host private key file - Authentication test + Style: - - - InternetAccessControlConfigurationPage - Internet access control + Native - Backend: + Color scheme: - General settings + Light - Backend settings + Dark - - - InternetAccessControlPlugin - - Block access to the internet - Liegt interneta piekļuvi - - - Allow access to the internet - Atļaut interneta piekļuvi - - - Show help about command - Parādīt palīdzību par komandu - - Block internet - Atslēgt internetu + User groups + Lietotāju grupas - Click this button to block access to the internet. + Backend: - Unblock internet - Pieslēgt internetu + Include user groups from domain + - Click this button to allow access to the internet. - + Missing user groups backend + Trūks lietotāju grupas backends - Control access to the internet + No user groups plugin was found. Please check your installation! + + + HeadlessVncServer - Commands for controlling access to the internet + Headless VNC server @@ -1817,314 +2287,284 @@ The public key is used on client computers to authenticate incoming connection r - LdapConfigurationPage + LdapConfiguration - Basic settings + LDAP connection failed - General - Vispārīgi - - - LDAP server and port + Could not connect to the LDAP server. Please check the server parameters. + +%1 - Bind DN + LDAP bind failed - Bind password + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 - Anonymous bind + LDAP bind successful - Use bind credentials + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - Base DN + LDAP base DN test failed - Fixed base DN + Could not query the configured base DN. Please check the base DN parameter. + +%1 - e.g. dc=example,dc=org + LDAP base DN test successful - Discover base DN by naming context + The LDAP base DN has been queried successfully. The following entries were found: + +%1 - e.g. namingContexts or defaultNamingContext + LDAP naming context test failed - Environment settings + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 - Object trees + LDAP naming context test successful - Computer tree + The LDAP naming context has been queried successfully. The following base DN was found: +%1 - e.g. OU=Groups + user tree User tree - - - - e.g. OU=Users - + Lietotāju koks - e.g. OU=Computers + group tree Group tree - + Grupu koks - Perform recursive search operations in object trees - + computer tree + datoru koks - Object attributes - + Computer tree + Datoru koks - e.g. hwAddress + computer group tree - e.g. member or memberUid - + Computer group tree + Datoru grupu koks - e.g. dNSHostName + user objects - Computer MAC address attribute + User login name attribute - Group member attribute - + group members + grupas dalībnieki - e.g. uid or sAMAccountName + Group member attribute - Advanced settings - + Group not found + Grupa nav atrasta - Optional object filters + Could not find a group with the name "%1". Please check the group name or the group tree parameter. - Filter for user groups + computer objects - Filter for users + Computer display name attribute - Filter for computer groups + Invalid hostname - Group member identification + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Distinguished name (Samba/AD) + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - List all groups of a user + Computer hostname attribute - List all groups of a computer + computer MAC addresses - Get computer object by IP address + Computer MAC address attribute - LDAP connection failed + computer locations - LDAP bind failed + Computer location attribute - LDAP bind successful + Location name attribute - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - + users + lietotāji - LDAP base DN test failed - + user groups + lietotāju grupas - LDAP base DN test successful - + computers + datori - LDAP naming context test failed - + computer groups + datoru grupas - LDAP naming context test successful + computer containers - The LDAP naming context has been queried successfully. The following base DN was found: -%1 + groups of user - user tree - + User not found + Lietotājs nav atrasts - group tree + Could not find a user with the name "%1". Please check the username or the user tree parameter. - computer tree + groups of computer - Enter username - Ievadi lietotājvārdu + Computer not found + Dators nav atrasts - Please enter a user login name (wildcards allowed) which to query: + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - user objects + Hostname lookup failed - Enter group name - Ievadi grupas nosaukumu - - - Please enter a group name whose members to query: + Could not lookup hostname for IP address %1. Please check your DNS server settings. - group members - grupas dalībnieki - - - Group not found - Grupa nav atrasta - - - Could not find a group with the name "%1". Please check the group name or the group tree parameter. + location entries - Enter computer name - Ievadi datora nosaukumu - - - computer objects + Computer groups filter - Enter computer DN + Computer locations identification - Please enter the DN of a computer whose MAC address to query: + Filter for computer groups - computer MAC addresses + Invalid test value - users - lietotāji - - - user groups - lietotāju grupas - - - computer groups - datoru grupas - - - Please enter a user login name whose group memberships to query: + An empty or invalid value has been supplied for this test. - groups of user + LDAP %1 test failed - User not found - Lietotājs nav atrasts - - - groups of computer + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 - Computer not found + LDAP %1 test successful - Enter computer IP address + The %1 has been queried successfully and %2 entries were found. - Please enter a computer IP address which to resolve to an computer object: + LDAP test failed - computers - datori - - - LDAP %1 test failed + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 - LDAP %1 test successful - + and + un - The %1 has been queried successfully and %2 entries were found. + LDAP test successful @@ -2152,538 +2592,484 @@ The public key is used on client computers to authenticate incoming connection r - (only if different from group tree) - - - - Computer group tree - - - - computer group tree - - - - Filter for computers - - - - e.g. room or computerLab + LDAP directory + + + LdapConfigurationPage - Integration tests - + Basic settings + Pamata iestatījumi - Computer groups - Datoru grupas + General + Vispārīgi - e.g. name or description + LDAP server and port - Filter for computer containers + Bind DN - Computer containers or OUs + Bind password - Connection security + Anonymous bind - TLS certificate verification + Use bind credentials - System defaults - Sistēmas noklusējums - - - Never (insecure!) + Base DN - Custom CA certificate file + Fixed base DN - None - Nav - - - TLS + e.g. dc=example,dc=org - SSL + Discover base DN by naming context - e.g. (objectClass=computer) + e.g. namingContexts or defaultNamingContext - e.g. (objectClass=group) + Environment settings - e.g. (objectClass=person) - + Object trees + Objektu koks - e.g. (objectClass=room) or (objectClass=computerLab) - + Computer tree + Datoru koks - e.g. (objectClass=container) or (objectClass=organizationalUnit) + e.g. OU=Groups - Could not query the configured base DN. Please check the base DN parameter. - -%1 - + User tree + Lietotāju koks - The LDAP base DN has been queried successfully. The following entries were found: - -%1 + e.g. OU=Users - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 + e.g. OU=Computers - Certificate files (*.pem) - + Group tree + Grupu koks - Could not connect to the LDAP server. Please check the server parameters. - -%1 + Perform recursive search operations in object trees - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 + Object attributes - Encryption protocol + e.g. hwAddress - Computer location attribute + e.g. member or memberUid - Computer display name attribute + e.g. dNSHostName - Location name attribute + Computer MAC address attribute - e.g. cn or displayName + Group member attribute - Computer locations identification + e.g. uid or sAMAccountName - Identify computer locations (e.g. rooms) via: - + Advanced settings + Paplašināti iestatījumi - Location attribute in computer objects + Optional object filters - List all entries of a location + Filter for user groups - List all locations - + Filter for users + Lietotāju filtrs - Enter computer display name + Filter for computer groups - Please enter a computer display name to query: + Group member identification - Enter computer location name + Distinguished name (Samba/AD) - Please enter the name of a computer location (wildcards allowed): + List all groups of a user - computer locations + List all groups of a computer - Enter location name + Get computer object by IP address - Please enter the name of a location whose entries to query: - + Enter username + Ievadi lietotājvārdu - location entries + Please enter a user login name (wildcards allowed) which to query: - LDAP test failed - + Enter group name + Ievadi grupas nosaukumu - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 + Please enter a group name whose members to query: - and - + Enter computer name + Ievadi datora nosaukumu - LDAP test successful - + Enter computer DN + Ievadi datora DN - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 + Please enter the DN of a computer whose MAC address to query: - Browse + Please enter a user login name whose group memberships to query: - Test - Tests + Enter computer IP address + Ievadi datora IP adresi - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Please enter a computer IP address which to resolve to an computer object: - Computer hostname attribute + (only if different from group tree) - Please enter a computer hostname to query: - + Computer group tree + Datoru grupu koks - Invalid hostname + Filter for computers - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + e.g. room or computerLab - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Integration tests - Could not find a user with the name "%1". Please check the username or the user tree parameter. - + Computer groups + Datoru grupas - Enter hostname - + e.g. name or description + piemēram vārds vai apraksts - Please enter a computer hostname whose group memberships to query: + Filter for computer containers - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Computer containers or OUs - Hostname lookup failed + Connection security - Could not lookup hostname for IP address %1. Please check your DNS server settings. + TLS certificate verification - User login name attribute - + System defaults + Sistēmas noklusējums - Configured attribute for user login name or computer hostname (OpenLDAP) - + Never (insecure!) + Nekad (nedrošs!) - computer containers + Custom CA certificate file - - - LdapPlugin - Auto-configure the base DN via naming context - + None + Nav - Query objects from LDAP directory - + TLS + TLS - Show help about command - Parādīt palīdzību par komandu + SSL + SSL - Commands for configuring and testing LDAP/AD integration + e.g. (objectClass=computer) - Basic LDAP/AD support for Veyon + e.g. (objectClass=group) - %1 (load computers and locations from LDAP/AD) + e.g. (objectClass=person) - %1 (load users and groups from LDAP/AD) + e.g. (objectClass=room) or (objectClass=computerLab) - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + e.g. (objectClass=container) or (objectClass=organizationalUnit) - No naming context attribute name given - falling back to configured value. + Certificate files (*.pem) - Could not query base DN. Please check your LDAP configuration. - + Encryption protocol + Kriptēšanas protokols - Configuring %1 as base DN and disabling naming context queries. + Computer location attribute - - - LdapProConfigurationPage - LDAP Pro + Computer display name attribute - Instances + Location name attribute - Enter name + e.g. cn or displayName - Please enter a name for the instance (can't be changed later!): + Computer locations identification - Remove instance + Identify computer locations (e.g. rooms) via: - Do you really want to remove instance "%1"? + Location attribute in computer objects - Configuration for instance "%1" + List all entries of a location - - - LdapProPlugin - Professional LDAP/AD integration for Veyon - + List all locations + Saraksts ar visām vietām - %1 (load computers and locations from LDAP/AD) + Enter computer display name - %1 (load users and groups from LDAP/AD) + Please enter a computer display name to query: - - - LicensingConfigurationPage - Licensing + Enter computer location name - Installed licenses + Please enter the name of a computer location (wildcards allowed): - Add new network range + Enter location name - Remove selected network range + Please enter the name of a location whose entries to query: - ID + Browse - Feature - + Test + Tests - Valid until + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - Licensee + Computer hostname attribute - Browse license file + Please enter a computer hostname to query: - Veyon license files (*.vlf) + Enter hostname - Remove license + Please enter a computer hostname whose group memberships to query: - Do you really want to remove the selected license? + User login name attribute - <N/A> - <N/A> + Configured attribute for user login name or computer hostname (OpenLDAP) + - Invalid license file + Directory name - Could not open the license file for reading! + Query options - The selected license file does not contain valid data. + Query nested user groups (supported by AD only) - The selected license file could not be verified. - + Query timeout + Pieprasījuma noilgums - The selected license file is not valid for this installation. - + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. + LDAP - The license is already installed. + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + LdapPlugin - Information + Auto-configure the base DN via naming context - Installation ID + Query objects from LDAP directory - Addons available for licensing - + Show help about command + Parādīt palīdzību par komandu - Addon + Commands for configuring and testing LDAP/AD integration - - - LicensingPlugin - Show help for specific command - Parādīt palīdzību izvēlētajai komandai + Basic LDAP/AD support for Veyon + - Show all installed licenses + %1 (load computers and locations from LDAP/AD) - Add license file + %1 (load users and groups from LDAP/AD) - Remove installed license + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - -USAGE - -%1 add <LICENSE FILE> - - + No naming context attribute name given - falling back to configured value. - -USAGE - -%1 remove <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. - No certificate found with given ID + Configuring %1 as base DN and disabling naming context queries. - <N/A> - <N/A> + Test binding to an LDAP server + - Licensing management + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Commands for managing license keys + LDAP bind @@ -2691,7 +3077,7 @@ USAGE LinuxPlatformConfigurationPage Linux - + Linux Custom PAM service for user authentication @@ -2699,14 +3085,22 @@ USAGE User authentication + Lietotāja autentificēšanās + + + User sessions - Session management + Minimum session lifetime before server start - Display manager users + User login + Lietotāja logins + + + Login key sequence @@ -2716,10 +3110,6 @@ USAGE Plugin implementing abstract functions for the Linux platform - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2739,11 +3129,11 @@ USAGE - Disable balloon tooltips - + Show icons only + Rādīt ikonas tikai - Show icons only + Disable tooltips @@ -2793,10 +3183,6 @@ USAGE About Qt - - Authentication impossible - - Configuration not writable @@ -2827,7 +3213,7 @@ USAGE Master - + Galvenais Access control @@ -2839,7 +3225,7 @@ USAGE Auto - + Automātiski About @@ -2857,10 +3243,6 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - - Access denied Piekļuve liegta @@ -2882,63 +3264,101 @@ USAGE - Reset configuration + Reset configuration + + + + Do you really want to reset the local configuration and revert all settings to their defaults? + + + + Search users and computers + + + + Align computers to grid + Sakārtot datorus režģī + + + %1 Configurator + + + + Insufficient privileges + + + + Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + + + + Only show powered on computers + + + + &Save settings to file + + + + &View - Do you really want to reset the local configuration and revert all settings to their defaults? + &Standard - Search users and computers + &Advanced - Adjust optimal size - Pielāgot labākajam izmēram + Use custom computer arrangement + - Align computers to grid - Sakārtot datorus režģī + Locations && computers + - %1 Configurator - + Authentication + Autentifikācija - Insufficient privileges + Adjust size of computer icons automatically - Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + Slideshow - Only show powered on computers - + Spotlight + Izcelt - &Save settings to file + Veyon Master - &View - + Locations & computers + Vietas un datori - &Standard + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. - &Advanced + Only show computers with logged on users - Use custom computer arrangement + Load computer positions - Locations && computers + Save computer positions @@ -2948,10 +3368,6 @@ USAGE Directories Mapes - - ... - ... - User configuration @@ -2982,11 +3398,11 @@ USAGE Basic settings - + Pamata iestatījumi Behaviour - + Rīcība Enforce selected mode for client computers @@ -2994,7 +3410,7 @@ USAGE Hide local computer - + Slēpt lokālos datorus Hide computer filter field @@ -3006,11 +3422,11 @@ USAGE User interface - + Lietotāja saskarne Background color - + Fona krāsa Thumbnail update interval @@ -3022,23 +3438,27 @@ USAGE Program start - + Programmas izpilde Modes and features - + Režīmi un iespējas User and computer name - + Lietotāja un datora vārds Only user name + Tikai lietotāja vārdu + + + Only last part of user name Only computer name - + Tikai datora vārds Computer thumbnail caption @@ -3046,19 +3466,19 @@ USAGE Text color - + Teksta krāsa Sort order - + Kārtošanas kārtība Computer and user name - + Datoru un lietotāju vārdi Computer locations - + Datoru atrašanās vietas Show current location only @@ -3085,172 +3505,187 @@ USAGE - Automatically adjust computer thumbnail size + Automatically open computer select panel - Automatically open computer select panel + Use modern user interface (experimental) - - - MonitoringMode - Monitoring + Thumbnail spacing - Builtin monitoring mode + px - This mode allows you to monitor all computers at one or more locations. + Hide local session - - - NetworkDiscoveryConfigurationPage - Network discovery - + Auto + Automātiski - Mode + Thumbnail aspect ratio - Scan network ranges + Automatically adjust computer icon size - e.g. 192.168.1.0/24 + Open feature windows on the same screen as the main window - Scan all subnets of computer + Configuration templates - Scan custom subnet + Image quality in monitoring mode - Scan sessions on local computer + Highest - Test - Tests + High + - Network ranges + Medium - Add new group + Low - Remove selected group + Lowest - Groups + Remote access image quality - First address + Advanced - Last address + Computer name source - Add new network range + Default - Remove selected network range + Host address + Dalībnieku adreses + + + Session client address - Parallel scans + Session client name - Scan timeout + Session host name - ms - ms + Session metadata + - Session scan limit + Full name of user - Options - Iespējas + User login name + - Reverse lookup discovered IP addresses to host names + Computer UID role - New location + Session meta data hash - - - NetworkDiscoveryDirectory - Scanning... - Skenējas... + Always expand all locations + - Discovered computers - Atklātie datori + Image quality + - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command - Parādīt palīdzību izvēlētajai komandai + Monitoring + Uzraudzība - Scan a subnet - Skenēt apakštīklu + Builtin monitoring mode + - -USAGE - -%1 scan [<SUBNET>] - - + This mode allows you to monitor all computers at one or more locations. - Network object directory which automatically discovers computers in the network + Query application version of the server - Network discovery (scan network for Veyon clients) + Query active features - Commands for managing the network discovery directory + Query properties of remotely available screens + + NestedNetworkObjectDirectory + + All directories + Visas direktorijas + + + + NetworkObjectDirectoryConfigurationPage + + Update interval: + Atsvaidzināšanas intervāls: + + + seconds + sekundes + + + + NetworkObjectDirectoryConfigurationPageTab + + Enabled + Iespējots + + NetworkObjectTreeModel Locations/Computers - + Atrašanās vietas/Datori @@ -3261,15 +3696,15 @@ USAGE e.g. Veyon - + piem. Veyon Remember and add to website menu - + Atcerēties un pievienot mājaslapu izvēlei e.g. www.veyon.io - + piem. www.veyon.io Please enter the URL of the website to open: @@ -3277,33 +3712,45 @@ USAGE Name: - + Vārds: + + + Website name + Mājaslapas nosaukums - PasswordDialog + PluginCommands - Username - Lietotājvārds + List names of all installed plugins + - Password - Parole + Show table with details of all installed plugins + - Veyon Logon - + Name + Vārds - Authentication error - Autentifikācijas kļūda + Description + Apraksts - Logon failed with given username and password. Please try again! + Version + Versija + + + UID + UID + + + Plugin-related CLI operations - Please enter your username and password in order to access computers. + Commands for managing plugins @@ -3323,7 +3770,7 @@ USAGE Click this button to reboot all computers. - + Noklikšķiniet uz šīs pogas, lai restartētu visus datorus. Power down @@ -3331,7 +3778,7 @@ USAGE Click this button to power down all computers. This way you do not have to power down each computer by hand. - + Noklikšķiniet uz šīs pogas, lai izslēgtu visus datorus. Tādējādi nav nepieciešams katru datoru izslēgt atsevišķi. Power on/down or reboot a computer @@ -3349,13 +3796,9 @@ USAGE Do you really want to reboot the selected computers? Vai Tu tiešām vēlies restartēt izvēlētos datorus? - - Do you really want to power down the selected computer? - Vai Tu tiešām vēlies izslēgt izvēlētos datorus? - Power on a computer via Wake-on-LAN (WOL) - + Ieslēgt datoru izmantojot Wake-on-LAN (WOL) MAC ADDRESS @@ -3363,45 +3806,59 @@ USAGE This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. - + Šī komanda pārraida tīklā Wake-on-LAN (WOL) paketi, lai ieslēgtu datoru ar norādīto MAC adresi. Please specify the command to display help for! - + Lūdzu, norādiet komandu, kurai parādīt palīdzību! Invalid MAC address specified! - + Norādītā MAC adrese nav pareiza! Commands for controlling power status of computers - + Datoru statusa kontroles komandas Power down now - + Izslēgt tagad Install updates and power down - + Instalēt atjauninājumus un izslēgt Power down after user confirmation - + Izslēgt pēc lietotāja piekrišanas Power down after timeout - + Izslēgt pēc noteikta laika The computer was remotely requested to power down. Do you want to power down the computer now? - + Datoram pieprasa attālināti izslēgties. Vai vēlaties izslēgt datoru tagad? The computer will be powered down in %1 minutes, %2 seconds. Please save your work and close all programs. - + Dators tiks izslēgts pēc %1 minūtēm, %2 sekundēm. + +Lūdzu, saglabājiet savu darbu un aizveriet visas programmas. + + + Do you really want to reboot <b>ALL</b> computers? + Vai tiešām vēlaties restartēt <b>ALL</b> datorus? + + + Do you really want to power down <b>ALL</b> computers? + Vai tiešām vēlaties izslēgt <b>ALL</b> datorus? + + + Do you really want to power down the selected computers? + Vai tiešām vēlaties izslēgt atlasītos datorus? @@ -3412,15 +3869,15 @@ Please save your work and close all programs. Please specify a timeout for powering down the selected computers: - + Lūdzu, norādiet taimautu, lai izslēgtu atlasītos datorus: minutes - + minūtes seconds - + sekundes @@ -3447,15 +3904,26 @@ Please save your work and close all programs. Remote view or control a computer + Datora attālā skatīšana vai vadība + + + Show help about command + Parādīt palīdzību par komandu + + + Exchange clipboard contents - Please enter the hostname or IP address of the computer to access: + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + RemoteAccessPage - Show help about command - Parādīt palīdzību par komandu + Remote access: %1 + Attālā piekļuve: %1 @@ -3464,6 +3932,10 @@ Please save your work and close all programs. %1 - %2 Remote Access %1 - %2 Attālināta piekļuve + + %1 - %2 - %3 Remote Access + %1 - %2 - %3 Attālā piekļuve + RemoteAccessWidgetToolBar @@ -3519,10 +3991,6 @@ Please save your work and close all programs. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - Pieslēdzas %1 - Connected. Pieslēdzies. @@ -3533,60 +4001,19 @@ Please save your work and close all programs. Exit - - - - - Routing - - Control internet access by modifying routing table - - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - - - - Add custom route to block internet - Pievienot papildus ceļu lai bloķētu internetu - - - Destination - Mērķis - - - Gateway - Vārteja - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - + Iziet - Run programs - Palaist programmas + Connecting... + Pieslēdzas... - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - - - - Name: - - - - Remember and add to program menu + Select screen - e.g. VLC - + All screens + Visi ekrāni @@ -3601,10 +4028,22 @@ Please save your work and close all programs. Lock screen and input devices of a computer - + Bloķēt datora ekrānu un ievadierīces. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + Lai atgūtu visu lietotāja uzmanību, varat bloķēt viņu datorus, izmantojot šo pogu. Šajā režīmā visas ievades ierīces ir bloķētas un ekrāni ir melni. + + + Lock input devices + Slēgt ievadierīces + + + Unlock input devices + Pieslēgt ievadierīces + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. @@ -3622,6 +4061,10 @@ Please save your work and close all programs. Screenshot Ekrānšāviņš + + Could not open screenshot file %1 for writing. + + ScreenshotFeaturePlugin @@ -3642,39 +4085,85 @@ Please save your work and close all programs. Ekrānšāviņs veiksmīgi uzņemts datoram %1. - Take screenshots of computers and save them locally. - Uzņemt datora ekrānšāviņu un saglabāt lokāli. + Take screenshots of computers and save them locally. + Uzņemt datora ekrānšāviņu un saglabāt lokāli. + + + + ScreenshotManagementPage + + Screenshots + Ekranšāviņi + + + + ScreenshotManagementPanel + + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + + + + User: + Lietotājs: + + + Computer: + Dators: + + + Date: + Datums: + + + Time: + Laiks: + + + Show + Parādīt + + + Delete + Izdzēst + + + Screenshot + Ekrānšāviņš + + + Do you really want to delete all selected screenshots? + - ScreenshotManagementPanel + ServerAccessControlManager - All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + Requested authentication method not available - User: - Lietotājs: + Access allowed by rule "%1" + - Computer: - Dators: + Access denied by rule "%1" + - Date: - Datums: + No rule allowed access + - Time: - Laiks: + Accessing user not member of an authorized user group + - Show - Parādīt + User has denied access + - Delete - Izdzēst + User confirmed access + @@ -3707,14 +4196,6 @@ Please save your work and close all programs. State: - - Network - Tīkls - - - Demo server port - Demonstrējuma servera ports - Enable firewall exception Iespējot ugunsmūra izņēmumu @@ -3723,10 +4204,6 @@ Please save your work and close all programs. Allow connections from localhost only - - Internal VNC server port - Iekšējais VNC servera ports - VNC server VNC serveris @@ -3748,68 +4225,138 @@ Please save your work and close all programs. Darbojas - Feature manager port + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. + + + + Show notification on remote connection - Primary service port + Show notification when an unauthorized access is blocked - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. + Maximum session count + Maksimālais sesiju skaits + + + Network port numbers + Tīkla porta numurs + + + Veyon server + Veyon serveris + + + Internal VNC server + Iekšējais VNC serveris + + + Feature manager - Show notification on remote connection + Demo server + Demonstrējuma serveris + + + Miscellaneous network settings - Multi session mode (for terminal and remote desktop servers) + Session mode - Show notification when an unauthorized access is blocked + Local session mode (single server instance for primary local session) - - - ServiceControl - Starting service %1 - Palaižas pakalpojums %1 + Active session mode (single server instance for active local or remote session) + - Stopping service %1 - Apstājas pakalpojums %1 + Multi session mode (distinct server instance for each local and remote desktop session) + - Registering service %1 - Reģistrēt pakalpojumu %1 + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + - Unregistering service %1 - Atcelt reģistrāciju pakalpojumam %1 + Miscellaneous settings + - Service control - Pakalpojuma kontrole + Disable clipboard synchronization + + + + Session metadata + + + + Content + + + + None + Nav + + + Value of an environment variable + + + + Value of a registry key + + + + Environment variable name: + + + + Registry key name: + + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + - ServiceControlPlugin + ServiceControl - Service is running - Pakalpojums darbojas + Service control + Pakalpojuma kontrole - Service is not running - Pakalpojums nedarbojas + Starting %1 + - Configure and control Veyon service + Stopping %1 + + + + Restarting %1 + + + + Registering %1 + + Unregistering %1 + + + + + ServiceControlCommands Register Veyon Service Reģistrēt Veyon pakalpojumu @@ -3834,13 +4381,25 @@ Typically this is required to support terminal servers. Query status of Veyon Service + + Service is running + Pakalpojums darbojas + + + Service is not running + Pakalpojums nedarbojas + + + Configure and control Veyon service + + Commands for configuring and controlling Veyon Service - ShellCommandLinePlugin + ShellCommands Run command file Palaist komandu failu @@ -3850,7 +4409,7 @@ Typically this is required to support terminal servers. Fails "%1" neeksistē! - Interactive shell and script execution for Veyon Control + Interactive shell and script execution for Veyon CLI @@ -3858,6 +4417,92 @@ Typically this is required to support terminal servers. + + SlideshowPanel + + Previous + Iepriekšējais + + + Start/pause + Starts/pauze + + + Next + Nākošais + + + Duration: + Ilgums: + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + Pievienot izvēlētos datorus + + + Remove selected computers + Noņemt izvēlētos datorus + + + Update computers in realtime + Atjaunot datorus tiešsaistē + + + Spotlight + Izcelt + + + Please select at least one computer to add. + + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + + + StartAppDialog + + Start application + Palaist lietotni + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + + Remember and add to application menu + + + + Application name + + + + Name: + Vārds: + + + e.g. VLC + piemēram VLC + + SystemTrayIcon @@ -3894,7 +4539,7 @@ Typically this is required to support terminal servers. Nosūtīt teksta ziņojumu - Use the field below to type your message which will be sent to all selected users. + Please enter your message which send to all selected users. @@ -3943,27 +4588,43 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer + + Maximum CPU usage + Maksimālais procesora lietojums + - UserConfig + UserLoginDialog - No write access - Nav rakstīšanas atļauja + User login + Lietotāja logins - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Please enter a username and password for automatic login on all computers. + + Username + Lietotājvārds + + + Password + Parole + - UserSessionControl + UserSessionControlPlugin - User session control + Log in + Pieslēgties + + + Click this button to log in a specific user on all computers. Log off - + Atslēgties Click this button to log off users from all computers. @@ -3971,12 +4632,20 @@ Typically this is required to support terminal servers. Confirm user logoff - + Apstiprināt lietotāja atslēgšanu Do you really want to log off the selected users? + + User session control + + + + Do you really want to log off <b>ALL</b> users? + + VeyonCore @@ -4028,39 +4697,47 @@ Typically this is required to support terminal servers. ERROR Kļūda - - licensed for - licenzēts uz - USAGE - + LIETOJUMS DESCRIPTION - + APRAKSTS EXAMPLES - + PIEMĒRI WARNING - + BRĪDINĀJUMS + + + Authentication test + Autentifikācijas tests + + + Screen %1 + Ekrāns %1 - VeyonServiceControl + VeyonMaster - Veyon Service - Veyon pakalpojums + No write access + Nav rakstīšanas atļauja + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + - VncView + VeyonServiceControl - Establishing connection to %1 ... - Veido savienojumu ar %1 ... + Veyon Service + Veyon pakalpojums @@ -4074,7 +4751,7 @@ Typically this is required to support terminal servers. WindowsPlatformConfigurationPage Windows - + Windows General @@ -4086,28 +4763,52 @@ Typically this is required to support terminal servers. Screen lock - + Aizslēgt ekrānu Hide taskbar - + Paslēpt uzdevumu joslu Hide start menu - + Paslēpt start menu Hide desktop - + Paslēpt darba virsmu User authentication - + Lietotāja autentificēšanās Use alternative user authentication mechanism + + User login + Lietotāja logins + + + Input start delay + Ievadi palaišanas aizkavi + + + Simulated key presses interval + + + + Confirm legal notice (message displayed before user logs in) + + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4116,8 +4817,8 @@ Typically this is required to support terminal servers. - Plugin implementing specific functions for the Windows platform - + Internal display + Iekšējais ekrāns @@ -4127,27 +4828,31 @@ Typically this is required to support terminal servers. - The service "%1" could not be installed. + The service "%1" has been installed successfully. + + + + The service "%1" has been uninstalled successfully. - The service "%1" has been installed successfully. + Service "%1" could not be found. - The service "%1" could not be uninstalled. + The service "%1" could not be installed (error %2). - The service "%1" has been uninstalled successfully. + Could not change the failure actions config for service "%1" (error %2). - The start type of service "%1" could not be changed. + The service "%1" could not be uninstalled (error %2). - Service "%1" could not be found. + The start type of service "%1" could not be changed (error %2). diff --git a/translations/mn.ts b/translations/veyon_mn.ts similarity index 78% rename from translations/mn.ts rename to translations/veyon_mn.ts index ee31945fc..0f88cd4f0 100644 --- a/translations/mn.ts +++ b/translations/veyon_mn.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -78,13 +78,9 @@ If you're interested in translating Veyon into your local or another langua All groups Бүх групп - - ... - ... - Access control rules - + Хандалт удирдах дүрмүүд Add access control rule @@ -139,15 +135,14 @@ If you're interested in translating Veyon into your local or another langua - Missing user groups backend - - - - No default user groups plugin was found. Please check your installation! + Restrict access to members of specific user groups + + + AccessControlProvider - Restrict access to members of specific user groups + Provider for access control features @@ -178,87 +173,159 @@ If you're interested in translating Veyon into your local or another langua - Invert all conditions ("is/has" interpreted as "is/has not") + Conditions - Conditions + If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. - is member of group + Action - Accessing computer is localhost + Allow access - Accessing user is logged on user + Deny access - Accessing user is already connected + Ask logged on user for permission - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. + None (rule disabled) - Action + Accessing user - Allow access + Accessing computer - Deny access + Always process rule and ignore conditions - Ask logged on user for permission + Accessing computer and local computer - None (rule disabled) + User being accessed - Accessing user + is logged in locally - Accessing computer + is logged in remotely - Local (logged on) user + No user is logged in locally - Local computer + One or multiple users are logged in locally - Always process rule and ignore conditions + No user is logged in remotely - No user logged on + One or multiple users are logged in remotely + + + + is located at - Accessing user has one or more groups in common with local (logged on) user + is not located at - Accessing computer and local computer are at the same location + are located at the same location - is located at + are not located the same location + + + + is member of group + + + + is not member of group + + + + is authenticated via + + + + is not authenticated via + + + + has one or more groups in common with user being accessed + + + + has no groups in common with user being accessed + + + + equals user being accessed + + + + is different from user being accessed + + + + is already connected + + + + is not connected + + + + is local computer + + + + is not local computer + + + + Computer being accessed + + + + Session being accessed is a user session + + + + Session being accessed is a login screen + + + + Local computer is already being accessed + + + + Local computer is not yet being accessed @@ -305,40 +372,42 @@ If you're interested in translating Veyon into your local or another langua - ERROR: Unknown action + Test result - Test result + Authentication method + + + + There is no matching rule with a valid action. The access is therefore denied. - AndroidPlatformConfigurationPage + AuthKeysConfigurationWidget - Android + Introduction - General - Ерөнхий + Please perform the following steps to set up key file authentication: + - - - AndroidPlatformPlugin - Plugin implementing specific functions for the Android platform + 1) Create a key pair on the master computer. - - - AuthKeysConfigurationPage - Authentication keys + 2) Set an access group whose members should be allowed to access other computers. - Introduction + 3) Export the public key and import it on all client computers with the same name. + + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. @@ -354,11 +423,14 @@ If you're interested in translating Veyon into your local or another langua Хувийн түлхүүрийг агуулсан сан - ... - ... + Available authentication keys + - Available authentication keys + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. @@ -401,10 +473,6 @@ If you're interested in translating Veyon into your local or another langua Please select a key to delete! - - Please enter the name of the user group or role for which to import the authentication key: - - Please select a key to export! @@ -418,30 +486,9 @@ If you're interested in translating Veyon into your local or another langua - Please perform the following steps to set up key file authentication: - - - - 1) Create a key pair on the master computer. - - - - 2) Set an access group whose members should be allowed to access other computers. - - - - 3) Export the public key and import it on all client computers with the same name. - - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. @@ -642,10 +689,6 @@ The public key is used on client computers to authenticate incoming connection r This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - - Please specify the command to display help for! - - TYPE @@ -654,10 +697,6 @@ The public key is used on client computers to authenticate incoming connection r PAIR ID - - Command line support for managing authentication keys - - Commands for managing authentication keys @@ -674,6 +713,30 @@ The public key is used on client computers to authenticate incoming connection r This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + + + + Key file authentication + Түлхүүр файлын баталгаажуулалт + + + Key file + + + + Please specify the key name (e.g. "teacher/public") as the first argument. + + + + Please specify the command to display help for. + + + + The specified command does not exist or no help is available for it. + + AuthKeysTableModel @@ -695,108 +758,251 @@ The public key is used on client computers to authenticate incoming connection r - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - + General + Ерөнхий - Name - Нэр + Username to bind DN mapping: + - Host address/IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + AuthLdapDialog - MAC address - MAC хаяг + Veyon Logon + - Add new computer + Please enter your domain/LDAP username and password in order to access computers. - Remove selected computer - + Username + Хэрэглэгчийн нэр - New computer - + Password + Нууц үг - Builtin directory - + Authentication error + Баталгаажуулалтын алдаа - Locations & computers + Logon failed with given username and password. Please try again! + + + AuthLogonDialog - Locations + Veyon Logon - Add new location + Please enter your username and password in order to access computers. - Remove selected location - + Username + Хэрэглэгчийн нэр - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - + Password + Нууц үг - New location + Authentication error + Баталгаажуулалтын алдаа + + + Logon failed with given username and password. Please try again! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Import objects from given file - + Logon authentication + Нэвтрэлт танилт - Export objects to given file + Logon + + + AuthSimpleDialog - Invalid type specified. Valid values are "%1" or "%2". + Veyon Logon - Type - Төрөл + Please enter the Veyon password: + - Name - Нэр + Authentication error + Баталгаажуулалтын алдаа - Host address + Logon failed with given password. Please try again! + + + AuthSimplePlugin - MAC address - MAC хаяг + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + - Specified object not found. + Simple password authentication - File "%1" does not exist! + Simple password + + + AuthenticationPage - Can't open file "%1" for reading! + Authentication is set up properly on this computer. + + + + + AuthenticationPageTab + + Enabled + + + + Test + Тест + + + + BuiltinDirectoryConfiguration + + Builtin directory + + + + + BuiltinDirectoryConfigurationPage + + Computers + + + + Name + Нэр + + + Host address/IP + + + + MAC address + MAC хаяг + + + Add new computer + + + + Remove selected computer + + + + New computer + + + + Builtin directory + + + + Locations + + + + Add new location + + + + Remove selected location + + + + New location + + + + Directory name + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + + + + BuiltinDirectoryPlugin + + Show help for specific command + + + + Import objects from given file + + + + Export objects to given file + + + + Invalid type specified. Valid values are "%1" or "%2". + + + + Type + Төрөл + + + Name + Нэр + + + Host address + + + + MAC address + MAC хаяг + + + Specified object not found. + + + + File "%1" does not exist! + + + + Can't open file "%1" for reading! @@ -995,6 +1201,14 @@ The public key is used on client computers to authenticate incoming connection r MAC ADDRESS + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. + + BuiltinUltraVncServer @@ -1012,10 +1226,6 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - - Active features: %1 @@ -1032,10 +1242,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off - - Service unreachable or not running - - Authentication failed or access denied @@ -1056,6 +1262,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 + + [no user] + + + + Veyon Server unreachable or not running + + + + Name: %1 + + + + Hostname: %1 + + + + unknown + үл мэдэгдэх + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + ComputerControlServer @@ -1087,6 +1325,17 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + + Active connections: + + + + + ComputerGroupSelector + + Group %1 + + ComputerManager @@ -1114,13 +1363,48 @@ The public key is used on client computers to authenticate incoming connection r Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + + Logged in since + + + + %1 days + + + + 1 day + + - ComputerSelectPanel + ComputerMonitoring + + Computers + + + + Search users and computers + + + + Select all + + + + Unselect all + + - Computer management + Add to group + + Remove from group + + + + + ComputerSelectPanel Computer search @@ -1149,79 +1433,83 @@ The public key is used on client computers to authenticate incoming connection r Could not write the computer and users list to %1! Please check the file access permissions. + + Search computers + + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. + Clear system-wide Veyon configuration - Please specify a valid filename for the configuration export. + List all configuration keys and values - Please specify a valid key. + Import configuration from given file - Specified key does not exist in current configuration! + Export configuration to given file - Please specify a valid value. + Read and output configuration value for given key - Configure Veyon at command line + Write given value to given configuration key - Output file is not writable! + Unset (remove) given configuration key - Output directory is not writable! + Upgrade and save configuration of program and plugins - Configuration file is not readable! + Please specify an existing configuration file to import. - Clear system-wide Veyon configuration + Configuration file is not readable! - List all configuration keys and values + Please specify a valid filename for the configuration export. - Import configuration from given file + Output file is not writable! - Export configuration to given file + Output directory is not writable! - Read and output configuration value for given key + Please specify a valid key. - Write given value to given configuration key + Specified key does not exist in current configuration! - Unset (remove) given configuration key + Please specify a valid value. - Commands for managing the configuration of Veyon + Configure Veyon at command line - Upgrade and save configuration of program and plugins + Commands for managing the configuration of Veyon @@ -1247,6 +1535,10 @@ The public key is used on client computers to authenticate incoming connection r Could not apply platform-specific configuration settings. + + Could not configure the firewall configuration for the %1 Service. + + DemoClient @@ -1277,10 +1569,6 @@ The public key is used on client computers to authenticate incoming connection r Memory limit - - Use multithreading (experimental) - - MB @@ -1297,13 +1585,17 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running + + Bandwidth limit + + + + MB/s + + DemoFeaturePlugin - - Fullscreen demo - Бүтэн дэлгэцээр харуулах - Stop demo @@ -1317,22 +1609,66 @@ The public key is used on client computers to authenticate incoming connection r - Demo server - Демо сервер + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. + Demo - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Share your screen or allow a user to share his screen with other users. - - - DesktopAccessDialog - Desktop access dialog + Full screen demo + + + + Share your own screen in fullscreen mode + + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share your own screen in a window + + + + Share selected user's screen in fullscreen mode + + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share selected user's screen in a window + + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + + + + Please select only one user screen to share. + + + + All screens + + + + + DesktopAccessDialog + + Desktop access dialog @@ -1355,86 +1691,90 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - Programs & websites + Name + Нэр + + + Path - Predefined programs + Predefined websites - Name - Нэр + Remove selected website + - Path + URL - Add new program + New website - Remove selected program + Applications & websites - Predefined websites + Predefined applications - Remove selected website + Add new application - URL + Remove selected application - New program + Add new website - New website + New application DesktopServicesFeaturePlugin - Run program + Open website - Open website + Click this button to open a website on all computers. - Click this button to open a website on all computers. + Open website "%1" - Start programs and services in user desktop + Custom website - Click this button to run a program on all computers. + Start application - Run program "%1" + Click this button to start an application on all computers. - Custom program + Start application "%1" - Open website "%1" + Custom application - Custom website + Start apps and open websites in user sessions @@ -1469,15 +1809,19 @@ The public key is used on client computers to authenticate incoming connection r - Custom program + Handout - Handout + Texts to read - Texts to read + generic-student-user + + + + Custom application @@ -1504,9 +1848,164 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands + + List names of all available features + + + + Show table with details of all available features + + + + Start a feature on a remote host + + + + Stop a feature on a remote host + + + + Please specify the command to display help for. + + + + Displays a list with the names of all available features. + + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + + + + HOST ADDRESS + + + + FEATURE + + + + ARGUMENTS + + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + + + + Lock the screen + + + + Display a text message + + + + Test message + + + + Start an application + + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + + + + Unlock the screen + + + + The specified command does not exist or no help is available for it. + + + + Name + Нэр + + + Description + + + + Master + + + + Service + + + + Worker + + + + UID + + + + Plugin + + + + Invalid feature name or UID specified + + + + Error parsing the JSON-encoded arguments: %1 + + + + Failed to initialize credentials + + + + Could not establish a connection to host %1 + + + + Failed to send feature control message to host %1 + + + + Feature-related CLI operations + + + + Commands for controlling features + + + + + FileTransferConfigurationPage + + File transfer + + + + Directories + Каталоги + + + Destination directory + + + + Default source directory + + + + Options + + + + Remember last source directory + + - Feature control + Create destination directory if it does not exist @@ -1552,6 +2051,13 @@ The public key is used on client computers to authenticate incoming connection r + + FileTransferFileDialog + + Select one or more files to transfer + + + FileTransferPlugin @@ -1609,10 +2115,6 @@ The public key is used on client computers to authenticate incoming connection r Log file directory Нэвтрэх файлын сан - - ... - ... - Log level Нэвтрэх түвшин @@ -1653,18 +2155,6 @@ The public key is used on client computers to authenticate incoming connection r Log to standard error output Нэвтрэх үеийн энгийн алдааны гаралт - - Network object directory - - - - Backend: - - - - Update interval: - - %1 service @@ -1701,102 +2191,79 @@ The public key is used on client computers to authenticate incoming connection r x - - seconds - секунд - Write to logging system of operating system - Authentication - Баталгаажуулалт - - - Method: + TLS configuration - Logon authentication - Нэвтрэлт танилт - - - Key file authentication - Түлхүүр файлын баталгаажуулалт - - - Test - Тест - - - Authentication is set up properly on this computer. + Use certificate authority for TLS connections - Authentication keys are not set up properly on this computer. + CA certificate file - Authentication test - + ... + ... - - - InternetAccessControlConfigurationPage - Internet access control + Host certificate file - Backend: + Host private key file - General settings + Style: - Backend settings + Native - - - InternetAccessControlPlugin - Block access to the internet + Color scheme: - Allow access to the internet + Light - Show help about command + Dark - Block internet + User groups - Click this button to block access to the internet. + Backend: - Unblock internet + Include user groups from domain - Click this button to allow access to the internet. + Missing user groups backend - Control access to the internet + No user groups plugin was found. Please check your installation! + + + HeadlessVncServer - Commands for controlling access to the internet + Headless VNC server @@ -1815,69 +2282,76 @@ The public key is used on client computers to authenticate incoming connection r - LdapConfigurationPage + LdapConfiguration - Basic settings + LDAP connection failed - General - Ерөнхий - - - LDAP server and port + Could not connect to the LDAP server. Please check the server parameters. + +%1 - Bind DN + LDAP bind failed - Bind password + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 - Anonymous bind + LDAP bind successful - Use bind credentials + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - Base DN + LDAP base DN test failed - Fixed base DN + Could not query the configured base DN. Please check the base DN parameter. + +%1 - e.g. dc=example,dc=org + LDAP base DN test successful - Discover base DN by naming context + The LDAP base DN has been queried successfully. The following entries were found: + +%1 - e.g. namingContexts or defaultNamingContext + LDAP naming context test failed - Environment settings + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 - Object trees + LDAP naming context test successful - Computer tree + The LDAP naming context has been queried successfully. The following base DN was found: +%1 - e.g. OU=Groups + user tree @@ -1885,39 +2359,39 @@ The public key is used on client computers to authenticate incoming connection r - e.g. OU=Users + group tree - e.g. OU=Computers + Group tree - Group tree + computer tree - Perform recursive search operations in object trees + Computer tree - Object attributes + computer group tree - e.g. hwAddress + Computer group tree - e.g. member or memberUid + user objects - e.g. dNSHostName + User login name attribute - Computer MAC address attribute + group members @@ -1925,786 +2399,703 @@ The public key is used on client computers to authenticate incoming connection r - e.g. uid or sAMAccountName + Group not found - Advanced settings + Could not find a group with the name "%1". Please check the group name or the group tree parameter. - Optional object filters + computer objects - Filter for user groups + Computer display name attribute - Filter for users + Invalid hostname - Filter for computer groups + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Group member identification + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - Distinguished name (Samba/AD) + Computer hostname attribute - List all groups of a user + computer MAC addresses - List all groups of a computer + Computer MAC address attribute - Get computer object by IP address + computer locations - LDAP connection failed + Computer location attribute - LDAP bind failed + Location name attribute - LDAP bind successful + users - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + user groups - LDAP base DN test failed + computers - LDAP base DN test successful + computer groups - LDAP naming context test failed + computer containers - LDAP naming context test successful + groups of user - The LDAP naming context has been queried successfully. The following base DN was found: -%1 + User not found - user tree + Could not find a user with the name "%1". Please check the username or the user tree parameter. - group tree + groups of computer - computer tree + Computer not found - Enter username + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - Please enter a user login name (wildcards allowed) which to query: + Hostname lookup failed - user objects + Could not lookup hostname for IP address %1. Please check your DNS server settings. - Enter group name + location entries - Please enter a group name whose members to query: + Computer groups filter - group members + Computer locations identification - Group not found + Filter for computer groups - Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Invalid test value - Enter computer name + An empty or invalid value has been supplied for this test. - computer objects + LDAP %1 test failed - Enter computer DN + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 - Please enter the DN of a computer whose MAC address to query: + LDAP %1 test successful - computer MAC addresses + The %1 has been queried successfully and %2 entries were found. - users + LDAP test failed - user groups + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 - computer groups + and - Please enter a user login name whose group memberships to query: + LDAP test successful - groups of user + %1 %2 have been queried successfully: + +%3 - User not found + LDAP filter test failed - groups of computer + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 - Computer not found + LDAP filter test successful - Enter computer IP address + %1 %2 have been queried successfully using the configured filter. - Please enter a computer IP address which to resolve to an computer object: + LDAP directory + + + LdapConfigurationPage - computers + Basic settings - LDAP %1 test failed - + General + Ерөнхий - LDAP %1 test successful + LDAP server and port - The %1 has been queried successfully and %2 entries were found. + Bind DN - %1 %2 have been queried successfully: - -%3 + Bind password - LDAP filter test failed + Anonymous bind - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 + Use bind credentials - LDAP filter test successful + Base DN - %1 %2 have been queried successfully using the configured filter. + Fixed base DN - (only if different from group tree) + e.g. dc=example,dc=org - Computer group tree + Discover base DN by naming context - computer group tree + e.g. namingContexts or defaultNamingContext - Filter for computers + Environment settings - e.g. room or computerLab + Object trees - Integration tests + Computer tree - Computer groups + e.g. OU=Groups - e.g. name or description + User tree - Filter for computer containers + e.g. OU=Users - Computer containers or OUs + e.g. OU=Computers - Connection security + Group tree - TLS certificate verification + Perform recursive search operations in object trees - System defaults + Object attributes - Never (insecure!) + e.g. hwAddress - Custom CA certificate file + e.g. member or memberUid - None + e.g. dNSHostName - TLS + Computer MAC address attribute - SSL + Group member attribute - e.g. (objectClass=computer) + e.g. uid or sAMAccountName - e.g. (objectClass=group) + Advanced settings - e.g. (objectClass=person) + Optional object filters - e.g. (objectClass=room) or (objectClass=computerLab) + Filter for user groups - e.g. (objectClass=container) or (objectClass=organizationalUnit) + Filter for users - Could not query the configured base DN. Please check the base DN parameter. - -%1 + Filter for computer groups - The LDAP base DN has been queried successfully. The following entries were found: - -%1 + Group member identification - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 + Distinguished name (Samba/AD) - Certificate files (*.pem) + List all groups of a user - Could not connect to the LDAP server. Please check the server parameters. - -%1 + List all groups of a computer - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 + Get computer object by IP address - Encryption protocol + Enter username - Computer location attribute + Please enter a user login name (wildcards allowed) which to query: - Computer display name attribute + Enter group name - Location name attribute + Please enter a group name whose members to query: - e.g. cn or displayName - - - - Computer locations identification - - - - Identify computer locations (e.g. rooms) via: - - - - Location attribute in computer objects - - - - List all entries of a location - - - - List all locations + Enter computer name - Enter computer display name + Enter computer DN - Please enter a computer display name to query: + Please enter the DN of a computer whose MAC address to query: - Enter computer location name + Please enter a user login name whose group memberships to query: - Please enter the name of a computer location (wildcards allowed): + Enter computer IP address - computer locations + Please enter a computer IP address which to resolve to an computer object: - Enter location name + (only if different from group tree) - Please enter the name of a location whose entries to query: + Computer group tree - location entries + Filter for computers - LDAP test failed + e.g. room or computerLab - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 + Integration tests - and + Computer groups - LDAP test successful + e.g. name or description - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 + Filter for computer containers - Browse + Computer containers or OUs - Test - Тест - - - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Connection security - Computer hostname attribute + TLS certificate verification - Please enter a computer hostname to query: + System defaults - Invalid hostname + Never (insecure!) - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Custom CA certificate file - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + None - Could not find a user with the name "%1". Please check the username or the user tree parameter. + TLS - Enter hostname + SSL - Please enter a computer hostname whose group memberships to query: + e.g. (objectClass=computer) - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + e.g. (objectClass=group) - Hostname lookup failed + e.g. (objectClass=person) - Could not lookup hostname for IP address %1. Please check your DNS server settings. + e.g. (objectClass=room) or (objectClass=computerLab) - User login name attribute + e.g. (objectClass=container) or (objectClass=organizationalUnit) - Configured attribute for user login name or computer hostname (OpenLDAP) + Certificate files (*.pem) - computer containers + Encryption protocol - - - LdapPlugin - Auto-configure the base DN via naming context + Computer location attribute - Query objects from LDAP directory + Computer display name attribute - Show help about command + Location name attribute - Commands for configuring and testing LDAP/AD integration + e.g. cn or displayName - Basic LDAP/AD support for Veyon + Computer locations identification - %1 (load computers and locations from LDAP/AD) + Identify computer locations (e.g. rooms) via: - %1 (load users and groups from LDAP/AD) + Location attribute in computer objects - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + List all entries of a location - No naming context attribute name given - falling back to configured value. + List all locations - Could not query base DN. Please check your LDAP configuration. + Enter computer display name - Configuring %1 as base DN and disabling naming context queries. + Please enter a computer display name to query: - - - LdapProConfigurationPage - LDAP Pro + Enter computer location name - Instances + Please enter the name of a computer location (wildcards allowed): - Enter name + Enter location name - Please enter a name for the instance (can't be changed later!): + Please enter the name of a location whose entries to query: - Remove instance + Browse - Do you really want to remove instance "%1"? - + Test + Тест - Configuration for instance "%1" + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - - - LdapProPlugin - Professional LDAP/AD integration for Veyon + Computer hostname attribute - %1 (load computers and locations from LDAP/AD) + Please enter a computer hostname to query: - %1 (load users and groups from LDAP/AD) + Enter hostname - - - LicensingConfigurationPage - Licensing + Please enter a computer hostname whose group memberships to query: - Installed licenses + User login name attribute - Add new network range + Configured attribute for user login name or computer hostname (OpenLDAP) - Remove selected network range + Directory name - ID + Query options - Feature + Query nested user groups (supported by AD only) - Valid until + Query timeout - Licensee + ms + + + LdapNetworkObjectDirectoryConfigurationPage - Browse license file + LDAP - Veyon license files (*.vlf) + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + LdapPlugin - Remove license + Auto-configure the base DN via naming context - Do you really want to remove the selected license? + Query objects from LDAP directory - <N/A> + Show help about command - Invalid license file + Commands for configuring and testing LDAP/AD integration - Could not open the license file for reading! + Basic LDAP/AD support for Veyon - The selected license file does not contain valid data. + %1 (load computers and locations from LDAP/AD) - The selected license file could not be verified. + %1 (load users and groups from LDAP/AD) - The selected license file is not valid for this installation. + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - The selected license file is expired. + No naming context attribute name given - falling back to configured value. - The license is already installed. + Could not query base DN. Please check your LDAP configuration. - Information + Configuring %1 as base DN and disabling naming context queries. - Installation ID + Test binding to an LDAP server - Addons available for licensing + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Addon + LDAP bind - LicensingPlugin - - Show help for specific command - - - - Show all installed licenses - - - - Add license file - - - - Remove installed license - - - - -USAGE - -%1 add <LICENSE FILE> - - - - - - -USAGE - -%1 remove <LICENSE ID> - - - - - - No certificate found with given ID - - - - <N/A> - - + LinuxPlatformConfigurationPage - Licensing management + Linux - Commands for managing license keys + Custom PAM service for user authentication - - - LinuxPlatformConfigurationPage - Linux + User authentication - Custom PAM service for user authentication + User sessions - User authentication + Minimum session lifetime before server start - Session management + User login - Display manager users + Login key sequence @@ -2714,10 +3105,6 @@ USAGE Plugin implementing abstract functions for the Linux platform - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2737,11 +3124,11 @@ USAGE - Disable balloon tooltips + Show icons only - Show icons only + Disable tooltips @@ -2791,10 +3178,6 @@ USAGE About Qt Qt-ын тухай - - Authentication impossible - Өөрийгөө таниулан нэвтэрч чадахгүй байна - Configuration not writable Тохиргоо бичигдэх боломжгүй @@ -2855,10 +3238,6 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - - Access denied @@ -2891,10 +3270,6 @@ USAGE Search users and computers - - Adjust optimal size - - Align computers to grid @@ -2939,6 +3314,48 @@ USAGE Locations && computers + + Authentication + Баталгаажуулалт + + + Adjust size of computer icons automatically + + + + Slideshow + + + + Spotlight + + + + Veyon Master + + + + Locations & computers + + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + + + + Load computer positions + + + + Save computer positions + + MasterConfigurationPage @@ -2946,10 +3363,6 @@ USAGE Directories Каталоги - - ... - ... - User configuration @@ -3034,6 +3447,10 @@ USAGE Only user name + + Only last part of user name + + Only computer name @@ -3083,164 +3500,179 @@ USAGE - Automatically adjust computer thumbnail size + Automatically open computer select panel - Automatically open computer select panel + Use modern user interface (experimental) - - - MonitoringMode - Monitoring + Thumbnail spacing - Builtin monitoring mode + px - This mode allows you to monitor all computers at one or more locations. + Hide local session - - - NetworkDiscoveryConfigurationPage - Network discovery + Auto - Mode + Thumbnail aspect ratio - Scan network ranges + Automatically adjust computer icon size - e.g. 192.168.1.0/24 + Open feature windows on the same screen as the main window - Scan all subnets of computer + Configuration templates - Scan custom subnet + Image quality in monitoring mode - Scan sessions on local computer + Highest - Test - Тест + High + - Network ranges + Medium - Add new group + Low - Remove selected group + Lowest - Groups + Remote access image quality - First address + Advanced - Last address + Computer name source - Add new network range + Default - Remove selected network range + Host address - Parallel scans + Session client address - Scan timeout + Session client name - ms + Session host name - Session scan limit + Session metadata - Options + Full name of user - Reverse lookup discovered IP addresses to host names + User login name - New location + Computer UID role - - - NetworkDiscoveryDirectory - Scanning... + Session meta data hash - Discovered computers + Always expand all locations + + + + Image quality - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command + Monitoring - Scan a subnet + Builtin monitoring mode - -USAGE - -%1 scan [<SUBNET>] - - + This mode allows you to monitor all computers at one or more locations. + + + + Query application version of the server - Network object directory which automatically discovers computers in the network + Query active features - Network discovery (scan network for Veyon clients) + Query properties of remotely available screens + + + NestedNetworkObjectDirectory - Commands for managing the network discovery directory + All directories + + + + + NetworkObjectDirectoryConfigurationPage + + Update interval: + + + + seconds + секунд + + + + NetworkObjectDirectoryConfigurationPageTab + + Enabled @@ -3277,31 +3709,43 @@ USAGE Name: + + Website name + + - PasswordDialog + PluginCommands - Username - Хэрэглэгчийн нэр + List names of all installed plugins + - Password - Нууц үг + Show table with details of all installed plugins + - Veyon Logon + Name + Нэр + + + Description - Authentication error - Баталгаажуулалтын алдаа + Version + - Logon failed with given username and password. Please try again! + UID - Please enter your username and password in order to access computers. + Plugin-related CLI operations + + + + Commands for managing plugins @@ -3347,10 +3791,6 @@ USAGE Do you really want to reboot the selected computers? - - Do you really want to power down the selected computer? - - Power on a computer via Wake-on-LAN (WOL) @@ -3401,6 +3841,18 @@ USAGE Please save your work and close all programs. + + Do you really want to reboot <b>ALL</b> computers? + + + + Do you really want to power down <b>ALL</b> computers? + + + + Do you really want to power down the selected computers? + + PowerDownTimeInputDialog @@ -3448,11 +3900,22 @@ Please save your work and close all programs. - Please enter the hostname or IP address of the computer to access: + Show help about command - Show help about command + Exchange clipboard contents + + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + + + RemoteAccessPage + + Remote access: %1 @@ -3462,6 +3925,10 @@ Please save your work and close all programs. %1 - %2 Remote Access + + %1 - %2 - %3 Remote Access + + RemoteAccessWidgetToolBar @@ -3490,369 +3957,542 @@ Please save your work and close all programs. - Ctrl+Esc - + Ctrl+Esc + + + + Alt+Tab + + + + Alt+F4 + + + + Win+Tab + + + + Win + + + + Menu + + + + Alt+Ctrl+F1 + + + + Connected. + Холбогдсон. + + + Screenshot + + + + Exit + + + + Connecting... + + + + Select screen + + + + All screens + + + + + ScreenLockFeaturePlugin + + Lock + + + + Unlock + + + + Lock screen and input devices of a computer + + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + + + + Lock input devices + + + + Unlock input devices + + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + + + + Screenshot + + unknown + үл мэдэгдэх + + + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + + + + Screenshot + + + + Could not open screenshot file %1 for writing. + + + + + ScreenshotFeaturePlugin + + Screenshot + + + + Use this function to take a screenshot of selected computers. + + + + Screenshots taken + + + + Screenshot of %1 computer have been taken successfully. + + + + Take screenshots of computers and save them locally. + + + + + ScreenshotManagementPage + + Screenshots + + + + + ScreenshotManagementPanel + + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + + + + User: + Хэрэглэгч: + + + Computer: + + + + Date: + Огноо: + + + Time: + Хугацаа: + + + Show + Харах + + + Delete + Устгах + + + Screenshot + + + + Do you really want to delete all selected screenshots? + + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + + + + User has denied access + + + + User confirmed access + + + + + ServiceConfigurationPage + + General + Ерөнхий + + + Autostart + Автоматаар эхлэх + + + Hide tray icon + Тавиурын дүрсийг нуух + + + Start service + Сервисийг эхлүүлэх + + + Stopped + Зогссон + + + Stop service + Сервисийг зогсоох + + + State: + Төлөв: - Alt+Tab - + Enable firewall exception + Онцгой хамгаалалтыг идэвхжүүлэх - Alt+F4 - + Allow connections from localhost only + Зөвхөн дотоод холболтууддаа зөвшөөрөх - Win+Tab + VNC server - Win + Plugin: - Menu + Restart %1 Service - Alt+Ctrl+F1 + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - Connecting %1 - Холбогдож байна %1 - - - Connected. - Холбогдсон. + Running + Ажиллуулах - Screenshot + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. - Exit + Show notification on remote connection - - - Routing - Control internet access by modifying routing table + Show notification when an unauthorized access is blocked - - - RoutingConfigurationWidget - Remove default routes to block internet access + Maximum session count - Add custom route to block internet + Network port numbers - Destination + Veyon server - Gateway + Internal VNC server - - - RunProgramDialog - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. + Feature manager - Run programs - + Demo server + Демо сервер - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + Miscellaneous network settings - Name: + Session mode - Remember and add to program menu + Local session mode (single server instance for primary local session) - e.g. VLC + Active session mode (single server instance for active local or remote session) - - - ScreenLockFeaturePlugin - Lock + Multi session mode (distinct server instance for each local and remote desktop session) - Unlock + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. - Lock screen and input devices of a computer + Miscellaneous settings - To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + Disable clipboard synchronization - - - Screenshot - unknown - үл мэдэгдэх + Session metadata + - Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + Content - Screenshot + None - - - ScreenshotFeaturePlugin - Screenshot + Value of an environment variable - Use this function to take a screenshot of selected computers. + Value of a registry key - Screenshots taken + Environment variable name: - Screenshot of %1 computer have been taken successfully. + Registry key name: - Take screenshots of computers and save them locally. + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) - ScreenshotManagementPanel + ServiceControl - All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + Service control - User: - Хэрэглэгч: - - - Computer: + Starting %1 - Date: - Огноо: + Stopping %1 + - Time: - Хугацаа: + Restarting %1 + - Show - Харах + Registering %1 + - Delete - Устгах + Unregistering %1 + - ServiceConfigurationPage - - General - Ерөнхий - + ServiceControlCommands - Autostart - Автоматаар эхлэх - - - Hide tray icon - Тавиурын дүрсийг нуух - - - Start service - Сервисийг эхлүүлэх - - - Stopped - Зогссон - - - Stop service - Сервисийг зогсоох - - - State: - Төлөв: - - - Network - Сүлжээ - - - Demo server port - Демо серверийн порт - - - Enable firewall exception - Онцгой хамгаалалтыг идэвхжүүлэх + Register Veyon Service + - Allow connections from localhost only - Зөвхөн дотоод холболтууддаа зөвшөөрөх + Unregister Veyon Service + - Internal VNC server port + Start Veyon Service - VNC server + Stop Veyon Service - Plugin: + Restart Veyon Service - Restart %1 Service + Query status of Veyon Service - All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + Service is running - Running - Ажиллуулах + Service is not running + - Feature manager port + Configure and control Veyon service - Primary service port + Commands for configuring and controlling Veyon Service + + + ShellCommands - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. + Run command file - Show notification on remote connection + File "%1" does not exist! - Multi session mode (for terminal and remote desktop servers) + Interactive shell and script execution for Veyon CLI - Show notification when an unauthorized access is blocked + Commands for shell functionalities - ServiceControl + SlideshowPanel - Starting service %1 + Previous - Stopping service %1 + Start/pause - Registering service %1 + Next - Unregistering service %1 + Duration: - Service control + View in separate window - - - ServiceControlPlugin - Service is running + %1 Master – Slideshow + + + SpotlightPanel - Service is not running + Add selected computers - Configure and control Veyon service + Remove selected computers - Register Veyon Service + Update computers in realtime - Unregister Veyon Service + Spotlight - Start Veyon Service + Please select at least one computer to add. - Stop Veyon Service + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + StartAppDialog - Restart Veyon Service + Start application - Query status of Veyon Service + Please enter the applications to start on the selected computers. You can separate multiple applications by line. - Commands for configuring and controlling Veyon Service + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - - - ShellCommandLinePlugin - Run command file + Remember and add to application menu - File "%1" does not exist! + Application name - Interactive shell and script execution for Veyon Control + Name: - Commands for shell functionalities + e.g. VLC @@ -3892,8 +4532,8 @@ Typically this is required to support terminal servers. Текст мессеж явуулах - Use the field below to type your message which will be sent to all selected users. - Доорх талбарт бүх сонгогдсон хэрэглэгчдэд илгээх мессежээ бичнэ. + Please enter your message which send to all selected users. + @@ -3941,22 +4581,38 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer + + Maximum CPU usage + + - UserConfig + UserLoginDialog - No write access - Бичих эрх байхгүй + User login + - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Please enter a username and password for automatic login on all computers. + + Username + Хэрэглэгчийн нэр + + + Password + Нууц үг + - UserSessionControl + UserSessionControlPlugin - User session control + Log in + + + + Click this button to log in a specific user on all computers. @@ -3975,6 +4631,14 @@ Typically this is required to support terminal servers. Do you really want to log off the selected users? + + User session control + + + + Do you really want to log off <b>ALL</b> users? + + VeyonCore @@ -4026,10 +4690,6 @@ Typically this is required to support terminal servers. ERROR - - licensed for - - USAGE @@ -4046,19 +4706,31 @@ Typically this is required to support terminal servers. WARNING + + Authentication test + + + + Screen %1 + + - VeyonServiceControl + VeyonMaster - Veyon Service + No write access + Бичих эрх байхгүй + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - VncView + VeyonServiceControl - Establishing connection to %1 ... - Үүлчилгээг бүртгүүлэх боломжгүй %1 ... + Veyon Service + @@ -4106,6 +4778,30 @@ Typically this is required to support terminal servers. Use alternative user authentication mechanism + + User login + + + + Input start delay + + + + Simulated key presses interval + + + + Confirm legal notice (message displayed before user logs in) + + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4114,7 +4810,7 @@ Typically this is required to support terminal servers. - Plugin implementing specific functions for the Windows platform + Internal display @@ -4125,27 +4821,31 @@ Typically this is required to support terminal servers. - The service "%1" could not be installed. + The service "%1" has been installed successfully. + + + + The service "%1" has been uninstalled successfully. - The service "%1" has been installed successfully. + Service "%1" could not be found. - The service "%1" could not be uninstalled. + The service "%1" could not be installed (error %2). - The service "%1" has been uninstalled successfully. + Could not change the failure actions config for service "%1" (error %2). - The start type of service "%1" could not be changed. + The service "%1" could not be uninstalled (error %2). - Service "%1" could not be found. + The start type of service "%1" could not be changed (error %2). diff --git a/translations/nl.ts b/translations/veyon_nl.ts similarity index 60% rename from translations/nl.ts rename to translations/veyon_nl.ts index 887a19b98..6a9c5f888 100644 --- a/translations/nl.ts +++ b/translations/veyon_nl.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -80,10 +80,6 @@ Als je geïnteresseerd bent in het vertalen van Veyon in je eigen taal of een an All groups Alle groepen - - ... - ... - Access control rules Toegangscontrole regels @@ -141,15 +137,14 @@ Als je geïnteresseerd bent in het vertalen van Veyon in je eigen taal of een an Gebruikersgroepen backend - Missing user groups backend - Ontbrekende gebruikersgroepen backend - - - No default user groups plugin was found. Please check your installation! - Er werd geen standaard gebruikersgroepplugin gevonden. Controleer de installatie! + Restrict access to members of specific user groups + Beperk toegang tot leden van bepaalde groepen + + + AccessControlProvider - Restrict access to members of specific user groups + Provider for access control features @@ -179,30 +174,10 @@ Als je geïnteresseerd bent in het vertalen van Veyon in je eigen taal of een an Rule description: Regelbeschrijving: - - Invert all conditions ("is/has" interpreted as "is/has not") - Keer all condities om ("is/heeft" geïnterpreteerd als "is/heeft niet") - Conditions Voorwaarden - - is member of group - is lid van groep - - - Accessing computer is localhost - Toegangzoekende computer is localhost - - - Accessing user is logged on user - Toegangzoekende gebruiker is de aangelogde gebruiker - - - Accessing user is already connected - Toegangzoekende gebruiker is reeds aangemeld - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. Als er meerdere condities zijn geactiveerd, moet elke conditie voldoen om de regel toe te passen (logisch EN). Als slechts één van meerdere voorwaarden moet voldoen (logisch OF), maak dan meerdere toegangsregels aan. @@ -217,11 +192,11 @@ Als je geïnteresseerd bent in het vertalen van Veyon in je eigen taal of een an Deny access - Ontzeg toegang + Weiger toegang Ask logged on user for permission - Vraag ingelogde gebruiker voor toestemming + Vraag ingelogde gebruiker om toestemming None (rule disabled) @@ -236,31 +211,123 @@ Als je geïnteresseerd bent in het vertalen van Veyon in je eigen taal of een an Toegangzoekende computer - Local (logged on) user - Lokale (ingelogde) gebruiker + Always process rule and ignore conditions + Verwerk altijd regel en negeer de voorwaarden - Local computer - Lokale computer + Accessing computer and local computer + Toegang tot computer en lokale computer - Always process rule and ignore conditions - Verwerk altijd regel en negeer de voorwaarden + User being accessed + Gebruiker die benaderd wordt - No user logged on - Geen gebruiker ingelogd + is logged in locally + is lokaal ingelogd - Accessing user has one or more groups in common with local (logged on) user - Toegangzoekende gebruiker heeft een of meerdere groepen gemeenschappelijk met de lokale (aangemelde) gebruiker + is logged in remotely + is op afstand ingelogd - Accessing computer and local computer are at the same location - + No user is logged in locally + Geen enkele gebruiker is lokaal ingelogd + + + One or multiple users are logged in locally + Een of meerdere gebruikers zijn lokaal ingelogd + + + No user is logged in remotely + Er is geen gebruiker op afstand ingelogd + + + One or multiple users are logged in remotely + Een of meerdere gebruikers zijn op afstand ingelogd is located at + bevind zich in + + + is not located at + bevindt zich niet in + + + are located at the same location + bevinden zich op dezelfde locatie + + + are not located the same location + bevinden zich niet op dezelfde locatie + + + is member of group + is lid van groep + + + is not member of group + is geen lid van groep + + + is authenticated via + is geverifieerd via + + + is not authenticated via + is niet geverifieerd via + + + has one or more groups in common with user being accessed + heeft een of meer groepen gemeen met de gebruiker die wordt benaderd + + + has no groups in common with user being accessed + heeft geen groepen gemeen met de gebruiker die wordt benaderd + + + equals user being accessed + is gelijk aan de gebruiker die wordt benaderd + + + is different from user being accessed + verschilt van de gebruiker die wordt benaderd + + + is already connected + is al verbonden + + + is not connected + is niet verbonden + + + is local computer + is de lokale computer + + + is not local computer + is geen lokale computer + + + Computer being accessed + Computer die wordt benaderd + + + Session being accessed is a user session + De sessie die wordt geopend is een gebruikerssessie + + + Session being accessed is a login screen + De sessie die wordt geopend is een inlogscherm + + + Local computer is already being accessed + + + + Local computer is not yet being accessed @@ -272,7 +339,7 @@ Als je geïnteresseerd bent in het vertalen van Veyon in je eigen taal of een an Accessing user: - Toegangzoekende gebruiker: + Toegang tot gebruiker: Local computer: @@ -280,7 +347,7 @@ Als je geïnteresseerd bent in het vertalen van Veyon in je eigen taal of een an Accessing computer: - Toegangzoekende computer: + Computer benaderen: Please enter the following user and computer information in order to test the configured ruleset. @@ -292,7 +359,7 @@ Als je geïnteresseerd bent in het vertalen van Veyon in je eigen taal of een an Connected users: - Geconnecteerde gebruikers: + Verbonden gebruikers: The access in the given scenario is allowed. @@ -306,62 +373,70 @@ Als je geïnteresseerd bent in het vertalen van Veyon in je eigen taal of een an The access in the given scenario needs permission of the logged on user. De toegang in het gegeven scenario heeft toestemming van de ingelogde gebruiker nodig. - - ERROR: Unknown action - FOUT: onbekende actie - Test result Testresultaat - - - AndroidPlatformConfigurationPage - Android - + Authentication method + Authenticatiemethode - General - Algemeen + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + Inleiding - - - AuthKeysConfigurationPage - Authentication keys - Authenticatie sleutels + Please perform the following steps to set up key file authentication: + Voer de volgende stappen uit om de verificatie van sleutelbestanden in te stellen: - Introduction - Inleiding + 1) Create a key pair on the master computer. + 1) Maak een key pair aan op de master computer. + + + 2) Set an access group whose members should be allowed to access other computers. + Stel een toegangsgroep in waarvan de leden toegang moeten krijgen tot andere computers. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Exporteer de publieke key en importeer deze op alle client computers met dezelfde naam. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Raadpleeg de <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> voor meer informatie. Key file directories - + Sleutelbestand map Public key file base directory - Publieke sleutel basis bestands folder + Publieke sleutel basis bestandsmap Private key file base directory - Privé sleutel basis bestands folder + Privé sleutel basis bestandsmap - ... - ... + Available authentication keys + Beschikbare authenticatiesleutels - Available authentication keys - + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Een authenticatiesleutelpaar bestaat uit twee gekoppelde cryptografische sleutels, een private en een publieke sleutel. +Een privesleutel geeft gebruikers op de mastercomputer toegang tot clientcomputers. +Het is belangrijk dat alleen bevoegde gebruikers leestoegang hebben tot het bestand met de prive-sleutel. +De publieke sleutel wordt gebruikt op clientcomputers om inkomende verbindingsaanvragen te controleren. Create key pair @@ -381,7 +456,7 @@ Als je geïnteresseerd bent in het vertalen van Veyon in je eigen taal of een an Set access group - + Stel toegangsgroep in Key files (*.pem) @@ -393,20 +468,16 @@ Als je geïnteresseerd bent in het vertalen van Veyon in je eigen taal of een an Please enter the name of the user group or role for which to create an authentication key pair: - Geef de naam van de gebruikers groep of rol waarvoor u een authenticatie sleutelpaar wil maken: + Geef de naam van de gebruikersgroep of rol waarvoor een authenticatie sleutelpaar moet worden gemaakt: Do you really want to delete authentication key "%1/%2"? - Bent u zeker om met de verwijdering van authenticatiesleutel "%1/%2" door te gaan? + Wilt u echt de authenticatie sleutel "%1/%2" verwijderen? Please select a key to delete! Gelieve de sleutel aan te duiden die u wilt verwijderen! - - Please enter the name of the user group or role for which to import the authentication key: - Geef de naam van de gebruikers groep of rol waarvoor u een authenticatie sleutel wil importeren: - Please select a key to export! Gelieve de sleutel aan te duiden die u wilt exporteren! @@ -420,31 +491,12 @@ Als je geïnteresseerd bent in het vertalen van Veyon in je eigen taal of een an Gelieve de sleutel aan te duiden waarvoor u de toegangsgroep wil instellen! - Please perform the following steps to set up key file authentication: - Gelieve volgende stappen te volgen om sleutel authenticatie in te stellen: - - - 1) Create a key pair on the master computer. - 1) Maak een key pair op de master computer. - - - 2) Set an access group whose members should be allowed to access other computers. - - - - 3) Export the public key and import it on all client computers with the same name. - 3) Exporteer de publieke key en importeer deze op alle client computers met dezelfde naam. - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + Voer de naam in van de gebruikersgroep of rol waarvoor de verificatiesleutel moet worden geïmporteerd + +Zorg ervoor dat de namen van de sleutels die bij elkaar horen identiek zijn op alle computers. @@ -455,23 +507,23 @@ The public key is used on client computers to authenticate incoming connection r Key name contains invalid characters! - Key naam bevat niet toegestane karakters + Sleutel naam bevat ongeldige tekens! Invalid key type specified! Please specify "%1" or "%2". - + Ongeldig sleutel type opgegeven! Geef "%1" of "%2" op. Specified key does not exist! Please use the "list" command to list all installed keys. - + De opgegeven sleutel bestaat niet! Gebruik het "list" commando om alle geïnstalleerde sleutels op te sommen. One or more key files already exist! Please delete them using the "delete" command. - Eén of meer key files bestaan al! Verwijder ze door gebruik te maken van het commando "verwijder". + Eén of meer sleutelbestanden bestaan al! Verwijder ze met het commando "delete". Creating new key pair for "%1" - Maak een nieuw key pair voor "%1" + Maak een nieuw sleutelpaar voor "%1" Failed to create public or private key! @@ -479,15 +531,15 @@ The public key is used on client computers to authenticate incoming connection r Newly created key pair has been saved to "%1" and "%2". - Het nieuwe key pair is opgeslagen op "%1" en "%2" + Het nieuw aangemaakt sleutelpaar is opgeslagen in "%1" en "%2" Could not remove key file "%1"! - Kan key bestand "%1" niet verwijderen! + Kon sleutelbestand "%1" niet verwijderen! Could not remove key file directory "%1"! - + Kon sleutelbestand map "%1" niet verwijderen! Failed to create directory for output file. @@ -503,7 +555,7 @@ The public key is used on client computers to authenticate incoming connection r Key "%1/%2" has been exported to "%3" successfully. - + Sleutel "%1/%2" is met succes geëxporteerd naar "%3". Failed read input file. @@ -527,15 +579,15 @@ The public key is used on client computers to authenticate incoming connection r Failed to set permissions for key file "%1"! - + Het instellen van machtigingen voor sleutelbestand "%1"! is mislukt! Key "%1/%2" has been imported successfully. Please check file permissions of "%3" in order to prevent unauthorized accesses. - + Sleutel "%1/%2" is met succes geïmporteerd. Controleer de bestandsrechten van "%3" om onrechtmatige toegang te voorkomen. Failed to convert private key to public key - Omzetten van private sleutel naar publieke sleutel is mislukt. + Het converteren van de private sleutel naar de publieke sleutel is mislukt Failed to create directory for private key file "%1". @@ -547,31 +599,31 @@ The public key is used on client computers to authenticate incoming connection r Failed to set permissions for private key file "%1"! - + Het instellen van machtigingen voor privésleutelbestand "%1" is mislukt! Failed to create directory for public key file "%1". - + Het aanmaken van de map voor het publieke sleutelbestand "%1" is mislukt. Failed to save public key in file "%1"! - + Het opslaan van de openbare sleutel in bestand "%1" is mislukt! Failed to set permissions for public key file "%1"! - + Het instellen van machtigingen voor openbare sleutelbestand "%1" is mislukt! Failed to set owner of key file "%1" to "%2". - + Het instellen van de eigenaar van sleutelbestand "%1" op "%2" is mislukt. Failed to set permissions for key file "%1". - + Het instellen van machtigingen voor sleutelbestand "%1" is mislukt. Key "%1" is now accessible by user group "%2". - + Sleutel "%1" is nu toegankelijk door gebruikersgroep "%2". <N/A> @@ -579,22 +631,22 @@ The public key is used on client computers to authenticate incoming connection r Failed to read key file. - Lezen van het sleutelbestand is mislukt. + Het lezen van het sleutelbestand is mislukt. AuthKeysPlugin Create new authentication key pair - + Maak nieuw verificatiesleutelpaar aan Delete authentication key - Verwijder authenticatie sleutel + Verwijder verificatiesleutel List authentication keys - + Lijst van verificatiesleutels Import public or private key @@ -606,11 +658,11 @@ The public key is used on client computers to authenticate incoming connection r Extract public key from existing private key - + Haal de openbare sleutel uit de bestaande private sleutel Set user group allowed to access a key - + Stel de gebruikersgroep in die toegang heeft tot een sleutel KEY @@ -622,7 +674,7 @@ The public key is used on client computers to authenticate incoming connection r This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. - + Dit commando past de bestandstoegangsrechten aan op <KEY> zodat alleen de gebruikersgroep <ACCESS GROUP> leestoegang heeft. NAME @@ -634,19 +686,15 @@ The public key is used on client computers to authenticate incoming connection r This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - + Dit commando exporteert de authenticatiesleutel <KEY> naar <FILE>. Als <FILE> niet is opgegeven, wordt een naam samengesteld uit de naam en het type van <KEY>. This command imports the authentication key <KEY> from <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - + Dit commando importeert de authenticatiesleutel <KEY> uit <FILE>. Als <FILE> niet is opgegeven, wordt een naam samengesteld uit de naam en het type van <KEY>. This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - - - - Please specify the command to display help for! - + Dit commando geeft een lijst weer van alle beschikbare authenticatiesleutels in de geconfigureerde sleutel map. Als de optie "%1" is opgegeven, wordt in plaats daarvan een tabel met sleuteldetails weergegeven. Sommige details kunnen ontbreken als een sleutel niet toegankelijk is, bijvoorbeeld door het ontbreken van leesrechten. TYPE @@ -656,25 +704,45 @@ The public key is used on client computers to authenticate incoming connection r PAIR ID PAIR ID - - Command line support for managing authentication keys - - Commands for managing authentication keys - + Commando's voor het beheren van authenticatiesleutels This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. - + Dit commando maakt een nieuw authenticatiesleutelpaar met de naam <NAME> en slaat de private en publieke sleutel op in de geconfigureerde sleutelmappen. De parameter moet een naam voor de sleutel zijn, die alleen letters mag bevatten. This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. - + Dit commando verwijdert de authenticatiesleutel <KEY> uit de geconfigureerde sleutelmap. Merk op dat een sleutel'niet kan worden hersteld als hij eenmaal is verwijderd. This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. - + Dit commando haalt het openbare sleutelgedeelte uit de private sleutel <KEY> en slaat het op als de corresponderende publieke sleutel. Bij het opzetten van een andere mastercomputer is het daarom voldoende om alleen de private sleutel over te dragen. De openbare sleutel kan dan worden uitgepakt. + + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + Authenticatiesleutelbestanden zijn op deze computer niet correct ingesteld. Maak nieuwe sleutelbestanden aan of schakel over op een andere authenticatiemethode met behulp van de Veyon Configurator. + + + Key file authentication + Sleutelbestand authenticatie + + + Key file + Sleutelbestand + + + Please specify the key name (e.g. "teacher/public") as the first argument. + Geef de sleutelnaam (bijv. "teacher/public") op als eerste argument. + + + Please specify the command to display help for. + Geef het commando op waarvoor hulp moet worden weergegeven. + + + The specified command does not exist or no help is available for it. + De opgegeven opdracht bestaat niet of er is geen hulp voor beschikbaar. @@ -697,82 +765,225 @@ The public key is used on client computers to authenticate incoming connection r - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - Computers + General + Algemeen - Name - Naam + Username to bind DN mapping: + Gebruikersnaam aan DN koppelen: - Host address/IP - Host adres/IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + bijv. %username%@DOMAIN of cn=%username%,ou=users,dc=example,dc=org + + + AuthLdapDialog - MAC address - MAC adres + Veyon Logon + Veyon inloggen - Add new computer - Voeg nieuwe computer toe + Please enter your domain/LDAP username and password in order to access computers. + Voer uw domein/LDAP-gebruikersnaam en wachtwoord in om toegang te krijgen tot computers. - Remove selected computer - Verwijder geselecteerde computer + Username + Gebruikersnaam - New computer - Nieuwe computer + Password + Wachtwoord - Builtin directory - + Authentication error + Authenticatiefout - Locations & computers - Locaties & computers + Logon failed with given username and password. Please try again! + Aanmelden mislukt met de opgegeven gebruikersnaam en wachtwoord. Probeer het opnieuw! + + + AuthLogonDialog - Locations - + Veyon Logon + Veyon inloggen - Add new location - + Please enter your username and password in order to access computers. + Geef uw gebruikersnaam en paswoord in om toegang tot de computers te krijgen. - Remove selected location - + Username + Gebruikersnaam - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - + Password + Wachtwoord - New location - + Authentication error + Authenticatiefout + + + Logon failed with given username and password. Please try again! + Aanmelden mislukt met de opgegeven gebruikersnaam en wachtwoord. Probeer het opnieuw! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command - + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + De opgegeven gebruikersnaam of wachtwoord is onjuist. Voer geldige gegevens in of schakel over op een andere authenticatiemethode met behulp van de Veyon Configurator. - Import objects from given file - Importeer objecten van opgegeven bestand + Logon authentication + Aanmeldingsverificatie - Export objects to given file - Exporteer objecten van opgegeven bestand + Logon + Log in + + + AuthSimpleDialog - Invalid type specified. Valid values are "%1" or "%2". - - + Veyon Logon + Veyon inloggen + + + Please enter the Veyon password: + Voer het Veyon wachtwoord in: + + + Authentication error + Authenticatiefout + + + Logon failed with given password. Please try again! + Aanmelden mislukt met opgegeven wachtwoord. Probeer het opnieuw! + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + Het opgegeven wachtwoord is onjuist. Voer het juiste wachtwoord in of schakel over op een andere authenticatiemethode met behulp van de Veyon Configurator. + + + Simple password authentication + Eenvoudige wachtwoordverificatie + + + Simple password + Eenvoudig wachtwoord + + + + AuthenticationPage + + Authentication is set up properly on this computer. + Authenticatie is correct ingesteld op deze computer. + + + + AuthenticationPageTab + + Enabled + Ingeschakeld + + + Test + Test + + + + BuiltinDirectoryConfiguration + + Builtin directory + Ingebouwde map + + + + BuiltinDirectoryConfigurationPage + + Computers + Computers + + + Name + Naam + + + Host address/IP + Host adres/IP + + + MAC address + MAC adres + + + Add new computer + Voeg nieuwe computer toe + + + Remove selected computer + Verwijder geselecteerde computer + + + New computer + Nieuwe computer + + + Builtin directory + Ingebouwde map + + + Locations + Locaties + + + Add new location + Voeg nieuwe locatie toe + + + Remove selected location + Verwijder geselecteerde locatie + + + New location + Nieuwe locatie + + + Directory name + Map naam + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + Het importeren van CSV-bestanden is mogelijk via de opdrachtregelinterface. Zie voor meer informatie de <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + + + BuiltinDirectoryPlugin + + Show help for specific command + Geef hulp weer voor een specifiek commando + + + Import objects from given file + Importeer objecten uit een opgegeven bestand + + + Export objects to given file + Exporteer objecten naar een opgegeven bestand + + + Invalid type specified. Valid values are "%1" or "%2". + Ongeldig type opgegeven. Geldige waarden zijn "%1" of "%2". + Type Type @@ -783,7 +994,7 @@ The public key is used on client computers to authenticate incoming connection r Host address - + Host adres MAC address @@ -791,7 +1002,7 @@ The public key is used on client computers to authenticate incoming connection r Specified object not found. - Gevraagd object niet gevonnden. + Het opgegeven object is niet gevonden. File "%1" does not exist! @@ -807,11 +1018,11 @@ The public key is used on client computers to authenticate incoming connection r Computer "%1" (host address: "%2" MAC address: "%3") - + Computer "%1" (host adres: "%2" MAC-adres: "%3") Unclassified object "%1" with ID "%2" - + Niet-geclassificeerd object "%1" met ID "%2" None @@ -823,7 +1034,7 @@ The public key is used on client computers to authenticate incoming connection r Root - + Root Invalid @@ -831,67 +1042,67 @@ The public key is used on client computers to authenticate incoming connection r Error while parsing line %1. - + Fout tijdens het ontleden van regel %1. Network object directory which stores objects in local configuration - + Netwerk object map die objecten opslaat in lokale configuratie Commands for managing the builtin network object directory - + Commando's voor het beheren van de ingebouwde netwerk object map No format string or regular expression specified! - + Geen format string of reguliere expressie gespecificeerd! Can't open file "%1" for writing! - + Can't open bestand "%1" om te schrijven! No format string specified! - + Geen format string gespecificeerd! Object UUID - + Object UUID Parent UUID - + Ouder UUID Add a location or computer - + Een locatie of computer toevoegen Clear all locations and computers - + Wis alle locaties en computers Dump all or individual locations and computers - + Alle of afzonderlijke locaties en computers dumpen List all locations and computers - + Alle locaties en computers weergeven Remove a location or computer - + Een locatie of computer verwijderen Location "%1" - + Locatie "%1" Builtin (computers and locations in local configuration) - + Ingebouwd (computers en locaties in lokale configuratie) Location - + Locatie FILE @@ -899,47 +1110,47 @@ The public key is used on client computers to authenticate incoming connection r LOCATION - + LOCATIE FORMAT-STRING-WITH-PLACEHOLDERS - + FORMAT-STRING-MET-PLAATSHOUDERS REGULAR-EXPRESSION-WITH-PLACEHOLDER - + REGELMATIG-EXPRESSIE-MET-PLAATSHOUDER Imports objects from the specified text file using the given format string or regular expression containing one or multiple placeholders. Valid placeholders are: %1 - + Importeert objecten uit het opgegeven tekstbestand met behulp van de opgegeven opmaaktekenreeks of reguliere expressie die een of meer plaatsaanduidingen bevat. Geldige plaatsaanduidingen zijn: %1 Import simple CSV file to a single room - + Importeer eenvoudig CSV-bestand naar een enkele kamer Import CSV file with location name in first column - + CSV-bestand importeren met locatienaam in eerste kolom Import text file with with key/value pairs using regular expressions - + Tekstbestand importeren met sleutel/waarde-paren met behulp van reguliere expressies Import arbitrarily formatted data - + Willekeurig opgemaakte gegevens importeren Exports objects to the specified text file using the given format string containing one or multiple placeholders. Valid placeholders are: %1 - + Exporteert objecten naar het opgegeven tekstbestand met behulp van de opgegeven opmaaktekenreeks die een of meerdere plaatsaanduidingen bevat. Geldige plaatsaanduidingen zijn: %1 Export all objects to a CSV file - + Alle objecten exporteren naar een CSV-bestand Export all computers in a specific location to a CSV file - + Alle computers op een specifieke locatie exporteren naar een CSV-bestand TYPE @@ -951,52 +1162,60 @@ The public key is used on client computers to authenticate incoming connection r PARENT - + OUDER Adds an object where %1 can be one of "%2" or "%3". %4 can be specified by name or UUID. - + Voegt een object toe waarbij %1 een van "%2" of "%3" kan zijn. %4 kan worden gespecificeerd met naam of UUID. Add a room - + Voeg een ruimte toe Add a computer to room %1 - + Een computer toevoegen aan ruimte %1 OBJECT - + OBJECT Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. - + Verwijdert het opgegeven object uit de map. %1 kan worden opgegeven met naam of UUID. Als een locatie wordt verwijderd, worden ook alle gerelateerde computers verwijderd. Remove a computer by name - + Verwijder een computer op naam Remove an object by UUID - + Verwijder een object op UUID "Room 01" - + " Ruimte 01" "Computer 01" - + "Computer 01" HOST ADDRESS - + HOST ADRES MAC ADDRESS MAC ADRES + + The specified command does not exist or no help is available for it. + De opgegeven opdracht bestaat niet of er is geen hulp voor beschikbaar. + + + Location "%1" not found. + Locatie "%1" niet gevonden. + BuiltinUltraVncServer @@ -1014,13 +1233,9 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - Host/IP adres: %1 - Active features: %1 - + Actieve functies: %1 Online and connected @@ -1034,10 +1249,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off Computer offline of uitgeschakeld - - Service unreachable or not running - Service onbereikbaar of niet draaiende - Authentication failed or access denied Verificatie mislukt of toegang geweigerd @@ -1056,6 +1267,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 + Locatie: %1 + + + [no user] + [geen gebruiker] + + + Veyon Server unreachable or not running + Veyon Server onbereikbaar of niet actief + + + Name: %1 + Naam: %1 + + + Hostname: %1 + + + + unknown + onbekend + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active @@ -1075,19 +1318,30 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" is now accessing this computer. - + Gebruiker "%1" op host "%2" benadert nu deze computer. User "%1" at host "%2" attempted to access this computer but could not authenticate successfully. - + Gebruiker "%1" op host "%2" probeerde toegang te krijgen tot deze computer maar kon zich niet met succes aanmelden. Access control error - + Fout bij toegangscontrole User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. - + Gebruiker "%1" op host "%2" heeft geprobeerd toegang te krijgen tot deze computer, maar is geblokkeerd vanwege de instellingen voor toegangscontrole. + + + Active connections: + Actieve verbindingen: + + + + ComputerGroupSelector + + Group %1 + Groep %1 @@ -1102,34 +1356,69 @@ The public key is used on client computers to authenticate incoming connection r No default network object directory plugin was found. Please check your installation or configure a different network object directory backend via %1 Configurator. - Er is geen standaard plugin voor netwerkobjecten gevonden. Controleer uw installatie of configureer een andere netwerk object directory backend via% 1 Configurator. + Er is geen standaard plugin voor de netwerkobjectdirectory gevonden. Controleer uw installatie of configureer een andere netwerk object directory backend via %1 Configurator. Location detection failed - + Locatiedetectie mislukt Computer name;Hostname;User - + Computernaam;Hostnaam;Gebruiker Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. - + Kan de locatie van deze computer niet bepalen. Dit wijst op een probleem met de systeemconfiguratie. In plaats daarvan worden alle locaties weergegeven in het selectiepaneel van de computer. + + + Logged in since + Aangemeld sinds + + + %1 days + %1 dagen + + + 1 day + 1 dag - ComputerSelectPanel + ComputerMonitoring + + Computers + Computers + + + Search users and computers + Zoek gebruikers en computers + + + Select all + Selecteer alle + + + Unselect all + Alles de-selecteren + + + Add to group + Toevoegen aan groep + - Computer management - Computer management + Remove from group + Verwijder uit groep + + + ComputerSelectPanel Computer search Computer zoeken Add location - + Locatie toevoegen Save computer/user list @@ -1149,105 +1438,113 @@ The public key is used on client computers to authenticate incoming connection r Could not write the computer and users list to %1! Please check the file access permissions. - Kon de computer en gebruikerslijst niet schrijven naar% 1! Controleer de toegangsrechten voor het bestand. + Kon de computer- en gebruikerslijst niet schrijven naar %1! Controleer de toegangsrechten voor het bestand. + + + Search computers + Zoek computers - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. - Geef alstublieft een bestaand configuratiebestand op om te importeren. + Clear system-wide Veyon configuration + Veyon-configuratie voor het hele systeem wissen - Please specify a valid filename for the configuration export. - Geef alstublieft een geldige bestandsnaam op voor de configuratie export. + List all configuration keys and values + Alle configuratiesleutels en -waarden weergeven - Please specify a valid key. - Geef alstublief een geldige sleutel op. + Import configuration from given file + Importeer configuratie uit opgegeven bestand - Specified key does not exist in current configuration! - Opgegeven sleutel bestaat niet in de huidige configuratie! + Export configuration to given file + Exporteer configuratie naar opgegeven bestand - Please specify a valid value. - Geef alstublief een geldige waarde op. + Read and output configuration value for given key + Configuratiewaarde lezen en uitvoeren voor gegeven sleutel - Configure Veyon at command line - Configureer Veyon via opdrachtregel + Write given value to given configuration key + Schrijf een gegeven waarde naar een gegeven configuratiesleutel - Output file is not writable! - Uitvoerbestand is niet schrijfbaar! + Unset (remove) given configuration key + Ontkoppel (verwijder) een gegeven configuratiesleutel - Output directory is not writable! - Uitvoermap is niet schrijfbaar! + Upgrade and save configuration of program and plugins + Configuratie van programma en plugins upgraden en opslaan + + + Please specify an existing configuration file to import. + Geef een bestaand configuratiebestand op om te importeren. Configuration file is not readable! Configuratiebestand is niet leesbaar! - Clear system-wide Veyon configuration - Veyon-configuratie helemaal wissen + Please specify a valid filename for the configuration export. + Geef een geldige bestandsnaam op voor de configuratie-export. - List all configuration keys and values - Lijst alle configuratie sleutels en waarden op + Output file is not writable! + Uitvoerbestand is niet beschrijfbaar! - Import configuration from given file - Importeer configuratie van opgegeven bestand + Output directory is not writable! + Uitvoermap is niet beschrijfbaar! - Export configuration to given file - Exporteer configuratie naar opgegeven bestand + Please specify a valid key. + Geef een geldige sleutel op. - Read and output configuration value for given key - Lees en lever configuratiewaarde voor de gegeven sleutel uit + Specified key does not exist in current configuration! + Opgegeven sleutel bestaat niet in de huidige configuratie! - Write given value to given configuration key - Schrijf de gegeven waarde naar de gegeven configuratiesleutel + Please specify a valid value. + Geef een geldige waarde op. - Unset (remove) given configuration key - Ontkoppel (verwijder) de gegeven configuratiesleutel + Configure Veyon at command line + Configureer Veyon via de opdrachtregel Commands for managing the configuration of Veyon - Commando's voor het beheren van de configuratie van Veyon - - - Upgrade and save configuration of program and plugins - + Commando's voor het beheer van de configuratie van Veyon ConfigurationManager Could not modify the autostart property for the %1 Service. - Kon de autostart eigenschap niet wijzigen voor de %1 service. + Kon de autostart eigenschap voor de %1 service niet wijzigen. Could not configure the firewall configuration for the %1 Server. - + Kon de firewallconfiguratie voor de %1 Server niet configureren. Could not configure the firewall configuration for the %1 Worker. - + Kon de firewallconfiguratie voor de %1 Werker niet configureren. Configuration is not writable. Please check your permissions! - + Configuratie is niet beschrijfbaar. Controleer uw rechten! Could not apply platform-specific configuration settings. - + Kon platform-specifieke configuratie-instellingen niet toepassen. + + + Could not configure the firewall configuration for the %1 Service. + Kon de firewallconfiguratie voor de %1-service niet configureren. @@ -1265,11 +1562,11 @@ The public key is used on client computers to authenticate incoming connection r Tunables - Tunables + Afstembare ms - ms + ms Key frame interval @@ -1279,13 +1576,9 @@ The public key is used on client computers to authenticate incoming connection r Memory limit Geheugenlimiet - - Use multithreading (experimental) - Gebruik multithreading (experimenteel) - MB - MB + MB Update interval @@ -1293,19 +1586,23 @@ The public key is used on client computers to authenticate incoming connection r s - s + s Slow down thumbnail updates while demo is running - + Vertraag thumbnailupdates terwijl demo draait + + + Bandwidth limit + Bandbreedtelimiet + + + MB/s + MB/s DemoFeaturePlugin - - Fullscreen demo - Volledige scherm demo - Stop demo Stop demo @@ -1316,19 +1613,63 @@ The public key is used on client computers to authenticate incoming connection r Give a demonstration by screen broadcasting - Geef een demonstratie door het uitzenden van het scherm + Geef een demonstratie door middel van schermuitzendingen - Demo server - Demo server + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + In deze modus wordt je scherm weergegeven in een venster op alle computers. De gebruikers kunnen naar behoefte naar andere vensters overschakelen. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - In deze modus wordt uw scherm in de fullscreen modus op alle computers weergegeven, terwijl de invoerapparaten van de gebruikers vergrendeld zijn. + Demo + Demo - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - In deze modus wordt uw scherm in een venster op alle computers weergegeven. De gebruikers kunnen, indien nodig, overstappen naar andere vensters. + Share your screen or allow a user to share his screen with other users. + Deel je scherm of laat een gebruiker zijn scherm delen met andere gebruikers. + + + Full screen demo + Demoweergave op volledig scherm + + + Share your own screen in fullscreen mode + Deel je eigen scherm in schermvullende modus + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + In deze modus wordt je scherm in volledig scherm weergegeven op alle computers terwijl de invoerapparaten van de gebruikers zijn vergrendeld. + + + Share your own screen in a window + Deel je eigen scherm in een venster + + + Share selected user's screen in fullscreen mode + Deel het scherm van geselecteerde gebruiker's op volledig scherm + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + In deze modus wordt het scherm van de geselecteerde gebruiker schermvullend weergegeven op alle computers terwijl de invoerapparaten van de gebruikers zijn vergrendeld. + + + Share selected user's screen in a window + Deel het scherm van geselecteerde gebruiker's in een venster + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + In deze modus wordt het scherm van de geselecteerde gebruiker weergegeven in een venster op alle computers. De gebruikers kunnen naar behoefte naar andere vensters overschakelen. + + + Please select a user screen to share. + Selecteer een gebruikersscherm om te delen. + + + Please select only one user screen to share. + Selecteer slechts een gebruikersscherm om te delen. + + + All screens + Alle schermen @@ -1356,14 +1697,6 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - - Programs & websites - Programma's & websites - - - Predefined programs - - Name Naam @@ -1372,17 +1705,9 @@ The public key is used on client computers to authenticate incoming connection r Path Pad - - Add new program - Nieuw programma toevoegen - - - Remove selected program - Geselecteerd programma verwijderen - Predefined websites - + Voorgedefinieerde websites Remove selected website @@ -1392,21 +1717,37 @@ The public key is used on client computers to authenticate incoming connection r URL URL - - New program - Nieuw programma - New website Nieuwe website + + Applications & websites + Toepassingen & websites + + + Predefined applications + Voorgedefinieerde toepassingen + + + Add new application + Nieuwe toepassing toevoegen + + + Remove selected application + Verwijder geselecteerde toepassing + + + Add new website + Nieuwe website toevoegen + + + New application + Nieuwe toepassing + DesktopServicesFeaturePlugin - - Run program - Voer programma uit - Open website Open website @@ -1416,28 +1757,32 @@ The public key is used on client computers to authenticate incoming connection r Klik op deze knop om een website op alle computers te openen. - Start programs and services in user desktop - Start programma's en services in de gebruikersdesktop + Open website "%1" + Open website "%1" - Click this button to run a program on all computers. - Klik op deze knop om een programma op alle computers uit te voeren. + Custom website + Aangepaste website - Run program "%1" - Programma "%1" uitvoeren + Start application + Start toepassing - Custom program - Aangepast programma + Click this button to start an application on all computers. + Klik op deze knop om een toepassing op alle computers te starten. - Open website "%1" - Open website "%1" + Start application "%1" + Start toepassing "%1" - Custom website - Aangepaste website + Custom application + Aangepaste toepassing + + + Start apps and open websites in user sessions + Start apps en open websites in gebruikerssessies @@ -1448,11 +1793,11 @@ The public key is used on client computers to authenticate incoming connection r Room %1 - + Room %1 Please complete all tasks within the next 5 minutes. - + Voltooi alle taken binnen de komende 5 minuten. Custom website @@ -1460,27 +1805,31 @@ The public key is used on client computers to authenticate incoming connection r Open file manager - + Open bestandsbeheer Start learning tool - + Leermiddel starten Play tutorial video - - - - Custom program - Aangepast programma + Zelfstudievideo afspelen Handout - + Uitreiking Texts to read - + Te lezen teksten + + + generic-student-user + generieke-student-gebruiker + + + Custom application + Aangepaste toepassing @@ -1506,59 +1855,223 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands + + List names of all available features + Namen van alle beschikbare functies weergeven + + + Show table with details of all available features + Toon tabel met details van alle beschikbare functies + + + Start a feature on a remote host + Een functie starten op een externe host + + + Stop a feature on a remote host + Een functie op een externe host stoppen + + + Please specify the command to display help for. + Geef het commando op waarvoor hulp moet worden weergegeven. + + + Displays a list with the names of all available features. + Geeft een lijst weer met de namen van alle beschikbare functies. + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + Toont een tabel met gedetailleerde informatie over alle beschikbare functies. Deze informatie bevat een beschrijving, de UID, de naam van de plugin die de betreffende eigenschap levert en enkele andere implementatie-gerelateerde details. + + + HOST ADDRESS + HOST ADRES + + + FEATURE + FUNCTIE + + + ARGUMENTS + STANDPUNTEN + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + Start de opgegeven functie op de opgegeven host door verbinding te maken met de Veyon Server die extern draait. De functie kan op naam of UID worden opgegeven. Gebruik het ``show`` commando om alle beschikbare functies te zien. Afhankelijk van het kenmerk moeten extra argumenten (zoals de weer te geven tekstboodschap) gecodeerd als een enkele JSON string worden opgegeven. Raadpleeg de documentatie voor ontwikkelaars voor meer informatie + +Translated with DeepL + + + Lock the screen + Scherm vergrendelen + + + Display a text message + Tekstbericht weergeven + + + Test message + Testbericht + + + Start an application + Start een toepassing + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + Stopt de opgegeven functie op de opgegeven host door verbinding te maken met de Veyon Server die extern draait. De functie kan worden opgegeven met naam of UID. Gebruik het ``show`` commando om alle beschikbare functies te zien. + + + Unlock the screen + Ontgrendel het scherm + + + The specified command does not exist or no help is available for it. + De opgegeven opdracht bestaat niet of er is geen hulp voor beschikbaar. + + + Name + Naam + + + Description + Beschrijving + + + Master + Master + + + Service + Service + + + Worker + Werknemer + + + UID + UID + + + Plugin + Plugin + + + Invalid feature name or UID specified + Ongeldige functienaam of UID gespecificeerd + + + Error parsing the JSON-encoded arguments: %1 + Fout bij het ontleden van de JSON-gecodeerde argumenten: %1 + + + Failed to initialize credentials + Initialisatie van referenties mislukt + + + Could not establish a connection to host %1 + Kon geen verbinding maken met host %1 + + + Failed to send feature control message to host %1 + Fout bij het verzenden van functie-controle bericht naar host %1 + + + Feature-related CLI operations + Functie-gerelateerde CLI-bewerkingen + + + Commands for controlling features + Commando's voor het bedienen van functies + + + + FileTransferConfigurationPage + + File transfer + Bestandsoverdracht + + + Directories + Mappen + + + Destination directory + Bestemmingsmap + + + Default source directory + Standaard bronmap + + + Options + Opties + + + Remember last source directory + Onthoud laatste bronmap + - Feature control - Kenmerkencontrole + Create destination directory if it does not exist + Doelmap aanmaken als deze niet bestaat FileTransferController Could not open file "%1" for reading! Please check your permissions! - + Kon bestand "%1" niet openen om te lezen! Controleer uw rechten! FileTransferDialog File transfer - + Bestandsoverdracht Options - + Opties Transfer only - + Alleen overdracht Transfer and open file(s) with associated program - + Bestand(en) overdragen en openen met bijbehorend programma Transfer and open destination folder - + Doelmap overbrengen en openen Files - + Bestanden Start - + Start Overwrite existing files - + Bestaande bestanden overschrijven + + + + FileTransferFileDialog + + Select one or more files to transfer + Selecteer één of meerdere bestanden om over te zetten. FileTransferPlugin File transfer - + Bestandsoverdracht Click this button to transfer files from your computer to all computers. @@ -1570,19 +2083,19 @@ The public key is used on client computers to authenticate incoming connection r Transfer files to remote computer - + Bestanden overzetten naar externe computer Received file "%1". - + Ontvangen bestand "%1". Could not receive file "%1" as it already exists. - + Kon bestand "%1" niet ontvangen omdat het al bestaat. Could not receive file "%1" as it could not be opened for writing! - + Kon bestand "%1" niet ontvangen omdat het niet geopend kon worden om te schrijven! @@ -1611,10 +2124,6 @@ The public key is used on client computers to authenticate incoming connection r Log file directory Logbestand map - - ... - ... - Log level Log niveau @@ -1655,18 +2164,6 @@ The public key is used on client computers to authenticate incoming connection r Log to standard error output Log naar standaard fout uitgang - - Network object directory - Netwerk object map - - - Backend: - Backend: - - - Update interval: - Update interval: - %1 service %1 service @@ -1689,11 +2186,11 @@ The public key is used on client computers to authenticate incoming connection r Could not remove all log files. - Kon alle log bestanden niet verwijderen. + Kon niet alle logbestanden verwijderen. MB - MB + MB Rotate log files @@ -1704,429 +2201,392 @@ The public key is used on client computers to authenticate incoming connection r x - seconds - seconden + Write to logging system of operating system + Schrijven naar het logsysteem van het besturingssysteem - Write to logging system of operating system - + TLS configuration + TLS configuratie - Authentication - Authenticatie + Use certificate authority for TLS connections + Gebruik een certificeringsinstantie voor TLS-verbindingen - Method: - Methode: + CA certificate file + CA-certificaat bestand - Logon authentication - Aanmeldingsverificatie + ... + ... - Key file authentication - Sleutel bestand authenticatie + Host certificate file + Hostcertificaat bestand - Test - Test + Host private key file + Host privé sleutelbestand - Authentication is set up properly on this computer. - + Style: + Stijl: + + + Native + Eigen - Authentication keys are not set up properly on this computer. + Color scheme: - Authentication test + Light - - - InternetAccessControlConfigurationPage - Internet access control + Dark + + User groups + Gebruikersgroepen + Backend: Backend: - General settings - Algemene instellingen + Include user groups from domain + Gebruikersgroepen uit domein opnemen - Backend settings - + Missing user groups backend + Ontbrekende gebruikersgroepen backend + + + No user groups plugin was found. Please check your installation! + Er is geen plugin voor gebruikersgroepen gevonden. Controleer je installatie! - InternetAccessControlPlugin + HeadlessVncServer - Block access to the internet - Toegang tot internet blokkeren + Headless VNC server + VNC-server zonder hoofd + + + LdapBrowseDialog - Allow access to the internet - Toegang tot internet toestaan + Browse LDAP + Bladeren door LDAP + + + LdapClient - Show help about command - Toon hulp over commando + LDAP error description: %1 + LDAP foutbeschrijving: %1 + + + LdapConfiguration - Block internet - Blokkeer internet + LDAP connection failed + LDAP connectie mislukt - Click this button to block access to the internet. - Klik op deze knop om toegang tot internet te blokkeren - - - Unblock internet - Deblokkeer internet - - - Click this button to allow access to the internet. - Klik op deze knop om toegang tot internet toe te staan - - - Control access to the internet - - - - Commands for controlling access to the internet - - - - - LdapBrowseDialog - - Browse LDAP - - - - - LdapClient - - LDAP error description: %1 - LDAP foutbeschrijving: %1 - - - - LdapConfigurationPage - - Basic settings - Basisinstellingen - - - General - Algemeen - - - LDAP server and port - LDAP server en poort + Could not connect to the LDAP server. Please check the server parameters. + +%1 + Kon geen verbinding maken met de LDAP server. Controleer de server parameters. + +%1 - Bind DN - Bind DN + LDAP bind failed + LDAP bind mislukt - Bind password - Bind wachtwoord + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + Kan niet koppelen aan de LDAP-server. Controleer de serverparameters en de aanmeldingsgegevens. + +%1 - Anonymous bind - Anonieme bind + LDAP bind successful + LDAP bind gelukt - Use bind credentials - Gebruik bind credentials + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Succesvol geconnecteerd op de LDAP-server en een LDAP-bind uitgevoerd. De basis LDAP instellingen zijn correct geconfigureerd. - Base DN - Base DN + LDAP base DN test failed + LDAP base DN test mislukt - Fixed base DN - Vaste basis DN + Could not query the configured base DN. Please check the base DN parameter. + +%1 + De geconfigureerde basis-DN kon niet worden opgevraagd. Controleer de parameter base DN. + +%1 - e.g. dc=example,dc=org - bv. dc=example,dc=org + LDAP base DN test successful + LDAP base DN test gelukt - Discover base DN by naming context - Ontdek basis DN door naming context + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + De LDAP base DN is met succes opgevraagd. De volgende vermeldingen zijn gevonden: + +%1 - e.g. namingContexts or defaultNamingContext - bv. namingContexts of defaultNamingContext + LDAP naming context test failed + LDAP naming context test mislukt - Environment settings - Omgevingsinstellingen + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + Kan de basis-DN niet opvragen via naamcontexten. Controleer de naamcontext attribuutparameter. + +%1 - Object trees - Object boomstructuren + LDAP naming context test successful + LDAP naming context test gelukt - Computer tree - Computer boomstructuur + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + De LDAP naming context is succesvol bevraagd. De volgende basis DN werd gevonden: +%1 - e.g. OU=Groups - bv. OU=Groups + user tree + gebruiker boomstructuur User tree Gebruiker boomstructuur - e.g. OU=Users - bv. OU=Users - - - e.g. OU=Computers - bv. OU=Computers + group tree + groep boomstructuur Group tree Groep boomstructuur - Perform recursive search operations in object trees - Voer recursieve zoekacties uit in objectbomen - - - Object attributes - Object attributen - - - e.g. hwAddress - bv. hwAddress - - - e.g. member or memberUid - bv. member of memberUid - - - e.g. dNSHostName - bv. dNSHostName - - - Computer MAC address attribute - Computer MAC adres attribuut - - - Group member attribute - Groepslid attribuut - - - e.g. uid or sAMAccountName - bv. uid of sAMAccountName - - - Advanced settings - Geavanceerde instellingen - - - Optional object filters - Optionele objectfilters + computer tree + computer boomstructuur - Filter for user groups - Filter voor gebruikersgroepen + Computer tree + Computer boomstructuur - Filter for users - Filter voor gebruikers + computer group tree + computer groep structuur - Filter for computer groups - Filter voor computergroepen + Computer group tree + Computer groep structuur - Group member identification - Groepslid identificatie + user objects + gebruikersobjecten - Distinguished name (Samba/AD) - Onderscheidende naam (Samba/AD) + User login name attribute + Attribuut inlognaam gebruiker - List all groups of a user - Lijst alle groepen van een gebruiker op + group members + groepsleden - List all groups of a computer - Lijst alle groepen van een computer op + Group member attribute + Groepslid attribuut - Get computer object by IP address - Verkrijg computer object door IP-adres + Group not found + Groep niet gevonden - LDAP connection failed - LDAP connectie mislukt + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Kan een groep met de naam "%1" niet vinden. Controleer de groepsnaam of de groepsboomstructuur parameter. - LDAP bind failed - LDAP bind mislukt + computer objects + computer objecten - LDAP bind successful - LDAP bind gelukt + Computer display name attribute + Attribuut weergavenaam computer - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - Succesvol geconnecteerd op de LDAP-server en een LDAP-bind uitgevoerd. De basis LDAP instellingen zijn correct geconfigureerd. + Invalid hostname + Ongeldige hostnaam - LDAP base DN test failed - LDAP base DN test mislukt + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Je hebt hostnamen van computers geconfigureerd om te worden opgeslagen als volledig gekwalificeerde domeinnamen (FQDN), maar je hebt een hostnaam zonder domein ingevoerd. - LDAP base DN test successful - LDAP base DN test gelukt + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Je hebt hostnamen van computers geconfigureerd om te worden opgeslagen als eenvoudige hostnamen zonder domeinnaam, maar je hebt een hostnaam ingevoerd met een domeinnaamgedeelte. - LDAP naming context test failed - LDAP naming context test mislukt + Computer hostname attribute + Computer hostnaam kenmerk - LDAP naming context test successful - LDAP naming context test gelukt + computer MAC addresses + computer MAC adressen - The LDAP naming context has been queried successfully. The following base DN was found: -%1 - De LDAP naming context is succesvol bevraagd. De volgende basis DN werd gevonden: -%1 + Computer MAC address attribute + Computer MAC adres attribuut - user tree - gebruiker boomstructuur + computer locations + computerlocaties - group tree - groep boomstructuur + Computer location attribute + Computerlocatiekenmerk - computer tree - computer boomstructuur + Location name attribute + Kenmerk locatienaam - Enter username - Voer gebruikersnaam in + users + gebruikers - Please enter a user login name (wildcards allowed) which to query: - Vul alstublieft een gebruikersnaam in (wildcards toegestaan) die bevraagd moet worden: + user groups + gebruikersgroepen - user objects - gebruikersobjecten + computers + computers - Enter group name - Voer de groepsnaam in + computer groups + computergroepen - Please enter a group name whose members to query: - Vul alstublieft een groepsnaam in waarvan de leden bevraagd moeten worden: + computer containers + computercontainers - group members - groepsleden + groups of user + groepen van gebruiker - Group not found - Groep niet gevonden + User not found + Gebruiker niet gevonden - Could not find a group with the name "%1". Please check the group name or the group tree parameter. - Kan een groep met de naam "%1" niet vinden. Controleer de groepsnaam of de groepsboomstructuur parameter. + Could not find a user with the name "%1". Please check the username or the user tree parameter. + Kon geen gebruiker vinden met de naam "%1". Controleer de gebruikersnaam of de parameter van de gebruikersstructuur. - Enter computer name - Voer de computernaam in + groups of computer + groepen van computer - computer objects - computer objecten + Computer not found + Computer niet gevonden - Enter computer DN - Voer de computer DN in + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Kon geen computer vinden met de hostnaam "%1". Controleer de hostnaam of de computerstructuur parameter. + + - Please enter the DN of a computer whose MAC address to query: - Vul alstublieft de DN in van een computer waarvan het MAC-adres moet worden bevraagd: + Hostname lookup failed + Hostnaam opzoeken mislukt - computer MAC addresses - computer MAC adressen + Could not lookup hostname for IP address %1. Please check your DNS server settings. + Kan hostnaam voor IP-adres %1 niet opzoeken. Controleer uw DNS-server instellingen. - users - gebruikers + location entries + locatievermeldingen - user groups - gebruikersgroepen + Computer groups filter + Filter computergroepen - computer groups - computergroepen + Computer locations identification + Identificatie computerlocaties - Please enter a user login name whose group memberships to query: - Vul alstublieft een gebruikersnaam in van wie de groepslidmaatschappen moeten bevraagd worden: + Filter for computer groups + Filter voor computergroepen - groups of user - groepen van gebruiker + Invalid test value + Ongeldige testwaarde - User not found - Gebruiker niet gevonden + An empty or invalid value has been supplied for this test. + Er is een lege of ongeldige waarde opgegeven voor deze test. - groups of computer - groepen van computer + LDAP %1 test failed + LDAP %1 test mislukt - Computer not found - Computer niet gevonden + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + Er konden geen items worden opgevraagd in geconfigureerd %1. Controleer de parameter "%2". + +%3 - Enter computer IP address - Voer computer IP adres in + LDAP %1 test successful + LDAP %1 test gelukt - Please enter a computer IP address which to resolve to an computer object: - Voer het IP-adres van een computer in dat moet worden omgezet naar een computerobject: + The %1 has been queried successfully and %2 entries were found. + De %1 is met succes opgevraagd en %2 ingaven zijn gevonden. - computers - computers + LDAP test failed + LDAP test mislukt - LDAP %1 test failed - LDAP %1 test mislukt + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + Kan %1 niet opvragen. Controleer de parameter(s) %2 en voer de naam van een bestaand object in. + +%3 - LDAP %1 test successful - LDAP %1 test gelukt + and + en - The %1 has been queried successfully and %2 entries were found. - De %1 is met succes opgevraagd en %2 ingaven zijn gevonden. + LDAP test successful + LDAP-test geslaagd %1 %2 have been queried successfully: @@ -2157,542 +2617,485 @@ The public key is used on client computers to authenticate incoming connection r %1 %2 zijn met succes opgevraagd gebruikmakend van de ingestelde filter. - (only if different from group tree) - (Alleen als verschillend van groep-structuur) - - - Computer group tree - Computer groep structuur - - - computer group tree - computer groep structuur - - - Filter for computers - Filter voor computers - - - e.g. room or computerLab - bv. lokaal of computerlabo - - - Integration tests - Intregatietests - - - Computer groups - Computergroepen + LDAP directory + LDAP map + + + LdapConfigurationPage - e.g. name or description - bv. naam of beschrijving + Basic settings + Basisinstellingen - Filter for computer containers - Filter voor computer containers + General + Algemeen - Computer containers or OUs - Computer containers of OUs + LDAP server and port + LDAP server en poort - Connection security - Verbindingsbeveiliging + Bind DN + Bind DN - TLS certificate verification - TLS certificaatverificatie - + Bind password + Bind wachtwoord - System defaults - Systeem standaard + Anonymous bind + Anonieme bind - Never (insecure!) - Nooit (onveilig!) + Use bind credentials + Gebruik bind credentials - Custom CA certificate file - Aangepast CA certificaatbestand + Base DN + Base DN - None - Geen + Fixed base DN + Vaste basis DN - TLS - TLS + e.g. dc=example,dc=org + bv. dc=example,dc=org - SSL - SSL + Discover base DN by naming context + Ontdek basis DN door naming context - e.g. (objectClass=computer) - bv. (objectClass=computer) + e.g. namingContexts or defaultNamingContext + bv. namingContexts of defaultNamingContext - e.g. (objectClass=group) - bv. (objectClass=group) + Environment settings + Omgevingsinstellingen - e.g. (objectClass=person) - bv. (objectClass=person) + Object trees + Object boomstructuren - e.g. (objectClass=room) or (objectClass=computerLab) - bv. (objectClass=room) of (objectClass=computerLab) + Computer tree + Computer boomstructuur - e.g. (objectClass=container) or (objectClass=organizationalUnit) - bv. (objectClass=container) of (objectClass=organizationalUnit) + e.g. OU=Groups + bv. OU=Groups - Could not query the configured base DN. Please check the base DN parameter. - -%1 - + User tree + Gebruiker boomstructuur - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - + e.g. OU=Users + bv. OU=Users - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - + e.g. OU=Computers + bv. OU=Computers - Certificate files (*.pem) - Certificaatbestanden (*.pem) + Group tree + Groep boomstructuur - Could not connect to the LDAP server. Please check the server parameters. - -%1 - Kon geen verbinding maken met de LDAP server. Controleer de server parameters. - -%1 + Perform recursive search operations in object trees + Voer recursieve zoekacties uit in objectbomen - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - + Object attributes + Object attributen - Encryption protocol - Encryptie protocol + e.g. hwAddress + bv. hwAddress - Computer location attribute - + e.g. member or memberUid + bv. member of memberUid - Computer display name attribute - + e.g. dNSHostName + bv. dNSHostName - Location name attribute - + Computer MAC address attribute + Computer MAC adres attribuut - e.g. cn or displayName - + Group member attribute + Groepslid attribuut - Computer locations identification - + e.g. uid or sAMAccountName + bv. uid of sAMAccountName - Identify computer locations (e.g. rooms) via: - + Advanced settings + Geavanceerde instellingen - Location attribute in computer objects - + Optional object filters + Optionele objectfilters - List all entries of a location - + Filter for user groups + Filter voor gebruikersgroepen - List all locations - + Filter for users + Filter voor gebruikers - Enter computer display name - + Filter for computer groups + Filter voor computergroepen - Please enter a computer display name to query: - + Group member identification + Groepslid identificatie - Enter computer location name - + Distinguished name (Samba/AD) + Onderscheidende naam (Samba/AD) - Please enter the name of a computer location (wildcards allowed): - + List all groups of a user + Lijst alle groepen van een gebruiker op - computer locations - + List all groups of a computer + Lijst alle groepen van een computer op - Enter location name - + Get computer object by IP address + Verkrijg computer object door IP-adres - Please enter the name of a location whose entries to query: - + Enter username + Voer gebruikersnaam in - location entries - + Please enter a user login name (wildcards allowed) which to query: + Vul alstublieft een gebruikersnaam in (wildcards toegestaan) die bevraagd moet worden: - LDAP test failed - + Enter group name + Voer de groepsnaam in - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - + Please enter a group name whose members to query: + Vul alstublieft een groepsnaam in waarvan de leden bevraagd moeten worden: - and - + Enter computer name + Voer de computernaam in - LDAP test successful - + Enter computer DN + Voer de computer DN in - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - + Please enter the DN of a computer whose MAC address to query: + Vul alstublieft de DN in van een computer waarvan het MAC-adres moet worden bevraagd: - Browse - + Please enter a user login name whose group memberships to query: + Vul alstublieft een gebruikersnaam in van wie de groepslidmaatschappen moeten bevraagd worden: - Test - Test + Enter computer IP address + Voer computer IP adres in - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - + Please enter a computer IP address which to resolve to an computer object: + Voer het IP-adres van een computer in dat moet worden omgezet naar een computerobject: - Computer hostname attribute - + (only if different from group tree) + (Alleen als verschillend van groep-structuur) - Please enter a computer hostname to query: - + Computer group tree + Computer groep structuur - Invalid hostname - + Filter for computers + Filter voor computers - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - + e.g. room or computerLab + bv. lokaal of computerlabo - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - + Integration tests + Intregatietests - Could not find a user with the name "%1". Please check the username or the user tree parameter. - + Computer groups + Computergroepen - Enter hostname - + e.g. name or description + bv. naam of beschrijving - Please enter a computer hostname whose group memberships to query: - + Filter for computer containers + Filter voor computer containers - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - + Computer containers or OUs + Computer containers of OUs - Hostname lookup failed - + Connection security + Verbindingsbeveiliging - Could not lookup hostname for IP address %1. Please check your DNS server settings. - + TLS certificate verification + TLS certificaatverificatie - User login name attribute - + System defaults + Systeem standaard - Configured attribute for user login name or computer hostname (OpenLDAP) - + Never (insecure!) + Nooit (onveilig!) - computer containers - + Custom CA certificate file + Aangepast CA certificaatbestand - - - LdapPlugin - Auto-configure the base DN via naming context - Automatiseer de base DN dmv. naamgevingscontext + None + Geen - Query objects from LDAP directory - Objecten opvragen uit LDAP directory + TLS + TLS - Show help about command - Toon hulp over commando + SSL + SSL - Commands for configuring and testing LDAP/AD integration - Commando's voor het configureren en testen van LDAP/AD-integratie + e.g. (objectClass=computer) + bv. (objectClass=computer) - Basic LDAP/AD support for Veyon - + e.g. (objectClass=group) + bv. (objectClass=group) - %1 (load computers and locations from LDAP/AD) - + e.g. (objectClass=person) + bv. (objectClass=person) - %1 (load users and groups from LDAP/AD) - + e.g. (objectClass=room) or (objectClass=computerLab) + bv. (objectClass=room) of (objectClass=computerLab) - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - + e.g. (objectClass=container) or (objectClass=organizationalUnit) + bv. (objectClass=container) of (objectClass=organizationalUnit) - No naming context attribute name given - falling back to configured value. - + Certificate files (*.pem) + Certificaatbestanden (*.pem) - Could not query base DN. Please check your LDAP configuration. - + Encryption protocol + Encryptie protocol - Configuring %1 as base DN and disabling naming context queries. - + Computer location attribute + Computerlocatiekenmerk - - - LdapProConfigurationPage - LDAP Pro - + Computer display name attribute + Attribuut weergavenaam computer - Instances - + Location name attribute + Kenmerk locatienaam - Enter name - + e.g. cn or displayName + bijv. cn of displayName - Please enter a name for the instance (can't be changed later!): - + Computer locations identification + Identificatie computerlocaties - Remove instance - + Identify computer locations (e.g. rooms) via: + Computerlocaties (bijv. ruimtes) identificeren via: - Do you really want to remove instance "%1"? - + Location attribute in computer objects + Locatiekenmerk in computerobjecten - Configuration for instance "%1" - + List all entries of a location + Alle vermeldingen van een locatie weergeven - - - LdapProPlugin - Professional LDAP/AD integration for Veyon - + List all locations + Alle locaties weergeven - %1 (load computers and locations from LDAP/AD) - + Enter computer display name + Voer de weergavenaam van de computer in - %1 (load users and groups from LDAP/AD) - + Please enter a computer display name to query: + Voer een computernaam in om op te vragen: - - - LicensingConfigurationPage - Licensing - + Enter computer location name + Voer de naam van de computerlocatie in - Installed licenses - + Please enter the name of a computer location (wildcards allowed): + Voer de naam van een computerlocatie in (jokertekens toegestaan): - Add new network range - + Enter location name + Locatie naam invoeren - Remove selected network range - + Please enter the name of a location whose entries to query: + Voer de naam in van een locatie waarvan u de gegevens wilt opvragen: - ID - + Browse + Bladeren - Feature - + Test + Test - Valid until - + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Hostnamen opgeslagen als volledig gekwalificeerde domeinnamen (FQDN, bijv. myhost.example.org) - Licensee - + Computer hostname attribute + Computer hostnaam kenmerk - Browse license file - + Please enter a computer hostname to query: + Voer de hostnaam van een computer in om een zoekopdracht uit te voeren: - Veyon license files (*.vlf) - + Enter hostname + Voer hostnaam in - Remove license - + Please enter a computer hostname whose group memberships to query: + Voer een hostnaam van een computer in waarvan de groepslidmaatschappen moeten worden opgevraagd: - Do you really want to remove the selected license? - + User login name attribute + Attribuut inlognaam gebruiker - <N/A> - <N/A> + Configured attribute for user login name or computer hostname (OpenLDAP) + Geconfigureerd attribuut voor aanmeldingsnaam van gebruiker of hostnaam van computer (OpenLDAP) - Invalid license file - + Directory name + Map naam - Could not open the license file for reading! - + Query options + Zoekopties - The selected license file does not contain valid data. - + Query nested user groups (supported by AD only) + Geneste gebruikersgroepen opvragen (alleen ondersteund door AD) - The selected license file could not be verified. - + Query timeout + Time-out zoekopdracht - The selected license file is not valid for this installation. - + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. - + LDAP + LDAP - The license is already installed. - + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + Gebruik de globale LDAP-configuratiepagina om te configureren hoe locaties en computers worden opgehaald uit uw LDAP-gebaseerde mapservice. + + + LdapPlugin - Information - + Auto-configure the base DN via naming context + Automatiseer de base DN dmv. naamgevingscontext - Installation ID - + Query objects from LDAP directory + Objecten opvragen uit LDAP directory - Addons available for licensing - + Show help about command + Toon hulp over commando - Addon - + Commands for configuring and testing LDAP/AD integration + Commando's voor het configureren en testen van LDAP/AD-integratie - - - LicensingPlugin - Show help for specific command - + Basic LDAP/AD support for Veyon + Basis LDAP/AD-ondersteuning voor Veyon - Show all installed licenses - + %1 (load computers and locations from LDAP/AD) + %1 (computers en locaties laden vanuit LDAP/AD) - Add license file - + %1 (load users and groups from LDAP/AD) + %1 (gebruikers en groepen laden vanuit LDAP/AD) - Remove installed license - + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Geef een geldige LDAP-url op volgens het schema "ldap[s]://[user[:password]@]hostnaam[:poort]". - -USAGE - -%1 add <LICENSE FILE> - - - + No naming context attribute name given - falling back to configured value. + Geen naamgeving context attribuut gegeven - wordt teruggezet op geconfigureerde waarde. - -USAGE - -%1 remove <LICENSE ID> - - - + Could not query base DN. Please check your LDAP configuration. + Kan basis-DN niet opvragen. Controleer uw LDAP-configuratie. - No certificate found with given ID - + Configuring %1 as base DN and disabling naming context queries. + %1 configureren als basis DN en zoekopdrachten voor naamcontext uitschakelen. - <N/A> - <N/A> + Test binding to an LDAP server + Test de koppeling met een LDAP-server - Licensing management - + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + De opgegeven gebruikersnaam of wachtwoord is onjuist. Voer geldige gegevens in of schakel over op een andere authenticatiemethode met behulp van de Veyon Configurator. - Commands for managing license keys - + LDAP bind + LDAP koppeling @@ -2703,19 +3106,27 @@ USAGE Custom PAM service for user authentication - + Aangepaste PAM-service voor gebruikersverificatie User authentication - + Gebruikersverificatie - Session management - + User sessions + Gebruiker sessies - Display manager users - + Minimum session lifetime before server start + Minimale sessieduur voor het starten van de server + + + User login + Aanmelden gebruiker + + + Login key sequence + Toetsvolgorde aanmelden @@ -2724,16 +3135,12 @@ USAGE Plugin implementing abstract functions for the Linux platform Plugin uitvoering van abstracte functies voor Linux - - Plugin implementing specific functions for the Linux platform - - LocationDialog Select location - + Kies locatie enter search filter... @@ -2746,14 +3153,14 @@ USAGE Configuration Configuratie - - Disable balloon tooltips - Schakel ballontooltips uit - Show icons only Toon enkel iconen + + Disable tooltips + Tooltips uitschakelen + MainWindow @@ -2801,10 +3208,6 @@ USAGE About Qt Over Qt - - Authentication impossible - Authenticatie onmogelijk - Configuration not writable Configuratie niet schrijfbaar @@ -2865,10 +3268,6 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. De lokale backend configuratie rapporteert dat de configuratie niet-schrijfbaar is. Start de %1 configurator met admin of hogere previleges. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - Er werden geen verificatiesleutels gevonden of de huidige zijn verlopen. Maak nieuwe sleutelbestanden aan, of als alternatief stel logon verificatie in, met de %1 configurator. U krijgt geen toegang tot computers, gebruikmakend van %1, indien u niet een van beide gebruikt. - Access denied Toegang geweigerd @@ -2901,10 +3300,6 @@ USAGE Search users and computers Zoek gebruikers en computers - - Adjust optimal size - Pas de optimale grootte aan - Align computers to grid Computers uitlijnen op rooster @@ -2914,39 +3309,81 @@ USAGE %1 Configurator - Insufficient privileges - Onvoldoende toegangsrechten + Insufficient privileges + Onvoldoende toegangsrechten + + + Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + Kon niet starten met beheerdersrechten. Zorg ervoor dat er een sudo-achtig programma is geïnstalleerd voor je desktopomgeving! Het programma wordt uitgevoerd met normale gebruikersrechten. + + + Only show powered on computers + Toon alleen de ingeschakelde computers + + + &Save settings to file + &Instellingen opslaan naar bestand + + + &View + &View + + + &Standard + &Standard + + + &Advanced + &Advanced + + + Use custom computer arrangement + Aangepaste computeropstelling gebruiken + + + Locations && computers + Locaties && computers + + + Authentication + Authenticatie + + + Adjust size of computer icons automatically + Pas de grootte van computerpictogrammen automatisch aan - Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. - + Slideshow + Diavoorstelling - Only show powered on computers - Toon alleen de ingeschakelde computers + Spotlight + In de kijker - &Save settings to file - &Instellingen opslaan naar bestand + Veyon Master + Veyon Master - &View - + Locations & computers + Locaties & computers - &Standard + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. - &Advanced - + Only show computers with logged on users + Toon alleen computers met aangemelde gebruikers - Use custom computer arrangement + Load computer positions - Locations && computers + Save computer positions @@ -2956,10 +3393,6 @@ USAGE Directories Mappen - - ... - ... - User configuration Gebruikerconfiguratie @@ -3034,7 +3467,7 @@ USAGE Modes and features - + Modi en functies User and computer name @@ -3044,6 +3477,10 @@ USAGE Only user name Alleen gebruikersnaam + + Only last part of user name + + Only computer name Alleen computernaam @@ -3058,11 +3495,11 @@ USAGE Sort order - + Sorteer volgorde Computer and user name - + Computer- en gebruikersnaam Computer locations @@ -3070,195 +3507,210 @@ USAGE Show current location only - + Alleen huidige locatie weergeven Allow adding hidden locations manually - + Toestaan om verborgen locaties handmatig toe te voegen Hide empty locations - + Verberg lege locaties Show confirmation dialog for potentially unsafe actions - + Bevestigingsdialoog weergeven voor mogelijk onveilige acties Perform access control - + Toegangscontrole uitvoeren Automatically select current location - - - - Automatically adjust computer thumbnail size - + Automatisch huidige locatie selecteren Automatically open computer select panel - + Automatisch computer selectiepaneel openen - - - MonitoringMode - Monitoring - Toezicht + Use modern user interface (experimental) + Gebruik moderne gebruikersinterface (experimenteel) - Builtin monitoring mode - Ingebouwde monitoring modus + Thumbnail spacing + Tussenruimte voor miniaturen - This mode allows you to monitor all computers at one or more locations. - + px + px - - - NetworkDiscoveryConfigurationPage - Network discovery - + Hide local session + Lokale sessie verbergen - Mode - + Auto + Auto - Scan network ranges - + Thumbnail aspect ratio + Beeldverhouding miniaturen - e.g. 192.168.1.0/24 - + Automatically adjust computer icon size + Pictogramgrootte van computer automatisch aanpassen - Scan all subnets of computer - + Open feature windows on the same screen as the main window + Functievensters openen op hetzelfde scherm als het hoofdvenster - Scan custom subnet + Configuration templates - Scan sessions on local computer - + Image quality in monitoring mode + Beeldkwaliteit in bewakingsmodus - Test - Test + Highest + Hoogste - Network ranges - + High + Hoog - Add new group - Nieuwe groep toevoegen + Medium + Medium - Remove selected group - Geselecteerde groep verwijderen + Low + Laag - Groups - Groepen + Lowest + Laagste - First address - Eerste adres + Remote access image quality + Beeldkwaliteit van externe toegang - Last address - Laatste adres + Advanced + - Add new network range + Computer name source - Remove selected network range - + Default + Standaard - Parallel scans - + Host address + Host adres - Scan timeout - + Session client address + Sessie-clientadres - ms - ms + Session client name + Sessie-clientnaam - Session scan limit + Session host name - Options + Session metadata - Reverse lookup discovered IP addresses to host names - + Full name of user + Volledige naam van gebruiker - New location + User login name + Loginnaam gebruiker + + + Computer UID role - - - NetworkDiscoveryDirectory - Scanning... + Session meta data hash - Discovered computers + Always expand all locations + + Image quality + Beeldkwaliteit + - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command - + Monitoring + Toezicht - Scan a subnet - + Builtin monitoring mode + Ingebouwde monitoring modus - -USAGE - -%1 scan [<SUBNET>] - - - + This mode allows you to monitor all computers at one or more locations. + Deze modus stelt je in staat om alle computers op één of meer locaties te controleren. - Network object directory which automatically discovers computers in the network - + Query application version of the server + Toepassingsversie van de server opvragen - Network discovery (scan network for Veyon clients) - + Query active features + Actieve functies opvragen - Commands for managing the network discovery directory - + Query properties of remotely available screens + Eigenschappen opvragen van schermen die op afstand beschikbaar zijn + + + + NestedNetworkObjectDirectory + + All directories + Alle mappen + + + + NetworkObjectDirectoryConfigurationPage + + Update interval: + Update interval: + + + seconds + seconden + + + + NetworkObjectDirectoryConfigurationPageTab + + Enabled + Ingeschakeld NetworkObjectTreeModel Locations/Computers - + Locaties/Computers @@ -3269,15 +3721,15 @@ USAGE e.g. Veyon - + bijv. Veyon Remember and add to website menu - + Onthoud en voeg toe aan website menu e.g. www.veyon.io - + bijv. www.veyon.io Please enter the URL of the website to open: @@ -3285,34 +3737,46 @@ USAGE Name: - + Naam: + + + Website name + Website naam - PasswordDialog + PluginCommands - Username - Gebruikersnaam + List names of all installed plugins + Namen van alle geïnstalleerde plugins weergeven - Password - Wachtwoord + Show table with details of all installed plugins + Tabel weergeven met details van alle geïnstalleerde plugins - Veyon Logon - Veyon inloggen + Name + Naam - Authentication error - Authenticatie fout + Description + Beschrijving - Logon failed with given username and password. Please try again! - Inloggen mislukt met de opgegeven gebruikersnaam en wachtwoord. Probeer het opnieuw! + Version + Versie - Please enter your username and password in order to access computers. - Geef uw gebruikersnaam en paswoord in om toegang tot de computers te krijgen. + UID + UID + + + Plugin-related CLI operations + Plugin-gerelateerde CLI-bewerkingen + + + Commands for managing plugins + Commando's voor het beheren van plugins @@ -3357,13 +3821,9 @@ USAGE Do you really want to reboot the selected computers? Wilt u werkelijk de geselecteerde computers heropstarten? - - Do you really want to power down the selected computer? - Wilt u werkelijk de geselecteerde computers uitschakelen? - Power on a computer via Wake-on-LAN (WOL) - + Een computer inschakelen via Wake-on-LAN (WOL) MAC ADDRESS @@ -3371,11 +3831,11 @@ USAGE This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. - + Dit commando zendt een Wake-on-LAN (WOL) pakket uit naar het netwerk om de computer met het opgegeven MAC-adres in te schakelen. Please specify the command to display help for! - + Geef het commando op waarvoor hulp moet worden weergegeven! Invalid MAC address specified! @@ -3383,33 +3843,47 @@ USAGE Commands for controlling power status of computers - + Commando's om de energiestatus van computers te regelen Power down now - + Schakel nu uit Install updates and power down - + Installeer updates en schakel uit Power down after user confirmation - + Schakel uit na gebruikersbevestiging Power down after timeout - + Schakel uit na timeout The computer was remotely requested to power down. Do you want to power down the computer now? - + Er is op afstand gevraagd om de computer uit te schakelen. Wilt u de computer nu uitschakelen? The computer will be powered down in %1 minutes, %2 seconds. Please save your work and close all programs. - + De computer wordt over %1 minuten, %2 seconden uitgeschakeld. + +Sla je werk op en sluit alle programma's af. + + + Do you really want to reboot <b>ALL</b> computers? + Wilt u echt <b>ALLE</b> computers opnieuw opstarten? + + + Do you really want to power down <b>ALL</b> computers? + Wilt u echt <b>ALLE</b> computers uitschakelen? + + + Do you really want to power down the selected computers? + Wil je echt de geselecteerde computers uitschakelen? @@ -3420,15 +3894,15 @@ Please save your work and close all programs. Please specify a timeout for powering down the selected computers: - + Geef een time-out op voor het uitschakelen van de geselecteerde computers: minutes - + minuten seconds - + seconden @@ -3457,14 +3931,25 @@ Please save your work and close all programs. Remote view or control a computer Meekijken of overnemen op afstand - - Please enter the hostname or IP address of the computer to access: - Voer de hostnaam of het IP-adres van de computer in waartoe u toegang wil: - Show help about command Toon hulp over commando + + Exchange clipboard contents + Inhoud klembord uitwisselen + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + Er is geen computer geselecteerd, dus je kunt een hostnaam of IP-adres van een computer invoeren voor handmatige toegang: + + + + RemoteAccessPage + + Remote access: %1 + Toegang op afstand: %1 + RemoteAccessWidget @@ -3472,6 +3957,10 @@ Please save your work and close all programs. %1 - %2 Remote Access %1 - %2 Externe toegang + + %1 - %2 - %3 Remote Access + %1 - %2 - %3 Toegang op afstand + RemoteAccessWidgetToolBar @@ -3527,10 +4016,6 @@ Please save your work and close all programs. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - Verbinden met %1 - Connected. Verbonden. @@ -3541,60 +4026,19 @@ Please save your work and close all programs. Exit - - - - - Routing - - Control internet access by modifying routing table - - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - - - - Add custom route to block internet - - - - Destination - - - - Gateway - - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - Voer alsjeblieft de programma's of commando's in om op de geselecteerde computer(s) te draaien. U kunt meerdere programma's / opdrachten per lijn scheiden. - - - Run programs - Voer programma's uit - - - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - bv. "C:\Program Files\VideoLAN\VLC\vlc.exe" + Verlaten - Name: - + Connecting... + Verbinden... - Remember and add to program menu - + Select screen + Selecteer scherm - e.g. VLC - + All screens + Alle schermen @@ -3615,6 +4059,18 @@ Please save your work and close all programs. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. Om de volledige aandacht van alle gebruikers te eisen, kunt u hun computers vergrendelen met deze knop. In deze modus zijn alle invoerapparaten vergrendeld en de schermen zijn zwart. + + Lock input devices + Invoerapparaten vergrendelen + + + Unlock input devices + Ontgrendel invoerapparaten + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + Om de volledige aandacht van alle gebruikers terug te krijgen, kun je hun computers vergrendelen met deze knop. In deze modus worden alle invoerapparaten vergrendeld terwijl het bureaublad nog steeds zichtbaar is. + Screenshot @@ -3630,6 +4086,10 @@ Please save your work and close all programs. Screenshot Schermafbeelding + + Could not open screenshot file %1 for writing. + Kan schermopnamebestand %1 niet openen om te schrijven. + ScreenshotFeaturePlugin @@ -3654,6 +4114,13 @@ Please save your work and close all programs. Maak schermafbeeldingen van computers en sla ze lokaal op. + + ScreenshotManagementPage + + Screenshots + Schermafbeeldingen + + ScreenshotManagementPanel @@ -3661,28 +4128,67 @@ Please save your work and close all programs. Alle screenshots die door u zijn gemaakt, worden hier vermeld. U kunt screenshots maken door op het "Screenshot" item in het contextmenu van een computer te klikken. De screenshots kunnen worden beheerd met behulp van onderstaande knoppen. - User: - Gebruiker: + User: + Gebruiker: + + + Computer: + Computer: + + + Date: + Datum: + + + Time: + Tijd: + + + Show + Toon + + + Delete + Verwijder + + + Screenshot + Schermafbeelding + + + Do you really want to delete all selected screenshots? + Wil je echt alle geselecteerde schermafbeeldingen verwijderen? + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + - Computer: - Computer: + Access denied by rule "%1" + - Date: - Datum: + No rule allowed access + - Time: - Tijd: + Accessing user not member of an authorized user group + - Show - Toon + User has denied access + - Delete - Verwijder + User confirmed access + @@ -3715,14 +4221,6 @@ Please save your work and close all programs. State: Staat: - - Network - Netwerk - - - Demo server port - Demo server poort - Enable firewall exception Schakel firewall uitzondering in @@ -3731,10 +4229,6 @@ Please save your work and close all programs. Allow connections from localhost only Sta alleen verbindingen van localhost toe - - Internal VNC server port - Interne VNC server poort - VNC server VNC server @@ -3756,68 +4250,141 @@ Please save your work and close all programs. Gestart - Feature manager port - Feature manager poort + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. + Het inschakelen van deze optie zorgt ervoor dat de service een serverproces start voor elke interactieve sessie op een computer. +Dit is meestal nodig om terminalservers te ondersteunen. - Primary service port - Primaire service poort + Show notification on remote connection + Toon melding bij externe verbinding - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. - + Show notification when an unauthorized access is blocked + Meldingen tonen wanneer een niet-geautoriseerde toegang is geblokkeerd - Show notification on remote connection - Toon melding op externe verbinding + Maximum session count + Maximaal aantal sessies - Multi session mode (for terminal and remote desktop servers) - + Network port numbers + Netwerkpoort nummers - Show notification when an unauthorized access is blocked + Veyon server + Veyon server + + + Internal VNC server + Interne VNC server + + + Feature manager + Functiebeheerder + + + Demo server + Demo server + + + Miscellaneous network settings + Diverse netwerkinstellingen + + + Session mode + Sessie modus + + + Local session mode (single server instance for primary local session) + Lokale sessiemodus (enkele serverinstantie voor primaire lokale sessie) + + + Active session mode (single server instance for active local or remote session) + Actieve sessiemodus (één serverinstantie voor actieve lokale of externe sessie) + + + Multi session mode (distinct server instance for each local and remote desktop session) + Modus voor meerdere sessies (afzonderlijke serverinstantie voor elke lokale en externe desktopsessie) + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. - - - ServiceControl - Starting service %1 - Service %1 wordt gestart + Miscellaneous settings + Diverse instellingen - Stopping service %1 - Service %1 wordt gestopt + Disable clipboard synchronization + Klembordsynchronisatie uitschakelen - Registering service %1 - Service %1 wordt geregistreerd + Session metadata + - Unregistering service %1 + Content - Service control + None + Geen + + + Value of an environment variable + + Value of a registry key + + + + Environment variable name: + Naam omgevingsvariabele: + + + Registry key name: + Naam registersleutel: + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + Voer optioneel een reguliere expressie met een capture in om een deel van de computernaam te extraheren en te gebruiken als weergavenaam voor de computer. + +Voorbeeld: [^-]*-(PC[0-9]*) + - ServiceControlPlugin + ServiceControl - Service is running - Service is actief + Service control + Servicecontrole - Service is not running - Service is niet actief + Starting %1 + - Configure and control Veyon service - Configureer en beheer Veyon service + Stopping %1 + + + + Restarting %1 + + + Registering %1 + + + + Unregistering %1 + + + + + ServiceControlCommands Register Veyon Service Registreer Veyon Service @@ -3842,30 +4409,129 @@ Typically this is required to support terminal servers. Query status of Veyon Service Bevraag status van Veyon Service + + Service is running + Service is actief + + + Service is not running + Service is niet actief + + + Configure and control Veyon service + Configureer en beheer Veyon service + Commands for configuring and controlling Veyon Service Commando's voor het configureren en besturen van Veyon Service - ShellCommandLinePlugin + ShellCommands Run command file - + Opdrachtbestand uitvoeren File "%1" does not exist! Bestand "%1" bestaat niet! - Interactive shell and script execution for Veyon Control - + Interactive shell and script execution for Veyon CLI + Interactieve shell en uitvoering van scripts voor Veyon CLI Commands for shell functionalities + Commando's voor shell-functionaliteiten + + + + SlideshowPanel + + Previous + Vorige + + + Start/pause + Start/pauze + + + Next + Volgende + + + Duration: + Duur: + + + View in separate window + + + + %1 Master – Slideshow + + SpotlightPanel + + Add selected computers + Voeg geselecteerde computers toe + + + Remove selected computers + Verwijder geselecteerde computers + + + Update computers in realtime + Computers in realtime bijwerken + + + Spotlight + In de kijker + + + Please select at least one computer to add. + Selecteer ten minste één computer om toe te voegen. + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + Voeg computers toe door met de middelste muisknop te klikken of door op de eerste knop hieronder te klikken. +De tweede knop verwijdert de geselecteerde of laatste computer. + + + + StartAppDialog + + Start application + Start toepassing + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + Voer de applicaties in die moeten worden gestart op de geselecteerde computers. Je kunt meerdere applicaties van elkaar scheiden door een regel. + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + bv. "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + Onthouden en toevoegen aan applicatiemenu + + + Application name + Applicatie naam + + + Name: + Naam: + + + e.g. VLC + bijv. VLC + + SystemTrayIcon @@ -3877,22 +4543,22 @@ Typically this is required to support terminal servers. SystemUserGroupsPlugin User groups backend for system user groups - + Gebruikersgroepen backend voor systeemgebruikersgroepen Default (system user groups) - + Standaard (systeemgebruikersgroepen) TestingCommandLinePlugin Test internal Veyon components and functions - + Interne Veyon componenten en functies testen Commands for testing internal components and functions of Veyon - + Commando's voor het testen van interne componenten en functies van Veyon @@ -3902,8 +4568,8 @@ Typically this is required to support terminal servers. Stuur tekstbericht - Use the field below to type your message which will be sent to all selected users. - Gebruik de onderstaande veld om uw bericht dat voor alle geselecteerde gebruikers wordt verzonden te typen. + Please enter your message which send to all selected users. + Voer uw bericht in en verstuur het naar alle geselecteerde gebruikers. @@ -3945,45 +4611,69 @@ Typically this is required to support terminal servers. Enable multi monitor support - + Ondersteuning voor meerdere monitors inschakelen Enable Desktop Duplication Engine on Windows 8 and newer - + Bureaublad Duplicatie Engine inschakelen op Windows 8 en nieuwer + + + Maximum CPU usage + Maximaal CPU-gebruik - UserConfig + UserLoginDialog - No write access - Geen schrijftoegang + User login + Aanmelden gebruiker - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - Kon uw persoonlijke instellingen niet opslaan! Controleer het gebruikersconfiguratiebestandspad door gebruik te maken van de %1 Configurator. + Please enter a username and password for automatic login on all computers. + Voer een gebruikersnaam en wachtwoord in om automatisch in te loggen op alle computers. + + + Username + Gebruikersnaam + + + Password + Wachtwoord - UserSessionControl + UserSessionControlPlugin - User session control - Gebruikers sessie controle + Log in + Log in + + + Click this button to log in a specific user on all computers. + Klik op deze knop om een specifieke gebruiker op alle computers aan te melden. Log off - + Afmelden Click this button to log off users from all computers. - + Klik op deze knop om gebruikers van alle computers uit te loggen. Confirm user logoff - + Bevestig uitloggen gebruiker Do you really want to log off the selected users? - + Wil je echt de geselecteerde gebruikers afmelden? + + + User session control + Gebruikers sessie controle + + + Do you really want to log off <b>ALL</b> users? + Wilt u echt <b>ALLE</b> gebruikers afmelden? @@ -4022,53 +4712,61 @@ Typically this is required to support terminal servers. No module specified or module not found - available modules are: - + Geen module opgegeven of module niet gevonden - beschikbare modules zijn: Plugin not licensed - + Plugin niet gelicentieerd INFO - + INFO ERROR - - - - licensed for - + FOUT USAGE - + GEBRUIK DESCRIPTION - + BESCHRIJVING EXAMPLES - + VOORBEELDEN WARNING - + WAARSCHUWING + + + Authentication test + Authenticatietest + + + Screen %1 + Scherm %1 - VeyonServiceControl + VeyonMaster - Veyon Service - Veyon Service + No write access + Geen schrijftoegang + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Kon uw persoonlijke instellingen niet opslaan! Controleer het gebruikersconfiguratiebestandspad door gebruik te maken van de %1 Configurator. - VncView + VeyonServiceControl - Establishing connection to %1 ... - Verbinding tot stand brengen naar %1 ... + Veyon Service + Veyon Service @@ -4082,7 +4780,7 @@ Typically this is required to support terminal servers. WindowsPlatformConfigurationPage Windows - + Windows General @@ -4094,27 +4792,51 @@ Typically this is required to support terminal servers. Screen lock - + Schermvergrendeling Hide taskbar - + Verberg taakbalk Hide start menu - + Verberg startmenu Hide desktop - + Verberg bureaublad User authentication - + Gebruikersverificatie Use alternative user authentication mechanism - + Gebruik alternatief authenticatiemechanisme voor gebruikers + + + User login + Aanmelden gebruiker + + + Input start delay + Ingangsvertraging + + + Simulated key presses interval + Interval gesimuleerde toetsaanslagen + + + Confirm legal notice (message displayed before user logs in) + Bevestig wettelijke kennisgeving (bericht dat wordt weergegeven voordat de gebruiker inlogt) + + + Use input device interception driver + Gebruik het stuurprogramma voor het onderscheppen van invoerapparaten + + + Use custom power scheme with disabled power button + Aangepast voedingsschema gebruiken met uitgeschakelde aan/uit-knop @@ -4124,39 +4846,43 @@ Typically this is required to support terminal servers. Uitvoering plugin abstracte functies voor Windows - Plugin implementing specific functions for the Windows platform - + Internal display + Intern scherm WindowsServiceControl The service "%1" is already installed. - + De service "%1" is al geïnstalleerd. - The service "%1" could not be installed. - + The service "%1" has been installed successfully. + De service "%1" is met succes geïnstalleerd. - The service "%1" has been installed successfully. - + The service "%1" has been uninstalled successfully. + De service "%1" is met succes verwijderd. - The service "%1" could not be uninstalled. - + Service "%1" could not be found. + Service "%1" kon niet worden gevonden. - The service "%1" has been uninstalled successfully. - + The service "%1" could not be installed (error %2). + De service "%1" kon niet worden geïnstalleerd (fout %2). - The start type of service "%1" could not be changed. - + Could not change the failure actions config for service "%1" (error %2). + Kon de storing acties config niet wijzigen voor service "%1" (fout %2). - Service "%1" could not be found. - + The service "%1" could not be uninstalled (error %2). + De service "%1" kon niet worden verwijderd (fout %2). + + + The start type of service "%1" could not be changed (error %2). + Het starttype van de service "%1" kon niet worden gewijzigd (fout %2). diff --git a/translations/no_NO.ts b/translations/veyon_no_NO.ts similarity index 78% rename from translations/no_NO.ts rename to translations/veyon_no_NO.ts index 06e1184e9..12c95d6cf 100644 --- a/translations/no_NO.ts +++ b/translations/veyon_no_NO.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -78,10 +78,6 @@ If you're interested in translating Veyon into your local or another langua All groups Alle grupper - - ... - ... - Access control rules @@ -139,15 +135,14 @@ If you're interested in translating Veyon into your local or another langua - Missing user groups backend - - - - No default user groups plugin was found. Please check your installation! + Restrict access to members of specific user groups + + + AccessControlProvider - Restrict access to members of specific user groups + Provider for access control features @@ -178,87 +173,159 @@ If you're interested in translating Veyon into your local or another langua - Invert all conditions ("is/has" interpreted as "is/has not") + Conditions - Conditions + If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. - is member of group + Action - Accessing computer is localhost + Allow access + Tillat tilgang + + + Deny access - Accessing user is logged on user + Ask logged on user for permission - Accessing user is already connected + None (rule disabled) - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. + Accessing user - Action + Accessing computer - Allow access - Tillat tilgang + Always process rule and ignore conditions + - Deny access + Accessing computer and local computer - Ask logged on user for permission + User being accessed - None (rule disabled) + is logged in locally - Accessing user + is logged in remotely - Accessing computer + No user is logged in locally - Local (logged on) user + One or multiple users are logged in locally - Local computer + No user is logged in remotely - Always process rule and ignore conditions + One or multiple users are logged in remotely - No user logged on - Ingen bruker pålogget + is located at + - Accessing user has one or more groups in common with local (logged on) user + is not located at - Accessing computer and local computer are at the same location + are located at the same location - is located at + are not located the same location + + + + is member of group + + + + is not member of group + + + + is authenticated via + + + + is not authenticated via + + + + has one or more groups in common with user being accessed + + + + has no groups in common with user being accessed + + + + equals user being accessed + + + + is different from user being accessed + + + + is already connected + + + + is not connected + + + + is local computer + + + + is not local computer + + + + Computer being accessed + + + + Session being accessed is a user session + + + + Session being accessed is a login screen + + + + Local computer is already being accessed + + + + Local computer is not yet being accessed @@ -305,40 +372,42 @@ If you're interested in translating Veyon into your local or another langua - ERROR: Unknown action + Test result + + + + Authentication method - Test result + There is no matching rule with a valid action. The access is therefore denied. - AndroidPlatformConfigurationPage + AuthKeysConfigurationWidget - Android + Introduction - General - Generelt + Please perform the following steps to set up key file authentication: + - - - AndroidPlatformPlugin - Plugin implementing specific functions for the Android platform + 1) Create a key pair on the master computer. - - - AuthKeysConfigurationPage - Authentication keys + 2) Set an access group whose members should be allowed to access other computers. - Introduction + 3) Export the public key and import it on all client computers with the same name. + + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. @@ -354,11 +423,14 @@ If you're interested in translating Veyon into your local or another langua - ... - ... + Available authentication keys + - Available authentication keys + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. @@ -401,10 +473,6 @@ If you're interested in translating Veyon into your local or another langua Please select a key to delete! - - Please enter the name of the user group or role for which to import the authentication key: - - Please select a key to export! @@ -418,30 +486,9 @@ If you're interested in translating Veyon into your local or another langua - Please perform the following steps to set up key file authentication: - - - - 1) Create a key pair on the master computer. - - - - 2) Set an access group whose members should be allowed to access other computers. - - - - 3) Export the public key and import it on all client computers with the same name. - - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. @@ -642,10 +689,6 @@ The public key is used on client computers to authenticate incoming connection r This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - - Please specify the command to display help for! - - TYPE @@ -654,10 +697,6 @@ The public key is used on client computers to authenticate incoming connection r PAIR ID - - Command line support for managing authentication keys - - Commands for managing authentication keys @@ -674,166 +713,333 @@ The public key is used on client computers to authenticate incoming connection r This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. - - - AuthKeysTableModel - Name - Navn + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + - Type + Key file authentication - Access group + Key file - Pair ID + Please specify the key name (e.g. "teacher/public") as the first argument. - - - BuiltinDirectoryConfigurationPage - Computers - Datamaskiner + Please specify the command to display help for. + + + + The specified command does not exist or no help is available for it. + + + + AuthKeysTableModel Name Navn - Host address/IP + Type - MAC address + Access group - Add new computer + Pair ID + + + AuthLdapConfigurationWidget - Remove selected computer - + General + Generelt - New computer + Username to bind DN mapping: - Builtin directory + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + AuthLdapDialog - Locations & computers + Veyon Logon - Locations + Please enter your domain/LDAP username and password in order to access computers. - Add new location + Username - Remove selected location + Password - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + Authentication error - New location + Logon failed with given username and password. Please try again! - BuiltinDirectoryPlugin + AuthLogonDialog - Show help for specific command + Veyon Logon - Import objects from given file + Please enter your username and password in order to access computers. - Export objects to given file + Username - Invalid type specified. Valid values are "%1" or "%2". + Password - Type + Authentication error - Name - Navn - - - Host address + Logon failed with given username and password. Please try again! + + + AuthLogonPlugin - MAC address + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Specified object not found. + Logon authentication - File "%1" does not exist! + Logon + + + AuthSimpleDialog - Can't open file "%1" for reading! + Veyon Logon - Unknown argument "%1". + Please enter the Veyon password: - Computer "%1" (host address: "%2" MAC address: "%3") + Authentication error - Unclassified object "%1" with ID "%2" + Logon failed with given password. Please try again! + + + AuthSimplePlugin - None + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. - Computer + Simple password authentication - Root + Simple password + + + AuthenticationPage - Invalid + Authentication is set up properly on this computer. + + + AuthenticationPageTab - Error while parsing line %1. + Enabled - Network object directory which stores objects in local configuration - + Test + Test + + + + BuiltinDirectoryConfiguration + + Builtin directory + + + + + BuiltinDirectoryConfigurationPage + + Computers + Datamaskiner + + + Name + Navn + + + Host address/IP + + + + MAC address + + + + Add new computer + + + + Remove selected computer + + + + New computer + + + + Builtin directory + + + + Locations + + + + Add new location + + + + Remove selected location + + + + New location + + + + Directory name + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + + + + BuiltinDirectoryPlugin + + Show help for specific command + + + + Import objects from given file + + + + Export objects to given file + + + + Invalid type specified. Valid values are "%1" or "%2". + + + + Type + + + + Name + Navn + + + Host address + + + + MAC address + + + + Specified object not found. + + + + File "%1" does not exist! + + + + Can't open file "%1" for reading! + + + + Unknown argument "%1". + + + + Computer "%1" (host address: "%2" MAC address: "%3") + + + + Unclassified object "%1" with ID "%2" + + + + None + + + + Computer + + + + Root + + + + Invalid + + + + Error while parsing line %1. + + + + Network object directory which stores objects in local configuration + Commands for managing the builtin network object directory @@ -995,6 +1201,14 @@ The public key is used on client computers to authenticate incoming connection r MAC ADDRESS + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. + + BuiltinUltraVncServer @@ -1012,10 +1226,6 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - - Active features: %1 @@ -1032,10 +1242,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off - - Service unreachable or not running - - Authentication failed or access denied @@ -1056,6 +1262,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 + + [no user] + + + + Veyon Server unreachable or not running + + + + Name: %1 + + + + Hostname: %1 + + + + unknown + + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + ComputerControlServer @@ -1087,6 +1325,17 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + + Active connections: + + + + + ComputerGroupSelector + + Group %1 + + ComputerManager @@ -1114,80 +1363,83 @@ The public key is used on client computers to authenticate incoming connection r Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. - - - ComputerSelectPanel - Computer management + Logged in since - Computer search + %1 days - Add location + 1 day + + + ComputerMonitoring - Save computer/user list - + Computers + Datamaskiner - Select output filename + Search users and computers - CSV files (*.csv) - CSV filer (*.csv) + Select all + - File error + Unselect all - Could not write the computer and users list to %1! Please check the file access permissions. + Add to group - - - ConfigCommandLinePlugin - Please specify an existing configuration file to import. + Remove from group + + + ComputerSelectPanel - Please specify a valid filename for the configuration export. + Computer search - Please specify a valid key. + Add location - Specified key does not exist in current configuration! + Save computer/user list - Please specify a valid value. + Select output filename - Configure Veyon at command line - + CSV files (*.csv) + CSV filer (*.csv) - Output file is not writable! + File error - Output directory is not writable! + Could not write the computer and users list to %1! Please check the file access permissions. - Configuration file is not readable! + Search computers + + + ConfigCommands Clear system-wide Veyon configuration @@ -1217,42 +1469,82 @@ The public key is used on client computers to authenticate incoming connection r - Commands for managing the configuration of Veyon + Upgrade and save configuration of program and plugins - Upgrade and save configuration of program and plugins + Please specify an existing configuration file to import. - - - ConfigurationManager - Could not modify the autostart property for the %1 Service. + Configuration file is not readable! - Could not configure the firewall configuration for the %1 Server. + Please specify a valid filename for the configuration export. - Could not configure the firewall configuration for the %1 Worker. + Output file is not writable! - Configuration is not writable. Please check your permissions! + Output directory is not writable! - Could not apply platform-specific configuration settings. + Please specify a valid key. - - - DemoClient - %1 Demo - %1 Demo + Specified key does not exist in current configuration! + + + + Please specify a valid value. + + + + Configure Veyon at command line + + + + Commands for managing the configuration of Veyon + + + + + ConfigurationManager + + Could not modify the autostart property for the %1 Service. + + + + Could not configure the firewall configuration for the %1 Server. + + + + Could not configure the firewall configuration for the %1 Worker. + + + + Configuration is not writable. Please check your permissions! + + + + Could not apply platform-specific configuration settings. + + + + Could not configure the firewall configuration for the %1 Service. + + + + + DemoClient + + %1 Demo + %1 Demo @@ -1277,10 +1569,6 @@ The public key is used on client computers to authenticate incoming connection r Memory limit - - Use multithreading (experimental) - - MB MB @@ -1297,13 +1585,17 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running - - - DemoFeaturePlugin - Fullscreen demo + Bandwidth limit + + + + MB/s + + + DemoFeaturePlugin Stop demo Stopp demo @@ -1317,15 +1609,59 @@ The public key is used on client computers to authenticate incoming connection r - Demo server - Demo server + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. + Demo - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Share your screen or allow a user to share his screen with other users. + + + + Full screen demo + + + + Share your own screen in fullscreen mode + + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share your own screen in a window + + + + Share selected user's screen in fullscreen mode + + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share selected user's screen in a window + + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + + + + Please select only one user screen to share. + + + + All screens @@ -1355,56 +1691,56 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - Programs & websites + Name + Navn + + + Path - Predefined programs + Predefined websites - Name - Navn + Remove selected website + - Path + URL - Add new program + New website - Remove selected program + Applications & websites - Predefined websites + Predefined applications - Remove selected website + Add new application - URL + Remove selected application - New program + Add new website - New website + New application DesktopServicesFeaturePlugin - - Run program - - Open website @@ -1414,27 +1750,31 @@ The public key is used on client computers to authenticate incoming connection r Klikk denne knappen for å åpne nettsiden på alle datamaskinene. - Start programs and services in user desktop + Open website "%1" - Click this button to run a program on all computers. + Custom website - Run program "%1" + Start application - Custom program + Click this button to start an application on all computers. - Open website "%1" + Start application "%1" - Custom website + Custom application + + + + Start apps and open websites in user sessions @@ -1469,15 +1809,19 @@ The public key is used on client computers to authenticate incoming connection r - Custom program + Handout - Handout + Texts to read - Texts to read + generic-student-user + + + + Custom application @@ -1504,513 +1848,522 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands - Feature control + List names of all available features - - - FileTransferController - Could not open file "%1" for reading! Please check your permissions! + Show table with details of all available features - - - FileTransferDialog - File transfer + Start a feature on a remote host - Options + Stop a feature on a remote host - Transfer only + Please specify the command to display help for. - Transfer and open file(s) with associated program + Displays a list with the names of all available features. - Transfer and open destination folder + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. - Files + HOST ADDRESS - Start + FEATURE - Overwrite existing files + ARGUMENTS - - - FileTransferPlugin - File transfer + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information - Click this button to transfer files from your computer to all computers. + Lock the screen - Select one or more files to transfer + Display a text message - Transfer files to remote computer + Test message - Received file "%1". + Start an application - Could not receive file "%1" as it already exists. + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. - Could not receive file "%1" as it could not be opened for writing! + Unlock the screen - - - GeneralConfigurationPage - User interface + The specified command does not exist or no help is available for it. - Language: - Språk: + Name + Navn - Use system language setting + Description - Veyon - Veyon + Master + - Logging + Service - Log file directory + Worker - ... - ... + UID + - Log level + Plugin - Nothing + Invalid feature name or UID specified - Only critical messages + Error parsing the JSON-encoded arguments: %1 - Errors and critical messages + Failed to initialize credentials - Warnings and errors + Could not establish a connection to host %1 - Information, warnings and errors + Failed to send feature control message to host %1 - Debug messages and everything else + Feature-related CLI operations - Limit log file size + Commands for controlling features + + + FileTransferConfigurationPage - Clear all log files + File transfer - Log to standard error output + Directories - Network object directory + Destination directory - Backend: + Default source directory - Update interval: + Options - %1 service + Remember last source directory - The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + Create destination directory if it does not exist + + + FileTransferController - Log files cleared + Could not open file "%1" for reading! Please check your permissions! + + + FileTransferDialog - All log files were cleared successfully. + File transfer - Error + Options - Could not remove all log files. + Transfer only - MB - MB + Transfer and open file(s) with associated program + - Rotate log files + Transfer and open destination folder - x - x + Files + - seconds - sekunder + Start + - Write to logging system of operating system + Overwrite existing files + + + FileTransferFileDialog - Authentication + Select one or more files to transfer + + + FileTransferPlugin - Method: + File transfer - Logon authentication + Click this button to transfer files from your computer to all computers. - Key file authentication + Select one or more files to transfer - Test - Test + Transfer files to remote computer + - Authentication is set up properly on this computer. + Received file "%1". - Authentication keys are not set up properly on this computer. + Could not receive file "%1" as it already exists. - Authentication test + Could not receive file "%1" as it could not be opened for writing! - InternetAccessControlConfigurationPage + GeneralConfigurationPage - Internet access control + User interface - Backend: - + Language: + Språk: - General settings + Use system language setting - Backend settings - + Veyon + Veyon - - - InternetAccessControlPlugin - Block access to the internet + Logging - Allow access to the internet + Log file directory - Show help about command + Log level - Block internet + Nothing - Click this button to block access to the internet. + Only critical messages - Unblock internet + Errors and critical messages - Click this button to allow access to the internet. + Warnings and errors - Control access to the internet + Information, warnings and errors - Commands for controlling access to the internet + Debug messages and everything else - - - LdapBrowseDialog - Browse LDAP + Limit log file size - - - LdapClient - LDAP error description: %1 + Clear all log files - - - LdapConfigurationPage - Basic settings + Log to standard error output - General - Generelt - - - LDAP server and port + %1 service - Bind DN + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? - Bind password + Log files cleared - Anonymous bind + All log files were cleared successfully. - Use bind credentials + Error - Base DN + Could not remove all log files. - Fixed base DN - + MB + MB - e.g. dc=example,dc=org + Rotate log files - Discover base DN by naming context - + x + x - e.g. namingContexts or defaultNamingContext + Write to logging system of operating system - Environment settings + TLS configuration - Object trees + Use certificate authority for TLS connections - Computer tree + CA certificate file - e.g. OU=Groups - + ... + ... - User tree + Host certificate file - e.g. OU=Users + Host private key file - e.g. OU=Computers + Style: - Group tree + Native - Perform recursive search operations in object trees + Color scheme: - Object attributes + Light - e.g. hwAddress + Dark - e.g. member or memberUid + User groups - e.g. dNSHostName + Backend: - Computer MAC address attribute + Include user groups from domain - Group member attribute + Missing user groups backend - e.g. uid or sAMAccountName + No user groups plugin was found. Please check your installation! + + + HeadlessVncServer - Advanced settings + Headless VNC server + + + LdapBrowseDialog - Optional object filters + Browse LDAP + + + LdapClient - Filter for user groups + LDAP error description: %1 + + + LdapConfiguration - Filter for users + LDAP connection failed - Filter for computer groups + Could not connect to the LDAP server. Please check the server parameters. + +%1 - Group member identification + LDAP bind failed - Distinguished name (Samba/AD) + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 - List all groups of a user + LDAP bind successful - List all groups of a computer + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - Get computer object by IP address + LDAP base DN test failed - LDAP connection failed + Could not query the configured base DN. Please check the base DN parameter. + +%1 - LDAP bind failed + LDAP base DN test successful - LDAP bind successful + The LDAP base DN has been queried successfully. The following entries were found: + +%1 - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + LDAP naming context test failed - LDAP base DN test failed + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 - LDAP base DN test successful + LDAP naming context test successful - LDAP naming context test failed + The LDAP naming context has been queried successfully. The following base DN was found: +%1 - LDAP naming context test successful + user tree - The LDAP naming context has been queried successfully. The following base DN was found: -%1 + User tree - user tree + group tree - group tree + Group tree @@ -2018,23 +2371,23 @@ The public key is used on client computers to authenticate incoming connection r - Enter username + Computer tree - Please enter a user login name (wildcards allowed) which to query: + computer group tree - user objects + Computer group tree - Enter group name + user objects - Please enter a group name whose members to query: + User login name attribute @@ -2042,15 +2395,15 @@ The public key is used on client computers to authenticate incoming connection r - Group not found + Group member attribute - Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Group not found - Enter computer name + Could not find a group with the name "%1". Please check the group name or the group tree parameter. @@ -2058,55 +2411,51 @@ The public key is used on client computers to authenticate incoming connection r - Enter computer DN + Computer display name attribute - Please enter the DN of a computer whose MAC address to query: + Invalid hostname - computer MAC addresses + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - users - Brukere - - - user groups + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - computer groups + Computer hostname attribute - Please enter a user login name whose group memberships to query: + computer MAC addresses - groups of user + Computer MAC address attribute - User not found + computer locations - groups of computer + Computer location attribute - Computer not found + Location name attribute - Enter computer IP address - + users + Brukere - Please enter a computer IP address which to resolve to an computer object: + user groups @@ -2114,662 +2463,700 @@ The public key is used on client computers to authenticate incoming connection r datamaskiner - LDAP %1 test failed + computer groups - LDAP %1 test successful + computer containers - The %1 has been queried successfully and %2 entries were found. + groups of user - %1 %2 have been queried successfully: - -%3 + User not found - LDAP filter test failed + Could not find a user with the name "%1". Please check the username or the user tree parameter. - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 + groups of computer - LDAP filter test successful + Computer not found - %1 %2 have been queried successfully using the configured filter. + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - (only if different from group tree) + Hostname lookup failed - Computer group tree + Could not lookup hostname for IP address %1. Please check your DNS server settings. - computer group tree + location entries - Filter for computers + Computer groups filter - e.g. room or computerLab + Computer locations identification - Integration tests + Filter for computer groups - Computer groups + Invalid test value - e.g. name or description + An empty or invalid value has been supplied for this test. - Filter for computer containers + LDAP %1 test failed - Computer containers or OUs + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 - Connection security + LDAP %1 test successful - TLS certificate verification + The %1 has been queried successfully and %2 entries were found. - System defaults + LDAP test failed - Never (insecure!) + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 - Custom CA certificate file + and - None + LDAP test successful - TLS + %1 %2 have been queried successfully: + +%3 - SSL + LDAP filter test failed - e.g. (objectClass=computer) + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 - e.g. (objectClass=group) + LDAP filter test successful - e.g. (objectClass=person) + %1 %2 have been queried successfully using the configured filter. - e.g. (objectClass=room) or (objectClass=computerLab) + LDAP directory + + + LdapConfigurationPage - e.g. (objectClass=container) or (objectClass=organizationalUnit) + Basic settings - Could not query the configured base DN. Please check the base DN parameter. - -%1 - + General + Generelt - The LDAP base DN has been queried successfully. The following entries were found: - -%1 + LDAP server and port - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 + Bind DN - Certificate files (*.pem) + Bind password - Could not connect to the LDAP server. Please check the server parameters. - -%1 + Anonymous bind - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 + Use bind credentials - Encryption protocol + Base DN - Computer location attribute + Fixed base DN - Computer display name attribute + e.g. dc=example,dc=org - Location name attribute + Discover base DN by naming context - e.g. cn or displayName + e.g. namingContexts or defaultNamingContext - Computer locations identification + Environment settings - Identify computer locations (e.g. rooms) via: + Object trees - Location attribute in computer objects + Computer tree - List all entries of a location + e.g. OU=Groups - List all locations + User tree - Enter computer display name + e.g. OU=Users - Please enter a computer display name to query: + e.g. OU=Computers - Enter computer location name + Group tree - Please enter the name of a computer location (wildcards allowed): + Perform recursive search operations in object trees - computer locations + Object attributes - Enter location name + e.g. hwAddress - Please enter the name of a location whose entries to query: + e.g. member or memberUid - location entries + e.g. dNSHostName - LDAP test failed + Computer MAC address attribute - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 + Group member attribute - and + e.g. uid or sAMAccountName - LDAP test successful + Advanced settings - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 + Optional object filters - Browse + Filter for user groups - Test - Test + Filter for users + - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Filter for computer groups - Computer hostname attribute + Group member identification - Please enter a computer hostname to query: + Distinguished name (Samba/AD) - Invalid hostname + List all groups of a user - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + List all groups of a computer - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Get computer object by IP address - Could not find a user with the name "%1". Please check the username or the user tree parameter. + Enter username - Enter hostname + Please enter a user login name (wildcards allowed) which to query: - Please enter a computer hostname whose group memberships to query: + Enter group name - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Please enter a group name whose members to query: - Hostname lookup failed + Enter computer name - Could not lookup hostname for IP address %1. Please check your DNS server settings. + Enter computer DN - User login name attribute + Please enter the DN of a computer whose MAC address to query: - Configured attribute for user login name or computer hostname (OpenLDAP) + Please enter a user login name whose group memberships to query: - computer containers + Enter computer IP address - - - LdapPlugin - Auto-configure the base DN via naming context + Please enter a computer IP address which to resolve to an computer object: - Query objects from LDAP directory + (only if different from group tree) - Show help about command + Computer group tree - Commands for configuring and testing LDAP/AD integration + Filter for computers - Basic LDAP/AD support for Veyon + e.g. room or computerLab - %1 (load computers and locations from LDAP/AD) + Integration tests - %1 (load users and groups from LDAP/AD) + Computer groups - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + e.g. name or description - No naming context attribute name given - falling back to configured value. + Filter for computer containers - Could not query base DN. Please check your LDAP configuration. + Computer containers or OUs - Configuring %1 as base DN and disabling naming context queries. + Connection security - - - LdapProConfigurationPage - LDAP Pro + TLS certificate verification - Instances + System defaults - Enter name + Never (insecure!) - Please enter a name for the instance (can't be changed later!): + Custom CA certificate file - Remove instance + None - Do you really want to remove instance "%1"? + TLS - Configuration for instance "%1" + SSL - - - LdapProPlugin - Professional LDAP/AD integration for Veyon + e.g. (objectClass=computer) - %1 (load computers and locations from LDAP/AD) + e.g. (objectClass=group) - %1 (load users and groups from LDAP/AD) + e.g. (objectClass=person) - - - LicensingConfigurationPage - Licensing + e.g. (objectClass=room) or (objectClass=computerLab) - Installed licenses + e.g. (objectClass=container) or (objectClass=organizationalUnit) - Add new network range + Certificate files (*.pem) - Remove selected network range + Encryption protocol - ID + Computer location attribute - Feature + Computer display name attribute - Valid until + Location name attribute - Licensee + e.g. cn or displayName - Browse license file + Computer locations identification - Veyon license files (*.vlf) + Identify computer locations (e.g. rooms) via: - Remove license + Location attribute in computer objects - Do you really want to remove the selected license? + List all entries of a location - <N/A> + List all locations - Invalid license file + Enter computer display name - Could not open the license file for reading! + Please enter a computer display name to query: - The selected license file does not contain valid data. + Enter computer location name - The selected license file could not be verified. + Please enter the name of a computer location (wildcards allowed): - The selected license file is not valid for this installation. + Enter location name - The selected license file is expired. + Please enter the name of a location whose entries to query: - The license is already installed. + Browse - Information - + Test + Test - Installation ID + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - Addons available for licensing + Computer hostname attribute - Addon + Please enter a computer hostname to query: - - - LicensingPlugin - Show help for specific command + Enter hostname - Show all installed licenses + Please enter a computer hostname whose group memberships to query: - Add license file + User login name attribute - Remove installed license + Configured attribute for user login name or computer hostname (OpenLDAP) - -USAGE - -%1 add <LICENSE FILE> - - + Directory name - -USAGE - -%1 remove <LICENSE ID> - - + Query options - No certificate found with given ID + Query nested user groups (supported by AD only) - <N/A> + Query timeout - Licensing management - + ms + ms + + + + LdapNetworkObjectDirectoryConfigurationPage + + LDAP + LDAP - Commands for managing license keys + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. - LinuxPlatformConfigurationPage + LdapPlugin - Linux + Auto-configure the base DN via naming context - Custom PAM service for user authentication + Query objects from LDAP directory - User authentication + Show help about command - Session management + Commands for configuring and testing LDAP/AD integration - Display manager users + Basic LDAP/AD support for Veyon - - - LinuxPlatformPlugin - Plugin implementing abstract functions for the Linux platform + %1 (load computers and locations from LDAP/AD) - Plugin implementing specific functions for the Linux platform + %1 (load users and groups from LDAP/AD) - - - LocationDialog - Select location + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - enter search filter... + No naming context attribute name given - falling back to configured value. - - - MainToolBar - Configuration + Could not query base DN. Please check your LDAP configuration. - Disable balloon tooltips + Configuring %1 as base DN and disabling naming context queries. - Show icons only + Test binding to an LDAP server + + + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + + + + LDAP bind - MainWindow + LinuxPlatformConfigurationPage - MainWindow + Linux - toolBar + Custom PAM service for user authentication - General - Generelt + User authentication + - &File - &Fil + User sessions + - &Help - &Hjelp + Minimum session lifetime before server start + - &Quit - &Avslutt + User login + + + + Login key sequence + + + + + LinuxPlatformPlugin + + Plugin implementing abstract functions for the Linux platform + + + + + LocationDialog + + Select location + + + + enter search filter... + + + + + MainToolBar + + Configuration + + + + Show icons only + + + + Disable tooltips + + + + + MainWindow + + MainWindow + + + + toolBar + + + + General + Generelt + + + &File + &Fil + + + &Help + &Hjelp + + + &Quit + &Avslutt Ctrl+Q @@ -2791,10 +3178,6 @@ USAGE About Qt - - Authentication impossible - - Configuration not writable @@ -2855,10 +3238,6 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - - Access denied @@ -2876,983 +3255,1244 @@ USAGE - The feature "%1" is still active. Please stop it before closing %2. + The feature "%1" is still active. Please stop it before closing %2. + + + + Reset configuration + + + + Do you really want to reset the local configuration and revert all settings to their defaults? + + + + Search users and computers + + + + Align computers to grid + + + + %1 Configurator + + + + Insufficient privileges + + + + Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + + + + Only show powered on computers + + + + &Save settings to file + + + + &View + + + + &Standard + + + + &Advanced + + + + Use custom computer arrangement + + + + Locations && computers + + + + Authentication + + + + Adjust size of computer icons automatically + + + + Slideshow + + + + Spotlight + + + + Veyon Master + + + + Locations & computers + + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + + + + Load computer positions + + + + Save computer positions + + + + + MasterConfigurationPage + + Directories + + + + User configuration + + + + Feature on computer double click: + + + + Features + + + + All features + + + + Disabled features + + + + Screenshots + Skjermbilder + + + <no feature> + + + + Basic settings + + + + Behaviour + + + + Enforce selected mode for client computers + + + + Hide local computer + + + + Hide computer filter field + + + + Actions such as rebooting or powering down computers + + + + User interface + + + + Background color + + + + Thumbnail update interval + + + + ms + ms + + + Program start + + + + Modes and features + + + + User and computer name + + + + Only user name + + + + Only last part of user name + + + + Only computer name + + + + Computer thumbnail caption + + + + Text color + + + + Sort order + + + + Computer and user name + + + + Computer locations + + + + Show current location only + + + + Allow adding hidden locations manually + + + + Hide empty locations + + + + Show confirmation dialog for potentially unsafe actions + + + + Perform access control + + + + Automatically select current location + + + + Automatically open computer select panel + + + + Use modern user interface (experimental) + + + + Thumbnail spacing + + + + px + + + + Hide local session + + + + Auto + Auto + + + Thumbnail aspect ratio + + + + Automatically adjust computer icon size - Reset configuration + Open feature windows on the same screen as the main window - Do you really want to reset the local configuration and revert all settings to their defaults? + Configuration templates - Search users and computers + Image quality in monitoring mode - Adjust optimal size + Highest - Align computers to grid + High - %1 Configurator + Medium - Insufficient privileges + Low - Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + Lowest - Only show powered on computers + Remote access image quality - &Save settings to file + Advanced - &View + Computer name source - &Standard + Default - &Advanced + Host address - Use custom computer arrangement + Session client address - Locations && computers + Session client name - - - MasterConfigurationPage - Directories + Session host name - ... - ... + Session metadata + - User configuration + Full name of user - Feature on computer double click: + User login name - Features + Computer UID role - All features + Session meta data hash - Disabled features + Always expand all locations - Screenshots - Skjermbilder + Image quality + + + + MonitoringMode - <no feature> + Monitoring - Basic settings + Builtin monitoring mode - Behaviour + This mode allows you to monitor all computers at one or more locations. - Enforce selected mode for client computers + Query application version of the server - Hide local computer + Query active features - Hide computer filter field + Query properties of remotely available screens + + + NestedNetworkObjectDirectory - Actions such as rebooting or powering down computers + All directories + + + NetworkObjectDirectoryConfigurationPage - User interface + Update interval: - Background color - + seconds + sekunder + + + NetworkObjectDirectoryConfigurationPageTab - Thumbnail update interval + Enabled + + + NetworkObjectTreeModel - ms - ms + Locations/Computers + + + + OpenWebsiteDialog - Program start + Open website - Modes and features + e.g. Veyon - User and computer name + Remember and add to website menu - Only user name + e.g. www.veyon.io - Only computer name + Please enter the URL of the website to open: - Computer thumbnail caption + Name: - Text color + Website name + + + PluginCommands - Sort order + List names of all installed plugins - Computer and user name + Show table with details of all installed plugins - Computer locations - + Name + Navn - Show current location only + Description - Allow adding hidden locations manually + Version - Hide empty locations + UID - Show confirmation dialog for potentially unsafe actions + Plugin-related CLI operations - Perform access control + Commands for managing plugins + + + PowerControlFeaturePlugin - Automatically select current location + Power on - Automatically adjust computer thumbnail size + Click this button to power on all computers. This way you do not have to power on each computer by hand. - Automatically open computer select panel + Reboot - - - MonitoringMode - Monitoring + Click this button to reboot all computers. - Builtin monitoring mode + Power down - This mode allows you to monitor all computers at one or more locations. + Click this button to power down all computers. This way you do not have to power down each computer by hand. - - - NetworkDiscoveryConfigurationPage - Network discovery + Power on/down or reboot a computer - Mode + Confirm reboot - Scan network ranges + Confirm power down - e.g. 192.168.1.0/24 + Do you really want to reboot the selected computers? - Scan all subnets of computer + Power on a computer via Wake-on-LAN (WOL) - Scan custom subnet + MAC ADDRESS - Scan sessions on local computer + This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. - Test - Test + Please specify the command to display help for! + - Network ranges + Invalid MAC address specified! - Add new group + Commands for controlling power status of computers - Remove selected group + Power down now - Groups + Install updates and power down - First address + Power down after user confirmation - Last address + Power down after timeout - Add new network range + The computer was remotely requested to power down. Do you want to power down the computer now? - Remove selected network range + The computer will be powered down in %1 minutes, %2 seconds. + +Please save your work and close all programs. - Parallel scans + Do you really want to reboot <b>ALL</b> computers? - Scan timeout + Do you really want to power down <b>ALL</b> computers? - ms - ms + Do you really want to power down the selected computers? + + + + PowerDownTimeInputDialog - Session scan limit + Power down - Options + Please specify a timeout for powering down the selected computers: - Reverse lookup discovered IP addresses to host names + minutes - New location + seconds - NetworkDiscoveryDirectory + RemoteAccessFeaturePlugin - Scanning... + Remote view - Discovered computers + Open a remote view for a computer without interaction. - - - NetworkDiscoveryPlugin - Show help for specific command + Remote control - Scan a subnet + Open a remote control window for a computer. - -USAGE - -%1 scan [<SUBNET>] - - + Remote access - Network object directory which automatically discovers computers in the network + Remote view or control a computer - Network discovery (scan network for Veyon clients) + Show help about command - Commands for managing the network discovery directory + Exchange clipboard contents - - - NetworkObjectTreeModel - Locations/Computers + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: - OpenWebsiteDialog + RemoteAccessPage - Open website + Remote access: %1 + + + RemoteAccessWidget - e.g. Veyon + %1 - %2 Remote Access - Remember and add to website menu + %1 - %2 - %3 Remote Access + + + RemoteAccessWidgetToolBar - e.g. www.veyon.io + View only - Please enter the URL of the website to open: + Remote control - Name: + Send shortcut - - - PasswordDialog - Username + Fullscreen - Password + Window - Veyon Logon + Ctrl+Alt+Del - Authentication error + Ctrl+Esc - Logon failed with given username and password. Please try again! + Alt+Tab - Please enter your username and password in order to access computers. + Alt+F4 - - - PowerControlFeaturePlugin - Power on + Win+Tab - Click this button to power on all computers. This way you do not have to power on each computer by hand. + Win - Reboot + Menu - Click this button to reboot all computers. + Alt+Ctrl+F1 - Power down + Connected. - Click this button to power down all computers. This way you do not have to power down each computer by hand. + Screenshot - Power on/down or reboot a computer + Exit - Confirm reboot + Connecting... - Confirm power down + Select screen - Do you really want to reboot the selected computers? + All screens + + + ScreenLockFeaturePlugin - Do you really want to power down the selected computer? + Lock - Power on a computer via Wake-on-LAN (WOL) + Unlock - MAC ADDRESS + Lock screen and input devices of a computer - This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. - Please specify the command to display help for! + Lock input devices - Invalid MAC address specified! + Unlock input devices - Commands for controlling power status of computers + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + + Screenshot - Power down now + unknown - Install updates and power down + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. - Power down after user confirmation + Screenshot - Power down after timeout + Could not open screenshot file %1 for writing. + + + ScreenshotFeaturePlugin - The computer was remotely requested to power down. Do you want to power down the computer now? + Screenshot - The computer will be powered down in %1 minutes, %2 seconds. - -Please save your work and close all programs. + Use this function to take a screenshot of selected computers. - - - PowerDownTimeInputDialog - Power down + Screenshots taken - Please specify a timeout for powering down the selected computers: + Screenshot of %1 computer have been taken successfully. - minutes + Take screenshots of computers and save them locally. + + + ScreenshotManagementPage - seconds - + Screenshots + Skjermbilder - RemoteAccessFeaturePlugin + ScreenshotManagementPanel - Remote view + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. - Open a remote view for a computer without interaction. + User: - Remote control + Computer: - Open a remote control window for a computer. + Date: - Remote access + Time: - Remote view or control a computer + Show - Please enter the hostname or IP address of the computer to access: + Delete - Show help about command + Screenshot - - - RemoteAccessWidget - %1 - %2 Remote Access + Do you really want to delete all selected screenshots? - RemoteAccessWidgetToolBar - - View only - - + ServerAccessControlManager - Remote control + Requested authentication method not available - Send shortcut + Access allowed by rule "%1" - Fullscreen + Access denied by rule "%1" - Window + No rule allowed access - Ctrl+Alt+Del + Accessing user not member of an authorized user group - Ctrl+Esc + User has denied access - Alt+Tab + User confirmed access + + + ServiceConfigurationPage - Alt+F4 - + General + Generelt - Win+Tab + Autostart - Win + Hide tray icon - Menu + Start service - Alt+Ctrl+F1 + Stopped - Connecting %1 + Stop service - Connected. + State: - Screenshot + Enable firewall exception - Exit + Allow connections from localhost only - - - Routing - Control internet access by modifying routing table + VNC server - - - RoutingConfigurationWidget - Remove default routes to block internet access + Plugin: - Add custom route to block internet + Restart %1 Service - Destination + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - Gateway + Running - - - RunProgramDialog - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. - Run programs + Show notification on remote connection - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + Show notification when an unauthorized access is blocked - Name: + Maximum session count - Remember and add to program menu + Network port numbers - e.g. VLC + Veyon server - - - ScreenLockFeaturePlugin - Lock + Internal VNC server - Unlock + Feature manager - Lock screen and input devices of a computer - + Demo server + Demo server - To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + Miscellaneous network settings - - - Screenshot - unknown + Session mode - Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + Local session mode (single server instance for primary local session) - Screenshot + Active session mode (single server instance for active local or remote session) - - - ScreenshotFeaturePlugin - Screenshot + Multi session mode (distinct server instance for each local and remote desktop session) - Use this function to take a screenshot of selected computers. + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. - Screenshots taken + Miscellaneous settings - Screenshot of %1 computer have been taken successfully. + Disable clipboard synchronization - Take screenshots of computers and save them locally. + Session metadata - - - ScreenshotManagementPanel - All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + Content - User: + None - Computer: + Value of an environment variable - Date: + Value of a registry key - Time: + Environment variable name: - Show + Registry key name: - Delete + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) - ServiceConfigurationPage - - General - Generelt - - - Autostart - - - - Hide tray icon - - + ServiceControl - Start service + Service control - Stopped + Starting %1 - Stop service + Stopping %1 - State: + Restarting %1 - Network + Registering %1 - Demo server port + Unregistering %1 + + + ServiceControlCommands - Enable firewall exception + Register Veyon Service - Allow connections from localhost only + Unregister Veyon Service - Internal VNC server port + Start Veyon Service - VNC server + Stop Veyon Service - Plugin: + Restart Veyon Service - Restart %1 Service + Query status of Veyon Service - All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + Service is running - Running + Service is not running - Feature manager port + Configure and control Veyon service - Primary service port + Commands for configuring and controlling Veyon Service + + + ShellCommands - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. + Run command file - Show notification on remote connection + File "%1" does not exist! - Multi session mode (for terminal and remote desktop servers) + Interactive shell and script execution for Veyon CLI - Show notification when an unauthorized access is blocked + Commands for shell functionalities - ServiceControl + SlideshowPanel - Starting service %1 + Previous - Stopping service %1 + Start/pause - Registering service %1 + Next - Unregistering service %1 + Duration: - Service control + View in separate window - - - ServiceControlPlugin - Service is running + %1 Master – Slideshow + + + SpotlightPanel - Service is not running + Add selected computers - Configure and control Veyon service + Remove selected computers - Register Veyon Service + Update computers in realtime - Unregister Veyon Service + Spotlight - Start Veyon Service + Please select at least one computer to add. - Stop Veyon Service + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + StartAppDialog - Restart Veyon Service + Start application - Query status of Veyon Service + Please enter the applications to start on the selected computers. You can separate multiple applications by line. - Commands for configuring and controlling Veyon Service + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - - - ShellCommandLinePlugin - Run command file + Remember and add to application menu - File "%1" does not exist! + Application name - Interactive shell and script execution for Veyon Control + Name: - Commands for shell functionalities + e.g. VLC @@ -3892,7 +4532,7 @@ Typically this is required to support terminal servers. - Use the field below to type your message which will be sent to all selected users. + Please enter your message which send to all selected users. @@ -3941,22 +4581,38 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer + + Maximum CPU usage + + - UserConfig + UserLoginDialog - No write access + User login - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Please enter a username and password for automatic login on all computers. + + + + Username + + + + Password - UserSessionControl + UserSessionControlPlugin - User session control + Log in + + + + Click this button to log in a specific user on all computers. @@ -3975,6 +4631,14 @@ Typically this is required to support terminal servers. Do you really want to log off the selected users? + + User session control + + + + Do you really want to log off <b>ALL</b> users? + + VeyonCore @@ -4026,10 +4690,6 @@ Typically this is required to support terminal servers. ERROR - - licensed for - - USAGE @@ -4046,18 +4706,30 @@ Typically this is required to support terminal servers. WARNING + + Authentication test + + + + Screen %1 + + - VeyonServiceControl + VeyonMaster - Veyon Service + No write access + + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - VncView + VeyonServiceControl - Establishing connection to %1 ... + Veyon Service @@ -4106,6 +4778,30 @@ Typically this is required to support terminal servers. Use alternative user authentication mechanism + + User login + + + + Input start delay + + + + Simulated key presses interval + + + + Confirm legal notice (message displayed before user logs in) + + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4114,7 +4810,7 @@ Typically this is required to support terminal servers. - Plugin implementing specific functions for the Windows platform + Internal display @@ -4125,27 +4821,31 @@ Typically this is required to support terminal servers. - The service "%1" could not be installed. + The service "%1" has been installed successfully. + + + + The service "%1" has been uninstalled successfully. - The service "%1" has been installed successfully. + Service "%1" could not be found. - The service "%1" could not be uninstalled. + The service "%1" could not be installed (error %2). - The service "%1" has been uninstalled successfully. + Could not change the failure actions config for service "%1" (error %2). - The start type of service "%1" could not be changed. + The service "%1" could not be uninstalled (error %2). - Service "%1" could not be found. + The start type of service "%1" could not be changed (error %2). diff --git a/translations/pl.ts b/translations/veyon_pl.ts similarity index 61% rename from translations/pl.ts rename to translations/veyon_pl.ts index 42dfad9b4..6adbf6edd 100644 --- a/translations/pl.ts +++ b/translations/veyon_pl.ts @@ -1,9 +1,9 @@ - + AboutDialog About - O programie + Informacje Translation @@ -19,7 +19,7 @@ Contributors - Współpraca + Współtwórcy Version: @@ -33,24 +33,24 @@ Current language not translated yet (or native English). If you're interested in translating Veyon into your local or another language or want to improve an existing translation, please contact a Veyon developer! - Bieżący język nie jest jeszcze do końca przetłumaczony. + Bieżący język nie został jeszcze przetłumaczony (lub wybrano angielski). -Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące tłumaczenie, skontaktuj się z twórcami Veyon. +Jeśli chcesz przetłumaczyć Veyon na swój język lub chcesz poprawić obecne tłumaczenie, należy skontaktować się z twórcą Veyon! About %1 %2 - + Informacje o %1 %2 Support Veyon project with a donation - Wesprzyj projekt Veyon za pomocą dotacji + Przekaż dotację na projekt Veyon AccessControlPage Computer access control - + Kontrola dostępu do komputera Grant access to every authenticated user (default) @@ -62,15 +62,15 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t Process access control rules - + Użyj reguł kontroli dostępu User groups authorized for computer access - + Grupy użytkowników z uwierzytelnieniem dostępu do komputerów Please add the groups whose members should be authorized to access computers in your Veyon network. - + Dodaj grupy użytkowników z autoryzacją dostępu do komputerów w twojej sieci Veyon. Authorized user groups @@ -80,10 +80,6 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t All groups Wszystkie grupy - - ... - ... - Access control rules Reguły dostępu @@ -98,11 +94,11 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t Move selected rule down - Przesuń regułę niżej + Przenieś regułę niżej Move selected rule up - Przesuń regułę wyżej + Przenieś regułę wyżej Edit selected rule @@ -114,7 +110,7 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t Please enter a user login name whose access permissions to test: - + Wprowadź nazwę użytkownika, którego uprawnienia chcesz sprawdzić: Access allowed @@ -122,7 +118,7 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t The specified user is allowed to access computers with this configuration. - + Użytkownik ma dostęp do komputerów przy tej konfiguracji. Access denied @@ -130,7 +126,7 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t The specified user is not allowed to access computers with this configuration. - + Użytkownik nie ma dostępu do komputerów przy tej konfiguracji. Enable usage of domain groups @@ -138,18 +134,17 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t User groups backend: - - - - Missing user groups backend - + Zarządzanie grupami użytkowników: - No default user groups plugin was found. Please check your installation! - + Restrict access to members of specific user groups + Ogranicz dostęp do członków wybranych grup + + + AccessControlProvider - Restrict access to members of specific user groups + Provider for access control features @@ -173,39 +168,19 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t enter a description for the rule here - tutaj wprowadź opis reguły + wprowadź opis reguły Rule description: Opis reguły: - - Invert all conditions ("is/has" interpreted as "is/has not") - - Conditions Warunki - - is member of group - jest członkiem grupy - - - Accessing computer is localhost - - - - Accessing user is logged on user - - - - Accessing user is already connected - - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. - + eśli aktywowany jest więcej niż jeden warunek, każdy warunek musi zostać spełniony, aby reguła miała zastosowanie (logiczne AND). Jeśli tylko jeden z wielu warunków musi zostać spełniony (logiczne OR), proszę utwórz wiele reguł kontroli dostępu. Action @@ -229,38 +204,130 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t Accessing user - + Logujący się użytkownik Accessing computer + Łączący się komputer + + + Always process rule and ignore conditions + Zawsze stosuj regułę i ignoruj warunki + + + Accessing computer and local computer + Uzyskiwanie dostępu do komputera i komputera lokalnego + + + User being accessed + Użytkownik uzyskuje dostęp + + + is logged in locally + zalogowany lokalnie + + + is logged in remotely + zalogowany zdalnie + + + No user is logged in locally + Żaden użytkownik nie jest zalogowany lokalnie + + + One or multiple users are logged in locally + Jeden lub kliku użytkowników zalogowanych lokalnie + + + No user is logged in remotely + Żaden użytkownik nie jest zalogowany zdalnie + + + One or multiple users are logged in remotely + Jeden lub wielu użytkowników jest zalogowanych zdalnie + + + is located at + jest w + + + is not located at + nie jest w + + + are located at the same location + znajdują się w tym samym miejscu + + + are not located the same location - Local (logged on) user - Użytkownik lokalny (zalogowany) + is member of group + jest członkiem grupy - Local computer - Komputer lokalny + is not member of group + nie jest członkiem grupy - Always process rule and ignore conditions - Zawsze stosuj regułę i ignoruj warunki + is authenticated via + jest uwierzytelniany przez - No user logged on - Brak zalogowanych użytkowników. + is not authenticated via + - Accessing user has one or more groups in common with local (logged on) user + has one or more groups in common with user being accessed - Accessing computer and local computer are at the same location + has no groups in common with user being accessed - is located at + equals user being accessed + + + + is different from user being accessed + + + + is already connected + jest już podłączony + + + is not connected + nie jest połączony + + + is local computer + jest komputerem lokalnym + + + is not local computer + nie jest komputerem lokalnym + + + Computer being accessed + Dostęp do komputera + + + Session being accessed is a user session + Dostęp do sesji jest sesją użytkownika + + + Session being accessed is a login screen + Dostęp do sesji to ekran logowania + + + Local computer is already being accessed + + + + Local computer is not yet being accessed @@ -272,7 +339,7 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t Accessing user: - + Logujący się użytkownik: Local computer: @@ -280,11 +347,11 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t Accessing computer: - + Łączący się komputer: Please enter the following user and computer information in order to test the configured ruleset. - + Wprowadź następujące informacje o użytkowniku i komputerze, aby przetestować skonfigurowany zestaw reguł. Local user: @@ -296,52 +363,54 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t The access in the given scenario is allowed. - + Dostęp w danym scenariuszu jest dozwolony. The access in the given scenario is denied. - + Odmowa dostępu w danym scenariuszu. The access in the given scenario needs permission of the logged on user. - - - - ERROR: Unknown action - Błąd: nieznana akcja. + Dostęp w danym scenariuszu wymaga zgody zalogowanego użytkownika. Test result Wynik testu - - - AndroidPlatformConfigurationPage - Android - + Authentication method + Metoda uwierzytelnienia - General - Ogólne + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + Wprowadzenie + + + Please perform the following steps to set up key file authentication: + Wykonaj poniższe kroki w celu ustawienia pliku klucza uwierzytelniającego: - - - AuthKeysConfigurationPage - Authentication keys - Klucze uwierzytelniające + 1) Create a key pair on the master computer. + )1 Stwórz parę kluczy uwierzytelniających na głównym komputerze. - Introduction - + 2) Set an access group whose members should be allowed to access other computers. + 2) Utwórz grupę użytkowników którzy mają mieć dostęp do innych komputerów. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Wyeksportuj klucz publiczny i zaimportuj go na wszystkich komputerach klienckich z taką samą nazwą. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Więcej informacji można znaleźć w <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Podręczniku administratora Veyon</a>. Key file directories @@ -355,14 +424,20 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t Private key file base directory Katalog z plikami kluczy prywatnych - - ... - ... - Available authentication keys Dostępne klucze uwierzytelniające + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Para kluczy uwierzytelniających składa się z dwóch kluczy kryptograficznych, prywatnego i publicznego. +Klucz prywatny umożliwia użytkownikom komputera głównego dostęp do komputerów klienta. +Ważne jest, aby jedynie autoryzowani użytkownicy mogli odczytać plik klucza prywatnego. +Klucz publiczny jest używany na komputerach klienta do uwierzytelnienia połączeń przychodzących. + Create key pair Stwórz parę kluczy @@ -381,7 +456,7 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t Set access group - + Ustaw grupę dostępu Key files (*.pem) @@ -393,7 +468,7 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t Please enter the name of the user group or role for which to create an authentication key pair: - + Wprowadź nazwę grupy użytkowników lub roli, dla której chcesz utworzyć parę kluczy uwierzytelniających: Do you really want to delete authentication key "%1/%2"? @@ -403,10 +478,6 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t Please select a key to delete! Wybierz klucz do usunięcia! - - Please enter the name of the user group or role for which to import the authentication key: - - Please select a key to export! Wybierz klucz do wyeksportowania! @@ -420,30 +491,9 @@ Jeżeli chcesz pomóc w tłumaczeniu programu lub chcesz poprawić istniejące t Wybierz klucz do którego chcesz przydzielić dostęp dla grupy! - Please perform the following steps to set up key file authentication: - Wykonaj poniższe kroki w celu ustawienia pliku klucza uwierzytelniającego: - - - 1) Create a key pair on the master computer. - )1 Stwórz parę kluczy uwierzytelniających na głównym komputerze. - - - 2) Set an access group whose members should be allowed to access other computers. - 2) Utwórz grupę użytkowników którzy mają mieć dostęp do innych komputerów. - - - 3) Export the public key and import it on all client computers with the same name. - 3) Wyeksportuj klucz publiczny i zaimportuj go na wszystkich komputerach klienckich z taką samą nazwą. - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. @@ -459,7 +509,7 @@ The public key is used on client computers to authenticate incoming connection r Invalid key type specified! Please specify "%1" or "%2". - + Niepoprawny typ klucza! Proszę podać "%1" lub "%2". Specified key does not exist! Please use the "list" command to list all installed keys. @@ -467,11 +517,11 @@ The public key is used on client computers to authenticate incoming connection r One or more key files already exist! Please delete them using the "delete" command. - + Jeden lub więcej plików kluczy już istnieje! Usuń je za pomocą polecenia „usuń”. Creating new key pair for "%1" - + Stwórz nową parę kluczy uwierzytelniających dla "%1" Failed to create public or private key! @@ -479,31 +529,31 @@ The public key is used on client computers to authenticate incoming connection r Newly created key pair has been saved to "%1" and "%2". - + Nowa para kluczy uwierzytelniających została zapisana do "%1" i "%2". Could not remove key file "%1"! - + Nie można usunąć pliku klucza „%1”! Could not remove key file directory "%1"! - + Nie można usunąć katalogu plików kluczy „%1”! Failed to create directory for output file. - + Nie udało się utworzyć katalogu dla pliku wyjściowego. File "%1" already exists. - + Plik "%1" już istnieje. Failed to write output file. - + Nie udało się zapisać pliku wyjściowego. Key "%1/%2" has been exported to "%3" successfully. - + Klucz „%1 /%2” został pomyślnie wyeksportowany do „%3”. Failed read input file. @@ -511,11 +561,11 @@ The public key is used on client computers to authenticate incoming connection r File "%1" does not contain a valid private key! - + Plik „%1” nie zawiera poprawnego klucza prywatnego! File "%1" does not contain a valid public key! - + Plik „%1” nie zawiera poprawnego klucza publicznego! Failed to create directory for key file. @@ -563,7 +613,7 @@ The public key is used on client computers to authenticate incoming connection r Failed to set owner of key file "%1" to "%2". - + Nie można zamienić właściciela pliku kluczy „%1” na „%2”. Failed to set permissions for key file "%1". @@ -618,15 +668,15 @@ The public key is used on client computers to authenticate incoming connection r ACCESS GROUP - + GRUPA DOSTĘPU This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. - + To polecenie dostosowuje uprawnienia dostępu do <KEY>w taki sposób, że tylko grupa <ACCESS GROUP> ma do niego dostęp do odczytu. NAME - + NAZWA FILE @@ -634,19 +684,15 @@ The public key is used on client computers to authenticate incoming connection r This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - + To polecenie eksportuje klucz uwierzytelniający <KEY> do <FILE>. Jeśli <FILE>nie zostanie określony, nazwa zostanie utworzona na podstawie nazwy i typu <KEY>. This command imports the authentication key <KEY> from <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - + To polecenie importuje klucz uwierzytelniający <KEY> z <FILE>. Jeśli <FILE>nie zostanie określony, nazwa <KEY> zostanie utworzona na podstawie nazwy i typu. This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - - - - Please specify the command to display help for! - + To polecenie wyświetla listę wszystkich dostępnych kluczy uwierzytelniania w katalogu kluczy. Jeśli podano opcję „%1”, zamiast niej zostanie wyświetlona tabela ze szczegółami klucza. Niektórych szczegółów może brakować, jeśli klucz nie jest dostępny, np. z powodu braku uprawnień do odczytu. TYPE @@ -654,11 +700,7 @@ The public key is used on client computers to authenticate incoming connection r PAIR ID - - - - Command line support for managing authentication keys - + PAIR ID Commands for managing authentication keys @@ -666,14 +708,38 @@ The public key is used on client computers to authenticate incoming connection r This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. - + To polecenie tworzy nową parę kluczy uwierzytelniających z nazwą <NAME>i zapisuje klucz prywatny i publiczny w skonfigurowanych katalogach kluczy. Parametr musi być nazwą klucza, która może zawierać tylko litery. This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. - + To polecenie usuwa klucz uwierzytelniający <KEY>ze skonfigurowanego katalogu kluczy. Pamiętaj, że klucza nie można odzyskać po jego usunięciu. This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + To polecenie wyodrębnia część klucza publicznego z klucza prywatnego <KEY> i zapisuje ją jako odpowiedni klucz publiczny. Dlatego podczas konfigurowania innego komputera głównego wystarczy przesłać tylko klucz prywatny. Następnie można wyodrębnić klucz publiczny. + + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + Pliki kluczy uwierzytelniania nie są poprawnie skonfigurowane na tym komputerze. Utwórz nowe pliki kluczy lub przejdź na inną metodę uwierzytelniania za pomocą Konfiguratora Veyon. + + + Key file authentication + Uwierzytelnienie z użyciem klucza + + + Key file + Plik z kluczem + + + Please specify the key name (e.g. "teacher/public") as the first argument. + Proszę wybrać nazwę klucza (np. "nauczyciel/publiczny") jako pierwszy argument + + + Please specify the command to display help for. + Podaj polecenie, dla którego chcesz wyświetlić pomoc. + + + The specified command does not exist or no help is available for it. @@ -689,69 +755,212 @@ The public key is used on client computers to authenticate incoming connection r Access group - + Grupa dostępu Pair ID - + Pair ID - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - Komputery + General + Ogólne - Name - Nazwa + Username to bind DN mapping: + - Host address/IP - adres hosta/IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + np.: %username%@DOMAIN lub cn=%username%,ou=users,dc=example,dc=org + + + AuthLdapDialog - MAC address - Adres MAC + Veyon Logon + Logowanie Veyon - Add new computer - Dodaj nowy komputer + Please enter your domain/LDAP username and password in order to access computers. + Wprowadź nazwę użytkownika i hasło domeny/LDAP, aby uzyskać dostęp do komputerów. - Remove selected computer - Usuń wybrany komputer + Username + Nazwa użytkownika - New computer - Nowy komputer + Password + Hasło - Builtin directory - + Authentication error + Błąd uwierzytelnienia - Locations & computers - + Logon failed with given username and password. Please try again! + Nie można się zalogować z użytym loginem i hasłem. Spróbuj ponownie! + + + + AuthLogonDialog + + Veyon Logon + Logowanie Veyon + + + Please enter your username and password in order to access computers. + Aby uzyskać dostęp do komputerów wprowadź nazwę użytkownika i hasło. + + + Username + Nazwa użytkownika + + + Password + Hasło + + + Authentication error + Błąd uwierzytelnienia + + + Logon failed with given username and password. Please try again! + Nie można się zalogować z użytym loginem i hasłem. Spróbuj ponownie! + + + + AuthLogonPlugin + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Podana nazwa użytkownika lub hasło jest nieprawidłowe. Wprowadź prawidłowe dane uwierzytelniające lub przejdź na inną metodę uwierzytelniania za pomocą Konfiguratora Veyon. + + + Logon authentication + Uwierzytelnienie z użyciem loginu + + + Logon + Zaloguj się + + + + AuthSimpleDialog + + Veyon Logon + Logowanie Veyon + + + Please enter the Veyon password: + Wprowadź hasło Veyon: + + + Authentication error + Błąd uwierzytelnienia + + + Logon failed with given password. Please try again! + Logowanie nie powiodło się z podanym hasłem. Proszę spróbuj ponownie! + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + Podane hasło jest nieprawidłowe. Wprowadź poprawnie hasło lub przejdź do innej metody uwierzytelniania za pomocą Konfiguratora Veyon. + + + Simple password authentication + Proste uwierzytelnianie hasłem + + + Simple password + Proste hasło + + + + AuthenticationPage + + Authentication is set up properly on this computer. + Uwierzytelnianie jest poprawnie skonfigurowane na tym komputerze. + + + + AuthenticationPageTab + + Enabled + Włączony + + + Test + Test + + + + BuiltinDirectoryConfiguration + + Builtin directory + Wbudowany katalog + + + + BuiltinDirectoryConfigurationPage + + Computers + Komputery + + + Name + Nazwa + + + Host address/IP + adres hosta/IP + + + MAC address + Adres MAC + + + Add new computer + Dodaj nowy komputer + + + Remove selected computer + Usuń wybrany komputer + + + New computer + Nowy komputer + + + Builtin directory + Wbudowany katalog Locations - + Sale Add new location - + Dodaj nową salę Remove selected location - + Usuń wybraną lokalizację - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - + New location + Nowa lokalizacja - New location + Directory name + Nazwa katalogu + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. @@ -767,11 +976,11 @@ The public key is used on client computers to authenticate incoming connection r Export objects to given file - Eksportuj obiekty do wskazanego pliku + Eksportuj obiekty do pliku Invalid type specified. Valid values are "%1" or "%2". - + Podano nieprawidłowy typ. Prawidłowe wartości to „%1” lub „%2”. Type @@ -807,11 +1016,11 @@ The public key is used on client computers to authenticate incoming connection r Computer "%1" (host address: "%2" MAC address: "%3") - Komputer %1 (adres hosta: %2 adres MAC: %3) + Komputer "%1" (adres hosta: "%2" adres MAC: "%3") Unclassified object "%1" with ID "%2" - + Nieklasyfikowany obiekt „%1” o identyfikatorze „%2" None @@ -831,19 +1040,19 @@ The public key is used on client computers to authenticate incoming connection r Error while parsing line %1. - + Błąd podczas analizowania linii %1. Network object directory which stores objects in local configuration - + Katalog obiektów sieciowych przechowujący obiekty w konfiguracji lokalnej Commands for managing the builtin network object directory - + Polecenia do zarządzania wbudowanym katalogiem obiektów sieciowych No format string or regular expression specified! - + Nie podano prawidłowego ciągu ani wyrażenia! Can't open file "%1" for writing! @@ -851,47 +1060,47 @@ The public key is used on client computers to authenticate incoming connection r No format string specified! - + Nie podano prawidłowego ciągu! Object UUID - + UUID Objektu Parent UUID - + Nadrzędny UUID Add a location or computer - + Dodaj lokalizację lub komputer Clear all locations and computers - + Wyczyść wszystkie lokalizacje i komputery Dump all or individual locations and computers - + Zrzuć wszystkie lub pojedyncze lokalizacje i komputery List all locations and computers - + Wyświetl wszystkie lokalizacje i komputery Remove a location or computer - + Usuń lokalizację lub komputer Location "%1" - + Lokalizacja "%1" Builtin (computers and locations in local configuration) - + Wbudowane (komputery i lokalizacje w konfiguracji lokalnej) Location - + Lokalizacja FILE @@ -899,47 +1108,47 @@ The public key is used on client computers to authenticate incoming connection r LOCATION - + LOKALIZACJA FORMAT-STRING-WITH-PLACEHOLDERS - + FORMAT-STRING-WITH-PLACEHOLDERS REGULAR-EXPRESSION-WITH-PLACEHOLDER - + REGULAR-EXPRESSION-WITH-PLACEHOLDER Imports objects from the specified text file using the given format string or regular expression containing one or multiple placeholders. Valid placeholders are: %1 - + Importuje obiekty z określonego pliku tekstowego przy użyciu podanego ciągu lub wyrażenia zawierającego jeden lub wiele symboli zastępczych. Prawidłowe symbole zastępcze to: %1 Import simple CSV file to a single room - + Zaimportuj plik CSV Import CSV file with location name in first column - + Zaimportuj plik CSV z nazwą lokalizacji w pierwszej kolumnie Import text file with with key/value pairs using regular expressions - + Zaimportuj plik tekstowy z parami klucz / wartość za pomocą wyrażeń regularnych Import arbitrarily formatted data - + Importuj dowolnie sformatowane dane Exports objects to the specified text file using the given format string containing one or multiple placeholders. Valid placeholders are: %1 - + Eksportuje obiekty do określonego pliku tekstowego przy użyciu ciągu formatu podanego zawierającego jeden lub wiele symboli zastępczych. Prawidłowe symbole zastępcze to: %1 Export all objects to a CSV file - + Wyeksportuj wszystkie obiekty do pliku CSV Export all computers in a specific location to a CSV file - + Wyeksportuj wszystkie komputery w określonej lokalizacji do pliku CSV TYPE @@ -947,54 +1156,62 @@ The public key is used on client computers to authenticate incoming connection r NAME - + NAZWA PARENT - + NADRZĘDNY Adds an object where %1 can be one of "%2" or "%3". %4 can be specified by name or UUID. - + Dodaje obiekt, w którym %1 może być jednym z „%2” lub „%3”. %4 można określić według nazwy lub UUID. Add a room - + Dodaj salę Add a computer to room %1 - + Dodaj komputer do sali %1 OBJECT - + OBJEKT Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. - + Usuwa określony obiekt z katalogu. %1 można określić według nazwy lub UUID. Usunięcie lokalizacji spowoduje również usunięcie wszystkich powiązanych komputerów. Remove a computer by name - + Usuń komputer według nazwy Remove an object by UUID - + Usuń obiekt za pomocą UUID "Room 01" - + "Sala 01" "Computer 01" - + "Komputer 01" HOST ADDRESS - + ADRES HOSTA MAC ADDRESS + ADRES MAC + + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. @@ -1014,10 +1231,6 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - Host/adres IP: %1 - Active features: %1 Aktywne funkcje: %1 @@ -1034,10 +1247,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off Komputer nie połączony z siecią lub wyłączony - - Service unreachable or not running - Usługa jest niedostępna lub nie uruchomiona - Authentication failed or access denied Uwierzytelnienie nie powiodło się lub dostęp jest zabroniony @@ -1056,6 +1265,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 + Lokalizacja: %1 + + + [no user] + [no user] + + + Veyon Server unreachable or not running + Serwer Veyon nieosiagalny lub nie uruchomiony + + + Name: %1 + + + + Hostname: %1 + + + + unknown + nieznane + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active @@ -1063,7 +1304,7 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlServer %1 Service %2 at %3:%4 - + %1 Usługa %2 w %3:%4 Authentication error @@ -1075,19 +1316,30 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" is now accessing this computer. - + Użytkownik „%1” na hoście „%2” uzyskuje teraz dostęp do tego komputera. User "%1" at host "%2" attempted to access this computer but could not authenticate successfully. - + Użytkownik „%1” na hoście „%2” próbował uzyskać dostęp do tego komputera, ale nie mógł się pomyślnie uwierzytelnić. Access control error - + Błąd kontroli dostępu User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. - + Użytkownik „%1” na hoście „%2” próbował uzyskać dostęp do tego komputera, ale został zablokowany z powodu ustawień kontroli dostępu. + + + Active connections: + Aktywne połączenia: + + + + ComputerGroupSelector + + Group %1 + Grupa %1 @@ -1098,38 +1350,73 @@ The public key is used on client computers to authenticate incoming connection r Missing network object directory plugin - + Brak wtyczki katalogu obiektów sieciowych No default network object directory plugin was found. Please check your installation or configure a different network object directory backend via %1 Configurator. - + Nie znaleziono domyślnej wtyczki katalogu obiektów sieciowych. Sprawdź swoją instalację lub skonfiguruj inny backend katalogu obiektów sieciowych za pomocą Konfiguratora %1. Location detection failed - + Wykrywanie lokalizacji nie powiodło się Computer name;Hostname;User - + Nazwa komputera; Nazwa Hosta; Użytkownik Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + Nie można określić lokalizacji tego komputera. Wskazuje to na problem z konfiguracją systemu. W panelu wyboru komputera pokazane zostaną wszystkie lokalizacje. + + + Logged in since + + + + %1 days + + + + 1 day - ComputerSelectPanel + ComputerMonitoring - Computer management - Zarządzanie komputerem + Computers + Komputery + + + Search users and computers + Wyszukaj użytkowników i komputery + + + Select all + Zaznacz wszystko + + Unselect all + Odznacz wszystko + + + Add to group + Dodaj do grupy + + + Remove from group + Usuń z grupy + + + + ComputerSelectPanel Computer search Znajdź komputer Add location - + Dodaj lokalizację Save computer/user list @@ -1151,103 +1438,111 @@ The public key is used on client computers to authenticate incoming connection r Could not write the computer and users list to %1! Please check the file access permissions. Nie można zapisać listy komputerów i użytkowników w %1! Sprawdź prawa dostępu do pliku + + Search computers + Wyszukiwanie komputerów + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. - Wskaż istniejący plik konfiguracyjny w celu zaimportowania. + Clear system-wide Veyon configuration + Wyczyść konfigurację programu Veyon - Please specify a valid filename for the configuration export. - Wskaż nazwę wyeksportowanego pliku konfiguracyjnego. + List all configuration keys and values + Wyświetl wszystkie klucze konfiguracyjne i wartości - Please specify a valid key. - Wskaż poprawny klucz + Import configuration from given file + Zaimportuj konfiguracje z podanego pliku - Specified key does not exist in current configuration! - Wskazany klucz nie istnieje w bieżącej konfiguracji! + Export configuration to given file + Wyeksportuj konfiguracje do podanego pliku - Please specify a valid value. - Proszę wpisać prawidłową wartość. + Read and output configuration value for given key + Odczyt i wyjście wartości konfiguracji dla danego klucza - Configure Veyon at command line - Konfiguruj Veyon za pomocą wiersza polecenia + Write given value to given configuration key + Zapisz podaną wartość do podanego klucza konfiguracji - Output file is not writable! - Plik wyjściowy nie ma uprawnień zapisu! + Unset (remove) given configuration key + Odznacz (usuń) dany klucz konfiguracji - Output directory is not writable! - Lokalizacja wyjściowa nie ma uprawnień zapisu! - + Upgrade and save configuration of program and plugins + Aktualizuj i zapisz konfigurację programu i rozszerzeń + + + Please specify an existing configuration file to import. + Wskaż istniejący plik konfiguracyjny w celu zaimportowania. + Configuration file is not readable! Plik konfiguracyjny nie nadaje się do odczytu! - Clear system-wide Veyon configuration - Wyczyść konfigurację programu Veyon + Please specify a valid filename for the configuration export. + Wskaż nazwę wyeksportowanego pliku konfiguracyjnego. - List all configuration keys and values - Wyświetl wszystkie klucze konfiguracyjne i wartości + Output file is not writable! + Plik wyjściowy nie ma uprawnień zapisu! - Import configuration from given file - Zaimportuj konfiguracje z podanego pliku + Output directory is not writable! + Lokalizacja wyjściowa nie ma uprawnień zapisu! - Export configuration to given file - Wyeksportuj konfiguracje do podanego pliku + Please specify a valid key. + Wskaż poprawny klucz - Read and output configuration value for given key - + Specified key does not exist in current configuration! + Wskazany klucz nie istnieje w bieżącej konfiguracji! - Write given value to given configuration key - + Please specify a valid value. + Proszę wpisać prawidłową wartość. - Unset (remove) given configuration key - + Configure Veyon at command line + Konfiguruj Veyon za pomocą wiersza polecenia Commands for managing the configuration of Veyon Komendy do zarządzania konfiguracją programu Veyon - - Upgrade and save configuration of program and plugins - Aktualizuj i zapisz konfigurację programu i rozszerzeń - ConfigurationManager Could not modify the autostart property for the %1 Service. - + Nie można zmodyfikować właściwości autostartu dla usługi %1. Could not configure the firewall configuration for the %1 Server. - + Nie można ustawić konfiguracji zapory dla serwera %1. Could not configure the firewall configuration for the %1 Worker. - + Nie można ustawić konfiguracji zapory sieciowej dla stacji %1. Configuration is not writable. Please check your permissions! - + Nie można zapisać konfiguracji. Sprawdź swoje uprawnienia! Could not apply platform-specific configuration settings. - + Nie można zastosować ustawień konfiguracji specyficznych dla platformy. + + + Could not configure the firewall configuration for the %1 Service. + Nie można ustawić konfiguracji zapory dla usługi %1. @@ -1265,7 +1560,7 @@ The public key is used on client computers to authenticate incoming connection r Tunables - + Dostrajalne ms @@ -1273,16 +1568,12 @@ The public key is used on client computers to authenticate incoming connection r Key frame interval - + Interwał między klatkami Memory limit Limit pamięci - - Use multithreading (experimental) - Użyj wielowątkowości (eksperymentalne) - MB MB @@ -1297,49 +1588,97 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running + Spowalniaj aktualizacje miniatur podczas działania wersji demonstracyjnej + + + Bandwidth limit - - - DemoFeaturePlugin - Fullscreen demo + MB/s + + + DemoFeaturePlugin Stop demo - + Zakończ demonstrację Window demo - + Demonstracja w trybie okienkowym Give a demonstration by screen broadcasting - + Transmituj demonstrację na ekran - Demo server - Serwer demo + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + W tym trybie twój ekran jest wyświetlany w oknie na wszystkich komputerach. Użytkownicy mogą się przełączać między oknami. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - W tym trybie twój ekran jest wyświetlany w trybie pełnoekranowym na wszystkich komputerach. Urządzenia wejścia użytkowników są zablokowane. + Demo + Demo - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - W tym trybie twój ekran jest wyświetlany w oknie na wszystkich komputerach. Użytkownicy mogą się przełączać między oknami. + Share your screen or allow a user to share his screen with other users. + Udostępnij swój ekran lub zezwól użytkownikowi na udostępnienie jego ekranu innym użytkownikom. + + + Full screen demo + Demo pełnoekranowe + + + Share your own screen in fullscreen mode + Udostępnij swój ekran w trybie pełnoekranowym + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + W tym trybie ekran jest wyświetlany w trybie pełnoekranowym na wszystkich komputerach, podczas gdy urządzenia wejściowe użytkowników są zablokowane. + + + Share your own screen in a window + Udostępnij swój ekran w oknie + + + Share selected user's screen in fullscreen mode + Udostępnij ekran wybranego użytkownika w trybie pełnoekranowym + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + W tym trybie ekran wybranego użytkownika jest wyświetlany w trybie pełnoekranowym na wszystkich komputerach, podczas gdy urządzenia wejściowe użytkowników są zablokowane. + + + Share selected user's screen in a window + Udostępnij ekran wybranego użytkownika w oknie + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + W tym trybie ekran wybranego użytkownika jest wyświetlany w oknie na wszystkich komputerach. Użytkownicy mogą w razie potrzeby przełączać się do innych okien. + + + Please select a user screen to share. + Wybierz ekran użytkownika do udostępnienia. + + + Please select only one user screen to share. + Wybierz tylko jeden ekran użytkownika do udostępnienia. + + + All screens + Wszystkie ekrany DesktopAccessDialog Desktop access dialog - + Okno dialogowe dostępu do pulpitu Confirm desktop access - + Potwierdź dostęp do pulpitu Never for this session @@ -1356,14 +1695,6 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - - Programs & websites - Programy i strony internetowe - - - Predefined programs - Predefiniowane programy - Name Nazwa @@ -1372,14 +1703,6 @@ The public key is used on client computers to authenticate incoming connection r Path Ścieżka - - Add new program - Dodaj nowy program - - - Remove selected program - Usuń wybrane programy - Predefined websites Predefiniowane strony @@ -1392,21 +1715,37 @@ The public key is used on client computers to authenticate incoming connection r URL Adres - - New program - Nowy program - New website Nowa strona + + Applications & websites + Aplikacje i strony internetowe + + + Predefined applications + + + + Add new application + Dodaj nową aplikacje + + + Remove selected application + Usuń wybraną aplikację + + + Add new website + Dodaj nową stronę + + + New application + Nowa aplikacja + DesktopServicesFeaturePlugin - - Run program - Uruchom program - Open website Otwórz stronę WWW @@ -1416,28 +1755,32 @@ The public key is used on client computers to authenticate incoming connection r Przyciśnij ten przycisk żeby otworzyć stronę WWW na wszystkich komputerach - Start programs and services in user desktop - + Open website "%1" + Otwórz stronę "%1" - Click this button to run a program on all computers. - Przyciśnij ten przycisk żeby uruchomić program na wszystkich komputerach + Custom website + Inna strona - Run program "%1" - Uruchom program "%1" + Start application + Uruchom aplikację - Custom program - Inny program + Click this button to start an application on all computers. + - Open website "%1" - Otwórz stronę "%1" + Start application "%1" + - Custom website - Inna strona + Custom application + + + + Start apps and open websites in user sessions + Uruchamiaj aplikacje i otwieraj strony internetowe w sesjach użytkownika @@ -1448,11 +1791,11 @@ The public key is used on client computers to authenticate incoming connection r Room %1 - + Sala %1 Please complete all tasks within the next 5 minutes. - + Zakończ wszystkie zadania w ciągu najbliższych 5 minut. Custom website @@ -1460,26 +1803,30 @@ The public key is used on client computers to authenticate incoming connection r Open file manager - + Otwórz menedżera plików Start learning tool - + Uruchom narzędzie do nauki Play tutorial video - - - - Custom program - Inny program + Odtwórz film instruktażowy Handout - + Materiały informacyjne Texts to read + Teksty do przeczytania + + + generic-student-user + generic-student-user + + + Custom application @@ -1506,501 +1853,506 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands - Feature control - Zarządzanie funkcjami + List names of all available features + - - - FileTransferController - Could not open file "%1" for reading! Please check your permissions! + Show table with details of all available features - - - FileTransferDialog - File transfer + Start a feature on a remote host - Options + Stop a feature on a remote host - Transfer only - + Please specify the command to display help for. + Podaj polecenie, dla którego chcesz wyświetlić pomoc. - Transfer and open file(s) with associated program - + Displays a list with the names of all available features. + Wyświetla listę z nazwami wszystkich dostępnych funkcji. - Transfer and open destination folder - + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + Wyświetla tabelę ze szczegółowymi informacjami o wszystkich dostępnych funkcjach. Informacje te obejmują opis, identyfikator UID, nazwę wtyczki zapewniającej odpowiednią funkcję oraz kilka innych szczegółów związanych z implementacją. - Files - + HOST ADDRESS + ADRES HOSTA - Start + FEATURE - Overwrite existing files + ARGUMENTS - - - FileTransferPlugin - File transfer - + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + Uruchamia określoną funkcję na określonym hoście, łącząc się ze zdalnie uruchomionym serwerem Veyon Server. Funkcja może być określona przez nazwę lub UID. Użyj polecenia ``show``, aby zobaczyć wszystkie dostępne funkcje. W zależności od funkcji należy określić dodatkowe argumenty (takie jak wiadomość tekstowa do wyświetlenia) zakodowane jako pojedynczy ciąg JSON. Więcej informacji można znaleźć w dokumentacji deweloperskiej - Click this button to transfer files from your computer to all computers. - + Lock the screen + Zablokuj ekran - Select one or more files to transfer - + Display a text message + Wyświetl wiadomość tekstową - Transfer files to remote computer - + Test message + Wiadomość testowa - Received file "%1". + Start an application - Could not receive file "%1" as it already exists. + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. - Could not receive file "%1" as it could not be opened for writing! - + Unlock the screen + Odblokuj ekran - - - GeneralConfigurationPage - User interface - Interfejs użytkownika: + The specified command does not exist or no help is available for it. + - Language: - Język: + Name + Nazwa - Use system language setting - Użyj systemowych ustawień językowych + Description + Opis - Veyon - Veyon + Master + Master - Logging - Logowanie + Service + Usługa - Log file directory - Katalog plików dziennika logowania + Worker + - ... - ... + UID + Identyfikator użytkownika - Log level - Poziom logowania + Plugin + Dodatki - Nothing - Nic + Invalid feature name or UID specified + - Only critical messages - Tylko komunikaty o błędach krytycznych + Error parsing the JSON-encoded arguments: %1 + - Errors and critical messages - Błędy i komunikaty o błędach krytycznych + Failed to initialize credentials + - Warnings and errors - Ostrzeżenia i błedy + Could not establish a connection to host %1 + - Information, warnings and errors - Informacje, ostrzeżenia i błędy + Failed to send feature control message to host %1 + - Debug messages and everything else - Komunikaty debugowania i wszystkie pozostałe + Feature-related CLI operations + - Limit log file size - Ogranicz rozmiar pliku dziennika + Commands for controlling features + + + + FileTransferConfigurationPage - Clear all log files - Wyczyść wszystkie pliki dzienników + File transfer + Transfer plików - Log to standard error output - + Directories + Lokalizacje - Network object directory - Adres obiektu sieciowego + Destination directory + Katalog docelowy - Backend: - + Default source directory + Domyślny katalog źródłowy - Update interval: - Interwał odświeżania: + Options + Opcje - %1 service - Usługa %1 + Remember last source directory + Zapamiętaj ostatni katalog źródłowy - The %1 service needs to be stopped temporarily in order to remove the log files. Continue? - Usługa %1 musi zostać zatrzymana w celu usunięcia plików dziennika. Kontynuować? + Create destination directory if it does not exist + Utwórz katalog docelowy jeśli nie istnieje + + + FileTransferController - Log files cleared - Pliki dziennika zostały usunięte + Could not open file "%1" for reading! Please check your permissions! + Nie można otworzyć pliku „%1”! Sprawdź uprawnienia! + + + FileTransferDialog - All log files were cleared successfully. - Wszystkie pliki dziennika zostały pomyślnie usunięte. + File transfer + Transfer plików - Error - Błąd + Options + Opcje - Could not remove all log files. - Nie można usunąć wszystkich plików dziennika. + Transfer only + Tylko wyślij - MB - MB + Transfer and open file(s) with associated program + Wyślij plik(i) i otwórz za pomocą skojarzonego programu - Rotate log files - + Transfer and open destination folder + Wyślij plik i otwórz folder docelowy - x - x + Files + Pliki - seconds - sekundy + Start + Uruchom - Write to logging system of operating system - + Overwrite existing files + Nadpisz istniejące pliki + + + FileTransferFileDialog - Authentication - Uwierzytelnienie + Select one or more files to transfer + Wybierz jeden lub więcej plików do przesłania + + + FileTransferPlugin - Method: - Metoda: + File transfer + Transfer plików - Logon authentication - Uwierzytelnienie z użyciem loginu + Click this button to transfer files from your computer to all computers. + Kliknij ten przycisk, aby przesłać pliki z twojego komputera na wszystkie komputery. - Key file authentication - Uwierzytelnienie z użyciem klucza + Select one or more files to transfer + Wybierz jeden lub więcej plików do przesłania - Test - Test + Transfer files to remote computer + Prześlij pliki na komputer zdalny - Authentication is set up properly on this computer. - + Received file "%1". + Odebrano plik „%1”. - Authentication keys are not set up properly on this computer. - + Could not receive file "%1" as it already exists. + Nie można odebrać pliku „%1”, ponieważ już istnieje. - Authentication test - + Could not receive file "%1" as it could not be opened for writing! + Nie można odebrać pliku „%1”, ponieważ nie można go otworzyć do zapisu! - InternetAccessControlConfigurationPage - - Internet access control - Kontrola dostępu do internetu - - - Backend: - - - - General settings - - + GeneralConfigurationPage - Backend settings - + User interface + Interfejs użytkownika: - - - InternetAccessControlPlugin - Block access to the internet - Zablokuj dostęp do internetu + Language: + Język: - Allow access to the internet - Zezwól na dostęp do internetu + Use system language setting + Użyj systemowych ustawień językowych - Show help about command - Pokaż pomoc dotyczącą komendy + Veyon + Veyon - Block internet - Zablokuj internet + Logging + Logowanie - Click this button to block access to the internet. - Naciśnij ten przycisk żeby zablokować dostęp do internetu + Log file directory + Katalog plików dziennika logowania - Unblock internet - Odblokuj internet + Log level + Poziom logowania - Click this button to allow access to the internet. - Naciśnij ten przycisk żeby zezwolić na dostęp do internetu + Nothing + Nic - Control access to the internet - Kontroluj dostęp do internetu + Only critical messages + Tylko komunikaty o błędach krytycznych - Commands for controlling access to the internet - Komendy do zarządzania dostępem do internetu + Errors and critical messages + Błędy i komunikaty o błędach krytycznych - - - LdapBrowseDialog - Browse LDAP - + Warnings and errors + Ostrzeżenia i błedy - - - LdapClient - LDAP error description: %1 - + Information, warnings and errors + Informacje, ostrzeżenia i błędy - - - LdapConfigurationPage - Basic settings - Ustawienia podstawowe + Debug messages and everything else + Komunikaty debugowania i wszystkie pozostałe - General - Ogólne + Limit log file size + Ogranicz rozmiar pliku dziennika - LDAP server and port - Serwer LDAP i port + Clear all log files + Wyczyść wszystkie pliki dzienników - Bind DN - Wskaż nazwę domeny + Log to standard error output + Loguj do standardowego wyjścia błędów - Bind password - wskaż hasło + %1 service + Usługa %1 - Anonymous bind - + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + Usługa %1 musi zostać zatrzymana w celu usunięcia plików dziennika. Kontynuować? - Use bind credentials - Użyj wskazanych poświadczeń + Log files cleared + Pliki dziennika zostały usunięte - Base DN - + All log files were cleared successfully. + Wszystkie pliki dziennika zostały pomyślnie usunięte. - Fixed base DN - + Error + Błąd - e.g. dc=example,dc=org - np. dc=przykład,dc=org + Could not remove all log files. + Nie można usunąć wszystkich plików dziennika. - Discover base DN by naming context - + MB + MB - e.g. namingContexts or defaultNamingContext - + Rotate log files + Zamieniaj logi - Environment settings - Ustawienia środowiska + x + x - Object trees - + Write to logging system of operating system + Zapisz w logach systemu operacyjnego - Computer tree + TLS configuration - e.g. OU=Groups + Use certificate authority for TLS connections - User tree - + CA certificate file + Plik certyfikatu CA - e.g. OU=Users - + ... + ... - e.g. OU=Computers - + Host certificate file + Plik certyfikatu hosta - Group tree - + Host private key file + Plik klucza prywatnego hosta - Perform recursive search operations in object trees + Style: - Object attributes + Native - e.g. hwAddress + Color scheme: - e.g. member or memberUid + Light - e.g. dNSHostName + Dark - Computer MAC address attribute + User groups - Group member attribute - + Backend: + Zaplecze: - e.g. uid or sAMAccountName + Include user groups from domain - Advanced settings - Ustawienia zaawansowane + Missing user groups backend + Nieskonfigurowane źródło grup użytkowników - Optional object filters + No user groups plugin was found. Please check your installation! + + + HeadlessVncServer - Filter for user groups + Headless VNC server + + + LdapBrowseDialog - Filter for users - + Browse LDAP + Przeglądaj LDAP + + + LdapClient - Filter for computer groups - + LDAP error description: %1 + Opis błędu LDAP: %1 + + + LdapConfiguration - Group member identification - + LDAP connection failed + Połączenie LDAP zakończone niepowodzeniem - Distinguished name (Samba/AD) - + Could not connect to the LDAP server. Please check the server parameters. + +%1 + Nie można połączyć się z serwerem LDAP. Sprawdź parametry serwera. + +%1 - List all groups of a user - Wyświetl wszystkie grupy użytkownika + LDAP bind failed + Podłączenie LDAP nie powiodło się - List all groups of a computer - Wyświetl wszystkie grupy komputera + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + Nie można powiązać z serwerem LDAP. Sprawdź parametry serwera i powiąż poświadczenia. + +%1 - Get computer object by IP address - Wybierz komputer za pomocą adresu IP + LDAP bind successful + Podłączenie LDAP powiodło się - LDAP connection failed - Połączenie LDAP zakończone niepowodzeniem + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Pomyślnie nawiązano połączenie z serwerem LDAP. Podstawowe ustawienia LDAP są poprawnie skonfigurowane. - LDAP bind failed - + LDAP base DN test failed + Test podstawowego DN z LDAP nie powiódł się - LDAP bind successful + Could not query the configured base DN. Please check the base DN parameter. + +%1 - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - + LDAP base DN test successful + Test podstawowego DN z LDAP powiódł się - LDAP base DN test failed + The LDAP base DN has been queried successfully. The following entries were found: + +%1 - LDAP base DN test successful - + LDAP naming context test failed + Test LDAP nie powiódł się - LDAP naming context test failed + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 LDAP naming context test successful - + Test kontekstu LDAP powiódł się The LDAP naming context has been queried successfully. The following base DN was found: @@ -2009,68 +2361,104 @@ The public key is used on client computers to authenticate incoming connection r user tree - + drzewo użytkowników - group tree - + User tree + Drzewo użytkownika - computer tree - + group tree + drzewo grupy - Enter username - Wprowadź nazwę użytkownika + Group tree + Drzewo grupy - Please enter a user login name (wildcards allowed) which to query: - + computer tree + drzewo komputera - user objects - + Computer tree + Drzewo komputerów - Enter group name - Wprowadź nazwę grupy + computer group tree + drzewo grup komputerowych - Please enter a group name whose members to query: - + Computer group tree + Drzewo grup komputerowych + + + user objects + obiekty użytkownika + + + User login name attribute + Atrybut nazwy logowania użytkownika group members Członkowie grupy + + Group member attribute + Atrybut członka grupy + Group not found Nie znaleziono grupy Could not find a group with the name "%1". Please check the group name or the group tree parameter. - + Nie można znaleźć grupy o nazwie „%1”. Sprawdź nazwę grupy lub jej drzewo. - Enter computer name - Wprowadź nazwę komputera + computer objects + Obiekty komputerowe - computer objects - + Computer display name attribute + Atrybut wyświetlanej nazwy komputera - Enter computer DN - + Invalid hostname + Nieprawidłowa nazwa hosta - Please enter the DN of a computer whose MAC address to query: - + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Skonfigurowałeś nazwy komputerów, aby były przechowywane jako w pełni kwalifikowane nazwy domen (FQDN), ale wprowadziłeś nazwę hosta bez domeny. + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Skonfigurowałeś nazwy komputerów, aby były przechowywane jako proste nazwy hostów bez nazwy domeny, ale wprowadziłeś nazwę hosta z częścią nazwy domeny. + + + Computer hostname attribute + Atrybut nazwy hosta komputera computer MAC addresses adres MAC komputera + + Computer MAC address attribute + Atrybut adresu MAC komputera + + + computer locations + lokalizacje komputerów + + + Computer location attribute + Atrybut lokalizacji komputera + + + Location name attribute + Atrybut nazwy lokalizacji + users użytkownicy @@ -2079,59 +2467,122 @@ The public key is used on client computers to authenticate incoming connection r user groups grupy użytkowników + + computers + komputery + computer groups grupy komputerów - Please enter a user login name whose group memberships to query: + computer containers groups of user - + grupy użytkownika User not found Nie znaleziono użytkownika + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + Nie można znaleźć użytkownika o nazwie „%1”. Sprawdź nazwę użytkownika lub parametr drzewa użytkownika. + groups of computer - + grupy komputera Computer not found Nie znaleziono komputera - Enter computer IP address - Wprowadź adres IP komputera + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Nie można znaleźć komputera o nazwie hosta „%1”. Sprawdź nazwę hosta lub parametr drzewa komputera. - Please enter a computer IP address which to resolve to an computer object: - + Hostname lookup failed + Wyszukiwanie nazwy hosta nie powiodło się - computers - komputery + Could not lookup hostname for IP address %1. Please check your DNS server settings. + Nie można wyszukać nazwy hosta dla adresu IP %1. Sprawdź ustawienia serwera DNS. + + + location entries + lokalizacje + + + Computer groups filter + Filtr grupy komputerów + + + Computer locations identification + Identyfikacja lokalizacji komputera + + + Filter for computer groups + Filtruj według grup komputerów + + + Invalid test value + Nieprawidłowa wartość + + + An empty or invalid value has been supplied for this test. + Podano pustą lub niepoprawną wartość. LDAP %1 test failed test LDAP %1 zakończony niepowodzeniem + + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + Nie można wyszukać żadnych wpisów w skonfigurowanym %1. Sprawdź parametr „%2”. + +%3 + LDAP %1 test successful test LDAP %1 zakończony powodzeniem The %1 has been queried successfully and %2 entries were found. - + Zapytanie o %1 zakończyło się powodzeniem i znaleziono %2 wpisów. +  + + + LDAP test failed + Test LDAP nie powiódł się + + + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + Nie można wysłać zapytania do żadnego %1. Sprawdź parametr(y) %2 i wprowadź nazwę istniejącego obiektu. + +%3 + + + and + oraz + + + LDAP test successful + Test LDAP powiódł się %1 %2 have been queried successfully: %3 - + Zadania %1 %2 zostały pomyślnie wykonane + +%3 LDAP filter test failed @@ -2141,7 +2592,9 @@ The public key is used on client computers to authenticate incoming connection r Could not query any %1 using the configured filter. Please check the LDAP filter for %1. %2 - + Nie można wysłać zapytania do żadnego %1 przy użyciu skonfigurowanego filtra. Sprawdź filtr LDAP dla %1 + +%2 LDAP filter test successful @@ -2149,583 +2602,534 @@ The public key is used on client computers to authenticate incoming connection r %1 %2 have been queried successfully using the configured filter. - + Zadanie %1 %2 zakończyło się pomyślnie przy użyciu skonfigurowanego filtra. - (only if different from group tree) + LDAP directory + + + LdapConfigurationPage - Computer group tree - - - - computer group tree - - - - Filter for computers - - - - e.g. room or computerLab - - - - Integration tests - - - - Computer groups - Grupy komputerów - - - e.g. name or description - np. nazwa lub opis + Basic settings + Ustawienia podstawowe - Filter for computer containers - + General + Ogólne - Computer containers or OUs - + LDAP server and port + Serwer LDAP i port - Connection security - Bezpieczeństwo połączenia + Bind DN + Wskaż nazwę domeny - TLS certificate verification - Weryfikacja certyfikatu TLS + Bind password + wskaż hasło - System defaults - + Anonymous bind + Anonimowy dostęp - Never (insecure!) - Nigdy (niebezpieczne!) + Use bind credentials + Użyj wskazanych poświadczeń - Custom CA certificate file - Inny plik certyfikatu + Base DN + Podstawowy serwer DNS - None - Brak + Fixed base DN + Zapasowy serwer DNS - TLS - TLS + e.g. dc=example,dc=org + np. dc=przykład,dc=org - SSL - SSL + Discover base DN by naming context + Rozpoznaj podstawową nazwę z DN wskazując kontekst - e.g. (objectClass=computer) - np. (objectClass=komputer) + e.g. namingContexts or defaultNamingContext + np. namingContexts lub defaultNamingContext - e.g. (objectClass=group) - np. (objectClass=grupa) + Environment settings + Ustawienia środowiska - e.g. (objectClass=person) - np. (objectClass=osoba) + Object trees + Drzewa obiektów - e.g. (objectClass=room) or (objectClass=computerLab) - np. (objectClass=sala) lub (objectClass=PracowniaKomputerowa) + Computer tree + Drzewo komputerów - e.g. (objectClass=container) or (objectClass=organizationalUnit) - np. (objectClass=kontener) lub (objectClass=JednostkaOrganizacyjna) + e.g. OU=Groups + np. OU=Groups - Could not query the configured base DN. Please check the base DN parameter. - -%1 - + User tree + Drzewo użytkownika - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - + e.g. OU=Users + np. OU=Users - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - + e.g. OU=Computers + np. OU=Computers - Certificate files (*.pem) - Pliki certyfikatów (*.pem) + Group tree + Drzewo grupy - Could not connect to the LDAP server. Please check the server parameters. - -%1 - + Perform recursive search operations in object trees + Wykonuj rekurencyjne operacje wyszukiwania w drzewach obiektów - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - + Object attributes + Atrybuty obiektów - Encryption protocol - + e.g. hwAddress + np. hwAddress - Computer location attribute - + e.g. member or memberUid + np. member lub memberUid - Computer display name attribute - + e.g. dNSHostName + np. dNSHostName - Location name attribute - + Computer MAC address attribute + Atrybut adresu MAC komputera - e.g. cn or displayName - + Group member attribute + Atrybut członka grupy - Computer locations identification - + e.g. uid or sAMAccountName + np. uid lub sAMAccountName - Identify computer locations (e.g. rooms) via: - + Advanced settings + Ustawienia zaawansowane - Location attribute in computer objects - + Optional object filters + Opcjonalne filtry obiektów - List all entries of a location - + Filter for user groups + Filtruj według grup użytkowników - List all locations - + Filter for users + Filtruj według użytkowników - Enter computer display name - + Filter for computer groups + Filtruj według grup komputerów - Please enter a computer display name to query: - + Group member identification + Identyfikacja członka grupy - Enter computer location name - + Distinguished name (Samba/AD) + Nazwa wyróżniająca (SAMBA/AD) - Please enter the name of a computer location (wildcards allowed): - + List all groups of a user + Wyświetl wszystkie grupy użytkownika - computer locations - + List all groups of a computer + Wyświetl wszystkie grupy komputera - Enter location name - + Get computer object by IP address + Wybierz komputer za pomocą adresu IP - Please enter the name of a location whose entries to query: - + Enter username + Wprowadź nazwę użytkownika - location entries - + Please enter a user login name (wildcards allowed) which to query: + Wprowadź nazwę logowania użytkownika (dozwolone są symbole), którą chcesz sprawdzić: - LDAP test failed - + Enter group name + Wprowadź nazwę grupy - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - + Please enter a group name whose members to query: + Podaj nazwę grupy, którą chcesz sprawdzić: - and - + Enter computer name + Wprowadź nazwę komputera - LDAP test successful - + Enter computer DN + Wpisz DN komputera - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 + Please enter the DN of a computer whose MAC address to query: - Browse - + Please enter a user login name whose group memberships to query: + Wprowadź nazwę użytkownika, którego członkostwo w grupach ma być wyszukiwane: - Test - Test + Enter computer IP address + Wprowadź adres IP komputera - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - + Please enter a computer IP address which to resolve to an computer object: + Wprowadź adres IP komputera, który ma zostać przekształcony w obiekt komputerowy: - Computer hostname attribute - + (only if different from group tree) + (tylko jeśli różni się od drzewa grupy) - Please enter a computer hostname to query: - + Computer group tree + Drzewo grup komputerowych - Invalid hostname - + Filter for computers + Filtruj komputery - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - + e.g. room or computerLab + np. room lub computerLab - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - + Integration tests + Testy integracyjne - Could not find a user with the name "%1". Please check the username or the user tree parameter. - + Computer groups + Grupy komputerów - Enter hostname - + e.g. name or description + np. nazwa lub opis - Please enter a computer hostname whose group memberships to query: - + Filter for computer containers + Filtruj według grup komputerów - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Computer containers or OUs - Hostname lookup failed - + Connection security + Bezpieczeństwo połączenia - Could not lookup hostname for IP address %1. Please check your DNS server settings. - + TLS certificate verification + Weryfikacja certyfikatu TLS - User login name attribute - + System defaults + Ustawienia domyślne - Configured attribute for user login name or computer hostname (OpenLDAP) - + Never (insecure!) + Nigdy (niebezpieczne!) - computer containers - + Custom CA certificate file + Inny plik certyfikatu - - - LdapPlugin - Auto-configure the base DN via naming context - + None + Brak - Query objects from LDAP directory - + TLS + TLS - Show help about command - Pokaż pomoc dotyczącą komendy + SSL + SSL - Commands for configuring and testing LDAP/AD integration - + e.g. (objectClass=computer) + np. (objectClass=komputer) - Basic LDAP/AD support for Veyon - + e.g. (objectClass=group) + np. (objectClass=grupa) - %1 (load computers and locations from LDAP/AD) - + e.g. (objectClass=person) + np. (objectClass=osoba) - %1 (load users and groups from LDAP/AD) - + e.g. (objectClass=room) or (objectClass=computerLab) + np. (objectClass=sala) lub (objectClass=PracowniaKomputerowa) - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - + e.g. (objectClass=container) or (objectClass=organizationalUnit) + np. (objectClass=kontener) lub (objectClass=JednostkaOrganizacyjna) - No naming context attribute name given - falling back to configured value. - + Certificate files (*.pem) + Pliki certyfikatów (*.pem) - Could not query base DN. Please check your LDAP configuration. - + Encryption protocol + Protokół szyfrowania - Configuring %1 as base DN and disabling naming context queries. - + Computer location attribute + Atrybut lokalizacji komputera - - - LdapProConfigurationPage - LDAP Pro - + Computer display name attribute + Atrybut wyświetlanej nazwy komputera - Instances - + Location name attribute + Atrybut nazwy lokalizacji - Enter name - + e.g. cn or displayName + np. cn or displayName - Please enter a name for the instance (can't be changed later!): - + Computer locations identification + Identyfikacja lokalizacji komputera - Remove instance - + Identify computer locations (e.g. rooms) via: + Zidentyfikuj lokalizacje komputerów (np. sale) przez: - Do you really want to remove instance "%1"? + Location attribute in computer objects - Configuration for instance "%1" - + List all entries of a location + Wyświetl wszystkie wpisy lokalizacji - - - LdapProPlugin - Professional LDAP/AD integration for Veyon - + List all locations + Wyświetl wszystkie lokalizacje - %1 (load computers and locations from LDAP/AD) - + Enter computer display name + Wpisz wyświetlaną nazwę komputera - %1 (load users and groups from LDAP/AD) - + Please enter a computer display name to query: + Wprowadź wyświetlaną nazwę komputera, aby wysłać zapytanie: - - - LicensingConfigurationPage - Licensing - + Enter computer location name + Wprowadź nazwę lokalizacji komputera - Installed licenses - + Please enter the name of a computer location (wildcards allowed): + Wprowadź nazwę lokalizacji komputera (dozwolone są znaki specjalne): - Add new network range - + Enter location name + Wpisz nazwę lokalizacji - Remove selected network range - + Please enter the name of a location whose entries to query: + Wprowadź nazwę lokalizacji, której wpisy dotyczą zapytania: - ID - + Browse + Przeglądaj - Feature - + Test + Test - Valid until - + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Nazwy hostów przechowywane jako w pełni kwalifikowane nazwy domen (FQDN, np. myhost.example.org) +  - Licensee - + Computer hostname attribute + Atrybut nazwy hosta komputera - Browse license file - + Please enter a computer hostname to query: + Wprowadź nazwę hosta, aby wysłać zapytanie: - Veyon license files (*.vlf) - + Enter hostname + Wpisz nazwę hosta - Remove license - + Please enter a computer hostname whose group memberships to query: + Wprowadź nazwę hosta, którego członkostwo w grupach ma być wyszukiwane: - Do you really want to remove the selected license? - + User login name attribute + Atrybut nazwy logowania użytkownika - <N/A> - Brak danych + Configured attribute for user login name or computer hostname (OpenLDAP) + Skonfigurowany atrybut użytkownik lub komputer (OpenLDAP) - Invalid license file - + Directory name + Nazwa katalogu - Could not open the license file for reading! - + Query options + Opcje zapytań - The selected license file does not contain valid data. - + Query nested user groups (supported by AD only) + Zapytanie o zagnieżdżone grupy użytkowników (obsługiwane tylko przez AD) - The selected license file could not be verified. + Query timeout - The selected license file is not valid for this installation. - + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. - + LDAP + LDAP - The license is already installed. + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + LdapPlugin - Information + Auto-configure the base DN via naming context - Installation ID - + Query objects from LDAP directory + Zapytaj obiekty z katalogu LDAP - Addons available for licensing - + Show help about command + Pokaż pomoc dotyczącą komendy - Addon - + Commands for configuring and testing LDAP/AD integration + Polecenia do konfigurowania i testowania integracji LDAP / AD - - - LicensingPlugin - Show help for specific command - Pokaż pomoc dla wskazanej komendy + Basic LDAP/AD support for Veyon + Podstawowa obsługa LDAP / AD dla Veyon - Show all installed licenses - + %1 (load computers and locations from LDAP/AD) + %1 (wczytywanie komputerów i lokacji z LDAP / AD) - Add license file - + %1 (load users and groups from LDAP/AD) + %1 (wczytywanie użytkowników i grupy z LDAP / AD) - Remove installed license - + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Podaj prawidłowy adres URL LDAP zgodnie ze schematem „ldap[s]://[użytkownik[:hasło]@]nazwahosta[:port] - -USAGE - -%1 add <LICENSE FILE> - - - + No naming context attribute name given - falling back to configured value. + Nie podano poprawnie - powrót do skonfigurowanej wartości. - -USAGE - -%1 remove <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. - No certificate found with given ID + Configuring %1 as base DN and disabling naming context queries. - <N/A> - Brak danych + Test binding to an LDAP server + Zweryfikuj połączenie do serwera LDAP - Licensing management - + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Podana nazwa użytkownika lub hasło jest nieprawidłowe. Wprowadź prawidłowe dane uwierzytelniające lub przejdź na inną metodę uwierzytelniania za pomocą Konfiguratora Veyon. - Commands for managing license keys - + LDAP bind + Powiąż z LDAP LinuxPlatformConfigurationPage Linux - + Linux Custom PAM service for user authentication - + Niestandardowa usługa PAM do uwierzytelniania użytkownika User authentication - + Uwierzytelnianie użytkownika - Session management - + User sessions + Sesja użytkownia - Display manager users + Minimum session lifetime before server start + + User login + Login użytkownika + + + Login key sequence + Sekwencja klawiszy logowania + LinuxPlatformPlugin Plugin implementing abstract functions for the Linux platform - - - - Plugin implementing specific functions for the Linux platform - + Wtyczka włączająca specyficzne funkcje dla platformy Linux LocationDialog Select location - + Wybierz lokalizację enter search filter... @@ -2738,14 +3142,14 @@ USAGE Configuration Konfiguracja - - Disable balloon tooltips - - Show icons only Pokaż tylko ikony + + Disable tooltips + + MainWindow @@ -2793,10 +3197,6 @@ USAGE About Qt O Qt - - Authentication impossible - Uwierzytelnienie niemożliwe - Configuration not writable Nie można zapisać konfiguracji @@ -2847,7 +3247,7 @@ USAGE %1 Configurator %2 - + %1 Konfigurator %2 JSON files (*.json) @@ -2855,11 +3255,7 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - - - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - + Lokalny backend konfiguracji poinformował, że konfiguracji nie można zapisać! Uruchom konfigurator %1 z wyższymi uprawnieniami. Access denied @@ -2867,7 +3263,7 @@ USAGE According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. - + Zgodnie z lokalną konfiguracją nie masz dostępu do komputerów w sieci. Zaloguj się przy użyciu innego konta lub pozwól administratorowi systemu sprawdzić konfigurację lokalną. Screenshots @@ -2890,55 +3286,93 @@ USAGE Czy na pewno chcesz zresetować lokalną konfigurację i przywrócić wszystkie ustawienia do wartości domyślnych? - Search users and computers - Wyszukaj użytkowników i komputery + Search users and computers + Wyszukaj użytkowników i komputery + + + Align computers to grid + Dopasuj komputery w siatkę + + + %1 Configurator + Konfigurator %1 + + + Insufficient privileges + Niewystarczające uprawnienia + + + Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + Nie można rozpocząć z uprawnieniami administratora. Upewnij się, że w środowisku zainstalowany program podobny do sudo! Program zostanie uruchomiony z normalnymi uprawnieniami użytkownika. + + + Only show powered on computers + Pokaż tylko włączone komputery + + + &Save settings to file + Zapi&sz ustawienia do pliku + + + &View + Podgląd + + + &Standard + &Standard - Adjust optimal size - Dopasuj optymalny rozmiar + &Advanced + Z&aawansowany - Align computers to grid - Dopasuj komputery w siatkę + Use custom computer arrangement + Użyj niestandardowego ustawienia komputera - %1 Configurator - Konfigurator %1 + Locations && computers + Lokalizacje i komputery - Insufficient privileges - Niewystarczające uprawnienia + Authentication + Uwierzytelnienie - Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + Adjust size of computer icons automatically - Only show powered on computers - + Slideshow + Pokaz slajdów - &Save settings to file + Spotlight - &View - + Veyon Master + Veyon Master - &Standard + Locations & computers + Sale i komputery + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. - &Advanced + Only show computers with logged on users - Use custom computer arrangement + Load computer positions - Locations && computers + Save computer positions @@ -2948,17 +3382,13 @@ USAGE Directories Lokalizacje - - ... - ... - User configuration Konfiguracja użytkownika Feature on computer double click: - + Działanie po podwójnym kliknięciu na komputerze: Features @@ -2990,7 +3420,7 @@ USAGE Enforce selected mode for client computers - + Wymuszaj wybrany tryb dla komputerów klienckich Hide local computer @@ -2998,7 +3428,7 @@ USAGE Hide computer filter field - + Ukryj pole filtra komputera Actions such as rebooting or powering down computers @@ -3030,227 +3460,246 @@ USAGE User and computer name - + Nazwa użytkownika i komputera Only user name + Tylko nazwa użytkownika + + + Only last part of user name Only computer name - + Tylko nazwa komputera Computer thumbnail caption - + Sekcja miniatur komputera Text color - + Kolor tekstu Sort order - + Kolejność sortowania Computer and user name - + Nazwa komputera i użytkownika Computer locations - + Lokalizacje komputerów Show current location only - + Pokaż tylko bieżącą lokalizację Allow adding hidden locations manually - + Zezwalaj na ręczne dodawanie ukrytych lokalizacji Hide empty locations - + Ukryj puste lokalizacje Show confirmation dialog for potentially unsafe actions - + Pokaż okno dialogowe potwierdzenia dla potencjalnie niebezpiecznych działań Perform access control - + Wykonaj weryfikację dostępu Automatically select current location - + Automatycznie wybierz bieżącą lokalizację - Automatically adjust computer thumbnail size - + Automatically open computer select panel + Automatycznie otwórz panel wyboru komputera - Automatically open computer select panel - + Use modern user interface (experimental) + Użyj nowoczesnego interfejsu użytkownika (eksperymentalne) - - - MonitoringMode - Monitoring - Monitoring + Thumbnail spacing + Odstęp między miniaturami - Builtin monitoring mode + px - This mode allows you to monitor all computers at one or more locations. - + Hide local session + Ukryj lokalną sesję - - - NetworkDiscoveryConfigurationPage - Network discovery - + Auto + Auto - Mode - + Thumbnail aspect ratio + Proporcje miniatury + + + Automatically adjust computer icon size + Automatycznie dostosuj rozmiar ikony komputera + + + Open feature windows on the same screen as the main window + Otwieraj okna funkcji na tym samym ekranie, co okno główne - Scan network ranges + Configuration templates - e.g. 192.168.1.0/24 + Image quality in monitoring mode - Scan all subnets of computer + Highest - Scan custom subnet + High - Scan sessions on local computer + Medium - Test - Test + Low + - Network ranges + Lowest - Add new group + Remote access image quality - Remove selected group + Advanced - Groups + Computer name source - First address + Default - Last address + Host address + Adres hosta + + + Session client address - Add new network range + Session client name - Remove selected network range + Session host name - Parallel scans + Session metadata - Scan timeout + Full name of user - ms - ms + User login name + Nazwa użytkownika - Session scan limit + Computer UID role - Options + Session meta data hash - Reverse lookup discovered IP addresses to host names + Always expand all locations - New location + Image quality - NetworkDiscoveryDirectory + MonitoringMode - Scanning... - + Monitoring + Monitoring - Discovered computers - + Builtin monitoring mode + Wbudowany tryb monitorowania - - - NetworkDiscoveryPlugin - Show help for specific command - Pokaż pomoc dla wskazanej komendy + This mode allows you to monitor all computers at one or more locations. + Ten tryb umożliwia monitorowanie wszystkich komputerów w co najmniej jednej lokalizacji. - Scan a subnet + Query application version of the server - -USAGE - -%1 scan [<SUBNET>] - - + Query active features - Network object directory which automatically discovers computers in the network + Query properties of remotely available screens + + + NestedNetworkObjectDirectory - Network discovery (scan network for Veyon clients) + All directories + + + NetworkObjectDirectoryConfigurationPage - Commands for managing the network discovery directory - + Update interval: + Interwał odświeżania: + + + seconds + sekundy + + + + NetworkObjectDirectoryConfigurationPageTab + + Enabled + Włączony NetworkObjectTreeModel Locations/Computers - + Lokalizacje/Komputery @@ -3261,15 +3710,15 @@ USAGE e.g. Veyon - + np. Veyon Remember and add to website menu - + Zapamiętaj i dodaj do menu strony e.g. www.veyon.io - + np.: www.veyon.io Please enter the URL of the website to open: @@ -3277,34 +3726,46 @@ USAGE Name: + Nazwa: + + + Website name - PasswordDialog + PluginCommands - Username - Nazwa użytkownika + List names of all installed plugins + Wyświetl nazwy wszystkich zainstalowanych wtyczek - Password - Hasło + Show table with details of all installed plugins + Pokaż szczegółową tabelę zainstalowanych wtyczek - Veyon Logon - + Name + Nazwa - Authentication error - Błąd uwierzytelnienia + Description + Opis - Logon failed with given username and password. Please try again! - Nie można się zalogować z użytym loginem i hasłem. Spróbuj ponownie! + Version + Wersja - Please enter your username and password in order to access computers. - By uzyskać dostęp do komputerów wprowadź nazwę użytkownika i hasło. + UID + Identyfikator użytkownika + + + Plugin-related CLI operations + Operacje linii komend związane z wtyczkami + + + Commands for managing plugins + Polecenia do zarządzania wtyczkami @@ -3349,58 +3810,68 @@ USAGE Do you really want to reboot the selected computers? Czy na pewno chcesz uruchomić ponownie wybrane komputery? - - Do you really want to power down the selected computer? - Czy na pewno chcesz wyłączyć wybrany komputer? - Power on a computer via Wake-on-LAN (WOL) - + Włącz komputer przez Wake-on-LAN (WOL) MAC ADDRESS - + ADRES MAC This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. - + To polecenie wysyła pakiet Wake-on-LAN (WOL) do sieci w celu włączenia komputera o podanym adresie MAC. Please specify the command to display help for! - + Podaj polecenie aby wyświetlić pomoc! Invalid MAC address specified! - + Podano nieprawidłowy adres MAC! Commands for controlling power status of computers - + Polecenia do kontrolowania stanu zasilania komputerów Power down now - + Wyłącz natychmiast Install updates and power down - + Zainstaluj aktualizacje i wyłącz Power down after user confirmation - + Wyłącz po potwierdzeniu przez użytkownika Power down after timeout - + Wyłącz po upływie limitu czasu The computer was remotely requested to power down. Do you want to power down the computer now? - + Komputer został zdalnie poproszony o wyłączenie. Czy chcesz teraz wyłączyć komputer? The computer will be powered down in %1 minutes, %2 seconds. Please save your work and close all programs. + Komputer zostanie wyłączony za %1 minut, %2 sekund. + +Zapisz swoją pracę i zamknij wszystkie programy. + + + Do you really want to reboot <b>ALL</b> computers? + + + + Do you really want to power down <b>ALL</b> computers? + + + + Do you really want to power down the selected computers? @@ -3412,15 +3883,15 @@ Please save your work and close all programs. Please specify a timeout for powering down the selected computers: - + Określ limit czasu dla wyłączania wybranych komputerów: minutes - + minut seconds - + sekund @@ -3449,20 +3920,35 @@ Please save your work and close all programs. Remote view or control a computer Zdalny podgląd lub sterowanie komputerem - - Please enter the hostname or IP address of the computer to access: - Wprowadź nazwę lub adres IP komputera, do którego chcesz uzyskać dostęp: - Show help about command Pokaż pomoc dotyczącą komendy + + Exchange clipboard contents + + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + Nie zaznaczono komputera, wpisz nazwę lub adres IP komputera do dostępu ręcznego + + + + RemoteAccessPage + + Remote access: %1 + Zdalny dostęp: %1 + RemoteAccessWidget %1 - %2 Remote Access - + %1 -%2 dostęp zdalny + + + %1 - %2 - %3 Remote Access + %1 - %2 - %3 Zdalny dostęp @@ -3519,10 +4005,6 @@ Please save your work and close all programs. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - Łączenie z %1 - Connected. Połączono. @@ -3533,60 +4015,19 @@ Please save your work and close all programs. Exit - - - - - Routing - - Control internet access by modifying routing table - - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - - - - Add custom route to block internet - - - - Destination - - - - Gateway - - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - Wprowadź nazwę programów lub komendy do uruchomienia na zdalnym komputerze(komputerach). Możesz oddzielić je, zapisując w osobnych wierszach. + Wyjście - Run programs - Uruchom programy - - - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - np. "C:\Program Files\VideoLAN\VLC\vlc.exe" - - - Name: - + Connecting... + Łączenie... - Remember and add to program menu - + Select screen + Wybierz ekran - e.g. VLC - + All screens + Wszystkie ekrany @@ -3607,6 +4048,18 @@ Please save your work and close all programs. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. Żeby zdobyć pełną uwagę użytkowników, możesz zablokować ich komputery za pomocą tego przycisku. W tym trybie wszystkie urządzenia wejścia oraz ekran są zablokowane. + + Lock input devices + Zablokuj urządzenia wejściowe + + + Unlock input devices + Odblokuj urządzenie wejsciowe + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + Aby odzyskać pełną uwagę wszystkich użytkowników, możesz zablokować ich komputery za pomocą tego przycisku. W tym trybie wszystkie urządzenia wejściowe są zablokowane, podczas gdy pulpit jest nadal widoczny.  + Screenshot @@ -3622,6 +4075,10 @@ Please save your work and close all programs. Screenshot Zrzut ekranu + + Could not open screenshot file %1 for writing. + Nie udało się zapisać zrzutu ekranu do pliku %1 + ScreenshotFeaturePlugin @@ -3646,6 +4103,13 @@ Please save your work and close all programs. Wykonaj zrzuty ekranów komputerów i zapisz je lokalnie. + + ScreenshotManagementPage + + Screenshots + Zrzuty ekranu + + ScreenshotManagementPanel @@ -3665,16 +4129,55 @@ Please save your work and close all programs. Data: - Time: - Czas: + Time: + Czas: + + + Show + Pokaż + + + Delete + Usuń + + + Screenshot + Zrzut ekranu + + + Do you really want to delete all selected screenshots? + Czy na pewno chcesz usunąć wszystkie zaznaczone zrzuty ekranu? + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + - Show - Pokaż + User has denied access + - Delete - Usuń + User confirmed access + @@ -3707,14 +4210,6 @@ Please save your work and close all programs. State: Stan - - Network - Sieć - - - Demo server port - port serwera demo - Enable firewall exception Uruchom wyjątki w zaporze sieciowej @@ -3723,10 +4218,6 @@ Please save your work and close all programs. Allow connections from localhost only Zezwalaj tylko na połączenia z localhosta - - Internal VNC server port - Wewnętrzny port VNC - VNC server Serwer VNC @@ -3748,68 +4239,139 @@ Please save your work and close all programs. Uruchomiona - Feature manager port + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. + Włączenie tej opcji spowoduje, że usługa uruchomi proces serwera dla każdej interaktywnej sesji na komputerze. +Zazwyczaj jest to wymagane do obsługi serwerów terminali. + + + Show notification on remote connection + Pokaż powiadomienie o zdalnym połączeniu + + + Show notification when an unauthorized access is blocked + Pokaż powiadomienie, gdy zostanie zablokowany nieautoryzowany dostęp + + + Maximum session count + Maksymalna liczba sesji + + + Network port numbers + Numery portów sieciowych + + + Veyon server + Serwer Veyon + + + Internal VNC server + Wewnętrzny serwer VNC + + + Feature manager + Menedżer funkcji + + + Demo server + Serwer demo + + + Miscellaneous network settings + Różne ustawienia sieci + + + Session mode - Primary service port - Główny port usługi + Local session mode (single server instance for primary local session) + - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. + Active session mode (single server instance for active local or remote session) - Show notification on remote connection + Multi session mode (distinct server instance for each local and remote desktop session) - Multi session mode (for terminal and remote desktop servers) + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. - Show notification when an unauthorized access is blocked + Miscellaneous settings - - - ServiceControl - Starting service %1 - Uruchamianie usługi %1 + Disable clipboard synchronization + - Stopping service %1 - Zatrzymywanie usługi %1 + Session metadata + - Registering service %1 - Rejestrowanie usługi %1 + Content + - Unregistering service %1 - Wyrejestrowywanie usługi %1 + None + Brak - Service control - Zarządzenie usługą + Value of an environment variable + + + + Value of a registry key + + + + Environment variable name: + + + + Registry key name: + + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + - ServiceControlPlugin + ServiceControl - Service is running - Usługa jest uruchomiona + Service control + Zarządzenie usługą - Service is not running - Usługa nie jest uruchomiona + Starting %1 + - Configure and control Veyon service - Konfiguruj i zarządzaj usługą Veyon + Stopping %1 + + + + Restarting %1 + + + + Registering %1 + + + Unregistering %1 + + + + + ServiceControlCommands Register Veyon Service Rejestracja usługi Veyon @@ -3834,13 +4396,25 @@ Typically this is required to support terminal servers. Query status of Veyon Service Status kolejki usługi Veyon + + Service is running + Usługa jest uruchomiona + + + Service is not running + Usługa nie jest uruchomiona + + + Configure and control Veyon service + Konfiguruj i zarządzaj usługą Veyon + Commands for configuring and controlling Veyon Service Komendy do konfiguracji i zarządzania usługą Veyon - ShellCommandLinePlugin + ShellCommands Run command file Uruchom plik komend @@ -3850,13 +4424,99 @@ Typically this is required to support terminal servers. Plik "%1" nie istnieje! - Interactive shell and script execution for Veyon Control + Interactive shell and script execution for Veyon CLI Commands for shell functionalities + Komendy dotyczące funkcjonalności powłoki + + + + SlideshowPanel + + Previous + Poprzedni + + + Start/pause + Start/pauza + + + Next + Następny + + + Duration: + Czas trwania: + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + Dodaj wybrane komputery + + + Remove selected computers + Usuń wybrane komputery + + + Update computers in realtime + + + + Spotlight + + + + Please select at least one computer to add. + Wybierz co najmniej jeden komputer do dodania. + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + + + StartAppDialog + + Start application + Uruchom aplikację + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + np. "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + + + + Application name + + + + Name: + Nazwa: + + + e.g. VLC + np.: VLC + SystemTrayIcon @@ -3873,18 +4533,18 @@ Typically this is required to support terminal servers. Default (system user groups) - + Domyślnie (systemowe grupy użytkowników) TestingCommandLinePlugin Test internal Veyon components and functions - + Testuj wewnętrzne komponenty i funkcje Veyon Commands for testing internal components and functions of Veyon - + Polecenia do testowania wewnętrznych komponentów i funkcji Veyon @@ -3894,8 +4554,8 @@ Typically this is required to support terminal servers. Wyślij wiadomość tekstową - Use the field below to type your message which will be sent to all selected users. - W polu poniżej napisz wiadomość, która ma zostać wysłana do wybranych użytkowników. + Please enter your message which send to all selected users. + @@ -3921,11 +4581,11 @@ Typically this is required to support terminal servers. UltraVncConfigurationWidget Enable capturing of layered (semi-transparent) windows - + Włącz przechwytywanie półprzezroczystych okien Poll full screen (leave this enabled per default) - + Rozciągnij na pełny ekran (domyślnie pozostaw włączone) Low accuracy (turbo mode) @@ -3937,45 +4597,69 @@ Typically this is required to support terminal servers. Enable multi monitor support - + Włącz obsługę wielu monitorów Enable Desktop Duplication Engine on Windows 8 and newer - + Włącz mechanizm kopiowania pulpitu w systemie Windows 8 i nowszych + + + Maximum CPU usage + Maksymalne wykorzystanie CPU - UserConfig + UserLoginDialog - No write access - Brak prawa edycji + User login + Login użytkownika - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - + Please enter a username and password for automatic login on all computers. + Wprowadź nazwę użytkownika i hasło do automatycznego logowania na wszystkich komputerach. + + + Username + Nazwa użytkownika + + + Password + Hasło - UserSessionControl + UserSessionControlPlugin - User session control - Kontrola sesji użytkownika + Log in + Zaloguj + + + Click this button to log in a specific user on all computers. + Kliknij ten przycisk, aby zalogować określonego użytkownika na wszystkich komputerach. Log off - + Wyloguj Click this button to log off users from all computers. - + Kliknij ten przycisk, aby wylogować użytkowników ze wszystkich komputerów. Confirm user logoff - + Potwierdź wylogowanie użytkownika Do you really want to log off the selected users? - + Czy naprawdę chcesz wylogować wybranych użytkowników? + + + User session control + Kontrola sesji użytkownika + + + Do you really want to log off <b>ALL</b> users? + Czy na pewno chcesz wylogować WSZYSTKICH użytkowników? @@ -4002,11 +4686,11 @@ Typically this is required to support terminal servers. Not enough arguments given - use "%1 help" for more information - + Podano za mało argumentów - użyj „%1 help”, aby uzyskać więcej informacji Unknown result! - + Nieznany wynik! Available modules: @@ -4018,63 +4702,71 @@ Typically this is required to support terminal servers. Plugin not licensed - + Nielicencjonowana wtyczka INFO - + INFORMACJA ERROR - - - - licensed for - + BŁĄD USAGE - + UŻYCIE DESCRIPTION - + OPIS EXAMPLES - + PRZYKŁADY WARNING + OSTRZEŻENIE + + + Authentication test + Test uwierzytelnienia + + + Screen %1 - VeyonServiceControl + VeyonMaster - Veyon Service - Usługa Veyon + No write access + Brak prawa edycji + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Nie można zapisać ustawień osobistych! Sprawdź ścieżkę pliku konfiguracji użytkownika za pomocą Konfiguratora %1. - VncView + VeyonServiceControl - Establishing connection to %1 ... - Nawiązywanie połączenia z %1 + Veyon Service + Usługa Veyon WindowsPlatformConfiguration Could not change the setting for SAS generation by software. Sending Ctrl+Alt+Del via remote control will not work! - + Nie można zmienić ustawienia systemowego Zdalne wywołanie Ctrl + Alt + Del nie działa! WindowsPlatformConfigurationPage Windows - + Windows General @@ -4086,26 +4778,50 @@ Typically this is required to support terminal servers. Screen lock - + blokada ekranu Hide taskbar - + Ukryj pasek zadań Hide start menu - + Ukryj Menu Start Hide desktop - + Ukryj pulpit User authentication - + Uwierzytelnianie użytkownika Use alternative user authentication mechanism + Użyj alternatywnego mechanizmu uwierzytelniania użytkownika + + + User login + Login użytkownika + + + Input start delay + Opóźnienie rozpoczęcia pisania + + + Simulated key presses interval + Interwał naciskania klawiszy + + + Confirm legal notice (message displayed before user logs in) + Potwierdź informację prawną (komunikat wyświetlany przed zalogowaniem się użytkownika) + + + Use input device interception driver + Użyj sterownika przechwytywania urządzenia wejściowego + + + Use custom power scheme with disabled power button @@ -4113,10 +4829,10 @@ Typically this is required to support terminal servers. WindowsPlatformPlugin Plugin implementing abstract functions for the Windows platform - + Wtyczka dodająca specyficzne funkcje dla platformy Windows - Plugin implementing specific functions for the Windows platform + Internal display @@ -4124,30 +4840,34 @@ Typically this is required to support terminal servers. WindowsServiceControl The service "%1" is already installed. - + Usługa „%1” jest już zainstalowana. - The service "%1" could not be installed. - + The service "%1" has been installed successfully. + Usługa „%1” została pomyślnie zainstalowana. - The service "%1" has been installed successfully. - + The service "%1" has been uninstalled successfully. + Usługa „%1” została pomyślnie odinstalowana. + + + Service "%1" could not be found. + Nie można znaleźć usługi „%1”. - The service "%1" could not be uninstalled. + The service "%1" could not be installed (error %2). - The service "%1" has been uninstalled successfully. + Could not change the failure actions config for service "%1" (error %2). - The start type of service "%1" could not be changed. + The service "%1" could not be uninstalled (error %2). - Service "%1" could not be found. + The start type of service "%1" could not be changed (error %2). @@ -4159,11 +4879,11 @@ Typically this is required to support terminal servers. Custom x11vnc parameters: - + Niestandardowe parametry x11vnc: Do not use X Damage extension - + Nie używaj rozszerzenia X Damage \ No newline at end of file diff --git a/translations/pt_BR.ts b/translations/veyon_pt_BR.ts similarity index 70% rename from translations/pt_BR.ts rename to translations/veyon_pt_BR.ts index dcfc878d1..365fc339c 100644 --- a/translations/pt_BR.ts +++ b/translations/veyon_pt_BR.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -80,10 +80,6 @@ Se você tem interesse em traduzir o Veyon para o seu idioma local, ou outro idi All groups Todos os grupos - - ... - ... - Access control rules Regras de controle de acesso @@ -134,22 +130,21 @@ Se você tem interesse em traduzir o Veyon para o seu idioma local, ou outro idi Enable usage of domain groups - + Habilitar o uso de grupos de domínio User groups backend: - - - - Missing user groups backend - + Back-end dos grupos de usuários: - No default user groups plugin was found. Please check your installation! - + Restrict access to members of specific user groups + Restringir acesso para membros de determinados grupos + + + AccessControlProvider - Restrict access to members of specific user groups + Provider for access control features @@ -179,30 +174,10 @@ Se você tem interesse em traduzir o Veyon para o seu idioma local, ou outro idi Rule description: Descrição da regra: - - Invert all conditions ("is/has" interpreted as "is/has not") - Inverter todas as condições - Conditions Condições - - is member of group - é membro do grupo - - - Accessing computer is localhost - O computador acessando é localhost - - - Accessing user is logged on user - O usuário acessando está logado como usuário - - - Accessing user is already connected - O usuário acessando já está conectado - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. Se mais de uma condição for ativada, todas devem ser atendidas para que a regra seja aplicada (E lógico). Se apenas uma das múltiplas condições tiver que ser atendida (OU lógico), crie múltiplas regras de controle de acesso. @@ -236,31 +211,123 @@ Se você tem interesse em traduzir o Veyon para o seu idioma local, ou outro idi Computador acessando - Local (logged on) user - Usuários locais (logados) + Always process rule and ignore conditions + Sempre processe as regras e ignore as condições - Local computer - Computador local + Accessing computer and local computer + - Always process rule and ignore conditions - Sempre processe as regras e ignore as condições + User being accessed + - No user logged on - Nenhum usuário logado + is logged in locally + + + + is logged in remotely + + + + No user is logged in locally + + + + One or multiple users are logged in locally + - Accessing user has one or more groups in common with local (logged on) user - O acesso ao usuário tem um ou mais grupos em comum com o usuário local (logado) + No user is logged in remotely + - Accessing computer and local computer are at the same location + One or multiple users are logged in remotely is located at + está localizado em + + + is not located at + + + + are located at the same location + + + + are not located the same location + + + + is member of group + é membro do grupo + + + is not member of group + + + + is authenticated via + + + + is not authenticated via + + + + has one or more groups in common with user being accessed + + + + has no groups in common with user being accessed + + + + equals user being accessed + + + + is different from user being accessed + + + + is already connected + + + + is not connected + + + + is local computer + + + + is not local computer + + + + Computer being accessed + + + + Session being accessed is a user session + + + + Session being accessed is a login screen + + + + Local computer is already being accessed + Computador local já está sendo acessado + + + Local computer is not yet being accessed @@ -306,46 +373,48 @@ Se você tem interesse em traduzir o Veyon para o seu idioma local, ou outro idi The access in the given scenario needs permission of the logged on user. O acesso na configuração atual requer a permissão de um usuário logado. - - ERROR: Unknown action - ERRO: Ação desconhecida - Test result Resultado do teste - - - AndroidPlatformConfigurationPage - Android - + Authentication method + Método de autenticação - General - Geral + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + Introdução - - - AuthKeysConfigurationPage - Authentication keys - Chaves de autenticação + Please perform the following steps to set up key file authentication: + Por favor, realize os passos a seguir para configurar a autenticação por arquivo chave: - Introduction - Introdução + 1) Create a key pair on the master computer. + 1) Crie um par de chaves no computador master. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Defina um grupo de acesso, cujos membros devem ter permissão para acessar outros computadores. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Exporte a chave pública e importe ela, com o mesmo nome, nos computadores clientes. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Por favor, consulte o <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Manual de administração do Veyon </a> para mais informações. Key file directories - + Diretórios do arquivo chave Public key file base directory @@ -356,16 +425,22 @@ Se você tem interesse em traduzir o Veyon para o seu idioma local, ou outro idi Diretório base do arquivo de chave privada - ... - ... + Available authentication keys + Chaves de autenticação disponíveis - Available authentication keys - + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Um par de chaves de autenticação consiste em duas chaves criptografadas, uma chave privada e uma chave pública. +A chave privada concede acesso ao computador cliente através do computador master. +É importante que somente usuários autorizados tenham acesso de leitura ao arquivo da chave privada. +A chave pública é usada no computadores clientes para autenticar as requisições de conexão do computador master. Create key pair - + Criar um par de chaves Delete key @@ -381,69 +456,44 @@ Se você tem interesse em traduzir o Veyon para o seu idioma local, ou outro idi Set access group - + Definir grupo de acesso Key files (*.pem) - + Arquivos chaves (*.pem) Authentication key name - + Nome da chave de autenticação Please enter the name of the user group or role for which to create an authentication key pair: - + Por favor insira o nome do grupo de usuários ou função para o qual deseja criar um par de chaves de autenticação: Do you really want to delete authentication key "%1/%2"? - + Tem certeza que deseja deletar a chave de autenticação "%1/%2"? Please select a key to delete! - - - - Please enter the name of the user group or role for which to import the authentication key: - + Por favor, selecione uma chave para deletar! Please select a key to export! - + Por favor, selecione uma chave para exportar! Please select a user group which to grant access to key "%1": - + Por favor, selecione um grupo de usuários para conceder acesso a chave "%1": Please select a key which to set the access group for! - - - - Please perform the following steps to set up key file authentication: - - - - 1) Create a key pair on the master computer. - - - - 2) Set an access group whose members should be allowed to access other computers. - - - - 3) Export the public key and import it on all client computers with the same name. - - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - + Selecione uma chave para a atribuir o grupo de acesso! - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. @@ -459,39 +509,39 @@ The public key is used on client computers to authenticate incoming connection r Invalid key type specified! Please specify "%1" or "%2". - + Chave inválida! Especifique "%1" or "%2". Specified key does not exist! Please use the "list" command to list all installed keys. - + A chave especificada não existe! Use o comando "list" para listar todas as chaves instaladas. One or more key files already exist! Please delete them using the "delete" command. - + Um ou mais arquivos de chave já existem! Exclua-os usando o comando "delete". Creating new key pair for "%1" - + Criando um novo par de chaves para "%1" Failed to create public or private key! - + Falha ao criar uma chave pública o privada! Newly created key pair has been saved to "%1" and "%2". - + O par de chaves recém-criado foi salvo em "%1" e "%2". Could not remove key file "%1"! - + Não foi possível remover o arquivo da chave "%1"! Could not remove key file directory "%1"! - + Não foi possível remover a pasta da chave "%1"! Failed to create directory for output file. - + Falha ao criar a pasta para guardar as chaves. File "%1" already exists. @@ -499,79 +549,79 @@ The public key is used on client computers to authenticate incoming connection r Failed to write output file. - + Falha ao gravar no arquivo. Key "%1/%2" has been exported to "%3" successfully. - + Chave "%1/%2" foi exportada para "%3" com sucesso. Failed read input file. - + Falha ao ler o arquivo. File "%1" does not contain a valid private key! - + O arquivo "%1" não possui uma chave privada válida! File "%1" does not contain a valid public key! - + O arquivo "%1" não possui uma chave pública válida! Failed to create directory for key file. - + Falha ao criar a pasta para o arquivo de chave. Failed to write key file "%1". - + Falha ao escrever no arquivo da chave "%1". Failed to set permissions for key file "%1"! - + Falha ao definir as permissões para o arquivo de chave "%1"! Key "%1/%2" has been imported successfully. Please check file permissions of "%3" in order to prevent unauthorized accesses. - + A chave "%1/%2" foi importada com sucesso. Verifique as permissões de arquivo de "%3" para evitar acessos não autorizados. Failed to convert private key to public key - + Falha ao converter chave privada em chave pública. Failed to create directory for private key file "%1". - + Falha ao criar diretório para o arquivo de chave privada "%1". Failed to save private key in file "%1"! - + Falha ao salvar a chave privada no arquivo "%1"! Failed to set permissions for private key file "%1"! - + Falha ao definir permissões para o arquivo de chave privada "%1"! Failed to create directory for public key file "%1". - + Falha ao criar diretório para o arquivo de chave pública "%1". Failed to save public key in file "%1"! - + Falha ao salvar a chave pública no arquivo "%1"! Failed to set permissions for public key file "%1"! - + Falha ao definir permissões para o arquivo de chave pública "%1"! Failed to set owner of key file "%1" to "%2". - + Falha ao definir o proprietário da chave "%1" para "%2". Failed to set permissions for key file "%1". - + Falha ao definir permissões para o arquivo de chave "%1". Key "%1" is now accessible by user group "%2". - + A chave "%1" agora está acessível ao grupo de usuários "%2". <N/A> @@ -579,14 +629,14 @@ The public key is used on client computers to authenticate incoming connection r Failed to read key file. - + Falha ao ler o arquivo de chave. AuthKeysPlugin Create new authentication key pair - + Criar um novo par de chaves de autenticação Delete authentication key @@ -606,11 +656,11 @@ The public key is used on client computers to authenticate incoming connection r Extract public key from existing private key - + Extrair chave pública de um chave privada existente Set user group allowed to access a key - + Definir grupo de usuários com permissão para acessar uma chave KEY @@ -618,11 +668,11 @@ The public key is used on client computers to authenticate incoming connection r ACCESS GROUP - + GRUPO DE ACESSO This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. - + Este comando ajusta as permissões de acesso ao arquivo <KEY> de modo que apenas o grupo de usuários <ACCESS GROUP> tenha acesso de leitura a ele. NAME @@ -634,35 +684,27 @@ The public key is used on client computers to authenticate incoming connection r This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - + Este comando exporta a chave de autenticação de <KEY> para <FILE>. Se <FILE> não estiver especificado um nome será construído do nome e tipo de <KEY>. This command imports the authentication key <KEY> from <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - + Este comando importa a chave de autenticação de<KEY> de <FILE>. Se <FILE> não tiver um nome especificado será atribuído o nome e tipo de <KEY>. This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - - - - Please specify the command to display help for! - + Este comando lista todas as chaves de autenticação disponíveis no diretório de chaves configurado. Se a opção "%1" for especificada, uma tabela com detalhes da chave será exibida. Alguns detalhes podem estar faltando se uma chave não estiver acessível. devido à falta de permissões de leitura. TYPE - + Tipo PAIR ID - - - - Command line support for managing authentication keys - + ID DO PAR Commands for managing authentication keys - + Comandos para gerenciar chaves de autenticação This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. @@ -676,6 +718,30 @@ The public key is used on client computers to authenticate incoming connection r This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + Os arquivos da chave de autenticação não estão configurados corretamente neste computador. Crie novos arquivos de chave ou mude para um método de autenticação diferente usando o Veyon Configurator. + + + Key file authentication + Autenticação de arquivo de chave + + + Key file + Arquivo da chave + + + Please specify the key name (e.g. "teacher/public") as the first argument. + Por favor, especifique o nome da chave (ex. "Professor/público") como primeiro argumento. + + + Please specify the command to display help for. + Por favor, especifique o comando para o qual quer exibir ajuda. + + + The specified command does not exist or no help is available for it. + O comando especificado não existe ou não possui ajuda disponível. + AuthKeysTableModel @@ -689,30 +755,173 @@ The public key is used on client computers to authenticate incoming connection r Access group - + Grupo de acesso Pair ID - + ID do par - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - Computadores + General + Geral - Name - Nome + Username to bind DN mapping: + Nome de usuário para vincular o mapeamento de DN: - Host address/IP - Endereço do Host/IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + ex.: %usuario%@DOMINIO ou cn=%usuario%,ou=users,dc=examplo,dc=org + + + AuthLdapDialog - MAC address - Endereço MAC + Veyon Logon + Logon Veyon + + + Please enter your domain/LDAP username and password in order to access computers. + Insira seu nome de usuário e senha de domínio/LDAP para acessar os computadores. + + + Username + Nome de usuário + + + Password + Senha + + + Authentication error + Erro de autenticação + + + Logon failed with given username and password. Please try again! + Falha no logon com o nome de usuário e senha fornecidos. Por favor tente novamente! + + + + AuthLogonDialog + + Veyon Logon + Logon Veyon + + + Please enter your username and password in order to access computers. + Por favor digite o seu nome de usuário e senha para poder acessar os computadores. + + + Username + Nome de usuário + + + Password + Senha + + + Authentication error + Erro de autenticação + + + Logon failed with given username and password. Please try again! + Falha no logon com o nome de usuário e senha fornecidos. Por favor tente novamente! + + + + AuthLogonPlugin + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + O nome de usuário ou senha fornecidos estão incorretos. Insira credenciais válidas ou mude para um método de autenticação diferente usando o Veyon Configurator. + + + Logon authentication + Autenticação de logon + + + Logon + Entrar + + + + AuthSimpleDialog + + Veyon Logon + Logon Veyon + + + Please enter the Veyon password: + Por favor, digite a senha do Veyon + + + Authentication error + Erro de autenticação + + + Logon failed with given password. Please try again! + Falha no logon com a senha fornecida. Por favor, tente novamente! + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + A senha fornecida está errada. Digite a senha correta ou mude para um método de autenticação diferente usando o Veyon Configurator. + + + Simple password authentication + Autenticação com senha simples + + + Simple password + Senha simples + + + + AuthenticationPage + + Authentication is set up properly on this computer. + A autenticação está configurada corretamente neste computador. + + + + AuthenticationPageTab + + Enabled + Ativado + + + Test + Teste + + + + BuiltinDirectoryConfiguration + + Builtin directory + Diretório integrado + + + + BuiltinDirectoryConfigurationPage + + Computers + Computadores + + + Name + Nome + + + Host address/IP + Endereço do Host/IP + + + MAC address + Endereço MAC Add new computer @@ -728,30 +937,30 @@ The public key is used on client computers to authenticate incoming connection r Builtin directory - - - - Locations & computers - + Diretório integrado Locations - + Locais Add new location - + Adicionar novo local Remove selected location - + Remover local selecionado + + + New location + Novo local - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + Directory name - New location + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. @@ -759,19 +968,19 @@ The public key is used on client computers to authenticate incoming connection r BuiltinDirectoryPlugin Show help for specific command - + Exibir ajuda para o comando específico Import objects from given file - + Importar objetos de arquivo Export objects to given file - + Exportar objetos para arquivo Invalid type specified. Valid values are "%1" or "%2". - + Tipo inválido especificado. Os valores válidos são "%1" ou "%2". Type @@ -783,7 +992,7 @@ The public key is used on client computers to authenticate incoming connection r Host address - + Ip do host MAC address @@ -791,31 +1000,31 @@ The public key is used on client computers to authenticate incoming connection r Specified object not found. - + Objeto não encontrado. File "%1" does not exist! - + O arquivo "%1" não existe! Can't open file "%1" for reading! - + Não é possível abrir o arquivo "%1" para leitura! Unknown argument "%1". - + Argumento desconhecido "%1". Computer "%1" (host address: "%2" MAC address: "%3") - + Computador "%1" (endereço do host: "%2" endereço MAC: "%3") Unclassified object "%1" with ID "%2" - + Objeto não classificado "%1" com ID "%2" None - + Nenhum Computer @@ -823,27 +1032,27 @@ The public key is used on client computers to authenticate incoming connection r Root - + Root Invalid - + Inválido Error while parsing line %1. - + Erro ao analisar a linha %1. Network object directory which stores objects in local configuration - + Diretório de objetos de rede que armazena objetos em configuração local Commands for managing the builtin network object directory - + Comandos para gerenciar o diretório interno de objetos de rede No format string or regular expression specified! - + Nenhuma string de formato ou expressão regular especificada! Can't open file "%1" for writing! @@ -855,7 +1064,7 @@ The public key is used on client computers to authenticate incoming connection r Object UUID - + Objeto UUID Parent UUID @@ -863,11 +1072,11 @@ The public key is used on client computers to authenticate incoming connection r Add a location or computer - + Adicione uma local ou um computador Clear all locations and computers - + Remova todas as localizações e computadores Dump all or individual locations and computers @@ -899,7 +1108,7 @@ The public key is used on client computers to authenticate incoming connection r LOCATION - + LOCAL FORMAT-STRING-WITH-PLACEHOLDERS @@ -943,7 +1152,7 @@ The public key is used on client computers to authenticate incoming connection r TYPE - + Tipo NAME @@ -967,7 +1176,7 @@ The public key is used on client computers to authenticate incoming connection r OBJECT - + OBJETO Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. @@ -975,7 +1184,7 @@ The public key is used on client computers to authenticate incoming connection r Remove a computer by name - + Remover um computador pelo nome Remove an object by UUID @@ -983,18 +1192,26 @@ The public key is used on client computers to authenticate incoming connection r "Room 01" - + "Sala 01" "Computer 01" - + "Computador 01" HOST ADDRESS - + Endereço host MAC ADDRESS + Endereço MAC + + + The specified command does not exist or no help is available for it. + O comando especificado não existe ou não possui ajuda disponível. + + + Location "%1" not found. @@ -1014,10 +1231,6 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - Servidor/endereço IP: %1 - Active features: %1 Funcionalidades ativas: %1 @@ -1034,10 +1247,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off Computador offline ou desligado - - Service unreachable or not running - Serviço inacessível ou parado - Authentication failed or access denied Falha na autenticação ou acesso negado @@ -1058,6 +1267,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 + + [no user] + + + + Veyon Server unreachable or not running + Servidor Veyon inacessível ou não está sendo executado + + + Name: %1 + + + + Hostname: %1 + Nome do host: %1 + + + unknown + desconhecido + + + IP address: %1 + Endereço IP: %1 + + + Hostname could not be resolved + + + + No features active + Nenhum recurso ativado + ComputerControlServer @@ -1083,12 +1324,23 @@ The public key is used on client computers to authenticate incoming connection r Access control error - + Erro no controle de acesso User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + + Active connections: + Conecções ativas: + + + + ComputerGroupSelector + + Group %1 + + ComputerManager @@ -1106,30 +1358,65 @@ The public key is used on client computers to authenticate incoming connection r Location detection failed - + Falha na detecção do local Computer name;Hostname;User - + Nome do computador;Hostname;Usuário Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + + Logged in since + Conectado desde + + + %1 days + 1% dias + + + 1 day + 1 dia + - ComputerSelectPanel + ComputerMonitoring + + Computers + Computadores + + + Search users and computers + Buscar usuários e computadores + + + Select all + + + + Unselect all + + + + Add to group + + - Computer management - Gerenciamento de computadores + Remove from group + + + + ComputerSelectPanel Computer search Pesquisa de computador Add location - + Adicionar local Save computer/user list @@ -1151,81 +1438,85 @@ The public key is used on client computers to authenticate incoming connection r Could not write the computer and users list to %1! Please check the file access permissions. Não foi possível salvar a lista de computadores e usuários em %1! Verifique as permissões de acesso ao arquivo. + + Search computers + Procurar computadores + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. - Por favor especifique um arquivo existente para importar. + Clear system-wide Veyon configuration + Apagar a configuração Veyon em todo o sistema - Please specify a valid filename for the configuration export. - Por favor especifique um nome valido para o arquivo exportado. + List all configuration keys and values + Listar todas as chaves de configuração e valores - Please specify a valid key. - Por favor especifique uma chave válida. + Import configuration from given file + Importar configuração de um dado arquivo - Specified key does not exist in current configuration! - Chave especificada não existe na configuração atual. + Export configuration to given file + Exportar configuração de um dado arquivo - Please specify a valid value. - Por favor especifique um valor valido. + Read and output configuration value for given key + Valor de configuração de leitura e saída para a chave - Configure Veyon at command line - Configurar Veyon pela linha de comando. + Write given value to given configuration key + Escrever um valor para a chave de configuração - Output file is not writable! - Arquivo de saída não é gravável! + Unset (remove) given configuration key + Remover a chave de configuração - Output directory is not writable! - Diretório de saída não é gravável! + Upgrade and save configuration of program and plugins + Atualize e salve a configuração do programa e plug-ins + + + Please specify an existing configuration file to import. + Por favor especifique um arquivo existente para importar. Configuration file is not readable! O arquivo de configuração não pode ser lido! - Clear system-wide Veyon configuration - Apagar a configuração Veyon em todo o sistema + Please specify a valid filename for the configuration export. + Por favor especifique um nome valido para o arquivo exportado. - List all configuration keys and values - Listar todas as chaves de configuração e valores + Output file is not writable! + Arquivo de saída não é gravável! - Import configuration from given file - Importar configuração de um dado arquivo + Output directory is not writable! + Diretório de saída não é gravável! - Export configuration to given file - Exportar configuração de um dado arquivo + Please specify a valid key. + Por favor especifique uma chave válida. - Read and output configuration value for given key - Valor de configuração de leitura e saída para a chave + Specified key does not exist in current configuration! + Chave especificada não existe na configuração atual. - Write given value to given configuration key - Escrever um valor para a chave de configuração + Please specify a valid value. + Por favor especifique um valor valido. - Unset (remove) given configuration key - Remover a chave de configuração + Configure Veyon at command line + Configurar Veyon pela linha de comando. Commands for managing the configuration of Veyon Comandos para gerenciar a configuração do Veyon - - Upgrade and save configuration of program and plugins - - ConfigurationManager @@ -1243,12 +1534,16 @@ The public key is used on client computers to authenticate incoming connection r Configuration is not writable. Please check your permissions! - + A configuração não é gravável. Por favor, verifique suas permissões! Could not apply platform-specific configuration settings. + + Could not configure the firewall configuration for the %1 Service. + + DemoClient @@ -1279,10 +1574,6 @@ The public key is used on client computers to authenticate incoming connection r Memory limit Limite de memória - - Use multithreading (experimental) - Utilizar multithreading (experimental) - MB MB @@ -1297,15 +1588,19 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running - + Diminua a velocidade das atualizações de miniaturas enquanto a demonstração está em execução + + + Bandwidth limit + Limite de rede + + + MB/s + MB/s DemoFeaturePlugin - - Fullscreen demo - Exibir em tela cheia - Stop demo Parar exibição @@ -1319,16 +1614,60 @@ The public key is used on client computers to authenticate incoming connection r Exibir por transmissão de tela - Demo server - Servidor de exibição + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Neste modo a sua tela está sendo exibida em uma janela em todos os computadores. Os usuários podem mudar para outras janelas como necessário. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - Neste modo a sua tela está sendo exibida em modo tela cheia em todos os computadores enquanto os dispositivos de entrada dos usuários estão travados. + Demo + Demonstração - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - Neste modo a sua tela está sendo exibida em uma janela em todos os computadores. Os usuários podem mudar para outras janelas como necessário. + Share your screen or allow a user to share his screen with other users. + Compartilhe sua tela ou permita que um usuário compartilhe sua tela com outros usuários. + + + Full screen demo + Demonstração em tela inteira + + + Share your own screen in fullscreen mode + Compartilhe sua própria tela em modo de tela inteira + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + Neste modo, sua tela está sendo exibida em modo de tela inteira em todos os computadores enquanto os dispositivos de entrada dos usuários estão bloqueados. + + + Share your own screen in a window + Compartilhe sua própria tela em uma janela + + + Share selected user's screen in fullscreen mode + Compartilhe a tela do usuário selecionado em modo de tela inteira + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + Neste modo, a tela do usuário selecionado é exibida em modo de tela inteira em todos os computadores enquanto os dispositivos de entrada dos usuários estão bloqueados. + + + Share selected user's screen in a window + Compartilhar a tela do usuário selecionado em uma janela + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + Neste modo, a tela do usuário selecionado é exibida em uma janela em todos os computadores. Os usuários podem alternar para outras janelas conforme necessário. + + + Please select a user screen to share. + Selecione uma tela de um usuário para compartilhar. + + + Please select only one user screen to share. + Selecione apenas uma tela de usuário para compartilhar. + + + All screens + Todas as telas @@ -1357,56 +1696,56 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - Programs & websites - + Name + Nome - Predefined programs - + Path + Caminho - Name - Nome + Predefined websites + Sites predefinidos - Path - + Remove selected website + Remover sites selecionados - Add new program - Adicionar novo programa + URL + URL - Remove selected program - Remover programa selecionado + New website + Novo website - Predefined websites - + Applications & websites + Aplicativos & websites - Remove selected website - + Predefined applications + Aplicativos pré-definidos - URL - URL + Add new application + Adicionar novo aplicativo - New program - Novo programa + Remove selected application + Remover aplicativo selecionado - New website - Novo website + Add new website + Adicionar novo website + + + New application + Novo aplicativo DesktopServicesFeaturePlugin - - Run program - Executar programa - Open website Abrir website @@ -1416,27 +1755,31 @@ The public key is used on client computers to authenticate incoming connection r Clique neste botão para abrir um website em todos os computadores. - Start programs and services in user desktop - Iniciar programas e serviços no desktop do usuário + Open website "%1" + Abrir site "%1" - Click this button to run a program on all computers. - Clique neste botão para executar um programa em todos os computadores. + Custom website + Website personalizado - Run program "%1" - Executar programa "%1" + Start application + Iniciar aplicativo - Custom program - + Click this button to start an application on all computers. + Clique nesse botão para iniciar um aplicativo em todos os computadores - Open website "%1" - + Start application "%1" + Iniciar aplicativo "%1" - Custom website + Custom application + Aplicativo customizado + + + Start apps and open websites in user sessions @@ -1448,31 +1791,27 @@ The public key is used on client computers to authenticate incoming connection r Room %1 - + Sala "%1" Please complete all tasks within the next 5 minutes. - + Por favor, complete todas as tarefas nos próximos 5 minutos. Custom website - + Website personalizado Open file manager - + Abrir gerenciador de arquivos Start learning tool - + Iniciar ferramenta de aprendizagem Play tutorial video - - - - Custom program - + Iniciar vídeo tutorial Handout @@ -1480,8 +1819,16 @@ The public key is used on client computers to authenticate incoming connection r Texts to read + Textos para ler + + + generic-student-user + + Custom application + Aplicativo customizado + ExternalVncServer @@ -1506,478 +1853,461 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands - Feature control - Controle de funcionalidades + List names of all available features + - - - FileTransferController - Could not open file "%1" for reading! Please check your permissions! + Show table with details of all available features - - - FileTransferDialog - File transfer + Start a feature on a remote host - Options + Stop a feature on a remote host - Transfer only - + Please specify the command to display help for. + Por favor, especifique o comando para o qual quer exibir ajuda. - Transfer and open file(s) with associated program + Displays a list with the names of all available features. - Transfer and open destination folder + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. - Files - + HOST ADDRESS + Endereço host - Start - + FEATURE + Recurso - Overwrite existing files - + ARGUMENTS + ARGUMENTOS - - - FileTransferPlugin - File transfer + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information - Click this button to transfer files from your computer to all computers. - + Lock the screen + Bloquear a tela - Select one or more files to transfer - + Display a text message + Mostrar uma mensagem de texto - Transfer files to remote computer - + Test message + Mensagem de teste - Received file "%1". - + Start an application + Iniciar um aplicativo - Could not receive file "%1" as it already exists. + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. - Could not receive file "%1" as it could not be opened for writing! - + Unlock the screen + Desbloquear a tela - - - GeneralConfigurationPage - User interface - Interface do usuário + The specified command does not exist or no help is available for it. + O comando especificado não existe ou não possui ajuda disponível. - Language: - Idioma: + Name + Nome - Use system language setting - Usar a configuração de idioma do sistema + Description + Descrição - Veyon - Veyon + Master + Mestre - Logging - Registrando + Service + Serviço - Log file directory - Diretório de arquivo de log + Worker + - ... - ... + UID + - Log level - Nível de log + Plugin + Plugin - Nothing - Nada + Invalid feature name or UID specified + - Only critical messages - Somente mensagens críticas + Error parsing the JSON-encoded arguments: %1 + - Errors and critical messages - Mensagens críticas e de erros + Failed to initialize credentials + - Warnings and errors - Avisos e erros + Could not establish a connection to host %1 + - Information, warnings and errors - Informações, avisos e erros + Failed to send feature control message to host %1 + - Debug messages and everything else - Mensagens de depuração e tudo o mais + Feature-related CLI operations + - Limit log file size - Limite do tamanho do arquivo de log + Commands for controlling features + + + + FileTransferConfigurationPage - Clear all log files - Remover todos os arquivos de log + File transfer + Transferência de arquivo - Log to standard error output - Log para a saída de erro padrão + Directories + Diretórios - Network object directory - Diretório de objetos de rede + Destination directory + Diretório de destino - Backend: - Backend: + Default source directory + Diretório padrão de origem - Update interval: - Intervalo de atualização: + Options + Opções - %1 service - serviço %1 + Remember last source directory + Lembrar último diretório de origem - The %1 service needs to be stopped temporarily in order to remove the log files. Continue? - O serviço %1 precisa ser interrompido temporariamente para remover os arquivos de log. Continuar? + Create destination directory if it does not exist + Crie o diretório de destino se ele não existir + + + FileTransferController - Log files cleared - Arquivos de log limpos + Could not open file "%1" for reading! Please check your permissions! + Não foi possível abrir o arquivo "%1" para leitura! Por favor, verifique suas permissões! + + + FileTransferDialog - All log files were cleared successfully. - Todos os arquivos de log foram limpos com sucesso. + File transfer + Transferência de arquivo - Error - Erro + Options + Opções - Could not remove all log files. - Não foi possível remover todos os arquivos de log. + Transfer only + Apenas transferir - MB - MB + Transfer and open file(s) with associated program + Transferir e abrir arquivo(s) com programa associado - Rotate log files - Rodar arquivos de log + Transfer and open destination folder + Transferir e abrir a pasta de destino - x - x + Files + Arquivos - seconds - segundos - - - Write to logging system of operating system - - - - Authentication - Autenticação - - - Method: - Método: - - - Logon authentication - Autenticação de logon - - - Key file authentication - Autenticação de arquivo de chave - - - Test - Teste - - - Authentication is set up properly on this computer. - - - - Authentication keys are not set up properly on this computer. - + Start + Iniciar - Authentication test - + Overwrite existing files + Sobrescrever arquivos existentes - InternetAccessControlConfigurationPage + FileTransferFileDialog - Internet access control - + Select one or more files to transfer + Selecione um ou mais arquivos para transferir + + + FileTransferPlugin - Backend: - Backend: + File transfer + Transferência de arquivo - General settings - + Click this button to transfer files from your computer to all computers. + Clique neste botão para transferir arquivos de seu computador para todos os computadores. - Backend settings - + Select one or more files to transfer + Selecione um ou mais arquivos para transferir - - - InternetAccessControlPlugin - Block access to the internet - Bloquear acesso à internet + Transfer files to remote computer + Transferir arquivos para computador remoto - Allow access to the internet - Permitir acesso à Internet + Received file "%1". + Arquivo recebido: "%1". - Show help about command - Mostrar ajuda sobre comando + Could not receive file "%1" as it already exists. + Não foi possível receber o arquivo "%1" porque ele já existe. - Block internet - Bloquear internet + Could not receive file "%1" as it could not be opened for writing! + Não foi possível receber o arquivo "%1" porque ele não pôde ser aberto para gravação! + + + GeneralConfigurationPage - Click this button to block access to the internet. - + User interface + Interface do usuário - Unblock internet - Desbloquear internet + Language: + Idioma: - Click this button to allow access to the internet. - + Use system language setting + Usar a configuração de idioma do sistema - Control access to the internet - Controlar acesso à internet + Veyon + Veyon - Commands for controlling access to the internet - + Logging + Registrando - - - LdapBrowseDialog - Browse LDAP - + Log file directory + Diretório de arquivo de log - - - LdapClient - LDAP error description: %1 - Descrição de erro LDAP: %1 + Log level + Nível de log - - - LdapConfigurationPage - Basic settings - Configurações básicas + Nothing + Nada - General - Geral + Only critical messages + Somente mensagens críticas - LDAP server and port - Servidor LDAP e porta + Errors and critical messages + Mensagens críticas e de erros - Bind DN - Bind DN + Warnings and errors + Avisos e erros - Bind password - Senha bind + Information, warnings and errors + Informações, avisos e erros - Anonymous bind - Bind anônimo + Debug messages and everything else + Mensagens de depuração e tudo o mais - Use bind credentials - Utilizar credenciais de bind + Limit log file size + Limite do tamanho do arquivo de log - Base DN - Base DN + Clear all log files + Remover todos os arquivos de log - Fixed base DN - Base DN fixo + Log to standard error output + Log para a saída de erro padrão - e.g. dc=example,dc=org - e.g. dc=exemplo,dc=org + %1 service + serviço %1 - Discover base DN by naming context - Descobrir o DN base por contexto de nomeação + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + O serviço %1 precisa ser interrompido temporariamente para remover os arquivos de log. Continuar? - e.g. namingContexts or defaultNamingContext - e.g. namingContexts ou defaultNamingContext + Log files cleared + Arquivos de log limpos - Environment settings - Configurações de ambiente + All log files were cleared successfully. + Todos os arquivos de log foram limpos com sucesso. - Object trees - Árvores de objeto + Error + Erro - Computer tree - Árvore de computador + Could not remove all log files. + Não foi possível remover todos os arquivos de log. - e.g. OU=Groups - e.g. OU=Grupos + MB + MB - User tree - Árvore de usuário + Rotate log files + Rodar arquivos de log - e.g. OU=Users - e.g. OU=Usuários + x + x - e.g. OU=Computers - e.g. OU=Computadores + Write to logging system of operating system + Grave no sistema de registro do sistema operacional - Group tree - Árvore de grupo + TLS configuration + - Perform recursive search operations in object trees - Executar operações de pesquisa recursivas em árvores de objeto + Use certificate authority for TLS connections + - Object attributes - Atributos de objeto + CA certificate file + - e.g. hwAddress - e.g. hwAddress + ... + ... - e.g. member or memberUid - e.g. member ou memberUid + Host certificate file + - e.g. dNSHostName - e.g. dNSHostName + Host private key file + - Computer MAC address attribute - Atributo de endereço MAC do computador + Style: + Estilo: - Group member attribute - Atributo de membro do grupo + Native + Nativo - e.g. uid or sAMAccountName - e.g. uid ou sAMAccountName + Color scheme: + - Advanced settings - Configurações avançadas + Light + Claro - Optional object filters - Filtros de objeto opcionais + Dark + Escuro - Filter for user groups - FIltro para grupos de usuários + User groups + Grupo de usuários - Filter for users - FIltro para usuários + Backend: + Backend: - Filter for computer groups - Filtro para grupos de computador + Include user groups from domain + - Group member identification - Identificação de membro do grupo + Missing user groups backend + Sem Back-end dos grupos de usuários: - Distinguished name (Samba/AD) - Nome distinto (Samba/AD) + No user groups plugin was found. Please check your installation! + + + + HeadlessVncServer - List all groups of a user - Listar todos os grupos de um usuário + Headless VNC server + + + + LdapBrowseDialog - List all groups of a computer - Listar todos os grupos de um computador + Browse LDAP + Pesquisar LDAP + + + LdapClient - Get computer object by IP address - Obter objeto de computador pelo endereço IP + LDAP error description: %1 + Descrição de erro LDAP: %1 + + + LdapConfiguration LDAP connection failed Falha na conexão LDAP + + Could not connect to the LDAP server. Please check the server parameters. + +%1 + + LDAP bind failed Falha no bind de LDAP + + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + + LDAP bind successful Bind de LDAP bem sucedido @@ -1990,14 +2320,32 @@ The public key is used on client computers to authenticate incoming connection r LDAP base DN test failed Falha no teste de base DN LDAP + + Could not query the configured base DN. Please check the base DN parameter. + +%1 + + LDAP base DN test successful Teste de base DN LDAP bem sucedido + + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + + LDAP naming context test failed Falha no teste de contexto de nomeação LDAP + + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + + LDAP naming context test successful Teste de contexto de nomeação LDAP bem sucedido @@ -2012,65 +2360,101 @@ The public key is used on client computers to authenticate incoming connection r user tree árvore de usuário + + User tree + Árvore de usuário + group tree árvore de grupo + + Group tree + Árvore de grupo + computer tree árvore de computador - Enter username - Digite o nome do usuário + Computer tree + Árvore de computador - Please enter a user login name (wildcards allowed) which to query: - Por favor digite um nome de login de usuário (wildcards permitidos) para ser consultado: + computer group tree + árvore de grupos de computador + + + Computer group tree + Árvore de grupos de computador user objects objetos de usuário - Enter group name - Digite o nome do grupo + User login name attribute + Atributo de nome de login do usuário - Please enter a group name whose members to query: - Por favor digite um nome de um grupo cujos membros devem ser consultados: + group members + Membros do grupo + + + Group member attribute + Atributo de membro do grupo + + + Group not found + Grupo não encontrado + + + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Não foi possível encontrar um grupo com o nome "%1". Por favor verifique o nome do grupo ou o parâmetro de árvore. + + + computer objects + objetos do computador + + + Computer display name attribute + Atributo de nome de exibição do computador + + + Invalid hostname + Hostname inválido - group members - Membros do grupo + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Você configurou nomes de host de computador para serem armazenados como nomes de domínio totalmente qualificados (FQDN), mas inseriu um nome de host sem domínio. - Group not found - Grupo não encontrado + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Você configurou nomes de host de computador para serem armazenados como nomes de host simples sem um nome de domínio, mas inseriu um nome de host com uma parte do nome de domínio. - Could not find a group with the name "%1". Please check the group name or the group tree parameter. - Não foi possível encontrar um grupo com o nome "%1". Por favor verifique o nome do grupo ou o parâmetro de árvore. + Computer hostname attribute + Atributo de hostname do computador - Enter computer name - Digite o nome do computador + computer MAC addresses + endereços MAC dos computadores - computer objects - objetos do computador + Computer MAC address attribute + Atributo de endereço MAC do computador - Enter computer DN - Digite o DN do computador + computer locations + localizações de computador - Please enter the DN of a computer whose MAC address to query: - Por favor digite o DN de um computador cujos endereços MAC devem ser consultados: + Computer location attribute + Atributo de nome de localização do computador - computer MAC addresses - endereços MAC dos computadores + Location name attribute + Atributo de nome de localização users @@ -2080,13 +2464,17 @@ The public key is used on client computers to authenticate incoming connection r user groups grupos de usuários + + computers + computadores + computer groups grupos de computadores - Please enter a user login name whose group memberships to query: - Por favor digite um nome de login cujas associações de grupo devem ser consultadas: + computer containers + groups of user @@ -2096,6 +2484,10 @@ The public key is used on client computers to authenticate incoming connection r User not found Usuário não encontrado + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + Não foi possível encontrar um usuário com o nome "%1". Verifique o nome de usuário ou o parâmetro da árvore do usuário. + groups of computer grupos do computador @@ -2105,21 +2497,51 @@ The public key is used on client computers to authenticate incoming connection r Computador não encontrado - Enter computer IP address - Digite o endereço IP do computador + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Não foi possível encontrar um computador com o nome de host "%1". Verifique o nome do host ou o parâmetro da árvore do computador. - Please enter a computer IP address which to resolve to an computer object: - Por favor digite um endereço de IP que deve ser resolvido para um objeto: + Hostname lookup failed + A pesquisa de nome de host falhou - computers - computadores + Could not lookup hostname for IP address %1. Please check your DNS server settings. + Não foi possível pesquisar o nome do host para o endereço IP "%1". Verifique as configurações do servidor DNS. + + + location entries + + + + Computer groups filter + Filtro de grupos de computadores + + + Computer locations identification + Identificação de localização do computador + + + Filter for computer groups + Filtro para grupos de computador + + + Invalid test value + Valor de teste inválido + + + An empty or invalid value has been supplied for this test. + Um valor vazio ou inválido foi fornecido para este teste. LDAP %1 test failed Falha no teste LDAP %1 + + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + + LDAP %1 test successful Teste LDAP %1 bem sucedido @@ -2128,6 +2550,24 @@ The public key is used on client computers to authenticate incoming connection r The %1 has been queried successfully and %2 entries were found. O %1 foi consultado com sucesso e %2 entradas foram encontradas. + + LDAP test failed + Teste LDAP falhou. + + + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + + + + and + e + + + LDAP test successful + Teste LDAP bem sucedido + %1 %2 have been queried successfully: @@ -2157,538 +2597,484 @@ The public key is used on client computers to authenticate incoming connection r %1 %2 foram consultados com sucesso usando o filtro configurado. - (only if different from group tree) - (apenas se for diferente da árvore de grupo) - - - Computer group tree - Árvore de grupos de computador - - - computer group tree - árvore de grupos de computador - - - Filter for computers - Filtro para computadores - - - e.g. room or computerLab - e.g. sala ou salaDeComputador - - - Integration tests - Testes de integração - - - Computer groups - Grupos de computadores - - - e.g. name or description - e.g. nome ou descrição + LDAP directory + + + + LdapConfigurationPage - Filter for computer containers - Filtro para contêineres de computador + Basic settings + Configurações básicas - Computer containers or OUs - Contêineres de computador ou OUs + General + Geral - Connection security - + LDAP server and port + Servidor LDAP e porta - TLS certificate verification - + Bind DN + Bind DN - System defaults - + Bind password + Senha bind - Never (insecure!) - + Anonymous bind + Bind anônimo - Custom CA certificate file - + Use bind credentials + Utilizar credenciais de bind - None - + Base DN + Base DN - TLS - TLS + Fixed base DN + Base DN fixo - SSL - SSL + e.g. dc=example,dc=org + e.g. dc=exemplo,dc=org - e.g. (objectClass=computer) - + Discover base DN by naming context + Descobrir o DN base por contexto de nomeação - e.g. (objectClass=group) - + e.g. namingContexts or defaultNamingContext + e.g. namingContexts ou defaultNamingContext - e.g. (objectClass=person) - + Environment settings + Configurações de ambiente - e.g. (objectClass=room) or (objectClass=computerLab) - + Object trees + Árvores de objeto - e.g. (objectClass=container) or (objectClass=organizationalUnit) - + Computer tree + Árvore de computador - Could not query the configured base DN. Please check the base DN parameter. - -%1 - + e.g. OU=Groups + e.g. OU=Grupos - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - + User tree + Árvore de usuário - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - + e.g. OU=Users + e.g. OU=Usuários - Certificate files (*.pem) - + e.g. OU=Computers + e.g. OU=Computadores - Could not connect to the LDAP server. Please check the server parameters. - -%1 - + Group tree + Árvore de grupo - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - + Perform recursive search operations in object trees + Executar operações de pesquisa recursivas em árvores de objeto - Encryption protocol - + Object attributes + Atributos de objeto - Computer location attribute - + e.g. hwAddress + e.g. hwAddress - Computer display name attribute - + e.g. member or memberUid + e.g. member ou memberUid - Location name attribute - + e.g. dNSHostName + e.g. dNSHostName - e.g. cn or displayName - + Computer MAC address attribute + Atributo de endereço MAC do computador - Computer locations identification - + Group member attribute + Atributo de membro do grupo - Identify computer locations (e.g. rooms) via: - + e.g. uid or sAMAccountName + e.g. uid ou sAMAccountName - Location attribute in computer objects - + Advanced settings + Configurações avançadas - List all entries of a location - + Optional object filters + Filtros de objeto opcionais - List all locations - + Filter for user groups + FIltro para grupos de usuários - Enter computer display name - + Filter for users + FIltro para usuários - Please enter a computer display name to query: - + Filter for computer groups + Filtro para grupos de computador - Enter computer location name - + Group member identification + Identificação de membro do grupo - Please enter the name of a computer location (wildcards allowed): - + Distinguished name (Samba/AD) + Nome distinto (Samba/AD) - computer locations - + List all groups of a user + Listar todos os grupos de um usuário - Enter location name - + List all groups of a computer + Listar todos os grupos de um computador - Please enter the name of a location whose entries to query: - + Get computer object by IP address + Obter objeto de computador pelo endereço IP - location entries - + Enter username + Digite o nome do usuário - LDAP test failed - + Please enter a user login name (wildcards allowed) which to query: + Por favor digite um nome de login de usuário (wildcards permitidos) para ser consultado: - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - + Enter group name + Digite o nome do grupo - and - + Please enter a group name whose members to query: + Por favor digite um nome de um grupo cujos membros devem ser consultados: - LDAP test successful - + Enter computer name + Digite o nome do computador - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - + Enter computer DN + Digite o DN do computador - Browse - + Please enter the DN of a computer whose MAC address to query: + Por favor digite o DN de um computador cujos endereços MAC devem ser consultados: - Test - Teste + Please enter a user login name whose group memberships to query: + Por favor digite um nome de login cujas associações de grupo devem ser consultadas: - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - + Enter computer IP address + Digite o endereço IP do computador - Computer hostname attribute - + Please enter a computer IP address which to resolve to an computer object: + Por favor digite um endereço de IP que deve ser resolvido para um objeto: - Please enter a computer hostname to query: - + (only if different from group tree) + (apenas se for diferente da árvore de grupo) - Invalid hostname - + Computer group tree + Árvore de grupos de computador - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - + Filter for computers + Filtro para computadores - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - + e.g. room or computerLab + e.g. sala ou salaDeComputador - Could not find a user with the name "%1". Please check the username or the user tree parameter. - + Integration tests + Testes de integração - Enter hostname - + Computer groups + Grupos de computadores - Please enter a computer hostname whose group memberships to query: - + e.g. name or description + e.g. nome ou descrição - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - + Filter for computer containers + Filtro para contêineres de computador - Hostname lookup failed - + Computer containers or OUs + Contêineres de computador ou OUs - Could not lookup hostname for IP address %1. Please check your DNS server settings. - + Connection security + Segurança da conexão - User login name attribute - + TLS certificate verification + Verificação de certificado TLS - Configured attribute for user login name or computer hostname (OpenLDAP) - + System defaults + Padrões do sistems - computer containers - + Never (insecure!) + Nunca (inseguro!) - - - LdapPlugin - Auto-configure the base DN via naming context - Auto-configurar o DN base via contexto de nomeação + Custom CA certificate file + Arquivo personalizado de certificado CA - Query objects from LDAP directory - Objetos de query do diretório LDAP + None + Nenhum - Show help about command - Mostrar ajuda sobre comando + TLS + TLS - Commands for configuring and testing LDAP/AD integration - Comandos para configurar e testar integração LDAP/AD + SSL + SSL - Basic LDAP/AD support for Veyon - + e.g. (objectClass=computer) + ex.: (objectClass=computer) - %1 (load computers and locations from LDAP/AD) - + e.g. (objectClass=group) + ex.: (objectClass=group) - %1 (load users and groups from LDAP/AD) - + e.g. (objectClass=person) + ex.: (objectClass=person) - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - + e.g. (objectClass=room) or (objectClass=computerLab) + ex.: (objectClass=room) or (objectClass=computerLab) - No naming context attribute name given - falling back to configured value. - + e.g. (objectClass=container) or (objectClass=organizationalUnit) + ex.: (objectClass=container) ou (objectClass=organizationalUnit) - Could not query base DN. Please check your LDAP configuration. - + Certificate files (*.pem) + Arquivos de certificados (*.pem) - Configuring %1 as base DN and disabling naming context queries. - + Encryption protocol + Protocolo de encriptação - - - LdapProConfigurationPage - LDAP Pro - + Computer location attribute + Atributo de nome de localização do computador - Instances - + Computer display name attribute + Atributo de nome de exibição do computador - Enter name - + Location name attribute + Atributo de nome de localização - Please enter a name for the instance (can't be changed later!): - + e.g. cn or displayName + Ex.: cn ou displayName - Remove instance - + Computer locations identification + Identificação de localização do computador - Do you really want to remove instance "%1"? + Identify computer locations (e.g. rooms) via: - Configuration for instance "%1" + Location attribute in computer objects - - - LdapProPlugin - Professional LDAP/AD integration for Veyon - + List all entries of a location + Lista todas as entradas de um local - %1 (load computers and locations from LDAP/AD) - + List all locations + Liste todos os locais - %1 (load users and groups from LDAP/AD) - + Enter computer display name + Insira o nome de exibição do computador - - - LicensingConfigurationPage - Licensing - + Please enter a computer display name to query: + Insira um nome de exibição do computador para consultar: - Installed licenses - + Enter computer location name + Insira o nome do local do computador - Add new network range - + Please enter the name of a computer location (wildcards allowed): + Insira o nome de um local de computador (caracteres curinga permitidos): - Remove selected network range - + Enter location name + Insira o nome do local - ID - + Please enter the name of a location whose entries to query: + Insira o nome de um local cujas entradas deseja consultar: - Feature - + Browse + Pesquisar - Valid until - + Test + Teste - Licensee + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - Browse license file - + Computer hostname attribute + Atributo de hostname do computador - Veyon license files (*.vlf) + Please enter a computer hostname to query: - Remove license - + Enter hostname + Insira o nome do host - Do you really want to remove the selected license? + Please enter a computer hostname whose group memberships to query: - <N/A> - <N/A> + User login name attribute + Atributo de nome de login do usuário - Invalid license file + Configured attribute for user login name or computer hostname (OpenLDAP) - Could not open the license file for reading! + Directory name - The selected license file does not contain valid data. + Query options - The selected license file could not be verified. + Query nested user groups (supported by AD only) - The selected license file is not valid for this installation. + Query timeout - The selected license file is expired. - + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - The license is already installed. - + LDAP + LDAP - Information + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + LdapPlugin - Installation ID - + Auto-configure the base DN via naming context + Auto-configurar o DN base via contexto de nomeação - Addons available for licensing - + Query objects from LDAP directory + Objetos de query do diretório LDAP - Addon - + Show help about command + Mostrar ajuda sobre comando - - - LicensingPlugin - Show help for specific command - + Commands for configuring and testing LDAP/AD integration + Comandos para configurar e testar integração LDAP/AD - Show all installed licenses + Basic LDAP/AD support for Veyon - Add license file - + %1 (load computers and locations from LDAP/AD) + % 1 (carregar computadores e locais do LDAP/AD) - Remove installed license - + %1 (load users and groups from LDAP/AD) + %1 (carregar usuários e grupos do LDAP/AD) - -USAGE - -%1 add <LICENSE FILE> - - + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - -USAGE - -%1 remove <LICENSE ID> - - + No naming context attribute name given - falling back to configured value. - No certificate found with given ID + Could not query base DN. Please check your LDAP configuration. - <N/A> - <N/A> + Configuring %1 as base DN and disabling naming context queries. + - Licensing management + Test binding to an LDAP server - Commands for managing license keys + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + O nome de usuário ou senha fornecidos estão incorretos. Insira credenciais válidas ou mude para um método de autenticação diferente usando o Veyon Configurator. + + + LDAP bind @@ -2696,22 +3082,30 @@ USAGE LinuxPlatformConfigurationPage Linux - + Linux Custom PAM service for user authentication - User authentication + User authentication + Autenticação de usuário + + + User sessions + + + + Minimum session lifetime before server start - Session management - + User login + Usuário: - Display manager users + Login key sequence @@ -2721,10 +3115,6 @@ USAGE Plugin implementing abstract functions for the Linux platform Plugin implementando funções abstratas para a plataforma Linux - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2743,14 +3133,14 @@ USAGE Configuration Configuração - - Disable balloon tooltips - Desativar balões tooltip - Show icons only Exibir apenas ícones + + Disable tooltips + + MainWindow @@ -2798,10 +3188,6 @@ USAGE About Qt Sobre o QT - - Authentication impossible - Autenticação impossível - Configuration not writable Configuração não gravável @@ -2862,10 +3248,6 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. O backend de configuração local relatou que a configuração não é gravável! Por favor execute o Configurador %1 com privilégios mais altos. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - Nenhum arquivo de autenticação de chave foi encontrado ou as existentes estão desatualizadas. Por favor crie novos arquivos de chave usando o Configurador %1. Alternativamente, configure a autenticação local usando o Configurador %1. Caso contrário você não poderá acessar computadores usando o %1. - Access denied Acesso negado @@ -2898,10 +3280,6 @@ USAGE Search users and computers Buscar usuários e computadores - - Adjust optimal size - Ajustar janelas e seus tamanhos - Align computers to grid @@ -2946,6 +3324,48 @@ USAGE Locations && computers + + Authentication + Autenticação + + + Adjust size of computer icons automatically + + + + Slideshow + + + + Spotlight + + + + Veyon Master + + + + Locations & computers + Locais e computadores + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + + + + Load computer positions + + + + Save computer positions + + MasterConfigurationPage @@ -2953,10 +3373,6 @@ USAGE Directories Diretórios - - ... - ... - User configuration Configuração de usuário @@ -3041,6 +3457,10 @@ USAGE Only user name + + Only last part of user name + + Only computer name @@ -3090,165 +3510,180 @@ USAGE - Automatically adjust computer thumbnail size + Automatically open computer select panel - Automatically open computer select panel + Use modern user interface (experimental) - - - MonitoringMode - Monitoring - Monitoramento + Thumbnail spacing + - Builtin monitoring mode - Modo de monitoramento embutido + px + px - This mode allows you to monitor all computers at one or more locations. + Hide local session - - - NetworkDiscoveryConfigurationPage - Network discovery - + Auto + Auto - Mode + Thumbnail aspect ratio - Scan network ranges + Automatically adjust computer icon size - e.g. 192.168.1.0/24 + Open feature windows on the same screen as the main window - Scan all subnets of computer + Configuration templates - Scan custom subnet + Image quality in monitoring mode - Scan sessions on local computer + Highest - Test - Teste + High + - Network ranges + Medium - Add new group + Low - Remove selected group + Lowest - Groups + Remote access image quality - First address + Advanced - Last address + Computer name source - Add new network range + Default - Remove selected network range - + Host address + Ip do host + + + Session client address + Endereço do cliente da sessão + + + Session client name + Nome do cliente da sessão - Parallel scans + Session host name - Scan timeout + Session metadata - ms - ms + Full name of user + Nome completo do usuário + + + User login name + Nome de login do usuário - Session scan limit + Computer UID role - Options + Session meta data hash - Reverse lookup discovered IP addresses to host names + Always expand all locations - New location + Image quality - NetworkDiscoveryDirectory + MonitoringMode - Scanning... - + Monitoring + Monitoramento - Discovered computers - + Builtin monitoring mode + Modo de monitoramento embutido - - - NetworkDiscoveryPlugin - Show help for specific command + This mode allows you to monitor all computers at one or more locations. - Scan a subnet + Query application version of the server - -USAGE - -%1 scan [<SUBNET>] - - + Query active features - Network object directory which automatically discovers computers in the network + Query properties of remotely available screens + + + NestedNetworkObjectDirectory - Network discovery (scan network for Veyon clients) + All directories + + + NetworkObjectDirectoryConfigurationPage + + Update interval: + Intervalo de atualização: + - Commands for managing the network discovery directory - + seconds + segundos + + + + NetworkObjectDirectoryConfigurationPageTab + + Enabled + Ativado @@ -3282,34 +3717,46 @@ USAGE Name: + Nome: + + + Website name - PasswordDialog + PluginCommands - Username - Nome de usuário + List names of all installed plugins + - Password - Senha + Show table with details of all installed plugins + - Veyon Logon - Logon Veyon + Name + Nome - Authentication error - Erro de autenticação + Description + Descrição - Logon failed with given username and password. Please try again! - Falha no logon com o nome de usuário e senha fornecidos. Por favor tente novamente! + Version + - Please enter your username and password in order to access computers. - Por favor digite o seu nome de usuário e senha para poder acessar os computadores. + UID + + + + Plugin-related CLI operations + + + + Commands for managing plugins + @@ -3354,17 +3801,13 @@ USAGE Do you really want to reboot the selected computers? Tem certeza que quer reiniciar todos os computadores selecionados? - - Do you really want to power down the selected computer? - Tem certeza que quer desligar os computadores selecionados? - Power on a computer via Wake-on-LAN (WOL) MAC ADDRESS - + Endereço MAC This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. @@ -3372,7 +3815,7 @@ USAGE Please specify the command to display help for! - + Especifique o comando para o qual exibir ajuda! Invalid MAC address specified! @@ -3408,6 +3851,18 @@ USAGE Please save your work and close all programs. + + Do you really want to reboot <b>ALL</b> computers? + + + + Do you really want to power down <b>ALL</b> computers? + + + + Do you really want to power down the selected computers? + + PowerDownTimeInputDialog @@ -3454,14 +3909,25 @@ Please save your work and close all programs. Remote view or control a computer Exibir tela ou controlar um computador - - Please enter the hostname or IP address of the computer to access: - Por favor digite o hostname ou endereço IP do computador para acessar: - Show help about command Mostrar ajuda sobre comando + + Exchange clipboard contents + + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + + + RemoteAccessPage + + Remote access: %1 + + RemoteAccessWidget @@ -3469,6 +3935,10 @@ Please save your work and close all programs. %1 - %2 Remote Access + + %1 - %2 - %3 Remote Access + + RemoteAccessWidgetToolBar @@ -3524,10 +3994,6 @@ Please save your work and close all programs. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - Conectando %1 - Connected. Conectado. @@ -3540,58 +4006,17 @@ Please save your work and close all programs. Exit - - - Routing - - Control internet access by modifying routing table - - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - - - - Add custom route to block internet - - - - Destination - - - - Gateway - - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - Por favor digite os programas ou comandos para executar no(s) computador(s) selecionado(s). Você pode separar múltiplos programas/comandos por linha. - - - Run programs - Executar programas - - - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - e.g. "C:\Arquivos de Programas\VideoLAN\VLC\vlc.exe" - - Name: + Connecting... - Remember and add to program menu + Select screen - e.g. VLC - + All screens + Todas as telas @@ -3612,6 +4037,18 @@ Please save your work and close all programs. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. Com esse botão, você pode bloquear os computadores de todos os usuários para chamar a atenção deles. Nesse modo todos os dispositivos de entrada são travados e as telas são desligadas. + + Lock input devices + + + + Unlock input devices + + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + Screenshot @@ -3627,6 +4064,10 @@ Please save your work and close all programs. Screenshot Captura de tela + + Could not open screenshot file %1 for writing. + + ScreenshotFeaturePlugin @@ -3651,6 +4092,13 @@ Please save your work and close all programs. Tire capturas de tela de computadores e salve-as localmente. + + ScreenshotManagementPage + + Screenshots + Capturas de tela + + ScreenshotManagementPanel @@ -3666,20 +4114,59 @@ Please save your work and close all programs. Computador: - Date: - Data: + Date: + Data: + + + Time: + Hora: + + + Show + Exibir + + + Delete + Excluir + + + Screenshot + Captura de tela + + + Do you really want to delete all selected screenshots? + + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + - Time: - Hora: + Accessing user not member of an authorized user group + - Show - Exibir + User has denied access + - Delete - Excluir + User confirmed access + @@ -3712,14 +4199,6 @@ Please save your work and close all programs. State: Estado: - - Network - Rede - - - Demo server port - Exibir porta do servidor - Enable firewall exception Habilitar exceção de firewall @@ -3728,10 +4207,6 @@ Please save your work and close all programs. Allow connections from localhost only Permitir conexões de localhost apenas - - Internal VNC server port - Porta do servidor VNC interno - VNC server Servidor VNC @@ -3753,68 +4228,140 @@ Please save your work and close all programs. Em execução - Feature manager port - Porta de gerenciador de funcionalidades + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. + - Primary service port - Porta de serviço primário + Show notification on remote connection + - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. + Show notification when an unauthorized access is blocked - Show notification on remote connection + Maximum session count - Multi session mode (for terminal and remote desktop servers) + Network port numbers - Show notification when an unauthorized access is blocked + Veyon server - - - ServiceControl - Starting service %1 + Internal VNC server - Stopping service %1 + Feature manager - Registering service %1 + Demo server + Servidor de exibição + + + Miscellaneous network settings - Unregistering service %1 + Session mode - Service control + Local session mode (single server instance for primary local session) + + + + Active session mode (single server instance for active local or remote session) + + + + Multi session mode (distinct server instance for each local and remote desktop session) + + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + + + + Miscellaneous settings + + + + Disable clipboard synchronization + + + + Session metadata + + + + Content + + + + None + Nenhum + + + Value of an environment variable + + Value of a registry key + + + + Environment variable name: + + + + Registry key name: + + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + Opcionalmente, insira uma expressão regular com uma captura para extrair uma parte do nome do computador e usá-la como nome de exibição do computador. + +Exemplo: [^-]*-(PC[0-9]*) + - ServiceControlPlugin + ServiceControl - Service is running - Serviço em execução + Service control + - Service is not running - Serviço não está em execução + Starting %1 + - Configure and control Veyon service - Configurar e controlar serviço Veyon + Stopping %1 + + + + Restarting %1 + + + + Registering %1 + + + + Unregistering %1 + + + + ServiceControlCommands Register Veyon Service Registrar serviço Veyon @@ -3839,23 +4386,35 @@ Typically this is required to support terminal servers. Query status of Veyon Service Estado de query do Serviço Veyon + + Service is running + Serviço em execução + + + Service is not running + Serviço não está em execução + + + Configure and control Veyon service + Configurar e controlar serviço Veyon + Commands for configuring and controlling Veyon Service Comandos para configurar e controlar o Serviço Veyon - ShellCommandLinePlugin + ShellCommands Run command file File "%1" does not exist! - + O arquivo "%1" não existe! - Interactive shell and script execution for Veyon Control + Interactive shell and script execution for Veyon CLI @@ -3863,6 +4422,92 @@ Typically this is required to support terminal servers. + + SlideshowPanel + + Previous + + + + Start/pause + + + + Next + + + + Duration: + Duração: + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + Adicionar computadores selecionados + + + Remove selected computers + Remover computadores selecionados + + + Update computers in realtime + Atualizar computadores em tempo real + + + Spotlight + + + + Please select at least one computer to add. + Selecione pelo menos um computador para adicionar. + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + + + StartAppDialog + + Start application + Iniciar aplicativo + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + e.g. "C:\Arquivos de Programas\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + + + + Application name + + + + Name: + Nome: + + + e.g. VLC + + + SystemTrayIcon @@ -3899,8 +4544,8 @@ Typically this is required to support terminal servers. Enviar mensagem de texto - Use the field below to type your message which will be sent to all selected users. - Use o campo abaixo para digitar sua mensagem que será enviada para todos os usuários selecionados. + Please enter your message which send to all selected users. + @@ -3948,38 +4593,62 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer + + Maximum CPU usage + Máximo uso de CPU + - UserConfig + UserLoginDialog - No write access - Sem acesso de escrita + User login + Usuário: - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - Não foi possível salvar suas configurações pessoais! Por favor verifique o arquivo de configuração usando o configurador %1. + Please enter a username and password for automatic login on all computers. + Insira um nome de usuário e senha para login automático em todos os computadores. + + + Username + Nome de usuário + + + Password + Senha - UserSessionControl + UserSessionControlPlugin - User session control - Controle de sessão do usuário. + Log in + Entrar + + + Click this button to log in a specific user on all computers. + Clique neste botão para fazer login de um usuário específico em todos os computadores. Log off - + Sair Click this button to log off users from all computers. - + Clique neste botão para fazer logoff de usuários de todos os computadores. Confirm user logoff - + Confirmar logoff Do you really want to log off the selected users? + Você realmente deseja deslogar o usuário selecionado? + + + User session control + Controle de sessão do usuário. + + + Do you really want to log off <b>ALL</b> users? @@ -4019,53 +4688,61 @@ Typically this is required to support terminal servers. No module specified or module not found - available modules are: - + Nenhum módulo especificado ou módulo não encontrado - os módulos disponíveis são: Plugin not licensed - + Plugin não licenciado INFO - + INFORMAÇÃO ERROR - - - - licensed for - + ERRO USAGE - + USO DESCRIPTION - + DESCRIÇÃO EXAMPLES - + EXEMPLOS WARNING + ATENÇÃO + + + Authentication test + Teste de autenticação + + + Screen %1 - VeyonServiceControl + VeyonMaster - Veyon Service - + No write access + Sem acesso de escrita + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Não foi possível salvar suas configurações pessoais! Por favor verifique o arquivo de configuração usando o configurador %1. - VncView + VeyonServiceControl - Establishing connection to %1 ... - Estabelecendo conexão para %1 ... + Veyon Service + @@ -4079,7 +4756,7 @@ Typically this is required to support terminal servers. WindowsPlatformConfigurationPage Windows - + Windows General @@ -4091,26 +4768,50 @@ Typically this is required to support terminal servers. Screen lock - + Bloquear tela Hide taskbar - + Ocultar barra de tarefas Hide start menu - + Ocultar menu iniciar Hide desktop - + Ocultar desktop User authentication - + Autenticação de usuário Use alternative user authentication mechanism + Usar mecanismo de autenticação alternativo + + + User login + Usuário: + + + Input start delay + Inserir delay de início + + + Simulated key presses interval + Intervalo de simulação de pressionamento de teclas + + + Confirm legal notice (message displayed before user logs in) + + + + Use input device interception driver + + + + Use custom power scheme with disabled power button @@ -4121,7 +4822,7 @@ Typically this is required to support terminal servers. Plugin implementando funções abstratas para a plataforma WIndows - Plugin implementing specific functions for the Windows platform + Internal display @@ -4132,27 +4833,31 @@ Typically this is required to support terminal servers. - The service "%1" could not be installed. + The service "%1" has been installed successfully. - The service "%1" has been installed successfully. + The service "%1" has been uninstalled successfully. - The service "%1" could not be uninstalled. + Service "%1" could not be found. + Serviço "%1" não foi encontrado. + + + The service "%1" could not be installed (error %2). - The service "%1" has been uninstalled successfully. + Could not change the failure actions config for service "%1" (error %2). - The start type of service "%1" could not be changed. + The service "%1" could not be uninstalled (error %2). - Service "%1" could not be found. + The start type of service "%1" could not be changed (error %2). diff --git a/translations/pt_PT.ts b/translations/veyon_pt_PT.ts similarity index 76% rename from translations/pt_PT.ts rename to translations/veyon_pt_PT.ts index 8ad1acb43..05b6c40e9 100644 --- a/translations/pt_PT.ts +++ b/translations/veyon_pt_PT.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -80,10 +80,6 @@ Se está interessado em traduzir o Veyon para o seu idioma ou quer melhorar uma All groups Todos os grupos - - ... - ... - Access control rules Regras de controlo do acesso @@ -114,7 +110,7 @@ Se está interessado em traduzir o Veyon para o seu idioma ou quer melhorar uma Please enter a user login name whose access permissions to test: - + Por favor introduza o nome de utilizador cujas permissões serão testadas: Access allowed @@ -134,22 +130,21 @@ Se está interessado em traduzir o Veyon para o seu idioma ou quer melhorar uma Enable usage of domain groups - + Ativar a utilização de grupos de domínio User groups backend: - - - - Missing user groups backend - + Back-end de grupos de utilizador: - No default user groups plugin was found. Please check your installation! - + Restrict access to members of specific user groups + Restringir acesso a membros de grupos de utilizadores específicos + + + AccessControlProvider - Restrict access to members of specific user groups + Provider for access control features @@ -179,33 +174,13 @@ Se está interessado em traduzir o Veyon para o seu idioma ou quer melhorar uma Rule description: Descrição da regra: - - Invert all conditions ("is/has" interpreted as "is/has not") - - Conditions Condições - - is member of group - é membro do grupo - - - Accessing computer is localhost - - - - Accessing user is logged on user - - - - Accessing user is already connected - O utilizador a aceder já está conectado - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. - + Se mais do que uma condição for ativada, cada condição deve ser atendida para que a regra seja aplicada (E lógico). Se apenas uma das várias condições precisar ser atendida (OR lógico), por favor crie várias regras de controle de acesso. Action @@ -221,7 +196,7 @@ Se está interessado em traduzir o Veyon para o seu idioma ou quer melhorar uma Ask logged on user for permission - + Pedir permissão a um utilizador ligado None (rule disabled) @@ -236,31 +211,123 @@ Se está interessado em traduzir o Veyon para o seu idioma ou quer melhorar uma Computador a aceder - Local (logged on) user - + Always process rule and ignore conditions + Processar sempre as regras e ignorar as condições - Local computer - Computador local + Accessing computer and local computer + A aceder ao computador e ao computador local - Always process rule and ignore conditions - Processar sempre as regras e ignorar as condições + User being accessed + Utilizador a ser acedido - No user logged on - + is logged in locally + está ligado localmente - Accessing user has one or more groups in common with local (logged on) user - + is logged in remotely + está ligado remotamente - Accessing computer and local computer are at the same location - + No user is logged in locally + Nenhum utilizador ligado localmente + + + One or multiple users are logged in locally + Um ou vários utilizadores ligados localmente + + + No user is logged in remotely + Nenhum utilizador ligado remotamente + + + One or multiple users are logged in remotely + Um ou vários utilizadores ligados remotamente is located at + está localizado em + + + is not located at + não está localizado em + + + are located at the same location + estão localizados no mesmo local + + + are not located the same location + não estão localizados no mesmo local + + + is member of group + é membro do grupo + + + is not member of group + não é membro do grupo + + + is authenticated via + está autenticado através de + + + is not authenticated via + não está autenticado através de + + + has one or more groups in common with user being accessed + tem um ou mais grupos em comum com o utilizador que está a ser acedido + + + has no groups in common with user being accessed + não tem grupos em comum com o utilizador que está a ser acedido + + + equals user being accessed + é igual ao utilizador que está a ser acedido + + + is different from user being accessed + é diferente do utilizador que está a ser acedido + + + is already connected + já está ligado + + + is not connected + não está ligado + + + is local computer + é um computador local + + + is not local computer + não é um computador local + + + Computer being accessed + Computador a ser acedido + + + Session being accessed is a user session + A sessão a ser acedida é uma sessão de utilizador + + + Session being accessed is a login screen + A sessão a ser acedida é um ecrã de início de sessão + + + Local computer is already being accessed + + + + Local computer is not yet being accessed @@ -284,7 +351,7 @@ Se está interessado em traduzir o Veyon para o seu idioma ou quer melhorar uma Please enter the following user and computer information in order to test the configured ruleset. - + Por favor introduza as seguintes informações de utilizador e computador para poder testar o conjunto de regras configurado. Local user: @@ -296,100 +363,108 @@ Se está interessado em traduzir o Veyon para o seu idioma ou quer melhorar uma The access in the given scenario is allowed. - + O acesso no cenário determinado é permitido. The access in the given scenario is denied. - + O acesso no cenário determinado não é permitido. The access in the given scenario needs permission of the logged on user. - + O acesso no cenário determinado necessita permissão do utilizador ligado. - ERROR: Unknown action - + Test result + Resultado do teste - Test result + Authentication method + Método de autenticação + + + There is no matching rule with a valid action. The access is therefore denied. - AndroidPlatformConfigurationPage + AuthKeysConfigurationWidget - Android - + Introduction + Introdução - General - Geral + Please perform the following steps to set up key file authentication: + Execute as seguintes etapas para configurar a autenticação do ficheiro de chave: - - - AndroidPlatformPlugin - Plugin implementing specific functions for the Android platform - + 1) Create a key pair on the master computer. + 1) Crie um par de chaves no computador principal. - - - AuthKeysConfigurationPage - Authentication keys - + 2) Set an access group whose members should be allowed to access other computers. + 2) Defina um grupo de acesso cujos membros devem ter permissão para aceder a outros computadores. - Introduction - + 3) Export the public key and import it on all client computers with the same name. + 3) Exporte a chave pública e importe-a em todos os computadores clientes com o mesmo nome. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Consulte o <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Manual do Administrador Veyon</a> para mais informação. Key file directories - + Diretório de ficheiros de chave Public key file base directory - + Diretório base de chave pública Private key file base directory - + Diretório base de chave privada - ... - ... + Available authentication keys + Chaves de autenticação disponíveis - Available authentication keys - + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Um par de chaves de autenticação consiste em duas chaves criptográficas acopladas, uma chave privada e uma pública. +Uma chave privada permite que os utilizadores do computador mestre acedam a computadores clientes. +É importante que apenas utilizadores autorizados tenham acesso de leitura ao arquivo de chave privada. +A chave pública é usada em computadores clientes para autenticar solicitações de conexão de entrada. Create key pair - + Criar par de chaves Delete key - + Eliminar chave Import key - + Importar chave Export key - + Exportar chave Set access group - + Definir grupo de acesso Key files (*.pem) - + Ficheiros de chave (*.pem) Authentication key name - + Nome da chave de autenticação Please enter the name of the user group or role for which to create an authentication key pair: @@ -401,15 +476,11 @@ Se está interessado em traduzir o Veyon para o seu idioma ou quer melhorar uma Please select a key to delete! - - - - Please enter the name of the user group or role for which to import the authentication key: - + Por favor selecione uma chave para eliminar! Please select a key to export! - + Por favor selecione uma chave para exportar! Please select a user group which to grant access to key "%1": @@ -420,30 +491,9 @@ Se está interessado em traduzir o Veyon para o seu idioma ou quer melhorar uma - Please perform the following steps to set up key file authentication: - - - - 1) Create a key pair on the master computer. - - - - 2) Set an access group whose members should be allowed to access other computers. - - - - 3) Export the public key and import it on all client computers with the same name. - - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. @@ -451,7 +501,7 @@ The public key is used on client computers to authenticate incoming connection r AuthKeysManager Please check your permissions. - + Por favor verifique as suas permissões. Key name contains invalid characters! @@ -471,7 +521,7 @@ The public key is used on client computers to authenticate incoming connection r Creating new key pair for "%1" - + A criar um novo par de chaves para "%1" Failed to create public or private key! @@ -495,7 +545,7 @@ The public key is used on client computers to authenticate incoming connection r File "%1" already exists. - + O ficheiro "%1" já existe. Failed to write output file. @@ -575,7 +625,7 @@ The public key is used on client computers to authenticate incoming connection r <N/A> - + <N/D> Failed to read key file. @@ -586,7 +636,7 @@ The public key is used on client computers to authenticate incoming connection r AuthKeysPlugin Create new authentication key pair - + Criar novo par de chaves de autenticação Delete authentication key @@ -614,11 +664,11 @@ The public key is used on client computers to authenticate incoming connection r KEY - + CHAVE ACCESS GROUP - + GRUPO DE ACESSO This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. @@ -626,11 +676,11 @@ The public key is used on client computers to authenticate incoming connection r NAME - + NOME FILE - + FICHEIRO This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. @@ -645,35 +695,51 @@ The public key is used on client computers to authenticate incoming connection r - Please specify the command to display help for! + TYPE + TIPO + + + PAIR ID + ID DO PAR + + + Commands for managing authentication keys - TYPE + This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. - PAIR ID + This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. - Command line support for managing authentication keys + This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. - Commands for managing authentication keys + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. - This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. + Key file authentication - This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. + Key file - This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + Please specify the key name (e.g. "teacher/public") as the first argument. + + + + Please specify the command to display help for. + + + + The specified command does not exist or no help is available for it. @@ -681,114 +747,257 @@ The public key is used on client computers to authenticate incoming connection r AuthKeysTableModel Name - + Nome Type - + Tipo Access group - + Grupo de acesso Pair ID - + ID do par - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - + General + Geral - Name + Username to bind DN mapping: - Host address/IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + AuthLdapDialog - MAC address - + Veyon Logon + Logon do Veyon - Add new computer + Please enter your domain/LDAP username and password in order to access computers. - Remove selected computer - + Username + Nome de utilizador - New computer - + Password + Palavra-passe - Builtin directory - + Authentication error + Erro de autenticação - Locations & computers + Logon failed with given username and password. Please try again! + + + AuthLogonDialog - Locations - + Veyon Logon + Logon do Veyon - Add new location + Please enter your username and password in order to access computers. - Remove selected location - + Username + Nome de utilizador - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - + Password + Palavra-passe - New location + Authentication error + Erro de autenticação + + + Logon failed with given username and password. Please try again! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Import objects from given file - + Logon authentication + Autenticação de logon - Export objects to given file - + Logon + Logon + + + AuthSimpleDialog - Invalid type specified. Valid values are "%1" or "%2". + Veyon Logon + Logon do Veyon + + + Please enter the Veyon password: + Por favor introduza a palavra-passe do Veyon + + + Authentication error + Erro de autenticação + + + Logon failed with given password. Please try again! + + + AuthSimplePlugin - Type + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. - Name + Simple password authentication - Host address + Simple password + + + + + AuthenticationPage + + Authentication is set up properly on this computer. + + + + + AuthenticationPageTab + + Enabled + + + + Test + Teste + + + + BuiltinDirectoryConfiguration + + Builtin directory + + + + + BuiltinDirectoryConfigurationPage + + Computers + Computadores + + + Name + Nome + + + Host address/IP MAC address + Endereço MAC + + + Add new computer + Adicionar computador novo + + + Remove selected computer + + + + New computer + Computador novo + + + Builtin directory + + + + Locations + Localizações + + + Add new location + Adicionar localização nova + + + Remove selected location + + + + New location + Localização nova + + + Directory name + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + + + + BuiltinDirectoryPlugin + + Show help for specific command + + + + Import objects from given file + + + + Export objects to given file + + + + Invalid type specified. Valid values are "%1" or "%2". + + Type + Tipo + + + Name + Nome + + + Host address + Endereço do anfitrião + + + MAC address + Endereço MAC + Specified object not found. @@ -815,19 +1024,19 @@ The public key is used on client computers to authenticate incoming connection r None - + Nenhum Computer - + Computador Root - + Raiz Invalid - + Inválido Error while parsing line %1. @@ -895,11 +1104,11 @@ The public key is used on client computers to authenticate incoming connection r FILE - + FICHEIRO LOCATION - + LOCALIZAÇÃO FORMAT-STRING-WITH-PLACEHOLDERS @@ -943,15 +1152,15 @@ The public key is used on client computers to authenticate incoming connection r TYPE - + TIPO NAME - + NOME PARENT - + PARENTE Adds an object where %1 can be one of "%2" or "%3". %4 can be specified by name or UUID. @@ -959,15 +1168,15 @@ The public key is used on client computers to authenticate incoming connection r Add a room - + Adicionar uma sala Add a computer to room %1 - + Adicionar um computador à sala %1 OBJECT - + OBJETO Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. @@ -983,20 +1192,28 @@ The public key is used on client computers to authenticate incoming connection r "Room 01" - + "Sala 01" "Computer 01" - + "Computador 01" HOST ADDRESS - + ENDEREÇO DO ANFITRIÃO MAC ADDRESS + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. + + BuiltinUltraVncServer @@ -1014,10 +1231,6 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - - Active features: %1 @@ -1034,10 +1247,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off - - Service unreachable or not running - - Authentication failed or access denied @@ -1058,6 +1267,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 + + [no user] + + + + Veyon Server unreachable or not running + + + + Name: %1 + + + + Hostname: %1 + + + + unknown + + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + ComputerControlServer @@ -1067,7 +1308,7 @@ The public key is used on client computers to authenticate incoming connection r Authentication error - + Erro de autenticação Remote access @@ -1089,6 +1330,17 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + + Active connections: + + + + + ComputerGroupSelector + + Group %1 + + ComputerManager @@ -1116,13 +1368,48 @@ The public key is used on client computers to authenticate incoming connection r Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + + Logged in since + + + + %1 days + + + + 1 day + + - ComputerSelectPanel + ComputerMonitoring + + Computers + Computadores + + + Search users and computers + + + + Select all + + + + Unselect all + + + + Add to group + + - Computer management + Remove from group + + + ComputerSelectPanel Computer search @@ -1151,79 +1438,83 @@ The public key is used on client computers to authenticate incoming connection r Could not write the computer and users list to %1! Please check the file access permissions. + + Search computers + + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. + Clear system-wide Veyon configuration - Please specify a valid filename for the configuration export. + List all configuration keys and values - Please specify a valid key. + Import configuration from given file - Specified key does not exist in current configuration! + Export configuration to given file - Please specify a valid value. + Read and output configuration value for given key - Configure Veyon at command line + Write given value to given configuration key - Output file is not writable! + Unset (remove) given configuration key - Output directory is not writable! + Upgrade and save configuration of program and plugins - Configuration file is not readable! + Please specify an existing configuration file to import. - Clear system-wide Veyon configuration + Configuration file is not readable! - List all configuration keys and values + Please specify a valid filename for the configuration export. - Import configuration from given file + Output file is not writable! - Export configuration to given file + Output directory is not writable! - Read and output configuration value for given key + Please specify a valid key. - Write given value to given configuration key + Specified key does not exist in current configuration! - Unset (remove) given configuration key + Please specify a valid value. - Commands for managing the configuration of Veyon + Configure Veyon at command line - Upgrade and save configuration of program and plugins + Commands for managing the configuration of Veyon @@ -1249,6 +1540,10 @@ The public key is used on client computers to authenticate incoming connection r Could not apply platform-specific configuration settings. + + Could not configure the firewall configuration for the %1 Service. + + DemoClient @@ -1279,10 +1574,6 @@ The public key is used on client computers to authenticate incoming connection r Memory limit - - Use multithreading (experimental) - - MB @@ -1299,13 +1590,17 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running + + Bandwidth limit + + + + MB/s + + DemoFeaturePlugin - - Fullscreen demo - Demonstração em ecrã inteiro - Stop demo @@ -1319,15 +1614,59 @@ The public key is used on client computers to authenticate incoming connection r - Demo server + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. + Demo - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Share your screen or allow a user to share his screen with other users. + + + + Full screen demo + + + + Share your own screen in fullscreen mode + + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share your own screen in a window + + + + Share selected user's screen in fullscreen mode + + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share selected user's screen in a window + + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + + + + Please select only one user screen to share. + + + + All screens @@ -1357,86 +1696,90 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - Programs & websites + Name + Nome + + + Path - Predefined programs + Predefined websites - Name + Remove selected website - Path + URL - Add new program + New website - Remove selected program + Applications & websites - Predefined websites + Predefined applications - Remove selected website + Add new application - URL + Remove selected application - New program + Add new website - New website + New application DesktopServicesFeaturePlugin - Run program + Open website - Open website + Click this button to open a website on all computers. - Click this button to open a website on all computers. + Open website "%1" - Start programs and services in user desktop + Custom website - Click this button to run a program on all computers. + Start application - Run program "%1" + Click this button to start an application on all computers. - Custom program + Start application "%1" - Open website "%1" + Custom application - Custom website + Start apps and open websites in user sessions @@ -1471,15 +1814,19 @@ The public key is used on client computers to authenticate incoming connection r - Custom program + Handout + + + + Texts to read - Handout + generic-student-user - Texts to read + Custom application @@ -1506,525 +1853,538 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands - Feature control + List names of all available features - - - FileTransferController - Could not open file "%1" for reading! Please check your permissions! + Show table with details of all available features - - - FileTransferDialog - File transfer + Start a feature on a remote host - Options + Stop a feature on a remote host - Transfer only + Please specify the command to display help for. - Transfer and open file(s) with associated program + Displays a list with the names of all available features. - Transfer and open destination folder + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. - Files - + HOST ADDRESS + ENDEREÇO DO ANFITRIÃO - Start + FEATURE - Overwrite existing files + ARGUMENTS - - - FileTransferPlugin - File transfer + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information - Click this button to transfer files from your computer to all computers. + Lock the screen - Select one or more files to transfer + Display a text message - Transfer files to remote computer + Test message - Received file "%1". + Start an application - Could not receive file "%1" as it already exists. + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. - Could not receive file "%1" as it could not be opened for writing! + Unlock the screen - - - GeneralConfigurationPage - User interface + The specified command does not exist or no help is available for it. - Language: - + Name + Nome - Use system language setting + Description - Veyon - + Master + Principal - Logging + Service - Log file directory + Worker - ... - ... + UID + - Log level + Plugin - Nothing + Invalid feature name or UID specified - Only critical messages + Error parsing the JSON-encoded arguments: %1 - Errors and critical messages + Failed to initialize credentials - Warnings and errors + Could not establish a connection to host %1 - Information, warnings and errors + Failed to send feature control message to host %1 - Debug messages and everything else + Feature-related CLI operations - Limit log file size + Commands for controlling features + + + FileTransferConfigurationPage - Clear all log files + File transfer - Log to standard error output + Directories - Network object directory + Destination directory - Backend: + Default source directory - Update interval: + Options - %1 service + Remember last source directory - The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + Create destination directory if it does not exist + + + FileTransferController - Log files cleared + Could not open file "%1" for reading! Please check your permissions! + + + FileTransferDialog - All log files were cleared successfully. + File transfer - Error + Options - Could not remove all log files. + Transfer only - MB + Transfer and open file(s) with associated program - Rotate log files + Transfer and open destination folder - x + Files - seconds + Start - Write to logging system of operating system + Overwrite existing files + + + FileTransferFileDialog - Authentication + Select one or more files to transfer + + + FileTransferPlugin - Method: + File transfer - Logon authentication + Click this button to transfer files from your computer to all computers. - Key file authentication + Select one or more files to transfer - Test - Teste + Transfer files to remote computer + - Authentication is set up properly on this computer. + Received file "%1". - Authentication keys are not set up properly on this computer. + Could not receive file "%1" as it already exists. - Authentication test + Could not receive file "%1" as it could not be opened for writing! - InternetAccessControlConfigurationPage + GeneralConfigurationPage - Internet access control + User interface - Backend: + Language: - General settings + Use system language setting - Backend settings + Veyon - - - InternetAccessControlPlugin - Block access to the internet + Logging - Allow access to the internet + Log file directory - Show help about command + Log level - Block internet + Nothing - Click this button to block access to the internet. + Only critical messages - Unblock internet + Errors and critical messages - Click this button to allow access to the internet. + Warnings and errors - Control access to the internet + Information, warnings and errors - Commands for controlling access to the internet + Debug messages and everything else - - - LdapBrowseDialog - Browse LDAP + Limit log file size - - - LdapClient - LDAP error description: %1 + Clear all log files - - - LdapConfigurationPage - Basic settings + Log to standard error output - General - Geral + %1 service + - LDAP server and port + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? - Bind DN + Log files cleared - Bind password + All log files were cleared successfully. - Anonymous bind + Error - Use bind credentials + Could not remove all log files. - Base DN + MB - Fixed base DN + Rotate log files - e.g. dc=example,dc=org + x - Discover base DN by naming context + Write to logging system of operating system - e.g. namingContexts or defaultNamingContext + TLS configuration - Environment settings + Use certificate authority for TLS connections - Object trees + CA certificate file - Computer tree - + ... + ... - e.g. OU=Groups + Host certificate file - User tree + Host private key file - e.g. OU=Users + Style: - e.g. OU=Computers + Native - Group tree + Color scheme: - Perform recursive search operations in object trees + Light - Object attributes + Dark - e.g. hwAddress + User groups - e.g. member or memberUid + Backend: - e.g. dNSHostName + Include user groups from domain - Computer MAC address attribute - + Missing user groups backend + Back-end de grupos de utilizador em falta - Group member attribute + No user groups plugin was found. Please check your installation! + + + HeadlessVncServer - e.g. uid or sAMAccountName + Headless VNC server + + + LdapBrowseDialog - Advanced settings + Browse LDAP - - Optional object filters + + + LdapClient + + LDAP error description: %1 + + + LdapConfiguration - Filter for user groups + LDAP connection failed - Filter for users + Could not connect to the LDAP server. Please check the server parameters. + +%1 - Filter for computer groups + LDAP bind failed - Group member identification + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 - Distinguished name (Samba/AD) + LDAP bind successful - List all groups of a user + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - List all groups of a computer + LDAP base DN test failed - Get computer object by IP address + Could not query the configured base DN. Please check the base DN parameter. + +%1 - LDAP connection failed + LDAP base DN test successful - LDAP bind failed + The LDAP base DN has been queried successfully. The following entries were found: + +%1 - LDAP bind successful + LDAP naming context test failed - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 - LDAP base DN test failed + LDAP naming context test successful - LDAP base DN test successful + The LDAP naming context has been queried successfully. The following base DN was found: +%1 - LDAP naming context test failed + user tree - LDAP naming context test successful + User tree - The LDAP naming context has been queried successfully. The following base DN was found: -%1 + group tree - user tree + Group tree - group tree + computer tree - computer tree + Computer tree - Enter username - Introduza o nome de utilizador + computer group tree + - Please enter a user login name (wildcards allowed) which to query: + Computer group tree @@ -2032,15 +2392,15 @@ The public key is used on client computers to authenticate incoming connection r - Enter group name - + User login name attribute + Atributo do nome de início de sessão de utilizador - Please enter a group name whose members to query: + group members - group members + Group member attribute @@ -2052,25 +2412,49 @@ The public key is used on client computers to authenticate incoming connection r - Enter computer name + computer objects - computer objects + Computer display name attribute - Enter computer DN + Invalid hostname - Please enter the DN of a computer whose MAC address to query: + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + + + + Computer hostname attribute computer MAC addresses + + Computer MAC address attribute + + + + computer locations + + + + Computer location attribute + + + + Location name attribute + + users @@ -2079,12 +2463,16 @@ The public key is used on client computers to authenticate incoming connection r user groups + + computers + + computer groups - Please enter a user login name whose group memberships to query: + computer containers @@ -2095,6 +2483,10 @@ The public key is used on client computers to authenticate incoming connection r User not found + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + + groups of computer @@ -2104,21 +2496,51 @@ The public key is used on client computers to authenticate incoming connection r - Enter computer IP address + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - Please enter a computer IP address which to resolve to an computer object: + Hostname lookup failed - computers + Could not lookup hostname for IP address %1. Please check your DNS server settings. + + + + location entries + + + + Computer groups filter + + + + Computer locations identification + + + + Filter for computer groups + + + + Invalid test value + + + + An empty or invalid value has been supplied for this test. LDAP %1 test failed + + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + + LDAP %1 test successful @@ -2127,6 +2549,24 @@ The public key is used on client computers to authenticate incoming connection r The %1 has been queried successfully and %2 entries were found. + + LDAP test failed + + + + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + + + + and + + + + LDAP test successful + + %1 %2 have been queried successfully: @@ -2152,15 +2592,210 @@ The public key is used on client computers to authenticate incoming connection r - (only if different from group tree) + LDAP directory + + + LdapConfigurationPage - Computer group tree + Basic settings - computer group tree + General + Geral + + + LDAP server and port + + + + Bind DN + + + + Bind password + + + + Anonymous bind + + + + Use bind credentials + + + + Base DN + + + + Fixed base DN + + + + e.g. dc=example,dc=org + + + + Discover base DN by naming context + + + + e.g. namingContexts or defaultNamingContext + + + + Environment settings + + + + Object trees + + + + Computer tree + + + + e.g. OU=Groups + + + + User tree + + + + e.g. OU=Users + + + + e.g. OU=Computers + + + + Group tree + + + + Perform recursive search operations in object trees + + + + Object attributes + + + + e.g. hwAddress + + + + e.g. member or memberUid + + + + e.g. dNSHostName + + + + Computer MAC address attribute + + + + Group member attribute + + + + e.g. uid or sAMAccountName + + + + Advanced settings + + + + Optional object filters + + + + Filter for user groups + + + + Filter for users + + + + Filter for computer groups + + + + Group member identification + + + + Distinguished name (Samba/AD) + + + + List all groups of a user + + + + List all groups of a computer + + + + Get computer object by IP address + + + + Enter username + Introduza o nome de utilizador + + + Please enter a user login name (wildcards allowed) which to query: + Introduza um nome de início de sessão de utilizador (caracter * permitido) que deseja consultar: + + + Enter group name + + + + Please enter a group name whose members to query: + + + + Enter computer name + + + + Enter computer DN + + + + Please enter the DN of a computer whose MAC address to query: + + + + Please enter a user login name whose group memberships to query: + Introduza um nome de início de sessão de utilizador cujas associações de grupo que deseja consultar: + + + Enter computer IP address + + + + Please enter a computer IP address which to resolve to an computer object: + + + + (only if different from group tree) + + + + Computer group tree @@ -2213,7 +2848,7 @@ The public key is used on client computers to authenticate incoming connection r None - + Nenhum TLS @@ -2243,40 +2878,10 @@ The public key is used on client computers to authenticate incoming connection r e.g. (objectClass=container) or (objectClass=organizationalUnit) - - Could not query the configured base DN. Please check the base DN parameter. - -%1 - - - - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - - - - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - - Certificate files (*.pem) - - Could not connect to the LDAP server. Please check the server parameters. - -%1 - - - - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - - Encryption protocol @@ -2334,1527 +2939,1565 @@ The public key is used on client computers to authenticate incoming connection r - computer locations + Enter location name - Enter location name + Please enter the name of a location whose entries to query: - Please enter the name of a location whose entries to query: + Browse - location entries + Test + Teste + + + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - LDAP test failed + Computer hostname attribute - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 + Please enter a computer hostname to query: - and + Enter hostname - LDAP test successful + Please enter a computer hostname whose group memberships to query: - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 + User login name attribute + Atributo do nome de início de sessão de utilizador + + + Configured attribute for user login name or computer hostname (OpenLDAP) + Atributo configurado para o nome de início de sessão do utilizador ou o nome de host do computador (OpenLDAP) + + + Directory name - Browse + Query options - Test - Teste + Query nested user groups (supported by AD only) + - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Query timeout - Computer hostname attribute + ms + + + LdapNetworkObjectDirectoryConfigurationPage - Please enter a computer hostname to query: + LDAP + + + + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + + + LdapPlugin + + Auto-configure the base DN via naming context + + + + Query objects from LDAP directory + + + + Show help about command + + + + Commands for configuring and testing LDAP/AD integration + + + + Basic LDAP/AD support for Veyon + + + + %1 (load computers and locations from LDAP/AD) + + + + %1 (load users and groups from LDAP/AD) + + + + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + + + + No naming context attribute name given - falling back to configured value. + + + + Could not query base DN. Please check your LDAP configuration. - Invalid hostname + Configuring %1 as base DN and disabling naming context queries. - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Test binding to an LDAP server - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Could not find a user with the name "%1". Please check the username or the user tree parameter. + LDAP bind + + + LinuxPlatformConfigurationPage - Enter hostname + Linux - Please enter a computer hostname whose group memberships to query: + Custom PAM service for user authentication - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - + User authentication + Autenticação de utilizador - Hostname lookup failed + User sessions - Could not lookup hostname for IP address %1. Please check your DNS server settings. + Minimum session lifetime before server start - User login name attribute - + User login + Início de sessão de utilizador - Configured attribute for user login name or computer hostname (OpenLDAP) - + Login key sequence + Sequência de chaves de início de sessão + + + LinuxPlatformPlugin - computer containers + Plugin implementing abstract functions for the Linux platform - LdapPlugin + LocationDialog - Auto-configure the base DN via naming context + Select location - Query objects from LDAP directory + enter search filter... + + + MainToolBar - Show help about command + Configuration - Commands for configuring and testing LDAP/AD integration + Show icons only - Basic LDAP/AD support for Veyon + Disable tooltips + + + MainWindow - %1 (load computers and locations from LDAP/AD) - + MainWindow + Janela Principal - %1 (load users and groups from LDAP/AD) - + toolBar + Barra de Farementas - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - + General + Geral - No naming context attribute name given - falling back to configured value. + &File - Could not query base DN. Please check your LDAP configuration. + &Help - Configuring %1 as base DN and disabling naming context queries. + &Quit - - - LdapProConfigurationPage - LDAP Pro + Ctrl+Q - Instances + Ctrl+S - Enter name + L&oad settings from file - Please enter a name for the instance (can't be changed later!): + Ctrl+O - Remove instance + About Qt - Do you really want to remove instance "%1"? + Configuration not writable - Configuration for instance "%1" + Load settings from file - - - LdapProPlugin - Professional LDAP/AD integration for Veyon + Save settings to file - %1 (load computers and locations from LDAP/AD) + Unsaved settings - %1 (load users and groups from LDAP/AD) + There are unsaved settings. Quit anyway? - - - LicensingConfigurationPage - Licensing + Veyon Configurator - Installed licenses + Service - Add new network range - + Master + Principal - Remove selected network range + Access control - ID - + About Veyon + Sobre o Veyon - Feature + Auto - Valid until - + About + Sobre - Licensee + %1 Configurator %2 - Browse license file + JSON files (*.json) - Veyon license files (*.vlf) + The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - Remove license - + Access denied + Acesso negado - Do you really want to remove the selected license? + According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. - <N/A> + Screenshots - Invalid license file + Feature active - Could not open the license file for reading! + The feature "%1" is still active. Please stop it before closing %2. - The selected license file does not contain valid data. + Reset configuration - The selected license file could not be verified. + Do you really want to reset the local configuration and revert all settings to their defaults? - The selected license file is not valid for this installation. + Search users and computers - The selected license file is expired. + Align computers to grid - The license is already installed. + %1 Configurator - Information + Insufficient privileges - Installation ID + Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. - Addons available for licensing + Only show powered on computers - Addon + &Save settings to file - - - LicensingPlugin - Show help for specific command + &View - Show all installed licenses + &Standard - Add license file + &Advanced - Remove installed license + Use custom computer arrangement - -USAGE - -%1 add <LICENSE FILE> - - + Locations && computers - -USAGE - -%1 remove <LICENSE ID> - - + Authentication - No certificate found with given ID + Adjust size of computer icons automatically - <N/A> + Slideshow - Licensing management + Spotlight - Commands for managing license keys - + Veyon Master + Veyon Principal - - - LinuxPlatformConfigurationPage - Linux + Locations & computers - Custom PAM service for user authentication + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. - User authentication + Only show computers with logged on users - Session management + Load computer positions - Display manager users + Save computer positions - LinuxPlatformPlugin + MasterConfigurationPage - Plugin implementing abstract functions for the Linux platform + Directories - Plugin implementing specific functions for the Linux platform + User configuration - - - LocationDialog - Select location + Feature on computer double click: - enter search filter... + Features - - - MainToolBar - Configuration + All features - Disable balloon tooltips + Disabled features - Show icons only + Screenshots - - - MainWindow - MainWindow - Janela Principal + <no feature> + - toolBar - Barra de Farementas + Basic settings + - General - Geral + Behaviour + - &File + Enforce selected mode for client computers - &Help + Hide local computer - &Quit + Hide computer filter field - Ctrl+Q + Actions such as rebooting or powering down computers - Ctrl+S + User interface - L&oad settings from file + Background color - Ctrl+O + Thumbnail update interval - About Qt + ms - Authentication impossible + Program start - Configuration not writable + Modes and features - Load settings from file + User and computer name - Save settings to file + Only user name - Unsaved settings + Only last part of user name - There are unsaved settings. Quit anyway? + Only computer name - Veyon Configurator + Computer thumbnail caption - Service + Text color - Master + Sort order - Access control + Computer and user name - About Veyon - Sobre o Veyon + Computer locations + - Auto + Show current location only - About - Sobre + Allow adding hidden locations manually + - %1 Configurator %2 + Hide empty locations - JSON files (*.json) + Show confirmation dialog for potentially unsafe actions - The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. + Perform access control - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. + Automatically select current location - Access denied - Acesso negado + Automatically open computer select panel + - According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. + Use modern user interface (experimental) - Screenshots + Thumbnail spacing - Feature active + px - The feature "%1" is still active. Please stop it before closing %2. + Hide local session - Reset configuration + Auto - Do you really want to reset the local configuration and revert all settings to their defaults? + Thumbnail aspect ratio - Search users and computers + Automatically adjust computer icon size - Adjust optimal size + Open feature windows on the same screen as the main window - Align computers to grid + Configuration templates - %1 Configurator + Image quality in monitoring mode - Insufficient privileges + Highest - Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + High - Only show powered on computers + Medium - &Save settings to file + Low - &View + Lowest - &Standard + Remote access image quality - &Advanced + Advanced - Use custom computer arrangement + Computer name source - Locations && computers + Default - - - MasterConfigurationPage - Directories - + Host address + Endereço do anfitrião - ... - ... + Session client address + - User configuration + Session client name - Feature on computer double click: + Session host name - Features + Session metadata - All features + Full name of user - Disabled features + User login name - Screenshots + Computer UID role - <no feature> + Session meta data hash - Basic settings + Always expand all locations - Behaviour + Image quality + + + MonitoringMode - Enforce selected mode for client computers + Monitoring - Hide local computer + Builtin monitoring mode - Hide computer filter field + This mode allows you to monitor all computers at one or more locations. - Actions such as rebooting or powering down computers + Query application version of the server - User interface + Query active features - Background color + Query properties of remotely available screens + + + NestedNetworkObjectDirectory - Thumbnail update interval + All directories + + + NetworkObjectDirectoryConfigurationPage - ms + Update interval: - Program start + seconds + + + NetworkObjectDirectoryConfigurationPageTab - Modes and features + Enabled + + + NetworkObjectTreeModel - User and computer name + Locations/Computers + + + OpenWebsiteDialog - Only user name + Open website - Only computer name + e.g. Veyon - Computer thumbnail caption + Remember and add to website menu - Text color + e.g. www.veyon.io - Sort order + Please enter the URL of the website to open: - Computer and user name + Name: - Computer locations + Website name + + + PluginCommands - Show current location only + List names of all installed plugins - Allow adding hidden locations manually + Show table with details of all installed plugins - Hide empty locations - + Name + Nome - Show confirmation dialog for potentially unsafe actions + Description - Perform access control + Version - Automatically select current location + UID - Automatically adjust computer thumbnail size + Plugin-related CLI operations - Automatically open computer select panel + Commands for managing plugins - MonitoringMode + PowerControlFeaturePlugin - Monitoring - + Power on + Ligar - Builtin monitoring mode + Click this button to power on all computers. This way you do not have to power on each computer by hand. - This mode allows you to monitor all computers at one or more locations. + Reboot + Reiniciar + + + Click this button to reboot all computers. - - - NetworkDiscoveryConfigurationPage - Network discovery + Power down + Desligar + + + Click this button to power down all computers. This way you do not have to power down each computer by hand. - Mode + Power on/down or reboot a computer - Scan network ranges + Confirm reboot - e.g. 192.168.1.0/24 + Confirm power down - Scan all subnets of computer + Do you really want to reboot the selected computers? - Scan custom subnet + Power on a computer via Wake-on-LAN (WOL) - Scan sessions on local computer + MAC ADDRESS - Test - Teste + This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. + - Network ranges + Please specify the command to display help for! - Add new group + Invalid MAC address specified! - Remove selected group + Commands for controlling power status of computers - Groups + Power down now - First address + Install updates and power down - Last address + Power down after user confirmation - Add new network range + Power down after timeout - Remove selected network range + The computer was remotely requested to power down. Do you want to power down the computer now? - Parallel scans + The computer will be powered down in %1 minutes, %2 seconds. + +Please save your work and close all programs. - Scan timeout + Do you really want to reboot <b>ALL</b> computers? - ms + Do you really want to power down <b>ALL</b> computers? - Session scan limit + Do you really want to power down the selected computers? + + + PowerDownTimeInputDialog - Options + Power down + Desligar + + + Please specify a timeout for powering down the selected computers: - Reverse lookup discovered IP addresses to host names + minutes - New location + seconds - NetworkDiscoveryDirectory + RemoteAccessFeaturePlugin - Scanning... + Remote view - Discovered computers + Open a remote view for a computer without interaction. - - - NetworkDiscoveryPlugin - Show help for specific command + Remote control + Controlo remoto + + + Open a remote control window for a computer. - Scan a subnet + Remote access - -USAGE - -%1 scan [<SUBNET>] - - + Remote view or control a computer - Network object directory which automatically discovers computers in the network + Show help about command - Network discovery (scan network for Veyon clients) + Exchange clipboard contents - Commands for managing the network discovery directory + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: - NetworkObjectTreeModel + RemoteAccessPage - Locations/Computers + Remote access: %1 - OpenWebsiteDialog + RemoteAccessWidget - Open website + %1 - %2 Remote Access - e.g. Veyon + %1 - %2 - %3 Remote Access + + + RemoteAccessWidgetToolBar - Remember and add to website menu + View only - e.g. www.veyon.io - + Remote control + Controlo remoto - Please enter the URL of the website to open: + Send shortcut - Name: + Fullscreen - - - PasswordDialog - Username - + Window + Janela - Password + Ctrl+Alt+Del - Veyon Logon + Ctrl+Esc - Authentication error + Alt+Tab - Logon failed with given username and password. Please try again! + Alt+F4 - Please enter your username and password in order to access computers. + Win+Tab - - - PowerControlFeaturePlugin - - Power on - Ligar - - Click this button to power on all computers. This way you do not have to power on each computer by hand. + Win - Reboot - Reiniciar + Menu + - Click this button to reboot all computers. + Alt+Ctrl+F1 - Power down - Desligar + Connected. + Ligado - Click this button to power down all computers. This way you do not have to power down each computer by hand. + Screenshot - Power on/down or reboot a computer + Exit - Confirm reboot + Connecting... - Confirm power down + Select screen - Do you really want to reboot the selected computers? + All screens + + + ScreenLockFeaturePlugin - Do you really want to power down the selected computer? + Lock - Power on a computer via Wake-on-LAN (WOL) + Unlock - MAC ADDRESS + Lock screen and input devices of a computer - This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. - Please specify the command to display help for! + Lock input devices - Invalid MAC address specified! + Unlock input devices - Commands for controlling power status of computers + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + + Screenshot - Power down now + unknown - Install updates and power down + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. - Power down after user confirmation + Screenshot - Power down after timeout + Could not open screenshot file %1 for writing. + + + ScreenshotFeaturePlugin - The computer was remotely requested to power down. Do you want to power down the computer now? + Screenshot - The computer will be powered down in %1 minutes, %2 seconds. - -Please save your work and close all programs. + Use this function to take a screenshot of selected computers. - - - PowerDownTimeInputDialog - Power down - Desligar + Screenshots taken + - Please specify a timeout for powering down the selected computers: + Screenshot of %1 computer have been taken successfully. - minutes + Take screenshots of computers and save them locally. + + + ScreenshotManagementPage - seconds + Screenshots - RemoteAccessFeaturePlugin + ScreenshotManagementPanel - Remote view + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. - Open a remote view for a computer without interaction. + User: - Remote control - Controlo remoto + Computer: + - Open a remote control window for a computer. + Date: - Remote access + Time: - Remote view or control a computer + Show - Please enter the hostname or IP address of the computer to access: + Delete - Show help about command + Screenshot - - - RemoteAccessWidget - %1 - %2 Remote Access + Do you really want to delete all selected screenshots? - RemoteAccessWidgetToolBar + ServerAccessControlManager - View only + Requested authentication method not available - Remote control - Controlo remoto - - - Send shortcut + Access allowed by rule "%1" - Fullscreen + Access denied by rule "%1" - Window - Janela - - - Ctrl+Alt+Del + No rule allowed access - Ctrl+Esc + Accessing user not member of an authorized user group - Alt+Tab + User has denied access - Alt+F4 + User confirmed access + + + ServiceConfigurationPage - Win+Tab - + General + Geral - Win + Autostart - Menu + Hide tray icon - Alt+Ctrl+F1 + Start service - Connecting %1 - Ligando %1 - - - Connected. - Ligado - - - Screenshot + Stopped - Exit + Stop service - - - Routing - Control internet access by modifying routing table + State: - - - RoutingConfigurationWidget - Remove default routes to block internet access + Enable firewall exception - Add custom route to block internet + Allow connections from localhost only - Destination + VNC server - Gateway + Plugin: - - - RunProgramDialog - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. + Restart %1 Service - Run programs + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + Running - Name: + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. - Remember and add to program menu + Show notification on remote connection - e.g. VLC + Show notification when an unauthorized access is blocked - - - ScreenLockFeaturePlugin - Lock + Maximum session count - Unlock + Network port numbers - Lock screen and input devices of a computer + Veyon server - To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + Internal VNC server - - - Screenshot - unknown + Feature manager - Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + Demo server - Screenshot + Miscellaneous network settings - - - ScreenshotFeaturePlugin - Screenshot + Session mode - Use this function to take a screenshot of selected computers. + Local session mode (single server instance for primary local session) - Screenshots taken + Active session mode (single server instance for active local or remote session) - Screenshot of %1 computer have been taken successfully. + Multi session mode (distinct server instance for each local and remote desktop session) - Take screenshots of computers and save them locally. + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. - - - ScreenshotManagementPanel - All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + Miscellaneous settings - User: + Disable clipboard synchronization - Computer: + Session metadata - Date: + Content - Time: - + None + Nenhum - Show + Value of an environment variable - Delete + Value of a registry key - - - ServiceConfigurationPage - General - Geral + Environment variable name: + - Autostart + Registry key name: - Hide tray icon + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + + + ServiceControl - Start service + Service control - Stopped + Starting %1 - Stop service + Stopping %1 - State: + Restarting %1 - Network + Registering %1 - Demo server port + Unregistering %1 + + + ServiceControlCommands - Enable firewall exception + Register Veyon Service - Allow connections from localhost only + Unregister Veyon Service - Internal VNC server port + Start Veyon Service - VNC server + Stop Veyon Service - Plugin: + Restart Veyon Service - Restart %1 Service + Query status of Veyon Service - All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + Service is running - Running + Service is not running - Feature manager port + Configure and control Veyon service - Primary service port + Commands for configuring and controlling Veyon Service + + + ShellCommands - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. + Run command file - Show notification on remote connection + File "%1" does not exist! - Multi session mode (for terminal and remote desktop servers) + Interactive shell and script execution for Veyon CLI - Show notification when an unauthorized access is blocked + Commands for shell functionalities - ServiceControl + SlideshowPanel - Starting service %1 + Previous - Stopping service %1 + Start/pause - Registering service %1 + Next - Unregistering service %1 + Duration: - Service control + View in separate window - - - ServiceControlPlugin - Service is running + %1 Master – Slideshow + + + SpotlightPanel - Service is not running + Add selected computers - Configure and control Veyon service + Remove selected computers - Register Veyon Service + Update computers in realtime - Unregister Veyon Service + Spotlight - Start Veyon Service + Please select at least one computer to add. - Stop Veyon Service + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + StartAppDialog - Restart Veyon Service + Start application - Query status of Veyon Service + Please enter the applications to start on the selected computers. You can separate multiple applications by line. - Commands for configuring and controlling Veyon Service + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - - - ShellCommandLinePlugin - Run command file + Remember and add to application menu - File "%1" does not exist! + Application name - Interactive shell and script execution for Veyon Control + Name: - Commands for shell functionalities + e.g. VLC @@ -3894,7 +4537,7 @@ Typically this is required to support terminal servers. Enviar mensagem de texto - Use the field below to type your message which will be sent to all selected users. + Please enter your message which send to all selected users. @@ -3943,27 +4586,43 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer + + Maximum CPU usage + + - UserConfig + UserLoginDialog - No write access - + User login + Início de sessão de utilizador - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - + Please enter a username and password for automatic login on all computers. + Por favor introduza o nome de utilizador e palavra-passe para início de sessão automático em todos os computadores. + + + Username + Nome de utilizador + + + Password + Palavra-passe - UserSessionControl + UserSessionControlPlugin - User session control + Log in + Iniciar sessão + + + Click this button to log in a specific user on all computers. Log off - + Terminar sessão Click this button to log off users from all computers. @@ -3977,16 +4636,24 @@ Typically this is required to support terminal servers. Do you really want to log off the selected users? + + User session control + + + + Do you really want to log off <b>ALL</b> users? + Tem a certeza que quer terminar a sessão de <b>TODOS</b> os utilizadores? + VeyonCore [OK] - + [OK] [FAIL] - + [FALHA] Invalid command! @@ -4010,7 +4677,7 @@ Typically this is required to support terminal servers. Available modules: - + Módulos disponíveis No module specified or module not found - available modules are: @@ -4022,45 +4689,53 @@ Typically this is required to support terminal servers. INFO - + INFO ERROR - - - - licensed for - + ERRO USAGE - + USO DESCRIPTION - + DESCRIÇÃO EXAMPLES - + EXEMPLOS WARNING - + AVISO + + + Authentication test + Teste de autenticação + + + Screen %1 + Ecrã %1 - VeyonServiceControl + VeyonMaster - Veyon Service + No write access + + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - VncView + VeyonServiceControl - Establishing connection to %1 ... - + Veyon Service + Serviço Veyon @@ -4074,7 +4749,7 @@ Typically this is required to support terminal servers. WindowsPlatformConfigurationPage Windows - + Windows General @@ -4086,28 +4761,52 @@ Typically this is required to support terminal servers. Screen lock - + Bloquear ecrã Hide taskbar - + Ocultar a barra de tarefas Hide start menu - + Ocultar o menú iniciar Hide desktop - + Ocultar o ambiente de trabalho User authentication - + Autenticação de utilizador Use alternative user authentication mechanism + + User login + Início de sessão de utilizador + + + Input start delay + + + + Simulated key presses interval + + + + Confirm legal notice (message displayed before user logs in) + + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4116,7 +4815,7 @@ Typically this is required to support terminal servers. - Plugin implementing specific functions for the Windows platform + Internal display @@ -4127,27 +4826,31 @@ Typically this is required to support terminal servers. - The service "%1" could not be installed. + The service "%1" has been installed successfully. + + + + The service "%1" has been uninstalled successfully. - The service "%1" has been installed successfully. + Service "%1" could not be found. - The service "%1" could not be uninstalled. + The service "%1" could not be installed (error %2). - The service "%1" has been uninstalled successfully. + Could not change the failure actions config for service "%1" (error %2). - The start type of service "%1" could not be changed. + The service "%1" could not be uninstalled (error %2). - Service "%1" could not be found. + The start type of service "%1" could not be changed (error %2). diff --git a/translations/ru.ts b/translations/veyon_ru.ts similarity index 70% rename from translations/ru.ts rename to translations/veyon_ru.ts index b86bb29ec..9bb9c0cf7 100644 --- a/translations/ru.ts +++ b/translations/veyon_ru.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -35,7 +35,7 @@ If you're interested in translating Veyon into your local or another language or want to improve an existing translation, please contact a Veyon developer! Перевод на данный язык ещё не осуществлён. -Если Вы желаете добавить перевод программы Veyon на новый язык или улучшить уже существующий, пожалуйста, свяжитесь с разработчиками Veyon! +Чтобы добавить перевод программы Veyon на новый язык или улучшить уже существующий, пожалуйста, свяжитесь с разработчиками Veyon! About %1 %2 @@ -66,7 +66,7 @@ If you're interested in translating Veyon into your local or another langua User groups authorized for computer access - Группы пользователей, разрешенные для доступа к компьютеру + Группы пользователей, которым разрешён доступ к компьютерам Please add the groups whose members should be authorized to access computers in your Veyon network. @@ -74,16 +74,12 @@ If you're interested in translating Veyon into your local or another langua Authorized user groups - Разрешенные группы пользователей + Разрешённые группы пользователей All groups Все группы - - ... - ... - Access control rules Правила контроля доступа @@ -118,7 +114,7 @@ If you're interested in translating Veyon into your local or another langua Access allowed - Доступ разрешен + Доступ разрешён The specified user is allowed to access computers with this configuration. @@ -140,19 +136,18 @@ If you're interested in translating Veyon into your local or another langua User groups backend: Группы пользователей: - - Missing user groups backend - Отсутствующие группы пользователей - - - No default user groups plugin was found. Please check your installation! - Не был найден плагин по умолчанию для пользовательских групп. Проверьте свою установку! - Restrict access to members of specific user groups Ограничить доступ участникам указанных групп пользователей + + AccessControlProvider + + Provider for access control features + Поставщик функций контроля доступа + + AccessControlRuleEditDialog @@ -179,30 +174,10 @@ If you're interested in translating Veyon into your local or another langua Rule description: Описание правила: - - Invert all conditions ("is/has" interpreted as "is/has not") - Инвертировать все условия («быть / иметь» интерпретируется как «не быть / не иметь») - Conditions Условия - - is member of group - является членом группы - - - Accessing computer is localhost - Доступ к компьютеру как localhost - - - Accessing user is logged on user - Доступ к пользователю осуществляется пользователем - - - Accessing user is already connected - Доступ к пользователю уже подключен - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. Если активировано более одного условия, каждое условие должно соответствовать для применения правила (логическое И). Если требуется только одно из нескольких условий (логическое ИЛИ), создайте несколько правил контроля доступа. @@ -236,33 +211,125 @@ If you're interested in translating Veyon into your local or another langua Доступ к компьютеру - Local (logged on) user - Локальный (вошедший в систему) пользователь + Always process rule and ignore conditions + Всегда обрабатывать правило и игнорировать условия - Local computer - Локальный компьютер + Accessing computer and local computer + Доступ к компьютеру и локальный компьютер - Always process rule and ignore conditions - Всегда обрабатывать правило и игнорировать условия + User being accessed + Пользователь для доступа - No user logged on - Пользователь не вошел + is logged in locally + вошёл в систему локально - Accessing user has one or more groups in common with local (logged on) user - Доступ к пользователю имеет одна или несколько групп, совместно с локальным пользователем (вошедшим в систему) + is logged in remotely + вошёл в систему удалённо - Accessing computer and local computer are at the same location - Компьютер для доступа расположен в том же месте, что и локальный компьютер + No user is logged in locally + Нет пользователей, вошедших в систему локально + + + One or multiple users are logged in locally + Один или несколько пользователей вошли в систему локально + + + No user is logged in remotely + Нет пользователей, вошедших в систему удалённо + + + One or multiple users are logged in remotely + Один или несколько пользователей вошли в систему удалённо is located at расположен в + + is not located at + не расположен в + + + are located at the same location + расположены в одном и том же месте + + + are not located the same location + не расположены в одном и том же месте + + + is member of group + является членом группы + + + is not member of group + не является членом группы + + + is authenticated via + аутентифицирован с помощью + + + is not authenticated via + не аутентифицирован с помощью + + + has one or more groups in common with user being accessed + входит в одну или несколько групп, членом которых является пользователь для доступа + + + has no groups in common with user being accessed + не входит ни в одну из групп, членом которых является пользователь для доступа + + + equals user being accessed + совпадает с пользователем для доступа + + + is different from user being accessed + отличается от пользователя для доступа + + + is already connected + уже подключён + + + is not connected + не подключён + + + is local computer + является локальным компьютером + + + is not local computer + не является локальным компьютером + + + Computer being accessed + Компьютер для доступа + + + Session being accessed is a user session + Сеанс для доступа является сеансом пользователя + + + Session being accessed is a login screen + Сеанс для доступа является экраном входа + + + Local computer is already being accessed + К локальному компьютеру уже осуществляется доступ + + + Local computer is not yet being accessed + Локальный компьютер пока недоступен + AccessControlRulesTestDialog @@ -292,11 +359,11 @@ If you're interested in translating Veyon into your local or another langua Connected users: - Подключенные пользователи: + Подключённые пользователи: The access in the given scenario is allowed. - Доступ в данном сценарии разрешен. + Доступ в данном сценарии разрешён. The access in the given scenario is denied. @@ -306,42 +373,44 @@ If you're interested in translating Veyon into your local or another langua The access in the given scenario needs permission of the logged on user. Доступ в данном сценарии требует разрешения зарегистрированного пользователя. - - ERROR: Unknown action - ОШИБКА: Неизвестное действие - Test result Результат испытаний - - - AndroidPlatformConfigurationPage - Android - + Authentication method + Метод проверки подлинности - General - Главное + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + Вступление - - - AuthKeysConfigurationPage - Authentication keys - Ключи аутентификации + Please perform the following steps to set up key file authentication: + Для настройки проверки подлинности ключа выполните следующие действия: - Introduction - Вступление + 1) Create a key pair on the master computer. + 1) Создайте ключевую пару на главном компьютере. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Установите группу доступа, члены которой должны иметь доступ к другим компьютерам. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Экспортируйте открытый ключ и импортируйте его на всех клиентских компьютерах с тем же именем. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Дополнительную информацию см.<a href="https://veyon.readthedocs.io/en/latest/admin/index.html">В Руководстве администратора Veyon</a>. Key file directories @@ -355,14 +424,20 @@ If you're interested in translating Veyon into your local or another langua Private key file base directory Каталог, содержащий закрытые ключи - - ... - ... - Available authentication keys Доступные ключи аутентификации + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Ключевая пара аутентификации состоит из двух связанных криптографических ключей, частного и открытого ключа. +Закрытый ключ позволяет пользователям на главном компьютере обращаться к клиентским компьютерам. +Важно, чтобы только авторизованные пользователи имели доступ к чтению в файл закрытого ключа. +Открытый ключ используется на клиентских компьютерах для аутентификации входящего запроса на соединение. + Create key pair Создать ключевую пару @@ -397,57 +472,31 @@ If you're interested in translating Veyon into your local or another langua Do you really want to delete authentication key "%1/%2"? - Вы действительно хотите удалить ключ аутентификации «%1/%2»? + Действительно удалить ключ аутентификации "%1/%2"? Please select a key to delete! Выберите ключ для удаления! - - Please enter the name of the user group or role for which to import the authentication key: - Введите имя группы пользователей или роли, для которой необходимо импортировать ключ аутентификации: - Please select a key to export! Выберите ключ для экспорта! Please select a user group which to grant access to key "%1": - Выберите группу пользователей, которая предоставит доступ к ключу «%1»: + Выберите группу пользователей, которая предоставит доступ к ключу "%1": Please select a key which to set the access group for! Выберите ключ, для которого необходимо установить группу доступа! - Please perform the following steps to set up key file authentication: - Для настройки проверки подлинности ключа выполните следующие действия: - - - 1) Create a key pair on the master computer. - 1) Создайте ключевую пару на главном компьютере. - - - 2) Set an access group whose members should be allowed to access other computers. - 2) Установите группу доступа, члены которой должны иметь доступ к другим компьютерам. - - - 3) Export the public key and import it on all client computers with the same name. - 3) Экспортируйте открытый ключ и импортируйте его на всех клиентских компьютерах с тем же именем. - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - Дополнительную информацию см.<a href="https://veyon.readthedocs.io/en/latest/admin/index.html">В Руководстве администратора Veyon</a>. - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - Ключевая пара аутентификации состоит из двух связанных криптографических ключей, частного и открытого ключа. -Закрытый ключ позволяет пользователям на главном компьютере обращаться к клиентским компьютерам. -Важно, чтобы только авторизованные пользователи имели доступ к чтению в файл закрытого ключа. -Открытый ключ используется на клиентских компьютерах для аутентификации входящего запроса на соединение. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + Введите имя группы пользователей или роли, для которой необходимо импортировать ключ аутентификации. + +Убедитесь, что имена ключей, принадлежащих друг другу, идентичны на всех компьютерах. @@ -462,19 +511,19 @@ The public key is used on client computers to authenticate incoming connection r Invalid key type specified! Please specify "%1" or "%2". - Указан недопустимый тип ключа! Укажите «%1» или «%2». + Указан недопустимый тип ключа! Укажите "%1" или "%2". Specified key does not exist! Please use the "list" command to list all installed keys. - Указанный ключ не существует! Пожалуйста, используйте команду «list», чтобы перечислить все установленные ключи. + Указанный ключ не существует! Пожалуйста, используйте команду "list", чтобы перечислить все установленные ключи. One or more key files already exist! Please delete them using the "delete" command. - Один или несколько ключевых файлов уже существуют! Удалите их, используя команду «удалить». + Один или несколько ключевых файлов уже существуют! Удалите их, используя команду "удалить". Creating new key pair for "%1" - Создание новой ключевой пары для «%1» + Создание новой ключевой пары для "%1" Failed to create public or private key! @@ -534,7 +583,7 @@ The public key is used on client computers to authenticate incoming connection r Key "%1/%2" has been imported successfully. Please check file permissions of "%3" in order to prevent unauthorized accesses. - Ключ "%1/%2» был успешно импортирован. Пожалуйста, проверьте права доступа к файлу "%3», чтобы предотвратить неуполномоченный доступ. + Ключ "%1/%2" был успешно импортирован. Пожалуйста, проверьте права доступа к файлу "%3", чтобы предотвратить неуполномоченный доступ. Failed to convert private key to public key @@ -645,11 +694,7 @@ The public key is used on client computers to authenticate incoming connection r This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - Эта команда выводит список всех ключей аутентификации в настроенном каталоге ключей. Если выбрана опция "%1", то вместо списка будет выведена таблица с подробностями про ключи. Некоторые параметры ключа могут быть не показаны, если доступ к ключу ограничен, например из-за нехватки прав на чтение файла ключа. - - - Please specify the command to display help for! - Пожалуйста, укажите команду, для которой следует показать справку! + Эта команда выводит список всех ключей аутентификации в настроенном каталоге ключей. Если выбрана опция "%1", то вместо списка будет выведена таблица с подробностями про ключи. Некоторые параметры ключа могут быть не показаны, если доступ к ключу ограничен, например, из-за нехватки прав на чтение файла ключа. TYPE @@ -659,10 +704,6 @@ The public key is used on client computers to authenticate incoming connection r PAIR ID ИД ПАРЫ - - Command line support for managing authentication keys - Поддержка управления ключами аутентификации в командной строке - Commands for managing authentication keys Команды для управления ключами аутентификации @@ -679,6 +720,30 @@ The public key is used on client computers to authenticate incoming connection r This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. Эта команда добывает часть, связанную с открытым ключом, из закрытого ключа <КЛЮЧ> и сохраняет её в соответствующий файла открытого ключа. Поэтому при настройке дополнительного основного компьютера достаточно перенести на него только закрытый ключ. После переноса открытый ключ можно просто добыть. + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + На этом компьютере не настроены должным образом ключи распознавания. Пожалуйста, создайте новые ключи или переключите систему на другой способ распознавания с помощью средства настройки Veyon. + + + Key file authentication + Аутентификация с помощью ключа доступа + + + Key file + Ключевой файл + + + Please specify the key name (e.g. "teacher/public") as the first argument. + Укажите имя ключа (например, "teacher/public") в качестве первого аргумента. + + + Please specify the command to display help for. + Укажите команду, для которой следует показать справку. + + + The specified command does not exist or no help is available for it. + Указанная команда не существует, или для неё недоступна справка. + AuthKeysTableModel @@ -700,93 +765,236 @@ The public key is used on client computers to authenticate incoming connection r - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - Компьютеры + General + Главное - Name - Имя + Username to bind DN mapping: + Имя пользователя для привязки сопоставления DN: - Host address/IP - Адрес хоста/IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + например, %username%@DOMAIN или cn=%username%,ou=users,dc=example,dc=org + + + AuthLdapDialog - MAC address - MAC-адрес + Veyon Logon + Вход в систему Veyon - Add new computer - Добавить новый компьютер + Please enter your domain/LDAP username and password in order to access computers. + Пожалуйста, введите ваш домен/имя пользователя и пароль LDAP для доступа к компьютерам. - Remove selected computer - Удалить выбранный компьютер + Username + Имя пользователя - New computer - Новый компьютер + Password + Пароль - Builtin directory - Встроенный каталог + Authentication error + Ошибка аутенфикации - Locations & computers - Места и компьютеры + Logon failed with given username and password. Please try again! + Не удалось войти, используя указанные имя пользователя и пароль. Пожалуйста, повторите попытку! + + + AuthLogonDialog - Locations - Места + Veyon Logon + Вход в систему Veyon - Add new location - Добавить новое место + Please enter your username and password in order to access computers. + Пожалуйста, введите имя пользователя и пароль для доступа к компьютерам. - Remove selected location - Удалить выделенное место + Username + Имя пользователя + + + Password + Пароль - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - Импорт файлов CSV можно выполнить с помощью интерфейса командной строки. Подробное описание можно найти в <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">интернет-документации</a>. + Authentication error + Ошибка аутенфикации - New location - Новое место + Logon failed with given username and password. Please try again! + Не удалось войти, используя указанные имя пользователя и пароль. Пожалуйста, повторите попытку! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command - Показать справку по определённой команде + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Предоставленое значение имени пользователя и пароля является ошибочным. Пожалуйста, укажите корректные регистрационные данные или переключите систему на другой способ распознавания с помощью средства настройки Veyon. - Import objects from given file - Импортировать объекты из указанного файла + Logon authentication + Аутентификация при входе в систему - Export objects to given file - Экспортировать объекты в указанный файл + Logon + Вход в систему + + + AuthSimpleDialog - Invalid type specified. Valid values are "%1" or "%2". - Указан некорректный тип. Корректными являются значения "%1" и "%2". + Veyon Logon + Вход в систему Veyon - Type - Тип + Please enter the Veyon password: + Пожалуйста, введите пароль Veyon: - Name - Имя + Authentication error + Ошибка аутенфикации - Host address - Адрес хоста + Logon failed with given password. Please try again! + Не удалось войти в систему по указанному паролю. Пожалуйста, повторите попытку! + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + Предоставленое значение пароля является ошибочным. Пожалуйста, укажите действующий пароль или переключите систему на другой способ распознавания с помощью средства настройки Veyon. + + + Simple password authentication + Простое распознавание по паролю + + + Simple password + Простой пароль + + + + AuthenticationPage + + Authentication is set up properly on this computer. + На этом компьютере аутентификация установлена правильно. + + + + AuthenticationPageTab + + Enabled + Включено + + + Test + Тестировать + + + + BuiltinDirectoryConfiguration + + Builtin directory + Встроенный каталог + + + + BuiltinDirectoryConfigurationPage + + Computers + Компьютеры + + + Name + Имя + + + Host address/IP + Адрес хоста/IP + + + MAC address + MAC-адрес + + + Add new computer + Добавить новый компьютер + + + Remove selected computer + Удалить выбранный компьютер + + + New computer + Новый компьютер + + + Builtin directory + Встроенный каталог + + + Locations + Места + + + Add new location + Добавить новое место + + + Remove selected location + Удалить выделенное место + + + New location + Новое место + + + Directory name + Имя каталога + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + Файлы CSV можно импортировать с помощью интерфейса командной строки. Для получения дополнительных сведений ознакомьтесь с <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">документацией в Интернете</a>. + + + + BuiltinDirectoryPlugin + + Show help for specific command + Показать справку по определённой команде + + + Import objects from given file + Импортировать объекты из указанного файла + + + Export objects to given file + Экспортировать объекты в указанный файл + + + Invalid type specified. Valid values are "%1" or "%2". + Указан некорректный тип. Корректными являются значения "%1" и "%2". + + + Type + Тип + + + Name + Имя + + + Host address + Адрес хоста MAC address @@ -1000,6 +1208,14 @@ The public key is used on client computers to authenticate incoming connection r MAC ADDRESS MAC-АДРЕСА + + The specified command does not exist or no help is available for it. + Указанная команда не существует, или для неё недоступна справка. + + + Location "%1" not found. + Местоположение "%1" не найдено. + BuiltinUltraVncServer @@ -1017,17 +1233,13 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - Хост/IP-адрес: %1 - Active features: %1 Задействованные возможности: %1 Online and connected - Онлайн и подключен + Онлайн и подключён Establishing connection @@ -1037,10 +1249,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off Компьютер в автономном режиме или выключен - - Service unreachable or not running - Сервис недоступен или не работает - Authentication failed or access denied Ошибка аутентификации или доступ запрещен @@ -1061,6 +1269,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 Место: %1 + + [no user] + [нет пользователя] + + + Veyon Server unreachable or not running + Сервер Veyon недоступен или не запущен + + + Name: %1 + Имя: %1 + + + Hostname: %1 + Имя хоста: %1 + + + unknown + неизвестный + + + IP address: %1 + IP-адрес: %1 + + + Hostname could not be resolved + Имя хоста не может быть разрешено + + + No features active + Нет активных функций + ComputerControlServer @@ -1092,6 +1332,17 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. Пользователь "%1" на узле "%2" пытался получить доступ к этому компьютеру, но был заблокирован из-за параметров управления доступом. + + Active connections: + Активные соединения: + + + + ComputerGroupSelector + + Group %1 + Группа %1 + ComputerManager @@ -1119,13 +1370,48 @@ The public key is used on client computers to authenticate incoming connection r Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. Не удалось определить место этого компьютера. Это означает, что в настройках системы есть проблемы. На панели выбора компьютера будут показаны все места. + + Logged in since + Вошел в систему с + + + %1 days + %1 дн. + + + 1 day + 1 день + - ComputerSelectPanel + ComputerMonitoring + + Computers + Компьютеры + + + Search users and computers + Поиск пользователей и компьютеров + + + Select all + Выбрать все + + + Unselect all + Отменить выбор всего + + + Add to group + Добавить в группу + - Computer management - Управление компьютером + Remove from group + Удалить из группы + + + ComputerSelectPanel Computer search Компьютерный поиск @@ -1154,81 +1440,85 @@ The public key is used on client computers to authenticate incoming connection r Could not write the computer and users list to %1! Please check the file access permissions. Не удалось записать список компьютеров и пользователей в %1! Пожалуйста, проверьте права доступа к файлу. + + Search computers + Поиск компьютеров + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. - Пожалуйста, укажите существующий файл конфигурации для импорта. + Clear system-wide Veyon configuration + Очистка всей системы Veyon - Please specify a valid filename for the configuration export. - Пожалуйста, укажите допустимое имя файла для экспорта конфигурации. + List all configuration keys and values + Список всех ключей и значений конфигурации - Please specify a valid key. - Пожалуйста, укажите действующий ключ. + Import configuration from given file + Импорт конфигурации из указанного файла - Specified key does not exist in current configuration! - Указанный ключ не существует в текущей конфигурации! + Export configuration to given file + Экспорт конфигурации в указанный файл - Please specify a valid value. - Укажите действительное значение. + Read and output configuration value for given key + Чтение и вывод значений конфигурации для заданного ключа - Configure Veyon at command line - Настройка Veyon в командной строке + Write given value to given configuration key + Записать указанное значение в заданный ключ конфигурации - Output file is not writable! - Выходной файл не доступен для записи! + Unset (remove) given configuration key + Отменить (удалить) данный ключ конфигурации - Output directory is not writable! - Каталог вывода не доступен для записи! + Upgrade and save configuration of program and plugins + Обновить и сохранить настройки программы и дополнений + + + Please specify an existing configuration file to import. + Пожалуйста, укажите существующий файл конфигурации для импорта. Configuration file is not readable! Файл конфигурации не читается! - Clear system-wide Veyon configuration - Очистка всей системы Veyon + Please specify a valid filename for the configuration export. + Пожалуйста, укажите допустимое имя файла для экспорта конфигурации. - List all configuration keys and values - Список всех ключей и значений конфигурации + Output file is not writable! + Выходной файл не доступен для записи! - Import configuration from given file - Импорт конфигурации из указанного файла + Output directory is not writable! + Каталог вывода не доступен для записи! - Export configuration to given file - Экспорт конфигурации в указанный файл + Please specify a valid key. + Пожалуйста, укажите действующий ключ. - Read and output configuration value for given key - Чтение и вывод значений конфигурации для заданного ключа + Specified key does not exist in current configuration! + Указанный ключ не существует в текущей конфигурации! - Write given value to given configuration key - Записать указанное значение в заданный ключ конфигурации + Please specify a valid value. + Укажите действительное значение. - Unset (remove) given configuration key - Отменить (удалить) данный ключ конфигурации + Configure Veyon at command line + Настройка Veyon в командной строке Commands for managing the configuration of Veyon Команды для управления настройками Veyon - - Upgrade and save configuration of program and plugins - Обновить и сохранить настройки программы и дополнений - ConfigurationManager @@ -1252,6 +1542,10 @@ The public key is used on client computers to authenticate incoming connection r Could not apply platform-specific configuration settings. Не удалось применить специфические для платформы параметры настроек. + + Could not configure the firewall configuration for the %1 Service. + Не удалось настроить конфигурацию брандмауэра для службы %1. + DemoClient @@ -1272,7 +1566,7 @@ The public key is used on client computers to authenticate incoming connection r ms - мс + мс Key frame interval @@ -1282,13 +1576,9 @@ The public key is used on client computers to authenticate incoming connection r Memory limit Предел памяти - - Use multithreading (experimental) - Использовать многопоточность (экспериментально) - MB - МБ + МБ Update interval @@ -1296,19 +1586,23 @@ The public key is used on client computers to authenticate incoming connection r s - с + с Slow down thumbnail updates while demo is running Замедлить обновление миниатюр, пока запущена демонстрация + + Bandwidth limit + Ограничение пропускной способности + + + MB/s + МБ/с + DemoFeaturePlugin - - Fullscreen demo - Полноэкранное демо - Stop demo Оставить демонстрацию @@ -1322,16 +1616,60 @@ The public key is used on client computers to authenticate incoming connection r Выполнить демонстрацию трансляцией изображения на экране - Demo server - Демонстрационный сервер + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + В этом режиме изображение с вашего экрана будет показано в окне на всех компьютерах. Пользователи, если захотят, смогут переключаться на другие окна. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - В этом режиме изображение с экрана вашего компьютера будет демонстрироваться на весь экран на всех компьютерах, а устройства ввода данных на компьютерах будут заблокированы. + Demo + Демонстрация - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - В этом режиме изображение с вашего экрана будет показано в окне на всех компьютерах. Пользователи, если захотят, смогут переключаться на другие окна. + Share your screen or allow a user to share his screen with other users. + Демонстрировать свой экран или разрешить другим пользователям демонстрировать свой экран. + + + Full screen demo + Полноэкранная демонстрация + + + Share your own screen in fullscreen mode + Демонстрировать собственный экран в полноэкранном режиме + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + В этом режиме изображение с экрана вашего компьютера будет демонстрироваться на весь экран на всех компьютерах, а устройства ввода данных на компьютерах будут заблокированы. + + + Share your own screen in a window + Демонстрировать собственный экран в оконном режиме + + + Share selected user's screen in fullscreen mode + Демонстрировать экран выбранного пользователя в полноэкранном режиме + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + В этом режиме экран выбранного пользователя отображается в полноэкранном режиме на всех компьютерах, в то время как устройства ввода пользователей заблокированы. + + + Share selected user's screen in a window + Демонстрировать экран выбранного пользователя в оконном режиме + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + В этом режиме экран выбранного пользователя отображается в окне на всех компьютерах. При необходимости пользователи могут переключаться на другие окна. + + + Please select a user screen to share. + Выберите экран пользователя, который следует демонстрировать. + + + Please select only one user screen to share. + Пожалуйста, выберите только один пользовательский экран для демонстрации. + + + All screens + Все экраны @@ -1354,19 +1692,11 @@ The public key is used on client computers to authenticate incoming connection r The user %1 at computer %2 wants to access your desktop. Do you want to grant access? - Пользователь %1 компьютера %2 пытается подключиться к Вашему рабочему столу. Разрешить ему доступ к Вашему рабочему столу? + Пользователь %1 компьютера %2 пытается подключиться к вашему рабочему столу. Разрешить ему доступ к вашему рабочему столу? DesktopServicesConfigurationPage - - Programs & websites - Программы и сайты - - - Predefined programs - Предварительно определённые программы - Name Имя @@ -1375,14 +1705,6 @@ The public key is used on client computers to authenticate incoming connection r Path Путь - - Add new program - Добавить новую программу - - - Remove selected program - Удалить выделенную программу - Predefined websites Предварительно определённые сайты @@ -1395,21 +1717,37 @@ The public key is used on client computers to authenticate incoming connection r URL Адрес - - New program - Новая программа - New website Новый сайт + + Applications & websites + Приложения и веб-сайты + + + Predefined applications + Предопределённые приложения + + + Add new application + Добавить новое приложение + + + Remove selected application + Удалить выбранное приложение + + + Add new website + Добавить новый веб-сайт + + + New application + Новое приложение + DesktopServicesFeaturePlugin - - Run program - Запустить программу - Open website Открыть веб-сайт @@ -1419,28 +1757,32 @@ The public key is used on client computers to authenticate incoming connection r Нажмите эту кнопку для открытия веб-сайта на всех компьютерах. - Start programs and services in user desktop - Запуск программ и сервисов на рабочем столе пользователя + Open website "%1" + Открыть сайт "%1" - Click this button to run a program on all computers. - Нажмите эту кнопку для запуска программы на всех компьютерах. + Custom website + Другой веб-сайт - Run program "%1" - Выполнить программу "%1" + Start application + Запустить приложение - Custom program - Необычная программа + Click this button to start an application on all computers. + Нажмите эту кнопку, чтобы запустить приложение на всех компьютерах. - Open website "%1" - Открыть сайт "%1" + Start application "%1" + Запустить приложение "%1" - Custom website - Необычный сайт + Custom application + Другое приложение + + + Start apps and open websites in user sessions + Запустить программы и открыть веб-сайты в сеансах пользователей @@ -1459,7 +1801,7 @@ The public key is used on client computers to authenticate incoming connection r Custom website - Необычный сайт + Другой веб-сайт Open file manager @@ -1473,17 +1815,21 @@ The public key is used on client computers to authenticate incoming connection r Play tutorial video Воспроизвести обучающее видео - - Custom program - Необычная программа - Handout - + Бесплатный образец Texts to read - + Фрагменты текста для чтения + + + generic-student-user + типичный-ученик-пользователь + + + Custom application + Другое приложение @@ -1509,10 +1855,165 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands + + List names of all available features + Показать названия всех доступных функций + + + Show table with details of all available features + Показать таблицу с описанием всех доступных функций + + + Start a feature on a remote host + Запустить функцию на удалённом хосте + + + Stop a feature on a remote host + Остановить функцию на удалённом хосте + + + Please specify the command to display help for. + Укажите команду, для которой следует показать справку. + + + Displays a list with the names of all available features. + Показывает список с именами всех доступных функций. + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + Показывает таблицу с подробной информацией обо всех доступных функциях. Эта информация включает описание, UID, имя плагина, предоставляющего соответствующую функцию, и некоторые другие сведения, которые относятся к реализации. + + + HOST ADDRESS + АДРЕСА ХОСТА + + + FEATURE + ФУНКЦИЯ + + + ARGUMENTS + АРГУМЕНТЫ + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + Запускает указанную функцию на указанном хосте путём соединения с запущенным удалённо сервером Veyon. Функцию можно указать по имени или UID. Воспользуйтесь командой "show" для просмотра списка всех доступных функций. В зависимости от функции, могут указываться дополнительные аргументы (например, текстовое сообщение для показа), которые должны быть закодированы в одну строку JSON. Чтобы узнать больше, обратитесь к документации для разработчиков. + + + Lock the screen + Заблокировать экран + + + Display a text message + Показать текстовое сообщение + + + Test message + Проверочное сообщение + + + Start an application + Запустить приложение + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + Останавливает указанную функцию на указанном хосте путём соединения с запущенным удалённо сервером Veyon. Функцию можно указать по имени или UID. Воспользуйтесь командой "show" для просмотра списка всех доступных функций. + + + Unlock the screen + Разблокировать экран + + + The specified command does not exist or no help is available for it. + Указанная команда не существует, или для неё недоступна справка. + + + Name + Имя + + + Description + Описание + + + Master + Мастер + + + Service + Сервис + + + Worker + Рабочая станция + + + UID + UID + + + Plugin + Плагин + + + Invalid feature name or UID specified + Указано некорректное имя или UID функции + + + Error parsing the JSON-encoded arguments: %1 + Ошибка при обработке аргументов в кодировке JSON: %1 + + + Failed to initialize credentials + Не удалось инициализировать регистрационные данные + + + Could not establish a connection to host %1 + Не удалось установить подключение к хосту %1 + + + Failed to send feature control message to host %1 + Не удалось отправить сообщение управления функциями хосту %1 + + + Feature-related CLI operations + Связанные с функцией операции CLI + + + Commands for controlling features + Команды для управления функциями + + + + FileTransferConfigurationPage + + File transfer + Передача файлов + + + Directories + Каталоги + + + Destination directory + Целевой каталог + + + Default source directory + Исходный каталог по умолчанию + + + Options + Параметры + + + Remember last source directory + Запомнить последний исходный каталог + - Feature control - Управление функциями + Create destination directory if it does not exist + Создайте целевой каталог, если он не существует @@ -1557,6 +2058,13 @@ The public key is used on client computers to authenticate incoming connection r Перезаписать существующие файлы + + FileTransferFileDialog + + Select one or more files to transfer + Выберите один или несколько файлов для передачи + + FileTransferPlugin @@ -1614,10 +2122,6 @@ The public key is used on client computers to authenticate incoming connection r Log file directory Каталог, содержащий файл журнала - - ... - ... - Log level Уровень журналирования @@ -1658,18 +2162,6 @@ The public key is used on client computers to authenticate incoming connection r Log to standard error output Обычное журналирование - - Network object directory - Каталог сетевых объектов - - - Backend: - Бэкэнд: - - - Update interval: - Интервал обновления: - %1 service сервис %1 @@ -1696,7 +2188,7 @@ The public key is used on client computers to authenticate incoming connection r MB - МБ + МБ Rotate log files @@ -1706,103 +2198,80 @@ The public key is used on client computers to authenticate incoming connection r x x - - seconds - секунд - Write to logging system of operating system Записывать в журнал операционной системы - Authentication - Аутентификация - - - Method: - Метод: - - - Logon authentication - Аутентификация при входе в систему - - - Key file authentication - Аутентификация с помощью ключа доступа - - - Test - Тестировать + TLS configuration + Конфигурация TLS - Authentication is set up properly on this computer. - На этом компьютере аутентификация установлена правильно. + Use certificate authority for TLS connections + Использовать центр сертификации для подключений TLS - Authentication keys are not set up properly on this computer. - Ключи аутентификации на этом компьютере установлены неправильно. + CA certificate file + Файл сертификата центра сертификации - Authentication test - Тест аутентификации + ... + ... - - - InternetAccessControlConfigurationPage - Internet access control - Управление доступом к интернету + Host certificate file + Файл сертификата хоста - Backend: - Бэкэнд: + Host private key file + Файл закрытого ключа хоста - General settings - Общие параметры + Style: + Стиль: - Backend settings - Параметры модулей + Native + Нативный - - - InternetAccessControlPlugin - Block access to the internet - Блокировать доступ к интернету + Color scheme: + Цветовая схема: - Allow access to the internet - Разрешить доступ к интернету + Light + Светлая - Show help about command - Показать помощь по команде + Dark + Тёмная - Block internet - Блокировать интернет + User groups + Группы пользователей - Click this button to block access to the internet. - Нажмите эту кнопку, чтобы заблокировать доступ к интернету. + Backend: + Бэкэнд: - Unblock internet - Разблокировать интернет + Include user groups from domain + Включить группы пользователей из домена - Click this button to allow access to the internet. - Нажмите эту кнопку, чтобы разрешить доступ к интернету. + Missing user groups backend + Отсутствующие группы пользователей - Control access to the internet - Управление доступом к интернету + No user groups plugin was found. Please check your installation! + Плагин групп пользователей не найден. Проверьте установку! + + + HeadlessVncServer - Commands for controlling access to the internet - Команды для управления доступом к интернету + Headless VNC server + Автоматический VNC-сервер @@ -1820,344 +2289,527 @@ The public key is used on client computers to authenticate incoming connection r - LdapConfigurationPage + LdapConfiguration - Basic settings - Основные настройки + LDAP connection failed + Неудачная попытка установить LDAP-соединение - General - Главное + Could not connect to the LDAP server. Please check the server parameters. + +%1 + Не удалось соединиться с сервером LDAP. Пожалуйста, проверьте, правильно ли указаны параметры сервера. + +%1 - LDAP server and port - LDAP сервер и порт + LDAP bind failed + Ошибка привязки к LDAP - Bind DN - DN для привязки + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + Не удалось привязаться к серверу LDAP. Пожалуйста, проверьте, правильно ли указаны параметры сервера и регистрационные данные привязки. + +%1 - Bind password - Пароль привязки + LDAP bind successful + Успешная привязка к LDAP - Anonymous bind - Анонимная привязка + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Выполнено успешное соединение с сервером LDAP и привязка к LDAP. Должным образом настроены основные параметры LDAP. - Use bind credentials - Регистрационные данные привязки + LDAP base DN test failed + Не удалось пройти проверку корневого DN LDAP - Base DN - Корневой DN - + Could not query the configured base DN. Please check the base DN parameter. + +%1 + Не удалось опросить настроенный базовый DN. Пожалуйста, проверите, правильно ли указан параметр базового DN. + +%1 + - Fixed base DN - Фиксированный корневой DN + LDAP base DN test successful + Успешная проверка корневого DN LDAP - e.g. dc=example,dc=org - например, dc=example,dc=org + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + Успешно опрошен базовый DN LDAP. Найдены следующие записи: + +%1 - Discover base DN by naming context - Определить корневой DN по контексту имён + LDAP naming context test failed + Не удалось пройти проверку контекста именования LDAP - e.g. namingContexts or defaultNamingContext - например, namingContexts или defaultNamingContext + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + Не удалось опросить базовый DN через контексты именования. Пожалуйста, проверите, правильно ли указан параметр атрибута контекста именования. + +%1 - Environment settings - Настройки среды + LDAP naming context test successful + Успешно пройдена проверка контекста именования LDAP - Object trees - Деревья объектов + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + Успешно выполнен опрос контекста именования LDAP. Выявлен такой корневой DN: +%1 + + + user tree + дерево пользователей + + + User tree + Дерево пользователей + + + group tree + дерево групп + + + Group tree + Дерево групп + + + computer tree + дерево компьютеров Computer tree Дерево компьютеров - e.g. OU=Groups - например, OU=Groups + computer group tree + дерево групп компьютеров - User tree - Дерево пользователей + Computer group tree + Дерево групп компьютеров - e.g. OU=Users - например, OU=Users + user objects + пользовательские объекты - e.g. OU=Computers - например, OU=Computers + User login name attribute + Атрибут имени пользователя для входа - Group tree - Дерево групп + group members + участники группы - Perform recursive search operations in object trees - Выполнить рекурсивные действия по поиску в деревьях объектов + Group member attribute + Атрибут членства в группе - Object attributes - Атрибуты объектов + Group not found + Группа не найдена - e.g. hwAddress - например, hwAddress + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Не удалось найти группу с именем "%1". Пожалуйста, проверьте, правильно ли указано имя группы или параметр дерева групп. - e.g. member or memberUid - например, member или memberUid + computer objects + объекты компьютеров - e.g. dNSHostName - например, dNSHostName + Computer display name attribute + Атрибут показываемого названия компьютера + + + Invalid hostname + Некорректное имя хоста + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Вы настроили программу на хранение полных доменных имён хостов компьютеров (FQDN), но указали имя хоста без домена. + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Вы настроили программу на хранение простых имён хостов компьютеров, но указали название хоста вместе с именем домена. + + + Computer hostname attribute + Атрибут имени хоста компьютера + + + computer MAC addresses + MAC-адреса компьютера Computer MAC address attribute Атрибут MAC-адреса компьютера - Group member attribute - Атрибут членства в группе + computer locations + места компьютеров - e.g. uid or sAMAccountName - например, uid или sAMAccountName + Computer location attribute + Атрибут места компьютера - Advanced settings - Расширенные настройки + Location name attribute + Атрибут названия места - Optional object filters - Опциональные фильтры объектов + users + пользователи - Filter for user groups - Фильтр для групп пользователей + user groups + группы пользователей - Filter for users - Фильтр для пользователей + computers + компьютеры + + + computer groups + группы компьютеров + + + computer containers + контейнеры компьютеров + + + groups of user + группы пользователя + + + User not found + Пользователь не найден + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + Не удалось найти пользователя с именем "%1". Пожалуйста, проверьте, правильно ли указано имя пользователя или параметр дерева пользователей. + + + groups of computer + группы компьютера + + + Computer not found + Компьютер не найден + + + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Не удалось найти компьютер с именем хоста "%1". Пожалуйста, проверьте, правильно ли указано имя хоста или параметр дерева компьютеров. + + + Hostname lookup failed + Ошибка поиска имени хоста + + + Could not lookup hostname for IP address %1. Please check your DNS server settings. + Не удалось выполнить поиск имени хоста для IP-адреса %1. Пожалуйста, проверьте, правильно ли указаны параметры вашего сервера DNS. + + + location entries + записи мест + + + Computer groups filter + Фильтр групп компьютеров + + + Computer locations identification + Идентификация мест компьютеров Filter for computer groups Фильтр для групп компьютеров - Group member identification - Идентификация участников группы + Invalid test value + Неверное значение теста - Distinguished name (Samba/AD) - Уникальное имя (Samba/AD) + An empty or invalid value has been supplied for this test. + Для этого теста было предоставлено пустое или неверное значение. - List all groups of a user - Список всех групп пользователя + LDAP %1 test failed + Ошибка тестирования LDAP %1 - List all groups of a computer - Список всех групп компьютера + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + Не удалось опросить ни одну из записей в настроенной %1. Пожалуйста, проверьте, правильно ли указан параметр "%2". + +%3 - Get computer object by IP address - Получить объект компьютера по IP-адресу + LDAP %1 test successful + Успешное тестирование LDAP %1 - LDAP connection failed - Неудачная попытка установить LDAP-соединение + The %1 has been queried successfully and %2 entries were found. + Успешно опрошено %1, выявлено %2 записей. - LDAP bind failed - Ошибка привязки к LDAP + LDAP test failed + Ошибка тестирования LDAP - LDAP bind successful - Успешная привязка к LDAP + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + Не удалось выполнить опрос для одного %1. Пожалуйста, проверьте параметр(ы) %2, или укажите имя имеющегося обьекта. + +%3 - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - Выполнено успешное соединение с сервером LDAP и привязка к LDAP. Должным образом настроены основные параметры LDAP. + and + и - LDAP base DN test failed - Не удалось пройти проверку корневого DN LDAP + LDAP test successful + Успешное тестирование LDAP - LDAP base DN test successful - Успешная проверка корневого DN LDAP + %1 %2 have been queried successfully: + +%3 + %1 %2 успешно опрошено: + +%3 - LDAP naming context test failed - Не удалось пройти проверку контекста именования LDAP + LDAP filter test failed + Ошибка тестирования фильтрации LDAP - LDAP naming context test successful - Успешно пройдена проверка контекста именования LDAP + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 + Не удалось выполнить опрос для одного %1 с использованием настроенной фильтрации. Пожалуйста, проверьте, правильно ли указан фильтр LDAP для %1. + +%2 - The LDAP naming context has been queried successfully. The following base DN was found: -%1 - Успешно выполнен опрос контекста именования LDAP. Выявлен такой корневой DN: -%1 + LDAP filter test successful + Успешная проверка фильтрации LDAP - user tree - дерево пользователей + %1 %2 have been queried successfully using the configured filter. + %1 %2 успешно опрошен с помощью настроенного фильтра. - group tree - дерево групп + LDAP directory + Каталог LDAP + + + LdapConfigurationPage - computer tree - дерево компьютеров + Basic settings + Основные настройки - Enter username - Введите имя пользователя + General + Главное - Please enter a user login name (wildcards allowed) which to query: - Выберите запись пользователя (можно использовать символы-заменители), данные которого следует получить: + LDAP server and port + LDAP сервер и порт - user objects - пользовательские объекты + Bind DN + DN для привязки - Enter group name - Введите имя группы + Bind password + Пароль привязки - Please enter a group name whose members to query: - Пожалуйста, укажите имя группы, участников которой следует определить: + Anonymous bind + Анонимная привязка - group members - участники группы + Use bind credentials + Регистрационные данные привязки - Group not found - Группа не найдена + Base DN + Корневой DN - Could not find a group with the name "%1". Please check the group name or the group tree parameter. - Не удалось найти группу с именем "%1". Пожалуйста, проверьте, правильно ли указано имя группы или параметр дерева групп. + Fixed base DN + Фиксированный корневой DN - Enter computer name - Введите имя компьютера + e.g. dc=example,dc=org + например, dc=example,dc=org - computer objects - объекты компьютеров + Discover base DN by naming context + Определить корневой DN по контексту имён - Enter computer DN - Укажите DN компьютера + e.g. namingContexts or defaultNamingContext + например, namingContexts или defaultNamingContext - Please enter the DN of a computer whose MAC address to query: - Пожалуйста, укажите DN компьютера, запрос по MAC-адресу которого следует прислать: + Environment settings + Настройки среды - computer MAC addresses - MAC-адреса компьютера + Object trees + Деревья объектов - users - пользователи + Computer tree + Дерево компьютеров - user groups - группы пользователей + e.g. OU=Groups + например, OU=Groups - computer groups - группы компьютеров + User tree + Дерево пользователей - Please enter a user login name whose group memberships to query: - Пожалуйста, укажите имя записи пользователя, для кого следует получить данные об участии в группах: + e.g. OU=Users + например, OU=Users - groups of user - группы пользователя + e.g. OU=Computers + например, OU=Computers - User not found - Пользователь не найден + Group tree + Дерево групп - groups of computer - группы компьютера + Perform recursive search operations in object trees + Выполнить рекурсивные действия по поиску в деревьях объектов - Computer not found - Компьютер не найден + Object attributes + Атрибуты объектов - Enter computer IP address - Введите IP адрес компьютера + e.g. hwAddress + например, hwAddress - Please enter a computer IP address which to resolve to an computer object: - Пожалуйста, укажите IP-адрес компьютера, с которой следует определить объект компьютера: + e.g. member or memberUid + например, member или memberUid - computers - компьютеры + e.g. dNSHostName + например, dNSHostName - LDAP %1 test failed - Ошибка тестирования LDAP %1 + Computer MAC address attribute + Атрибут MAC-адреса компьютера - LDAP %1 test successful - Успешное тестирование LDAP %1 + Group member attribute + Атрибут членства в группе - The %1 has been queried successfully and %2 entries were found. - Успешно опрошено %1, выявлено %2 записей. + e.g. uid or sAMAccountName + например, uid или sAMAccountName - %1 %2 have been queried successfully: - -%3 - %1 %2 успешно опрошено: - -%3 + Advanced settings + Расширенные настройки + + + Optional object filters + Опциональные фильтры объектов + + + Filter for user groups + Фильтр для групп пользователей + + + Filter for users + Фильтр для пользователей + + + Filter for computer groups + Фильтр для групп компьютеров + + + Group member identification + Идентификация участников группы + + + Distinguished name (Samba/AD) + Уникальное имя (Samba/AD) + + + List all groups of a user + Список всех групп пользователя + + + List all groups of a computer + Список всех групп компьютера + + + Get computer object by IP address + Получить объект компьютера по IP-адресу + + + Enter username + Введите имя пользователя + + + Please enter a user login name (wildcards allowed) which to query: + Выберите запись пользователя (можно использовать символы-заменители), данные которого следует получить: + + + Enter group name + Введите имя группы + + + Please enter a group name whose members to query: + Пожалуйста, укажите имя группы, участников которой следует определить: + + + Enter computer name + Введите имя компьютера + + + Enter computer DN + Укажите DN компьютера - LDAP filter test failed - Ошибка тестирования фильтрации LDAP + Please enter the DN of a computer whose MAC address to query: + Пожалуйста, укажите DN компьютера, чей MAC-адрес необходимо получить: - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 - Не удалось выполнить опрос для одного %1 с использованием настроенной фильтрации. Пожалуйста, проверьте, правильно ли указан фильтр LDAP для %1. - -%2 + Please enter a user login name whose group memberships to query: + Пожалуйста, укажите имя пользователя, для которого следует получить данные об участии в группах: - LDAP filter test successful - Успешная проверка фильтрации LDAP + Enter computer IP address + Введите IP адрес компьютера - %1 %2 have been queried successfully using the configured filter. - %1 %2 успешно опрошен с помощью настроенного фильтра. + Please enter a computer IP address which to resolve to an computer object: + Пожалуйста, укажите IP-адрес компьютера, для которого необходимо получить объект компьютера. (only if different from group tree) @@ -2167,10 +2819,6 @@ The public key is used on client computers to authenticate incoming connection r Computer group tree Дерево групп компьютеров - - computer group tree - дерево групп компьютеров - Filter for computers Фильтр для компьютеров @@ -2251,50 +2899,10 @@ The public key is used on client computers to authenticate incoming connection r e.g. (objectClass=container) or (objectClass=organizationalUnit) например, (objectClass=container) или (objectClass=organizationalUnit) - - Could not query the configured base DN. Please check the base DN parameter. - -%1 - Не удалось опросить настроенный базовый DN. Пожалуйста, проверите, правильно ли указан параметр базового DN. - -%1 - - - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - Успешно опрошен базовый DN LDAP. Найдены следующие записи: - -%1 - - - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - Не удалось опросить базовый DN через контексты именования. Пожалуйста, проверите, правильно ли указан параметр атрибута контекста именования. - -%1 - Certificate files (*.pem) Файлы сертификатов (*.pem) - - Could not connect to the LDAP server. Please check the server parameters. - -%1 - Не удалось соединиться с сервером LDAP. Пожалуйста, проверьте, правильно ли указаны параметры сервера. - -%1 - - - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - Не удалось привязаться к серверу LDAP. Пожалуйста, проверьте, правильно ли указаны параметры сервера и регистрационные данные привязки. - -%1 - Encryption protocol Протокол шифрования @@ -2313,7 +2921,7 @@ The public key is used on client computers to authenticate incoming connection r e.g. cn or displayName - например cn или displayName + например, cn или displayName Computer locations identification @@ -2321,7 +2929,7 @@ The public key is used on client computers to authenticate incoming connection r Identify computer locations (e.g. rooms) via: - Идентифицировать места компьютеров (например классы) на основе: + Идентифицировать места компьютеров (например, классы) на основе: Location attribute in computer objects @@ -2344,379 +2952,146 @@ The public key is used on client computers to authenticate incoming connection r Пожалуйста, укажите показываемое имя компьютера для запроса: - Enter computer location name - Введите название места компьютера - - - Please enter the name of a computer location (wildcards allowed): - Пожалуйста, введите имя места компьютера (можно использовать символы-заменители): - - - computer locations - места компьютеров - - - Enter location name - Введите название места - - - Please enter the name of a location whose entries to query: - Пожалуйста, укажите название места, запрос к участникам которого следует выполнить: - - - location entries - записи мест - - - LDAP test failed - Ошибка тестирования LDAP - - - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - Не удалось выполнить опрос для одного %1. Пожалуйста, проверьте параметр(ы) %2, или укажите имя имеющегося обьекта. - -%3 - - - and - и - - - LDAP test successful - Успешное тестирование LDAP - - - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - Не удалось опросить ни одну из записей в настроенной %1. Пожалуйста, проверьте, правильно ли указан параметр "%2". - -%3 - - - Browse - Навигация - - - Test - Тестировать - - - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - Имена хостов сохранены как полные доменные имена (FQDN, например myhost.example.org) - - - Computer hostname attribute - Атрибут имени хоста компьютера - - - Please enter a computer hostname to query: - Пожалуйста, укажите имя хоста компьютера для запроса: - - - Invalid hostname - Некорректное имя хоста - - - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Вы настроили программу на хранение полных доменных имён хостов компьютеров (FQDN), но указали имя хоста без домена. - - - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - Вы настроили программу на хранение простых имён хостов компьютеров, но указали название хоста вместе с именем домена. - - - Could not find a user with the name "%1". Please check the username or the user tree parameter. - Не удалось найти пользователя с именем "%1". Пожалуйста, проверьте, правильно ли указано имя пользователя или параметр дерева пользователей. - - - Enter hostname - Введите имя хоста - - - Please enter a computer hostname whose group memberships to query: - Пожалуйста, укажите имя хоста компьютера, для кого следует получить данные об участии в группах: - - - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - Не удалось найти компьютер с именем хоста "%1". Пожалуйста, проверьте, правильно ли указано имя хоста или параметр дерева компьютеров. - - - Hostname lookup failed - Ошибка поиска имени хоста - - - Could not lookup hostname for IP address %1. Please check your DNS server settings. - Не удалось выполнить поиск имени хоста для IP-адреса %1. Пожалуйста, проверьте, правильно ли указаны параметры вашего сервера DNS. - - - User login name attribute - Атрибут имени пользователя для входа - - - Configured attribute for user login name or computer hostname (OpenLDAP) - Настроенный атрибут для имени пользователя для входа или имени хоста компьютера (OpenLDAP) - - - computer containers - контейнеры компьютеров - - - - LdapPlugin - - Auto-configure the base DN via naming context - Автоматическое конфигурирование базового DN через контекст имён - - - Query objects from LDAP directory - Опросить объекты из каталога LDAP - - - Show help about command - Показать помощь по команде - - - Commands for configuring and testing LDAP/AD integration - Команды для конфигурирования и тестирования интеграции LDAP/AD - - - Basic LDAP/AD support for Veyon - Базовая поддержка LDAP/AD в Veyon - - - %1 (load computers and locations from LDAP/AD) - %1 (загрузить записи компьютеров и мест с LDAP/AD) - - - %1 (load users and groups from LDAP/AD) - %1 (загрузить записи пользователей и групп с LDAP/AD) - - - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - Пожалуйста, укажите корректный адрес LDAP в следующем формате: "ldap[s]://[пользователь[:пароль]@]название_узла[:порт]" - - - No naming context attribute name given - falling back to configured value. - Не указан атрибут контекста именования - возвращаемся к настроенному значению. - - - Could not query base DN. Please check your LDAP configuration. - Не удалось обработать запрос по корневому DN. Пожалуйста, проверьте, правильно ли настроен LDAP. - - - Configuring %1 as base DN and disabling naming context queries. - Настраиваем %1 как корневой DN и выключаем запросы по контексту именования. - - - - LdapProConfigurationPage - - LDAP Pro - LDAP Pro - - - Instances - Экземпляры - - - Enter name - Введите имя - - - Please enter a name for the instance (can't be changed later!): - Пожалуйста, введите название экземпляра (его нельзя будет изменить!): - - - Remove instance - Удалить экземпляр - - - Do you really want to remove instance "%1"? - Вы действительно хотите удалить экземпляр "%1"? - - - Configuration for instance "%1" - Настройка для экземпляра "%1" - - - - LdapProPlugin - - Professional LDAP/AD integration for Veyon - Профессиональная интеграция LDAP/AD в Veyon - - - %1 (load computers and locations from LDAP/AD) - %1 (загрузить записи компьютеров и мест с LDAP/AD) - - - %1 (load users and groups from LDAP/AD) - %1 (загрузить записи пользователей и групп с LDAP/AD) - - - - LicensingConfigurationPage - - Licensing - Лицензирование + Enter computer location name + Введите название места компьютера - Installed licenses - Установленные лицензии + Please enter the name of a computer location (wildcards allowed): + Пожалуйста, введите имя места компьютера (можно использовать символы-заменители): - Add new network range - Добавить новый диапазон сети + Enter location name + Введите название места - Remove selected network range - Удалить выделенный диапазон сети + Please enter the name of a location whose entries to query: + Пожалуйста, укажите название места, запрос к участникам которого следует выполнить: - ID - Идентификатор + Browse + Навигация - Feature - Функция + Test + Тестировать - Valid until - В силе до + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Имена хостов сохранены как полные доменные имена (FQDN, например, myhost.example.org) - Licensee - Лицензиат + Computer hostname attribute + Атрибут имени хоста компьютера - Browse license file - Просмотреть файл лицензии + Please enter a computer hostname to query: + Пожалуйста, укажите имя хоста компьютера для запроса: - Veyon license files (*.vlf) - файлы лицензий Veyon (*.vlf) + Enter hostname + Введите имя хоста - Remove license - Удалить лицензию + Please enter a computer hostname whose group memberships to query: + Пожалуйста, укажите имя компьютера, для которого следует получить данные об участии в группах: - Do you really want to remove the selected license? - Вы действительно хотите удалить выбранную лицензию? + User login name attribute + Атрибут имени пользователя для входа - <N/A> - <н/д> + Configured attribute for user login name or computer hostname (OpenLDAP) + Настроенный атрибут для имени пользователя для входа или имени хоста компьютера (OpenLDAP) - Invalid license file - Некорректный файл лицензии + Directory name + Имя каталога - Could not open the license file for reading! - Не удалось открыть файл лицензии для чтения! + Query options + Параметры запроса - The selected license file does not contain valid data. - В указанном файле лицензии не содержится корректных данных. + Query nested user groups (supported by AD only) + Опросить вложенные группы пользователей (поддерживается только AD) - The selected license file could not be verified. - Выделенный файл лицензии не удалось проверить. + Query timeout + Время ожидания запроса - The selected license file is not valid for this installation. - Выделенный файл лицензии не действует для этой установки. + ms + мс + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. - Срок действия выделенного файла лицензии истек. + LDAP + LDAP - The license is already installed. - Эта лицензия уже установлена. + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + Воспользуйтесь общей страницей настройки LDAP для настройки способа получения данных о расположениях и компьютерах от службы каталогов на основе LDAP. + + + LdapPlugin - Information - Информация + Auto-configure the base DN via naming context + Автоматическое конфигурирование базового DN через контекст имён - Installation ID - Ид. установки + Query objects from LDAP directory + Опросить объекты из каталога LDAP - Addons available for licensing - Дополнения, доступные для лицензирования + Show help about command + Показать помощь по команде - Addon - Дополнение + Commands for configuring and testing LDAP/AD integration + Команды для конфигурирования и тестирования интеграции LDAP/AD - - - LicensingPlugin - Show help for specific command - Показать справку по определённой команде + Basic LDAP/AD support for Veyon + Базовая поддержка LDAP/AD в Veyon - Show all installed licenses - Показать все установленные лицензии + %1 (load computers and locations from LDAP/AD) + %1 (загрузить записи компьютеров и мест с LDAP/AD) - Add license file - Добавить файл лицензии + %1 (load users and groups from LDAP/AD) + %1 (загрузить записи пользователей и групп с LDAP/AD) - Remove installed license - Удалить установленную лицензию + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Пожалуйста, укажите корректный адрес LDAP в следующем формате: "ldap[s]://[пользователь[:пароль]@]название_узла[:порт]" - -USAGE - -%1 add <LICENSE FILE> - - - -ИСПОЛЬЗОВАНИЕ - -%1 add <LICENSE FILE> - - + No naming context attribute name given - falling back to configured value. + Не указан атрибут контекста именования - возвращаемся к настроенному значению. - -USAGE - -%1 remove <LICENSE ID> - - - -ИСПОЛЬЗОВАНИЕ - -%1 remove <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. + Не удалось обработать запрос по корневому DN. Пожалуйста, проверьте, правильно ли настроен LDAP. - No certificate found with given ID - Не найдено сертификата с указанным идентификатором + Configuring %1 as base DN and disabling naming context queries. + Настраиваем %1 как корневой DN и выключаем запросы по контексту именования. - <N/A> - <н/д> + Test binding to an LDAP server + Тест настройки сервера LDAP - Licensing management - Управление лицензиями + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Предоставленое значение имени пользователя и пароля является ошибочным. Пожалуйста, укажите корректные регистрационные данные или переключите систему на другой способ распознавания с помощью средства настройки Veyon. - Commands for managing license keys - Команды для управления файлами лицензий + LDAP bind + Связывание LDAP @@ -2734,12 +3109,20 @@ USAGE Аутентификация пользователей - Session management - Управление сеансами + User sessions + Сеансы пользователей + + + Minimum session lifetime before server start + Минимальная продолжительность сеанса перед запуском сервера + + + User login + Имя пользователя - Display manager users - Пользователи управления дисплеем + Login key sequence + Последовательность ключей для входа @@ -2748,10 +3131,6 @@ USAGE Plugin implementing abstract functions for the Linux platform Плагин, который реализует абстрактные функции на платформе Linux - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2770,14 +3149,14 @@ USAGE Configuration Конфигурация - - Disable balloon tooltips - Отключить всплывающие подсказки - Show icons only Показывать только значки + + Disable tooltips + Отключить всплывающие подсказки + MainWindow @@ -2815,7 +3194,7 @@ USAGE L&oad settings from file - Загрузить настройки из файла + &Загрузить настройки из файла Ctrl+O @@ -2825,10 +3204,6 @@ USAGE About Qt О пакете Qt - - Authentication impossible - Невозможно выполнить аутентификацию - Configuration not writable Файл конфигурации не доступен для записи @@ -2889,21 +3264,17 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. Локальный сервер сообщил, что конфигурация защищена от записи. Запустите конфигуратор %1 с более высокими привилегиями. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - Не найдены файлы ключей аутентификации или они устарели. Пожалуйста, создайте новые файлы, используя конфигуратор %1. Как альтернатива установите аутентификацию входа, используя конфигуратор %1. Иначе Вы не сможете получить доступ к компьютерам с помощью %1. - Access denied Доступ запрещён According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. - Согласно локальных настроек вам запрещён доступ к компьютерам в сети. Пожалуйста, войдите из-под другой учётной записи или попросите администратора вашей системы изменить локальные настройки соответствующим образом. + Согласно локальным настройкам вам запрещён доступ к компьютерам в сети. Пожалуйста, войдите с другой учётной записью или попросите администратора вашей системы изменить локальные настройки соответствующим образом. Screenshots - Скриншоты + Снимки экрана Feature active @@ -2919,16 +3290,12 @@ USAGE Do you really want to reset the local configuration and revert all settings to their defaults? - Вы действительно хотите сбросить локальную конфигурацию и вернуть все настройки по умолчанию? + Действительно сбросить локальную конфигурацию и вернуть все настройки по умолчанию? Search users and computers Поиск пользователей и компьютеров - - Adjust optimal size - Скорректировать оптимальный размер - Align computers to grid Выравнивать компьютеры по сетке @@ -2963,16 +3330,60 @@ USAGE &Advanced - &Рвсширенный + &Расширенный Use custom computer arrangement - Использовать необычное расположение компьютеров + Использовать нестандартное расположение компьютеров Locations && computers Места && компьютеры + + Authentication + Аутентификация + + + Adjust size of computer icons automatically + Автоматическая регулировка размера значков компьютера + + + Slideshow + Слайд-шоу + + + Spotlight + Акцент + + + Veyon Master + Veyon Мастер + + + Locations & computers + Места и компьютеры + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + Использовать пользовательское расположение компьютеров. + +Нажмите и удерживайте, чтобы загрузить расположение из файла или сохранить текущее расположение в файл. + + + Only show computers with logged on users + Показывать только те компьютеры, где пользователи выполнили вход в систему + + + Load computer positions + Загрузить позиции компьютеров + + + Save computer positions + Сохранить позиции компьютеров + MasterConfigurationPage @@ -2980,10 +3391,6 @@ USAGE Directories Каталоги - - ... - ... - User configuration Пользовательская конфигурация @@ -3002,11 +3409,11 @@ USAGE Disabled features - Отключенные функции + Отключённые функции Screenshots - Скриншоты + Снимки экрана <no feature> @@ -3068,6 +3475,10 @@ USAGE Only user name Только имя пользователя + + Only last part of user name + + Only computer name Только имя компьютера @@ -3116,171 +3527,181 @@ USAGE Automatically select current location Автоматически выбирать текущее место - - Automatically adjust computer thumbnail size - Автоматически корректировать размер миниатюры компьютера - Automatically open computer select panel Автоматически открыть панель выбора компьютера - - - MonitoringMode - Monitoring - Мониторинг + Use modern user interface (experimental) + Использовать современный пользовательский интерфейс (экспериментально) - Builtin monitoring mode - Встроенный режим мониторинга + Thumbnail spacing + Интервал миниатюр - This mode allows you to monitor all computers at one or more locations. - В этом режиме вы можете наблюдать за всеми компьютерами в одном или нескольких местах. + px + пкс - - - NetworkDiscoveryConfigurationPage - Network discovery - Обнаружение сети + Hide local session + Скрыть локальные сессии - Mode - Режим + Auto + Авто - Scan network ranges - Сканировать диапазоны сети + Thumbnail aspect ratio + Соотношение сторон миниатюры - e.g. 192.168.1.0/24 - Например: 192.168.1.0/24 + Automatically adjust computer icon size + Автоматически настраивать размер значка компьютера - Scan all subnets of computer - Сканировать все подсети компьютера + Open feature windows on the same screen as the main window + Открывать окно функций на том же экране, что и главное окно - Scan custom subnet - Сканировать нетипичную подсеть + Configuration templates + Шаблоны конфигурации - Scan sessions on local computer - Сканировать сеансы на локальном компьютере + Image quality in monitoring mode + Качество изображения в режиме мониторинга - Test - Тестировать + Highest + Самое высокое - Network ranges - Диапазоны сети + High + Высокое - Add new group - Добавить новую группу + Medium + Среднее - Remove selected group - Удалить выделенную группу + Low + Низкое - Groups - Группы + Lowest + Самое низкое - First address - Первый адрес + Remote access image quality + Качество изображения удаленного доступа - Last address - Последний адрес + Advanced + Расширенный - Add new network range - Добавить новый диапазон сети + Computer name source + Источник имени компьютера - Remove selected network range - Удалить выделенный диапазон сети + Default + По умолчанию - Parallel scans - Параллельное сканирование + Host address + Адрес хоста - Scan timeout - Время ожидания сканирования + Session client address + Адрес клиента сеанса - ms - мс + Session client name + Имя клиента сеанса - Session scan limit - Ограничение сканирования сеансов + Session host name + Имя хоста сеанса - Options - Параметры + Session metadata + Метаданные сеанса - Reverse lookup discovered IP addresses to host names - Обратным поиском определены IP-адреса для названий узлов + Full name of user + Полное имя пользователя - New location - Новое место + User login name + Имя пользователя (логин) + + + Computer UID role + Роль UID компьютера - - - NetworkDiscoveryDirectory - Scanning... - Сканирование... + Session meta data hash + Хеш метаданных сеанса - Discovered computers - Обнаруженные компьютеры + Always expand all locations + Всегда раскрывать все местоположения + + + Image quality + Качество изображения - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command - Показать справку по определённой команде + Monitoring + Мониторинг + + + Builtin monitoring mode + Встроенный режим мониторинга - Scan a subnet - Сканировать подсеть + This mode allows you to monitor all computers at one or more locations. + В этом режиме вы можете наблюдать за всеми компьютерами в одном или нескольких местах. - -USAGE - -%1 scan [<SUBNET>] - - - -ИСПОЛЬЗОВАНИЕ - -%1 scan [<SUBNET>] - - + Query application version of the server + Запросить версию серверного приложения + + + Query active features + Запросить активные функции + + + Query properties of remotely available screens + Запросить свойства удаленно доступных экранов + + + + NestedNetworkObjectDirectory + + All directories + Все каталоги + + + NetworkObjectDirectoryConfigurationPage - Network object directory which automatically discovers computers in the network - Каталог объектов сети, который автоматически обнаруживает компьютеры в сети + Update interval: + Интервал обновления: - Network discovery (scan network for Veyon clients) - Обнаружение сети (поиск в сети клиентов Veyon) + seconds + сек. + + + NetworkObjectDirectoryConfigurationPageTab - Commands for managing the network discovery directory - Команды для управления каталогом обнаружения сети + Enabled + Включено @@ -3298,7 +3719,7 @@ USAGE e.g. Veyon - например Veyon + например, Veyon Remember and add to website menu @@ -3306,7 +3727,7 @@ USAGE e.g. www.veyon.io - например www.veyon.io + например, www.veyon.io Please enter the URL of the website to open: @@ -3316,32 +3737,44 @@ USAGE Name: Имя: + + Website name + Имя веб-сайта + - PasswordDialog + PluginCommands - Username - Имя пользователя + List names of all installed plugins + Список имён всех установленных плагинов - Password - Пароль + Show table with details of all installed plugins + Показать таблицу с описанием всех установленных плагинов - Veyon Logon - Вход в систему Veyon + Name + Имя - Authentication error - Ошибка аутенфикации + Description + Описание - Logon failed with given username and password. Please try again! - Не удалось войти, используя указанные имя пользователя и пароль. Пожалуйста, повторите попытку! + Version + Версия - Please enter your username and password in order to access computers. - Пожалуйста, введите имя пользователя и пароль для доступа компьютеров. + UID + UID + + + Plugin-related CLI operations + Связанные с плагином операции CLI + + + Commands for managing plugins + Команды для управления плагинами @@ -3352,7 +3785,7 @@ USAGE Click this button to power on all computers. This way you do not have to power on each computer by hand. - Нажмите эту кнопку для включения всех компьютеров. Это позволит вам не включать каждый компьютер вручную. + Нажмите эту кнопку для включения всех компьютеров. Это позволит не включать каждый компьютер вручную. Reboot @@ -3368,7 +3801,7 @@ USAGE Click this button to power down all computers. This way you do not have to power down each computer by hand. - Нажмите эту кнопку для выключения всех компьютеров. Это позволит вам не выключать каждый компьютер вручную. + Нажмите эту кнопку для выключения всех компьютеров. Это позволит не выключать каждый компьютер вручную. Power on/down or reboot a computer @@ -3384,11 +3817,7 @@ USAGE Do you really want to reboot the selected computers? - Вы действительно хотите перезагрузить выбранные компьютеры? - - - Do you really want to power down the selected computer? - Вы действительно хотите выключить выбранный компьютер? + Действительно перезагрузить выбранные компьютеры? Power on a computer via Wake-on-LAN (WOL) @@ -3432,15 +3861,27 @@ USAGE The computer was remotely requested to power down. Do you want to power down the computer now? - Компьютер получил удалённую команду по выключению. Хотите выключить компьютер сейчас? + Компьютер получил удалённую команду по выключению. Выключить компьютер сейчас? The computer will be powered down in %1 minutes, %2 seconds. Please save your work and close all programs. - Компьютер выключится через %1 минут, %2 секунд. + Компьютер выключится через %1 мин., %2 сек. -Пожалуйста, сохраните результаты вашей работы и завершите работу всех программ. +Пожалуйста, сохраните результаты работы и завершите работу всех программ. + + + Do you really want to reboot <b>ALL</b> computers? + Действительно перезагрузить <b>ВСЕ</b> компьютеры? + + + Do you really want to power down <b>ALL</b> computers? + Действительно выключить <b>ВСЕ</b> компьютеры? + + + Do you really want to power down the selected computers? + Действительно выключить выбранные компьютеры? @@ -3455,11 +3896,11 @@ Please save your work and close all programs. minutes - минут + мин. seconds - секунд + сек. @@ -3488,14 +3929,25 @@ Please save your work and close all programs. Remote view or control a computer Удалённый просмотр или управление компьютером - - Please enter the hostname or IP address of the computer to access: - Пожалуйста, укажите имя хоста или IP-адрес компьютера, доступ к которому необходимо получить: - Show help about command Показать помощь по команде + + Exchange clipboard contents + Обмен содержимым буфера обмена + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + Компьютер не выбран, поэтому вы можете ввести имя хоста или IP-адрес компьютера для доступа к нему: + + + + RemoteAccessPage + + Remote access: %1 + Удаленный доступ: %1 + RemoteAccessWidget @@ -3503,6 +3955,10 @@ Please save your work and close all programs. %1 - %2 Remote Access %1 — %2, удалённый доступ + + %1 - %2 - %3 Remote Access + %1 - %2 - %3 Удаленный доступ + RemoteAccessWidgetToolBar @@ -3544,88 +4000,43 @@ Please save your work and close all programs. Win+Tab - Win+Tab - - - Win - Win - - - Menu - Меню - - - Alt+Ctrl+F1 - Alt+Ctrl+F1 - - - Connecting %1 - Соединение с %1 - - - Connected. - Подключен. - - - Screenshot - Скриншот - - - Exit - Выход - - - - Routing - - Control internet access by modifying routing table - Управление доступом к интернету путём внесения изменений в таблицы маршрутизации - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - Удалить маршруты по-умолчанию для блокировки доступа к интернету + Win+Tab - Add custom route to block internet - Добавить нетипичный маршрут для блокировки интернета + Win + Win - Destination - Назначение + Menu + Меню - Gateway - Шлюз + Alt+Ctrl+F1 + Alt+Ctrl+F1 - - - RunProgramDialog - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - Пожалуйста, введите программы или команды для их выполнения на выбранных компьютерах. Вы можете записать несколько программ/команд, по одной в строке. + Connected. + Подключён. - Run programs - Запустить программы + Screenshot + Снимок экрана - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - например, "C:\Program Files\VideoLAN\VLC\vlc.exe" + Exit + Выход - Name: - Имя: + Connecting... + Подключение... - Remember and add to program menu - Запомнить и добавить в меню программ + Select screen + Выбрать экран - e.g. VLC - например VLC + All screens + Все экраны @@ -3646,6 +4057,18 @@ Please save your work and close all programs. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. Чтобы завладеть вниманием пользователей, вы можете заблокировать их компьютеры с помощью этой кнопки. В этом режиме все устройства ввода данных будут заблокированы, а экраны станут чёрными. + + Lock input devices + Заблокировать устройства ввода + + + Unlock input devices + Разблокировать устройства ввода + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + Вы можете использовать эту кнопку для привлечения полного внимания всех пользователей и блокировки их настольных компьютеров. В этом режиме блокируются все устройства ввода. + Screenshot @@ -3659,14 +4082,18 @@ Please save your work and close all programs. Screenshot - Скриншот + Снимок экрана + + + Could not open screenshot file %1 for writing. + Не удалось открыть файл снимка экрана %1 для записи. ScreenshotFeaturePlugin Screenshot - Скриншот + Снимок экрана Use this function to take a screenshot of selected computers. @@ -3685,6 +4112,13 @@ Please save your work and close all programs. Создание снимков экранов компьютеров и их локальное хранение. + + ScreenshotManagementPage + + Screenshots + Снимки экрана + + ScreenshotManagementPanel @@ -3715,6 +4149,45 @@ Please save your work and close all programs. Delete Удалить + + Screenshot + Снимок экрана + + + Do you really want to delete all selected screenshots? + Действительно удалить выбранные снимки экрана? + + + + ServerAccessControlManager + + Requested authentication method not available + Запрошенный метод аутентификации недоступен + + + Access allowed by rule "%1" + Доступ разрешен правилом "%1" + + + Access denied by rule "%1" + Доступ запрещён правилом "%1" + + + No rule allowed access + Ни одно правило не разрешает доступ + + + Accessing user not member of an authorized user group + Доступ пользователя, не являющегося членом авторизованной группы пользователей + + + User has denied access + Пользователю отказано в доступе + + + User confirmed access + Пользователь подтвердил доступ + ServiceConfigurationPage @@ -3746,14 +4219,6 @@ Please save your work and close all programs. State: Состояние: - - Network - Сеть - - - Demo server port - Порт демонстрационного сервера - Enable firewall exception Включить исключения брандмауэра @@ -3762,10 +4227,6 @@ Please save your work and close all programs. Allow connections from localhost only Разрешить только локальные подключения - - Internal VNC server port - Порт внутреннего сервера VNC - VNC server VNC-сервер @@ -3786,14 +4247,6 @@ Please save your work and close all programs. Running Работает - - Feature manager port - Порт управления функциями - - - Primary service port - Порт основного сервиса - Enabling this option will make the service launch a server process for every interactive session on a computer. Typically this is required to support terminal servers. @@ -3804,52 +4257,132 @@ Typically this is required to support terminal servers. Show notification on remote connection Показывать оповещение по удалённому доступу - - Multi session mode (for terminal and remote desktop servers) - Режим со многими сеансами (для сервера-терминала и сервера удалённого рабочего стола) - Show notification when an unauthorized access is blocked Показывать оповещения, когда программа блокирует неавторизованный доступ - - - ServiceControl - Starting service %1 - Запускаем сервис %1 + Maximum session count + Максимальное количество сеансов - Stopping service %1 - Останавливаем сервис %1 + Network port numbers + Номера сетевых портов - Registering service %1 - Регистрируем сервис %1 + Veyon server + Veyon сервер - Unregistering service %1 - Отменяем регистрацию сервиса %1 + Internal VNC server + Встроенный VNC-сервер - Service control - Управление сервисам + Feature manager + Менеджер функций + + + Demo server + Демонстрационный сервер + + + Miscellaneous network settings + Дополнительные настройки сети + + + Session mode + Режим сеанса + + + Local session mode (single server instance for primary local session) + Режим локального сеанса (один экземпляр сервера для основного локального сеанса) + + + Active session mode (single server instance for active local or remote session) + Режим активного сеанса (один экземпляр сервера для активного локального или удалённого сеанса) + + + Multi session mode (distinct server instance for each local and remote desktop session) + Режим мультисеанса (отдельный экземпляр сервера для каждого сеанса локального и удалённого рабочего стола) + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + Включите этот параметр, если необходимо запустить один экземпляр сервера Veyon для текущего активного сеанса, независимо от того, локальный он или удаленный. + + + Miscellaneous settings + Дополнительные настройки + + + Disable clipboard synchronization + Отключить синхронизацию буфера обмена + + + Session metadata + Метаданные сеанса + + + Content + Содержимое + + + None + Нет + + + Value of an environment variable + Значение переменной среды + + + Value of a registry key + Значение ключа реестра + + + Environment variable name: + Имя переменной среды: + + + Registry key name: + Имя ключа реестра: + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + При необходимости введите регулярное выражение с захватом, чтобы извлечь часть имени компьютера и использовать её в качестве отображаемого имени компьютера. + +Пример: [^-]*-(PC[0-9]*) - ServiceControlPlugin + ServiceControl - Service is running - Сервис работает + Service control + Управление сервисам - Service is not running - Сервис не работает + Starting %1 + Запуск %1 - Configure and control Veyon service - Настройка и управление сервисом Veyon + Stopping %1 + Остановка %1 + + + Restarting %1 + Перезапуск %1 + + Registering %1 + Регистрация %1 + + + Unregistering %1 + Отмена регистрации %1 + + + + ServiceControlCommands Register Veyon Service Регистрация сервиса Veyon @@ -3874,13 +4407,25 @@ Typically this is required to support terminal servers. Query status of Veyon Service Определить состояние сервиса Veyon + + Service is running + Сервис работает + + + Service is not running + Сервис не работает + + + Configure and control Veyon service + Настройка и управление сервисом Veyon + Commands for configuring and controlling Veyon Service Команды для настройки и управления сервисом Veyon - ShellCommandLinePlugin + ShellCommands Run command file Запустить командный файл @@ -3890,14 +4435,101 @@ Typically this is required to support terminal servers. Файла "%1" не существует! - Interactive shell and script execution for Veyon Control - Интерактивная оболочка и средство выполнения скриптов для Управления Veyon + Interactive shell and script execution for Veyon CLI + Интерактивная оболочка и способ выполнения сценариев для CLI Veyon Commands for shell functionalities Команды для возможностей оболочки + + SlideshowPanel + + Previous + Предыдущий + + + Start/pause + Старт/пауза + + + Next + Следующий + + + Duration: + Продолжительность: + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + Добавить выбранные компьютеры + + + Remove selected computers + Удалить выбранные компьютеры + + + Update computers in realtime + Обновлять компьютеры в реальном времени + + + Spotlight + Акцент + + + Please select at least one computer to add. + Выберите хотя бы один компьютер для добавления. + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + Нажимайте среднюю кнопку мыши или первую расположенную ниже кнопку, чтобы добавить компьютеры. +Вторая кнопка удаляет выбранный или последний компьютер. + + + + StartAppDialog + + Start application + Запустить приложение + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + Укажите приложения для запуска на выбранных компьютерах. Чтобы перечислить несколько приложений, укажите каждое в отдельной строке. + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + например, "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + Запомнить и добавить в меню приложений + + + Application name + Имя приложения + + + Name: + Имя: + + + e.g. VLC + например, VLC + + SystemTrayIcon @@ -3931,11 +4563,11 @@ Typically this is required to support terminal servers. TextMessageDialog Send text message - Послать текстовое сообщение + Отправить текстовое сообщение - Use the field below to type your message which will be sent to all selected users. - Используйте это поле снизу для набора сообщения, которое хотите послать всем выбранным пользователям. + Please enter your message which send to all selected users. + Введите сообщение, которое будет отправлено всем выбранным пользователям. @@ -3946,7 +4578,7 @@ Typically this is required to support terminal servers. Use this function to send a text message to all users e.g. to assign them new tasks. - Используйте эту функцию для посылки текстового сообщения всем пользователям, например, сказав им о новых задачах и т. д. + Используйте эту функцию для отправки текстового сообщения всем пользователям (например, чтобы сообщить им о новых задачах). Message from teacher @@ -3954,7 +4586,7 @@ Typically this is required to support terminal servers. Send a message to a user - Послать сообщение пользователю + Отправить сообщение пользователю @@ -3965,7 +4597,7 @@ Typically this is required to support terminal servers. Poll full screen (leave this enabled per default) - Опрос полного экрана (оставьте включенным по умолчанию) + Опрос полного экрана (оставьте включённым по умолчанию) Low accuracy (turbo mode) @@ -3983,23 +4615,39 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer Включить двигатель дублирования рабочего стола в Windows 8 и более новых версиях + + Maximum CPU usage + Максимальное использование ЦП + - UserConfig + UserLoginDialog - No write access - Нет доступа на запись + User login + Имя пользователя - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - Не удалось сохранить ваши личные настройки! Пожалуйста, проверьте, правильно ли указан путь к файлу настроек пользователей с помощью конфигуратора %1. + Please enter a username and password for automatic login on all computers. + Пожалуйста, введите имя пользователя и пароль для автоматического входа на все компьютеры. + + + Username + Имя пользователя + + + Password + Пароль - UserSessionControl + UserSessionControlPlugin - User session control - Управление сеансами пользователей + Log in + Залогиниться + + + Click this button to log in a specific user on all computers. + Нажмите эту кнопку, чтобы войти в систему под определённым пользователем на всех компьютерах. Log off @@ -4015,7 +4663,15 @@ Typically this is required to support terminal servers. Do you really want to log off the selected users? - Вы действительно хотите выполнить выход из системы для выбранных пользователей? + Действительно выполнить выход из системы для выбранных пользователей? + + + User session control + Управление сеансами пользователей + + + Do you really want to log off <b>ALL</b> users? + Действительно выполнить выход из системы для <b>ВСЕХ</b> пользователей? @@ -4042,7 +4698,7 @@ Typically this is required to support terminal servers. Not enough arguments given - use "%1 help" for more information - Дано недостаточно аргументов - используйте "справку %1" для большей информации + Недостаточно аргументов - используйте "%1 help" для получения дополнительной информации Unknown result! @@ -4068,10 +4724,6 @@ Typically this is required to support terminal servers. ERROR ОШИБКА - - licensed for - лицензировано для - USAGE ИСПОЛЬЗОВАНИЕ @@ -4088,19 +4740,31 @@ Typically this is required to support terminal servers. WARNING ПРЕДУПРЕЖДЕНИЕ + + Authentication test + Тест аутентификации + + + Screen %1 + Экран %1 + - VeyonServiceControl + VeyonMaster - Veyon Service - Сервис Veyon + No write access + Нет доступа на запись + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Не удалось сохранить ваши личные настройки! Пожалуйста, проверьте, правильно ли указан путь к файлу настроек пользователей с помощью конфигуратора %1. - VncView + VeyonServiceControl - Establishing connection to %1 ... - Восстановление соединения с %1 ... + Veyon Service + Сервис Veyon @@ -4148,6 +4812,30 @@ Typically this is required to support terminal servers. Use alternative user authentication mechanism Использовать альтернативный механизм аутентификации пользователей + + User login + Имя пользователя + + + Input start delay + Задержка входа + + + Simulated key presses interval + Имитированный интервал между нажатиями клавиш + + + Confirm legal notice (message displayed before user logs in) + Подтвердить официальное уведомление (сообщение отображается перед входом пользователя) + + + Use input device interception driver + Использовать драйвер перехвата устройства ввода + + + Use custom power scheme with disabled power button + Использовать пользовательскую схему питания с отключенной кнопкой питания + WindowsPlatformPlugin @@ -4156,39 +4844,43 @@ Typically this is required to support terminal servers. Плагин, который реализует абстрактные функции на платформе Windows - Plugin implementing specific functions for the Windows platform - + Internal display + Внутренний дисплей WindowsServiceControl The service "%1" is already installed. - Служба «%1» уже установлена. + Служба "%1" уже установлена. - The service "%1" could not be installed. - Не удалось установить службу «%1». + The service "%1" has been installed successfully. + Служба "%1" была успешно установлена. - The service "%1" has been installed successfully. - Служба «%1» была успешно установлена. + The service "%1" has been uninstalled successfully. + Служба "%1" была успешно деинсталлирована. + + + Service "%1" could not be found. + Не удалось найти службу "%1". - The service "%1" could not be uninstalled. - Не удалось деинсталлировать службу «%1». + The service "%1" could not be installed (error %2). + Не удалось установить службу "%1" (ошибка %2). - The service "%1" has been uninstalled successfully. - Служба «%1» была успешно деинсталирована. + Could not change the failure actions config for service "%1" (error %2). + Не удалось изменить конфигурацию действий при отказе для службы "%1" (ошибка %2). - The start type of service "%1" could not be changed. - Не удалось изменить тип запуска службы «%1». + The service "%1" could not be uninstalled (error %2). + Не удалось деинсталлировать службу "%1" (ошибка %2). - Service "%1" could not be found. - Не удалось найти службу «%1». + The start type of service "%1" could not be changed (error %2). + Не удалось изменить тип запуска службы "%1" (ошибка %2). diff --git a/translations/sl.ts b/translations/veyon_sl.ts similarity index 77% rename from translations/sl.ts rename to translations/veyon_sl.ts index c405b09e3..a9f0eb423 100644 --- a/translations/sl.ts +++ b/translations/veyon_sl.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -80,10 +80,6 @@ If you're interested in translating Veyon into your local or another langua All groups Vse skupine - - ... - ... - Access control rules Pravila za nadzor dostopa @@ -140,19 +136,18 @@ If you're interested in translating Veyon into your local or another langua User groups backend: Uporabniške skupine ozadja: - - Missing user groups backend - Manjkajoče skupine uporabnikov ozadja - - - No default user groups plugin was found. Please check your installation! - Noben privzeti vtičnik uporabniških skupin ni bil najden. Prosimo, preverite namestitev! - Restrict access to members of specific user groups Omejite dostop do članov določenih skupin uporabnikov + + AccessControlProvider + + Provider for access control features + + + AccessControlRuleEditDialog @@ -179,30 +174,10 @@ If you're interested in translating Veyon into your local or another langua Rule description: Opis pravila: - - Invert all conditions ("is/has" interpreted as "is/has not") - Obrni vse pogoje ("je/ima" razloženo kot "je/ni") - Conditions Pogoji - - is member of group - je član skupine - - - Accessing computer is localhost - Dostopni računalnik je lokalni gostitelj - - - Accessing user is logged on user - Dostopni uporabnik je prijavljen na uporabnik - - - Accessing user is already connected - Dostopni uporabnik je že povezan - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. Če je aktiviranih več pogojev, se mora izpolniti vsak pogoj, da se pravilo uporabi (logični AND). Če se mora izpolniti samo eden od več pogojev (logični OR), ustvarite več pravil za nadzor dostopa. @@ -236,33 +211,125 @@ If you're interested in translating Veyon into your local or another langua Dostopni računalnik - Local (logged on) user - Lokalni (prijavljeni) uporabnik + Always process rule and ignore conditions + Vedno obdelaj pravila in prezri pogoje - Local computer - Lokalni računalnik + Accessing computer and local computer + - Always process rule and ignore conditions - Vedno obdelaj pravila in prezri pogoje + User being accessed + - No user logged on - Uporabnik ni prijavljen na + is logged in locally + + + + is logged in remotely + + + + No user is logged in locally + + + + One or multiple users are logged in locally + - Accessing user has one or more groups in common with local (logged on) user - Dostopni uporabnik ima eno ali več skupnin, skupnih z lokalnim (prijavljenim) uporabnikom + No user is logged in remotely + - Accessing computer and local computer are at the same location - Dostop do računalnika in lokalni računalnik sta na isti lokaciji + One or multiple users are logged in remotely + is located at se nahaja na + + is not located at + + + + are located at the same location + + + + are not located the same location + + + + is member of group + je član skupine + + + is not member of group + + + + is authenticated via + + + + is not authenticated via + + + + has one or more groups in common with user being accessed + + + + has no groups in common with user being accessed + + + + equals user being accessed + + + + is different from user being accessed + + + + is already connected + + + + is not connected + + + + is local computer + + + + is not local computer + + + + Computer being accessed + + + + Session being accessed is a user session + + + + Session being accessed is a login screen + + + + Local computer is already being accessed + + + + Local computer is not yet being accessed + + AccessControlRulesTestDialog @@ -306,46 +373,48 @@ If you're interested in translating Veyon into your local or another langua The access in the given scenario needs permission of the logged on user. Dostop v danem scenariju potrebuje dovoljenje prijavljenega uporabnika - - ERROR: Unknown action - NAPAKA: neznano dejanje - Test result Rezultati testa - - - AndroidPlatformConfigurationPage - Android - + Authentication method + Metoda overjanja - General - Splošno + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + Uvod - - - AuthKeysConfigurationPage - Authentication keys - Ključi preverjanja pristnosti + Please perform the following steps to set up key file authentication: + Če želite nastaviti overjanje datotek ključa, naredite naslednje: - Introduction - Uvod + 1) Create a key pair on the master computer. + 1) Ustvarite par ključev na glavnem računalniku. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Nastavite skupino za dostop, katere člani bi morali imeti dostop do drugih računalnikov. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Izvozite javni ključ in ga uvozite v vse odjemalske računalnike z istim imenom. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Prosimo, obiščite <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon skrbniški priročnik</a> za več informacij. Key file directories - Imeniki ključne datoteke + Imeniki datoteke ključa Public key file base directory @@ -355,14 +424,20 @@ If you're interested in translating Veyon into your local or another langua Private key file base directory Imenik datoteke z zasebnim ključem - - ... - ... - Available authentication keys Razpoložljivi ključi za preverjanje pristnosti + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Par ključev za preverjanje pristnosti je sestavljen iz dveh povezanih kriptografskih ključev, zasebnega in javnega ključa. +Zasebni ključ omogoča uporabnikom na glavnem računalniku dostop do odjemalskih računalnikov. +Pomembno je, da imajo samo pooblaščeni uporabniki dostop do datoteke zasebnega ključa. +Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti dohodne povezave. + Create key pair Ustvari par ključev @@ -403,10 +478,6 @@ If you're interested in translating Veyon into your local or another langua Please select a key to delete! Prosimo, izberite ključ za brisanje! - - Please enter the name of the user group or role for which to import the authentication key: - Vnesite ime uporabniške skupine ali vzorca, za katero želite uvoziti ključ za preverjanje pristnosti: - Please select a key to export! Prosimo, izberite ključ za izvoz! @@ -420,34 +491,10 @@ If you're interested in translating Veyon into your local or another langua Izberite ključ, za katerega želite nastaviti skupino za dostop! - Please perform the following steps to set up key file authentication: - Če želite nastaviti overjanje datotek ključa, naredite naslednje: - - - 1) Create a key pair on the master computer. - 1) Ustvarite par ključev na glavnem računalniku. - - - 2) Set an access group whose members should be allowed to access other computers. - 2) Nastavite skupino za dostop, katere člani bi morali imeti dostop do drugih računalnikov. - - - 3) Export the public key and import it on all client computers with the same name. - 3) Izvozite javni ključ in ga uvozite v vse odjemalske računalnike z istim imenom. - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - Prosimo, obiščite <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon skrbniški priročnik</a> za več informacij. - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - Par ključev za preverjanje pristnosti je sestavljen iz dveh povezanih kriptografskih ključev, zasebnega in javnega ključa. -Zasebni ključ omogoča uporabnikom na glavnem računalniku dostop do odjemalskih računalnikov. -Pomembno je, da imajo samo pooblaščeni uporabniki dostop do datoteke zasebnega ključa. -Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti dohodne povezave. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + @@ -625,7 +672,7 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. - Ta ukaz prilagaja dovoljenja za dostop do datotek na <KLJUČ> tako da ima samo skupina uporabnikov <SKUPINA ZA DOSTOP> bralni dostop do njega. + Ta ukaz prilagodi dovoljenja za dostop do datotek <KEY> tako, da ima dostop samo do skupine uporabnikov <ACCESS GROUP>bralni dostop do njega. NAME @@ -647,10 +694,6 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. Ta ukaz navaja vse razpoložljive ključe za overjanje v nastavljenem imeniku ključev. Če je možnost "%1" določena, bo prikazana tabela s podatki ključa namesto tega. Nekateri podatki morda manjkajo, če ključ ni dostopen, npr. zaradi pomanjkanja dovoljenj za branje. - - Please specify the command to display help for! - Navedite ukaz za prikaz pomoči! - TYPE VRSTA @@ -659,10 +702,6 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti PAIR ID PAR ID - - Command line support for managing authentication keys - Podpora za ukazno vrstico za upravljanje ključev za preverjanje pristnosti - Commands for managing authentication keys Ukazi za upravljanje ključev za preverjanje pristnosti @@ -679,6 +718,30 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. Ta ukaz izdela del javnega ključa iz zasebnega ključa <KEY> in ga shrani kot ustrezen javni ključ. Pri nastavljanju drugega glavnega računalnika je torej dovolj, da prenesete samo zasebni ključ. Nato se lahko izvleče javni ključ. + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + + + + Key file authentication + Preverjanje pristnosti z datotečnim ključem + + + Key file + Datoteka ključa + + + Please specify the key name (e.g. "teacher/public") as the first argument. + + + + Please specify the command to display help for. + + + + The specified command does not exist or no help is available for it. + + AuthKeysTableModel @@ -700,63 +763,206 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - Računalniki + General + Splošno - Name - Ime + Username to bind DN mapping: + - Host address/IP - Ime gostitelja/IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + + AuthLdapDialog - MAC address - MAC naslov + Veyon Logon + Veyon prijava - Add new computer - Dodaj nov računalnik + Please enter your domain/LDAP username and password in order to access computers. + - Remove selected computer - Odstrani izbrani računalnik + Username + Uporabniško ime - New computer - Nov računalnik + Password + Geslo - Builtin directory - Vgrajen imenik + Authentication error + Napaka preverjanja pristnosti - Locations & computers - Lokacije in računalniki + Logon failed with given username and password. Please try again! + Prijava z neodobrenim uporabniškim imenom in geslom ni uspela. Prosim, poskusite ponovno! + + + AuthLogonDialog - Locations - Lokacije + Veyon Logon + Veyon prijava - Add new location - Dodaj novo lokacijo + Please enter your username and password in order to access computers. + Vnesite svoje uporabniško ime in geslo za dostop do računalnikov. - Remove selected location - Odstrani izbrano lokacijo + Username + Uporabniško ime + + + Password + Geslo + + + Authentication error + Napaka preverjanja pristnosti + + + Logon failed with given username and password. Please try again! + Prijava z neodobrenim uporabniškim imenom in geslom ni uspela. Prosim, poskusite ponovno! + + + + AuthLogonPlugin + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + + + + Logon authentication + Preverjanje pristnosti prijave + + + Logon + + + + + AuthSimpleDialog + + Veyon Logon + Veyon prijava + + + Please enter the Veyon password: + + + + Authentication error + Napaka preverjanja pristnosti + + + Logon failed with given password. Please try again! + + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + + + + Simple password authentication + + + + Simple password + + + + + AuthenticationPage + + Authentication is set up properly on this computer. + Preverjanje pristnosti je pravilno nastavljeno v tem računalniku. + + + + AuthenticationPageTab + + Enabled + + + + Test + Preizkus + + + + BuiltinDirectoryConfiguration + + Builtin directory + Vgrajen imenik + + + + BuiltinDirectoryConfigurationPage + + Computers + Računalniki + + + Name + Ime + + + Host address/IP + Ime gostitelja/IP + + + MAC address + MAC naslov + + + Add new computer + Dodaj nov računalnik + + + Remove selected computer + Odstrani izbrani računalnik + + + New computer + Nov računalnik + + + Builtin directory + Vgrajen imenik + + + Locations + Lokacije + + + Add new location + Dodaj novo lokacijo - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - Uvoz CSV datotek je možen prek vmesnika ukazne vrstice. Za več informacij, glejte <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">spletna dokumentacija</a>. + Remove selected location + Odstrani izbrano lokacijo New location Nova lokacija + + Directory name + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + BuiltinDirectoryPlugin @@ -1000,6 +1206,14 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti MAC ADDRESS MAC naslov + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. + + BuiltinUltraVncServer @@ -1017,10 +1231,6 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti ComputerControlListModel - - Host/IP address: %1 - Gostitelj/IP naslov: %1 - Active features: %1 Aktivne funkcije: %1 @@ -1037,10 +1247,6 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Computer offline or switched off Računalnik je brez povezave ali izklopljen - - Service unreachable or not running - Storitev ni dosegljiva ali se ne izvaja - Authentication failed or access denied Preverjanje pristnosti ni uspelo ali je dostop zavrnjen @@ -1061,6 +1267,38 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Location: %1 Lokacija: %1 + + [no user] + + + + Veyon Server unreachable or not running + + + + Name: %1 + + + + Hostname: %1 + + + + unknown + neznano + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + ComputerControlServer @@ -1092,6 +1330,17 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + + Active connections: + + + + + ComputerGroupSelector + + Group %1 + + ComputerManager @@ -1119,80 +1368,83 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. Ne morem določiti lokacije tega računalnika. To kaže na težavo s konfiguracijo sistema. Namesto tega bodo v izbranem oknu računalnika prikazane vse lokacije. - - - ComputerSelectPanel - Computer management - Upravljanje računalnika + Logged in since + - Computer search - Preišči računalnik + %1 days + - Add location - Dodaj lokacijo + 1 day + + + + ComputerMonitoring - Save computer/user list - Shrani seznam računalnikov/uporabnikov + Computers + Računalniki - Select output filename - Izberi izhodno ime datoteke + Search users and computers + Iskanje uporabnikov in računalnikov - CSV files (*.csv) - CSV datoteka (*.csv) + Select all + - File error - Napaka v datoteki + Unselect all + - Could not write the computer and users list to %1! Please check the file access permissions. - Računalnika in uporabnikov ni mogoče vpisati v seznam %1! Preverite dovoljenja za dostop do datotek. + Add to group + - - - ConfigCommandLinePlugin - Please specify an existing configuration file to import. - Navedite obstoječo konfiguracijsko datoteko za uvoz. + Remove from group + + + + ComputerSelectPanel - Please specify a valid filename for the configuration export. - Navedite veljavno ime datoteke za izvoz konfiguracije. + Computer search + Preišči računalnik - Please specify a valid key. - Prosimo, navedite veljaven ključ. + Add location + Dodaj lokacijo - Specified key does not exist in current configuration! - Določen ključ v trenutni konfiguraciji ne obstaja! + Save computer/user list + Shrani seznam računalnikov/uporabnikov - Please specify a valid value. - Navedite veljavno vrednost. + Select output filename + Izberi izhodno ime datoteke - Configure Veyon at command line - Konfigurirajte Veyon v ukazni vrstici + CSV files (*.csv) + CSV datoteka (*.csv) - Output file is not writable! - Izhodna datoteka ni zapisljiva! + File error + Napaka v datoteki - Output directory is not writable! - Izhodna mapa ni zapisljiva! + Could not write the computer and users list to %1! Please check the file access permissions. + Računalnika in uporabnikov ni mogoče vpisati v seznam %1! Preverite dovoljenja za dostop do datotek. - Configuration file is not readable! - Konfiguracijska datoteka ni berljiva! + Search computers + + + + ConfigCommands Clear system-wide Veyon configuration Počisti celotno sistemsko Veyon konfiguracijo @@ -1221,28 +1473,64 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Unset (remove) given configuration key Odstranite dodeljeni konfiguracijski ključ - - Commands for managing the configuration of Veyon - Ukazi za upravljanje konfiguracije Veyon - Upgrade and save configuration of program and plugins Nadgradite in shranite konfiguracijo programa in vtičnikov - - - ConfigurationManager - Could not modify the autostart property for the %1 Service. - Lastnosti samodejnega zagona za storitev %1 ni bilo mogoče spremeniti. + Please specify an existing configuration file to import. + Navedite obstoječo konfiguracijsko datoteko za uvoz. - Could not configure the firewall configuration for the %1 Server. - Konfiguracije požarnega zidu za strežnik %1 ni bilo mogoče konfigurirati. + Configuration file is not readable! + Konfiguracijska datoteka ni berljiva! - Could not configure the firewall configuration for the %1 Worker. - Konfiguracije požarnega zidu za delavca %1 ni bilo mogoče konfigurirati. + Please specify a valid filename for the configuration export. + Navedite veljavno ime datoteke za izvoz konfiguracije. + + + Output file is not writable! + Izhodna datoteka ni zapisljiva! + + + Output directory is not writable! + Izhodna mapa ni zapisljiva! + + + Please specify a valid key. + Prosimo, navedite veljaven ključ. + + + Specified key does not exist in current configuration! + Določen ključ v trenutni konfiguraciji ne obstaja! + + + Please specify a valid value. + Navedite veljavno vrednost. + + + Configure Veyon at command line + Konfigurirajte Veyon v ukazni vrstici + + + Commands for managing the configuration of Veyon + Ukazi za upravljanje konfiguracije Veyon + + + + ConfigurationManager + + Could not modify the autostart property for the %1 Service. + Lastnosti samodejnega zagona za storitev %1 ni bilo mogoče spremeniti. + + + Could not configure the firewall configuration for the %1 Server. + Konfiguracije požarnega zidu za strežnik %1 ni bilo mogoče konfigurirati. + + + Could not configure the firewall configuration for the %1 Worker. + Konfiguracije požarnega zidu za delavca %1 ni bilo mogoče konfigurirati. Configuration is not writable. Please check your permissions! @@ -1252,6 +1540,10 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Could not apply platform-specific configuration settings. + + Could not configure the firewall configuration for the %1 Service. + + DemoClient @@ -1282,10 +1574,6 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Memory limit Omejitev pomnilnika - - Use multithreading (experimental) - Uporabite večnitnostnost (eksperimentalno) - MB MB @@ -1302,13 +1590,17 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Slow down thumbnail updates while demo is running + + Bandwidth limit + + + + MB/s + + DemoFeaturePlugin - - Fullscreen demo - Predavaj v celem zaslonu - Stop demo Ustavi predavanje @@ -1322,16 +1614,60 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Podaj predstavitev z zaslonom predvajanja - Demo server - Demonstracijski strežnik + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + V tem načinu se zaslon prikaže v oknu na vseh računalnikih. Uporabniki lahko po potrebi preklopijo na druga okna. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - V tem načinu se vaš zaslon prikaže v celozaslonskem načinu na vseh računalnikih, medtem ko so vhodne naprave uporabnikov zaklenjene. + Demo + - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - V tem načinu se zaslon prikaže v oknu na vseh računalnikih. Uporabniki lahko po potrebi preklopijo na druga okna. + Share your screen or allow a user to share his screen with other users. + + + + Full screen demo + + + + Share your own screen in fullscreen mode + + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share your own screen in a window + + + + Share selected user's screen in fullscreen mode + + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share selected user's screen in a window + + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + + + + Please select only one user screen to share. + + + + All screens + @@ -1359,14 +1695,6 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti DesktopServicesConfigurationPage - - Programs & websites - Programi in spletne strani - - - Predefined programs - Vnaprej določeni programi - Name Ime @@ -1375,14 +1703,6 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Path Pot - - Add new program - Dodaj nov program - - - Remove selected program - Odstrani izbrani program - Predefined websites Vnaprej določene spletne strani @@ -1395,21 +1715,37 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti URL URL - - New program - Nov program - New website Nova spletna stran + + Applications & websites + + + + Predefined applications + + + + Add new application + + + + Remove selected application + + + + Add new website + + + + New application + + DesktopServicesFeaturePlugin - - Run program - Zaženi program - Open website Odpri spletno stran @@ -1419,28 +1755,32 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Kliknite ta gumb, da odprete spletno mesto na vseh računalnikih. - Start programs and services in user desktop - Zaženite programe in storitve na uporabniškem namizju + Open website "%1" + Odpri spletno stran "%1" - Click this button to run a program on all computers. - Kliknite ta gumb za zagon programa na vseh računalnikih. + Custom website + Spletna stran po meri - Run program "%1" - Zaženi program "%1" + Start application + - Custom program - Program po meri + Click this button to start an application on all computers. + - Open website "%1" - Odpri spletno stran "%1" + Start application "%1" + - Custom website - Spletna stran po meri + Custom application + + + + Start apps and open websites in user sessions + @@ -1473,10 +1813,6 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Play tutorial video - - Custom program - Program po meri - Handout @@ -1485,6 +1821,14 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Texts to read + + generic-student-user + + + + Custom application + + ExternalVncServer @@ -1509,141 +1853,299 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti - FeatureControl + FeatureCommands - Feature control - Funkcija nadzora + List names of all available features + - - - FileTransferController - Could not open file "%1" for reading! Please check your permissions! - Žal ne morem odpreti datoteke "%1" za branje! Prosimo, preverite svoja dovoljenja! + Show table with details of all available features + - - - FileTransferDialog - File transfer - Prenos datoteke + Start a feature on a remote host + - Options - Možnosti + Stop a feature on a remote host + - Transfer only - Samo prenos + Please specify the command to display help for. + - Transfer and open file(s) with associated program - Prenesi in odpri datoteko(e) s pripadajočim programom + Displays a list with the names of all available features. + - Transfer and open destination folder - Prenesi in odpri ciljno mapo + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + - Files - Datoteke + HOST ADDRESS + NASLOV GOSTITELJA - Start - Začetek + FEATURE + - Overwrite existing files - Prepiši obstoječe datoteke + ARGUMENTS + - - - FileTransferPlugin - File transfer - Prenos datoteke + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + - Click this button to transfer files from your computer to all computers. - Klikni na ta gumb za prenos datotek iz vašega računalnika na vse računalnike. + Lock the screen + - Select one or more files to transfer - Izberi eno ali več datotek za prenos + Display a text message + - Transfer files to remote computer - Prenesi datoteke na oddaljeni računalnik + Test message + - Received file "%1". - Prejeta datoteka "%1". + Start an application + - Could not receive file "%1" as it already exists. - Ne morem prejeti datoteke "%1", ker že obstaja. + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + - Could not receive file "%1" as it could not be opened for writing! - Datoteke "%1" ni bilo mogoče prejeti, ker je ni bilo mogoče odpreti za pisanje! + Unlock the screen + - - - GeneralConfigurationPage - User interface - Uporabniški vmesnik + The specified command does not exist or no help is available for it. + - Language: - Jezik: + Name + Ime - Use system language setting - Uporabi sistemske nastavitve jezika + Description + - Veyon - Veyon + Master + Glavni - Logging - Beleženje + Service + Storitev - Log file directory - Imenik datoteke dnevnikov + Worker + - ... - ... + UID + - Log level - Nivo beleženja + Plugin + Vtičnik - Nothing - Nič + Invalid feature name or UID specified + - Only critical messages - Samo kritična sporočila + Error parsing the JSON-encoded arguments: %1 + - Errors and critical messages - Napake in kritična sporočila + Failed to initialize credentials + - Warnings and errors - Opozorila in napake + Could not establish a connection to host %1 + - Information, warnings and errors - Informacije, opozorila in napake + Failed to send feature control message to host %1 + - Debug messages and everything else + Feature-related CLI operations + + + + Commands for controlling features + + + + + FileTransferConfigurationPage + + File transfer + Prenos datoteke + + + Directories + Imeniki + + + Destination directory + + + + Default source directory + + + + Options + Možnosti + + + Remember last source directory + + + + Create destination directory if it does not exist + + + + + FileTransferController + + Could not open file "%1" for reading! Please check your permissions! + Žal ne morem odpreti datoteke "%1" za branje! Prosimo, preverite svoja dovoljenja! + + + + FileTransferDialog + + File transfer + Prenos datoteke + + + Options + Možnosti + + + Transfer only + Samo prenos + + + Transfer and open file(s) with associated program + Prenesi in odpri datoteko(e) s pripadajočim programom + + + Transfer and open destination folder + Prenesi in odpri ciljno mapo + + + Files + Datoteke + + + Start + Začetek + + + Overwrite existing files + Prepiši obstoječe datoteke + + + + FileTransferFileDialog + + Select one or more files to transfer + Izberi eno ali več datotek za prenos + + + + FileTransferPlugin + + File transfer + Prenos datoteke + + + Click this button to transfer files from your computer to all computers. + Klikni na ta gumb za prenos datotek iz vašega računalnika na vse računalnike. + + + Select one or more files to transfer + Izberi eno ali več datotek za prenos + + + Transfer files to remote computer + Prenesi datoteke na oddaljeni računalnik + + + Received file "%1". + Prejeta datoteka "%1". + + + Could not receive file "%1" as it already exists. + Ne morem prejeti datoteke "%1", ker že obstaja. + + + Could not receive file "%1" as it could not be opened for writing! + Datoteke "%1" ni bilo mogoče prejeti, ker je ni bilo mogoče odpreti za pisanje! + + + + GeneralConfigurationPage + + User interface + Uporabniški vmesnik + + + Language: + Jezik: + + + Use system language setting + Uporabi sistemske nastavitve jezika + + + Veyon + Veyon + + + Logging + Beleženje + + + Log file directory + Imenik datoteke dnevnikov + + + Log level + Nivo beleženja + + + Nothing + Nič + + + Only critical messages + Samo kritična sporočila + + + Errors and critical messages + Napake in kritična sporočila + + + Warnings and errors + Opozorila in napake + + + Information, warnings and errors + Informacije, opozorila in napake + + + Debug messages and everything else Razhroščevanje sporočil in vsega ostalega @@ -1658,18 +2160,6 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Log to standard error output Dnevnik na standardni izhod za napako - - Network object directory - Imenik omrežnih objektov - - - Backend: - Ozadje: - - - Update interval: - Posodobi interval: - %1 service %1 storitev @@ -1706,117 +2196,423 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti x x - - seconds - sekund - Write to logging system of operating system Zapiši v sistem beleženja operacijskega sistema - Authentication - Preverjanje pristnosti + TLS configuration + - Method: - Metoda: + Use certificate authority for TLS connections + - Logon authentication - Preverjanje pristnosti prijave + CA certificate file + - Key file authentication - Preverjanje pristnosti z datotečnim ključem + ... + ... - Test - Preizkus + Host certificate file + - Authentication is set up properly on this computer. - Preverjanje pristnosti je pravilno nastavljeno v tem računalniku. + Host private key file + + + + Style: + + + + Native + + + + Color scheme: + + + + Light + + + + Dark + + + + User groups + + + + Backend: + Ozadje: + + + Include user groups from domain + + + + Missing user groups backend + Manjkajoče skupine uporabnikov ozadja + + + No user groups plugin was found. Please check your installation! + + + + + HeadlessVncServer + + Headless VNC server + + + + + LdapBrowseDialog + + Browse LDAP + Brskaj po LDAP + + + + LdapClient + + LDAP error description: %1 + Opis napake LDAP: %1 + + + + LdapConfiguration + + LDAP connection failed + Neuspela povezava na LDAP + + + Could not connect to the LDAP server. Please check the server parameters. + +%1 + Povezave s strežnikom LDAP ni bilo mogoče vzpostaviti. Preverite parametre strežnika. + +%1 + + + LDAP bind failed + Povezava LDAP ni uspela + + + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + Ne morem se povezati na strežnik LDAP. Preverite parametre strežnika in povezovalne poverilnice. + +%1 + + + LDAP bind successful + Povezava LDAP je uspela + + + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Uspelo se je povezati s strežnikom LDAP in opraviti povezavo LDAP. Osnovne nastavitve LDAP so pravilno konfigurirane. + + + LDAP base DN test failed + LDAP base DN test ni uspel + + + Could not query the configured base DN. Please check the base DN parameter. + +%1 + Ni mogoča poizvedba nastavljene base DN. Preverite base DN parameter. + +%1 + + + LDAP base DN test successful + LDAP base DN test je uspel + + + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + Poizvedba LDAP base DN je bila uspešna. Ugotovljeni so bili naslednji vnosi: + +%1 + + + LDAP naming context test failed + Ozadje poimenovanja LDAP ni uspelo - Authentication keys are not set up properly on this computer. - Ključi za preverjanje pristnosti v tem računalniku niso pravilno nastavljeni. + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + Neuspešna poizvedba base DN preko kontekstnih poimenovanj . Preverite parameter atributa konteksta poimenovanja. + +%1 + + + LDAP naming context test successful + Ozadje poimenovanja LDAP je uspelo + + + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + Ozadje imena poimenovanja LDAP je bilo uspešno preverjeno. Najden je bil naslednji osnovni DN: +%1 + + + user tree + uporabniško drevo + + + User tree + Uporabniško drevo + + + group tree + skupinsko drevo + + + Group tree + Skupinsko drevo + + + computer tree + računalniško drevo + + + Computer tree + Računalniško drevo + + + computer group tree + drevo računalniške skupine + + + Computer group tree + Drevo računalniške skupine + + + user objects + uporabnikovi predmeti + + + User login name attribute + Atribut uporabniškega imena za prijavo + + + group members + člani skupine + + + Group member attribute + Atribut člana skupine + + + Group not found + Skupine ni bilo mogoče najti + + + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Ni bilo mogoče najti skupine z imenom "%1". Preverite ime skupine ali parameter drevesa skupine. + + + computer objects + računalniški predmeti + + + Computer display name attribute + Atribut prikaznega imena računalnika + + + Invalid hostname + Neveljavno ime gostitelja + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Konfigurirali ste računalniška imena gostiteljev, ki jih želite shraniti kot popolne domene (FQDN), vendar ste vnesli ime gostitelja brez domene. + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Računalniška imena gostiteljev ste konfigurirali za shranjevanje kot preprosta imena gostiteljev brez imena domene, vendar ste vnesli ime gostitelja z delom imena domene. + + + Computer hostname attribute + Atribut gostiteljskega računalnika + + + computer MAC addresses + računalnik MAC naslovov + + + Computer MAC address attribute + Atribut MAC naslova računalnika + + + computer locations + lokacije računalnika + + + Computer location attribute + Atribut lokacije računalnika + + + Location name attribute + Atribut imena mesta + + + users + uporabniki + + + user groups + skupine uporabnikov + + + computers + računalniki + + + computer groups + skupine računalnikov + + + computer containers + + + + groups of user + skupine uporabnika + + + User not found + Uporabnik ni najden + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + Uporabnika z imenom "%1" ni bilo mogoče najti. Preverite uporabniško ime ali parameter drevesa uporabnika. + + + groups of computer + skupine računalnika + + + Computer not found + Računalnika ni bilo mogoče najti + + + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Ni bilo mogoče najti računalnika z imenom gostitelja "%1". Preverite ime gostitelja ali parameter drevesa računalnika. + + + Hostname lookup failed + Iskanje imena gostitelja ni uspelo + + + Could not lookup hostname for IP address %1. Please check your DNS server settings. + Ni bilo mogoče iskati imena gostitelja za IP naslov %1. Preverite nastavitve strežnika DNS. + + + location entries + vnosi lokacije + + + Computer groups filter + + + + Computer locations identification + Identifikacija lokacij računalnika + + + Filter for computer groups + Filter za računalniške skupine - Authentication test - Preverjanje pristnosti + Invalid test value + - - - InternetAccessControlConfigurationPage - Internet access control - Nadzor dostopa do interneta + An empty or invalid value has been supplied for this test. + - Backend: - Ozadje: + LDAP %1 test failed + Preizkus LDAP %1 ni uspel - General settings - Splošne nastavitve + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + Ni bila mogoča poizvedba o vnosih v konfiguriranem %1. Preverite parameter "%2". + +%3 - Backend settings - Nastavitve ozadja + LDAP %1 test successful + Preizkus LDAP %1 je uspel - - - InternetAccessControlPlugin - Block access to the internet - Blokiraj dostop do interneta + The %1 has been queried successfully and %2 entries were found. + %1 je bila uspešna poizvedba in ugotovljeno je, da je bilo %2 vnosov. - Allow access to the internet - Dovoli dostop do interneta + LDAP test failed + Preizkus LDAP ni uspel - Show help about command - Prikaži pomoč o ukazu + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + Za noben %1 ni bila mogoča poizvedba. Preverite parametre %2 in vnesite ime obstoječega objekta. + +%3 - Block internet - Blokiraj internet + and + in - Click this button to block access to the internet. - Kliknite ta gumb, da blokirate dostop do interneta. + LDAP test successful + Test LDAP uspešen - Unblock internet - Odblokiraj internet + %1 %2 have been queried successfully: + +%3 + %1 %2 je bilo uspešno vprašanih: + +%3 - Click this button to allow access to the internet. - Kliknite ta gumb, da omogočite dostop do interneta. + LDAP filter test failed + Test LDAP filtra ni uspel - Control access to the internet - Nadzor dostopa do interneta + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 + Ni bilo mogoče izvesti poizvedbe %1 z uporabo nastavljenega filtra. Preverite filter LDAP za %1. + +%2 - Commands for controlling access to the internet - Ukazi za nadzor dostopa do interneta + LDAP filter test successful + Test LDAP filtra je uspel - - - LdapBrowseDialog - Browse LDAP - Brskaj po LDAP + %1 %2 have been queried successfully using the configured filter. + %1 %2 je bilo uspešno vprašanih z uporabo nastavljenega filtra. - - - LdapClient - LDAP error description: %1 - Opis napake LDAP: %1 + LDAP directory + @@ -1875,7 +2671,7 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Object trees - Predmetna drevesa + Objektna drevesa Computer tree @@ -1973,56 +2769,6 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Get computer object by IP address Pridobi računalniški predmet po naslovu IP - - LDAP connection failed - Neuspela povezava na LDAP - - - LDAP bind failed - Povezava LDAP ni uspela - - - LDAP bind successful - Povezava LDAP je uspela - - - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - Uspelo se je povezati s strežnikom LDAP in opraviti povezavo LDAP. Osnovne nastavitve LDAP so pravilno konfigurirane. - - - LDAP base DN test failed - LDAP base DN test ni uspel - - - LDAP base DN test successful - LDAP base DN test je uspel - - - LDAP naming context test failed - Ozadje poimenovanja LDAP ni uspelo - - - LDAP naming context test successful - Ozadje poimenovanja LDAP je uspelo - - - The LDAP naming context has been queried successfully. The following base DN was found: -%1 - Ozadje imena poimenovanja LDAP je bilo uspešno preverjeno. Najden je bil naslednji osnovni DN: -%1 - - - user tree - uporabniško drevo - - - group tree - skupinsko drevo - - - computer tree - računalniško drevo - Enter username Vnesite uporabniško ime @@ -2031,10 +2777,6 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Please enter a user login name (wildcards allowed) which to query: Vnesite uporabniško ime za prijavo (omogočeni so nadomestni znaki) za poizvedbo: - - user objects - uporabnikovi predmeti - Enter group name Vnesi ime skupine @@ -2043,26 +2785,10 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Please enter a group name whose members to query: Vnesite ime skupine, katerega člani lahko poizvedujejo: - - group members - člani skupine - - - Group not found - Skupine ni bilo mogoče najti - - - Could not find a group with the name "%1". Please check the group name or the group tree parameter. - Ni bilo mogoče najti skupine z imenom "%1". Preverite ime skupine ali parameter drevesa skupine. - Enter computer name Vnesite ime računalnika - - computer objects - računalniški predmeti - Enter computer DN Vnesite DN računalnika @@ -2071,42 +2797,10 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Please enter the DN of a computer whose MAC address to query: Vnesite DN računalnika, katerega naslov MAC je za poizvedbo: - - computer MAC addresses - računalnik MAC naslovov - - - users - uporabniki - - - user groups - skupine uporabnikov - - - computer groups - skupine računalnikov - Please enter a user login name whose group memberships to query: Prosimo, vnesite uporabniško ime za prijavo katerega člani skupine želite poizvedovati: - - groups of user - skupine uporabnika - - - User not found - Uporabnik ni najden - - - groups of computer - skupine računalnika - - - Computer not found - Računalnika ni bilo mogoče najti - Enter computer IP address Vnesite računalnikov IP naslov @@ -2115,50 +2809,6 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Please enter a computer IP address which to resolve to an computer object: Vnesite IP naslov računalnika, ki ga želite razrešiti na računalniški objekt: - - computers - računalniki - - - LDAP %1 test failed - Preizkus LDAP %1 ni uspel - - - LDAP %1 test successful - Preizkus LDAP %1 je uspel - - - The %1 has been queried successfully and %2 entries were found. - %1 je bila uspešna poizvedba in ugotovljeno je, da je bilo %2 vnosov. - - - %1 %2 have been queried successfully: - -%3 - %1 %2 je bilo uspešno vprašanih: - -%3 - - - LDAP filter test failed - Test LDAP filtra ni uspel - - - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 - Ni bilo mogoče izvesti poizvedbe %1 z uporabo nastavljenega filtra. Preverite filter LDAP za %1. - -%2 - - - LDAP filter test successful - Test LDAP filtra je uspel - - - %1 %2 have been queried successfully using the configured filter. - %1 %2 je bilo uspešno vprašanih z uporabo nastavljenega filtra. - (only if different from group tree) (le, če je drugačen od drevesa skupine) @@ -2167,10 +2817,6 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Computer group tree Drevo računalniške skupine - - computer group tree - drevo računalniške skupine - Filter for computers Filter za računalnike @@ -2245,55 +2891,15 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti e.g. (objectClass=room) or (objectClass=computerLab) - npr. (objectClass = soba) ali npr. (objectClass = računalnikLab) - - - e.g. (objectClass=container) or (objectClass=organizationalUnit) - npr. (objectClass = vsebnik) ali npr. (objectClass = organizacijska enota) - - - Could not query the configured base DN. Please check the base DN parameter. - -%1 - Ni mogoča poizvedba nastavljene base DN. Preverite base DN parameter. - -%1 - - - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - Poizvedba LDAP base DN je bila uspešna. Ugotovljeni so bili naslednji vnosi: - -%1 - - - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - Neuspešna poizvedba base DN preko kontekstnih poimenovanj . Preverite parameter atributa konteksta poimenovanja. - -%1 - - - Certificate files (*.pem) - Datoteke potrdil (*.pem) - - - Could not connect to the LDAP server. Please check the server parameters. - -%1 - Povezave s strežnikom LDAP ni bilo mogoče vzpostaviti. Preverite parametre strežnika. - -%1 + npr. (objectClass = soba) ali npr. (objectClass = računalnikLab) - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - Ne morem se povezati na strežnik LDAP. Preverite parametre strežnika in povezovalne poverilnice. - -%1 + e.g. (objectClass=container) or (objectClass=organizationalUnit) + npr. (objectClass = vsebnik) ali npr. (objectClass = organizacijska enota) + + + Certificate files (*.pem) + Datoteke potrdil (*.pem) Encryption protocol @@ -2351,10 +2957,6 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Please enter the name of a computer location (wildcards allowed): Vnesi ime lokacije računalnika (dovoljeni nadomestni znaki): - - computer locations - lokacije računalnika - Enter location name Vnesi ime lokacije @@ -2363,38 +2965,6 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Please enter the name of a location whose entries to query: Vnesi ime lokacije, katere vnosi so za poizvedbo: - - location entries - vnosi lokacije - - - LDAP test failed - Preizkus LDAP ni uspel - - - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - Za noben %1 ni bila mogoča poizvedba. Preverite parametre %2 in vnesite ime obstoječega objekta. - -%3 - - - and - in - - - LDAP test successful - Test LDAP uspešen - - - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - Ni bila mogoča poizvedba o vnosih v konfiguriranem %1. Preverite parameter "%2". - -%3 - Browse Brskanje @@ -2416,51 +2986,50 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Vnesite ime gostiteljskega računalnika za poizvedbo: - Invalid hostname - Neveljavno ime gostitelja - - - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Konfigurirali ste računalniška imena gostiteljev, ki jih želite shraniti kot popolne domene (FQDN), vendar ste vnesli ime gostitelja brez domene. + Enter hostname + Vnesite ime gostitelja - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - Računalniška imena gostiteljev ste konfigurirali za shranjevanje kot preprosta imena gostiteljev brez imena domene, vendar ste vnesli ime gostitelja z delom imena domene. + Please enter a computer hostname whose group memberships to query: + Vnesite ime gostitelja računalnika, ki je član v skupini za poizvedbo: - Could not find a user with the name "%1". Please check the username or the user tree parameter. - Uporabnika z imenom "%1" ni bilo mogoče najti. Preverite uporabniško ime ali parameter drevesa uporabnika. + User login name attribute + Atribut uporabniškega imena za prijavo - Enter hostname - Vnesite ime gostitelja + Configured attribute for user login name or computer hostname (OpenLDAP) + Konfiguriran atribut za uporabniško ime za prijavo ali ime gostitelja računalnika (OpenLDAP) - Please enter a computer hostname whose group memberships to query: - Vnesite ime gostitelja računalnika, ki je član v skupini za poizvedbo: + Directory name + - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - Ni bilo mogoče najti računalnika z imenom gostitelja "%1". Preverite ime gostitelja ali parameter drevesa računalnika. + Query options + - Hostname lookup failed - Iskanje imena gostitelja ni uspelo + Query nested user groups (supported by AD only) + - Could not lookup hostname for IP address %1. Please check your DNS server settings. - Ni bilo mogoče iskati imena gostitelja za IP naslov %1. Preverite nastavitve strežnika DNS. + Query timeout + - User login name attribute - Atribut uporabniškega imena za prijavo + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - Configured attribute for user login name or computer hostname (OpenLDAP) - Konfiguriran atribut za uporabniško ime za prijavo ali ime gostitelja računalnika (OpenLDAP) + LDAP + LDAP - computer containers + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. @@ -2510,215 +3079,19 @@ Javni ključ se uporablja v odjemalskih računalnikih za preverjanje pristnosti Configuring %1 as base DN and disabling naming context queries. - - - LdapProConfigurationPage - - LDAP Pro - LDAP Pro - - - Instances - Primerki - - - Enter name - Vnesi ime - - - Please enter a name for the instance (can't be changed later!): - Vnesite ime primerka (kasneje ga ni mogoče spremeniti!): - - - Remove instance - Odstrani primerek - - - Do you really want to remove instance "%1"? - Ali res želite odstraniti primerek "%1"? - - - Configuration for instance "%1" - Konfiguracija za primerek "%1" - - - - LdapProPlugin - - Professional LDAP/AD integration for Veyon - Profesionalna LDAP/AD integracija za Veyon - - - %1 (load computers and locations from LDAP/AD) - %1 (naložite računalnike in lokacije iz LDAP/AD) - - - %1 (load users and groups from LDAP/AD) - %1 (naložite uporabnike in skupine iz LDAP/AD) - - - - LicensingConfigurationPage - - Licensing - Licenciranje - - - Installed licenses - Nameščene licence - - - Add new network range - Dodajte novo omrežno območje - - - Remove selected network range - Odstranite izbrano omrežno območje - - - ID - ID - - - Feature - Funkcija - - - Valid until - Veljavno do - - - Licensee - Licenca - - - Browse license file - Brskanje po datoteki licence - - - Veyon license files (*.vlf) - Veyon licenčne datoteke (*.vlf) - - - Remove license - Odstrani licenco - - - Do you really want to remove the selected license? - Ali res želite odstraniti izbrano licenco? - - - <N/A> - <N/A> - - - Invalid license file - Neveljavna licenčna datoteka - - - Could not open the license file for reading! - Datoteke z licenco ni bilo mogoče odpreti za branje! - - - The selected license file does not contain valid data. - Izbrana licenčna datoteka ne vsebuje veljavnih podatkov. - - - The selected license file could not be verified. - Izbrane datoteke licence ni bilo mogoče preveriti. - - - The selected license file is not valid for this installation. - Izbrana datoteka licence ni veljavna za to namestitev. - - - The selected license file is expired. - Izbrana datoteka z licenco je potekla. - - - The license is already installed. - Licenca je že nameščena. - - - Information - - - Installation ID + Test binding to an LDAP server - Addons available for licensing + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Addon + LDAP bind - - LicensingPlugin - - Show help for specific command - Prikaži pomoč za določen ukaz - - - Show all installed licenses - Pokaži vse nameščene licence - - - Add license file - Dodaj licenčno datoteko - - - Remove installed license - Odstrani licenčno datoteko - - - -USAGE - -%1 add <LICENSE FILE> - - - -UPORABA - -%1 dodana <LICENSE FILE> - - - - - -USAGE - -%1 remove <LICENSE ID> - - - -UPORABA - -%1 odstranjena <LICENSE ID> - - - - - No certificate found with given ID - Z danim ID-jem ni bilo najdenega nobenega potrdila - - - <N/A> - <N/A> - - - Licensing management - Upravljanje licenc - - - Commands for managing license keys - Ukazi za upravljanje licenčnih ključev - - LinuxPlatformConfigurationPage @@ -2734,11 +3107,19 @@ UPORABA - Session management + User sessions - Display manager users + Minimum session lifetime before server start + + + + User login + + + + Login key sequence @@ -2748,10 +3129,6 @@ UPORABA Plugin implementing abstract functions for the Linux platform Vtičnik izvajanja abstraktnih funkcij za platformo Linux - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2768,16 +3145,16 @@ UPORABA MainToolBar Configuration - Nastavitev - - - Disable balloon tooltips - Onemogoči namige v balončkih + Nastavitve Show icons only Prikaži samo ikone + + Disable tooltips + + MainWindow @@ -2825,10 +3202,6 @@ UPORABA About Qt Vizitka Qt - - Authentication impossible - Preverjanje pristnosti ni mogoče - Configuration not writable Nastavitve niso zapisljive @@ -2889,10 +3262,6 @@ UPORABA The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. Lokalno konfiguracijsko ozadje je sporočilo, da konfiguracije ni mogoče zapisati! Konfiguratorja %1 zaženite z višjimi pravicami. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - Datoteke ključa za preverjanje pristnosti niso bile najdene, ali so vaše trenutne zastarele. Ustvarite nove datoteke ključa z uporabo konfiguratorja %1. Druga možnost je nastaviti preverjanje pristnosti pri prijavi z uporabo %1 konfiguratorja. V nasprotnem primeru ne boste mogli dostopati do računalnikov z uporabo %1. - Access denied Dostop zavrnjen @@ -2925,10 +3294,6 @@ UPORABA Search users and computers Iskanje uporabnikov in računalnikov - - Adjust optimal size - Prilagodi optimalno velikost - Align computers to grid Poravnaj računalnike z mrežo @@ -2946,32 +3311,74 @@ UPORABA Ni bilo mogoče začeti z administrativnimi pravicami. Prosimo, prepričajte se, da je podoben program nameščen za vaše namizno okolje! Program bo deloval z običajnimi uporabniškimi pravicami. - Only show powered on computers - Pokaži samo priklope na računalnikih + Only show powered on computers + Pokaži samo priklope na računalnikih + + + &Save settings to file + &Shrani nastavitve v datoteko + + + &View + &Pogled + + + &Standard + &Standardno + + + &Advanced + &Napredno + + + Use custom computer arrangement + Uporabite urejanje računalnika po meri + + + Locations && computers + Lokacije && računalniki + + + Authentication + Preverjanje pristnosti + + + Adjust size of computer icons automatically + + + + Slideshow + + + + Spotlight + - &Save settings to file - &Shrani nastavitve v datoteko + Veyon Master + Veyon Master - &View - &Pogled + Locations & computers + Lokacije in računalniki - &Standard - &Standardno + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + - &Advanced - &Napredno + Only show computers with logged on users + - Use custom computer arrangement - Uporabite urejanje računalnika po meri + Load computer positions + - Locations && computers - Lokacije && računalniki + Save computer positions + @@ -2980,10 +3387,6 @@ UPORABA Directories Imeniki - - ... - ... - User configuration Uporabniška konfiguracija @@ -3068,6 +3471,10 @@ UPORABA Only user name Samo uporabniško ime + + Only last part of user name + + Only computer name Samo ime računalnika @@ -3116,171 +3523,181 @@ UPORABA Automatically select current location Samodejno izberi trenutno lokacijo - - Automatically adjust computer thumbnail size - Samodejno prilagodi velikost računalniške sličice - Automatically open computer select panel Samodejno odpri izbrano okno računalnika - - - MonitoringMode - Monitoring - Nadzor + Use modern user interface (experimental) + - Builtin monitoring mode - Vgrajen način nadzora + Thumbnail spacing + - This mode allows you to monitor all computers at one or more locations. - Ta način omogoča nadzor vseh računalnikov na eni ali več lokacijah. + px + + + + Hide local session + + + + Auto + Samodejno - - - NetworkDiscoveryConfigurationPage - Network discovery - Odkrivanje omrežja + Thumbnail aspect ratio + - Mode - Način + Automatically adjust computer icon size + - Scan network ranges - Preglej obsege omrežja + Open feature windows on the same screen as the main window + - e.g. 192.168.1.0/24 - npr. 192.168.1.0/24 + Configuration templates + - Scan all subnets of computer - Preglej vsa podomrežja računalnika + Image quality in monitoring mode + - Scan custom subnet - Preglej podomrežje po meri + Highest + - Scan sessions on local computer - Preglej seje na lokalnem računalniku + High + - Test - Preizkus + Medium + - Network ranges - Območja omrežja + Low + - Add new group - Dodaj novo skupino + Lowest + - Remove selected group - Odstrani izbrano skupino + Remote access image quality + - Groups - Skupine + Advanced + - First address - Prvi naslov + Computer name source + - Last address - Zadnji naslov + Default + - Add new network range - Dodajte novo omrežno območje + Host address + Naslov gostitelja - Remove selected network range - Odstranite izbrano omrežno območje + Session client address + - Parallel scans - Vzporedno skeniranje + Session client name + - Scan timeout - Časovna omejitev skeniranja + Session host name + - ms - ms + Session metadata + - Session scan limit - Meja skeniranja seje + Full name of user + - Options - Možnosti + User login name + - Reverse lookup discovered IP addresses to host names - Povratno iskanje je odkrilo naslove IP za imena gostiteljev + Computer UID role + - New location - Nova lokacija + Session meta data hash + - - - NetworkDiscoveryDirectory - Scanning... - Skeniranje... + Always expand all locations + - Discovered computers - Odkriti računalniki + Image quality + - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command - Prikaži pomoč za določen ukaz + Monitoring + Nadzor + + + Builtin monitoring mode + Vgrajen način nadzora - Scan a subnet - Skeniraj podomrežje + This mode allows you to monitor all computers at one or more locations. + Ta način omogoča nadzor vseh računalnikov na eni ali več lokacijah. - -USAGE - -%1 scan [<SUBNET>] - - - -UPORABA - -%1 skenirano [<SUBNET>] - - + Query application version of the server + + + + Query active features + + + + Query properties of remotely available screens + + + + NestedNetworkObjectDirectory + + All directories + + + + + NetworkObjectDirectoryConfigurationPage - Network object directory which automatically discovers computers in the network - Imenik omrežnih objektov, ki samodejno odkrije računalnike v omrežju + Update interval: + Posodobi interval: - Network discovery (scan network for Veyon clients) - Odkrivanje omrežja (skeniranje omrežja za stranke Veyon) + seconds + sekund + + + NetworkObjectDirectoryConfigurationPageTab - Commands for managing the network discovery directory - Ukazi za upravljanje imenika za odkrivanje omrežja + Enabled + @@ -3316,32 +3733,44 @@ UPORABA Name: + + Website name + + - PasswordDialog + PluginCommands - Username - Uporabniško ime + List names of all installed plugins + - Password - Geslo + Show table with details of all installed plugins + - Veyon Logon - Veyon prijava + Name + Ime - Authentication error - Napaka preverjanja pristnosti + Description + - Logon failed with given username and password. Please try again! - Prijava z neodobrenim uporabniškim imenom in geslom ni uspela. Prosim, poskusite ponovno! + Version + - Please enter your username and password in order to access computers. - Vnesite svoje uporabniško ime in geslo za dostop do računalnikov. + UID + + + + Plugin-related CLI operations + + + + Commands for managing plugins + @@ -3386,10 +3815,6 @@ UPORABA Do you really want to reboot the selected computers? Ali res želite ponovno zagnati izbrane računalnike? - - Do you really want to power down the selected computer? - Ste prepričani, da želite izklopiti izbrani računalnik? - Power on a computer via Wake-on-LAN (WOL) Zagon računalnika preko Wake-on-LAN (WOL) @@ -3440,6 +3865,18 @@ UPORABA Please save your work and close all programs. + + Do you really want to reboot <b>ALL</b> computers? + + + + Do you really want to power down <b>ALL</b> computers? + + + + Do you really want to power down the selected computers? + + PowerDownTimeInputDialog @@ -3486,14 +3923,25 @@ Please save your work and close all programs. Remote view or control a computer Oddaljeni pogled ali nadzor računalnika - - Please enter the hostname or IP address of the computer to access: - Vnesite ime gostitelja ali naslov IP računalnika za dostop: - Show help about command Prikaži pomoč o ukazu + + Exchange clipboard contents + + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + + + RemoteAccessPage + + Remote access: %1 + + RemoteAccessWidget @@ -3501,6 +3949,10 @@ Please save your work and close all programs. %1 - %2 Remote Access %1 - %2 oddaljen dostop + + %1 - %2 - %3 Remote Access + + RemoteAccessWidgetToolBar @@ -3556,10 +4008,6 @@ Please save your work and close all programs. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - Povezujem %1 - Connected. Povezan. @@ -3572,57 +4020,16 @@ Please save your work and close all programs. Exit - - - Routing - - Control internet access by modifying routing table - Nadzor dostopa do interneta s spreminjanjem usmerjevalne tabele - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - Odstrani privzete poti za blokiranje dostopa do interneta - - - Add custom route to block internet - Dodaj prilagojeno pot za blokiranje interneta - - - Destination - Destinacija - - - Gateway - Prehod - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - Prosimo, vnesite programe ali ukaze, ki se izvajajo v izbranih računalnikih. Več programov / ukazov lahko ločite po vrstici. - - - Run programs - Zaženi programe - - - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - npr. "C:\Program Files\VideoLAN\VLC\vlc.exe" - - Name: + Connecting... - Remember and add to program menu + Select screen - e.g. VLC + All screens @@ -3644,6 +4051,18 @@ Please save your work and close all programs. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. Če želite povrniti celotno pozornost vseh uporabnikov, lahko z uporabo tega gumba zaklenete njihove računalnike. V tem načinu so vse vhodne naprave zaklenjene in zasloni so črni. + + Lock input devices + + + + Unlock input devices + + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + Screenshot @@ -3659,6 +4078,10 @@ Please save your work and close all programs. Screenshot Zaslonska slika + + Could not open screenshot file %1 for writing. + + ScreenshotFeaturePlugin @@ -3683,6 +4106,13 @@ Please save your work and close all programs. Posnemite zaslone računalnikov in jih shranite lokalno. + + ScreenshotManagementPage + + Screenshots + Zaslonske slike + + ScreenshotManagementPanel @@ -3710,8 +4140,47 @@ Please save your work and close all programs. Prikaži - Delete - Briši + Delete + Briši + + + Screenshot + Zaslonska slika + + + Do you really want to delete all selected screenshots? + + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + + + + User has denied access + + + + User confirmed access + @@ -3744,14 +4213,6 @@ Please save your work and close all programs. State: Stanje: - - Network - Omrežje - - - Demo server port - Vrata strežnika za predavanja - Enable firewall exception Omogoči izjemo požarnega zidu @@ -3760,10 +4221,6 @@ Please save your work and close all programs. Allow connections from localhost only Omogočite povezave samo z lokalnega gostitelja - - Internal VNC server port - Vrata notranjega strežnika VNC - VNC server VNC strežnik @@ -3784,14 +4241,6 @@ Please save your work and close all programs. Running V teku - - Feature manager port - Vrata upravitelja funkcij - - - Primary service port - Primarna vrata storitve - Enabling this option will make the service launch a server process for every interactive session on a computer. Typically this is required to support terminal servers. @@ -3803,51 +4252,129 @@ Običajno je to potrebno za podporo terminalskih strežnikov. Prikaži obvestilo o oddaljeni povezavi - Multi session mode (for terminal and remote desktop servers) + Show notification when an unauthorized access is blocked + + + + Maximum session count - Show notification when an unauthorized access is blocked + Network port numbers + + + + Veyon server - - - ServiceControl - Starting service %1 - Zagon storitve %1 + Internal VNC server + Notranji VNC strežnik - Stopping service %1 - Zaustavitev storitve %1 + Feature manager + Upravitelj funkcij - Registering service %1 - Registracija storitve %1 + Demo server + Demonstracijski strežnik - Unregistering service %1 - Odregistracija storitve %1 + Miscellaneous network settings + - Service control - Nadzor storitve + Session mode + + + + Local session mode (single server instance for primary local session) + + + + Active session mode (single server instance for active local or remote session) + + + + Multi session mode (distinct server instance for each local and remote desktop session) + + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + + + + Miscellaneous settings + + + + Disable clipboard synchronization + + + + Session metadata + + + + Content + + + + None + Brez + + + Value of an environment variable + + + + Value of a registry key + + + + Environment variable name: + + + + Registry key name: + + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + - ServiceControlPlugin + ServiceControl - Service is running - Storitev teče + Service control + Nadzor storitve - Service is not running - Storitev ne teče + Starting %1 + - Configure and control Veyon service - Konfigurirajte in nadzirajte Veyon storitev + Stopping %1 + + + + Restarting %1 + + + + Registering %1 + + + + Unregistering %1 + + + + ServiceControlCommands Register Veyon Service Registriraj Veyon storitev @@ -3872,13 +4399,25 @@ Običajno je to potrebno za podporo terminalskih strežnikov. Query status of Veyon Service Stanje poizvedbe storitve Veyon + + Service is running + Storitev teče + + + Service is not running + Storitev ne teče + + + Configure and control Veyon service + Konfigurirajte in nadzirajte Veyon storitev + Commands for configuring and controlling Veyon Service Ukazi za konfiguracijo in nadzor Veyon storitve - ShellCommandLinePlugin + ShellCommands Run command file Zaženi ukazno datoteko @@ -3888,14 +4427,100 @@ Običajno je to potrebno za podporo terminalskih strežnikov. Datoteka "%1" ne obstaja! - Interactive shell and script execution for Veyon Control - Interaktivna lupina in izvedba skripte za nadzor Veyon + Interactive shell and script execution for Veyon CLI + Commands for shell functionalities Ukazi za funkcionalnosti lupine + + SlideshowPanel + + Previous + + + + Start/pause + + + + Next + + + + Duration: + + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + + + + Remove selected computers + + + + Update computers in realtime + + + + Spotlight + + + + Please select at least one computer to add. + + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + + + StartAppDialog + + Start application + + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + npr. "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + + + + Application name + + + + Name: + + + + e.g. VLC + + + SystemTrayIcon @@ -3932,8 +4557,8 @@ Običajno je to potrebno za podporo terminalskih strežnikov. Pošlji sporočilo - Use the field below to type your message which will be sent to all selected users. - Uporabite spodnje polje za vpis sporočila, ki ga želite poslati izbranim uporabnikom. + Please enter your message which send to all selected users. + @@ -3981,23 +4606,39 @@ Običajno je to potrebno za podporo terminalskih strežnikov. Enable Desktop Duplication Engine on Windows 8 and newer Omogoči pogon za podvajanje namizja računalnika na Windows 8 in novejših + + Maximum CPU usage + + - UserConfig + UserLoginDialog - No write access - Ni pravice pisanja + User login + - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - Vaših osebnih nastavitev ni bilo mogoče shraniti! Preverite pot do konfiguracijske datoteke uporabnika s konfiguratorjem %1. + Please enter a username and password for automatic login on all computers. + + + + Username + Uporabniško ime + + + Password + Geslo - UserSessionControl + UserSessionControlPlugin - User session control - Nadzor seje uporabnika + Log in + + + + Click this button to log in a specific user on all computers. + Log off @@ -4015,6 +4656,14 @@ Običajno je to potrebno za podporo terminalskih strežnikov. Do you really want to log off the selected users? + + User session control + Nadzor seje uporabnika + + + Do you really want to log off <b>ALL</b> users? + + VeyonCore @@ -4066,10 +4715,6 @@ Običajno je to potrebno za podporo terminalskih strežnikov. ERROR NAPAKA - - licensed for - licenca za - USAGE UPORABA @@ -4086,19 +4731,31 @@ Običajno je to potrebno za podporo terminalskih strežnikov. WARNING + + Authentication test + Preverjanje pristnosti + + + Screen %1 + + - VeyonServiceControl + VeyonMaster - Veyon Service - Veyon storitev + No write access + Ni pravice pisanja + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Vaših osebnih nastavitev ni bilo mogoče shraniti! Preverite pot do konfiguracijske datoteke uporabnika s konfiguratorjem %1. - VncView + VeyonServiceControl - Establishing connection to %1 ... - Vzspostavljam povezavo na %1 ... + Veyon Service + Veyon storitev @@ -4146,6 +4803,30 @@ Običajno je to potrebno za podporo terminalskih strežnikov. Use alternative user authentication mechanism Uporabite alternativni mehanizem za preverjanje pristnosti uporabnika + + User login + + + + Input start delay + + + + Simulated key presses interval + + + + Confirm legal notice (message displayed before user logs in) + + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4154,7 +4835,7 @@ Običajno je to potrebno za podporo terminalskih strežnikov. Vtičnik izvajanja abstraktnih funkcij za platformo Windows - Plugin implementing specific functions for the Windows platform + Internal display @@ -4165,27 +4846,31 @@ Običajno je to potrebno za podporo terminalskih strežnikov. - The service "%1" could not be installed. + The service "%1" has been installed successfully. + + + + The service "%1" has been uninstalled successfully. - The service "%1" has been installed successfully. + Service "%1" could not be found. - The service "%1" could not be uninstalled. + The service "%1" could not be installed (error %2). - The service "%1" has been uninstalled successfully. + Could not change the failure actions config for service "%1" (error %2). - The start type of service "%1" could not be changed. + The service "%1" could not be uninstalled (error %2). - Service "%1" could not be found. + The start type of service "%1" could not be changed (error %2). diff --git a/translations/veyon_sr.ts b/translations/veyon_sr.ts new file mode 100644 index 000000000..968aa16ae --- /dev/null +++ b/translations/veyon_sr.ts @@ -0,0 +1,4896 @@ + + + AboutDialog + + About + O nama + + + Translation + Prevod + + + License + Licenca + + + About Veyon + O Veyonu + + + Contributors + Saradnici + + + Version: + Verzija + + + Website: + Websajt: + + + Current language not translated yet (or native English). + +If you're interested in translating Veyon into your local or another language or want to improve an existing translation, please contact a Veyon developer! + Trenutni jezik nije još preveden (ili maternji Engleski). + +Ako ste zainteresovani za prevodjenje Veyon na vaš lokalni ili drugi jezik ili želite poboljšati postojeći prevod,molimo kontaktirajte Veyon programera! + + + About %1 %2 + O %1 %2 + + + Support Veyon project with a donation + Podržite Veyon projekat sa donacijom + + + + AccessControlPage + + Computer access control + Kontrola pristupa računaru + + + Grant access to every authenticated user (default) + Odobriti pristup autorizovanom korisniku (podrazumevano) + + + Test + Test + + + Process access control rules + Obraditi pravila kontrole pristupa + + + User groups authorized for computer access + Autorizovane grupe korisnika za pristup računaru + + + Please add the groups whose members should be authorized to access computers in your Veyon network. + Molimo dodajte grupe čiji članovi trebaju biti autorizovani za pristup računarima u vašoj Veyon mreži. + + + Authorized user groups + Autorizovane grupe korisnika + + + All groups + Sve grupe + + + Access control rules + Pravila kotrole pristupa + + + Add access control rule + Dodaj pravilo kontrole pristupa + + + Remove access control rule + Ukloni pravilo kotrole pristupa + + + Move selected rule down + Pomeri obeleženo pravilo dole + + + Move selected rule up + Pomeri pravilo gore + + + Edit selected rule + Izmeni obeleženo pravilo + + + Enter username + Unesi korisničko ime + + + Please enter a user login name whose access permissions to test: + Molim unesite korisničko ime prijave čiji pristup je dozvoljen za test: + + + Access allowed + Pristup dozvoljen + + + The specified user is allowed to access computers with this configuration. + Navedenom korisniku je dozvoljen pristup računarima sa ovom konfiguracijom. + + + Access denied + Pristup odbijen + + + The specified user is not allowed to access computers with this configuration. + Navedenom korisniku nije dozvoljen pristup računarima sa ovom konfiguracijom. + + + Enable usage of domain groups + Omogući korišćenje domen grupa + + + User groups backend: + Pozadina grupe korisnika: + + + Restrict access to members of specific user groups + Ograniči pristup članovima određjenih grupa korisnika + + + + AccessControlProvider + + Provider for access control features + + + + + AccessControlRuleEditDialog + + Edit access control rule + Izmeni pristup pravila kontrole + + + General + Opšte + + + enter a short name for the rule here + unesite kratko ime za pravilo ovde + + + Rule name: + Ime pravila: + + + enter a description for the rule here + unesite opis za pravilo ovde + + + Rule description: + Opis pravila: + + + Conditions + Uslovi + + + If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. + Ako je aktivirano više od jednog uslova, svaki se uslov mora ispuniti da bi se pravilo primenilo (logično I). Ako mora biti ispunjen samo jedan od više uslova (logički ILI),kreirajte više pravila kontrole pristupa. + + + Action + Akcija + + + Allow access + Dozvoli pristup + + + Deny access + Odbi pristup + + + Ask logged on user for permission + Pitajte prijavljenog korisnika za dozvolu + + + None (rule disabled) + Nema (pravilo onemogućeno) + + + Accessing user + Pristup korisniku + + + Accessing computer + Pristup kompjuteru + + + Always process rule and ignore conditions + Uvek obradi pravilo i ignoriši uslove + + + Accessing computer and local computer + + + + User being accessed + + + + is logged in locally + + + + is logged in remotely + + + + No user is logged in locally + + + + One or multiple users are logged in locally + + + + No user is logged in remotely + + + + One or multiple users are logged in remotely + + + + is located at + nalazi se na + + + is not located at + + + + are located at the same location + + + + are not located the same location + + + + is member of group + je član grupe + + + is not member of group + + + + is authenticated via + + + + is not authenticated via + + + + has one or more groups in common with user being accessed + + + + has no groups in common with user being accessed + + + + equals user being accessed + + + + is different from user being accessed + + + + is already connected + + + + is not connected + + + + is local computer + + + + is not local computer + + + + Computer being accessed + + + + Session being accessed is a user session + + + + Session being accessed is a login screen + + + + Local computer is already being accessed + + + + Local computer is not yet being accessed + + + + + AccessControlRulesTestDialog + + Access control rules test + Testiranje pravila kontrole pristupa + + + Accessing user: + Pristupni korisnik: + + + Local computer: + Lokalni računar: + + + Accessing computer: + Pristupni računar: + + + Please enter the following user and computer information in order to test the configured ruleset. + Molimo unesite sledeće podatke o korisniku i računaru kako biste testirali konfigurisani skup pravila. + + + Local user: + Lokalni korisnik: + + + Connected users: + Povezani korisnici: + + + The access in the given scenario is allowed. + Dozvoljen je pristup u datom scenariju. + + + The access in the given scenario is denied. + Odbijen je pristup u datom scenariju + + + The access in the given scenario needs permission of the logged on user. + Za pristup datom scenariju potrebne su dozvole prijavljenog korisnika. + + + Test result + Rezultati testa + + + Authentication method + Način provere autentifikacije + + + There is no matching rule with a valid action. The access is therefore denied. + + + + + AuthKeysConfigurationWidget + + Introduction + Uvod + + + Please perform the following steps to set up key file authentication: + Molimo vas da izvršite sledeće korake za podešavanje provjere autentičnosti datoteka: + + + 1) Create a key pair on the master computer. + 1) Na glavnom računaru napravite par ključeva. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Postavite pristupnu grupu čiji članovi trebaju imati pristup drugim računarima. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Izvezite javni ključ i uvezite ga na sve računare klijenta sa istim nazivom. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Više informacija potražite u Priručniku za administratore Veyon.<a href="https://veyon.readthedocs.io/en/latest/admin/index.html"> + + + Key file directories + Ključne datoteke direktorijuma + + + Public key file base directory + Osnovni direktorijum datoteka javnih ključeva + + + Private key file base directory + Osnovni direktorijum datoteka privatnih ključeva + + + Available authentication keys + Dostupni ključevi za proveru autentičnosti + + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Par ključeva za autentifikaciju sastoji se od dva povezana kriptografska ključa, privatnog i javnog ključa. +Privatni ključ omogućava korisnicima na matičnom računaru pristup klijentima. +Važno je da su samo ovlašćeni korisnici pročitali pristup datoteci privatnog ključa. +Javni ključ koristi se na klijentskim računarima za proveru dolaznog zahteva za povezivanje. + + + Create key pair + Kreirajte par ključeva + + + Delete key + Obriši ključ + + + Import key + Uvozni ključ + + + Export key + Izvozni ključ + + + Set access group + Podesite grupu pristupa + + + Key files (*.pem) + Ključne datoteke (*.pem) + + + Authentication key name + Naziv ključa za autentifikaciju + + + Please enter the name of the user group or role for which to create an authentication key pair: + Unesite ime korisničke grupe ili uloge za kreiranje parova ključeva za provjeru autentičnosti: + + + Do you really want to delete authentication key "%1/%2"? + Želite li stvarno izbrisati autentifikacijski ključ "%1/%2"? + + + Please select a key to delete! + Odaberite ključ za brisanje! + + + Please select a key to export! + Odaberite ključ za izvoz! + + + Please select a user group which to grant access to key "%1": + Odaberite grupu korisnika koja će odobriti pristup ključu "%1": + + + Please select a key which to set the access group for! + Odaberite ključ za koji ćete podesiti pristupnu grupu! + + + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + + + + + AuthKeysManager + + Please check your permissions. + Proverite vaše dozvole. + + + Key name contains invalid characters! + Ime ključa sadrži nevažeće znakove! + + + Invalid key type specified! Please specify "%1" or "%2". + Navedena je nevažeća vrsta ključa! Navedite "%1" ili "%2". + + + Specified key does not exist! Please use the "list" command to list all installed keys. + Navedeni ključ ne postoji! Upotrebite komandu "list" za popis svih instaliranih ključeva. + + + One or more key files already exist! Please delete them using the "delete" command. + Jedna ili više ključnih datoteka već postoje! Izbrišite ih pomoću komande "delete". + + + Creating new key pair for "%1" + Izrada novog para ključeva za "%1" + + + Failed to create public or private key! + Nije uspelo kreiranje javnog ili privatnog ključa! + + + Newly created key pair has been saved to "%1" and "%2". + Novostvoreni par ključeva sačuvan je u „%1“ i „%2“. + + + Could not remove key file "%1"! + Nije moguće ukloniti datoteku s ključevima "%1"! + + + Could not remove key file directory "%1"! + Nije moguće ukloniti direktorijum ključnih datoteka "%1"! + + + Failed to create directory for output file. + Nije uspelo kreiranje direktorijuma za izlaznu datoteku. + + + File "%1" already exists. + Datoteka "%1" već postoji. + + + Failed to write output file. + Pisanje izlazne datoteke nije uspelo. + + + Key "%1/%2" has been exported to "%3" successfully. + Ključ "%1/%2" je uspešno izvezen u "%3". + + + Failed read input file. + Učitavanje ulazne datoteke nije uspelo. + + + File "%1" does not contain a valid private key! + Datoteka "%1" ne sadrži validni privatni ključ! + + + File "%1" does not contain a valid public key! + Datoteka "%1" ne sadrži validni javni ključ! + + + Failed to create directory for key file. + Nije uspelo kreiranje direktorijuma za ključnu datoteku. + + + Failed to write key file "%1". + Nije uspelo pisanje datoteke ključa "%1". + + + Failed to set permissions for key file "%1"! + Nije moguće postaviti dozvole za ključnu datoteku "%1"! + + + Key "%1/%2" has been imported successfully. Please check file permissions of "%3" in order to prevent unauthorized accesses. + Ključ "%1/%2" je uspešno uvežen. Proverite dozvole datoteka "%3" kako biste sprečili neovlašćeni pristup. + + + Failed to convert private key to public key + Nije uspelo konvertovati privatni ključ u javni ključ + + + Failed to create directory for private key file "%1". + Nije uspelo kreiranje direktorijuma za datoteku privatnog ključa "%1". + + + Failed to save private key in file "%1"! + Privatni ključ u datoteci "%1" nije uspešno sačuvan! + + + Failed to set permissions for private key file "%1"! + Neuspešno postavljanje dozvola za datoteku privatnog ključa "%1"! + + + Failed to create directory for public key file "%1". + Neuspešno kreiranje direktorijuma za datoteku javnog ključa "%1". + + + Failed to save public key in file "%1"! + Javni ključ u datoteci "%1" nije uspešno sačuvan! + + + Failed to set permissions for public key file "%1"! + Nije moguće postaviti dozvole za datoteku javnog ključa "%1"! + + + Failed to set owner of key file "%1" to "%2". + Neuspešno postavljanje vlasnika datoteke ključa "%1" na "%2". + + + Failed to set permissions for key file "%1". + Neuspešno postavljanje dozvola za ključnu datoteku "%1". + + + Key "%1" is now accessible by user group "%2". + Ključ "%1" je sada dostupan grupi korisnika "%2". + + + <N/A> + <N/A> + + + Failed to read key file. + Nije moguće pročitati datoteku s ključevima. + + + + AuthKeysPlugin + + Create new authentication key pair + Kreirajte novi par ključeva za autentifikaciju + + + Delete authentication key + Izbriši ključ za provjeru autentičnosti + + + List authentication keys + Lista ključeva za proveru autentičnosti + + + Import public or private key + Uvezite javni ili privatni ključ + + + Export public or private key + Izvoz javnog ili privatnog ključa + + + Extract public key from existing private key + Izdvojite javni ključ iz postojećeg privatnog ključa + + + Set user group allowed to access a key + Postavite korisničkoj grupi dozvoljen pristup ključu + + + KEY + KLJUČ + + + ACCESS GROUP + PRISTUPNA GRUPA + + + This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. + Ova naredba prilagođjava dozvole za pristup datoteci na <KEY> tako da samo korisnička grupa <ACCESS GROUP> može pročitati pristup. + + + NAME + IME + + + FILE + FAJL + + + This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. + Ova naredba izvozi ključ autentičnosti <KEY> u <FILE>.Ako <FILE> nije specifičan i ime će se konstruisati iz imena i tipa <KEY> . + + + This command imports the authentication key <KEY> from <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. + Ova komanda uvozi autentičnost ključa <KEY> od <FILE>.Ako <FILE> nije specifičan ime će biti konstruisano od imena i tipa <KEY>. + + + This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. + Ova naredba navodi sve dostupne ključeve za proveru autentičnosti u konfiguracionom direktorijumu ključeva. Ako je navedena opcija "%1",specifična tablica s ključnim detaljima biće prikazana umesto opcija. Neki detalji možda nedostaju ako ključ nije dostupan, npr. zbog nedostatka dozvola za čitanje. + + + TYPE + TIP + + + PAIR ID + PAR ID + + + Commands for managing authentication keys + Komande za upravljanje ključevima autentičnosti + + + This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. + Ova naredba kreira novi par ključeva za provjeru autentičnosti s imenom <NAME> i sačuvaće privatni i javni ključ u konfiguracione direktorijume ključeva. Parametar mora biti naziv ključa koji može sadržavati samo slova. + + + This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. + Ova naredba briše ključ za proveru autentičnosti <KEY> iz konfiguracionog direktorija ključeva. Imajte na umu da ključ nije moguće vratiti nakon što ga izbrišete. + + + This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + Ova naredba izdvaja deo javnog ključa iz privatnog ključa <KEY> i sačuvaće ga kao odgovarajući javni ključ. Pri podešavanju drugog glavnog računara dovoljno je preneti samo privatni ključ. Javni ključ se zatim može izvući. + + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + Datoteke sa ključem za provjeru autentičnosti nisu ispravno postavljene na ovom kompjuteru. Molimo da kreirate nove datoteke sa ključevima ili se prebacite na drugi metod autentifikacije kroz Veyon Configurator. + + + Key file authentication + Autentičnost ključa datoteke + + + Key file + Datoteka ključa + + + Please specify the key name (e.g. "teacher/public") as the first argument. + + + + Please specify the command to display help for. + + + + The specified command does not exist or no help is available for it. + + + + + AuthKeysTableModel + + Name + Ime + + + Type + Tip + + + Access group + Pristupna grupa + + + Pair ID + Par ID + + + + AuthLdapConfigurationWidget + + General + Opšte + + + Username to bind DN mapping: + + + + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + + + AuthLdapDialog + + Veyon Logon + Prijava u Veyon + + + Please enter your domain/LDAP username and password in order to access computers. + + + + Username + Korisničko ime + + + Password + Šifra/lozinka + + + Authentication error + Greška autentifikacije + + + Logon failed with given username and password. Please try again! + Prijava je neuspešna sa datim korisničkim imenom i šifrom. Molimo pokušajte ponovo! + + + + AuthLogonDialog + + Veyon Logon + Prijava u Veyon + + + Please enter your username and password in order to access computers. + Molimo unesite vaše korisničko ime i šifru za pristup kompjuterima. + + + Username + Korisničko ime + + + Password + Šifra/lozinka + + + Authentication error + Greška autentifikacije + + + Logon failed with given username and password. Please try again! + Prijava je neuspešna sa datim korisničkim imenom i šifrom. Molimo pokušajte ponovo! + + + + AuthLogonPlugin + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Uneseno korisničko ime ili šifra nisu ispravni. Molimo unesite ispravne podatke ili se prebacite na drugi metod autentifikacije upotrebom Veyon Configurator-a. + + + Logon authentication + Provera autentičnosti + + + Logon + Prijava + + + + AuthSimpleDialog + + Veyon Logon + Prijava u Veyon + + + Please enter the Veyon password: + Molimo unesite Veyon šifru: + + + Authentication error + Greška autentifikacije + + + Logon failed with given password. Please try again! + Prijava je neuspešna sa datom šifrom. +Molimo pokušajte ponovo! + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + Unesena šifra je pogrešna. +Molimo unesite ispravnu šifru ili se prebacite na drugi metod autentifikacije upotrebom Veyon Configurator-a. + + + Simple password authentication + Jednostavna provera šifre + + + Simple password + + + + + AuthenticationPage + + Authentication is set up properly on this computer. + Autentifikacija je na ovom računaru pravilno postavljena. + + + + AuthenticationPageTab + + Enabled + + + + Test + Test + + + + BuiltinDirectoryConfiguration + + Builtin directory + Ugradjeni direktorijum + + + + BuiltinDirectoryConfigurationPage + + Computers + Računari + + + Name + Ime + + + Host address/IP + Host adresa/IP + + + MAC address + MAC adresa + + + Add new computer + Dodaj nov računar + + + Remove selected computer + Ukloni obeležene računar + + + New computer + Novi računar + + + Builtin directory + Ugradjeni direktorijum + + + Locations + Lokacije + + + Add new location + Dodaj novu lokaciju + + + Remove selected location + Ukloni obeleženu lokaciju + + + New location + Nova lokacija + + + Directory name + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + + + + BuiltinDirectoryPlugin + + Show help for specific command + Prikaži pomoć za specifičnu komandu + + + Import objects from given file + Uvoz predmeta iz date datoteke + + + Export objects to given file + Izvoz predmeta iz date datoteke + + + Invalid type specified. Valid values are "%1" or "%2". + Naveden nevažeći tip. Važeće vrednosti su „%1“ ili „%2“. + + + Type + Tip + + + Name + Ime + + + Host address + Host adresa + + + MAC address + MAC adresa + + + Specified object not found. + Navedeni objekt nije pronađen. + + + File "%1" does not exist! + Fajl "%1" nije pronadjen! + + + Can't open file "%1" for reading! + Nije moguće otvoriti datoteku "%1" za čitanje! + + + Unknown argument "%1". + Nepoznati argument "%1". + + + Computer "%1" (host address: "%2" MAC address: "%3") + Računar "%1" (adresa domaćina: "%2" MAC adresa: "%3") + + + Unclassified object "%1" with ID "%2" + Nerazvrstani objekt "%1" sa ID-om "%2" + + + None + Nijedan + + + Computer + Računar + + + Root + Ruta + + + Invalid + Nevažeći + + + Error while parsing line %1. + Greška prilikom raščlanjivanja linije%1. + + + Network object directory which stores objects in local configuration + Mrežni objektni direktorijum koji je sačuvan objekat u lokalnoj konfiguraciji + + + Commands for managing the builtin network object directory + Komande za upravljanje ugrađenim direktorijom mrežnih objekata + + + No format string or regular expression specified! + Nije naveden niz formata ili regularni izraz! + + + Can't open file "%1" for writing! + Nije moguće otvoriti datoteku "%1" za pisanje! + + + No format string specified! + Nije naveden specifičan niz formata! + + + Object UUID + Objekat UUID + + + Parent UUID + Roditeljski UUID + + + Add a location or computer + Dodaj lokaciju ili računar + + + Clear all locations and computers + Očistite sve lokacije i računare + + + Dump all or individual locations and computers + Izbacite sve ili pojedine lokacije i računare + + + List all locations and computers + Lista svih lokacija i računara + + + Remove a location or computer + Ukloni lokaciju ili računar + + + Location "%1" + Lokacija "%1" + + + Builtin (computers and locations in local configuration) + Ugrađeni (računari i lokacije u lokalnoj konfiguraciji) + + + Location + Lokacija + + + FILE + FAJL + + + LOCATION + LOKACIJA + + + FORMAT-STRING-WITH-PLACEHOLDERS + FORMAT-NIZ-SA-MESTIMA + + + REGULAR-EXPRESSION-WITH-PLACEHOLDER + REGULARNO-IZRAŽENJE-SA-PLOČA + + + Imports objects from the specified text file using the given format string or regular expression containing one or multiple placeholders. Valid placeholders are: %1 + Uvozi objekte iz zadane tekstualne datoteke pomoću datog niza formata ili regularnog izraza koji sadrži jedno ili više rezervi. Važeća rezervirana mesta su: %1 + + + Import simple CSV file to a single room + Uvezi jednostavnu CSV datoteku u jednu prostoriju + + + Import CSV file with location name in first column + Uvezi CSV datoteku sa imenom lokacije u prvu kolonu + + + Import text file with with key/value pairs using regular expressions + Uvezi tekstualnu datoteku s parovima ključ / vrijednost koristeći regularne izraze + + + Import arbitrarily formatted data + Uvezi proizvoljno formatirane podatke + + + Exports objects to the specified text file using the given format string containing one or multiple placeholders. Valid placeholders are: %1 + Izvezi objekte u navedenu tekstualnu datoteku koristeći zadani format niza koji sadrži jedno ili više rezervi. Važeća rezervisana mesta su:%1 + + + Export all objects to a CSV file + Izvezite sve objekte u CSV datoteku + + + Export all computers in a specific location to a CSV file + Izvezite sve računare na određenoj lokaciji u CSV datoteku + + + TYPE + TIP + + + NAME + IME + + + PARENT + RODITELJ + + + Adds an object where %1 can be one of "%2" or "%3". %4 can be specified by name or UUID. + Dodaje objekt u kojem %1 može biti jedan od "%2" ili "%3". %4 može se odrediti imenom ili UUID-om. + + + Add a room + Dodaj prostoriju + + + Add a computer to room %1 + Dodaj računar u prostoriju + + + OBJECT + OBJEKAT + + + Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. + Uklanja navedeni objekt iz direktorijuma. %1 može se odrediti imenom ili UUID-om. Ako uklonite lokaciju, uklonite i sva povezana računara. + + + Remove a computer by name + Uklonite računar po imenu + + + Remove an object by UUID + Uklonite objekt po UUID + + + "Room 01" + "Prostorija 01" + + + "Computer 01" + "Računar 01" + + + HOST ADDRESS + DOMAĆIN ADRESA + + + MAC ADDRESS + MAC ADRESA + + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. + + + + + BuiltinUltraVncServer + + Builtin VNC server (UltraVNC) + Ugrađeni VNC server (UltraVNC) + + + + BuiltinX11VncServer + + Builtin VNC server (x11vnc) + Ugrađeni VNC server (x11vnc) + + + + ComputerControlListModel + + Active features: %1 + Aktivne karakteristike: %1 + + + Online and connected + Online i povezan + + + Establishing connection + Uspostavljanje veze + + + Computer offline or switched off + Računar nije mreži ili je isključen + + + Authentication failed or access denied + Autentifikacija nije uspela ili je pristup odbijen + + + Disconnected + Nepovezan + + + No user logged on + Nijedan korisnik nije prijavljen + + + Logged on user: %1 + Prijavljeni korisnik: %1 + + + Location: %1 + Lokacija: %1 + + + [no user] + + + + Veyon Server unreachable or not running + + + + Name: %1 + + + + Hostname: %1 + + + + unknown + nepoznato + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + + + + ComputerControlServer + + %1 Service %2 at %3:%4 + %1 Usluga %2 na %3:%4 + + + Authentication error + Greška autentifikacije + + + Remote access + Udaljeni pristup + + + User "%1" at host "%2" is now accessing this computer. + Korisnik "%1" kod domaćina "%2" sada pristupa ovom računalu. + + + User "%1" at host "%2" attempted to access this computer but could not authenticate successfully. + Korisnik "%1" kod domaćina "%2" pokušao je pristupiti ovom računaru, ali nije uspeo uspješno proveriti identitet. + + + Access control error + Greška kontrole pristupa + + + User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + Korisnik "%1" kod računara "%2" pokušao je pristupiti ovom računaru, ali je blokiran zbog postavki kontrole pristupa. + + + Active connections: + + + + + ComputerGroupSelector + + Group %1 + + + + + ComputerManager + + User + Korisnik + + + Missing network object directory plugin + Nedostaje dodatak mrežnog objekta direktorijuma + + + No default network object directory plugin was found. Please check your installation or configure a different network object directory backend via %1 Configurator. + Nije pronađen nijedan podrazumevani dodatak mrežnog objekta. Proverite vašu instalaciju ili konfigurišite drugačiju poziciju direktorijuma mrežnih objekata putem %1 Konfigurator. + + + Location detection failed + Otkrivanje lokacije nije uspelo + + + Computer name;Hostname;User + Ime računara; Ime domaćina; Korisnik + + + Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + Ne mogu odrediti lokaciju ovog računara. Ovo ukazuje na problem sa konfiguracijom sistema. Sve lokacije će se umesto toga prikazati na ploči za odabir računara. + + + Logged in since + + + + %1 days + + + + 1 day + + + + + ComputerMonitoring + + Computers + Računari + + + Search users and computers + Pretražite korisnike i računare + + + Select all + + + + Unselect all + + + + Add to group + + + + Remove from group + + + + + ComputerSelectPanel + + Computer search + Pretraživanje računara + + + Add location + Dodaj lokaciju + + + Save computer/user list + Sačuvaj listu računara/korisnika + + + Select output filename + Odaberite naziv izlazne datoteke + + + CSV files (*.csv) + CSV datoteke (* .csv) + + + File error + Greška datoteke + + + Could not write the computer and users list to %1! Please check the file access permissions. + Ne može se zapisati lista računara i korisnika na %1! Proverite dozvole za pristup datoteci. + + + Search computers + + + + + ConfigCommands + + Clear system-wide Veyon configuration + Jasna konfiguracija Veyon na celom sistemu + + + List all configuration keys and values + Navedi sve konfiguracijske ključeve i vrednosti + + + Import configuration from given file + Uvezi konfiguraciju iz date datoteke + + + Export configuration to given file + Izvoz konfiguracije u datu datoteku + + + Read and output configuration value for given key + Pročitajte i iznesite konfiguracione vrednosti za zadani ključ + + + Write given value to given configuration key + Zapišite zadatu vrednost zadatom konfiguracijskom ključu + + + Unset (remove) given configuration key + Poništite (uklonite) dati konfiguracijski ključ + + + Upgrade and save configuration of program and plugins + Nadogradite i spremite konfiguraciju programa i dodataka + + + Please specify an existing configuration file to import. + Navedite postojeću konfiguracijsku datoteku za uvoz. + + + Configuration file is not readable! + Konfiguracijska datoteka nije čitljiva! + + + Please specify a valid filename for the configuration export. + Navedite valjano ime datoteke za izvoz konfiguracije + + + Output file is not writable! + Izlazna datoteka se ne može pisati! + + + Output directory is not writable! + Izlazni direktorijum nije zapisan! + + + Please specify a valid key. + Molimo navedite važeći ključ. + + + Specified key does not exist in current configuration! + Navedeni ključ ne postoji u trenutnoj konfiguraciji! + + + Please specify a valid value. + Navedite valjanu vrednost. + + + Configure Veyon at command line + Konfigurišite Veyon u komandnoj liniji + + + Commands for managing the configuration of Veyon + Naredbe za upravljanje konfiguracijom Veyon-a + + + + ConfigurationManager + + Could not modify the autostart property for the %1 Service. + Nije moguće izmeniti svojstvo automatskog pokretanja za uslugu %1. + + + Could not configure the firewall configuration for the %1 Server. + Nije moguće konfigurisati konfiguraciju zaštitnog zida za %1 Server. + + + Could not configure the firewall configuration for the %1 Worker. + Nije moguće konfigurisati konfiguraciju zaštitnog zida za %1 Radnika. + + + Configuration is not writable. Please check your permissions! + Konfiguracija nije upisiva. Molimo proverite svoje dozvole! + + + Could not apply platform-specific configuration settings. + Ne mogu se primeniti postavke konfiguracije specifične za platformu. + + + Could not configure the firewall configuration for the %1 Service. + + + + + DemoClient + + %1 Demo + %1 Demonstracija + + + + DemoConfigurationPage + + Demo server + Demo server + + + Tunables + Tunables + + + ms + ms + + + Key frame interval + Interval ključnog okvira + + + Memory limit + Memorijski limit + + + MB + MB + + + Update interval + Interval ažuriranja + + + s + s + + + Slow down thumbnail updates while demo is running + Usporite ažuriranje sličica dok je demonstracija aktivna + + + Bandwidth limit + + + + MB/s + + + + + DemoFeaturePlugin + + Stop demo + Zaustavi demonstraciju + + + Window demo + Prozor demonstracije + + + Give a demonstration by screen broadcasting + Pokažite demonstraciju ekranskim emitovanjem + + + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + U ovom režimu se vaš ekran prikazuje u prozoru na svim računarima. Korisnici se po potrebi mogu prebaciti na druge prozore. + + + Demo + + + + Share your screen or allow a user to share his screen with other users. + + + + Full screen demo + + + + Share your own screen in fullscreen mode + + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share your own screen in a window + + + + Share selected user's screen in fullscreen mode + + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share selected user's screen in a window + + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + + + + Please select only one user screen to share. + + + + All screens + + + + + DesktopAccessDialog + + Desktop access dialog + Dijalog pristupa radnoj površini + + + Confirm desktop access + Potvrdite pristup radnoj površini + + + Never for this session + Nikada za ovu sesiju + + + Always for this session + Uvek za ovu sesiju + + + The user %1 at computer %2 wants to access your desktop. Do you want to grant access? + Korisnik %1 na računaru %2 želi pristupiti vašoj radnoj površini. Želite li odobriti pristup? + + + + DesktopServicesConfigurationPage + + Name + Ime + + + Path + Putanja + + + Predefined websites + Unapred definisani websajtovi + + + Remove selected website + Ukloni obeležen websajt + + + URL + URL + + + New website + Novi websajt + + + Applications & websites + + + + Predefined applications + + + + Add new application + + + + Remove selected application + + + + Add new website + + + + New application + + + + + DesktopServicesFeaturePlugin + + Open website + Otvori websajt + + + Click this button to open a website on all computers. + Klikni ovo dugme da otvorite websajt na svim računarima. + + + Open website "%1" + Otvori web lokaciju "%1" + + + Custom website + Prilagodjena web lokacija + + + Start application + + + + Click this button to start an application on all computers. + + + + Start application "%1" + + + + Custom application + + + + Start apps and open websites in user sessions + + + + + DocumentationFigureCreator + + Teacher + Nastavnik + + + Room %1 + Prostorija %1 + + + Please complete all tasks within the next 5 minutes. + Molimo ispunite sve zadatke u narednih 5 minuta. + + + Custom website + Prilagodjena web lokacija + + + Open file manager + Otvorite menadžer datoteka + + + Start learning tool + Pokrenite alat za učenje + + + Play tutorial video + Reprodukujte video tutorial + + + Handout + Brošura + + + Texts to read + Tekstovi za čitanje + + + generic-student-user + opšti-student-korisnik + + + Custom application + + + + + ExternalVncServer + + External VNC server + Spoljni VNC server + + + + ExternalVncServerConfigurationWidget + + External VNC server configuration + Spoljna VNC server konfiguracija + + + Port: + Port: + + + Password: + Lozinka + + + + FeatureCommands + + List names of all available features + + + + Show table with details of all available features + + + + Start a feature on a remote host + + + + Stop a feature on a remote host + + + + Please specify the command to display help for. + + + + Displays a list with the names of all available features. + + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + + + + HOST ADDRESS + DOMAĆIN ADRESA + + + FEATURE + + + + ARGUMENTS + + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + + + + Lock the screen + + + + Display a text message + + + + Test message + + + + Start an application + + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + + + + Unlock the screen + + + + The specified command does not exist or no help is available for it. + + + + Name + Ime + + + Description + + + + Master + Glavni + + + Service + Servis + + + Worker + + + + UID + + + + Plugin + Dodatak + + + Invalid feature name or UID specified + + + + Error parsing the JSON-encoded arguments: %1 + + + + Failed to initialize credentials + + + + Could not establish a connection to host %1 + + + + Failed to send feature control message to host %1 + + + + Feature-related CLI operations + + + + Commands for controlling features + + + + + FileTransferConfigurationPage + + File transfer + Prenos datoteka + + + Directories + Direktorijumi + + + Destination directory + + + + Default source directory + + + + Options + Opcije + + + Remember last source directory + + + + Create destination directory if it does not exist + + + + + FileTransferController + + Could not open file "%1" for reading! Please check your permissions! + Nije moguće otvoriti datoteku "%1" za čitanje! Molimo proverite svoje dozvole! + + + + FileTransferDialog + + File transfer + Otpremanje datoteka + + + Options + Opcije + + + Transfer only + Samo prenos + + + Transfer and open file(s) with associated program + Prenos i otvaranje datoteke(a) s pripadajućim programom + + + Transfer and open destination folder + Prenos i otvaranje odredišne fascikle + + + Files + Datoteke + + + Start + Pokreni + + + Overwrite existing files + Prepišite postojeće datoteke + + + + FileTransferFileDialog + + Select one or more files to transfer + Obeležite jednu ili više datoteka za prenos. + + + + FileTransferPlugin + + File transfer + Otpremanje datoteka + + + Click this button to transfer files from your computer to all computers. + Kliknite ovo dugme za prenos datoteka od vašeg računara na sve računare. + + + Select one or more files to transfer + Obeležite jednu ili više datoteka za prenos. + + + Transfer files to remote computer + Prenos datoteka na upravljani računar + + + Received file "%1". + Primljena datoteka "%1". + + + Could not receive file "%1" as it already exists. + Nije moguće primiti datoteku "%1" jer ona već postoji. + + + Could not receive file "%1" as it could not be opened for writing! + Ne mogu primiti datoteku "%1" jer se ne može otvoriti za pisanje! + + + + GeneralConfigurationPage + + User interface + Korisnički interfejs + + + Language: + Jezik: + + + Use system language setting + Koristi podešeni sistemski jezik + + + Veyon + Veyon + + + Logging + Prijavljivanje + + + Log file directory + Dnevnik datoteka direktorijuma + + + Log level + Nivo zapisa + + + Nothing + Ništa + + + Only critical messages + Samo kritične poruke + + + Errors and critical messages + Greške i kritične poruke + + + Warnings and errors + Upozorenja i greške + + + Information, warnings and errors + Informacija,upozorenja i greške + + + Debug messages and everything else + Poruke za uklanjanje grešaka i sve ostalo + + + Limit log file size + Ograničite veličinu datoteke dnevnika + + + Clear all log files + Očistite sve datoteke dnevnika + + + Log to standard error output + Prijavite se na standardni izlaz greške + + + %1 service + %1 usluga + + + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + Uslugu %1 potrebno je privremeno zaustaviti kako biste uklonili datoteke dnevnika. Nastaviti? + + + Log files cleared + Datoteke dnevnika su očišćene + + + All log files were cleared successfully. + Sve datoteke dnevnika uspešno su izbrisane. + + + Error + Greška + + + Could not remove all log files. + Nije bilo moguće ukloniti sve datoteke dnevnika. + + + MB + MB + + + Rotate log files + Rotacija datoteka dnevnika + + + x + x + + + Write to logging system of operating system + Zapisati u sistem za prijavu operativnog sistema + + + TLS configuration + + + + Use certificate authority for TLS connections + + + + CA certificate file + + + + ... + ... + + + Host certificate file + + + + Host private key file + + + + Style: + + + + Native + + + + Color scheme: + + + + Light + + + + Dark + + + + User groups + + + + Backend: + Pozadina: + + + Include user groups from domain + + + + Missing user groups backend + Nedostaje pozadina grupe korisnika + + + No user groups plugin was found. Please check your installation! + + + + + HeadlessVncServer + + Headless VNC server + + + + + LdapBrowseDialog + + Browse LDAP + Pregledajte LDAP + + + + LdapClient + + LDAP error description: %1 + Opis greške LDAP: %1 + + + + LdapConfiguration + + LDAP connection failed + LDAP veza je neuspešna + + + Could not connect to the LDAP server. Please check the server parameters. + +%1 + Ne mogu se povezati s LDAP serverom. Molimo proverite parametre servera. + +%1 + + + LDAP bind failed + Neuspešna LDAP veza + + + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + Nije se moglo povezati na LDAP server. Proverite parametre servera i povežite akreditive. + +%1 + + + LDAP bind successful + LDAP vezanje je uspešno + + + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Uspešno se povezao s LDAP serverom i izvršio LDAP vezanje. Osnovne postavke LDAP-a ispravno su konfigurisane. + + + LDAP base DN test failed + DN-test za LDAP bazu je neuspešan + + + Could not query the configured base DN. Please check the base DN parameter. + +%1 + Ne može se zatražiti konfigurisana baza DN. Molimo proverite osnovni DN parametar. + +%1 + + + LDAP base DN test successful + LDAP baza DN test je uspešan + + + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + LDAP baza DN uspješno prosledjen upit. Pronađjeni su sledeći unosi: + +%1 + + + LDAP naming context test failed + Neuspešan kontekstni test LDAP imenovanja + + + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + Nije moguć upit baznog DN-a putem imenovanja konteksta. Molimo proverite parametar atributa konteksta imenovanja. + +%1 + + + LDAP naming context test successful + LDAP kontekstni test imenovanja je uspešan + + + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + Kontekst imenovanja LDAP uspešno je prosledio upit. Pronađjena je sledeća baza DN: +%1 + + + user tree + stablo korisnika + + + User tree + Korisnik prikaz stablo + + + group tree + stablo grupe + + + Group tree + Grupa prikaz stabla + + + computer tree + stablo računara + + + Computer tree + Rašunar prikaz stablo + + + computer group tree + stablo računarske grupe + + + Computer group tree + Stablo računarskih grupa + + + user objects + korisnički objekti + + + User login name attribute + Atribut korisničkog imena za prijavu + + + group members + članovi grupe + + + Group member attribute + Atribut člana grupe + + + Group not found + Grupa nije pronadjena + + + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Nije bilo moguće pronaći grupu sa nazivom "%1". Proverite naziv grupe ili parametar stabla grupe. + + + computer objects + računarski objekti + + + Computer display name attribute + Atribut prikaza računarskog imena + + + Invalid hostname + Nevažeće ime domaćina + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Konfigurisali ste imena domaćina računara da se sačuvaju kao potpuno kvalifikovana imena domena (FQDN), ali ste unieli ime računara domaćina bez domena. + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Konfigurisali ste imena domaćina računara da se sačuvaju kao jednostavna imena računara bez imena domena, ali ste unieli ime računara s delom imena domena. + + + Computer hostname attribute + Atribut imena domaćina računara + + + computer MAC addresses + računarske MAC adrese + + + Computer MAC address attribute + Atribut računarske MAC adrese + + + computer locations + lokacije računara + + + Computer location attribute + Atribut lokacije računara + + + Location name attribute + Atribut naziva lokacije + + + users + korisnici + + + user groups + korisničke grupe + + + computers + računari + + + computer groups + računarske grupe + + + computer containers + kontejneri za računare + + + groups of user + grupe korisnika + + + User not found + Korisnik nije pronadjen + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + Ne mogu pronaći korisnika s imenom "%1". Proverite korisničko ime ili parametar korisničkog stabla. + + + groups of computer + grupe računara + + + Computer not found + Računar nije pronadjen + + + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Ne mogu pronaći računar s imenom domaćina "%1". Molimo proverite naziv domaćina ili parametar stabla računara. + + + Hostname lookup failed + Pretraživanje imena hosta nije uspelo + + + Could not lookup hostname for IP address %1. Please check your DNS server settings. + Nije moguće potražiti ime hosta za IP adresu %1. Proverite postavke DNS servera. + + + location entries + unosi lokacije + + + Computer groups filter + + + + Computer locations identification + Identifikacija računarskih lokacija + + + Filter for computer groups + Filter za grupe računara + + + Invalid test value + + + + An empty or invalid value has been supplied for this test. + + + + LDAP %1 test failed + LDAP %1 test je neuspešan + + + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + Ne može se zatražiti ni jedan unos u konfigurisanom %1. Molimo proverite parametar "%2". + +%3 + + + LDAP %1 test successful + LDAP %1 test je uspešan + + + The %1 has been queried successfully and %2 entries were found. + %1 je uspešno upitan i pronađjeni su unosi %2. + + + LDAP test failed + LDAP test neuspešan + + + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + Nije moguće postaviti nijedan %1. Proverite parametar(e) %2 i unesite ime postojećeg objekta. + +%3 + + + and + i + + + LDAP test successful + LDAP test je uspešan + + + %1 %2 have been queried successfully: + +%3 + %1 %2 uspešno je prosledjen upit: + +%3 + + + LDAP filter test failed + Provera LDAP filtera nije uspela + + + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 + Nije moguće proslediti upit nijednog %1 pomoću konfigurisanog filtera. Molimo proverite LDAP filter za %1. + +%2 + + + LDAP filter test successful + Provera LDAP filtera uspešna + + + %1 %2 have been queried successfully using the configured filter. + %1 %2 uspešno je ispitan pomoću konfigurisanog filtera. + + + LDAP directory + + + + + LdapConfigurationPage + + Basic settings + Osnovna podešavanja + + + General + Opšte + + + LDAP server and port + LDAP server i port + + + Bind DN + Vezati DN + + + Bind password + Vezati lozinku + + + Anonymous bind + Anonimni vez + + + Use bind credentials + Koristite veze akreditiva + + + Base DN + Osnovni DN + + + Fixed base DN + Fiksna baza DN + + + e.g. dc=example,dc=org + npr. dc = primer, dc = org + + + Discover base DN by naming context + Otkrijte bazu DN imenovanjem konteksta + + + e.g. namingContexts or defaultNamingContext + npr. imenovanje Konteksta ili podrazumevaoImenovanjeKonteksta + + + Environment settings + Postavke okruženja + + + Object trees + Objektna stabla + + + Computer tree + Rašunar prikaz stablo + + + e.g. OU=Groups + npr. OU=Grupe + + + User tree + Korisnik prikaz stablo + + + e.g. OU=Users + npr. OU=Korisnici + + + e.g. OU=Computers + npr.OU=Računari + + + Group tree + Grupa prikaz stabla + + + Perform recursive search operations in object trees + Izvođenje rekurzivnih pretraga u stablima objekata + + + Object attributes + Objekat atributi + + + e.g. hwAddress + npr.hwAdresa + + + e.g. member or memberUid + npr. član ili članUid + + + e.g. dNSHostName + npr.dNSHostName + + + Computer MAC address attribute + Atribut računarske MAC adrese + + + Group member attribute + Atribut člana grupe + + + e.g. uid or sAMAccountName + npr.uid ili sAMAccountName + + + Advanced settings + Napredna podešavanja + + + Optional object filters + Opcionalni filteri objekata + + + Filter for user groups + Filter za korisničke grupe + + + Filter for users + Filter za korisnike + + + Filter for computer groups + Filter za grupe računara + + + Group member identification + Identifikacija člana grupe + + + Distinguished name (Samba/AD) + Istaknuto ime (Samba / AD) + + + List all groups of a user + Lista svih grupa korisnika + + + List all groups of a computer + Lista svih grupa računara + + + Get computer object by IP address + Nabavite predmet računara putem IP adrese + + + Enter username + Unesi korisničko ime + + + Please enter a user login name (wildcards allowed) which to query: + Unesite korisničko ime za prijavu (dozvoljeni zamenski znakovi) za upite: + + + Enter group name + Unesi ime grupe + + + Please enter a group name whose members to query: + Molimo unesite naziv grupe čiji će članovi zatražiti: + + + Enter computer name + Unesite ime računara + + + Enter computer DN + Unesite DN računara + + + Please enter the DN of a computer whose MAC address to query: + Molimo unesite DN računara čija je MAC adresa upitana: + + + Please enter a user login name whose group memberships to query: + Unesite korisničko ime za prijavu čija će članarina grupe biti upitna: + + + Enter computer IP address + Unesite IP adresu računara + + + Please enter a computer IP address which to resolve to an computer object: + Unesite računarsku IP adresu koja se može rešiti na računarskom objektu: + + + (only if different from group tree) + (samo ako se razlikuje od stabla grupe) + + + Computer group tree + Stablo računarskih grupa + + + Filter for computers + Filter za računare + + + e.g. room or computerLab + npr. soba ili kompjuterska laboratorija + + + Integration tests + Integracijski testovi + + + Computer groups + Računarske grupe + + + e.g. name or description + npr. ime ili opis + + + Filter for computer containers + Filter za kontejnere računara + + + Computer containers or OUs + Kontejneri za računare ili OU + + + Connection security + Sigurnost veze + + + TLS certificate verification + Potvrda TLS certifikata + + + System defaults + Podrazumevane postavke sistema + + + Never (insecure!) + Nikada (nesigurno!) + + + Custom CA certificate file + Prilagođena datoteka certifikata CA + + + None + Nijedan + + + TLS + TLS + + + SSL + SSL + + + e.g. (objectClass=computer) + npr. (objectClass = računar) + + + e.g. (objectClass=group) + npr. (objectClass = grupa) + + + e.g. (objectClass=person) + npr. (objectClass = osoba) + + + e.g. (objectClass=room) or (objectClass=computerLab) + npr. (objectClass = soba) ili (objectClass = kompjuterska laboratorija) + + + e.g. (objectClass=container) or (objectClass=organizationalUnit) + npr. (objectClass = kontejner) ili (objectClass = organizationUnit) + + + Certificate files (*.pem) + Datoteke certifikata (* .pem) + + + Encryption protocol + Protokol šifrovanja + + + Computer location attribute + Atribut lokacije računara + + + Computer display name attribute + Atribut prikaza računarskog imena + + + Location name attribute + Atribut naziva lokacije + + + e.g. cn or displayName + npr. cn ili displayName + + + Computer locations identification + Identifikacija računarskih lokacija + + + Identify computer locations (e.g. rooms) via: + Prepoznajte lokacije računara (npr. Sobe) putem: + + + Location attribute in computer objects + Atribut lokacije u računarskim objektima + + + List all entries of a location + Lista svih unosa lokacije + + + List all locations + Lista svih lokacija + + + Enter computer display name + Unesite ime računara za prikaz + + + Please enter a computer display name to query: + Unesite prikazno ime računara za upit: + + + Enter computer location name + Unesite naziv lokacije računara + + + Please enter the name of a computer location (wildcards allowed): + Unesite ime lokacije računara (dozvoljene zamenske karte): + + + Enter location name + Unesite naziv lokacije + + + Please enter the name of a location whose entries to query: + Unesite naziv lokacije koji se unosi traže: + + + Browse + Pregledajte + + + Test + Test + + + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Imena hosta sačuvana su kao potpuno kvalifikovana imena domena (FQDN, npr. Myhost.example.org) + + + Computer hostname attribute + Atribut imena domaćina računara + + + Please enter a computer hostname to query: + Da biste poslali upit unesite ime domaćin računara: + + + Enter hostname + Unesite ime domaćina + + + Please enter a computer hostname whose group memberships to query: + Unesite ime računara domaćina čije će članstvo u grupi biti upitno: + + + User login name attribute + Atribut korisničkog imena za prijavu + + + Configured attribute for user login name or computer hostname (OpenLDAP) + Konfigurisani atribut za korisničko ime za prijavu ili domaćin računara (OpenLDAP) + + + Directory name + + + + Query options + + + + Query nested user groups (supported by AD only) + + + + Query timeout + + + + ms + ms + + + + LdapNetworkObjectDirectoryConfigurationPage + + LDAP + LDAP + + + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + + + LdapPlugin + + Auto-configure the base DN via naming context + Automatski konfigurišite osnovni DN putem konteksta imenovanja + + + Query objects from LDAP directory + Upit objekata iz LDAP direktorijuma + + + Show help about command + Pokažite pomoć o naredbi + + + Commands for configuring and testing LDAP/AD integration + Naredbe za konfigurisanje i testiranje LDAP / AD integracije + + + Basic LDAP/AD support for Veyon + Osnovna podrška za LDAP / AD za Veyon + + + %1 (load computers and locations from LDAP/AD) + %1 (učitavanje računara i lokacija iz LDAP / AD) + + + %1 (load users and groups from LDAP/AD) + %1 (učitavanje korisnika i grupa iz LDAP / AD) + + + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Navedite valjani LDAP URL prateći šemu "ldap [s]: // [korisnik [: lozinka] @] ime hosta [: port]" + + + No naming context attribute name given - falling back to configured value. + Nije dodato ime atributa konteksta imenovanja - vraća se na konfigurisanu vrednost. + + + Could not query base DN. Please check your LDAP configuration. + Ne može se zatražiti baza DN. Molimo proverite LDAP konfiguraciju. + + + Configuring %1 as base DN and disabling naming context queries. + Konfigurisanje %1 kao osnovnog DN-a i onemogućavanje imenovanja kontekstnih upita. + + + Test binding to an LDAP server + + + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Uneseno korisničko ime ili šifra nisu ispravni. Molimo unesite ispravne podatke ili se prebacite na drugi metod autentifikacije upotrebom Veyon Configurator-a. + + + LDAP bind + + + + + LinuxPlatformConfigurationPage + + Linux + LINUX + + + Custom PAM service for user authentication + Prilagođena PAM usluga za proveru autentičnosti korisnika + + + User authentication + Autentifikacija korisnika + + + User sessions + + + + Minimum session lifetime before server start + + + + User login + Prijava korisnika + + + Login key sequence + + + + + LinuxPlatformPlugin + + Plugin implementing abstract functions for the Linux platform + Dodatak implementira apstraktne funkcije za Linux platformu + + + + LocationDialog + + Select location + Obeleži lokaciju + + + enter search filter... + unesite filter pretraživanja ... + + + + MainToolBar + + Configuration + Konfiguracija + + + Show icons only + Prikaži samo ikone + + + Disable tooltips + + + + + MainWindow + + MainWindow + Glavni prozor + + + toolBar + alatna traka + + + General + Opšte + + + &File + &Datoteka + + + &Help + &Pomoć + + + &Quit + &Odustati + + + Ctrl+Q + Ctrl+Q + + + Ctrl+S + Ctrl+S + + + L&oad settings from file + Učitajte postavke iz datoteke + + + Ctrl+O + Ctrl+O + + + About Qt + O QT + + + Configuration not writable + Konfiguracija se ne može prepisati + + + Load settings from file + Učitajte postavke iz datoteka + + + Save settings to file + Sačuvaj postavke u datoteku + + + Unsaved settings + Nečuvaj podešavanja + + + There are unsaved settings. Quit anyway? + Postoje ne sačuvana podešavanja. Prestati svakako? + + + Veyon Configurator + Veyon Konfigurator + + + Service + Servis + + + Master + Glavni + + + Access control + Pristup kontroli + + + About Veyon + O Veyonu + + + Auto + Automatski + + + About + O nama + + + %1 Configurator %2 + %1 Konfigurator %2 + + + JSON files (*.json) + JSON datoteke (*.json) + + + The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. + Lokalni pomoćni program za konfiguraciju izveštava da konfiguracija ne može biti napisana! Molimo pokrenite %1 konfigurator s većim privilegijama. + + + Access denied + Pristup odbijen + + + According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. + Prema lokalnoj konfiguraciji nije vam dopušten pristup računarima u mreži. Prijavite se pomoću drugog naloga ili dopustite administratoru sistema da proveri lokalnu konfiguraciju. + + + Screenshots + Snimci ekrana + + + Feature active + Aktivna funkcija + + + The feature "%1" is still active. Please stop it before closing %2. + Funkcija "%1" i dalje je aktivna. Molim zaustavite pre zatvaranja %2. + + + Reset configuration + Resetujte konfiguraciju + + + Do you really want to reset the local configuration and revert all settings to their defaults? + Želite li stvarno resetovati lokalnu konfiguraciju i vratiti sve postavke na njihove početne vrednosti? + + + Search users and computers + Pretražite korisnike i računare + + + Align computers to grid + Poravnajte računare po mreži + + + %1 Configurator + %1 Konfigurator + + + Insufficient privileges + Nedovoljno privilegija + + + Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + Ne mogu započeti s administrativnim privilegijama. Molimo vas proverite da li je instaliran program sličan sudo-u za radnu površinu! Program će se pokrenuti sa uobičajenim korisničkim privilegijama. + + + Only show powered on computers + Pokaži samo na pokrenutim računarima + + + &Save settings to file + % Sačuvajte postavke u datoteci + + + &View + %Vidi + + + &Standard + &Standardno + + + &Advanced + &Napredno + + + Use custom computer arrangement + Koristite prilagođjeni raspored računara + + + Locations && computers + Lokacije i računari + + + Authentication + Autentifikacija + + + Adjust size of computer icons automatically + + + + Slideshow + + + + Spotlight + + + + Veyon Master + Veyon Master + + + Locations & computers + Lokacije & računari + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + + + + Load computer positions + + + + Save computer positions + + + + + MasterConfigurationPage + + Directories + Direktorijumi + + + User configuration + Korisnička konfiguracija + + + Feature on computer double click: + Dvostruki klik na računaru: + + + Features + Karakteristike + + + All features + Sve karakteristike + + + Disabled features + Onemogući karakteristike + + + Screenshots + Snimci ekrana + + + <no feature> + <no feature> + + + Basic settings + Osnovna podešavanja + + + Behaviour + Ponašanje + + + Enforce selected mode for client computers + Pojačajte odabrani režim za klijentske računare + + + Hide local computer + Sakri lokalni računar + + + Hide computer filter field + Sakri polje filtera računara + + + Actions such as rebooting or powering down computers + Radnje poput ponovnog pokretanja ili isključivanja računara + + + User interface + Korisnički interfejs + + + Background color + Boja pozadine + + + Thumbnail update interval + Interval ažuriranja sličica + + + ms + ms + + + Program start + Startovanje programa + + + Modes and features + Načini i funkcije + + + User and computer name + Ime korisnika i računara + + + Only user name + Samo korisničko ime + + + Only last part of user name + + + + Only computer name + Samo ime računara + + + Computer thumbnail caption + Opis računara u sličicama + + + Text color + Boja teksta + + + Sort order + Poredjaj prema + + + Computer and user name + Ime računara i korisnika + + + Computer locations + Lokacije računara + + + Show current location only + Prikaži samo trenutnu lokaciju + + + Allow adding hidden locations manually + Dopusti ručno dodavanje skrivenih lokacija + + + Hide empty locations + Sakri prazne lokacije + + + Show confirmation dialog for potentially unsafe actions + Prikaži potvrdni dijalog za potencijalno nesigurne radnje + + + Perform access control + Izvršite kontrolu pristupa + + + Automatically select current location + Automatski odaberite trenutnu lokaciju + + + Automatically open computer select panel + Automatski otvorite panel za odabir računara + + + Use modern user interface (experimental) + + + + Thumbnail spacing + + + + px + + + + Hide local session + + + + Auto + Automatski + + + Thumbnail aspect ratio + + + + Automatically adjust computer icon size + + + + Open feature windows on the same screen as the main window + + + + Configuration templates + + + + Image quality in monitoring mode + + + + Highest + + + + High + + + + Medium + + + + Low + + + + Lowest + + + + Remote access image quality + + + + Advanced + + + + Computer name source + + + + Default + + + + Host address + Domaćin adresa + + + Session client address + + + + Session client name + + + + Session host name + + + + Session metadata + + + + Full name of user + + + + User login name + + + + Computer UID role + + + + Session meta data hash + + + + Always expand all locations + + + + Image quality + + + + + MonitoringMode + + Monitoring + Nadgledanje + + + Builtin monitoring mode + Ugrađeni način praćenja + + + This mode allows you to monitor all computers at one or more locations. + Ovaj način rada omogućuje vam praćenje svih računara na jednoj ili više lokacija. + + + Query application version of the server + + + + Query active features + + + + Query properties of remotely available screens + + + + + NestedNetworkObjectDirectory + + All directories + + + + + NetworkObjectDirectoryConfigurationPage + + Update interval: + Ažuriraj interval: + + + seconds + sekunde + + + + NetworkObjectDirectoryConfigurationPageTab + + Enabled + + + + + NetworkObjectTreeModel + + Locations/Computers + Lokacije/Kompjuteri + + + + OpenWebsiteDialog + + Open website + Otvori websajt + + + e.g. Veyon + npr. Veyon + + + Remember and add to website menu + Zapamti i dodaj meniju web stranice + + + e.g. www.veyon.io + npr. www.veyon.io + + + Please enter the URL of the website to open: + Molimo unesite adresu-URL web stranice za otvaranje: + + + Name: + Ime: + + + Website name + + + + + PluginCommands + + List names of all installed plugins + + + + Show table with details of all installed plugins + + + + Name + Ime + + + Description + + + + Version + + + + UID + + + + Plugin-related CLI operations + + + + Commands for managing plugins + + + + + PowerControlFeaturePlugin + + Power on + Uključite + + + Click this button to power on all computers. This way you do not have to power on each computer by hand. + Klik na ovo dugme za uključivanje svih kompjutra. Na ovaj način ne morate uključivati svaki računar ručno. + + + Reboot + Ponovno podizanje sistema + + + Click this button to reboot all computers. + Klik na ovo dugme za ponovno podizanje sistema na svim kompjuterima. + + + Power down + Isključiti + + + Click this button to power down all computers. This way you do not have to power down each computer by hand. + Klik na ovo dugme za isključivanje svih kompjutera. Na ovaj način ne morate isključivati svaki kompjuter ručno. + + + Power on/down or reboot a computer + Uključite/Isključite ili pokrenite ponovo sistem kompjutera + + + Confirm reboot + Potvrdite ponovno podizanje sistema + + + Confirm power down + Potvrdite isključivanje + + + Do you really want to reboot the selected computers? + Da li stvarno želite ponovo pokrenuti sistem izabranih kompjutera? + + + Power on a computer via Wake-on-LAN (WOL) + Uključivanje kompjutera preko Wake-on-LAN (WOL) + + + MAC ADDRESS + MAC ADRESA + + + This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. + Ova komanda emituje Wake-on-LAN (WOL) paket na mreži da bi bio uključen kompjuter sa datom MAC adresom. + + + Please specify the command to display help for! + Molimo navedite naredbu za prikaz pomoći! + + + Invalid MAC address specified! + Specificirana je neispravna MAC adresa! + + + Commands for controlling power status of computers + Komande za kontrolu statusa napajanja kompjutera + + + Power down now + Isključiti odmah + + + Install updates and power down + Instalisati ažuriranja i isključiti + + + Power down after user confirmation + Isključiti posle potvrde od strane korisnika + + + Power down after timeout + Isključiti posle isteka vremena + + + The computer was remotely requested to power down. Do you want to power down the computer now? + Isključenje kompjutera je bilo daljinski zahtevano. Želite li isključiti kompjuter odmah? + + + The computer will be powered down in %1 minutes, %2 seconds. + +Please save your work and close all programs. + Kompjuter će biti isljučen za %1 minuta, %2 sekundi. + +Molimo snimite/spasite Vaš rad i zatvorite sve programe. + + + Do you really want to reboot <b>ALL</b> computers? + + + + Do you really want to power down <b>ALL</b> computers? + + + + Do you really want to power down the selected computers? + + + + + PowerDownTimeInputDialog + + Power down + Isključiti + + + Please specify a timeout for powering down the selected computers: + Molimo odredite vreme potrebno za isključenje izabranih kompjutera: + + + minutes + minuta + + + seconds + sekundi + + + + RemoteAccessFeaturePlugin + + Remote view + Daljinski prikaz + + + Open a remote view for a computer without interaction. + Otvorite daljinski prikaz kompjutera bez interakcije. + + + Remote control + Daljinska kontrola + + + Open a remote control window for a computer. + Otvorite prozor daljinske kontrole kompjutera. + + + Remote access + Udaljeni pristup + + + Remote view or control a computer + Daljinski prikaz ili kontrola kompjutera + + + Show help about command + Pokažite pomoć o naredbi + + + Exchange clipboard contents + + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + + + RemoteAccessPage + + Remote access: %1 + + + + + RemoteAccessWidget + + %1 - %2 Remote Access + %1 - %2 Daljinski pristup + + + %1 - %2 - %3 Remote Access + + + + + RemoteAccessWidgetToolBar + + View only + Samo prikaz + + + Remote control + Daljinska kontrola + + + Send shortcut + Pošalji prečicu + + + Fullscreen + Celi ekran + + + Window + Prozor + + + Ctrl+Alt+Del + Ctrl+Alt+Del + + + Ctrl+Esc + Ctrl+Esc + + + Alt+Tab + Alt+Tab + + + Alt+F4 + Alt+F4 + + + Win+Tab + Win+Tab + + + Win + Win + + + Menu + Meni + + + Alt+Ctrl+F1 + Alt+Ctrl+F1 + + + Connected. + Spojen. + + + Screenshot + Snimka ekrana + + + Exit + Izlaz + + + Connecting... + + + + Select screen + + + + All screens + + + + + ScreenLockFeaturePlugin + + Lock + Zaključaj + + + Unlock + Otključaj + + + Lock screen and input devices of a computer + Zaključajte ekran i ulazne uređaje kompjutera + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + Da biste privukli punu pažnju svih korisnika možete zaključati njihove kompjutere upotrebom ovog dugmeta. Na ovaj način svi ulazni uređaji su zaključani a ekrani su zatamnjeni. + + + Lock input devices + Zaključaj ulazne uređaje + + + Unlock input devices + + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + + + + Screenshot + + unknown + nepoznato + + + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + Ne može se napraviti snimak ekrana jer direktorij %1 ne postoji i ne može biti kreiran. + + + Screenshot + Snimka ekrana + + + Could not open screenshot file %1 for writing. + + + + + ScreenshotFeaturePlugin + + Screenshot + Snimka ekrana + + + Use this function to take a screenshot of selected computers. + Upotrebite ovu funkciju da napravite snimak ekrana izabranog kompjutera. + + + Screenshots taken + Snimka ekrana napravljena + + + Screenshot of %1 computer have been taken successfully. + Snimka ekrana %1 kompjutera je napravljena uspešno. + + + Take screenshots of computers and save them locally. + Uzmi snimku ekrana kompjutera i sačuvaj je lokalno. + + + + ScreenshotManagementPage + + Screenshots + Snimci ekrana + + + + ScreenshotManagementPanel + + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + Sve snimke ekrana koje ste napravili su prikazane ovdje. Možete napraviti snimku ekrana klikom na "Screenshot" u meniju koji dobijete desnim klikom na kompjuteru. snimke ekrana mogu biti upravljane upotrebom dugmadi ispod. + + + User: + Korisnik: + + + Computer: + Kompjuter: + + + Date: + Datum: + + + Time: + Vreme: + + + Show + Prikazati + + + Delete + Pobrisati + + + Screenshot + Snimka ekrana + + + Do you really want to delete all selected screenshots? + + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + + + + User has denied access + + + + User confirmed access + + + + + ServiceConfigurationPage + + General + Opšte + + + Autostart + Autostart + + + Hide tray icon + Sakrij ikonu u tray-u + + + Start service + Startuj servis + + + Stopped + Zaustavljen + + + Stop service + Zaustavi servis + + + State: + Stanje: + + + Enable firewall exception + Uključi firewall izuzetak + + + Allow connections from localhost only + Dozvoli samo konekcije od lokalnog kompjutera + + + VNC server + VNC server + + + Plugin: + Plugin: + + + Restart %1 Service + Ponovo pokreni %1 servis + + + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + Sve postavke su uspješno spašene. Da bi se primijenile servis %1 treba biti ponovo pokrenut. Želite li sada ponovo pokrenuti? + + + Running + Pokrenut + + + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. + Omogućavanjem ove opcije postići ćete da servis pokrene server proces za svaku interaktivnu sesiju na kompjuteru. +Obično je ovo zahtevano kao podrška trminal serverima. + + + Show notification on remote connection + Prikaži obaveštenje na daljinskoj vezi + + + Show notification when an unauthorized access is blocked + Prikaži obavest kada je zabranjeni pristup blokiran. + + + Maximum session count + + + + Network port numbers + + + + Veyon server + + + + Internal VNC server + Interni VNC server + + + Feature manager + Upravitelj svojstava + + + Demo server + Demo server + + + Miscellaneous network settings + + + + Session mode + + + + Local session mode (single server instance for primary local session) + + + + Active session mode (single server instance for active local or remote session) + + + + Multi session mode (distinct server instance for each local and remote desktop session) + + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + + + + Miscellaneous settings + + + + Disable clipboard synchronization + + + + Session metadata + + + + Content + + + + None + Nijedan + + + Value of an environment variable + + + + Value of a registry key + + + + Environment variable name: + + + + Registry key name: + + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + + + + + ServiceControl + + Service control + Kontrola servisa + + + Starting %1 + + + + Stopping %1 + + + + Restarting %1 + + + + Registering %1 + + + + Unregistering %1 + + + + + ServiceControlCommands + + Register Veyon Service + Registracija Veyon servisa + + + Unregister Veyon Service + Deregistracija Veyon servisa + + + Start Veyon Service + Pokreni Veyon servis + + + Stop Veyon Service + Zaustavi Veyon servis + + + Restart Veyon Service + Ponovo pokreni Veyon servis + + + Query status of Veyon Service + Status ispitivanja Veyon servisa + + + Service is running + Servis se izvršava + + + Service is not running + Servis se ne izvršava + + + Configure and control Veyon service + Konfiguracija i kontrola Veyon servisa + + + Commands for configuring and controlling Veyon Service + Komande za konfiguraciju i kontrolu Veyon servisa + + + + ShellCommands + + Run command file + Pokreni komandnu datoteku + + + File "%1" does not exist! + Datoteka "%1" nije pronadjena! + + + Interactive shell and script execution for Veyon CLI + + + + Commands for shell functionalities + Komande za funkcije ljuske - shell + + + + SlideshowPanel + + Previous + + + + Start/pause + + + + Next + + + + Duration: + + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + + + + Remove selected computers + + + + Update computers in realtime + + + + Spotlight + + + + Please select at least one computer to add. + + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + + + StartAppDialog + + Start application + + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + npr. "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + + + + Application name + + + + Name: + Ime: + + + e.g. VLC + npr. VLC + + + + SystemTrayIcon + + System tray icon + Ikona sistem tray-a + + + + SystemUserGroupsPlugin + + User groups backend for system user groups + Podrška korisničkih grupa za sistemske korisničke grupe + + + Default (system user groups) + Zadano (sistemske korisničke grupe) + + + + TestingCommandLinePlugin + + Test internal Veyon components and functions + Test internih komponenti i funkcija Veyon-a + + + Commands for testing internal components and functions of Veyon + Komande za testiranje internih komponenti i funkcija Veyon-a + + + + TextMessageDialog + + Send text message + Pošalji tekstualnu poruku + + + Please enter your message which send to all selected users. + + + + + TextMessageFeaturePlugin + + Text message + Tekstualna poruka + + + Use this function to send a text message to all users e.g. to assign them new tasks. + Upotrebi ovu funkciju za slanje tekst poruke svim korisnicima npr. da im dodelite zadatke. + + + Message from teacher + Poruka od predavača + + + Send a message to a user + Pošalji poruku korisniku + + + + UltraVncConfigurationWidget + + Enable capturing of layered (semi-transparent) windows + Omogući hvatanje polu providnih prozora + + + Poll full screen (leave this enabled per default) + Preko celog ekrana (ostaviti uključeno kao zadano) + + + Low accuracy (turbo mode) + Mala preciznost (brzi način) + + + Builtin UltraVNC server configuration + Konfiguracija ugrađenog UltraVNC servera + + + Enable multi monitor support + Uključi više ekransku podršku + + + Enable Desktop Duplication Engine on Windows 8 and newer + Uključi Desktop Duplication Engine- mogućnost dupliciranja desktopa na Windows 8 i novijim + + + Maximum CPU usage + + + + + UserLoginDialog + + User login + Prijava korisnika + + + Please enter a username and password for automatic login on all computers. + Molimo unesite korisničko ime i šifru za automatsku prijavu na svim kompjuterima. + + + Username + Korisničko ime + + + Password + Šifra/lozinka + + + + UserSessionControlPlugin + + Log in + Prijavite se + + + Click this button to log in a specific user on all computers. + Klik na ovo dugme za prijavu određenog korisnika na sve kompjutere. + + + Log off + Odjava + + + Click this button to log off users from all computers. + Klik na ovo dugme za odjavu korisnika sa svih kompjutera. + + + Confirm user logoff + Potvrdite odjavu korisnika + + + Do you really want to log off the selected users? + Želite li stvarno odjaviti izabrane korisnike? + + + User session control + Kontrola sesije korisnika + + + Do you really want to log off <b>ALL</b> users? + + + + + VeyonCore + + [OK] + [OK] + + + [FAIL] + [NEIZVRŠENO] + + + Invalid command! + Pogrešna komanda! + + + Available commands: + Dostupne komande: + + + Invalid arguments given + Određeni-dati pogrešni argumenti + + + Not enough arguments given - use "%1 help" for more information + Nije dato dovoljno argumenata - upotrebiti "1 help" za više informacija + + + Unknown result! + Nepoznat rezultat! + + + Available modules: + Dostupni moduli: + + + No module specified or module not found - available modules are: + Nije specificiran modul ili modul nije nađen - dostupni moduli su: + + + Plugin not licensed + Plugin nije licenciran + + + INFO + INFO + + + ERROR + GREŠKA + + + USAGE + UPOTREBA + + + DESCRIPTION + OPIS + + + EXAMPLES + PRIMJERI + + + WARNING + UPOZORENJE + + + Authentication test + Test provere autentičnosti + + + Screen %1 + + + + + VeyonMaster + + No write access + Nema pristupa za pisanje + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Ne mogu se spasiti vaše lične postavke! Molimo proverite put do korisničke konfiguraciske datoteke upotrebom %1 Configurator-a + + + + VeyonServiceControl + + Veyon Service + Veyon servis + + + + WindowsPlatformConfiguration + + Could not change the setting for SAS generation by software. Sending Ctrl+Alt+Del via remote control will not work! + Postavka za programsko SAS generisanje ne može biti promjenjena. Slanje Ctrl+Alt+Del putem daljinske kontrole neće raditi! + + + + WindowsPlatformConfigurationPage + + Windows + Windows + + + General + Opšte + + + Enable SAS generation by software (Ctrl+Alt+Del) + Omogućavanje programskog SAS generisanja (Ctrl+Alt+Del) + + + Screen lock + Ekran zaključan + + + Hide taskbar + Sakriti traku zadataka + + + Hide start menu + Sakriti start meni + + + Hide desktop + Sakriti radnu površinu + + + User authentication + Autentifikacija korisnika + + + Use alternative user authentication mechanism + Upotrebiti alternativni mehanizam provere korisnika + + + User login + Prijava korisnika + + + Input start delay + Odgoda pokretanja ulaza + + + Simulated key presses interval + Interval simultanih pritisaka tipki + + + Confirm legal notice (message displayed before user logs in) + Potvrdite pravnu napomenu (poruka se prikazuje pre nego što se korisnik prijavi) + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + + + + WindowsPlatformPlugin + + Plugin implementing abstract functions for the Windows platform + Plugin implementiranje apstraktnih funkcija za Windows platformu + + + Internal display + + + + + WindowsServiceControl + + The service "%1" is already installed. + Servis "%1" je već instaliran. + + + The service "%1" has been installed successfully. + Servis "%1" je instaliran uspešno. + + + The service "%1" has been uninstalled successfully. + Servis "%1" je deinstalisan uspešno. + + + Service "%1" could not be found. + Servis "%1" ne može biti pronađen. + + + The service "%1" could not be installed (error %2). + + + + Could not change the failure actions config for service "%1" (error %2). + + + + The service "%1" could not be uninstalled (error %2). + + + + The start type of service "%1" could not be changed (error %2). + + + + + X11VncConfigurationWidget + + Builtin x11vnc server configuration + Konfiguracija ugrađenog x11vnc servera + + + Custom x11vnc parameters: + Prilagođeni x11vnc parametri: + + + Do not use X Damage extension + Ne upotrebljavajte X Demage ekstenziju + + + \ No newline at end of file diff --git a/translations/veyon_sv.ts b/translations/veyon_sv.ts new file mode 100644 index 000000000..20bd511af --- /dev/null +++ b/translations/veyon_sv.ts @@ -0,0 +1,4901 @@ + + + AboutDialog + + About + Om + + + Translation + Översättning + + + License + Licens + + + About Veyon + Om Veyon + + + Contributors + Medarbetare + + + Version: + Version: + + + Website: + Webbsida: + + + Current language not translated yet (or native English). + +If you're interested in translating Veyon into your local or another language or want to improve an existing translation, please contact a Veyon developer! + Nuvarande språk ej översatt än (eller originalspråk Engelska). + +Om du är intresserad av att översätta Veyon till ditt lokala eller ett ett annat språk, vänligen kontakta en Veyon-utvecklare! + + + About %1 %2 + Om %1 %2 + + + Support Veyon project with a donation + Stöd Veyon-projektet med en donation + + + + AccessControlPage + + Computer access control + Datoråtkomstskontroll + + + Grant access to every authenticated user (default) + Bevilja åtkomst för alla autentiserade användare (standard) + + + Test + Testa + + + Process access control rules + Processåtkomstkontroll-regler + + + User groups authorized for computer access + Användargrupper auktoriserade för datoråtkomst + + + Please add the groups whose members should be authorized to access computers in your Veyon network. + Vänligen lägg till grupperna vilkas medlemmar ska vara auktoriserade för att komma åt datorer i ditt Veyon-nätverk. + + + Authorized user groups + Auktoriserade användargrupper + + + All groups + Alla grupper + + + Access control rules + Åtkomstregler + + + Add access control rule + Lägg till åtkomstregel + + + Remove access control rule + Ta bort åtkomstregel + + + Move selected rule down + Flytta vald regel nedåt + + + Move selected rule up + Flytta vald regel uppåt + + + Edit selected rule + Redigera vald regel + + + Enter username + Skriv in användarnamn + + + Please enter a user login name whose access permissions to test: + Vänligen skriv in ett användarnamn vars åtkomstbehörigheter ska testas: + + + Access allowed + Åtkomst beviljad + + + The specified user is allowed to access computers with this configuration. + Den specificerade användaren är tillåten att komma åt datorer med den här konfigurationen. + + + Access denied + Åtkomst nekad + + + The specified user is not allowed to access computers with this configuration. + Den specificerade användaren är inte tillåten att komma åt datorer med den här konfigurationen. + + + Enable usage of domain groups + Aktivera användandet av domängrupper + + + User groups backend: + Backend för användargrupper: + + + Restrict access to members of specific user groups + Begränsa åtkomsten till medlemmar i specifika användargrupper + + + + AccessControlProvider + + Provider for access control features + + + + + AccessControlRuleEditDialog + + Edit access control rule + Redigera åtkomstregel + + + General + Allmänt + + + enter a short name for the rule here + skriv in ett kort namn på regeln här + + + Rule name: + Regelnamn: + + + enter a description for the rule here + skriv in en beskrivning av regeln här + + + Rule description: + Regelbeskrivning: + + + Conditions + Villkor + + + If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. + Om fler än ett villkor aktiveras behöver varje villkor mötas för att regeln ska gälla (logiskt OCH). Om endast en av flera villkor behöver mötas (logiskt ELLER) vänligen skapa flera åtkomstregler. + + + Action + Åtgärd + + + Allow access + Bevilja åtkomst + + + Deny access + Neka åtkomst + + + Ask logged on user for permission + Fråga inloggad användare om tillstånd + + + None (rule disabled) + Inga (regel inaktiverad) + + + Accessing user + Åtkomstanvändare + + + Accessing computer + Åtkomstdator + + + Always process rule and ignore conditions + Bearbeta alltid regel- och ignoreringsvillkor + + + Accessing computer and local computer + Åtkomst till dator och lokal dator + + + User being accessed + Användare som nås + + + is logged in locally + är inloggad lokalt + + + is logged in remotely + är inloggad på distans + + + No user is logged in locally + Ingen användare är inloggad lokalt + + + One or multiple users are logged in locally + En eller flera användare är inloggade lokalt + + + No user is logged in remotely + Ingen användare är inloggad på distans + + + One or multiple users are logged in remotely + En eller flera användare är inloggade på distans + + + is located at + är belägen på + + + is not located at + är inte belägen på + + + are located at the same location + är belägna på samma plats + + + are not located the same location + inte är belägna på samma plats + + + is member of group + är medlem av gruppen + + + is not member of group + inte är medlem i gruppen + + + is authenticated via + är autentiserad via + + + is not authenticated via + inte är autentiserad via + + + has one or more groups in common with user being accessed + har en eller flera grupper gemensamt med användaren som får åtkomst + + + has no groups in common with user being accessed + har inga grupper gemensamt med användaren som nås + + + equals user being accessed + är lika med användaren som nås + + + is different from user being accessed + är annorlunda än den användare som nås + + + is already connected + är redan ansluten + + + is not connected + är inte ansluten + + + is local computer + är lokal dator + + + is not local computer + är inte lokal dator + + + Computer being accessed + Åtkomst till datorn + + + Session being accessed is a user session + Sessionen som öppnas är en användarsession + + + Session being accessed is a login screen + Sessionen som öppnas är en inloggningsskärm + + + Local computer is already being accessed + Den lokala datorn är redan tillgänglig + + + Local computer is not yet being accessed + Den lokala datorn är ännu inte åtkomlig + + + + AccessControlRulesTestDialog + + Access control rules test + Åtkomstregel-test + + + Accessing user: + Tillgång till användare: + + + Local computer: + Lokal dator: + + + Accessing computer: + Åtkomst till dator: + + + Please enter the following user and computer information in order to test the configured ruleset. + Ange följande användar- och datorinformation för att testa den konfigurerade regeluppsättningen. + + + Local user: + Lokal användare: + + + Connected users: + Anslutna användare: + + + The access in the given scenario is allowed. + Åtkomsten i det givna scenariot är tillåten. + + + The access in the given scenario is denied. + Tillträde i det givna scenariot nekas. + + + The access in the given scenario needs permission of the logged on user. + Åtkomsten i det givna scenariot kräver tillstånd från den inloggade användaren. + + + Test result + Testresultat + + + Authentication method + Autentiseringsmetod + + + There is no matching rule with a valid action. The access is therefore denied. + + + + + AuthKeysConfigurationWidget + + Introduction + Introduktion + + + Please perform the following steps to set up key file authentication: + Utför följande steg för att konfigurera autentisering av nyckelfiler: + + + 1) Create a key pair on the master computer. + 1) Skapa ett nyckelpar på huvuddatorn. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Ange en åtkomstgrupp vars medlemmar ska ha åtkomst till andra datorer. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Exportera den publika nyckeln och importera den på alla klientdatorer med samma namn. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Mer information finns i <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyons administratörshandbok</a>. + + + Key file directories + Kataloger med nyckelfiler + + + Public key file base directory + Baskatalog för fil med offentlig nyckel + + + Private key file base directory + Baskatalog för fil med privat nyckel + + + Available authentication keys + Tillgängliga autentiseringsnycklar + + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Ett nyckelpar för autentisering består av två kopplade kryptografiska nycklar, en privat och en offentlig nyckel. +En privat nyckel ger användare på huvuddatorn åtkomst till klientdatorer. +Det är viktigt att endast behöriga användare har läsbehörighet till den privata nyckelfilen. +Den publika nyckeln används på klientdatorer för att autentisera inkommande anslutningsbegäran. + + + Create key pair + Skapa nyckelpar + + + Delete key + Radera tangent + + + Import key + Importera nyckel + + + Export key + Exportknapp + + + Set access group + Ställ in åtkomstgrupp + + + Key files (*.pem) + Nyckelfiler (*.pem) + + + Authentication key name + Namn på autentiseringsnyckel + + + Please enter the name of the user group or role for which to create an authentication key pair: + Ange namnet på den användargrupp eller roll för vilken du vill skapa ett nyckelpar för autentisering: + + + Do you really want to delete authentication key "%1/%2"? + Vill du verkligen ta bort autentiseringsnyckeln "%1/%2"? + + + Please select a key to delete! + Välj en nyckel som ska raderas! + + + Please select a key to export! + Vänligen välj en nyckel för export! + + + Please select a user group which to grant access to key "%1": + Välj en användargrupp som ska få tillgång till nyckeln "%1": + + + Please select a key which to set the access group for! + Välj en nyckel som du vill ställa in åtkomstgruppen för! + + + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + Ange namnet på den användargrupp eller roll som autentiseringsnyckeln ska importeras för. + +Se till att namnen på de nycklar som tillhör varandra är identiska på alla datorer. + + + + AuthKeysManager + + Please check your permissions. + Vänligen kontrollera dina behörigheter. + + + Key name contains invalid characters! + Nyckelns namn innehåller ogiltiga tecken! + + + Invalid key type specified! Please specify "%1" or "%2". + Ogiltig nyckeltyp angiven! Vänligen ange "%1" eller "%2". + + + Specified key does not exist! Please use the "list" command to list all installed keys. + Angiven nyckel finns inte! Använd kommandot "list" för att lista alla installerade nycklar. + + + One or more key files already exist! Please delete them using the "delete" command. + En eller flera nyckelfiler finns redan! Ta bort dem med hjälp av kommandot "delete". + + + Creating new key pair for "%1" + Skapar nytt nyckelpar för "%1" + + + Failed to create public or private key! + Misslyckades med att skapa offentlig eller privat nyckel! + + + Newly created key pair has been saved to "%1" and "%2". + Det nyskapade nyckelparet har sparats till "%1" och "%2". + + + Could not remove key file "%1"! + Det gick inte att ta bort nyckelfilen "%1"! + + + Could not remove key file directory "%1"! + Det gick inte att ta bort nyckelfilskatalogen "%1"! + + + Failed to create directory for output file. + Misslyckades med att skapa katalog för utdatafil. + + + File "%1" already exists. + Filen "%1" finns redan. + + + Failed to write output file. + Misslyckades med att skriva utdatafilen. + + + Key "%1/%2" has been exported to "%3" successfully. + Nyckel "%1/%2" har exporterats till "%3" framgångsrikt. + + + Failed read input file. + Misslyckades med att läsa inmatningsfilen. + + + File "%1" does not contain a valid private key! + Filen "%1" innehåller inte en giltig privat nyckel! + + + File "%1" does not contain a valid public key! + Filen "%1" innehåller inte en giltig offentlig nyckel! + + + Failed to create directory for key file. + Misslyckades med att skapa katalog för nyckelfilen. + + + Failed to write key file "%1". + Misslyckades med att skriva nyckelfilen "%1". + + + Failed to set permissions for key file "%1"! + Misslyckades med att ange behörigheter för nyckelfilen "%1"! + + + Key "%1/%2" has been imported successfully. Please check file permissions of "%3" in order to prevent unauthorized accesses. + Nyckel "%1/%2" har importerats framgångsrikt. Kontrollera filbehörigheterna för "%3" för att förhindra obehörig åtkomst. + + + Failed to convert private key to public key + Misslyckades med att konvertera privat nyckel till offentlig nyckel + + + Failed to create directory for private key file "%1". + Det gick inte att skapa en katalog för den privata nyckelfilen "%1". + + + Failed to save private key in file "%1"! + Misslyckades med att spara privat nyckel i filen "%1"! + + + Failed to set permissions for private key file "%1"! + Misslyckades med att ange behörigheter för privat nyckelfil "%1"! + + + Failed to create directory for public key file "%1". + Det gick inte att skapa en katalog för den offentliga nyckelfilen "%1". + + + Failed to save public key in file "%1"! + Misslyckades med att spara offentlig nyckel i filen "%1"! + + + Failed to set permissions for public key file "%1"! + Misslyckades med att ange behörigheter för den offentliga nyckelfilen "%1"! + + + Failed to set owner of key file "%1" to "%2". + Misslyckades med att ange ägare för nyckelfilen "%1" till "%2". + + + Failed to set permissions for key file "%1". + Misslyckades med att ange behörigheter för nyckelfilen "%1". + + + Key "%1" is now accessible by user group "%2". + Nyckel "%1" är nu tillgänglig för användargrupp "%2". + + + <N/A> + <N/A> + + + Failed to read key file. + Misslyckades med att läsa nyckelfilen. + + + + AuthKeysPlugin + + Create new authentication key pair + Skapa ett nytt nyckelpar för autentisering + + + Delete authentication key + Ta bort autentiseringsnyckel + + + List authentication keys + Lista autentiseringsnycklar + + + Import public or private key + Importera offentlig eller privat nyckel + + + Export public or private key + Exportera offentlig eller privat nyckel + + + Extract public key from existing private key + Extrahera offentlig nyckel från befintlig privat nyckel + + + Set user group allowed to access a key + Ange vilken användargrupp som ska ha åtkomst till en nyckel + + + KEY + Nyckel + + + ACCESS GROUP + TILLGÅNGSGRUPP + + + This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. + Detta kommando justerar filåtkomstbehörigheterna för <KEY> så att endast användargruppen <ACCESS GROUP> har läsåtkomst till den. + + + NAME + NAMN + + + FILE + ORDER + + + This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. + Detta kommando exporterar autentiseringsnyckeln <KEY> till <FILE>. Om <FILE> inte anges kommer ett namn att konstrueras utifrån namn och typ för <KEY>. + + + This command imports the authentication key <KEY> from <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. + Detta kommando importerar autentiseringsnyckeln <KEY> från <FILE>. Om <FILE> inte anges kommer ett namn att konstrueras utifrån namn och typ i <KEY>. + + + This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. + Detta kommando listar alla tillgängliga autentiseringsnycklar i den konfigurerade nyckelkatalogen. Om alternativet "%1" anges visas i stället en tabell med nyckelinformation. Vissa detaljer kan saknas om en nyckel inte är tillgänglig, t.ex. på grund av att läsbehörighet saknas. + + + TYPE + TYP + + + PAIR ID + PAIR ID + + + Commands for managing authentication keys + Kommandon för hantering av autentiseringsnycklar + + + This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. + Det här kommandot skapar ett nytt nyckelpar för autentisering med namnet <NAME> och sparar den privata och offentliga nyckeln i de konfigurerade nyckelkatalogerna. Parametern måste vara ett namn för nyckeln, som endast får innehålla bokstäver. + + + This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. + Detta kommando raderar autentiseringsnyckeln <KEY> från den konfigurerade nyckelkatalogen. Observera att en nyckel inte kan återställas när den har tagits bort. + + + This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + Detta kommando extraherar den offentliga nyckeldelen från den privata nyckeln <KEY> och sparar den som motsvarande offentliga nyckel. När du installerar en annan huvuddator räcker det därför med att endast överföra den privata nyckeln. Den publika nyckeln kan sedan extraheras. + + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + Autentiseringsnyckelfiler är inte korrekt inställda på den här datorn. Skapa nya nyckelfiler eller byt till en annan autentiseringsmetod med hjälp av Veyon Configurator. + + + Key file authentication + Autentisering av nyckelfiler + + + Key file + Nyckelfil + + + Please specify the key name (e.g. "teacher/public") as the first argument. + Ange nyckelns namn (t.ex. "teacher/public") som första argument. + + + Please specify the command to display help for. + Ange det kommando som du vill visa hjälp för. + + + The specified command does not exist or no help is available for it. + Det angivna kommandot finns inte eller så finns det ingen hjälp tillgänglig för det. + + + + AuthKeysTableModel + + Name + Namn + + + Type + Typ + + + Access group + Behörighetsgrupp + + + Pair ID + Par-ID + + + + AuthLdapConfigurationWidget + + General + Allmänt + + + Username to bind DN mapping: + Användarnamn för att binda DN-mappning: + + + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + t.ex. %username%@DOMAIN eller cn=%username%,ou=users,dc=example,dc=org + + + + AuthLdapDialog + + Veyon Logon + Veyon inloggning + + + Please enter your domain/LDAP username and password in order to access computers. + Ange ditt domän/LDAP-användarnamn och lösenord för att få tillgång till datorer. + + + Username + Användarnamn + + + Password + Lösenord + + + Authentication error + Autentiseringsfel + + + Logon failed with given username and password. Please try again! + Inloggning misslyckades med angivet användarnamn och lösenord. Vänligen försök igen! + + + + AuthLogonDialog + + Veyon Logon + Veyon inloggning + + + Please enter your username and password in order to access computers. + Ange ditt användarnamn och lösenord för att få tillgång till datorerna. + + + Username + Användarnamn + + + Password + Lösenord + + + Authentication error + Autentiseringsfel + + + Logon failed with given username and password. Please try again! + Inloggning misslyckades med angivet användarnamn och lösenord. Vänligen försök igen! + + + + AuthLogonPlugin + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Det angivna användarnamnet eller lösenordet är fel. Ange giltiga inloggningsuppgifter eller byt till en annan autentiseringsmetod med Veyon Configurator. + + + Logon authentication + Autentisering av inloggning + + + Logon + Logga in + + + + AuthSimpleDialog + + Veyon Logon + Veyon inloggning + + + Please enter the Veyon password: + Vänligen ange lösenordet för Veyon: + + + Authentication error + Autentiseringsfel + + + Logon failed with given password. Please try again! + Inloggning misslyckades med angivet lösenord. Vänligen försök igen! + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + Det angivna lösenordet är fel. Ange rätt lösenord eller byt till en annan autentiseringsmetod med hjälp av Veyon Configurator. + + + Simple password authentication + Enkel autentisering med lösenord + + + Simple password + Enkelt lösenord + + + + AuthenticationPage + + Authentication is set up properly on this computer. + Autentiseringen är korrekt inställd på den här datorn. + + + + AuthenticationPageTab + + Enabled + Aktiverad + + + Test + Testa + + + + BuiltinDirectoryConfiguration + + Builtin directory + Inbyggd katalog + + + + BuiltinDirectoryConfigurationPage + + Computers + Datorer + + + Name + Namn + + + Host address/IP + Värdadress/IP + + + MAC address + MAC-adress + + + Add new computer + Lägg till ny dator + + + Remove selected computer + Ta bort vald dator + + + New computer + Ny dator + + + Builtin directory + Inbyggd katalog + + + Locations + Platser + + + Add new location + Skapa ny plats + + + Remove selected location + Ta bort vald plats + + + New location + Ny plats + + + Directory name + Namn på katalog + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + Import av CSV-filer är möjlig via kommandoradsgränssnittet. Mer information finns i <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">onlinedokumentationen</a>. + + + + BuiltinDirectoryPlugin + + Show help for specific command + Visa hjälp för ett specifikt kommando + + + Import objects from given file + Importera objekt från en given fil + + + Export objects to given file + Exportera objekt till en given fil + + + Invalid type specified. Valid values are "%1" or "%2". + Ogiltig typ angiven. Giltiga värden är "%1" eller "%2". + + + Type + Typ + + + Name + Namn + + + Host address + Värdadress + + + MAC address + MAC-adress + + + Specified object not found. + Angivet objekt hittades inte. + + + File "%1" does not exist! + Filen "%1" finns inte! + + + Can't open file "%1" for reading! + Kan inte öppna filen "%1" för läsning! + + + Unknown argument "%1". + Okänt argument "%1". + + + Computer "%1" (host address: "%2" MAC address: "%3") + Dator "%1" (värdadress: "%2" MAC-adress: "%3") + + + Unclassified object "%1" with ID "%2" + Oklassificerat objekt "%1" med ID "%2" + + + None + Ingen + + + Computer + Dator + + + Root + Rot + + + Invalid + Ogiltig + + + Error while parsing line %1. + Fel vid parsning av rad %1. + + + Network object directory which stores objects in local configuration + Nätverksobjektkatalog som lagrar objekt i lokal konfiguration + + + Commands for managing the builtin network object directory + Kommandon för att hantera den inbyggda katalogen för nätverksobjekt + + + No format string or regular expression specified! + Ingen formatsträng eller reguljärt uttryck har angetts! + + + Can't open file "%1" for writing! + Kan inte öppna filen "%1" för skrivning! + + + No format string specified! + Ingen formatsträng specificerad! + + + Object UUID + Objektets UUID + + + Parent UUID + Förälder UUID + + + Add a location or computer + Lägg till en plats eller dator + + + Clear all locations and computers + Rensa alla platser och datorer + + + Dump all or individual locations and computers + Dumpa alla eller enskilda platser och datorer + + + List all locations and computers + Lista alla platser och datorer + + + Remove a location or computer + Ta bort en plats eller dator + + + Location "%1" + Plats "%1" + + + Builtin (computers and locations in local configuration) + Inbyggd (datorer och platser i lokal konfiguration) + + + Location + Plats + + + FILE + ORDER + + + LOCATION + PLATS + + + FORMAT-STRING-WITH-PLACEHOLDERS + FORMAT-STRÄNG-MED-PLATSHÅLLARE + + + REGULAR-EXPRESSION-WITH-PLACEHOLDER + REGULJÄRT UTTRYCK-MED-PLATSHÅLLARE + + + Imports objects from the specified text file using the given format string or regular expression containing one or multiple placeholders. Valid placeholders are: %1 + Importerar objekt från den angivna textfilen med hjälp av den angivna formatsträngen eller det reguljära uttrycket som innehåller en eller flera platshållare. Giltiga platshållare är: %1 + + + Import simple CSV file to a single room + Importera enkel CSV-fil till ett enda rum + + + Import CSV file with location name in first column + Importera CSV-fil med platsnamn i första kolumnen + + + Import text file with with key/value pairs using regular expressions + Importera textfil med nyckel/värde-par med hjälp av reguljära uttryck + + + Import arbitrarily formatted data + Importera godtyckligt formaterad data + + + Exports objects to the specified text file using the given format string containing one or multiple placeholders. Valid placeholders are: %1 + Exporterar objekt till den angivna textfilen med hjälp av den angivna formatsträngen som innehåller en eller flera platshållare. Giltiga platshållare är: %1 + + + Export all objects to a CSV file + Exportera alla objekt till en CSV-fil + + + Export all computers in a specific location to a CSV file + Exportera alla datorer på en viss plats till en CSV-fil + + + TYPE + TYP + + + NAME + NAMN + + + PARENT + FÖRÄLDRAR + + + Adds an object where %1 can be one of "%2" or "%3". %4 can be specified by name or UUID. + Lägger till ett objekt där %1 ckan vara en av "%2" eller "%3". %4 ckan specificeras med namn eller UUID. + + + Add a room + Lägg till ett rum + + + Add a computer to room %1 + Lägg till en dator i rum %1 + + + OBJECT + OBJECT + + + Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. + Tar bort det angivna objektet från katalogen. %1 c kan anges med namn eller UUID. Om du tar bort en plats tas även alla relaterade datorer bort. + + + Remove a computer by name + Ta bort en dator med namn + + + Remove an object by UUID + Ta bort ett objekt med UUID + + + "Room 01" + "Rum 01" + + + "Computer 01" + "Dator 01" + + + HOST ADDRESS + VÄRDENS ADRESS + + + MAC ADDRESS + MAC-ADRESS + + + The specified command does not exist or no help is available for it. + Det angivna kommandot finns inte eller så finns det ingen hjälp tillgänglig för det. + + + Location "%1" not found. + Platsen "%1" hittades inte. + + + + BuiltinUltraVncServer + + Builtin VNC server (UltraVNC) + Inbyggd VNC-server (UltraVNC) + + + + BuiltinX11VncServer + + Builtin VNC server (x11vnc) + Inbyggd VNC-server (x11vnc) + + + + ComputerControlListModel + + Active features: %1 + Aktiva funktioner: %1 + + + Online and connected + Online och uppkopplad + + + Establishing connection + Upprättande av anslutning + + + Computer offline or switched off + Dator offline eller avstängd + + + Authentication failed or access denied + Autentiseringen misslyckades eller åtkomst nekades + + + Disconnected + Urkopplad + + + No user logged on + Ingen användare inloggad + + + Logged on user: %1 + Inloggad användare: %1 + + + Location: %1 + Plats: %1 + + + [no user] + [ingen användare] + + + Veyon Server unreachable or not running + Veyon Server går inte att nå eller körs inte + + + Name: %1 + Namn: %1 + + + Hostname: %1 + + + + unknown + okänd + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + + + + ComputerControlServer + + %1 Service %2 at %3:%4 + %1 Service %2 vid %3:%4 + + + Authentication error + Autentiseringsfel + + + Remote access + Fjärråtkomst + + + User "%1" at host "%2" is now accessing this computer. + Användaren "%1" på värden "%2" har nu tillgång till den här datorn. + + + User "%1" at host "%2" attempted to access this computer but could not authenticate successfully. + Användaren "%1" på värden "%2" försökte komma åt den här datorn men kunde inte autentisera sig. + + + Access control error + Fel i åtkomstkontroll + + + User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + Användaren "%1" på värden "%2" försökte komma åt den här datorn men blockerades på grund av inställningar för åtkomstkontroll. + + + Active connections: + Aktiva anslutningar: + + + + ComputerGroupSelector + + Group %1 + Grupp %1 + + + + ComputerManager + + User + Användare + + + Missing network object directory plugin + Saknar plugin för nätverksobjektkatalog + + + No default network object directory plugin was found. Please check your installation or configure a different network object directory backend via %1 Configurator. + Inget standardinsticksprogram för nätverksobjektkatalog hittades. Kontrollera din installation eller konfigurera en annan backend för nätverksobjektkatalog via %1 Configurator. + + + Location detection failed + Platsdetektering misslyckades + + + Computer name;Hostname;User + Datornamn;Värdnamn;Användare + + + Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + Det gick inte att fastställa platsen för den här datorn. Detta indikerar ett problem med systemkonfigurationen. Alla platser visas i stället i panelen för val av dator. + + + Logged in since + Inloggad sedan + + + %1 days + %1 days + + + 1 day + 1 dag + + + + ComputerMonitoring + + Computers + Datorer + + + Search users and computers + Sök användare och datorer + + + Select all + Markera allt + + + Unselect all + Avmarkera alla + + + Add to group + Lägg till i grupp + + + Remove from group + Ta bort från grupp + + + + ComputerSelectPanel + + Computer search + Sökning i dator + + + Add location + Lägg till plats + + + Save computer/user list + Spara dator/användarlista + + + Select output filename + Välj filnamn för utdata + + + CSV files (*.csv) + CSV-filer (*.csv) + + + File error + Fel i filen + + + Could not write the computer and users list to %1! Please check the file access permissions. + Det gick inte att skriva dator- och användarlistan till %1! Kontrollera filåtkomstbehörigheterna. + + + Search computers + Sök datorer + + + + ConfigCommands + + Clear system-wide Veyon configuration + Rensa systemomfattande Veyon-konfiguration + + + List all configuration keys and values + Lista alla konfigurationsnycklar och värden + + + Import configuration from given file + Importera konfiguration från given fil + + + Export configuration to given file + Exportera konfiguration till angiven fil + + + Read and output configuration value for given key + Läser och matar ut konfigurationsvärde för given nyckel + + + Write given value to given configuration key + Skriv ett givet värde till en given konfigurationsnyckel + + + Unset (remove) given configuration key + Ta bort (unset) en given konfigurationsnyckel + + + Upgrade and save configuration of program and plugins + Uppgradera och spara konfiguration av program och plugins + + + Please specify an existing configuration file to import. + Ange en befintlig konfigurationsfil som ska importeras. + + + Configuration file is not readable! + Konfigurationsfilen är inte läsbar! + + + Please specify a valid filename for the configuration export. + Ange ett giltigt filnamn för konfigurationsexporten. + + + Output file is not writable! + Utdatafilen är inte skrivbar! + + + Output directory is not writable! + Utdatakatalogen är inte skrivbar! + + + Please specify a valid key. + Vänligen ange en giltig nyckel. + + + Specified key does not exist in current configuration! + Angiven nyckel finns inte i aktuell konfiguration! + + + Please specify a valid value. + Vänligen ange ett giltigt värde. + + + Configure Veyon at command line + Konfigurera Veyon på kommandoraden + + + Commands for managing the configuration of Veyon + Kommandon för att hantera konfigurationen av Veyon + + + + ConfigurationManager + + Could not modify the autostart property for the %1 Service. + Det gick inte att ändra egenskapen autostart för tjänsten %1. + + + Could not configure the firewall configuration for the %1 Server. + Det gick inte att konfigurera brandväggskonfigurationen för servern %1. + + + Could not configure the firewall configuration for the %1 Worker. + Det gick inte att konfigurera brandväggskonfigurationen för %1 Worker. + + + Configuration is not writable. Please check your permissions! + Konfigurationen är inte skrivbar. Vänligen kontrollera dina behörigheter! + + + Could not apply platform-specific configuration settings. + Det gick inte att tillämpa plattformsspecifika konfigurationsinställningar. + + + Could not configure the firewall configuration for the %1 Service. + Det gick inte att konfigurera brandväggskonfigurationen för tjänsten %1. + + + + DemoClient + + %1 Demo + %1 Demo + + + + DemoConfigurationPage + + Demo server + Demoserver + + + Tunables + Avstämbara instrument + + + ms + ms + + + Key frame interval + Intervall för nyckelram + + + Memory limit + Minnesgräns + + + MB + MB + + + Update interval + Uppdateringsintervall + + + s + s + + + Slow down thumbnail updates while demo is running + Långsammare uppdatering av miniatyrbilder när demo körs + + + Bandwidth limit + Begränsning av bandbredd + + + MB/s + MB/s + + + + DemoFeaturePlugin + + Stop demo + Stoppa demo + + + Window demo + Demo i fönster + + + Give a demonstration by screen broadcasting + Ge en demonstration genom skärmutsändning + + + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + I det här läget visas din skärm i ett fönster på alla datorer. Användarna kan växla till andra fönster efter behov. + + + Demo + Demo + + + Share your screen or allow a user to share his screen with other users. + Dela din skärm eller låt en användare dela sin skärm med andra användare. + + + Full screen demo + Demo i fullskärm + + + Share your own screen in fullscreen mode + Dela din egen skärm i helskärmsläge + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + I det här läget visas din skärm i helskärmsläge på alla datorer medan användarnas inmatningsenheter är låsta. + + + Share your own screen in a window + Dela din egen skärm i ett fönster + + + Share selected user's screen in fullscreen mode + Dela den valda användarens skärm i helskärmsläge + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + I detta läge visas skärmen för den valda användaren i helskärmsläge på alla datorer medan användarnas inmatningsenheter är låsta. + + + Share selected user's screen in a window + Dela den valda användarens skärm i ett fönster + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + I det här läget visas skärmen för den valda användaren i ett fönster på alla datorer. Användarna kan växla till andra fönster efter behov. + + + Please select a user screen to share. + Välj en användarskärm som du vill dela med dig av. + + + Please select only one user screen to share. + Välj bara en användarskärm att dela med dig av. + + + All screens + Alla skärmar + + + + DesktopAccessDialog + + Desktop access dialog + Dialog för åtkomst till skrivbord + + + Confirm desktop access + Bekräfta åtkomst till skrivbordet + + + Never for this session + Aldrig för denna session + + + Always for this session + Alltid för denna session + + + The user %1 at computer %2 wants to access your desktop. Do you want to grant access? + Användaren %1 på datorn %2 vill komma åt ditt skrivbord. Vill du bevilja åtkomst? + + + + DesktopServicesConfigurationPage + + Name + Namn + + + Path + Sökväg + + + Predefined websites + Fördefinierade webbplatser + + + Remove selected website + Ta bort vald webbplats + + + URL + URL + + + New website + Ny webbplats + + + Applications & websites + Applikationer & webbplatser + + + Predefined applications + Fördefinierade applikationer + + + Add new application + Lägg till ny applikation + + + Remove selected application + Ta bort vald applikation + + + Add new website + Lägg till ny webbplats + + + New application + Ny application + + + + DesktopServicesFeaturePlugin + + Open website + Öppna webbplats + + + Click this button to open a website on all computers. + Klicka på den här knappen för att öppna en webbplats på alla datorer. + + + Open website "%1" + Öppna webbplatsen "%1" + + + Custom website + Anpassad webbplats + + + Start application + Starta ansökan + + + Click this button to start an application on all computers. + Klicka på den här knappen för att starta ett program på alla datorer. + + + Start application "%1" + Starta applikationen "%1" + + + Custom application + Anpassad applikation + + + Start apps and open websites in user sessions + Starta appar och öppna webbplatser i användarsessioner + + + + DocumentationFigureCreator + + Teacher + Lärare + + + Room %1 + Rum %1 + + + Please complete all tasks within the next 5 minutes. + Vänligen slutför alla uppgifter inom de närmaste 5 minuterna. + + + Custom website + Anpassad webbplats + + + Open file manager + Öppna filhanteraren + + + Start learning tool + Starta inlärningsverktyget + + + Play tutorial video + Spela upp instruktionsvideo + + + Handout + Handout + + + Texts to read + Texter att läsa + + + generic-student-user + generisk-student-användare + + + Custom application + Anpassad applikation + + + + ExternalVncServer + + External VNC server + Extern VNC-server + + + + ExternalVncServerConfigurationWidget + + External VNC server configuration + Konfiguration av extern VNC-server + + + Port: + Hamn: + + + Password: + Lösenord: + + + + FeatureCommands + + List names of all available features + Lista namn på alla tillgängliga funktioner + + + Show table with details of all available features + Visa tabell med detaljer om alla tillgängliga funktioner + + + Start a feature on a remote host + Starta en funktion på en avlägsen värd + + + Stop a feature on a remote host + Stoppa en funktion på en fjärrvärd + + + Please specify the command to display help for. + Ange det kommando som du vill visa hjälp för. + + + Displays a list with the names of all available features. + Visar en lista med namnen på alla tillgängliga funktioner. + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + Visar en tabell med detaljerad information om alla tillgängliga funktioner. Informationen omfattar en beskrivning, UID, namnet på det plugin som tillhandahåller respektive funktion och vissa andra implementeringsrelaterade detaljer. + + + HOST ADDRESS + VÄRDENS ADRESS + + + FEATURE + Funktion + + + ARGUMENTS + Aktivera extra videoargument + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + Startar den angivna funktionen på den angivna värden genom att ansluta till Veyon Server som körs på distans. Funktionen kan anges med namn eller UID. Använd kommandot ``show`` för att se alla tillgängliga funktioner. Beroende på funktionen måste ytterligare argument (t.ex. textmeddelandet som ska visas) kodade som en enda JSON-sträng anges. Se utvecklarens dokumentation för mer information + + + Lock the screen + Lås skärmen + + + Display a text message + Visa ett textmeddelande + + + Test message + Test meddelande + + + Start an application + Starta en ansökan + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + Stoppar den angivna funktionen på den angivna värden genom att ansluta till Veyon-servern som körs på distans. Funktionen kan anges med namn eller UID. Använd kommandot ``show`` för att se alla tillgängliga funktioner. + + + Unlock the screen + Lås upp skärmen + + + The specified command does not exist or no help is available for it. + Det angivna kommandot finns inte eller så finns det ingen hjälp tillgänglig för det. + + + Name + Namn + + + Description + Beskrivning + + + Master + Säkerhetsansvarig + + + Service + Tjänst + + + Worker + Vägledare + + + UID + UID + + + Plugin + Tillägg + + + Invalid feature name or UID specified + Ogiltigt funktionsnamn eller UID angivet + + + Error parsing the JSON-encoded arguments: %1 + Fel vid analys av JSON-kodade argument: %1 + + + Failed to initialize credentials + Initialisering av autentiseringsuppgifter misslyckades + + + Could not establish a connection to host %1 + Det gick inte att upprätta en anslutning till värden %1 + + + Failed to send feature control message to host %1 + Misslyckades med att skicka feature control-meddelande till host %1 + + + Feature-related CLI operations + Funktionsrelaterade CLI-åtgärder + + + Commands for controlling features + Kommandon för styrning av funktioner + + + + FileTransferConfigurationPage + + File transfer + Filöverföring + + + Directories + Kataloger + + + Destination directory + Destinationskatalog + + + Default source directory + Standard källkatalog + + + Options + Alternativ + + + Remember last source directory + Kom ihåg den senaste källkatalogen + + + Create destination directory if it does not exist + Skapa destinationskatalog om den inte finns + + + + FileTransferController + + Could not open file "%1" for reading! Please check your permissions! + Filen "%1" kunde inte öppnas för läsning! Vänligen kontrollera dina behörigheter! + + + + FileTransferDialog + + File transfer + Filöverföring + + + Options + Alternativ + + + Transfer only + Endast överföring + + + Transfer and open file(s) with associated program + Överför och öppna fil(er) med tillhörande program + + + Transfer and open destination folder + Överför och öppna målmappen + + + Files + Filer + + + Start + Starta + + + Overwrite existing files + Skriv över befintliga filer + + + + FileTransferFileDialog + + Select one or more files to transfer + Välj en eller flera filer som ska överföras + + + + FileTransferPlugin + + File transfer + Filöverföring + + + Click this button to transfer files from your computer to all computers. + Klicka på den här knappen för att överföra filer från din dator till alla datorer. + + + Select one or more files to transfer + Välj en eller flera filer som ska överföras + + + Transfer files to remote computer + Överför filer till fjärrdatorn + + + Received file "%1". + Mottagen fil "%1". + + + Could not receive file "%1" as it already exists. + Kunde inte ta emot filen "%1" eftersom den redan finns. + + + Could not receive file "%1" as it could not be opened for writing! + Kunde inte ta emot filen "%1" eftersom den inte kunde öppnas för skrivning! + + + + GeneralConfigurationPage + + User interface + Användargränssnitt + + + Language: + Språk: + + + Use system language setting + Använd systemets språkinställning + + + Veyon + Veyon + + + Logging + Loggning + + + Log file directory + Loggfilskatalog + + + Log level + Loggnivå + + + Nothing + Ingenting + + + Only critical messages + Endast kritiska meddelanden + + + Errors and critical messages + Fel och kritiska meddelanden + + + Warnings and errors + Varningar och fel + + + Information, warnings and errors + Information, varningar och fel + + + Debug messages and everything else + Felsökningsmeddelanden och allting annat + + + Limit log file size + Begränsa storlek på loggfil + + + Clear all log files + Töm alla loggfiler + + + Log to standard error output + Logga till standardfelutmatning + + + %1 service + %1 tjänst + + + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + %1 service måste stoppas tillfälligt för att ta bort loggfilerna. Fortsätter du? + + + Log files cleared + Loggfiler rensade + + + All log files were cleared successfully. + Alla loggfiler rensades framgångsrikt. + + + Error + Fel + + + Could not remove all log files. + Det gick inte att ta bort alla loggfiler. + + + MB + MB + + + Rotate log files + Rotera loggfiler + + + x + bredd + + + Write to logging system of operating system + Skriv till operativsystemets loggningssystem + + + TLS configuration + TLS-konfiguration + + + Use certificate authority for TLS connections + Använd certifikatutfärdare för TLS-anslutningar + + + CA certificate file + CA-certifikatfil + + + ... + ... + + + Host certificate file + Värdcertifikatfil + + + Host private key file + Värdens privata nyckelfil + + + Style: + Stil: + + + Native + Inbyggd + + + Color scheme: + + + + Light + + + + Dark + + + + User groups + Användargrupper + + + Backend: + Bakände: + + + Include user groups from domain + Inkludera användargrupper från domänen + + + Missing user groups backend + Saknad backend för användargrupper + + + No user groups plugin was found. Please check your installation! + Inget plugin för användargrupper hittades. Vänligen kontrollera din installation! + + + + HeadlessVncServer + + Headless VNC server + Huvudlös VNC-server + + + + LdapBrowseDialog + + Browse LDAP + Bläddra i LDAP + + + + LdapClient + + LDAP error description: %1 + Beskrivning av LDAP-fel: %1 + + + + LdapConfiguration + + LDAP connection failed + LDAP-anslutningen misslyckades + + + Could not connect to the LDAP server. Please check the server parameters. + +%1 + Det gick inte att ansluta till LDAP-servern. Kontrollera serverns parametrar. + +%1 + + + LDAP bind failed + LDAP-bindning misslyckades + + + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + Det gick inte att binda till LDAP-servern. Kontrollera serverparametrarna och bindningsuppgifterna. + +%1 + + + LDAP bind successful + LDAP bindning framgångsrik + + + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Anslöt till LDAP-servern och utförde en LDAP-bindning. De grundläggande LDAP-inställningarna är korrekt konfigurerade. + + + LDAP base DN test failed + Test av LDAP-bas-DN misslyckades + + + Could not query the configured base DN. Please check the base DN parameter. + +%1 + Det gick inte att fråga efter det konfigurerade bas-DN:et. Kontrollera parametern för bas-DN. + +%1 + + + LDAP base DN test successful + Test av LDAP-bas-DN framgångsrikt + + + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + LDAP-bas-DN:n har sökts framgångsrikt. Följande poster hittades: + +%1 + + + LDAP naming context test failed + Test av LDAP-namngivningskontext misslyckades + + + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + Det gick inte att fråga efter bas-DN via namngivningskontexter. Kontrollera parametern för attribut för namngivningskontext. + +%1 + + + LDAP naming context test successful + Test av LDAP-namngivningskontext framgångsrikt + + + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + LDAP-namngivningskontexten har sökts framgångsrikt. Följande bas-DN hittades: +%1 + + + user tree + användarträd + + + User tree + Användarträd + + + group tree + gruppträd + + + Group tree + Gruppträd + + + computer tree + datorträd + + + Computer tree + Dator träd + + + computer group tree + datorgrupp träd + + + Computer group tree + Dator grupp träd + + + user objects + användarobjekt + + + User login name attribute + Attribut för användarens inloggningsnamn + + + group members + gruppmedlemmar + + + Group member attribute + Attribut för gruppmedlem + + + Group not found + Gruppen hittades inte + + + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Det gick inte att hitta en grupp med namnet "%1". Kontrollera gruppnamnet eller parametern för gruppträdet. + + + computer objects + datorobjekt + + + Computer display name attribute + Attribut för datorns visningsnamn + + + Invalid hostname + Ogiltigt värdnamn + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Du konfigurerade datorns värdnamn så att de lagras som fullständigt kvalificerade domännamn (FQDN) men angav ett värdnamn utan domän. + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Du konfigurerade datorns värdnamn så att de lagras som enkla värdnamn utan domännamn, men angav ett värdnamn med en domännamnsdel. + + + Computer hostname attribute + Attribut för datorns värdnamn + + + computer MAC addresses + mAC-adresser till datorer + + + Computer MAC address attribute + MAC-adressattribut för dator + + + computer locations + datorplatser + + + Computer location attribute + Attribut för datorplats + + + Location name attribute + Attribut för platsnamn + + + users + användare + + + user groups + användargrupper + + + computers + datorer + + + computer groups + datorgrupper + + + computer containers + datorbehållare + + + groups of user + grupper av användare + + + User not found + Användare kunde inte hittas + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + Det gick inte att hitta en användare med namnet "%1". Kontrollera användarnamnet eller parametern för användarträdet. + + + groups of computer + grupper av datorer + + + Computer not found + Datorn hittades inte + + + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Det gick inte att hitta en dator med värdnamnet "%1". Kontrollera värdnamnet eller parametern för datorträdet. + + + Hostname lookup failed + Sökningen efter värdnamn misslyckades + + + Could not lookup hostname for IP address %1. Please check your DNS server settings. + Det gick inte att söka efter värdnamn för IP-adressen %1. Kontrollera inställningarna för din DNS-server. + + + location entries + platsangivelser + + + Computer groups filter + Filter för datorgrupper + + + Computer locations identification + Identifiering av datorplatser + + + Filter for computer groups + Filter för datorgrupper + + + Invalid test value + Ogiltigt testvärde + + + An empty or invalid value has been supplied for this test. + Ett tomt eller ogiltigt värde har angetts för detta test. + + + LDAP %1 test failed + LDAP %1-testet misslyckades + + + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + Det gick inte att fråga efter några poster i konfigurerad %1. Vänligen kontrollera parametern "%2". + +%3 + + + LDAP %1 test successful + LDAP %1-test framgångsrikt + + + The %1 has been queried successfully and %2 entries were found. + %1 har sökts framgångsrikt och %2 entries hittades. + + + LDAP test failed + LDAP-testet misslyckades + + + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + Kunde inte fråga någon %1. Kontrollera parametern/parametrarna %2 och ange namnet på ett befintligt objekt. + +%3 + + + and + och + + + LDAP test successful + LDAP-test framgångsrikt + + + %1 %2 have been queried successfully: + +%3 + %1 %2 har sökts framgångsrikt: + +%3 + + + LDAP filter test failed + Test av LDAP-filter misslyckades + + + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 + Kunde inte fråga någon %1 using det konfigurerade filtret. Kontrollera LDAP-filtret för %1. + +%2 + + + LDAP filter test successful + Test av LDAP-filter framgångsrikt + + + %1 %2 have been queried successfully using the configured filter. + %1 %2 har sökts framgångsrikt med hjälp av det konfigurerade filtret. + + + LDAP directory + LDAP-katalog + + + + LdapConfigurationPage + + Basic settings + Standardinställningar + + + General + Allmänt + + + LDAP server and port + LDAP-server och port + + + Bind DN + Binda DN + + + Bind password + Bind lösenord + + + Anonymous bind + Anonym bindning + + + Use bind credentials + Använd inloggningsuppgifter för bindning + + + Base DN + Bas DN + + + Fixed base DN + Fast bas DN + + + e.g. dc=example,dc=org + t.ex. dc=exempel,dc=org + + + Discover base DN by naming context + Upptäck bas-DN genom att namnge sammanhang + + + e.g. namingContexts or defaultNamingContext + t.ex. namingContexts eller defaultNamingContext + + + Environment settings + Miljöinställningar + + + Object trees + Objektträd + + + Computer tree + Dator träd + + + e.g. OU=Groups + t.ex. OU=Grupper + + + User tree + Användarträd + + + e.g. OU=Users + t.ex. OU=Användare + + + e.g. OU=Computers + t.ex. OU=Datorer + + + Group tree + Gruppträd + + + Perform recursive search operations in object trees + Utföra rekursiva sökoperationer i objektträd + + + Object attributes + Objektets attribut + + + e.g. hwAddress + t.ex. hwAddress + + + e.g. member or memberUid + t.ex. medlem eller memberUid + + + e.g. dNSHostName + t.ex. dNSHostName + + + Computer MAC address attribute + MAC-adressattribut för dator + + + Group member attribute + Attribut för gruppmedlem + + + e.g. uid or sAMAccountName + t.ex. uid eller sAMAccountName + + + Advanced settings + Avancerade inställningar + + + Optional object filters + Valfria objektfilter + + + Filter for user groups + Filter för användargrupper + + + Filter for users + Filter för användare + + + Filter for computer groups + Filter för datorgrupper + + + Group member identification + Identifiering av gruppmedlem + + + Distinguished name (Samba/AD) + Särskiljande namn (Samba/AD) + + + List all groups of a user + Lista alla grupper för en användare + + + List all groups of a computer + Lista alla grupper i en dator + + + Get computer object by IP address + Hämta datorobjekt via IP-adress + + + Enter username + Skriv in användarnamn + + + Please enter a user login name (wildcards allowed) which to query: + Ange ett användarinloggningsnamn (jokertecken tillåtna) som du vill fråga: + + + Enter group name + Ange gruppnamn + + + Please enter a group name whose members to query: + Ange ett gruppnamn vars medlemmar du vill fråga: + + + Enter computer name + Ange datorns namn + + + Enter computer DN + Gå in i datorn DN + + + Please enter the DN of a computer whose MAC address to query: + Ange DN för en dator vars MAC-adress du vill fråga efter: + + + Please enter a user login name whose group memberships to query: + Ange ett inloggningsnamn för den användare vars gruppmedlemskap ska efterfrågas: + + + Enter computer IP address + Ange datorns IP-adress + + + Please enter a computer IP address which to resolve to an computer object: + Ange en IP-adress för en dator som ska lösas upp till ett datorobjekt: + + + (only if different from group tree) + (endast om det skiljer sig från gruppträdet) + + + Computer group tree + Dator grupp träd + + + Filter for computers + Filter för datorer + + + e.g. room or computerLab + t.ex. rum eller datorLab + + + Integration tests + Integrationstest + + + Computer groups + Datorgrupper + + + e.g. name or description + t.ex. namn eller beskrivning + + + Filter for computer containers + Filter för datorbehållare + + + Computer containers or OUs + Datorbehållare eller OU:er + + + Connection security + Anslutningssäkerhet + + + TLS certificate verification + Verifiering av TLS-certifikat + + + System defaults + Systemets standardinställningar + + + Never (insecure!) + Aldrig (osäker!) + + + Custom CA certificate file + Anpassad CA-certifikatfil + + + None + Ingen + + + TLS + TLS + + + SSL + SSL + + + e.g. (objectClass=computer) + t.ex. (objektKlass=dator) + + + e.g. (objectClass=group) + t.ex. (objektKlass=grupp) + + + e.g. (objectClass=person) + t.ex. (objektKlass=person) + + + e.g. (objectClass=room) or (objectClass=computerLab) + t.ex. (objektKlass=rum) eller (objektKlass=datalabb) + + + e.g. (objectClass=container) or (objectClass=organizationalUnit) + t.ex. (objectClass=container) eller (objectClass=organizationalUnit) + + + Certificate files (*.pem) + Certifikatfiler (*.pem) + + + Encryption protocol + Krypteringsprotokoll + + + Computer location attribute + Attribut för datorplats + + + Computer display name attribute + Attribut för datorns visningsnamn + + + Location name attribute + Attribut för platsnamn + + + e.g. cn or displayName + t.ex. cn eller displayName + + + Computer locations identification + Identifiering av datorplatser + + + Identify computer locations (e.g. rooms) via: + Identifiera datorplatser (t.ex. rum) via: + + + Location attribute in computer objects + Platsattribut i datorobjekt + + + List all entries of a location + Lista alla poster för en plats + + + List all locations + Lista alla platser + + + Enter computer display name + Ange datorns visningsnamn + + + Please enter a computer display name to query: + Ange en dators visningsnamn för att ställa en fråga: + + + Enter computer location name + Ange datorns platsnamn + + + Please enter the name of a computer location (wildcards allowed): + Ange namnet på en datorplats (jokertecken tillåtna): + + + Enter location name + Ange platsens namn + + + Please enter the name of a location whose entries to query: + Ange namnet på en plats vars poster du vill söka efter: + + + Browse + Bläddra + + + Test + Testa + + + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Värdnamn lagrade som fullständigt kvalificerade domännamn (FQDN, t.ex. myhost.example.org) + + + Computer hostname attribute + Attribut för datorns värdnamn + + + Please enter a computer hostname to query: + Ange en dators värdnamn för att ställa en fråga: + + + Enter hostname + Ange värdnamn + + + Please enter a computer hostname whose group memberships to query: + Ange ett värdnamn på en dator vars gruppmedlemskap ska frågas: + + + User login name attribute + Attribut för användarens inloggningsnamn + + + Configured attribute for user login name or computer hostname (OpenLDAP) + Konfigurerat attribut för användarens inloggningsnamn eller datorns värdnamn (OpenLDAP) + + + Directory name + Namn på katalog + + + Query options + Alternativ för frågor + + + Query nested user groups (supported by AD only) + Fråga efter nästlade användargrupper (stöds endast av AD) + + + Query timeout + Tidsgräns för förfrågningar + + + ms + ms + + + + LdapNetworkObjectDirectoryConfigurationPage + + LDAP + LDAP + + + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + Använd den globala LDAP-konfigurationssidan för att konfigurera hur du hämtar platser och datorer från din LDAP-baserade katalogtjänst. + + + + LdapPlugin + + Auto-configure the base DN via naming context + Automatisk konfiguration av bas-DN via namngivningskontext + + + Query objects from LDAP directory + Fråga efter objekt från LDAP-katalog + + + Show help about command + Visa hjälp om kommandot + + + Commands for configuring and testing LDAP/AD integration + Kommandon för att konfigurera och testa LDAP/AD-integration + + + Basic LDAP/AD support for Veyon + Grundläggande LDAP/AD-stöd för Veyon + + + %1 (load computers and locations from LDAP/AD) + %1 (ladda datorer och platser från LDAP/AD) + + + %1 (load users and groups from LDAP/AD) + %1 (ladda användare och grupper från LDAP/AD) + + + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Ange en giltig LDAP-url enligt schemat "ldap[s]://[user[:password]@]hostname[:port]" + + + No naming context attribute name given - falling back to configured value. + Inget namn på attribut i namngivningskontext anges - faller tillbaka till konfigurerat värde. + + + Could not query base DN. Please check your LDAP configuration. + Kunde inte fråga bas DN. Kontrollera din LDAP-konfiguration. + + + Configuring %1 as base DN and disabling naming context queries. + Konfigurera %1 som bas-DN och inaktivera frågor om namngivningskontext. + + + Test binding to an LDAP server + Testa bindning till en LDAP-server + + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Det angivna användarnamnet eller lösenordet är fel. Ange giltiga inloggningsuppgifter eller byt till en annan autentiseringsmetod med Veyon Configurator. + + + LDAP bind + LDAP-bindning + + + + LinuxPlatformConfigurationPage + + Linux + Linux + + + Custom PAM service for user authentication + Anpassad PAM-tjänst för autentisering av användare + + + User authentication + Autentisering av användare + + + User sessions + Användarsessioner + + + Minimum session lifetime before server start + Minsta sessionslivslängd före serverstart + + + User login + Användarinloggning + + + Login key sequence + Tangentsekvens för inloggning + + + + LinuxPlatformPlugin + + Plugin implementing abstract functions for the Linux platform + Plugin som implementerar abstrakta funktioner för Linux-plattformen + + + + LocationDialog + + Select location + Välj plats + + + enter search filter... + ange sökfilter ... + + + + MainToolBar + + Configuration + Konfiguration + + + Show icons only + Visa endast ikoner + + + Disable tooltips + Inaktivera verktygstips + + + + MainWindow + + MainWindow + Huvudfönster + + + toolBar + verktygsrad + + + General + Allmänt + + + &File + &Arkiv + + + &Help + &Hjälp + + + &Quit + A&vsluta + + + Ctrl+Q + Ctrl+Q + + + Ctrl+S + Ctrl+S + + + L&oad settings from file + &Läs in inställningar från fil + + + Ctrl+O + Ctrl+O + + + About Qt + Om Qt + + + Configuration not writable + Konfigurationen är inte skrivbar + + + Load settings from file + Läs in inställningar från fil + + + Save settings to file + Spara inställningar till fil + + + Unsaved settings + Osparade inställningar + + + There are unsaved settings. Quit anyway? + Det finns osparade inställningar. Avsluta ändå? + + + Veyon Configurator + Veyon konfigurator + + + Service + Tjänst + + + Master + Säkerhetsansvarig + + + Access control + Åtkomstkontroll + + + About Veyon + Om Veyon + + + Auto + Auto + + + About + Om + + + %1 Configurator %2 + %1 Konfigurator %2 + + + JSON files (*.json) + JSON-filer (*.json) + + + The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. + Den lokala konfigurationsbackend rapporterade att konfigurationen inte är skrivbar! Kör %1 Configurator med högre behörigheter. + + + Access denied + Åtkomst nekad + + + According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. + Enligt den lokala konfigurationen har du inte åtkomst till datorer i nätverket. Logga in med ett annat konto eller låt din systemadministratör kontrollera den lokala konfigurationen. + + + Screenshots + Skärmbilder + + + Feature active + Funktion aktiv + + + The feature "%1" is still active. Please stop it before closing %2. + Funktionen "%1" är fortfarande aktiv. Vänligen stoppa den innan du stänger %2. + + + Reset configuration + Återställ konfiguration + + + Do you really want to reset the local configuration and revert all settings to their defaults? + Vill du verkligen återställa den lokala konfigurationen och återställa alla inställningar till standardvärdena? + + + Search users and computers + Sök användare och datorer + + + Align computers to grid + Rikta in datorerna i rutnätet + + + %1 Configurator + %1 Konfigurator + + + Insufficient privileges + Otillräckliga privilegier + + + Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + Kunde inte starta med administrativa behörigheter. Se till att ett sudo-liknande program är installerat för din skrivbordsmiljö! Programmet kommer att köras med normala användarrättigheter. + + + Only show powered on computers + Visa endast datorer som är påslagna + + + &Save settings to file + &Spara inställningar till fil + + + &View + &Visa + + + &Standard + Skärm %1$u Standard (%2$u:%3$u) + + + &Advanced + Avancerat + + + Use custom computer arrangement + Använd anpassade datorarrangemang + + + Locations && computers + Platser & & datorer + + + Authentication + Autentisering + + + Adjust size of computer icons automatically + Justera storleken på datorikoner automatiskt + + + Slideshow + Bildspel + + + Spotlight + Strålkastare + + + Veyon Master + Veyon Master + + + Locations & computers + Platser och datorer + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + Använd anpassade datorarrangemang. + +Håll nedtryckt för att ladda arrangemanget från en fil eller spara aktuellt arrangemang i en fil. + + + Only show computers with logged on users + Visa endast datorer med inloggade användare + + + Load computer positions + Ladda datorpositioner + + + Save computer positions + Spara datorpositioner + + + + MasterConfigurationPage + + Directories + Kataloger + + + User configuration + Konfiguration av användare + + + Feature on computer double click: + Funktion på datorn dubbelklicka: + + + Features + Funktioner + + + All features + Alla funktioner + + + Disabled features + Funktioner för funktionshindrade + + + Screenshots + Skärmbilder + + + <no feature> + <no feature> + + + Basic settings + Standardinställningar + + + Behaviour + Beteende + + + Enforce selected mode for client computers + Tillämpa valt läge för klientdatorer + + + Hide local computer + Dölj lokal dator + + + Hide computer filter field + Dölj datorns filterfält + + + Actions such as rebooting or powering down computers + Åtgärder som att starta om eller stänga av datorer + + + User interface + Användargränssnitt + + + Background color + Bakgrundsfärg + + + Thumbnail update interval + Uppdateringsintervall för miniatyrbilder + + + ms + ms + + + Program start + Start av program + + + Modes and features + Modi och funktioner + + + User and computer name + Användar- och datornamn + + + Only user name + Endast användarnamn + + + Only last part of user name + + + + Only computer name + Endast datorns namn + + + Computer thumbnail caption + Bildtext för datorns miniatyrbild + + + Text color + Textfärg + + + Sort order + Sorteringsordning + + + Computer and user name + Dator och användarnamn + + + Computer locations + Datorplatser + + + Show current location only + Visa endast den aktuella platsen + + + Allow adding hidden locations manually + Tillåt att lägga till dolda platser manuellt + + + Hide empty locations + Dölj tomma platser + + + Show confirmation dialog for potentially unsafe actions + Visa bekräftelsedialog för potentiellt osäkra åtgärder + + + Perform access control + Utföra åtkomstkontroll + + + Automatically select current location + Välj automatiskt aktuell plats + + + Automatically open computer select panel + Öppna automatiskt datorns urvalspanel + + + Use modern user interface (experimental) + Använd ett modernt användargränssnitt (experimentellt) + + + Thumbnail spacing + Avstånd mellan miniatyrbilder + + + px + bildpunkter + + + Hide local session + Dölj lokal session + + + Auto + Auto + + + Thumbnail aspect ratio + Bildförhållande för miniatyrbilder + + + Automatically adjust computer icon size + Justera automatiskt storleken på datorikonen + + + Open feature windows on the same screen as the main window + Öppna funktionsfönster på samma skärm som huvudfönstret + + + Configuration templates + Konfigurationsmallar + + + Image quality in monitoring mode + Bildkvalitet i övervakningsläge + + + Highest + Högst + + + High + Hög + + + Medium + Medium + + + Low + Låg + + + Lowest + Lägsta + + + Remote access image quality + Bildkvalitet för fjärråtkomst + + + Advanced + Avancerat + + + Computer name source + Datornamn källa + + + Default + Standard + + + Host address + Värdadress + + + Session client address + Sessionens klientadress + + + Session client name + Sessionens klientnamn + + + Session host name + Sessionens värdnamn + + + Session metadata + Metadata för sessionen + + + Full name of user + Fullständigt namn på användaren + + + User login name + Användarens inloggningsnamn + + + Computer UID role + Dator UID roll + + + Session meta data hash + Hash för sessionens metadata + + + Always expand all locations + Expandera alltid alla platser + + + Image quality + Bildkvalitet + + + + MonitoringMode + + Monitoring + Monitorering + + + Builtin monitoring mode + Inbyggt övervakningsläge + + + This mode allows you to monitor all computers at one or more locations. + I det här läget kan du övervaka alla datorer på en eller flera platser. + + + Query application version of the server + Fråga efter serverns applikationsversion + + + Query active features + Fråga efter aktiva funktioner + + + Query properties of remotely available screens + Fråga efter egenskaper för fjärrtillgängliga skärmar + + + + NestedNetworkObjectDirectory + + All directories + Alla kataloger + + + + NetworkObjectDirectoryConfigurationPage + + Update interval: + Uppdateringsintervall: + + + seconds + sekunder + + + + NetworkObjectDirectoryConfigurationPageTab + + Enabled + Aktiverad + + + + NetworkObjectTreeModel + + Locations/Computers + Platser/Datorer + + + + OpenWebsiteDialog + + Open website + Öppna webbplats + + + e.g. Veyon + t.ex. Veyon + + + Remember and add to website menu + Kom ihåg och lägg till i webbplatsens meny + + + e.g. www.veyon.io + t.ex. www.veyon.io + + + Please enter the URL of the website to open: + Ange webbadressen till den webbplats som ska öppnas: + + + Name: + Namn: + + + Website name + Webbplats + + + + PluginCommands + + List names of all installed plugins + Lista namn på alla installerade plugins + + + Show table with details of all installed plugins + Visa en tabell med information om alla installerade plugins + + + Name + Namn + + + Description + Beskrivning + + + Version + Version + + + UID + UID + + + Plugin-related CLI operations + Plugin-relaterade CLI-åtgärder + + + Commands for managing plugins + Kommandon för hantering av plugins + + + + PowerControlFeaturePlugin + + Power on + Starta + + + Click this button to power on all computers. This way you do not have to power on each computer by hand. + Klicka på den här knappen för att slå på alla datorer. På så sätt behöver du inte slå på varje dator för hand. + + + Reboot + Starta om + + + Click this button to reboot all computers. + Klicka på den här knappen för att starta om alla datorer. + + + Power down + Stäng av + + + Click this button to power down all computers. This way you do not have to power down each computer by hand. + Klicka på den här knappen för att stänga av alla datorer. På så sätt behöver du inte stänga av varje dator för hand. + + + Power on/down or reboot a computer + Slå på/av eller starta om en dator + + + Confirm reboot + Bekräfta omstart + + + Confirm power down + Bekräfta avstängning + + + Do you really want to reboot the selected computers? + Vill du verkligen starta om de utvalda datorerna? + + + Power on a computer via Wake-on-LAN (WOL) + Slå på en dator via Wake-on-LAN (WOL) + + + MAC ADDRESS + MAC-ADRESS + + + This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. + Detta kommando sänder ett WOL-paket (Wake-on-LAN) till nätverket för att slå på datorn med den angivna MAC-adressen. + + + Please specify the command to display help for! + Ange det kommando som du vill visa hjälp för! + + + Invalid MAC address specified! + Ogiltig MAC-adress angiven! + + + Commands for controlling power status of computers + Kommandon för att kontrollera datorers strömstatus + + + Power down now + Stäng av strömmen nu + + + Install updates and power down + Installera uppdateringar och stäng av strömmen + + + Power down after user confirmation + Avstängning efter användarens bekräftelse + + + Power down after timeout + Stängs av efter timeout + + + The computer was remotely requested to power down. Do you want to power down the computer now? + Datorn fick en fjärrstyrd begäran om avstängning. Vill du stänga av datorn nu? + + + The computer will be powered down in %1 minutes, %2 seconds. + +Please save your work and close all programs. + Datorn kommer att stängas av om %1 minuter, %2 second. + +Spara ditt arbete och stäng alla program. + + + Do you really want to reboot <b>ALL</b> computers? + Vill du verkligen starta om <b>ALLA</b> datorer? + + + Do you really want to power down <b>ALL</b> computers? + Vill du verkligen stänga av <b>ALLA</b> datorer? + + + Do you really want to power down the selected computers? + Vill du verkligen stänga av de utvalda datorerna? + + + + PowerDownTimeInputDialog + + Power down + Stäng av + + + Please specify a timeout for powering down the selected computers: + Ange en tidsgräns för när de valda datorerna ska stängas av: + + + minutes + minuter + + + seconds + sekunder + + + + RemoteAccessFeaturePlugin + + Remote view + Fjärrvisning + + + Open a remote view for a computer without interaction. + Öppna en fjärrvy för en dator utan interaktion. + + + Remote control + Fjärrstyrning + + + Open a remote control window for a computer. + Öppna ett fjärrkontrollfönster för en dator. + + + Remote access + Fjärråtkomst + + + Remote view or control a computer + Fjärrvisning eller fjärrstyrning av en dator + + + Show help about command + Visa hjälp om kommandot + + + Exchange clipboard contents + Innehåll i Exchange-klippbord + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + Ingen dator har valts så du kan ange ett värdnamn eller en IP-adress för en dator för manuell åtkomst: + + + + RemoteAccessPage + + Remote access: %1 + Fjärråtkomst: %1 + + + + RemoteAccessWidget + + %1 - %2 Remote Access + %1 - %2 Fjärråtkomst + + + %1 - %2 - %3 Remote Access + %1 - %2 - %3 Fjärråtkomst + + + + RemoteAccessWidgetToolBar + + View only + Visa endast + + + Remote control + Fjärrstyrning + + + Send shortcut + Genväg för att skicka + + + Fullscreen + Helskärm + + + Window + Fönster + + + Ctrl+Alt+Del + Ctrl+Alt+Del + + + Ctrl+Esc + Ctrl+Esc + + + Alt+Tab + Alt+Tab + + + Alt+F4 + Alt+F4 + + + Win+Tab + Win+Tab + + + Win + Vinst + + + Menu + Meny + + + Alt+Ctrl+F1 + Alt+Ctrl+F1 + + + Connected. + Ansluten. + + + Screenshot + Skärmbild + + + Exit + Avsluta + + + Connecting... + Ansluter... + + + Select screen + Välj skärm + + + All screens + Alla skärmar + + + + ScreenLockFeaturePlugin + + Lock + Lås + + + Unlock + Lås upp + + + Lock screen and input devices of a computer + Låsskärm och inmatningsenheter på en dator + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + För att återfå alla användares fulla uppmärksamhet kan du låsa deras datorer med den här knappen. I det här läget är alla inmatningsenheter låsta och skärmarna är mörklagda. + + + Lock input devices + Lås inmatningsenheter + + + Unlock input devices + Lås upp inmatningsenheter + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + För att återfå alla användares fulla uppmärksamhet kan du låsa deras datorer med den här knappen. I det här läget är alla inmatningsenheter låsta medan skrivbordet fortfarande är synligt. + + + + Screenshot + + unknown + okänd + + + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + Det gick inte att ta en skärmdump eftersom katalogen %1 d inte finns och inte kunde skapas. + + + Screenshot + Skärmbild + + + Could not open screenshot file %1 for writing. + Det gick inte att öppna skärmdumpfilen %1 f eller skriva. + + + + ScreenshotFeaturePlugin + + Screenshot + Skärmbild + + + Use this function to take a screenshot of selected computers. + Använd den här funktionen för att ta en skärmdump av valda datorer. + + + Screenshots taken + Skärmdumpar tagna + + + Screenshot of %1 computer have been taken successfully. + Skärmdump av %1 computer har tagits framgångsrikt. + + + Take screenshots of computers and save them locally. + Ta skärmdumpar av datorer och spara dem lokalt. + + + + ScreenshotManagementPage + + Screenshots + Skärmbilder + + + + ScreenshotManagementPanel + + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + Här listas alla skärmdumpar som du har tagit. Du kan ta skärmdumpar genom att klicka på objektet "Skärmdump" i snabbmenyn på en dator. Skärmdumparna kan hanteras med hjälp av knapparna nedan. + + + User: + Användare: + + + Computer: + Dator: + + + Date: + Datum: + + + Time: + Tid: + + + Show + Visa + + + Delete + Ta bort + + + Screenshot + Skärmbild + + + Do you really want to delete all selected screenshots? + Vill du verkligen ta bort alla valda skärmdumpar? + + + + ServerAccessControlManager + + Requested authentication method not available + Begärd autentiseringsmetod är inte tillgänglig + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + + + + User has denied access + + + + User confirmed access + + + + + ServiceConfigurationPage + + General + Allmänt + + + Autostart + Automatisk start + + + Hide tray icon + Dölj aktivitetsikonen + + + Start service + Starta tjänst + + + Stopped + Stoppad + + + Stop service + Stoppa tjänst + + + State: + Tillstånd: + + + Enable firewall exception + Aktivera brandväggsundantag + + + Allow connections from localhost only + Tillåt endast anslutningar från localhost + + + VNC server + VNC-server + + + Plugin: + Tillägg: + + + Restart %1 Service + Starta om %1-tjänsten + + + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + Alla inställningar sparades framgångsrikt. För att de ska träda i kraft måste %1 service startas om. Starta om den nu? + + + Running + Kör + + + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. + Om du aktiverar det här alternativet kommer tjänsten att starta en serverprocess för varje interaktiv session på en dator. +Detta krävs vanligtvis för att stödja terminalservrar. + + + Show notification on remote connection + Visa meddelande om fjärranslutning + + + Show notification when an unauthorized access is blocked + Visa meddelande när en obehörig åtkomst blockeras + + + Maximum session count + Maximalt antal sessioner + + + Network port numbers + Portnummer för nätverk + + + Veyon server + Veyon server + + + Internal VNC server + Intern VNC-server + + + Feature manager + Funktionschef + + + Demo server + Demoserver + + + Miscellaneous network settings + Diverse nätverksinställningar + + + Session mode + Sessionsläge + + + Local session mode (single server instance for primary local session) + Läge för lokal session (en enda serverinstans för primär lokal session) + + + Active session mode (single server instance for active local or remote session) + Aktivt sessionsläge (en enda serverinstans för aktiv lokal session eller fjärrsession) + + + Multi session mode (distinct server instance for each local and remote desktop session) + Multisessionsläge (separat serverinstans för varje lokal skrivbordssession och fjärrskrivbordssession) + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + Aktivera om en enda Veyon Server-instans ska startas för den aktuella aktiva sessionen, oavsett om den är lokal eller fjärrstyrd. + + + Miscellaneous settings + Övriga inställningar + + + Disable clipboard synchronization + Inaktivera synkronisering av urklipp + + + Session metadata + Metadata för sessionen + + + Content + Innehåll + + + None + Ingen + + + Value of an environment variable + Värde för en miljövariabel + + + Value of a registry key + Värde för en registernyckel + + + Environment variable name: + Namn på miljövariabel: + + + Registry key name: + Namn på registernyckel: + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + Ange eventuellt ett reguljärt uttryck med en capture för att extrahera en del av datornamnet och använda det som datorns visningsnamn. + +Exempel: [^-]*-(pc[0-9]*) [^-]*-(PC[0-9]*) + + + + ServiceControl + + Service control + Servicekontroll + + + Starting %1 + + + + Stopping %1 + + + + Restarting %1 + + + + Registering %1 + + + + Unregistering %1 + + + + + ServiceControlCommands + + Register Veyon Service + Registrera Veyon Service + + + Unregister Veyon Service + Avregistrera Veyon Service + + + Start Veyon Service + Starta Veyon Service + + + Stop Veyon Service + Stoppa Veyon Service + + + Restart Veyon Service + Starta om Veyon Service + + + Query status of Veyon Service + Förfrågningsstatus för Veyon Service + + + Service is running + Tjänsten är igång + + + Service is not running + Tjänsten är inte igång + + + Configure and control Veyon service + Konfigurera och kontrollera Veyon-tjänster + + + Commands for configuring and controlling Veyon Service + Kommandon för att konfigurera och styra Veyon Service + + + + ShellCommands + + Run command file + Kör kommandofilen + + + File "%1" does not exist! + Filen "%1" finns inte! + + + Interactive shell and script execution for Veyon CLI + Interaktiv shell- och skriptexekvering för Veyon CLI + + + Commands for shell functionalities + Kommandon för shell-funktioner + + + + SlideshowPanel + + Previous + Föregående + + + Start/pause + Starta/pausa + + + Next + Nästa + + + Duration: + Varaktighet: + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + Lägg till valda datorer + + + Remove selected computers + Ta bort valda datorer + + + Update computers in realtime + Uppdatera datorer i realtid + + + Spotlight + Strålkastare + + + Please select at least one computer to add. + Vänligen välj minst en dator att lägga till. + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + Lägg till datorer genom att klicka med den mellersta musknappen eller klicka på den första knappen nedan. +Den andra knappen tar bort den valda eller sista datorn. + + + + StartAppDialog + + Start application + Starta ansökan + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + Ange de program som ska startas på de valda datorerna. Du kan separera flera program med en rad. + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + t.ex. "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + Kom ihåg och lägg till i applikationsmenyn + + + Application name + Applikationsnamn + + + Name: + Namn: + + + e.g. VLC + t.ex. VLC + + + + SystemTrayIcon + + System tray icon + Ikon för systemfältet + + + + SystemUserGroupsPlugin + + User groups backend for system user groups + Användargrupper backend för systemets användargrupper + + + Default (system user groups) + Standard (systemets användargrupper) + + + + TestingCommandLinePlugin + + Test internal Veyon components and functions + Testa Veyons interna komponenter och funktioner + + + Commands for testing internal components and functions of Veyon + Kommandon för att testa interna komponenter och funktioner i Veyon + + + + TextMessageDialog + + Send text message + Skicka textmeddelande + + + Please enter your message which send to all selected users. + Ange ditt meddelande som skickas till alla utvalda användare. + + + + TextMessageFeaturePlugin + + Text message + Textmeddelande + + + Use this function to send a text message to all users e.g. to assign them new tasks. + Använd den här funktionen för att skicka ett textmeddelande till alla användare, t.ex. för att tilldela dem nya uppgifter. + + + Message from teacher + Meddelande från lärare + + + Send a message to a user + Skicka ett meddelande till en användare + + + + UltraVncConfigurationWidget + + Enable capturing of layered (semi-transparent) windows + Aktivera fångst av flerskiktade fönster (semi-transparant) + + + Poll full screen (leave this enabled per default) + Poll fullskärm (låt detta vara aktiverat som standard) + + + Low accuracy (turbo mode) + Låg precision (turboläge) + + + Builtin UltraVNC server configuration + Inbyggd konfiguration av UltraVNC-server + + + Enable multi monitor support + Aktivera stöd för flera skärmar + + + Enable Desktop Duplication Engine on Windows 8 and newer + Aktivera Desktop Duplication Engine i Windows 8 och nyare + + + Maximum CPU usage + Maximal CPU-användning + + + + UserLoginDialog + + User login + Användarinloggning + + + Please enter a username and password for automatic login on all computers. + Ange användarnamn och lösenord för automatisk inloggning på alla datorer. + + + Username + Användarnamn + + + Password + Lösenord + + + + UserSessionControlPlugin + + Log in + Logga in + + + Click this button to log in a specific user on all computers. + Klicka på den här knappen för att logga in en viss användare på alla datorer. + + + Log off + Logga ut + + + Click this button to log off users from all computers. + Klicka på den här knappen för att logga ut användare från alla datorer. + + + Confirm user logoff + Bekräfta utloggning av användare + + + Do you really want to log off the selected users? + Vill du verkligen logga ut de utvalda användarna? + + + User session control + Kontroll av användarsessioner + + + Do you really want to log off <b>ALL</b> users? + Vill du verkligen logga ut <b>ALLA</b> användare? + + + + VeyonCore + + [OK] + Ok + + + [FAIL] + [FAIL] + + + Invalid command! + Ogiltigt kommando! + + + Available commands: + Tillgängliga kommandon: + + + Invalid arguments given + Ogiltiga argument angivna + + + Not enough arguments given - use "%1 help" for more information + Inte tillräckligt med argument angivna - använd "%1 help" för mer information + + + Unknown result! + Okänt resultat! + + + Available modules: + Tillgängliga moduler: + + + No module specified or module not found - available modules are: + Ingen modul angiven eller modul hittades inte - tillgängliga moduler är: + + + Plugin not licensed + Plugin inte licensierat + + + INFO + INFO + + + ERROR + FEL + + + USAGE + Användning + + + DESCRIPTION + BESKRIVNING + + + EXAMPLES + Exempel + + + WARNING + VARNING + + + Authentication test + Autentiseringstest + + + Screen %1 + Skärm %1 + + + + VeyonMaster + + No write access + Ingen skrivåtkomst + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Det gick inte att spara dina personliga inställningar! Kontrollera sökvägen till användarkonfigurationsfilen med hjälp av %1 Configurator. + + + + VeyonServiceControl + + Veyon Service + Veyon Service + + + + WindowsPlatformConfiguration + + Could not change the setting for SAS generation by software. Sending Ctrl+Alt+Del via remote control will not work! + Det gick inte att ändra inställningen för SAS-generering med programvaran. Att skicka Ctrl+Alt+Del via fjärrkontroll fungerar inte! + + + + WindowsPlatformConfigurationPage + + Windows + Fönster + + + General + Allmänt + + + Enable SAS generation by software (Ctrl+Alt+Del) + Aktivera SAS-generering med programvara (Ctrl+Alt+Del) + + + Screen lock + Skärmlås + + + Hide taskbar + Dölj aktivitetsfältet + + + Hide start menu + Dölj startmenyn + + + Hide desktop + Dölj skrivbordet + + + User authentication + Autentisering av användare + + + Use alternative user authentication mechanism + Använd alternativ mekanism för användarautentisering + + + User login + Användarinloggning + + + Input start delay + Fördröjning av start av ingång + + + Simulated key presses interval + Intervall för simulerade tangenttryckningar + + + Confirm legal notice (message displayed before user logs in) + Bekräfta juridiskt meddelande (meddelande som visas innan användaren loggar in) + + + Use input device interception driver + Använd drivrutin för avlyssning av inmatningsenheter + + + Use custom power scheme with disabled power button + Använd ett anpassat strömschema med inaktiverad strömknapp + + + + WindowsPlatformPlugin + + Plugin implementing abstract functions for the Windows platform + Plugin som implementerar abstrakta funktioner för Windows-plattformen + + + Internal display + Intern display + + + + WindowsServiceControl + + The service "%1" is already installed. + Tjänsten "%1" är redan installerad. + + + The service "%1" has been installed successfully. + Tjänsten "%1" har installerats framgångsrikt. + + + The service "%1" has been uninstalled successfully. + Tjänsten "%1" har avinstallerats framgångsrikt. + + + Service "%1" could not be found. + Tjänsten "%1" kunde inte hittas. + + + The service "%1" could not be installed (error %2). + Tjänsten "%1" kunde inte installeras (fel %2). + + + Could not change the failure actions config for service "%1" (error %2). + Det gick inte att ändra konfigurationen för felåtgärder för tjänsten "%1" (fel %2). + + + The service "%1" could not be uninstalled (error %2). + Tjänsten "%1" kunde inte avinstalleras (fel %2). + + + The start type of service "%1" could not be changed (error %2). + Det gick inte att ändra starttypen för tjänsten "%1" (fel %2). + + + + X11VncConfigurationWidget + + Builtin x11vnc server configuration + Inbyggd konfiguration av x11vnc-server + + + Custom x11vnc parameters: + Anpassade x11vnc-parametrar: + + + Do not use X Damage extension + Använd inte X Damage-tillägget + + + \ No newline at end of file diff --git a/translations/th.ts b/translations/veyon_th.ts similarity index 76% rename from translations/th.ts rename to translations/veyon_th.ts index 8b3b8a0ae..05e90bd58 100644 --- a/translations/th.ts +++ b/translations/veyon_th.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -78,10 +78,6 @@ If you're interested in translating Veyon into your local or another langua All groups กลุ่มทั้งหมด - - ... - ... - Access control rules @@ -139,15 +135,14 @@ If you're interested in translating Veyon into your local or another langua - Missing user groups backend - - - - No default user groups plugin was found. Please check your installation! + Restrict access to members of specific user groups + + + AccessControlProvider - Restrict access to members of specific user groups + Provider for access control features @@ -171,36 +166,16 @@ If you're interested in translating Veyon into your local or another langua enter a description for the rule here - + กรอกคำอธิบายสำหรับกฏได้ที่นี่ Rule description: คำอธิบายกฏ: - - Invert all conditions ("is/has" interpreted as "is/has not") - - Conditions เงื่อนไข - - is member of group - เป็นสมาชิกของกลุ่ม - - - Accessing computer is localhost - - - - Accessing user is logged on user - - - - Accessing user is already connected - - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. @@ -234,33 +209,125 @@ If you're interested in translating Veyon into your local or another langua คอมพิวเตอร์ที่เข้าถึง - Local (logged on) user - ผู้ใช้ท้องที่ (อยู่ในระบบ) + Always process rule and ignore conditions + + + + Accessing computer and local computer + - Local computer - คอมพิวเตอร์ท้องที่ + User being accessed + - Always process rule and ignore conditions + is logged in locally - No user logged on - ไม่มีผู้ใช้เข้าสู่ระบบ + is logged in remotely + + + + No user is logged in locally + + + + One or multiple users are logged in locally + - Accessing user has one or more groups in common with local (logged on) user + No user is logged in remotely - Accessing computer and local computer are at the same location + One or multiple users are logged in remotely is located at + + is not located at + + + + are located at the same location + + + + are not located the same location + + + + is member of group + เป็นสมาชิกของกลุ่ม + + + is not member of group + + + + is authenticated via + + + + is not authenticated via + + + + has one or more groups in common with user being accessed + + + + has no groups in common with user being accessed + + + + equals user being accessed + + + + is different from user being accessed + + + + is already connected + + + + is not connected + + + + is local computer + + + + is not local computer + + + + Computer being accessed + + + + Session being accessed is a user session + + + + Session being accessed is a login screen + + + + Local computer is already being accessed + + + + Local computer is not yet being accessed + + AccessControlRulesTestDialog @@ -304,41 +371,43 @@ If you're interested in translating Veyon into your local or another langua The access in the given scenario needs permission of the logged on user. - - ERROR: Unknown action - ข้อผิดพลาด: การกระทำที่ไม่รู้จัก - Test result ผลการทดสอบ - - - AndroidPlatformConfigurationPage - Android + Authentication method - General - ทั่วไป + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform + Introduction - - - AuthKeysConfigurationPage - Authentication keys + Please perform the following steps to set up key file authentication: - Introduction + 1) Create a key pair on the master computer. + 1) สร้างคู่กุญแจบนคอมพิวเตอร์หลัก + + + 2) Set an access group whose members should be allowed to access other computers. + 2) ตั้งกลุ่มการเข้าถึง โดยสมาชิกใดบ้างที่จะสามารถเข้าถึงคอมพิวเตอร์เครื่องอื่นได้ + + + 3) Export the public key and import it on all client computers with the same name. + 3) ส่งออกไฟล์กุญแจสาธารณะ และนำเข้าลงในเครื่องคอมพิวเตอร์ลูกข่ายโดยใช้ชื่อไฟล์เดียวกัน + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. @@ -353,14 +422,20 @@ If you're interested in translating Veyon into your local or another langua Private key file base directory - - ... - ... - Available authentication keys + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + คู่กุญแจยืนยันตัวตนนั้นจะประกอบด้วยกุญแจคริปโตกราฟิกสองดอกกุญแจสาธารณะและกุญแจส่วนตัว +กุญแจส่วนตัวจะอนุญาตให้ผู้ใช้งานในเครื่องมาสเตอร์ในการการเข้าถึงเครื่องลูกข่าย +ซึ่งเป็นสิ่งที่สำคัญว่า ต้องกำหนดให้ผู้ใช้ที่ได้รับการอนุญาตเท่านั้นที่จะสามารถอ่านไฟล์กุญแจส่วนตัวได้ +ไฟล์กุญแจสาธารณะจะใช้บนเครื่องลูกข่ายเพื่อรับการยืนยันตัวตนจากการร้องขอการเชื่อมต่อที่เข้ามา + Create key pair สร้างคู่กุญแจ @@ -401,10 +476,6 @@ If you're interested in translating Veyon into your local or another langua Please select a key to delete! โปรดเลือกกุญแจที่จะลบก่อน! - - Please enter the name of the user group or role for which to import the authentication key: - - Please select a key to export! กรุณาเลือกกุญแจที่จะส่งออกก่อน! @@ -418,35 +489,11 @@ If you're interested in translating Veyon into your local or another langua - Please perform the following steps to set up key file authentication: - - - - 1) Create a key pair on the master computer. - 1) สร้างคู่กุญแจบนคอมพิวเตอร์หลัก - - - 2) Set an access group whose members should be allowed to access other computers. - 2) ตั้งกลุ่มการเข้าถึง โดยสมาชิกใดบ้างที่จะสามารถเข้าถึงคอมพิวเตอร์เครื่องอื่นได้ - - - 3) Export the public key and import it on all client computers with the same name. - 3) ส่งออกไฟล์กุญแจสาธารณะ และนำเข้าลงในเครื่องคอมพิวเตอร์ลูกข่ายโดยใช้ชื่อไฟล์เดียวกัน - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - คู่กุญแจยืนยันตัวตนนั้นจะประกอบด้วยกุญแจคริปโตกราฟิกสองดอกกุญแจสาธารณะและกุญแจส่วนตัว -กุญแจส่วนตัวจะอนุญาตให้ผู้ใช้งานในเครื่องมาสเตอร์ในการการเข้าถึงเครื่องลูกข่าย -ซึ่งเป็นสิ่งที่สำคัญว่า ต้องกำหนดให้ผู้ใช้ที่ได้รับการอนุญาตเท่านั้นที่จะสามารถอ่านไฟล์กุญแจส่วนตัวได้ -ไฟล์กุญแจสาธารณะจะใช้บนเครื่องลูกข่ายเพื่อรับการยืนยันตัวตนจากการร้องขอการเชื่อมต่อที่เข้ามา - AuthKeysManager @@ -645,10 +692,6 @@ The public key is used on client computers to authenticate incoming connection r This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - - Please specify the command to display help for! - - TYPE @@ -657,10 +700,6 @@ The public key is used on client computers to authenticate incoming connection r PAIR ID - - Command line support for managing authentication keys - - Commands for managing authentication keys @@ -677,6 +716,30 @@ The public key is used on client computers to authenticate incoming connection r This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + + + + Key file authentication + การยืนยันตัวตนด้วยไฟล์กุญแจ + + + Key file + + + + Please specify the key name (e.g. "teacher/public") as the first argument. + + + + Please specify the command to display help for. + + + + The specified command does not exist or no help is available for it. + + AuthKeysTableModel @@ -698,63 +761,206 @@ The public key is used on client computers to authenticate incoming connection r - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - คอมพิวเตอร์ + General + ทั่วไป - Name - ชื่อ + Username to bind DN mapping: + - Host address/IP - โฮสแอดแดรส/IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + + AuthLdapDialog - MAC address - MAC แอดแดรส + Veyon Logon + - Add new computer - เพิ่มคอมพิวเตอร์ใหม่ + Please enter your domain/LDAP username and password in order to access computers. + - Remove selected computer - ลบคอมพิวเตอร์ที่เลือก + Username + ชื่อผู้ใช้ - New computer - คอมพิวเตอร์ใหม่ + Password + รหัสผ่าน - Builtin directory - + Authentication error + การยืนยันตัวตนผิดพลาด - Locations & computers - สถานที่และคอมพิวเตอร์ + Logon failed with given username and password. Please try again! + + + + AuthLogonDialog - Locations - สถานที่ + Veyon Logon + - Add new location - เพิ่มสถานที่ใหม่ + Please enter your username and password in order to access computers. + - Remove selected location - ลบสถานที่ที่เลือก + Username + ชื่อผู้ใช้ - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - + Password + รหัสผ่าน - New location + Authentication error + การยืนยันตัวตนผิดพลาด + + + Logon failed with given username and password. Please try again! + + + + + AuthLogonPlugin + + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + + + + Logon authentication + การยืนยันตัวตนด้วยการลงชื่อเข้าใช้ + + + Logon + + + + + AuthSimpleDialog + + Veyon Logon + + + + Please enter the Veyon password: + + + + Authentication error + การยืนยันตัวตนผิดพลาด + + + Logon failed with given password. Please try again! + + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + + + + Simple password authentication + + + + Simple password + + + + + AuthenticationPage + + Authentication is set up properly on this computer. + การยืนยันตัวตนถูกติดตั้งบนคอมพิวเตอร์ได้อย่างถูกต้องแล้ว + + + + AuthenticationPageTab + + Enabled + + + + Test + ทดสอบ + + + + BuiltinDirectoryConfiguration + + Builtin directory + + + + + BuiltinDirectoryConfigurationPage + + Computers + คอมพิวเตอร์ + + + Name + ชื่อ + + + Host address/IP + โฮสแอดแดรส/IP + + + MAC address + MAC แอดแดรส + + + Add new computer + เพิ่มคอมพิวเตอร์ใหม่ + + + Remove selected computer + ลบคอมพิวเตอร์ที่เลือก + + + New computer + คอมพิวเตอร์ใหม่ + + + Builtin directory + + + + Locations + สถานที่ + + + Add new location + เพิ่มสถานที่ใหม่ + + + Remove selected location + ลบสถานที่ที่เลือก + + + New location สถานที่ใหม่ + + Directory name + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + BuiltinDirectoryPlugin @@ -864,11 +1070,11 @@ The public key is used on client computers to authenticate incoming connection r Add a location or computer - + เพิ่มสถานที่หรือคอมพิวเตอร์ Clear all locations and computers - + ล้างรายการสถานที่และคอมพิวเตอร์ทั้งหมด Dump all or individual locations and computers @@ -998,27 +1204,31 @@ The public key is used on client computers to authenticate incoming connection r MAC ADDRESS + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. + + BuiltinUltraVncServer Builtin VNC server (UltraVNC) - + เซิฟเวอร์ VNC ในตัว (UltraVNC) BuiltinX11VncServer Builtin VNC server (x11vnc) - + เซิฟเวอร์ VNC ในตัว (x11vnc) ComputerControlListModel - - Host/IP address: %1 - - Active features: %1 @@ -1035,10 +1245,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off คอมพิวเตอร์ออฟไลน์หรือปิดเครื่องอยู่ - - Service unreachable or not running - ไม่สามารถเข้าถึงเซอร์วิสได้ หรือไม่ได้ทำงาน - Authentication failed or access denied @@ -1059,6 +1265,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 + + [no user] + + + + Veyon Server unreachable or not running + + + + Name: %1 + + + + Hostname: %1 + + + + unknown + ไม่รู้จัก + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + ComputerControlServer @@ -1090,6 +1328,17 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + + Active connections: + + + + + ComputerGroupSelector + + Group %1 + + ComputerManager @@ -1117,13 +1366,48 @@ The public key is used on client computers to authenticate incoming connection r Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + + Logged in since + + + + %1 days + + + + 1 day + + - ComputerSelectPanel + ComputerMonitoring + + Computers + คอมพิวเตอร์ + + + Search users and computers + ค้นหาผู้ใช้และคอมพิวเตอร์ + + + Select all + เลือกทั้งหมด + + + Unselect all + ยกเลิกการเลือกทั้งหมด + + + Add to group + + - Computer management - การจัดการคอมพิวเตอร์ + Remove from group + + + + ComputerSelectPanel Computer search การค้นหาคอมพิวเตอร์ @@ -1146,85 +1430,89 @@ The public key is used on client computers to authenticate incoming connection r File error - + ไฟล์มีข้อผิดพลาด Could not write the computer and users list to %1! Please check the file access permissions. + + Search computers + + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. + Clear system-wide Veyon configuration - Please specify a valid filename for the configuration export. + List all configuration keys and values - Please specify a valid key. + Import configuration from given file - Specified key does not exist in current configuration! + Export configuration to given file - Please specify a valid value. + Read and output configuration value for given key - Configure Veyon at command line + Write given value to given configuration key - Output file is not writable! + Unset (remove) given configuration key - Output directory is not writable! + Upgrade and save configuration of program and plugins - Configuration file is not readable! + Please specify an existing configuration file to import. - Clear system-wide Veyon configuration + Configuration file is not readable! - List all configuration keys and values + Please specify a valid filename for the configuration export. - Import configuration from given file + Output file is not writable! - Export configuration to given file + Output directory is not writable! - Read and output configuration value for given key + Please specify a valid key. - Write given value to given configuration key + Specified key does not exist in current configuration! - Unset (remove) given configuration key + Please specify a valid value. - Commands for managing the configuration of Veyon + Configure Veyon at command line - Upgrade and save configuration of program and plugins + Commands for managing the configuration of Veyon @@ -1250,6 +1538,10 @@ The public key is used on client computers to authenticate incoming connection r Could not apply platform-specific configuration settings. + + Could not configure the firewall configuration for the %1 Service. + + DemoClient @@ -1280,10 +1572,6 @@ The public key is used on client computers to authenticate incoming connection r Memory limit จำกัดหน่วยความจำ - - Use multithreading (experimental) - - MB MB @@ -1298,15 +1586,19 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running + ลดความเร็วการอัปเดตภาพทัมเนลลงเมื่ออยู่ในโหมดสาธิต + + + Bandwidth limit + + + + MB/s DemoFeaturePlugin - - Fullscreen demo - สาธิตแบบเต็มจอ - Stop demo หยุดการสาธิต @@ -1320,17 +1612,61 @@ The public key is used on client computers to authenticate incoming connection r อธิบายสาธิตด้วยการถ่ายทอดสดจากหน้าจอ - Demo server - เซิฟเวอร์สาธิต + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - ในโหมดนี้ หน้าจอของคุณจะถูกแสดงในแบบเต็มจอบนเครื่องคอมพิวเตอร์ทั้งหมดในขณะที่อุปกรณ์นำเข้าของผู้ใช้งานจะถูกล็อกไว้ + Demo + สาธิต - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Share your screen or allow a user to share his screen with other users. + แบ่งปันหน้าจอของคุณเอง หรืออนุญาตให้ผู้ใช้ได้แบ่งหน้าจอของเขาให้ผู้ใช้คนอื่น + + + Full screen demo + สาธิตแบบเต็มจอ + + + Share your own screen in fullscreen mode + แบ่งปันหน้าจอของคุณในโหมดเต็มหน้าจอ + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share your own screen in a window + แบ่งปันหน้าจอของคุณในหน้าต่างแยก + + + Share selected user's screen in fullscreen mode + + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + Share selected user's screen in a window + + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + + + + Please select only one user screen to share. + + + + All screens + หน้าจอทั้งหมด + DesktopAccessDialog @@ -1358,56 +1694,56 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - Programs & websites - + Name + ชื่อ - Predefined programs + Path - Name - ชื่อ + Predefined websites + - Path + Remove selected website - Add new program - เพิ่มโปรแกรมใหม่ + URL + URL - Remove selected program - ลบโปรแกรมที่เลือก + New website + เว็บไซต์ใหม่ - Predefined websites + Applications & websites - Remove selected website + Predefined applications - URL - URL + Add new application + - New program - โปรแกรมใหม่ + Remove selected application + - New website - เว็บไซต์ใหม่ + Add new website + + + + New application + แอพพลิเคชั่นใหม่ DesktopServicesFeaturePlugin - - Run program - สั่งเปิดโปรแกรม - Open website เปิดเว็บไซต์ @@ -1417,28 +1753,32 @@ The public key is used on client computers to authenticate incoming connection r คลิกที่ปุ่มนี้เพื่อเปิดเว็บไซต์ทั้งหมด - Start programs and services in user desktop - + Open website "%1" + เปิดเว็บไซต์ "%1" - Click this button to run a program on all computers. - คลิกปุ่มนี้เพื่อสั่งเปิดโปรแกรมบนเครื่องคอมพิวเตอร์ทุกเครื่อง + Custom website + เว็บไซต์กำหนดเอง - Run program "%1" - สั่งเปิดโปรแกรม "%1" + Start application + เริ่มแอพพลิเคชั่น - Custom program - โปรแกรมกำหนดเอง + Click this button to start an application on all computers. + - Open website "%1" - เปิดเว็บไซต์ "%1" + Start application "%1" + - Custom website - เว็บไซต์กำหนดเอง + Custom application + + + + Start apps and open websites in user sessions + @@ -1471,10 +1811,6 @@ The public key is used on client computers to authenticate incoming connection r Play tutorial video - - Custom program - โปรแกรมกำหนดเอง - Handout @@ -1483,19 +1819,27 @@ The public key is used on client computers to authenticate incoming connection r Texts to read + + generic-student-user + + + + Custom application + + ExternalVncServer External VNC server - + เซิฟเวอร์ VNC ภายนอก ExternalVncServerConfigurationWidget External VNC server configuration - + การตั้งค่าเซิฟเวอร์ VNC ภายนอก Port: @@ -1507,9 +1851,164 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands + + List names of all available features + + + + Show table with details of all available features + + + + Start a feature on a remote host + + + + Stop a feature on a remote host + + + + Please specify the command to display help for. + + + + Displays a list with the names of all available features. + + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + + + + HOST ADDRESS + + + + FEATURE + + + + ARGUMENTS + + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + + + + Lock the screen + ล็อกหน้าจอ + + + Display a text message + แสดงข้อความตัวอักษร + + + Test message + + + + Start an application + + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + + + + Unlock the screen + ปลดล็อกหน้าจอ + + + The specified command does not exist or no help is available for it. + + + + Name + ชื่อ + + + Description + + + + Master + + + + Service + + + + Worker + + + + UID + + + + Plugin + + + + Invalid feature name or UID specified + + + + Error parsing the JSON-encoded arguments: %1 + + + + Failed to initialize credentials + + + + Could not establish a connection to host %1 + + + + Failed to send feature control message to host %1 + + + + Feature-related CLI operations + + + + Commands for controlling features + + + + + FileTransferConfigurationPage + + File transfer + การถ่ายโอนไฟล์ + + + Directories + + + + Destination directory + + - Feature control + Default source directory + + + + Options + ตัวเลือก + + + Remember last source directory + + + + Create destination directory if it does not exist @@ -1555,6 +2054,13 @@ The public key is used on client computers to authenticate incoming connection r บันทึกทับไฟล์ที่มีอยู่แล้ว + + FileTransferFileDialog + + Select one or more files to transfer + เลือกไฟล์อย่างน้อยหนึ่งไฟล์เพื่อนำไปถ่ายโอน + + FileTransferPlugin @@ -1563,11 +2069,11 @@ The public key is used on client computers to authenticate incoming connection r Click this button to transfer files from your computer to all computers. - + คลิกที่ปุ่มนี้เพื่อถ่ายโอนไฟล์ในคอมพิวเตอร์ของคุณไปยังคอมพิวเตอร์ทุกเครื่อง Select one or more files to transfer - + เลือกไฟล์อย่างน้อยหนึ่งไฟล์เพื่อนำไปถ่ายโอน Transfer files to remote computer @@ -1590,7 +2096,7 @@ The public key is used on client computers to authenticate incoming connection r GeneralConfigurationPage User interface - + ส่วนติดต่อผู้ใช้ Language: @@ -1612,10 +2118,6 @@ The public key is used on client computers to authenticate incoming connection r Log file directory - - ... - ... - Log level @@ -1656,18 +2158,6 @@ The public key is used on client computers to authenticate incoming connection r Log to standard error output - - Network object directory - - - - Backend: - - - - Update interval: - - %1 service @@ -1704,102 +2194,79 @@ The public key is used on client computers to authenticate incoming connection r x x - - seconds - วินาที - Write to logging system of operating system - Authentication - การยืนยันตัวตน + TLS configuration + - Method: - วิธีการ: + Use certificate authority for TLS connections + - Logon authentication - การยืนยันตัวตนด้วยการลงชื่อเข้าใช้ + CA certificate file + - Key file authentication - การยืนยันตัวตนด้วยไฟล์กุญแจ + ... + ... - Test - ทดสอบ + Host certificate file + - Authentication is set up properly on this computer. - การยืนยันตัวตนถูกติดตั้งบนคอมพิวเตอร์ได้อย่างถูกต้องแล้ว + Host private key file + - Authentication keys are not set up properly on this computer. - การยืนยันตัวตนยังไม่ได้รับถูกติดตั้งบนคอมพิวเตอร์อย่างถูกต้อง + Style: + - Authentication test - การทดสอบการยืนยันตัวตน + Native + - - - InternetAccessControlConfigurationPage - Internet access control + Color scheme: - Backend: + Light - General settings - การตั้งค่าทั่วไป + Dark + - Backend settings + User groups - - - InternetAccessControlPlugin - Block access to the internet - - - - Allow access to the internet + Backend: - Show help about command + Include user groups from domain - Block internet - บล็อกอินเทอร์เน็ต - - - Click this button to block access to the internet. - คลิกปุ่มนี้ เพื่อปิดกั้นการเข้าถึงอินเทอร์เน็ต - - - Unblock internet - ปลดบล็อกอินเทอร์เน็ต - - - Click this button to allow access to the internet. + Missing user groups backend - Control access to the internet + No user groups plugin was found. Please check your installation! + + + HeadlessVncServer - Commands for controlling access to the internet + Headless VNC server @@ -1818,61 +2285,92 @@ The public key is used on client computers to authenticate incoming connection r - LdapConfigurationPage + LdapConfiguration - Basic settings - การตั้งค่าพื้นฐาน + LDAP connection failed + - General - ทั่วไป + Could not connect to the LDAP server. Please check the server parameters. + +%1 + - LDAP server and port + LDAP bind failed - Bind DN + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 - Bind password + LDAP bind successful - Anonymous bind + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - Use bind credentials + LDAP base DN test failed + การทดสอบ LDAP base DN ล้มเหลว + + + Could not query the configured base DN. Please check the base DN parameter. + +%1 - Base DN + LDAP base DN test successful + การทดสอบ LDAP base DN สำเร็จลุล่วง + + + The LDAP base DN has been queried successfully. The following entries were found: + +%1 - Fixed base DN + LDAP naming context test failed - e.g. dc=example,dc=org - เช่น dc=example,dc=org + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + - Discover base DN by naming context + LDAP naming context test successful - e.g. namingContexts or defaultNamingContext + The LDAP naming context has been queried successfully. The following base DN was found: +%1 - Environment settings + user tree - Object trees + User tree + + + + group tree + + + + Group tree + + + + computer tree @@ -1880,43 +2378,63 @@ The public key is used on client computers to authenticate incoming connection r - e.g. OU=Groups + computer group tree - User tree + Computer group tree - e.g. OU=Users - เช่น OU=Users + user objects + - e.g. OU=Computers - เช่น OU=Computers + User login name attribute + - Group tree + group members + สมาชิกกลุ่ม + + + Group member attribute - Perform recursive search operations in object trees + Group not found + ไม่พบกลุ่ม + + + Could not find a group with the name "%1". Please check the group name or the group tree parameter. - Object attributes + computer objects - e.g. hwAddress + Computer display name attribute - e.g. member or memberUid + Invalid hostname - e.g. dNSHostName + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + + + + Computer hostname attribute + + + + computer MAC addresses @@ -1924,27 +2442,79 @@ The public key is used on client computers to authenticate incoming connection r - Group member attribute + computer locations - e.g. uid or sAMAccountName + Computer location attribute - Advanced settings - การตั้งค่าขั้นสูง + Location name attribute + - Optional object filters + users - Filter for user groups + user groups - Filter for users + computers + + + + computer groups + + + + computer containers + + + + groups of user + + + + User not found + ไม่พบผู้ใช้ + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + + + + groups of computer + + + + Computer not found + ไม่พบคอมพิวเตอร์ + + + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + + + + Hostname lookup failed + + + + Could not lookup hostname for IP address %1. Please check your DNS server settings. + + + + location entries + + + + Computer groups filter + + + + Computer locations identification @@ -1952,204 +2522,270 @@ The public key is used on client computers to authenticate incoming connection r - Group member identification + Invalid test value - Distinguished name (Samba/AD) + An empty or invalid value has been supplied for this test. - List all groups of a user + LDAP %1 test failed + การทดสอบ LDAP %1 ล้มเหลว + + + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 - List all groups of a computer + LDAP %1 test successful + การทดสอบ LDAP %1 สำเร็จลุล่วง + + + The %1 has been queried successfully and %2 entries were found. - Get computer object by IP address + LDAP test failed + การทดสอบ LDAP ล้มเหลว + + + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 - LDAP connection failed + and - LDAP bind failed + LDAP test successful + การทดสอบ LDAP สำเร็จลุล่วง + + + %1 %2 have been queried successfully: + +%3 - LDAP bind successful + LDAP filter test failed - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 - LDAP base DN test failed - การทดสอบ LDAP base DN ล้มเหลว + LDAP filter test successful + - LDAP base DN test successful - การทดสอบ LDAP base DN สำเร็จลุล่วง + %1 %2 have been queried successfully using the configured filter. + - LDAP naming context test failed + LDAP directory + + + LdapConfigurationPage - LDAP naming context test successful + Basic settings + การตั้งค่าพื้นฐาน + + + General + ทั่วไป + + + LDAP server and port - The LDAP naming context has been queried successfully. The following base DN was found: -%1 + Bind DN - user tree + Bind password - group tree + Anonymous bind - computer tree + Use bind credentials - Enter username - ใส่ชื่อผู้ใช้ + Base DN + - Please enter a user login name (wildcards allowed) which to query: + Fixed base DN - user objects + e.g. dc=example,dc=org + เช่น dc=example,dc=org + + + Discover base DN by naming context - Enter group name + e.g. namingContexts or defaultNamingContext - Please enter a group name whose members to query: + Environment settings - group members - สมาชิกกลุ่ม + Object trees + - Group not found - ไม่พบกลุ่ม + Computer tree + - Could not find a group with the name "%1". Please check the group name or the group tree parameter. + e.g. OU=Groups - Enter computer name + User tree - computer objects + e.g. OU=Users + เช่น OU=Users + + + e.g. OU=Computers + เช่น OU=Computers + + + Group tree - Enter computer DN + Perform recursive search operations in object trees - Please enter the DN of a computer whose MAC address to query: + Object attributes - computer MAC addresses + e.g. hwAddress - users + e.g. member or memberUid - user groups + e.g. dNSHostName - computer groups + Computer MAC address attribute - Please enter a user login name whose group memberships to query: + Group member attribute - groups of user + e.g. uid or sAMAccountName - User not found - ไม่พบผู้ใช้ + Advanced settings + การตั้งค่าขั้นสูง - groups of computer + Optional object filters - Computer not found + Filter for user groups - Enter computer IP address + Filter for users - Please enter a computer IP address which to resolve to an computer object: + Filter for computer groups - computers + Group member identification + + + + Distinguished name (Samba/AD) + + + + List all groups of a user + + + + List all groups of a computer + + + + Get computer object by IP address + + + + Enter username + ใส่ชื่อผู้ใช้ + + + Please enter a user login name (wildcards allowed) which to query: - LDAP %1 test failed - การทดสอบ LDAP %1 ล้มเหลว + Enter group name + - LDAP %1 test successful - การทดสอบ LDAP %1 สำเร็จลุล่วง + Please enter a group name whose members to query: + - The %1 has been queried successfully and %2 entries were found. + Enter computer name - %1 %2 have been queried successfully: - -%3 + Enter computer DN - LDAP filter test failed + Please enter the DN of a computer whose MAC address to query: - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 + Please enter a user login name whose group memberships to query: - LDAP filter test successful + Enter computer IP address - %1 %2 have been queried successfully using the configured filter. + Please enter a computer IP address which to resolve to an computer object: @@ -2160,10 +2796,6 @@ The public key is used on client computers to authenticate incoming connection r Computer group tree - - computer group tree - - Filter for computers @@ -2244,40 +2876,10 @@ The public key is used on client computers to authenticate incoming connection r e.g. (objectClass=container) or (objectClass=organizationalUnit) เช่น (objectClass=container) หรือ (objectClass=organizationalUnit) - - Could not query the configured base DN. Please check the base DN parameter. - -%1 - - - - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - - - - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - - Certificate files (*.pem) - - Could not connect to the LDAP server. Please check the server parameters. - -%1 - - - - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - - Encryption protocol @@ -2334,10 +2936,6 @@ The public key is used on client computers to authenticate incoming connection r Please enter the name of a computer location (wildcards allowed): กรุณากรอกชื่อของสถานที่ของคอมพิวเตอร์ (อนุญาตใช้อักขระแทนได้ เช่น ดอกจัน): - - computer locations - - Enter location name @@ -2346,34 +2944,6 @@ The public key is used on client computers to authenticate incoming connection r Please enter the name of a location whose entries to query: - - location entries - - - - LDAP test failed - การทดสอบ LDAP ล้มเหลว - - - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - - - - and - - - - LDAP test successful - การทดสอบ LDAP สำเร็จลุล่วง - - - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - - Browse @@ -2395,51 +2965,50 @@ The public key is used on client computers to authenticate incoming connection r - Invalid hostname - - - - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Enter hostname - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Please enter a computer hostname whose group memberships to query: - Could not find a user with the name "%1". Please check the username or the user tree parameter. + User login name attribute - Enter hostname + Configured attribute for user login name or computer hostname (OpenLDAP) - Please enter a computer hostname whose group memberships to query: + Directory name - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Query options - Hostname lookup failed + Query nested user groups (supported by AD only) - Could not lookup hostname for IP address %1. Please check your DNS server settings. + Query timeout - User login name attribute - + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - Configured attribute for user login name or computer hostname (OpenLDAP) - + LDAP + LDAP - computer containers + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. @@ -2489,225 +3058,47 @@ The public key is used on client computers to authenticate incoming connection r Configuring %1 as base DN and disabling naming context queries. - - - LdapProConfigurationPage - - LDAP Pro - LDAP Pro - - - Instances - - - - Enter name - ใส่ชื่อ - - - Please enter a name for the instance (can't be changed later!): - - - - Remove instance - - - - Do you really want to remove instance "%1"? - - - - Configuration for instance "%1" - - - - - LdapProPlugin - - Professional LDAP/AD integration for Veyon - - - - %1 (load computers and locations from LDAP/AD) - - - - %1 (load users and groups from LDAP/AD) - - - - - LicensingConfigurationPage - - Licensing - - - - Installed licenses - ใบอนุญาตที่ติดตั้งอยู่ - - - Add new network range - - - - Remove selected network range - - - - ID - ID - - - Feature - - - - Valid until - ใช้ได้จนถึง - - - Licensee - ผู้ขอรับใบอนุญาต - - - Browse license file - เปิดหาไฟล์ใบอนุญาต - - - Veyon license files (*.vlf) - ไฟล์ใบอนุญาต Veyon (*.vlf) - - - Remove license - ลบใบอนุญาต - - - Do you really want to remove the selected license? - - - - <N/A> - <N/A> - - - Invalid license file - - - - Could not open the license file for reading! - - - The selected license file does not contain valid data. + Test binding to an LDAP server - The selected license file could not be verified. + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - The selected license file is not valid for this installation. - - - - The selected license file is expired. - - - - The license is already installed. - - - - Information - - - - Installation ID - - - - Addons available for licensing - - - - Addon + LDAP bind - LicensingPlugin - - Show help for specific command - - - - Show all installed licenses - - - - Add license file - - - - Remove installed license - - - - -USAGE - -%1 add <LICENSE FILE> - - - - - - -USAGE - -%1 remove <LICENSE ID> - - - - + LinuxPlatformConfigurationPage - No certificate found with given ID + Linux - <N/A> - <N/A> - - - Licensing management + Custom PAM service for user authentication - Commands for managing license keys - + User authentication + การยืนยันตัวตนผู้ใช้ - - - LinuxPlatformConfigurationPage - Linux + User sessions - Custom PAM service for user authentication + Minimum session lifetime before server start - User authentication - การยืนยันตัวตนผู้ใช้ - - - Session management + User login - Display manager users + Login key sequence @@ -2717,10 +3108,6 @@ USAGE Plugin implementing abstract functions for the Linux platform - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2730,7 +3117,7 @@ USAGE enter search filter... - + กรอกตัวกรองการค้นหา... @@ -2739,14 +3126,14 @@ USAGE Configuration - - Disable balloon tooltips - - Show icons only แสดงไอคอนเท่านั้น + + Disable tooltips + + MainWindow @@ -2794,10 +3181,6 @@ USAGE About Qt เกี่ยวกับ Qt - - Authentication impossible - - Configuration not writable @@ -2858,10 +3241,6 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - - Access denied การเข้าถึงถูกปฏิเสธ @@ -2880,7 +3259,7 @@ USAGE The feature "%1" is still active. Please stop it before closing %2. - + ฟีเจอร์ "%1" ยังถูกในระหว่างการใช้งานอยู่ กรุณาหยุดการใช้งานก่อนปิด %2 Reset configuration @@ -2892,11 +3271,7 @@ USAGE Search users and computers - - - - Adjust optimal size - + ค้นหาผู้ใช้และคอมพิวเตอร์ Align computers to grid @@ -2924,15 +3299,15 @@ USAGE &View - + &มุมมอง &Standard - + &มาตรฐาน &Advanced - + &ขั้นสูง Use custom computer arrangement @@ -2940,6 +3315,48 @@ USAGE Locations && computers + สถานที่ && คอมพิวเตอร์ + + + Authentication + การยืนยันตัวตน + + + Adjust size of computer icons automatically + ตั้งค่าขนาดไอคอนคอมพิวเตอร์โดยอัตโนมัติ + + + Slideshow + สไลด์โชว์ + + + Spotlight + สปอร์ตไลท์ + + + Veyon Master + + + + Locations & computers + สถานที่และคอมพิวเตอร์ + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + + + + Only show computers with logged on users + + + + Load computer positions + + + + Save computer positions @@ -2949,10 +3366,6 @@ USAGE Directories - - ... - ... - User configuration @@ -3003,11 +3416,11 @@ USAGE Actions such as rebooting or powering down computers - + การกระทำอย่างเช่นการสั่งบู๊ตเครื่องใหม่ หรือการสั่งปิดคอมพิวเตอร์ User interface - + ส่วนติดต่อผู้ใช้ Background color @@ -3037,6 +3450,10 @@ USAGE Only user name เฉพาะชื่อผู้ใช้ + + Only last part of user name + + Only computer name เฉพาะชื่อคอมพิวเตอร์ @@ -3086,164 +3503,179 @@ USAGE - Automatically adjust computer thumbnail size + Automatically open computer select panel - Automatically open computer select panel + Use modern user interface (experimental) - - - MonitoringMode - Monitoring - สังเกตการณ์ + Thumbnail spacing + - Builtin monitoring mode + px - This mode allows you to monitor all computers at one or more locations. + Hide local session - - - NetworkDiscoveryConfigurationPage - Network discovery - การค้นพบเครือข่าย + Auto + - Mode - โหมด + Thumbnail aspect ratio + - Scan network ranges - สแกนระยะเครือข่าย + Automatically adjust computer icon size + ปรับเปลี่ยนขนาดไอคอนของคอมพิวเตอร์โดยอัตโนมัติ - e.g. 192.168.1.0/24 - เช่น 192.168.1.0/24 + Open feature windows on the same screen as the main window + - Scan all subnets of computer + Configuration templates - Scan custom subnet + Image quality in monitoring mode - Scan sessions on local computer + Highest - Test - ทดสอบ + High + - Network ranges - ระยะเครือข่าย + Medium + - Add new group - เพิ่มกลุ่มใหม่ + Low + - Remove selected group - ลบกลุ่มที่เลือก + Lowest + - Groups - กลุ่ม + Remote access image quality + - First address - ที่อยู่แรก + Advanced + - Last address - ที่อยู่สุดท้าย + Computer name source + - Add new network range + Default - Remove selected network range + Host address + โฮสแอดแดรส + + + Session client address - Parallel scans - สแกนคู่ขนาน + Session client name + - Scan timeout - กำหนดการหมดเวลาการสแกน + Session host name + - ms - ms + Session metadata + - Session scan limit + Full name of user - Options - ตัวเลือก + User login name + - Reverse lookup discovered IP addresses to host names + Computer UID role - New location - สถานที่ใหม่ + Session meta data hash + - - - NetworkDiscoveryDirectory - Scanning... - กำลังสแกน... + Always expand all locations + - Discovered computers - คอมพิวเตอร์ที่พบ + Image quality + - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command + Monitoring + สังเกตการณ์ + + + Builtin monitoring mode + + + + This mode allows you to monitor all computers at one or more locations. + โหมดนี้จะให้คุณได้สังเกตการณ์คอมพิวเตอร์ทุกเครื่องจากสถานที่ใดสถานที่หนึ่งหรือมากกว่านั้น + + + Query application version of the server - Scan a subnet + Query active features - -USAGE - -%1 scan [<SUBNET>] - - + Query properties of remotely available screens + + + NestedNetworkObjectDirectory - Network object directory which automatically discovers computers in the network + All directories + + + NetworkObjectDirectoryConfigurationPage - Network discovery (scan network for Veyon clients) + Update interval: - Commands for managing the network discovery directory + seconds + วินาที + + + + NetworkObjectDirectoryConfigurationPageTab + + Enabled @@ -3280,31 +3712,43 @@ USAGE Name: ชื่อ: + + Website name + ชื่อเว็บไซต์ + - PasswordDialog + PluginCommands - Username - ชื่อผู้ใช้ + List names of all installed plugins + - Password - รหัสผ่าน + Show table with details of all installed plugins + - Veyon Logon + Name + ชื่อ + + + Description - Authentication error - การยืนยันตัวตนผิดพลาด + Version + - Logon failed with given username and password. Please try again! + UID - Please enter your username and password in order to access computers. + Plugin-related CLI operations + + + + Commands for managing plugins @@ -3332,7 +3776,7 @@ USAGE Click this button to power down all computers. This way you do not have to power down each computer by hand. - + คลิกที่ปุ่มนี้เพื่อทำการสั่งปิดเครื่องคอมพิวเตอร์ทั้งหมด วิธีนี้จะทำให้คุณไม่จำเป็นต้องเดินไปปิดคอมพิวเตอร์ด้วยตัวเองทีละเครื่อง Power on/down or reboot a computer @@ -3350,10 +3794,6 @@ USAGE Do you really want to reboot the selected computers? - - Do you really want to power down the selected computer? - - Power on a computer via Wake-on-LAN (WOL) เปิดเครื่องคอมพิวเตอร์โดยใช้ Wake-on-LAN (WOL) @@ -3396,12 +3836,25 @@ USAGE The computer was remotely requested to power down. Do you want to power down the computer now? - + คอมพิวเตอร์ได้รับการร้องขอจากระยะไกลให้ปิดเครื่องลง คุณต้องการปิดเครื่องลงตอนนี้หรือไม่? The computer will be powered down in %1 minutes, %2 seconds. Please save your work and close all programs. + คอมพิวเตอร์จะปิดลงใน %1 นาที %2 วินาที +กรุณาบันทึกงานให้เรียบร้อยแล้วปิดโปรแกรมทุกโปรแกรม + + + Do you really want to reboot <b>ALL</b> computers? + + + + Do you really want to power down <b>ALL</b> computers? + + + + Do you really want to power down the selected computers? @@ -3440,7 +3893,7 @@ Please save your work and close all programs. Open a remote control window for a computer. - + เปิดหน้าต่างการเข้าควบคุมระยะไกลสำหรับคอมพิวเตอร์ Remote access @@ -3451,11 +3904,22 @@ Please save your work and close all programs. ดูจากระยะไกลหรือเข้าควบคุมคอมพิวเตอร์ - Please enter the hostname or IP address of the computer to access: + Show help about command + + + + Exchange clipboard contents - Show help about command + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + + + RemoteAccessPage + + Remote access: %1 @@ -3465,6 +3929,10 @@ Please save your work and close all programs. %1 - %2 Remote Access + + %1 - %2 - %3 Remote Access + + RemoteAccessWidgetToolBar @@ -3520,10 +3988,6 @@ Please save your work and close all programs. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - กำลังเชื่อมต่อ %1 - Connected. เชื่อมต่อแล้ว @@ -3536,58 +4000,17 @@ Please save your work and close all programs. Exit ออก - - - Routing - - Control internet access by modifying routing table - - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - - - - Add custom route to block internet - ตั้งเส้นทางกำหนดเองเพื่อบล็อกอินเทอร์เน็ต - - - Destination - ปลายทาง - - Gateway - เกตเวย์ + Connecting... + กำลังเชื่อมต่อ... - - - RunProgramDialog - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. + Select screen - Run programs - สั่งเปิดโปรแกรม - - - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - เช่น "C:\Program Files\VideoLAN\VLC\vlc.exe" - - - Name: - ชื่อ: - - - Remember and add to program menu - จำไว้และเพิ่มไปยังเมนูโปรแกรม - - - e.g. VLC - เช่น VLC + All screens + หน้าจอทั้งหมด @@ -3606,6 +4029,18 @@ Please save your work and close all programs. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + เพื่อที่จะดึงความสนใจจากผู้ใช้ทั้งหมดให้กลับมา คุณสามารถล็อกคอมพิวเตอร์ของเขาโดยใช้ปุ่มนี้ ในโหมดนี้ อุปกรณ์ประเภทนำเข้าข้อมูล เช่น เมาส์ คีย์บอร์ด จะถูกล็อกและหน้าจอจะดับลง + + + Lock input devices + + + + Unlock input devices + + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. @@ -3623,6 +4058,10 @@ Please save your work and close all programs. Screenshot ภาพหน้าจอ + + Could not open screenshot file %1 for writing. + + ScreenshotFeaturePlugin @@ -3632,7 +4071,7 @@ Please save your work and close all programs. Use this function to take a screenshot of selected computers. - + ใช้ฟังก์ชั่นนี้เพื่อเก็บภาพหน้าจอจากคอมพิวเตอร์ที่เลือกไว้ Screenshots taken @@ -3647,6 +4086,13 @@ Please save your work and close all programs. + + ScreenshotManagementPage + + Screenshots + ภาพถ่ายหน้าจอ + + ScreenshotManagementPanel @@ -3670,12 +4116,51 @@ Please save your work and close all programs. เวลา: - Show - แสดง + Show + แสดง + + + Delete + ลบ + + + Screenshot + ภาพหน้าจอ + + + Do you really want to delete all selected screenshots? + + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + + + + User has denied access + - Delete - ลบ + User confirmed access + @@ -3708,25 +4193,13 @@ Please save your work and close all programs. State: - - Network - เครือข่าย - - - Demo server port - - Enable firewall exception - + เปิดใช้ข้อยกเว้นของไฟร์วอลล์ Allow connections from localhost only - - - - Internal VNC server port - + อนุญาตการเชื่อมต่อจาก localhost เท่านั้น VNC server @@ -3749,68 +4222,138 @@ Please save your work and close all programs. กำลังทำงาน - Feature manager port + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. - Primary service port + Show notification on remote connection + แสดงการแจ้งเตือนเมื่อมีการเชื่อมต่อจากระยะไกล + + + Show notification when an unauthorized access is blocked + แสดงการแจ้งเตือนเมื่อการเข้าถึงที่ไม่ได้รับอนุญาตถูกบล็อก + + + Maximum session count - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. + Network port numbers - Show notification on remote connection - แสดงการแจ้งเตือนเมื่อมีการเชื่อมต่อจากระยะไกล + Veyon server + - Multi session mode (for terminal and remote desktop servers) + Internal VNC server - Show notification when an unauthorized access is blocked + Feature manager - - - ServiceControl - Starting service %1 - กำลังเริ่มเซอร์วิส %1 + Demo server + เซิฟเวอร์สาธิต + + + Miscellaneous network settings + - Stopping service %1 - กำลังหยุดเซอร์วิส %1 + Session mode + - Registering service %1 - กำลังลงทะเบียนเซอร์วิส %1 + Local session mode (single server instance for primary local session) + - Unregistering service %1 - กำลังถอนการลงทะเบียนเซอร์วิส %1 + Active session mode (single server instance for active local or remote session) + - Service control - การควบคุมเซอร์วิส + Multi session mode (distinct server instance for each local and remote desktop session) + + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + + + + Miscellaneous settings + + + + Disable clipboard synchronization + + + + Session metadata + + + + Content + + + + None + ไม่มี + + + Value of an environment variable + + + + Value of a registry key + + + + Environment variable name: + + + + Registry key name: + + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + - ServiceControlPlugin + ServiceControl - Service is running - เซอร์วิสกำลังทำงาน + Service control + การควบคุมเซอร์วิส - Service is not running - เซอร์วิสไม่ได้ทำงาน + Starting %1 + - Configure and control Veyon service + Stopping %1 + + + + Restarting %1 + + + + Registering %1 + + + + Unregistering %1 + + + ServiceControlCommands Register Veyon Service ลงทะเบียน Veyon Service @@ -3835,13 +4378,25 @@ Typically this is required to support terminal servers. Query status of Veyon Service + + Service is running + เซอร์วิสกำลังทำงาน + + + Service is not running + เซอร์วิสไม่ได้ทำงาน + + + Configure and control Veyon service + ตั้งค่าและควบคุม Veyon Service + Commands for configuring and controlling Veyon Service - ShellCommandLinePlugin + ShellCommands Run command file @@ -3851,7 +4406,7 @@ Typically this is required to support terminal servers. ไฟล์ "%1" ไม่มีอยู่! - Interactive shell and script execution for Veyon Control + Interactive shell and script execution for Veyon CLI @@ -3859,6 +4414,92 @@ Typically this is required to support terminal servers. + + SlideshowPanel + + Previous + + + + Start/pause + + + + Next + + + + Duration: + ระยะเวลา: + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + + + + Remove selected computers + + + + Update computers in realtime + + + + Spotlight + สปอร์ตไลท์ + + + Please select at least one computer to add. + + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + + + StartAppDialog + + Start application + เริ่มแอพพลิเคชั่น + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + เช่น "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + + + + Application name + ชื่อแอพพลิเคชั่น + + + Name: + ชื่อ: + + + e.g. VLC + เช่น VLC + + SystemTrayIcon @@ -3895,7 +4536,7 @@ Typically this is required to support terminal servers. ส่งข้อความอักษระ - Use the field below to type your message which will be sent to all selected users. + Please enter your message which send to all selected users. @@ -3930,36 +4571,52 @@ Typically this is required to support terminal servers. Low accuracy (turbo mode) - + ความแม่นยำต่ำ (โหมดเทอร์โบ) Builtin UltraVNC server configuration - + การตั้งค่าเซิฟเวอร์ UltraVNC ในตัว Enable multi monitor support - + เปิดใช้การสนับสนุนการแสดงหลายหน้าจอ Enable Desktop Duplication Engine on Windows 8 and newer + + Maximum CPU usage + + - UserConfig + UserLoginDialog - No write access + User login - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Please enter a username and password for automatic login on all computers. + + Username + ชื่อผู้ใช้ + + + Password + รหัสผ่าน + - UserSessionControl + UserSessionControlPlugin - User session control + Log in + + + + Click this button to log in a specific user on all computers. @@ -3978,6 +4635,14 @@ Typically this is required to support terminal servers. Do you really want to log off the selected users? คุณต้องการล็อกออฟผู้ใช้ที่เลือกไว้หรือไม่ + + User session control + + + + Do you really want to log off <b>ALL</b> users? + + VeyonCore @@ -4029,10 +4694,6 @@ Typically this is required to support terminal servers. ERROR - - licensed for - ได้รับอนุญาต สำหรับ - USAGE @@ -4049,19 +4710,31 @@ Typically this is required to support terminal servers. WARNING + + Authentication test + การทดสอบการยืนยันตัวตน + + + Screen %1 + + - VeyonServiceControl + VeyonMaster - Veyon Service - Veyon Service + No write access + + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + - VncView + VeyonServiceControl - Establishing connection to %1 ... - กำลังสร้างการเชื่อมต่อไปยัง %1 ... + Veyon Service + Veyon Service @@ -4109,6 +4782,30 @@ Typically this is required to support terminal servers. Use alternative user authentication mechanism + + User login + + + + Input start delay + + + + Simulated key presses interval + + + + Confirm legal notice (message displayed before user logs in) + + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4117,7 +4814,7 @@ Typically this is required to support terminal servers. - Plugin implementing specific functions for the Windows platform + Internal display @@ -4127,28 +4824,32 @@ Typically this is required to support terminal servers. The service "%1" is already installed. เซอร์วิส "%1" ถูกติดตั้งอยู่ก่อนแล้ว - - The service "%1" could not be installed. - เซอร์วิส "%1" ไม่สามารถทำการติดตั้งได้ - The service "%1" has been installed successfully. เซอร์วิส "%1" ได้รับการติดตั้งอย่างเสร็จสมบูรณ์แล้ว - - The service "%1" could not be uninstalled. - เซอร์วิส "%1" ไม่สามารถทำการยกเลิกการติดตั้งได้ - The service "%1" has been uninstalled successfully. เซอร์วิส "%1" ได้รับการยกเลิกการติดตั้งอย่างเสร็จสมบูรณ์แล้ว - The start type of service "%1" could not be changed. + Service "%1" could not be found. - Service "%1" could not be found. + The service "%1" could not be installed (error %2). + + + + Could not change the failure actions config for service "%1" (error %2). + + + + The service "%1" could not be uninstalled (error %2). + + + + The start type of service "%1" could not be changed (error %2). diff --git a/translations/tr.ts b/translations/veyon_tr.ts similarity index 57% rename from translations/tr.ts rename to translations/veyon_tr.ts index fe2b7ec28..368a05844 100644 --- a/translations/tr.ts +++ b/translations/veyon_tr.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -27,7 +27,7 @@ Website: - Web Sitesi: + İnternet Sitesi: Current language not translated yet (or native English). @@ -39,7 +39,7 @@ Veyon'u kendi dilinizde veya başka bir dile çevirmek istiyorsanız veya v About %1 %2 -  %1 %2 Hakkında + %1 %2 Hakkında Support Veyon project with a donation @@ -58,7 +58,7 @@ Veyon'u kendi dilinizde veya başka bir dile çevirmek istiyorsanız veya v Test - Sına + Test Process access control rules @@ -66,23 +66,19 @@ Veyon'u kendi dilinizde veya başka bir dile çevirmek istiyorsanız veya v User groups authorized for computer access - Bilgisayar erişimi için yetkili kullanıcı kümeleri + Bilgisayar erişimi için yetkilendirilmiş kullanıcı grupları Please add the groups whose members should be authorized to access computers in your Veyon network. - Veyon ağınızdaki bilgisayarlara erişmeye yetkili olacak kullanıcıları içeren kümeleri ekleyin. + Lütfen Veyon ağınızdaki bilgisayarlara erişim yetkisi verilmesi gereken üyelerin gruplarını ekleyin. Authorized user groups - Yetkili kullanıcı kümeleri + Yetkili kullanıcı grupları All groups - Tüm kümeler - - - ... - ... + Tüm gruplar Access control rules @@ -114,7 +110,7 @@ Veyon'u kendi dilinizde veya başka bir dile çevirmek istiyorsanız veya v Please enter a user login name whose access permissions to test: - Sınamak için izinlere erişecek bir kullanıcı giriş adı girin: + Lütfen test etmek için erişim izinlerine sahip bir kullanıcı oturum açma adı girin: Access allowed @@ -134,23 +130,22 @@ Veyon'u kendi dilinizde veya başka bir dile çevirmek istiyorsanız veya v Enable usage of domain groups - Alan adı kümelerinin kullanımını etkinleştir + Etki alanı gruplarının kullanımını etkinleştir User groups backend: - Kullanıcı kümeleri arka ucu: + Kullanıcı grupları arka ucu: - Missing user groups backend - Eksik kullanıcı kümeleri arka ucu - - - No default user groups plugin was found. Please check your installation! - Öntanımlı kullanıcı kümeleri eklentisi bulunamadı. Lütfen kurulumunuzu gözden geçirin! + Restrict access to members of specific user groups + Giriş yetkisini sadece belirli kullanıcı grup üyeleriyle sınırla + + + AccessControlProvider - Restrict access to members of specific user groups - + Provider for access control features + Erişim denetimi özellikleri sağlayıcısı @@ -179,30 +174,10 @@ Veyon'u kendi dilinizde veya başka bir dile çevirmek istiyorsanız veya v Rule description: Kural açıklaması: - - Invert all conditions ("is/has" interpreted as "is/has not") - Tüm koşulları tersine çevir ("is/has" [-dır], "is/has not" [...değildir] olarak yorumlanır) - Conditions Koşullar - - is member of group - kümenin üyesidir - - - Accessing computer is localhost - - - - Accessing user is logged on user - Erişilen kullanıcı oturumu açmış - - - Accessing user is already connected - Erişilen kullanıcı zaten bağlı - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. Eğer birden çok koşul etkinse, kuralın uygulanması için her koşulun yerine getirilmesi gerekiyorsa (mantıksal VE). Eğer birden çok koşulun yalnızca birinin yerine getirilmesi gerekiyorsa (mantıksal VEYA) lütfen çoğul erişim denetimi kuralları oluşturun. @@ -236,32 +211,124 @@ Veyon'u kendi dilinizde veya başka bir dile çevirmek istiyorsanız veya v Bilgisayara erişim - Local (logged on) user - Yerel (oturum açmış) kullanıcı + Always process rule and ignore conditions + Her zaman kuralı işle ve koşulları yok say - Local computer - Yerel bilgisayar + Accessing computer and local computer + Bilgisayara ve yerel bilgisayara erişim - Always process rule and ignore conditions - Her zaman kuralı işle ve koşulları yok say + User being accessed + Kullanıcıya erişiliyor - No user logged on - Oturum açan kullanıcı yok + is logged in locally + yerel olarak oturum açıldı - Accessing user has one or more groups in common with local (logged on) user - Erişilen kullanıcı, yerel (oturum açmış) kullanıcıyla ortak bir veya daha çok kümeye sahip + is logged in remotely + uzaktan oturum açıldı - Accessing computer and local computer are at the same location - + No user is logged in locally + Yerel olarak oturum açmış kullanıcı yok + + + One or multiple users are logged in locally + Bir veya birden fazla kullanıcı yerel olarak oturum açmış durumda + + + No user is logged in remotely + Uzaktan oturum açmış kullanıcı yok + + + One or multiple users are logged in remotely + Bir veya birden fazla kullanıcı uzaktan oturum açtı is located at - + bulunduğu yer + + + is not located at + konumda bulunmuyor + + + are located at the same location + aynı yerde bulunmaktadır + + + are not located the same location + aynı yerde bulunmuyor + + + is member of group + grubun üyesidir + + + is not member of group + grubun üyesi değil + + + is authenticated via + aracılığıyla doğrulandı + + + is not authenticated via + aracılığıyla doğrulanmadı + + + has one or more groups in common with user being accessed + erişilen kullanıcıyla ortak bir veya daha fazla gruba sahip + + + has no groups in common with user being accessed + erişilen kullanıcıyla ortak hiçbir grup yok + + + equals user being accessed + erişilen kullanıcıya eşittir + + + is different from user being accessed + erişilen kullanıcıdan farklıdır + + + is already connected + zaten bağlı + + + is not connected + bağlı değil + + + is local computer + yerel bilgisayar + + + is not local computer + yerel bilgisayar değil + + + Computer being accessed + Bilgisayara erişiliyor + + + Session being accessed is a user session + Erişilen oturum bir kullanıcı oturumudur + + + Session being accessed is a login screen + Erişilen oturum bir giriş ekranıdır + + + Local computer is already being accessed + Yerel bilgisayara zaten erişiliyor + + + Local computer is not yet being accessed + Yerel bilgisayara henüz erişilemiyor @@ -307,41 +374,43 @@ Veyon'u kendi dilinizde veya başka bir dile çevirmek istiyorsanız veya v Verilen senaryodaki erişim, oturum açmış kullanıcının iznini gerektiriyor. - ERROR: Unknown action - HATA: Bilinmeyen eylem + Test result + Test sonucu + + + Authentication method + Kimlik doğrulama yöntemi - Test result - Sınama sonuçları + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformConfigurationPage + AuthKeysConfigurationWidget - Android - + Introduction + Giriş - General - Genel + Please perform the following steps to set up key file authentication: + Anahtar dosyası yetkilendirmesi için lütfen bu adımları gerçekleştirin: - - - AndroidPlatformPlugin - Plugin implementing specific functions for the Android platform - + 1) Create a key pair on the master computer. + 1) Ana bilgisayarda anahtar çifti oluşturun. - - - AuthKeysConfigurationPage - Authentication keys - Yetkilendirme anahtarları + 2) Set an access group whose members should be allowed to access other computers. + 2) Diğer bilgisayarlara giriş yetkisi olan bir giriş grubu oluşturun. - Introduction - Giriş + 3) Export the public key and import it on all client computers with the same name. + 3) Genel anahtarı dışarı verin ve tüm katılımcı bilgisayarlara aynı isimle ekleyin. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Lütfen <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Yönetici Kılavuzuna </a> daha fazla bilgi için göz atın. Key file directories @@ -356,12 +425,18 @@ Veyon'u kendi dilinizde veya başka bir dile çevirmek istiyorsanız veya v Özel anahtar dizin yolu - ... - ... + Available authentication keys + Kullanılabilir yetkilendirme anahtarları - Available authentication keys - + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Bir kimlik doğrulama anahtarı çifti, özel ve genel anahtar olmak üzere iki bağlantılı şifreleme anahtarından oluşur. +Özel anahtar, ana bilgisayardaki kullanıcıların istemci bilgisayarlara erişmesine olanak tanır. +Özel anahtar dosyasına yalnızca yetkili kullanıcıların okuma erişimi olması önemlidir. +Genel anahtar, istemci bilgisayarlarda gelen bağlantı isteğinin kimliğini doğrulamak için kullanılır. Create key pair @@ -381,7 +456,7 @@ Veyon'u kendi dilinizde veya başka bir dile çevirmek istiyorsanız veya v Set access group - + Erişim grubunu ayarla Key files (*.pem) @@ -393,7 +468,7 @@ Veyon'u kendi dilinizde veya başka bir dile çevirmek istiyorsanız veya v Please enter the name of the user group or role for which to create an authentication key pair: - Lütfen yetkilendirme anahtarı çifti oluşturulacak kullanıcı kümesinin veya rolün adını girin: + Lütfen kimlik doğrulama anahtar çifti oluşturmak istediğiniz kullanıcı grubu veya rolünün adını girin: Do you really want to delete authentication key "%1/%2"? @@ -403,48 +478,25 @@ Veyon'u kendi dilinizde veya başka bir dile çevirmek istiyorsanız veya v Please select a key to delete! Lütfen silinecek anahtar seçin! - - Please enter the name of the user group or role for which to import the authentication key: - Lütfen içe aktarılacak yetkilendirme anahtarı için kullanıcı kümesinin veya rolün adını girin: - Please select a key to export! Lütfen dışa aktarılacak anahtar seçin! Please select a user group which to grant access to key "%1": - + Lütfen "%1" anahtarına erişim izni verilecek bir kullanıcı grubu seçin: Please select a key which to set the access group for! - - - - Please perform the following steps to set up key file authentication: - - - - 1) Create a key pair on the master computer. - - - - 2) Set an access group whose members should be allowed to access other computers. - - - - 3) Export the public key and import it on all client computers with the same name. - - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - + Lütfen erişim grubunu ayarlamak için bir anahtar seçin! - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + Lütfen kimlik doğrulama anahtarının içe aktarılacağı kullanıcı grubu veya rolünün adını girin. + +Birbirine ait anahtarların isimlerinin tüm bilgisayarlarda aynı olduğundan emin olun. @@ -515,7 +567,7 @@ The public key is used on client computers to authenticate incoming connection r File "%1" does not contain a valid public key! - "%1" dosyası geçerli genel anahtar içermiyor! + "%1" dosyası geçerli genel anahtar içermiyor! Failed to create directory for key file. @@ -523,11 +575,11 @@ The public key is used on client computers to authenticate incoming connection r Failed to write key file "%1". - "%1" anahtar dosyasına yazılamadı. + "%1" anahtar dosyasına yazılamadı. Failed to set permissions for key file "%1"! - "%1" anahtar dosyası için izinler ayarlanamadı! + "%1" anahtar dosyası için izinler ayarlanamadı! Key "%1/%2" has been imported successfully. Please check file permissions of "%3" in order to prevent unauthorized accesses. @@ -575,7 +627,7 @@ The public key is used on client computers to authenticate incoming connection r <N/A> - + <N/A> Failed to read key file. @@ -610,71 +662,87 @@ The public key is used on client computers to authenticate incoming connection r Set user group allowed to access a key - + Bir anahtara erişmesine izin verilen kullanıcı grubunu ayarla KEY - + ANAHTAR ACCESS GROUP - + ERİŞİM GRUBU This command adjusts file access permissions to <KEY> such that only the user group <ACCESS GROUP> has read access to it. - + Bu komut, dosya erişim izinlerini yalnızca <ACCESS GROUP> kullanıcı grubunun okuma erişimine sahip olacağı şekilde <KEY> olarak ayarlar. NAME - + İSİM FILE - + DOSYA This command exports the authentication key <KEY> to <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - + Bu komut, <KEY> kimlik doğrulama anahtarını <FILE> öğesine dışa aktarır. <FILE> belirtilmezse, <KEY> adından ve türünden bir ad oluşturulur. This command imports the authentication key <KEY> from <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - + Bu komut, <FILE> öğesinden <KEY> kimlik doğrulama anahtarını alır. <FILE> belirtilmezse, <KEY> adından ve türünden bir ad oluşturulur. This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. - - - - Please specify the command to display help for! - + Bu komut, yapılandırılmış anahtar dizinindeki tüm kullanılabilir kimlik doğrulama anahtarlarını listeler. "%1" seçeneği belirtilirse, bunun yerine anahtar ayrıntılarını içeren bir tablo görüntülenir. Bir anahtara erişilemiyorsa bazı ayrıntılar eksik olabilir; okuma izinlerinin olmaması nedeniyle. TYPE - + TİP PAIR ID - - - - Command line support for managing authentication keys - + ÇİFT ID Commands for managing authentication keys - + Kimlik doğrulama anahtarlarını yönetme komutları This command creates a new authentication key pair with name <NAME> and saves private and public key to the configured key directories. The parameter must be a name for the key, which may only contain letters. - + Bu komut, <NAME> adında yeni bir kimlik doğrulama anahtarı çifti oluşturur ve özel ve genel anahtarı yapılandırılmış anahtar dizinlerine kaydeder. Parametre, anahtar için yalnızca harf içerebilecek bir ad olmalıdır. This command deletes the authentication key <KEY> from the configured key directory. Please note that a key can't be recovered once it has been deleted. - + Bu komut, <KEY> kimlik doğrulama anahtarını yapılandırılmış anahtar dizininden siler. Bir anahtar silindikten sonra kurtarılamayacağını lütfen unutmayın. This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. - + Bu komut, ortak anahtar bölümünü <KEY> özel anahtarından çıkarır ve karşılık gelen ortak anahtar olarak kaydeder. Başka bir ana bilgisayar kurarken, yalnızca özel anahtarı aktarmak yeterlidir. Genel anahtar daha sonra çıkarılabilir. + + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + Kimlik doğrulama anahtarı dosyaları bu bilgisayarda düzgün ayarlanmamış. Lütfen yeni anahtar dosyaları oluşturun veya Veyon Configurator'ı kullanarak farklı bir kimlik doğrulama yöntemine geçin. + + + Key file authentication + Anahtar dosya yetkilendirmesi + + + Key file + Anahtar dosya + + + Please specify the key name (e.g. "teacher/public") as the first argument. + Lütfen ilk argüman olarak anahtar adını belirtin (örneğin "öğretmen/genel"). + + + Please specify the command to display help for. + Lütfen yardımın görüntüleneceği komutu belirtin. + + + The specified command does not exist or no help is available for it. + Belirtilen komut mevcut değil veya bu komut için yardım mevcut değil. @@ -685,97 +753,240 @@ The public key is used on client computers to authenticate incoming connection r Type - + Tür Access group - + Erişim grubu Pair ID - + Çift ID - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - Bilgisayarlar + General + Genel - Name - Ad + Username to bind DN mapping: + DN eşlemesini bağlamak için kullanıcı adı: - Host address/IP - Ana makine adresi/IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + AuthLdapDialog - MAC address - MAC adresi + Veyon Logon + Veyon Girişi - Add new computer - Yeni bilgisayar ekle + Please enter your domain/LDAP username and password in order to access computers. + Bilgisayarlara erişmek için lütfen alan/LDAP kullanıcı adınızı ve şifrenizi girin. - Remove selected computer - Seçilen bilgisayarı kaldır + Username + Kullanıcı adı - New computer - Yeni bilgisayar + Password + Parola - Builtin directory - + Authentication error + Yetkilendirme hatası - Locations & computers - + Logon failed with given username and password. Please try again! + Verilen kullanıcı adı ve parola ile giriş başarısız. Lütfen yeniden deneyin! + + + AuthLogonDialog - Locations - + Veyon Logon + Veyon Girişi - Add new location - + Please enter your username and password in order to access computers. + Lütfen bilgisayarlara erişmek için kullanıcı adı ve parolanızı girin. - Remove selected location - + Username + Kullanıcı adı - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - + Password + Parola - New location - + Authentication error + Yetkilendirme hatası + + + Logon failed with given username and password. Please try again! + Verilen kullanıcı adı ve parola ile giriş başarısız. Lütfen yeniden deneyin! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command - Komutlar için yardım göster + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Verilen kullanıcı adı veya şifre yanlış. Lütfen geçerli kimlik bilgilerini girin veya Veyon Configurator'ı kullanarak farklı bir kimlik doğrulama yöntemine geçin. - Import objects from given file - + Logon authentication + Oturum açma yetkilendirmesi - Export objects to given file - + Logon + Oturum Aç + + + AuthSimpleDialog - Invalid type specified. Valid values are "%1" or "%2". - + Veyon Logon + Veyon Girişi + + + Please enter the Veyon password: + Lütfen Veyon şifresini girin: + + + Authentication error + Yetkilendirme hatası + + + Logon failed with given password. Please try again! + Oturum açma, verilen parola ile başarısız oldu. Lütfen tekrar deneyin! + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + Verilen şifre yanlış. Lütfen doğru şifreyi girin veya Veyon Configurator'ı kullanarak farklı bir kimlik doğrulama yöntemine geçin. + + + Simple password authentication + Basit şifre doğrulaması + + + Simple password + Basit şifre + + + + AuthenticationPage + + Authentication is set up properly on this computer. + Kimlik doğrulama bu bilgisayarda doğru şekilde ayarlandı. + + + + AuthenticationPageTab + + Enabled + Aktif edildi + + + Test + Test + + + + BuiltinDirectoryConfiguration + + Builtin directory + Yerleşik dizin + + + + BuiltinDirectoryConfigurationPage + + Computers + Bilgisayarlar + + + Name + Ad + + + Host address/IP + Ana makine adresi/IP + + + MAC address + MAC adresi + + + Add new computer + Yeni bilgisayar ekle + + + Remove selected computer + Seçili bilgisayarı kaldır + + + New computer + Yeni bilgisayar + + + Builtin directory + Yerleşik dizin + + + Locations + Konumlar + + + Add new location + Yeni konum ekle + + + Remove selected location + Seçilen konumu sil + + + New location + Yeni konum + + + Directory name + Dizin adı + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + CSV dosyalarının içe aktarılması komut satırı arayüzü aracılığıyla mümkündür. Daha fazla bilgi için <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">çevrimiçi belgelere</a> bakın. + + + + BuiltinDirectoryPlugin + + Show help for specific command + Komutlar için yardım göster + + + Import objects from given file + Verilen dosyadan nesne içe aktarma + + + Export objects to given file + Nesneleri verilen dosyaya aktarma + + + Invalid type specified. Valid values are "%1" or "%2". + Geçersiz tür belirtildi. Geçerli değerler "%1" veya "%2" dir. Type - + Tür Name @@ -783,7 +994,7 @@ The public key is used on client computers to authenticate incoming connection r Host address - + Host adresi MAC address @@ -791,211 +1002,219 @@ The public key is used on client computers to authenticate incoming connection r Specified object not found. - + Belirtilen nesne bulunamadı. File "%1" does not exist! - + "%1" dosyası mevcut değil! Can't open file "%1" for reading! - + "%1" dosyası okumak için açılamıyor! Unknown argument "%1". - + Bilinmeyen argüman "%1". Computer "%1" (host address: "%2" MAC address: "%3") - + Bilgisayar "%1" (ana bilgisayar adresi: "%2" MAC adresi: "%3") Unclassified object "%1" with ID "%2" - + "%2" kimliğine sahip sınıflandırılmamış nesne "%1" None - + Yok Computer - + Bilgisayar Root - + Kök Invalid - + Geçersiz Error while parsing line %1. - + %1 satırı ayrıştırılırken hata oluştu. Network object directory which stores objects in local configuration - + Nesneleri yerel yapılandırmada depolayan ağ nesnesi dizini Commands for managing the builtin network object directory - + Yerleşik ağ nesnesi dizinini yönetme komutları No format string or regular expression specified! - + Biçim dizesi veya normal ifade belirtilmedi! Can't open file "%1" for writing! - + "%1" dosyası yazmak için açılamıyor! No format string specified! - + Biçim dizesi belirtilmedi! Object UUID - + Nesne UUID Parent UUID - + Üst UUID Add a location or computer - + Konum veya bilgisayar ekleyin Clear all locations and computers - + Tüm konumları ve bilgisayarları temizle Dump all or individual locations and computers - + Tüm veya tek tek konumları ve bilgisayarları boşalt List all locations and computers - + Tüm yerleri ve bilgisayarları listele Remove a location or computer - + Bir konumu veya bilgisayarı kaldır Location "%1" - + Konum "%1" Builtin (computers and locations in local configuration) - + Yerleşik (yerel yapılandırmadaki bilgisayarlar ve konumlar) Location - + Konum FILE - + DOSYA LOCATION - + KONUM FORMAT-STRING-WITH-PLACEHOLDERS - + BİÇİMLENDİRME-DİZİSİYLE-YER-TUTUCULAR REGULAR-EXPRESSION-WITH-PLACEHOLDER - + DÜZENLİ-İFADE-YER-TUTUCULU Imports objects from the specified text file using the given format string or regular expression containing one or multiple placeholders. Valid placeholders are: %1 - + Verilen biçim dizesini veya bir veya birden çok yer tutucu içeren normal ifadeyi kullanarak nesneleri belirtilen metin dosyasından içe aktarır. Geçerli yer tutucular:%1 Import simple CSV file to a single room - + Basit CSV dosyasını tek bir odaya aktar Import CSV file with location name in first column - + İlk sütunda konum adına sahip CSV dosyasını içe aktar Import text file with with key/value pairs using regular expressions - + Normal ifadeleri kullanarak anahtar/değer çiftleriyle metin dosyasını içe aktar Import arbitrarily formatted data - + Rasgele biçimlendirilmiş verileri içe aktar Exports objects to the specified text file using the given format string containing one or multiple placeholders. Valid placeholders are: %1 - + Bir veya daha fazla yer tutucu içeren verilen biçim dizesini kullanarak nesneleri belirtilen metin dosyasına aktarır. Geçerli yer tutucular: %1 Export all objects to a CSV file - + Tüm nesneleri CSV dosyasına aktar Export all computers in a specific location to a CSV file - + Belirli bir konumdaki tüm bilgisayarları bir CSV dosyasına aktar TYPE - + TİP NAME - + İSİM PARENT - + AİLE Adds an object where %1 can be one of "%2" or "%3". %4 can be specified by name or UUID. - + %1 öğesinin "%2" veya "%3" öğelerinden biri olabileceği bir nesne ekler. %4, ad veya UUID ile belirtilebilir. Add a room - + Bir oda ekle Add a computer to room %1 - + %1 odasına bir bilgisayar ekleyin OBJECT - + NESNE Removes the specified object from the directory. %1 can be specified by name or UUID. Removing a location will also remove all related computers. - + Belirtilen nesneyi dizinden kaldırır. %1, ad veya UUID ile belirtilebilir. Konum kaldırıldığında ilgili tüm bilgisayarlar da kaldırılır. Remove a computer by name - + Bilgisayarı ada göre kaldır Remove an object by UUID - + Bir nesneyi UUID'e göre kaldır "Room 01" - + "Oda 01" "Computer 01" - + "Bilgisayar 01" HOST ADDRESS - + HOST ADRESİ MAC ADDRESS - + MAC ADRESİ + + + The specified command does not exist or no help is available for it. + Belirtilen komut mevcut değil veya bu komut için yardım mevcut değil. + + + Location "%1" not found. + "%1" konumu bulunamadı. @@ -1014,10 +1233,6 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - Ana makine/IP adresi: %1 - Active features: %1 Etkin özellikler: %1 @@ -1034,10 +1249,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off Bilgisayar çevrim dışı veya kapalı - - Service unreachable or not running - Hizmet erişilebilir değil veya çalışmıyor - Authentication failed or access denied Yetkilendirme başarısız veya erişim reddedildi @@ -1056,14 +1267,46 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 - + Konum: %1 + + + [no user] + [kullanıcı yok] + + + Veyon Server unreachable or not running + Veyon Sunucusuna erişilemiyor veya çalışmıyor + + + Name: %1 + İsim: %1 + + + Hostname: %1 + Ana bilgisayar adı: %1 + + + unknown + bilinmeyen + + + IP address: %1 + IP adresi: %1 + + + Hostname could not be resolved + Ana bilgisayar adı çözülemedi + + + No features active + Hiçbir özellik etkin değil ComputerControlServer %1 Service %2 at %3:%4 - + %1 Hizmet %2'de %3:%4 Authentication error @@ -1075,19 +1318,30 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" is now accessing this computer. - + "%2" ana bilgisayarındaki "%1" kullanıcısı bu bilgisayara erişiyor. User "%1" at host "%2" attempted to access this computer but could not authenticate successfully. - + "%2" ana bilgisayarındaki "%1" kullanıcısı bu bilgisayara erişmeye çalıştı, ancak kimlik doğrulaması başarıyla gerçekleştirilemedi. Access control error - + Erişim kontrolü hatası User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. - + "%2" ana bilgisayarındaki "%1" kullanıcısı bu bilgisayara erişmeye çalıştı, ancak erişim denetimi ayarları nedeniyle engellendi. + + + Active connections: + Etkin bağlantılar: + + + + ComputerGroupSelector + + Group %1 + Grup %1 @@ -1106,90 +1360,93 @@ The public key is used on client computers to authenticate incoming connection r Location detection failed - + Konum algılama başarısız Computer name;Hostname;User - + Bilgisayar adı; Ana bilgisayar adı; Kullanıcı Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. - + Bu bilgisayarın konumu belirlenemedi. Bu, sistem yapılandırmasında bir sorun olduğunu gösterir. Bunun yerine tüm konumlar bilgisayar seçim panelinde gösterilir. - - - ComputerSelectPanel - Computer management - Bilgisayar yönetimi + Logged in since + den beri giriş yapıldı - Computer search - Bilgisayar ara + %1 days + %1 gün - Add location - + 1 day + 1 gün + + + ComputerMonitoring - Save computer/user list - Bilgisayar/kullanıcı listesini kaydet + Computers + Bilgisayarlar - Select output filename - Çıktı dosya adı seç + Search users and computers + Kullanıcı ve bilgisayarları ara - CSV files (*.csv) - CSV dosyaları (*.csv) + Select all + Hepsini seç - File error - Dosya hatası + Unselect all + Tüm seçimi kaldır - Could not write the computer and users list to %1! Please check the file access permissions. - Bilgisayar ve kullanıcı listesi %1 konumuna yazılamadı! Lütfen dosya erişim izinlerini gözden geçirin. + Add to group + Gruba ekle - - - ConfigCommandLinePlugin - Please specify an existing configuration file to import. - Lütfen içe aktarmak için var olan yapılandırma dosyasını belirtin. + Remove from group + Gruptan kaldır + + + ComputerSelectPanel - Please specify a valid filename for the configuration export. - Lütfen yapılandırmayı dışarı aktarmak için geçerli bir ad belirtin. + Computer search + Bilgisayar ara - Please specify a valid key. - Lütfen geçerli bir anahtar belirtin. + Add location + Konum ekle - Specified key does not exist in current configuration! - Belirtilen anahtar geçerli yapılandırmada bulunmuyor! + Save computer/user list + Bilgisayar/kullanıcı listesini kaydet - Please specify a valid value. - Lütfen geçerli bir değer belirtin. + Select output filename + Çıktı dosya adı seç - Configure Veyon at command line - Veyon'u komut satırında yapılandır + CSV files (*.csv) + CSV dosyaları (*.csv) - Output file is not writable! - Çıktı dosyası yazılabilir değil! + File error + Dosya hatası - Output directory is not writable! - Çıktı dizini yazılabilir değil! + Could not write the computer and users list to %1! Please check the file access permissions. + Bilgisayar ve kullanıcı listesi %1 konumuna yazılamadı! Lütfen dosya erişim izinlerini gözden geçirin. - Configuration file is not readable! - Yapılandırma dosyası okunabilir değil! + Search computers + Bilgisayarları ara + + + ConfigCommands Clear system-wide Veyon configuration Sistem geneli Veyon yapılandırmasını temizle @@ -1216,15 +1473,51 @@ The public key is used on client computers to authenticate incoming connection r Unset (remove) given configuration key - Verilen yapılandırma anahtarını kaldır + Verilen yapılandırma anahtarını kaldır (ayarını kaldır) - Commands for managing the configuration of Veyon - Veyon'un yapılandırmasını yönetmek için komutlar + Upgrade and save configuration of program and plugins + Program ve eklentilerin yapılandırmasını yükseltin ve kaydedin - Upgrade and save configuration of program and plugins - + Please specify an existing configuration file to import. + Lütfen içe aktarmak için var olan yapılandırma dosyasını belirtin. + + + Configuration file is not readable! + Yapılandırma dosyası okunabilir değil! + + + Please specify a valid filename for the configuration export. + Lütfen yapılandırmayı dışarı aktarmak için geçerli bir ad belirtin. + + + Output file is not writable! + Çıktı dosyası yazılabilir değil! + + + Output directory is not writable! + Çıktı dizini yazılabilir değil! + + + Please specify a valid key. + Lütfen geçerli bir anahtar belirtin. + + + Specified key does not exist in current configuration! + Belirtilen anahtar geçerli yapılandırmada bulunmuyor! + + + Please specify a valid value. + Lütfen geçerli bir değer belirtin. + + + Configure Veyon at command line + Veyon'u komut satırında yapılandır + + + Commands for managing the configuration of Veyon + Veyon'un yapılandırmasını yönetmek için komutlar @@ -1235,33 +1528,37 @@ The public key is used on client computers to authenticate incoming connection r Could not configure the firewall configuration for the %1 Server. - + %1 sunucusu için güvenlik duvarı yapılandırması yapılandırılamadı. Could not configure the firewall configuration for the %1 Worker. - + %1 çalışan için güvenlik duvarı yapılandırması yapılandırılamadı. Configuration is not writable. Please check your permissions! - + Yapılandırma yazılabilir değil. Lütfen izinlerinizi kontrol edin! Could not apply platform-specific configuration settings. - + Platforma özgü yapılandırma ayarları uygulanamadı. + + + Could not configure the firewall configuration for the %1 Service. + %1 hizmeti için güvenlik duvarı yapılandırması yapılandırılamadı. DemoClient %1 Demo - %1 Tanıtımı + %1 Gösteri DemoConfigurationPage Demo server - Tanıtım sunucusu + Gösteri sunucusu Tunables @@ -1269,7 +1566,7 @@ The public key is used on client computers to authenticate incoming connection r ms - ms + ms Key frame interval @@ -1279,13 +1576,9 @@ The public key is used on client computers to authenticate incoming connection r Memory limit Bellek sınırı - - Use multithreading (experimental) - Çoklu iş parçacığı kullanımı (deneysel) - MB - MB + MB Update interval @@ -1293,42 +1586,90 @@ The public key is used on client computers to authenticate incoming connection r s - s + s Slow down thumbnail updates while demo is running - + Gösteri çalışırken küçük resim güncellemelerini yavaşlatın + + + Bandwidth limit + Bant genişliği sınırı + + + MB/s + MB/s DemoFeaturePlugin - - Fullscreen demo - Tam ekran kipinde tanıtım - Stop demo - Tanıtımı durdur + Gösteriyi durdur Window demo - Pencere kipinde gösterim + Pencere kipinde gösteri Give a demonstration by screen broadcasting - Ekran yayını ile bir tanıtım gerçekleştir + Ekran yayını ile bir gösteri gerçekleştir - Demo server - Tanıtım sunucusu + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Bu kipte, ekranınız tüm bilgisayarlarda bir pencerede görüntülenir. Kullanıcılar, gerektiğinde diğer pencerelere geçiş yapabilirler. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - Bu kipte, kullanıcıların giriş aygıtları kilitlenirken ekranınız tüm bilgisayarlarda tam ekran kipinde görüntülenir. + Demo + Gösteri - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - Bu kipte, ekranınız tüm bilgisayarlarda bir pencerede görüntülenir. Kullanıcılar, gerektiğinde diğer pencerelere geçiş yapabilirler. + Share your screen or allow a user to share his screen with other users. + Ekranınızı paylaşın veya bir kullanıcının ekranını diğer kullanıcılarla paylaşmasına izin verin. + + + Full screen demo + Tam ekran gösterisi + + + Share your own screen in fullscreen mode + Kendi ekranınızı tam ekran modunda paylaş + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + Bu modda ekranınız tüm bilgisayarlarda tam ekran modunda görüntülenirken kullanıcıların giriş cihazları kilitlidir. + + + Share your own screen in a window + Kendi ekranınızı bir pencerede paylaş + + + Share selected user's screen in fullscreen mode + Seçili kullanıcının ekranını tam ekran modunda paylaş + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + Bu modda, seçili kullanıcının ekranı tüm bilgisayarlarda tam ekran modunda görüntülenirken, kullanıcıların giriş cihazları kilitlidir. + + + Share selected user's screen in a window + Seçili kullanıcının ekranını bir pencerede paylaş + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + Bu modda seçili kullanıcının ekranı tüm bilgisayarlarda bir pencerede görüntülenir. Kullanıcılar ihtiyaç duyduklarında diğer pencerelere geçebilirler. + + + Please select a user screen to share. + Lütfen paylaşmak için bir kullanıcı ekranı seçin. + + + Please select only one user screen to share. + Lütfen paylaşmak için yalnızca bir kullanıcı ekranı seçin. + + + All screens + Tüm ekranlar @@ -1357,87 +1698,91 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - Programs & websites - + Name + Ad - Predefined programs - + Path + Yol - Name - Ad + Predefined websites + Önceden tanımlanmış internet siteleri - Path - + Remove selected website + Seçilen internet sitesini kaldır - Add new program - + URL + URL - Remove selected program - + New website + Yeni internet sitesi - Predefined websites - + Applications & websites + Uygulamalar ve internet siteleri - Remove selected website - + Predefined applications + Önceden tanımlanmış uygulamalar - URL - + Add new application + Yeni uygulama ekle - New program - + Remove selected application + Seçili uygulamayı kaldır - New website - + Add new website + Yeni internet sitesi ekle + + + New application + Yeni uygulama DesktopServicesFeaturePlugin - - Run program - Program çalıştır - Open website - Web sitesi aç + İnternet sitesi aç Click this button to open a website on all computers. - Tüm bilgisayarlarda bir web sitesi açmak için bu düğmeye tıklayın. + Tüm bilgisayarlarda bir internet sitesi açmak için bu düğmeye tıklayın. + + + Open website "%1" + "%1" internet sitesini aç - Start programs and services in user desktop - Kullanıcı masaüstünde program ve hizmetler başlat + Custom website + Özel internet sitesi - Click this button to run a program on all computers. - Tüm bilgisayarlarda bir program çalıştırmak için bu düğmeye tıklayın. + Start application + Uygulama başlat - Run program "%1" - + Click this button to start an application on all computers. + Bir uygulamayı tüm bilgisayarlarda başlatmak için bu butona tıklayın. - Custom program - + Start application "%1" + "%1" uygulamasını başlat - Open website "%1" - + Custom application + Özel uygulama - Custom website - + Start apps and open websites in user sessions + Kullanıcı oturumlarında uygulamaları başlatın ve internet sitelerini açın @@ -1448,39 +1793,43 @@ The public key is used on client computers to authenticate incoming connection r Room %1 - + Oda %1 Please complete all tasks within the next 5 minutes. - + Lütfen tüm görevleri önümüzdeki 5 dakika içinde tamamlayın. Custom website - + Özel internet sitesi Open file manager - + Dosya yöneticisini aç Start learning tool - + Öğrenme aracını başlat Play tutorial video - - - - Custom program - + Eğitici videoyu oynat Handout - + Elden çıkar Texts to read - + Okunacak metinler + + + generic-student-user + Jenerik-öğrenci-kullanıcı + + + Custom application + Özel uygulama @@ -1506,83 +1855,245 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands + + List names of all available features + Mevcut tüm özelliklerin adlarını listeleyin + + + Show table with details of all available features + Tüm mevcut özelliklerin ayrıntılarını içeren tabloyu göster + + + Start a feature on a remote host + Uzak bir ana bilgisayarda bir özelliği başlatın + + + Stop a feature on a remote host + Uzak bir ana bilgisayarda bir özelliği durdurun + + + Please specify the command to display help for. + Lütfen yardımın görüntüleneceği komutu belirtin. + + + Displays a list with the names of all available features. + Mevcut tüm özelliklerin adlarını içeren bir liste görüntüler. + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + Mevcut tüm özellikler hakkında ayrıntılı bilgi içeren bir tablo görüntüler. Bu bilgiler bir açıklama, UID, ilgili özelliği sağlayan eklentinin adı ve diğer bazı uygulamayla ilgili ayrıntıları içerir. + + + HOST ADDRESS + HOST ADRESİ + + + FEATURE + ÖZELLİK + + + ARGUMENTS + ARGÜMANLAR + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + Belirtilen özelliği belirtilen ana bilgisayarda uzaktan çalışan Veyon Sunucusuna bağlanarak başlatır. Özellik, ad veya UID ile belirtilebilir. Tüm kullanılabilir özellikleri görmek için ``show`` komutunu kullanın. Özelliğe bağlı olarak, tek bir JSON dizesi olarak kodlanmış ek argümanlar (görüntülenecek metin mesajı gibi) belirtilmelidir. Daha fazla bilgi için lütfen geliştirici belgelerine bakın + + + Lock the screen + Ekranı kilitle + + + Display a text message + Bir metin mesajı görüntüle + + + Test message + Test mesajı + + + Start an application + Bir uygulamayı başlat + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + Uzaktan çalışan Veyon Sunucusuna bağlanarak belirtilen ana bilgisayarda belirtilen özelliği durdurur. Özellik ad veya UID ile belirtilebilir. Kullanılabilir tüm özellikleri görmek için ``show`` komutunu kullanın. + + + Unlock the screen + Ekranın kilidini aç + + + The specified command does not exist or no help is available for it. + Belirtilen komut mevcut değil veya bu komut için yardım mevcut değil. + + + Name + Ad + + + Description + Açıklama + + + Master + Usta + + + Service + Hizmet + + + Worker + Çalışan + + + UID + UID + + + Plugin + Eklenti + + + Invalid feature name or UID specified + Geçersiz özellik adı veya UID belirtildi + + + Error parsing the JSON-encoded arguments: %1 + JSON kodlu argümanları ayrıştırırken hata oluştu: %1 + + + Failed to initialize credentials + Kimlik bilgileri başlatılamadı + + + Could not establish a connection to host %1 + %1 ana makinesine bağlantı kurulamadı + + + Failed to send feature control message to host %1 + Özellik kontrol mesajı %1 ana bilgisayarına gönderilemedi + + + Feature-related CLI operations + Özellik ile ilgili CLI işlemleri + + + Commands for controlling features + Özellikleri kontrol etmek için komutlar + + + + FileTransferConfigurationPage + + File transfer + Dosya transferi + + + Directories + Dizinler + + + Destination directory + Hedef dizin + + + Default source directory + Varsayılan kaynak dizini + + + Options + Seçenekler + + + Remember last source directory + Son kaynak dizinini hatırla + - Feature control - Özellik denetimi + Create destination directory if it does not exist + Hedef dizin yoksa oluşturun FileTransferController Could not open file "%1" for reading! Please check your permissions! - + "%1" dosyası okumak için açılamadı! Lütfen izinlerinizi kontrol edin! FileTransferDialog File transfer - + Dosya transferi Options - + Seçenekler Transfer only - + Yalnızca aktar Transfer and open file(s) with associated program - + İlgili programla dosya(ları) aktarın ve açın Transfer and open destination folder - + Hedef klasörü aktarma ve açma Files - + Dosyalar Start - + Başlat Overwrite existing files - + Mevcut dosyaların üzerine yaz + + + + FileTransferFileDialog + + Select one or more files to transfer + Aktarılacak bir veya daha fazla dosya seçin FileTransferPlugin File transfer - + Dosya transferi Click this button to transfer files from your computer to all computers. - + Dosyaları bilgisayarınızdan tüm bilgisayarlara aktarmak için bu düğmeyi tıklatın. Select one or more files to transfer - + Aktarılacak bir veya daha fazla dosya seçin Transfer files to remote computer - + Uzak bilgisayara dosya aktarma Received file "%1". - + Alınan dosya "%1". Could not receive file "%1" as it already exists. - + Zaten var olduğundan "%1" dosyası alınamadı. Could not receive file "%1" as it could not be opened for writing! - + Yazılmak için açılamadığı için "%1" dosyası alınamadı! @@ -1611,10 +2122,6 @@ The public key is used on client computers to authenticate incoming connection r Log file directory Günlük dosyası dizini - - ... - ... - Log level Günlükleme düzeyi @@ -1656,24 +2163,12 @@ The public key is used on client computers to authenticate incoming connection r Standart hata çıktısına günlükle - Network object directory - Ağ nesnesi dizini + %1 service + %1 hizmeti - Backend: - Arka uç: - - - Update interval: - Güncelleme aralığı: - - - %1 service - %1 hizmeti - - - The %1 service needs to be stopped temporarily in order to remove the log files. Continue? - Günlük dosyalarının kaldırılması için %1 hizmetinin geçici olarak durdurulması gerekiyor. Devam et? + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + Günlük dosyalarının kaldırılması için %1 hizmetinin geçici olarak durdurulması gerekiyor. Devam et? Log files cleared @@ -1693,7 +2188,7 @@ The public key is used on client computers to authenticate incoming connection r MB - MB + MB Rotate log files @@ -1703,110 +2198,87 @@ The public key is used on client computers to authenticate incoming connection r x x - - seconds - saniye - Write to logging system of operating system İşletim sisteminin günlükleme sistemine yaz - Authentication - Kimlik - - - Method: - - - - Logon authentication - Oturum açma yetkilendirmesi - - - Key file authentication - Anahtar dosya yetkilendirmesi - - - Test - Sına + TLS configuration + TLS yapılandırması - Authentication is set up properly on this computer. - + Use certificate authority for TLS connections + TLS bağlantıları için sertifika yetkilisini kullan - Authentication keys are not set up properly on this computer. - + CA certificate file + CA sertifika dosyası - Authentication test - + ... + ... - - - InternetAccessControlConfigurationPage - Internet access control - + Host certificate file + Ana bilgisayar sertifika dosyası - Backend: - Arka uç: + Host private key file + Özel anahtar dosyasını barındır - General settings - + Style: + Stil: - Backend settings - + Native + Yerel - - - InternetAccessControlPlugin - Block access to the internet - + Color scheme: + Renk şeması: - Allow access to the internet - + Light + Aydınlık - Show help about command - Komut hakkında bilgi göster + Dark + Karanlık - Block internet - + User groups + Kullanıcı grupları - Click this button to block access to the internet. - + Backend: + Arka uç: - Unblock internet - + Include user groups from domain + Etki alanından kullanıcı gruplarını dahil et - Click this button to allow access to the internet. - + Missing user groups backend + Eksik kullanıcı grupları arka ucu - Control access to the internet - + No user groups plugin was found. Please check your installation! + Hiçbir kullanıcı grubu eklentisi bulunamadı. Lütfen kurulumunuzu kontrol edin! + + + HeadlessVncServer - Commands for controlling access to the internet - + Headless VNC server + Başlıksız VNC sunucusu LdapBrowseDialog Browse LDAP - + LDAP'ye göz at @@ -1817,316 +2289,300 @@ The public key is used on client computers to authenticate incoming connection r - LdapConfigurationPage + LdapConfiguration - Basic settings - Temel ayarlar - - - General - Genel + LDAP connection failed + LDAP bağlantısı başarısız - LDAP server and port - LDAP sunucusu ve bağlantı noktası + Could not connect to the LDAP server. Please check the server parameters. + +%1 + LDAP sunucusuna bağlanılamadı. Lütfen sunucu parametrelerini gözden geçirin. + +%1 - Bind DN - + LDAP bind failed + LDAP bağlantısı başarısız - Bind password - + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + LDAP sunucusuna bağlanılamadı. Lütfen sunucu değişkenlerini ve bağlama kimliklerini kontrol edin. + +%1 - Anonymous bind - + LDAP bind successful + LDAP bağlantısı başarılı - Use bind credentials - + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + LDAP sunucusu bağlantısı başarılı. Temel LDAP ayarları düzgün şekilde yapılandırıldı. - Base DN - Temel DN + LDAP base DN test failed + LDAP tabanlı DN testi başarısız oldu - Fixed base DN - Durağan temel DN + Could not query the configured base DN. Please check the base DN parameter. + +%1 + Yapılandırılmış temel DN kuyruklaması başarısız. Lütfen temel DN değişkenini kontrol ediniz. + +%1 - e.g. dc=example,dc=org - örn. dc=ornek,dc=org + LDAP base DN test successful + LDAP tabanlı DN testi başarılı - Discover base DN by naming context - Temel DN'yi adlandırma bağlamına göre keşfet + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + LDAP temel DN'si başarıyla sorgulandı. Aşağıdaki girdiler bulundu:: + +%1 - e.g. namingContexts or defaultNamingContext - örn. namingContexts veya defaultNamingContext + LDAP naming context test failed + LDAP adlandırma bağlamı testi başarısız oldu - Environment settings - Ortam ayarları + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + Adlandırma bağlamları aracılığıyla temel DN sorgulanamadı. Lütfen adlandırma bağlamı öznitelik parametresini kontrol edin. + +%1 - Object trees - Nesne ağaçları + LDAP naming context test successful + LDAP adlandırma bağlamı testi başarılı - Computer tree - Bilgisayar ağacı + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + LDAP adlandırma bağlamı başarıyla sorgulandı. Şu temel DN bulundu: +%1 - e.g. OU=Groups - örn. OU=Kümeler + user tree + kullanıcı ağacı User tree Kullanıcı ağacı - e.g. OU=Users - örn. OU=Kullanıcılar + group tree + grup ağacı - e.g. OU=Computers - örn. OU=Bilgisayarlar + Group tree + Grup ağacı - Group tree - Küme ağacı + computer tree + bilgisayar ağacı - Perform recursive search operations in object trees - Nesne ağaçlarında özyinelemeli arama işlemleri gerçekleştir + Computer tree + Bilgisayar ağacı - Object attributes - Nesne öznitelikleri + computer group tree + bilgisayar grup ağacı - e.g. hwAddress - örn. hwAddress + Computer group tree + Bilgisayar grup ağacı - e.g. member or memberUid - örn. member veya memberUid + user objects + kullanıcı nesneleri - e.g. dNSHostName - örn. dNSHostName + User login name attribute + Kullanıcı giriş niteliği - Computer MAC address attribute - Bilgisayar MAC adresi özniteliği + group members + grup üyeleri Group member attribute - Küme üyesi özniteliği + Grup üyesi özniteliği - e.g. uid or sAMAccountName - örn. uid veya sAMAccountName + Group not found + Grup bulunamadı - Advanced settings - Gelişmiş ayarlar + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + "%1" adında bir grup bulunamadı. Lütfen grup adını veya grup ağacı parametresini kontrol edin. - Optional object filters - İsteğe bağlı nesne süzgeçleri + computer objects + bilgisayar nesneleri - Filter for user groups - Kullanıcı kümeleri için süzgeç + Computer display name attribute + Bilgisayar görüntü adı niteliği - Filter for users - Kullanıcılar için süzme + Invalid hostname + Geçersiz ana makine adı - Filter for computer groups - Bilgisayar kümeleri için süzme + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Bilgisayar ana bilgisayar adlarını tam nitelikli etki alanı adları (FQDN) olarak depolanacak şekilde yapılandırdınız ancak etki alanı olmayan bir ana bilgisayar adı girdiniz. - Group member identification - Küme üyesi kimliği + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Bilgisayar ana bilgisayar adlarını, etki alanı adı olmadan basit ana bilgisayar adları olarak depolanacak şekilde yapılandırdınız ancak etki alanı adı kısmı olan bir ana bilgisayar adı girdiniz. - Distinguished name (Samba/AD) - Ayırt edilen ad (Samba/AD) + Computer hostname attribute + Bilgisayar ana makine adı niteliği - List all groups of a user - Kullanıcının tüm kümelerini listele + computer MAC addresses + bilgisayar MAC adresleri - List all groups of a computer - Bilgisayarın tüm kümelerini listele + Computer MAC address attribute + Bilgisayar MAC adresi özniteliği - Get computer object by IP address - IP adresiyle bilgisayar nesnesi al + computer locations + bilgisayar konumları - LDAP connection failed - LDAP bağlantısı başarısız + Computer location attribute + Bilgisayar konum niteliği - LDAP bind failed - + Location name attribute + Konum adı niteliği - LDAP bind successful - + users + kullanıcılar - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - + user groups + kullanıcı grupları - LDAP base DN test failed - LDAP temel DN sınaması başarısız + computers + bilgisayarlar - LDAP base DN test successful - LDAP temel DN sınaması başarılı + computer groups + bilgisayar grupları - LDAP naming context test failed - LDAP adlandırma bağlamı sınaması başarısız + computer containers + bilgisayar taşıyıcıları - LDAP naming context test successful - LDAP adlandırma bağlamı sınaması başarılı + groups of user + kullanıcı grupları - The LDAP naming context has been queried successfully. The following base DN was found: -%1 - LDAP adlandırma bağlamı başarıyla sorgulandı. Şu temel DN bulundu: -%1 + User not found + Kullanıcı bulunamadı - user tree - kullanıcı ağacı + Could not find a user with the name "%1". Please check the username or the user tree parameter. + "%1" adlı bir kullanıcı bulunamadı. Lütfen kullanıcı adını veya kullanıcı ağacı parametresini kontrol edin. - group tree - küme ağacı + groups of computer + bilgisayar grupları - computer tree - bilgisayar ağacı + Computer not found + Bilgisayar bulunamadı - Enter username - Kullanıcı adı gir + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + "%1" ana bilgisayar adına sahip bir bilgisayar bulunamadı. Lütfen ana bilgisayar adını veya bilgisayar ağacı parametresini kontrol edin. - Please enter a user login name (wildcards allowed) which to query: - Sorgulanacak kullanıcı giriş adını (joker karakterlere izin verilir) girin: + Hostname lookup failed + Sunucu adı araması başarısız - user objects - kullanıcı nesneleri + Could not lookup hostname for IP address %1. Please check your DNS server settings. + IP adresi %1 için ana bilgisayar adı bulunamadı. Lütfen DNS sunucu ayarlarınızı kontrol edin. - Enter group name - Küme adı gir + location entries + konum girdileri - Please enter a group name whose members to query: - Üyeleri sorgulanacak küme adını girin: + Computer groups filter + Bilgisayar grubu filtreleri - group members - küme üyeleri + Computer locations identification + Bilgisayar konumları tanımlaması - Group not found - Küme bulunamadı + Filter for computer groups + Bilgisayar grupları için filtre - Could not find a group with the name "%1". Please check the group name or the group tree parameter. - "%1" adlı bir küme bulunamadı.. Lütfen küme adını veya küme ağacı parametresini gözden geçirin. + Invalid test value + Geçersiz test değeri - Enter computer name - Bilgisayar adı gir + An empty or invalid value has been supplied for this test. + Bu test için geçersiz veya boş bir değer sağlandı. - computer objects - bilgisayar nesneleri + LDAP %1 test failed + LDAP %1 testi başarısız oldu - Enter computer DN - Bilgisayar DN'sini gir - - - Please enter the DN of a computer whose MAC address to query: - - - - computer MAC addresses - bilgisayar MAC adresleri - - - users - kullanıcılar - - - user groups - kullanıcı kümeleri - - - computer groups - bilgisayar kümeleri - - - Please enter a user login name whose group memberships to query: - Küme üyelikleri sorgulanacak kullanıcı giriş adı girin: - - - groups of user - kullanıcı kümeleri - - - User not found - Kullanıcı bulunamadı - - - groups of computer - bilgisayar kümeleri - - - Computer not found - Bilgisayar bulunamadı + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + Yapılandırılan %1'deki hiçbir girdi sorgulanamadı. Lütfen "%2" parametresini kontrol edin. + +%3 - Enter computer IP address - Bilgisayar IP adresi gir + LDAP %1 test successful + LDAP %1 testi başarılı - Please enter a computer IP address which to resolve to an computer object: - Bilgisayar nesnesine çıkan bir bilgisayar IP adresi girin: + The %1 has been queried successfully and %2 entries were found. + %1 sorgulandı ve %2 girdi bulundu. - computers - bilgisayarlar + LDAP test failed + LDAP testi başarısız - LDAP %1 test failed - LDAP %1 sınaması başarısız + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + %1 sorgulanamadı. Lütfen %2 parametresini(lerini) kontrol edin ve var olan bir nesnenin adını girin. + +%3 - LDAP %1 test successful - LDAP %1 sınaması başarılı + and + ve - The %1 has been queried successfully and %2 entries were found. - %1 sorgulandı ve %2 girdi bulundu. + LDAP test successful + LDAP testi başarılı %1 %2 have been queried successfully: @@ -2138,583 +2594,535 @@ The public key is used on client computers to authenticate incoming connection r LDAP filter test failed - LDAP süzgeç sınaması başarısız + LDAP filtre testi başarısız oldu Could not query any %1 using the configured filter. Please check the LDAP filter for %1. %2 - Yapılandırılmış süzgeç kullanılarak herhangi bir %1 sorgulanamadı. Lütfen %1 için LDAP süzgecini denetleyin. + Yapılandırılmış filtre kullanılarak herhangi bir %1 sorgulanamadı. Lütfen %1 için LDAP filtresini kontrol edin. %2 LDAP filter test successful - LDAP süzgeç sınaması başarılı + LDAP filtre testi başarılı %1 %2 have been queried successfully using the configured filter. - Yapılandırılmış süzgeç kullanılarak %1 %2 başarıyla sorgulandı. + %1 %2 yapılandırılmış filtre kullanılarak başarıyla sorgulandı. - (only if different from group tree) - (eğer yalnızca küme ağacından farklıysa) - - - Computer group tree - Bilgisayar kümesi ağacı - - - computer group tree - bilgisayar kümesi ağacı - - - Filter for computers - - - - e.g. room or computerLab - örn. room veya computerLab - - - Integration tests - Tümleştirme sınamaları - - - Computer groups - Bilgisayar kümeleri - - - e.g. name or description - örn. ad ve tanımlama + LDAP directory + LDAP dizini + + + LdapConfigurationPage - Filter for computer containers - + Basic settings + Temel ayarlar - Computer containers or OUs - + General + Genel - Connection security - + LDAP server and port + LDAP sunucusu ve bağlantı noktası - TLS certificate verification - + Bind DN + DN bağla - System defaults - + Bind password + Şifre bağla - Never (insecure!) - + Anonymous bind + Kimliksiz bağla - Custom CA certificate file - + Use bind credentials + Bağlama yetkileri kullan - None - + Base DN + Temel DN - TLS - + Fixed base DN + Durağan temel DN - SSL - + e.g. dc=example,dc=org + örn. dc=ornek,dc=org - e.g. (objectClass=computer) - + Discover base DN by naming context + Temel DN'yi adlandırma bağlamına göre keşfet - e.g. (objectClass=group) - + e.g. namingContexts or defaultNamingContext + örn. namingContexts veya defaultNamingContext - e.g. (objectClass=person) - + Environment settings + Ortam ayarları - e.g. (objectClass=room) or (objectClass=computerLab) - + Object trees + Nesne ağaçları - e.g. (objectClass=container) or (objectClass=organizationalUnit) - + Computer tree + Bilgisayar ağacı - Could not query the configured base DN. Please check the base DN parameter. - -%1 - + e.g. OU=Groups + örn. OU=Gruplar - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - + User tree + Kullanıcı ağacı - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - + e.g. OU=Users + örn. OU=Kullanıcılar - Certificate files (*.pem) - Sertifika dosyaları (*.pem) + e.g. OU=Computers + örn. OU=Bilgisayarlar - Could not connect to the LDAP server. Please check the server parameters. - -%1 - LDAP sunucusuna bağlanılamadı. Lütfen sunucu parametrelerini gözden geçirin. - -%1 + Group tree + Grup ağacı - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - + Perform recursive search operations in object trees + Nesne ağaçlarında özyinelemeli arama işlemleri gerçekleştir - Encryption protocol - Şifreleme iletişim kuralı + Object attributes + Nesne öznitelikleri - Computer location attribute - + e.g. hwAddress + örn. hwAddress - Computer display name attribute - + e.g. member or memberUid + örn. member veya memberUid - Location name attribute - + e.g. dNSHostName + örn. dNSHostName - e.g. cn or displayName - + Computer MAC address attribute + Bilgisayar MAC adresi özniteliği - Computer locations identification - + Group member attribute + Grup üyesi özniteliği - Identify computer locations (e.g. rooms) via: - + e.g. uid or sAMAccountName + örn. uid veya sAMAccountName - Location attribute in computer objects - + Advanced settings + Gelişmiş ayarlar - List all entries of a location - + Optional object filters + İsteğe bağlı nesne filtreleri - List all locations - + Filter for user groups + Kullanıcı grupları için filtre - Enter computer display name - + Filter for users + Kullanıcılar için filtre - Please enter a computer display name to query: - + Filter for computer groups + Bilgisayar grupları için filtre - Enter computer location name - + Group member identification + Grup üye tanımlaması - Please enter the name of a computer location (wildcards allowed): - + Distinguished name (Samba/AD) + Ayırt edilen ad (Samba/AD) - computer locations - + List all groups of a user + Bir kullanıcının tüm gruplarını listele - Enter location name - + List all groups of a computer + Bir bilgisayarın tüm gruplarını listele - Please enter the name of a location whose entries to query: - + Get computer object by IP address + IP adresiyle bilgisayar nesnesi al - location entries - + Enter username + Kullanıcı adı gir - LDAP test failed - + Please enter a user login name (wildcards allowed) which to query: + Sorgulanacak kullanıcı giriş adını (joker karakterlere izin verilir) girin: - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - + Enter group name + Grup adını girin - and - + Please enter a group name whose members to query: + Lütfen üyelerini sorgulamak istediğiniz grubun adını girin: - LDAP test successful - + Enter computer name + Bilgisayar adı gir - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - + Enter computer DN + Bilgisayar DN'sini gir - Browse - + Please enter the DN of a computer whose MAC address to query: + Lütfen MAC adresi sorgulanacak bir bilgisayarın DN'sini girin: - Test - Sına + Please enter a user login name whose group memberships to query: + Lütfen sorgulanacak grup üyeliklerinin kullanıcı adını girin: - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - + Enter computer IP address + Bilgisayar IP adresi gir - Computer hostname attribute - + Please enter a computer IP address which to resolve to an computer object: + Bilgisayar nesnesine çıkan bir bilgisayar IP adresi girin: - Please enter a computer hostname to query: - + (only if different from group tree) + (sadece grup ağacından farklıysa) - Invalid hostname - + Computer group tree + Bilgisayar grubu ağacı - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - + Filter for computers + Bilgisayarlar için filtrele - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - + e.g. room or computerLab + örn. room veya computerLab - Could not find a user with the name "%1". Please check the username or the user tree parameter. - + Integration tests + Entegrasyon testleri - Enter hostname - + Computer groups + Bilgisayar grupları - Please enter a computer hostname whose group memberships to query: - + e.g. name or description + örn. ad ve tanımlama - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - + Filter for computer containers + Bilgisayar taşıyıcıları için filtrele - Hostname lookup failed - + Computer containers or OUs + Bilgisayar konteynerleri veya OU'lar - Could not lookup hostname for IP address %1. Please check your DNS server settings. - + Connection security + Bağlantı güvenliği - User login name attribute - + TLS certificate verification + TLS sertifika doğrulaması - Configured attribute for user login name or computer hostname (OpenLDAP) - + System defaults + Sistem varsayılanları - computer containers - + Never (insecure!) + Asla (güvensiz!) - - - LdapPlugin - Auto-configure the base DN via naming context - Temel DN'yi adlandırma bağlamı aracılığıyla kendiliğinden yapılandır + Custom CA certificate file + Özel CA sertifika dosyası - Query objects from LDAP directory - LDAP dizininden nesneleri sorgula + None + Yok - Show help about command - Komut hakkında bilgi göster + TLS + TLS - Commands for configuring and testing LDAP/AD integration - LDAP/AD tümelemesini yapılandırmak ve sınamak için komutlar + SSL + SSL - Basic LDAP/AD support for Veyon - + e.g. (objectClass=computer) + örnek: (nesneSınıfı=bilgisayar) - %1 (load computers and locations from LDAP/AD) - + e.g. (objectClass=group) + ör. (objectClass=grup) - %1 (load users and groups from LDAP/AD) - + e.g. (objectClass=person) + örnek: (nesneSınıfı=kişi) - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - + e.g. (objectClass=room) or (objectClass=computerLab) + ör. (objectClass=room) VEYA (objectClass=computerLab) - No naming context attribute name given - falling back to configured value. - + e.g. (objectClass=container) or (objectClass=organizationalUnit) + ör. (objectClass=container) veya (objectClass=organizationalUnit) - Could not query base DN. Please check your LDAP configuration. - + Certificate files (*.pem) + Sertifika dosyaları (*.pem) - Configuring %1 as base DN and disabling naming context queries. - + Encryption protocol + Şifreleme iletişim kuralı - - - LdapProConfigurationPage - LDAP Pro - + Computer location attribute + Bilgisayar konum niteliği - Instances - + Computer display name attribute + Bilgisayar görüntü adı özniteliği - Enter name - + Location name attribute + Konum adı niteliği - Please enter a name for the instance (can't be changed later!): - + e.g. cn or displayName + ör. cn veya ekranAdı - Remove instance - + Computer locations identification + Bilgisayar konumları tanımlaması - Do you really want to remove instance "%1"? - + Identify computer locations (e.g. rooms) via: + Bilgisayar konumlarını şu şekilde tanımla (örn. odalar): - Configuration for instance "%1" - + Location attribute in computer objects + Bilgisayar nesnelerindeki konum niteliği - - - LdapProPlugin - Professional LDAP/AD integration for Veyon - + List all entries of a location + Bir konumun tüm girdilerini listele - %1 (load computers and locations from LDAP/AD) - + List all locations + Tüm konumları listele - %1 (load users and groups from LDAP/AD) - + Enter computer display name + Bilgisayar ekran adı gir - - - LicensingConfigurationPage - Licensing - + Please enter a computer display name to query: + Lütfen sıralama için bir bilgisayar ekran adı girin: - Installed licenses - + Enter computer location name + Bilgisayar konum adı gir - Add new network range - + Please enter the name of a computer location (wildcards allowed): + Lütfen bilgisayar konumunun adını girin (joker karakterlere izin verilir): - Remove selected network range - + Enter location name + Konum adı gir - ID - + Please enter the name of a location whose entries to query: + Lütfen sorgulanacak girişlerin bulunduğu konumun adını girin: - Feature - + Browse + Gözat - Valid until - + Test + Test - Licensee - + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Tam nitelikli alan adları (FQDN, örn. myhost.example.org) olarak depolanan ana bilgisayar adları - Browse license file - + Computer hostname attribute + Bilgisayar ana makine adı özniteliği - Veyon license files (*.vlf) - + Please enter a computer hostname to query: + Lütfen sorgulanacak bir bilgisayar adı girin: - Remove license - + Enter hostname + Ana makine adı gir - Do you really want to remove the selected license? - + Please enter a computer hostname whose group memberships to query: + Lütfen sorgulanacak grup üyeliklerinin bulunduğu bilgisayarın adını girin: - <N/A> - + User login name attribute + Kullanıcı giriş özniteliği - Invalid license file - + Configured attribute for user login name or computer hostname (OpenLDAP) + Kullanıcı oturum açma adı veya bilgisayar ana bilgisayar adı için yapılandırılmış öznitelik (OpenLDAP) - Could not open the license file for reading! - + Directory name + Dizin adı - The selected license file does not contain valid data. - + Query options + Sorgu seçenekleri - The selected license file could not be verified. - + Query nested user groups (supported by AD only) + İç içe geçmiş kullanıcı gruplarını sorgula (yalnızca AD tarafından desteklenir) - The selected license file is not valid for this installation. - + Query timeout + Sorgu zaman aşımı - The selected license file is expired. - + ms + ms + + + LdapNetworkObjectDirectoryConfigurationPage - The license is already installed. - + LDAP + LDAP - Information - + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + Konumları ve bilgisayarları LDAP tabanlı dizin hizmetinizden nasıl alacağınızı yapılandırmak için lütfen genel LDAP yapılandırma sayfasını kullanın. + + + LdapPlugin - Installation ID - + Auto-configure the base DN via naming context + Temel DN'yi adlandırma bağlamı aracılığıyla kendiliğinden yapılandır - Addons available for licensing - + Query objects from LDAP directory + LDAP dizininden nesneleri sorgula - Addon - + Show help about command + Komut hakkında bilgi göster - - - LicensingPlugin - Show help for specific command - Komutlar için yardım göster + Commands for configuring and testing LDAP/AD integration + LDAP/AD entegrasyonunu yapılandırma ve test etme komutları - Show all installed licenses - + Basic LDAP/AD support for Veyon + Veyon için temel LDAP/AD desteği - Add license file - + %1 (load computers and locations from LDAP/AD) + %1 (LDAP/AD'den bilgisayarlar ve konumlar yükleme) - Remove installed license - + %1 (load users and groups from LDAP/AD) + %1 (LDAP/AD'den kullanıcıları ve grupları yükleme) - -USAGE - -%1 add <LICENSE FILE> - - - + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Lütfen şemayı takip eden geçerli bir LDAP URL'si belirtin"ldap[s]://[user[:password]@]hostname[:port]" - -USAGE - -%1 remove <LICENSE ID> - - - + No naming context attribute name given - falling back to configured value. + Adlandırma bağlamı özniteliği adı verilmedi - yapılandırılmış değere geri dönülüyor. - No certificate found with given ID - + Could not query base DN. Please check your LDAP configuration. + Temel DN sorgulanamadı. Lütfen LDAP yapılandırmanızı kontrol edin. - <N/A> - + Configuring %1 as base DN and disabling naming context queries. + %1'i temel DN olarak yapılandırıyor ve adlandırma bağlamı sorgularını devre dışı bırakıyor. - Licensing management - + Test binding to an LDAP server + Bir LDAP sunucusuna bağlanma testi yap - Commands for managing license keys - + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Verilen kullanıcı adı veya şifre yanlış. Lütfen geçerli kimlik bilgilerini girin veya Veyon Configurator'ı kullanarak farklı bir kimlik doğrulama yöntemine geçin. + + + LDAP bind + LDAP bağlaması LinuxPlatformConfigurationPage Linux - + Linux Custom PAM service for user authentication - + Kullanıcı kimlik doğrulaması için özel PAM hizmeti User authentication - + Kullanıcı doğrulama - Session management - + User sessions + Kullanıcı oturumları - Display manager users - + Minimum session lifetime before server start + Sunucu başlamadan önceki minimum oturum ömrü + + + User login + Kullanıcı Girişi + + + Login key sequence + Oturum açma anahtarı dizisi @@ -2723,20 +3131,16 @@ USAGE Plugin implementing abstract functions for the Linux platform Eklenti, Linux platformu için soyut işlevleri yerine getirir - - Plugin implementing specific functions for the Linux platform - - LocationDialog Select location - + Konum seç enter search filter... - arama süzgeci gir... + arama filtresine girin... @@ -2745,14 +3149,14 @@ USAGE Configuration Yapılandırma - - Disable balloon tooltips - Balon iouçlarını devre dışı bırak - Show icons only Yalnızca simgeleri göster + + Disable tooltips + Araç ipuçlarını devre dışı bırak + MainWindow @@ -2770,15 +3174,15 @@ USAGE &File - Dosya + &Dosya &Help - Yardım + &Yardım &Quit - Çıkış + &Çıkış Ctrl+Q @@ -2800,10 +3204,6 @@ USAGE About Qt Qt Hakkında - - Authentication impossible - Kimlik doğrulama imkansız - Configuration not writable Yapılandırma yazılabilir değil @@ -2834,7 +3234,7 @@ USAGE Master - + Master Access control @@ -2864,10 +3264,6 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. Yerel yapılandırma arka ucu, yapılandırmanın yazılabilir olmadığını bildirdi! Lütfen %1 Yapılandırıcıyı yüksek ayrıcalıklarla çalıştırın. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - Yetkilendirme anahtar dosyaları yok veya var olanlar geçersiz. Lütfen, %1 Yapılandırıcı kullanarak yeni anahtar dosyalar oluşturun. Diğer bir seçenek olarak, %1 Yapılandırıcıyı kullanarak giriş yetkilendirmesini ayarlayın. Bunu dışında %1 kullanarak bilgisayarlara erişemezsiniz. - Access denied Erişim reddedildi @@ -2882,7 +3278,7 @@ USAGE Feature active - + Özellik etkin The feature "%1" is still active. Please stop it before closing %2. @@ -2900,13 +3296,9 @@ USAGE Search users and computers Kullanıcı ve bilgisayarları ara - - Adjust optimal size - En uygun boyuta ayarla - Align computers to grid - + Bilgisayarları ızgaraya hizala %1 Configurator @@ -2930,23 +3322,67 @@ USAGE &View - + &Görünüm &Standard - + &Standart &Advanced - + &Gelişmiş + + + Use custom computer arrangement + Özel bilgisayar düzenlemesi kullan + + + Locations && computers + Konumlar ve && bilgisayarlar + + + Authentication + Kimlik + + + Adjust size of computer icons automatically + Bilgisayar simgelerinin boyutunu otomatik olarak ayarla + + + Slideshow + Slayt gösterisi + + + Spotlight + Spot ışığı + + + Veyon Master + Veyon Usta + + + Locations & computers + Konumlar ve bilgisayarlar + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + Özel bilgisayar düzenlemesini kullanın. + +Düzenlemeyi bir dosyadan yüklemek veya mevcut düzenlemeyi bir dosyaya kaydetmek için basılı tutun. + + + Only show computers with logged on users + Yalnızca oturum açmış kullanıcıların olduğu bilgisayarları göster - Use custom computer arrangement - + Load computer positions + Bilgisayar pozisyonlarını yükle - Locations && computers - + Save computer positions + Bilgisayar pozisyonlarını kaydet @@ -2955,17 +3391,13 @@ USAGE Directories Dizinler - - ... - ... - User configuration Kullanıcı yapılandırması Feature on computer double click: - + Bilgisayarda çift tıklama özelliği: Features @@ -3005,7 +3437,7 @@ USAGE Hide computer filter field - Bilgisayar süzme alanını gizle + Bilgisayar filtre alanını gizle Actions such as rebooting or powering down computers @@ -3025,15 +3457,15 @@ USAGE ms - ms + ms Program start - + Program başlat Modes and features - + Modlar ve özellikler User and computer name @@ -3043,6 +3475,10 @@ USAGE Only user name Yalnızca kullanıcı adı + + Only last part of user name + + Only computer name Yalnızca bilgisayar adı @@ -3053,265 +3489,292 @@ USAGE Text color - + Metin rengi Sort order - + Sıralama düzeni Computer and user name - + Bilgisayar ve kullanıcı adı Computer locations - + Bilgisayar konumları Show current location only - + Yalnızca geçerli konumu göster Allow adding hidden locations manually - + Gizli yerleri manuel olarak eklemeye izin ver Hide empty locations - + Boş yerleri gizle Show confirmation dialog for potentially unsafe actions - + Güvenli olmayabilecek işlemler için onay iletişim kutusunu göster Perform access control - + Erişim kontrolü gerçekleştir Automatically select current location - + Geçerli konumu otomatik olarak seç - Automatically adjust computer thumbnail size - + Automatically open computer select panel + Bilgisayar seçme panelini otomatik olarak aç - Automatically open computer select panel - + Use modern user interface (experimental) + Modern kullanıcı arayüzü kullanın (deneysel) - - - MonitoringMode - Monitoring - Gözlemleme + Thumbnail spacing + Küçük resim aralığı - Builtin monitoring mode - Dahili gözlemleme kipi + px + px - This mode allows you to monitor all computers at one or more locations. - + Hide local session + Yerel oturumu gizle - - - NetworkDiscoveryConfigurationPage - Network discovery - + Auto + Kendiliğinden - Mode - + Thumbnail aspect ratio + Küçük resim en boy oranı - Scan network ranges - + Automatically adjust computer icon size + Bilgisayar simgesi boyutunu otomatik olarak ayarla - e.g. 192.168.1.0/24 - + Open feature windows on the same screen as the main window + Özellik pencerelerini ana pencereyle aynı ekranda açın - Scan all subnets of computer - + Configuration templates + Yapılandırma şablonları - Scan custom subnet - + Image quality in monitoring mode + İzleme modunda görüntü kalitesi - Scan sessions on local computer - + Highest + En yüksek - Test - Sına + High + Yüksek - Network ranges - + Medium + Orta - Add new group - + Low + Düşük - Remove selected group - + Lowest + En düşük - Groups - + Remote access image quality + Uzaktan erişim görüntü kalitesi - First address - + Advanced + Gelişmiş - Last address - + Computer name source + Bilgisayar adı kaynağı - Add new network range - + Default + Varsayılan - Remove selected network range - + Host address + Host adresi - Parallel scans - + Session client address + Oturum istemci adresi - Scan timeout - + Session client name + Oturum istemci adı - ms - ms + Session host name + Oturum ana bilgisayar adı - Session scan limit - + Session metadata + Oturum meta verileri - Options - + Full name of user + Kullanıcının tam adı - Reverse lookup discovered IP addresses to host names - + User login name + Kullanıcı oturum açma adı - New location - + Computer UID role + Bilgisayar UID rolü - - - NetworkDiscoveryDirectory - Scanning... - + Session meta data hash + Oturum meta verileri karma değeri - Discovered computers - + Always expand all locations + Her zaman tüm konumları genişlet + + + Image quality + Görüntü kalitesi - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command - Komutlar için yardım göster + Monitoring + Gözlemleme - Scan a subnet - + Builtin monitoring mode + Dahili gözlemleme kipi - -USAGE - -%1 scan [<SUBNET>] - - - + This mode allows you to monitor all computers at one or more locations. + Bu mod, bir veya daha fazla konumdaki tüm bilgisayarları izlemenizi sağlar. - Network object directory which automatically discovers computers in the network - + Query application version of the server + Sunucunun uygulama sürümünü sorgula - Network discovery (scan network for Veyon clients) - + Query active features + Etkin özellikleri sorgula - Commands for managing the network discovery directory - + Query properties of remotely available screens + Uzaktan erişilebilen ekranların sorgu özellikleri + + + + NestedNetworkObjectDirectory + + All directories + Tüm dizinler + + + + NetworkObjectDirectoryConfigurationPage + + Update interval: + Güncelleme aralığı: + + + seconds + saniye + + + + NetworkObjectDirectoryConfigurationPageTab + + Enabled + Aktif edildi NetworkObjectTreeModel Locations/Computers - + Konumlar/Bilgisayarlar OpenWebsiteDialog Open website - Web sitesi aç + İnternet sitesi aç e.g. Veyon - + Örn. Veyon Remember and add to website menu - + Hatırla ve internet sitesi menüsüne ekle e.g. www.veyon.io - + örn. www.veyon.io Please enter the URL of the website to open: - Lütfen açılacak web sitesinin URL'sini girin: + Lütfen açılacak internet sitesinin URL'sini girin: Name: - + İsim: + + + Website name + İnternet sitesi adı - PasswordDialog + PluginCommands - Username - Kullanıcı adı + List names of all installed plugins + Yüklü tüm eklentilerin adlarını listele - Password - Parola + Show table with details of all installed plugins + Yüklü tüm eklentilerin ayrıntılarını içeren tabloyu göster - Veyon Logon - Veyon Girişi + Name + Ad - Authentication error - Yetkilendirme hatası + Description + Açıklama - Logon failed with given username and password. Please try again! - Verilen kullanıcı adı ve parola ile giriş başarısız. Lütfen yeniden deneyin! + Version + Sürüm - Please enter your username and password in order to access computers. - Lütfen bilgisayarlara erişmek için kullanıcı adı ve parolanızı girin. + UID + UID + + + Plugin-related CLI operations + Eklentiyle ilgili CLI işlemleri + + + Commands for managing plugins + Eklentileri yönetme komutları @@ -3356,59 +3819,69 @@ USAGE Do you really want to reboot the selected computers? Seçilen bilgisayarları yeniden başlatmak istediğinize emin misiniz? - - Do you really want to power down the selected computer? - Seçilen bilgisayarları kapatmak istediğinize emin misiniz? - Power on a computer via Wake-on-LAN (WOL) - + Bir bilgisayarı ağdan uyandır (WOL) MAC ADDRESS - + MAC ADRESİ This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. - + Bu komut, verilen MAC adresine sahip bilgisayarı ağ üzerinden uyandırmak için Ağdan-Uyandırma (WOL) paketi yayımlar Please specify the command to display help for! - + Lütfen yardım görüntüleme komutunu belirtin! Invalid MAC address specified! - + Geçersiz MAC adresi tanımlandı! Commands for controlling power status of computers - + Bilgisayarların güç durumunu kontrol etmek için komutlar Power down now - + Gücü şimdi kapat Install updates and power down - + Güncellemeleri kurduktan sonra gücü kapat Power down after user confirmation - + Kullanıcı onayından sonra gücü kapat Power down after timeout - + Belirli süre sonunda gücü kapat The computer was remotely requested to power down. Do you want to power down the computer now? - + Bu bilgisayarın kapatılması istendi. Şimdi kapatmak ister misiniz? The computer will be powered down in %1 minutes, %2 seconds. Please save your work and close all programs. - + Bilgisayarınız %1 dakika, %2 saniye sonra kapatılacak. + +Lütfen çalışmalarınızı kaydedip tüm açık pencereleri kapatın. + + + Do you really want to reboot <b>ALL</b> computers? + Gerçekten <b>TÜM</b> bilgisayarları yeniden başlatmak istiyor musunuz? + + + Do you really want to power down <b>ALL</b> computers? + Gerçekten <b>TÜM</b> bilgisayarları kapatmak istiyor musunuz? + + + Do you really want to power down the selected computers? + Seçili bilgisayarların gerçekten kapanmasını istiyor musunuz? @@ -3419,15 +3892,15 @@ Please save your work and close all programs. Please specify a timeout for powering down the selected computers: - + Lütfen seçilen bilgisayarları kapatmak için bir zaman aşımı süresi belirtin: minutes - + dakika seconds - + saniye @@ -3456,20 +3929,35 @@ Please save your work and close all programs. Remote view or control a computer Bilgisayarı uzaktan görüntüle veya denetle - - Please enter the hostname or IP address of the computer to access: - Bilgisayara erişim için lütfen bir ana makine adı veya IP adresi giriniz: - Show help about command Komut hakkında bilgi göster + + Exchange clipboard contents + Panodaki içerikleri değiştir + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + Hiçbir bilgisayar seçilmediğinden manuel erişim için bir bilgisayarın ana bilgisayar adını veya IP adresini girebilirsiniz: + + + + RemoteAccessPage + + Remote access: %1 + Uzaktan erişim:%1 + RemoteAccessWidget %1 - %2 Remote Access - + %1 -%2 Uzaktan Erişim + + + %1 - %2 - %3 Remote Access + %1 - %2 - %3 Uzaktan Erişim @@ -3526,10 +4014,6 @@ Please save your work and close all programs. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - %1 bağlanıyor - Connected. Bağlandı. @@ -3540,60 +4024,19 @@ Please save your work and close all programs. Exit - - - - - Routing - - Control internet access by modifying routing table - - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - - - - Add custom route to block internet - - - - Destination - - - - Gateway - - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - Lütfen seçilen bilgisayar(lar)da çalıştırılacak programları veya komutları girin. Birden çok program/komut satır ile ayrılabilir. - - - Run programs - Program çalıştır - - - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - örnek. "C:\Program Files\VideoLAN\VLC\vlc.exe" + Çıkış - Name: - + Connecting... + Bağlanıyor... - Remember and add to program menu - + Select screen + Ekran seç - e.g. VLC - + All screens + Tüm ekranlar @@ -3614,6 +4057,18 @@ Please save your work and close all programs. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. Tüm kullanıcının dikkatini toplamak için bilgisayarlarını bu düğmeyi kullanarak kilitleyebilirsiniz. Bu kipte tüm giriş aygıtları kilitlenir ve ekranlar karartılır. + + Lock input devices + Giriş aygıtlarını kilitle + + + Unlock input devices + Giriş aygıtlarının kilidini aç + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + Tüm kullanıcıların tüm dikkatini geri kazanmak için bu düğmeyi kullanarak bilgisayarlarını kilitleyebilirsiniz. Bu modda masaüstü hala görünürken tüm giriş aygıtları kilitlenir. + Screenshot @@ -3623,12 +4078,16 @@ Please save your work and close all programs. Could not take a screenshot as directory %1 doesn't exist and couldn't be created. - % 1 dizini olmadığı ve oluşturulamadığı için bir ekran görüntüsü alınamadı. + %1 dizini olmadığı ve oluşturulamadığı için bir ekran görüntüsü alınamadı. Screenshot Ekran görüntüsü + + Could not open screenshot file %1 for writing. + %1 ekran görüntüsü dosyası yazmak için açılamadı. + ScreenshotFeaturePlugin @@ -3654,34 +4113,80 @@ Please save your work and close all programs. - ScreenshotManagementPanel + ScreenshotManagementPage + + Screenshots + Ekran görüntüleri + + + + ScreenshotManagementPanel + + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + Sizin tarafınızdan alınan tüm ekran görüntüleri burada listelenmiştir. Bir bilgisayarın sağ tuş menüsünde "ekran görüntüsü" ögesini tıklayarak ekran görüntülerini alabilir. Aşağıdaki düğmeler kullanılarak ekran görüntüleri yönetilebilir. + + + User: + Kullanıcı: + + + Computer: + Bilgisayar: + + + Date: + Tarih: + + + Time: + Zaman: + + + Show + Göster + + + Delete + Sil + + + Screenshot + Ekran görüntüsü + + + Do you really want to delete all selected screenshots? + Seçili tüm ekran görüntülerini gerçekten silmek istiyor musunuz? + + + + ServerAccessControlManager - All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. - Sizin tarafınızdan alınan tüm ekran görüntüleri burada listelenmiştir. Bir bilgisayarın sağ tuş menüsünde "ekran görüntüsü" ögesini tıklayarak ekran görüntülerini alabilir. Aşağıdaki düğmeler kullanılarak ekran görüntüleri yönetilebilir. + Requested authentication method not available + İstenen kimlik doğrulama yöntemi mevcut değil - User: - Kullanıcı: + Access allowed by rule "%1" + "%1" kuralı tarafından erişime izin verildi - Computer: - Bilgisayar: + Access denied by rule "%1" + Erişim "%1" kuralı tarafından engellendi - Date: - Tarih: + No rule allowed access + Hiçbir kurala erişime izin verilmiyor - Time: - Zaman: + Accessing user not member of an authorized user group + Yetkili bir kullanıcı grubunun üyesi olmayan kullanıcıya erişim - Show - Göster + User has denied access + Kullanıcının erişimi engellendi - Delete - Sil + User confirmed access + Kullanıcı erişimi onayladı @@ -3714,14 +4219,6 @@ Please save your work and close all programs. State: Durum: - - Network - - - - Demo server port - Tanıtım sunucusu bağlantı noktası - Enable firewall exception Güvenlik duvarı özel durumu etkinleştir @@ -3730,10 +4227,6 @@ Please save your work and close all programs. Allow connections from localhost only Yalnızca yerel sunucu bağlantılarına izin ver - - Internal VNC server port - Dahili VNC sunucu bağlantı noktası - VNC server VNC sunucusu @@ -3755,68 +4248,141 @@ Please save your work and close all programs. Çalışıyor - Feature manager port - Özellik yöneticisi bağlantı noktası + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. + Bu seçeneğin etkinleştirilmesi, hizmetin bilgisayardaki her etkileşimli oturum için bir sunucu işlemi başlatmasını sağlar. +Bu genellikle terminal sunucularını desteklemek için gereklidir. - Primary service port - Birincil hizmet bağlantı noktası + Show notification on remote connection + Uzak bağlantıda bildirim göster - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. - + Show notification when an unauthorized access is blocked + Yetkisiz erişim engellendiğinde bildirim göster - Show notification on remote connection - + Maximum session count + Maksimum oturum sayısı - Multi session mode (for terminal and remote desktop servers) - + Network port numbers + Ağ bağlantı noktası numaraları - Show notification when an unauthorized access is blocked - + Veyon server + Veyon sunucusu - - - ServiceControl - Starting service %1 - + Internal VNC server + Dahili VNC sunucusu - Stopping service %1 - + Feature manager + Özellik yöneticisi - Registering service %1 - + Demo server + Gösteri sunucusu - Unregistering service %1 - + Miscellaneous network settings + Çeşitli ağ ayarları - Service control - + Session mode + Oturum modu + + + Local session mode (single server instance for primary local session) + Yerel oturum modu (birincil yerel oturum için tek sunucu örneği) + + + Active session mode (single server instance for active local or remote session) + Etkin oturum modu (etkin yerel veya uzak oturum için tek sunucu örneği) + + + Multi session mode (distinct server instance for each local and remote desktop session) + Çoklu oturum modu (her yerel ve uzak masaüstü oturumu için ayrı sunucu örneği) + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + Yerel veya uzak olması fark etmeksizin, geçerli etkin oturum için tek bir Veyon Sunucu örneğinin başlatılması gerekiyorsa etkinleştirin. + + + Miscellaneous settings + Çeşitli ayarlar + + + Disable clipboard synchronization + Pano senkronizasyonunu devre dışı bırak + + + Session metadata + Oturum meta verileri + + + Content + İçerik + + + None + Yok + + + Value of an environment variable + Bir ortam değişkeninin değeri + + + Value of a registry key + Bir kayıt defteri anahtarının değeri + + + Environment variable name: + Ortam değişkeni adı: + + + Registry key name: + Kayıt anahtarı adı: + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + İsteğe bağlı olarak, bilgisayar adının bir kısmını çıkarmak ve bunu bilgisayar için görüntü adı olarak kullanmak üzere bir yakalama içeren düzenli bir ifade girin. + +Örnek: [^-]*-(PC[0-9]*) - ServiceControlPlugin + ServiceControl - Service is running - Hizmet çalışıyor + Service control + Hizmet kontrolü - Service is not running - Hizmet çalışmıyor + Starting %1 + %1 başlatılıyor - Configure and control Veyon service - Veyon hizmetini ayarla ve denetle + Stopping %1 + %1 durduruluyor + + + Restarting %1 + %1 tekrar başlatılıyor + + + Registering %1 + %1 kayıt oluyor + + + Unregistering %1 + %1 kaydı siliniyor + + + ServiceControlCommands Register Veyon Service Veyon Hizmetini Kaydet @@ -3841,30 +4407,129 @@ Typically this is required to support terminal servers. Query status of Veyon Service Veyon Hizmetinin sorgu durumu + + Service is running + Hizmet çalışıyor + + + Service is not running + Hizmet çalışmıyor + + + Configure and control Veyon service + Veyon hizmetini ayarla ve denetle + Commands for configuring and controlling Veyon Service Veyon Hizmetini yapılandırmak ve denetlemek için komutlar - ShellCommandLinePlugin + ShellCommands Run command file - + Komut dosyasını çalıştır File "%1" does not exist! - + "%1" dosyası mevcut değil! - Interactive shell and script execution for Veyon Control - + Interactive shell and script execution for Veyon CLI + Veyon CLI için etkileşimli kabuk ve betik yürütme Commands for shell functionalities + Kabuk işlevleri için komutlar + + + + SlideshowPanel + + Previous + Önceki + + + Start/pause + Başlat/duraklat + + + Next + Sonraki + + + Duration: + Süre: + + + View in separate window + + + + %1 Master – Slideshow + + SpotlightPanel + + Add selected computers + Seçili bilgisayarları ekle + + + Remove selected computers + Seçili bilgisayarları kaldır + + + Update computers in realtime + Bilgisayarları gerçek zamanlı olarak güncelle + + + Spotlight + Spot ışığı + + + Please select at least one computer to add. + Lütfen eklemek için en az bir bilgisayar seçin. + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + Orta fare düğmesine tıklayarak veya alttaki ilk düğmeye tıklayarak bilgisayar ekleyin. +İkinci buton seçili veya son bilgisayarı kaldırır. + + + + StartAppDialog + + Start application + Uygulama başlat + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + Lütfen seçili bilgisayarlarda başlatılacak uygulamaları girin. Birden fazla uygulamayı satırla ayırabilirsiniz. + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + örnek. "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + Hatırla ve uygulama menüsüne ekle + + + Application name + Uygulama adı + + + Name: + İsim: + + + e.g. VLC + örn. VLC + + SystemTrayIcon @@ -3876,33 +4541,33 @@ Typically this is required to support terminal servers. SystemUserGroupsPlugin User groups backend for system user groups - + Sistem kullanıcı grupları için kullanıcı grupları arka ucu Default (system user groups) - + Varsayılan (sistem kullanıcı grupları) TestingCommandLinePlugin Test internal Veyon components and functions - + Dahili Veyon bileşenlerini ve fonksiyonlarını test et Commands for testing internal components and functions of Veyon - + Veyon'un dahili bileşenlerini ve işlevlerini test etme komutları TextMessageDialog Send text message - Metin iletisi gönder + Metin iletisi gönder - Use the field below to type your message which will be sent to all selected users. - Tüm seçili kullanıcılara gönderilecek iletinizi yazmak için aşağıdaki alanı kullanın. + Please enter your message which send to all selected users. + Lütfen seçili tüm kullanıcılara gönderilecek mesajınızı girin. @@ -3932,7 +4597,7 @@ Typically this is required to support terminal servers. Poll full screen (leave this enabled per default) - + Anket tam ekranı (bunu varsayılan olarak etkin bırakın) Low accuracy (turbo mode) @@ -3944,45 +4609,69 @@ Typically this is required to support terminal servers. Enable multi monitor support - + Çoklu monitör desteğini etkinleştir Enable Desktop Duplication Engine on Windows 8 and newer - + Windows 8 ve daha yeni sürümlerde Masaüstü Çoğaltma Altyapısını etkinleştir + + + Maximum CPU usage + Maksimum işlemci kullanımı - UserConfig + UserLoginDialog - No write access - Erişim izni yok + User login + Kullanıcı Girişi - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - Kişisel ayarlarınız kaydedilemedi! Lütfen kullanıcı yapılandırma dosyasının yolunu, %1 Yapılandırıcıyı kullanarak gözden geçirin. + Please enter a username and password for automatic login on all computers. + Lütfen tüm bilgisayarlarda otomatik oturum açmak için bir kullanıcı adı ve şifre girin. + + + Username + Kullanıcı adı + + + Password + Parola - UserSessionControl + UserSessionControlPlugin - User session control - Kullanıcı oturum denetimi + Log in + Giriş + + + Click this button to log in a specific user on all computers. + Tüm bilgisayarlarda belirli bir kullanıcıya giriş yapmak için bu düğmeyi tıklatın. Log off - + Çıkış Click this button to log off users from all computers. - + Tüm bilgisayarlardaki kullanıcıların oturumlarını kapatmak için bu düğmeyi tıklayın. Confirm user logoff - + Kullanıcı oturumunu kapatmayı onayla Do you really want to log off the selected users? - + Seçilen kullanıcıların oturumunu gerçekten kapatmak istiyor musunuz? + + + User session control + Kullanıcı oturum denetimi + + + Do you really want to log off <b>ALL</b> users? + Gerçekten <b>TÜM</b> kullanıcıların oturumunu kapatmak istiyor musunuz? @@ -4021,67 +4710,75 @@ Typically this is required to support terminal servers. No module specified or module not found - available modules are: - + Modül belirtilmedi veya modül bulunamadı - kullanılabilir modüller: Plugin not licensed - + Eklenti lisanslı değil INFO - + BİLGİ ERROR - - - - licensed for - + HATA USAGE - + KULLANIMI DESCRIPTION - + AÇIKLAMA EXAMPLES - + ÖRNEKLER WARNING - + UYARI + + + Authentication test + Kimlik doğrulama testi + + + Screen %1 + Ekran %1 - VeyonServiceControl + VeyonMaster - Veyon Service - + No write access + Erişim izni yok + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Kişisel ayarlarınız kaydedilemedi! Lütfen kullanıcı yapılandırma dosyasının yolunu, %1 Yapılandırıcıyı kullanarak gözden geçirin. - VncView + VeyonServiceControl - Establishing connection to %1 ... - %1 ile bağlantı kuruluyor... + Veyon Service + Veyon Hizmeti WindowsPlatformConfiguration Could not change the setting for SAS generation by software. Sending Ctrl+Alt+Del via remote control will not work! - + SAS üretimi ayarı yazılımla değiştirilemedi. Uzaktan kontrol ile Ctrl + Alt + Del gönderme özelliği çalışmaz! WindowsPlatformConfigurationPage Windows - + Windows General @@ -4089,31 +4786,55 @@ Typically this is required to support terminal servers. Enable SAS generation by software (Ctrl+Alt+Del) - + Yazılım tarafından SAS oluşturulmasını etkinleştir (Ctrl+Alt+Del) Screen lock - + Ekran kilidi Hide taskbar - + Görev çubuğunu gizle Hide start menu - + Başlat menüsünü gizle Hide desktop - + Masaüstünü gizle User authentication - + Kullanıcı doğrulama Use alternative user authentication mechanism - + Kullanıcı yetkilendirmesi için alternatif mekanizma kullan + + + User login + Kullanıcı Girişi + + + Input start delay + Girdi başlangıç gecikmesi + + + Simulated key presses interval + Taklit edilmiş tuş basış süresi + + + Confirm legal notice (message displayed before user logs in) + Yasal bilgilendirmeyi onaylat (kullanıcı oturum açmadan önce mesaj gösterilir) + + + Use input device interception driver + Girdi cihazı müdahale sürücüsü kullan + + + Use custom power scheme with disabled power button + Güç düğmesi devre dışıyken özel güç şemasını kullan @@ -4123,39 +4844,43 @@ Typically this is required to support terminal servers. Eklenti, Windows platformu için soyut işlevleri yerine getirir - Plugin implementing specific functions for the Windows platform - + Internal display + Dahili ekran WindowsServiceControl The service "%1" is already installed. - + "%1" hizmeti zaten yüklü. - The service "%1" could not be installed. - + The service "%1" has been installed successfully. + "%1" hizmeti başarıyla yüklendi. - The service "%1" has been installed successfully. - + The service "%1" has been uninstalled successfully. + "%1" hizmeti başarıyla kaldırıldı. - The service "%1" could not be uninstalled. - + Service "%1" could not be found. + "%1" hizmeti bulunamadı. - The service "%1" has been uninstalled successfully. - + The service "%1" could not be installed (error %2). + "%1" hizmeti yüklenemedi (hata %2). - The start type of service "%1" could not be changed. - + Could not change the failure actions config for service "%1" (error %2). + "%1" hizmeti için hata eylemleri yapılandırması değiştirilemedi (hata %2). - Service "%1" could not be found. - + The service "%1" could not be uninstalled (error %2). + "%1" hizmeti kaldırılamadı (hata %2). + + + The start type of service "%1" could not be changed (error %2). + "%1" hizmetinin başlangıç ​​türü değiştirilemedi (hata %2). diff --git a/translations/uk.ts b/translations/veyon_uk.ts similarity index 73% rename from translations/uk.ts rename to translations/veyon_uk.ts index 5e4616f12..4c00779b5 100644 --- a/translations/uk.ts +++ b/translations/veyon_uk.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -80,10 +80,6 @@ If you're interested in translating Veyon into your local or another langua All groups Всі групи - - ... - ... - Access control rules Правила керування доступом @@ -140,19 +136,18 @@ If you're interested in translating Veyon into your local or another langua User groups backend: Модуль груп користувачів: - - Missing user groups backend - Не вистачає модуля обробки груп користувачів - - - No default user groups plugin was found. Please check your installation! - Не знайдено типового додатка груп користувачів. Будь ласка, перевірте, чи належним чином встановлено програму! - Restrict access to members of specific user groups Обмежити доступ учасникам вказаних груп користувачів + + AccessControlProvider + + Provider for access control features + Надавач можливостей керування доступом + + AccessControlRuleEditDialog @@ -179,30 +174,10 @@ If you're interested in translating Veyon into your local or another langua Rule description: Опис правила: - - Invert all conditions ("is/has" interpreted as "is/has not") - Інверсія усіх умов («є або має» буде вважатися записом «не є або не має») - Conditions Умови - - is member of group - є учасником групи - - - Accessing computer is localhost - Комп’ютер для доступу є локальним - - - Accessing user is logged on user - Користувач для доступу є розпізнаним користувачем системи - - - Accessing user is already connected - Користувача для доступу вже з’єднано - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. Якщо вказано декілька умов, для застосування правила має бути виконано усі ці умови (логічне «І»). Якщо має бути виконано хоч одну з декількох умов (логічне «АБО»), вам слід створити декілька відповідних правил керування доступом. @@ -236,33 +211,125 @@ If you're interested in translating Veyon into your local or another langua Комп’ютер для доступу - Local (logged on) user - Локальний користувач (у системі) + Always process rule and ignore conditions + Завжди обробляти правило і ігнорувати умови - Local computer - Локальний комп’ютер + Accessing computer and local computer + Доступ до комп'ютера і локальний комп'ютер - Always process rule and ignore conditions - Завжди обробляти правило і ігнорувати умови + User being accessed + Доступ до користувача - No user logged on - Немає користувачів у системі + is logged in locally + який увійшов локально - Accessing user has one or more groups in common with local (logged on) user - Користувач для доступу є учасником однієї або декількох груп, які є спільними із локальним (поточним) користувачем + is logged in remotely + який увійшов віддалено - Accessing computer and local computer are at the same location - Комп’ютер для доступу розташовано у тому самому місці, що і локальний комп’ютер + No user is logged in locally + Жоден користувач не увійшов локально + + + One or multiple users are logged in locally + Один або декілька користувачів увійшли локально + + + No user is logged in remotely + Жоден користувач не увійшов віддалено + + + One or multiple users are logged in remotely + Один або декілька користувачів увійшли віддалено is located at розташовано у + + is not located at + не розташовано у + + + are located at the same location + розташовано у тому самому місці + + + are not located the same location + не розташовано у тому самому місці + + + is member of group + є учасником групи + + + is not member of group + є учасником групи + + + is authenticated via + розпізнано за допомогою + + + is not authenticated via + не розпізнано за допомогою + + + has one or more groups in common with user being accessed + належать до однієї або декількох спільних груп із користувачем для доступу + + + has no groups in common with user being accessed + не належать до спільних груп із користувачем для доступу + + + equals user being accessed + збігається із користувачем для доступу + + + is different from user being accessed + не збігається із користувачем для доступу + + + is already connected + вже з'єднано + + + is not connected + не з'єднано + + + is local computer + є локальним комп'ютером + + + is not local computer + не є локальним комп'ютером + + + Computer being accessed + Комп'ютер для доступу + + + Session being accessed is a user session + Сеанс доступу є сеансом користувача + + + Session being accessed is a login screen + Сеанс доступу є вікном вітання + + + Local computer is already being accessed + Доступ до локального комп'ютера вже здійснюється + + + Local computer is not yet being accessed + Доступ до локального комп'ютера ще не здійснюється + AccessControlRulesTestDialog @@ -306,42 +373,44 @@ If you're interested in translating Veyon into your local or another langua The access in the given scenario needs permission of the logged on user. Доступ за вказаним сценарієм потребує дозволу від користувача, який увійшов до системи. - - ERROR: Unknown action - ПОМИЛКА: невідома дія - Test result Результат тестування - - - AndroidPlatformConfigurationPage - Android - + Authentication method + Метод розпізнавання - General - Загальні + There is no matching rule with a valid action. The access is therefore denied. + Немає відповідного правила із коректною дією. Через це у доступі відмовлено. - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + Вступ - - - AuthKeysConfigurationPage - Authentication keys - Ключі розпізнавання + Please perform the following steps to set up key file authentication: + Будь ласка, виконайте такі кроки, щоб налаштувати файл ключа розпізнавання: - Introduction - Вступ + 1) Create a key pair on the master computer. + 1) Створіть пару ключів на основному комп'ютері. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Встановіть групу доступу, учасникам якої буде дозволено доступу до інших комп'ютерів. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Експортуйте відкритий ключ і імпортуйте його на всіх клієнтські комп'ютери із однаковою назвою. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Будь ласка, ознайомтеся із <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Підручником із адміністрування Veyon</a>, щоб дізнатися більше. Key file directories @@ -355,14 +424,17 @@ If you're interested in translating Veyon into your local or another langua Private key file base directory Основний каталог файлів закритих ключів - - ... - ... - Available authentication keys Доступні ключі розпізнавання + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Пара ключів для розпізнавання складається із поєднаних між собою криптографічних ключів, закритого і відкритого. За допомогою закритого ключа користувачі на основному комп'ютері можуть отримувати доступу до клієнтських комп'ютерів. Важливо, щоб право на читання файла закритого ключа мали лише уповноважені на це користувачі. Відкритий ключ використовується на клієнтських комп'ютерах для розпізнавання вхідних запитів щодо з'єднання. + Create key pair Створити пару ключів @@ -403,10 +475,6 @@ If you're interested in translating Veyon into your local or another langua Please select a key to delete! Будь ласка, виберіть ключ для вилучення! - - Please enter the name of the user group or role for which to import the authentication key: - Будь ласка, вкажіть назву групи користувачів або роль, для якої слід імпортувати ключ розпізнавання: - Please select a key to export! Будь ласка, виберіть ключ для експортування! @@ -420,31 +488,12 @@ If you're interested in translating Veyon into your local or another langua Будь ласка, виберіть ключ, доступ до якого слід встановити для групи! - Please perform the following steps to set up key file authentication: - Будь ласка, виконайте такі кроки, щоб налаштувати файл ключа розпізнавання: - - - 1) Create a key pair on the master computer. - 1) Створіть пару ключів на основному комп'ютері. - - - 2) Set an access group whose members should be allowed to access other computers. - 2) Встановіть групу доступу, учасникам якої буде дозволено доступу до інших комп'ютерів. - - - 3) Export the public key and import it on all client computers with the same name. - 3) Експортуйте відкритий ключ і імпортуйте його на всіх клієнтські комп'ютери із однаковою назвою. - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - Будь ласка, ознайомтеся із <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Підручником із адміністрування Veyon</a>, щоб дізнатися більше. - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - Пара ключів для розпізнавання складається із поєднаних між собою криптографічних ключів, закритого і відкритого. За допомогою закритого ключа користувачі на основному комп'ютері можуть отримувати доступу до клієнтських комп'ютерів. Важливо, щоб право на читання файла закритого ключа мали лише уповноважені на це користувачі. Відкритий ключ використовується на клієнтських комп'ютерах для розпізнавання вхідних запитів щодо з'єднання. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + Будь ласка, вкажіть назву групи користувачів або роль, для якої слід імпортувати ключ розпізнавання. + +Переконайтеся, що назви ключів, пов'язаних один із одним, є однаковими на усіх комп'ютерах. @@ -644,10 +693,6 @@ The public key is used on client computers to authenticate incoming connection r This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. Ця команда виводить список усіх доступних ключів розпізнавання у налаштованому каталозі ключів. Якщо вказано параметр «%1», замість списку буде виведено таблицю із подробицями щодо ключів. Деякі параметри ключа може бути не показано, якщо доступ до ключа обмежено, наприклад через брак прав на читання файла ключа. - - Please specify the command to display help for! - Будь ласка, вкажіть команду, для якої слід показати довідку! - TYPE ТИП @@ -656,10 +701,6 @@ The public key is used on client computers to authenticate incoming connection r PAIR ID ІД ПАРИ - - Command line support for managing authentication keys - Підтримка керування ключами розпізнавання у командному рядку - Commands for managing authentication keys Команди для керування ключами розпізнавання @@ -676,6 +717,30 @@ The public key is used on client computers to authenticate incoming connection r This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. Ця команда видобуває частину, пов'язану із відкритим ключем, з закритого ключа <КЛЮЧ> і зберігає її до відповідного файла відкритого ключа. Через це при налаштовуванні додаткового основного комп'ютера достатньо перенести на нього лише закритий ключ. Після перенесення відкритий ключ можна просто видобути. + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + На цьому комп'ютері не налаштовано належним чином ключі розпізнавання. Будь ласка, створіть нові ключі або перемкніть систему на інший спосіб розпізнавання за допомогою засобу налаштовування Veyon. + + + Key file authentication + Розпізнавання за файлами ключів + + + Key file + Файл ключа + + + Please specify the key name (e.g. "teacher/public") as the first argument. + Будь ласка, вкажіть назву ключа (наприклад «teacher/public») першим аргументом. + + + Please specify the command to display help for. + Будь ласка, вкажіть команду, для якої слід показати довідку. + + + The specified command does not exist or no help is available for it. + Вказаної команди не існує або немає доступу до довідки до неї. + AuthKeysTableModel @@ -697,97 +762,240 @@ The public key is used on client computers to authenticate incoming connection r - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - Комп'ютери + General + Загальні - Name - Назва + Username to bind DN mapping: + Користувач для прив'язки DN: - Host address/IP - Адреса/IP вузла + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + Приклад: %користувач%@ДОМЕН або cn=%користувач%,ou=users,dc=example,dc=org + + + AuthLdapDialog - MAC address - MAC-адреса + Veyon Logon + Вхід до Veyon - Add new computer - Додати новий комп’ютер + Please enter your domain/LDAP username and password in order to access computers. + Для отримання доступу до комп'ютерів, будь ласка, вкажіть ваше ім'я користувача і пароль домену/LDAP. - Remove selected computer - Вилучити позначений комп’ютер + Username + Ім’я користувача - New computer - Новий комп’ютер + Password + Пароль - Builtin directory - Вбудований каталог + Authentication error + Помилка розпізнавання - Locations & computers - Місця і комп'ютери + Logon failed with given username and password. Please try again! + Не вдалося увійти на основі вказаних імені користувача і пароля. Будь ласка, повторіть спробу! + + + AuthLogonDialog - Locations - Місця + Veyon Logon + Вхід до Veyon - Add new location - Додати нове місце + Please enter your username and password in order to access computers. + Будь ласка, вкажіть ваше ім’я користувача та пароль, щоб отримати доступ до комп’ютерів. - Remove selected location - Вилучити позначене місце + Username + Ім’я користувача - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - Імпортування файлів CSV можна виконати за допомогою інтерфейсу командного рядка. Докладніший опис можна знайти у <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">інтернет-документації</a>. + Password + Пароль - New location - Нове місце + Authentication error + Помилка розпізнавання + + + Logon failed with given username and password. Please try again! + Не вдалося увійти на основі вказаних імені користувача і пароля. Будь ласка, повторіть спробу! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command - Показати довідку щодо певної команди + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Надане значення імені користувача або пароля є помилковим. Будь ласка, вкажіть коректні реєстраційні дані або перемкніть систему на інший спосіб розпізнавання за допомогою засобу налаштовування Veyon. - Import objects from given file - Імпортувати об'єкти із вказаного файла + Logon authentication + Розпізнавання під час входу - Export objects to given file - Експортувати об'єкти до вказаного файла + Logon + Вхід + + + AuthSimpleDialog - Invalid type specified. Valid values are "%1" or "%2". - Вказано некоректний тип. Коректними є значення «%1» і «%2». + Veyon Logon + Вхід до Veyon - Type - Тип + Please enter the Veyon password: + Будь ласка, введіть пароль Veyon: - Name - Назва + Authentication error + Помилка розпізнавання - Host address - Адреса вузла + Logon failed with given password. Please try again! + Не вдалося увійти до системи за вказаним паролем. Будь ласка, повторіть спробу! + + + AuthSimplePlugin - MAC address - MAC-адреса + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + Надане значення пароля є помилковим. Будь ласка, вкажіть чинний пароль або перемкніть систему на інший спосіб розпізнавання за допомогою засобу налаштовування Veyon. + + + Simple password authentication + Просте розпізнавання за паролем + + + Simple password + Простий пароль + + + + AuthenticationPage + + Authentication is set up properly on this computer. + На цьому комп'ютері належним чином налаштовано розпізнавання. + + + + AuthenticationPageTab + + Enabled + Увімкнено + + + Test + Перевірити + + + + BuiltinDirectoryConfiguration + + Builtin directory + Вбудований каталог + + + + BuiltinDirectoryConfigurationPage + + Computers + Комп'ютери + + + Name + Назва + + + Host address/IP + Адреса/IP вузла + + + MAC address + MAC-адреса + + + Add new computer + Додати новий комп’ютер + + + Remove selected computer + Вилучити позначений комп’ютер + + + New computer + Новий комп’ютер + + + Builtin directory + Вбудований каталог + + + Locations + Місця + + + Add new location + Додати нове місце + + + Remove selected location + Вилучити позначене місце + + + New location + Нове місце + + + Directory name + Назва каталогу + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + Імпортування файлів CSV можна виконати за допомогою інтерфейсу командного рядка. Докладніший опис можна знайти у <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">інтернет-документації</a>. + + + + BuiltinDirectoryPlugin + + Show help for specific command + Показати довідку щодо певної команди + + + Import objects from given file + Імпортувати об'єкти із вказаного файла + + + Export objects to given file + Експортувати об'єкти до вказаного файла + + + Invalid type specified. Valid values are "%1" or "%2". + Вказано некоректний тип. Коректними є значення «%1» і «%2». + + + Type + Тип + + + Name + Назва + + + Host address + Адреса вузла + + + MAC address + MAC-адреса Specified object not found. @@ -997,6 +1205,14 @@ The public key is used on client computers to authenticate incoming connection r MAC ADDRESS MAC-АДРЕСА + + The specified command does not exist or no help is available for it. + Вказаної команди не існує або немає доступу до довідки до неї. + + + Location "%1" not found. + Місце «%1» не знайдено. + BuiltinUltraVncServer @@ -1014,10 +1230,6 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - Вузол/IP-адреса: %1 - Active features: %1 Задіяні можливості: %1 @@ -1034,10 +1246,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off Комп’ютер перебуває поза мережею або його вимкнено - - Service unreachable or not running - Служба недоступна або її не запущено - Authentication failed or access denied Не пройдено розпізнавання або заборонено доступ @@ -1058,6 +1266,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 Місце: %1 + + [no user] + [немає користувача] + + + Veyon Server unreachable or not running + Сервер Veyon є недоступним або сервер не запущено + + + Name: %1 + Назва: %1 + + + Hostname: %1 + Назва вузла: %1 + + + unknown + невідомий + + + IP address: %1 + IP-адреса: %1 + + + Hostname could not be resolved + Не вдалося визначити адресу за назвою вузла + + + No features active + Немає активних можливостей + ComputerControlServer @@ -1089,6 +1329,17 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. Користувач «%1» на вузлі «%2» намагався отримати доступ до цього комп'ютера, але його було заблоковано через параметри керування доступом. + + Active connections: + Активні з'єднання: + + + + ComputerGroupSelector + + Group %1 + Група %1 + ComputerManager @@ -1116,13 +1367,48 @@ The public key is used on client computers to authenticate incoming connection r Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. Не вдалося визначити місце цього комп'ютера. Це означає, що у налаштуваннях системи є проблеми. На панелі вибору комп'ютера буде показано усі місця. + + Logged in since + Працює у системі протягом + + + %1 days + %1 днів + + + 1 day + 1 дня + - ComputerSelectPanel + ComputerMonitoring + + Computers + Комп'ютери + + + Search users and computers + Пошук користувачів і комп'ютерів + + + Select all + Позначити все + + + Unselect all + Скасувати позначення + + + Add to group + Додати до групи + - Computer management - Керування комп'ютерами + Remove from group + Вилучити з групи + + + ComputerSelectPanel Computer search Пошук комп’ютера @@ -1151,81 +1437,85 @@ The public key is used on client computers to authenticate incoming connection r Could not write the computer and users list to %1! Please check the file access permissions. Не вдалося записати список комп’ютерів і користувачів до %1! Будь ласка, перевірте, чи є у вас належні права для доступу до цього файла. + + Search computers + Шукати комп'ютери + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. - Будь ласка, вкажіть файл наявних налаштувань для імпортування. + Clear system-wide Veyon configuration + Вилучити загальносистемні налаштування Veyon - Please specify a valid filename for the configuration export. - Будь ласка, вкажіть коректну назву файла для експортування налаштувань. + List all configuration keys and values + Список усіх ключів і значень налаштувань - Please specify a valid key. - Будь ласка, вкажіть коректний ключ. + Import configuration from given file + Імпортувати налаштування із вказаного файла - Specified key does not exist in current configuration! - Вказаного ключа не існує у поточних налаштуваннях! + Export configuration to given file + Експортувати налаштування до вказаного файла - Please specify a valid value. - Будь ласка, вкажіть коректне значення. + Read and output configuration value for given key + Прочитати і вивести значення налаштування для вказаного ключа - Configure Veyon at command line - Налаштувати Veyon з командного рядка + Write given value to given configuration key + Записати вказане значення до вказаного ключа налаштування - Output file is not writable! - Файл для виведення даних непридатний до запису! + Unset (remove) given configuration key + Скинути (вилучити) вказаний ключ налаштування - Output directory is not writable! - Каталог для виведення даних непридатний до запису! + Upgrade and save configuration of program and plugins + Оновити і зберегти налаштування програми і додатків + + + Please specify an existing configuration file to import. + Будь ласка, вкажіть файл наявних налаштувань для імпортування. Configuration file is not readable! Не вдалося прочитати файл налаштувань! - Clear system-wide Veyon configuration - Вилучити загальносистемні налаштування Veyon + Please specify a valid filename for the configuration export. + Будь ласка, вкажіть коректну назву файла для експортування налаштувань. - List all configuration keys and values - Список усіх ключів і значень налаштувань + Output file is not writable! + Файл для виведення даних непридатний до запису! - Import configuration from given file - Імпортувати налаштування із вказаного файла + Output directory is not writable! + Каталог для виведення даних непридатний до запису! - Export configuration to given file - Експортувати налаштування до вказаного файла + Please specify a valid key. + Будь ласка, вкажіть коректний ключ. - Read and output configuration value for given key - Прочитати і вивести значення налаштування для вказаного ключа + Specified key does not exist in current configuration! + Вказаного ключа не існує у поточних налаштуваннях! - Write given value to given configuration key - Записати вказане значення до вказаного ключа налаштування + Please specify a valid value. + Будь ласка, вкажіть коректне значення. - Unset (remove) given configuration key - Скинути (вилучити) вказаний ключ налаштування + Configure Veyon at command line + Налаштувати Veyon з командного рядка Commands for managing the configuration of Veyon Команди для керування налаштуваннями Veyon - - Upgrade and save configuration of program and plugins - Оновити і зберегти налаштування програми і додатків - ConfigurationManager @@ -1249,6 +1539,10 @@ The public key is used on client computers to authenticate incoming connection r Could not apply platform-specific configuration settings. Не вдалося застосувати специфічні для платформи параметри налаштувань. + + Could not configure the firewall configuration for the %1 Service. + Не вдалося налаштувати брандмауер для служби %1. + DemoClient @@ -1279,10 +1573,6 @@ The public key is used on client computers to authenticate incoming connection r Memory limit Межа пам’яті - - Use multithreading (experimental) - Використовувати багатопоточність (експериментальне) - MB МБ @@ -1299,13 +1589,17 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running Уповільнити оновлення мініатюр, доки запущено демонстрацію + + Bandwidth limit + Обмеження потоку даних + + + MB/s + МБ/с + DemoFeaturePlugin - - Fullscreen demo - Повноекранне демо - Stop demo Припинити демонстрацію @@ -1319,16 +1613,60 @@ The public key is used on client computers to authenticate incoming connection r Виконати демонстрацію трансляцією зображення на екрані - Demo server - Демосервер + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + У цьому режимі зображення з вашого екрана буде показано у вікні на всіх комп’ютерах. Користувачі, якщо захочуть, матимуть змогу перемикатися на інші вікна. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. + Demo + Демонстрація + + + Share your screen or allow a user to share his screen with other users. + Оприлюдніть зображення з вашого екрана або дозвольте користувачам оприлюднювати зображення з їхнього екрана для інших користувачів. + + + Full screen demo + Повноекранне демо + + + Share your own screen in fullscreen mode + Оприлюднити ваш екран у повноекранному режимі + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. У цьому режимі зображення з екрана вашого комп'ютера демонструватиметься на увесь екран на усіх комп'ютерах, а пристрої введення даних на комп'ютерах буде заблоковано. - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - У цьому режимі зображення з вашого екрана буде показано у вікні на всіх комп’ютерах. Користувачі, якщо захочуть, матимуть змогу перемикатися на інші вікна. + Share your own screen in a window + Оприлюднити ваш екран у вікні + + + Share selected user's screen in fullscreen mode + Оприлюднити екран вибраного користувача у повноекранному режимі + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + У цьому режимі зображення з екрана комп'ютера вибраного користувача демонструватиметься на увесь екран на усіх комп'ютерах, а пристрої введення даних на комп'ютерах буде заблоковано. + + + Share selected user's screen in a window + Оприлюднити екран вибраного користувача у вікні + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + У цьому режимі зображення з екрана вибраного користувача буде показано у вікні на всіх комп'ютерах. Користувачі, якщо захочуть, матимуть змогу перемикатися на інші вікна. + + + Please select a user screen to share. + Будь ласка, виберіть екран користувача для оприлюднення. + + + Please select only one user screen to share. + Будь ласка, виберіть лише один екран користувача для оприлюднення. + + + All screens + Усі екрани @@ -1356,14 +1694,6 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - - Programs & websites - Програми і сайти - - - Predefined programs - Попередньо визначені програми - Name Назва @@ -1372,14 +1702,6 @@ The public key is used on client computers to authenticate incoming connection r Path Шлях - - Add new program - Додати нову програму - - - Remove selected program - Вилучити позначену програму - Predefined websites Попередньо визначені сайти @@ -1392,21 +1714,37 @@ The public key is used on client computers to authenticate incoming connection r URL Адреса - - New program - Нова програма - New website Новий сайт + + Applications & websites + Програми і сайти + + + Predefined applications + Попередньо визначені програми + + + Add new application + Додати нову програму + + + Remove selected application + Вилучити позначену програму + + + Add new website + Додати новий сайт + + + New application + Нова програма + DesktopServicesFeaturePlugin - - Run program - Виконати програму - Open website Відкрити сайт @@ -1416,28 +1754,32 @@ The public key is used on client computers to authenticate incoming connection r Натисніть цю кнопку, щоб відкрити сайт на усіх комп’ютерах. - Start programs and services in user desktop - Запустити програми і служби на робочій станції користувача + Open website "%1" + Відкрити сайт «%1» - Click this button to run a program on all computers. - Натисніть цю кнопку, щоб запустити програму на усіх комп’ютерах. + Custom website + Нетиповий сайт - Run program "%1" - Виконати програму «%1» + Start application + Запустити програму - Custom program - Нетипова програма + Click this button to start an application on all computers. + Натисніть цю кнопку, щоб запустити програму на усіх комп'ютерах. - Open website "%1" - Відкрити сайт «%1» + Start application "%1" + Запустити програму «%1» - Custom website - Нетиповий сайт + Custom application + Нетипова програма + + + Start apps and open websites in user sessions + Запустити програми і відкрити сайти у сеансах користувачів @@ -1470,17 +1812,21 @@ The public key is used on client computers to authenticate incoming connection r Play tutorial video Відтворити навчальне відео - - Custom program - Нетипова програма - Handout - + Безкоштовний зразок Texts to read - + Фрагменти тексту для читання + + + generic-student-user + типовий-користувач-учень + + + Custom application + Нетипова програма @@ -1506,10 +1852,165 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands + + List names of all available features + Вивести список назв усіх доступних можливостей + + + Show table with details of all available features + Показати таблицю із подробицями щодо усіх доступних можливостей + + + Start a feature on a remote host + Запустити можливість на віддаленому вузлі + + + Stop a feature on a remote host + Зупинити роботу можливості на віддаленому вузлі + + + Please specify the command to display help for. + Будь ласка, вкажіть команду, для якої слід показати довідку. + + + Displays a list with the names of all available features. + Показати список із назвами усіх доступних можливостей + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + Показує таблицю із докладними відомостями щодо усіх доступних можливостей. Серед цих відомостей опис, UID, назва додатка, який забезпечує роботу можливості, та деякі інші пов'язані із реалізацією подробиці. + + + HOST ADDRESS + АДРЕСА ВУЗЛА + + + FEATURE + МОЖЛИВІСТЬ + + + ARGUMENTS + АРГУМЕНТИ + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + Запускає вказану можливість на вказаному вузлі шляхом з'єднання із запущеним віддалено сервером Veyon. Можливість можна вказати за назвою або UID. Скористайтеся командою «show», щоб переглянути список усіх доступних можливостей. Залежно від можливості, може бути вказано додаткові аргументи (зокрема текстове повідомлення для показу), які має бути закодовано у один рядок JSON. Щоб дізнатися більше, зверніться до документації для розробників. + + + Lock the screen + Заблокувати екран + + + Display a text message + Показати текстове повідомлення + + + Test message + Тестове повідомлення + + + Start an application + Запустити програму + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + Зупиняє роботу вказаної можливості на вказанмоу вузлі шляхом з'єднання із запущеним віддалено сервером Veyon. Можливість можна вказати за назвою або UID. Скористайтеся командою «show», щоб переглянути список усіх доступних можливостей. + + + Unlock the screen + Розблокувати екран + + + The specified command does not exist or no help is available for it. + Вказаної команди не існує або немає доступу до довідки до неї. + + + Name + Назва + + + Description + Опис + + + Master + Основний + + + Service + Служба + + + Worker + Обробник + + + UID + UID + + + Plugin + Додаток + + + Invalid feature name or UID specified + Вказано некоректну назву або UID можливості + + + Error parsing the JSON-encoded arguments: %1 + Помилка під час спроби обробити закодовані у JSON аргументи: %1 + + + Failed to initialize credentials + Не вдалося ініціалізувати реєстраційні дані + + + Could not establish a connection to host %1 + Не вдалося встановити з'єднання із вузлом %1 + + + Failed to send feature control message to host %1 + Не вдалося надіслати повідомлення керування можливістю на вузол %1 + + + Feature-related CLI operations + Пов'язані із можливістю дії командного рядка + + + Commands for controlling features + Команди для керування можливостями + + + + FileTransferConfigurationPage + + File transfer + Передавання файлів + - Feature control - Керування можливосями + Directories + Каталоги + + + Destination directory + Каталог призначення + + + Default source directory + Типовий каталог початкових даних + + + Options + Параметри + + + Remember last source directory + Запам'ятовувати останній каталог початкових даних + + + Create destination directory if it does not exist + Створювати каталог призначення, якщо його не існує @@ -1554,6 +2055,13 @@ The public key is used on client computers to authenticate incoming connection r Перезаписати наявні файли + + FileTransferFileDialog + + Select one or more files to transfer + Виберіть один або декілька файлів для передавання + + FileTransferPlugin @@ -1611,10 +2119,6 @@ The public key is used on client computers to authenticate incoming connection r Log file directory Каталог файла журналу - - ... - ... - Log level Рівень журналювання @@ -1655,18 +2159,6 @@ The public key is used on client computers to authenticate incoming connection r Log to standard error output Виводити повідомлення до стандартного виводу помилок - - Network object directory - Каталог мережевих об’єктів - - - Backend: - Модуль: - - - Update interval: - Інтервал оновлення: - %1 service Служба %1 @@ -1703,103 +2195,80 @@ The public key is used on client computers to authenticate incoming connection r x x - - seconds - секунд - Write to logging system of operating system Записувати до журналу операційної системи - Authentication - Розпізнавання - - - Method: - Метод: - - - Logon authentication - Розпізнавання під час входу - - - Key file authentication - Розпізнавання за файлами ключів - - - Test - Перевірити + TLS configuration + Налаштування TLS - Authentication is set up properly on this computer. - На цьому комп'ютері належним чином налаштовано розпізнавання. + Use certificate authority for TLS connections + Використовувати службу сертифікації для з'єднань TLS - Authentication keys are not set up properly on this computer. - На цьому комп'ютері ключі розпізнавання налаштовано не так, як слід. + CA certificate file + Файл сертифіката CA - Authentication test - Перевірка розпізнавання + ... + ... - - - InternetAccessControlConfigurationPage - Internet access control - Керування доступом до інтернету + Host certificate file + Файл сертифіката вузла - Backend: - Модуль: + Host private key file + Файл закритого ключа вузла - General settings - Загальні параметри + Style: + Стиль: - Backend settings - Параметри модулів + Native + Природний - - - InternetAccessControlPlugin - Block access to the internet - Блокувати доступу до інтернету + Color scheme: + Схема кольорів: - Allow access to the internet - Дозволити доступ до інтернету + Light + Світла - Show help about command - Показати довідку щодо команди + Dark + Темна - Block internet - Блокувати інтернет + User groups + Групи користувачів - Click this button to block access to the internet. - Натисніть цю кнопку, щоб заблокувати доступ до інтернету. + Backend: + Модуль: - Unblock internet - Розблокувати інтернет + Include user groups from domain + Включити групи користувачів з домену - Click this button to allow access to the internet. - Натисніть цю кнопку, щоб дозволити доступ до інтернету. + Missing user groups backend + Не вистачає модуля обробки груп користувачів - Control access to the internet - Керування доступом до інтернету + No user groups plugin was found. Please check your installation! + Не знайдено додатка груп користувачів. Будь ласка, перевірте, чи належним чином встановлено програму! + + + HeadlessVncServer - Commands for controlling access to the internet - Команди для керування доступом до інтернету + Headless VNC server + Автоматичний сервер VNC @@ -1817,23 +2286,354 @@ The public key is used on client computers to authenticate incoming connection r - LdapConfigurationPage + LdapConfiguration - Basic settings - Основні параметри + LDAP connection failed + Невдала спроба встановити LDAP-з’єднання - General - Загальні + Could not connect to the LDAP server. Please check the server parameters. + +%1 + Не вдалося з'єднатися із сервером LDAP. Будь ласка, перевірте, чи правильно вказано параметри сервера. + +%1 + + - LDAP server and port - Сервер і порт LDAP + LDAP bind failed + Помилка прив’язування до LDAP - Bind DN - DN для прив'язки - + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + Не вдалося прив'язатися до сервера LDAP. Будь ласка, перевірте, чи правильно вказано параметри сервера та реєстраційні дані прив'язки. + +%1 + + + LDAP bind successful + Успішне прив’язування до LDAP + + + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Виконано успішне з’єднання із сервером LDAP і прив’язування LDAP. Належним чином налаштовано основні параметри LDAP. + + + LDAP base DN test failed + Не вдалося пройти перевірку кореневого DN LDAP + + + Could not query the configured base DN. Please check the base DN parameter. + +%1 + Не вдалося опитати налаштований базовий DN. Будь ласка, перевірите, чи правильно вказано параметр базового DN. + +%1 + + + LDAP base DN test successful + Успішна перевірка кореневого DN LDAP + + + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + Успішно опитано базовий DN LDAP. Знайдено такі записи: + +%1 + + + LDAP naming context test failed + Не вдалося пройти перевірку контексту іменування LDAP + + + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + Не вдалося опитати базовий DN за контекстами іменування. Будь ласка, перевірите, чи правильно вказано параметр атрибута контексту іменування. + +%1 + + + LDAP naming context test successful + Успішно пройдено перевірку контексту іменування LDAP + + + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + Успішно виконано опитування контексту іменування LDAP. Виявлено такий кореневий DN: +%1 + + + user tree + ієрархія користувачів + + + User tree + Ієрархія користувачів + + + group tree + ієрархія груп + + + Group tree + Ієрархія груп + + + computer tree + ієрархія комп’ютерів + + + Computer tree + Ієрархія комп’ютерів + + + computer group tree + ієрархії груп комп’ютерів + + + Computer group tree + Ієрархія груп комп’ютерів + + + user objects + об’єкти користувачів + + + User login name attribute + Атрибут імені користувача + + + group members + учасники групи + + + Group member attribute + Атрибут членства у групі + + + Group not found + Групи не знайдено + + + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + Не вдалося знайти групу із назвою «%1». Будь ласка, перевірте, чи правильно вказано назву групи або параметр ієрархії груп. + + + computer objects + об’єкти комп’ютерів + + + Computer display name attribute + Атрибут показаної назви комп'ютера + + + Invalid hostname + Некоректна назва вузла + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + Ви налаштували програму на зберігання повних доменних назв вузлів комп’ютерів (FQDN), але вказали назву вузла без домену. + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + Ви налаштували програму на зберігання простих назв вузлів комп’ютерів, але вказали назву вузла разом із назвою домену. + + + Computer hostname attribute + Атрибут назви вузла комп’ютера + + + computer MAC addresses + MAC-адреси комп’ютерів + + + Computer MAC address attribute + Атрибут MAC-адреси комп’ютера + + + computer locations + місця комп'ютерів + + + Computer location attribute + Атрибут місця комп'ютера + + + Location name attribute + Атрибут назви місця + + + users + користувачі + + + user groups + групи користувачів + + + computers + комп'ютери + + + computer groups + групи комп’ютерів + + + computer containers + контейнери комп'ютерів + + + groups of user + групи користувача + + + User not found + Користувача не знайдено + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + Не вдалося знайти користувача із іменем «%1». Будь ласка, перевірте, чи правильно вказано ім’я користувача або параметр ієрархії користувачів. + + + groups of computer + групи комп’ютера + + + Computer not found + Комп’ютер не знайдено + + + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Не вдалося знайти комп’ютер із назвою вузла «%1». Будь ласка, перевірте, чи правильно вказано назву вузла або параметр ієрархії комп’ютерів. + + + Hostname lookup failed + Помилка пошуку вузла за назвою + + + Could not lookup hostname for IP address %1. Please check your DNS server settings. + Не вдалося виконати пошук назви вузла для IP-адреси %1. Будь ласка, перевірте, чи правильно вказано параметри вашого сервера DNS. + + + location entries + записи місць + + + Computer groups filter + Фільтр груп комп'ютерів + + + Computer locations identification + Ідентифікація місць комп'ютерів + + + Filter for computer groups + Фільтрування за групами комп’ютерів + + + Invalid test value + Некоректне тестове значення + + + An empty or invalid value has been supplied for this test. + Для тестування надано порожнє або некоректне значення. + + + LDAP %1 test failed + Помилка тестування LDAP %1 + + + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + Не вдалося опитати жодний із записів у налаштованій %1. Будь ласка, перевірте, чи правильно вказано параметр «%2». + +%3 + + + LDAP %1 test successful + Успішне тестування LDAP %1 + + + The %1 has been queried successfully and %2 entries were found. + Успішно опитано %1, виявлено %2 записів. + + + LDAP test failed + Не пройдено перевірку LDAP + + + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + Не вдалося виконати опитування для жодного %1. Будь ласка, перевірте, чи правильно вказано параметри %2, або вкажіть назву наявного об’єкта. + +%3 + + + and + і + + + LDAP test successful + Перевірку LDAP пройдено + + + %1 %2 have been queried successfully: + +%3 + %1 %2 успішно опитано: + +%3 + + + LDAP filter test failed + Помилка тестування фільтрування LDAP + + + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 + Не вдалося виконати опитування для жодного %1 з використанням налаштованого фільтрування. Будь ласка, перевірте, чи правильно вказано фільтр LDAP для %1. + +%2 + + + LDAP filter test successful + Успішна перевірка фільтрування LDAP + + + %1 %2 have been queried successfully using the configured filter. + %1 %2 було успішно опитано за допомогою налаштованого фільтра. + + + LDAP directory + Каталог LDAP + + + + LdapConfigurationPage + + Basic settings + Основні параметри + + + General + Загальні + + + LDAP server and port + Сервер і порт LDAP + + + Bind DN + DN для прив'язки + Bind password Пароль прив’язки @@ -1970,56 +2770,6 @@ The public key is used on client computers to authenticate incoming connection r Get computer object by IP address Отримати об’єкт комп’ютера за IP-адресою - - LDAP connection failed - Невдала спроба встановити LDAP-з’єднання - - - LDAP bind failed - Помилка прив’язування до LDAP - - - LDAP bind successful - Успішне прив’язування до LDAP - - - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - Виконано успішне з’єднання із сервером LDAP і прив’язування LDAP. Належним чином налаштовано основні параметри LDAP. - - - LDAP base DN test failed - Не вдалося пройти перевірку кореневого DN LDAP - - - LDAP base DN test successful - Успішна перевірка кореневого DN LDAP - - - LDAP naming context test failed - Не вдалося пройти перевірку контексту іменування LDAP - - - LDAP naming context test successful - Успішно пройдено перевірку контексту іменування LDAP - - - The LDAP naming context has been queried successfully. The following base DN was found: -%1 - Успішно виконано опитування контексту іменування LDAP. Виявлено такий кореневий DN: -%1 - - - user tree - ієрархія користувачів - - - group tree - ієрархія груп - - - computer tree - ієрархія комп’ютерів - Enter username Введіть ім’я користувача @@ -2028,10 +2778,6 @@ The public key is used on client computers to authenticate incoming connection r Please enter a user login name (wildcards allowed) which to query: Вкажіть запис користувача (можна використовувати символи-замінники), дані якого слід отримати: - - user objects - об’єкти користувачів - Enter group name Введіть назву групи @@ -2040,26 +2786,10 @@ The public key is used on client computers to authenticate incoming connection r Please enter a group name whose members to query: Будь ласка, вкажіть назву групи, учасників якої слід визначити: - - group members - учасники групи - - - Group not found - Групи не знайдено - - - Could not find a group with the name "%1". Please check the group name or the group tree parameter. - Не вдалося знайти групу із назвою «%1». Будь ласка, перевірте, чи правильно вказано назву групи або параметр ієрархії груп. - Enter computer name Вкажіть назву комп’ютера - - computer objects - об’єкти комп’ютерів - Enter computer DN Вкажіть DN комп’ютера @@ -2069,92 +2799,16 @@ The public key is used on client computers to authenticate incoming connection r Будь ласка, вкажіть DN комп’ютера, запит щодо MAC-адреси якого слід надіслати: - computer MAC addresses - MAC-адреси комп’ютерів - - - users - користувачі - - - user groups - групи користувачів - - - computer groups - групи комп’ютерів - - - Please enter a user login name whose group memberships to query: - Будь ласка, вкажіть назву запису користувача, для кого слід отримати дані щодо участі у групах: - - - groups of user - групи користувача - - - User not found - Користувача не знайдено - - - groups of computer - групи комп’ютера - - - Computer not found - Комп’ютер не знайдено - - - Enter computer IP address - Вкажіть IP-адресу комп’ютера - - - Please enter a computer IP address which to resolve to an computer object: - Будь ласка, вкажіть IP-адресу комп’ютера, за якою слід визначити об’єкт комп’ютера: - - - computers - комп'ютери - - - LDAP %1 test failed - Помилка тестування LDAP %1 - - - LDAP %1 test successful - Успішне тестування LDAP %1 - - - The %1 has been queried successfully and %2 entries were found. - Успішно опитано %1, виявлено %2 записів. - - - %1 %2 have been queried successfully: - -%3 - %1 %2 успішно опитано: - -%3 - - - LDAP filter test failed - Помилка тестування фільтрування LDAP - - - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 - Не вдалося виконати опитування для жодного %1 з використанням налаштованого фільтрування. Будь ласка, перевірте, чи правильно вказано фільтр LDAP для %1. - -%2 - - - LDAP filter test successful - Успішна перевірка фільтрування LDAP + Please enter a user login name whose group memberships to query: + Будь ласка, вкажіть назву запису користувача, для кого слід отримати дані щодо участі у групах: - %1 %2 have been queried successfully using the configured filter. - %1 %2 було успішно опитано за допомогою налаштованого фільтра. + Enter computer IP address + Вкажіть IP-адресу комп’ютера + + + Please enter a computer IP address which to resolve to an computer object: + Будь ласка, вкажіть IP-адресу комп’ютера, за якою слід визначити об’єкт комп’ютера: (only if different from group tree) @@ -2164,10 +2818,6 @@ The public key is used on client computers to authenticate incoming connection r Computer group tree Ієрархія груп комп’ютерів - - computer group tree - ієрархії груп комп’ютерів - Filter for computers Фільтр для комп’ютерів @@ -2248,52 +2898,10 @@ The public key is used on client computers to authenticate incoming connection r e.g. (objectClass=container) or (objectClass=organizationalUnit) наприклад (objectClass=container) або (objectClass=organizationalUnit) - - Could not query the configured base DN. Please check the base DN parameter. - -%1 - Не вдалося опитати налаштований базовий DN. Будь ласка, перевірите, чи правильно вказано параметр базового DN. - -%1 - - - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - Успішно опитано базовий DN LDAP. Знайдено такі записи: - -%1 - - - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - Не вдалося опитати базовий DN за контекстами іменування. Будь ласка, перевірите, чи правильно вказано параметр атрибута контексту іменування. - -%1 - Certificate files (*.pem) файли сертифікатів (*.pem) - - Could not connect to the LDAP server. Please check the server parameters. - -%1 - Не вдалося з'єднатися із сервером LDAP. Будь ласка, перевірте, чи правильно вказано параметри сервера. - -%1 - - - - - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - Не вдалося прив'язатися до сервера LDAP. Будь ласка, перевірте, чи правильно вказано параметри сервера та реєстраційні дані прив'язки. - -%1 - Encryption protocol Протокол шифрування @@ -2343,379 +2951,146 @@ The public key is used on client computers to authenticate incoming connection r Будь ласка, вкажіть показану назву комп’ютера для запиту: - Enter computer location name - Введіть назву місця комп'ютера - - - Please enter the name of a computer location (wildcards allowed): - Введіть назву місця комп'ютера (можна використовувати символи-замінники): - - - computer locations - місця комп'ютерів - - - Enter location name - Вкажіть назву місця - - - Please enter the name of a location whose entries to query: - Будь ласка, вкажіть назву місця, запит до учасників якого слід виконати: - - - location entries - записи місць - - - LDAP test failed - Не пройдено перевірку LDAP - - - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - Не вдалося виконати опитування для жодного %1. Будь ласка, перевірте, чи правильно вказано параметри %2, або вкажіть назву наявного об’єкта. - -%3 - - - and - і - - - LDAP test successful - Перевірку LDAP пройдено - - - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - Не вдалося опитати жодний із записів у налаштованій %1. Будь ласка, перевірте, чи правильно вказано параметр «%2». - -%3 - - - Browse - Навігація - - - Test - Перевірити - - - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - Назви вузлів збережено як повні доменні назви (FQDN, наприклад myhost.example.org) - - - Computer hostname attribute - Атрибут назви вузла комп’ютера - - - Please enter a computer hostname to query: - Будь ласка, вкажіть назву вузла комп’ютера для запиту: - - - Invalid hostname - Некоректна назва вузла - - - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - Ви налаштували програму на зберігання повних доменних назв вузлів комп’ютерів (FQDN), але вказали назву вузла без домену. - - - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - Ви налаштували програму на зберігання простих назв вузлів комп’ютерів, але вказали назву вузла разом із назвою домену. - - - Could not find a user with the name "%1". Please check the username or the user tree parameter. - Не вдалося знайти користувача із іменем «%1». Будь ласка, перевірте, чи правильно вказано ім’я користувача або параметр ієрархії користувачів. - - - Enter hostname - Введіть назву вузла - - - Please enter a computer hostname whose group memberships to query: - Будь ласка, вкажіть назву вузла комп’ютера, для кого слід отримати дані щодо участі у групах: - - - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - Не вдалося знайти комп’ютер із назвою вузла «%1». Будь ласка, перевірте, чи правильно вказано назву вузла або параметр ієрархії комп’ютерів. - - - Hostname lookup failed - Помилка пошуку вузла за назвою - - - Could not lookup hostname for IP address %1. Please check your DNS server settings. - Не вдалося виконати пошук назви вузла для IP-адреси %1. Будь ласка, перевірте, чи правильно вказано параметри вашого сервера DNS. - - - User login name attribute - Атрибут імені користувача - - - Configured attribute for user login name or computer hostname (OpenLDAP) - Налаштований атрибут для імені користувача або назви вузла комп’ютера (OpenLDAP) - - - computer containers - контейнери комп'ютерів - - - - LdapPlugin - - Auto-configure the base DN via naming context - Автоматичне налаштовування базового DN за контекстном назви - - - Query objects from LDAP directory - Опитати об’єкти з каталогу LDAP - - - Show help about command - Показати довідку щодо команди - - - Commands for configuring and testing LDAP/AD integration - Команди для налаштовування і тестування інтеграції із LDAP/AD - - - Basic LDAP/AD support for Veyon - Базова підтримка LDAP/AD у Veyon - - - %1 (load computers and locations from LDAP/AD) - %1 (завантажити записи комп'ютерів та місця з LDAP/AD) - - - %1 (load users and groups from LDAP/AD) - %1 (завантажити записи користувачів та груп з LDAP/AD) - - - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - Будь ласка, вкажіть коректну адресу LDAP у такому форматі: "ldap[s]://[користувач[:пароль]@]назва_вузла[:порт]" - - - No naming context attribute name given - falling back to configured value. - Не вказано атрибута контексту іменування — повертаємося до налаштованого значення. - - - Could not query base DN. Please check your LDAP configuration. - Не вдалося обробити запит щодо кореневого DN. Будь ласка, перевірте, чи правильно налаштовано LDAP. - - - Configuring %1 as base DN and disabling naming context queries. - Налаштовуємо %1 як кореневий DN і вимикаємо запити щодо контексту іменування. - - - - LdapProConfigurationPage - - LDAP Pro - LDAP Pro - - - Instances - Екземпляри - - - Enter name - Введіть назву - - - Please enter a name for the instance (can't be changed later!): - Будь ласка, введіть назву екземпляра (її не можна буде змінити!): - - - Remove instance - Вилучити екземпляр - - - Do you really want to remove instance "%1"? - Ви справді хочете вилучити екземпляр «%1»? - - - Configuration for instance "%1" - Налаштування для екземпляра «%1» - - - - LdapProPlugin - - Professional LDAP/AD integration for Veyon - Професійна інтеграція LDAP/AD до Veyon - - - %1 (load computers and locations from LDAP/AD) - %1 (завантажити записи комп'ютерів та місця з LDAP/AD) - - - %1 (load users and groups from LDAP/AD) - %1 (завантажити записи користувачів та груп з LDAP/AD) - - - - LicensingConfigurationPage - - Licensing - Ліцензування + Enter computer location name + Введіть назву місця комп'ютера - Installed licenses - Встановлені ліцензії + Please enter the name of a computer location (wildcards allowed): + Введіть назву місця комп'ютера (можна використовувати символи-замінники): - Add new network range - Додати новий діапазон мережі + Enter location name + Вкажіть назву місця - Remove selected network range - Вилучити позначений діапазон мережі + Please enter the name of a location whose entries to query: + Будь ласка, вкажіть назву місця, запит до учасників якого слід виконати: - ID - Ідентифікатор + Browse + Навігація - Feature - Можливість + Test + Перевірити - Valid until - Чинний до + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + Назви вузлів збережено як повні доменні назви (FQDN, наприклад myhost.example.org) - Licensee - Ліцензіат + Computer hostname attribute + Атрибут назви вузла комп’ютера - Browse license file - Переглянути файл ліцензії + Please enter a computer hostname to query: + Будь ласка, вкажіть назву вузла комп’ютера для запиту: - Veyon license files (*.vlf) - файли ліцензій Veyon (*.vlf) + Enter hostname + Введіть назву вузла - Remove license - Вилучити ліцензію + Please enter a computer hostname whose group memberships to query: + Будь ласка, вкажіть назву вузла комп’ютера, для кого слід отримати дані щодо участі у групах: - Do you really want to remove the selected license? - Ви справді хочете вилучити позначену ліцензію? + User login name attribute + Атрибут імені користувача - <N/A> - <н/д> + Configured attribute for user login name or computer hostname (OpenLDAP) + Налаштований атрибут для імені користувача або назви вузла комп’ютера (OpenLDAP) - Invalid license file - Некоректний файл ліцензії + Directory name + Назва каталогу - Could not open the license file for reading! - Не вдалося відкрити файл ліцензії для читання! + Query options + Параметри запиту - The selected license file does not contain valid data. - У позначеному файлі ліцензії не міститься коректних даних. + Query nested user groups (supported by AD only) + Опитати вкладені групи користувачів (лише для AD) - The selected license file could not be verified. - Позначений файл ліцензії не вдалося перевірити. + Query timeout + Перевищення часу очікування на виконання запиту - The selected license file is not valid for this installation. - Позначений файл ліцензії не є чинним для цього встановлення. + ms + мс + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. - Строк дії позначеного файла ліцензії вичерпано. + LDAP + LDAP - The license is already installed. - Цю ліцензію вже встановлено. + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + Будь ласка, скористайтеся загальною сторінкою налаштувань LDAP для налаштовування способу отримання даних щодо розташування та комп'ютерів з вашої служби каталогів на основі LDAP. + + + LdapPlugin - Information - Інформація + Auto-configure the base DN via naming context + Автоматичне налаштовування базового DN за контекстном назви - Installation ID - Ід. встановлення + Query objects from LDAP directory + Опитати об’єкти з каталогу LDAP - Addons available for licensing - Додатки, які доступні до ліцензування + Show help about command + Показати довідку щодо команди - Addon - Додаток + Commands for configuring and testing LDAP/AD integration + Команди для налаштовування і тестування інтеграції із LDAP/AD - - - LicensingPlugin - Show help for specific command - Показати довідку щодо певної команди + Basic LDAP/AD support for Veyon + Базова підтримка LDAP/AD у Veyon - Show all installed licenses - Показати усі встановлені ліцензії + %1 (load computers and locations from LDAP/AD) + %1 (завантажити записи комп'ютерів та місця з LDAP/AD) - Add license file - Додати файл ліцензії + %1 (load users and groups from LDAP/AD) + %1 (завантажити записи користувачів та груп з LDAP/AD) - Remove installed license - Вилучити встановлену ліцензію + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Будь ласка, вкажіть коректну адресу LDAP у такому форматі: "ldap[s]://[користувач[:пароль]@]назва_вузла[:порт]" - -USAGE - -%1 add <LICENSE FILE> - - - -КОРИСТУВАННЯ - -%1 add <LICENSE FILE> - - + No naming context attribute name given - falling back to configured value. + Не вказано атрибута контексту іменування — повертаємося до налаштованого значення. - -USAGE - -%1 remove <LICENSE ID> - - - -КОРИСТУВАННЯ - -%1 remove <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. + Не вдалося обробити запит щодо кореневого DN. Будь ласка, перевірте, чи правильно налаштовано LDAP. - No certificate found with given ID - Не знайдено сертифіката із вказаним ідентифікатором + Configuring %1 as base DN and disabling naming context queries. + Налаштовуємо %1 як кореневий DN і вимикаємо запити щодо контексту іменування. - <N/A> - <н/д> + Test binding to an LDAP server + Тестова прив'язка до сервера LDAP - Licensing management - Керування ліцензіями + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + Надане значення імені користувача або пароля є помилковим. Будь ласка, вкажіть коректні реєстраційні дані або перемкніть систему на інший спосіб розпізнавання за допомогою засобу налаштовування Veyon. - Commands for managing license keys - Команди для керування файлами ліцензій + LDAP bind + Прив'язка до LDAP @@ -2733,12 +3108,20 @@ USAGE Розпізнавання користувача - Session management - Керування сеансами + User sessions + Сеанси користувачів + + + Minimum session lifetime before server start + Мінімальна тривалість сеансу до запуску сервера - Display manager users - Користувачі керування дисплеєм + User login + Вхід від імені користувача + + + Login key sequence + Послідовність ключів для входу @@ -2747,10 +3130,6 @@ USAGE Plugin implementing abstract functions for the Linux platform Додаток, який реалізуває абстрактні функції на платформі Linux - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2769,14 +3148,14 @@ USAGE Configuration Налаштування - - Disable balloon tooltips - Вимкнути панелі підказок - Show icons only Показати лише піктограми + + Disable tooltips + Вимкнути підказки + MainWindow @@ -2824,10 +3203,6 @@ USAGE About Qt Про Qt - - Authentication impossible - Розпізнавання неможливе - Configuration not writable Не вдалося записати налаштування @@ -2888,10 +3263,6 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. Модуль керування локальними налаштуваннями повідомив, що не вдалося виконати запис до файла налаштувань! Будь ласка, запустіть Засіб налаштовування %1 із ширшими правами доступу. - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - Не знайдено файлів ключів розпізнавання або строк дії знайдених ключів вичерпано. Будь ласка, створіть нові файли ключів за допомогою засобу налаштовування %1. Крім того, ви можете налаштувати розпізнавання за іменем користувача під час входу до системи, скориставшись для цього засобом налаштовування %1. Якщо ви не створите ключів і не налаштуєте розпізнавання, ви не зможете отримувати доступ до комп’ютерів за допомогою %1. - Access denied Доступ заборонено @@ -2924,10 +3295,6 @@ USAGE Search users and computers Пошук користувачів і комп'ютерів - - Adjust optimal size - Скоригувати оптимальний розмір - Align computers to grid Вирівняти комп'ютери за ґраткою @@ -2972,6 +3339,50 @@ USAGE Locations && computers Місця && комп'ютери + + Authentication + Розпізнавання + + + Adjust size of computer icons automatically + Автоматично коригувати розмір піктограм комп'ютерів + + + Slideshow + Показ слайдів + + + Spotlight + Акцент + + + Veyon Master + Головний комп'ютер Veyon (Veyon Master) + + + Locations & computers + Місця і комп'ютери + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + Використати нетипову конфігурацію комп'ютерів. + +Натисніть і утримуйте, щоб завантажити конфігурацію з файла або зберегти конфігурацію до файла. + + + Only show computers with logged on users + Показувати лише комп'ютери із користувачами у системі + + + Load computer positions + Звантажити місця комп'ютерів + + + Save computer positions + Зберегти місця комп'ютерів + MasterConfigurationPage @@ -2979,10 +3390,6 @@ USAGE Directories Каталоги - - ... - ... - User configuration Налаштування користувачів @@ -3067,6 +3474,10 @@ USAGE Only user name Лише ім'я користувача + + Only last part of user name + + Only computer name Лише назва комп'ютера @@ -3115,171 +3526,181 @@ USAGE Automatically select current location Автоматично вибирати поточне місце - - Automatically adjust computer thumbnail size - Автоматично коригувати розмір мініатюри комп'ютера - Automatically open computer select panel Автоматично відкрити панель вибору комп'ютера - - - MonitoringMode - Monitoring - Спостереження + Use modern user interface (experimental) + Сучасний інтерфейс користувача (експериментальне) - Builtin monitoring mode - Вбудований режим стеження + Thumbnail spacing + Інтервали між мініатюрами - This mode allows you to monitor all computers at one or more locations. - У цьому режимі ви можете спостерігати за усіма комп'ютерами у одному або декількох місцях. + px + пк - - - NetworkDiscoveryConfigurationPage - Network discovery - Виявлення мережі + Hide local session + Приховати локальний сеанс - Mode - Режим + Auto + Авто - Scan network ranges - Сканувати діапазони мережі + Thumbnail aspect ratio + Співвідношення розмірів мініатюри - e.g. 192.168.1.0/24 - Приклад: 192.168.1.0/24 + Automatically adjust computer icon size + Автоматично коригувати розмір піктограм комп'ютерів - Scan all subnets of computer - Сканувати усі підмережі комп'ютера + Open feature windows on the same screen as the main window + Відкривати вікна додатків на тому самому екрані, що і головне вікно - Scan custom subnet - Сканувати нетипову підмережу + Configuration templates + Шаблони налаштувань - Scan sessions on local computer - Сканувати сеанси на локальному комп'ютері + Image quality in monitoring mode + Якість зображення у режимі стеження - Test - Перевірити + Highest + Найвища - Network ranges - Діапазони мережі + High + Висока - Add new group - Додати нову групу + Medium + Середня - Remove selected group - Вилучити позначену групу + Low + Низька - Groups - Групи + Lowest + Найнижча - First address - Перша адреса + Remote access image quality + Якість зображення віддаленого доступу - Last address - Остання адреса + Advanced + Додатково - Add new network range - Додати новий діапазон мережі + Computer name source + Джерело назв комп'ютерів - Remove selected network range - Вилучити позначений діапазон мережі + Default + Типове - Parallel scans - Паралельне сканування + Host address + Адреса вузла - Scan timeout - Час очікування на сканування + Session client address + Адреса клієнта сеансу - ms - мс + Session client name + Назва клієнта сеансу - Session scan limit - Обмеження сканування сеансів + Session host name + Назва вузла сеансу - Options - Параметри + Session metadata + Метадані сеансу - Reverse lookup discovered IP addresses to host names - Зворотним пошуком визначено IP-адреси для назв вузлів + Full name of user + Повне ім'я користувача - New location - Нове місце + User login name + Назва запису користувача + + + Computer UID role + Роль UID комп'ютера + + + Session meta data hash + Хеш-сума метаданих сеансу - - - NetworkDiscoveryDirectory - Scanning... - Сканування… + Always expand all locations + Завжди розгортати усі місця - Discovered computers - Виявлені комп'ютери + Image quality + Якість зображення - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command - Показати довідку щодо певної команди + Monitoring + Спостереження - Scan a subnet - Сканувати підмережу + Builtin monitoring mode + Вбудований режим стеження - -USAGE - -%1 scan [<SUBNET>] - - - -КОРИСТУВАННЯ - -%1 scan [<SUBNET>] - - + This mode allows you to monitor all computers at one or more locations. + У цьому режимі ви можете спостерігати за усіма комп'ютерами у одному або декількох місцях. + + + Query application version of the server + Опитати сервер щодо версії програми + + + Query active features + Опитати щодо активних можливостей + + + Query properties of remotely available screens + Опитати віддалені доступні екрани щодо властивостей + + + + NestedNetworkObjectDirectory + + All directories + Усі каталоги + + + NetworkObjectDirectoryConfigurationPage - Network object directory which automatically discovers computers in the network - Каталог об'єктів мережі, який автоматично виявляє комп'ютери у мережі + Update interval: + Інтервал оновлення: - Network discovery (scan network for Veyon clients) - Виявлення мережі (пошук у мережі клієнтів Veyon) + seconds + секунд + + + NetworkObjectDirectoryConfigurationPageTab - Commands for managing the network discovery directory - Команди для керування каталогом виявлення мережі + Enabled + Увімкнено @@ -3315,32 +3736,44 @@ USAGE Name: Назва: + + Website name + Назва сайта + - PasswordDialog + PluginCommands - Username - Ім’я користувача + List names of all installed plugins + Вивести список назв усіх встановлених додатків - Password - Пароль + Show table with details of all installed plugins + Показати таблицю із подробицями щодо усіх встановлених додатків - Veyon Logon - Вхід до Veyon + Name + Назва - Authentication error - Помилка розпізнавання + Description + Опис - Logon failed with given username and password. Please try again! - Не вдалося увійти на основі вказаних імені користувача і пароля. Будь ласка, повторіть спробу! + Version + Версія - Please enter your username and password in order to access computers. - Будь ласка, вкажіть ваше ім’я користувача та пароль, щоб отримати доступ до комп’ютерів. + UID + UID + + + Plugin-related CLI operations + Пов'язані із додатком дії командного рядка + + + Commands for managing plugins + Команди для керування додатками @@ -3385,10 +3818,6 @@ USAGE Do you really want to reboot the selected computers? Ви справді хочете перезавантажити позначені комп'ютери? - - Do you really want to power down the selected computer? - Ви справді хочете вимкнути позначений комп'ютер? - Power on a computer via Wake-on-LAN (WOL) Увімкнути комп'ютер за допомогою Wake-on-LAN (WOL) @@ -3441,6 +3870,18 @@ Please save your work and close all programs. Будь ласка, збережіть результати вашої роботи і завершіть роботу усіх програм. + + Do you really want to reboot <b>ALL</b> computers? + Ви справді хочете перезавантажити <b>УСІ</b> комп'ютери? + + + Do you really want to power down <b>ALL</b> computers? + Ви справді хочете вимкнути <b>УСІ</b> комп'ютери? + + + Do you really want to power down the selected computers? + Ви справді хочете вимкнути позначені комп'ютери? + PowerDownTimeInputDialog @@ -3487,14 +3928,25 @@ Please save your work and close all programs. Remote view or control a computer Віддалений перегляд або керування комп’ютером - - Please enter the hostname or IP address of the computer to access: - Будь ласка, вкажіть назву вузла або IP-адресу комп’ютера, доступ до якого слід отримати: - Show help about command Показати довідку щодо команди + + Exchange clipboard contents + Обмін вмістом буфера обміну даними + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + Не вибрано жодного комп'ютера. Ви можете ввести назву вузла або IP-адресу комп'ютера для доступу вручну: + + + + RemoteAccessPage + + Remote access: %1 + Віддалений доступ: %1 + RemoteAccessWidget @@ -3502,6 +3954,10 @@ Please save your work and close all programs. %1 - %2 Remote Access %1 — %2, віддалений доступ + + %1 - %2 - %3 Remote Access + %1 — %2 — %3, віддалений доступ + RemoteAccessWidgetToolBar @@ -3557,74 +4013,29 @@ Please save your work and close all programs. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - З’єднання з %1 - Connected. - З’єднано. - - - Screenshot - Знімок вікна - - - Exit - Вийти - - - - Routing - - Control internet access by modifying routing table - Керування доступом до інтернету шляхом внесення змін до таблиці маршрутизації - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - Вилучити типові маршрути для блокування доступу до інтернету - - - Add custom route to block internet - Додати нетиповий маршрут для блокування інтернету - - - Destination - Призначення - - - Gateway - Шлюз - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - Будь ласка, вкажіть програми або команди, які слід виконати на позначених комп’ютерах. Ви можете вказати декілька програм або команд, записавши їх в окремих рядках. + З’єднано. - Run programs - Виконати програми + Screenshot + Знімок вікна - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - наприклад, «C:\Program Files\VideoLAN\VLC\vlc.exe» + Exit + Вийти - Name: - Назва: + Connecting... + Встановлюємо з'єднання… - Remember and add to program menu - Запам'ятати і додати до меню програм + Select screen + Виберіть екран - e.g. VLC - наприклад VLC + All screens + Усі екрани @@ -3645,6 +4056,18 @@ Please save your work and close all programs. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. Щоб заволодіти увагою учнів, ви можете заблокувати їхні комп’ютери за допомогою цієї кнопки. У цьому режимі всі пристрої введення даних буде заблоковано, а екрани стануть чорними. + + Lock input devices + Блокування пристроїв введення + + + Unlock input devices + Розблокувати пристрої введення + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + Щоб заволодіти увагою учнів, ви можете заблокувати їхні комп'ютери за допомогою цієї кнопки. У цьому режимі всі пристрої введення даних буде заблоковано, а зображення на екрані лишиться видимим. + Screenshot @@ -3660,6 +4083,10 @@ Please save your work and close all programs. Screenshot Знімок вікна + + Could not open screenshot file %1 for writing. + Не вдалося відкрити файл знімка вікна %1 для запису даних. + ScreenshotFeaturePlugin @@ -3684,6 +4111,13 @@ Please save your work and close all programs. Створення знімків екранів комп’ютерів і їхнє локальне зберігання. + + ScreenshotManagementPage + + Screenshots + Знімки вікон + + ScreenshotManagementPanel @@ -3714,6 +4148,45 @@ Please save your work and close all programs. Delete Вилучити + + Screenshot + Знімок вікна + + + Do you really want to delete all selected screenshots? + Справді хочете вилучити усі позначені знімки вікон? + + + + ServerAccessControlManager + + Requested authentication method not available + Запитаний спосіб розпізнавання недоступний + + + Access allowed by rule "%1" + Доступ дозволено за правилом «%1» + + + Access denied by rule "%1" + Доступ заборонено за правилом «%1» + + + No rule allowed access + Жодне правило не надає доступу + + + Accessing user not member of an authorized user group + Доступ для користувача, який не є учасником уповноваженої групи користувачів + + + User has denied access + Доступ користувачеві заборонено + + + User confirmed access + Доступ підтверджено користувачем + ServiceConfigurationPage @@ -3745,14 +4218,6 @@ Please save your work and close all programs. State: Стан: - - Network - Мережа - - - Demo server port - Порт демосервера - Enable firewall exception Увімкнути виключення брандмауера @@ -3761,10 +4226,6 @@ Please save your work and close all programs. Allow connections from localhost only Дозволити з’єднання лише з локального вузла - - Internal VNC server port - Порт внутрішнього сервера VNC - VNC server Сервер VNC @@ -3785,14 +4246,6 @@ Please save your work and close all programs. Running Запущено - - Feature manager port - Порт керування можливостями - - - Primary service port - Порт основної служби - Enabling this option will make the service launch a server process for every interactive session on a computer. Typically this is required to support terminal servers. @@ -3803,52 +4256,132 @@ Typically this is required to support terminal servers. Show notification on remote connection Показувати сповіщення щодо віддаленого з'єднання - - Multi session mode (for terminal and remote desktop servers) - Режим із багатьма сеансами (для сервера-термінала та сервера віддаленої стільниці) - Show notification when an unauthorized access is blocked Показувати сповіщення, коли програма блокує неуповноважений доступ - - - ServiceControl - Starting service %1 - Запускаємо службу %1 + Maximum session count + Максимальна кількість сеансів - Stopping service %1 - Зупиняємо службу %1 + Network port numbers + Номери портів мережі - Registering service %1 - Реєструємо службу %1 + Veyon server + Сервер Veyon - Unregistering service %1 - Скасовуємо реєстрацію служби %1 + Internal VNC server + Вбудований сервер VNC - Service control - Керування службами + Feature manager + Керування можливостями + + + Demo server + Демосервер + + + Miscellaneous network settings + Різноманітні параметри мережі + + + Session mode + Режим сеансу + + + Local session mode (single server instance for primary local session) + Режим локального сеансу (один екземпляр сервера для основного локального сеансу) + + + Active session mode (single server instance for active local or remote session) + Режим активного сеансу (один екземпляр сервера для активного локального або віддаленого сеансу) + + + Multi session mode (distinct server instance for each local and remote desktop session) + Режим багатьох сеансів (окремий екземпляр сервера для кожного локального і віддаленого стільничного сеансу) + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + Увімкніть, якщо єдиний екземпляр Veyon Server має бути запущено для поточного активного сеансу, локального чи віддаленого. + + + Miscellaneous settings + Інші параметри + + + Disable clipboard synchronization + Вимкнути синхронізацію буфера обміну + + + Session metadata + Метадані сеансу + + + Content + Дані + + + None + Немає + + + Value of an environment variable + Значення змінної середовища + + + Value of a registry key + Значення ключа реєстру + + + Environment variable name: + Назва змінної середовища: + + + Registry key name: + Назва ключа реєстра: + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + Якщо хочете, введіть формальний вираз із використанням захоплення даних для видобування частини назви комп'ютера і використання її як показану назву комп'ютера. + +Приклад: [^-]*-(PC[0-9]*) - ServiceControlPlugin + ServiceControl - Service is running - Службу запущено + Service control + Керування службами - Service is not running - Службу не запущено + Starting %1 + Запускаємо %1 - Configure and control Veyon service - Налаштовування і керування службою Veyon + Stopping %1 + Зупиняємо %1 + + + Restarting %1 + Перезапускаємо %1 + + + Registering %1 + Реєструємо %1 + + + Unregistering %1 + Скасовуємо реєстрацію %1 + + + ServiceControlCommands Register Veyon Service Зареєструвати службу Veyon @@ -3873,13 +4406,25 @@ Typically this is required to support terminal servers. Query status of Veyon Service Визначити стан служби Veyon + + Service is running + Службу запущено + + + Service is not running + Службу не запущено + + + Configure and control Veyon service + Налаштовування і керування службою Veyon + Commands for configuring and controlling Veyon Service Команди для налаштовування і керування службою Veyon - ShellCommandLinePlugin + ShellCommands Run command file Виконати файл команди @@ -3889,14 +4434,101 @@ Typically this is required to support terminal servers. Файла «%1» не існує! - Interactive shell and script execution for Veyon Control - Інтерактивна оболонка і засіб виконання скриптів для Керування Veyon + Interactive shell and script execution for Veyon CLI + Інтерактивна оболонка і засіб виконання скриптів для командного рядка Veyon Commands for shell functionalities Команди для можливостей оболонки + + SlideshowPanel + + Previous + Назад + + + Start/pause + Старт/Пауза + + + Next + Далі + + + Duration: + Тривалість: + + + View in separate window + Переглянути в окремому вікні + + + %1 Master – Slideshow + Основне керування %1 – Показ слайдів + + + + SpotlightPanel + + Add selected computers + Додати позначені комп'ютери + + + Remove selected computers + Вилучити позначені комп'ютери + + + Update computers in realtime + Оновлювати комп'ютери у реальному часу + + + Spotlight + Акцент + + + Please select at least one computer to add. + Будь ласка, позначте принаймні один комп'ютер для додавання. + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + Додайте комп'ютери клацанням середньої кнопки миші або натисканням першої кнопки нижче. +Другу кнопку призначено для вилучення позначеного або останнього запису комп'ютера. + + + + StartAppDialog + + Start application + Запустити програму + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + Будь ласка, вкажіть програми, які слід запустити на позначених комп'ютерах. Ви можете вказати декілька програм, відокремивши записи символом розриву рядка. + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + наприклад, «C:\Program Files\VideoLAN\VLC\vlc.exe» + + + Remember and add to application menu + Запам'ятати і додати до меню програм + + + Application name + Назва програми + + + Name: + Назва: + + + e.g. VLC + наприклад VLC + + SystemTrayIcon @@ -3933,8 +4565,8 @@ Typically this is required to support terminal servers. Надіслати текстове повідомлення - Use the field below to type your message which will be sent to all selected users. - Використовуйте це поле, щоб набрати текст повідомлення, яке буде надіслано всім позначеним користувачам. + Please enter your message which send to all selected users. + Будь ласка, вкажіть ваше повідомлення, яке слід надіслати усім позначеним користувачам. @@ -3982,23 +4614,39 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer Увімкнути рушій дублювання стільниці у Windows 8 та новіших версіях + + Maximum CPU usage + Максимальне використання процесора + - UserConfig + UserLoginDialog - No write access - Немає доступу на запис + User login + Ім'я користувача - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - Не вдалося зберегти ваші особисті параметри! Будь ласка, перевірте, чи правильно вказано шлях до файла налаштувань користувачів за допомогою засобу налаштовування %1. + Please enter a username and password for automatic login on all computers. + Будь ласка, вкажіть ім'я користувача і пароль для автоматичного входу до усіх комп'ютерів. + + + Username + Ім’я користувача + + + Password + Пароль - UserSessionControl + UserSessionControlPlugin - User session control - Керування сеансами користувачів + Log in + Увійти + + + Click this button to log in a specific user on all computers. + Натисніть цю кнопку, щоб увійти від імені вказаного користувача на усі комп'ютери. Log off @@ -4016,6 +4664,14 @@ Typically this is required to support terminal servers. Do you really want to log off the selected users? Ви справді хочете виконати вихід із системи для позначених користувачів? + + User session control + Керування сеансами користувачів + + + Do you really want to log off <b>ALL</b> users? + Ви справді хочете виконати вихід з системи для <b>УСІХ</b> користувачів? + VeyonCore @@ -4067,10 +4723,6 @@ Typically this is required to support terminal servers. ERROR ПОМИЛКА - - licensed for - ліцензовано для - USAGE КОРИСТУВАННЯ @@ -4087,19 +4739,31 @@ Typically this is required to support terminal servers. WARNING ПОПЕРЕДЖЕННЯ + + Authentication test + Перевірка розпізнавання + + + Screen %1 + Екран %1 + - VeyonServiceControl + VeyonMaster - Veyon Service - Служба Veyon + No write access + Немає доступу на запис + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Не вдалося зберегти ваші особисті параметри! Будь ласка, перевірте, чи правильно вказано шлях до файла налаштувань користувачів за допомогою засобу налаштовування %1. - VncView + VeyonServiceControl - Establishing connection to %1 ... - Встановлення зв’язку з %1 ... + Veyon Service + Служба Veyon @@ -4147,6 +4811,30 @@ Typically this is required to support terminal servers. Use alternative user authentication mechanism Альтернативний механізм розпізнавання користувачів + + User login + Ім'я користувача + + + Input start delay + Затримка початку введення + + + Simulated key presses interval + Імітований інтервал між натисканнями клавіш + + + Confirm legal notice (message displayed before user logs in) + Підтвердити прочитання правового зауваження (повідомлення, яке показано до входу до системи) + + + Use input device interception driver + Скористатися драйвером-перехоплювачем пристроїв введення + + + Use custom power scheme with disabled power button + Використати нетипову схему живлення із вимкненою кнопкою живлення + WindowsPlatformPlugin @@ -4155,8 +4843,8 @@ Typically this is required to support terminal servers. Додаток, який реалізуває абстрактні функції на платформі Windows - Plugin implementing specific functions for the Windows platform - + Internal display + Внутрішній дисплей @@ -4165,30 +4853,34 @@ Typically this is required to support terminal servers. The service "%1" is already installed. Службу «%1» вже встановлено. - - The service "%1" could not be installed. - Не вдалося встановити службу «%1». - The service "%1" has been installed successfully. Службу «%1» було успішно встановлено. - - The service "%1" could not be uninstalled. - Не вдалося вилучити службу «%1». - The service "%1" has been uninstalled successfully. Службу «%1» успішно вилучено. - - The start type of service "%1" could not be changed. - Не вдалося змінити тип запуску служби «%1». - Service "%1" could not be found. Не вдалося знайти службу «%1». + + The service "%1" could not be installed (error %2). + Не вдалося встановити службу «%1» (помилка %2). + + + Could not change the failure actions config for service "%1" (error %2). + Не вдалося змінити налаштування дій у відповідь на помилки для служби «%1» (помилка %2). + + + The service "%1" could not be uninstalled (error %2). + Не вдалося вилучити службу «%1» (помилка %2). + + + The start type of service "%1" could not be changed (error %2). + TНе вдалося змінити тип запуску служби «%1» (помилка %2). + X11VncConfigurationWidget diff --git a/translations/vi.ts b/translations/veyon_vi.ts similarity index 78% rename from translations/vi.ts rename to translations/veyon_vi.ts index 352e43dce..0e617b7eb 100644 --- a/translations/vi.ts +++ b/translations/veyon_vi.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -80,10 +80,6 @@ Nếu bạn quan tâm đến việc dịch Veyon thành ngôn ngữ bản địa All groups Tất cả các nhóm - - ... - ... - Access control rules Quy tắc điều khiển truy cập @@ -141,15 +137,14 @@ Nếu bạn quan tâm đến việc dịch Veyon thành ngôn ngữ bản địa Backend nhóm người dùng: - Missing user groups backend - Thiếu backend nhóm người dùng - - - No default user groups plugin was found. Please check your installation! - Không tìm thấy plugin nhóm người dùng mặc định. Vui lòng kiểm tra bản cài đặt của bạn! + Restrict access to members of specific user groups + + + + AccessControlProvider - Restrict access to members of specific user groups + Provider for access control features @@ -179,30 +174,10 @@ Nếu bạn quan tâm đến việc dịch Veyon thành ngôn ngữ bản địa Rule description: Mô tả quy tắc: - - Invert all conditions ("is/has" interpreted as "is/has not") - Đảo ngược tất cả các điều kiện (có được hiểu là không) - Conditions Điều kiện - - is member of group - là thành viên của nhóm - - - Accessing computer is localhost - Máy tính đang truy cập là localhost - - - Accessing user is logged on user - Người dùng đang truy cập là người dùng đã đăng nhập - - - Accessing user is already connected - Người dùng đang truy cập đã được kết nối - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. Nếu có nhiều hơn một điều kiện kích hoạt, mỗi điều kiện phải thỏa mãn để áp dụng quy tắc (AND logic). Nếu chỉ một trong số nhiều điều kiện phải thoải mãn (OR logic) vui lòng tạo nhiều quy tắc điều khiển truy cập. @@ -236,33 +211,125 @@ Nếu bạn quan tâm đến việc dịch Veyon thành ngôn ngữ bản địa Máy tính đang truy cập - Local (logged on) user - Người dùng cục bộ (đã đăng nhập) + Always process rule and ignore conditions + Luôn xử lý quy tắc và bỏ qua các điều kiện - Local computer - Máy tính cục bộ + Accessing computer and local computer + - Always process rule and ignore conditions - Luôn xử lý quy tắc và bỏ qua các điều kiện + User being accessed + - No user logged on - Không có người dùng đã đăng nhập + is logged in locally + + + + is logged in remotely + + + + No user is logged in locally + - Accessing user has one or more groups in common with local (logged on) user - Người dùng đang truy cập có một hoặc nhiều nhóm chung với người dùng cục bộ (đã đăng nhập) + One or multiple users are logged in locally + + + + No user is logged in remotely + - Accessing computer and local computer are at the same location + One or multiple users are logged in remotely is located at + + is not located at + + + + are located at the same location + + + + are not located the same location + + + + is member of group + là thành viên của nhóm + + + is not member of group + + + + is authenticated via + + + + is not authenticated via + + + + has one or more groups in common with user being accessed + + + + has no groups in common with user being accessed + + + + equals user being accessed + + + + is different from user being accessed + + + + is already connected + + + + is not connected + + + + is local computer + + + + is not local computer + + + + Computer being accessed + + + + Session being accessed is a user session + + + + Session being accessed is a login screen + + + + Local computer is already being accessed + + + + Local computer is not yet being accessed + + AccessControlRulesTestDialog @@ -306,42 +373,44 @@ Nếu bạn quan tâm đến việc dịch Veyon thành ngôn ngữ bản địa The access in the given scenario needs permission of the logged on user. Truy cập trong tình huống đã cho cần quyền của người dùng đã đăng nhập. - - ERROR: Unknown action - LỖI: Hành động không xác định - Test result Kết quả kiểm tra - - - AndroidPlatformConfigurationPage - Android + Authentication method - General - Chung + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + Giới thiệu - - - AuthKeysConfigurationPage - Authentication keys - Khóa xác thực + Please perform the following steps to set up key file authentication: + Vui lòng thực hiện các bước sau để thiết lập xác thực tập tin khóa: - Introduction - Giới thiệu + 1) Create a key pair on the master computer. + 1) Tạo một cặp khóa trên máy tính chủ. + + + 2) Set an access group whose members should be allowed to access other computers. + 2) Thiết lập một nhóm truy cập mà các thành viên sẽ được phép truy cập vào các máy tính khác. + + + 3) Export the public key and import it on all client computers with the same name. + 3) Xuất khóa công và nhập nó trên tất cả các máy tính khách với cùng tên. + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + Vui lòng tham khảo <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Hướng dẫn quản trị Veyon</a>để biết thêm thông tin. Key file directories @@ -355,14 +424,20 @@ Nếu bạn quan tâm đến việc dịch Veyon thành ngôn ngữ bản địa Private key file base directory Thư mục cơ sở tập tin khóa riêng - - ... - ... - Available authentication keys Khóa xác thực khả dụng + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + Một cặp khóa xác thực bao gồm hai khóa mật mã, một khóa riêng và một khóa công. +Một khóa riêng cho phép người dùng trên máy tính chủ truy cập vào các máy tính khách. +Điều quan trọng đó là chỉ những người dùng được cấp quyền mới có truy cập đọc vào tập tin khóa riêng. +Khóa công được sử dụng trên các máy tính khách để xác thực yêu cầu kết nối đến. + Create key pair Tặp cặp khóa @@ -403,10 +478,6 @@ Nếu bạn quan tâm đến việc dịch Veyon thành ngôn ngữ bản địa Please select a key to delete! Vui lòng chọn một khóa để xóa! - - Please enter the name of the user group or role for which to import the authentication key: - Vui lòng nhập tên của nhóm người dùng hoặc vai trò để nhập khóa xác thực: - Please select a key to export! Vui lòng chọn một khóa để xuất! @@ -420,34 +491,10 @@ Nếu bạn quan tâm đến việc dịch Veyon thành ngôn ngữ bản địa Vui lòng chọn một khóa để đặt nhóm truy cập! - Please perform the following steps to set up key file authentication: - Vui lòng thực hiện các bước sau để thiết lập xác thực tập tin khóa: - - - 1) Create a key pair on the master computer. - 1) Tạo một cặp khóa trên máy tính chủ. - - - 2) Set an access group whose members should be allowed to access other computers. - 2) Thiết lập một nhóm truy cập mà các thành viên sẽ được phép truy cập vào các máy tính khác. - - - 3) Export the public key and import it on all client computers with the same name. - 3) Xuất khóa công và nhập nó trên tất cả các máy tính khách với cùng tên. - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - Vui lòng tham khảo <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Hướng dẫn quản trị Veyon</a>để biết thêm thông tin. - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - Một cặp khóa xác thực bao gồm hai khóa mật mã, một khóa riêng và một khóa công. -Một khóa riêng cho phép người dùng trên máy tính chủ truy cập vào các máy tính khách. -Điều quan trọng đó là chỉ những người dùng được cấp quyền mới có truy cập đọc vào tập tin khóa riêng. -Khóa công được sử dụng trên các máy tính khách để xác thực yêu cầu kết nối đến. + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + @@ -647,10 +694,6 @@ Khóa công được sử dụng trên các máy tính khách để xác thực This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. Lệnh này liệt kê tất cả các khóa xác thực khả dụng trong thư mục khóa đã cấu hinh. Nếu tùy chọn "%1" được chỉ định, một bảng với chi tiết khóa sẽ được hiển thị để thay thế. Một số chi tiết có thể bị thiếu nếu một khóa không thể truy cập được ví dụ do thiếu quyền đọc. - - Please specify the command to display help for! - Vui lòng chỉ định lệnh để hiển thị trợ giúp! - TYPE KIỂU @@ -659,10 +702,6 @@ Khóa công được sử dụng trên các máy tính khách để xác thực PAIR ID ID CẶP - - Command line support for managing authentication keys - Hỗ trợ dòng lệnh để quản lý các khóa xác thực - Commands for managing authentication keys Lệnh để quản lý các khóa xác thực @@ -679,6 +718,30 @@ Khóa công được sử dụng trên các máy tính khách để xác thực This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + + + + Key file authentication + + + + Key file + + + + Please specify the key name (e.g. "teacher/public") as the first argument. + + + + Please specify the command to display help for. + + + + The specified command does not exist or no help is available for it. + + AuthKeysTableModel @@ -700,90 +763,233 @@ Khóa công được sử dụng trên các máy tính khách để xác thực - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers + General + Chung + + + Username to bind DN mapping: - Name - Tên + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + + AuthLdapDialog - Host address/IP + Veyon Logon - MAC address + Please enter your domain/LDAP username and password in order to access computers. - Add new computer + Username - Remove selected computer + Password - New computer + Authentication error - Builtin directory + Logon failed with given username and password. Please try again! + + + AuthLogonDialog - Locations & computers + Veyon Logon - Locations + Please enter your username and password in order to access computers. - Add new location + Username - Remove selected location + Password - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + Authentication error - New location + Logon failed with given username and password. Please try again! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Import objects from given file + Logon authentication - Export objects to given file + Logon + + + AuthSimpleDialog - Invalid type specified. Valid values are "%1" or "%2". + Veyon Logon - Type - Kiểu + Please enter the Veyon password: + - Name - Tên - + Authentication error + + + + Logon failed with given password. Please try again! + + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + + + + Simple password authentication + + + + Simple password + + + + + AuthenticationPage + + Authentication is set up properly on this computer. + + + + + AuthenticationPageTab + + Enabled + + + + Test + Kiểm tra + + + + BuiltinDirectoryConfiguration + + Builtin directory + + + + + BuiltinDirectoryConfigurationPage + + Computers + + + + Name + Tên + + + Host address/IP + + + + MAC address + + + + Add new computer + + + + Remove selected computer + + + + New computer + + + + Builtin directory + + + + Locations + + + + Add new location + + + + Remove selected location + + + + New location + + + + Directory name + + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + + + + + BuiltinDirectoryPlugin + + Show help for specific command + + + + Import objects from given file + + + + Export objects to given file + + + + Invalid type specified. Valid values are "%1" or "%2". + + + + Type + Kiểu + + + Name + Tên + Host address @@ -1000,6 +1206,14 @@ Khóa công được sử dụng trên các máy tính khách để xác thực MAC ADDRESS + + The specified command does not exist or no help is available for it. + + + + Location "%1" not found. + + BuiltinUltraVncServer @@ -1017,10 +1231,6 @@ Khóa công được sử dụng trên các máy tính khách để xác thực ComputerControlListModel - - Host/IP address: %1 - - Active features: %1 @@ -1037,10 +1247,6 @@ Khóa công được sử dụng trên các máy tính khách để xác thực Computer offline or switched off - - Service unreachable or not running - - Authentication failed or access denied @@ -1061,6 +1267,38 @@ Khóa công được sử dụng trên các máy tính khách để xác thực Location: %1 + + [no user] + + + + Veyon Server unreachable or not running + + + + Name: %1 + + + + Hostname: %1 + + + + unknown + + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + ComputerControlServer @@ -1092,6 +1330,17 @@ Khóa công được sử dụng trên các máy tính khách để xác thực User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. + + Active connections: + + + + + ComputerGroupSelector + + Group %1 + + ComputerManager @@ -1119,13 +1368,48 @@ Khóa công được sử dụng trên các máy tính khách để xác thực Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. + + Logged in since + + + + %1 days + + + + 1 day + + - ComputerSelectPanel + ComputerMonitoring + + Computers + + + + Search users and computers + + + + Select all + + + + Unselect all + + + + Add to group + + - Computer management + Remove from group + + + ComputerSelectPanel Computer search @@ -1154,79 +1438,83 @@ Khóa công được sử dụng trên các máy tính khách để xác thực Could not write the computer and users list to %1! Please check the file access permissions. + + Search computers + + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. + Clear system-wide Veyon configuration - Please specify a valid filename for the configuration export. + List all configuration keys and values - Please specify a valid key. + Import configuration from given file - Specified key does not exist in current configuration! + Export configuration to given file - Please specify a valid value. + Read and output configuration value for given key - Configure Veyon at command line + Write given value to given configuration key - Output file is not writable! + Unset (remove) given configuration key - Output directory is not writable! + Upgrade and save configuration of program and plugins - Configuration file is not readable! + Please specify an existing configuration file to import. - Clear system-wide Veyon configuration + Configuration file is not readable! - List all configuration keys and values + Please specify a valid filename for the configuration export. - Import configuration from given file + Output file is not writable! - Export configuration to given file + Output directory is not writable! - Read and output configuration value for given key + Please specify a valid key. - Write given value to given configuration key + Specified key does not exist in current configuration! - Unset (remove) given configuration key + Please specify a valid value. - Commands for managing the configuration of Veyon + Configure Veyon at command line - Upgrade and save configuration of program and plugins + Commands for managing the configuration of Veyon @@ -1252,6 +1540,10 @@ Khóa công được sử dụng trên các máy tính khách để xác thực Could not apply platform-specific configuration settings. + + Could not configure the firewall configuration for the %1 Service. + + DemoClient @@ -1282,10 +1574,6 @@ Khóa công được sử dụng trên các máy tính khách để xác thực Memory limit - - Use multithreading (experimental) - - MB @@ -1302,13 +1590,17 @@ Khóa công được sử dụng trên các máy tính khách để xác thực Slow down thumbnail updates while demo is running - - - DemoFeaturePlugin - Fullscreen demo + Bandwidth limit + + + + MB/s + + + DemoFeaturePlugin Stop demo @@ -1322,19 +1614,63 @@ Khóa công được sử dụng trên các máy tính khách để xác thực - Demo server + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. + Demo - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + Share your screen or allow a user to share his screen with other users. - - + + Full screen demo + + + + Share your own screen in fullscreen mode + + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share your own screen in a window + + + + Share selected user's screen in fullscreen mode + + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share selected user's screen in a window + + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + + + + Please select only one user screen to share. + + + + All screens + + + + DesktopAccessDialog Desktop access dialog @@ -1360,86 +1696,90 @@ Khóa công được sử dụng trên các máy tính khách để xác thực DesktopServicesConfigurationPage - Programs & websites + Name + Tên + + + Path - Predefined programs + Predefined websites - Name - Tên + Remove selected website + - Path + URL - Add new program + New website - Remove selected program + Applications & websites - Predefined websites + Predefined applications - Remove selected website + Add new application - URL + Remove selected application - New program + Add new website - New website + New application DesktopServicesFeaturePlugin - Run program + Open website - Open website + Click this button to open a website on all computers. - Click this button to open a website on all computers. + Open website "%1" - Start programs and services in user desktop + Custom website - Click this button to run a program on all computers. + Start application - Run program "%1" + Click this button to start an application on all computers. - Custom program + Start application "%1" - Open website "%1" + Custom application - Custom website + Start apps and open websites in user sessions @@ -1474,15 +1814,19 @@ Khóa công được sử dụng trên các máy tính khách để xác thực - Custom program + Handout - Handout + Texts to read - Texts to read + generic-student-user + + + + Custom application @@ -1509,525 +1853,538 @@ Khóa công được sử dụng trên các máy tính khách để xác thực - FeatureControl + FeatureCommands - Feature control + List names of all available features - - - FileTransferController - Could not open file "%1" for reading! Please check your permissions! + Show table with details of all available features - - - FileTransferDialog - File transfer + Start a feature on a remote host - Options + Stop a feature on a remote host - Transfer only + Please specify the command to display help for. - Transfer and open file(s) with associated program + Displays a list with the names of all available features. - Transfer and open destination folder + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. - Files + HOST ADDRESS - Start + FEATURE - Overwrite existing files + ARGUMENTS - - - FileTransferPlugin - File transfer + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information - Click this button to transfer files from your computer to all computers. + Lock the screen - Select one or more files to transfer + Display a text message - Transfer files to remote computer + Test message - Received file "%1". + Start an application - Could not receive file "%1" as it already exists. + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. - Could not receive file "%1" as it could not be opened for writing! + Unlock the screen - - - GeneralConfigurationPage - User interface + The specified command does not exist or no help is available for it. - Language: - + Name + Tên - Use system language setting + Description - Veyon + Master - Logging + Service - Log file directory + Worker - ... - ... + UID + - Log level + Plugin - Nothing + Invalid feature name or UID specified - Only critical messages + Error parsing the JSON-encoded arguments: %1 - Errors and critical messages + Failed to initialize credentials - Warnings and errors + Could not establish a connection to host %1 - Information, warnings and errors + Failed to send feature control message to host %1 - Debug messages and everything else + Feature-related CLI operations - Limit log file size + Commands for controlling features + + + FileTransferConfigurationPage - Clear all log files + File transfer - Log to standard error output + Directories - Network object directory + Destination directory - Backend: + Default source directory - Update interval: + Options - %1 service + Remember last source directory - The %1 service needs to be stopped temporarily in order to remove the log files. Continue? + Create destination directory if it does not exist + + + FileTransferController - Log files cleared + Could not open file "%1" for reading! Please check your permissions! + + + FileTransferDialog - All log files were cleared successfully. + File transfer - Error + Options - Could not remove all log files. + Transfer only - MB + Transfer and open file(s) with associated program - Rotate log files + Transfer and open destination folder - x + Files - seconds + Start - Write to logging system of operating system + Overwrite existing files + + + FileTransferFileDialog - Authentication + Select one or more files to transfer + + + FileTransferPlugin - Method: + File transfer - Logon authentication + Click this button to transfer files from your computer to all computers. - Key file authentication + Select one or more files to transfer - Test - Kiểm tra + Transfer files to remote computer + - Authentication is set up properly on this computer. + Received file "%1". - Authentication keys are not set up properly on this computer. + Could not receive file "%1" as it already exists. - Authentication test + Could not receive file "%1" as it could not be opened for writing! - InternetAccessControlConfigurationPage + GeneralConfigurationPage - Internet access control + User interface - Backend: + Language: - General settings + Use system language setting - Backend settings + Veyon - - - InternetAccessControlPlugin - Block access to the internet + Logging - Allow access to the internet + Log file directory - Show help about command + Log level - Block internet + Nothing - Click this button to block access to the internet. + Only critical messages - Unblock internet + Errors and critical messages - Click this button to allow access to the internet. + Warnings and errors - Control access to the internet + Information, warnings and errors - Commands for controlling access to the internet + Debug messages and everything else - - - LdapBrowseDialog - Browse LDAP + Limit log file size - - - LdapClient - LDAP error description: %1 + Clear all log files - - - LdapConfigurationPage - Basic settings + Log to standard error output - General - Chung + %1 service + - LDAP server and port + The %1 service needs to be stopped temporarily in order to remove the log files. Continue? - Bind DN + Log files cleared - Bind password + All log files were cleared successfully. - Anonymous bind + Error - Use bind credentials + Could not remove all log files. - Base DN + MB - Fixed base DN + Rotate log files - e.g. dc=example,dc=org + x - Discover base DN by naming context + Write to logging system of operating system - e.g. namingContexts or defaultNamingContext + TLS configuration - Environment settings + Use certificate authority for TLS connections - Object trees + CA certificate file - Computer tree - + ... + ... - e.g. OU=Groups + Host certificate file - User tree + Host private key file - e.g. OU=Users + Style: - e.g. OU=Computers + Native - Group tree + Color scheme: - Perform recursive search operations in object trees + Light - Object attributes + Dark - e.g. hwAddress + User groups - e.g. member or memberUid + Backend: - e.g. dNSHostName + Include user groups from domain - Computer MAC address attribute - + Missing user groups backend + Thiếu backend nhóm người dùng - Group member attribute + No user groups plugin was found. Please check your installation! + + + HeadlessVncServer - e.g. uid or sAMAccountName + Headless VNC server - - Advanced settings + + + LdapBrowseDialog + + Browse LDAP + + + LdapClient - Optional object filters + LDAP error description: %1 + + + LdapConfiguration - Filter for user groups + LDAP connection failed - Filter for users + Could not connect to the LDAP server. Please check the server parameters. + +%1 - Filter for computer groups + LDAP bind failed - Group member identification + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 - Distinguished name (Samba/AD) + LDAP bind successful - List all groups of a user + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - List all groups of a computer + LDAP base DN test failed - Get computer object by IP address + Could not query the configured base DN. Please check the base DN parameter. + +%1 - LDAP connection failed + LDAP base DN test successful - LDAP bind failed + The LDAP base DN has been queried successfully. The following entries were found: + +%1 - LDAP bind successful + LDAP naming context test failed - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 - LDAP base DN test failed + LDAP naming context test successful - LDAP base DN test successful + The LDAP naming context has been queried successfully. The following base DN was found: +%1 - LDAP naming context test failed + user tree - LDAP naming context test successful + User tree - The LDAP naming context has been queried successfully. The following base DN was found: -%1 + group tree - user tree + Group tree - group tree + computer tree - computer tree + Computer tree - Enter username - Nhập tên người dùng + computer group tree + - Please enter a user login name (wildcards allowed) which to query: + Computer group tree @@ -2035,15 +2392,15 @@ Khóa công được sử dụng trên các máy tính khách để xác thực - Enter group name + User login name attribute - Please enter a group name whose members to query: + group members - group members + Group member attribute @@ -2055,25 +2412,49 @@ Khóa công được sử dụng trên các máy tính khách để xác thực - Enter computer name + computer objects - computer objects + Computer display name attribute - Enter computer DN + Invalid hostname - Please enter the DN of a computer whose MAC address to query: + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + + + + Computer hostname attribute computer MAC addresses + + Computer MAC address attribute + + + + computer locations + + + + Computer location attribute + + + + Location name attribute + + users @@ -2082,12 +2463,16 @@ Khóa công được sử dụng trên các máy tính khách để xác thực user groups + + computers + + computer groups - Please enter a user login name whose group memberships to query: + computer containers @@ -2098,6 +2483,10 @@ Khóa công được sử dụng trên các máy tính khách để xác thực User not found + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + + groups of computer @@ -2107,21 +2496,51 @@ Khóa công được sử dụng trên các máy tính khách để xác thực - Enter computer IP address + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - Please enter a computer IP address which to resolve to an computer object: + Hostname lookup failed - computers + Could not lookup hostname for IP address %1. Please check your DNS server settings. + + + + location entries + + + + Computer groups filter + + + + Computer locations identification + + + + Filter for computer groups + + + + Invalid test value + + + + An empty or invalid value has been supplied for this test. LDAP %1 test failed + + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + + LDAP %1 test successful @@ -2130,6 +2549,24 @@ Khóa công được sử dụng trên các máy tính khách để xác thực The %1 has been queried successfully and %2 entries were found. + + LDAP test failed + + + + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + + + + and + + + + LDAP test successful + + %1 %2 have been queried successfully: @@ -2155,15 +2592,210 @@ Khóa công được sử dụng trên các máy tính khách để xác thực - (only if different from group tree) + LDAP directory + + + LdapConfigurationPage - Computer group tree + Basic settings - computer group tree + General + Chung + + + LDAP server and port + + + + Bind DN + + + + Bind password + + + + Anonymous bind + + + + Use bind credentials + + + + Base DN + + + + Fixed base DN + + + + e.g. dc=example,dc=org + + + + Discover base DN by naming context + + + + e.g. namingContexts or defaultNamingContext + + + + Environment settings + + + + Object trees + + + + Computer tree + + + + e.g. OU=Groups + + + + User tree + + + + e.g. OU=Users + + + + e.g. OU=Computers + + + + Group tree + + + + Perform recursive search operations in object trees + + + + Object attributes + + + + e.g. hwAddress + + + + e.g. member or memberUid + + + + e.g. dNSHostName + + + + Computer MAC address attribute + + + + Group member attribute + + + + e.g. uid or sAMAccountName + + + + Advanced settings + + + + Optional object filters + + + + Filter for user groups + + + + Filter for users + + + + Filter for computer groups + + + + Group member identification + + + + Distinguished name (Samba/AD) + + + + List all groups of a user + + + + List all groups of a computer + + + + Get computer object by IP address + + + + Enter username + Nhập tên người dùng + + + Please enter a user login name (wildcards allowed) which to query: + + + + Enter group name + + + + Please enter a group name whose members to query: + + + + Enter computer name + + + + Enter computer DN + + + + Please enter the DN of a computer whose MAC address to query: + + + + Please enter a user login name whose group memberships to query: + + + + Enter computer IP address + + + + Please enter a computer IP address which to resolve to an computer object: + + + + (only if different from group tree) + + + + Computer group tree @@ -2247,1617 +2879,1625 @@ Khóa công được sử dụng trên các máy tính khách để xác thực - Could not query the configured base DN. Please check the base DN parameter. - -%1 + Certificate files (*.pem) - The LDAP base DN has been queried successfully. The following entries were found: - -%1 + Encryption protocol - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 + Computer location attribute - Certificate files (*.pem) + Computer display name attribute - Could not connect to the LDAP server. Please check the server parameters. - -%1 + Location name attribute - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 + e.g. cn or displayName - Encryption protocol + Computer locations identification - Computer location attribute + Identify computer locations (e.g. rooms) via: - Computer display name attribute + Location attribute in computer objects - Location name attribute + List all entries of a location - e.g. cn or displayName + List all locations - Computer locations identification + Enter computer display name + + + + Please enter a computer display name to query: + + + + Enter computer location name + + + + Please enter the name of a computer location (wildcards allowed): + + + + Enter location name + + + + Please enter the name of a location whose entries to query: + + + + Browse + + + + Test + Kiểm tra + + + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + + + + Computer hostname attribute + + + + Please enter a computer hostname to query: + + + + Enter hostname + + + + Please enter a computer hostname whose group memberships to query: + + + + User login name attribute + + + + Configured attribute for user login name or computer hostname (OpenLDAP) - Identify computer locations (e.g. rooms) via: + Directory name - Location attribute in computer objects + Query options - List all entries of a location + Query nested user groups (supported by AD only) - List all locations + Query timeout - Enter computer display name + ms + + + LdapNetworkObjectDirectoryConfigurationPage - Please enter a computer display name to query: + LDAP - Enter computer location name + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + + + LdapPlugin - Please enter the name of a computer location (wildcards allowed): + Auto-configure the base DN via naming context - computer locations + Query objects from LDAP directory - Enter location name + Show help about command - Please enter the name of a location whose entries to query: + Commands for configuring and testing LDAP/AD integration - location entries + Basic LDAP/AD support for Veyon - LDAP test failed + %1 (load computers and locations from LDAP/AD) - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 + %1 (load users and groups from LDAP/AD) - and + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - LDAP test successful + No naming context attribute name given - falling back to configured value. - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 + Could not query base DN. Please check your LDAP configuration. - Browse + Configuring %1 as base DN and disabling naming context queries. - Test - Kiểm tra + Test binding to an LDAP server + - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. - Computer hostname attribute + LDAP bind + + + LinuxPlatformConfigurationPage - Please enter a computer hostname to query: + Linux - Invalid hostname + Custom PAM service for user authentication - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + User authentication - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + User sessions - Could not find a user with the name "%1". Please check the username or the user tree parameter. + Minimum session lifetime before server start - Enter hostname + User login - Please enter a computer hostname whose group memberships to query: + Login key sequence + + + LinuxPlatformPlugin - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + Plugin implementing abstract functions for the Linux platform + + + LocationDialog - Hostname lookup failed + Select location - Could not lookup hostname for IP address %1. Please check your DNS server settings. + enter search filter... + + + MainToolBar - User login name attribute + Configuration - Configured attribute for user login name or computer hostname (OpenLDAP) + Show icons only - computer containers + Disable tooltips - LdapPlugin + MainWindow - Auto-configure the base DN via naming context + MainWindow - Query objects from LDAP directory + toolBar - Show help about command - + General + Chung - Commands for configuring and testing LDAP/AD integration + &File - Basic LDAP/AD support for Veyon + &Help - %1 (load computers and locations from LDAP/AD) + &Quit - %1 (load users and groups from LDAP/AD) + Ctrl+Q - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + Ctrl+S - No naming context attribute name given - falling back to configured value. + L&oad settings from file - Could not query base DN. Please check your LDAP configuration. + Ctrl+O - Configuring %1 as base DN and disabling naming context queries. + About Qt - - - LdapProConfigurationPage - LDAP Pro + Configuration not writable - Instances + Load settings from file - Enter name + Save settings to file - Please enter a name for the instance (can't be changed later!): + Unsaved settings - Remove instance + There are unsaved settings. Quit anyway? - Do you really want to remove instance "%1"? + Veyon Configurator - Configuration for instance "%1" + Service - - - LdapProPlugin - Professional LDAP/AD integration for Veyon + Master - %1 (load computers and locations from LDAP/AD) + Access control - %1 (load users and groups from LDAP/AD) - + About Veyon + Về Veyon - - - LicensingConfigurationPage - Licensing + Auto - Installed licenses - + About + Giới thiệu - Add new network range + %1 Configurator %2 - Remove selected network range + JSON files (*.json) - ID + The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - Feature - + Access denied + Truy cập bị từ chối - Valid until + According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. - Licensee + Screenshots - Browse license file + Feature active - Veyon license files (*.vlf) + The feature "%1" is still active. Please stop it before closing %2. - Remove license + Reset configuration - Do you really want to remove the selected license? + Do you really want to reset the local configuration and revert all settings to their defaults? - <N/A> - <Không> + Search users and computers + - Invalid license file + Align computers to grid - Could not open the license file for reading! + %1 Configurator - The selected license file does not contain valid data. + Insufficient privileges - The selected license file could not be verified. + Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. - The selected license file is not valid for this installation. + Only show powered on computers - The selected license file is expired. + &Save settings to file - The license is already installed. + &View - Information + &Standard - Installation ID + &Advanced - Addons available for licensing + Use custom computer arrangement - Addon + Locations && computers - - - LicensingPlugin - Show help for specific command + Authentication - Show all installed licenses + Adjust size of computer icons automatically - Add license file + Slideshow - Remove installed license + Spotlight - -USAGE - -%1 add <LICENSE FILE> - - + Veyon Master - -USAGE - -%1 remove <LICENSE ID> - - + Locations & computers - No certificate found with given ID + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. - <N/A> - <Không> + Only show computers with logged on users + - Licensing management + Load computer positions - Commands for managing license keys + Save computer positions - LinuxPlatformConfigurationPage + MasterConfigurationPage - Linux + Directories - Custom PAM service for user authentication + User configuration - User authentication + Feature on computer double click: - Session management + Features - Display manager users + All features - - - LinuxPlatformPlugin - Plugin implementing abstract functions for the Linux platform + Disabled features - Plugin implementing specific functions for the Linux platform + Screenshots - - - LocationDialog - Select location + <no feature> - enter search filter... + Basic settings - - - MainToolBar - Configuration + Behaviour - Disable balloon tooltips + Enforce selected mode for client computers - Show icons only + Hide local computer - - - MainWindow - MainWindow + Hide computer filter field - toolBar + Actions such as rebooting or powering down computers - General - Chung - - - &File + User interface - &Help + Background color - &Quit + Thumbnail update interval - Ctrl+Q + ms - Ctrl+S + Program start - L&oad settings from file + Modes and features - Ctrl+O + User and computer name - About Qt + Only user name - Authentication impossible + Only last part of user name - Configuration not writable + Only computer name - Load settings from file + Computer thumbnail caption - Save settings to file + Text color - Unsaved settings + Sort order - There are unsaved settings. Quit anyway? + Computer and user name - Veyon Configurator + Computer locations - Service + Show current location only - Master + Allow adding hidden locations manually - Access control + Hide empty locations - About Veyon - Về Veyon - - - Auto + Show confirmation dialog for potentially unsafe actions - About - Giới thiệu + Perform access control + - %1 Configurator %2 + Automatically select current location - JSON files (*.json) + Automatically open computer select panel - The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. + Use modern user interface (experimental) - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. + Thumbnail spacing - Access denied - Truy cập bị từ chối + px + - According to the local configuration you're not allowed to access computers in the network. Please log in with a different account or let your system administrator check the local configuration. + Hide local session - Screenshots + Auto - Feature active + Thumbnail aspect ratio - The feature "%1" is still active. Please stop it before closing %2. + Automatically adjust computer icon size - Reset configuration + Open feature windows on the same screen as the main window - Do you really want to reset the local configuration and revert all settings to their defaults? + Configuration templates - Search users and computers + Image quality in monitoring mode - Adjust optimal size + Highest - Align computers to grid + High - %1 Configurator + Medium - Insufficient privileges + Low - Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + Lowest - Only show powered on computers + Remote access image quality - &Save settings to file + Advanced - &View + Computer name source - &Standard + Default - &Advanced + Host address - Use custom computer arrangement + Session client address - Locations && computers + Session client name - - - MasterConfigurationPage - Directories + Session host name - ... - ... + Session metadata + - User configuration + Full name of user - Feature on computer double click: + User login name - Features + Computer UID role - All features + Session meta data hash - Disabled features + Always expand all locations - Screenshots + Image quality + + + MonitoringMode - <no feature> + Monitoring - Basic settings + Builtin monitoring mode - Behaviour + This mode allows you to monitor all computers at one or more locations. - Enforce selected mode for client computers + Query application version of the server - Hide local computer + Query active features - Hide computer filter field + Query properties of remotely available screens + + + NestedNetworkObjectDirectory - Actions such as rebooting or powering down computers + All directories + + + NetworkObjectDirectoryConfigurationPage - User interface + Update interval: - Background color + seconds + + + NetworkObjectDirectoryConfigurationPageTab - Thumbnail update interval + Enabled + + + NetworkObjectTreeModel - ms + Locations/Computers + + + OpenWebsiteDialog - Program start + Open website - Modes and features + e.g. Veyon - User and computer name + Remember and add to website menu - Only user name + e.g. www.veyon.io - Only computer name + Please enter the URL of the website to open: - Computer thumbnail caption + Name: - Text color + Website name + + + PluginCommands - Sort order + List names of all installed plugins - Computer and user name + Show table with details of all installed plugins - Computer locations - + Name + Tên - Show current location only + Description - Allow adding hidden locations manually + Version - Hide empty locations + UID - Show confirmation dialog for potentially unsafe actions + Plugin-related CLI operations - Perform access control + Commands for managing plugins + + + PowerControlFeaturePlugin - Automatically select current location + Power on - Automatically adjust computer thumbnail size + Click this button to power on all computers. This way you do not have to power on each computer by hand. - Automatically open computer select panel + Reboot - - - MonitoringMode - Monitoring + Click this button to reboot all computers. - Builtin monitoring mode + Power down - This mode allows you to monitor all computers at one or more locations. + Click this button to power down all computers. This way you do not have to power down each computer by hand. - - - NetworkDiscoveryConfigurationPage - Network discovery + Power on/down or reboot a computer - Mode + Confirm reboot - Scan network ranges + Confirm power down - e.g. 192.168.1.0/24 + Do you really want to reboot the selected computers? - Scan all subnets of computer + Power on a computer via Wake-on-LAN (WOL) - Scan custom subnet + MAC ADDRESS - Scan sessions on local computer + This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. - Test - Kiểm tra + Please specify the command to display help for! + Vui lòng chỉ định lệnh để hiển thị trợ giúp! - Network ranges + Invalid MAC address specified! - Add new group + Commands for controlling power status of computers - Remove selected group + Power down now - Groups + Install updates and power down - First address + Power down after user confirmation - Last address + Power down after timeout - Add new network range + The computer was remotely requested to power down. Do you want to power down the computer now? - Remove selected network range + The computer will be powered down in %1 minutes, %2 seconds. + +Please save your work and close all programs. - Parallel scans + Do you really want to reboot <b>ALL</b> computers? - Scan timeout + Do you really want to power down <b>ALL</b> computers? - ms + Do you really want to power down the selected computers? + + + PowerDownTimeInputDialog - Session scan limit + Power down - Options + Please specify a timeout for powering down the selected computers: - Reverse lookup discovered IP addresses to host names + minutes - New location + seconds - NetworkDiscoveryDirectory + RemoteAccessFeaturePlugin - Scanning... + Remote view - Discovered computers + Open a remote view for a computer without interaction. - - - NetworkDiscoveryPlugin - Show help for specific command + Remote control - Scan a subnet + Open a remote control window for a computer. - -USAGE - -%1 scan [<SUBNET>] - - + Remote access - Network object directory which automatically discovers computers in the network + Remote view or control a computer - Network discovery (scan network for Veyon clients) + Show help about command - Commands for managing the network discovery directory + Exchange clipboard contents - - - NetworkObjectTreeModel - Locations/Computers + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: - OpenWebsiteDialog + RemoteAccessPage - Open website + Remote access: %1 + + + RemoteAccessWidget - e.g. Veyon + %1 - %2 Remote Access - Remember and add to website menu + %1 - %2 - %3 Remote Access + + + RemoteAccessWidgetToolBar - e.g. www.veyon.io + View only - Please enter the URL of the website to open: + Remote control - Name: + Send shortcut - - - PasswordDialog - Username + Fullscreen - Password + Window - Veyon Logon + Ctrl+Alt+Del - Authentication error + Ctrl+Esc - Logon failed with given username and password. Please try again! + Alt+Tab - Please enter your username and password in order to access computers. + Alt+F4 - - - PowerControlFeaturePlugin - Power on + Win+Tab - Click this button to power on all computers. This way you do not have to power on each computer by hand. + Win - Reboot + Menu - Click this button to reboot all computers. + Alt+Ctrl+F1 - Power down + Connected. - Click this button to power down all computers. This way you do not have to power down each computer by hand. + Screenshot - Power on/down or reboot a computer + Exit - Confirm reboot + Connecting... - Confirm power down + Select screen - Do you really want to reboot the selected computers? + All screens + + + ScreenLockFeaturePlugin - Do you really want to power down the selected computer? + Lock - Power on a computer via Wake-on-LAN (WOL) + Unlock - MAC ADDRESS + Lock screen and input devices of a computer - This command broadcasts a Wake-on-LAN (WOL) packet to the network in order to power on the computer with the given MAC address. + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. - Please specify the command to display help for! - Vui lòng chỉ định lệnh để hiển thị trợ giúp! + Lock input devices + - Invalid MAC address specified! + Unlock input devices - Commands for controlling power status of computers + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + + Screenshot - Power down now + unknown - Install updates and power down + Could not take a screenshot as directory %1 doesn't exist and couldn't be created. - Power down after user confirmation + Screenshot - Power down after timeout + Could not open screenshot file %1 for writing. + + + ScreenshotFeaturePlugin - The computer was remotely requested to power down. Do you want to power down the computer now? + Screenshot - The computer will be powered down in %1 minutes, %2 seconds. - -Please save your work and close all programs. + Use this function to take a screenshot of selected computers. - - - PowerDownTimeInputDialog - Power down + Screenshots taken - Please specify a timeout for powering down the selected computers: + Screenshot of %1 computer have been taken successfully. - minutes + Take screenshots of computers and save them locally. + + + ScreenshotManagementPage - seconds + Screenshots - RemoteAccessFeaturePlugin + ScreenshotManagementPanel - Remote view + All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. - Open a remote view for a computer without interaction. + User: - Remote control + Computer: - Open a remote control window for a computer. + Date: - Remote access + Time: - Remote view or control a computer + Show - Please enter the hostname or IP address of the computer to access: + Delete - Show help about command + Screenshot - - - RemoteAccessWidget - %1 - %2 Remote Access + Do you really want to delete all selected screenshots? - RemoteAccessWidgetToolBar - - View only - - + ServerAccessControlManager - Remote control + Requested authentication method not available - Send shortcut + Access allowed by rule "%1" - Fullscreen + Access denied by rule "%1" - Window + No rule allowed access - Ctrl+Alt+Del + Accessing user not member of an authorized user group - Ctrl+Esc + User has denied access - Alt+Tab + User confirmed access + + + ServiceConfigurationPage - Alt+F4 - + General + Chung - Win+Tab + Autostart - Win + Hide tray icon - Menu + Start service - Alt+Ctrl+F1 + Stopped - Connecting %1 + Stop service - Connected. + State: - Screenshot + Enable firewall exception - Exit + Allow connections from localhost only - - - Routing - Control internet access by modifying routing table + VNC server - - - RoutingConfigurationWidget - Remove default routes to block internet access + Plugin: - Add custom route to block internet + Restart %1 Service - Destination + All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - Gateway + Running - - - RunProgramDialog - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. + Enabling this option will make the service launch a server process for every interactive session on a computer. +Typically this is required to support terminal servers. - Run programs + Show notification on remote connection - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + Show notification when an unauthorized access is blocked - Name: + Maximum session count - Remember and add to program menu + Network port numbers - e.g. VLC + Veyon server - - - ScreenLockFeaturePlugin - Lock + Internal VNC server - Unlock + Feature manager - Lock screen and input devices of a computer + Demo server - To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. + Miscellaneous network settings - - - Screenshot - unknown + Session mode - Could not take a screenshot as directory %1 doesn't exist and couldn't be created. + Local session mode (single server instance for primary local session) - Screenshot + Active session mode (single server instance for active local or remote session) - - - ScreenshotFeaturePlugin - Screenshot + Multi session mode (distinct server instance for each local and remote desktop session) - Use this function to take a screenshot of selected computers. + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. - Screenshots taken + Miscellaneous settings - Screenshot of %1 computer have been taken successfully. + Disable clipboard synchronization - Take screenshots of computers and save them locally. + Session metadata - - - ScreenshotManagementPanel - All screenshots taken by you are listed here. You can take screenshots by clicking the "Screenshot" item in the context menu of a computer. The screenshots can be managed using the buttons below. + Content - User: + None - Computer: + Value of an environment variable - Date: + Value of a registry key - Time: + Environment variable name: - Show + Registry key name: - Delete + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) - ServiceConfigurationPage - - General - Chung - - - Autostart - - - - Hide tray icon - - + ServiceControl - Start service + Service control - Stopped + Starting %1 - Stop service + Stopping %1 - State: + Restarting %1 - Network + Registering %1 - Demo server port + Unregistering %1 + + + ServiceControlCommands - Enable firewall exception + Register Veyon Service - Allow connections from localhost only + Unregister Veyon Service - Internal VNC server port + Start Veyon Service - VNC server + Stop Veyon Service - Plugin: + Restart Veyon Service - Restart %1 Service + Query status of Veyon Service - All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? + Service is running - Running + Service is not running - Feature manager port + Configure and control Veyon service - Primary service port + Commands for configuring and controlling Veyon Service + + + ShellCommands - Enabling this option will make the service launch a server process for every interactive session on a computer. -Typically this is required to support terminal servers. + Run command file - Show notification on remote connection + File "%1" does not exist! - Multi session mode (for terminal and remote desktop servers) + Interactive shell and script execution for Veyon CLI - Show notification when an unauthorized access is blocked + Commands for shell functionalities - ServiceControl + SlideshowPanel - Starting service %1 + Previous - Stopping service %1 + Start/pause - Registering service %1 + Next - Unregistering service %1 + Duration: - Service control + View in separate window - - - ServiceControlPlugin - Service is running + %1 Master – Slideshow + + + SpotlightPanel - Service is not running + Add selected computers - Configure and control Veyon service + Remove selected computers - Register Veyon Service + Update computers in realtime - Unregister Veyon Service + Spotlight - Start Veyon Service + Please select at least one computer to add. - Stop Veyon Service + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + StartAppDialog - Restart Veyon Service + Start application - Query status of Veyon Service + Please enter the applications to start on the selected computers. You can separate multiple applications by line. - Commands for configuring and controlling Veyon Service + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - - - ShellCommandLinePlugin - Run command file + Remember and add to application menu - File "%1" does not exist! + Application name - Interactive shell and script execution for Veyon Control + Name: - Commands for shell functionalities + e.g. VLC @@ -3897,7 +4537,7 @@ Typically this is required to support terminal servers. - Use the field below to type your message which will be sent to all selected users. + Please enter your message which send to all selected users. @@ -3946,22 +4586,38 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer + + Maximum CPU usage + + - UserConfig + UserLoginDialog - No write access + User login - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + Please enter a username and password for automatic login on all computers. + + + + Username + + + + Password - UserSessionControl + UserSessionControlPlugin - User session control + Log in + + + + Click this button to log in a specific user on all computers. @@ -3980,6 +4636,14 @@ Typically this is required to support terminal servers. Do you really want to log off the selected users? + + User session control + + + + Do you really want to log off <b>ALL</b> users? + + VeyonCore @@ -4031,10 +4695,6 @@ Typically this is required to support terminal servers. ERROR - - licensed for - - USAGE @@ -4051,18 +4711,30 @@ Typically this is required to support terminal servers. WARNING + + Authentication test + + + + Screen %1 + + - VeyonServiceControl + VeyonMaster - Veyon Service + No write access + + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - VncView + VeyonServiceControl - Establishing connection to %1 ... + Veyon Service @@ -4111,6 +4783,30 @@ Typically this is required to support terminal servers. Use alternative user authentication mechanism + + User login + + + + Input start delay + + + + Simulated key presses interval + + + + Confirm legal notice (message displayed before user logs in) + + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4119,7 +4815,7 @@ Typically this is required to support terminal servers. - Plugin implementing specific functions for the Windows platform + Internal display @@ -4130,27 +4826,31 @@ Typically this is required to support terminal servers. - The service "%1" could not be installed. + The service "%1" has been installed successfully. + + + + The service "%1" has been uninstalled successfully. - The service "%1" has been installed successfully. + Service "%1" could not be found. - The service "%1" could not be uninstalled. + The service "%1" could not be installed (error %2). - The service "%1" has been uninstalled successfully. + Could not change the failure actions config for service "%1" (error %2). - The start type of service "%1" could not be changed. + The service "%1" could not be uninstalled (error %2). - Service "%1" could not be found. + The start type of service "%1" could not be changed (error %2). diff --git a/translations/zh_CN.ts b/translations/veyon_zh_CN.ts similarity index 75% rename from translations/zh_CN.ts rename to translations/veyon_zh_CN.ts index 72886a6dd..341a1b88d 100644 --- a/translations/zh_CN.ts +++ b/translations/veyon_zh_CN.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -80,10 +80,6 @@ If you're interested in translating Veyon into your local or another langua All groups 所有群组 - - ... - ... - Access control rules 访问控制规则 @@ -140,19 +136,18 @@ If you're interested in translating Veyon into your local or another langua User groups backend: 用户组后端: - - Missing user groups backend - 缺少用户组后端 - - - No default user groups plugin was found. Please check your installation! - 没有找到默认的用户组插件,请检查您的安装程序! - Restrict access to members of specific user groups 限制特定用户组成员的访问权限 + + AccessControlProvider + + Provider for access control features + + + AccessControlRuleEditDialog @@ -179,30 +174,10 @@ If you're interested in translating Veyon into your local or another langua Rule description: 规则描述: - - Invert all conditions ("is/has" interpreted as "is/has not") - 反转所有条件(“是/有”变成“否/没有”) - Conditions 条件 - - is member of group - 是组成员 - - - Accessing computer is localhost - 正在访问局域网中的计算机 - - - Accessing user is logged on user - 访问的用户已登录 - - - Accessing user is already connected - 访问的用户已连接 - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. 如果激活多个条件,则必须满足每个条件才能适用规则(逻辑与)。 如果只需满足多个条件中的一个,(逻辑或),请创建多个访问控制规则。 @@ -236,33 +211,125 @@ If you're interested in translating Veyon into your local or another langua 访问计算机 - Local (logged on) user - 本地(登录)用户 + Always process rule and ignore conditions + 总是按规则运行并忽略条件 - Local computer - 本地计算机 + Accessing computer and local computer + 正在访问计算机和本地计算机 - Always process rule and ignore conditions - 总是按规则运行并忽略条件 + User being accessed + 使用者正在访问 - No user logged on - 没有用户登录 + is logged in locally + 本地登录 + + + is logged in remotely + 远程登录 + + + No user is logged in locally + 没有用户本地登录 + + + One or multiple users are logged in locally + 一个或多个用户本地登录 - Accessing user has one or more groups in common with local (logged on) user - 访问用户有一个或多个与本地(登录)用户相同的组 + No user is logged in remotely + 没有用户远程登录 - Accessing computer and local computer are at the same location - 访问计算机和本地计算机位于同一地点 + One or multiple users are logged in remotely + 一个或多个用户远程登录 is located at 位于 + + is not located at + 没有位于 + + + are located at the same location + 位于同一位置 + + + are not located the same location + 位于不同位置 + + + is member of group + 是组成员 + + + is not member of group + 不是组成员 + + + is authenticated via + 身份验证通过 + + + is not authenticated via + 未身份验证通过 + + + has one or more groups in common with user being accessed + 有一个或多个公共组的用户正在访问 + + + has no groups in common with user being accessed + 没有公共组的用户正在访问 + + + equals user being accessed + 等于用户正在访问 + + + is different from user being accessed + 不同于用户被访问 + + + is already connected + 已连接 + + + is not connected + 未连接 + + + is local computer + 是本地计算机 + + + is not local computer + 不是本地计算机 + + + Computer being accessed + 计算机正在被访问 + + + Session being accessed is a user session + 正在被访问的会话是用户会话 + + + Session being accessed is a login screen + 正在被访问的会话是登录界面 + + + Local computer is already being accessed + + + + Local computer is not yet being accessed + + AccessControlRulesTestDialog @@ -306,42 +373,44 @@ If you're interested in translating Veyon into your local or another langua The access in the given scenario needs permission of the logged on user. 指定场景中的访问需要登录用户的权限。 - - ERROR: Unknown action - 错误:未知的操作 - Test result 测试规则 - - - AndroidPlatformConfigurationPage - Android - + Authentication method + 验证模式 - General - 常规 + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + 介绍 - - - AuthKeysConfigurationPage - Authentication keys - 验证密钥 + Please perform the following steps to set up key file authentication: + 请按以下步骤设置密钥文件验证: - Introduction - 介绍 + 1) Create a key pair on the master computer. + 1)在主计算机上创建密钥对。 + + + 2) Set an access group whose members should be allowed to access other computers. + 2)设置一个访问组,其成员应该被允许访问其他计算机。 + + + 3) Export the public key and import it on all client computers with the same name. + 3)将公钥其导入到具有相同名称的所有客户端计算机上。 + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + 请访问链接 <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon 管理员手册</a> 以获得更多信息。 Key file directories @@ -355,14 +424,21 @@ If you're interested in translating Veyon into your local or another langua Private key file base directory 私钥文件主目录 - - ... - ... - Available authentication keys 可用的验证密钥 + + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + 密钥包括两部分,私钥和公钥。 +私钥允许主机上的用户访问客户机。 +重要:只有经过验证的用户才可以读取私钥文件。 +公钥存放于客户端电脑,用以验证前来访问的请求。 + + Create key pair 创建密钥对 @@ -403,10 +479,6 @@ If you're interested in translating Veyon into your local or another langua Please select a key to delete! 请选择要删除的密钥! - - Please enter the name of the user group or role for which to import the authentication key: - 请输入要为其导入身份验证密钥的用户组或角色的名称: - Please select a key to export! 请选择要导出的密钥! @@ -420,35 +492,10 @@ If you're interested in translating Veyon into your local or another langua 请选择一个用于访问组的的密钥! - Please perform the following steps to set up key file authentication: - 请按以下步骤设置密钥文件验证: - - - 1) Create a key pair on the master computer. - 1)在主计算机上创建密钥对。 - - - 2) Set an access group whose members should be allowed to access other computers. - 2)设置一个访问组,其成员应该被允许访问其他计算机。 - - - 3) Export the public key and import it on all client computers with the same name. - 3)将公钥其导入到具有相同名称的所有客户端计算机上。 - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - 请访问链接 <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon 管理员手册</a> 以获得更多信息。 - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - 密钥包括两部分,私钥和公钥。 -私钥允许主机上的用户访问客户机。 -重要:只有经过验证的用户才可以读取私钥文件。 -公钥存放于客户端电脑,用以验证前来访问的请求。 - + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + @@ -648,10 +695,6 @@ The public key is used on client computers to authenticate incoming connection r This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. 此命令列出配置的密钥目录中的所有可用身份验证密钥。 如果指定了选项 "%1" ,则会显示包含密钥详细信息的表格。 如果无法访问密钥,某些细节可能会丢失,例如,没有读取权限。 - - Please specify the command to display help for! - 请指定需要显示用法命令! - TYPE TYPE @@ -660,10 +703,6 @@ The public key is used on client computers to authenticate incoming connection r PAIR ID PAIR ID - - Command line support for managing authentication keys - 用于管理验证密钥的命令行支持 - Commands for managing authentication keys 管理身份验证密钥的命令 @@ -680,6 +719,30 @@ The public key is used on client computers to authenticate incoming connection r This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. 此命令从私钥<KEY>中抽取公钥部分并将其保存为相应的公钥。因此当设置另一台主计算机时,只传输私钥就可以了。公钥可以被抽取出来。 + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + 此计算机上的验证密钥文件没有被正确配置。请创建新的密钥文件或使用Veyon配置器切换不同的验证方法。 + + + Key file authentication + 密钥验证 + + + Key file + 密钥文件 + + + Please specify the key name (e.g. "teacher/public") as the first argument. + 请指定键名 (例如: "teacher/public") 作为第一个参数。 + + + Please specify the command to display help for. + 请指定显示说明的命令。 + + + The specified command does not exist or no help is available for it. + 指定的命令不存在或没有它的说明可以使用。 + AuthKeysTableModel @@ -701,84 +764,227 @@ The public key is used on client computers to authenticate incoming connection r - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - 计算机 + General + 常规 - Name - 名称 + Username to bind DN mapping: + 绑定 DN 对应的用户名: - Host address/IP - 主机 IP 地址 + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + + + + AuthLdapDialog - MAC address - MAC 地址 + Veyon Logon + Veyon 登录 - Add new computer - 添加新计算机 + Please enter your domain/LDAP username and password in order to access computers. + 请输入您的域/LDAP用户名和密码以访问计算机。 - Remove selected computer - 删除选中的计算机 + Username + 用户名 - New computer - 新计算机 + Password + 密码 - Builtin directory - 内置目录 + Authentication error + 验证错误 - Locations & computers - 地点及计算机 + Logon failed with given username and password. Please try again! + 使用给定的用户名和密码登录失败。 请再试一次! + + + AuthLogonDialog - Locations - 地点 + Veyon Logon + Veyon 登录 - Add new location - 添加新地点 + Please enter your username and password in order to access computers. + 请输入您的用户名和密码才能访问计算机。 - Remove selected location - 移除选中的地点 + Username + 用户名 + + + Password + 密码 - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - 通过命令行界面可导入CSV文件。更多信息,请参看<a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">在线文档</a>。 + Authentication error + 验证错误 - New location - 新地点 + Logon failed with given username and password. Please try again! + 使用给定的用户名和密码登录失败。 请再试一次! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command - 为指定的命令显示帮助 + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + 提供的用户名或密码错误。请输入正确的密码或使用Veyon配置器切换不同的验证方法。 - Import objects from given file - 从给定的文件导入对象 + Logon authentication + 登录验证 - Export objects to given file - 导出对象到指定的文件 + Logon + 登录 + + + AuthSimpleDialog - Invalid type specified. Valid values are "%1" or "%2". - 指定的类型无效,有效值是 "%1" 或 "%2"。 + Veyon Logon + Veyon 登录 - Type + Please enter the Veyon password: + 请输入Veyon密码: + + + Authentication error + 验证错误 + + + Logon failed with given password. Please try again! + 使用提供的密码登录失败。请重试! + + + + AuthSimplePlugin + + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + 提供的密码是错误的。请输入正确的密码或使用Veyon配置器切换不同的验证方法。 + + + Simple password authentication + 简单密码验证 + + + Simple password + 简单密码 + + + + AuthenticationPage + + Authentication is set up properly on this computer. + 身份验证已在此计算机上正确配置。 + + + + AuthenticationPageTab + + Enabled + 已启用 + + + Test + 测试 + + + + BuiltinDirectoryConfiguration + + Builtin directory + 内置目录 + + + + BuiltinDirectoryConfigurationPage + + Computers + 计算机 + + + Name + 名称 + + + Host address/IP + 主机 IP 地址 + + + MAC address + MAC 地址 + + + Add new computer + 添加新计算机 + + + Remove selected computer + 删除选中的计算机 + + + New computer + 新计算机 + + + Builtin directory + 内置目录 + + + Locations + 地点 + + + Add new location + 添加新地点 + + + Remove selected location + 移除选中的地点 + + + New location + 新地点 + + + Directory name + 目录名称 + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + 可以通过命令行导入 CSV 文件。更多信息请查看<a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">在线文档</a>。 + + + + BuiltinDirectoryPlugin + + Show help for specific command + 为指定的命令显示帮助 + + + Import objects from given file + 从给定的文件导入对象 + + + Export objects to given file + 导出对象到指定的文件 + + + Invalid type specified. Valid values are "%1" or "%2". + 指定的类型无效,有效值是 "%1" 或 "%2"。 + + + Type 类型 @@ -1001,6 +1207,14 @@ The public key is used on client computers to authenticate incoming connection r MAC ADDRESS MAC 地址(网卡物理地) + + The specified command does not exist or no help is available for it. + 指定的命令不存在或没有它的说明可以使用。 + + + Location "%1" not found. + + BuiltinUltraVncServer @@ -1018,10 +1232,6 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - 主机/IP 地址: %1 - Active features: %1 激活的功能: %1 @@ -1038,10 +1248,6 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off 计算机离线或者已关机 - - Service unreachable or not running - 服务无法访问或未运行 - Authentication failed or access denied 验证失败或访问被拒绝 @@ -1062,6 +1268,38 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 地点:%1 + + [no user] + [无用户] + + + Veyon Server unreachable or not running + Veyon 服务器无法连接或未在运行 + + + Name: %1 + 名称:%1 + + + Hostname: %1 + + + + unknown + 未知 + + + IP address: %1 + + + + Hostname could not be resolved + + + + No features active + + ComputerControlServer @@ -1093,6 +1331,17 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. 主机 "%2" 上的用户 "%1" 尝试访问此计算机但因访问控制设置被阻止。 + + Active connections: + 活跃连接: + + + + ComputerGroupSelector + + Group %1 + 组 %1 + ComputerManager @@ -1120,13 +1369,48 @@ The public key is used on client computers to authenticate incoming connection r Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. 无法确定此计算机的地点。这表明系统配置存在问题。所有地点都将显示在计算机选择面板中。 + + Logged in since + 登录自 + + + %1 days + %1 天 + + + 1 day + 1 天 + - ComputerSelectPanel + ComputerMonitoring + + Computers + 计算机 + + + Search users and computers + 搜索用户和计算机 + + + Select all + 选择全部 + + + Unselect all + 取消选择全部 + + + Add to group + 添加到组 + - Computer management - 计算机管理 + Remove from group + 从组中移除 + + + ComputerSelectPanel Computer search 搜索计算机 @@ -1155,81 +1439,85 @@ The public key is used on client computers to authenticate incoming connection r Could not write the computer and users list to %1! Please check the file access permissions. 无法将计算机和用户列表写入 %1!请检查文件访问权限。 + + Search computers + 搜索计算机 + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. - 请指定要导入的配置文件。 + Clear system-wide Veyon configuration + 清除系统级别 Veyon 配置 - Please specify a valid filename for the configuration export. - 请为导出的配置指定一个有效的文件名。 + List all configuration keys and values + 列出所有配置密钥和值 - Please specify a valid key. - 请指定一个有效的密钥。 + Import configuration from given file + 从给定的文件导入配置 - Specified key does not exist in current configuration! - 指定的密钥在当前配置中不存在! + Export configuration to given file + 导出配置到指定的文件 - Please specify a valid value. - 请指定一个有效的值。 + Read and output configuration value for given key + 读取并输出配置值给指定的密钥 - Configure Veyon at command line - 在命令行配置 + Write given value to given configuration key + 将给定的值写入给定的配置密钥 - Output file is not writable! - 输出文件不可写! + Unset (remove) given configuration key + 取消设置(移除)给定的配置密钥 - Output directory is not writable! - 输出目录不可写! + Upgrade and save configuration of program and plugins + 升级并保存程序和插件的配置 + + + Please specify an existing configuration file to import. + 请指定要导入的配置文件。 Configuration file is not readable! 配置文件不可读! - Clear system-wide Veyon configuration - 清除系统级别 Veyon 配置 + Please specify a valid filename for the configuration export. + 请为导出的配置指定一个有效的文件名。 - List all configuration keys and values - 列出所有配置密钥和值 + Output file is not writable! + 输出文件不可写! - Import configuration from given file - 从给定的文件导入配置 + Output directory is not writable! + 输出目录不可写! - Export configuration to given file - 导出配置到指定的文件 + Please specify a valid key. + 请指定一个有效的密钥。 - Read and output configuration value for given key - 读取并输出配置值给指定的密钥 + Specified key does not exist in current configuration! + 指定的密钥在当前配置中不存在! - Write given value to given configuration key - 将给定的值写入给定的配置密钥 + Please specify a valid value. + 请指定一个有效的值。 - Unset (remove) given configuration key - 取消设置(移除)给定的配置密钥 + Configure Veyon at command line + 在命令行配置 Commands for managing the configuration of Veyon 管理 Veyon 配置的命令 - - Upgrade and save configuration of program and plugins - 升级并保存程序和插件的配置 - ConfigurationManager @@ -1253,6 +1541,10 @@ The public key is used on client computers to authenticate incoming connection r Could not apply platform-specific configuration settings. 无法应用平台相关的配置。 + + Could not configure the firewall configuration for the %1 Service. + + DemoClient @@ -1283,10 +1575,6 @@ The public key is used on client computers to authenticate incoming connection r Memory limit 内存限制 - - Use multithreading (experimental) - 使用多线程(实验) - MB MB @@ -1303,13 +1591,17 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running 当演示正在运行时降低缩略图更新频率 + + Bandwidth limit + 带宽限制 + + + MB/s + MB/s + DemoFeaturePlugin - - Fullscreen demo - 全屏演示 - Stop demo 停止演示 @@ -1323,16 +1615,60 @@ The public key is used on client computers to authenticate incoming connection r 通过屏幕广播进行演示 - Demo server - 演示服务 + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + 在此模式下,您的屏幕将作为窗口显示在所有计算机中。用户可以根据需要切换到其他窗口。 + + + Demo + 屏幕演示 + + + Share your screen or allow a user to share his screen with other users. + 分享您的屏幕或允许一个用户与其他用户分享其屏幕。 + + + Full screen demo + 全屏演示 + + + Share your own screen in fullscreen mode + 以全屏模式分享您自己的屏幕 - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. 在此模式下,您的屏幕将以全屏模式显示在所有电脑上,用户的输入设备将被锁定。 - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - 在此模式下,您的屏幕将作为窗口显示在所有计算机中。用户可以根据需要切换到其他窗口。 + Share your own screen in a window + 在窗口中分享您自己的屏幕 + + + Share selected user's screen in fullscreen mode + 以全屏模式分享选中用户的屏幕 + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + + + + Share selected user's screen in a window + 在窗口中分享选中用户的屏幕 + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + + + + Please select a user screen to share. + 请选择一个用户的屏幕进行分享 + + + Please select only one user screen to share. + 请仅选择一个用户的屏幕进行分享 + + + All screens + 所有屏幕 @@ -1360,14 +1696,6 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - - Programs & websites - 程序和网站 - - - Predefined programs - 预定义的程序 - Name 名称 @@ -1376,14 +1704,6 @@ The public key is used on client computers to authenticate incoming connection r Path 路径 - - Add new program - 添加新程序 - - - Remove selected program - 移除选中的程序 - Predefined websites 预定义的网站 @@ -1396,21 +1716,37 @@ The public key is used on client computers to authenticate incoming connection r URL URL - - New program - 新程序 - New website 新站点 + + Applications & websites + 程序 & 网站 + + + Predefined applications + 预定义的程序 + + + Add new application + 添加新程序 + + + Remove selected application + 移除选中的程序 + + + Add new website + 添加新的网站 + + + New application + 新程序 + DesktopServicesFeaturePlugin - - Run program - 运行程序 - Open website 打开网站 @@ -1420,28 +1756,32 @@ The public key is used on client computers to authenticate incoming connection r 点击此按钮,将在所有计算机上打开一个网站 - Start programs and services in user desktop - 在用户桌面运行程序和服务 + Open website "%1" + 打开站点 "%1" + + + Custom website + 定制站点 - Click this button to run a program on all computers. - 点击此按钮将在所有计算机上运行一个程序。 + Start application + 启动程序 - Run program "%1" - 运行程序 "%1" + Click this button to start an application on all computers. + 点击此按钮,将在所有计算机上启动一个程序 - Custom program - 定制程序 + Start application "%1" + 启动程序 "%1" - Open website "%1" - 打开站点 "%1" + Custom application + 自定义程序 - Custom website - 定制站点 + Start apps and open websites in user sessions + @@ -1474,17 +1814,21 @@ The public key is used on client computers to authenticate incoming connection r Play tutorial video 播放教程视频 - - Custom program - 定制程序 - Handout - + 讲义 Texts to read - + 要阅读的文本 + + + generic-student-user + 一般学生用户 + + + Custom application + 自定义程序 @@ -1510,10 +1854,165 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands + + List names of all available features + 列出所有可用功能的名称 + + + Show table with details of all available features + 显示含有所有可用功能的详细信息表格 + + + Start a feature on a remote host + 启动远程主机功能 + + + Stop a feature on a remote host + 停止远程主机功能 + + + Please specify the command to display help for. + 请指定显示说明的命令。 + + + Displays a list with the names of all available features. + + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + + + + HOST ADDRESS + 主机地址 + + + FEATURE + 功能 + + + ARGUMENTS + + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + + + + Lock the screen + 锁定屏幕 + + + Display a text message + 显示文字消息 + + + Test message + 文字消息 + + + Start an application + 启动程序 + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + + + + Unlock the screen + 解锁屏幕 + + + The specified command does not exist or no help is available for it. + 指定的命令不存在或没有它的说明可以使用。 + + + Name + 名称 + + + Description + 介绍 + + + Master + 主机 + + + Service + 服务 + + + Worker + Worker + + + UID + UID + + + Plugin + 插件 + + + Invalid feature name or UID specified + + + + Error parsing the JSON-encoded arguments: %1 + + + + Failed to initialize credentials + 初始化认证失败 + + + Could not establish a connection to host %1 + 无法建立到主机 %1 的连接 + + + Failed to send feature control message to host %1 + + + + Feature-related CLI operations + + + + Commands for controlling features + + + + + FileTransferConfigurationPage + + File transfer + 发布文件 + + + Directories + 文件夹 + + + Destination directory + 目标文件夹 + + + Default source directory + 默认源目录 + + + Options + 首选项 + + + Remember last source directory + 记住上次的源目录 + - Feature control - 功能控制 + Create destination directory if it does not exist + 如果不存在则创建目标目录 @@ -1558,6 +2057,13 @@ The public key is used on client computers to authenticate incoming connection r 覆盖已存在的文件 + + FileTransferFileDialog + + Select one or more files to transfer + 选择一个或多个要发送的文件 + + FileTransferPlugin @@ -1615,10 +2121,6 @@ The public key is used on client computers to authenticate incoming connection r Log file directory 日志文件存放目录 - - ... - ... - Log level 日志级别 @@ -1659,18 +2161,6 @@ The public key is used on client computers to authenticate incoming connection r Log to standard error output 日志显示于标准输出设备(显示器) - - Network object directory - 网络对象文件夹 - - - Backend: - 后端: - - - Update interval: - 更新频率: - %1 service %1 服务 @@ -1707,117 +2197,423 @@ The public key is used on client computers to authenticate incoming connection r x x - - seconds - - Write to logging system of operating system 写入操作系统的日志记录系统 - Authentication - 验证 - - - Method: - 方法: + TLS configuration + TLS 配置 - Logon authentication - 登录验证 + Use certificate authority for TLS connections + - Key file authentication - 密钥验证 + CA certificate file + CA 证书文件 - Test - 测试 + ... + ... - Authentication is set up properly on this computer. - 身份验证已在此计算机上正确配置。 + Host certificate file + 主机证书文件 - Authentication keys are not set up properly on this computer. - 验证密钥在此计算机上没有正确配置。 + Host private key file + 主机私钥文件 - Authentication test - 验证测试 + Style: + - - - InternetAccessControlConfigurationPage - Internet access control - 互联网访问控制 + Native + - Backend: - 后端: + Color scheme: + - General settings - 常规设置 + Light + - Backend settings - 后台设置 + Dark + - - - InternetAccessControlPlugin - Block access to the internet - 阻止访问互联网 + User groups + 用户组 - Allow access to the internet - 允许访问互联网 + Backend: + 后端: - Show help about command - 显此命令的帮助信息 + Include user groups from domain + - Block internet - 阻止互联网 + Missing user groups backend + 缺少用户组后端 - Click this button to block access to the internet. - 点击此按钮,阻止访问互联网。 + No user groups plugin was found. Please check your installation! + + + + HeadlessVncServer - Unblock internet - 取消阻止互联网 + Headless VNC server + + + + LdapBrowseDialog - Click this button to allow access to the internet. - 点击此按钮,取消阻止访问互联网。 + Browse LDAP + 浏览LDAP + + + + LdapClient + + LDAP error description: %1 + LDAP错误描述: %1 + + + + LdapConfiguration + + LDAP connection failed + LDAP 连接失败 + + + Could not connect to the LDAP server. Please check the server parameters. + +%1 + 无法连接到 LDAP 服务器。 请检查服务器参数。 + +%1 + + + LDAP bind failed + LDAP 绑定失败 + + + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + 无法绑定到 LDAP 服务器。 请检查服务器参数并绑定证书。 + +%1 + + + LDAP bind successful + LDAP 绑定成功 + + + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + 成功连接到 LDAP 服务器并执行 LDAP 绑定。 基本的 LDAP 设置配置正确。 + + + LDAP base DN test failed + LDAP 基础 DN 测试失败 + + + Could not query the configured base DN. Please check the base DN parameter. + +%1 + 无法查询配置的基本 DN。 请检查基本 DN 参数 + +%1 + + + LDAP base DN test successful + LDAP 基础 DN 测试通过 + + + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + LDAP 基本 DN 已成功查询。 找到以下条目: + +%1 + + + LDAP naming context test failed + LDAP 命名上下文测试失败 + + + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + 无法通过命名上下文查询基本 DN。 请检查命名上下文属性参数。 + +%1 + + + LDAP naming context test successful + LDAP 命名上下文测试通过 + + + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + LDAP 命名上下文已成功查询。 发现以下基本 DN: +%1 + + + user tree + 用户树 + + + User tree + User tree + + + group tree + 组树 + + + Group tree + Group tree + + + computer tree + 计算机树 + + + Computer tree + Computer tree + + + computer group tree + 计算机组树 + + + Computer group tree + 计算机组树 + + + user objects + 用户对象 + + + User login name attribute + 用户登录名属性 + + + group members + 组成员 + + + Group member attribute + 组成员属性 + + + Group not found + 未找到组 + + + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + 找不到名称为 "%1" 的组。 请检查组名称或组树参数。 + + + computer objects + 计算机对象 + + + Computer display name attribute + 计算机显示名称属性 + + + Invalid hostname + 主机名无效 + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + 您将计算机主机名配置为存储为完全限定域名(FQDN),但输入的是没有域名部分的主机名。 + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + 您将计算机主机名配置为存储没有域名的简单主机名,但输入了带有域名部分的主机名。 + + + Computer hostname attribute + 计算机主机名属性 + + + computer MAC addresses + 计算机 MAC 地址 + + + Computer MAC address attribute + 计算机 MAC 地址属性 + + + computer locations + 计算机地点 + + + Computer location attribute + 计算机地点属性 + + + Location name attribute + 地点名称属性 + + + users + 用户 + + + user groups + 用户组 + + + computers + 计算机 + + + computer groups + 计算机组 + + + computer containers + 计算机容器 + + + groups of user + 用户组 + + + User not found + 未找到用户 + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + 无法找到名称为 "%1" 的用户。 请检查用户名或用户树参数。 + + + groups of computer + 计算机组 + + + Computer not found + 未找到计算机 + + + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + 无法找到主机名为 "%1" 的计算机。 请检查主机名或计算机树参数。 + + + Hostname lookup failed + 主机名查询失败 + + + Could not lookup hostname for IP address %1. Please check your DNS server settings. + 无法查找IP地址为 %1 的主机名。请检查您的DNS服务器设置。 + + + location entries + 地点条目 + + + Computer groups filter + 计算机组筛选器 + + + Computer locations identification + 计算机地点标识 + + + Filter for computer groups + 计算机组过滤器 + + + Invalid test value + 测试值无效 + + + An empty or invalid value has been supplied for this test. + + + + LDAP %1 test failed + LDAP %1 测试失败 - Control access to the internet - 控制访问互联网 + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + Could not query any entries in configured %1.无法查询已配置的 %1 中的任何条目。请检查参数 "%2"。 + +%3 - Commands for controlling access to the internet - 控制访问互联网的命令 + LDAP %1 test successful + LDAP %1 测试成功 - - - LdapBrowseDialog - Browse LDAP - 浏览LDAP + The %1 has been queried successfully and %2 entries were found. + 已成功查询 %1 ,并找到 %2 个条目。 - - - LdapClient - LDAP error description: %1 - LDAP错误描述: %1 + LDAP test failed + LDAP测试失败 + + + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + 无法查询任何 %1。 请检查参数 %2 或输入现有对象的名称。 + +%3 + + + and + + + + LDAP test successful + LDAP测试成功 + + + %1 %2 have been queried successfully: + +%3 + %1 %2 查询成功: + +%3 + + + LDAP filter test failed + LDAP 过滤器测试失败 + + + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 + 无法使用配置的过滤器查询任何 %1 。 请检查 LDAP 过滤器的 %1 。 + +%2 + + + LDAP filter test successful + LDAP 过滤器测试成功 + + + %1 %2 have been queried successfully using the configured filter. + %1 %2 使用配置的过滤器成功查询。 + + + LDAP directory + LDAP 目录 @@ -1974,56 +2770,6 @@ The public key is used on client computers to authenticate incoming connection r Get computer object by IP address 通过 IP 地址获取计算机对象 - - LDAP connection failed - LDAP 连接失败 - - - LDAP bind failed - LDAP 绑定失败 - - - LDAP bind successful - LDAP 绑定成功 - - - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - 成功连接到 LDAP 服务器并执行 LDAP 绑定。 基本的 LDAP 设置配置正确。 - - - LDAP base DN test failed - LDAP 基础 DN 测试失败 - - - LDAP base DN test successful - LDAP 基础 DN 测试通过 - - - LDAP naming context test failed - LDAP 命名上下文测试失败 - - - LDAP naming context test successful - LDAP 命名上下文测试通过 - - - The LDAP naming context has been queried successfully. The following base DN was found: -%1 - LDAP 命名上下文已成功查询。 发现以下基本 DN: -%1 - - - user tree - 用户树 - - - group tree - 组树 - - - computer tree - 计算机树 - Enter username 请输入用户名 @@ -2032,10 +2778,6 @@ The public key is used on client computers to authenticate incoming connection r Please enter a user login name (wildcards allowed) which to query: 请输入要查询的用户登录名(允许使用通配符): - - user objects - 用户对象 - Enter group name 输入组名称 @@ -2044,26 +2786,10 @@ The public key is used on client computers to authenticate incoming connection r Please enter a group name whose members to query: 请输入要查询其成员的群组名称: - - group members - 组成员 - - - Group not found - 未找到组 - - - Could not find a group with the name "%1". Please check the group name or the group tree parameter. - 找不到名称为 "%1" 的组。 请检查组名称或组树参数。 - Enter computer name 输入计算机名称 - - computer objects - 计算机对象 - Enter computer DN 输入计算机 @@ -2072,42 +2798,10 @@ The public key is used on client computers to authenticate incoming connection r Please enter the DN of a computer whose MAC address to query: 请输入要查询 MAC 地址的计算机的 DN: - - computer MAC addresses - 计算机 MAC 地址 - - - users - 用户 - - - user groups - 用户组 - - - computer groups - 计算机组 - Please enter a user login name whose group memberships to query: 请输入要查询的组成员资格的用户登录名: - - groups of user - 用户组 - - - User not found - 未找到用户 - - - groups of computer - 计算机组 - - - Computer not found - 未找到计算机 - Enter computer IP address 输入计算机 IP 地址 @@ -2116,50 +2810,6 @@ The public key is used on client computers to authenticate incoming connection r Please enter a computer IP address which to resolve to an computer object: 请输入要解析为计算机对象的计算机 IP 地址: - - computers - 计算机 - - - LDAP %1 test failed - LDAP %1 测试失败 - - - LDAP %1 test successful - LDAP %1 测试成功 - - - The %1 has been queried successfully and %2 entries were found. - 已成功查询 %1 ,并找到 %2 个条目。 - - - %1 %2 have been queried successfully: - -%3 - %1 %2 查询成功: - -%3 - - - LDAP filter test failed - LDAP 过滤器测试失败 - - - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 - 无法使用配置的过滤器查询任何 %1 。 请检查 LDAP 过滤器的 %1 。 - -%2 - - - LDAP filter test successful - LDAP 过滤器测试成功 - - - %1 %2 have been queried successfully using the configured filter. - %1 %2 使用配置的过滤器成功查询。 - (only if different from group tree) (仅当与组树不同时) @@ -2168,10 +2818,6 @@ The public key is used on client computers to authenticate incoming connection r Computer group tree 计算机组树 - - computer group tree - 计算机组树 - Filter for computers 计算机过滤器 @@ -2250,51 +2896,11 @@ The public key is used on client computers to authenticate incoming connection r e.g. (objectClass=container) or (objectClass=organizationalUnit) - 例如 (objectClass=container) 或 (objectClass=organizationalUnit) - - - Could not query the configured base DN. Please check the base DN parameter. - -%1 - 无法查询配置的基本 DN。 请检查基本 DN 参数 - -%1 - - - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - LDAP 基本 DN 已成功查询。 找到以下条目: - -%1 - - - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - 无法通过命名上下文查询基本 DN。 请检查命名上下文属性参数。 - -%1 - - - Certificate files (*.pem) - 证书文件 (*.pem) - - - Could not connect to the LDAP server. Please check the server parameters. - -%1 - 无法连接到 LDAP 服务器。 请检查服务器参数。 - -%1 + 例如 (objectClass=container) 或 (objectClass=organizationalUnit) - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - 无法绑定到 LDAP 服务器。 请检查服务器参数并绑定证书。 - -%1 + Certificate files (*.pem) + 证书文件 (*.pem) Encryption protocol @@ -2352,10 +2958,6 @@ The public key is used on client computers to authenticate incoming connection r Please enter the name of a computer location (wildcards allowed): 请输入计算机地点名称(允许使用通配符): - - computer locations - 计算机地点 - Enter location name 输入地点名称 @@ -2364,38 +2966,6 @@ The public key is used on client computers to authenticate incoming connection r Please enter the name of a location whose entries to query: 请输入要查询其条目的地点名称: - - location entries - 地点条目 - - - LDAP test failed - LDAP测试失败 - - - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - 无法查询任何 %1。 请检查参数 %2 或输入现有对象的名称。 - -%3 - - - and - - - - LDAP test successful - LDAP测试成功 - - - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - Could not query any entries in configured %1.无法查询已配置的 %1 中的任何条目。请检查参数 "%2"。 - -%3 - Browse 浏览 @@ -2417,52 +2987,51 @@ The public key is used on client computers to authenticate incoming connection r 请输入要查询的计算机主机名: - Invalid hostname - 无效的主机名 - - - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - 您将计算机主机名配置为存储为完全限定域名(FQDN),但输入的是没有域名部分的主机名。 + Enter hostname + 输入主机名 - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - 您将计算机主机名配置为存储没有域名的简单主机名,但输入了带有域名部分的主机名。 + Please enter a computer hostname whose group memberships to query: + 请输入要查询其组成员的计算机主机名: - Could not find a user with the name "%1". Please check the username or the user tree parameter. - 无法找到名称为 "%1" 的用户。 请检查用户名或用户树参数。 + User login name attribute + 用户登录名属性 - Enter hostname - 输入主机名 + Configured attribute for user login name or computer hostname (OpenLDAP) + 用户登录名或计算机主机名的配置属性(OpenLDAP) - Please enter a computer hostname whose group memberships to query: - 请输入要查询其组成员的计算机主机名: + Directory name + 目录名称 - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - 无法找到主机名为 "%1" 的计算机。 请检查主机名或计算机树参数。 + Query options + 查询选项 - Hostname lookup failed - 主机名查询失败 + Query nested user groups (supported by AD only) + - Could not lookup hostname for IP address %1. Please check your DNS server settings. - 无法查找IP地址为 %1 的主机名。请检查您的DNS服务器设置。 + Query timeout + - User login name attribute - 用户登录名属性 + ms + 毫秒 + + + LdapNetworkObjectDirectoryConfigurationPage - Configured attribute for user login name or computer hostname (OpenLDAP) - 用户登录名或计算机主机名的配置属性(OpenLDAP) + LDAP + LDAP - computer containers - 计算机容器 + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + @@ -2511,213 +3080,17 @@ The public key is used on client computers to authenticate incoming connection r Configuring %1 as base DN and disabling naming context queries. 正配置 %1 为base DN,并禁用命名上下文查询。 - - - LdapProConfigurationPage - - LDAP Pro - LDAP Pro - - - Instances - 实例 - - - Enter name - 输入名称 - - - Please enter a name for the instance (can't be changed later!): - 请输入此实例的名称(设置后无法更改!): - - - Remove instance - 移除实例 - - - Do you really want to remove instance "%1"? - 您确定要移除实例 "%1" 吗? - - - Configuration for instance "%1" - 实例 "%1" 的配置 - - - - LdapProPlugin - - Professional LDAP/AD integration for Veyon - 为Veyon提供LDAP/AD专业集成 - - - %1 (load computers and locations from LDAP/AD) - %1 (从LDAP/AD加载计算机和地点) - - - %1 (load users and groups from LDAP/AD) - %1(从LDAP/AD加载用户和组) - - - - LicensingConfigurationPage - - Licensing - 许可 - - - Installed licenses - 已安装的许可证 - - - Add new network range - 添加新的网络范围 - - - Remove selected network range - 移除选中的网络范围 - - - ID - ID - - - Feature - 特性 - - Valid until - 有效期至 - - - Licensee - 被许可人 - - - Browse license file - 浏览许可证文件 - - - Veyon license files (*.vlf) - Veyon 许可证文件 - - - Remove license - 删除许可证 - - - Do you really want to remove the selected license? - 您确定要删除所选的许可证吗? - - - <N/A> - <N/A> - - - Invalid license file - 无效的许可证文件 - - - Could not open the license file for reading! - 无法打开打开并读取许可证文件! - - - The selected license file does not contain valid data. - 选定的许可证文件不包含有效数据。 - - - The selected license file could not be verified. - 无法验证所选的许可证文件。 - - - The selected license file is not valid for this installation. - 选定的许可证文件对此安装无效。 - - - The selected license file is expired. - 选定的许可证文件已过期。 - - - The license is already installed. - 许可证已安装。 - - - Information - 信息 - - - Installation ID - 安装ID - - - Addons available for licensing - 需要许可证的可用插件 - - - Addon - 插件 - - - - LicensingPlugin - - Show help for specific command - 为指定的命令显示帮助 - - - Show all installed licenses - 显示所有已安装的许可 - - - Add license file - 添加许可证文件 - - - Remove installed license - 删除已安装的许可证 - - - -USAGE - -%1 add <LICENSE FILE> - - - -用法: - -%1 add <LICENSE FILE> - - - - - -USAGE - -%1 remove <LICENSE ID> - - - -用法: - -%1 remove <LICENSE ID> - - - - - No certificate found with given ID - 找不到给定 ID 的许可证书 - - - <N/A> - <N/A> + Test binding to an LDAP server + - Licensing management - 许可管理 + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + 提供的用户名或密码错误。请输入正确的密码或使用Veyon配置器切换不同的验证方法。 - Commands for managing license keys - 用于管理许可证密钥的命令 + LDAP bind + LDAP 绑定 @@ -2735,12 +3108,20 @@ USAGE 用户验证 - Session management - 会话管理 + User sessions + 用户会话 + + + Minimum session lifetime before server start + + + + User login + 用户登陆 - Display manager users - 显示管理员用户 + Login key sequence + @@ -2749,10 +3130,6 @@ USAGE Plugin implementing abstract functions for the Linux platform 通过插件实现 Linux 平台的抽象函数 - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2771,14 +3148,14 @@ USAGE Configuration 配置 - - Disable balloon tooltips - 禁用气球浮动提示 - Show icons only 仅显示图标 + + Disable tooltips + + MainWindow @@ -2826,10 +3203,6 @@ USAGE About Qt 关于 Qt - - Authentication impossible - 无法验证 - Configuration not writable 配置文件不可写 @@ -2890,10 +3263,6 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. 本地配置后端报告配置不可写入! 请以更高的权限来运行 %1 配置程序。 - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - 没有找到密钥验证文件或者您当前的文件已过期。 请使用 %1 配置程序创建新的密钥文件。 或者使用 %1 配置器设置登录验证。 否则,您将无法使用 %1 访问计算机。 - Access denied 拒绝访问 @@ -2926,10 +3295,6 @@ USAGE Search users and computers 搜索用户和计算机 - - Adjust optimal size - 调整最佳尺寸 - Align computers to grid 将计算机图标与网格对齐 @@ -2939,40 +3304,82 @@ USAGE %1 配置器 - Insufficient privileges - 权限不够 + Insufficient privileges + 权限不够 + + + Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. + 无法以管理权限运行。 请确保您的桌面环境安装了类似 sudo 的程序!程序将以普通用户权限运行。 + + + Only show powered on computers + 仅显示开机的计算机 + + + &Save settings to file + &S保存设置到文件 + + + &View + &视图 + + + &Standard + &标准 + + + &Advanced + &高级 + + + Use custom computer arrangement + 使用自定义的计算机排序 + + + Locations && computers + 地点及计算机 + + + Authentication + 验证 + + + Adjust size of computer icons automatically + - Could not start with administrative privileges. Please make sure a sudo-like program is installed for your desktop environment! The program will be run with normal user privileges. - 无法以管理权限运行。 请确保您的桌面环境安装了类似 sudo 的程序!程序将以普通用户权限运行。 + Slideshow + - Only show powered on computers - 仅显示开机的计算机 + Spotlight + - &Save settings to file - &S保存设置到文件 + Veyon Master + - &View - &视图 + Locations & computers + 地点及计算机 - &Standard - &标准 + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + - &Advanced - &高级 + Only show computers with logged on users + - Use custom computer arrangement - 使用自定义的计算机排序 + Load computer positions + - Locations && computers - 地点及计算机 + Save computer positions + @@ -2981,10 +3388,6 @@ USAGE Directories 文件夹 - - ... - ... - User configuration 用户配置 @@ -3069,6 +3472,10 @@ USAGE Only user name 仅用户名 + + Only last part of user name + + Only computer name 仅计算机名称 @@ -3117,171 +3524,181 @@ USAGE Automatically select current location 自动选择当前地点 - - Automatically adjust computer thumbnail size - 自动调整计算机缩略图大小 - Automatically open computer select panel 自动打开计算机选择面板 - - - MonitoringMode - Monitoring - 监控 + Use modern user interface (experimental) + - Builtin monitoring mode - 内置监控模式 + Thumbnail spacing + - This mode allows you to monitor all computers at one or more locations. - 此模式允许您在一个或多个地点监控所有计算机。 + px + px - - - NetworkDiscoveryConfigurationPage - Network discovery - 网络发现 + Hide local session + 隐藏本机会话 - Mode - 模式 + Auto + 自动 - Scan network ranges - 扫描网络范围 + Thumbnail aspect ratio + - e.g. 192.168.1.0/24 - 例如: 192.168.1.0/24 + Automatically adjust computer icon size + - Scan all subnets of computer - 扫描计算机的所有子网 + Open feature windows on the same screen as the main window + - Scan custom subnet - 扫描指定的子网 + Configuration templates + - Scan sessions on local computer - 扫描会话在本地计算机上 + Image quality in monitoring mode + - Test - 测试 + Highest + + + + High + - Network ranges - 网络范围 + Medium + - Add new group - 添加新的组 + Low + - Remove selected group - 移除选中的组 + Lowest + - Groups - + Remote access image quality + - First address - 第一个地址 + Advanced + - Last address - 最后一个地址 + Computer name source + - Add new network range - 添加新的网络范围 + Default + - Remove selected network range - 移除选中的网络范围 + Host address + 主机地址 - Parallel scans - 并行扫描 + Session client address + - Scan timeout - 扫描超时 + Session client name + - ms - 毫秒 + Session host name + - Session scan limit - 会话扫描限制 + Session metadata + - Options - 首选项 + Full name of user + - Reverse lookup discovered IP addresses to host names - 反向查找已发现的IP地址到主机名 + User login name + - New location - 新地点 + Computer UID role + + + + Session meta data hash + - - - NetworkDiscoveryDirectory - Scanning... - 正在扫描... + Always expand all locations + - Discovered computers - 查找计算机 + Image quality + - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command - 为指定的命令显示帮助 + Monitoring + 监控 - Scan a subnet - 扫描一个子网 + Builtin monitoring mode + 内置监控模式 - -USAGE - -%1 scan [<SUBNET>] - - - -用法: - -%1 scan [<SUBNET>] - - + This mode allows you to monitor all computers at one or more locations. + 此模式允许您在一个或多个地点监控所有计算机。 + + + Query application version of the server + - Network object directory which automatically discovers computers in the network - 网络中,可自动发现计算机的网络对象目录 + Query active features + + + + Query properties of remotely available screens + + + + + NestedNetworkObjectDirectory + + All directories + + + + + NetworkObjectDirectoryConfigurationPage + + Update interval: + 更新频率: - Network discovery (scan network for Veyon clients) - 网络发现(Veyon 客户端的扫描网络) + seconds + + + + NetworkObjectDirectoryConfigurationPageTab - Commands for managing the network discovery directory - 用于管理网络发现目录的命令 + Enabled + 已启用 @@ -3317,32 +3734,44 @@ USAGE Name: 名称: + + Website name + + - PasswordDialog + PluginCommands - Username - 用户名 + List names of all installed plugins + - Password - 密码 + Show table with details of all installed plugins + - Veyon Logon - Veyon 登录 + Name + 名称 - Authentication error - 验证错误 + Description + 介绍 - Logon failed with given username and password. Please try again! - 使用给定的用户名和密码登录失败。 请再试一次! + Version + 版本 - Please enter your username and password in order to access computers. - 请输入您的用户名和密码才能访问计算机。 + UID + UID + + + Plugin-related CLI operations + + + + Commands for managing plugins + @@ -3387,10 +3816,6 @@ USAGE Do you really want to reboot the selected computers? 你确定要重新启动选定的电脑吗? - - Do you really want to power down the selected computer? - 你确定要关闭选定的电脑吗? - Power on a computer via Wake-on-LAN (WOL) 通过局域网唤醒(WOL)打开计算机电源 @@ -3443,6 +3868,18 @@ Please save your work and close all programs. 请保存您的工作并关闭所有程序。 + + Do you really want to reboot <b>ALL</b> computers? + 您真的要重新启动<b>所有的</b>计算机? + + + Do you really want to power down <b>ALL</b> computers? + 您真的要关闭<b>所有的</b>计算机? + + + Do you really want to power down the selected computers? + + PowerDownTimeInputDialog @@ -3489,14 +3926,25 @@ Please save your work and close all programs. Remote view or control a computer 远程查看或控制电脑 - - Please enter the hostname or IP address of the computer to access: - 请输入要访问的计算机的主机名或IP地址: - Show help about command 显此命令的帮助信息 + + Exchange clipboard contents + + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + + + + + RemoteAccessPage + + Remote access: %1 + + RemoteAccessWidget @@ -3504,6 +3952,10 @@ Please save your work and close all programs. %1 - %2 Remote Access %1 - %2 远程访问 + + %1 - %2 - %3 Remote Access + + RemoteAccessWidgetToolBar @@ -3559,10 +4011,6 @@ Please save your work and close all programs. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - 正在连接 %1 - Connected. 已连接。 @@ -3575,58 +4023,17 @@ Please save your work and close all programs. Exit 退出 - - - Routing - - Control internet access by modifying routing table - 通过修改路由表来控制 Internet 访问 - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - 删除默认路由以阻止 Internet 访问 - - Add custom route to block internet - 通过添加自定义路由来阻止访问互联网 + Connecting... + 正在连接... - Destination - 目标地址 + Select screen + 选择屏幕 - Gateway - 网关 - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - 请输入要在所选计算机上运行的程序或命令。 您可以按行分隔多个程序/命令。 - - - Run programs - 运行程序 - - - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - 例如 "C:\Program Files\VideoLAN\VLC\vlc.exe" - - - Name: - 名称: - - - Remember and add to program menu - 记住并添加到程序菜单 - - - e.g. VLC - 例如 VLC + All screens + 所有屏幕 @@ -3647,6 +4054,18 @@ Please save your work and close all programs. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. 要集中所有用户的注意力,您可以使用此按钮锁定他们的计算机。 在这种模式下,所有输入设备都被锁定,屏幕变黑。 + + Lock input devices + 锁定输入设备 + + + Unlock input devices + 解锁输入设备 + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + + Screenshot @@ -3662,6 +4081,10 @@ Please save your work and close all programs. Screenshot 屏幕截图 + + Could not open screenshot file %1 for writing. + + ScreenshotFeaturePlugin @@ -3686,6 +4109,13 @@ Please save your work and close all programs. 以计算机屏幕截图并将其保存在本地。 + + ScreenshotManagementPage + + Screenshots + 屏幕截图 + + ScreenshotManagementPanel @@ -3713,8 +4143,47 @@ Please save your work and close all programs. 显示 - Delete - 删除 + Delete + 删除 + + + Screenshot + 屏幕截图 + + + Do you really want to delete all selected screenshots? + 您确定要删除所有选中的屏幕截图吗? + + + + ServerAccessControlManager + + Requested authentication method not available + + + + Access allowed by rule "%1" + + + + Access denied by rule "%1" + + + + No rule allowed access + + + + Accessing user not member of an authorized user group + + + + User has denied access + + + + User confirmed access + @@ -3747,14 +4216,6 @@ Please save your work and close all programs. State: 状态: - - Network - 网络 - - - Demo server port - 演示服务端口 - Enable firewall exception 开启防火墙例外设定 @@ -3763,10 +4224,6 @@ Please save your work and close all programs. Allow connections from localhost only 只允许本地连接 - - Internal VNC server port - 内部 VNC 服务器端口 - VNC server VNC 服务 @@ -3787,14 +4244,6 @@ Please save your work and close all programs. Running 正在运行 - - Feature manager port - 功能管理器端口 - - - Primary service port - 主服务端口 - Enabling this option will make the service launch a server process for every interactive session on a computer. Typically this is required to support terminal servers. @@ -3805,52 +4254,130 @@ Typically this is required to support terminal servers. Show notification on remote connection 在远程连接上显示通知 - - Multi session mode (for terminal and remote desktop servers) - 多会话模式(适用于终端及远程桌面服务器) - Show notification when an unauthorized access is blocked 当未授权访问被阻止时显示通知 - - - ServiceControl - Starting service %1 - 启动服务 %1 + Maximum session count + - Stopping service %1 - 停止服务 %1 + Network port numbers + - Registering service %1 - 注册服务 %1 + Veyon server + - Unregistering service %1 - 反注册服务 %1 + Internal VNC server + 内部 VNC 服务器 - Service control - 服务控制 + Feature manager + + + + Demo server + 演示服务 + + + Miscellaneous network settings + + + + Session mode + 会话模式 + + + Local session mode (single server instance for primary local session) + + + + Active session mode (single server instance for active local or remote session) + + + + Multi session mode (distinct server instance for each local and remote desktop session) + + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + + + + Miscellaneous settings + + + + Disable clipboard synchronization + + + + Session metadata + + + + Content + + + + None + + + + Value of an environment variable + + + + Value of a registry key + + + + Environment variable name: + + + + Registry key name: + + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + - ServiceControlPlugin + ServiceControl - Service is running - 服务正在运行 + Service control + 服务控制 - Service is not running - 服务没有运行 + Starting %1 + - Configure and control Veyon service - 配置和控制 Veyon 服务 + Stopping %1 + + + + Restarting %1 + + + + Registering %1 + + + Unregistering %1 + + + + + ServiceControlCommands Register Veyon Service 注册 Veyon 服务 @@ -3875,13 +4402,25 @@ Typically this is required to support terminal servers. Query status of Veyon Service 查询 Veyon 服务状态 + + Service is running + 服务正在运行 + + + Service is not running + 服务没有运行 + + + Configure and control Veyon service + 配置和控制 Veyon 服务 + Commands for configuring and controlling Veyon Service 用于配置和控制Veyon服务的命令 - ShellCommandLinePlugin + ShellCommands Run command file 运行命令文件 @@ -3891,14 +4430,100 @@ Typically this is required to support terminal servers. 文件 "%1" 不存在! - Interactive shell and script execution for Veyon Control - Veyon 控制器的交互式 shell 和脚本运行 + Interactive shell and script execution for Veyon CLI + Commands for shell functionalities shell功能的命令 + + SlideshowPanel + + Previous + + + + Start/pause + + + + Next + + + + Duration: + 持续时间: + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + 添加选中的计算机 + + + Remove selected computers + 删除选中的计算机 + + + Update computers in realtime + 实时更新计算机 + + + Spotlight + + + + Please select at least one computer to add. + + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + + + + + StartAppDialog + + Start application + 启动程序 + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + 例如 "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + + + + Application name + + + + Name: + 名称: + + + e.g. VLC + 例如 VLC + + SystemTrayIcon @@ -3935,8 +4560,8 @@ Typically this is required to support terminal servers. 发送消息 - Use the field below to type your message which will be sent to all selected users. - 在下面的文本框中输入您要发送给所选用户的消息。 + Please enter your message which send to all selected users. + @@ -3984,23 +4609,39 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer 启用Windows 8及更新操作系统上的桌面拷贝引擎 + + Maximum CPU usage + + - UserConfig + UserLoginDialog - No write access - 没有写入权限 + User login + 用户登陆 - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - 无法保存您的个人设置! 请使用 %1 配置器检查用户配置文件路径。 + Please enter a username and password for automatic login on all computers. + 请输入用来在所有计算机自动登陆的用户名和密码。 + + + Username + 用户名 + + + Password + 密码 - UserSessionControl + UserSessionControlPlugin - User session control - 用户会话控制 + Log in + 登陆 + + + Click this button to log in a specific user on all computers. + 点击此按钮以便于在所有计算机上登陆制定账户 Log off @@ -4018,6 +4659,14 @@ Typically this is required to support terminal servers. Do you really want to log off the selected users? 您确定要注销选定的用户吗? + + User session control + 用户会话控制 + + + Do you really want to log off <b>ALL</b> users? + 您确定要注销 <b>所有</b> 用户吗? + VeyonCore @@ -4069,10 +4718,6 @@ Typically this is required to support terminal servers. ERROR ERROR - - licensed for - 许可给 - USAGE 使用情况 @@ -4089,19 +4734,31 @@ Typically this is required to support terminal servers. WARNING 警告 + + Authentication test + 验证测试 + + + Screen %1 + 屏幕 %1 + - VeyonServiceControl + VeyonMaster - Veyon Service - Veyon 服务 + No write access + 没有写入权限 + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + 无法保存您的个人设置! 请使用 %1 配置器检查用户配置文件路径。 - VncView + VeyonServiceControl - Establishing connection to %1 ... - 正在建立到 %1 的连接... + Veyon Service + Veyon 服务 @@ -4149,6 +4806,30 @@ Typically this is required to support terminal servers. Use alternative user authentication mechanism 使用其他用户验证机制 + + User login + 用户登陆 + + + Input start delay + 输入启动延迟 + + + Simulated key presses interval + 模拟按键间隔 + + + Confirm legal notice (message displayed before user logs in) + + + + Use input device interception driver + + + + Use custom power scheme with disabled power button + + WindowsPlatformPlugin @@ -4157,8 +4838,8 @@ Typically this is required to support terminal servers. 插件实现 Windows 平台的抽象函数 - Plugin implementing specific functions for the Windows platform - + Internal display + 内部显示 @@ -4167,30 +4848,34 @@ Typically this is required to support terminal servers. The service "%1" is already installed. 服务 "%1" 已安装。 - - The service "%1" could not be installed. - 服务 "%1" 未能安装。 - The service "%1" has been installed successfully. 服务 "%1" 已成功安装。 - - The service "%1" could not be uninstalled. - 服务 "%1" 未能卸载。 - The service "%1" has been uninstalled successfully. 服务 "%1" 已成功卸载。 - - The start type of service "%1" could not be changed. - 服务 "%1" 的启动类型无法更改。 - Service "%1" could not be found. 服务 "%1" 未找到。 + + The service "%1" could not be installed (error %2). + + + + Could not change the failure actions config for service "%1" (error %2). + + + + The service "%1" could not be uninstalled (error %2). + + + + The start type of service "%1" could not be changed (error %2). + + X11VncConfigurationWidget diff --git a/translations/zh_TW.ts b/translations/veyon_zh_TW.ts similarity index 71% rename from translations/zh_TW.ts rename to translations/veyon_zh_TW.ts index c87b224fd..c10d22e33 100644 --- a/translations/zh_TW.ts +++ b/translations/veyon_zh_TW.ts @@ -1,4 +1,4 @@ - + AboutDialog @@ -54,7 +54,7 @@ If you're interested in translating Veyon into your local or another langua Grant access to every authenticated user (default) - 每個經過驗證的使用者授予存取權限 (預設值) + 每個已驗證的使用者授予存取權限 (預設值) Test @@ -80,10 +80,6 @@ If you're interested in translating Veyon into your local or another langua All groups 所有群組 - - ... - ... - Access control rules 存取控制規則 @@ -138,21 +134,20 @@ If you're interested in translating Veyon into your local or another langua User groups backend: - 使用者群組後台: - - - Missing user groups backend - 缺少使用者群組後台 - - - No default user groups plugin was found. Please check your installation! - 找不到預設的使用者群組外掛件。 請檢查您的安裝! + 使用者群組後端: Restrict access to members of specific user groups 限制對指定使用者群組成員的存取 + + AccessControlProvider + + Provider for access control features + 存取控制功能的提供者 + + AccessControlRuleEditDialog @@ -179,30 +174,10 @@ If you're interested in translating Veyon into your local or another langua Rule description: 規則描述: - - Invert all conditions ("is/has" interpreted as "is/has not") - 反向所有條件 ("是/有" 解釋為 "不是/沒有") - Conditions 條件 - - is member of group - 是群組的成員 - - - Accessing computer is localhost - 存取電腦是 localhost - - - Accessing user is logged on user - 存取使用者是登入的使用者 - - - Accessing user is already connected - 存取使用者已經連線 - If more than one condition is activated each condition has to meet in order to make the rule apply (logical AND). If only one of multiple conditions has to meet (logical OR) please create multiple access control rules. 如果有啟用一個以上條件,每個條件必須滿足,以便使規則套用 (邏輯 AND)。 如果多個條件只有一個必須滿足 (邏輯 OR),請建立多個存取控制規則。 @@ -236,33 +211,125 @@ If you're interested in translating Veyon into your local or another langua 存取電腦 - Local (logged on) user - 本機 (登入的) 使用者 + Always process rule and ignore conditions + 始終處理規則和忽略條件 - Local computer - 本機電腦 + Accessing computer and local computer + 存取電腦和本機電腦 - Always process rule and ignore conditions - 始終處理規則和忽略條件 + User being accessed + 使用者正在存取 - No user logged on - 沒有使用者登入 + is logged in locally + 本機登入 + + + is logged in remotely + 遠端登入 + + + No user is logged in locally + 沒有使用者本機登入 + + + One or multiple users are logged in locally + 一個或多個使用者本機登入 - Accessing user has one or more groups in common with local (logged on) user - 存取使用者與本機 (登入的) 使用者有一個或數個群組在通用 + No user is logged in remotely + 沒有使用者遠端登入 - Accessing computer and local computer are at the same location - 存取電腦和本機電腦位於同一位置 + One or multiple users are logged in remotely + 一個或多個使用者遠端登入 is located at 位於 + + is not located at + 沒有位於 + + + are located at the same location + 位於同一位置 + + + are not located the same location + 位於不同位置 + + + is member of group + 是群組的成員 + + + is not member of group + 不是群組成員 + + + is authenticated via + 身份驗證透過 + + + is not authenticated via + 未身份驗證透過 + + + has one or more groups in common with user being accessed + 有一個或多個通用中群組的使用者正在存取 + + + has no groups in common with user being accessed + 沒有通用中群組的使用者正在存取 + + + equals user being accessed + 等於使用者正在存取 + + + is different from user being accessed + 不同的使用者正在存取 + + + is already connected + 已經連接 + + + is not connected + 未連接 + + + is local computer + 是本機電腦 + + + is not local computer + 不是本機電腦 + + + Computer being accessed + 電腦正在存取 + + + Session being accessed is a user session + 正在存取的工作階段是使用者工作階段 + + + Session being accessed is a login screen + 正在存取的工作階段是登入畫面 + + + Local computer is already being accessed + 已經存取本機電腦 + + + Local computer is not yet being accessed + 尚未存取本機電腦 + AccessControlRulesTestDialog @@ -306,42 +373,44 @@ If you're interested in translating Veyon into your local or another langua The access in the given scenario needs permission of the logged on user. 在給予情境中存取。需要登入使用者的權限。 - - ERROR: Unknown action - 錯誤: 未知的動作 - Test result 測試結果 - - - AndroidPlatformConfigurationPage - Android - + Authentication method + 身份驗證方法 - General - 一般 + There is no matching rule with a valid action. The access is therefore denied. + - AndroidPlatformPlugin + AuthKeysConfigurationWidget - Plugin implementing specific functions for the Android platform - + Introduction + 介紹 - - - AuthKeysConfigurationPage - Authentication keys - 身份驗證金鑰 + Please perform the following steps to set up key file authentication: + 請執行以下步驟以設定金鑰檔身份驗證: - Introduction - 介紹 + 1) Create a key pair on the master computer. + 1) 在主電腦上建立金鑰對。 + + + 2) Set an access group whose members should be allowed to access other computers. + 2) 設定一個存取群組,應該允許其成員存取其它電腦。 + + + 3) Export the public key and import it on all client computers with the same name. + 3) 匯出公開金鑰並將其匯入到具有相同名稱的所有用戶端電腦上。 + + + Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. + 請參閱 <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon 管理員手冊</a>,取得更多資訊。 Key file directories @@ -356,12 +425,18 @@ If you're interested in translating Veyon into your local or another langua 私密金鑰檔基礎目錄 - ... - ... + Available authentication keys + 可用身份驗證金鑰 - Available authentication keys - 可用驗證金鑰 + An authentication key pair consist of two coupled cryptographic keys, a private and a public key. +A private key allows users on the master computer to access client computers. +It is important that only authorized users have read access to the private key file. +The public key is used on client computers to authenticate incoming connection request. + 身份驗證金鑰配對由兩個耦合的加密金鑰,一個私有金鑰和一個公開金鑰組成。 +私密金鑰允許主機電腦上的使用者存取用戶端電腦。 +重要的是,只有授權使用者才能對私密金鑰檔進行讀取存取。 +公開金鑰用於用戶端電腦以驗證傳入連線請求。 Create key pair @@ -385,11 +460,11 @@ If you're interested in translating Veyon into your local or another langua Key files (*.pem) - 金鑰檔 (*. pem) + 金鑰檔 (*.pem) Authentication key name - 驗證金鑰名稱 + 身份驗證金鑰名稱 Please enter the name of the user group or role for which to create an authentication key pair: @@ -401,11 +476,7 @@ If you're interested in translating Veyon into your local or another langua Please select a key to delete! - 請選擇要刪除的金鑰! - - - Please enter the name of the user group or role for which to import the authentication key: - 請輸入要為其匯入身份驗證金鑰的使用者群組或角色的名稱: + 請選取要刪除的金鑰! Please select a key to export! @@ -420,34 +491,12 @@ If you're interested in translating Veyon into your local or another langua 請選擇要為其設定存取群組的金鑰! - Please perform the following steps to set up key file authentication: - 請執行以下步驟以設定金鑰檔身份驗證: - - - 1) Create a key pair on the master computer. - 1) 在主電腦上建立金鑰對。 - - - 2) Set an access group whose members should be allowed to access other computers. - 2) 設定一個存取群組,應該允許其成員存取其它電腦。 - - - 3) Export the public key and import it on all client computers with the same name. - 3) 匯出公開金鑰並將其匯入到具有相同名稱的所有用戶端電腦上。 - - - Please refer to the <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon Administrator Manual</a> for more information. - 有關詳細資訊,請參閱 <a href="https://veyon.readthedocs.io/en/latest/admin/index.html">Veyon 管理員手冊</a>。 - - - An authentication key pair consist of two coupled cryptographic keys, a private and a public key. -A private key allows users on the master computer to access client computers. -It is important that only authorized users have read access to the private key file. -The public key is used on client computers to authenticate incoming connection request. - 身份驗證金鑰配對由兩個耦合的加密金鑰,一個私有金鑰和一個公開金鑰組成。 -私密金鑰允許主機電腦上的使用者存取用戶端電腦。 -重要的是,只有授權使用者才能對私密金鑰檔進行讀取存取。 -公開金鑰用於用戶端電腦以驗證傳入連線請求。 + Please enter the name of the user group or role for which to import the authentication key. + +Make sure that the names of the keys belonging to each other are identical on all computers. + 請輸入要為其匯入身份驗證金鑰的使用者群組或角色的名稱。 + +確認所有電腦上彼此所屬的金鑰名稱相同。 @@ -502,7 +551,7 @@ The public key is used on client computers to authenticate incoming connection r Failed to write output file. - 無法寫入輸出檔案。 + 寫入輸出檔案失敗。 Key "%1/%2" has been exported to "%3" successfully. @@ -641,16 +690,12 @@ The public key is used on client computers to authenticate incoming connection r This command imports the authentication key <KEY> from <FILE>. If <FILE> is not specified a name will be constructed from name and type of <KEY>. - 這個命令從 <FILE> 匯入驗證金鑰 <KEY>。 如果沒有指定 <FILE>,將根據 <KEY> 的名稱和類型構造名稱。 + 這個命令從 <FILE> 匯入身分驗證金鑰 <KEY>。 如果未指定 <FILE>,則名稱將從 <KEY> 的名稱和類型構造。 This command lists all available authentication keys in the configured key directory. If the option "%1" is specified a table with key details will be displayed instead. Some details might be missing if a key is not accessible e.g. due to the lack of read permissions. 這個命令列出組態的金鑰目錄中所有可用的驗證金鑰。 如果有指定選項「%1」,則會顯示包含金鑰詳細資料的表格。 如果無法存取金鑰,某些詳細資料可能會遺失,例如: 由於缺乏讀取權限。 - - Please specify the command to display help for! - 請指定顯示說明的命令! - TYPE 類型 @@ -659,10 +704,6 @@ The public key is used on client computers to authenticate incoming connection r PAIR ID 配對 ID - - Command line support for managing authentication keys - 管理驗證金鑰的命令列支援 - Commands for managing authentication keys 管理驗證金鑰的命令 @@ -679,6 +720,30 @@ The public key is used on client computers to authenticate incoming connection r This command extracts the public key part from the private key <KEY> and saves it as the corresponding public key. When setting up another master computer, it is therefore sufficient to transfer the private key only. The public key can then be extracted. 這個命令從私密金鑰 <KEY> 中提取公開金鑰部分,並將其儲存為相應的公開金鑰。 因此,在設定另一部主機電腦時,只需要傳輸私密金鑰。接著可以提取公開金鑰。 + + Authentication key files are not set up properly on this computer. Please create new key files or switch to a different authentication method using the Veyon Configurator. + 在這部電腦上未正確組態身份驗證金鑰檔。 請建立新金鑰檔或使用 Veyon 組態器切換到其它身份驗證方法。 + + + Key file authentication + 金鑰檔身份驗證 + + + Key file + 金鑰檔 + + + Please specify the key name (e.g. "teacher/public") as the first argument. + 請指定金鑰名稱 (例如: "teacher/public") 作為第一個引數。 + + + Please specify the command to display help for. + 請指定顯示說明的命令。 + + + The specified command does not exist or no help is available for it. + 指定的命令不存在或沒有它的說明可以使用。 + AuthKeysTableModel @@ -700,105 +765,248 @@ The public key is used on client computers to authenticate incoming connection r - BuiltinDirectoryConfigurationPage + AuthLdapConfigurationWidget - Computers - 電腦 + General + 一般 - Name - 名稱 + Username to bind DN mapping: + 繫結 DN 對應的使用者名稱: - Host address/IP - 主機位址/IP + e.g. %username%@DOMAIN or cn=%username%,ou=users,dc=example,dc=org + 例如: %username%@DOMAIN 或 cn=%username%,ou=users,dc=example,dc=org + + + AuthLdapDialog - MAC address - MAC 位址 + Veyon Logon + Veyon 登入 - Add new computer - 加入新的電腦 + Please enter your domain/LDAP username and password in order to access computers. + 請輸入您的網域/LDAP使用者名稱和密碼以便存取電腦。 - Remove selected computer - 移除選取的電腦 + Username + 使用者名稱 - New computer - 新電腦 + Password + 密碼 - Builtin directory - 內建目錄 + Authentication error + 身份驗證錯誤 - Locations & computers - 位置 & 電腦 + Logon failed with given username and password. Please try again! + 以給予的使用者名稱和密碼登入失敗。 請再試一次! + + + AuthLogonDialog - Locations - 位置 + Veyon Logon + Veyon 登入 - Add new location - 加入新位置 + Please enter your username and password in order to access computers. + 請輸入您的使用者名稱和密碼才能存取電腦。 - Remove selected location - 刪除選取的位置 + Username + 使用者名稱 - The import of CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. - 可以通過命令列介面匯入 CSV 檔。 有關詳細資訊,請參閱 <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">線上文件</a>。 + Password + 密碼 - New location - 新位置 + Authentication error + 身份驗證錯誤 + + + Logon failed with given username and password. Please try again! + 以給予的使用者名稱和密碼登入失敗。 請再試一次! - BuiltinDirectoryPlugin + AuthLogonPlugin - Show help for specific command - 顯示指定命令的說明 + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + 提供的使用者名稱或密碼錯誤。 請輸入有效的認證或使用 Veyon 組態器切換到其它身份驗證方法。 - Import objects from given file - 從給予的檔案匯入物件 + Logon authentication + 登入驗證 - Export objects to given file - 匯出物件到給予的檔案 + Logon + 登入 + + + AuthSimpleDialog - Invalid type specified. Valid values are "%1" or "%2". - 指定的類型無效。 有效值 "%1" 或 "%2". + Veyon Logon + Veyon 登入 - Type - 類型 + Please enter the Veyon password: + 請輸入 Veyon 密碼: - Name - 名稱 + Authentication error + 身份驗證錯誤 - Host address - 主機位址 + Logon failed with given password. Please try again! + 使用給予的密碼登入失敗。 請重試! + + + AuthSimplePlugin - MAC address - MAC 位址 + The supplied password is wrong. Please enter the correct password or switch to a different authentication method using the Veyon Configurator. + 提供的密碼錯誤。 請輸入正確的密碼或使用 Veyon 組態器切換到其它身份驗證方法。 - Specified object not found. - 找不到指定的物件。 + Simple password authentication + 簡單密碼身份驗證 - File "%1" does not exist! - 檔案 "%1" 不存在! + Simple password + 簡單密碼 + + + + AuthenticationPage + + Authentication is set up properly on this computer. + 在這部電腦中正確設定身份驗證。 + + + + AuthenticationPageTab + + Enabled + 啟用 + + + Test + 測試 + + + + BuiltinDirectoryConfiguration + + Builtin directory + 內建目錄 + + + + BuiltinDirectoryConfigurationPage + + Computers + 電腦 + + + Name + 名稱 + + + Host address/IP + 主機位址/IP + + + MAC address + MAC 位址 + + + Add new computer + 加入新的電腦 + + + Remove selected computer + 移除選取的電腦 + + + New computer + 新電腦 + + + Builtin directory + 內建目錄 + + + Locations + 位置 + + + Add new location + 加入新位置 + + + Remove selected location + 移除選取的位置 + + + New location + 新位置 + + + Directory name + 目錄名稱 + + + Importing CSV files is possible through the command line interface. For more information, see the <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">online documentation</a>. + 可以透過命令列界面匯入 CSV 檔案。 更多資訊,請參閱 <a href="https://docs.veyon.io/en/latest/admin/cli.html#network-object-directory">線上文件</a>。 + + + + BuiltinDirectoryPlugin + + Show help for specific command + 顯示指定命令的說明 + + + Import objects from given file + 從給予的檔案匯入物件 + + + Export objects to given file + 匯出物件到給予的檔案 + + + Invalid type specified. Valid values are "%1" or "%2". + 指定的類型無效。 有效值 "%1" 或 "%2"。 + + + Type + 類型 + + + Name + 名稱 + + + Host address + 主機位址 + + + MAC address + MAC 位址 + + + Specified object not found. + 找不到指定的物件。 + + + File "%1" does not exist! + 檔案 "%1" 不存在! Can't open file "%1" for reading! @@ -1000,6 +1208,14 @@ The public key is used on client computers to authenticate incoming connection r MAC ADDRESS MAC 位址 + + The specified command does not exist or no help is available for it. + 指定的命令不存在或沒有它的說明可以使用。 + + + Location "%1" not found. + 找不到位置 "%1"。 + BuiltinUltraVncServer @@ -1017,10 +1233,6 @@ The public key is used on client computers to authenticate incoming connection r ComputerControlListModel - - Host/IP address: %1 - 主機/IP 位址: %1 - Active features: %1 可用功能: %1 @@ -1037,13 +1249,9 @@ The public key is used on client computers to authenticate incoming connection r Computer offline or switched off 電腦離線或關機 - - Service unreachable or not running - 服務無法存取或未執行 - Authentication failed or access denied - 驗證失敗或存取拒絕 + 身份驗證失敗或存取拒絕 Disconnected @@ -1061,16 +1269,48 @@ The public key is used on client computers to authenticate incoming connection r Location: %1 位置: %1 + + [no user] + [沒有使用者] + + + Veyon Server unreachable or not running + Veyon 伺服器無法存取或未執行 + + + Name: %1 + 名稱: %1 + + + Hostname: %1 + 主機名稱: %1 + + + unknown + 未知 + + + IP address: %1 + IP 位址: %1 + + + Hostname could not be resolved + 無法解析主機名稱 + + + No features active + 沒有功能啟用 + ComputerControlServer %1 Service %2 at %3:%4 - %1 服務 %2 在 %3: %4 + %1 服務 %2 在 %3:%4 Authentication error - 驗證錯誤 + 身份驗證錯誤 Remote access @@ -1092,6 +1332,17 @@ The public key is used on client computers to authenticate incoming connection r User "%1" at host "%2" attempted to access this computer but has been blocked due to access control settings. 主機 "%2" 的使用者 "%1" 嘗試存取這部電腦,但因為存取控制設定已封鎖。 + + Active connections: + 使用中連線: + + + + ComputerGroupSelector + + Group %1 + 群組 %1 + ComputerManager @@ -1105,7 +1356,7 @@ The public key is used on client computers to authenticate incoming connection r No default network object directory plugin was found. Please check your installation or configure a different network object directory backend via %1 Configurator. - 找不到預設網路物件目錄外掛程式。 請檢查您的安裝或透過 %1 組態器設定不同的網路物件目錄後台。 + 找不到預設網路物件目錄外掛程式。 請檢查您的安裝或透過 %1 組態器設定不同的網路物件目錄後端。 Location detection failed @@ -1119,13 +1370,48 @@ The public key is used on client computers to authenticate incoming connection r Could not determine the location of this computer. This indicates a problem with the system configuration. All locations will be shown in the computer select panel instead. 無法確定這部電腦的位置。 這表示系統組態有問題。 所有位置將顯示在電腦選取面板中。 + + Logged in since + 登入自 + + + %1 days + %1 天 + + + 1 day + 1 天 + - ComputerSelectPanel + ComputerMonitoring + + Computers + 電腦 + + + Search users and computers + 搜尋使用者和電腦 + + + Select all + 全選 + + + Unselect all + 全部不選 + + + Add to group + 加入到群組 + - Computer management - 電腦管理 + Remove from group + 從群組移除 + + + ComputerSelectPanel Computer search 電腦搜尋 @@ -1140,7 +1426,7 @@ The public key is used on client computers to authenticate incoming connection r Select output filename - 選擇輸出檔案名稱 + 選取輸出檔案名稱 CSV files (*.csv) @@ -1154,81 +1440,85 @@ The public key is used on client computers to authenticate incoming connection r Could not write the computer and users list to %1! Please check the file access permissions. 無法寫入電腦和使用者清單到 %1! 請檢查檔案的存取權限。 + + Search computers + 搜尋電腦 + - ConfigCommandLinePlugin + ConfigCommands - Please specify an existing configuration file to import. - 請指定要匯入的現有組態檔。 + Clear system-wide Veyon configuration + 清除系統範圍 Veyon 組態 - Please specify a valid filename for the configuration export. - 請指定一個有效的檔案名稱作為組態匯出。 + List all configuration keys and values + 列出所有組態金鑰和數值 - Please specify a valid key. - 請指定一個有效的金鑰。 + Import configuration from given file + 從給予的檔案匯入組態 - Specified key does not exist in current configuration! - 在目前組態中指定的金鑰不存在! + Export configuration to given file + 匯出組態到給予的檔案 - Please specify a valid value. - 請指定一個有效的值。 + Read and output configuration value for given key + 讀取和輸出給予金鑰的組態值 - Configure Veyon at command line - 在命令列上組態 Veyon + Write given value to given configuration key + 寫入給予的數值到給予的組態金鑰 - Output file is not writable! - 輸出檔案無法寫入! + Unset (remove) given configuration key + 取消設定 (移除) 給予的組態金鑰 - Output directory is not writable! - 輸出目錄無法寫入! + Upgrade and save configuration of program and plugins + 升級並儲存程式及外掛程式的組態 + + + Please specify an existing configuration file to import. + 請指定要匯入的現有組態檔。 Configuration file is not readable! 組態檔無法讀取! - Clear system-wide Veyon configuration - 清除系統範圍 Veyon 組態 + Please specify a valid filename for the configuration export. + 請指定一個有效的檔案名稱作為組態匯出。 - List all configuration keys and values - 列出所有組態金鑰和數值 + Output file is not writable! + 輸出檔案無法寫入! - Import configuration from given file - 從給予的檔案匯入組態 + Output directory is not writable! + 輸出目錄無法寫入! - Export configuration to given file - 匯出組態到給予的檔案 + Please specify a valid key. + 請指定一個有效的金鑰。 - Read and output configuration value for given key - 讀取和輸出給予金鑰的組態值 + Specified key does not exist in current configuration! + 在目前組態中指定的金鑰不存在! - Write given value to given configuration key - 寫入給予的數值到給予的組態金鑰 + Please specify a valid value. + 請指定一個有效的值。 - Unset (remove) given configuration key - 取消設定 (移除) 給予的組態金鑰 + Configure Veyon at command line + 在命令列上組態 Veyon Commands for managing the configuration of Veyon 管理 Veyon 組態的命令 - - Upgrade and save configuration of program and plugins - 升級並儲存程式及外掛的組態 - ConfigurationManager @@ -1252,19 +1542,23 @@ The public key is used on client computers to authenticate incoming connection r Could not apply platform-specific configuration settings. 無法套用特定平臺的組態設定。 + + Could not configure the firewall configuration for the %1 Service. + 無法組態 %1 服務的防火牆設定。 + DemoClient %1 Demo - %1 展示 + %1 演示 DemoConfigurationPage Demo server - 展示伺服器 + 演示伺服器 Tunables @@ -1282,10 +1576,6 @@ The public key is used on client computers to authenticate incoming connection r Memory limit 記憶體限制 - - Use multithreading (experimental) - 使用多執行緒 (實驗性) - MB MB @@ -1300,42 +1590,90 @@ The public key is used on client computers to authenticate incoming connection r Slow down thumbnail updates while demo is running - 展示執行時,縮圖更新速度變慢 + 演示執行時,縮圖更新速度變慢 + + + Bandwidth limit + 頻寬限制 + + + MB/s + MB/秒 DemoFeaturePlugin - - Fullscreen demo - 全螢幕展示 - Stop demo - 停止展示 + 停止演示 Window demo - 視窗展示 + 視窗演示 Give a demonstration by screen broadcasting - 通過螢幕廣播給予展示 + 透過螢幕廣播給予演示 - Demo server - 展示伺服器 + In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. + 在這個模式下,所有電腦上的畫面都以視窗顯示,使用者可以視需要切換到其它視窗。 - In this mode your screen is being displayed in fullscreen mode on all computers while input devices of the users are locked. - 在這個模式下,所有電腦上的畫面都以全螢幕模式顯示,使用者的輸入裝置鎖定。 + Demo + 演示 - In this mode your screen being displayed in a window on all computers. The users are able to switch to other windows as needed. - 在這個模式下,所有電腦上的畫面都以視窗顯示,使用者可以視需要切換到其它視窗。 + Share your screen or allow a user to share his screen with other users. + 共用螢幕或允許使用者與其他使用者共用其螢幕。 - - - DesktopAccessDialog + + Full screen demo + 全螢幕演示 + + + Share your own screen in fullscreen mode + 以全螢幕模式共用您自己的螢幕 + + + In this mode your screen is being displayed in full screen mode on all computers while the input devices of the users are locked. + 在此模式下,使用者的輸入裝置鎖定時,您的螢幕以全螢幕模式在所有電腦上顯示。 + + + Share your own screen in a window + 在視窗共用您自己的螢幕 + + + Share selected user's screen in fullscreen mode + 以全螢幕模式共用選取使用者的螢幕 + + + In this mode the screen of the selected user is being displayed in full screen mode on all computers while the input devices of the users are locked. + 在此模式下,使用者的輸入裝置鎖定時,選取使用者的螢幕以全螢幕模式在所有電腦上顯示。 + + + Share selected user's screen in a window + 在視窗共用選取使用者的螢幕 + + + In this mode the screen of the selected user being displayed in a window on all computers. The users are able to switch to other windows as needed. + 在此模式下,選取使用者的螢幕顯示在所有電腦的視窗中。 使用者能夠根據需要切換到其它視窗。 + + + Please select a user screen to share. + 請選取要共用的使用者螢幕。 + + + Please select only one user screen to share. + 請只選取一個使用者螢幕進行共用。 + + + All screens + 所有螢幕 + + + + DesktopAccessDialog Desktop access dialog 桌面存取對話方塊 @@ -1359,14 +1697,6 @@ The public key is used on client computers to authenticate incoming connection r DesktopServicesConfigurationPage - - Programs & websites - 程式 & 網站 - - - Predefined programs - 預先定義程式 - Name 名稱 @@ -1375,14 +1705,6 @@ The public key is used on client computers to authenticate incoming connection r Path 路徑 - - Add new program - 加入新的程式 - - - Remove selected program - 移除所選程式 - Predefined websites 預先定義網站 @@ -1395,21 +1717,37 @@ The public key is used on client computers to authenticate incoming connection r URL URL - - New program - 新程式 - New website 新網站 + + Applications & websites + 應用程式 & 網站 + + + Predefined applications + 預先定義應用程式 + + + Add new application + 新增應用程式 + + + Remove selected application + 移除選取的應用程式 + + + Add new website + 新增網站 + + + New application + 新應用程式 + DesktopServicesFeaturePlugin - - Run program - 執行程式 - Open website 開啟網站 @@ -1419,28 +1757,32 @@ The public key is used on client computers to authenticate incoming connection r 按一下這個按鈕可以在所有電腦上開啟一個網站。 - Start programs and services in user desktop - 啟動程式和服務在使用者桌面 + Open website "%1" + 開啟網站 "%1" - Click this button to run a program on all computers. - 按一下這個按鈕可以在所有電腦上執行一個程式。 + Custom website + 自訂網站 - Run program "%1" - 執行程式 "%1" + Start application + 啟動應用程式 - Custom program - 自訂程式 + Click this button to start an application on all computers. + 按一下這個按鈕以在所有電腦啟動一個應用程式。 - Open website "%1" - 開啟網站 "%1" + Start application "%1" + 啟動應用程式 "%1" - Custom website - 自訂網站 + Custom application + 自訂應用程式 + + + Start apps and open websites in user sessions + 啟動應用程式和開啟網站在使用者工作階段 @@ -1455,7 +1797,7 @@ The public key is used on client computers to authenticate incoming connection r Please complete all tasks within the next 5 minutes. - 請在接下來的 5 分鐘內完成所有任務。 + 請在接下來的 5 分鐘內完成所有工作。 Custom website @@ -1471,19 +1813,23 @@ The public key is used on client computers to authenticate incoming connection r Play tutorial video - 播放教程視訊 - - - Custom program - 自訂程式 + 播放指南視訊 Handout - + 講義 Texts to read - + 要閱讀的文字 + + + generic-student-user + 通用學生使用者 + + + Custom application + 自訂應用程式 @@ -1509,10 +1855,165 @@ The public key is used on client computers to authenticate incoming connection r - FeatureControl + FeatureCommands + + List names of all available features + 列出所有可用功能的名稱 + + + Show table with details of all available features + 顯示含所有可用功能的詳細資訊表格 + + + Start a feature on a remote host + 啟動遠端主機功能 + + + Stop a feature on a remote host + 停止遠端主機功能 + + + Please specify the command to display help for. + 請指定顯示說明的命令。 + + + Displays a list with the names of all available features. + 顯示包含所有可用功能名稱的清單。 + + + Displays a table with detailed information about all available features. This information include a description, the UID, the name of the plugin providing the respective feature and some other implementation-related details. + 顯示表格,其中包含有關所有可用功能的詳細資料。 這個資訊包含描述、UID、提供相應功能的外掛程式名稱以及其它一些與實現相關的詳細資料。 + + + HOST ADDRESS + 主機位址 + + + FEATURE + 功能 + + + ARGUMENTS + 引數 + + + Starts the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. Depending on the feature, additional arguments (such as the text message to display) encoded as a single JSON string have to be specified. Please refer to the developer documentation for more information + 透過連線到遠端執行的 Veyon 伺服器來啟動指定主機的指定功能。 該功能可以由名稱或 UID 指定。 使用「show」命令查看所有的可用功能。 根據功能,必須指定編碼為單一 JSON 字串的附加引數 (比如顯示的文字訊息)。 請參閱開發人員文件取得更多資訊 + + + Lock the screen + 鎖定畫面 + + + Display a text message + 顯示文字資訊 + + + Test message + 測試文字 + + + Start an application + 啟動應用程式 + + + Stops the specified feature on the specified host by connecting to the Veyon Server running remotely. The feature can be specified by name or UID. Use the ``show`` command to see all available features. + 透過連線到遠端執行的 Veyon 伺服器來停止指定主機的指定功能。 該功能可以由名稱或 UID 指定。 使用「show」命令查看所有的可用功能。 + + + Unlock the screen + 解鎖畫面 + + + The specified command does not exist or no help is available for it. + 指定的命令不存在或沒有它的說明可以使用。 + + + Name + 名稱 + + + Description + 描述 + + + Master + 主要 + + + Service + 服務 + + + Worker + Worker + + + UID + UID + + + Plugin + 外掛程式 + + + Invalid feature name or UID specified + 功能名稱或指定的 UID 無效 + + + Error parsing the JSON-encoded arguments: %1 + 解析 JSON 編碼的參數時錯誤: %1 + + + Failed to initialize credentials + 初始化認證失敗 + + + Could not establish a connection to host %1 + 無法建立到主機 %1 的連線 + + + Failed to send feature control message to host %1 + 向主機 %1 傳送功能控制訊息失敗 + + + Feature-related CLI operations + 功能相關的 CLI 操作 + + + Commands for controlling features + 用於控制功能的命令 + + + + FileTransferConfigurationPage + + File transfer + 檔案傳輸 + + + Directories + 目錄 + + + Destination directory + 目的地目錄 + + + Default source directory + 預設來源目錄 + + + Options + 選項 + + + Remember last source directory + 記住上次來源目錄 + - Feature control - 功能控制 + Create destination directory if it does not exist + 如果目的地目錄不存在則建立 @@ -1557,6 +2058,13 @@ The public key is used on client computers to authenticate incoming connection r 覆寫現有檔案 + + FileTransferFileDialog + + Select one or more files to transfer + 選擇要傳輸的一個或多個檔案 + + FileTransferPlugin @@ -1614,10 +2122,6 @@ The public key is used on client computers to authenticate incoming connection r Log file directory 紀錄檔目錄 - - ... - ... - Log level 紀錄等級 @@ -1658,18 +2162,6 @@ The public key is used on client computers to authenticate incoming connection r Log to standard error output 紀錄到標準錯誤輸出 - - Network object directory - 網路物件目錄 - - - Backend: - 後台: - - - Update interval: - 更新間隔: - %1 service %1 服務 @@ -1706,103 +2198,80 @@ The public key is used on client computers to authenticate incoming connection r x x - - seconds - - Write to logging system of operating system 寫入到作業系統的記錄系統 - Authentication - 身份驗證 - - - Method: - 方式: - - - Logon authentication - 登入驗證 - - - Key file authentication - 金鑰檔身分驗證 - - - Test - 測試 + TLS configuration + TLS 組態 - Authentication is set up properly on this computer. - 在這部電腦中正確設定身份驗證。 + Use certificate authority for TLS connections + TLS 連線使用憑證頒發機構 - Authentication keys are not set up properly on this computer. - 這部電腦中的身份驗證金鑰設定不正確。 + CA certificate file + 憑證檔 - Authentication test - 身份驗證測試 + ... + ... - - - InternetAccessControlConfigurationPage - Internet access control - Internet 存取控制 + Host certificate file + 主機憑證檔 - Backend: - 後台: + Host private key file + 主機私密金鑰檔 - General settings - 一般設定 + Style: + 樣式: - Backend settings - 後台設定 + Native + 原生 - - - InternetAccessControlPlugin - Block access to the internet - 封鎖存取 internet + Color scheme: + 色彩架構: - Allow access to the internet - 允許存取到 internet + Light + 淺色 - Show help about command - 顯示命令的說明 + Dark + 深色 - Block internet - 封鎖 internet + User groups + 使用者群組 - Click this button to block access to the internet. - 按一下這個按鈕以封鎖存取到 internet。 + Backend: + 後端: - Unblock internet - 取消封鎖 internet + Include user groups from domain + 包含網域中的使用者群組 - Click this button to allow access to the internet. - 按一下這個按鈕以允許存取到 internet。 + Missing user groups backend + 缺少使用者群組後端 - Control access to the internet - 控制存取 internet + No user groups plugin was found. Please check your installation! + 找不到使用者群組外掛程式。 請檢查您的安裝! + + + HeadlessVncServer - Commands for controlling access to the internet - 控制存取 internet 的命令 + Headless VNC server + 無標題 VNC 伺服器 @@ -1820,344 +2289,527 @@ The public key is used on client computers to authenticate incoming connection r - LdapConfigurationPage + LdapConfiguration - Basic settings - 基本設定 + LDAP connection failed + LDAP 連線失敗 - General - 一般 + Could not connect to the LDAP server. Please check the server parameters. + +%1 + 無法連接到 LDAP 伺服器。 請檢查伺服器參數。 + +%1 - LDAP server and port - LDAP 伺服器和埠 + LDAP bind failed + LDAP 繫結失敗 - Bind DN - 綁定 DN + Could not bind to the LDAP server. Please check the server parameters and bind credentials. + +%1 + 無法繫結到 LDAP 伺服器。 請檢查伺服器參數並繫結認證。 + +%1 - Bind password - 綁定密碼 + LDAP bind successful + LDAP 繫結成功 - Anonymous bind - 匿名綁定 + Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. + 成功地連接到 LDAP 伺服器並執行 LDAP 繫結。 基本的 LDAP 設定正確組態。 - Use bind credentials - 使用綁定認證 + LDAP base DN test failed + LDAP 基礎 DN 測試失敗 - Base DN - 基礎 DN + Could not query the configured base DN. Please check the base DN parameter. + +%1 + 無法查詢組態的基礎 DN。 請檢查基礎 DN 參數。 + +%1 - Fixed base DN - 固定的基礎 DN + LDAP base DN test successful + LDAP 基礎 DN 測試成功 - e.g. dc=example,dc=org - 例如: dc=example,dc=org + The LDAP base DN has been queried successfully. The following entries were found: + +%1 + LDAP 基礎 DN 已成功查詢。 找到以下項目: + +%1 - Discover base DN by naming context - 以命名內容探索基礎 DN + LDAP naming context test failed + LDAP 命名內容測試失敗 - e.g. namingContexts or defaultNamingContext - 例如: namingCoNtexts 或 defaultNamingCoNtext + Could not query the base DN via naming contexts. Please check the naming context attribute parameter. + +%1 + 無法透過命名內容查詢基礎 DN。 請檢查命名內容屬性參數。 + +%1 - Environment settings - 環境設定 + LDAP naming context test successful + LDAP 命名內容測試成功 - Object trees - 物件樹 + The LDAP naming context has been queried successfully. The following base DN was found: +%1 + 查詢 LDAP 命名內容成功。 找到以下基礎 DN: +%1 + + + user tree + 使用者樹 + + + User tree + 使用者樹 + + + group tree + 群組樹 + + + Group tree + 群組樹 + + + computer tree + 電腦樹 Computer tree 電腦樹 - e.g. OU=Groups - 例如: OU=群組 + computer group tree + 電腦群組樹 - User tree - 使用者樹 + Computer group tree + 電腦群組樹 - e.g. OU=Users - 例如: OU=使用者 + user objects + 使用者物件 - e.g. OU=Computers - 例如: OU=電腦 + User login name attribute + 使用者登入名稱屬性 - Group tree - 群組樹 + group members + 群組成員 - Perform recursive search operations in object trees - 在物件樹中執行遞迴搜尋操作 + Group member attribute + 群組成員屬性 - Object attributes - 物件屬性 + Group not found + 找不到群組 - e.g. hwAddress - 例如: hwAddress + Could not find a group with the name "%1". Please check the group name or the group tree parameter. + 找不到名稱為「%1」的群組。 請檢查群組名稱或群組樹參數。 - e.g. member or memberUid - 例如: 成員或 memberUid + computer objects + 電腦物件 - e.g. dNSHostName - 例如: dNSHostName + Computer display name attribute + 電腦顯示名稱屬性 + + + Invalid hostname + 主機名稱無效 + + + You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. + 您將電腦主機名稱組態為以完全限定網域名稱 (FQDN) 存儲,但輸入了不含網域的主機名稱。 + + + You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. + 您將電腦主機名稱組態為以不含域名的簡單主機名稱存儲,但輸入了含有域名部分的主機名稱。 + + + Computer hostname attribute + 電腦主機名稱屬性 + + + computer MAC addresses + 電腦 MAC 位址 Computer MAC address attribute 電腦 MAC 位址屬性 - Group member attribute - 群組成員屬性 + computer locations + 電腦位置 - e.g. uid or sAMAccountName - 例如: uid 或 sAMAccountName + Computer location attribute + 電腦位置屬性 - Advanced settings - 進階設定 + Location name attribute + 位置名稱屬性 - Optional object filters - 可選的物件篩選器 + users + 使用者 - Filter for user groups - 使用者群組的篩選器 + user groups + 使用者群組 - Filter for users - 使用者的篩選器 + computers + 電腦 + + + computer groups + 電腦群組 + + + computer containers + 電腦容器 + + + groups of user + 使用者的群組 + + + User not found + 找不到使用者 + + + Could not find a user with the name "%1". Please check the username or the user tree parameter. + 找不到名為「%1」的使用者。 請檢查使用者名稱或使用者樹參數。 + + + groups of computer + 電腦的群組 + + + Computer not found + 找不到電腦 + + + Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. + 找不到主機名稱為「%1」的電腦。 請檢查主機名稱或電腦樹參數。 + + + Hostname lookup failed + 主機名稱尋找失敗 + + + Could not lookup hostname for IP address %1. Please check your DNS server settings. + 無法查找 IP 位址 %1 的主機名稱。 請檢查您的 DNS 伺服器設定。 + + + location entries + 位置項目 + + + Computer groups filter + 電腦群組篩選器 + + + Computer locations identification + 電腦位置識別 Filter for computer groups 電腦群組的篩選器 - Group member identification - 群組成員身份 + Invalid test value + 測試值無效 - Distinguished name (Samba/AD) - 可分辨名稱 (Samba/AD) + An empty or invalid value has been supplied for this test. + 這個測試提供空白或無效的值。 - List all groups of a user - 列出所有的使用者群組 + LDAP %1 test failed + LDAP %1 測試失敗 - List all groups of a computer - 列出所有電腦的群組 + Could not query any entries in configured %1. Please check the parameter "%2". + +%3 + 無法查詢組態的 %1 中的任何項目。 請檢查參數 "%2"。 + +%3 - Get computer object by IP address - 以 IP 位址取得電腦物件 + LDAP %1 test successful + LDAP %1 測試成功 - LDAP connection failed - LDAP 連線失敗 + The %1 has been queried successfully and %2 entries were found. + 查詢 %1 成功和找到 %2 個項目。 - LDAP bind failed - LDAP 綁定失敗 + LDAP test failed + LDAP 測試失敗 - LDAP bind successful - LDAP 綁定成功 + Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. + +%3 + 無法查詢任何 %1。 請檢查參數 %2 並輸入現有物件的名稱。 + +%3 - Successfully connected to the LDAP server and performed an LDAP bind. The basic LDAP settings are configured correctly. - 成功地連接到 LDAP 伺服器並執行 LDAP 綁定。 基本的 LDAP 設定正確組態。 + and + - LDAP base DN test failed - LDAP 基礎 DN 測試失敗 + LDAP test successful + LDAP 測試成功 - LDAP base DN test successful - LDAP 基礎 DN 測試成功 + %1 %2 have been queried successfully: + +%3 + %1 %2 查詢成功: + +%3 - LDAP naming context test failed - LDAP 命名內容測試失敗 + LDAP filter test failed + LDAP 篩選器測試失敗 - LDAP naming context test successful - LDAP 命名內容測試成功 + Could not query any %1 using the configured filter. Please check the LDAP filter for %1. + +%2 + 使用組態的篩選器無法查詢任何 %1。 請檢查 %1 的 LDAP 篩選器。 + +%2 - The LDAP naming context has been queried successfully. The following base DN was found: -%1 - 查詢 LDAP 命名內容成功。 找到以下基礎 DN: -%1 + LDAP filter test successful + LDAP 篩選器測試成功 - user tree - 使用者樹 + %1 %2 have been queried successfully using the configured filter. + %1 %2 使用組態的篩選器查詢成功。 - group tree - 群組樹 + LDAP directory + LDAP 目錄 + + + LdapConfigurationPage - computer tree - 電腦樹 + Basic settings + 基本設定 - Enter username - 輸入使用者名稱 + General + 一般 - Please enter a user login name (wildcards allowed) which to query: - 請輸入查詢的使用者登入名稱 (允許使用萬用字元): + LDAP server and port + LDAP 伺服器和埠 - user objects - 使用者物件 + Bind DN + 繫結 DN - Enter group name - 輸入群組名稱 + Bind password + 繫結密碼 - Please enter a group name whose members to query: - 請輸入查詢其成員的群組名稱: + Anonymous bind + 匿名繫結 - group members - 群組成員 + Use bind credentials + 使用繫結認證 - Group not found - 找不到群組 + Base DN + 基本 DN - Could not find a group with the name "%1". Please check the group name or the group tree parameter. - 找不到名稱為「%1」的群組。 請檢查群組名稱或群組樹參數。 + Fixed base DN + 固定的基礎 DN - Enter computer name - 輸入電腦名稱 + e.g. dc=example,dc=org + 例如: dc=example,dc=org - computer objects - 電腦物件 + Discover base DN by naming context + 以命名內容探索基礎 DN - Enter computer DN - 輸入電腦 DN + e.g. namingContexts or defaultNamingContext + 例如: namingCoNtexts 或 defaultNamingCoNtext - Please enter the DN of a computer whose MAC address to query: - 請輸入查詢其 MAC 位址的電腦 DN : + Environment settings + 環境設定 - computer MAC addresses - 電腦 MAC 位址 + Object trees + 物件樹 - users - 使用者 + Computer tree + 電腦樹 - user groups - 使用者群組 + e.g. OU=Groups + 例如: OU=群組 - computer groups - 電腦群組 + User tree + 使用者樹 - Please enter a user login name whose group memberships to query: - 請輸入查詢其群組成員的使用者登入名稱: + e.g. OU=Users + 例如: OU=使用者 - groups of user - 使用者的群組 + e.g. OU=Computers + 例如: OU=電腦 - User not found - 找不到使用者 + Group tree + 群組樹 - groups of computer - 電腦的群組 + Perform recursive search operations in object trees + 在物件樹中執行遞迴搜尋操作 - Computer not found - 找不到電腦 + Object attributes + 物件屬性 - Enter computer IP address - 輸入電腦 IP 位址 + e.g. hwAddress + 例如: hwAddress - Please enter a computer IP address which to resolve to an computer object: - 請輸入電腦的 IP 位址,解析為一個電腦物件: + e.g. member or memberUid + 例如: 成員或 memberUid - computers - 電腦 + e.g. dNSHostName + 例如: dNSHostName - LDAP %1 test failed - LDAP %1 測試失敗 + Computer MAC address attribute + 電腦 MAC 位址屬性 - LDAP %1 test successful - LDAP %1 測試成功 + Group member attribute + 群組成員屬性 - The %1 has been queried successfully and %2 entries were found. - 查詢 %1 成功和找到 %2 個項目。 + e.g. uid or sAMAccountName + 例如: uid 或 sAMAccountName - %1 %2 have been queried successfully: - -%3 - %1 %2 查詢成功: - -%3 + Advanced settings + 進階設定 + + + Optional object filters + 可選的物件篩選器 + + + Filter for user groups + 使用者群組的篩選器 + + + Filter for users + 使用者的篩選器 + + + Filter for computer groups + 電腦群組的篩選器 + + + Group member identification + 群組成員身份 + + + Distinguished name (Samba/AD) + 可分辨名稱 (Samba/AD) + + + List all groups of a user + 列出所有的使用者群組 + + + List all groups of a computer + 列出所有電腦的群組 + + + Get computer object by IP address + 以 IP 位址取得電腦物件 + + + Enter username + 輸入使用者名稱 + + + Please enter a user login name (wildcards allowed) which to query: + 請輸入查詢的使用者登入名稱 (允許萬用字元): + + + Enter group name + 輸入群組名稱 + + + Please enter a group name whose members to query: + 請輸入查詢其成員的群組名稱: + + + Enter computer name + 輸入電腦名稱 - LDAP filter test failed - LDAP 篩選器測試失敗 + Enter computer DN + 輸入電腦 DN - Could not query any %1 using the configured filter. Please check the LDAP filter for %1. - -%2 - 使用組態的篩選器無法查詢任何 %1。 請檢查 %1 的 LDAP 篩選器。 - -%2 + Please enter the DN of a computer whose MAC address to query: + 請輸入查詢其 MAC 位址的電腦 DN: - LDAP filter test successful - LDAP 篩選器測試成功 + Please enter a user login name whose group memberships to query: + 請輸入查詢其群組成員的使用者登入名稱: - %1 %2 have been queried successfully using the configured filter. - %1 %2 使用組態的篩選器查詢成功。 + Enter computer IP address + 輸入電腦 IP 位址 + + + Please enter a computer IP address which to resolve to an computer object: + 請輸入電腦的 IP 位址,解析為一個電腦物件: (only if different from group tree) @@ -2167,10 +2819,6 @@ The public key is used on client computers to authenticate incoming connection r Computer group tree 電腦群組樹 - - computer group tree - 電腦群組樹 - Filter for computers 電腦的篩選器 @@ -2251,50 +2899,10 @@ The public key is used on client computers to authenticate incoming connection r e.g. (objectClass=container) or (objectClass=organizationalUnit) 例如: (objectClass=container) 或 (objectClass=organizationalUnit) - - Could not query the configured base DN. Please check the base DN parameter. - -%1 - 無法查詢組態的基礎 DN。 請檢查基礎 DN 參數。 - -%1 - - - The LDAP base DN has been queried successfully. The following entries were found: - -%1 - LDAP 基礎 DN 已成功查詢。 找到以下項目: - -%1 - - - Could not query the base DN via naming contexts. Please check the naming context attribute parameter. - -%1 - 無法透過命名內容查詢基礎 DN。 請檢查命名內容屬性參數。 - -%1 - Certificate files (*.pem) 憑證檔 (*.pem) - - Could not connect to the LDAP server. Please check the server parameters. - -%1 - 無法連接到 LDAP 伺服器。 請檢查伺服器參數。 - -%1 - - - Could not bind to the LDAP server. Please check the server parameters and bind credentials. - -%1 - 無法綁定到 LDAP 伺服器。 請檢查伺服器參數並綁定認證。 - -%1 - Encryption protocol 加密協定 @@ -2336,387 +2944,154 @@ The public key is used on client computers to authenticate incoming connection r 列出所有位置 - Enter computer display name - 輸入電腦顯示名稱 - - - Please enter a computer display name to query: - 請輸入要查詢的電腦顯示名稱: - - - Enter computer location name - 輸入電腦位置名稱 - - - Please enter the name of a computer location (wildcards allowed): - 請輸入電腦位置的名稱 (允許萬用字元): - - - computer locations - 電腦位置 - - - Enter location name - 輸入位置名稱 - - - Please enter the name of a location whose entries to query: - 請輸入要查詢其項目的位置名稱: - - - location entries - 位置項目 - - - LDAP test failed - LDAP 測試失敗 - - - Could not query any %1. Please check the parameter(s) %2 and enter the name of an existing object. - -%3 - 無法查詢任何 %1。 請檢查參數 %2 並輸入現有物件的名稱。 - -%3 - - - and - - - - LDAP test successful - LDAP 測試成功 - - - Could not query any entries in configured %1. Please check the parameter "%2". - -%3 - 無法查詢組態的 %1 中的任何項目。 請檢查參數 "%2"。 - -%3 - - - Browse - 瀏覽 - - - Test - 測試 - - - Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) - 主機名稱存儲為完全限定網域名稱 (FQDN, 例如: myhost.example.org) - - - Computer hostname attribute - 電腦主機名稱屬性 - - - Please enter a computer hostname to query: - 請輸入要查詢的電腦主機名稱: - - - Invalid hostname - 主機名稱無效 - - - You configured computer hostnames to be stored as fully qualified domain names (FQDN) but entered a hostname without domain. - 您將電腦主機名組態為以完全限定網域名稱 (FQDN) 存儲,但輸入了不含網域的主機名稱。 - - - You configured computer hostnames to be stored as simple hostnames without a domain name but entered a hostname with a domain name part. - 您將電腦主機名組態為以不含域名的簡單主機名稱存儲,但輸入了含有域名部分的主機名稱。 - - - Could not find a user with the name "%1". Please check the username or the user tree parameter. - 找不到名為「%1」的使用者。 請檢查使用者名稱或使用者樹參數。 - - - Enter hostname - 輸入主機名稱 - - - Please enter a computer hostname whose group memberships to query: - 請輸入要查詢其群組成員身份的電腦主機名稱: - - - Could not find a computer with the hostname "%1". Please check the hostname or the computer tree parameter. - 找不到主機名稱為「%1」的電腦。請檢查主機名稱或電腦樹參數。 - - - Hostname lookup failed - 主機名稱查找失敗 - - - Could not lookup hostname for IP address %1. Please check your DNS server settings. - 無法查找 IP 位址 %1 的主機名稱。 請檢查您的 DNS 伺服器設定。 - - - User login name attribute - 使用者登入名稱屬性 - - - Configured attribute for user login name or computer hostname (OpenLDAP) - 為使用者登入名稱或電腦主機名稱組態的屬性 (OpenLDAP) - - - computer containers - 電腦容器 - - - - LdapPlugin - - Auto-configure the base DN via naming context - 透過命名內文自動組態基礎 DN - - - Query objects from LDAP directory - 從 LDAP 目錄查詢物件 - - - Show help about command - 顯示命令的說明 - - - Commands for configuring and testing LDAP/AD integration - 組態和測試 LDAP/AD 整合的命命 - - - Basic LDAP/AD support for Veyon - Veyon 的基本 LDAP/AD 支援 - - - %1 (load computers and locations from LDAP/AD) - %1 (從 LDAP/AD 載入電腦和位置) - - - %1 (load users and groups from LDAP/AD) - %1 (從 LDAP/AD 載入使用者和群組) - - - Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" - 請指定一個有效的 LDAP url,其架構如下 "ldap[s]://[user[:password]@]hostname[:port]" - - - No naming context attribute name given - falling back to configured value. - 沒有給予命名內容屬性名稱 - 返回到組態的值。 - - - Could not query base DN. Please check your LDAP configuration. - 無法查詢基本 DN。 請檢查您的 LDAP 組態。 - - - Configuring %1 as base DN and disabling naming context queries. - 將 %1 組態為基本 DN 並停用命名內容查詢。 - - - - LdapProConfigurationPage - - LDAP Pro - LDAP Pro - - - Instances - 實例 - - - Enter name - 輸入名稱 - - - Please enter a name for the instance (can't be changed later!): - 請輸入實例的名稱 (之後無法變更!): - - - Remove instance - 移除實例 - - - Do you really want to remove instance "%1"? - 是否確實要刪除實例 "%1"? - - - Configuration for instance "%1" - 實例 "%1" 的組態 - - - - LdapProPlugin - - Professional LDAP/AD integration for Veyon - Veyon 的專業 LDAP/AD 整合 - - - %1 (load computers and locations from LDAP/AD) - %1 (從 LDAP/AD 載入電腦和位置) + Enter computer display name + 輸入電腦顯示名稱 - %1 (load users and groups from LDAP/AD) - %1 (從 LDAP/AD 載入使用者和群組) + Please enter a computer display name to query: + 請輸入查詢的電腦顯示名稱: - - - LicensingConfigurationPage - Licensing - 授權 + Enter computer location name + 輸入電腦位置名稱 - Installed licenses - 已安裝的授權 + Please enter the name of a computer location (wildcards allowed): + 請輸入電腦位置的名稱 (允許萬用字元): - Add new network range - 加入新的網路範圍 + Enter location name + 輸入位置名稱 - Remove selected network range - 刪除選取的網路範圍 + Please enter the name of a location whose entries to query: + 請輸入查詢其項目的位置名稱: - ID - ID + Browse + 瀏覽 - Feature - 功能 + Test + 測試 - Valid until - 有效期至 + Hostnames stored as fully qualified domain names (FQDN, e.g. myhost.example.org) + 主機名稱存儲為完全限定網域名稱 (FQDN, 例如: myhost.example.org) - Licensee - 授權 + Computer hostname attribute + 電腦主機名稱屬性 - Browse license file - 瀏覽授權檔 + Please enter a computer hostname to query: + 請輸入查詢的電腦主機名稱: - Veyon license files (*.vlf) - Veyon 授權檔案 (*.vlf) + Enter hostname + 輸入主機名稱 - Remove license - 移除授權 + Please enter a computer hostname whose group memberships to query: + 請輸入查詢其群組成員身份的電腦主機名稱: - Do you really want to remove the selected license? - 是否真的要移除選取的授權? + User login name attribute + 使用者登入名稱屬性 - <N/A> - <不適用> + Configured attribute for user login name or computer hostname (OpenLDAP) + 為使用者登入名稱或電腦主機名稱組態的屬性 (OpenLDAP) - Invalid license file - 授權檔無效 + Directory name + 目錄名稱 - Could not open the license file for reading! - 無法開啟授權檔來讀取! + Query options + 查詢選項 - The selected license file does not contain valid data. - 選取的授權檔不包含有效資料。 + Query nested user groups (supported by AD only) + 查詢巢狀使用者群組 (只有 AD 支援) - The selected license file could not be verified. - 無法驗證選取的授權檔。 + Query timeout + 查詢逾時 - The selected license file is not valid for this installation. - 選取的授權檔對此安裝無效。 + ms + 毫秒 + + + LdapNetworkObjectDirectoryConfigurationPage - The selected license file is expired. - 選取的授權檔已過期。 + LDAP + LDAP - The license is already installed. - 授權已經安裝。 + Please use the global LDAP configuration page to configure how to retrieve locations and computers from your LDAP-based directory service. + 請使用全域 LDAP 組態頁面來組態如何從基於 LDAP 的目錄服務中檢索位置和電腦。 + + + LdapPlugin - Information - 資訊 + Auto-configure the base DN via naming context + 透過命名內文自動組態基礎 DN - Installation ID - 安裝 ID + Query objects from LDAP directory + 從 LDAP 目錄查詢物件 - Addons available for licensing - 授權的附加元件可用 + Show help about command + 顯示有關命令的說明 - Addon - 附加元件 + Commands for configuring and testing LDAP/AD integration + 組態和測試 LDAP/AD 整合的命命 - - - LicensingPlugin - Show help for specific command - 顯示指定命令的說明 + Basic LDAP/AD support for Veyon + Veyon 的基本 LDAP/AD 支援 - Show all installed licenses - 顯示所有已安裝的授權 + %1 (load computers and locations from LDAP/AD) + %1 (從 LDAP/AD 載入電腦和位置) - Add license file - 加入授權檔 + %1 (load users and groups from LDAP/AD) + %1 (從 LDAP/AD 載入使用者和群組) - Remove installed license - 移除已安裝的授權 + Please specify a valid LDAP url following the schema "ldap[s]://[user[:password]@]hostname[:port]" + 請指定一個有效的 LDAP url,其架構如下 "ldap[s]://[user[:password]@]hostname[:port]" - -USAGE - -%1 add <LICENSE FILE> - - - -用法 - -%1 add <LICENSE FILE> - - + No naming context attribute name given - falling back to configured value. + 沒有給予命名內容屬性名稱 - 返回到組態的值。 - -USAGE - -%1 remove <LICENSE ID> - - - -用法 - -%1 remove <LICENSE ID> - - + Could not query base DN. Please check your LDAP configuration. + 無法查詢基本 DN。 請檢查您的 LDAP 組態。 - No certificate found with given ID - 找不到具有給予 ID 的憑證 + Configuring %1 as base DN and disabling naming context queries. + 將 %1 組態為基本 DN 並停用命名內容查詢。 - <N/A> - <不適用> + Test binding to an LDAP server + 測試繫結到 LDAP 伺服器 - Licensing management - 授權管理 + The supplied username or password is wrong. Please enter valid credentials or switch to a different authentication method using the Veyon Configurator. + 提供的使用者名稱或密碼錯誤。 請輸入有效的認證或使用 Veyon 組態器切換到其它身份驗證方法。 - Commands for managing license keys - 用於管理授權金鑰的命令 + LDAP bind + LDAP 繫結 @@ -2734,12 +3109,20 @@ USAGE 使用者身份驗證 - Session management - 工作階段管理 + User sessions + 使用者工作階段 + + + Minimum session lifetime before server start + 伺服器啟動前的最小工作階段長度 + + + User login + 使用者登入 - Display manager users - 顯示管理員使用者 + Login key sequence + 登入金鑰序列 @@ -2748,10 +3131,6 @@ USAGE Plugin implementing abstract functions for the Linux platform 外掛程式實現 Linux 平臺的抽象函數 - - Plugin implementing specific functions for the Linux platform - - LocationDialog @@ -2770,14 +3149,14 @@ USAGE Configuration 組態 - - Disable balloon tooltips - 停用氣球工具提示 - Show icons only 只顯示圖示 + + Disable tooltips + 停用工具提示 + MainWindow @@ -2825,10 +3204,6 @@ USAGE About Qt 關於 Qt - - Authentication impossible - 無法驗證 - Configuration not writable 組態無法寫入 @@ -2887,11 +3262,7 @@ USAGE The local configuration backend reported that the configuration is not writable! Please run the %1 Configurator with higher privileges. - 本機組態後台報告組態不可寫入! 請以較高特權執行 %1 組態器。 - - - No authentication key files were found or your current ones are outdated. Please create new key files using the %1 Configurator. Alternatively set up logon authentication using the %1 Configurator. Otherwise you won't be able to access computers using %1. - 找不到驗證金鑰檔或目前的已過時。 請使用 %1 組態器建立新的金鑰檔。 或者使用 %1 組態器設定登入驗證。 否則您將無法使用 %1 存取電腦。 + 本機組態後端報告組態不可寫入! 請以較高特權執行 %1 組態器。 Access denied @@ -2925,10 +3296,6 @@ USAGE Search users and computers 搜尋使用者和電腦 - - Adjust optimal size - 調整最佳大小 - Align computers to grid 將電腦對齊格線 @@ -2967,11 +3334,55 @@ USAGE Use custom computer arrangement - 使用自訂電腦排列 + 使用自訂電腦安排 Locations && computers - 地點 && 電腦 + 位置 && 電腦 + + + Authentication + 身份驗證 + + + Adjust size of computer icons automatically + 自動調整電腦圖示的大小 + + + Slideshow + 投影片 + + + Spotlight + 聚光燈 + + + Veyon Master + Veyon Master + + + Locations & computers + 位置 & 電腦 + + + Use custom computer arrangement. + +Press and hold to load arrangement from a file or save current arrangement to a file. + 使用自訂電腦安排。 + +按住不放以從檔案載入安排或將目前安排儲存到檔案。 + + + Only show computers with logged on users + 只顯示已登入使用者的電腦 + + + Load computer positions + 載入電腦位置 + + + Save computer positions + 儲存電腦位置 @@ -2980,10 +3391,6 @@ USAGE Directories 目錄 - - ... - ... - User configuration 使用者組態 @@ -3068,6 +3475,10 @@ USAGE Only user name 僅使用者名稱 + + Only last part of user name + + Only computer name 僅電腦名稱 @@ -3116,171 +3527,181 @@ USAGE Automatically select current location 自動選取目前位置 - - Automatically adjust computer thumbnail size - 自動調整電腦縮圖大小 - Automatically open computer select panel 自動開啟電腦選取面板 - - - MonitoringMode - Monitoring - 監視 + Use modern user interface (experimental) + 使用現代使用者介面 (實驗性) - Builtin monitoring mode - 內建監視模式 + Thumbnail spacing + 縮圖間距 - This mode allows you to monitor all computers at one or more locations. - 這個模式允許您監視在一個或數個位置的所有電腦。 + px + px - - - NetworkDiscoveryConfigurationPage - Network discovery - 網路探索 + Hide local session + 隱藏本機工作階段 - Mode - 模式 + Auto + 自動 - Scan network ranges - 掃描網路範圍 + Thumbnail aspect ratio + 縮圖外觀比例 - e.g. 192.168.1.0/24 - 例如: 192.168.1.0/24 + Automatically adjust computer icon size + 自動調整電腦圖示大小 - Scan all subnets of computer - 掃描電腦的所有子網路 + Open feature windows on the same screen as the main window + 在與主視窗同一螢幕上開啟功能視窗 - Scan custom subnet - 掃描自訂子網路 + Configuration templates + 組態範本 - Scan sessions on local computer - 掃描本機電腦上的工作階段 + Image quality in monitoring mode + 監控模式中圖片品質 - Test - 測試 + Highest + 最高 - Network ranges - 網路範圍 + High + - Add new group - 加入新群組 + Medium + - Remove selected group - 刪除選取的群組 + Low + - Groups - 群組 + Lowest + 最低 - First address - 第一個位址 + Remote access image quality + 遠端存取圖片品質 - Last address - 最後位址 + Advanced + 進階 - Add new network range - 加入新的網路範圍 + Computer name source + 電腦名稱來源 - Remove selected network range - 刪除選取的網路範圍 + Default + 預設值 - Parallel scans - 並行掃描 + Host address + 主機位址 - Scan timeout - 掃描逾時 + Session client address + 工作階段用戶端位址 - ms - 毫秒 + Session client name + 工作階段用戶端名稱 - Session scan limit - 工作階段掃描限制 + Session host name + 工作階段主機名稱 - Options - 選項 + Session metadata + 工作階段中繼資料 - Reverse lookup discovered IP addresses to host names - 反向對應發現的主機名稱的 IP 位址 + Full name of user + 使用者的全名 - New location - 新位置 + User login name + 使用者登入名稱 + + + Computer UID role + 電腦 UID 角色 - - - NetworkDiscoveryDirectory - Scanning... - 正在掃描... + Session meta data hash + 工作階段中繼資料雜湊 - Discovered computers - 發現的電腦 + Always expand all locations + 一律展開所有位置 + + + Image quality + 圖片品質 - NetworkDiscoveryPlugin + MonitoringMode - Show help for specific command - 顯示指定命令的說明 + Monitoring + 監視 - Scan a subnet - 掃描子網路 + Builtin monitoring mode + 內建監視模式 - -USAGE - -%1 scan [<SUBNET>] - - - -用法 - -%1 scan [<子網路>] - - + This mode allows you to monitor all computers at one or more locations. + 這個模式允許您監視在一個或數個位置的所有電腦。 + + + Query application version of the server + 查詢伺服器的應用程式版本 + + + Query active features + 查詢使用中功能 + + + Query properties of remotely available screens + 查詢遠端可用螢幕的內容 + + + + NestedNetworkObjectDirectory + + All directories + 全部目錄 + + + NetworkObjectDirectoryConfigurationPage - Network object directory which automatically discovers computers in the network - 自動探索網路中的電腦的網路物件目錄 + Update interval: + 更新間隔: - Network discovery (scan network for Veyon clients) - 網路探索 (掃描 Veyon 用戶端的網路) + seconds + + + + NetworkObjectDirectoryConfigurationPageTab - Commands for managing the network discovery directory - 用於管理網路探索目錄的命令 + Enabled + 啟用 @@ -3316,39 +3737,51 @@ USAGE Name: 名稱: + + Website name + 網站名稱 + - PasswordDialog + PluginCommands - Username - 使用者名稱 + List names of all installed plugins + 列出所有已安裝外掛程式的名稱 - Password - 密碼 + Show table with details of all installed plugins + 顯示含所有已安裝外掛程式的詳細資訊表格 - Veyon Logon - Veyon 登入 + Name + 名稱 - Authentication error - 驗證錯誤 + Description + 描述 - Logon failed with given username and password. Please try again! - 以給予的使用者名稱和密碼登入失敗。 請再試一次! + Version + 版本 - Please enter your username and password in order to access computers. - 請輸入您的使用者名稱和密碼才能存取電腦。 + UID + UID + + + Plugin-related CLI operations + 外掛程式相關的 CLI 操作 + + + Commands for managing plugins + 管理外掛程式的命令 PowerControlFeaturePlugin Power on - 開機 + 開啟電源 Click this button to power on all computers. This way you do not have to power on each computer by hand. @@ -3364,7 +3797,7 @@ USAGE Power down - 關機 + 關閉電源 Click this button to power down all computers. This way you do not have to power down each computer by hand. @@ -3384,11 +3817,7 @@ USAGE Do you really want to reboot the selected computers? - 您確定要重新啟動選取的電腦嗎? - - - Do you really want to power down the selected computer? - 您確定要關閉選取的電腦嗎? + 您真的要重新啟動選取的電腦嗎? Power on a computer via Wake-on-LAN (WOL) @@ -3420,15 +3849,15 @@ USAGE Install updates and power down - 安裝更新和關閉電源 + 安裝更新並關閉電源 Power down after user confirmation - 使用者確認後關機 + 使用者確認後關閉電源 Power down after timeout - 逾時後關機 + 逾時後關閉電源 The computer was remotely requested to power down. Do you want to power down the computer now? @@ -3442,12 +3871,24 @@ Please save your work and close all programs. 請儲存您的工作並關閉所有程式。 + + Do you really want to reboot <b>ALL</b> computers? + 您真的要重新啟動 <b>所有的</b> 電腦? + + + Do you really want to power down <b>ALL</b> computers? + 您真的要關閉 <b>所有的</b> 電腦? + + + Do you really want to power down the selected computers? + 您真的要關閉選取的電腦? + PowerDownTimeInputDialog Power down - 關機 + 關閉電源 Please specify a timeout for powering down the selected computers: @@ -3489,12 +3930,23 @@ Please save your work and close all programs. 遠端檢視或控制電腦 - Please enter the hostname or IP address of the computer to access: - 請輸入主機名稱或電腦的 IP 位址來存取: + Show help about command + 顯示有關命令的說明 - Show help about command - 顯示命令的說明 + Exchange clipboard contents + 交換剪貼簿內容 + + + No computer has been selected so you can enter a hostname or IP address of a computer for manual access: + 未選取電腦,因此您可以輸入電腦的主機名稱或 IP 地址以手動存取: + + + + RemoteAccessPage + + Remote access: %1 + 遠端存取: %1 @@ -3503,6 +3955,10 @@ Please save your work and close all programs. %1 - %2 Remote Access %1 - %2 遠端存取 + + %1 - %2 - %3 Remote Access + %1 - %2 - %3 遠端存取 + RemoteAccessWidgetToolBar @@ -3558,74 +4014,29 @@ Please save your work and close all programs. Alt+Ctrl+F1 Alt+Ctrl+F1 - - Connecting %1 - 正在連線 %1 - Connected. - 已連線。 - - - Screenshot - 螢幕快照 - - - Exit - 結束 - - - - Routing - - Control internet access by modifying routing table - 透過修改路由表控制 Internet 存取 - - - - RoutingConfigurationWidget - - Remove default routes to block internet access - 移除預設路由以封鎖 Internet 存取 - - - Add custom route to block internet - 加入自訂路由以封鎖 Internet - - - Destination - 目的地 - - - Gateway - 閘道 - - - - RunProgramDialog - - Please enter the programs or commands to run on the selected computer(s). You can separate multiple programs/commands by line. - 請輸入程式或在選取電腦上執行的命令。 您可以用行分隔多個程式/命令。 + 已連線。 - Run programs - 執行程式 + Screenshot + 螢幕快照 - e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" - 例如: "C:\Program Files\VideoLAN\VLC\vlc.exe" + Exit + 結束 - Name: - 名稱: + Connecting... + 正在連線... - Remember and add to program menu - 記住並加入到程式功能表 + Select screen + 選取螢幕 - e.g. VLC - 例如: VLC + All screens + 所有螢幕 @@ -3646,6 +4057,18 @@ Please save your work and close all programs. To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked and the screens are blacked. 若要收回所有使用者的完全注意,您可以使用此按鈕鎖定其電腦。 在這種模式下,所有的輸入設備鎖定和畫面全黑。 + + Lock input devices + 鎖定輸入裝置 + + + Unlock input devices + 解鎖輸入裝置 + + + To reclaim all user's full attention you can lock their computers using this button. In this mode all input devices are locked while the desktop is still visible. + 若要收回所有使用者的完全注意,您可以使用此按鈕鎖定其電腦。 在這種模式下,桌面仍可見時輸入設備鎖定。 + Screenshot @@ -3661,6 +4084,10 @@ Please save your work and close all programs. Screenshot 螢幕快照 + + Could not open screenshot file %1 for writing. + 無法開啟寫入的螢幕快照檔案 %1。 + ScreenshotFeaturePlugin @@ -3685,6 +4112,13 @@ Please save your work and close all programs. 取得電腦螢幕快照並儲存在本機。 + + ScreenshotManagementPage + + Screenshots + 螢幕快照 + + ScreenshotManagementPanel @@ -3715,6 +4149,45 @@ Please save your work and close all programs. Delete 刪除 + + Screenshot + 螢幕快照 + + + Do you really want to delete all selected screenshots? + 您真的要刪除所有的螢幕快照嗎? + + + + ServerAccessControlManager + + Requested authentication method not available + 請求的身份驗證方法不可用 + + + Access allowed by rule "%1" + 規則「%1」允許存取 + + + Access denied by rule "%1" + 規則「%1」拒絕存取 + + + No rule allowed access + 無規則允許存取 + + + Accessing user not member of an authorized user group + 存取使用者不是授權使用者群組的成員 + + + User has denied access + 使用者拒絕存取 + + + User confirmed access + 使用者確認存取 + ServiceConfigurationPage @@ -3746,14 +4219,6 @@ Please save your work and close all programs. State: 狀態: - - Network - 網路 - - - Demo server port - 展示伺服器連接埠 - Enable firewall exception 啟用防火牆例外 @@ -3762,10 +4227,6 @@ Please save your work and close all programs. Allow connections from localhost only 只允許來自 localhost 的連線 - - Internal VNC server port - 內部 VNC 伺服器埠 - VNC server VNC 伺服器 @@ -3780,20 +4241,12 @@ Please save your work and close all programs. All settings were saved successfully. In order to take effect the %1 service needs to be restarted. Restart it now? - 已成功儲存所有的設定。 為了生效 %1 服務需要重新啟動。 立即重新啟動它? + 儲存所有的設定成功。 為了生效 %1 服務需要重新啟動。 立即重新啟動它? Running 執行中 - - Feature manager port - 功能管理員埠 - - - Primary service port - 主服務埠 - Enabling this option will make the service launch a server process for every interactive session on a computer. Typically this is required to support terminal servers. @@ -3804,52 +4257,132 @@ Typically this is required to support terminal servers. Show notification on remote connection 遠端連線時顯示通知 - - Multi session mode (for terminal and remote desktop servers) - 多工作階段模式 (適用於終端機和遠端桌面伺服器) - Show notification when an unauthorized access is blocked 未授權的存取已封鎖時顯示通知 - - - ServiceControl - Starting service %1 - 正在啟動服務 %1 + Maximum session count + 最大工作階段數 - Stopping service %1 - 正在停止服務 %1 + Network port numbers + 網路埠號 - Registering service %1 - 註冊服務 %1 + Veyon server + Veyon 伺服器 - Unregistering service %1 - 取消註冊服務 %1 + Internal VNC server + 內部 VNC 伺服器 - Service control - 服務控制 + Feature manager + 功能管理員 + + + Demo server + 演示伺服器 + + + Miscellaneous network settings + 其它網路設定 + + + Session mode + 工作階段模式 + + + Local session mode (single server instance for primary local session) + 本機工作階段模式 (主要本機工作階段的單一伺服器實例) + + + Active session mode (single server instance for active local or remote session) + 使用中工作階段模式 (使用中本機或遠端工作階段的單ㄧ伺服器實例) + + + Multi session mode (distinct server instance for each local and remote desktop session) + 多工作階段模式 (每個本機和遠端桌面工作階段的不同伺服器實例) + + + Enable if a single Veyon Server instance should be launched for the currently active session, no matter if local or remote. + 如果應該為目前活動會話啟動單一 Veyon Server 實例 (無論是本機還是遠端),則啟用。 + + + Miscellaneous settings + 雜項設定 + + + Disable clipboard synchronization + 停用剪貼簿同步 + + + Session metadata + 工作階段中繼資料 + + + Content + 內文 + + + None + + + + Value of an environment variable + 環境變數的值 + + + Value of a registry key + 登錄檔機碼的值 + + + Environment variable name: + 環境變數名稱: + + + Registry key name: + 登錄檔機碼名稱: + + + Optionally enter a regular expression with a capture to extract a part of the computer name and use it as the display name for the computer. + +Example: [^-]*-(PC[0-9]*) + (可選) 輸入含擷取的正規表示式,以擷取電腦名稱的一部分並將其用於電腦的顯示名稱。 + +例如: [^-]*-(PC[0-9]*) - ServiceControlPlugin + ServiceControl - Service is running - 服務正在執行 + Service control + 服務控制 - Service is not running - 服務未執行 + Starting %1 + 正在啟動 %1 - Configure and control Veyon service - 組態和控制 Veyon 服務 + Stopping %1 + 正在停止 %1 + + Restarting %1 + 正在重新啟動 %1 + + + Registering %1 + 正在註冊 %1 + + + Unregistering %1 + 正在取消註冊 %1 + + + + ServiceControlCommands Register Veyon Service 註冊 Veyon 服務 @@ -3874,13 +4407,25 @@ Typically this is required to support terminal servers. Query status of Veyon Service 查詢 Veyon 服務的狀態 + + Service is running + 服務正在執行 + + + Service is not running + 服務未執行 + + + Configure and control Veyon service + 組態和控制 Veyon 服務 + Commands for configuring and controlling Veyon Service 組態和控制 Veyon 服務的命令 - ShellCommandLinePlugin + ShellCommands Run command file 執行命令列 @@ -3890,14 +4435,101 @@ Typically this is required to support terminal servers. 檔案 "%1" 不存在! - Interactive shell and script execution for Veyon Control - Veyon Control 的交互式殼層和指令碼執行 + Interactive shell and script execution for Veyon CLI + Veyon CLI 的交互式殼層和指令碼執行 Commands for shell functionalities 殼層功能的命令 + + SlideshowPanel + + Previous + 上一頁 + + + Start/pause + 開始/暫停 + + + Next + 下一頁 + + + Duration: + 持續時間: + + + View in separate window + + + + %1 Master – Slideshow + + + + + SpotlightPanel + + Add selected computers + 加入選取的電腦 + + + Remove selected computers + 移除選取的電腦 + + + Update computers in realtime + 即時更新電腦 + + + Spotlight + 聚光燈 + + + Please select at least one computer to add. + 請選擇至少一台電腦來加入。 + + + Add computers by clicking with the middle mouse button or clicking the first button below. +The second button removes the selected or last computer. + 以按一下滑鼠中鍵或按一下以下第一個按鈕來加入電腦。 +第二個按鈕移除選取的或最後一個電腦。 + + + + StartAppDialog + + Start application + 啟動應用程式 + + + Please enter the applications to start on the selected computers. You can separate multiple applications by line. + 請輸入應用程式以在選取的電腦啟動。 您可以以行分隔多個應用程式。 + + + e.g. "C:\Program Files\VideoLAN\VLC\vlc.exe" + 例如: "C:\Program Files\VideoLAN\VLC\vlc.exe" + + + Remember and add to application menu + 記住並加入到應用程式功能表 + + + Application name + 應用程式名稱 + + + Name: + 名稱: + + + e.g. VLC + 例如: VLC + + SystemTrayIcon @@ -3909,7 +4541,7 @@ Typically this is required to support terminal servers. SystemUserGroupsPlugin User groups backend for system user groups - 系統使用者群組的使用者群組後台 + 系統使用者群組的使用者群組後端 Default (system user groups) @@ -3934,8 +4566,8 @@ Typically this is required to support terminal servers. 傳送文字訊息 - Use the field below to type your message which will be sent to all selected users. - 使用下列欄位輸入您要傳送給所有選取使用者的訊息。 + Please enter your message which send to all selected users. + 請輸入您要傳送給所有選取使用者的訊息。 @@ -3946,7 +4578,7 @@ Typically this is required to support terminal servers. Use this function to send a text message to all users e.g. to assign them new tasks. - 使用此函數來向所有使用者傳送文字訊息,例如要向其分配新任務。 + 使用此函數來向所有使用者傳送文字訊息,例如要向其分配新工作。 Message from teacher @@ -3983,23 +4615,39 @@ Typically this is required to support terminal servers. Enable Desktop Duplication Engine on Windows 8 and newer 在 Windows 8 和以上啟用「桌面複製引擎」 + + Maximum CPU usage + 最大 CPU 使用率 + - UserConfig + UserLoginDialog - No write access - 沒有寫入存取 + User login + 使用者登入 - Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. - 無法儲存您的個人設定! 請檢查使用 %1 組態的使用者設定檔路徑。 + Please enter a username and password for automatic login on all computers. + 請在所有電腦上輸入自動登入的使用者名稱和密碼。 + + + Username + 使用者名稱 + + + Password + 密碼 - UserSessionControl + UserSessionControlPlugin - User session control - 使用者工作階段控制 + Log in + 登入 + + + Click this button to log in a specific user on all computers. + 按一下這個按鈕以登入所有電腦中的特定使用者。 Log off @@ -4017,6 +4665,14 @@ Typically this is required to support terminal servers. Do you really want to log off the selected users? 您真的要登出選取的使用者? + + User session control + 使用者工作階段控制 + + + Do you really want to log off <b>ALL</b> users? + 您真的要登出 <b>所有的</b> 使用者? + VeyonCore @@ -4068,13 +4724,9 @@ Typically this is required to support terminal servers. ERROR 錯誤 - - licensed for - 授權於 - USAGE - 使用 + 用法 DESCRIPTION @@ -4088,19 +4740,31 @@ Typically this is required to support terminal servers. WARNING 警告 + + Authentication test + 身份驗證測試 + + + Screen %1 + 螢幕 %1 + - VeyonServiceControl + VeyonMaster - Veyon Service - Veyon 服務 + No write access + 沒有寫入存取 + + + Could not save your personal settings! Please check the user configuration file path using the %1 Configurator. + 無法儲存您的個人設定! 請檢查使用 %1 組態的使用者設定檔路徑。 - VncView + VeyonServiceControl - Establishing connection to %1 ... - 建立連線到 %1 ... + Veyon Service + Veyon 服務 @@ -4122,7 +4786,7 @@ Typically this is required to support terminal servers. Enable SAS generation by software (Ctrl+Alt+Del) - 以軟體啟用 SAS 產生 (Ctrl + Alt + Del) + 以軟體啟用 SAS 產生 (Ctrl+Alt+Del) Screen lock @@ -4148,6 +4812,30 @@ Typically this is required to support terminal servers. Use alternative user authentication mechanism 使用替代使用者身份驗證機制 + + User login + 使用者登入 + + + Input start delay + 輸入啟動延遲 + + + Simulated key presses interval + 模擬按鍵間隔 + + + Confirm legal notice (message displayed before user logs in) + 確認法律聲明 (在使用者登入前顯示訊息) + + + Use input device interception driver + 使用輸入裝置攔截驅動程式 + + + Use custom power scheme with disabled power button + 使用停用電源按鈕的自訂電源方案 + WindowsPlatformPlugin @@ -4156,8 +4844,8 @@ Typically this is required to support terminal servers. 執行 Windows 平臺的抽象函數的外掛程式 - Plugin implementing specific functions for the Windows platform - + Internal display + 內部顯示 @@ -4166,30 +4854,34 @@ Typically this is required to support terminal servers. The service "%1" is already installed. 服務「%1」已經安裝。 - - The service "%1" could not be installed. - 無法安裝服務「%1」。 - The service "%1" has been installed successfully. 服務「%1」安裝成功。 - - The service "%1" could not be uninstalled. - 無法解除安裝服務「%1」。 - The service "%1" has been uninstalled successfully. 服務「%1」解除安裝成功。 - - The start type of service "%1" could not be changed. - 無法變更服務「%1」的啟動類型。 - Service "%1" could not be found. 找不到服務「%1」。 + + The service "%1" could not be installed (error %2). + 無法安裝服務「%1」的啟動類型 (錯誤 %2)。 + + + Could not change the failure actions config for service "%1" (error %2). + 無法變更服務「%1」的失敗動作組態 (錯誤 %2)。 + + + The service "%1" could not be uninstalled (error %2). + 無法解除安裝服務「%1」的啟動類型 (錯誤 %2)。 + + + The start type of service "%1" could not be changed (error %2). + 無法變更服務「%1」的啟動類型 (錯誤 %2)。 + X11VncConfigurationWidget diff --git a/worker/CMakeLists.txt b/worker/CMakeLists.txt index df1275009..997815800 100644 --- a/worker/CMakeLists.txt +++ b/worker/CMakeLists.txt @@ -1,14 +1,13 @@ -INCLUDE(BuildApplication) -INCLUDE(WindowsBuildHelpers) - -FILE(GLOB worker_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h) -FILE(GLOB worker_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) - -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src) -BUILD_APPLICATION(veyon-worker ${worker_SOURCES} ${worker_INCLUDES}) -TARGET_LINK_LIBRARIES(veyon-worker veyon-core Qt5::Network) - -ADD_WINDOWS_RESOURCE(veyon-worker) -MAKE_GRAPHICAL_APP(veyon-worker) - -COTIRE_VEYON(veyon-worker) +include(BuildVeyonApplication) +include(WindowsBuildHelpers) + +build_veyon_application(veyon-worker + src/FeatureWorkerManagerConnection.cpp + src/FeatureWorkerManagerConnection.h + src/main.cpp + src/VeyonWorker.cpp + src/VeyonWorker.h + ) + +add_windows_resource(veyon-worker) +make_graphical_app(veyon-worker) diff --git a/worker/src/FeatureWorkerManagerConnection.cpp b/worker/src/FeatureWorkerManagerConnection.cpp index 82c5d82d3..26cfa404c 100644 --- a/worker/src/FeatureWorkerManagerConnection.cpp +++ b/worker/src/FeatureWorkerManagerConnection.cpp @@ -1,7 +1,7 @@ /* * FeatureWorkerManagerConnection.cpp - class which handles communication between service and feature * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -31,33 +31,51 @@ FeatureWorkerManagerConnection::FeatureWorkerManagerConnection( VeyonWorkerInterface& worker, - FeatureManager& featureManager, Feature::Uid featureUid, QObject* parent ) : QObject( parent ), m_worker( worker ), - m_featureManager( featureManager ), + m_port(VeyonCore::config().featureWorkerManagerPort() + VeyonCore::sessionId()), m_socket( this ), m_featureUid( featureUid ) { + connect( &m_connectTimer, &QTimer::timeout, this, &FeatureWorkerManagerConnection::tryConnection ); + connect( &m_socket, &QTcpSocket::connected, this, &FeatureWorkerManagerConnection::sendInitMessage ); - connect( &m_socket, &QTcpSocket::disconnected, - QCoreApplication::instance(), &QCoreApplication::quit ); + connect(&m_socket, &QTcpSocket::disconnected, this, + [=]() { + vDebug() << "lost connection to FeatureWorkerManager – exiting"; + QCoreApplication::instance()->exit(0); + }, Qt::QueuedConnection); connect( &m_socket, &QTcpSocket::readyRead, this, &FeatureWorkerManagerConnection::receiveMessage ); - m_socket.connectToHost( QHostAddress::LocalHost, - static_cast( VeyonCore::config().featureWorkerManagerPort() + VeyonCore::sessionId() ) ); + tryConnection(); } bool FeatureWorkerManagerConnection::sendMessage( const FeatureMessage& message ) { - return message.send( &m_socket ); + vDebug() << message; + + return message.sendPlain(&m_socket); +} + + + +void FeatureWorkerManagerConnection::tryConnection() +{ + if( m_socket.state() != QTcpSocket::ConnectedState ) + { + vDebug() << "connecting to FeatureWorkerManager at port" << m_port; + + m_socket.connectToHost(QHostAddress::LocalHost, m_port); + m_connectTimer.start(ConnectTimeout); + } } @@ -66,7 +84,9 @@ void FeatureWorkerManagerConnection::sendInitMessage() { vDebug() << m_featureUid; - FeatureMessage( m_featureUid, FeatureMessage::InitCommand ).send( &m_socket ); + m_connectTimer.stop(); + + FeatureMessage(m_featureUid, FeatureMessage::InitCommand).sendPlain(&m_socket); } @@ -79,7 +99,7 @@ void FeatureWorkerManagerConnection::receiveMessage() { if( featureMessage.receive( &m_socket ) ) { - m_featureManager.handleFeatureMessage( m_worker, featureMessage ); + VeyonCore::featureManager().handleFeatureMessage( m_worker, featureMessage ); } } } diff --git a/worker/src/FeatureWorkerManagerConnection.h b/worker/src/FeatureWorkerManagerConnection.h index bd7d659a6..ee66bbd80 100644 --- a/worker/src/FeatureWorkerManagerConnection.h +++ b/worker/src/FeatureWorkerManagerConnection.h @@ -1,7 +1,7 @@ /* * FeatureWorkerManagerConnection.h - class which handles communication between worker manager and worker * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -25,6 +25,7 @@ #pragma once #include +#include #include "Feature.h" @@ -37,7 +38,6 @@ class FeatureWorkerManagerConnection : public QObject Q_OBJECT public: FeatureWorkerManagerConnection( VeyonWorkerInterface& worker, - FeatureManager& featureManager, Feature::Uid featureUid, QObject* parent = nullptr ); @@ -45,12 +45,16 @@ class FeatureWorkerManagerConnection : public QObject bool sendMessage( const FeatureMessage& message ); private: + static constexpr auto ConnectTimeout = 3000; + + void tryConnection(); void sendInitMessage(); void receiveMessage(); VeyonWorkerInterface& m_worker; - FeatureManager& m_featureManager; + const int m_port; QTcpSocket m_socket; Feature::Uid m_featureUid; + QTimer m_connectTimer{this}; } ; diff --git a/worker/src/VeyonWorker.cpp b/worker/src/VeyonWorker.cpp index ddc4bef3f..408031904 100644 --- a/worker/src/VeyonWorker.cpp +++ b/worker/src/VeyonWorker.cpp @@ -1,7 +1,7 @@ /* * VeyonWorker.cpp - basic implementation of Veyon Worker * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,21 +24,21 @@ #include +#include "FeatureManager.h" #include "FeatureWorkerManagerConnection.h" #include "VeyonConfiguration.h" #include "VeyonWorker.h" -VeyonWorker::VeyonWorker( const QString& featureUid, QObject* parent ) : +VeyonWorker::VeyonWorker( QUuid featureUid, QObject* parent ) : QObject( parent ), m_core( QCoreApplication::instance(), - QStringLiteral( "FeatureWorker-" ) + VeyonCore::formattedUuid( featureUid ) ), - m_featureManager(), - m_workerManagerConnection( nullptr ) + VeyonCore::Component::Worker, + QStringLiteral( "FeatureWorker-" ) + VeyonCore::formattedUuid( featureUid ) ) { const Feature* workerFeature = nullptr; - for( const auto& feature : m_featureManager.features() ) + for( const auto& feature : VeyonCore::featureManager().features() ) { if( feature.uid() == featureUid ) { @@ -51,19 +51,32 @@ VeyonWorker::VeyonWorker( const QString& featureUid, QObject* parent ) : qFatal( "Could not find specified feature" ); } - if( m_core.config().disabledFeatures().contains( featureUid ) ) + if( VeyonCore::config().disabledFeatures().contains( featureUid.toString() ) ) { qFatal( "Specified feature is disabled by configuration!" ); } - m_workerManagerConnection = new FeatureWorkerManagerConnection( *this, m_featureManager, featureUid, this ); + m_workerManagerConnection = new FeatureWorkerManagerConnection(*this, featureUid); vInfo() << "Running worker for feature" << workerFeature->name(); } +VeyonWorker::~VeyonWorker() +{ + vDebug(); + + delete m_workerManagerConnection; + m_workerManagerConnection = nullptr; + + vDebug() << "finished"; +} + + + bool VeyonWorker::sendFeatureMessageReply( const FeatureMessage& reply ) { - return m_workerManagerConnection->sendMessage( reply ); + return m_workerManagerConnection && + m_workerManagerConnection->sendMessage( reply ); } diff --git a/worker/src/VeyonWorker.h b/worker/src/VeyonWorker.h index 0ee510dce..719973aad 100644 --- a/worker/src/VeyonWorker.h +++ b/worker/src/VeyonWorker.h @@ -1,7 +1,7 @@ /* * VeyonWorker.h - basic implementation of Veyon Worker * - * Copyright (c) 2018-2019 Tobias Junghans + * Copyright (c) 2018-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -24,7 +24,7 @@ #pragma once -#include "FeatureManager.h" +#include "VeyonCore.h" #include "VeyonWorkerInterface.h" class FeatureWorkerManagerConnection; @@ -33,7 +33,8 @@ class VeyonWorker : public QObject, VeyonWorkerInterface { Q_OBJECT public: - explicit VeyonWorker( const QString& featureUid, QObject* parent = nullptr ); + explicit VeyonWorker( QUuid featureUid, QObject* parent = nullptr ); + ~VeyonWorker() override; bool sendFeatureMessageReply( const FeatureMessage& reply ) override; @@ -44,7 +45,6 @@ class VeyonWorker : public QObject, VeyonWorkerInterface private: VeyonCore m_core; - FeatureManager m_featureManager; - FeatureWorkerManagerConnection* m_workerManagerConnection; + FeatureWorkerManagerConnection* m_workerManagerConnection{nullptr}; } ; diff --git a/worker/src/main.cpp b/worker/src/main.cpp index 406ee7d6f..08e96ad24 100644 --- a/worker/src/main.cpp +++ b/worker/src/main.cpp @@ -1,7 +1,7 @@ /* * main.cpp - main file for Veyon Feature Worker * - * Copyright (c) 2017-2019 Tobias Junghans + * Copyright (c) 2017-2025 Tobias Junghans * * This file is part of Veyon - https://veyon.io * @@ -23,24 +23,28 @@ */ #include +#include +#include "Feature.h" #include "VeyonWorker.h" int main( int argc, char **argv ) { + VeyonCore::setupApplicationParameters(); + QApplication app( argc, argv ); - app.setWindowIcon( QIcon( QStringLiteral(":/core/icon64.png") ) ); + QApplication ::setWindowIcon( QIcon( QStringLiteral(":/core/icon64.png") ) ); - const auto arguments = app.arguments(); + const auto arguments = QApplication::arguments(); if( arguments.count() < 2 ) { qFatal( "Not enough arguments (feature)" ); } - const auto featureUid = arguments[1]; - if( QUuid( featureUid ).isNull() ) + const auto featureUid = Feature::Uid{arguments[1]}; + if( featureUid.isNull() ) { qFatal( "Invalid feature UID given" ); } diff --git a/worker/veyon-worker.rc.in b/worker/veyon-worker.rc.in index 7bd75efa9..b161c0aac 100644 --- a/worker/veyon-worker.rc.in +++ b/worker/veyon-worker.rc.in @@ -1,10 +1,10 @@ #include -ID_MANIFEST RT_MANIFEST data/veyon-worker.exe.manifest +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST data/veyon-worker.exe.manifest VS_VERSION_INFO VERSIONINFO FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,@VERSION_BUILD@ - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGSMASK 0x0L FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_APP FILESUBTYPE VFT2_UNKNOWN @@ -16,11 +16,16 @@ BEGIN BEGIN VALUE "Comments", "Virtual Eye On Networks (https://veyon.io)\0" VALUE "CompanyName", "Veyon Solutions\0" - VALUE "FileDescription", "Veyon Worker\0" + VALUE "ProductName", "Veyon\0" + VALUE "ProductVersion", "@VERSION_STRING@\0" + VALUE "FileDescription", "Veyon\0" VALUE "FileVersion", "@VERSION_STRING@\0" - VALUE "LegalCopyright", "Copyright (c) 2017-2019 Tobias Junghans\0" + VALUE "LegalCopyright", "Copyright (c) 2017-2025 Veyon Solutions / Tobias Junghans\0" VALUE "OriginalFilename", "veyon-worker.exe\0" - VALUE "ProductName", "Veyon\0" END END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04E4 + END END