|
GnuCash 2.4.99
|
00001 /* 00002 * gnc-gwen-gui.c -- 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License as 00006 * published by the Free Software Foundation; either version 2 of 00007 * the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, contact: 00016 * 00017 * Free Software Foundation Voice: +1-617-542-5942 00018 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 00019 * Boston, MA 02110-1301, USA gnu@gnu.org 00020 */ 00021 00031 #include "config.h" 00032 00033 #include <ctype.h> 00034 #include <glib/gi18n.h> 00035 #include <gwenhywfar/gui_be.h> 00036 #include <gwenhywfar/inherit.h> 00037 00038 #include "dialog-utils.h" 00039 #include "gnc-ab-utils.h" 00040 #include "gnc-component-manager.h" 00041 #include "gnc-gconf-utils.h" 00042 #include "gnc-gwen-gui.h" 00043 #include "gnc-session.h" 00044 #include "gnc-ui.h" 00045 #include "gnc-plugin-aqbanking.h" 00046 #include "md5.h" 00047 #include "qof.h" 00048 00049 #if GWENHYWFAR_VERSION_INT >= 39921 00050 /* For sufficiently new gwenhywfar (>=3.99.21) the gtk2 gui object is 00051 * working fine and it is enabled here here. */ 00052 # define USING_GWENHYWFAR_GTK2_GUI 00053 # define GNC_GWENHYWFAR_CB GWENHYWFAR_CB 00054 #else 00055 # define GNC_GWENHYWFAR_CB 00056 #endif 00057 00058 #ifdef USING_GWENHYWFAR_GTK2_GUI 00059 # include <gwen-gui-gtk2/gtk2_gui.h> 00060 #endif 00061 00062 /* This static indicates the debugging module that this .o belongs to. */ 00063 static QofLogModule log_module = G_LOG_DOMAIN; 00064 00065 /* The following block can be enabled, but the gwen-gtk2 widgets might 00066 * still need some work. */ 00067 #if 0 /*#ifdef USING_GWENHYWFAR_GTK2_GUI*/ 00068 00069 /* A GWEN_GUI implementation using gtk2 widgets */ 00070 static GWEN_GUI *gwen_gui = NULL; 00071 00072 void gnc_GWEN_Gui_log_init(void) 00073 { 00074 if (!gwen_gui) 00075 { 00076 gwen_gui = Gtk2_Gui_new(); 00077 GWEN_Gui_SetGui(gwen_gui); 00078 } 00079 } 00080 GncGWENGui *gnc_GWEN_Gui_get(GtkWidget *parent) 00081 { 00082 if (!gwen_gui) 00083 gnc_GWEN_Gui_log_init(); 00084 return (GncGWENGui*) gwen_gui; 00085 } 00086 void gnc_GWEN_Gui_release(GncGWENGui *gui) 00087 { 00088 } 00089 void gnc_GWEN_Gui_shutdown(void) 00090 { 00091 if (gwen_gui) 00092 { 00093 GWEN_Gui_free(gwen_gui); 00094 gwen_gui = NULL; 00095 GWEN_Gui_SetGui(NULL); 00096 } 00097 } 00098 void 00099 gnc_GWEN_Gui_set_close_flag(gboolean close_when_finished) 00100 { 00101 gnc_gconf_set_bool( 00102 GCONF_SECTION_AQBANKING, KEY_CLOSE_ON_FINISH, 00103 close_when_finished, 00104 NULL); 00105 } 00106 gboolean 00107 gnc_GWEN_Gui_get_close_flag() 00108 { 00109 return gnc_gconf_get_bool(GCONF_SECTION_AQBANKING, KEY_CLOSE_ON_FINISH, NULL); 00110 } 00111 00112 gboolean 00113 gnc_GWEN_Gui_show_dialog() 00114 { 00115 return; 00116 } 00117 00118 void 00119 gnc_GWEN_Gui_hide_dialog() 00120 { 00121 } 00122 00123 #else 00124 00125 /* A unique full-blown GUI, featuring */ 00126 static GncGWENGui *full_gui = NULL; 00127 00128 /* A unique Gwenhywfar GUI for hooking our logging into the gwenhywfar logging 00129 * framework */ 00130 static GWEN_GUI *log_gwen_gui = NULL; 00131 00132 /* A mapping from gwenhywfar log levels to glib ones */ 00133 static GLogLevelFlags log_levels[] = 00134 { 00135 G_LOG_LEVEL_ERROR, /* GWEN_LoggerLevel_Emergency */ 00136 G_LOG_LEVEL_ERROR, /* GWEN_LoggerLevel_Alert */ 00137 G_LOG_LEVEL_CRITICAL, /* GWEN_LoggerLevel_Critical */ 00138 G_LOG_LEVEL_CRITICAL, /* GWEN_LoggerLevel_Error */ 00139 G_LOG_LEVEL_WARNING, /* GWEN_LoggerLevel_Warning */ 00140 G_LOG_LEVEL_MESSAGE, /* GWEN_LoggerLevel_Notice */ 00141 G_LOG_LEVEL_INFO, /* GWEN_LoggerLevel_Info */ 00142 G_LOG_LEVEL_DEBUG, /* GWEN_LoggerLevel_Debug */ 00143 G_LOG_LEVEL_DEBUG /* GWEN_LoggerLevel_Verbous */ 00144 }; 00145 static guint8 n_log_levels = G_N_ELEMENTS(log_levels); 00146 00147 /* Macros to determine the GncGWENGui* from a GWEN_GUI* */ 00148 GWEN_INHERIT(GWEN_GUI, GncGWENGui) 00149 #define SETDATA_GUI(gwen_gui, gui) GWEN_INHERIT_SETDATA(GWEN_GUI, GncGWENGui, \ 00150 (gwen_gui), (gui), NULL) 00151 #define GETDATA_GUI(gwen_gui) GWEN_INHERIT_GETDATA(GWEN_GUI, GncGWENGui, (gwen_gui)) 00152 00153 #define GWEN_GUI_CM_CLASS "dialog-hbcilog" 00154 #define GCONF_SECTION_CONNECTION GCONF_SECTION_AQBANKING "/connection_dialog" 00155 #define KEY_CLOSE_ON_FINISH "close_on_finish" 00156 #define KEY_REMEMBER_PIN "remember_pin" 00157 00158 #define OTHER_ENTRIES_ROW_OFFSET 3 00159 00160 typedef struct _Progress Progress; 00161 typedef enum _GuiState GuiState; 00162 00163 static void register_callbacks(GncGWENGui *gui); 00164 static void unregister_callbacks(GncGWENGui *gui); 00165 static void setup_dialog(GncGWENGui *gui); 00166 static void enable_password_cache(GncGWENGui *gui, gboolean enabled); 00167 static void reset_dialog(GncGWENGui *gui); 00168 static void set_finished(GncGWENGui *gui); 00169 static void set_aborted(GncGWENGui *gui); 00170 static void show_dialog(GncGWENGui *gui, gboolean clear_log); 00171 static void hide_dialog(GncGWENGui *gui); 00172 static gboolean show_progress_cb(gpointer user_data); 00173 static void show_progress(GncGWENGui *gui, Progress *progress); 00174 static void hide_progress(GncGWENGui *gui, Progress *progress); 00175 static void free_progress(Progress *progress, gpointer unused); 00176 static gboolean keep_alive(GncGWENGui *gui); 00177 static void cm_close_handler(gpointer user_data); 00178 static void erase_password(gchar *password); 00179 static gchar *strip_html(gchar *text); 00180 static void get_input(GncGWENGui *gui, guint32 flags, const gchar *title, 00181 const gchar *text, gchar **input, gint min_len, 00182 gint max_len); 00183 static gint messagebox_cb(GWEN_GUI *gwen_gui, guint32 flags, const gchar *title, 00184 const gchar *text, const gchar *b1, const gchar *b2, 00185 const gchar *b3, guint32 guiid); 00186 static gint inputbox_cb(GWEN_GUI *gwen_gui, guint32 flags, const gchar *title, 00187 const gchar *text, gchar *buffer, gint min_len, 00188 gint max_len, guint32 guiid); 00189 static guint32 showbox_cb(GWEN_GUI *gwen_gui, guint32 flags, const gchar *title, 00190 const gchar *text, guint32 guiid); 00191 static void hidebox_cb(GWEN_GUI *gwen_gui, guint32 id); 00192 static guint32 progress_start_cb(GWEN_GUI *gwen_gui, uint32_t progressFlags, 00193 const char *title, const char *text, 00194 uint64_t total, uint32_t guiid); 00195 static gint progress_advance_cb(GWEN_GUI *gwen_gui, uint32_t id, 00196 uint64_t new_progress); 00197 static gint progress_log_cb(GWEN_GUI *gwen_gui, guint32 id, 00198 GWEN_LOGGER_LEVEL level, const gchar *text); 00199 static gint progress_end_cb(GWEN_GUI *gwen_gui, guint32 id); 00200 static gint GNC_GWENHYWFAR_CB getpassword_cb(GWEN_GUI *gwen_gui, guint32 flags, const gchar *token, 00201 const gchar *title, const gchar *text, gchar *buffer, 00202 gint min_len, gint max_len, guint32 guiid); 00203 static gint GNC_GWENHYWFAR_CB setpasswordstatus_cb(GWEN_GUI *gwen_gui, const gchar *token, 00204 const gchar *pin, 00205 GWEN_GUI_PASSWORD_STATUS status, guint32 guiid); 00206 static gint GNC_GWENHYWFAR_CB loghook_cb(GWEN_GUI *gwen_gui, const gchar *log_domain, 00207 GWEN_LOGGER_LEVEL priority, const gchar *text); 00208 #ifdef AQBANKING_VERSION_5_PLUS 00209 typedef GWEN_SYNCIO GWEN_IO_LAYER; 00210 #endif 00211 static gint GNC_GWENHYWFAR_CB checkcert_cb(GWEN_GUI *gwen_gui, const GWEN_SSLCERTDESCR *cert, 00212 GWEN_IO_LAYER *io, guint32 guiid); 00213 00214 gboolean ggg_delete_event_cb(GtkWidget *widget, GdkEvent *event, 00215 gpointer user_data); 00216 void ggg_abort_clicked_cb(GtkButton *button, gpointer user_data); 00217 void ggg_close_clicked_cb(GtkButton *button, gpointer user_data); 00218 void ggg_close_toggled_cb(GtkToggleButton *button, gpointer user_data); 00219 00220 enum _GuiState 00221 { 00222 INIT, 00223 RUNNING, 00224 FINISHED, 00225 ABORTED, 00226 HIDDEN 00227 }; 00228 00229 struct _GncGWENGui 00230 { 00231 GWEN_GUI *gwen_gui; 00232 GtkWidget *parent; 00233 GtkWidget *dialog; 00234 00235 /* Progress bars */ 00236 GtkWidget *entries_table; 00237 GtkWidget *top_entry; 00238 GtkWidget *top_progress; 00239 GtkWidget *second_entry; 00240 GtkWidget *other_entries_box; 00241 00242 /* Stack of nested Progresses */ 00243 GList *progresses; 00244 00245 /* Number of steps in top-level progress or -1 */ 00246 guint64 max_actions; 00247 guint64 current_action; 00248 00249 /* Log window */ 00250 GtkWidget *log_text; 00251 00252 /* Buttons */ 00253 GtkWidget *abort_button; 00254 GtkWidget *close_button; 00255 GtkWidget *close_checkbutton; 00256 00257 /* Flags to keep track on whether an HBCI action is running or not */ 00258 gboolean keep_alive; 00259 GuiState state; 00260 00261 /* Password caching */ 00262 gboolean cache_passwords; 00263 GHashTable *passwords; 00264 00265 /* Certificates handling */ 00266 GHashTable *accepted_certs; 00267 GWEN_DB_NODE *permanently_accepted_certs; 00268 GWEN_GUI_CHECKCERT_FN builtin_checkcert; 00269 00270 /* Dialogs */ 00271 guint32 showbox_id; 00272 GHashTable *showbox_hash; 00273 GtkWidget *showbox_last; 00274 00275 /* Cache the lowest loglevel, corresponding to the most serious warning */ 00276 GWEN_LOGGER_LEVEL min_loglevel; 00277 }; 00278 00279 struct _Progress 00280 { 00281 GncGWENGui *gui; 00282 00283 /* Title of the process */ 00284 gchar *title; 00285 00286 /* Event source id for showing delayed */ 00287 guint source; 00288 }; 00289 00290 void 00291 gnc_GWEN_Gui_log_init(void) 00292 { 00293 if (!log_gwen_gui) 00294 { 00295 log_gwen_gui = 00296 #ifdef USING_GWENHYWFAR_GTK2_GUI 00297 Gtk2_Gui_new() 00298 #else 00299 GWEN_Gui_new() 00300 #endif 00301 ; 00302 00303 /* Always use our own logging */ 00304 GWEN_Gui_SetLogHookFn(log_gwen_gui, loghook_cb); 00305 00306 /* Keep a reference so that the GWEN_GUI survives a GUI switch */ 00307 GWEN_Gui_Attach(log_gwen_gui); 00308 } 00309 GWEN_Gui_SetGui(log_gwen_gui); 00310 } 00311 00312 GncGWENGui * 00313 gnc_GWEN_Gui_get(GtkWidget *parent) 00314 { 00315 GncGWENGui *gui; 00316 00317 ENTER("parent=%p", parent); 00318 00319 if (full_gui) 00320 { 00321 if (full_gui->state == INIT || full_gui->state == RUNNING) 00322 { 00323 LEAVE("full_gui in use, state=%d", full_gui->state); 00324 return NULL; 00325 } 00326 00327 gui = full_gui; 00328 gui->parent = parent; 00329 reset_dialog(gui); 00330 register_callbacks(gui); 00331 00332 LEAVE("gui=%p", gui); 00333 return gui; 00334 } 00335 00336 gui = g_new0(GncGWENGui, 1); 00337 gui->parent = parent; 00338 setup_dialog(gui); 00339 register_callbacks(gui); 00340 00341 full_gui = gui; 00342 00343 LEAVE("new gui=%p", gui); 00344 return gui; 00345 } 00346 00347 void 00348 gnc_GWEN_Gui_release(GncGWENGui *gui) 00349 { 00350 g_return_if_fail(gui && gui == full_gui); 00351 00352 /* Currently a no-op */ 00353 ENTER("gui=%p", gui); 00354 LEAVE(" "); 00355 } 00356 00357 void 00358 gnc_GWEN_Gui_shutdown(void) 00359 { 00360 GncGWENGui *gui = full_gui; 00361 00362 ENTER(" "); 00363 00364 if (log_gwen_gui) 00365 { 00366 GWEN_Gui_free(log_gwen_gui); 00367 log_gwen_gui = NULL; 00368 } 00369 GWEN_Gui_SetGui(NULL); 00370 00371 if (!gui) 00372 return; 00373 00374 gui->parent = NULL; 00375 reset_dialog(gui); 00376 if (gui->passwords) 00377 g_hash_table_destroy(gui->passwords); 00378 if (gui->showbox_hash) 00379 g_hash_table_destroy(gui->showbox_hash); 00380 if (gui->permanently_accepted_certs) 00381 GWEN_DB_Group_free(gui->permanently_accepted_certs); 00382 if (gui->accepted_certs) 00383 g_hash_table_destroy(gui->accepted_certs); 00384 gtk_widget_destroy(gui->dialog); 00385 g_free(gui); 00386 00387 full_gui = NULL; 00388 00389 LEAVE(" "); 00390 } 00391 00392 void 00393 gnc_GWEN_Gui_set_close_flag(gboolean close_when_finished) 00394 { 00395 gnc_gconf_set_bool( 00396 GCONF_SECTION_AQBANKING, KEY_CLOSE_ON_FINISH, 00397 close_when_finished, 00398 NULL); 00399 00400 if (full_gui) 00401 { 00402 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(full_gui->close_checkbutton)) 00403 != close_when_finished) 00404 { 00405 gtk_toggle_button_set_active( 00406 GTK_TOGGLE_BUTTON(full_gui->close_checkbutton), 00407 close_when_finished); 00408 } 00409 } 00410 } 00411 00412 gboolean 00413 gnc_GWEN_Gui_get_close_flag() 00414 { 00415 return gnc_gconf_get_bool(GCONF_SECTION_AQBANKING, KEY_CLOSE_ON_FINISH, NULL); 00416 } 00417 00418 gboolean 00419 gnc_GWEN_Gui_show_dialog() 00420 { 00421 GncGWENGui *gui = full_gui; 00422 00423 if (!gui) 00424 { 00425 gnc_GWEN_Gui_get(NULL); 00426 } 00427 00428 if (gui) 00429 { 00430 if (gui->state == HIDDEN) 00431 { 00432 gui->state = FINISHED; 00433 } 00434 gtk_toggle_button_set_active( 00435 GTK_TOGGLE_BUTTON(gui->close_checkbutton), 00436 gnc_gconf_get_bool(GCONF_SECTION_AQBANKING, KEY_CLOSE_ON_FINISH, NULL)); 00437 00438 show_dialog(gui, FALSE); 00439 00440 return TRUE; 00441 } 00442 00443 return FALSE; 00444 } 00445 00446 void 00447 gnc_GWEN_Gui_hide_dialog() 00448 { 00449 GncGWENGui *gui = full_gui; 00450 00451 if (gui) 00452 { 00453 hide_dialog(gui); 00454 } 00455 } 00456 00457 static void 00458 register_callbacks(GncGWENGui *gui) 00459 { 00460 GWEN_GUI *gwen_gui; 00461 00462 g_return_if_fail(gui && !gui->gwen_gui); 00463 00464 ENTER("gui=%p", gui); 00465 00466 gwen_gui = 00467 #ifdef USING_GWENHYWFAR_GTK2_GUI 00468 Gtk2_Gui_new() 00469 #else 00470 GWEN_Gui_new() 00471 #endif 00472 ; 00473 gui->gwen_gui = gwen_gui; 00474 00475 GWEN_Gui_SetMessageBoxFn(gwen_gui, messagebox_cb); 00476 GWEN_Gui_SetInputBoxFn(gwen_gui, inputbox_cb); 00477 GWEN_Gui_SetShowBoxFn(gwen_gui, showbox_cb); 00478 GWEN_Gui_SetHideBoxFn(gwen_gui, hidebox_cb); 00479 GWEN_Gui_SetProgressStartFn(gwen_gui, progress_start_cb); 00480 GWEN_Gui_SetProgressAdvanceFn(gwen_gui, progress_advance_cb); 00481 GWEN_Gui_SetProgressLogFn(gwen_gui, progress_log_cb); 00482 GWEN_Gui_SetProgressEndFn(gwen_gui, progress_end_cb); 00483 GWEN_Gui_SetGetPasswordFn(gwen_gui, getpassword_cb); 00484 GWEN_Gui_SetSetPasswordStatusFn(gwen_gui, setpasswordstatus_cb); 00485 GWEN_Gui_SetLogHookFn(gwen_gui, loghook_cb); 00486 gui->builtin_checkcert = GWEN_Gui_SetCheckCertFn(gwen_gui, checkcert_cb); 00487 00488 GWEN_Gui_SetGui(gwen_gui); 00489 SETDATA_GUI(gwen_gui, gui); 00490 00491 LEAVE(" "); 00492 } 00493 00494 static void 00495 unregister_callbacks(GncGWENGui *gui) 00496 { 00497 g_return_if_fail(gui); 00498 00499 ENTER("gui=%p", gui); 00500 00501 if (!gui->gwen_gui) 00502 { 00503 LEAVE("already unregistered"); 00504 return; 00505 } 00506 00507 /* Switch to log_gwen_gui and free gui->gwen_gui */ 00508 gnc_GWEN_Gui_log_init(); 00509 00510 gui->gwen_gui = NULL; 00511 00512 LEAVE(" "); 00513 } 00514 00515 static void 00516 setup_dialog(GncGWENGui *gui) 00517 { 00518 GtkBuilder *builder; 00519 gint component_id; 00520 00521 g_return_if_fail(gui); 00522 00523 ENTER("gui=%p", gui); 00524 00525 builder = gtk_builder_new(); 00526 gnc_builder_add_from_file (builder, "dialog-ab.glade", "Connection Dialog"); 00527 00528 gui->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Connection Dialog")); 00529 00530 gui->entries_table = GTK_WIDGET(gtk_builder_get_object (builder, "entries_table")); 00531 gui->top_entry = GTK_WIDGET(gtk_builder_get_object (builder, "top_entry")); 00532 gui->top_progress = GTK_WIDGET(gtk_builder_get_object (builder, "top_progress")); 00533 gui->second_entry = GTK_WIDGET(gtk_builder_get_object (builder, "second_entry")); 00534 gui->other_entries_box = NULL; 00535 gui->progresses = NULL; 00536 gui->log_text = GTK_WIDGET(gtk_builder_get_object (builder, "log_text")); 00537 gui->abort_button = GTK_WIDGET(gtk_builder_get_object (builder, "abort_button")); 00538 gui->close_button = GTK_WIDGET(gtk_builder_get_object (builder, "close_button")); 00539 gui->close_checkbutton = GTK_WIDGET(gtk_builder_get_object (builder, "close_checkbutton")); 00540 gui->accepted_certs = NULL; 00541 gui->permanently_accepted_certs = NULL; 00542 gui->showbox_hash = NULL; 00543 gui->showbox_id = 1; 00544 00545 /* Connect the Signals */ 00546 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, gui); 00547 00548 gtk_toggle_button_set_active( 00549 GTK_TOGGLE_BUTTON(gui->close_checkbutton), 00550 gnc_gconf_get_bool(GCONF_SECTION_AQBANKING, KEY_CLOSE_ON_FINISH, NULL)); 00551 00552 component_id = gnc_register_gui_component(GWEN_GUI_CM_CLASS, NULL, 00553 cm_close_handler, gui); 00554 gnc_gui_component_set_session(component_id, gnc_get_current_session()); 00555 00556 00557 00558 g_object_unref(G_OBJECT(builder)); 00559 00560 reset_dialog(gui); 00561 00562 LEAVE(" "); 00563 } 00564 00565 static void 00566 enable_password_cache(GncGWENGui *gui, gboolean enabled) 00567 { 00568 g_return_if_fail(gui); 00569 00570 if (enabled && !gui->passwords) 00571 { 00572 /* Remember passwords in memory, mapping tokens to passwords */ 00573 gui->passwords = g_hash_table_new_full( 00574 g_str_hash, g_str_equal, (GDestroyNotify) g_free, 00575 (GDestroyNotify) erase_password); 00576 } 00577 else if (!enabled && gui->passwords) 00578 { 00579 /* Erase and free remembered passwords from memory */ 00580 g_hash_table_destroy(gui->passwords); 00581 gui->passwords = NULL; 00582 } 00583 gui->cache_passwords = enabled; 00584 } 00585 00586 static void 00587 reset_dialog(GncGWENGui *gui) 00588 { 00589 gboolean cache_passwords; 00590 00591 g_return_if_fail(gui); 00592 00593 ENTER("gui=%p", gui); 00594 00595 gtk_entry_set_text(GTK_ENTRY(gui->top_entry), ""); 00596 gtk_entry_set_text(GTK_ENTRY(gui->second_entry), ""); 00597 g_list_foreach(gui->progresses, (GFunc) free_progress, NULL); 00598 g_list_free(gui->progresses); 00599 gui->progresses = NULL; 00600 00601 if (gui->other_entries_box) 00602 { 00603 gtk_table_resize(GTK_TABLE(gui->entries_table), 00604 OTHER_ENTRIES_ROW_OFFSET, 2); 00605 gtk_widget_destroy(gui->other_entries_box); 00606 gui->other_entries_box = NULL; 00607 } 00608 if (gui->showbox_hash) 00609 g_hash_table_destroy(gui->showbox_hash); 00610 gui->showbox_last = NULL; 00611 gui->showbox_hash = g_hash_table_new_full( 00612 NULL, NULL, NULL, (GDestroyNotify) gtk_widget_destroy); 00613 00614 if (gui->parent) 00615 gtk_window_set_transient_for(GTK_WINDOW(gui->dialog), 00616 GTK_WINDOW(gui->parent)); 00617 gnc_restore_window_size(GCONF_SECTION_CONNECTION, GTK_WINDOW(gui->dialog)); 00618 00619 gui->keep_alive = TRUE; 00620 gui->state = INIT; 00621 gui->min_loglevel = GWEN_LoggerLevel_Verbous; 00622 00623 cache_passwords = gnc_gconf_get_bool(GCONF_SECTION_AQBANKING, 00624 KEY_REMEMBER_PIN, NULL); 00625 enable_password_cache(gui, cache_passwords); 00626 00627 if (!gui->accepted_certs) 00628 gui->accepted_certs = g_hash_table_new_full( 00629 g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL); 00630 if (!gui->permanently_accepted_certs) 00631 gui->permanently_accepted_certs = gnc_ab_get_permanent_certs(); 00632 00633 LEAVE(" "); 00634 } 00635 00636 static void 00637 set_running(GncGWENGui *gui) 00638 { 00639 g_return_if_fail(gui); 00640 00641 ENTER("gui=%p", gui); 00642 00643 gui->state = RUNNING; 00644 gtk_widget_set_sensitive(gui->abort_button, TRUE); 00645 gtk_widget_set_sensitive(gui->close_button, FALSE); 00646 gui->keep_alive = TRUE; 00647 00648 LEAVE(" "); 00649 } 00650 00651 static void 00652 set_finished(GncGWENGui *gui) 00653 { 00654 g_return_if_fail(gui); 00655 00656 ENTER("gui=%p", gui); 00657 00658 /* Do not serve as GUI anymore */ 00659 gui->state = FINISHED; 00660 unregister_callbacks(gui); 00661 00662 gtk_widget_set_sensitive(gui->abort_button, FALSE); 00663 gtk_widget_set_sensitive(gui->close_button, TRUE); 00664 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gui->close_checkbutton))) 00665 hide_dialog(gui); 00666 00667 LEAVE(" "); 00668 } 00669 00670 static void 00671 set_aborted(GncGWENGui *gui) 00672 { 00673 g_return_if_fail(gui); 00674 00675 ENTER("gui=%p", gui); 00676 00677 /* Do not serve as GUI anymore */ 00678 gui->state = ABORTED; 00679 unregister_callbacks(gui); 00680 00681 gtk_widget_set_sensitive(gui->abort_button, FALSE); 00682 gtk_widget_set_sensitive(gui->close_button, TRUE); 00683 gui->keep_alive = FALSE; 00684 00685 LEAVE(" "); 00686 } 00687 00688 static void 00689 show_dialog(GncGWENGui *gui, gboolean clear_log) 00690 { 00691 gboolean cache_pin; 00692 00693 g_return_if_fail(gui); 00694 00695 ENTER("gui=%p, clear_log=%d", gui, clear_log); 00696 00697 gtk_widget_show(gui->dialog); 00698 00699 gnc_plugin_aqbanking_set_logwindow_visible(TRUE); 00700 00701 /* Clear the log window */ 00702 if (clear_log) 00703 { 00704 gtk_text_buffer_set_text( 00705 gtk_text_view_get_buffer(GTK_TEXT_VIEW(gui->log_text)), "", 0); 00706 } 00707 00708 LEAVE(" "); 00709 } 00710 00711 static void 00712 hide_dialog(GncGWENGui *gui) 00713 { 00714 g_return_if_fail(gui); 00715 00716 ENTER("gui=%p", gui); 00717 00718 /* Hide the dialog */ 00719 gtk_widget_hide(gui->dialog); 00720 00721 gnc_plugin_aqbanking_set_logwindow_visible(FALSE); 00722 00723 /* Remember whether the dialog is to be closed when finished */ 00724 gnc_gconf_set_bool( 00725 GCONF_SECTION_AQBANKING, KEY_CLOSE_ON_FINISH, 00726 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gui->close_checkbutton)), 00727 NULL); 00728 00729 /* Remember size and position of the dialog */ 00730 gnc_save_window_size(GCONF_SECTION_CONNECTION, GTK_WINDOW(gui->dialog)); 00731 00732 /* Do not serve as GUI anymore */ 00733 gui->state = HIDDEN; 00734 unregister_callbacks(gui); 00735 00736 LEAVE(" "); 00737 } 00738 00739 static gboolean 00740 show_progress_cb(gpointer user_data) 00741 { 00742 Progress *progress = user_data; 00743 GncGWENGui *gui; 00744 GList *item; 00745 00746 g_return_val_if_fail(progress, FALSE); 00747 00748 ENTER("progress=%p", progress); 00749 00750 show_progress(progress->gui, progress); 00751 00752 LEAVE(" "); 00753 return FALSE; 00754 } 00755 00759 static void 00760 show_progress(GncGWENGui *gui, Progress *progress) 00761 { 00762 GList *item; 00763 Progress *current; 00764 00765 g_return_if_fail(gui); 00766 00767 ENTER("gui=%p, progress=%p", gui, progress); 00768 00769 for (item = g_list_last(gui->progresses); item; item = item->prev) 00770 { 00771 current = (Progress*) item->data; 00772 00773 if (!current->source 00774 && current != progress) 00775 /* Already showed */ 00776 continue; 00777 00778 /* Show it */ 00779 if (!item->next) 00780 { 00781 /* Top-level progress */ 00782 show_dialog(gui, TRUE); 00783 gtk_entry_set_text(GTK_ENTRY(gui->top_entry), current->title); 00784 } 00785 else if (!item->next->next) 00786 { 00787 /* Second-level progress */ 00788 gtk_entry_set_text(GTK_ENTRY(gui->second_entry), current->title); 00789 } 00790 else 00791 { 00792 /* Other progress */ 00793 GtkWidget *entry = gtk_entry_new(); 00794 GtkWidget *box = gui->other_entries_box; 00795 gboolean new_box = box == NULL; 00796 00797 gtk_entry_set_text(GTK_ENTRY(entry), current->title); 00798 if (new_box) 00799 gui->other_entries_box = box = gtk_vbox_new(TRUE, 6); 00800 gtk_box_pack_start_defaults(GTK_BOX(box), entry); 00801 gtk_widget_show(entry); 00802 if (new_box) 00803 { 00804 gtk_table_resize(GTK_TABLE(gui->entries_table), 00805 OTHER_ENTRIES_ROW_OFFSET + 1, 2); 00806 gtk_table_attach_defaults( 00807 GTK_TABLE(gui->entries_table), box, 1, 2, 00808 OTHER_ENTRIES_ROW_OFFSET, OTHER_ENTRIES_ROW_OFFSET + 1); 00809 gtk_widget_show(box); 00810 } 00811 } 00812 00813 if (current->source) 00814 { 00815 /* Stop delayed call */ 00816 g_source_remove(current->source); 00817 current->source = 0; 00818 } 00819 00820 if (current == progress) 00821 break; 00822 } 00823 00824 LEAVE(" "); 00825 } 00826 00830 static void 00831 hide_progress(GncGWENGui *gui, Progress *progress) 00832 { 00833 GList *item; 00834 Progress *current; 00835 00836 g_return_if_fail(gui); 00837 00838 ENTER("gui=%p, progress=%p", gui, progress); 00839 00840 for (item = gui->progresses; item; item = item->next) 00841 { 00842 current = (Progress*) item->data; 00843 00844 if (current->source) 00845 { 00846 /* Not yet showed */ 00847 g_source_remove(current->source); 00848 current->source = 0; 00849 if (current == progress) 00850 break; 00851 else 00852 continue; 00853 } 00854 00855 /* Hide it */ 00856 if (!item->next) 00857 { 00858 /* Top-level progress */ 00859 gtk_entry_set_text(GTK_ENTRY(gui->second_entry), ""); 00860 } 00861 else if (!item->next->next) 00862 { 00863 /* Second-level progress */ 00864 gtk_entry_set_text(GTK_ENTRY(gui->second_entry), ""); 00865 } 00866 else 00867 { 00868 /* Other progress */ 00869 GtkWidget *box = gui->other_entries_box; 00870 GList *entries; 00871 00872 g_return_if_fail(box); 00873 entries = gtk_container_get_children(GTK_CONTAINER(box)); 00874 g_return_if_fail(entries); 00875 if (entries->next) 00876 { 00877 /* Another progress is still to be showed */ 00878 gtk_widget_destroy(GTK_WIDGET(g_list_last(entries)->data)); 00879 } 00880 else 00881 { 00882 /* Last other progress to be hided */ 00883 gtk_table_resize(GTK_TABLE(gui->entries_table), 00884 OTHER_ENTRIES_ROW_OFFSET, 2); 00885 gtk_widget_destroy(box); 00886 gui->other_entries_box = NULL; 00887 } 00888 g_list_free(entries); 00889 } 00890 00891 if (current == progress) 00892 break; 00893 } 00894 00895 LEAVE(" "); 00896 } 00897 00898 static void 00899 free_progress(Progress *progress, gpointer unused) 00900 { 00901 if (progress->source) 00902 g_source_remove(progress->source); 00903 g_free(progress->title); 00904 g_free(progress); 00905 } 00906 00907 static gboolean 00908 keep_alive(GncGWENGui *gui) 00909 { 00910 g_return_val_if_fail(gui, FALSE); 00911 00912 ENTER("gui=%p", gui); 00913 00914 /* Let the widgets be redrawn */ 00915 while (g_main_context_iteration(NULL, FALSE)); 00916 00917 LEAVE("alive=%d", gui->keep_alive); 00918 return gui->keep_alive; 00919 } 00920 00921 static void 00922 cm_close_handler(gpointer user_data) 00923 { 00924 GncGWENGui *gui = user_data; 00925 00926 g_return_if_fail(gui); 00927 00928 ENTER("gui=%p", gui); 00929 00930 /* FIXME */ 00931 set_aborted(gui); 00932 00933 LEAVE(" "); 00934 } 00935 00936 static void 00937 erase_password(gchar *password) 00938 { 00939 g_return_if_fail(password); 00940 00941 ENTER(" "); 00942 00943 memset(password, 0, strlen(password)); 00944 g_free(password); 00945 00946 LEAVE(" "); 00947 } 00948 00952 static gchar * 00953 strip_html(gchar *text) 00954 { 00955 gchar *p, *q; 00956 00957 if (!text) 00958 return NULL; 00959 00960 p = text; 00961 while (strchr(p, '<')) 00962 { 00963 q = p + 1; 00964 if (*q && toupper(*q++) == 'H' 00965 && *q && toupper(*q++) == 'T' 00966 && *q && toupper(*q++) == 'M' 00967 && *q && toupper(*q) == 'L') 00968 { 00969 *p = '\0'; 00970 return text; 00971 } 00972 p++; 00973 } 00974 return text; 00975 } 00976 00977 static void 00978 get_input(GncGWENGui *gui, guint32 flags, const gchar *title, const gchar *text, 00979 gchar **input, gint min_len, gint max_len) 00980 { 00981 GtkBuilder *builder; 00982 GtkWidget *dialog; 00983 GtkWidget *heading_label; 00984 GtkWidget *input_entry; 00985 GtkWidget *confirm_entry; 00986 GtkWidget *confirm_label; 00987 GtkWidget *remember_pin_checkbutton; 00988 const gchar *internal_input, *internal_confirmed; 00989 gboolean confirm = (flags & GWEN_GUI_INPUT_FLAGS_CONFIRM) != 0; 00990 gboolean hidden = (flags & GWEN_GUI_INPUT_FLAGS_SHOW) == 0; 00991 gboolean is_tan = (flags & GWEN_GUI_INPUT_FLAGS_TAN) != 0; 00992 gint retval; 00993 00994 g_return_if_fail(input); 00995 g_return_if_fail(max_len >= min_len && max_len > 0); 00996 00997 ENTER(" "); 00998 00999 /* Set up dialog */ 01000 builder = gtk_builder_new(); 01001 gnc_builder_add_from_file (builder, "dialog-ab.glade", "Password Dialog"); 01002 dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Password Dialog")); 01003 01004 heading_label = GTK_WIDGET(gtk_builder_get_object (builder, "heading_label")); 01005 input_entry = GTK_WIDGET(gtk_builder_get_object (builder, "input_entry")); 01006 confirm_entry = GTK_WIDGET(gtk_builder_get_object (builder, "confirm_entry")); 01007 confirm_label = GTK_WIDGET(gtk_builder_get_object (builder, "confirm_label")); 01008 remember_pin_checkbutton = GTK_WIDGET(gtk_builder_get_object (builder, "remember_pin")); 01009 if (is_tan) 01010 { 01011 gtk_widget_hide(remember_pin_checkbutton); 01012 } 01013 else 01014 { 01015 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(remember_pin_checkbutton), 01016 gui->cache_passwords); 01017 } 01018 01019 if (gui->parent) 01020 gtk_window_set_transient_for(GTK_WINDOW(dialog), 01021 GTK_WINDOW(gui->parent)); 01022 if (title) 01023 gtk_window_set_title(GTK_WINDOW(dialog), title); 01024 01025 if (text) 01026 { 01027 gchar *raw_text = strip_html(g_strdup(text)); 01028 gtk_label_set_text(GTK_LABEL(heading_label), raw_text); 01029 g_free(raw_text); 01030 } 01031 01032 if (*input) 01033 { 01034 gtk_entry_set_text(GTK_ENTRY(input_entry), *input); 01035 erase_password(*input); 01036 *input = NULL; 01037 } 01038 01039 if (confirm) 01040 { 01041 gtk_entry_set_activates_default(GTK_ENTRY(input_entry), FALSE); 01042 gtk_entry_set_activates_default(GTK_ENTRY(confirm_entry), TRUE); 01043 gtk_entry_set_max_length(GTK_ENTRY(input_entry), max_len); 01044 gtk_entry_set_max_length(GTK_ENTRY(confirm_entry), max_len); 01045 } 01046 else 01047 { 01048 gtk_entry_set_activates_default(GTK_ENTRY(input_entry), TRUE); 01049 gtk_entry_set_max_length(GTK_ENTRY(input_entry), max_len); 01050 gtk_widget_hide(confirm_entry); 01051 gtk_widget_hide(confirm_label); 01052 } 01053 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); 01054 01055 /* Ask the user until he enters a valid input or cancels */ 01056 while (TRUE) 01057 { 01058 gboolean remember_pin; 01059 01060 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) 01061 break; 01062 01063 if (!is_tan) 01064 { 01065 /* Enable or disable the password cache */ 01066 remember_pin = gtk_toggle_button_get_active( 01067 GTK_TOGGLE_BUTTON(remember_pin_checkbutton)); 01068 enable_password_cache(gui, remember_pin); 01069 gnc_gconf_set_bool(GCONF_SECTION_AQBANKING, KEY_REMEMBER_PIN, 01070 remember_pin, NULL); 01071 } 01072 01073 internal_input = gtk_entry_get_text(GTK_ENTRY(input_entry)); 01074 if (strlen(internal_input) < min_len) 01075 { 01076 gboolean retval; 01077 gchar *msg = g_strdup_printf( 01078 _("The PIN needs to be at least %d characters \n" 01079 "long. Do you want to try again?"), min_len); 01080 retval = gnc_verify_dialog(gui->parent, TRUE, "%s", msg); 01081 g_free(msg); 01082 if (!retval) 01083 break; 01084 continue; 01085 } 01086 01087 if (!confirm) 01088 { 01089 *input = g_strdup(internal_input); 01090 break; 01091 } 01092 01093 internal_confirmed = gtk_entry_get_text(GTK_ENTRY(confirm_entry)); 01094 if (strcmp(internal_input, internal_confirmed) == 0) 01095 { 01096 *input = g_strdup(internal_input); 01097 break; 01098 } 01099 } 01100 01101 g_object_unref(G_OBJECT(builder)); 01102 01103 /* This trashes passwords in the entries' memory as well */ 01104 gtk_widget_destroy(dialog); 01105 01106 LEAVE("input %s", *input ? "non-NULL" : "NULL"); 01107 } 01108 01109 static gint 01110 messagebox_cb(GWEN_GUI *gwen_gui, guint32 flags, const gchar *title, 01111 const gchar *text, const gchar *b1, const gchar *b2, 01112 const gchar *b3, guint32 guiid) 01113 { 01114 GncGWENGui *gui = GETDATA_GUI(gwen_gui); 01115 GtkWidget *dialog; 01116 GtkWidget *vbox; 01117 GtkWidget *label; 01118 gchar *raw_text; 01119 gint result; 01120 01121 ENTER("gui=%p, flags=%d, title=%s, b1=%s, b2=%s, b3=%s", gui, flags, 01122 title ? title : "(null)", b1 ? b1 : "(null)", b2 ? b2 : "(null)", 01123 b3 ? b3 : "(null)"); 01124 01125 dialog = gtk_dialog_new_with_buttons( 01126 title, gui->parent ? GTK_WINDOW(gui->parent) : NULL, 01127 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, 01128 b1, 1, b2, 2, b3, 3, (gchar*) NULL); 01129 01130 raw_text = strip_html(g_strdup(text)); 01131 label = gtk_label_new(raw_text); 01132 g_free(raw_text); 01133 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); 01134 vbox = gtk_vbox_new(TRUE, 0); 01135 gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); 01136 gtk_container_add(GTK_CONTAINER(vbox), label); 01137 gtk_container_set_border_width(GTK_CONTAINER(dialog), 5); 01138 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), vbox); 01139 gtk_widget_show_all(dialog); 01140 01141 result = gtk_dialog_run(GTK_DIALOG(dialog)); 01142 gtk_widget_destroy(dialog); 01143 01144 if (result < 1 || result > 3) 01145 { 01146 g_warning("messagebox_cb: Bad result %d", result); 01147 result = 0; 01148 } 01149 01150 LEAVE("result=%d", result); 01151 return result; 01152 } 01153 01154 static gint 01155 inputbox_cb(GWEN_GUI *gwen_gui, guint32 flags, const gchar *title, 01156 const gchar *text, gchar *buffer, gint min_len, gint max_len, 01157 guint32 guiid) 01158 { 01159 GncGWENGui *gui = GETDATA_GUI(gwen_gui); 01160 gchar *input = NULL; 01161 01162 g_return_val_if_fail(gui, -1); 01163 01164 ENTER("gui=%p, flags=%d", gui, flags); 01165 01166 get_input(gui, flags, title, text, &input, min_len, max_len); 01167 01168 if (input) 01169 { 01170 /* Copy the input to the result buffer */ 01171 strncpy(buffer, input, max_len); 01172 buffer[max_len-1] = '\0'; 01173 } 01174 01175 LEAVE(" "); 01176 return input ? 0 : -1; 01177 } 01178 01179 static guint32 01180 showbox_cb(GWEN_GUI *gwen_gui, guint32 flags, const gchar *title, 01181 const gchar *text, guint32 guiid) 01182 { 01183 GncGWENGui *gui = GETDATA_GUI(gwen_gui); 01184 GtkWidget *dialog; 01185 guint32 showbox_id; 01186 01187 g_return_val_if_fail(gui, -1); 01188 01189 ENTER("gui=%p, flags=%d, title=%s", gui, flags, title ? title : "(null)"); 01190 01191 dialog = gtk_message_dialog_new( 01192 gui->parent ? GTK_WINDOW(gui->parent) : NULL, 0, GTK_MESSAGE_INFO, 01193 GTK_BUTTONS_OK, "%s", text); 01194 01195 if (title) 01196 gtk_window_set_title(GTK_WINDOW(dialog), title); 01197 01198 g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_hide), NULL); 01199 gtk_widget_show_all(dialog); 01200 01201 showbox_id = gui->showbox_id++; 01202 g_hash_table_insert(gui->showbox_hash, GUINT_TO_POINTER(showbox_id), 01203 dialog); 01204 gui->showbox_last = dialog; 01205 01206 /* Give it a change to be showed */ 01207 if (!keep_alive(gui)) 01208 showbox_id = 0; 01209 01210 LEAVE("id=%" G_GUINT32_FORMAT, showbox_id); 01211 return showbox_id; 01212 } 01213 01214 static void 01215 hidebox_cb(GWEN_GUI *gwen_gui, guint32 id) 01216 { 01217 GncGWENGui *gui = GETDATA_GUI(gwen_gui); 01218 GtkWidget *dialog; 01219 01220 g_return_if_fail(gui && gui->showbox_hash); 01221 01222 ENTER("gui=%p, id=%d", gui, id); 01223 01224 if (id == 0) 01225 { 01226 if (gui->showbox_last) 01227 { 01228 g_hash_table_remove(gui->showbox_hash, 01229 GUINT_TO_POINTER(gui->showbox_id)); 01230 gui->showbox_last = NULL; 01231 } 01232 else 01233 { 01234 g_warning("hidebox_cb: Last showed message box already destroyed"); 01235 } 01236 } 01237 else 01238 { 01239 gpointer p_var; 01240 p_var = g_hash_table_lookup(gui->showbox_hash, GUINT_TO_POINTER(id)); 01241 if (p_var) 01242 { 01243 g_hash_table_remove(gui->showbox_hash, GUINT_TO_POINTER(id)); 01244 if (p_var == gui->showbox_last) 01245 gui->showbox_last = NULL; 01246 } 01247 else 01248 { 01249 g_warning("hidebox_cb: Message box %d could not been found", id); 01250 } 01251 } 01252 01253 LEAVE(" "); 01254 } 01255 01256 static guint32 01257 progress_start_cb(GWEN_GUI *gwen_gui, uint32_t progressFlags, const char *title, 01258 const char *text, uint64_t total, uint32_t guiid) 01259 { 01260 GncGWENGui *gui = GETDATA_GUI(gwen_gui); 01261 Progress *progress; 01262 01263 g_return_val_if_fail(gui, -1); 01264 01265 ENTER("gui=%p, flags=%d, title=%s, total=%" G_GUINT64_FORMAT, gui, 01266 progressFlags, title ? title : "(null)", (guint64)total); 01267 01268 if (!gui->progresses) 01269 { 01270 /* Top-level progress */ 01271 if (progressFlags & GWEN_GUI_PROGRESS_SHOW_PROGRESS) 01272 { 01273 gtk_widget_set_sensitive(gui->top_progress, TRUE); 01274 gtk_progress_bar_set_fraction( 01275 GTK_PROGRESS_BAR(gui->top_progress), 0.0); 01276 gui->max_actions = total; 01277 } 01278 else 01279 { 01280 gtk_widget_set_sensitive(gui->top_progress, FALSE); 01281 gui->max_actions = -1; 01282 } 01283 set_running(gui); 01284 } 01285 01286 /* Put progress onto the stack */ 01287 progress = g_new0(Progress, 1); 01288 progress->gui = gui; 01289 progress->title = title ? g_strdup(title) : ""; 01290 gui->progresses = g_list_prepend(gui->progresses, progress); 01291 01292 if (progressFlags & GWEN_GUI_PROGRESS_DELAY) 01293 { 01294 /* Show progress later */ 01295 progress->source = g_timeout_add(GWEN_GUI_DELAY_SECS * 1000, 01296 (GSourceFunc) show_progress_cb, 01297 progress); 01298 } 01299 else 01300 { 01301 /* Show it now */ 01302 progress->source = 0; 01303 show_progress(gui, progress); 01304 } 01305 01306 LEAVE(" "); 01307 return g_list_length(gui->progresses); 01308 } 01309 01310 static gint 01311 progress_advance_cb(GWEN_GUI *gwen_gui, uint32_t id, uint64_t progress) 01312 { 01313 GncGWENGui *gui = GETDATA_GUI(gwen_gui); 01314 01315 g_return_val_if_fail(gui, -1); 01316 01317 ENTER("gui=%p, progress=%" G_GUINT64_FORMAT, gui, (guint64)progress); 01318 01319 if (id == 1 /* top-level progress */ 01320 && gui->max_actions > 0 /* progressbar active */ 01321 && progress != GWEN_GUI_PROGRESS_NONE) /* progressbar update needed */ 01322 { 01323 if (progress == GWEN_GUI_PROGRESS_ONE) 01324 gui->current_action++; 01325 else 01326 gui->current_action = progress; 01327 01328 gtk_progress_bar_set_fraction( 01329 GTK_PROGRESS_BAR(gui->top_progress), 01330 ((gdouble) gui->current_action) / ((gdouble) gui->max_actions)); 01331 } 01332 01333 LEAVE(" "); 01334 return !keep_alive(gui); 01335 } 01336 01337 static gint 01338 progress_log_cb(GWEN_GUI *gwen_gui, guint32 id, GWEN_LOGGER_LEVEL level, 01339 const gchar *text) 01340 { 01341 GncGWENGui *gui = GETDATA_GUI(gwen_gui); 01342 GtkTextBuffer *tb; 01343 GtkTextView *tv; 01344 01345 g_return_val_if_fail(gui, -1); 01346 01347 ENTER("gui=%p, text=%s", gui, text ? text : "(null)"); 01348 01349 tv = GTK_TEXT_VIEW(gui->log_text); 01350 tb = gtk_text_view_get_buffer(tv); 01351 gtk_text_buffer_insert_at_cursor(tb, text, -1); 01352 gtk_text_buffer_insert_at_cursor(tb, "\n", -1); 01353 01354 /* Scroll to the end of the buffer */ 01355 gtk_text_view_scroll_to_mark(tv, gtk_text_buffer_get_insert(tb), 01356 0.0, FALSE, 0.0, 0.0); 01357 01358 /* Cache loglevel */ 01359 if (level < gui->min_loglevel) 01360 gui->min_loglevel = level; 01361 01362 LEAVE(" "); 01363 return !keep_alive(gui); 01364 } 01365 01366 static gint 01367 progress_end_cb(GWEN_GUI *gwen_gui, guint32 id) 01368 { 01369 GncGWENGui *gui = GETDATA_GUI(gwen_gui); 01370 Progress *progress; 01371 01372 g_return_val_if_fail(gui, -1); 01373 g_return_val_if_fail(id == g_list_length(gui->progresses), -1); 01374 01375 ENTER("gui=%p, id=%d", gui, id); 01376 01377 if (gui->state != RUNNING) 01378 { 01379 /* Ignore finishes of progresses we do not track */ 01380 LEAVE("not running anymore"); 01381 return 0; 01382 } 01383 01384 /* Hide progress */ 01385 progress = (Progress*) gui->progresses->data; 01386 hide_progress(gui, progress); 01387 01388 /* Remove progress from stack and free memory */ 01389 gui->progresses = g_list_delete_link(gui->progresses, gui->progresses); 01390 free_progress(progress, NULL); 01391 01392 if (!gui->progresses) 01393 { 01394 /* top-level progress finished */ 01395 set_finished(gui); 01396 } 01397 01398 LEAVE(" "); 01399 return 0; 01400 } 01401 01402 static gint GNC_GWENHYWFAR_CB 01403 getpassword_cb(GWEN_GUI *gwen_gui, guint32 flags, const gchar *token, 01404 const gchar *title, const gchar *text, gchar *buffer, 01405 gint min_len, gint max_len, guint32 guiid) 01406 { 01407 GncGWENGui *gui = GETDATA_GUI(gwen_gui); 01408 gchar *password = NULL; 01409 gboolean is_tan = (flags & GWEN_GUI_INPUT_FLAGS_TAN) != 0; 01410 01411 g_return_val_if_fail(gui, -1); 01412 01413 ENTER("gui=%p, flags=%d, token=%s", gui, flags, token ? token : "(null"); 01414 01415 /* Check remembered passwords, excluding TANs */ 01416 if (!is_tan && gui->cache_passwords && gui->passwords && token) 01417 { 01418 if (flags & GWEN_GUI_INPUT_FLAGS_RETRY) 01419 { 01420 /* If remembered, remove password from memory */ 01421 g_hash_table_remove(gui->passwords, token); 01422 } 01423 else 01424 { 01425 gpointer p_var; 01426 if (g_hash_table_lookup_extended(gui->passwords, token, NULL, 01427 &p_var)) 01428 { 01429 /* Copy the password to the result buffer */ 01430 password = p_var; 01431 strncpy(buffer, password, max_len); 01432 buffer[max_len-1] = '\0'; 01433 01434 LEAVE("chose remembered password"); 01435 return 0; 01436 } 01437 } 01438 } 01439 01440 get_input(gui, flags, title, text, &password, min_len, max_len); 01441 01442 if (password) 01443 { 01444 /* Copy the password to the result buffer */ 01445 strncpy(buffer, password, max_len); 01446 buffer[max_len-1] = '\0'; 01447 01448 if (!is_tan && token) 01449 { 01450 if (gui->cache_passwords && gui->passwords) 01451 { 01452 /* Remember password */ 01453 DEBUG("Remember password, token=%s", token); 01454 g_hash_table_insert(gui->passwords, g_strdup(token), password); 01455 } 01456 else 01457 { 01458 /* Remove the password from memory */ 01459 DEBUG("Forget password, token=%s", token); 01460 erase_password(password); 01461 } 01462 } 01463 } 01464 01465 LEAVE(" "); 01466 return password ? 0 : -1; 01467 } 01468 01469 static gint GNC_GWENHYWFAR_CB 01470 setpasswordstatus_cb(GWEN_GUI *gwen_gui, const gchar *token, const gchar *pin, 01471 GWEN_GUI_PASSWORD_STATUS status, guint32 guiid) 01472 { 01473 GncGWENGui *gui = GETDATA_GUI(gwen_gui); 01474 01475 g_return_val_if_fail(gui, -1); 01476 01477 ENTER("gui=%p, token=%s, status=%d", gui, token ? token : "(null)", status); 01478 01479 if (gui->passwords && status != GWEN_Gui_PasswordStatus_Ok) 01480 { 01481 /* If remembered, remove password from memory */ 01482 g_hash_table_remove(gui->passwords, token); 01483 } 01484 01485 LEAVE(" "); 01486 return 0; 01487 } 01488 01489 static gint GNC_GWENHYWFAR_CB 01490 loghook_cb(GWEN_GUI *gwen_gui, const gchar *log_domain, 01491 GWEN_LOGGER_LEVEL priority, const gchar *text) 01492 { 01493 if (G_LIKELY(priority < n_log_levels)) 01494 g_log(log_domain, log_levels[priority], "%s", text); 01495 01496 return 1; 01497 } 01498 01499 static gint GNC_GWENHYWFAR_CB 01500 checkcert_cb(GWEN_GUI *gwen_gui, const GWEN_SSLCERTDESCR *cert, 01501 GWEN_IO_LAYER *io, guint32 guiid) 01502 { 01503 GncGWENGui *gui = GETDATA_GUI(gwen_gui); 01504 const gchar *hash, *status; 01505 struct md5_ctx md5_context; 01506 gchar cert_hash[16]; 01507 gchar *cert_hash_hex; 01508 gint retval, i; 01509 01510 g_return_val_if_fail(gui && gui->accepted_certs, -1); 01511 01512 ENTER("gui=%p, cert=%p", gui, cert); 01513 01514 hash = GWEN_SslCertDescr_GetFingerPrint(cert); 01515 status = GWEN_SslCertDescr_GetStatusText(cert); 01516 01517 /* Operate on an md5sum of the pair of hash and status */ 01518 md5_init_ctx(&md5_context); 01519 md5_process_bytes(hash, strlen(hash), &md5_context); 01520 md5_process_bytes(status, strlen(status), &md5_context); 01521 md5_finish_ctx(&md5_context, cert_hash); 01522 01523 /* Did we get the permanently accepted certs from AqBanking? */ 01524 if (gui->permanently_accepted_certs) 01525 { 01526 /* Generate a hex string of the cert_hash for usage by AqBanking cert store */ 01527 cert_hash_hex = g_new0(gchar, 33); 01528 for (i = 0; i < 16; i++) 01529 g_snprintf(cert_hash_hex + 2 * i, 3, "%02X", (unsigned char)cert_hash[i]); 01530 01531 retval = GWEN_DB_GetIntValue(gui->permanently_accepted_certs, cert_hash_hex, 0, -1); 01532 g_free(cert_hash_hex); 01533 if (retval == 0) 01534 { 01535 /* Certificate is marked as accepted in AqBanking's cert store */ 01536 LEAVE("Certificate accepted by AqBanking's permanent cert store"); 01537 return 0; 01538 } 01539 } 01540 else 01541 { 01542 g_warning("Can't check permanently accepted certs from invalid AqBanking cert store."); 01543 } 01544 01545 if (g_hash_table_lookup(gui->accepted_certs, cert_hash)) 01546 { 01547 /* Certificate has been accepted by Gnucash before */ 01548 LEAVE("Automatically accepting certificate"); 01549 return 0; 01550 } 01551 01552 retval = gui->builtin_checkcert(gwen_gui, cert, io, guiid); 01553 if (retval == 0) 01554 { 01555 /* Certificate has been accepted */ 01556 g_hash_table_insert(gui->accepted_certs, g_strdup(cert_hash), cert_hash); 01557 } 01558 01559 LEAVE("retval=%d", retval); 01560 return retval; 01561 } 01562 01563 gboolean 01564 ggg_delete_event_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) 01565 { 01566 GncGWENGui *gui = user_data; 01567 01568 g_return_val_if_fail(gui, FALSE); 01569 01570 ENTER("gui=%p, state=%d", gui, gui->state); 01571 01572 if (gui->state == RUNNING) 01573 { 01574 const char *still_running_msg = 01575 _("The Online Banking job is still running; are you " 01576 "sure you want to cancel?"); 01577 if (!gnc_verify_dialog(gui->dialog, FALSE, "%s", still_running_msg)) 01578 return FALSE; 01579 01580 set_aborted(gui); 01581 } 01582 01583 hide_dialog(gui); 01584 01585 LEAVE(" "); 01586 return TRUE; 01587 } 01588 01589 void 01590 ggg_abort_clicked_cb(GtkButton *button, gpointer user_data) 01591 { 01592 GncGWENGui *gui = user_data; 01593 01594 g_return_if_fail(gui && gui->state == RUNNING); 01595 01596 ENTER("gui=%p", gui); 01597 01598 set_aborted(gui); 01599 01600 LEAVE(" "); 01601 } 01602 01603 void 01604 ggg_close_clicked_cb(GtkButton *button, gpointer user_data) 01605 { 01606 GncGWENGui *gui = user_data; 01607 01608 g_return_if_fail(gui); 01609 g_return_if_fail(gui->state == FINISHED || gui->state == ABORTED); 01610 01611 ENTER("gui=%p", gui); 01612 01613 hide_dialog(gui); 01614 01615 LEAVE(" "); 01616 } 01617 01618 void 01619 ggg_close_toggled_cb(GtkToggleButton *button, gpointer user_data) 01620 { 01621 GncGWENGui *gui = user_data; 01622 01623 g_return_if_fail(gui); 01624 g_return_if_fail(gui->parent); 01625 01626 ENTER("gui=%p", gui); 01627 01628 gnc_gconf_set_bool( 01629 GCONF_SECTION_AQBANKING, KEY_CLOSE_ON_FINISH, 01630 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)), 01631 NULL); 01632 01633 LEAVE(" "); 01634 } 01635 #endif
1.7.4