Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package gtk-vnc for openSUSE:Factory checked 
in at 2021-11-24 23:54:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/gtk-vnc (Old)
 and      /work/SRC/openSUSE:Factory/.gtk-vnc.new.1895 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "gtk-vnc"

Wed Nov 24 23:54:14 2021 rev:55 rq:933065 version:1.3.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/gtk-vnc/gtk-vnc.changes  2021-04-24 
23:07:02.315215396 +0200
+++ /work/SRC/openSUSE:Factory/.gtk-vnc.new.1895/gtk-vnc.changes        
2021-11-24 23:54:23.536495181 +0100
@@ -1,0 +2,15 @@
+Wed Nov 17 11:39:16 UTC 2021 - Bj??rn Lie <bjorn....@gmail.com>
+
+- Update to version 1.3.0:
+  + Add API to request screen rotation.
+  + Automatically pick gthread coroutine if ucontext is not
+    available.
+  + Fix meson logic bug when disabling vala.
+  + Honour choice of python when generating keymaps.
+  + Fix error reporting and memory leaks encrypting auth data.
+  + Fix missing includes for GDK quartz and broadway backends.
+  + Switch to GNUTLS for VNC auth challenge to fix empty password
+    handling.
+  + Fix handling of auth subtypes in gvnccapture program.
+
+-------------------------------------------------------------------

Old:
----
  gtk-vnc-1.2.0.tar.xz

New:
----
  gtk-vnc-1.3.0.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ gtk-vnc.spec ++++++
--- /var/tmp/diff_new_pack.KKmN6H/_old  2021-11-24 23:54:23.972493718 +0100
+++ /var/tmp/diff_new_pack.KKmN6H/_new  2021-11-24 23:54:23.976493704 +0100
@@ -21,13 +21,13 @@
 %define _sonamepkg 2_0
 
 Name:           gtk-vnc
-Version:        1.2.0
+Version:        1.3.0
 Release:        0
 Summary:        A GTK widget for VNC clients
 License:        LGPL-2.1-only AND LGPL-2.1-or-later
 Group:          Development/Libraries/X11
 URL:            https://wiki.gnome.org/Projects/gtk-vnc
-Source0:        
https://download.gnome.org/sources/gtk-vnc/1.2/%{name}-%{version}.tar.xz
+Source0:        
https://download.gnome.org/sources/gtk-vnc/1.3/%{name}-%{version}.tar.xz
 
 BuildRequires:  cyrus-sasl-devel
 BuildRequires:  gobject-introspection-devel >= 0.9.4

++++++ gtk-vnc-1.2.0.tar.xz -> gtk-vnc-1.3.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gtk-vnc-1.2.0/AUTHORS new/gtk-vnc-1.3.0/AUTHORS
--- old/gtk-vnc-1.2.0/AUTHORS   2021-04-14 11:47:12.927097600 +0200
+++ new/gtk-vnc-1.3.0/AUTHORS   2021-11-17 11:24:01.254825400 +0100
@@ -84,6 +84,7 @@
 Marton Balint <c...@fazekas.hu>
 Mart Raudsepp <l...@gentoo.org>
 Matej Urban??i?? <mat...@svn.gnome.org>
+Matt Turner <matts...@gmail.com>
 Michael Ram??rez <radical_mich...@hotmail.com>
 Michal Novotny <minov...@redhat.com>
 Michal Suchanek <hramr...@centrum.cz>
@@ -115,6 +116,7 @@
 Stefano Stabellini <stefano.stabell...@eu.citrix.com>
 Steven Carr <steven.c...@scaa-usa.com>
 Takeshi AIHANA <takeshi.aih...@gmail.com>
+Thomas Loimer <thomas.loi...@tuwien.ac.at>
 Tom Schoonjans <tom.schoonj...@diamond.ac.uk>
 Victor Ibragimov <victor.ibragi...@gmail.com>
 Victor Toso <m...@victortoso.com>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gtk-vnc-1.2.0/ChangeLog new/gtk-vnc-1.3.0/ChangeLog
--- old/gtk-vnc-1.2.0/ChangeLog 2021-04-14 11:47:12.916097600 +0200
+++ new/gtk-vnc-1.3.0/ChangeLog 2021-11-17 11:24:01.237825400 +0100
@@ -1,3 +1,112 @@
+2021-11-17  Daniel P. Berrang??  <berra...@redhat.com>
+
+       Bump version to 1.3.0 and add release notes
+
+       The vala-tools package was dropped long ago
+       It has only existed as a virtual Provides line since Fedora 25
+
+2021-11-15  Daniel P. Berrang??  <berra...@redhat.com>
+
+       Remove bogus newlines from VNC_DEBUG calls
+       This macro is a wrappar around g_debug and as such doesn't need to add
+       its own newline, unless trying to break a single message across lines.
+
+2021-11-12  Daniel P. Berrang??  <berra...@redhat.com>
+
+       tools: fix gvnccapture handling of subauth types
+
+       src: rewrite challenge code to use gnutls
+       gcrypt refuses to encrypt DES data using an all-zeros key. While this
+       might seem reasonable, this is the key that you get when someone sets
+       a zero length password in a VNC server.
+
+       IOW, the gcrypt behaviour prevents gtk-vnc connecting to a server with
+       zero length password.
+
+       GNUTLS doesn't have this problem but also doesn't support DES-ECB,
+       so we have to fake it by calling DES-CBC for each block individually.
+       Conceptually this is horribly inefficient, but since the VNC challenge
+       is only 16 bytes long it isn't a problem in the real world.
+
+       src: pull challenge encryption out into separate helper method
+
+2021-05-27  Daniel P. Berrang??  <berra...@redhat.com>
+
+       fix missing includes for quartz and broadway GDK backends
+       This is another case of the bug fixed in
+
+       commit d2c93a2bc0a9caa73bbebb41333fa7930d4165ab
+       Author: Daniel P. Berrang?? <d...@berrange.com>
+       Date:   Tue Mar 30 15:00:00 2021 +0100
+
+           Add missing include of gdkwin32.h
+
+       Closes: https://gitlab.gnome.org/GNOME/gtk-vnc/-/issues/16
+
+       Remove unused variables
+
+2021-05-27  Thomas Loimer  <thomas.loi...@tuwien.ac.at>
+
+       Add a button to rotate the screen
+       On each click on the new menu item, the screen is rotated by additional
+       90 degrees clockwise.
+
+2021-05-27  Jakub Jank??  <jja...@redhat.com>
+
+       ard: set connection error
+       As with vncEncryptBytes2 in the earlier patch,
+       the connection error must be set, otherwise the connection
+       stays in the mainloop, but nothing is happening.
+
+       ard: cleanup properly
+       With the current code, if one of the gcry functions in
+       vnc_connection_perform_auth_ard() fails:
+       * key isn't released
+       * md5 isn't closed
+       * mpis and dh aren't released
+
+       vncEncryptBytes2: set connection error and cleanup
+       If vncEncryptBytes2 fails, the false return value propagates
+       upwards, but no error is set. The connection ends up stuck in
+       the mainloop with nothing happening.
+
+       Additionally, the mpis and dh aren't freed.
+
+       To fix that, return the gcry error from vncEncryptBytes2
+       and set the connection error accordingly.
+
+       vnc-auth: emit "vnc-auth-failure" for weak key
+       In vnc_connection_perform_auth_vnc(), if the user enters an empty
+       password, gcry_cipher_setkey() fails with GPG_ERR_WEAK_KEY.
+
+       In such case, we want to give the useranother chance to reenter
+       the password, as is the case when the password is incorrect.
+
+       To enable that, the auth-failure signal needs to be emitted.
+
+       Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1941398
+
+2021-05-07  Mart Raudsepp  <l...@gentoo.org>
+
+       meson: Find python explicitly to honor downstream python choice
+
+2021-04-28  Matt Turner  <matts...@gmail.com>
+
+       meson: Fix configuration failure with -Dwith-vala=disabled
+       Otherwise with_vala is not defined, and meson setup results in
+
+           src/meson.build:169:5: ERROR: Unknown variable "with_vala".
+
+2021-04-26  Jakub Jank??  <jja...@redhat.com>
+
+       build: improve --with-coroutine=auto choice
+       When the required ucontext functions aren't found, switch to gthread
+       coroutines instead of failing during the build.
+
+       These functions are absent from the POSIX.1-2008.
+
+       Fixes: https://gitlab.gnome.org/GNOME/gtk-vnc/-/issues/11
+
 2021-04-14  Daniel P. Berrang??  <berra...@redhat.com>
 
        meson: bump release to 1.2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gtk-vnc-1.2.0/NEWS new/gtk-vnc-1.3.0/NEWS
--- old/gtk-vnc-1.2.0/NEWS      2021-04-14 11:47:11.076112000 +0200
+++ new/gtk-vnc-1.3.0/NEWS      2021-11-17 11:23:59.967830400 +0100
@@ -1,6 +1,18 @@
     GTK VNC News
     ============
 
+Nov 16, 2021: Release 1.3.0
+===========================
+
+ o Add API to request screen rotation
+ o Automatically pick gthread coroutine if ucontext is not available
+ o Fix meson logic bug when disabling vala
+ o Honour choice of python when generating keymaps
+ o Fix error reporting and memory leaks encrypting auth data
+ o Fix missing includes for GDK quartz and broadway backends
+ o Switch to GNUTLS for VNC auth challenge to fix empty password handling
+ o Fix handling of auth subtypes in gvnccapture program
+
 Apr 14, 2021: Release 1.2.0
 ===========================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gtk-vnc-1.2.0/examples/gvncviewer.c 
new/gtk-vnc-1.3.0/examples/gvncviewer.c
--- old/gtk-vnc-1.2.0/examples/gvncviewer.c     2021-04-14 11:47:11.077112000 
+0200
+++ new/gtk-vnc-1.3.0/examples/gvncviewer.c     2021-11-17 11:23:59.968830300 
+0100
@@ -423,6 +423,13 @@
         vnc_display_set_keep_aspect_ratio(VNC_DISPLAY(vncdisplay), FALSE);
 }
 
+static void do_rotate(GtkWidget *menu G_GNUC_UNUSED, GtkWidget *vncdisplay)
+{
+    guint rotation = vnc_display_get_rotation(VNC_DISPLAY(vncdisplay));
+    vnc_display_set_rotation(VNC_DISPLAY(vncdisplay), rotation + 90u);
+}
+
+
 static void do_power_control(VncDisplay *vncdisplay, VncConnectionPowerAction 
action)
 {
     VncConnection *conn = vnc_display_get_connection(vncdisplay);
@@ -721,6 +728,7 @@
     GtkWidget *smoothing;
     GtkWidget *keep_aspect_ratio;
     GtkWidget *resize;
+    GtkWidget *rotate;
     GtkWidget *showgrabkeydlg;
     GtkWidget *shutdown;
     GtkWidget *reboot;
@@ -800,6 +808,7 @@
     smoothing = gtk_check_menu_item_new_with_mnemonic("Smooth scaling");
     keep_aspect_ratio = gtk_check_menu_item_new_with_mnemonic("Keep aspect 
ratio");
     resize = gtk_check_menu_item_new_with_mnemonic("Allow resizing");
+    rotate = gtk_menu_item_new_with_mnemonic("Rotate ???");
 
     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(scaling), TRUE);
     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(smoothing), TRUE);
@@ -809,6 +818,7 @@
     gtk_menu_shell_append(GTK_MENU_SHELL(submenu), scaling);
     gtk_menu_shell_append(GTK_MENU_SHELL(submenu), smoothing);
     gtk_menu_shell_append(GTK_MENU_SHELL(submenu), keep_aspect_ratio);
+    gtk_menu_shell_append(GTK_MENU_SHELL(submenu), rotate);
     gtk_menu_shell_append(GTK_MENU_SHELL(submenu), resize);
 
     gtk_menu_item_set_submenu(GTK_MENU_ITEM(view), submenu);
@@ -892,6 +902,7 @@
 
     vnc_display_set_scaling(VNC_DISPLAY(vnc), TRUE);
     vnc_display_set_allow_resize(VNC_DISPLAY(vnc), TRUE);
+    vnc_display_set_rotation(VNC_DISPLAY(vnc), 0u);
     vnc_display_set_lossy_encoding(VNC_DISPLAY(vnc), TRUE);
     vnc_display_set_zoom_level(VNC_DISPLAY(vnc), opt_zoom);
 
@@ -963,6 +974,8 @@
                      G_CALLBACK(do_smoothing), vnc);
     g_signal_connect(keep_aspect_ratio, "toggled",
                      G_CALLBACK(do_keep_aspect_ratio), vnc);
+    g_signal_connect(rotate, "activate",
+                     G_CALLBACK(do_rotate), vnc);
     g_signal_connect(shutdown, "activate",
                      G_CALLBACK(do_shutdown), vnc);
     g_signal_connect(reboot, "activate",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gtk-vnc-1.2.0/gtk-vnc.spec 
new/gtk-vnc-1.3.0/gtk-vnc.spec
--- old/gtk-vnc-1.2.0/gtk-vnc.spec      2021-04-14 11:47:12.917097600 +0200
+++ new/gtk-vnc-1.3.0/gtk-vnc.spec      2021-11-17 11:24:01.238825600 +0100
@@ -8,7 +8,7 @@
 
 Summary: A GTK widget for VNC clients
 Name: gtk-vnc
-Version: 1.2.0
+Version: 1.3.0
 Release: 1%{?dist}
 License: LGPLv2+
 Source: 
https://download.gnome.org/sources/%{name}/%{verdir}/%{name}-%{version}.tar.xz
@@ -18,7 +18,7 @@
 BuildRequires: gnutls-devel libgcrypt-devel cyrus-sasl-devel zlib-devel
 BuildRequires: gobject-introspection-devel
 BuildRequires: gtk3-devel
-BuildRequires: vala-tools
+BuildRequires: vala
 BuildRequires: pulseaudio-libs-devel
 BuildRequires: /usr/bin/pod2man
 BuildRequires: meson
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gtk-vnc-1.2.0/gtk-vnc.spec.in 
new/gtk-vnc-1.3.0/gtk-vnc.spec.in
--- old/gtk-vnc-1.2.0/gtk-vnc.spec.in   2021-04-14 11:47:11.077112000 +0200
+++ new/gtk-vnc-1.3.0/gtk-vnc.spec.in   2021-11-17 11:23:59.969830300 +0100
@@ -18,7 +18,7 @@
 BuildRequires: gnutls-devel libgcrypt-devel cyrus-sasl-devel zlib-devel
 BuildRequires: gobject-introspection-devel
 BuildRequires: gtk3-devel
-BuildRequires: vala-tools
+BuildRequires: vala
 BuildRequires: pulseaudio-libs-devel
 BuildRequires: /usr/bin/pod2man
 BuildRequires: meson
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gtk-vnc-1.2.0/meson.build 
new/gtk-vnc-1.3.0/meson.build
--- old/gtk-vnc-1.2.0/meson.build       2021-04-14 11:47:11.077112000 +0200
+++ new/gtk-vnc-1.3.0/meson.build       2021-11-17 11:23:59.969830300 +0100
@@ -1,6 +1,6 @@
 project(
   'gtk-vnc','c',
-  version: '1.2.0',
+  version: '1.3.0',
   license: 'LGPLv2.1+',
   default_options: [
     'buildtype=debugoptimized',
@@ -43,8 +43,20 @@
 
 coroutine = get_option('with-coroutine')
 
+uctx_args = []
+if host_machine.system() == 'darwin'
+  uctx_args += ['-D_XOPEN_SOURCE=600']
+endif
+has_ucontext = true
+foreach uctx_func : ['makecontext', 'swapcontext', 'getcontext']
+  if not cc.has_function(uctx_func, prefix: '#include <ucontext.h>', args: 
uctx_args)
+    has_ucontext = false
+    break
+  endif
+endforeach
+
 if coroutine == 'auto'
-  if host_machine.system() == 'windows'
+  if host_machine.system() == 'windows' or not has_ucontext
     coroutine = 'gthread'
   else
     coroutine = 'ucontext'
@@ -52,6 +64,9 @@
 endif
 
 if coroutine == 'ucontext'
+  if not has_ucontext
+    error('ucontext requested, but not available')
+  endif
   conf_data.set('WITH_UCONTEXT', true)
 elif coroutine != 'gthread'
   error('Unknown coroutine backend')
@@ -303,12 +318,11 @@
 with_gir = gir.found()
 
 vala_opt = get_option('with-vala')
+with_vala = false
 if not vala_opt.disabled()
   if not with_gir
     if vala_opt.enabled()
       error('Vala API requires GObject introspection (-Dintrospection=true)')
-    else
-      with_vala = false
     endif
   else
     with_vala = add_languages('vala', required: vala_opt)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gtk-vnc-1.2.0/src/libgtk-vnc_sym.version 
new/gtk-vnc-1.3.0/src/libgtk-vnc_sym.version
--- old/gtk-vnc-1.2.0/src/libgtk-vnc_sym.version        2021-04-14 
11:47:11.080112000 +0200
+++ new/gtk-vnc-1.3.0/src/libgtk-vnc_sym.version        2021-11-17 
11:23:59.972830300 +0100
@@ -100,6 +100,9 @@
     vnc_display_get_zoom_level;
     vnc_display_set_zoom_level;
 
+    vnc_display_get_rotation;
+    vnc_display_set_rotation;
+
   local:
       *;
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gtk-vnc-1.2.0/src/meson.build 
new/gtk-vnc-1.3.0/src/meson.build
--- old/gtk-vnc-1.2.0/src/meson.build   2021-04-14 11:47:11.080112000 +0200
+++ new/gtk-vnc-1.3.0/src/meson.build   2021-11-17 11:23:59.972830300 +0100
@@ -319,7 +319,7 @@
   'vncdisplaykeymap.c',
 ]
 
-python = import('python').find_installation()
+python = import('python').find_installation('python3')
 keymaps = [
   'xorgevdev',
   'xorgkbd',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gtk-vnc-1.2.0/src/vncconnection.c 
new/gtk-vnc-1.3.0/src/vncconnection.c
--- old/gtk-vnc-1.2.0/src/vncconnection.c       2021-04-14 11:47:11.081112000 
+0200
+++ new/gtk-vnc-1.3.0/src/vncconnection.c       2021-11-17 11:23:59.974830400 
+0100
@@ -1487,7 +1487,7 @@
 
     priv->ledstate = vnc_connection_read_u8(conn);
 
-    VNC_DEBUG("LED state: %d\n", priv->ledstate);
+    VNC_DEBUG("LED state: %d", priv->ledstate);
 
     sigdata.params.ledstate = priv->ledstate;
     vnc_connection_emit_main_context(conn, VNC_LED_STATE, &sigdata);
@@ -3472,7 +3472,7 @@
     if (!priv->audio_sample)
         return FALSE;
 
-    VNC_DEBUG("Audio tick %u\n", priv->audio_sample->length);
+    VNC_DEBUG("Audio tick %u", priv->audio_sample->length);
 
     if (priv->audio)
         vnc_audio_playback_data(priv->audio, priv->audio_sample);
@@ -3528,7 +3528,7 @@
         action,
     };
 
-    VNC_DEBUG("Emit audio action %d\n", action);
+    VNC_DEBUG("Emit audio action %d", action);
 
     g_idle_add(do_vnc_connection_audio_action, &data);
 
@@ -3898,14 +3898,52 @@
     }
 }
 
+
+static gboolean vnc_connection_encrypt_challenge(VncConnection *conn,
+                                                 guint8 *challenge,
+                                                 guint8 *key)
+{
+    int error;
+    size_t i;
+    unsigned char iv[8] = {};
+
+    vnc_munge_des_key(key, key);
+
+    for (i = 0; i < 16; i += 8) {
+        gnutls_cipher_hd_t handle;
+        gnutls_datum_t gkey = { (unsigned char *)key, 8 };
+        error = gnutls_cipher_init(&handle,
+                                   GNUTLS_CIPHER_DES_CBC,
+                                   &gkey, NULL);
+        if (error != 0)
+            goto error;
+
+        gnutls_cipher_set_iv(handle, iv, sizeof(iv));
+
+        error = gnutls_cipher_encrypt2(handle,
+                                       challenge + i, 8,
+                                       challenge + i, 8);
+        if (error != 0) {
+            gnutls_cipher_deinit(handle);
+            goto error;
+        }
+        gnutls_cipher_deinit(handle);
+    }
+
+    return TRUE;
+
+ error:
+    vnc_connection_set_error(conn, "Unknown authentication failure: %s",
+                             gnutls_strerror(error));
+    return FALSE;
+}
+
 static gboolean vnc_connection_perform_auth_vnc(VncConnection *conn)
 {
     VncConnectionPrivate *priv = conn->priv;
     guint8 challenge[16];
     guint8 key[8];
     gsize keylen;
-    gcry_cipher_hd_t c;
-    gcry_error_t error;
 
     VNC_DEBUG("Do Challenge");
     priv->want_cred_password = TRUE;
@@ -3925,43 +3963,12 @@
         keylen = sizeof(key);
     memcpy(key, priv->cred_password, keylen);
 
-    vnc_munge_des_key(key, key);
-
-    error = gcry_cipher_open(&c, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
-    if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
-        VNC_DEBUG("gcry_cipher_open error: %s\n", gcry_strerror(error));
-        goto error;
-    }
-
-    error = gcry_cipher_setkey(c, key, 8);
-    if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
-        VNC_DEBUG("gcry_cipher_setkey error: %s\n", gcry_strerror(error));
-        gcry_cipher_close(c);
-        goto error;
-    }
-
-    error = gcry_cipher_encrypt(c, challenge, 8, challenge, 8);
-    if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
-        VNC_DEBUG("gcry_cipher_encrypt error: %s\n", gcry_strerror(error));
-        gcry_cipher_close(c);
-        goto error;
-    }
-    error = gcry_cipher_encrypt(c, challenge + 8, 8, challenge + 8, 8);
-    if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
-        VNC_DEBUG("gcry_cipher_encrypt error: %s\n", gcry_strerror(error));
-        gcry_cipher_close(c);
-        goto error;
-    }
-    gcry_cipher_close(c);
+    if (!vnc_connection_encrypt_challenge(conn, challenge, key))
+        return FALSE;
 
     vnc_connection_write(conn, challenge, 16);
     vnc_connection_flush(conn);
     return vnc_connection_check_auth_result(conn);
-
-error:
-    vnc_connection_set_error(conn, "Unknown authentication failure: %s",
-                             gcry_strerror(error));
-    return FALSE;
 }
 
 static gboolean vnc_connection_perform_auth_plain(VncConnection *conn)
@@ -3992,12 +3999,11 @@
  *   Encrypt bytes[length] in memory using key.
  *   Key has to be 8 bytes, length a multiple of 8 bytes.
  */
-static gboolean
+static gcry_error_t
 vncEncryptBytes2(unsigned char *where, const int length, unsigned char *key)
 {
     gcry_cipher_hd_t c;
     int i, j;
-    gboolean ret = FALSE;
     gcry_error_t error;
     unsigned char newkey[8];
 
@@ -4005,13 +4011,13 @@
 
     error = gcry_cipher_open(&c, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
     if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
-        VNC_DEBUG("gcry_cipher_open error: %s\n", gcry_strerror(error));
-        return FALSE;
+        VNC_DEBUG("gcry_cipher_open error: %s", gcry_strerror(error));
+        return error;
     }
 
     error = gcry_cipher_setkey(c, newkey, 8);
     if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
-        VNC_DEBUG("gcry_cipher_setkey error: %s\n", gcry_strerror(error));
+        VNC_DEBUG("gcry_cipher_setkey error: %s", gcry_strerror(error));
         goto cleanup;
     }
 
@@ -4020,7 +4026,7 @@
 
     error = gcry_cipher_encrypt(c, where, 8, where, 8);
     if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
-        VNC_DEBUG("gcry_cipher_encrypt error: %s\n", gcry_strerror(error));
+        VNC_DEBUG("gcry_cipher_encrypt error: %s", gcry_strerror(error));
         goto cleanup;
     }
 
@@ -4030,16 +4036,14 @@
 
         error = gcry_cipher_encrypt(c, where + i, 8, where + i, 8);
         if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
-            VNC_DEBUG("gcry_cipher_encrypt error: %s\n", gcry_strerror(error));
+            VNC_DEBUG("gcry_cipher_encrypt error: %s", gcry_strerror(error));
             goto cleanup;
         }
     }
 
-    ret = TRUE;
-
  cleanup:
     gcry_cipher_close(c);
-    return ret;
+    return error;
 }
 
 static gboolean vnc_connection_perform_auth_mslogon(VncConnection *conn)
@@ -4048,6 +4052,7 @@
     struct vnc_dh *dh;
     guchar gen[8], mod[8], resp[8], pub[8], key[8];
     gcry_mpi_t genmpi, modmpi, respmpi, pubmpi, keympi;
+    gcry_error_t error;
     guchar username[256], password[64];
     guint passwordLen, usernameLen;
     gboolean allzeroes = TRUE;
@@ -4105,20 +4110,28 @@
     memcpy(password, priv->cred_password, passwordLen);
     memcpy(username, priv->cred_username, usernameLen);
 
-    if (!vncEncryptBytes2(username, sizeof(username), key))
-        return FALSE;
-    if (!vncEncryptBytes2(password, sizeof(password), key))
-        return FALSE;
+    error = vncEncryptBytes2(username, sizeof(username), key);
+    if (gcry_err_code(error) != GPG_ERR_NO_ERROR)
+        goto cleanup;
+    error = vncEncryptBytes2(password, sizeof(password), key);
+    if (gcry_err_code(error) != GPG_ERR_NO_ERROR)
+        goto cleanup;
 
     vnc_connection_write(conn, username, sizeof(username));
     vnc_connection_write(conn, password, sizeof(password));
     vnc_connection_flush(conn);
 
+cleanup:
     gcry_mpi_release(genmpi);
     gcry_mpi_release(modmpi);
     gcry_mpi_release(respmpi);
     vnc_dh_free (dh);
 
+    if (gcry_err_code(error) != GPG_ERR_NO_ERROR) {
+        vnc_connection_set_error(conn, "Unknown authentication failure: %s",
+                                 gcry_strerror(error));
+        return FALSE;
+    }
     return vnc_connection_check_auth_result(conn);
 }
 
@@ -4148,30 +4161,14 @@
 
     keylen = 256*len[0] + len[1];
     mod = malloc(keylen);
-    if (mod == NULL) {
-        VNC_DEBUG("malloc failed\n");
-        return FALSE;
-    }
     resp = malloc(keylen);
-    if (resp == NULL) {
-        free(mod);
-        VNC_DEBUG("malloc failed\n");
-        return FALSE;
-    }
     pub = malloc(keylen);
-    if (pub == NULL) {
-        free(resp);
-        free(mod);
-        VNC_DEBUG("malloc failed\n");
-        return FALSE;
-    }
     key = malloc(keylen);
-    if (key == NULL) {
-        free(pub);
-        free(resp);
-        free(mod);
-        VNC_DEBUG("malloc failed\n");
-        return FALSE;
+    if (mod == NULL || resp == NULL
+            || pub == NULL || key == NULL) {
+        VNC_DEBUG("malloc failed");
+        error = GPG_ERR_ENOMEM;
+        goto cleanup_mem;
     }
 
     vnc_connection_read(conn, mod, keylen);
@@ -4191,20 +4188,14 @@
 
     error=gcry_md_open(&md5, GCRY_MD_MD5, 0);
     if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
-        VNC_DEBUG("gcry_md_open error: %s\n", gcry_strerror(error));
-        free(pub);
-        free(resp);
-        free(mod);
-        return FALSE;
+        VNC_DEBUG("gcry_md_open error: %s", gcry_strerror(error));
+        goto cleanup_mpi;
     }
     gcry_md_write(md5, key, keylen);
     error=gcry_md_final(md5);
     if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
-        VNC_DEBUG("gcry_md_final error: %s\n", gcry_strerror(error));
-        free(pub);
-        free(resp);
-        free(mod);
-        return FALSE;
+        VNC_DEBUG("gcry_md_final error: %s", gcry_strerror(error));
+        goto cleanup_md5;
     }
     shared = gcry_md_read(md5, GCRY_MD_MD5);
 
@@ -4221,45 +4212,44 @@
 
     error=gcry_cipher_open(&aes, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, 0);
     if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
-        VNC_DEBUG("gcry_cipher_open error: %s\n", gcry_strerror(error));
-        free(pub);
-        free(resp);
-        free(mod);
-        return FALSE;
+        VNC_DEBUG("gcry_cipher_open error: %s", gcry_strerror(error));
+        goto cleanup_md5;
     }
     error=gcry_cipher_setkey(aes, shared, 16);
     if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
-        VNC_DEBUG("gcry_cipher_setkey error: %s\n", gcry_strerror(error));
-        free(pub);
-        free(resp);
-        free(mod);
-        gcry_cipher_close(aes);
-        return FALSE;
+        VNC_DEBUG("gcry_cipher_setkey error: %s", gcry_strerror(error));
+        goto cleanup;
     }
     error=gcry_cipher_encrypt(aes, ciphertext, sizeof(ciphertext), userpass, 
sizeof(userpass));
     if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
-        VNC_DEBUG("gcry_cipher_encrypt error: %s\n", gcry_strerror(error));
-        free(pub);
-        free(resp);
-        free(mod);
-        gcry_cipher_close(aes);
-        return FALSE;
+        VNC_DEBUG("gcry_cipher_encrypt error: %s", gcry_strerror(error));
+        goto cleanup;
     }
 
     vnc_connection_write(conn, ciphertext, sizeof(ciphertext));
     vnc_connection_write(conn, pub, keylen);
     vnc_connection_flush(conn);
 
-    free(mod);
-    free(resp);
-    free(pub);
-    free(key);
+cleanup:
     gcry_cipher_close(aes);
+cleanup_md5:
     gcry_md_close(md5);
+cleanup_mpi:
     gcry_mpi_release(genmpi);
     gcry_mpi_release(modmpi);
     gcry_mpi_release(respmpi);
     vnc_dh_free (dh);
+cleanup_mem:
+    free(mod);
+    free(resp);
+    free(pub);
+    free(key);
+
+    if (gcry_err_code(error) != GPG_ERR_NO_ERROR) {
+        vnc_connection_set_error(conn, "Unknown authentication failure: %s",
+                                 gcry_strerror(error));
+        return FALSE;
+    }
 
     return vnc_connection_check_auth_result(conn);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gtk-vnc-1.2.0/src/vncdisplay.c 
new/gtk-vnc-1.3.0/src/vncdisplay.c
--- old/gtk-vnc-1.2.0/src/vncdisplay.c  2021-04-14 11:47:11.082111800 +0200
+++ new/gtk-vnc-1.3.0/src/vncdisplay.c  2021-11-17 11:23:59.975830300 +0100
@@ -87,6 +87,7 @@
     gboolean allow_resize;
     gboolean smoothing;
     gboolean keep_aspect_ratio;
+    guint rotation;
     guint zoom_level;
 
     GSList *preferable_auths;
@@ -123,6 +124,7 @@
     PROP_ALLOW_RESIZE,
     PROP_SMOOTHING,
     PROP_KEEP_ASPECT_RATIO,
+    PROP_ROTATE,
     PROP_DEPTH,
     PROP_ZOOM_LEVEL,
     PROP_GRAB_KEYS,
@@ -232,6 +234,9 @@
         case PROP_KEEP_ASPECT_RATIO:
             g_value_set_boolean (value, vnc->priv->keep_aspect_ratio);
             break;
+        case PROP_ROTATE:
+            g_value_set_uint (value, vnc->priv->rotation);
+            break;
         case PROP_DEPTH:
             g_value_set_enum (value, vnc->priv->depth);
             break;
@@ -293,6 +298,9 @@
         case PROP_KEEP_ASPECT_RATIO:
             vnc_display_set_keep_aspect_ratio (vnc, g_value_get_boolean 
(value));
             break;
+        case PROP_ROTATE:
+            vnc_display_set_rotation (vnc, g_value_get_uint (value));
+            break;
         case PROP_DEPTH:
             vnc_display_set_depth (vnc, g_value_get_enum (value));
             break;
@@ -405,6 +413,9 @@
 {
     VncDisplay *obj = VNC_DISPLAY(widget);
     VncDisplayPrivate *priv = obj->priv;
+    /*
+     * Width and height of the unscaled, but possibly rotated remote desktop. 
*/
+    int rotwidth, rotheight;
 
     *winwidth = gdk_window_get_width(gtk_widget_get_window(widget));
     *winheight = gdk_window_get_height(gtk_widget_get_window(widget));
@@ -424,36 +435,44 @@
     *fbwidth = vnc_framebuffer_get_width(VNC_FRAMEBUFFER(priv->fb));
     *fbheight = vnc_framebuffer_get_height(VNC_FRAMEBUFFER(priv->fb));
 
+    if (priv->rotation == 0u || priv->rotation == 180u) {
+        rotwidth = *fbwidth;
+        rotheight = *fbheight;
+    } else {
+        rotwidth = *fbheight;
+        rotheight = *fbwidth;
+    }
+
     if (priv->allow_scaling) {
         *offsetx = 0;
         *offsety = 0;
         *width = *winwidth;
         *height = *winheight;
-        *scalex = (double)*winwidth / (double)*fbwidth;
-        *scaley = (double)*winheight / (double)*fbheight;
+        *scalex = (double)*winwidth / (double)rotwidth;
+        *scaley = (double)*winheight / (double)rotheight;
 
         if (priv->keep_aspect_ratio) {
             if (*scalex > *scaley) {
                 *scalex = *scaley;
-                *width = *fbwidth * *scalex;
+                *width = rotwidth * *scalex;
                 *offsetx = (*winwidth - *width) / 2;
             } else if (*scalex < *scaley) {
                 *scaley = *scalex;
-                *height = *fbheight * *scaley;
+                *height = rotheight * *scaley;
                 *offsety = (*winheight - *height) / 2;
             }
         }
     } else {
-        if (*winwidth > *fbwidth) {
-            *offsetx = (*winwidth - *fbwidth) / 2;
-            *width = *fbwidth;
+        if (*winwidth > rotwidth) {
+            *offsetx = (*winwidth - rotwidth) / 2;
+            *width = rotwidth;
         } else {
             *offsetx = 0;
             *width = *winwidth;
         }
-        if (*winheight > *fbheight) {
-            *offsety = (*winheight - *fbheight) / 2;
-            *height = *fbheight;
+        if (*winheight > rotheight) {
+            *offsety = (*winheight - rotheight) / 2;
+            *height = rotheight;
         } else {
             *offsety = 0;
             *height = *winheight;
@@ -506,11 +525,46 @@
     /* Now render the remote desktop, scaling/offsetting
      * as needed */
     if (priv->fb) {
-        cairo_scale(cr, scalex, scaley);
+        cairo_matrix_t mtx = {0., 0., 0., 0., 0., 0.};
+        double source_surface_offsetx, source_surface_offsety;
+
+        switch (priv->rotation) {
+        case 0u:
+        default:
+            mtx.xx = scalex;
+            mtx.yy = scaley;
+            source_surface_offsetx = offsetx / scalex;
+            source_surface_offsety = offsety / scaley;
+            break;
+        case 90u:
+            mtx.yx = scaley;
+            mtx.xy = -scalex;
+            mtx.x0 = (double)winwidth;
+            source_surface_offsetx = offsety / scaley;
+            source_surface_offsety = offsetx / scalex;
+            break;
+        case 180u:
+            mtx.xx = -scalex;
+            mtx.yy = -scaley;
+            mtx.x0 = (double)winwidth;
+            mtx.y0 = (double)winheight;
+            source_surface_offsetx = offsetx / scalex;
+            source_surface_offsety = offsety / scaley;
+            break;
+        case 270u:
+            mtx.yx = -scaley;
+            mtx.xy = scalex;
+            mtx.y0 = (double)winheight;
+            source_surface_offsetx = offsety / scaley;
+            source_surface_offsety = offsetx / scalex;
+            break;
+        }
+        cairo_transform(cr, &mtx);
         cairo_set_source_surface(cr,
-                                 priv->fbCache,
-                                 offsetx / scalex,
-                                 offsety / scaley);
+                priv->fbCache,
+                source_surface_offsetx,
+                source_surface_offsety);
+
         if (!priv->smoothing) {
             cairo_pattern_set_filter(cairo_get_source(cr),
                                      CAIRO_FILTER_NEAREST);
@@ -840,8 +894,28 @@
     motion->x -= offsetx;
     motion->y -= offsety;
 
-    motion->x /= scalex;
-    motion->y /= scaley;
+    /* The inverse transform of that applied in draw_event(). */
+    switch (priv->rotation) {
+        int tmp;
+    case 0u:
+    default:
+        motion->x /= scalex;
+        motion->y /= scaley;
+        break;
+    case 90u:
+        tmp = motion->x;
+        motion->x = motion->y / scaley;
+        motion->y = (width - tmp) / scalex;
+        break;
+    case 180u:
+        motion->x = (width - motion->x) / scalex;
+        motion->y = (height - motion->y) / scaley;
+        break;
+    case 270u:
+        tmp = motion->x;
+        motion->x = (height - motion->y) / scaley;
+        motion->y = tmp / scalex;
+    }
 
     /* Next adjust the real client pointer */
     if (!priv->absolute) {
@@ -881,7 +955,7 @@
              * them to the boundaries. We don't want to actually
              * drop the events though, because even if the X coord
              * is out of bounds we want the server to see Y coord
-             * changes, and vica-verca. */
+             * changes, and vice-versa. */
             if (dx < 0)
                 dx = 0;
             if (dy < 0)
@@ -1269,7 +1343,9 @@
         vnc_connection_is_initialized(priv->conn) &&
         priv->fb &&
         priv->force_size)
-        *defwidth = vnc_framebuffer_get_width(VNC_FRAMEBUFFER(priv->fb));
+        *defwidth = (priv->rotation == 0u || priv->rotation == 180u) ?
+                        vnc_framebuffer_get_width(VNC_FRAMEBUFFER(priv->fb)) :
+                        vnc_framebuffer_get_height(VNC_FRAMEBUFFER(priv->fb));
     else
         *defwidth = 0;
 
@@ -1290,7 +1366,9 @@
         vnc_connection_is_initialized(priv->conn) &&
         priv->fb &&
         priv->force_size)
-        *defheight = vnc_framebuffer_get_height(VNC_FRAMEBUFFER(priv->fb));
+        *defheight = (priv->rotation == 0u || priv->rotation == 180u) ?
+                        vnc_framebuffer_get_height(VNC_FRAMEBUFFER(priv->fb)) :
+                        vnc_framebuffer_get_width(VNC_FRAMEBUFFER(priv->fb));
     else
         *defheight = 0;
 
@@ -1336,10 +1414,39 @@
         cairo_destroy(cr);
     }
 
-    x *= scalex;
-    y *= scaley;
-    w *= scalex;
-    h *= scaley;
+    switch (priv->rotation) {
+        /* This repeates the same transformation as in draw_event() above. */
+        /* To put cairo_matrix_t mtx into struct priv, and use here? */
+        int tmp;
+    case 0u:
+    default:
+        x *= scalex;
+        y *= scaley;
+        w *= scalex;
+        h *= scaley;
+        break;
+    case 90u:
+        tmp = x;
+        x = (fbheight - y - h) * scalex;
+        y = tmp * scaley;
+        tmp = w;
+        w = h * scalex;
+        h = tmp * scaley;
+        break;
+    case 180u:
+        x = (fbwidth - x - w) * scalex;
+        y = (fbheight - y - h) * scaley;
+        w *= scalex;
+        h *= scaley;
+        break;
+    case 270u:
+        tmp = x;
+        x = y * scalex;
+        y = (fbwidth - tmp - w) * scaley;
+        tmp = w;
+        w = h * scalex;
+        h = tmp * scaley;
+    }
     x += offsetx;
     y += offsety;
 
@@ -2472,6 +2579,20 @@
                                                             
G_PARAM_STATIC_BLURB));
 
     g_object_class_install_property (object_class,
+                                     PROP_ROTATE,
+                                     g_param_spec_uint ( "rotation",
+                                                          "Rotate +90?? 
clockwise",
+                                                          "Rotate the image of 
the remote desktop 90?? clockwise",
+                                                          0,
+                                                          270,
+                                                          0,
+                                                          G_PARAM_READWRITE |
+                                                          G_PARAM_CONSTRUCT |
+                                                          G_PARAM_STATIC_NAME |
+                                                          G_PARAM_STATIC_NICK |
+                                                          
G_PARAM_STATIC_BLURB));
+
+    g_object_class_install_property (object_class,
                                      PROP_DEPTH,
                                      g_param_spec_enum    ( "depth",
                                                             "Depth",
@@ -2753,6 +2874,7 @@
     priv->allow_resize = FALSE;
     priv->smoothing = TRUE;
     priv->keep_aspect_ratio = FALSE;
+    priv->rotation = 0u;
     priv->zoom_level = 100;
     priv->vncgrabseq = vnc_grab_sequence_new_from_string("Control_L+Alt_L");
     priv->vncactiveseq = g_new0(gboolean, priv->vncgrabseq->nkeysyms);
@@ -3218,7 +3340,7 @@
  * Set whether changes in the widget size will be translated
  * into requests to resize the remote desktop. Resizing of
  * the remote desktop is not guaranteed to be honoured by
- * servers, but when it is, it will avoid the need todo
+ * servers, but when it is, it will avoid the need to do
  * scaling.
  */
 void vnc_display_set_allow_resize(VncDisplay *obj, gboolean enable)
@@ -3287,6 +3409,25 @@
 
 
 /**
+ * vnc_display_set_rotation:
+ * @obj: (transfer none): the VNC display widget
+ * @rotation: The angle of rotation, degrees clockwise.
+ *
+ * Set the rotation angle to view the display of the remote desktop, in
+ * clockwise direction.
+ */
+void vnc_display_set_rotation(VncDisplay *obj, guint rotation)
+{
+    g_return_if_fail (VNC_IS_DISPLAY (obj));
+    obj->priv->rotation = rotation % 360u;
+
+    if (obj->priv->fb != NULL) {
+        gtk_widget_queue_resize(GTK_WIDGET(obj));
+    }
+}
+
+
+/**
  * vnc_display_set_depth:
  * @obj: (transfer none): the VNC display widget
  * @depth: the desired colour depth
@@ -3395,6 +3536,22 @@
 }
 
 
+/**
+ * vnc_display_get_rotation:
+ * @obj: (transfer none): the VNC display widget
+ *
+ * Determine the current rotation angle of the remote desktop.
+ *
+ * Returns: the rotation angle in clockwise direction
+ */
+guint vnc_display_get_rotation(VncDisplay *obj)
+{
+    g_return_val_if_fail (VNC_IS_DISPLAY (obj), 0u);
+
+    return obj->priv->rotation;
+}
+
+
 /**
  * vnc_display_get_scaling:
  * @obj: (transfer none): the VNC display widget
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gtk-vnc-1.2.0/src/vncdisplay.h 
new/gtk-vnc-1.3.0/src/vncdisplay.h
--- old/gtk-vnc-1.2.0/src/vncdisplay.h  2021-04-14 11:47:11.082111800 +0200
+++ new/gtk-vnc-1.3.0/src/vncdisplay.h  2021-11-17 11:23:59.975830300 +0100
@@ -143,6 +143,9 @@
 void vnc_display_set_keep_aspect_ratio(VncDisplay *obj, gboolean enable);
 gboolean vnc_display_get_keep_aspect_ratio(VncDisplay *obj);
 
+void vnc_display_set_rotation(VncDisplay *obj, guint rotation);
+guint vnc_display_get_rotation(VncDisplay *obj);
+
 void vnc_display_set_shared_flag(VncDisplay *obj, gboolean shared);
 gboolean vnc_display_get_shared_flag(VncDisplay *obj);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gtk-vnc-1.2.0/src/vncdisplaykeymap.c 
new/gtk-vnc-1.3.0/src/vncdisplaykeymap.c
--- old/gtk-vnc-1.2.0/src/vncdisplaykeymap.c    2021-04-14 11:47:11.082111800 
+0200
+++ new/gtk-vnc-1.3.0/src/vncdisplaykeymap.c    2021-11-17 11:23:59.975830300 
+0100
@@ -64,12 +64,14 @@
 
 #ifdef GDK_WINDOWING_BROADWAY
 /* X11 keysyms */
+#include <gdk/gdkbroadway.h>
 #include "vncdisplaykeymap_x112qnum.h"
 
 #endif
 
 #ifdef GDK_WINDOWING_QUARTZ
 /* OS-X native keycodes */
+#include <gdk/gdkquartz.h>
 #include "vncdisplaykeymap_osx2qnum.h"
 #endif
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gtk-vnc-1.2.0/tools/gvnccapture.c 
new/gtk-vnc-1.3.0/tools/gvnccapture.c
--- old/gtk-vnc-1.2.0/tools/gvnccapture.c       2021-04-14 11:47:11.083112000 
+0200
+++ new/gtk-vnc-1.3.0/tools/gvnccapture.c       2021-11-17 11:23:59.976830200 
+0100
@@ -136,6 +136,16 @@
     VNC_CONNECTION_AUTH_NONE
 };
 
+static const guint preferable_vencrypt_auths[] = {
+    VNC_CONNECTION_AUTH_VENCRYPT_X509SASL,
+    VNC_CONNECTION_AUTH_VENCRYPT_X509PLAIN,
+    VNC_CONNECTION_AUTH_VENCRYPT_X509VNC,
+    VNC_CONNECTION_AUTH_VENCRYPT_X509NONE,
+    VNC_CONNECTION_AUTH_VENCRYPT_TLSSASL,
+    VNC_CONNECTION_AUTH_VENCRYPT_TLSPLAIN,
+    VNC_CONNECTION_AUTH_VENCRYPT_TLSVNC,
+    VNC_CONNECTION_AUTH_VENCRYPT_TLSNONE,
+};
 
 #ifndef G_OS_WIN32
 static gchar *
@@ -400,34 +410,76 @@
     g_free(data);
 }
 
-static void do_vnc_auth_choose_type(VncConnection *conn,
-                                    GValueArray *types,
-                                    gpointer opaque G_GNUC_UNUSED)
+
+static int do_vnc_auth_choose(const guint *prefer,
+                              gsize nprefer,
+                              GValueArray *avail)
 {
     guint i, j;
 
-    if (!types->n_values) {
-        VNC_DEBUG("No auth types to choose from");
-        return;
-    }
-
-    for (i = 0 ; i < G_N_ELEMENTS(preferable_auths) ; i++) {
-        int pref = preferable_auths[i];
+    for (i = 0 ; i < nprefer ; i++) {
+        int pref = prefer[i];
 
-        for (j = 0 ; j < types->n_values ; j++) {
-            GValue *type = g_value_array_get_nth(types, j);
+        for (j = 0 ; j < avail->n_values ; j++) {
+            GValue *type = g_value_array_get_nth(avail, j);
             VNC_DEBUG("Compare %d vs %d", pref, g_value_get_enum(type));
             if (pref == g_value_get_enum(type)) {
                 VNC_DEBUG("Chosen auth %d", pref);
-                vnc_connection_set_auth_type(conn, pref);
-                return;
+                return pref;
             }
         }
     }
 
-    GValue *type = g_value_array_get_nth(types, 0);
+    GValue *type = g_value_array_get_nth(avail, 0);
     VNC_DEBUG("Chosen default auth %d", g_value_get_enum(type));
-    vnc_connection_set_auth_type(conn, g_value_get_enum(type));
+    return g_value_get_enum(type);
+}
+
+static void do_vnc_auth_choose_subtype(VncConnection *conn,
+                                       int type,
+                                       GValueArray *subtypes,
+                                       gpointer opaque G_GNUC_UNUSED)
+{
+    guint auth;
+
+    if (!subtypes->n_values) {
+        VNC_DEBUG("No auth subtypes to choose from");
+        return;
+    }
+
+    if (type == VNC_CONNECTION_AUTH_TLS) {
+        auth = do_vnc_auth_choose(preferable_auths,
+                                  G_N_ELEMENTS(preferable_auths),
+                                  subtypes);
+    } else if (type == VNC_CONNECTION_AUTH_VENCRYPT) {
+        auth = do_vnc_auth_choose(preferable_vencrypt_auths,
+                                  G_N_ELEMENTS(preferable_vencrypt_auths),
+                                  subtypes);
+    } else {
+        VNC_DEBUG("Unexpected stackable auth type %u", type);
+        vnc_connection_shutdown(conn);
+        return;
+    }
+
+    vnc_connection_set_auth_subtype(conn, auth);
+}
+
+
+static void do_vnc_auth_choose_type(VncConnection *conn,
+                                    GValueArray *types,
+                                    gpointer opaque G_GNUC_UNUSED)
+{
+    guint auth;
+    if (!types->n_values) {
+        VNC_DEBUG("No auth types to choose from");
+        return;
+    }
+
+    auth = do_vnc_auth_choose(preferable_auths,
+                              G_N_ELEMENTS(preferable_auths),
+                              types);
+
+    vnc_connection_set_auth_type(conn, auth);
 }
 
 
@@ -528,7 +580,7 @@
     g_signal_connect(capture->conn, "vnc-auth-choose-type",
                      G_CALLBACK(do_vnc_auth_choose_type), capture);
     g_signal_connect(capture->conn, "vnc-auth-choose-subtype",
-                     G_CALLBACK(do_vnc_auth_choose_type), capture);
+                     G_CALLBACK(do_vnc_auth_choose_subtype), capture);
     g_signal_connect(capture->conn, "vnc-auth-credential",
                      G_CALLBACK(do_vnc_auth_credential), capture);
     g_signal_connect(capture->conn, "vnc-desktop-resize",

Reply via email to