diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/remmina_connection_window.c | 187 | ||||
-rw-r--r-- | src/remmina_connection_window.h | 3 | ||||
-rw-r--r-- | src/remmina_masterthread_exec.c | 15 | ||||
-rw-r--r-- | src/remmina_masterthread_exec.h | 26 | ||||
-rw-r--r-- | src/remmina_message_panel.c | 1132 | ||||
-rw-r--r-- | src/remmina_message_panel.h | 38 | ||||
-rw-r--r-- | src/remmina_plugin_manager.c | 36 | ||||
-rw-r--r-- | src/remmina_protocol_widget.c | 473 | ||||
-rw-r--r-- | src/remmina_protocol_widget.h | 49 | ||||
-rw-r--r-- | src/remmina_sftp_plugin.c | 3 | ||||
-rw-r--r-- | src/remmina_ssh.c | 61 | ||||
-rw-r--r-- | src/remmina_ssh.h | 2 | ||||
-rw-r--r-- | src/remmina_ssh_plugin.c | 3 |
13 files changed, 854 insertions, 1174 deletions
diff --git a/src/remmina_connection_window.c b/src/remmina_connection_window.c index 2e4b630f3..771f40fde 100644 --- a/src/remmina_connection_window.c +++ b/src/remmina_connection_window.c @@ -149,8 +149,6 @@ typedef struct _RemminaConnectionObject { GtkWidget* page; GtkWidget* scrolled_container; - GtkWidget* message_panel; - gboolean plugin_can_scale; gboolean connected; @@ -264,6 +262,9 @@ static void remmina_connection_window_class_init(RemminaConnectionWindowClass* k " padding: 2px;\n" " border: 0;\n" "}\n" + "#remmina-page {\n" + " background-color: black;\n" + "}\n" "#remmina-scrolled-container {\n" " background-color: black;\n" "}\n" @@ -1643,7 +1644,7 @@ static void remmina_connection_holder_toolbar_preferences(GtkWidget* widget, Rem GtkWidget* menu; GtkWidget* menuitem; gboolean separator; - const gchar* domain; + gchar* domain; gboolean enabled; if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(widget))) @@ -1680,6 +1681,8 @@ static void remmina_connection_holder_toolbar_preferences(GtkWidget* widget, Rem } } + g_free(domain); + g_signal_connect(G_OBJECT(menu), "deactivate", G_CALLBACK(remmina_connection_holder_toolbar_preferences_popdown), cnnhld); @@ -2316,8 +2319,11 @@ static void remmina_connection_window_focus_out(GtkWidget* widget, RemminaConnec if (REMMINA_IS_SCROLLED_VIEWPORT(cnnobj->scrolled_container)) { remmina_scrolled_viewport_remove_motion(REMMINA_SCROLLED_VIEWPORT(cnnobj->scrolled_container)); } - remmina_protocol_widget_call_feature_by_type(REMMINA_PROTOCOL_WIDGET(cnnobj->proto), - REMMINA_PROTOCOL_FEATURE_TYPE_UNFOCUS, 0); + + if (cnnobj->proto && cnnobj->scrolled_container) { + remmina_protocol_widget_call_feature_by_type(REMMINA_PROTOCOL_WIDGET(cnnobj->proto), + REMMINA_PROTOCOL_FEATURE_TYPE_UNFOCUS, 0); + } } @@ -2873,6 +2879,7 @@ static gint remmina_connection_object_append_page(RemminaConnectionObject* cnnob cnnobj->page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); g_object_set_data(G_OBJECT(cnnobj->page), "cnnobj", cnnobj); + gtk_widget_set_name(cnnobj->page, "remmina-scrolled-container"); remmina_connection_object_create_scrolled_container(cnnobj, view_mode); gtk_box_pack_start(GTK_BOX(cnnobj->page), cnnobj->scrolled_container, TRUE, TRUE, 0); @@ -2916,16 +2923,12 @@ static void remmina_connection_window_initialize_notebook(GtkNotebook* to, GtkNo * of GtkNotebook will return */ } else { - /* cnnobj is not on the "from" notebook. This is a new connection for a newly created window */ + /* cnnobj is not on the "from" notebook. This is a new connection for a newly created window, + * just add a tab put cnnobj->scrolled_container inside cnnobj->viewport */ tab = remmina_connection_object_create_tab(cnnobj); remmina_connection_object_append_page(cnnobj, to, tab, view_mode); - printf("GIO: here another warning...\n"); - G_GNUC_BEGIN_IGNORE_DEPRECATIONS - gtk_widget_reparent(cnnobj->viewport, cnnobj->scrolled_container); - G_GNUC_END_IGNORE_DEPRECATIONS - printf("GIO: appeared\n"); - + gtk_container_add(GTK_CONTAINER(cnnobj->scrolled_container), cnnobj->viewport); } }else { /* cnnobj=null: migrate all existing connections to the new notebook */ @@ -3735,6 +3738,9 @@ static void remmina_connection_object_on_connect(RemminaProtocolWidget* gp, Remm } #endif + /* Try to present window */ + g_timeout_add(200, remmina_connection_object_delayed_window_present, (gpointer)cnnobj); + } static void remmina_connection_object_closewin(RemminaProtocolWidget* gp) @@ -3743,11 +3749,11 @@ static void remmina_connection_object_closewin(RemminaProtocolWidget* gp) RemminaConnectionObject* cnnobj = gp->cnnobj; RemminaConnectionHolder* cnnhld = cnnobj->cnnhld; - if (cnnhld && cnnhld->cnnwin && cnnobj->scrolled_container) { + if (cnnhld && cnnhld->cnnwin) { gtk_notebook_remove_page( GTK_NOTEBOOK(cnnhld->cnnwin->priv->notebook), gtk_notebook_page_num(GTK_NOTEBOOK(cnnhld->cnnwin->priv->notebook), - cnnobj->scrolled_container)); + cnnobj->page)); } cnnobj->remmina_file = NULL; @@ -3756,10 +3762,9 @@ static void remmina_connection_object_closewin(RemminaProtocolWidget* gp) remmina_application_condexit(REMMINA_CONDEXIT_ONDISCONNECT); } -static void cb_lasterror_confirmed(GtkButton *button, void *cbdata) +static void cb_lasterror_confirmed(void *cbdata, int btn) { TRACE_CALL(__func__); - printf("GIO: in cb_lasterror_confirmed gp=%p\n", cbdata); remmina_connection_object_closewin((RemminaProtocolWidget*)cbdata); } @@ -3795,9 +3800,15 @@ static void remmina_connection_object_on_disconnect(RemminaProtocolWidget* gp, g FALSE); if (remmina_protocol_widget_has_error(gp)) { + /* We cannot close window immediately, but we must show a message panel */ RemminaMessagePanel *mp; + /* Destroy scrolled_contaner (and viewport) and all its children the plugin created + * on it, so they will not receive GUI signals */ + gtk_widget_destroy(cnnobj->scrolled_container); + cnnobj->scrolled_container = NULL; + cnnobj->viewport = NULL; mp = remmina_message_panel_new(); - remmina_message_panel_setup_message(mp, remmina_protocol_widget_get_error_message(gp)); + remmina_message_panel_setup_message(mp, remmina_protocol_widget_get_error_message(gp), cb_lasterror_confirmed, gp); remmina_connection_object_show_message_panel(gp->cnnobj, mp); }else { remmina_connection_object_closewin(gp); @@ -3860,7 +3871,6 @@ GtkWidget* remmina_connection_window_open_from_file_full(RemminaFile* remminafil TRACE_CALL(__func__); RemminaConnectionObject* cnnobj; - GtkWidget* protocolwidget; gint ret; GtkWidget* dialog; RemminaConnectionWindow* cnnwin; @@ -3878,6 +3888,16 @@ GtkWidget* remmina_connection_window_open_from_file_full(RemminaFile* remminafil /* Create the RemminaProtocolWidget */ cnnobj->proto = remmina_protocol_widget_new(); remmina_protocol_widget_setup((RemminaProtocolWidget*)cnnobj->proto, remminafile, cnnobj); + /* Set a name for the widget, for CSS selector */ + gtk_widget_set_name(GTK_WIDGET(cnnobj->proto), "remmina-protocol-widget"); + + gtk_widget_set_halign(GTK_WIDGET(cnnobj->proto), GTK_ALIGN_FILL); + gtk_widget_set_valign(GTK_WIDGET(cnnobj->proto), GTK_ALIGN_FILL); + + if (data) { + g_object_set_data(G_OBJECT(cnnobj->proto), "user-data", data); + } + /* Set default remote desktop size in the profile, so the plugins can query * protocolwidget and know WxH that the user put on the profile settings */ @@ -3886,6 +3906,24 @@ GtkWidget* remmina_connection_window_open_from_file_full(RemminaFile* remminafil remmina_file_get_int(remminafile, "resolution_height", -1) ); + /* Create the viewport to make the RemminaProtocolWidget scrollable */ + cnnobj->viewport = gtk_viewport_new(NULL, NULL); + gtk_widget_set_name(cnnobj->viewport, "remmina-cw-viewport"); + gtk_widget_show(cnnobj->viewport); + gtk_container_set_border_width(GTK_CONTAINER(cnnobj->viewport), 0); + gtk_viewport_set_shadow_type(GTK_VIEWPORT(cnnobj->viewport), GTK_SHADOW_NONE); + + + /* Determine whether the plugin can scale or not. If the plugin can scale and we do + * not want to expand, then we add a GtkAspectFrame to maintain aspect ratio during scaling */ + cnnobj->plugin_can_scale = remmina_plugin_manager_query_feature_by_type(REMMINA_PLUGIN_TYPE_PROTOCOL, + remmina_file_get_string(remminafile, "protocol"), + REMMINA_PROTOCOL_FEATURE_TYPE_SCALE); + + cnnobj->aspectframe = NULL; + gtk_container_add(GTK_CONTAINER(cnnobj->viewport), cnnobj->proto); + + /* Determine whether this connection will be put on a new window * or in an existing one */ cnnwin = remmina_connection_window_find(remminafile); @@ -3911,21 +3949,12 @@ GtkWidget* remmina_connection_window_open_from_file_full(RemminaFile* remminafil tab = remmina_connection_object_create_tab(cnnobj); i = remmina_connection_object_append_page(cnnobj, GTK_NOTEBOOK(cnnwin->priv->notebook), tab, cnnwin->priv->view_mode); + gtk_container_add(GTK_CONTAINER(cnnobj->scrolled_container), cnnobj->viewport); gtk_window_present(GTK_WINDOW(cnnwin)); gtk_notebook_set_current_page(GTK_NOTEBOOK(cnnwin->priv->notebook), i); } - /* Set a name for the widget, for CSS selector */ - gtk_widget_set_name(GTK_WIDGET(cnnobj->proto), "remmina-protocol-widget"); - - gtk_widget_set_halign(GTK_WIDGET(cnnobj->proto), GTK_ALIGN_FILL); - gtk_widget_set_valign(GTK_WIDGET(cnnobj->proto), GTK_ALIGN_FILL); - - if (data) { - g_object_set_data(G_OBJECT(cnnobj->proto), "user-data", data); - } - gtk_widget_show(cnnobj->proto); g_signal_connect(G_OBJECT(cnnobj->proto), "connect", G_CALLBACK(remmina_connection_object_on_connect), cnnobj); if (disconnect_cb) { @@ -3936,27 +3965,6 @@ GtkWidget* remmina_connection_window_open_from_file_full(RemminaFile* remminafil g_signal_connect(G_OBJECT(cnnobj->proto), "update-align", G_CALLBACK(remmina_connection_object_on_update_align), NULL); g_signal_connect(G_OBJECT(cnnobj->proto), "unlock-dynres", G_CALLBACK(remmina_connection_object_on_unlock_dynres), NULL); - /* Create the message_panel */ - cnnobj->message_panel = NULL; - - /* Create the viewport to make the RemminaProtocolWidget scrollable */ - cnnobj->viewport = gtk_viewport_new(NULL, NULL); - gtk_widget_set_name(cnnobj->viewport, "remmina-cw-viewport"); - gtk_widget_show(cnnobj->viewport); - gtk_container_set_border_width(GTK_CONTAINER(cnnobj->viewport), 0); - gtk_viewport_set_shadow_type(GTK_VIEWPORT(cnnobj->viewport), GTK_SHADOW_NONE); - - - /* Determine whether the plugin can scale or not. If the plugin can scale and we do - * not want to expand, then we add a GtkAspectFrame to maintain aspect ratio during scaling */ - cnnobj->plugin_can_scale = remmina_plugin_manager_query_feature_by_type(REMMINA_PLUGIN_TYPE_PROTOCOL, - remmina_file_get_string(remminafile, "protocol"), - REMMINA_PROTOCOL_FEATURE_TYPE_SCALE); - - cnnobj->aspectframe = NULL; - gtk_container_add(GTK_CONTAINER(cnnobj->viewport), cnnobj->proto); - gtk_container_add(GTK_CONTAINER(cnnobj->scrolled_container), cnnobj->viewport); - if (!remmina_pref.save_view_mode) remmina_file_set_int(cnnobj->remmina_file, "viewmode", remmina_pref.default_mode); @@ -3968,7 +3976,7 @@ GtkWidget* remmina_connection_window_open_from_file_full(RemminaFile* remminafil REMMINA_PROTOCOL_FEATURE_TYPE_GTKSOCKET); if (ret && !remmina_gtksocket_available()) { dialog = gtk_message_dialog_new( - GTK_WINDOW(cnnobj->window), + GTK_WINDOW(cnnwin), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, @@ -3976,8 +3984,6 @@ GtkWidget* remmina_connection_window_open_from_file_full(RemminaFile* remminafil g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), NULL); gtk_widget_show(dialog); return NULL; /* Should we destroy something before returning ? */ - }else { - remmina_protocol_widget_open_connection(REMMINA_PROTOCOL_WIDGET(cnnobj->proto), remminafile); } #if FLOATING_TOOLBAR_WIDGET @@ -4008,25 +4014,80 @@ void remmina_connection_window_set_delete_confirm_mode(RemminaConnectionWindow* cnnwin->priv->on_delete_confirm_mode = mode; } - -void remmina_connection_object_hide_message_panel(RemminaConnectionObject *cnnobj) +/** + * Deletes a RemminaMessagePanel from the current cnnobj + * and if it was visible, make visible the last remaining one. + */ +void remmina_connection_object_destroy_message_panel(RemminaConnectionObject *cnnobj, RemminaMessagePanel *mp) { - gtk_widget_hide(cnnobj->message_panel); + TRACE_CALL(__func__); + GList *childs, *cc; + RemminaMessagePanel *lastPanel; + gboolean was_visible; + + childs = gtk_container_get_children(GTK_CONTAINER(cnnobj->page)); + cc = g_list_first(childs); + while(cc != NULL) { + if ((RemminaMessagePanel*)cc->data == mp) + break; + cc = g_list_next(cc); + } + g_list_free(childs); + + if (cc == NULL) { + printf("REMMINA: warning, request to destroy a RemminaMessagePanel which is not on the page\n"); + return; + } + was_visible = gtk_widget_is_visible(GTK_WIDGET(mp)); + gtk_widget_destroy(GTK_WIDGET(mp)); + + /* And now, show the last remaining message panel, if needed */ + if (was_visible) { + childs = gtk_container_get_children(GTK_CONTAINER(cnnobj->page)); + cc = g_list_first(childs); + lastPanel = NULL; + while(cc != NULL) { + if (G_TYPE_CHECK_INSTANCE_TYPE(cc->data, REMMINA_TYPE_MESSAGE_PANEL)) + lastPanel = (RemminaMessagePanel*)cc->data; + cc = g_list_next(cc); + } + g_list_free(childs); + if (lastPanel) + gtk_widget_show(GTK_WIDGET(lastPanel)); + } + } +/** + * Each cnnobj->page can have more than one RemminaMessagePanel, but 0 or 1 are visible. + * + * This function adds a RemminaMessagePanel to cnnobj->page, move it to top, + * and makes it the only visible one. + */ void remmina_connection_object_show_message_panel(RemminaConnectionObject *cnnobj, RemminaMessagePanel *mp) { - /* Remove a previous message_panel */ - if (cnnobj->message_panel != NULL) { - gtk_widget_destroy(cnnobj->message_panel); - cnnobj->message_panel = NULL; + TRACE_CALL(__func__); + GList *childs, *cc; + + /* Hides all RemminaMessagePanels childs of cnnobj->page */ + childs = gtk_container_get_children(GTK_CONTAINER(cnnobj->page)); + cc = g_list_first(childs); + while(cc != NULL) { + if (G_TYPE_CHECK_INSTANCE_TYPE(cc->data, REMMINA_TYPE_MESSAGE_PANEL)) + gtk_widget_hide(GTK_WIDGET(cc->data)); + cc = g_list_next(cc); } + g_list_free(childs); + /* Add the new message panel at the top of cnnobj->page */ - gtk_box_pack_start(GTK_BOX(cnnobj->page), mp, FALSE, FALSE, 0); - cnnobj->message_panel = mp; - gtk_box_reorder_child(GTK_BOX(cnnobj->page), mp, 0); + gtk_box_pack_start(GTK_BOX(cnnobj->page), GTK_WIDGET(mp), FALSE, FALSE, 0); + gtk_box_reorder_child(GTK_BOX(cnnobj->page), GTK_WIDGET(mp), 0); /* Show the message panel */ - gtk_widget_show_all(mp); + gtk_widget_show_all(GTK_WIDGET(mp)); + + /* Focus the correct field of the RemminaMessagePanel */ + remmina_message_panel_focus_auth_entry(mp); + } diff --git a/src/remmina_connection_window.h b/src/remmina_connection_window.h index e3223bdd8..42fdec71d 100644 --- a/src/remmina_connection_window.h +++ b/src/remmina_connection_window.h @@ -80,7 +80,8 @@ void remmina_connection_window_set_delete_confirm_mode(RemminaConnectionWindow* GtkWidget* remmina_connection_window_open_from_file_full(RemminaFile* remminafile, GCallback disconnect_cb, gpointer data, guint* handler); -void remmina_connection_object_hide_message_panel(RemminaConnectionObject *cnnobj); + +void remmina_connection_object_destroy_message_panel(RemminaConnectionObject *cnnobj, RemminaMessagePanel *mp); void remmina_connection_object_show_message_panel(RemminaConnectionObject *cnnobj, RemminaMessagePanel *mp); #define MESSAGE_PANEL_SPINNER 0x00000001 diff --git a/src/remmina_masterthread_exec.c b/src/remmina_masterthread_exec.c index 9f1081e2c..53e9ce010 100644 --- a/src/remmina_masterthread_exec.c +++ b/src/remmina_masterthread_exec.c @@ -52,7 +52,7 @@ static gboolean remmina_masterthread_exec_callback(RemminaMTExecData *d) if (!d->cancelled) { switch (d->func) { case FUNC_INIT_SAVE_CRED: - remmina_protocol_widget_init_save_cred(d->p.init_save_creds.gp); + remmina_protocol_widget_save_cred(d->p.init_save_creds.gp); break; case FUNC_CHAT_RECEIVE: remmina_protocol_widget_chat_receive(d->p.chat_receive.gp, d->p.chat_receive.text); @@ -72,6 +72,16 @@ static gboolean remmina_masterthread_exec_callback(RemminaMTExecData *d) case FUNC_PROTOCOLWIDGET_EMIT_SIGNAL: remmina_protocol_widget_emit_signal(d->p.protocolwidget_emit_signal.gp, d->p.protocolwidget_emit_signal.signal_name); break; + case FUNC_PROTOCOLWIDGET_MPPROGRESS: + d->p.protocolwidget_mpprogress.ret_mp = remmina_protocol_widget_mpprogress(d->p.protocolwidget_mpprogress.cnnobj, d->p.protocolwidget_mpprogress.message, + d->p.protocolwidget_mpprogress.response_callback, d->p.protocolwidget_mpprogress.response_callback_data); + break; + case FUNC_PROTOCOLWIDGET_MPDESTROY: + remmina_protocol_widget_mpdestroy(d->p.protocolwidget_mpdestroy.cnnobj, d->p.protocolwidget_mpdestroy.mp); + break; + case FUNC_PROTOCOLWIDGET_MPSHOWRETRY: + remmina_protocol_widget_panel_show_retry(d->p.protocolwidget_mpshowretry.gp); + break; case FUNC_SFTP_CLIENT_CONFIRM_RESUME: #ifdef HAVE_LIBSSH d->p.sftp_client_confirm_resume.retval = remmina_sftp_client_confirm_resume( d->p.sftp_client_confirm_resume.client, @@ -87,9 +97,6 @@ static gboolean remmina_masterthread_exec_callback(RemminaMTExecData *d) #endif break; - case FUNC_MESSAGE_PANEL_SETUP_AUTH: - remmina_message_panel_setup_auth(d->p.message_panel_setup_auth.mp, d->p.message_panel_setup_auth.message, d->p.message_panel_setup_auth.flags); - break; } pthread_mutex_lock(&d->pt_mutex); d->complete = TRUE; diff --git a/src/remmina_masterthread_exec.h b/src/remmina_masterthread_exec.h index 52c57c8e4..d0a3437e1 100644 --- a/src/remmina_masterthread_exec.h +++ b/src/remmina_masterthread_exec.h @@ -47,8 +47,11 @@ typedef struct remmina_masterthread_exec_data { FUNC_FTP_CLIENT_UPDATE_TASK, FUNC_FTP_CLIENT_GET_WAITING_TASK, FUNC_SFTP_CLIENT_CONFIRM_RESUME, FUNC_PROTOCOLWIDGET_EMIT_SIGNAL, - FUNC_VTE_TERMINAL_SET_ENCODING_AND_PTY, - FUNC_MESSAGE_PANEL_SETUP_AUTH } func; + FUNC_PROTOCOLWIDGET_MPPROGRESS, + FUNC_PROTOCOLWIDGET_MPDESTROY, + FUNC_PROTOCOLWIDGET_MPSHOWRETRY, + FUNC_VTE_TERMINAL_SET_ENCODING_AND_PTY + } func; union { struct { @@ -79,6 +82,20 @@ typedef struct remmina_masterthread_exec_data { RemminaProtocolWidget* gp; const gchar* signal_name; } protocolwidget_emit_signal; + struct { + RemminaConnectionObject *cnnobj; + const gchar *message; + RemminaMessagePanelCallback response_callback; + gpointer response_callback_data; + RemminaMessagePanel *ret_mp; + } protocolwidget_mpprogress; + struct { + RemminaConnectionObject *cnnobj; + RemminaMessagePanel *mp; + } protocolwidget_mpdestroy; + struct { + RemminaProtocolWidget *gp; + } protocolwidget_mpshowretry; #ifdef HAVE_LIBSSH struct { RemminaSFTPClient *client; @@ -94,11 +111,6 @@ typedef struct remmina_masterthread_exec_data { int slave; } vte_terminal_set_encoding_and_pty; #endif - struct { - RemminaMessagePanel *mp; - gchar *message; - unsigned flags; - } message_panel_setup_auth; } p; /* Mutex for thread synchronization */ diff --git a/src/remmina_message_panel.c b/src/remmina_message_panel.c index c16b37525..99e9750ed 100644 --- a/src/remmina_message_panel.c +++ b/src/remmina_message_panel.c @@ -46,10 +46,11 @@ typedef struct { - /* mutex to have thread locked on this subpanel waiting for an answer */ - pthread_mutex_t pt_mutex; - pthread_cond_t pt_cond; - int pt_complete, pt_retcode; + + RemminaMessagePanelCallback response_callback; + void *response_callback_data; + GtkWidget *w[REMMINA_MESSAGE_PANEL_MAXWIDGETID]; + } RemminaMessagePanelPrivate; G_DEFINE_TYPE_WITH_PRIVATE (RemminaMessagePanel, remmina_message_panel, GTK_TYPE_BOX) @@ -78,8 +79,8 @@ RemminaMessagePanel *remmina_message_panel_new() priv = remmina_message_panel_get_instance_private(mp); - pthread_mutex_init(&priv->pt_mutex, NULL); - pthread_cond_init(&priv->pt_cond, NULL); + priv->response_callback = NULL; + priv->response_callback_data = NULL; /* Set widget class, for CSS styling */ // gtk_widget_set_name(GTK_WIDGET(mp), "remmina-cw-message-panel"); @@ -99,15 +100,13 @@ static void remmina_message_panel_button_clicked_callback( btn_data = (gint)((gint64)g_object_get_data(G_OBJECT(button), btn_response_key)); - pthread_mutex_lock(&priv->pt_mutex); - priv->pt_complete = TRUE; - priv->pt_retcode = btn_data; - pthread_cond_signal(&priv->pt_cond); - pthread_mutex_unlock(&priv->pt_mutex); + /* Calls the callback, if defined */ + if (priv->response_callback != NULL) + (*priv->response_callback)(priv->response_callback_data, btn_data); } -void remmina_message_panel_setup_progress(RemminaMessagePanel *mp, gchar *message) +void remmina_message_panel_setup_progress(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data) { /* * Setup a message panel to show a spinner, a message like "Connecting...", @@ -118,9 +117,11 @@ void remmina_message_panel_setup_progress(RemminaMessagePanel *mp, gchar *messag TRACE_CALL(__func__); GtkBox *hbox; GtkWidget *w; + RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp); if ( !remmina_masterthread_exec_is_main_thread() ) { printf("WARNING: %s called in a subthread. This should not happen.\n", __func__); + raise(SIGINT); } hbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0)); @@ -134,20 +135,24 @@ void remmina_message_panel_setup_progress(RemminaMessagePanel *mp, gchar *messag w = gtk_label_new(message); gtk_box_pack_start(hbox, w, TRUE, TRUE, 0); - /* A button to cancel the action */ - w = gtk_button_new_with_label(_("Cancel")); - gtk_box_pack_end(hbox, w, FALSE, FALSE, 0); - g_object_set_data(G_OBJECT(w), btn_response_key, 0); + priv->response_callback = response_callback; + priv->response_callback_data = response_callback_data; - g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp); + /* A button to cancel the action. The cancel button is available + * only when a response_callback function is defined. */ + if (response_callback) { + w = gtk_button_new_with_label(_("Cancel")); + gtk_box_pack_end(hbox, w, FALSE, FALSE, 0); + g_object_set_data(G_OBJECT(w), btn_response_key, (void *)GTK_RESPONSE_CANCEL); + g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp); + } gtk_box_pack_start(GTK_BOX(mp), GTK_WIDGET(hbox), TRUE, TRUE, 0); gtk_widget_show_all(GTK_WIDGET(mp)); } - -void remmina_message_panel_setup_message(RemminaMessagePanel *mp, gchar *message) +void remmina_message_panel_setup_message(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data) { /* * Setup a message panel to a message to read like "Cannot connect...", @@ -158,6 +163,7 @@ void remmina_message_panel_setup_message(RemminaMessagePanel *mp, gchar *message TRACE_CALL(__func__); GtkBox *hbox; GtkWidget *w; + RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp); if ( !remmina_masterthread_exec_is_main_thread() ) { printf("WARNING: %s called in a subthread. This should not happen.\n", __func__); @@ -172,8 +178,11 @@ void remmina_message_panel_setup_message(RemminaMessagePanel *mp, gchar *message /* A button to confirm reading */ w = gtk_button_new_with_label(_("Close")); gtk_box_pack_end(hbox, w, FALSE, FALSE, 0); - g_object_set_data(G_OBJECT(w), btn_response_key, 0); + priv->response_callback = response_callback; + priv->response_callback_data = response_callback_data; + + g_object_set_data(G_OBJECT(w), btn_response_key, (void *)GTK_RESPONSE_OK); g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp); gtk_box_pack_start(GTK_BOX(mp), GTK_WIDGET(hbox), TRUE, TRUE, 0); @@ -182,39 +191,46 @@ void remmina_message_panel_setup_message(RemminaMessagePanel *mp, gchar *message } -void remmina_message_panel_setup_question(RemminaMessagePanel *mp, gchar *message) +void remmina_message_panel_setup_question(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data) { /* * Setup a message panel to a message to read like "Do you accept ?", * and a pair of button for Yes and No - * Callback will receive 0 for No, 1 for Yes + * message is an HTML string + * Callback will receive GTK_RESPONSE_NO for No, GTK_RESPONSE_YES for Yes * */ TRACE_CALL(__func__); GtkBox *hbox; GtkWidget *w; + RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp); if ( !remmina_masterthread_exec_is_main_thread() ) { - printf("WARNING: %s called in a subthread. This should not happen.\n", __func__); + printf("WARNING: %s called in a subthread. This should not happen. Raising SIGINT for debugging.\n", __func__); + raise(SIGINT); } hbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0)); - /* A message */ - w = gtk_label_new(message); + /* A message, in HTML format */ + w = gtk_label_new(NULL); + gtk_label_set_markup(GTK_LABEL(w), message); gtk_box_pack_start(hbox, w, TRUE, TRUE, 0); /* A button for yes and one for no */ w = gtk_button_new_with_label(_("Yes")); gtk_box_pack_end(hbox, w, FALSE, FALSE, 0); - g_object_set_data(G_OBJECT(w), btn_response_key, (gpointer)1); + g_object_set_data(G_OBJECT(w), btn_response_key, (void *)GTK_RESPONSE_YES); g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp); w = gtk_button_new_with_label(_("No")); gtk_box_pack_end(hbox, w, FALSE, FALSE, 0); - g_object_set_data(G_OBJECT(w), btn_response_key, (gpointer)0); + g_object_set_data(G_OBJECT(w), btn_response_key, (void *)GTK_RESPONSE_NO); + + priv->response_callback = response_callback; + priv->response_callback_data = response_callback_data; g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp); @@ -224,7 +240,7 @@ void remmina_message_panel_setup_question(RemminaMessagePanel *mp, gchar *messag } -void remmina_message_panel_setup_auth(RemminaMessagePanel *mp, gchar *message, unsigned flags) +void remmina_message_panel_setup_auth(RemminaMessagePanel *mp, RemminaMessagePanelCallback response_callback, gpointer response_callback_data, const gchar *title, const gchar *password_prompt, unsigned flags) { TRACE_CALL(__func__); GtkWidget *grid; @@ -238,20 +254,11 @@ void remmina_message_panel_setup_auth(RemminaMessagePanel *mp, gchar *message, u GtkWidget *button_cancel; int grid_row; - /* ToDo: remove this debug call */ - printf("%s, flags = %u\n", __func__ , flags); + RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp); if ( !remmina_masterthread_exec_is_main_thread() ) { - /* Allow the execution of this function from a non main thread */ - RemminaMTExecData *d; - d = (RemminaMTExecData*)g_malloc( sizeof(RemminaMTExecData) ); - d->func = FUNC_MESSAGE_PANEL_SETUP_AUTH; - d->p.message_panel_setup_auth.mp = mp; - d->p.message_panel_setup_auth.message = message; - d->p.message_panel_setup_auth.flags = flags; - remmina_masterthread_exec_and_wait(d); - g_free(d); - return ; + printf("WARNING: %s called in a subthread. This should not happen. Raising SIGINT to debug.\n", __func__); + raise(SIGINT); } /* Create grid */ @@ -266,7 +273,7 @@ void remmina_message_panel_setup_auth(RemminaMessagePanel *mp, gchar *message, u /* Entries */ grid_row = 0; - widget = gtk_label_new(message); + widget = gtk_label_new(title); gtk_style_context_add_class(gtk_widget_get_style_context(widget), "title_label"); gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_FILL); @@ -312,8 +319,8 @@ void remmina_message_panel_setup_auth(RemminaMessagePanel *mp, gchar *message, u username_entry = NULL; } - /* ToDo: this "Password" can be "KEY" sometimes, we should introduce a flag */ - widget = gtk_label_new(_("Password")); + /* The password/key field */ + widget = gtk_label_new(password_prompt); gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); gtk_widget_set_margin_top (GTK_WIDGET(widget), 3); gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3); @@ -335,10 +342,8 @@ void remmina_message_panel_setup_auth(RemminaMessagePanel *mp, gchar *message, u gtk_entry_set_visibility(GTK_ENTRY(password_entry), FALSE); gtk_entry_set_activates_default(GTK_ENTRY(password_entry), TRUE); - grid_row++; - if (flags & REMMINA_MESSAGE_PANEL_FLAG_DOMAIN) { widget = gtk_label_new(_("Domain")); gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); @@ -416,911 +421,316 @@ void remmina_message_panel_setup_auth(RemminaMessagePanel *mp, gchar *message, u // gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), GTK_RESPONSE_OK, TRUE); - if (username_entry) { - gtk_widget_grab_focus(username_entry); - }else { - gtk_widget_grab_focus(password_entry); - } - -} - -void remmina_message_panel_setup_cert(RemminaMessagePanel *mp, const gchar* subject, const gchar* issuer, const gchar* new_fingerprint, const gchar* old_fingerprint) -{ - /* Used both to show a new or a changed certificate. - * - If old_fingerprint is null, we are showing a new certificate - * * - If old_fingerprint is not null, we are showing a changed */ - - /* See below remmina_init_dialog_certificate and remmina_init_dialog_certificate_changed */ -} - -void remmina_message_panel_setup_auth_x509(RemminaMessagePanel *mp, const gchar *cacert, const gchar *cacrl, const gchar *clientcert, const gchar *clientkey) -{ - /* Used for VNC x509 authentication. */ - - /* See below remmina_init_dialog_certificate and remmina_init_dialog_certificate_changed */ -} - - -int remmina_message_panel_wait_user_answer(RemminaMessagePanel *mp) -{ - /* Wait for the user to click on a button of the message panel. - * "Wait" is different when executed... - * - on the master thread: ??? - * - on a subthread: block the subthread until the user presses - * the button or mp is destroyed - */ - TRACE_CALL(__func__); - RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp); - - printf("Entering wait_user_answer\n"); - - if(remmina_masterthread_exec_is_main_thread()) { - /* On master thread */ - printf("ERROR: %s calls inside master thread is not implemented\n", __func__); - return -1; - } - - /* On a subthread, block until we receive something to unlock */ - pthread_mutex_lock(&priv->pt_mutex); - priv->pt_complete = FALSE; - while (!priv->pt_complete) - pthread_cond_wait(&priv->pt_cond, &priv->pt_mutex); - - return priv->pt_retcode; - -} - -#ifdef GARBAGE -typedef struct _RemminaMessagePanelPriv { - - RemminaConnectionObject *parent_cnnobj; - - GtkWidget *image; - GtkWidget *content_vbox; - GtkWidget *status_label; - - gint mode; - - gchar *title; - gchar *status; - gchar *username; - gchar *domain; - gchar *password; - gboolean save_password; - gchar *cacert; - gchar *cacrl; - gchar *clientcert; - gchar *clientkey; -} RemminaMessagePanel; - -static void remmina_message_panel_class_init(RemminaMessagePanelClass *klass) -{ - TRACE_CALL(__func__); -} - -static void remmina_message_panel_destroy(RemminaMessagePanel *dialog, gpointer data) -{ - TRACE_CALL(__func__); - - - g_free(mp->priv->title); - g_free(mp->priv->status); - g_free(mp->priv->username); - g_free(mp->priv->domain); - g_free(mp->priv->password); - g_free(mp->priv->cacert); - g_free(mp->priv->cacrl); - g_free(mp->priv->clientcert); - g_free(mp->priv->clientkey); - - g_free(mp->priv); - mp->priv = NULL; - -} - -static void remmina_message_panel_init(RemminaMessagePanel *mp) -{ - TRACE_CALL(__func__); - RemminaMessagePanelPriv *priv; - - mp->mode = REMMINA_PANEL_MODE_IDLE; - - priv = g_new0(RemminaConnectionWindowPriv, 1); - mp->priv = priv; - - - GtkWidget *hbox = NULL; - GtkWidget *widget; - - mp->image = NULL; - mp->content_vbox = NULL; - mp->status_label = NULL; - mp->title = NULL; - mp->status = NULL; - mp->username = NULL; - mp->domain = NULL; - mp->password = NULL; - mp->save_password = FALSE; - mp->cacert = NULL; - mp->cacrl = NULL; - mp->clientcert = NULL; - mp->clientkey = NULL; -} - -RemminaMessagePanel* remmina_message_panel_init(RemminaConnectionObject* parent_cnnobj) -{ - RemminaMessagePanel *mp; - mp = GTK_WIDGET(g_object_new(REMMINA_TYPE_PROTOCOL_WIDGET, NULL)); - mp->parent_cnnobj = parent_cnnobj; - return mp;: -} - - - - gtk_dialog_add_buttons(GTK_DIALOG(dialog), _("_Cancel"), GTK_RESPONSE_CANCEL, _("_OK"), GTK_RESPONSE_OK, NULL); - - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); - - gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); - - /**** Create the dialog content from here ****/ - - /* Create top-level hbox */ - hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4); - gtk_widget_show(hbox); - gtk_container_set_border_width(GTK_CONTAINER(hbox), 15); - gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), hbox, TRUE, TRUE, 0); - - /* Icon */ - widget = gtk_image_new_from_icon_name("dialog-information", GTK_ICON_SIZE_DIALOG); - gtk_widget_show(widget); - gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 4); - dialog->image = widget; - - /* Create vbox for other dialog content */ - widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4); - gtk_widget_show(widget); - gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 4); - dialog->content_vbox = widget; - - /* Entries */ - widget = gtk_label_new(dialog->title); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_END); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_box_pack_start(GTK_BOX(dialog->content_vbox), widget, TRUE, TRUE, 4); - dialog->status_label = widget; - - g_signal_connect(G_OBJECT(dialog), "destroy", G_CALLBACK(remmina_message_panel_destroy), NULL); + priv->w[REMMINA_MESSAGE_PANEL_USERNAME] = username_entry; + priv->w[REMMINA_MESSAGE_PANEL_PASSWORD] = password_entry; + priv->w[REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSRORD] = save_password_switch; + priv->w[REMMINA_MESSAGE_PANEL_DOMAIN] = domain_entry; + priv->response_callback = response_callback; + priv->response_callback_data = response_callback_data; + g_object_set_data(G_OBJECT(button_cancel), btn_response_key, (void *)GTK_RESPONSE_CANCEL); + g_signal_connect(G_OBJECT(button_cancel), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp); + g_object_set_data(G_OBJECT(button_ok), btn_response_key, (void *)GTK_RESPONSE_OK); + g_signal_connect(G_OBJECT(button_ok), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp); - remmina_widget_pool_register(GTK_WIDGET(dialog)); } - -static void remmina_message_panel_connecting(RemminaInitDialog *dialog) -{ - TRACE_CALL(__func__); - gtk_label_set_text(GTK_LABEL(dialog->status_label), (dialog->status ? dialog->status : dialog->title)); - gtk_image_set_from_icon_name(GTK_IMAGE(dialog->image), "dialog-information", GTK_ICON_SIZE_DIALOG); - gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), GTK_RESPONSE_OK, FALSE); - - dialog->mode = REMMINA_INIT_MODE_CONNECTING; -} - -GtkWidget* remmina_message_panel_new(const gchar *title_format, ...) -{ - TRACE_CALL(__func__); - RemminaInitDialog *dialog; - va_list args; - - dialog = REMMINA_INIT_DIALOG(g_object_new(REMMINA_TYPE_INIT_DIALOG, NULL)); - - va_start(args, title_format); - dialog->title = g_strdup_vprintf(title_format, args); - va_end(args); - gtk_window_set_title(GTK_WINDOW(dialog), dialog->title); - - remmina_message_panel_connecting(dialog); - - return GTK_WIDGET(dialog); -} - -void remmina_message_panel_set_status(RemminaInitDialog *dialog, const gchar *status_format, ...) -{ - TRACE_CALL(__func__); - /* This function can be called from a non main thread */ - - va_list args; - - if (!dialog) - return; - - if (status_format) { - if (dialog->status) - g_free(dialog->status); - - va_start(args, status_format); - dialog->status = g_strdup_vprintf(status_format, args); - va_end(args); - - if ( remmina_masterthread_exec_is_main_thread() ) { - gtk_label_set_text(GTK_LABEL(dialog->status_label), dialog->status); - }else { - RemminaMTExecData *d; - d = (RemminaMTExecData*)g_malloc( sizeof(RemminaMTExecData) ); - d->func = FUNC_GTK_LABEL_SET_TEXT; - d->p.gtk_label_set_text.label = GTK_LABEL(dialog->status_label); - d->p.gtk_label_set_text.str = dialog->status; - remmina_masterthread_exec_and_wait(d); - g_free(d); - } - } -} - -void remmina_message_panel_set_status_temp(RemminaInitDialog *dialog, const gchar *status_format, ...) -{ - TRACE_CALL(__func__); - - /* This function can be called from a non main thread */ - - gchar* s; - va_list args; - - if (status_format) { - va_start(args, status_format); - s = g_strdup_vprintf(status_format, args); - va_end(args); - - if ( remmina_masterthread_exec_is_main_thread() ) { - gtk_label_set_text(GTK_LABEL(dialog->status_label), dialog->status); - }else { - RemminaMTExecData *d; - d = (RemminaMTExecData*)g_malloc( sizeof(RemminaMTExecData) ); - d->func = FUNC_GTK_LABEL_SET_TEXT; - d->p.gtk_label_set_text.label = GTK_LABEL(dialog->status_label); - d->p.gtk_label_set_text.str = s; - remmina_masterthread_exec_and_wait(d); - g_free(d); - } - - g_free(s); - } -} - -gint remmina_message_panel_authpwd(RemminaMessagePanel *mp, const gchar *message, const gchar *keylabel, gboolean allow_save) +void remmina_message_panel_setup_auth_x509(RemminaMessagePanel *mp, RemminaMessagePanelCallback response_callback, gpointer response_callback_data) { TRACE_CALL(__func__); GtkWidget *grid; - GtkWidget *password_entry; - GtkWidget *save_password_check; GtkWidget *widget; - gint ret; - gchar *s; - - if ( !remmina_masterthread_exec_is_main_thread() ) { - /* Allow the execution of this function from a non main thread */ - RemminaMTExecData *d; - gint retval; - d = (RemminaMTExecData*)g_malloc( sizeof(RemminaMTExecData) ); - d->func = FUNC_DIALOG_AUTHPWD; - d->p.dialog_authpwd.dialog = dialog; - d->p.dialog_authpwd.label = label; - d->p.dialog_authpwd.allow_save = allow_save; - remmina_masterthread_exec_and_wait(d); - retval = d->p.dialog_authpwd.retval; - g_free(d); - return retval; - } - - if (mp->mode != REMMINA_PANEL_MODE_IDLE) { - printf("INTERNAL ERROR: message panel is not in IDLE mode and a new panel has been requested\n"); - } - - gtk_label_set_text(GTK_LABEL(dialog->status_label), (dialog->status ? dialog->status : dialog->title)); - - /* Create grid (was a table) */ - grid = gtk_grid_new(); - gtk_widget_show(grid); - gtk_grid_set_row_spacing(GTK_GRID(grid), 8); - gtk_grid_set_column_spacing(GTK_GRID(grid), 8); - - /* Text message */ - widget = gtk_label_new(message); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 0, 0, 2, 1); - - /* Icon */ - /* gtk_image_set_from_icon_name(GTK_IMAGE(dialog->image), "dialog-password", GTK_ICON_SIZE_DIALOG); */ - - /* Entries */ - widget = gtk_label_new(label); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 0, 1, 1, 1); - - password_entry = gtk_entry_new(); - gtk_widget_show(password_entry); - gtk_grid_attach(GTK_GRID(grid), password_entry, 1, 1, 2, 1); - gtk_entry_set_max_length(GTK_ENTRY(password_entry), 100); - gtk_entry_set_visibility(GTK_ENTRY(password_entry), FALSE); - gtk_entry_set_activates_default(GTK_ENTRY(password_entry), TRUE); - - s = g_strdup_printf(_("Save %s"), keylabel); - save_password_check = gtk_check_button_new_with_label(s); - g_free(s); - gtk_widget_show(save_password_check); - gtk_grid_attach(GTK_GRID(grid), save_password_check, 0, 2, 2, 1); - if (dialog->save_password) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(save_password_check), TRUE); - gtk_widget_set_sensitive(save_password_check, allow_save); - - /* Pack it into the RemminaMessagePanel (which is a GtkBox) */ - gtk_box_pack_start(GTK_BOX(mb), grid, TRUE, TRUE, 4); - - gtk_widget_grab_focus(password_entry); - - dialog->mode = REMMINA_INIT_MODE_AUTHPWD; - - /* Show it */ - remmina_connection_object_show_message_panel(mp->priv->parent_cnnobj); - - /* Now run it */ - ret = gtk_dialog_run(GTK_DIALOG(dialog)); - - if (ret == GTK_RESPONSE_OK) { - dialog->password = g_strdup(gtk_entry_get_text(GTK_ENTRY(password_entry))); - dialog->save_password = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(save_password_check)); - } - - gtk_widget_destroy(grid); - - remmina_message_panel_connecting(dialog); - - return ret; -} - -gint remmina_message_panel_wait_user_answer(RemminaMessagePanel *mp) -{ - /* This function is very similar to gtk_dialog_run() for a dialog box */ - -} - -gint remmina_message_panel_authuserpwd(RemminaInitDialog *dialog, gboolean want_domain, const gchar *default_username, - const gchar *default_domain, gboolean allow_save) -{ - TRACE_CALL(__func__); + GtkWidget *bbox; + GtkWidget *button_ok; + GtkWidget *button_cancel; + GtkWidget *cacert_file; + GtkWidget *cacrl_file; + GtkWidget *clientcert_file; + GtkWidget *clientkey_file; + int grid_row; - GtkWidget *grid; - GtkWidget *username_entry; - GtkWidget *password_entry; - GtkWidget *domain_entry = NULL; - GtkWidget *save_password_check; - GtkWidget *widget; - gint ret; + RemminaMessagePanelPrivate *priv = remmina_message_panel_get_instance_private(mp); if ( !remmina_masterthread_exec_is_main_thread() ) { - /* Allow the execution of this function from a non main thread */ - RemminaMTExecData *d; - gint retval; - d = (RemminaMTExecData*)g_malloc( sizeof(RemminaMTExecData) ); - d->func = FUNC_DIALOG_AUTHUSERPWD; - d->p.dialog_authuserpwd.dialog = dialog; - d->p.dialog_authuserpwd.want_domain = want_domain; - d->p.dialog_authuserpwd.default_username = default_username; - d->p.dialog_authuserpwd.default_domain = default_domain; - d->p.dialog_authuserpwd.allow_save = allow_save; - remmina_masterthread_exec_and_wait(d); - retval = d->p.dialog_authuserpwd.retval; - g_free(d); - return retval; + printf("WARNING: %s called in a subthread. This should not happen. Raising SIGINT to debug.\n", __func__); + raise(SIGINT); } - gtk_label_set_text(GTK_LABEL(dialog->status_label), (dialog->status ? dialog->status : dialog->title)); - /* Create grid */ grid = gtk_grid_new(); + gtk_widget_set_halign(GTK_WIDGET(grid), GTK_ALIGN_CENTER); + gtk_widget_set_valign(GTK_WIDGET(grid), GTK_ALIGN_CENTER); gtk_widget_show(grid); - gtk_grid_set_row_spacing(GTK_GRID(grid), 8); - gtk_grid_set_column_spacing(GTK_GRID(grid), 8); - gtk_grid_set_column_homogeneous(GTK_GRID(grid), TRUE); - - /* Icon */ - gtk_image_set_from_icon_name(GTK_IMAGE(dialog->image), "dialog-password", GTK_ICON_SIZE_DIALOG); - - /* Entries */ - widget = gtk_label_new(_("User name")); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 0, 0, 1, 1); - - username_entry = gtk_entry_new(); - gtk_widget_show(username_entry); - gtk_grid_attach(GTK_GRID(grid), username_entry, 1, 0, 2, 1); - gtk_entry_set_max_length(GTK_ENTRY(username_entry), 100); - if (default_username && default_username[0] != '\0') { - gtk_entry_set_text(GTK_ENTRY(username_entry), default_username); - } - - widget = gtk_label_new(_("Password")); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 0, 2, 1, 1); - - password_entry = gtk_entry_new(); - gtk_widget_show(password_entry); - gtk_grid_attach(GTK_GRID(grid), password_entry, 1, 2, 2, 1); - gtk_entry_set_max_length(GTK_ENTRY(password_entry), 100); - gtk_entry_set_visibility(GTK_ENTRY(password_entry), FALSE); - gtk_entry_set_activates_default(GTK_ENTRY(password_entry), TRUE); - - - if (want_domain) { - widget = gtk_label_new(_("Domain")); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 0, 3, 1, 1); - - domain_entry = gtk_entry_new(); - gtk_widget_show(domain_entry); - gtk_grid_attach(GTK_GRID(grid), domain_entry, 1, 3, 2, 1); - gtk_entry_set_max_length(GTK_ENTRY(domain_entry), 100); - gtk_entry_set_activates_default(GTK_ENTRY(domain_entry), TRUE); - if (default_domain && default_domain[0] != '\0') { - gtk_entry_set_text(GTK_ENTRY(domain_entry), default_domain); - } - } - - save_password_check = gtk_check_button_new_with_label(_("Save password")); - if (allow_save) { - gtk_widget_show(save_password_check); - gtk_grid_attach(GTK_GRID(grid), save_password_check, 0, 4, 2, 3); - if (dialog->save_password) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(save_password_check), TRUE); - }else { - gtk_widget_set_sensitive(save_password_check, FALSE); - } - - /* Pack it into the dialog */ - gtk_box_pack_start(GTK_BOX(dialog->content_vbox), grid, TRUE, TRUE, 4); - - gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), GTK_RESPONSE_OK, TRUE); - - if (default_username && default_username[0] != '\0') { - gtk_widget_grab_focus(password_entry); - }else { - gtk_widget_grab_focus(username_entry); - } - - dialog->mode = REMMINA_INIT_MODE_AUTHUSERPWD; - - /* Now run it */ - ret = gtk_dialog_run(GTK_DIALOG(dialog)); - if (ret == GTK_RESPONSE_OK) { - dialog->username = g_strdup(gtk_entry_get_text(GTK_ENTRY(username_entry))); - dialog->password = g_strdup(gtk_entry_get_text(GTK_ENTRY(password_entry))); - dialog->save_password = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(save_password_check)); - - if (want_domain) - dialog->domain = g_strdup(gtk_entry_get_text(GTK_ENTRY(domain_entry))); - } - - gtk_widget_destroy(grid); - - remmina_message_panel_connecting(dialog); - - return ret; -} - -gint remmina_message_panel_certificate(RemminaInitDialog* dialog, const gchar* subject, const gchar* issuer, const gchar* fingerprint) -{ - TRACE_CALL(__func__); - - gint status; - GtkWidget* grid; - GtkWidget* widget; - gchar* s; - - if ( !remmina_masterthread_exec_is_main_thread() ) { - /* Allow the execution of this function from a non main thread */ - RemminaMTExecData *d; - gint retval; - d = (RemminaMTExecData*)g_malloc( sizeof(RemminaMTExecData) ); - d->func = FUNC_DIALOG_CERT; - d->p.dialog_certificate.dialog = dialog; - d->p.dialog_certificate.subject = subject; - d->p.dialog_certificate.issuer = issuer; - d->p.dialog_certificate.fingerprint = fingerprint; - remmina_masterthread_exec_and_wait(d); - retval = d->p.dialog_certificate.retval; - g_free(d); - return retval; - } - - gtk_label_set_text(GTK_LABEL(dialog->status_label), _("Certificate Details:")); - - /* Create table */ - grid = gtk_grid_new(); - gtk_widget_show(grid); - gtk_grid_set_row_spacing(GTK_GRID(grid), 8); - gtk_grid_set_column_spacing(GTK_GRID(grid), 8); - //gtk_grid_set_column_homogeneous (GTK_GRID(grid), TRUE); - - /* Icon */ - gtk_image_set_from_icon_name(GTK_IMAGE(dialog->image), "dialog-password", GTK_ICON_SIZE_DIALOG); + gtk_grid_set_row_spacing(GTK_GRID(grid), 6); + gtk_grid_set_column_spacing(GTK_GRID(grid), 6); /* Entries */ - widget = gtk_label_new(_("Subject:")); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 0, 0, 1, 1); - - widget = gtk_label_new(subject); + grid_row = 0; + widget = gtk_label_new(_("Enter certificate authentication files")); + gtk_style_context_add_class(gtk_widget_get_style_context(widget), "title_label"); gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); + gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_FILL); + gtk_widget_set_margin_top (GTK_WIDGET(widget), 18); + gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 9); + gtk_widget_set_margin_start (GTK_WIDGET(widget), 18); + gtk_widget_set_margin_end (GTK_WIDGET(widget), 18); gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 1, 0, 2, 1); + gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 3, 1); + grid_row++; - widget = gtk_label_new(_("Issuer:")); + const gchar *lbl_cacert = _("CA Certificate File"); + widget = gtk_label_new(lbl_cacert); gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); + gtk_widget_set_margin_top (GTK_WIDGET(widget), 9); + gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3); + gtk_widget_set_margin_start (GTK_WIDGET(widget), 18); + gtk_widget_set_margin_end (GTK_WIDGET(widget), 6); gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 0, 1, 1, 1); + gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1); + cacert_file = gtk_file_chooser_button_new(lbl_cacert, GTK_FILE_CHOOSER_ACTION_OPEN); + // gtk_style_context_add_class(gtk_widget_get_style_context(username_entry), "panel_entry"); + gtk_widget_show(cacert_file); + gtk_widget_set_halign(GTK_WIDGET(cacert_file), GTK_ALIGN_FILL); + gtk_widget_set_valign(GTK_WIDGET(cacert_file), GTK_ALIGN_FILL); + gtk_widget_set_margin_top (GTK_WIDGET(cacert_file), 9); + gtk_widget_set_margin_bottom (GTK_WIDGET(cacert_file), 3); + gtk_widget_set_margin_start (GTK_WIDGET(cacert_file), 6); + gtk_widget_set_margin_end (GTK_WIDGET(cacert_file), 18); + gtk_grid_attach(GTK_GRID(grid), cacert_file, 1, grid_row, 2, 1); + grid_row++; - widget = gtk_label_new(issuer); + const gchar *lbl_cacrl = _("CA CRL File"); + widget = gtk_label_new(lbl_cacrl); gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); + gtk_widget_set_margin_top (GTK_WIDGET(widget), 9); + gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3); + gtk_widget_set_margin_start (GTK_WIDGET(widget), 18); + gtk_widget_set_margin_end (GTK_WIDGET(widget), 6); gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 1, 1, 2, 1); + gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1); + cacrl_file = gtk_file_chooser_button_new(lbl_cacrl, GTK_FILE_CHOOSER_ACTION_OPEN); + // gtk_style_context_add_class(gtk_widget_get_style_context(username_entry), "panel_entry"); + gtk_widget_show(cacrl_file); + gtk_widget_set_halign(GTK_WIDGET(cacrl_file), GTK_ALIGN_FILL); + gtk_widget_set_valign(GTK_WIDGET(cacrl_file), GTK_ALIGN_FILL); + gtk_widget_set_margin_top (GTK_WIDGET(cacrl_file), 9); + gtk_widget_set_margin_bottom (GTK_WIDGET(cacrl_file), 3); + gtk_widget_set_margin_start (GTK_WIDGET(cacrl_file), 6); + gtk_widget_set_margin_end (GTK_WIDGET(cacrl_file), 18); + gtk_grid_attach(GTK_GRID(grid), cacrl_file, 1, grid_row, 2, 1); + grid_row++; - widget = gtk_label_new(_("Fingerprint:")); + const gchar *lbl_clicert = _("Client Certificate File"); + widget = gtk_label_new(lbl_clicert); gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); + gtk_widget_set_margin_top (GTK_WIDGET(widget), 9); + gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3); + gtk_widget_set_margin_start (GTK_WIDGET(widget), 18); + gtk_widget_set_margin_end (GTK_WIDGET(widget), 6); gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 0, 2, 1, 1); + gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1); + clientcert_file = gtk_file_chooser_button_new(lbl_clicert, GTK_FILE_CHOOSER_ACTION_OPEN); + // gtk_style_context_add_class(gtk_widget_get_style_context(username_entry), "panel_entry"); + gtk_widget_show(clientcert_file); + gtk_widget_set_halign(GTK_WIDGET(clientcert_file), GTK_ALIGN_FILL); + gtk_widget_set_valign(GTK_WIDGET(clientcert_file), GTK_ALIGN_FILL); + gtk_widget_set_margin_top (GTK_WIDGET(clientcert_file), 9); + gtk_widget_set_margin_bottom (GTK_WIDGET(clientcert_file), 3); + gtk_widget_set_margin_start (GTK_WIDGET(clientcert_file), 6); + gtk_widget_set_margin_end (GTK_WIDGET(clientcert_file), 18); + gtk_grid_attach(GTK_GRID(grid), clientcert_file, 1, grid_row, 2, 1); + grid_row++; - widget = gtk_label_new(fingerprint); + const gchar *lbl_clikey = _("Client Certificate Key"); + widget = gtk_label_new(lbl_clikey); gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); + gtk_widget_set_margin_top (GTK_WIDGET(widget), 9); + gtk_widget_set_margin_bottom (GTK_WIDGET(widget), 3); + gtk_widget_set_margin_start (GTK_WIDGET(widget), 18); + gtk_widget_set_margin_end (GTK_WIDGET(widget), 6); gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 1, 2, 2, 1); - - widget = gtk_label_new(NULL); - s = g_strdup_printf("<span size=\"large\"><b>%s</b></span>", _("Accept Certificate?")); - gtk_label_set_markup(GTK_LABEL(widget), s); - g_free(s); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 0, 3, 3, 1); - - /* Pack it into the dialog */ - gtk_box_pack_start(GTK_BOX(dialog->content_vbox), grid, TRUE, TRUE, 4); - - gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), GTK_RESPONSE_OK, TRUE); - - dialog->mode = REMMINA_INIT_MODE_CERTIFICATE; + gtk_grid_attach(GTK_GRID(grid), widget, 0, grid_row, 1, 1); + clientkey_file = gtk_file_chooser_button_new(lbl_clikey, GTK_FILE_CHOOSER_ACTION_OPEN); + // gtk_style_context_add_class(gtk_widget_get_style_context(username_entry), "panel_entry"); + gtk_widget_show(clientkey_file); + gtk_widget_set_halign(GTK_WIDGET(clientkey_file), GTK_ALIGN_FILL); + gtk_widget_set_valign(GTK_WIDGET(clientkey_file), GTK_ALIGN_FILL); + gtk_widget_set_margin_top (GTK_WIDGET(clientkey_file), 9); + gtk_widget_set_margin_bottom (GTK_WIDGET(clientkey_file), 3); + gtk_widget_set_margin_start (GTK_WIDGET(clientkey_file), 6); + gtk_widget_set_margin_end (GTK_WIDGET(clientkey_file), 18); + gtk_grid_attach(GTK_GRID(grid), clientkey_file, 1, grid_row, 2, 1); + grid_row++; - /* Now run it */ - status = gtk_dialog_run(GTK_DIALOG(dialog)); + /* Buttons, ok and cancel */ + bbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL); + gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_EDGE); + gtk_box_set_spacing (GTK_BOX (bbox), 40); + gtk_widget_set_margin_top (GTK_WIDGET(bbox), 9); + gtk_widget_set_margin_bottom (GTK_WIDGET(bbox), 18); + gtk_widget_set_margin_start (GTK_WIDGET(bbox), 18); + gtk_widget_set_margin_end (GTK_WIDGET(bbox), 18); + button_ok = gtk_button_new_with_label(_("_OK")); + gtk_button_set_use_underline(GTK_BUTTON(button_ok), TRUE); + //gtk_widget_show(button_ok); + gtk_container_add (GTK_CONTAINER (bbox), button_ok); + //gtk_grid_attach(GTK_GRID(grid), button_ok, 0, grid_row, 1, 1); + /* Buttons, ok and cancel */ + button_cancel = gtk_button_new_with_label(_("_Cancel")); + gtk_button_set_use_underline(GTK_BUTTON(button_cancel), TRUE); + //gtk_widget_show(button_cancel); + gtk_container_add (GTK_CONTAINER (bbox), button_cancel); + gtk_grid_attach(GTK_GRID(grid), bbox, 0, grid_row, 3, 1); + /* Pack it into the panel */ + gtk_box_pack_start(GTK_BOX(mp), grid, TRUE, TRUE, 4); - if (status == GTK_RESPONSE_OK) { + priv->response_callback = response_callback; + priv->response_callback_data = response_callback_data; - } + priv->w[REMMINA_MESSAGE_PANEL_CACERTFILE] = cacert_file; + priv->w[REMMINA_MESSAGE_PANEL_CACRLFILE] = cacrl_file; + priv->w[REMMINA_MESSAGE_PANEL_CLIENTCERTFILE] = clientcert_file; + priv->w[REMMINA_MESSAGE_PANEL_CLIENTKEYFILE] = clientkey_file; - gtk_widget_destroy(grid); + g_object_set_data(G_OBJECT(button_cancel), btn_response_key, (void *)GTK_RESPONSE_CANCEL); + g_signal_connect(G_OBJECT(button_cancel), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp); + g_object_set_data(G_OBJECT(button_ok), btn_response_key, (void *)GTK_RESPONSE_OK); + g_signal_connect(G_OBJECT(button_ok), "clicked", G_CALLBACK(remmina_message_panel_button_clicked_callback), mp); - return status; } -gint remmina_message_panel_certificate_changed(RemminaInitDialog* dialog, const gchar* subject, const gchar* issuer, const gchar* new_fingerprint, const gchar* old_fingerprint) + +void remmina_message_panel_focus_auth_entry(RemminaMessagePanel *mp) { TRACE_CALL(__func__); - gint status; - GtkWidget* grid; - GtkWidget* widget; - gchar* s; - - if ( !remmina_masterthread_exec_is_main_thread() ) { - /* Allow the execution of this function from a non main thread */ - RemminaMTExecData *d; - gint retval; - d = (RemminaMTExecData*)g_malloc( sizeof(RemminaMTExecData) ); - d->func = FUNC_DIALOG_CERTCHANGED; - d->p.dialog_certchanged.dialog = dialog; - d->p.dialog_certchanged.subject = subject; - d->p.dialog_certchanged.issuer = issuer; - d->p.dialog_certchanged.new_fingerprint = new_fingerprint; - d->p.dialog_certchanged.old_fingerprint = old_fingerprint; - remmina_masterthread_exec_and_wait(d); - retval = d->p.dialog_certchanged.retval; - g_free(d); - return retval; - } - - gtk_label_set_text(GTK_LABEL(dialog->status_label), _("Certificate Changed! Details:")); - - /* Create table */ - grid = gtk_grid_new(); - gtk_widget_show(grid); - gtk_grid_set_row_spacing(GTK_GRID(grid), 8); - gtk_grid_set_column_spacing(GTK_GRID(grid), 8); - - /* Icon */ - gtk_image_set_from_icon_name(GTK_IMAGE(dialog->image), "dialog-password", GTK_ICON_SIZE_DIALOG); - - /* Entries */ - /* Not tested */ - widget = gtk_label_new(_("Subject:")); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 0, 0, 1, 1); - - - widget = gtk_label_new(subject); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 1, 0, 2, 1); - - widget = gtk_label_new(_("Issuer:")); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 0, 1, 1, 1); - - widget = gtk_label_new(issuer); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 1, 1, 2, 1); - - widget = gtk_label_new(_("Old Fingerprint:")); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 0, 2, 1, 1); - - widget = gtk_label_new(old_fingerprint); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 1, 2, 2, 1); - - widget = gtk_label_new(_("New Fingerprint:")); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 0, 3, 1, 1); - - widget = gtk_label_new(new_fingerprint); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 1, 3, 2, 1); - - widget = gtk_label_new(NULL); - s = g_strdup_printf("<span size=\"large\"><b>%s</b></span>", _("Accept Changed Certificate?")); - gtk_label_set_markup(GTK_LABEL(widget), s); - g_free(s); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_grid_attach(GTK_GRID(grid), widget, 0, 4, 3, 1); - - /* Pack it into the dialog */ - gtk_box_pack_start(GTK_BOX(dialog->content_vbox), grid, TRUE, TRUE, 4); - - gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), GTK_RESPONSE_OK, TRUE); - - dialog->mode = REMMINA_INIT_MODE_CERTIFICATE; - - /* Now run it */ - status = gtk_dialog_run(GTK_DIALOG(dialog)); - - if (status == GTK_RESPONSE_OK) { + RemminaMessagePanelPrivate *priv; + GtkWidget *w; - } + if (mp == NULL) + return; + priv = remmina_message_panel_get_instance_private(mp); - gtk_widget_destroy(grid); + w = priv->w[REMMINA_MESSAGE_PANEL_USERNAME]; + if (w == NULL) + w = priv->w[REMMINA_MESSAGE_PANEL_PASSWORD]; + if (w == NULL) + return; + if (!G_TYPE_CHECK_INSTANCE_TYPE(w, gtk_entry_get_type())) + return; - return status; + gtk_widget_grab_focus(w); } -/* NOT TESTED */ -static GtkWidget* remmina_message_panel_create_file_button(GtkGrid *grid, const gchar *label, gint row, const gchar *filename) +void remmina_message_panel_field_set_string(RemminaMessagePanel *mp, int entryid, const gchar *text) { - TRACE_CALL(__func__); - GtkWidget *widget; - gchar *pkidir; + RemminaMessagePanelPrivate *priv; - widget = gtk_label_new(label); - gtk_widget_show(widget); - gtk_grid_attach(grid, widget, 0, row, 1, row + 1); + if (mp == NULL) + return; + priv = remmina_message_panel_get_instance_private(mp); - widget = gtk_file_chooser_button_new(label, GTK_FILE_CHOOSER_ACTION_OPEN); - gtk_file_chooser_button_set_width_chars(GTK_FILE_CHOOSER_BUTTON(widget), 25); - gtk_widget_show(widget); - gtk_grid_attach(grid, widget, 1, row, 2, row + 1); - if (filename && filename[0] != '\0') { - gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(widget), filename); - }else { - pkidir = g_strdup_printf("%s/.pki", g_get_home_dir()); - if (g_file_test(pkidir, G_FILE_TEST_IS_DIR)) { - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(widget), pkidir); - } - g_free(pkidir); - } + if (priv->w[entryid] == NULL) + return; + if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_entry_get_type())) + return; - return widget; + gtk_entry_set_text(GTK_ENTRY(priv->w[entryid]), text); } -gint remmina_message_panel_authx509(RemminaInitDialog *dialog, const gchar *cacert, const gchar *cacrl, const gchar *clientcert, - const gchar *clientkey) +gchar* remmina_message_panel_field_get_string(RemminaMessagePanel *mp, int entryid) { TRACE_CALL(__func__); - GtkWidget *grid; - GtkWidget *cacert_button; - GtkWidget *cacrl_button; - GtkWidget *clientcert_button; - GtkWidget *clientkey_button; - gint ret; - - - if ( !remmina_masterthread_exec_is_main_thread() ) { - /* Allow the execution of this function from a non main thread */ - RemminaMTExecData *d; - gint retval; - d = (RemminaMTExecData*)g_malloc( sizeof(RemminaMTExecData) ); - d->func = FUNC_DIALOG_AUTHX509; - d->p.dialog_authx509.dialog = dialog; - d->p.dialog_authx509.cacert = cacert; - d->p.dialog_authx509.cacrl = cacrl; - d->p.dialog_authx509.clientcert = clientcert; - d->p.dialog_authx509.clientkey = clientkey; - remmina_masterthread_exec_and_wait(d); - retval = d->p.dialog_authx509.retval; - g_free(d); - return retval; - } - - gtk_label_set_text(GTK_LABEL(dialog->status_label), (dialog->status ? dialog->status : dialog->title)); - - /* Create table */ - grid = gtk_grid_new(); - gtk_widget_show(grid); - gtk_grid_set_row_spacing(GTK_GRID(grid), 8); - gtk_grid_set_column_spacing(GTK_GRID(grid), 8); - - /* Icon */ - gtk_image_set_from_icon_name(GTK_IMAGE(dialog->image), "dialog-password", GTK_ICON_SIZE_DIALOG); + RemminaMessagePanelPrivate *priv; - /* Buttons for choosing the certificates */ - cacert_button = remmina_message_panel_create_file_button(GTK_GRID(grid), _("CA certificate"), 0, cacert); - cacrl_button = remmina_message_panel_create_file_button(GTK_GRID(grid), _("CA CRL"), 1, cacrl); - clientcert_button = remmina_message_panel_create_file_button(GTK_GRID(grid), _("Client certificate"), 2, clientcert); - clientkey_button = remmina_message_panel_create_file_button(GTK_GRID(grid), _("Client key"), 3, clientkey); + if (mp == NULL) + return NULL; + priv = remmina_message_panel_get_instance_private(mp); - /* Pack it into the dialog */ - gtk_box_pack_start(GTK_BOX(dialog->content_vbox), grid, TRUE, TRUE, 4); + if (priv->w[entryid] == NULL) + return NULL; + if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_entry_get_type())) + return NULL; - gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), GTK_RESPONSE_OK, TRUE); + return g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->w[entryid]))); +} - dialog->mode = REMMINA_INIT_MODE_AUTHX509; +void remmina_message_panel_field_set_switch(RemminaMessagePanel *mp, int entryid, gboolean state) +{ + TRACE_CALL(__func__); - /* Now run it */ - ret = gtk_dialog_run(GTK_DIALOG(dialog)); - if (ret == GTK_RESPONSE_OK) { - dialog->cacert = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(cacert_button)); - dialog->cacrl = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(cacrl_button)); - dialog->clientcert = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(clientcert_button)); - dialog->clientkey = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(clientkey_button)); - } + RemminaMessagePanelPrivate *priv; - gtk_widget_destroy(grid); + if (mp == NULL) + return; + priv = remmina_message_panel_get_instance_private(mp); - remmina_message_panel_connecting(dialog); + if (priv->w[entryid] == NULL) + return; + if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_switch_get_type())) + return; - return ret; + gtk_switch_set_state(GTK_SWITCH(priv->w[entryid]), state); } -gint remmina_message_panel_serverkey_confirm(RemminaInitDialog *dialog, const gchar *serverkey, const gchar *prompt) +gboolean remmina_message_panel_field_get_switch_state(RemminaMessagePanel *mp, int entryid) { TRACE_CALL(__func__); - GtkWidget *vbox = NULL; - GtkWidget *widget; - gint ret; - - if ( !remmina_masterthread_exec_is_main_thread() ) { - /* Allow the execution of this function from a non main thread */ - RemminaMTExecData *d; - gint retval; - d = (RemminaMTExecData*)g_malloc( sizeof(RemminaMTExecData) ); - d->func = FUNC_DIALOG_SERVERKEY_CONFIRM; - d->p.dialog_serverkey_confirm.dialog = dialog; - d->p.dialog_serverkey_confirm.serverkey = serverkey; - d->p.dialog_serverkey_confirm.prompt = prompt; - remmina_masterthread_exec_and_wait(d); - retval = d->p.dialog_serverkey_confirm.retval; - g_free(d); - return retval; - } - - gtk_label_set_text(GTK_LABEL(dialog->status_label), (dialog->status ? dialog->status : dialog->title)); - - /* Create vbox */ - vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4); - gtk_widget_show(vbox); - - /* Icon */ - gtk_image_set_from_icon_name(GTK_IMAGE(dialog->image), "dialog-warning", GTK_ICON_SIZE_DIALOG); + RemminaMessagePanelPrivate *priv; - /* Entries */ - widget = gtk_label_new(prompt); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_box_pack_start(GTK_BOX(vbox), widget, TRUE, TRUE, 4); + if (mp == NULL) + return FALSE; + priv = remmina_message_panel_get_instance_private(mp); - widget = gtk_label_new(serverkey); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_box_pack_start(GTK_BOX(vbox), widget, TRUE, TRUE, 4); + if (priv->w[entryid] == NULL) + return FALSE; + if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_switch_get_type())) + return FALSE; - widget = gtk_label_new(_("Do you trust the new public key?")); - gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START); - gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER); - gtk_widget_show(widget); - gtk_box_pack_start(GTK_BOX(vbox), widget, TRUE, TRUE, 4); + return gtk_switch_get_state(GTK_SWITCH(priv->w[entryid])); +} - /* Pack it into the dialog */ - gtk_box_pack_start(GTK_BOX(dialog->content_vbox), vbox, TRUE, TRUE, 4); - gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), GTK_RESPONSE_OK, TRUE); +void remmina_message_panel_field_set_filename(RemminaMessagePanel *mp, int entryid, const gchar *filename) +{ + TRACE_CALL(__func__); - dialog->mode = REMMINA_INIT_MODE_SERVERKEY_CONFIRM; + RemminaMessagePanelPrivate *priv; - /* Now run it */ - ret = gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(vbox); - remmina_message_panel_connecting(dialog); + if (mp == NULL) + return; + priv = remmina_message_panel_get_instance_private(mp); + if (priv->w[entryid] == NULL) + return; + if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_file_chooser_button_get_type())) + return; - return ret; + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->w[entryid]), filename); } - -gint remmina_message_panel_serverkey_unknown(RemminaInitDialog *dialog, const gchar *serverkey) +gchar* remmina_message_panel_field_get_filename(RemminaMessagePanel *mp, int entryid) { TRACE_CALL(__func__); - /* This function can be called from a non main thread */ - return remmina_message_panel_serverkey_confirm(dialog, serverkey, - _("The server is unknown. The public key fingerprint is:")); -} + RemminaMessagePanelPrivate *priv; -gint remmina_message_panel_serverkey_changed(RemminaInitDialog *dialog, const gchar *serverkey) -{ - TRACE_CALL(__func__); - /* This function can be called from a non main thread */ + if (mp == NULL) + return NULL; + priv = remmina_message_panel_get_instance_private(mp); - return remmina_message_panel_serverkey_confirm(dialog, serverkey, - _("WARNING: The server has changed its public key. This means either you are under attack,\n" - "or the administrator has changed the key. The new public key fingerprint is:")); -} + if (priv->w[entryid] == NULL) + return NULL; + if (!G_TYPE_CHECK_INSTANCE_TYPE(priv->w[entryid], gtk_file_chooser_button_get_type())) + return NULL; -#endif + return gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(priv->w[entryid])); +} diff --git a/src/remmina_message_panel.h b/src/remmina_message_panel.h index 648fdf7be..69576c9ba 100644 --- a/src/remmina_message_panel.h +++ b/src/remmina_message_panel.h @@ -51,17 +51,35 @@ enum { REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSRORD=4 }; -RemminaMessagePanel *remmina_message_panel_new(void); -void remmina_message_panel_setup_progress(RemminaMessagePanel *mp, gchar *message); -void remmina_message_panel_setup_message(RemminaMessagePanel *mp, gchar *message); -void remmina_message_panel_setup_question(RemminaMessagePanel *mp, gchar *message); -void remmina_message_panel_setup_auth(RemminaMessagePanel *mp, gchar *message, unsigned flags); -void remmina_message_panel_setup_cert(RemminaMessagePanel *mp, const gchar* subject, const gchar* issuer, const gchar* new_fingerprint, const gchar* old_fingerprint); -void remmina_message_panel_setup_auth_x509(RemminaMessagePanel *mp, const gchar *cacert, const gchar *cacrl, const gchar *clientcert, const gchar *clientkey); -gint remmina_message_panel_wait_user_answer(RemminaMessagePanel *mp); - -G_END_DECLS +/* Widgets ID for dialog fields */ +enum { + REMMINA_MESSAGE_PANEL_USERNAME=1, + REMMINA_MESSAGE_PANEL_PASSWORD, + REMMINA_MESSAGE_PANEL_DOMAIN, + REMMINA_MESSAGE_PANEL_SAVEPASSWORD, + REMMINA_MESSAGE_PANEL_CACERTFILE, + REMMINA_MESSAGE_PANEL_CACRLFILE, + REMMINA_MESSAGE_PANEL_CLIENTCERTFILE, + REMMINA_MESSAGE_PANEL_CLIENTKEYFILE, + REMMINA_MESSAGE_PANEL_MAXWIDGETID +}; +/* Callback function type to receive buttons notification */ +typedef void (*RemminaMessagePanelCallback)(void *user_data, int button); +RemminaMessagePanel *remmina_message_panel_new(void); +void remmina_message_panel_setup_progress(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data); +void remmina_message_panel_setup_message(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data); +void remmina_message_panel_setup_question(RemminaMessagePanel *mp, const gchar *message, RemminaMessagePanelCallback response_callback, gpointer response_callback_data); +void remmina_message_panel_setup_auth(RemminaMessagePanel *mp, RemminaMessagePanelCallback response_callback, gpointer response_callback_data, const gchar *title, const gchar *password_prompt, unsigned flags); +void remmina_message_panel_setup_auth_x509(RemminaMessagePanel *mp, RemminaMessagePanelCallback response_callback, gpointer response_callback_data); +void remmina_message_panel_focus_auth_entry(RemminaMessagePanel *mp); +void remmina_message_panel_field_set_string(RemminaMessagePanel *mp, int entryid, const gchar *text); +gchar* remmina_message_panel_field_get_string(RemminaMessagePanel *mp, int entryid); +void remmina_message_panel_field_set_switch(RemminaMessagePanel *mp, int entryid, gboolean state); +gboolean remmina_message_panel_field_get_switch_state(RemminaMessagePanel *mp, int entryid); +void remmina_message_panel_field_set_filename(RemminaMessagePanel *mp, int entryid, const gchar *filename); +gchar* remmina_message_panel_field_get_filename(RemminaMessagePanel *mp, int entryid); +G_END_DECLS diff --git a/src/remmina_plugin_manager.c b/src/remmina_plugin_manager.c index 26fb2d03c..606623f6d 100644 --- a/src/remmina_plugin_manager.c +++ b/src/remmina_plugin_manager.c @@ -185,24 +185,24 @@ RemminaPluginService remmina_plugin_manager_service = remmina_protocol_widget_start_xport_tunnel, remmina_protocol_widget_set_display, remmina_protocol_widget_close_connection, - remmina_protocol_widget_init_authpwd, - remmina_protocol_widget_init_authuserpwd, - remmina_protocol_widget_init_certificate, - remmina_protocol_widget_changed_certificate, - remmina_protocol_widget_init_get_username, - remmina_protocol_widget_init_get_password, - remmina_protocol_widget_init_get_domain, - remmina_protocol_widget_init_get_savepassword, - remmina_protocol_widget_init_authx509, - remmina_protocol_widget_init_get_cacert, - remmina_protocol_widget_init_get_cacrl, - remmina_protocol_widget_init_get_clientcert, - remmina_protocol_widget_init_get_clientkey, - remmina_protocol_widget_init_save_cred, - remmina_protocol_widget_init_show_listen, - remmina_protocol_widget_init_show_retry, - remmina_protocol_widget_init_show, - remmina_protocol_widget_init_hide, + remmina_protocol_widget_panel_authpwd, + remmina_protocol_widget_panel_authuserpwd, + remmina_protocol_widget_panel_new_certificate, + remmina_protocol_widget_panel_changed_certificate, + remmina_protocol_widget_get_username, + remmina_protocol_widget_get_password, + remmina_protocol_widget_get_domain, + remmina_protocol_widget_get_savepassword, + remmina_protocol_widget_panel_authx509, + remmina_protocol_widget_get_cacert, + remmina_protocol_widget_get_cacrl, + remmina_protocol_widget_get_clientcert, + remmina_protocol_widget_get_clientkey, + remmina_protocol_widget_save_cred, + remmina_protocol_widget_panel_show_listen, + remmina_protocol_widget_panel_show_retry, + remmina_protocol_widget_panel_show, + remmina_protocol_widget_panel_hide, remmina_protocol_widget_ssh_exec, remmina_protocol_widget_chat_open, remmina_protocol_widget_chat_close, diff --git a/src/remmina_protocol_widget.c b/src/remmina_protocol_widget.c index c694c13fc..a4e5f5b3d 100644 --- a/src/remmina_protocol_widget.c +++ b/src/remmina_protocol_widget.c @@ -77,6 +77,9 @@ struct _RemminaProtocolWidgetPriv { gint profile_remote_width; gint profile_remote_height; + RemminaMessagePanel *connect_message_panel; + RemminaMessagePanel *auth_message_panel; + /* Data saved from the last message_panel when the user confirm */ gchar *username; gchar *password; @@ -92,6 +95,13 @@ struct _RemminaProtocolWidgetPriv { }; +enum panel_type { + RPWDT_AUTHUSERPWD, + RPWDT_AUTHPWD, + RPWDT_QUESTIONYESNO, + RPWDT_AUTHX509 +}; + G_DEFINE_TYPE(RemminaProtocolWidget, remmina_protocol_widget, GTK_TYPE_EVENT_BOX) enum { @@ -134,7 +144,6 @@ static void remmina_protocol_widget_class_init(RemminaProtocolWidgetClass *klass static void remmina_protocol_widget_destroy(RemminaProtocolWidget* gp, gpointer data) { TRACE_CALL(__func__); - remmina_connection_object_hide_message_panel(gp->cnnobj); g_free(gp->priv->username); gp->priv->username = NULL; @@ -170,7 +179,7 @@ static void remmina_protocol_widget_destroy(RemminaProtocolWidget* gp, gpointer gp->priv = NULL; } -static void remmina_protocol_widget_connect(RemminaProtocolWidget* gp, gpointer data) +static void remmina_protocol_widget_on_connected(RemminaProtocolWidget* gp, gpointer data) { TRACE_CALL(__func__); #ifdef HAVE_LIBSSH @@ -178,13 +187,13 @@ static void remmina_protocol_widget_connect(RemminaProtocolWidget* gp, gpointer remmina_ssh_tunnel_cancel_accept(gp->priv->ssh_tunnel); } #endif - remmina_connection_object_hide_message_panel(gp->cnnobj); + remmina_connection_object_destroy_message_panel(gp->cnnobj, gp->priv->connect_message_panel); + gp->priv->connect_message_panel = NULL; } -static void remmina_protocol_widget_disconnect(RemminaProtocolWidget* gp, gpointer data) +static void remmina_protocol_widget_on_disconnected(RemminaProtocolWidget* gp, gpointer data) { TRACE_CALL(__func__); - remmina_connection_object_hide_message_panel(gp->cnnobj); } void remmina_protocol_widget_grab_focus(RemminaProtocolWidget* gp) @@ -209,8 +218,8 @@ static void remmina_protocol_widget_init(RemminaProtocolWidget* gp) gp->priv = priv; g_signal_connect(G_OBJECT(gp), "destroy", G_CALLBACK(remmina_protocol_widget_destroy), NULL); - g_signal_connect(G_OBJECT(gp), "connect", G_CALLBACK(remmina_protocol_widget_connect), NULL); - g_signal_connect(G_OBJECT(gp), "disconnect", G_CALLBACK(remmina_protocol_widget_disconnect), NULL); + g_signal_connect(G_OBJECT(gp), "connect", G_CALLBACK(remmina_protocol_widget_on_connected), NULL); + g_signal_connect(G_OBJECT(gp), "disconnect", G_CALLBACK(remmina_protocol_widget_on_disconnected), NULL); } void remmina_protocol_widget_open_connection_real(gpointer data) @@ -267,6 +276,12 @@ void remmina_protocol_widget_open_connection_real(gpointer data) } } +static void cancel_open_connection_cb(void *cbdata, int btn) +{ + RemminaProtocolWidget *gp = (RemminaProtocolWidget*)cbdata; + remmina_protocol_widget_close_connection(gp); +} + void remmina_protocol_widget_open_connection(RemminaProtocolWidget* gp, RemminaFile* remminafile) { TRACE_CALL(__func__); @@ -280,17 +295,19 @@ void remmina_protocol_widget_open_connection(RemminaProtocolWidget* gp, RemminaF /* Exec precommand before everything else */ mp = remmina_message_panel_new(); - remmina_message_panel_setup_progress(mp, _("Executing external commands...")); + remmina_message_panel_setup_progress(mp, _("Executing external commands..."), NULL, NULL); remmina_connection_object_show_message_panel(gp->cnnobj, mp); remmina_ext_exec_new(remminafile, "precommand"); + remmina_connection_object_destroy_message_panel(gp->cnnobj, mp); name = remmina_file_get_string(remminafile, "name"); s = g_strdup_printf(_("Connecting to '%s'..."), (name ? name : "*")); mp = remmina_message_panel_new(); - remmina_message_panel_setup_progress(mp, s); + remmina_message_panel_setup_progress(mp, s, cancel_open_connection_cb, gp); g_free(s); + gp->priv->connect_message_panel = mp; remmina_connection_object_show_message_panel(gp->cnnobj, mp); remmina_protocol_widget_open_connection_real(gp); @@ -480,12 +497,6 @@ const RemminaProtocolFeature* remmina_protocol_widget_get_features(RemminaProtoc return gp->priv->features; } -const gchar* remmina_protocol_widget_get_domain(RemminaProtocolWidget* gp) -{ - TRACE_CALL(__func__); - return gp->priv->plugin->domain; -} - gboolean remmina_protocol_widget_query_feature_by_type(RemminaProtocolWidget* gp, RemminaProtocolFeatureType type) { TRACE_CALL(__func__); @@ -582,7 +593,52 @@ void remmina_protocol_widget_set_hostkey_func(RemminaProtocolWidget* gp, Remmina gp->priv->hostkey_func = func; } +RemminaMessagePanel* remmina_protocol_widget_mpprogress(RemminaConnectionObject* cnnobj, const gchar *msg, RemminaMessagePanelCallback response_callback, gpointer response_callback_data) +{ + RemminaMessagePanel *mp; + + if ( !remmina_masterthread_exec_is_main_thread() ) { + /* Allow the execution of this function from a non main thread */ + RemminaMTExecData *d; + d = (RemminaMTExecData*)g_malloc( sizeof(RemminaMTExecData) ); + d->func = FUNC_PROTOCOLWIDGET_MPPROGRESS; + d->p.protocolwidget_mpprogress.cnnobj = cnnobj; + d->p.protocolwidget_mpprogress.message = msg; + d->p.protocolwidget_mpprogress.response_callback = response_callback; + d->p.protocolwidget_mpprogress.response_callback_data = response_callback_data; + remmina_masterthread_exec_and_wait(d); + mp = d->p.protocolwidget_mpprogress.ret_mp; + g_free(d); + return mp; + } + + mp = remmina_message_panel_new(); + remmina_message_panel_setup_progress(mp, msg, response_callback, response_callback_data); + remmina_connection_object_show_message_panel(cnnobj, mp); + return mp; +} + +void remmina_protocol_widget_mpdestroy(RemminaConnectionObject *cnnobj, RemminaMessagePanel *mp) +{ + if ( !remmina_masterthread_exec_is_main_thread() ) { + /* Allow the execution of this function from a non main thread */ + RemminaMTExecData *d; + d = (RemminaMTExecData*)g_malloc( sizeof(RemminaMTExecData) ); + d->func = FUNC_PROTOCOLWIDGET_MPDESTROY; + d->p.protocolwidget_mpdestroy.cnnobj = cnnobj; + d->p.protocolwidget_mpdestroy.mp = mp; + remmina_masterthread_exec_and_wait(d); + g_free(d); + return; + } + remmina_connection_object_destroy_message_panel(cnnobj, mp); +} + #ifdef HAVE_LIBSSH +static void cancel_init_tunnel_cb(void *cbdata, int btn) +{ + printf("REMMINA: cancelling an opening tunnel is not implemented\n"); +} static gboolean remmina_protocol_widget_init_tunnel(RemminaProtocolWidget* gp) { TRACE_CALL(__func__); @@ -596,11 +652,9 @@ static gboolean remmina_protocol_widget_init_tunnel(RemminaProtocolWidget* gp) tunnel = remmina_ssh_tunnel_new_from_file(gp->priv->remmina_file); msg = g_strdup_printf(_("Connecting to SSH server %s..."), REMMINA_SSH(tunnel)->server); - mp = remmina_message_panel_new(); - remmina_message_panel_setup_progress(mp, msg); - g_free(msg); - remmina_connection_object_show_message_panel(gp->cnnobj, mp); + mp = remmina_protocol_widget_mpprogress(gp->cnnobj, msg, cancel_init_tunnel_cb, NULL); + g_free(msg); if (!remmina_ssh_init_session(REMMINA_SSH(tunnel))) { remmina_protocol_widget_set_error(gp, REMMINA_SSH(tunnel)->error); @@ -608,7 +662,7 @@ static gboolean remmina_protocol_widget_init_tunnel(RemminaProtocolWidget* gp) return FALSE; } - ret = remmina_ssh_auth_gui(REMMINA_SSH(tunnel), gp->cnnobj, gp->priv->remmina_file); + ret = remmina_ssh_auth_gui(REMMINA_SSH(tunnel), gp, gp->priv->remmina_file); if (ret <= 0) { if (ret == 0) { remmina_protocol_widget_set_error(gp, REMMINA_SSH(tunnel)->error); @@ -617,6 +671,8 @@ static gboolean remmina_protocol_widget_init_tunnel(RemminaProtocolWidget* gp) return FALSE; } + remmina_protocol_widget_mpdestroy(gp->cnnobj, mp); + gp->priv->ssh_tunnel = tunnel; } @@ -624,6 +680,15 @@ static gboolean remmina_protocol_widget_init_tunnel(RemminaProtocolWidget* gp) } #endif + +#ifdef HAVE_LIBSSH +static void cancel_start_direct_tunnel_cb(void *cbdata, int btn) +{ + printf("REMMINA: cancelling start_direct_tunnel is not implemented\n"); +} +#endif + + /** * Start an SSH tunnel if possible and return the host:port string. * @@ -635,7 +700,6 @@ gchar* remmina_protocol_widget_start_direct_tunnel(RemminaProtocolWidget* gp, gi gchar *host, *dest; gint port; gchar *msg; - RemminaMessagePanel *mp; server = remmina_file_get_string(gp->priv->remmina_file, "server"); @@ -651,6 +715,8 @@ gchar* remmina_protocol_widget_start_direct_tunnel(RemminaProtocolWidget* gp, gi } #ifdef HAVE_LIBSSH + RemminaMessagePanel *mp; + if (!remmina_file_get_int(gp->priv->remmina_file, "ssh_enabled", FALSE)) { dest = g_strdup_printf("[%s]:%i", host, port); g_free(host); @@ -669,10 +735,8 @@ gchar* remmina_protocol_widget_start_direct_tunnel(RemminaProtocolWidget* gp, gi } msg = g_strdup_printf(_("Connecting to %s through SSH tunnel..."), server); - mp = remmina_message_panel_new(); - remmina_message_panel_setup_progress(mp, msg); + mp = remmina_protocol_widget_mpprogress(gp->cnnobj, msg, cancel_start_direct_tunnel_cb, NULL); g_free(msg); - remmina_connection_object_show_message_panel(gp->cnnobj, mp); if (remmina_file_get_int(gp->priv->remmina_file, "ssh_loopback", FALSE)) { g_free(host); @@ -684,8 +748,10 @@ gchar* remmina_protocol_widget_start_direct_tunnel(RemminaProtocolWidget* gp, gi remmina_protocol_widget_set_error(gp, REMMINA_SSH(gp->priv->ssh_tunnel)->error); return NULL; } - g_free(host); + + remmina_protocol_widget_mpdestroy(gp->cnnobj, mp); + return g_strdup_printf("127.0.0.1:%i", remmina_pref.sshtunnel_port); #else @@ -697,6 +763,14 @@ gchar* remmina_protocol_widget_start_direct_tunnel(RemminaProtocolWidget* gp, gi #endif } +#ifdef HAVE_LIBSSH +static void cancel_start_reverse_tunnel_cb(void *cbdata, int btn) +{ + printf("REMMINA: cancelling start_reverse_tunnel is not implemented\n"); +} +#endif + + gboolean remmina_protocol_widget_start_reverse_tunnel(RemminaProtocolWidget* gp, gint local_port) { TRACE_CALL(__func__); @@ -713,15 +787,14 @@ gboolean remmina_protocol_widget_start_reverse_tunnel(RemminaProtocolWidget* gp, } msg = g_strdup_printf(_("Waiting for an incoming SSH tunnel at port %i..."), remmina_file_get_int(gp->priv->remmina_file, "listenport", 0)); - mp = remmina_message_panel_new(); - remmina_message_panel_setup_progress(mp, msg); + mp = remmina_protocol_widget_mpprogress(gp->cnnobj, msg, cancel_start_reverse_tunnel_cb, NULL); g_free(msg); - remmina_connection_object_show_message_panel(gp->cnnobj, mp); if (!remmina_ssh_tunnel_reverse(gp->priv->ssh_tunnel, remmina_file_get_int(gp->priv->remmina_file, "listenport", 0), local_port)) { remmina_protocol_widget_set_error(gp, REMMINA_SSH(gp->priv->ssh_tunnel)->error); return FALSE; } + remmina_protocol_widget_mpdestroy(gp->cnnobj, mp); #endif return TRUE; @@ -821,7 +894,12 @@ static gboolean remmina_protocol_widget_tunnel_disconnect_callback(RemminaSSHTun return TRUE; } #endif - +#ifdef HAVE_LIBSSH +static void cancel_connect_xport_cb(void *cbdata, int btn) +{ + printf("REMMINA: cancelling a xport connect is not implemented\n"); +} +#endif gboolean remmina_protocol_widget_start_xport_tunnel(RemminaProtocolWidget* gp, RemminaXPortTunnelInitFunc init_func) { TRACE_CALL(__func__); @@ -834,10 +912,8 @@ gboolean remmina_protocol_widget_start_xport_tunnel(RemminaProtocolWidget* gp, R if (!remmina_protocol_widget_init_tunnel(gp)) return FALSE; msg = g_strdup_printf(_("Connecting to %s through SSH tunnel..."), remmina_file_get_string(gp->priv->remmina_file, "server")); - mp = remmina_message_panel_new(); - remmina_message_panel_setup_progress(mp, msg); + mp = remmina_protocol_widget_mpprogress(gp->cnnobj, msg, cancel_connect_xport_cb, NULL); g_free(msg); - remmina_connection_object_show_message_panel(gp->cnnobj, mp); gp->priv->init_func = init_func; gp->priv->ssh_tunnel->init_func = remmina_protocol_widget_tunnel_init_callback; @@ -855,6 +931,8 @@ gboolean remmina_protocol_widget_start_xport_tunnel(RemminaProtocolWidget* gp, R return FALSE; } + remmina_protocol_widget_mpdestroy(gp->cnnobj, mp); + return TRUE; #else @@ -979,54 +1057,142 @@ RemminaFile* remmina_protocol_widget_get_file(RemminaProtocolWidget* gp) return gp->priv->remmina_file; } -gint remmina_protocol_widget_init_authpwd(RemminaProtocolWidget* gp, RemminaAuthpwdType authpwd_type, gboolean allow_password_saving) -{ - TRACE_CALL(__func__); - RemminaFile* remminafile = gp->priv->remmina_file; - gchar* s; - gint ret; - RemminaMessagePanel* mp; +struct remmina_protocol_widget_dialog_mt_data_t { + /* Input data */ + RemminaProtocolWidget *gp; + char *str1; + char *str2; + enum panel_type dtype; unsigned pflags; + /* Running status */ + pthread_mutex_t pt_mutex; + pthread_cond_t pt_cond; + /* Output/retval */ + int rcbutton; +}; - switch (authpwd_type) { - case REMMINA_AUTHPWD_TYPE_PROTOCOL: - s = g_strdup_printf(_("%s password"), remmina_file_get_string(remminafile, "protocol")); - break; - case REMMINA_AUTHPWD_TYPE_SSH_PWD: - s = g_strdup(_("SSH password")); - break; - case REMMINA_AUTHPWD_TYPE_SSH_PRIVKEY: - s = g_strdup(_("SSH private key passphrase")); - break; - default: - s = g_strdup(_("Password")); - break; +static void authuserpwd_mt_cb(void *user_data, int button) +{ + struct remmina_protocol_widget_dialog_mt_data_t *d = (struct remmina_protocol_widget_dialog_mt_data_t *)user_data; + d->rcbutton = button; + if (button == GTK_RESPONSE_OK) { + if (d->dtype == RPWDT_AUTHUSERPWD || d->dtype == RPWDT_AUTHPWD) { + d->gp->priv->password = remmina_message_panel_field_get_string(d->gp->priv->auth_message_panel, REMMINA_MESSAGE_PANEL_PASSWORD); + d->gp->priv->username = remmina_message_panel_field_get_string(d->gp->priv->auth_message_panel, REMMINA_MESSAGE_PANEL_USERNAME); + d->gp->priv->domain = remmina_message_panel_field_get_string(d->gp->priv->auth_message_panel, REMMINA_MESSAGE_PANEL_DOMAIN); + d->gp->priv->save_password = remmina_message_panel_field_get_switch_state(d->gp->priv->auth_message_panel, REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSRORD); + } else if (d->dtype == RPWDT_AUTHX509) { + d->gp->priv->cacert = remmina_message_panel_field_get_filename(d->gp->priv->auth_message_panel, REMMINA_MESSAGE_PANEL_CACERTFILE); + d->gp->priv->cacrl = remmina_message_panel_field_get_filename(d->gp->priv->auth_message_panel, REMMINA_MESSAGE_PANEL_CACRLFILE); + d->gp->priv->clientcert = remmina_message_panel_field_get_filename(d->gp->priv->auth_message_panel, REMMINA_MESSAGE_PANEL_CLIENTCERTFILE); + d->gp->priv->clientkey = remmina_message_panel_field_get_filename(d->gp->priv->auth_message_panel, REMMINA_MESSAGE_PANEL_CLIENTKEYFILE); + } } + /* Hide and destroy message panel, we can do it now because we are on the main thread */ + remmina_connection_object_destroy_message_panel(d->gp->cnnobj, d->gp->priv->auth_message_panel); + + /* Awake the locked subthread */ + pthread_mutex_lock(&d->pt_mutex); + + pthread_cond_signal(&d->pt_cond); + pthread_mutex_unlock(&d->pt_mutex); +} + +static gboolean remmina_protocol_widget_dialog_mt_setup(gpointer user_data) +{ + struct remmina_protocol_widget_dialog_mt_data_t *d = (struct remmina_protocol_widget_dialog_mt_data_t *)user_data; + + RemminaFile* remminafile = d->gp->priv->remmina_file; + RemminaMessagePanel *mp; + const gchar *s; mp = remmina_message_panel_new(); - /* ToDo: init mp with username, password, and checkbox */ - pflags = 0; - if (!remminafile->prevent_saving && allow_password_saving) - pflags |= REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSRORD; - remmina_message_panel_setup_auth(mp, s, pflags); - g_free(s); - remmina_connection_object_show_message_panel(gp->cnnobj, mp); - ret = remmina_message_panel_wait_user_answer(mp); - /* ToDo: take parameters from mp and save in gp->priv->password */ + if (d->dtype == RPWDT_AUTHUSERPWD) { + remmina_message_panel_setup_auth(mp, authuserpwd_mt_cb, d, _("Enter authentication credentials"), d->str1, d->pflags); + if ((s = remmina_file_get_string(remminafile, "username")) != NULL) + remmina_message_panel_field_set_string(mp, REMMINA_MESSAGE_PANEL_USERNAME, s); + if ((d->pflags & REMMINA_MESSAGE_PANEL_FLAG_DOMAIN) && (s = remmina_file_get_string(remminafile, "domain")) != NULL) + remmina_message_panel_field_set_string(mp, REMMINA_MESSAGE_PANEL_DOMAIN, s); + if ((s = remmina_file_get_string(remminafile, "password")) != NULL) + remmina_message_panel_field_set_string(mp, REMMINA_MESSAGE_PANEL_PASSWORD, s); + if (d->pflags & REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSRORD) { + remmina_message_panel_field_set_switch(mp, REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSRORD, FALSE); + } + } else if (d->dtype == RPWDT_AUTHPWD) { + remmina_message_panel_setup_auth(mp, authuserpwd_mt_cb, d, _("Enter authentication credentials"), d->str1, d->pflags); + if ((s = remmina_file_get_string(remminafile, "username")) != NULL) + remmina_message_panel_field_set_string(mp, REMMINA_MESSAGE_PANEL_USERNAME, s); + if ((s = remmina_file_get_string(remminafile, "password")) != NULL) + remmina_message_panel_field_set_string(mp, REMMINA_MESSAGE_PANEL_PASSWORD, s); + if (d->pflags & REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSRORD) { + remmina_message_panel_field_set_switch(mp, REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSRORD, FALSE); + } + } else if (d->dtype == RPWDT_QUESTIONYESNO) { + remmina_message_panel_setup_question(mp, d->str1, authuserpwd_mt_cb, d); + } else if (d->dtype == RPWDT_AUTHX509) { + remmina_message_panel_setup_auth_x509(mp, authuserpwd_mt_cb, d); + if ((s = remmina_file_get_string(remminafile, "cacert")) != NULL) + remmina_message_panel_field_set_filename(mp, REMMINA_MESSAGE_PANEL_CACERTFILE, s); + if ((s = remmina_file_get_string(remminafile, "cacrl")) != NULL) + remmina_message_panel_field_set_filename(mp, REMMINA_MESSAGE_PANEL_CACRLFILE, s); + if ((s = remmina_file_get_string(remminafile, "clientcert")) != NULL) + remmina_message_panel_field_set_filename(mp, REMMINA_MESSAGE_PANEL_CLIENTCERTFILE, s); + if ((s = remmina_file_get_string(remminafile, "clientkey")) != NULL) + remmina_message_panel_field_set_filename(mp, REMMINA_MESSAGE_PANEL_CLIENTKEYFILE, s); + } + + d->gp->priv->auth_message_panel = mp; + remmina_connection_object_show_message_panel(d->gp->cnnobj, mp); - g_clear_object(&mp); + return FALSE; +} - return ret; +static int remmina_protocol_widget_dialog(enum panel_type dtype, RemminaProtocolWidget* gp, unsigned pflags, const char *str1, const char *str2) +{ + + struct remmina_protocol_widget_dialog_mt_data_t *d = (struct remmina_protocol_widget_dialog_mt_data_t*)g_malloc( sizeof(struct remmina_protocol_widget_dialog_mt_data_t) ); + int rcbutton; + + if (remmina_masterthread_exec_is_main_thread()) { + printf("REMMINA warning. %s should not be called from the master thread.\n", __func__); + } + + d->gp = gp; + d->pflags = pflags; + d->dtype = dtype; + d->str1 = g_strdup(str1); + d->str2 = g_strdup(str2); + + // pthread_cleanup_push(ptcleanup, (void*)d); + pthread_cond_init(&d->pt_cond, NULL); + pthread_mutex_init(&d->pt_mutex, NULL); + g_idle_add(remmina_protocol_widget_dialog_mt_setup, d); + pthread_mutex_lock(&d->pt_mutex); + pthread_cond_wait(&d->pt_cond, &d->pt_mutex); + // pthread_cleanup_pop(0); + pthread_mutex_destroy(&d->pt_mutex); + pthread_cond_destroy(&d->pt_cond); + + rcbutton = d->rcbutton; + g_free(d->str1); + g_free(d->str2); + g_free(d); + + return rcbutton; + +} + +gint remmina_protocol_widget_panel_question_yesno(RemminaProtocolWidget* gp, const char *msg) +{ + return remmina_protocol_widget_dialog(RPWDT_QUESTIONYESNO, gp, 0, msg, NULL); } -gint remmina_protocol_widget_init_authuserpwd(RemminaProtocolWidget* gp, gboolean want_domain, gboolean allow_password_saving) +gint remmina_protocol_widget_panel_authuserpwd(RemminaProtocolWidget* gp, gboolean want_domain, gboolean allow_password_saving, const char *tips) { TRACE_CALL(__func__); - RemminaFile* remminafile = gp->priv->remmina_file; unsigned pflags; - RemminaMessagePanel* mp; - gint ret; + RemminaFile* remminafile = gp->priv->remmina_file; pflags = REMMINA_MESSAGE_PANEL_FLAG_USERNAME; if (remmina_file_get_filename(remminafile) != NULL && @@ -1035,106 +1201,120 @@ gint remmina_protocol_widget_init_authuserpwd(RemminaProtocolWidget* gp, gboolea if (want_domain) pflags |= REMMINA_MESSAGE_PANEL_FLAG_DOMAIN; - mp = remmina_message_panel_new(); - /* ToDo: init mp with username, password, domain (if want_domain) and checkbox */ - remmina_message_panel_setup_auth(mp, _("Enter authentication credentials"), pflags); - remmina_connection_object_show_message_panel(gp->cnnobj, mp); - ret = remmina_message_panel_wait_user_answer(mp); + return remmina_protocol_widget_dialog(RPWDT_AUTHUSERPWD, gp, pflags, _("Password"), tips); +} - /* ToDo: take parameters from mp and save in gp->priv->username/password/domain */ +gint remmina_protocol_widget_panel_authpwd(RemminaProtocolWidget* gp, RemminaAuthpwdType authpwd_type, gboolean allow_password_saving) +{ + TRACE_CALL(__func__); + unsigned pflags; + RemminaFile* remminafile = gp->priv->remmina_file; + char *password_prompt; + int rc; - g_clear_object(&mp); - return ret; + pflags = 0; + if (remmina_file_get_filename(remminafile) != NULL && + !remminafile->prevent_saving && allow_password_saving) + pflags |= REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSRORD; + + switch (authpwd_type) { + case REMMINA_AUTHPWD_TYPE_PROTOCOL: + password_prompt = g_strdup_printf(_("%s password"), remmina_file_get_string(remminafile, "protocol")); + break; + case REMMINA_AUTHPWD_TYPE_SSH_PWD: + password_prompt = g_strdup(_("SSH password")); + break; + case REMMINA_AUTHPWD_TYPE_SSH_PRIVKEY: + password_prompt = g_strdup(_("SSH private key passphrase")); + break; + default: + password_prompt = g_strdup(_("Password")); + break; + } -/* Original code: + rc = remmina_protocol_widget_dialog(RPWDT_AUTHPWD, gp, pflags, password_prompt, NULL); + g_free(password_prompt); + return rc; - return remmina_init_dialog_authuserpwd( - REMMINA_INIT_DIALOG(gp->priv->init_dialog), - want_domain, - remmina_file_get_string(remminafile, "username"), - want_domain ? remmina_file_get_string(remminafile, "domain") : NULL, - (remmina_file_get_filename(remminafile) != NULL && - !remminafile->prevent_saving && allow_password_saving)); - * - */ } -gint remmina_protocol_widget_init_certificate(RemminaProtocolWidget* gp, const gchar* subject, const gchar* issuer, const gchar* fingerprint) +gint remmina_protocol_widget_panel_authx509(RemminaProtocolWidget* gp) { TRACE_CALL(__func__); - RemminaMessagePanel* mp; - gint ret; - mp = remmina_message_panel_new(); - remmina_message_panel_setup_cert(mp, subject, issuer, fingerprint, NULL); - remmina_connection_object_show_message_panel(gp->cnnobj, mp); - ret = remmina_message_panel_wait_user_answer(mp); + return remmina_protocol_widget_dialog(RPWDT_AUTHX509, gp, 0, NULL, NULL); +} + + +gint remmina_protocol_widget_panel_new_certificate(RemminaProtocolWidget* gp, const gchar* subject, const gchar* issuer, const gchar* fingerprint) +{ + TRACE_CALL(__func__); + gchar *s; + int rc; + + // For markup see https://developer.gnome.org/pygtk/stable/pango-markup-language.html + s = g_strdup_printf( + "<big>%s</big>\n\n%s %s\n%s %s\n%s %s\n\n<big>%s</big>", + _("Certificate Details:"), + _("Subject:"), subject, + _("Issuer:"), issuer, + _("Fingerprint:"), fingerprint, + _("Accept Certificate?")); + rc = remmina_protocol_widget_dialog(RPWDT_QUESTIONYESNO, gp, 0, s, NULL); + g_free(s); + + /* For compatibility with plugin API: the plugin expects GTK_RESPONSE_OK when user confirms new cert */ + return rc == GTK_RESPONSE_YES ? GTK_RESPONSE_OK : rc; - g_clear_object(&mp); - return ret; } -gint remmina_protocol_widget_changed_certificate(RemminaProtocolWidget *gp, const gchar* subject, const gchar* issuer, const gchar* new_fingerprint, const gchar* old_fingerprint) +gint remmina_protocol_widget_panel_changed_certificate(RemminaProtocolWidget *gp, const gchar* subject, const gchar* issuer, const gchar* new_fingerprint, const gchar* old_fingerprint) { TRACE_CALL(__func__); - RemminaMessagePanel* mp; - gint ret; + gchar *s; + int rc; - mp = remmina_message_panel_new(); - remmina_message_panel_setup_cert(mp, subject, issuer, new_fingerprint, old_fingerprint); - remmina_connection_object_show_message_panel(gp->cnnobj, mp); - ret = remmina_message_panel_wait_user_answer(mp); + // For markup see https://developer.gnome.org/pygtk/stable/pango-markup-language.html + s = g_strdup_printf( + "<big>%s</big>\n\n%s %s\n%s %s\n%s %s\n%s %s\n\n<big>%s</big>", + _("Certificate Changed! Details:"), + _("Subject:"), subject, + _("Issuer:"), issuer, + _("Old Fingerprint:"), old_fingerprint, + _("New Fingerprint:"), new_fingerprint, + _("Accept Changed Certificate?")); + rc = remmina_protocol_widget_dialog(RPWDT_QUESTIONYESNO, gp, 0, s, NULL); + g_free(s); - g_clear_object(&mp); - return ret; + /* For compatibility with plugin API: the plugin expects GTK_RESPONSE_OK when user confirms new cert */ + return rc == GTK_RESPONSE_YES ? GTK_RESPONSE_OK : rc; } -gchar* remmina_protocol_widget_init_get_username(RemminaProtocolWidget* gp) +gchar* remmina_protocol_widget_get_username(RemminaProtocolWidget* gp) { TRACE_CALL(__func__); return g_strdup(gp->priv->username); } -gchar* remmina_protocol_widget_init_get_password(RemminaProtocolWidget* gp) +gchar* remmina_protocol_widget_get_password(RemminaProtocolWidget* gp) { TRACE_CALL(__func__); return g_strdup(gp->priv->password); } -gchar* remmina_protocol_widget_init_get_domain(RemminaProtocolWidget* gp) +gchar* remmina_protocol_widget_get_domain(RemminaProtocolWidget* gp) { TRACE_CALL(__func__); return g_strdup(gp->priv->domain); } -gboolean remmina_protocol_widget_init_get_savepassword(RemminaProtocolWidget *gp) +gboolean remmina_protocol_widget_get_savepassword(RemminaProtocolWidget *gp) { TRACE_CALL(__func__); return gp->priv->save_password; } -gint remmina_protocol_widget_init_authx509(RemminaProtocolWidget* gp) -{ - TRACE_CALL(__func__); - RemminaFile* remminafile = gp->priv->remmina_file; - RemminaMessagePanel *mp; - gint ret; - - mp = remmina_message_panel_new(); - remmina_message_panel_setup_auth_x509(mp, - remmina_file_get_string(remminafile, "cacert"), remmina_file_get_string(remminafile, "cacrl"), - remmina_file_get_string(remminafile, "clientcert"), remmina_file_get_string(remminafile, "clientkey")); - - remmina_connection_object_show_message_panel(gp->cnnobj, mp); - ret = remmina_message_panel_wait_user_answer(mp); - - /* ToDo: save cacert, cacrl, clientcert, clientkey into apposite gp->priv-> strings */ - - g_clear_object(&mp); - return ret; -} - -gchar* remmina_protocol_widget_init_get_cacert(RemminaProtocolWidget* gp) +gchar* remmina_protocol_widget_get_cacert(RemminaProtocolWidget* gp) { TRACE_CALL(__func__); gchar* s; @@ -1143,7 +1323,7 @@ gchar* remmina_protocol_widget_init_get_cacert(RemminaProtocolWidget* gp) return (s && s[0] ? g_strdup(s) : NULL); } -gchar* remmina_protocol_widget_init_get_cacrl(RemminaProtocolWidget* gp) +gchar* remmina_protocol_widget_get_cacrl(RemminaProtocolWidget* gp) { TRACE_CALL(__func__); gchar* s; @@ -1152,7 +1332,7 @@ gchar* remmina_protocol_widget_init_get_cacrl(RemminaProtocolWidget* gp) return (s && s[0] ? g_strdup(s) : NULL); } -gchar* remmina_protocol_widget_init_get_clientcert(RemminaProtocolWidget* gp) +gchar* remmina_protocol_widget_get_clientcert(RemminaProtocolWidget* gp) { TRACE_CALL(__func__); gchar* s; @@ -1161,7 +1341,7 @@ gchar* remmina_protocol_widget_init_get_clientcert(RemminaProtocolWidget* gp) return (s && s[0] ? g_strdup(s) : NULL); } -gchar* remmina_protocol_widget_init_get_clientkey(RemminaProtocolWidget* gp) +gchar* remmina_protocol_widget_get_clientkey(RemminaProtocolWidget* gp) { TRACE_CALL(__func__); gchar* s; @@ -1170,7 +1350,7 @@ gchar* remmina_protocol_widget_init_get_clientkey(RemminaProtocolWidget* gp) return (s && s[0] ? g_strdup(s) : NULL); } -void remmina_protocol_widget_init_save_cred(RemminaProtocolWidget* gp) +void remmina_protocol_widget_save_cred(RemminaProtocolWidget* gp) { TRACE_CALL(__func__); @@ -1225,7 +1405,7 @@ void remmina_protocol_widget_init_save_cred(RemminaProtocolWidget* gp) } -void remmina_protocol_widget_init_show_listen(RemminaProtocolWidget* gp, gint port) +void remmina_protocol_widget_panel_show_listen(RemminaProtocolWidget* gp, gint port) { TRACE_CALL(__func__); RemminaMessagePanel *mp; @@ -1235,33 +1415,44 @@ void remmina_protocol_widget_init_show_listen(RemminaProtocolWidget* gp, gint po s = g_strdup_printf( _("Listening on port %i for an incoming %s connection..."), port, remmina_file_get_string(gp->priv->remmina_file, "protocol")); - remmina_message_panel_setup_progress(mp, s); + remmina_message_panel_setup_progress(mp, s, NULL, NULL); g_free(s); remmina_connection_object_show_message_panel(gp->cnnobj, mp); } -void remmina_protocol_widget_init_show_retry(RemminaProtocolWidget* gp) +void remmina_protocol_widget_panel_show_retry(RemminaProtocolWidget* gp) { TRACE_CALL(__func__); RemminaMessagePanel *mp; + if ( !remmina_masterthread_exec_is_main_thread() ) { + /* Allow the execution of this function from a non main thread */ + RemminaMTExecData *d; + d = (RemminaMTExecData*)g_malloc( sizeof(RemminaMTExecData) ); + d->func = FUNC_PROTOCOLWIDGET_MPSHOWRETRY; + d->p.protocolwidget_mpshowretry.gp = gp; + remmina_masterthread_exec_and_wait(d); + g_free(d); + return; + } + mp = remmina_message_panel_new(); - remmina_message_panel_setup_progress(mp, _("Authentication failed. Trying to reconnect...")); + remmina_message_panel_setup_progress(mp, _("Authentication failed. Trying to reconnect..."), NULL, NULL); remmina_connection_object_show_message_panel(gp->cnnobj, mp); } -void remmina_protocol_widget_init_show(RemminaProtocolWidget* gp) +void remmina_protocol_widget_panel_show(RemminaProtocolWidget* gp) { TRACE_CALL(__func__); - printf("REMMINA: error, function %s is not implemented\n", __func__); + printf("REMMINA: error, function %s is not implemented. Is left here only for plugin API compatibility.\n", __func__); } -void remmina_protocol_widget_init_hide(RemminaProtocolWidget* gp) +void remmina_protocol_widget_panel_hide(RemminaProtocolWidget* gp) { TRACE_CALL(__func__); - remmina_connection_object_hide_message_panel(gp->cnnobj); + printf("REMMINA: error, function %s is not implemented. Is left here only for plugin API compatibility.\n", __func__); } static void remmina_protocol_widget_chat_on_destroy(RemminaProtocolWidget* gp) diff --git a/src/remmina_protocol_widget.h b/src/remmina_protocol_widget.h index e1d076e39..e0a8ab18e 100644 --- a/src/remmina_protocol_widget.h +++ b/src/remmina_protocol_widget.h @@ -97,7 +97,6 @@ void remmina_protocol_widget_open_connection(RemminaProtocolWidget *gp, RemminaF gboolean remmina_protocol_widget_close_connection(RemminaProtocolWidget *gp); void remmina_protocol_widget_grab_focus(RemminaProtocolWidget *gp); const RemminaProtocolFeature* remmina_protocol_widget_get_features(RemminaProtocolWidget *gp); -const gchar* remmina_protocol_widget_get_domain(RemminaProtocolWidget *gp); gboolean remmina_protocol_widget_query_feature_by_type(RemminaProtocolWidget *gp, RemminaProtocolFeatureType type); gboolean remmina_protocol_widget_query_feature_by_ref(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature); void remmina_protocol_widget_call_feature_by_type(RemminaProtocolWidget *gp, RemminaProtocolFeatureType type, gint id); @@ -121,24 +120,32 @@ gboolean remmina_protocol_widget_start_reverse_tunnel(RemminaProtocolWidget *gp, gboolean remmina_protocol_widget_start_xport_tunnel(RemminaProtocolWidget *gp, RemminaXPortTunnelInitFunc init_func); void remmina_protocol_widget_set_display(RemminaProtocolWidget *gp, gint display); -gint remmina_protocol_widget_init_authpwd(RemminaProtocolWidget *gp, RemminaAuthpwdType authpwd_type, gboolean allow_password_saving); -gint remmina_protocol_widget_init_authuserpwd(RemminaProtocolWidget *gp, gboolean want_domain, gboolean allow_password_saving); -gint remmina_protocol_widget_init_certificate(RemminaProtocolWidget* gp, const gchar* subject, const gchar* issuer, const gchar* fingerprint); -gint remmina_protocol_widget_changed_certificate(RemminaProtocolWidget *gp, const gchar* subject, const gchar* issuer, const gchar* new_fingerprint, const gchar* old_fingerprint); -gchar* remmina_protocol_widget_init_get_username(RemminaProtocolWidget *gp); -gchar* remmina_protocol_widget_init_get_password(RemminaProtocolWidget *gp); -gchar* remmina_protocol_widget_init_get_domain(RemminaProtocolWidget *gp); -gboolean remmina_protocol_widget_init_get_savepassword(RemminaProtocolWidget *gp); -gint remmina_protocol_widget_init_authx509(RemminaProtocolWidget *gp); -gchar* remmina_protocol_widget_init_get_cacert(RemminaProtocolWidget *gp); -gchar* remmina_protocol_widget_init_get_cacrl(RemminaProtocolWidget *gp); -gchar* remmina_protocol_widget_init_get_clientcert(RemminaProtocolWidget *gp); -gchar* remmina_protocol_widget_init_get_clientkey(RemminaProtocolWidget *gp); -void remmina_protocol_widget_init_save_cred(RemminaProtocolWidget *gp); -void remmina_protocol_widget_init_show_listen(RemminaProtocolWidget *gp, gint port); -void remmina_protocol_widget_init_show_retry(RemminaProtocolWidget *gp); -void remmina_protocol_widget_init_show(RemminaProtocolWidget *gp); -void remmina_protocol_widget_init_hide(RemminaProtocolWidget *gp); + +/* Dialog panel API used by the plugins */ + +gint remmina_protocol_widget_panel_authpwd(RemminaProtocolWidget *gp, RemminaAuthpwdType authpwd_type, gboolean allow_password_saving); +gint remmina_protocol_widget_panel_authuserpwd(RemminaProtocolWidget *gp, gboolean want_domain, gboolean allow_password_saving, const char *tips); +gint remmina_protocol_widget_panel_new_certificate(RemminaProtocolWidget* gp, const gchar* subject, const gchar* issuer, const gchar* fingerprint); +gint remmina_protocol_widget_panel_changed_certificate(RemminaProtocolWidget *gp, const gchar* subject, const gchar* issuer, const gchar* new_fingerprint, const gchar* old_fingerprint); +gint remmina_protocol_widget_panel_question_yesno(RemminaProtocolWidget* gp, const char *msg); + +void remmina_protocol_widget_panel_show(RemminaProtocolWidget *gp); +void remmina_protocol_widget_panel_hide(RemminaProtocolWidget *gp); +void remmina_protocol_widget_panel_destroy(RemminaProtocolWidget *gp); +gint remmina_protocol_widget_panel_authx509(RemminaProtocolWidget *gp); +void remmina_protocol_widget_panel_show_listen(RemminaProtocolWidget *gp, gint port); +void remmina_protocol_widget_panel_show_retry(RemminaProtocolWidget *gp); + +void remmina_protocol_widget_save_cred(RemminaProtocolWidget *gp); + +gchar* remmina_protocol_widget_get_username(RemminaProtocolWidget *gp); +gchar* remmina_protocol_widget_get_password(RemminaProtocolWidget *gp); +gchar* remmina_protocol_widget_get_domain(RemminaProtocolWidget *gp); +gboolean remmina_protocol_widget_get_savepassword(RemminaProtocolWidget *gp); +gchar* remmina_protocol_widget_get_cacert(RemminaProtocolWidget *gp); +gchar* remmina_protocol_widget_get_cacrl(RemminaProtocolWidget *gp); +gchar* remmina_protocol_widget_get_clientcert(RemminaProtocolWidget *gp); +gchar* remmina_protocol_widget_get_clientkey(RemminaProtocolWidget *gp); void remmina_protocol_widget_chat_open(RemminaProtocolWidget *gp, const gchar *name, void (*on_send)(RemminaProtocolWidget *gp, const gchar *text), void (*on_destroy)(RemminaProtocolWidget *gp)); @@ -154,6 +161,10 @@ gboolean remmina_protocol_widget_plugin_screenshot(RemminaProtocolWidget* gp, Re void remmina_protocol_widget_update_remote_resolution(RemminaProtocolWidget* gp, gint w, gint h); +/* Functions to support execution of GTK code on master thread */ +RemminaMessagePanel* remmina_protocol_widget_mpprogress(RemminaConnectionObject* cnnobj, const gchar *msg, RemminaMessagePanelCallback response_callback, gpointer response_callback_data); +void remmina_protocol_widget_mpdestroy(RemminaConnectionObject *cnnobj, RemminaMessagePanel *mp); + G_END_DECLS diff --git a/src/remmina_sftp_plugin.c b/src/remmina_sftp_plugin.c index 3e818cb1e..63a7895d2 100644 --- a/src/remmina_sftp_plugin.c +++ b/src/remmina_sftp_plugin.c @@ -157,8 +157,7 @@ remmina_plugin_sftp_main_thread(gpointer data) break; } - ret = remmina_ssh_auth_gui(REMMINA_SSH(sftp), gp->cnnobj, - remminafile); + ret = remmina_ssh_auth_gui(REMMINA_SSH(sftp), gp, remminafile); if (ret == 0) { remmina_plugin_service->protocol_plugin_set_error(gp, "%s", REMMINA_SSH(sftp)->error); } diff --git a/src/remmina_ssh.c b/src/remmina_ssh.c index 30be82d5a..1a54d0a22 100644 --- a/src/remmina_ssh.c +++ b/src/remmina_ssh.c @@ -362,7 +362,7 @@ remmina_ssh_auth(RemminaSSH *ssh, const gchar *password) } gint -remmina_ssh_auth_gui(RemminaSSH *ssh, RemminaConnectionObject *cnnobj, RemminaFile *remminafile) +remmina_ssh_auth_gui(RemminaSSH *ssh, RemminaProtocolWidget *gp, RemminaFile *remminafile) { TRACE_CALL(__func__); gchar *tips; @@ -375,10 +375,6 @@ remmina_ssh_auth_gui(RemminaSSH *ssh, RemminaConnectionObject *cnnobj, RemminaFi ssh_key server_pubkey; gboolean disablepasswordstoring; gboolean save_password; - RemminaMessagePanel *mp; - - if (!remmina_masterthread_exec_is_main_thread()) - printf("WARNING: function %s should never be called from the masterthread", __func__); /* Check if the server's public key is known */ ret = ssh_is_server_known(ssh->session); @@ -403,29 +399,25 @@ remmina_ssh_auth_gui(RemminaSSH *ssh, RemminaConnectionObject *cnnobj, RemminaFi ssh_key_free(server_pubkey); keyname = ssh_get_hexa(pubkey, len); - mp = remmina_message_panel_new(); if (ret == SSH_SERVER_NOT_KNOWN || ret == SSH_SERVER_FILE_NOT_FOUND) { - message = g_strdup_printf("%s %s %s", + message = g_strdup_printf("%s\n%s\n\n%s", _("The server is unknown. The public key fingerprint is:"), keyname, _("Do you trust the new public key?")); }else { - message = g_strdup_printf("%s %s %s", + message = g_strdup_printf("%s\n%s\n\n%s", _("WARNING: The server has changed its public key. This means either you are under attack,\n" "or the administrator has changed the key. The new public key fingerprint is:"), keyname, _("Do you trust the new public key?")); } - remmina_message_panel_setup_question(mp, message); + + ret = remmina_protocol_widget_panel_question_yesno(gp, message); g_free(message); - remmina_connection_object_show_message_panel(cnnobj, mp); - /* end of masterthread required */ - ret = remmina_message_panel_wait_user_answer(mp); - g_clear_object(&mp); ssh_string_free_char(keyname); ssh_clean_pubkey_hash(&pubkey); - if (ret != 1) return -1; + if (ret != GTK_RESPONSE_YES) return -1; ssh_write_knownhost(ssh->session); break; case SSH_SERVER_ERROR: @@ -461,46 +453,25 @@ remmina_ssh_auth_gui(RemminaSSH *ssh, RemminaConnectionObject *cnnobj, RemminaFi /* Requested for a non-empty password */ if (ret < 0) { - gchar *msg; - - if (!cnnobj) { - printf("WARNING: cnnobj is null in %s\n", __func__); - return -1; - } - - msg = g_strdup_printf(tips, ssh->user, ssh->server); + gchar *pwd; disablepasswordstoring = remmina_file_get_int(remminafile, "disablepasswordstoring", FALSE); + ret = remmina_protocol_widget_panel_authuserpwd(gp, FALSE, !disablepasswordstoring, tips); + save_password = remmina_protocol_widget_get_savepassword(gp); - mp = remmina_message_panel_new(); - remmina_message_panel_setup_auth(mp, keyname, disablepasswordstoring ? 0 : REMMINA_MESSAGE_PANEL_FLAG_SAVEPASSRORD); - remmina_connection_object_show_message_panel(cnnobj, mp); - - g_free(msg); - ret = remmina_message_panel_wait_user_answer(mp); - - /* ToDo: get save_password checkbox value from MessagePanel here (and password below) */ - save_password = FALSE; - g_clear_object(&mp); - -/* - remmina_init_dialog_set_status(dialog, tips, ssh->user, ssh->server); - - ret = remmina_init_dialog_authpwd(dialog, keyname, !disablepasswordstoring); - -*/ - - if (ret == 1) { + if (ret == GTK_RESPONSE_OK) { if (save_password) { - /* To do: get password value from mp here */ - remmina_file_set_string(remminafile, pwdtype, ""); + pwd = remmina_protocol_widget_get_password(gp); + remmina_file_set_string(remminafile, pwdtype, pwd); + g_free(pwd); } }else { return -1; } - /* To do: get password value from mp here */ - ret = remmina_ssh_auth(ssh, ""); + pwd = remmina_protocol_widget_get_password(gp); + ret = remmina_ssh_auth(ssh, pwd); + g_free(pwd); } if (ret <= 0) { diff --git a/src/remmina_ssh.h b/src/remmina_ssh.h index f46ec50d6..6faf20424 100644 --- a/src/remmina_ssh.h +++ b/src/remmina_ssh.h @@ -99,7 +99,7 @@ gboolean remmina_ssh_init_session(RemminaSSH *ssh); gint remmina_ssh_auth(RemminaSSH *ssh, const gchar *password); /* -1: Cancelled; 0: Failed; 1: Succeeded */ -gint remmina_ssh_auth_gui(RemminaSSH *ssh, RemminaConnectionObject *cnnobj, RemminaFile *remminafile); +gint remmina_ssh_auth_gui(RemminaSSH *ssh, RemminaProtocolWidget *gp, RemminaFile *remminafile); /* Error handling */ #define remmina_ssh_has_error(ssh) (((RemminaSSH*)ssh)->error != NULL) diff --git a/src/remmina_ssh_plugin.c b/src/remmina_ssh_plugin.c index 720cfd81c..9c9be86da 100644 --- a/src/remmina_ssh_plugin.c +++ b/src/remmina_ssh_plugin.c @@ -312,8 +312,7 @@ remmina_plugin_ssh_main_thread(gpointer data) break; } - ret = remmina_ssh_auth_gui(REMMINA_SSH(shell), gp->cnnobj, - remminafile); + ret = remmina_ssh_auth_gui(REMMINA_SSH(shell), gp, remminafile); if (ret == 0) { remmina_plugin_service->protocol_plugin_set_error(gp, "%s", REMMINA_SSH(shell)->error); } |