gnucash maint: Multiple changes pushed
John Ralls
jralls at code.gnucash.org
Sat Dec 12 20:08:42 EST 2020
Updated via https://github.com/Gnucash/gnucash/commit/2b01bde2 (commit)
via https://github.com/Gnucash/gnucash/commit/580975b9 (commit)
from https://github.com/Gnucash/gnucash/commit/7de24dec (commit)
commit 2b01bde2b6808d09a6ca9ef676ca2384fb005bb8
Merge: 7de24dec6 580975b92
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Dec 12 17:00:47 2020 -0800
Merge Christian Wehling's 'gnucash-flicker' into maint.
diff --cc gnucash/import-export/aqb/gnc-gwen-gui.c
index 54fa72953,aeb70b481..1a0569938
--- a/gnucash/import-export/aqb/gnc-gwen-gui.c
+++ b/gnucash/import-export/aqb/gnc-gwen-gui.c
@@@ -949,9 -954,33 +954,46 @@@ get_input(GncGWENGui *gui, guint32 flag
remember_pin_checkbutton = GTK_WIDGET(gtk_builder_get_object (builder, "remember_pin"));
optical_challenge = GTK_IMAGE(gtk_builder_get_object (builder, "optical_challenge"));
gtk_widget_set_visible(GTK_WIDGET(optical_challenge), FALSE);
+
+ flickergui = g_slice_new(GncFlickerGui);
+ flickergui->flicker_challenge = GTK_WIDGET(gtk_builder_get_object(builder, "flicker_challenge"));
+ flickergui->flicker_marker = GTK_WIDGET(gtk_builder_get_object(builder, "flicker_marker"));
+ flickergui->flicker_hbox = GTK_WIDGET(gtk_builder_get_object(builder, "flicker_hbox"));
+ flickergui->spin_barwidth = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "spin_barwidth"));
+ flickergui->spin_delay = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "spin_delay"));
+
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->flicker_challenge), FALSE);
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->flicker_marker), FALSE);
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->flicker_hbox), FALSE);
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->spin_barwidth), FALSE);
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->spin_delay), FALSE);
+
#ifdef AQBANKING6
- if(mimeType != NULL && pChallenge != NULL && lChallenge > 0)
+ if (g_strcmp0(mimeType,"text/x-flickercode") == 0 && pChallenge != NULL)
++<<<<<<< Updated upstream
{
+ /* Chiptan Optic (aka Flicker) */
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->flicker_challenge), TRUE);
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->flicker_marker), TRUE);
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->flicker_hbox), TRUE);
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->spin_barwidth), TRUE);
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->spin_delay), TRUE);
+ }
+ else if(mimeType != NULL && pChallenge != NULL && lChallenge > 0)
+ {
++=======
++ {
++ /* Chiptan Optic (aka Flicker) */
++ gtk_widget_set_visible(GTK_WIDGET(flickergui->flicker_challenge), TRUE);
++ gtk_widget_set_visible(GTK_WIDGET(flickergui->flicker_marker), TRUE);
++ gtk_widget_set_visible(GTK_WIDGET(flickergui->flicker_hbox), TRUE);
++ gtk_widget_set_visible(GTK_WIDGET(flickergui->spin_barwidth), TRUE);
++ gtk_widget_set_visible(GTK_WIDGET(flickergui->spin_delay), TRUE);
++ }
++ else if(mimeType != NULL && pChallenge != NULL && lChallenge > 0)
++ {
++>>>>>>> Stashed changes
+ /* Phototan or Chiptan QR */
gtk_widget_set_visible(GTK_WIDGET(optical_challenge), TRUE);
}
#endif
@@@ -993,9 -1023,10 +1036,22 @@@
}
#ifdef AQBANKING6
-- //if (optical_challenge)
-- if(mimeType != NULL && pChallenge != NULL && lChallenge > 0)
++ /* Optical challenge. Flickercode sets the mimetype to
++ * x-flickercode and doesn't set the challenge length */
++ if (g_strcmp0(mimeType,"text/x-flickercode") == 0 && pChallenge != NULL)
+ {
++ /* Chiptan Optic (aka Flicker) */
++ flickergui->dialog = dialog;
++ flickergui->input_entry = input_entry;
++
++ ini_flicker_gui(pChallenge, flickergui);
++ g_slice_free(GncFlickerGui, flickergui);
++ }
++ /* While phototan has multiple mimetypes and does set the
++ * challenge length. */
++ else if(mimeType != NULL && pChallenge != NULL && lChallenge > 0)
+ {
+ /* Phototan or Chiptan QR */
// convert PNG and load into widget
// TBD: check mimeType?
guchar *gudata = (guchar*)pChallenge;
@@@ -1019,7 -1050,16 +1075,7 @@@
gtk_image_set_from_pixbuf(optical_challenge, pixbuf);
}
- else if (g_strcmp0(mimeType,"text/x-flickercode") == 0 && pChallenge != NULL)
- {
- /* Chiptan Optic (aka Flicker) */
- flickergui->dialog = dialog;
- flickergui->input_entry = input_entry;
-
- ini_flicker_gui(pChallenge, flickergui);
- g_slice_free(GncFlickerGui, flickergui);
- }
-- #endif
++#endif
if (*input)
{
diff --cc po/POTFILES.in
index e1ffe403f,e1ffe403f..09c6ccc9b
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@@ -315,9 -315,9 +315,11 @@@ gnucash/import-export/aqb/gnc-ab-kvp.
gnucash/import-export/aqb/gnc-ab-transfer.c
gnucash/import-export/aqb/gnc-ab-utils.c
gnucash/import-export/aqb/gnc-file-aqb-import.c
++gnucash/import-export/aqb/gnc-flicker-gui.c
gnucash/import-export/aqb/gnc-gwen-gui.c
gnucash/import-export/aqb/gncmod-aqbanking.c
gnucash/import-export/aqb/gnc-plugin-aqbanking.c
++gnucash/import-export/aqb/gschemas/org.gnucash.dialogs.flicker.gschema.xml.in
gnucash/import-export/aqb/gschemas/org.gnucash.dialogs.import.hbci.gschema.xml.in
gnucash/import-export/bi-import/dialog-bi-import.c
gnucash/import-export/bi-import/dialog-bi-import-gui.c
commit 580975b924fb5b3c7cdf9f2ad04cb27b09a51fa7
Author: CWehli <christian.wehling at web.de>
Date: Sun Nov 15 15:06:09 2020 +0100
Bug 667490 - Support chipTAN optical "Flicker code"
Partly fixes bug 667490.
It implements the display of flashing optical TAN challenges (aka
flicker) in the "Enter TAN" dialog box.
diff --git a/gnucash/import-export/aqb/CMakeLists.txt b/gnucash/import-export/aqb/CMakeLists.txt
index e29c531d0..458b516e6 100644
--- a/gnucash/import-export/aqb/CMakeLists.txt
+++ b/gnucash/import-export/aqb/CMakeLists.txt
@@ -13,6 +13,7 @@ set (aqbanking_SOURCES
gnc-ab-transfer.c
gnc-ab-utils.c
gnc-file-aqb-import.c
+ gnc-flicker-gui.c
gnc-gwen-gui.c
gnc-plugin-aqbanking.c
gncmod-aqbanking.c
@@ -31,6 +32,7 @@ set (aqbanking_noinst_HEADERS
gnc-ab-transfer.h
gnc-ab-utils.h
gnc-file-aqb-import.h
+ gnc-flicker-gui.h
gnc-gwen-gui.h
gnc-plugin-aqbanking.h
)
diff --git a/gnucash/import-export/aqb/dialog-ab.glade b/gnucash/import-export/aqb/dialog-ab.glade
index d0e4450fe..0d78a5a83 100644
--- a/gnucash/import-export/aqb/dialog-ab.glade
+++ b/gnucash/import-export/aqb/dialog-ab.glade
@@ -634,14 +634,90 @@
</packing>
</child>
<child>
- <object class="GtkImage" id="optical_challenge">
- <property name="name">optical_challenge</property>
+ <object class="GtkBox" id="flicker_hbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="spacing">7</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">Bar_width</property>
+ <property name="xalign">0.7</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">spin_barwidth</property>
+ <attributes>
+ <attribute name="gravity" value="west"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spin_barwidth">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip-text" translatable="yes" comments="TAN generator with flicker interface common in DE only">Setting the bar width, adapting to the size of the TAN generator.</property>
+ <property name="numeric">True</property>
+ <property name="update_policy">if-valid</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="label" translatable="yes">_Delay</property>
+ <property name="xalign">0.7</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">spin_delay</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spin_delay">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip-text" translatable="yes" comments="TAN generator with flicker interface common in DE only">Setting the delay time, with small values the flicker graphic is repeated faster.</property>
+ <property name="numeric">True</property>
+ <property name="update_policy">if-valid</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkDrawingArea" id="flicker_marker">
+ <property name="visible">True</property>
+ <property name="app_paintable">True</property>
+ <property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
- <property name="icon_name">image-missing</property>
- <property name="icon_size">6</property>
</object>
<packing>
<property name="expand">False</property>
@@ -649,6 +725,48 @@
<property name="position">2</property>
</packing>
</child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImage" id="optical_challenge">
+ <property name="name">optical_challenge</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="icon_name">image-missing</property>
+ <property name="icon_size">6</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkDrawingArea" id="flicker_challenge">
+ <property name="visible">True</property>
+ <property name="app_paintable">True</property>
+ <property name="tooltip_text" translatable="yes" comments="TAN generator with flicker interface common in DE only">Hold the TAN generator in front of the animated graphic. The markings (triangles) on the graphic must match those on the TAN generator.</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
<child>
<object class="GtkGrid" id="grid1">
<property name="visible">True</property>
@@ -736,7 +854,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
- <property name="position">3</property>
+ <property name="position">4</property>
</packing>
</child>
</object>
diff --git a/gnucash/import-export/aqb/gnc-flicker-gui.c b/gnucash/import-export/aqb/gnc-flicker-gui.c
new file mode 100644
index 000000000..b8bb981e5
--- /dev/null
+++ b/gnucash/import-export/aqb/gnc-flicker-gui.c
@@ -0,0 +1,445 @@
+/*
+ * gnc-flicker-gui.c --
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
+ * Boston, MA 02110-1301, USA gnu at gnu.org
+ */
+
+/**
+ * @internal
+ * @file gnc-flicker-gui.c
+ * @brief GUI callbacks for Flicker and ChipTAN(optisch)
+ * @author Copyright (C) 2020 Christian Wehling <christian.wehling at web.de>
+ */
+
+#include <config.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include "dialog-utils.h"
+#include "gnc-flicker-gui.h"
+#include "gnc-state.h"
+#include "gnc-ui.h"
+
+#define GNC_PREFS_GROUP "dialogs.flicker"
+#define GNC_STATE_SECTION "Flicker"
+#define STATE_KEY_BAR_WIDTH "barwidth"
+#define STATE_KEY_DELAY "delay"
+
+#define BAR_WIDTH 44 /* Width of the flicker bars */
+#define BAR_HEIGHT 200 /* Height of the flicker bars */
+#define MARGIN 12 /* Distance between the flicker bars */
+#define DELAY 50 /* Pause between the flickering painting */
+
+static char *flicker_data (char const *challenge);
+static gboolean time_handler (GtkWidget *widget);
+static void do_marker_drawing (cairo_t *cr);
+static void draw_bit (cairo_t *cr, _Bool bit, int i);
+static void do_flicker_drawing (GtkWidget *widget, cairo_t *cr);
+static void do_flicker_load_state (GtkWidget *dialog);
+static void do_flicker_store_state (GtkWidget *dialog);
+static gboolean on_flicker_challenge_draw (GtkWidget *widget, cairo_t *cr,
+ gpointer user_data);
+static void on_flicker_challenge_map (GtkWidget *widget);
+static void on_flicker_challenge_destroy (GtkWidget *widget, gpointer user_data);
+static gboolean on_flicker_marker_draw (GtkWidget *widget, cairo_t *cr,
+ gpointer user_data);
+static void on_flicker_marker_map (GtkWidget *widget);
+static void on_spin_barwidth_value_changed (GtkSpinButton *spin, GtkWidget *widget);
+static void on_spin_delay_value_changed (GtkSpinButton *spin, GtkWidget *widget);
+static void on_dialog_destroy (GtkWidget *dialog, gpointer user_data);
+
+/* structured data for the flicker variables */
+struct Flickerdraw {
+ const char *challenge;
+ guint challenge_length;
+ guint margin; /* Distance between bars */
+ guint barwidth; /* Bar width */
+ guint barheight; /* Bar height */
+ guint x_barpos; /* x-value for the position of the bar */
+ guint y_barpos; /* y-value for the position of the bar */
+ guint x_drawpos; /* x-value of the first painting position */
+ guint y_drawpos; /* y-value of the first painting position */
+ guint height; /* Height of the drawing area */
+ guint width; /* Width of the drawing area */
+ guint delay; /* Waiting time between frames in milliseconds */
+ guint halfbyteid;
+ guint clock;
+ guint interval;
+ gboolean change_interval;
+};
+static struct Flickerdraw flickerdraw;
+
+static GncFlickerGui *flickergui = NULL;
+static _Bool bitarray[255][5];
+
+/* this function will return number corresponding 0,1,2..,9,A,B,C,D,E,F */
+static uint
+get_num (const char ch)
+{
+ int num =0;
+ if (ch >= '0' && ch <= '9')
+ num = ch - 0x30;
+ else
+ {
+ switch (ch)
+ {
+ case 'A': case 'a': num = 10; break;
+ case 'B': case 'b': num = 11; break;
+ case 'C': case 'c': num = 12; break;
+ case 'D': case 'd': num = 13; break;
+ case 'E': case 'e': num = 14; break;
+ case 'F': case 'f': num = 15; break;
+ default: num = 0;
+ }
+ }
+ /* The bank challenge has been verified by Aqbanking,
+ * so I assume that no error can occur. */
+ return num;
+}
+
+/* convert the bank challenge into the 5 bits for the flicker data */
+static char
+*flicker_data (const char *challenge)
+{
+ /* bitfield is a clock bit and a 4-bit code with the bits reversed
+ (bit 1 is the least significant and bit 4 the most
+ so 0x1 is 1000 and 0x8 is 0001) */
+ static const _Bool bits[16][5] =
+ {
+ {0, 0, 0, 0, 0}, {0, 1, 0, 0, 0}, {0, 0, 1, 0, 0}, {0, 1, 1, 0, 0},
+ {0, 0, 0, 1, 0}, {0, 1, 0, 1, 0}, {0, 0, 1, 1, 0}, {0, 1, 1, 1, 0},
+ {0, 0, 0, 0, 1}, {0, 1, 0, 0, 1}, {0, 0, 1, 0, 1}, {0, 1, 1, 0, 1},
+ {0, 0, 0, 1, 1}, {0, 1, 0, 1, 1}, {0, 0, 1, 1, 1}, {0, 1, 1, 1, 1}
+ };
+
+ /* prepend synchronization identifier */
+ const char pre[] = {'0', 'F', 'F', 'F'};
+ size_t len = sizeof (pre) + strlen (challenge) + 1;
+ char* code = (char*)malloc (len);
+ memcpy (code, pre, sizeof (pre));
+ memcpy (code + sizeof (pre), challenge, strlen (challenge));
+
+ /* Swap the position of the bits in pairs throughout the bank challenge
+ (low-order nibble first). */
+ for (uint i = 0; i < len - 1; i += 2)
+ {
+ u_int val1 = get_num (code[i]);
+ u_int val2 = get_num (code[i+1]);
+
+ memcpy (&bitarray[i], bits[val2], sizeof(bits[val2]));
+ memcpy (&bitarray[i+1], bits[val1], sizeof(bits[val1]));
+ }
+ return code;
+}
+
+/* A timer for redrawing the flickering painting, is started here and
+ * called up again when the "Delay" value is changed */
+static gboolean
+time_handler (GtkWidget *widget)
+{
+ /* Change of waiting time */
+ if (flickerdraw.change_interval)
+ {
+ g_source_remove (flickerdraw.interval);
+ flickerdraw.interval = g_timeout_add (flickerdraw.delay,
+ (GSourceFunc) time_handler,
+ (gpointer) widget);
+ flickerdraw.change_interval = FALSE;
+ return FALSE;
+ }
+ gtk_widget_queue_draw (widget);
+
+ return TRUE;
+}
+
+/* Show the colored triangle as a pointer for the position of the TAN generator */
+static void
+do_marker_drawing (cairo_t *cr)
+{
+ guint pos1;
+ guint pos2;
+
+ /* Initialize the drawing area to black */
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_paint (cr);
+
+ cairo_set_source_rgb (cr, 0.9, 0.1, 0.1);
+ /* draw the left triangle */
+ pos1 = flickerdraw.x_drawpos + flickerdraw.barwidth / 2;
+ cairo_move_to (cr, pos1, 20);
+ cairo_line_to (cr, pos1 + 10, 2);
+ cairo_line_to (cr, pos1 - 10, 2);
+ cairo_close_path (cr);
+ cairo_stroke_preserve (cr);
+ cairo_fill (cr);
+
+ /* draw the right triangle */
+ pos2 = flickerdraw.x_drawpos + 4 * flickerdraw.margin + 4 * flickerdraw.barwidth +
+ flickerdraw.barwidth / 2;
+ cairo_move_to (cr, pos2, 20);
+ cairo_line_to (cr, pos2 + 10, 2);
+ cairo_line_to (cr, pos2 - 10, 2);
+ cairo_close_path (cr);
+ cairo_stroke_preserve (cr);
+ cairo_fill (cr);
+}
+
+/* draws the 5 flickering bars of the bank data into the drawing area */
+static void
+draw_bit (cairo_t *cr, _Bool bit, int i)
+{
+ if (bit & 1)
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ else
+ cairo_set_source_rgb (cr, 0, 0, 0);
+
+ flickerdraw.x_barpos = flickerdraw.x_drawpos + i * flickerdraw.margin +
+ i * flickerdraw.barwidth;
+ cairo_rectangle (cr, flickerdraw.x_barpos, flickerdraw.y_barpos,
+ flickerdraw.barwidth, flickerdraw.barheight);
+ cairo_fill (cr);
+}
+
+/* Prepares the drawing area for the flicker graphic. */
+static void
+do_flicker_drawing (GtkWidget *widget, cairo_t *cr)
+{
+ /* Always align the flicker display in the middle of the drawing area */
+ flickerdraw.width = gtk_widget_get_allocated_width (widget);
+
+ /* Start position of the first bar */
+ flickerdraw.x_drawpos = (flickerdraw.width - 4 * flickerdraw.margin -
+ 5 * flickerdraw.barwidth) / 2;
+
+ /* Initialize the drawing area to black */
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_paint (cr);
+
+ /* paint the flicker graphic */
+ bitarray[flickerdraw.halfbyteid][0] = flickerdraw.clock;
+ draw_bit (cr, flickerdraw.clock, 0);
+ for (int i = 1; i <= 4; i++)
+ draw_bit (cr, bitarray[flickerdraw.halfbyteid][i], i);
+
+ /* Each flicker point is drawn twice. Once with clock = 1 and once with clock = 0 */
+ if (!flickerdraw.clock)
+ {
+ flickerdraw.clock = 1;
+ flickerdraw.halfbyteid++;
+ if (flickerdraw.halfbyteid >= flickerdraw.challenge_length)
+ flickerdraw.halfbyteid = 0;
+ }
+ else if (flickerdraw.clock)
+ flickerdraw.clock = 0;
+}
+
+/* Load the state of the GUI (Size of the Dialog, Value of the Spinbutton) */
+static void
+do_flicker_load_state (GtkWidget *dialog)
+{
+ /* Load the values in the spin button */
+ GKeyFile *state_file = gnc_state_get_current ();
+
+ if (g_key_file_has_key (state_file, GNC_STATE_SECTION, STATE_KEY_BAR_WIDTH, NULL))
+ flickerdraw.barwidth = g_key_file_get_integer (state_file,
+ GNC_STATE_SECTION,
+ STATE_KEY_BAR_WIDTH, NULL);
+ else
+ flickerdraw.barwidth = BAR_WIDTH;
+
+ if (g_key_file_has_key (state_file, GNC_STATE_SECTION, STATE_KEY_DELAY, NULL))
+ flickerdraw.delay = g_key_file_get_integer (state_file,
+ GNC_STATE_SECTION,
+ STATE_KEY_DELAY, NULL);
+ else
+ flickerdraw.delay = DELAY;
+
+ /* Load window size and position */
+ gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW (dialog),
+ gnc_ui_get_main_window (NULL));
+}
+
+/* Stores the state of the GUI (Size of the Dialog, Value of the Spinbutton) */
+static void
+do_flicker_store_state (GtkWidget *dialog)
+{
+ /* Save the values in the spin button */
+ GKeyFile *state_file = gnc_state_get_current ();
+
+ if (flickerdraw.barwidth != BAR_WIDTH)
+ g_key_file_set_integer (state_file, GNC_STATE_SECTION,
+ STATE_KEY_BAR_WIDTH, flickerdraw.barwidth);
+ else if (g_key_file_has_key (state_file, GNC_STATE_SECTION,
+ STATE_KEY_BAR_WIDTH, NULL))
+ g_key_file_remove_key (state_file, GNC_STATE_SECTION,
+ STATE_KEY_BAR_WIDTH, NULL);
+
+ if (flickerdraw.delay != DELAY)
+ g_key_file_set_integer (state_file, GNC_STATE_SECTION,
+ STATE_KEY_DELAY, flickerdraw.delay);
+ else if (g_key_file_has_key (state_file, GNC_STATE_SECTION,
+ STATE_KEY_DELAY, NULL))
+ g_key_file_remove_key (state_file, GNC_STATE_SECTION,
+ STATE_KEY_DELAY, NULL);
+
+ /* Save window size and position */
+ gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW (dialog));
+}
+
+/* This signal is emitted when the drawing area "flicker challenge" is visible */
+static void
+on_flicker_challenge_map (GtkWidget *widget)
+{
+ gchar *code = g_malloc (strlen (flickerdraw.challenge) + 4);
+ code = flicker_data (flickerdraw.challenge);
+ flickerdraw.challenge_length = strlen (code);
+
+ /* Set the height of the drawing area */
+ flickerdraw.height = flickerdraw.barheight + 2 * flickerdraw.y_barpos;
+ gtk_widget_set_size_request (widget, -1, flickerdraw.height);
+
+ /* Call up the time function and start the flicker display */
+ flickerdraw.interval = g_timeout_add (flickerdraw.delay,
+ (GSourceFunc) time_handler,
+ (gpointer) widget);
+}
+
+/* Initialize the drawingarea to black and paint the flickerchallenge */
+static gboolean
+on_flicker_challenge_draw (GtkWidget *widget, cairo_t *cr,
+ __attribute__((unused)) gpointer user_data)
+{
+ do_flicker_drawing (widget, cr);
+
+ return FALSE;
+}
+
+/* called when the drawing area is destroyed */
+static void
+on_flicker_challenge_destroy (GtkWidget *widget,
+ __attribute__((unused)) gpointer user_data)
+{
+ /* remove the timeout function */
+ g_source_remove (flickerdraw.interval);
+}
+
+/* Initialize the drawing area "flicker marker" in black and draw the marker for
+ * the position of the TAN-Generator */
+static gboolean
+on_flicker_marker_draw (__attribute__((unused)) GtkWidget *widget, cairo_t *cr,
+ __attribute__((unused)) gpointer data)
+{
+ do_marker_drawing (cr);
+
+ return FALSE;
+}
+
+/* This signal is emitted when the drawing area "flicker marker" is visible */
+static void
+on_flicker_marker_map (GtkWidget *widget)
+{
+ /* Set the height of the drawing area */
+ gtk_widget_set_size_request (widget, -1, flickerdraw.y_barpos);
+}
+
+/* The value for "Field width" has been changed on the spin button and the
+ * flicker display is updated */
+static void
+on_spin_barwidth_value_changed (GtkSpinButton *spin, GtkWidget *widget)
+{
+ flickerdraw.barwidth = gtk_spin_button_get_value_as_int (spin);
+ flickerdraw.x_drawpos = (flickerdraw.width - 4 * flickerdraw.margin -
+ 5 * flickerdraw.barwidth) / 2;
+
+ /* Moving the position triangles */
+ gtk_widget_queue_draw (widget);
+}
+
+/* The value for "waiting time" was changed on the spin button and
+ * the speed of the flickering display is updated */
+static void
+on_spin_delay_value_changed (GtkSpinButton *spin, GtkWidget *widget)
+{
+ flickerdraw.delay = gtk_spin_button_get_value_as_int (spin);
+
+ flickerdraw.change_interval = TRUE;
+ time_handler (widget);
+}
+
+static void
+on_dialog_destroy (GtkWidget *dialog, __attribute__((unused)) gpointer user_data)
+{
+ /* Store window size and initial setting values */
+ do_flicker_store_state (dialog);
+}
+
+/* The widgets for the GUI are prepared and the first parameters are set */
+void
+ini_flicker_gui (const char *pChallenge, GncFlickerGui *gui)
+{
+ /* Establish reference to the dialog widgets created in gnc_gwen_gui */
+ flickergui = gui;
+
+ /* Load window size and initial setting values */
+ do_flicker_load_state (GTK_WIDGET (flickergui->dialog));
+
+ /* Initialize application */
+ flickerdraw.barheight = BAR_HEIGHT;
+ flickerdraw.margin = MARGIN;
+ flickerdraw.y_barpos = 20; /* First painting position */
+ flickerdraw.halfbyteid = 0;
+ flickerdraw.clock = 1;
+
+ flickerdraw.challenge = pChallenge;
+
+ g_signal_connect (GTK_WINDOW (flickergui->dialog), "destroy",
+ G_CALLBACK (on_dialog_destroy), NULL);
+
+ g_signal_connect (GTK_WIDGET (flickergui->flicker_challenge), "map",
+ G_CALLBACK (on_flicker_challenge_map), NULL);
+ g_signal_connect (GTK_WIDGET (flickergui->flicker_challenge), "draw",
+ G_CALLBACK (on_flicker_challenge_draw), NULL);
+ g_signal_connect (GTK_WIDGET (flickergui->flicker_challenge), "destroy",
+ G_CALLBACK (on_flicker_challenge_destroy), NULL);
+
+ g_signal_connect (GTK_WIDGET (flickergui->flicker_marker), "map",
+ G_CALLBACK (on_flicker_marker_map), NULL);
+ g_signal_connect (GTK_WIDGET (flickergui->flicker_marker), "draw",
+ G_CALLBACK (on_flicker_marker_draw), NULL);
+
+ flickergui->adj_barwidth = gtk_adjustment_new (0.0, 10.0, 80.0, 1.0, 10.0, 0.0);
+ gtk_spin_button_set_adjustment (flickergui->spin_barwidth, flickergui->adj_barwidth);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (flickergui->spin_barwidth),
+ flickerdraw.barwidth);
+ g_signal_connect (GTK_WIDGET (flickergui->spin_barwidth), "value-changed",
+ G_CALLBACK (on_spin_barwidth_value_changed),
+ flickergui->flicker_marker);
+ gtk_widget_set_focus_on_click (GTK_WIDGET (flickergui->spin_barwidth), FALSE);
+
+ flickergui->adj_delay = gtk_adjustment_new (0.0, 10.0, 100.0, 10.0, 10.0, 0.0);
+ gtk_spin_button_set_adjustment (flickergui->spin_delay, flickergui->adj_delay);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (flickergui->spin_delay),
+ flickerdraw.delay);
+ g_signal_connect (GTK_WIDGET (flickergui->spin_delay), "value-changed",
+ G_CALLBACK (on_spin_delay_value_changed),
+ flickergui->flicker_challenge);
+ gtk_widget_set_focus_on_click (GTK_WIDGET (flickergui->spin_delay), FALSE);
+
+ gtk_widget_grab_focus (GTK_WIDGET (flickergui->input_entry));
+}
diff --git a/gnucash/import-export/aqb/gnc-flicker-gui.h b/gnucash/import-export/aqb/gnc-flicker-gui.h
new file mode 100644
index 000000000..bf1a7cd2b
--- /dev/null
+++ b/gnucash/import-export/aqb/gnc-flicker-gui.h
@@ -0,0 +1,63 @@
+/*
+ * gnc-flicker-gui.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
+ * Boston, MA 02110-1301, USA gnu at gnu.org
+ */
+
+/**
+ * @addtogroup Import_Export
+ * @{
+ * @addtogroup AqBanking
+ * @{
+ * @file gnc-flicker-gui.h
+ * @brief GUI callbacks for Flicker and ChipTAN(optisch)
+ * @author Copyright (C) 2020 Christian Wehling <christian.wehling at web.de>
+ */
+
+#ifndef GNC_FLICKER_GUI_H
+#define GNC_FLICKER_GUI_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+// structured data for the GUI
+typedef struct
+{
+ GtkWidget *dialog;
+ GtkWidget *input_entry;
+ GtkWidget *flicker_challenge;
+ GtkWidget *flicker_marker;
+ GtkWidget *flicker_hbox;
+ GtkAdjustment *adj_barwidth;
+ GtkAdjustment *adj_delay;
+ GtkSpinButton *spin_barwidth;
+ GtkSpinButton *spin_delay;
+} GncFlickerGui;
+
+/**
+ * Initialize the dialog and drawing area
+ *
+ * @param pChallenge: The answer from the bank which is shown as a flickering picture
+ * @param gui: The structure of the Dialog-Widgets
+ */
+void ini_flicker_gui (const char *pChallenge, GncFlickerGui *gui);
+
+G_END_DECLS
+
+#endif /* GNC_FLICKER_GUI_H */
diff --git a/gnucash/import-export/aqb/gnc-gwen-gui.c b/gnucash/import-export/aqb/gnc-gwen-gui.c
index 54fa72953..aeb70b481 100644
--- a/gnucash/import-export/aqb/gnc-gwen-gui.c
+++ b/gnucash/import-export/aqb/gnc-gwen-gui.c
@@ -46,6 +46,8 @@
#include "gnc-plugin-aqbanking.h"
#include "qof.h"
+#include "gnc-flicker-gui.h"
+
# define GNC_GWENHYWFAR_CB GWENHYWFAR_CB
#define GWEN_GUI_CM_CLASS "dialog-hbcilog"
@@ -928,6 +930,9 @@ get_input(GncGWENGui *gui, guint32 flags, const gchar *title,
GtkWidget *confirm_label;
GtkWidget *remember_pin_checkbutton;
GtkImage *optical_challenge;
+
+ static GncFlickerGui *flickergui = NULL;
+
const gchar *internal_input, *internal_confirmed;
gboolean confirm = (flags & GWEN_GUI_INPUT_FLAGS_CONFIRM) != 0;
gboolean is_tan = (flags & GWEN_GUI_INPUT_FLAGS_TAN) != 0;
@@ -949,9 +954,33 @@ get_input(GncGWENGui *gui, guint32 flags, const gchar *title,
remember_pin_checkbutton = GTK_WIDGET(gtk_builder_get_object (builder, "remember_pin"));
optical_challenge = GTK_IMAGE(gtk_builder_get_object (builder, "optical_challenge"));
gtk_widget_set_visible(GTK_WIDGET(optical_challenge), FALSE);
+
+ flickergui = g_slice_new(GncFlickerGui);
+ flickergui->flicker_challenge = GTK_WIDGET(gtk_builder_get_object(builder, "flicker_challenge"));
+ flickergui->flicker_marker = GTK_WIDGET(gtk_builder_get_object(builder, "flicker_marker"));
+ flickergui->flicker_hbox = GTK_WIDGET(gtk_builder_get_object(builder, "flicker_hbox"));
+ flickergui->spin_barwidth = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "spin_barwidth"));
+ flickergui->spin_delay = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "spin_delay"));
+
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->flicker_challenge), FALSE);
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->flicker_marker), FALSE);
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->flicker_hbox), FALSE);
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->spin_barwidth), FALSE);
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->spin_delay), FALSE);
+
#ifdef AQBANKING6
- if(mimeType != NULL && pChallenge != NULL && lChallenge > 0)
+ if (g_strcmp0(mimeType,"text/x-flickercode") == 0 && pChallenge != NULL)
{
+ /* Chiptan Optic (aka Flicker) */
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->flicker_challenge), TRUE);
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->flicker_marker), TRUE);
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->flicker_hbox), TRUE);
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->spin_barwidth), TRUE);
+ gtk_widget_set_visible(GTK_WIDGET(flickergui->spin_delay), TRUE);
+ }
+ else if(mimeType != NULL && pChallenge != NULL && lChallenge > 0)
+ {
+ /* Phototan or Chiptan QR */
gtk_widget_set_visible(GTK_WIDGET(optical_challenge), TRUE);
}
#endif
@@ -969,6 +998,7 @@ get_input(GncGWENGui *gui, guint32 flags, const gchar *title,
if ((flags & (GWEN_GUI_INPUT_FLAGS_TAN | GWEN_GUI_INPUT_FLAGS_SHOW)) != 0)
{
gtk_widget_set_visible(input_entry, TRUE);
+ gtk_entry_set_visibility(GTK_ENTRY(input_entry), TRUE);
}
if (gui->dialog)
@@ -996,6 +1026,7 @@ get_input(GncGWENGui *gui, guint32 flags, const gchar *title,
//if (optical_challenge)
if(mimeType != NULL && pChallenge != NULL && lChallenge > 0)
{
+ /* Phototan or Chiptan QR */
// convert PNG and load into widget
// TBD: check mimeType?
guchar *gudata = (guchar*)pChallenge;
@@ -1019,6 +1050,15 @@ get_input(GncGWENGui *gui, guint32 flags, const gchar *title,
gtk_image_set_from_pixbuf(optical_challenge, pixbuf);
}
+ else if (g_strcmp0(mimeType,"text/x-flickercode") == 0 && pChallenge != NULL)
+ {
+ /* Chiptan Optic (aka Flicker) */
+ flickergui->dialog = dialog;
+ flickergui->input_entry = input_entry;
+
+ ini_flicker_gui(pChallenge, flickergui);
+ g_slice_free(GncFlickerGui, flickergui);
+ }
#endif
if (*input)
@@ -1425,28 +1465,43 @@ getpassword_cb(GWEN_GUI *gwen_gui, guint32 flags, const gchar *token,
if(is_tan && methodId == GWEN_Gui_PasswordMethod_OpticalHHD)
{
/**
- * TODO: How to handle Flicker code (use WebView and JS???)
- *
* use GWEN_Gui_PasswordMethod_Mask to get the basic method id
* cf. gui/gui.h of gwenhywfar
*/
opticalMethodId=GWEN_DB_GetIntValue(methodParams, "tanMethodId", 0, AB_BANKING_TANMETHOD_TEXT);
switch(opticalMethodId)
{
+ case AB_BANKING_TANMETHOD_CHIPTAN:
+ break;
+ case AB_BANKING_TANMETHOD_CHIPTAN_OPTIC:
+ mimeType = "text/x-flickercode";
+ pChallenge = GWEN_DB_GetCharValue(methodParams, "challenge", 0, NULL);
+ if ((pChallenge == NULL) || (pChallenge[0] == '\0'))
+ {
+ /* empty flicker-data */
+ return GWEN_ERROR_NO_DATA;
+ }
+ break;
+ case AB_BANKING_TANMETHOD_CHIPTAN_USB:
+ /**
+ * ToDo: is this the same as CHIPTAN_OPTIC ?
+ */
+ break;
case AB_BANKING_TANMETHOD_PHOTOTAN:
case AB_BANKING_TANMETHOD_CHIPTAN_QR:
- /**
- * image data is in methodParams
- */
- mimeType=GWEN_DB_GetCharValue(methodParams, "mimeType", 0, NULL);
- pChallenge=(const char*) GWEN_DB_GetBinValue(methodParams, "imageData", 0, NULL, 0, &lChallenge);
- if (!(pChallenge && lChallenge)) {
- /* empty optical data */
- return GWEN_ERROR_NO_DATA;
- }
- break;
- default:
- break;
+ /**
+ * image data is in methodParams
+ */
+ mimeType=GWEN_DB_GetCharValue(methodParams, "mimeType", 0, NULL);
+ pChallenge=(const char*) GWEN_DB_GetBinValue(methodParams, "imageData", 0, NULL, 0, &lChallenge);
+ if (!(pChallenge && lChallenge))
+ {
+ /* empty optical data */
+ return GWEN_ERROR_NO_DATA;
+ }
+ break;
+ default:
+ break;
}
}
#endif
diff --git a/gnucash/import-export/aqb/gschemas/CMakeLists.txt b/gnucash/import-export/aqb/gschemas/CMakeLists.txt
index ba5425e6b..6ded5fd8d 100644
--- a/gnucash/import-export/aqb/gschemas/CMakeLists.txt
+++ b/gnucash/import-export/aqb/gschemas/CMakeLists.txt
@@ -1,8 +1,8 @@
if (WITH_AQBANKING)
- set(aqb_GSCHEMA org.gnucash.dialogs.import.hbci.gschema.xml)
+ set(aqb_GSCHEMA org.gnucash.dialogs.import.hbci.gschema.xml org.gnucash.dialogs.flicker.gschema.xml)
add_gschema_targets("${aqb_GSCHEMA}")
endif()
-set_dist_list(aqbanking_gschema_DIST CMakeLists.txt org.gnucash.dialogs.import.hbci.gschema.xml.in)
+set_dist_list(aqbanking_gschema_DIST CMakeLists.txt org.gnucash.dialogs.import.hbci.gschema.xml.in org.gnucash.dialogs.flicker.gschema.xml.in)
diff --git a/gnucash/import-export/aqb/gschemas/org.gnucash.dialogs.flicker.gschema.xml.in b/gnucash/import-export/aqb/gschemas/org.gnucash.dialogs.flicker.gschema.xml.in
new file mode 100644
index 000000000..d8e183f97
--- /dev/null
+++ b/gnucash/import-export/aqb/gschemas/org.gnucash.dialogs.flicker.gschema.xml.in
@@ -0,0 +1,13 @@
+<schemalist gettext-domain="@PROJECT_NAME@">
+
+ <schema id="org.gnucash.dialogs.flicker" path="/org/gnucash/dialogs/flicker/">
+ <key name="last-geometry" type="(iiii)">
+ <default>(-1,-1,-1,-1)</default>
+ <summary>Last window position and size</summary>
+ <description>This setting describes the size and position of the window when it was last closed.
+ The numbers are the X and Y coordinates of the top left corner of the window
+ followed by the width and height of the window.</description>
+ </key>
+ </schema>
+
+</schemalist>
Summary of changes:
gnucash/import-export/aqb/CMakeLists.txt | 2 +
gnucash/import-export/aqb/dialog-ab.glade | 128 +++++-
gnucash/import-export/aqb/gnc-flicker-gui.c | 445 +++++++++++++++++++++
.../aqb/{gnc-ab-transfer.h => gnc-flicker-gui.h} | 45 ++-
gnucash/import-export/aqb/gnc-gwen-gui.c | 107 ++++-
gnucash/import-export/aqb/gschemas/CMakeLists.txt | 4 +-
.../org.gnucash.dialogs.flicker.gschema.xml.in} | 9 +-
po/POTFILES.in | 2 +
8 files changed, 691 insertions(+), 51 deletions(-)
create mode 100644 gnucash/import-export/aqb/gnc-flicker-gui.c
copy gnucash/import-export/aqb/{gnc-ab-transfer.h => gnc-flicker-gui.h} (52%)
copy gnucash/{gschemas/org.gnucash.dialogs.commodities.gschema.xml.in => import-export/aqb/gschemas/org.gnucash.dialogs.flicker.gschema.xml.in} (62%)
More information about the gnucash-changes
mailing list