Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
001ff1aa47 | ||
|
|
12066abc66 | ||
|
|
a10358b5ca | ||
|
|
124d36a981 | ||
|
|
f02fbb0e2d | ||
|
|
8c7dd2ed30 | ||
|
|
ae70375afe | ||
|
|
127ab45329 | ||
|
|
3bc1024e7f | ||
|
|
228eb87db1 | ||
|
|
4f726e3654 | ||
|
|
ed9fbcbec2 | ||
|
|
659a4198fc | ||
|
|
5456ccc072 | ||
|
|
fddaab5124 | ||
|
|
7be7e34b51 | ||
|
|
5b64eb32f8 | ||
|
|
eef8e7264f | ||
|
|
e8b54db6bf | ||
|
|
7b442658e1 | ||
|
|
408fcd3415 | ||
|
|
7cdb7e1f3e | ||
|
|
b595c0bce8 | ||
|
|
4c9b065c31 | ||
|
|
8b5ee59ae2 | ||
|
|
4114d73ed6 | ||
|
|
1d8a2ed59a | ||
|
|
c055920348 | ||
|
|
b2d965b58d | ||
|
|
446497ad06 | ||
|
|
0de752f65e | ||
|
|
f712f5e7f8 | ||
|
|
d090e1b707 | ||
|
|
fb7570709a | ||
|
|
73c3bda8cd | ||
|
|
9a73cb4a60 | ||
|
|
6cd50869c2 | ||
|
|
5823b550a4 | ||
|
|
29c48a8679 | ||
|
|
c88b683354 | ||
|
|
7399e5dc62 | ||
|
|
e4a5004f4b | ||
|
|
da7c481fc8 | ||
|
|
32f4398115 | ||
|
|
7350b12b3d | ||
|
|
1b25ad8e54 | ||
|
|
2165c3e1ba | ||
|
|
d390d187b4 | ||
|
|
a4034865e6 | ||
|
|
7d6244fe1c |
147
.gitlab-ci.yml
147
.gitlab-ci.yml
@@ -11,7 +11,8 @@ variables:
|
||||
# arm builds, because build_debian_buster_arm matches build_debian_buster.
|
||||
# "BUILD_JOBS: none" won't build any build jobs, nor www.
|
||||
BUILD_JOBS: all
|
||||
DOCKER_HOST: unix://
|
||||
DOCKER_HOST: tcp://docker:2375
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
|
||||
workflow:
|
||||
rules:
|
||||
@@ -38,11 +39,13 @@ stages:
|
||||
|
||||
default:
|
||||
tags:
|
||||
- oci-fixed-amd64
|
||||
- oci-fixed-amd
|
||||
|
||||
build_www:
|
||||
stage: www
|
||||
allow_failure: false
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
script:
|
||||
@@ -66,6 +69,8 @@ build_www:
|
||||
build_ubuntu_bionic:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -84,7 +89,7 @@ build_ubuntu_bionic_arm:
|
||||
stage: build
|
||||
allow_failure: false
|
||||
tags:
|
||||
- oci-fixed-arm64
|
||||
- oci-fixed-arm
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -102,6 +107,8 @@ build_ubuntu_bionic_arm:
|
||||
build_ubuntu_focal:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -120,7 +127,7 @@ build_ubuntu_focal_arm:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-arm64
|
||||
- oci-fixed-arm
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -138,6 +145,8 @@ build_ubuntu_focal_arm:
|
||||
build_ubuntu_jammy:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -156,7 +165,7 @@ build_ubuntu_jammy_arm:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-arm64
|
||||
- oci-fixed-arm
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -174,6 +183,8 @@ build_ubuntu_jammy_arm:
|
||||
build_debian_buster:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -192,7 +203,7 @@ build_debian_buster_arm:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-arm64
|
||||
- oci-fixed-arm
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -210,6 +221,8 @@ build_debian_buster_arm:
|
||||
build_debian_bullseye:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -228,7 +241,7 @@ build_debian_bullseye_arm:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-arm64
|
||||
- oci-fixed-arm
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -247,6 +260,8 @@ build_debian_bullseye_arm:
|
||||
build_debian_bookworm:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -265,7 +280,7 @@ build_debian_bookworm_arm:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-arm64
|
||||
- oci-fixed-arm
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -283,6 +298,8 @@ build_debian_bookworm_arm:
|
||||
build_kali_rolling:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -301,7 +318,7 @@ build_kali_rolling_arm:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-arm64
|
||||
- oci-fixed-arm
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -319,6 +336,8 @@ build_kali_rolling_arm:
|
||||
build_centos7:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -336,6 +355,8 @@ build_centos7:
|
||||
build_oracle_8:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -354,7 +375,7 @@ build_oracle_8_arm:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-arm64
|
||||
- oci-fixed-arm
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -372,6 +393,8 @@ build_oracle_8_arm:
|
||||
build_oracle_9:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -390,7 +413,7 @@ build_oracle_9_arm:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-arm64
|
||||
- oci-fixed-arm
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -408,6 +431,8 @@ build_oracle_9_arm:
|
||||
build_opensuse_15:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -426,7 +451,7 @@ build_opensuse_15_arm:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-arm64
|
||||
- oci-fixed-arm
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -444,6 +469,8 @@ build_opensuse_15_arm:
|
||||
build_fedora_thirtyseven:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -462,7 +489,7 @@ build_fedora_thirtyseven_arm:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-arm64
|
||||
- oci-fixed-arm
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -480,6 +507,8 @@ build_fedora_thirtyseven_arm:
|
||||
build_fedora_thirtyeight:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -498,7 +527,7 @@ build_fedora_thirtyeight_arm:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-arm64
|
||||
- oci-fixed-arm
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -513,9 +542,49 @@ build_fedora_thirtyeight_arm:
|
||||
paths:
|
||||
- output/
|
||||
|
||||
build_fedora_thirtynine:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
after_script:
|
||||
- *prepare_artfacts
|
||||
script:
|
||||
- bash builder/build-package fedora thirtynine;
|
||||
only:
|
||||
variables:
|
||||
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
|
||||
artifacts:
|
||||
paths:
|
||||
- output/
|
||||
|
||||
build_fedora_thirtynine_arm:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-arm
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
after_script:
|
||||
- *prepare_artfacts
|
||||
script:
|
||||
- bash builder/build-package fedora thirtynine;
|
||||
only:
|
||||
variables:
|
||||
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
|
||||
artifacts:
|
||||
paths:
|
||||
- output/
|
||||
|
||||
build_alpine_317:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -534,7 +603,7 @@ build_alpine_317_arm:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-arm64
|
||||
- oci-fixed-arm
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -551,6 +620,8 @@ build_alpine_317_arm:
|
||||
|
||||
test:
|
||||
stage: test
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
script:
|
||||
@@ -560,6 +631,8 @@ test:
|
||||
build_alpine_318:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -578,7 +651,7 @@ build_alpine_318_arm:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-arm64
|
||||
- oci-fixed-arm
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
@@ -593,9 +666,49 @@ build_alpine_318_arm:
|
||||
paths:
|
||||
- output/
|
||||
|
||||
build_alpine_319:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
after_script:
|
||||
- *prepare_artfacts
|
||||
script:
|
||||
- bash builder/build-package alpine 319;
|
||||
only:
|
||||
variables:
|
||||
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
|
||||
artifacts:
|
||||
paths:
|
||||
- output/
|
||||
|
||||
build_alpine_319_arm:
|
||||
stage: build
|
||||
allow_failure: true
|
||||
tags:
|
||||
- oci-fixed-arm
|
||||
before_script:
|
||||
- *prepare_build
|
||||
- *prepare_www
|
||||
after_script:
|
||||
- *prepare_artfacts
|
||||
script:
|
||||
- bash builder/build-package alpine 319;
|
||||
only:
|
||||
variables:
|
||||
- $BUILD_JOBS == 'all' || $BUILD_JOBS =~ $CI_JOB_NAME
|
||||
artifacts:
|
||||
paths:
|
||||
- output/
|
||||
|
||||
upload:
|
||||
stage: upload
|
||||
image: ubuntu:focal
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
artifacts:
|
||||
paths:
|
||||
- output/
|
||||
@@ -633,6 +746,8 @@ upload_build_preview:
|
||||
needs: ["upload"]
|
||||
dependencies: ["upload"]
|
||||
image: ubuntu:focal
|
||||
tags:
|
||||
- oci-fixed-amd
|
||||
before_script:
|
||||
- . .ci/upload.sh
|
||||
resource_group: upload_build_preview
|
||||
|
||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -1,4 +1,4 @@
|
||||
[submodule "kasmweb"]
|
||||
path = kasmweb
|
||||
url = https://github.com/kasmtech/noVNC.git
|
||||
branch = release/1.1.3
|
||||
branch = release/1.2.0
|
||||
|
||||
7
builder/dockerfile.alpine_319.apk.build
Normal file
7
builder/dockerfile.alpine_319.apk.build
Normal file
@@ -0,0 +1,7 @@
|
||||
FROM alpine:3.19
|
||||
|
||||
RUN apk add shadow bash
|
||||
|
||||
RUN useradd -m docker && echo "docker:docker" | chpasswd
|
||||
|
||||
USER docker
|
||||
82
builder/dockerfile.alpine_319.build
Normal file
82
builder/dockerfile.alpine_319.build
Normal file
@@ -0,0 +1,82 @@
|
||||
FROM alpine:3.19
|
||||
|
||||
ENV KASMVNC_BUILD_OS alpine
|
||||
ENV KASMVNC_BUILD_OS_CODENAME 319
|
||||
ENV XORG_VER 1.20.14
|
||||
|
||||
RUN \
|
||||
echo "**** install build deps ****" && \
|
||||
apk add \
|
||||
alpine-release \
|
||||
alpine-sdk \
|
||||
autoconf \
|
||||
automake \
|
||||
bash \
|
||||
ca-certificates \
|
||||
cmake \
|
||||
coreutils \
|
||||
curl \
|
||||
eudev-dev \
|
||||
font-cursor-misc \
|
||||
font-misc-misc \
|
||||
font-util-dev \
|
||||
git \
|
||||
grep \
|
||||
jq \
|
||||
libdrm-dev \
|
||||
libepoxy-dev \
|
||||
libjpeg-turbo-dev \
|
||||
libjpeg-turbo-static \
|
||||
libpciaccess-dev \
|
||||
libtool \
|
||||
libwebp-dev \
|
||||
libx11-dev \
|
||||
libxau-dev \
|
||||
libxcb-dev \
|
||||
libxcursor-dev \
|
||||
libxcvt-dev \
|
||||
libxdmcp-dev \
|
||||
libxext-dev \
|
||||
libxfont2-dev \
|
||||
libxkbfile-dev \
|
||||
libxrandr-dev \
|
||||
libxshmfence-dev \
|
||||
libxtst-dev \
|
||||
mesa-dev \
|
||||
mesa-dri-gallium \
|
||||
meson \
|
||||
nettle-dev \
|
||||
openssl-dev \
|
||||
pixman-dev \
|
||||
procps \
|
||||
shadow \
|
||||
tar \
|
||||
tzdata \
|
||||
wayland-dev \
|
||||
wayland-protocols \
|
||||
xcb-util-dev \
|
||||
xcb-util-image-dev \
|
||||
xcb-util-keysyms-dev \
|
||||
xcb-util-renderutil-dev \
|
||||
xcb-util-wm-dev \
|
||||
xinit \
|
||||
xkbcomp \
|
||||
xkbcomp-dev \
|
||||
xkeyboard-config \
|
||||
xorgproto \
|
||||
xorg-server-common \
|
||||
xorg-server-dev \
|
||||
xtrans
|
||||
|
||||
|
||||
ENV SCRIPTS_DIR=/tmp/scripts
|
||||
COPY builder/scripts $SCRIPTS_DIR
|
||||
RUN $SCRIPTS_DIR/build-webp
|
||||
RUN $SCRIPTS_DIR/build-libjpeg-turbo
|
||||
|
||||
RUN useradd -m docker && echo "docker:docker" | chpasswd
|
||||
|
||||
COPY --chown=docker:docker . /src/
|
||||
|
||||
USER docker
|
||||
ENTRYPOINT ["/src/builder/build.sh"]
|
||||
86
builder/dockerfile.fedora_thirtynine.build
Normal file
86
builder/dockerfile.fedora_thirtynine.build
Normal file
@@ -0,0 +1,86 @@
|
||||
FROM fedora:39
|
||||
|
||||
ENV KASMVNC_BUILD_OS fedora
|
||||
ENV KASMVNC_BUILD_OS_CODENAME thirtynine
|
||||
ENV XORG_VER 1.20.14
|
||||
|
||||
RUN \
|
||||
echo "**** install build deps ****" && \
|
||||
dnf group install -y \
|
||||
"C Development Tools and Libraries" \
|
||||
"Development Tools" && \
|
||||
dnf install -y \
|
||||
autoconf \
|
||||
automake \
|
||||
bison \
|
||||
byacc \
|
||||
bzip2 \
|
||||
cmake \
|
||||
diffutils \
|
||||
doxygen \
|
||||
file \
|
||||
flex \
|
||||
fop \
|
||||
gcc \
|
||||
gcc-c++ \
|
||||
git \
|
||||
glibc-devel \
|
||||
libdrm-devel \
|
||||
libepoxy-devel \
|
||||
libmd-devel \
|
||||
libpciaccess-devel \
|
||||
libtool \
|
||||
libwebp-devel \
|
||||
libX11-devel \
|
||||
libXau-devel \
|
||||
libxcb-devel \
|
||||
libXcursor-devel \
|
||||
libxcvt-devel \
|
||||
libXdmcp-devel \
|
||||
libXext-devel \
|
||||
libXfont2-devel \
|
||||
libxkbfile-devel \
|
||||
libXrandr-devel \
|
||||
libxshmfence-devel \
|
||||
libXtst-devel \
|
||||
mesa-libEGL-devel \
|
||||
mesa-libgbm-devel \
|
||||
mesa-libGL-devel \
|
||||
meson \
|
||||
mingw64-binutils \
|
||||
mt-st \
|
||||
nettle-devel \
|
||||
openssl-devel \
|
||||
patch \
|
||||
pixman-devel \
|
||||
wayland-devel \
|
||||
wget \
|
||||
which \
|
||||
xcb-util-devel \
|
||||
xcb-util-image-devel \
|
||||
xcb-util-keysyms-devel \
|
||||
xcb-util-renderutil-devel \
|
||||
xcb-util-wm-devel \
|
||||
xinit \
|
||||
xkbcomp \
|
||||
xkbcomp-devel \
|
||||
xkeyboard-config \
|
||||
xmlto \
|
||||
xorg-x11-font-utils \
|
||||
xorg-x11-proto-devel \
|
||||
xorg-x11-server-common \
|
||||
xorg-x11-server-devel \
|
||||
xorg-x11-xtrans-devel \
|
||||
xsltproc
|
||||
|
||||
ENV SCRIPTS_DIR=/tmp/scripts
|
||||
COPY builder/scripts $SCRIPTS_DIR
|
||||
RUN $SCRIPTS_DIR/build-webp
|
||||
RUN $SCRIPTS_DIR/build-libjpeg-turbo
|
||||
|
||||
RUN useradd -m docker && echo "docker:docker" | chpasswd
|
||||
|
||||
COPY --chown=docker:docker . /src/
|
||||
|
||||
USER docker
|
||||
ENTRYPOINT ["/src/builder/build.sh"]
|
||||
13
builder/dockerfile.fedora_thirtynine.rpm.build
Normal file
13
builder/dockerfile.fedora_thirtynine.rpm.build
Normal file
@@ -0,0 +1,13 @@
|
||||
FROM fedora:39
|
||||
|
||||
RUN dnf install -y fedora-packager fedora-review
|
||||
RUN dnf install -y tree vim less
|
||||
RUN dnf install -y redhat-lsb-core
|
||||
RUN dnf install -y dnf-plugins-core
|
||||
|
||||
COPY fedora/*.spec /tmp
|
||||
RUN dnf builddep -y /tmp/*.spec
|
||||
|
||||
RUN useradd -m docker && echo "docker:docker" | chpasswd
|
||||
|
||||
USER docker
|
||||
@@ -198,6 +198,7 @@ generate_xstartup() {
|
||||
|
||||
cat <<-SCRIPT > "$xstartup_script"
|
||||
#!/bin/sh
|
||||
set -x
|
||||
$de_cmd
|
||||
SCRIPT
|
||||
chmod +x "$xstartup_script"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: kasmvncserver
|
||||
Version: 1.2.1
|
||||
Version: 1.3.0
|
||||
Release: 1%{?dist}
|
||||
Summary: VNC server accessible from a web browser
|
||||
|
||||
@@ -83,9 +83,13 @@ cd $DST_MAN && ln -s vncpasswd.1 kasmvncpasswd.1;
|
||||
%doc /usr/share/doc/kasmvncserver/README.md
|
||||
|
||||
%changelog
|
||||
* Tue Mar 12 2024 KasmTech <info@kasmweb.com> - 1.2.1-1
|
||||
- Fix exception with Firefox 124 and later
|
||||
- Fix bug with watermarking on odd resolutions
|
||||
* Mon Feb 05 2024 KasmTech <info@kasmweb.com> - 1.3.0-1
|
||||
- Multi-monitor support.
|
||||
- Increased performance with watermark enabled.
|
||||
- Added support for Fedora 39 and Alpine 319.
|
||||
- Allow special characters in usernames.
|
||||
- Better logging of client settings when client connects or changes settings.
|
||||
- Add support for rotation of text-based watermark.
|
||||
* Fri Aug 25 2023 KasmTech <info@kasmweb.com> - 1.2.0-1
|
||||
- Add support for Unix relays for bidirectional communication between noVNC
|
||||
and containerized applications.
|
||||
|
||||
@@ -550,7 +550,7 @@ void GetAPIMessager::netGetBottleneckStats(char *buf, uint32_t len) {
|
||||
const char *id = it->first.c_str();
|
||||
const char *data = it->second.c_str();
|
||||
|
||||
const char *at = strchr(id, '@');
|
||||
const char *at = strrchr(id, '@');
|
||||
if (!at)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ using namespace network;
|
||||
static rfb::LogWriter vlog("WebUdp");
|
||||
static WuHost *host = NULL;
|
||||
|
||||
rfb::IntParameter udpSize("udpSize", "UDP packet data size", 1300, 500, 1400);
|
||||
rfb::IntParameter udpSize("udpSize", "UDP packet data size", 1296, 500, 1400);
|
||||
|
||||
extern settings_t settings;
|
||||
|
||||
@@ -95,10 +95,11 @@ void *udpserver(void *nport) {
|
||||
}
|
||||
|
||||
// Send one packet, split into N UDP-sized pieces
|
||||
static uint8_t udpsend(WuClient *client, const uint8_t *data, unsigned len, uint32_t *id) {
|
||||
static uint8_t udpsend(WuClient *client, const uint8_t *data, unsigned len, uint32_t *id,
|
||||
const uint32_t *frame) {
|
||||
const uint32_t DATA_MAX = udpSize;
|
||||
|
||||
uint8_t buf[1400 + sizeof(uint32_t) * 4];
|
||||
uint8_t buf[1400 + sizeof(uint32_t) * 5];
|
||||
const uint32_t pieces = (len / DATA_MAX) + ((len % DATA_MAX) ? 1 : 0);
|
||||
|
||||
uint32_t i;
|
||||
@@ -111,12 +112,13 @@ static uint8_t udpsend(WuClient *client, const uint8_t *data, unsigned len, uint
|
||||
memcpy(&buf[4], &i, sizeof(uint32_t));
|
||||
memcpy(&buf[8], &pieces, sizeof(uint32_t));
|
||||
memcpy(&buf[12], &hash, sizeof(uint32_t));
|
||||
memcpy(&buf[16], frame, sizeof(uint32_t));
|
||||
|
||||
memcpy(&buf[16], data, curlen);
|
||||
memcpy(&buf[20], data, curlen);
|
||||
data += curlen;
|
||||
len -= curlen;
|
||||
|
||||
if (WuHostSendBinary(host, client, buf, curlen + sizeof(uint32_t) * 4) < 0)
|
||||
if (WuHostSendBinary(host, client, buf, curlen + sizeof(uint32_t) * 5) < 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -125,7 +127,8 @@ static uint8_t udpsend(WuClient *client, const uint8_t *data, unsigned len, uint
|
||||
return 0;
|
||||
}
|
||||
|
||||
UdpStream::UdpStream(): OutStream(), client(NULL), total_len(0), id(0), failed(false) {
|
||||
UdpStream::UdpStream(): OutStream(), client(NULL), total_len(0), id(0), failed(false),
|
||||
frame(0) {
|
||||
ptr = data;
|
||||
end = data + UDPSTREAM_BUFSIZE;
|
||||
|
||||
@@ -137,7 +140,7 @@ void UdpStream::flush() {
|
||||
total_len += len;
|
||||
|
||||
if (client) {
|
||||
if (udpsend(client, data, len, &id)) {
|
||||
if (udpsend(client, data, len, &id, &frame)) {
|
||||
vlog.error("Error sending udp, client gone?");
|
||||
failed = true;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,10 @@ namespace network {
|
||||
client = cli;
|
||||
}
|
||||
|
||||
void setFrameNumber(const unsigned in) {
|
||||
frame = in;
|
||||
}
|
||||
|
||||
bool isFailed() const;
|
||||
void clearFailed();
|
||||
private:
|
||||
@@ -48,6 +52,7 @@ namespace network {
|
||||
size_t total_len;
|
||||
uint32_t id;
|
||||
bool failed;
|
||||
uint32_t frame;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include <openssl/sha.h> /* sha1 hash */
|
||||
#include "websocket.h"
|
||||
#include "jsonescape.h"
|
||||
#include "kasmpasswd.h"
|
||||
#include <network/Blacklist.h>
|
||||
|
||||
/*
|
||||
@@ -1756,7 +1755,7 @@ ws_ctx_t *do_handshake(int sock, char * const ip) {
|
||||
}
|
||||
|
||||
unsigned char owner = 0;
|
||||
char inuser[32] = "-";
|
||||
char inuser[USERNAME_LEN] = "-";
|
||||
if (!settings.disablebasicauth) {
|
||||
const char *hdr = strstr(handshake, "Authorization: Basic ");
|
||||
if (!hdr) {
|
||||
@@ -1794,7 +1793,7 @@ ws_ctx_t *do_handshake(int sock, char * const ip) {
|
||||
if (resppw && *resppw)
|
||||
resppw++;
|
||||
if (settings.passwdfile) {
|
||||
if (resppw && *resppw && resppw - response < 32) {
|
||||
if (resppw && *resppw && resppw - response < USERNAME_LEN + 1) {
|
||||
char pwbuf[4096];
|
||||
struct kasmpasswd_t *set = readkasmpasswd(settings.passwdfile);
|
||||
if (!set->num) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <stdint.h>
|
||||
#include "GetAPIEnums.h"
|
||||
#include "datelog.h"
|
||||
#include "kasmpasswd.h"
|
||||
|
||||
#define BUFSIZE 65536
|
||||
#define DBUFSIZE (BUFSIZE * 3) / 4 - 20
|
||||
@@ -57,7 +58,7 @@ typedef struct {
|
||||
char *tin_buf;
|
||||
char *tout_buf;
|
||||
|
||||
char user[32];
|
||||
char user[USERNAME_LEN];
|
||||
char ip[64];
|
||||
} ws_ctx_t;
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <rfb/Exception.h>
|
||||
#include <rfb/encodings.h>
|
||||
#include <rfb/ledStates.h>
|
||||
#include <rfb/LogWriter.h>
|
||||
#include <rfb/clipboardTypes.h>
|
||||
#include <rfb/ConnParams.h>
|
||||
#include <rfb/ServerCore.h>
|
||||
@@ -32,6 +33,19 @@
|
||||
|
||||
using namespace rfb;
|
||||
|
||||
static LogWriter vlog("CP");
|
||||
|
||||
static void clientparlog(const char name[], const bool applied) {
|
||||
vlog.debug("Client sent config param %s, %s",
|
||||
name,
|
||||
applied ? "applied" : "ignored due to -IgnoreClientSettingsKasm/lacking perms");
|
||||
}
|
||||
static void clientparlog(const char name[], int val, const bool applied) {
|
||||
vlog.debug("Client sent config param %s %d, %s",
|
||||
name, val,
|
||||
applied ? "applied" : "ignored due to -IgnoreClientSettingsKasm/lacking perms");
|
||||
}
|
||||
|
||||
ConnParams::ConnParams()
|
||||
: majorVersion(0), minorVersion(0),
|
||||
width(0), height(0), useCopyRect(false),
|
||||
@@ -147,54 +161,71 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
|
||||
switch (encodings[i]) {
|
||||
case encodingCopyRect:
|
||||
useCopyRect = true;
|
||||
clientparlog("copyrect", true);
|
||||
break;
|
||||
case pseudoEncodingCursor:
|
||||
supportsLocalCursor = true;
|
||||
clientparlog("cursor", true);
|
||||
break;
|
||||
case pseudoEncodingXCursor:
|
||||
supportsLocalXCursor = true;
|
||||
clientparlog("xcursor", true);
|
||||
break;
|
||||
case pseudoEncodingCursorWithAlpha:
|
||||
supportsLocalCursorWithAlpha = true;
|
||||
clientparlog("cursorWithAlpha", true);
|
||||
break;
|
||||
case pseudoEncodingVMwareCursor:
|
||||
supportsVMWareCursor = true;
|
||||
clientparlog("vmwareCursor", true);
|
||||
break;
|
||||
case pseudoEncodingDesktopSize:
|
||||
supportsDesktopResize = true;
|
||||
clientparlog("desktopSize", true);
|
||||
break;
|
||||
case pseudoEncodingExtendedDesktopSize:
|
||||
supportsExtendedDesktopSize = true;
|
||||
clientparlog("extendedDesktopSize", true);
|
||||
break;
|
||||
case pseudoEncodingVMwareCursorPosition:
|
||||
supportsCursorPosition = true;
|
||||
clientparlog("vmwareCursorPosition", true);
|
||||
break;
|
||||
case pseudoEncodingDesktopName:
|
||||
supportsDesktopRename = true;
|
||||
clientparlog("desktopRename", true);
|
||||
break;
|
||||
case pseudoEncodingLastRect:
|
||||
supportsLastRect = true;
|
||||
clientparlog("lastRect", true);
|
||||
break;
|
||||
case pseudoEncodingLEDState:
|
||||
supportsLEDState = true;
|
||||
clientparlog("ledState", true);
|
||||
break;
|
||||
case pseudoEncodingQEMUKeyEvent:
|
||||
supportsQEMUKeyEvent = true;
|
||||
clientparlog("qemuKeyEvent", true);
|
||||
break;
|
||||
case pseudoEncodingWEBP:
|
||||
supportsWEBP = true;
|
||||
clientparlog("webp", true);
|
||||
break;
|
||||
case pseudoEncodingQOI:
|
||||
supportsQOI = true;
|
||||
clientparlog("qoi", true);
|
||||
break;
|
||||
case pseudoEncodingFence:
|
||||
supportsFence = true;
|
||||
clientparlog("fence", true);
|
||||
break;
|
||||
case pseudoEncodingContinuousUpdates:
|
||||
supportsContinuousUpdates = true;
|
||||
clientparlog("continuousUpdates", true);
|
||||
break;
|
||||
case pseudoEncodingExtendedClipboard:
|
||||
supportsExtendedClipboard = true;
|
||||
clientparlog("extendedClipboard", true);
|
||||
break;
|
||||
case pseudoEncodingSubsamp1X:
|
||||
subsampling = subsampleNone;
|
||||
@@ -215,8 +246,12 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
|
||||
subsampling = subsample16X;
|
||||
break;
|
||||
case pseudoEncodingPreferBandwidth:
|
||||
if (!rfb::Server::ignoreClientSettingsKasm && canChangeSettings)
|
||||
if (!rfb::Server::ignoreClientSettingsKasm && canChangeSettings) {
|
||||
Server::preferBandwidth.setParam(true);
|
||||
clientparlog("preferBandwidth", true);
|
||||
} else {
|
||||
clientparlog("preferBandwidth", false);
|
||||
}
|
||||
break;
|
||||
case pseudoEncodingMaxVideoResolution:
|
||||
if (!rfb::Server::ignoreClientSettingsKasm && canChangeSettings)
|
||||
@@ -225,57 +260,133 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingCompressLevel0 &&
|
||||
encodings[i] <= pseudoEncodingCompressLevel9)
|
||||
encodings[i] <= pseudoEncodingCompressLevel9) {
|
||||
compressLevel = encodings[i] - pseudoEncodingCompressLevel0;
|
||||
clientparlog("compressLevel", compressLevel, true);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingQualityLevel0 &&
|
||||
encodings[i] <= pseudoEncodingQualityLevel9)
|
||||
encodings[i] <= pseudoEncodingQualityLevel9) {
|
||||
qualityLevel = encodings[i] - pseudoEncodingQualityLevel0;
|
||||
clientparlog("qualityLevel", qualityLevel, true);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingFineQualityLevel0 &&
|
||||
encodings[i] <= pseudoEncodingFineQualityLevel100)
|
||||
encodings[i] <= pseudoEncodingFineQualityLevel100) {
|
||||
fineQualityLevel = encodings[i] - pseudoEncodingFineQualityLevel0;
|
||||
clientparlog("fineQualityLevel", fineQualityLevel, true);
|
||||
}
|
||||
|
||||
if (!rfb::Server::ignoreClientSettingsKasm && canChangeSettings) {
|
||||
if (encodings[i] >= pseudoEncodingJpegVideoQualityLevel0 &&
|
||||
encodings[i] <= pseudoEncodingJpegVideoQualityLevel9)
|
||||
encodings[i] <= pseudoEncodingJpegVideoQualityLevel9) {
|
||||
Server::jpegVideoQuality.setParam(encodings[i] - pseudoEncodingJpegVideoQualityLevel0);
|
||||
clientparlog("jpegVideoQuality", encodings[i] - pseudoEncodingJpegVideoQualityLevel0, true);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingWebpVideoQualityLevel0 &&
|
||||
encodings[i] <= pseudoEncodingWebpVideoQualityLevel9)
|
||||
encodings[i] <= pseudoEncodingWebpVideoQualityLevel9) {
|
||||
Server::webpVideoQuality.setParam(encodings[i] - pseudoEncodingWebpVideoQualityLevel0);
|
||||
clientparlog("webpVideoQuality", encodings[i] - pseudoEncodingWebpVideoQualityLevel0, true);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingTreatLosslessLevel0 &&
|
||||
encodings[i] <= pseudoEncodingTreatLosslessLevel10)
|
||||
encodings[i] <= pseudoEncodingTreatLosslessLevel10) {
|
||||
Server::treatLossless.setParam(encodings[i] - pseudoEncodingTreatLosslessLevel0);
|
||||
clientparlog("treatLossless", encodings[i] - pseudoEncodingTreatLosslessLevel0, true);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingDynamicQualityMinLevel0 &&
|
||||
encodings[i] <= pseudoEncodingDynamicQualityMinLevel9)
|
||||
encodings[i] <= pseudoEncodingDynamicQualityMinLevel9) {
|
||||
Server::dynamicQualityMin.setParam(encodings[i] - pseudoEncodingDynamicQualityMinLevel0);
|
||||
clientparlog("dynamicQualityMin", encodings[i] - pseudoEncodingDynamicQualityMinLevel0, true);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingDynamicQualityMaxLevel0 &&
|
||||
encodings[i] <= pseudoEncodingDynamicQualityMaxLevel9)
|
||||
encodings[i] <= pseudoEncodingDynamicQualityMaxLevel9) {
|
||||
Server::dynamicQualityMax.setParam(encodings[i] - pseudoEncodingDynamicQualityMaxLevel0);
|
||||
clientparlog("dynamicQualityMax", encodings[i] - pseudoEncodingDynamicQualityMaxLevel0, true);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingVideoAreaLevel1 &&
|
||||
encodings[i] <= pseudoEncodingVideoAreaLevel100)
|
||||
encodings[i] <= pseudoEncodingVideoAreaLevel100) {
|
||||
Server::videoArea.setParam(encodings[i] - pseudoEncodingVideoAreaLevel1 + 1);
|
||||
clientparlog("videoArea", encodings[i] - pseudoEncodingVideoAreaLevel1 + 1, true);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingVideoTimeLevel0 &&
|
||||
encodings[i] <= pseudoEncodingVideoTimeLevel100)
|
||||
encodings[i] <= pseudoEncodingVideoTimeLevel100) {
|
||||
Server::videoTime.setParam(encodings[i] - pseudoEncodingVideoTimeLevel0);
|
||||
clientparlog("videoTime", encodings[i] - pseudoEncodingVideoTimeLevel0, true);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingVideoOutTimeLevel1 &&
|
||||
encodings[i] <= pseudoEncodingVideoOutTimeLevel100)
|
||||
encodings[i] <= pseudoEncodingVideoOutTimeLevel100) {
|
||||
Server::videoOutTime.setParam(encodings[i] - pseudoEncodingVideoOutTimeLevel1 + 1);
|
||||
clientparlog("videoOutTime", encodings[i] - pseudoEncodingVideoOutTimeLevel1 + 1, true);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingFrameRateLevel10 &&
|
||||
encodings[i] <= pseudoEncodingFrameRateLevel60)
|
||||
encodings[i] <= pseudoEncodingFrameRateLevel60) {
|
||||
Server::frameRate.setParam(encodings[i] - pseudoEncodingFrameRateLevel10 + 10);
|
||||
clientparlog("frameRate", encodings[i] - pseudoEncodingFrameRateLevel10 + 10, true);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingVideoScalingLevel0 &&
|
||||
encodings[i] <= pseudoEncodingVideoScalingLevel9)
|
||||
encodings[i] <= pseudoEncodingVideoScalingLevel9) {
|
||||
Server::videoScaling.setParam(encodings[i] - pseudoEncodingVideoScalingLevel0);
|
||||
clientparlog("videoScaling", encodings[i] - pseudoEncodingVideoScalingLevel0, true);
|
||||
}
|
||||
} else {
|
||||
if (encodings[i] >= pseudoEncodingJpegVideoQualityLevel0 &&
|
||||
encodings[i] <= pseudoEncodingJpegVideoQualityLevel9) {
|
||||
clientparlog("jpegVideoQuality", encodings[i] - pseudoEncodingJpegVideoQualityLevel0, false);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingWebpVideoQualityLevel0 &&
|
||||
encodings[i] <= pseudoEncodingWebpVideoQualityLevel9) {
|
||||
clientparlog("webpVideoQuality", encodings[i] - pseudoEncodingWebpVideoQualityLevel0, false);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingTreatLosslessLevel0 &&
|
||||
encodings[i] <= pseudoEncodingTreatLosslessLevel10) {
|
||||
clientparlog("treatLossless", encodings[i] - pseudoEncodingTreatLosslessLevel0, false);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingDynamicQualityMinLevel0 &&
|
||||
encodings[i] <= pseudoEncodingDynamicQualityMinLevel9) {
|
||||
clientparlog("dynamicQualityMin", encodings[i] - pseudoEncodingDynamicQualityMinLevel0, false);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingDynamicQualityMaxLevel0 &&
|
||||
encodings[i] <= pseudoEncodingDynamicQualityMaxLevel9) {
|
||||
clientparlog("dynamicQualityMax", encodings[i] - pseudoEncodingDynamicQualityMaxLevel0, false);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingVideoAreaLevel1 &&
|
||||
encodings[i] <= pseudoEncodingVideoAreaLevel100) {
|
||||
clientparlog("videoArea", encodings[i] - pseudoEncodingVideoAreaLevel1 + 1, false);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingVideoTimeLevel0 &&
|
||||
encodings[i] <= pseudoEncodingVideoTimeLevel100) {
|
||||
clientparlog("videoTime", encodings[i] - pseudoEncodingVideoTimeLevel0, false);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingVideoOutTimeLevel1 &&
|
||||
encodings[i] <= pseudoEncodingVideoOutTimeLevel100) {
|
||||
clientparlog("videoOutTime", encodings[i] - pseudoEncodingVideoOutTimeLevel1 + 1, false);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingFrameRateLevel10 &&
|
||||
encodings[i] <= pseudoEncodingFrameRateLevel60) {
|
||||
clientparlog("frameRate", encodings[i] - pseudoEncodingFrameRateLevel10 + 10, false);
|
||||
}
|
||||
|
||||
if (encodings[i] >= pseudoEncodingVideoScalingLevel0 &&
|
||||
encodings[i] <= pseudoEncodingVideoScalingLevel9) {
|
||||
clientparlog("videoScaling", encodings[i] - pseudoEncodingVideoScalingLevel0, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (encodings[i] > 0)
|
||||
|
||||
@@ -363,6 +363,9 @@ void EncodeManager::doUpdate(bool allowLossy, const Region& changed_,
|
||||
unsigned screenArea;
|
||||
|
||||
updates++;
|
||||
if (conn->cp.supportsUdp)
|
||||
((network::UdpStream *) conn->getOutStream(conn->cp.supportsUdp))->setFrameNumber(updates);
|
||||
|
||||
|
||||
// The video resolution may have changed, check it
|
||||
if (conn->cp.kasmPassed[ConnParams::KASM_MAX_VIDEO_RESOLUTION])
|
||||
@@ -420,9 +423,6 @@ void EncodeManager::doUpdate(bool allowLossy, const Region& changed_,
|
||||
nRects++;
|
||||
}
|
||||
|
||||
if (watermarkData)
|
||||
packWatermark(changed);
|
||||
|
||||
conn->writer()->writeFramebufferUpdateStart(nRects);
|
||||
|
||||
writeCopyRects(copied, copyDelta);
|
||||
@@ -440,7 +440,7 @@ void EncodeManager::doUpdate(bool allowLossy, const Region& changed_,
|
||||
if (!videoDetected) // In case detection happened between the calls
|
||||
writeRects(cursorRegion, renderedCursor);
|
||||
|
||||
if (watermarkData) {
|
||||
if (watermarkData && conn->sendWatermark()) {
|
||||
beforeLength = conn->getOutStream(conn->cp.supportsUdp)->length();
|
||||
|
||||
const Rect rect(0, 0, pb->width(), pb->height());
|
||||
|
||||
@@ -198,6 +198,10 @@ namespace rfb {
|
||||
std::vector<unsigned char> data;
|
||||
};
|
||||
|
||||
virtual bool sendWatermark() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
void setState(stateEnum s) { state_ = s; }
|
||||
|
||||
|
||||
@@ -171,6 +171,9 @@ void SMsgReader::readSetMaxVideoResolution()
|
||||
if (!rfb::Server::ignoreClientSettingsKasm && handler->canChangeKasmSettings()) {
|
||||
sprintf(tmp, "%ux%u", width, height);
|
||||
rfb::Server::maxVideoResolution.setParam(tmp);
|
||||
vlog.debug("Client sent config param maxVideoResolution %ux%u, applied", width, height);
|
||||
} else {
|
||||
vlog.debug("Client sent config param maxVideoResolution %ux%u, ignored due to -IgnoreClientSettingsKasm/lacking perms", width, height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ static LogWriter vlog("SMsgWriter");
|
||||
|
||||
SMsgWriter::SMsgWriter(ConnParams* cp_, rdr::OutStream* os_, rdr::OutStream* udps_)
|
||||
: cp(cp_), os(os_), udps(udps_),
|
||||
nRectsInUpdate(0), nRectsInHeader(0),
|
||||
nRectsInUpdate(0), dataRectsInUpdate(0), nRectsInHeader(0),
|
||||
needSetDesktopSize(false), needExtendedDesktopSize(false),
|
||||
needSetDesktopName(false), needSetCursor(false),
|
||||
needSetXCursor(false), needSetCursorWithAlpha(false),
|
||||
@@ -340,7 +340,7 @@ void SMsgWriter::writeFramebufferUpdateStart(int nRects)
|
||||
|
||||
os->writeU16(nRects);
|
||||
|
||||
nRectsInUpdate = 0;
|
||||
nRectsInUpdate = dataRectsInUpdate = 0;
|
||||
if (nRects == 0xFFFF)
|
||||
nRectsInHeader = 0;
|
||||
else
|
||||
@@ -365,7 +365,7 @@ void SMsgWriter::writeFramebufferUpdateEnd()
|
||||
|
||||
// Send an UDP flip marker, if needed
|
||||
if (cp->supportsUdp) {
|
||||
udps->writeS16(0);
|
||||
udps->writeS16(dataRectsInUpdate);
|
||||
udps->writeS16(0);
|
||||
udps->writeU16(0);
|
||||
udps->writeU16(0);
|
||||
@@ -394,6 +394,7 @@ void SMsgWriter::startRect(const Rect& r, int encoding)
|
||||
{
|
||||
if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
|
||||
throw Exception("SMsgWriter::startRect: nRects out of sync");
|
||||
++dataRectsInUpdate;
|
||||
|
||||
if (cp->supportsUdp) {
|
||||
udps->writeS16(r.tl.x);
|
||||
|
||||
@@ -165,6 +165,7 @@ namespace rfb {
|
||||
rdr::OutStream* udps;
|
||||
|
||||
int nRectsInUpdate;
|
||||
int dataRectsInUpdate;
|
||||
int nRectsInHeader;
|
||||
|
||||
bool needSetDesktopSize;
|
||||
|
||||
@@ -201,6 +201,10 @@ rfb::IntParameter rfb::Server::DLP_WatermarkTimeOffsetMinutes
|
||||
("DLP_WatermarkTimeOffsetMinutes",
|
||||
"Offset from UTC for -DLP_WatermarkText, minutes",
|
||||
0, -24 * 60, 24 * 60);
|
||||
rfb::IntParameter rfb::Server::DLP_WatermarkTextAngle
|
||||
("DLP_WatermarkTextAngle",
|
||||
"Angle for -DLP_WatermarkText rotation",
|
||||
0, -359, 359);
|
||||
rfb::StringParameter rfb::Server::DLP_WatermarkImage
|
||||
("DLP_WatermarkImage",
|
||||
"PNG file to use as a watermark",
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace rfb {
|
||||
static IntParameter DLP_WatermarkFontSize;
|
||||
static IntParameter DLP_WatermarkTimeOffset;
|
||||
static IntParameter DLP_WatermarkTimeOffsetMinutes;
|
||||
static IntParameter DLP_WatermarkTextAngle;
|
||||
static StringParameter DLP_ClipLog;
|
||||
static StringParameter DLP_Region;
|
||||
static StringParameter DLP_Clip_Types;
|
||||
|
||||
@@ -88,8 +88,8 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
|
||||
wordfree(&wexp);
|
||||
|
||||
user[0] = '\0';
|
||||
const char *at = strchr(peerEndpoint.buf, '@');
|
||||
if (at && at - peerEndpoint.buf > 1 && at - peerEndpoint.buf < 32) {
|
||||
const char *at = strrchr(peerEndpoint.buf, '@');
|
||||
if (at && at - peerEndpoint.buf > 1 && at - peerEndpoint.buf < USERNAME_LEN) {
|
||||
memcpy(user, peerEndpoint.buf, at - peerEndpoint.buf);
|
||||
user[at - peerEndpoint.buf] = '\0';
|
||||
}
|
||||
@@ -997,8 +997,8 @@ void VNCSConnectionST::setDesktopSize(int fb_width, int fb_height,
|
||||
{
|
||||
unsigned int result;
|
||||
|
||||
if (!(accessRights & AccessSetDesktopSize)) return;
|
||||
if (!rfb::Server::acceptSetDesktopSize) return;
|
||||
if (!(accessRights & AccessSetDesktopSize)) goto justnotify;
|
||||
if (!rfb::Server::acceptSetDesktopSize) goto justnotify;
|
||||
|
||||
// Don't bother the desktop with an invalid configuration
|
||||
if (!layout.validate(fb_width, fb_height)) {
|
||||
@@ -1021,6 +1021,14 @@ void VNCSConnectionST::setDesktopSize(int fb_width, int fb_height,
|
||||
throw Exception("Desktop configured a different screen layout than requested");
|
||||
server->notifyScreenLayoutChange(this);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
justnotify:
|
||||
writer()->writeExtendedDesktopSize(reasonClient, resultProhibited,
|
||||
server->pb->getRect().width(),
|
||||
server->pb->getRect().height(),
|
||||
server->screenLayout);
|
||||
}
|
||||
|
||||
void VNCSConnectionST::fence(rdr::U32 flags, unsigned len, const char data[])
|
||||
@@ -1635,7 +1643,7 @@ void VNCSConnectionST::sendStats(const bool toClient) {
|
||||
void VNCSConnectionST::handleFrameStats(rdr::U32 all, rdr::U32 render)
|
||||
{
|
||||
if (server->apimessager) {
|
||||
const char *at = strchr(peerEndpoint.buf, '@');
|
||||
const char *at = strrchr(peerEndpoint.buf, '@');
|
||||
if (!at)
|
||||
at = peerEndpoint.buf;
|
||||
else
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include <rfb/Timer.h>
|
||||
#include <rfb/unixRelayLimits.h>
|
||||
|
||||
#include "kasmpasswd.h"
|
||||
|
||||
namespace rfb {
|
||||
class VNCServerST;
|
||||
|
||||
@@ -213,6 +215,10 @@ namespace rfb {
|
||||
virtual void sendUnixRelayData(const char name[], const unsigned char *buf,
|
||||
const unsigned len);
|
||||
|
||||
bool sendWatermark() const {
|
||||
return server->sendWatermark;
|
||||
}
|
||||
|
||||
private:
|
||||
// SConnection callbacks
|
||||
|
||||
@@ -318,7 +324,7 @@ namespace rfb {
|
||||
rdr::U64 bstats_total[BS_NUM];
|
||||
struct timeval connStart;
|
||||
|
||||
char user[32];
|
||||
char user[USERNAME_LEN];
|
||||
char kasmpasswdpath[4096];
|
||||
bool needsPermCheck;
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_)
|
||||
queryConnectionHandler(0), keyRemapper(&KeyRemapper::defInstance),
|
||||
lastConnectionTime(0), disableclients(false),
|
||||
frameTimer(this), apimessager(NULL), trackingFrameStats(0),
|
||||
clipboardId(0)
|
||||
clipboardId(0), sendWatermark(false)
|
||||
{
|
||||
lastUserInputTime = lastDisconnectTime = time(0);
|
||||
slog.debug("creating single-threaded server %s", name.buf);
|
||||
@@ -223,6 +223,9 @@ VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_)
|
||||
|
||||
trackingClient[0] = 0;
|
||||
|
||||
if (watermarkData)
|
||||
sendWatermark = true;
|
||||
|
||||
if (Server::selfBench)
|
||||
SelfBench();
|
||||
}
|
||||
@@ -279,6 +282,9 @@ void VNCServerST::addSocket(network::Socket* sock, bool outgoing)
|
||||
|
||||
VNCSConnectionST* client = new VNCSConnectionST(this, sock, outgoing);
|
||||
client->init();
|
||||
|
||||
if (watermarkData)
|
||||
sendWatermark = true;
|
||||
}
|
||||
|
||||
void VNCServerST::removeSocket(network::Socket* sock) {
|
||||
@@ -814,7 +820,7 @@ static void upgradeClientToUdp(const network::GetAPIMessager::action_data &act,
|
||||
inet_ntop(AF_INET, &act.udp.ip, buf, 32);
|
||||
|
||||
const char * const who = (*ci)->getPeerEndpoint();
|
||||
const char *start = strchr(who, '@');
|
||||
const char *start = strrchr(who, '@');
|
||||
if (!start)
|
||||
continue;
|
||||
start++;
|
||||
@@ -975,8 +981,8 @@ void VNCServerST::writeUpdate()
|
||||
}
|
||||
|
||||
if (watermarkData && Server::DLP_WatermarkText[0] && watermarkTextNeedsUpdate(true)) {
|
||||
// If using a text watermark, we have to mark everything as changed...
|
||||
refreshClients();
|
||||
// The text may have changed
|
||||
sendWatermark = true;
|
||||
}
|
||||
|
||||
comparer->getUpdateInfo(&ui, pb->getRect());
|
||||
@@ -1104,6 +1110,8 @@ void VNCServerST::writeUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
sendWatermark = false; // the client now caches it, only send once
|
||||
|
||||
if (trackingFrameStats) {
|
||||
if (enctime) {
|
||||
const unsigned totalMs = msSince(&start);
|
||||
|
||||
@@ -290,6 +290,8 @@ namespace rfb {
|
||||
|
||||
void checkAPIMessages(network::GetAPIMessager *apimessager,
|
||||
rdr::U8 &trackingFrameStats, char trackingClient[]);
|
||||
|
||||
bool sendWatermark;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <png.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -28,6 +29,7 @@
|
||||
#include "font.h"
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_GLYPH_H
|
||||
|
||||
#include "Watermark.h"
|
||||
|
||||
@@ -187,6 +189,149 @@ static uint32_t drawnwidth(const char *txt) {
|
||||
return x;
|
||||
}
|
||||
|
||||
static void angle2mat(FT_Matrix &mat) {
|
||||
const float angle = Server::DLP_WatermarkTextAngle / 360.f * 2 * -3.14159f;
|
||||
|
||||
mat.xx = (FT_Fixed)( cosf(angle) * 0x10000L);
|
||||
mat.xy = (FT_Fixed)(-sinf(angle) * 0x10000L);
|
||||
mat.yx = (FT_Fixed)( sinf(angle) * 0x10000L);
|
||||
mat.yy = (FT_Fixed)( cosf(angle) * 0x10000L);
|
||||
}
|
||||
|
||||
// Note: w and h are absolute
|
||||
static void angledstr(uint8_t *buf, const char *txt, const uint32_t x_, const uint32_t y_,
|
||||
const uint32_t w, const uint32_t h,
|
||||
const uint32_t stride, const bool invx, const bool invy) {
|
||||
|
||||
unsigned ucs[256], i, ucslen;
|
||||
unsigned len = strlen(txt);
|
||||
i = 0;
|
||||
ucslen = 0;
|
||||
while (len > 0 && txt[i]) {
|
||||
size_t ret = rfb::utf8ToUCS4(&txt[i], len, &ucs[ucslen]);
|
||||
i += ret;
|
||||
len -= ret;
|
||||
ucslen++;
|
||||
}
|
||||
|
||||
FT_Matrix mat;
|
||||
FT_Vector pen;
|
||||
|
||||
angle2mat(mat);
|
||||
|
||||
pen.x = 0;
|
||||
pen.y = 0;
|
||||
|
||||
uint32_t x, y;
|
||||
|
||||
x = x_;
|
||||
y = y_;
|
||||
for (i = 0; i < ucslen; i++) {
|
||||
FT_Set_Transform(face, &mat, &pen);
|
||||
|
||||
if (FT_Load_Char(face, ucs[i], FT_LOAD_RENDER))
|
||||
continue;
|
||||
const FT_Bitmap * const map = &(face->glyph->bitmap);
|
||||
|
||||
uint32_t row, col;
|
||||
for (row = 0; row < (uint32_t) map->rows; row++) {
|
||||
int ny = row + y - face->glyph->bitmap_top;
|
||||
if (ny < 0)
|
||||
continue;
|
||||
if ((unsigned) ny >= h)
|
||||
continue;
|
||||
|
||||
uint8_t *dst = (uint8_t *) buf;
|
||||
dst += ny * stride + x;
|
||||
|
||||
const uint8_t *src = map->buffer + map->pitch * row;
|
||||
for (col = 0; col < (uint32_t) map->width; col++) {
|
||||
if (col + x >= w)
|
||||
continue;
|
||||
const uint8_t out = (src[col] + 8) >> 4;
|
||||
dst[col] |= out < 16 ? out : 15;
|
||||
}
|
||||
}
|
||||
|
||||
x += face->glyph->advance.x >> 6;
|
||||
|
||||
pen.x += face->glyph->advance.x;
|
||||
pen.y += face->glyph->advance.y;
|
||||
}
|
||||
}
|
||||
|
||||
static void angledsize(const char *txt, uint32_t &w, uint32_t &h,
|
||||
uint32_t &recw, uint32_t &recy,
|
||||
bool &invx, bool &invy) {
|
||||
|
||||
unsigned ucs[256], i, ucslen;
|
||||
unsigned len = strlen(txt);
|
||||
i = 0;
|
||||
ucslen = 0;
|
||||
while (len > 0 && txt[i]) {
|
||||
size_t ret = rfb::utf8ToUCS4(&txt[i], len, &ucs[ucslen]);
|
||||
i += ret;
|
||||
len -= ret;
|
||||
ucslen++;
|
||||
}
|
||||
|
||||
FT_Matrix mat;
|
||||
FT_Vector pen;
|
||||
|
||||
angle2mat(mat);
|
||||
|
||||
pen.x = 0;
|
||||
pen.y = 0;
|
||||
|
||||
FT_BBox firstbox, lastbox;
|
||||
|
||||
for (i = 0; i < ucslen; i++) {
|
||||
FT_Set_Transform(face, &mat, &pen);
|
||||
|
||||
if (FT_Load_Char(face, ucs[i], FT_LOAD_DEFAULT))
|
||||
continue;
|
||||
|
||||
if (i == 0) {
|
||||
FT_Glyph glyph;
|
||||
|
||||
FT_Get_Glyph(face->glyph, &glyph);
|
||||
FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &firstbox);
|
||||
FT_Done_Glyph(glyph);
|
||||
|
||||
// recommended y; if the angle is steep enough, use the X bearing
|
||||
#define EDGE 22
|
||||
const int angle = abs(Server::DLP_WatermarkTextAngle);
|
||||
if ((angle > (45 + EDGE) && angle < (135 - EDGE)) ||
|
||||
(angle > (225 + EDGE) && angle < (315 - EDGE)))
|
||||
recy = face->glyph->metrics.horiBearingX >> 6;
|
||||
else
|
||||
recy = face->glyph->metrics.horiBearingY >> 6;
|
||||
#undef EDGE
|
||||
} else if (i == ucslen - 1) {
|
||||
FT_Glyph glyph;
|
||||
|
||||
FT_Get_Glyph(face->glyph, &glyph);
|
||||
FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &lastbox);
|
||||
FT_Done_Glyph(glyph);
|
||||
}
|
||||
|
||||
if (i != ucslen - 1) {
|
||||
pen.x += face->glyph->advance.x;
|
||||
pen.y += face->glyph->advance.y;
|
||||
}
|
||||
}
|
||||
|
||||
// recommended width, used when X is inverted
|
||||
recw = face->size->metrics.max_advance >> 6;
|
||||
|
||||
// The used area is an union of first box, last box, and their relative distance
|
||||
invx = pen.x < 0;
|
||||
invy = pen.y > 0;
|
||||
|
||||
w = (firstbox.xMax - firstbox.xMin) + (lastbox.xMax - lastbox.xMin) + abs(pen.x >> 6);
|
||||
h = (firstbox.yMax - firstbox.yMin) + (lastbox.yMax - lastbox.yMin) + abs(pen.y >> 6);
|
||||
}
|
||||
|
||||
static bool drawtext(const char fmt[], const int16_t utcOff, const char fontpath[],
|
||||
const uint8_t fontsize) {
|
||||
char buf[PATH_MAX];
|
||||
@@ -213,14 +358,33 @@ static bool drawtext(const char fmt[], const int16_t utcOff, const char fontpath
|
||||
return false;
|
||||
|
||||
free(watermarkInfo.src);
|
||||
const uint32_t h = fontsize + 4;
|
||||
const uint32_t w = drawnwidth(buf);
|
||||
if (Server::DLP_WatermarkTextAngle) {
|
||||
uint32_t w, h, recw, recy = fontsize;
|
||||
bool invx, invy;
|
||||
angledsize(buf, w, h, recw, recy, invx, invy);
|
||||
|
||||
watermarkInfo.w = w;
|
||||
watermarkInfo.h = h;
|
||||
watermarkInfo.src = (uint8_t *) calloc(w, h);
|
||||
// The max is because a rotated text with the time can change size.
|
||||
// With the max op, at least it will only grow instead of bouncing.
|
||||
w = __rfbmax(w, watermarkInfo.w);
|
||||
h = __rfbmax(h, watermarkInfo.h);
|
||||
|
||||
str(watermarkInfo.src, buf, 0, fontsize, w, h, w);
|
||||
watermarkInfo.w = w;
|
||||
watermarkInfo.h = h;
|
||||
watermarkInfo.src = (uint8_t *) calloc(w, h);
|
||||
|
||||
angledstr(watermarkInfo.src, buf,
|
||||
invx ? w - recw: 0, invy ? h - recy : recy,
|
||||
w, h, w, invx, invy);
|
||||
} else {
|
||||
const uint32_t h = fontsize + 4;
|
||||
const uint32_t w = drawnwidth(buf);
|
||||
|
||||
watermarkInfo.w = w;
|
||||
watermarkInfo.h = h;
|
||||
watermarkInfo.src = (uint8_t *) calloc(w, h);
|
||||
|
||||
str(watermarkInfo.src, buf, 0, fontsize, w, h, w);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -279,6 +443,31 @@ bool watermarkInit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void packWatermark() {
|
||||
// Take the expanded 4-bit data, filter it by the changed rects, pack
|
||||
// to shared bytes, and compress with zlib
|
||||
|
||||
uint16_t x, y;
|
||||
uint8_t pix[2], cur = 0;
|
||||
uint8_t *dst = watermarkTmp;
|
||||
|
||||
for (y = 0; y < rh; y++) {
|
||||
for (x = 0; x < rw; x++) {
|
||||
pix[cur] = watermarkUnpacked[y * rw + x];
|
||||
if (cur || (y == rh - 1 && x == rw - 1))
|
||||
*dst++ = pix[0] | (pix[1] << 4);
|
||||
|
||||
cur ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
uLong destLen = MAXW * MAXH / 2;
|
||||
if (compress2(watermarkData, &destLen, watermarkTmp, rw * rh / 2 + 1, 1) != Z_OK)
|
||||
vlog.error("Zlib compression error");
|
||||
|
||||
watermarkDataLen = destLen;
|
||||
}
|
||||
|
||||
// update the screen-size rendered watermark whenever the screen is resized
|
||||
// or if using text, every frame
|
||||
void VNCServerST::updateWatermark() {
|
||||
@@ -359,48 +548,10 @@ void VNCServerST::updateWatermark() {
|
||||
rw - sx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void packWatermark(const Region &changed) {
|
||||
// Take the expanded 4-bit data, filter it by the changed rects, pack
|
||||
// to shared bytes, and compress with zlib
|
||||
packWatermark();
|
||||
|
||||
uint16_t x, y;
|
||||
uint8_t pix[2], cur = 0;
|
||||
uint8_t *dst = watermarkTmp;
|
||||
|
||||
const Rect &bounding = changed.get_bounding_rect();
|
||||
|
||||
for (y = 0; y < rh; y++) {
|
||||
// Is the entire line outside the changed area?
|
||||
if (bounding.tl.y > y || bounding.br.y < y) {
|
||||
for (x = 0; x < rw; x++) {
|
||||
pix[cur] = 0;
|
||||
|
||||
if (cur || (y == rh - 1 && x == rw - 1))
|
||||
*dst++ = pix[0] | (pix[1] << 4);
|
||||
|
||||
cur ^= 1;
|
||||
}
|
||||
} else {
|
||||
for (x = 0; x < rw; x++) {
|
||||
pix[cur] = 0;
|
||||
if (bounding.contains(Point(x, y)) && changed.contains(x, y))
|
||||
pix[cur] = watermarkUnpacked[y * rw + x];
|
||||
|
||||
if (cur || (y == rh - 1 && x == rw - 1))
|
||||
*dst++ = pix[0] | (pix[1] << 4);
|
||||
|
||||
cur ^= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uLong destLen = MAXW * MAXH / 2;
|
||||
if (compress2(watermarkData, &destLen, watermarkTmp, rw * rh / 2 + 1, 1) != Z_OK)
|
||||
vlog.error("Zlib compression error");
|
||||
|
||||
watermarkDataLen = destLen;
|
||||
sendWatermark = true;
|
||||
}
|
||||
|
||||
// Limit changes to once per second
|
||||
@@ -412,5 +563,5 @@ bool watermarkTextNeedsUpdate(const bool early) {
|
||||
if (early)
|
||||
now = time(NULL);
|
||||
|
||||
return now != lastUpdate;
|
||||
return now != lastUpdate && strchr(Server::DLP_WatermarkText, '%');
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ struct watermarkInfo_t {
|
||||
extern watermarkInfo_t watermarkInfo;
|
||||
|
||||
bool watermarkInit();
|
||||
void packWatermark(const rfb::Region &changed); // filter and pack the watermark for sending
|
||||
bool watermarkTextNeedsUpdate(const bool early);
|
||||
|
||||
extern uint8_t *watermarkData;
|
||||
|
||||
12
debian/changelog
vendored
12
debian/changelog
vendored
@@ -1,9 +1,13 @@
|
||||
kasmvnc (1.2.1-1) unstable; urgency=medium
|
||||
kasmvnc (1.3.0-1) unstable; urgency=medium
|
||||
|
||||
* Fix exception with Firefox 124 and later
|
||||
* Fix bug with watermarking on odd resolutions
|
||||
* Multi-monitor support.
|
||||
* Increased performance with watermark enabled.
|
||||
* Added support for Fedora 39 and Alpine 319.
|
||||
* Allow special characters in usernames.
|
||||
* Better logging of client settings when client connects or changes settings.
|
||||
* Add support for rotation of text-based watermark.
|
||||
|
||||
-- Kasm Technologies LLC <info@kasmweb.com> Tue, 12 Mar 2023 11:38:00 +0000
|
||||
-- Kasm Technologies LLC <info@kasmweb.com> Mon, 02 Feb 2024 14:33:00 +0000
|
||||
|
||||
kasmvnc (1.2.0-1) unstable; urgency=medium
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: kasmvncserver
|
||||
Version: 1.2.1
|
||||
Version: 1.3.0
|
||||
Release: 1%{?dist}
|
||||
Summary: VNC server accessible from a web browser
|
||||
|
||||
@@ -83,9 +83,13 @@ cd $DST_MAN && ln -s vncpasswd.1 kasmvncpasswd.1;
|
||||
%doc /usr/share/doc/kasmvncserver/README.md
|
||||
|
||||
%changelog
|
||||
* Tue Mar 12 2024 KasmTech <info@kasmweb.com> - 1.2.1-1
|
||||
- Fix exception with Firefox 124 and later
|
||||
- Fix bug with watermarking on odd resolutions
|
||||
* Mon Feb 05 2024 KasmTech <info@kasmweb.com> - 1.3.0-1
|
||||
- Multi-monitor support.
|
||||
- Increased performance with watermark enabled.
|
||||
- Added support for Fedora 39 and Alpine 319.
|
||||
- Allow special characters in usernames.
|
||||
- Better logging of client settings when client connects or changes settings.
|
||||
- Add support for rotation of text-based watermark.
|
||||
* Fri Aug 25 2023 KasmTech <info@kasmweb.com> - 1.2.0-1
|
||||
- Add support for Unix relays for bidirectional communication between noVNC
|
||||
and containerized applications.
|
||||
|
||||
2
kasmweb
2
kasmweb
Submodule kasmweb updated: b4ce24e51f...958a60b947
@@ -1,5 +1,5 @@
|
||||
Name: kasmvncserver
|
||||
Version: 1.2.1
|
||||
Version: 1.3.0
|
||||
Release: leap15
|
||||
Summary: VNC server accessible from a web browser
|
||||
|
||||
@@ -81,9 +81,13 @@ cd $DST_MAN && ln -s vncpasswd.1 kasmvncpasswd.1;
|
||||
%doc /usr/share/doc/kasmvncserver/README.md
|
||||
|
||||
%changelog
|
||||
* Tue Mar 12 2024 KasmTech <info@kasmweb.com> - 1.2.1-1
|
||||
- Fix exception with Firefox 124 and later
|
||||
- Fix bug with watermarking on odd resolutions
|
||||
* Mon Feb 05 2024 KasmTech <info@kasmweb.com> - 1.3.0-1
|
||||
- Multi-monitor support.
|
||||
- Increased performance with watermark enabled.
|
||||
- Added support for Fedora 39 and Alpine 319.
|
||||
- Allow special characters in usernames.
|
||||
- Better logging of client settings when client connects or changes settings.
|
||||
- Add support for rotation of text-based watermark.
|
||||
* Fri Aug 25 2023 KasmTech <info@kasmweb.com> - 1.2.0-leap15
|
||||
- Add support for Unix relays for bidirectional communication between noVNC
|
||||
and containerized applications.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: kasmvncserver
|
||||
Version: 1.2.1
|
||||
Version: 1.3.0
|
||||
Release: 1%{?dist}
|
||||
Summary: VNC server accessible from a web browser
|
||||
|
||||
@@ -82,9 +82,13 @@ cd $DST_MAN && ln -s vncpasswd.1 kasmvncpasswd.1;
|
||||
%doc /usr/share/doc/kasmvncserver/README.md
|
||||
|
||||
%changelog
|
||||
* Tue Mar 12 2024 KasmTech <info@kasmweb.com> - 1.2.1-1
|
||||
- Fix exception with Firefox 124 and later
|
||||
- Fix bug with watermarking on odd resolutions
|
||||
* Mon Feb 05 2024 KasmTech <info@kasmweb.com> - 1.3.0-1
|
||||
- Multi-monitor support.
|
||||
- Increased performance with watermark enabled.
|
||||
- Added support for Fedora 39 and Alpine 319.
|
||||
- Allow special characters in usernames.
|
||||
- Better logging of client settings when client connects or changes settings.
|
||||
- Add support for rotation of text-based watermark.
|
||||
* Fri Aug 25 2023 KasmTech <info@kasmweb.com> - 1.2.0-1
|
||||
- Add support for Unix relays for bidirectional communication between noVNC
|
||||
and containerized applications.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: kasmvncserver
|
||||
Version: 1.2.1
|
||||
Version: 1.3.0
|
||||
Release: 1%{?dist}
|
||||
Summary: VNC server accessible from a web browser
|
||||
|
||||
@@ -82,9 +82,13 @@ cd $DST_MAN && ln -s vncpasswd.1 kasmvncpasswd.1;
|
||||
%doc /usr/share/doc/kasmvncserver/README.md
|
||||
|
||||
%changelog
|
||||
* Tue Mar 12 2024 KasmTech <info@kasmweb.com> - 1.2.1-1
|
||||
- Fix exception with Firefox 124 and later
|
||||
- Fix bug with watermarking on odd resolutions
|
||||
* Mon Feb 05 2024 KasmTech <info@kasmweb.com> - 1.3.0-1
|
||||
- Multi-monitor support.
|
||||
- Increased performance with watermark enabled.
|
||||
- Added support for Fedora 39 and Alpine 319.
|
||||
- Allow special characters in usernames.
|
||||
- Better logging of client settings when client connects or changes settings.
|
||||
- Add support for rotation of text-based watermark.
|
||||
* Fri Aug 25 2023 KasmTech <info@kasmweb.com> - 1.2.0-1
|
||||
- Add support for Unix relays for bidirectional communication between noVNC
|
||||
and containerized applications.
|
||||
|
||||
6
spec/fixtures/defaults_config.yaml
vendored
6
spec/fixtures/defaults_config.yaml
vendored
@@ -50,6 +50,12 @@ data_loss_prevention:
|
||||
# location: 10,10
|
||||
# tint: 255,20,20,128
|
||||
# repeat_spacing: 10
|
||||
#text:
|
||||
# template: "${USER} %H:%M"
|
||||
# font: auto
|
||||
# font_size: 48
|
||||
# timezone_name: Australia/Adelaide
|
||||
# angle: 0
|
||||
logging:
|
||||
level: off
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ data_loss_prevention:
|
||||
# font: auto
|
||||
# font_size: 48
|
||||
# timezone_name: Australia/Adelaide
|
||||
# angle: 0
|
||||
logging:
|
||||
# "verbose" SETTING LOGS YOUR PRIVATE INFORMATION. Keypresses and clipboard content
|
||||
level: off
|
||||
|
||||
@@ -6,7 +6,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
struct kasmpasswd_entry_t {
|
||||
char user[32];
|
||||
char user[128];
|
||||
char password[128];
|
||||
unsigned char read : 1;
|
||||
unsigned char write : 1;
|
||||
|
||||
@@ -669,9 +669,10 @@ sub RunXstartup {
|
||||
DetectAndExportDisplay();
|
||||
$ENV{VNCDESKTOP}= $desktopName;
|
||||
|
||||
my $xstartupCmd = "{ echo 'Running $xstartupFile'; $xstartupFile; }";
|
||||
if ($opt{'-fg'}) {
|
||||
if (! $skipxstartup) {
|
||||
system("$xstartupFile >> " . quotedString($desktopLog) . " 2>&1");
|
||||
system("$xstartupCmd >> " . quotedString($desktopLog) . " 2>&1");
|
||||
}
|
||||
if (IsXvncRunning()) {
|
||||
$opt{'-kill'} = ':'.$displayNumber;
|
||||
@@ -680,12 +681,12 @@ sub RunXstartup {
|
||||
} else {
|
||||
if ($opt{'-autokill'}) {
|
||||
if (! $skipxstartup) {
|
||||
system("($xstartupFile; $0 -kill :$displayNumber) >> "
|
||||
system("($xstartupCmd; $0 -kill :$displayNumber) >> "
|
||||
. quotedString($desktopLog) . " 2>&1 &");
|
||||
}
|
||||
} else {
|
||||
if (! $skipxstartup) {
|
||||
system("$xstartupFile >> " . quotedString($desktopLog)
|
||||
system("$xstartupCmd >> " . quotedString($desktopLog)
|
||||
. " 2>&1 &");
|
||||
}
|
||||
}
|
||||
@@ -1861,6 +1862,24 @@ sub DefineConfigToCLIConversion {
|
||||
$offset_in_seconds/60;
|
||||
}
|
||||
}),
|
||||
KasmVNC::CliOption->new({
|
||||
name => 'DLP_WatermarkTextAngle',
|
||||
configKeys => [
|
||||
KasmVNC::ConfigKey->new({
|
||||
name => "data_loss_prevention.watermark.text.angle",
|
||||
validator => KasmVNC::CallbackValidator->new({
|
||||
isValidCallback => sub {
|
||||
my $value = shift;
|
||||
|
||||
return 0 unless $value =~ /^-?\d+$/;
|
||||
|
||||
$value >= -359 && $value <= 359;
|
||||
},
|
||||
errorMessage => "must be in range -359..359"
|
||||
}),
|
||||
})
|
||||
]
|
||||
}),
|
||||
KasmVNC::CliOption->new({
|
||||
name => 'DLP_Log',
|
||||
configKeys => [
|
||||
|
||||
@@ -43,9 +43,9 @@ vncserver :13
|
||||
.RE
|
||||
|
||||
vncserver can detect desktop environments and prompt the user to select one to
|
||||
start with the session. The user can also manually edit the file
|
||||
$HOME/.vnc/xstartup to customize what commands should be run on startup of a
|
||||
new session.
|
||||
start with the session. The user can also manually edit the file
|
||||
$HOME/.vnc/xstartup to customize what commands should be run on startup of a
|
||||
new session.
|
||||
|
||||
.SH OPTIONS
|
||||
You can get a list of options by passing \fB\-h\fP as an option to vncserver.
|
||||
@@ -54,11 +54,18 @@ passed to Xvnc - see the Xvnc man page, or "Xvnc \-help", for details.
|
||||
|
||||
.TP
|
||||
.B \-select-de [\fIde_name\fP]
|
||||
Select Desktop Enviromnent to run. Cinnamon, Mate, LXDE, LXQT, KDE, Gnome, XFCE
|
||||
are supported. If \fIde_name\fP isn't specified, a text UI prompt to select a
|
||||
Desktop Enviromnent will be shown.
|
||||
Select Desktop Enviromnent to run. Cinnamon, Mate, LXDE, LXQT, KDE, Gnome, XFCE,
|
||||
are supported.
|
||||
|
||||
To trigger a text UI prompt to select a Desktop Enviromnent, run \fBvncserver\fP
|
||||
for the first time, or pass this option without arguments. To bypass the prompt,
|
||||
pass this option with the Desktop Enviromnent argument.
|
||||
Warning: $HOME/.vnc/xstartup will be overwritten.
|
||||
|
||||
To run a custom setup (not one of the supported Desktop Enviromnents), create
|
||||
$HOME/.vnc/xstartup executable and specify \fB\-select-de manual\fP to signify you
|
||||
don't want its contents to be auto-generated.
|
||||
|
||||
.TP
|
||||
.B \-geometry \fIwidth\fPx\fIheight\fP
|
||||
Specify the size of the VNC desktop to be created. Default is 1024x768.
|
||||
|
||||
@@ -384,6 +384,10 @@ Instead of an image, render this text as the watermark. Takes time formatting op
|
||||
for \fBstrftime\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-DLP_WatermarkTextAngle \fIangle\fP
|
||||
Rotate the text by this many degrees, increasing clockwise. Default \fB0\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-DLP_WatermarkFont \fI/path/to/font.ttf\fP
|
||||
Use a different font for -DLP_WatermarkText than the bundled one. TTF and OTF fonts
|
||||
are accepted.
|
||||
|
||||
@@ -96,7 +96,7 @@ from the X Consortium.
|
||||
#include "version-config.h"
|
||||
#include "site.h"
|
||||
|
||||
#define XVNCVERSION "KasmVNC 1.2.1"
|
||||
#define XVNCVERSION "KasmVNC 1.3.0"
|
||||
#define XVNCCOPYRIGHT ("Copyright (C) 1999-2018 KasmVNC Team and many others (see README.me)\n" \
|
||||
"See http://kasmweb.com for information on KasmVNC.\n")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user