Merge branch 'master' into feature/KASM-3747-optional-systemd-start

This commit is contained in:
Dmitry Maksyoma 2025-10-23 15:19:15 +13:00
commit c1dda78ea2
No known key found for this signature in database
290 changed files with 9242 additions and 20597 deletions

View file

@ -10,10 +10,13 @@ use Data::Dumper;
use KasmVNC::DataClumpValidator;
use KasmVNC::Utils;
use KasmVNC::SettingValidation;
our $fetchValueSub;
$KasmVNC::CliOption::dataClumpValidator = KasmVNC::DataClumpValidator->new();
@KasmVNC::CliOption::isActiveCallbacks = ();
our @ISA = ('KasmVNC::SettingValidation');
our $ConfigValue;
our $dataClumpValidator = KasmVNC::DataClumpValidator->new();
our @isActiveCallbacks = ();
sub new {
my ($class, $args) = @_;
@ -56,20 +59,20 @@ sub activate {
sub beforeIsActive {
my $callback = shift;
push @KasmVNC::CliOption::isActiveCallbacks, $callback;
push @isActiveCallbacks, $callback;
}
sub isActiveByCallbacks {
my $self = shift;
all { $_->($self) } @KasmVNC::CliOption::isActiveCallbacks;
all { $_->($self) } @isActiveCallbacks;
}
sub makeKeysWithValuesAccessible {
my $self = shift;
foreach my $name (@{ $self->configKeyNames() }) {
my $value = $self->fetchValue($name);
my $value = $ConfigValue->($name);
$self->{$name} = $value if defined($value);
}
}
@ -100,39 +103,11 @@ sub deriveValue {
my $self = shift;
my $value = $self->{deriveValueSub}->($self);
$self->interpolateEnvVars($value);
}
sub interpolateEnvVars {
my $self = shift;
my $value = shift;
return $value unless defined($value);
while ($value =~ /\$\{(\w+)\}/) {
my $envValue = $ENV{$1};
$value =~ s/\Q$&\E/$envValue/;
}
$value;
}
sub errorMessages {
my $self = shift;
join "\n", @{ $self->{errors} };
interpolateEnvVars($value);
}
# private
sub isValid {
my $self = shift;
$self->validate() unless $self->{validated};
$self->isNoErrorsPresent();
}
sub validate {
my $self = shift;
@ -142,22 +117,16 @@ sub validate {
$self->{validated} = 1;
}
sub isNoErrorsPresent {
my $self = shift;
scalar @{ $self->{errors} } == 0;
}
sub validateDataClump {
my $self = shift;
$KasmVNC::CliOption::dataClumpValidator->validate($self);
$dataClumpValidator->validate($self);
}
sub configValues {
my $self = shift;
map { $self->fetchValue($_->{name}) } @{ $self->{configKeys} };
map { $ConfigValue->($_->{name}) } @{ $self->{configKeys} };
}
sub configValue {
@ -183,22 +152,10 @@ sub hasKey {
first { $_ eq $configKey } @{ $self->configKeyNames() };
}
sub addErrorMessage {
my ($self, $errorMessage) = @_;
push @{ $self->{errors} }, $errorMessage;
}
sub validateConfigValues {
my $self = shift;
map { $_->validate($self) } @{ $self->{configKeys} };
}
sub fetchValue {
my $self = shift;
&$fetchValueSub(shift);
}
1;

View file

@ -53,6 +53,14 @@ sub get {
$value;
}
sub set {
my ($self, $absoluteKey, $value) = @_;
my $path = absoluteKeyToHashPath($absoluteKey);
my $config = $self->{data};
eval "\$config$path = \$value";
}
sub exists {
my ($self, $absoluteKey) = @_;
my $path = absoluteKeyToHashPath($absoluteKey);

View file

@ -0,0 +1,119 @@
package KasmVNC::ConfigEnvVars;
use strict;
use warnings;
use v5.10;
use Data::Dumper;
use Exporter;
@KasmVNC::ConfigEnvVars::ISA = qw(Exporter);
our @EXPORT = (
'OverrideConfigWithConfigEnvVars',
'CheckForUnsupportedConfigEnvVars'
);
use constant ENV_VAR_OVERRIDE_SETTING => "server.allow_environment_variables_to_override_config_settings";
our @configKeyOverrideDenylist = (
ENV_VAR_OVERRIDE_SETTING
);
our $logger;
our %prefixedEnvVars;
our %envVarAllowlist;
our $ConfigValue;
our $SetConfigValue;
our $ShouldPrintTopic;
our $SupportedAbsoluteKeys;
sub IsAllowEnvVarOverride {
my $allowOverride = $ConfigValue->(ENV_VAR_OVERRIDE_SETTING) // "false";
$allowOverride eq "true";
}
sub OverrideConfigWithConfigEnvVars {
return unless IsAllowEnvVarOverride();
%prefixedEnvVars = FetchPrefixedEnvVarsFromEnvironment();
PrepareEnvVarAllowlist();
for my $envVarName (sort keys %prefixedEnvVars) {
my $configKey = $envVarAllowlist{$envVarName};
next unless defined($configKey);
my $envVarValue = GetEnvVarValue($envVarName);
$logger->debug("Overriding $configKey with $envVarName=$envVarValue");
$SetConfigValue->($configKey, $envVarValue);
}
}
sub GetEnvVarValue {
my $envVarName = shift;
$prefixedEnvVars{$envVarName};
}
sub PrepareEnvVarAllowlist {
%envVarAllowlist = ();
my %configKeyOverrideAllowlist = %{ ConfigKeyOverrideAllowlist() };
for my $configKey (keys %configKeyOverrideAllowlist) {
my $allowedEnvVarName = ConvertConfigKeyToEnvVarName($configKey);
$envVarAllowlist{$allowedEnvVarName} = $configKey;
}
}
sub ConfigKeyOverrideAllowlist {
my %configKeyOverrideAllowlist = %{ $SupportedAbsoluteKeys->() };
delete @configKeyOverrideAllowlist{@configKeyOverrideDenylist};
\%configKeyOverrideAllowlist;
}
sub FetchPrefixedEnvVarsFromEnvironment {
my %prefixedEnvVars = map { $_ => $ENV{$_} } grep { /^KVNC_/ } keys %ENV;
PrintPrefixedEnvVars();
%prefixedEnvVars;
}
sub ConvertConfigKeyToEnvVarName {
my $configKey = shift;
my $envVarName = $configKey;
$envVarName =~ s/\./_/g;
$envVarName = "KVNC_$envVarName";
$envVarName = uc $envVarName;
$logger->debug("$configKey -> $envVarName");
$envVarName;
}
sub PrintPrefixedEnvVars {
$logger->debug("Found KVNC_ env vars:");
for my $envVarName (sort keys %prefixedEnvVars) {
$logger->debug("$envVarName=$prefixedEnvVars{$envVarName}");
}
}
sub CheckForUnsupportedConfigEnvVars {
return unless IsAllowEnvVarOverride();
my @unsupportedEnvVars =
grep(!defined($envVarAllowlist{$_}), keys %prefixedEnvVars);
return if (scalar @unsupportedEnvVars == 0);
if ($ShouldPrintTopic->("validation")) {
$logger->warn("Unsupported config env vars found:");
$logger->warn(join("\n", @unsupportedEnvVars));
$logger->warn();
}
exit 1;
}
1;

View file

@ -8,7 +8,7 @@ use Data::Dumper;
use KasmVNC::Utils;
our $fetchValueSub;
our $ConfigValue;
use constant {
INT => 0,
@ -32,13 +32,6 @@ sub validate {
return if $self->isValueBlank();
if ($self->{validator}) {
$self->resolveValidatorFromFunction() if (ref $self->{validator} eq "CODE");
$self->{validator}->validate($self);
return;
}
switch($self->{type}) {
case INT {
$self->validateInt();
@ -47,6 +40,13 @@ sub validate {
$self->validateBoolean();
}
}
if ($self->{validator}) {
$self->resolveValidatorFromFunction() if (ref $self->{validator} eq "CODE");
$self->{validator}->validate($self);
return;
}
}
sub resolveValidatorFromFunction {
@ -86,18 +86,12 @@ sub isValueBlank {
!defined($value) || $value eq "";
}
sub fetchValue {
my $self = shift;
&$fetchValueSub(shift);
}
sub constructErrorMessage {
my $self = shift;
my $staticErrorMessage = shift;
my $name = $self->{name};
my $value = join ", ", @{ listify($self->fetchValue($name)) };
my $value = join ", ", @{ listify($ConfigValue->($name)) };
"$name '$value': $staticErrorMessage";
}
@ -117,7 +111,7 @@ sub isValidBoolean {
sub value {
my $self = shift;
$self->fetchValue($self->{name});
$ConfigValue->($self->{name});
}
our @EXPORT_OK = ('INT', 'STRING', 'BOOLEAN');

View file

@ -0,0 +1,57 @@
package KasmVNC::ConfigSetting;
use strict;
use warnings;
use v5.10;
use KasmVNC::SettingValidation;
our @ISA = ('KasmVNC::SettingValidation');
our $ConfigValue;
sub new {
my ($class, $args) = @_;
my $self = bless {
configKey => $args->{configKey},
errors => []
}, $class;
}
sub toValue {
my $self = shift;
$self->deriveValue();
}
sub deriveValue {
my $self = shift;
my $configKeyName = $self->{configKey}->{name};
my $value = $ConfigValue->($configKeyName);
interpolateEnvVars($value);
}
sub configKeyNames {
my $self = shift;
[$self->{configKey}->{name}];
}
# private
sub validate {
my $self = shift;
$self->validateConfigValue();
$self->{validated} = 1;
}
sub validateConfigValue {
my $self = shift;
$self->{configKey}->validate($self);
}
1;

View file

@ -0,0 +1,33 @@
package KasmVNC::SettingValidation;
use strict;
use warnings;
use v5.10;
sub isValid {
my $self = shift;
$self->validate() unless $self->{validated};
$self->isNoErrorsPresent();
}
sub errorMessages {
my $self = shift;
join "\n", @{ $self->{errors} };
}
sub isNoErrorsPresent {
my $self = shift;
scalar @{ $self->{errors} } == 0;
}
sub addErrorMessage {
my ($self, $errorMessage) = @_;
push @{ $self->{errors} }, $errorMessage;
}
1;

View file

@ -11,7 +11,7 @@ use Exporter;
@KasmVNC::Utils::ISA = qw(Exporter);
our @EXPORT = ('listify', 'flatten', 'isBlank', 'isPresent', 'deriveBoolean',
'printStackTrace');
'printStackTrace', 'interpolateEnvVars');
sub listify {
# Implementation based on Hyper::Functions
@ -73,4 +73,17 @@ sub containsWideSymbols {
$string =~ /[^\x00-\xFF]/;
}
sub interpolateEnvVars {
my $value = shift;
return $value unless defined($value);
while ($value =~ /\$\{(\w+)\}/) {
my $envValue = $ENV{$1};
$value =~ s/\Q$&\E/$envValue/;
}
$value;
}
1;

View file

@ -37,7 +37,7 @@ user_session:
keyboard:
remap_keys:
# - 0x22->0x40
# - 0x22->0x40
ignore_numlock: false
raw_keyboard: false
@ -129,10 +129,15 @@ encoding:
logging:
level: off
scaling_algorithm: progressive_bilinear
webp_encoding_time: 30
compare_framebuffer: auto
zrle_zlib_level: auto
hextile_improved_compression: true
scrolling:
detect_vertical_scrolling: false
detect_horizontal_scrolling: false
scroll_detect_threshold: 25%
server:
http:
@ -148,6 +153,7 @@ server:
no_user_session_timeout: never
active_user_session_timeout: never
inactive_user_session_timeout: never
allow_environment_variables_to_override_config_settings: false
command_line:
prompt: true

View file

@ -43,6 +43,7 @@ use DateTime;
use DateTime::TimeZone;
use KasmVNC::CliOption;
use KasmVNC::ConfigSetting;
use KasmVNC::ConfigKey;
use KasmVNC::PatternValidator;
use KasmVNC::EnumValidator;
@ -54,6 +55,8 @@ use KasmVNC::TextUI;
use KasmVNC::Utils;
use KasmVNC::Logger;
use KasmVNC::ConfigEnvVars;
use constant {
NO_ARG_VALUE => 0,
REQUIRED_ARG_VALUE => 1,
@ -71,9 +74,18 @@ ParseAndProcessCliOptions();
PrepareLoggingAndXvncKillingFramework();
CreateUserConfigIfNeeded();
DefineConfigToCLIConversion();
DefinePossibleConfigSettings();
LoadConfigs();
OverrideConfigWithConfigEnvVars();
InterpolateEnvVarsIntoConfigValues();
ValidateConfigValues();
CheckForUnsupportedConfigEnvVars();
CheckForUnsupportedConfigKeys();
ActivateConfigToCLIConversion();
SetAppSettingsFromConfigAndCli();
DisableLegacyVncAuth();
AllowXProgramsToConnectToXvnc();
@ -1178,6 +1190,11 @@ sub DefineFilePathsAndStuff {
$KasmVNC::Users::vncPasswdBin = $exedir . "kasmvncpasswd";
$KasmVNC::Users::logger = $logger;
$KasmVNC::Config::logger = $logger;
$KasmVNC::ConfigEnvVars::logger = $logger;
$KasmVNC::ConfigEnvVars::SupportedAbsoluteKeys = \&SupportedAbsoluteKeys;
$KasmVNC::ConfigEnvVars::ConfigValue = \&ConfigValue;
$KasmVNC::ConfigEnvVars::SetConfigValue = \&SetConfigValue;
$KasmVNC::ConfigEnvVars::ShouldPrintTopic = \&ShouldPrintTopic;
$vncSystemConfigDir = "/etc/kasmvnc";
if ($ENV{KASMVNC_DEVELOPMENT}) {
@ -1227,8 +1244,9 @@ sub limitVncModeOptions {
}
sub DefineConfigToCLIConversion {
$KasmVNC::CliOption::fetchValueSub = \&ConfigValue;
$KasmVNC::ConfigKey::fetchValueSub = \&ConfigValue;
$KasmVNC::CliOption::ConfigValue = \&ConfigValue;
$KasmVNC::ConfigSetting::ConfigValue = \&ConfigValue;
$KasmVNC::ConfigKey::ConfigValue = \&ConfigValue;
my $regionValidator = KasmVNC::PatternValidator->new({
pattern => qr/^(-)?\d+(%)?$/,
@ -1246,6 +1264,10 @@ sub DefineConfigToCLIConversion {
pattern => qr/^(never|\d+)$/,
errorMessage => "must be a number or 'never'"
});
my $percentValidator = KasmVNC::PatternValidator->new({
pattern => qr/^(\d+%)$/,
errorMessage => "must be a number, followed by %"
});
my $allConfigKeysValidatorSub = sub {
my @allConfigKeys = map { $_->configKeyNames() } @xvncOptions;
@ -1253,6 +1275,14 @@ sub DefineConfigToCLIConversion {
allowedValues => [flatten(@allConfigKeys)]
})
};
my $deriveValueStripPercentSub = sub {
$self = shift;
my $value = $self->configValue();
$value =~ s/%$//;
$value;
};
KasmVNC::CliOption::beforeIsActive(\&limitVncModeOptions);
my $ipv4_regexp = '((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}';
my $ipv6_regexp = '(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))';
@ -1999,20 +2029,10 @@ sub DefineConfigToCLIConversion {
configKeys => [
KasmVNC::ConfigKey->new({
name => "encoding.video_encoding_mode.enter_video_encoding_mode.area_threshold",
validator => KasmVNC::PatternValidator->new({
pattern => qr/^(\d+%)$/,
errorMessage => "must be a number, followed by %"
}),
validator => $percentValidator
})
],
deriveValueSub => sub {
$self = shift;
my $value = $self->configValue();
$value =~ s/%$//;
$value;
}
deriveValueSub => $deriveValueStripPercentSub
}),
KasmVNC::CliOption->new({
name => 'VideoOutTime',
@ -2068,6 +2088,15 @@ sub DefineConfigToCLIConversion {
$value;
}
}),
KasmVNC::CliOption->new({
name => 'WebpEncodingTime',
configKeys => [
KasmVNC::ConfigKey->new({
name => "encoding.video_encoding_mode.webp_encoding_time",
type => KasmVNC::ConfigKey::INT
})
]
}),
KasmVNC::CliOption->new({
name => 'CompareFB',
configKeys => [
@ -2453,6 +2482,56 @@ sub DefineConfigToCLIConversion {
})
]
}),
KasmVNC::CliOption->new({
name => 'DetectScrolling',
configKeys => [
KasmVNC::ConfigKey->new({
name => "encoding.scrolling.detect_vertical_scrolling",
type => KasmVNC::ConfigKey::BOOLEAN
})
],
isActiveSub => sub {
$self = shift;
my $value = $self->configValue();
isPresent($value) && $value eq 'true';
}
}),
KasmVNC::CliOption->new({
name => 'DetectHorizontal',
configKeys => [
KasmVNC::ConfigKey->new({
name => "encoding.scrolling.detect_horizontal_scrolling",
type => KasmVNC::ConfigKey::BOOLEAN,
validator => KasmVNC::CallbackValidator->new({
isValidCallback => sub {
my $value = shift;
return 1 if $value eq "false";
ConfigValue("encoding.scrolling.detect_vertical_scrolling") eq "true";
},
errorMessage => "Detection of horizontal scrolling requires detection of vertical scrolling enabled"
}),
})
],
isActiveSub => sub {
$self = shift;
my $value = $self->configValue();
isPresent($value) && $value eq 'true';
}
}),
KasmVNC::CliOption->new({
name => 'ScrollDetectLimit',
configKeys => [
KasmVNC::ConfigKey->new({
name => "encoding.scrolling.scroll_detect_threshold",
validator => $percentValidator
})
],
deriveValueSub => $deriveValueStripPercentSub
}),
);
%cliArgMap = map { ("-" . $_->{name}) => $_ } @xvncOptions;
@ -2639,7 +2718,7 @@ sub ShouldPrintTopic {
sub SupportedAbsoluteKeys {
my @supportedAbsoluteKeys =
map { $_->configKeyNames() } @allCliOptions;
map { $_->configKeyNames() } (@allCliOptions, @configSettings);
@supportedAbsoluteKeys = flatten(@supportedAbsoluteKeys);
my %result = map { $_ => 1 } @supportedAbsoluteKeys;
@ -2663,7 +2742,6 @@ sub SupportedSectionsFromAbsoluteKey {
sub StartXvncOrExit {
$cmd = ConstructXvncCmd();
CheckForUnsupportedConfigKeys();
CheckSslCertReadable();
say $cmd if ($debug || IsDryRun()) && ShouldPrintTopic("xvnc-cmd");
@ -2816,6 +2894,13 @@ sub ConfigValue {
return $configRef->get($absoluteKey);
}
sub SetConfigValue {
my ($absoluteKey, $value, $configRef) = @_;
$configRef ||= $mergedConfig;
$configRef->set($absoluteKey, $value);
}
sub DerivedValue {
my $absoluteKey = shift;
@ -2890,7 +2975,6 @@ sub ConstructOptFromConfig{
}
sub ConfigToCmd {
ValidateConfig();
%optFromConfig = %{ ConstructOptFromConfig() };
my @cmd = map { $cliArgMap{$_}->toString() } (keys %optFromConfig);
@ -2899,20 +2983,20 @@ sub ConfigToCmd {
return $cmdStr;
}
sub ValidateConfig {
foreach my $cliOption (@allCliOptions) {
ValidateCliOption($cliOption);
sub ValidateConfigValues {
foreach my $setting (@allCliOptions, @configSettings) {
ValidateSetting($setting);
}
}
sub ValidateCliOption {
my $cliOption = $_[0];
sub ValidateSetting {
my $setting = $_[0];
return if ($cliOption->isValid());
return if ($setting->isValid());
if (ShouldPrintTopic("validation")) {
$logger->warn("config errors:");
$logger->warn($cliOption->errorMessages());
$logger->warn($setting->errorMessages());
$logger->warn();
}
@ -2972,3 +3056,34 @@ sub InitLogger {
sub UseUtfStdio {
use open qw( :std :encoding(UTF-8) );
}
sub DefinePossibleConfigSettings {
DefineConfigToCLIConversion();
DefineConfigSettings();
}
sub DefineConfigSettings {
@configSettings = (
KasmVNC::ConfigSetting->new({
configKey => KasmVNC::ConfigKey->new({
name => "server.allow_environment_variables_to_override_config_settings",
type => KasmVNC::ConfigKey::BOOLEAN
})
}),
);
}
sub InterpolateEnvVarsIntoConfigValues {
my @interpolationDenylist = (
"server.allow_environment_variables_to_override_config_settings"
);
my %supportedAbsoluteKeys = %{ SupportedAbsoluteKeys() };
delete @supportedAbsoluteKeys{@interpolationDenylist};
for my $absoluteKey (keys %supportedAbsoluteKeys) {
my $value = ConfigValue($absoluteKey);
my $interpolatedValue = interpolateEnvVars($value);
SetConfigValue($absoluteKey, $interpolatedValue);
}
}

View file

@ -52,7 +52,7 @@ Xvnc_CPPFLAGS = $(XVNC_CPPFLAGS) -DKASMVNC -DNO_MODULE_EXTS \
-I$(top_srcdir)/dri3 @LIBDRM_CFLAGS@
Xvnc_LDADD = $(XVNC_LIBS) libvnccommon.la $(COMMON_LIBS) \
$(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XVNC_SYS_LIBS) -lX11 -lwebp -lssl -lcrypto -lcrypt \
$(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XVNC_SYS_LIBS) -lX11 -lwebp -lsharpyuv -lssl -lcrypto -lcrypt \
-lfreetype
Xvnc_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG) -fopenmp

View file

@ -574,6 +574,33 @@ When \fBNoClipboard\fP parameter is set, allowing override of \fBSendCutText\fP
and \fBAcceptCutText\fP has no effect.
Default is \fBdesktop,AcceptPointerEvents,SendCutText,AcceptCutText,SendPrimary,SetPrimary\fP.
.
TP
.B -Benchmark <video_file>
Run the built-in benchmarking routines on the specified video file and exit.
When this option is used, benchmarking results can be saved to a file specified by the \fB-BenchmarkResults\fP option; otherwise, the results are saved to \fBBenchmark.xml\fP by default.
.
.TP
.B -BenchmarkResults <results_file.xml>
Save the benchmarking results to the specified file.
Use this option together with \fB-Benchmark\fP to output the report to a custom file.
.
.TP
.B \-DetectScrolling
Try to detect scrolled sections in a changed area.
Detect vertical scrolling on the screen and then use copyRects instead of
sending jpeg. A copy rect tells the client to copy a section of the screen and
paste it somewhere else. This significantly reduces bandwidth usage when someone
is scrolling down a page.
.
.TP
.B \-DetectHorizontal
With \fB-DetectScrolling\fP enabled, try to detect horizontal scrolls too, not just vertical.
.
.TP
.B \-ScrollDetectLimit
At least this % of the screen must change for scroll detection to happen, default 25.
.SH USAGE WITH INETD
By configuring the \fBinetd\fP(1) service appropriately, Xvnc can be launched

View file

@ -184,7 +184,7 @@ static void parseClipTypes()
vlog.debug("Adding DLP binary mime type %s", m.mime);
}
vlog.debug("Total %u binary mime types", dlp_mimetypes.size());
vlog.debug("Total %lu binary mime types", dlp_mimetypes.size());
free(origstr);
}

View file

@ -95,7 +95,7 @@ from the X Consortium.
#undef VENDOR_STRING
#include "version-config.h"
#define XVNCVERSION "KasmVNC 1.3.3"
#define XVNCVERSION "KasmVNC 1.3.4"
#define XVNCCOPYRIGHT ("Copyright (C) 1999-2018 KasmVNC Team and many others (see README.me)\n" \
"See http://kasmweb.com for information on KasmVNC.\n")