4141
4242#include <gtk/gtk.h>
4343#include <glib/gi18n.h>
44+ #include <gio/gio.h>
4445#include <vte/vte.h>
4546#include <locale.h>
4647#include <langinfo.h>
@@ -193,6 +194,7 @@ static struct {
193194typedef struct _RemminaPluginSshData
194195{
195196 RemminaSSHShell * shell ;
197+ GFile * vte_session_file ;
196198 GtkWidget * vte ;
197199
198200 const GdkRGBA * palette ;
@@ -377,22 +379,68 @@ remmina_plugin_ssh_set_vte_pref (RemminaProtocolWidget *gp)
377379}
378380
379381void
380- remmina_plugin_ssh_vte_select_all (GtkMenuItem * menuitem , gpointer user_data )
382+ remmina_plugin_ssh_vte_select_all (GtkMenuItem * menuitem , gpointer vte )
381383{
382- vte_terminal_select_all (VTE_TERMINAL (user_data ));
384+ TRACE_CALL (__func__ );
385+ vte_terminal_select_all (VTE_TERMINAL (vte ));
383386 /* TODO: we should add the vte_terminal_unselect_all as well */
384387}
385388
386389void
387- remmina_plugin_ssh_vte_copy_clipboard (GtkMenuItem * menuitem , gpointer user_data )
390+ remmina_plugin_ssh_vte_copy_clipboard (GtkMenuItem * menuitem , gpointer vte )
388391{
389- vte_terminal_copy_clipboard (VTE_TERMINAL (user_data ));
392+ TRACE_CALL (__func__ );
393+ #if VTE_CHECK_VERSION (0 ,50 ,0 )
394+ vte_terminal_copy_clipboard_format (VTE_TERMINAL (vte ), VTE_FORMAT_TEXT );
395+ #else
396+ vte_terminal_copy_clipboard (VTE_TERMINAL (vte ));
397+ #endif
398+ }
399+
400+ void
401+ remmina_plugin_ssh_vte_paste_clipboard (GtkMenuItem * menuitem , gpointer vte )
402+ {
403+ TRACE_CALL (__func__ );
404+ vte_terminal_paste_clipboard (VTE_TERMINAL (vte ));
390405}
391406
392407void
393- remmina_plugin_ssh_vte_paste_clipboard (GtkMenuItem * menuitem , gpointer user_data )
408+ remmina_plugin_ssh_vte_save_session (GtkMenuItem * menuitem , RemminaProtocolWidget * gp )
394409{
395- vte_terminal_paste_clipboard (VTE_TERMINAL (user_data ));
410+ TRACE_CALL (__func__ );
411+ RemminaPluginSshData * gpdata = GET_PLUGIN_DATA (gp );
412+
413+ GError * err = NULL ;
414+
415+ GFileOutputStream * stream = g_file_replace (gpdata -> vte_session_file , NULL , FALSE, G_FILE_CREATE_NONE , NULL , & err );
416+
417+ if (err != NULL ) {
418+ remmina_plugin_service -> protocol_plugin_set_error (gp , "%s" , err );
419+ return ;
420+ }
421+
422+ if (stream != NULL )
423+ #if VTE_CHECK_VERSION (0 ,38 ,0 )
424+ vte_terminal_write_contents_sync (VTE_TERMINAL (gpdata -> vte ), G_OUTPUT_STREAM (stream ),
425+ VTE_WRITE_DEFAULT , NULL , & err );
426+ #else
427+ vte_terminal_write_contents (VTE_TERMINAL (gpdata -> vte ), G_OUTPUT_STREAM (stream ),
428+ VTE_TERMINAL_WRITE_DEFAULT , NULL , & err );
429+ #endif
430+
431+ if (err == NULL ) {
432+ remmina_public_send_notification ("remmina-terminal-saved" ,
433+ _ ("Terminal content saved under" ),
434+ g_file_get_path (gpdata -> vte_session_file ));
435+ }
436+ else
437+ {
438+
439+ remmina_plugin_service -> protocol_plugin_set_error (gp , "%s" , err );
440+ }
441+
442+ g_free (err );
443+ g_object_unref (stream );
396444}
397445
398446/* Send a keystroke to the plugin window */
@@ -413,13 +461,8 @@ remmina_ssh_plugin_popup_menu(GtkWidget *widget, GdkEvent *event, GtkWidget *men
413461#if GTK_CHECK_VERSION (3 , 22 , 0 )
414462 gtk_menu_popup_at_pointer (GTK_MENU (menu ), NULL );
415463#else
416- gtk_menu_popup (GTK_MENU (menu ),
417- NULL ,
418- NULL ,
419- NULL ,
420- NULL ,
421- ((GdkEventButton * )event )-> button ,
422- gtk_get_current_event_time ());
464+ gtk_menu_popup (GTK_MENU (menu ), NULL , NULL , NULL , NULL ,
465+ ((GdkEventButton * )event )-> button , gtk_get_current_event_time ());
423466#endif
424467 return TRUE;
425468 }
@@ -437,20 +480,24 @@ void remmina_plugin_ssh_popup_ui(RemminaProtocolWidget *gp)
437480 GtkWidget * select_all = gtk_menu_item_new_with_label (_ ("Select All (Host+a)" ));
438481 GtkWidget * copy = gtk_menu_item_new_with_label (_ ("Copy (Host+c)" ));
439482 GtkWidget * paste = gtk_menu_item_new_with_label (_ ("Paste (Host+v)" ));
483+ GtkWidget * save = gtk_menu_item_new_with_label (_ ("Save session to file (Host+v)" ));
440484
441- gtk_menu_shell_append (GTK_MENU_SHELL (menu ), select_all );
442- gtk_menu_shell_append (GTK_MENU_SHELL (menu ), copy );
443- gtk_menu_shell_append (GTK_MENU_SHELL (menu ), paste );
485+ gtk_menu_shell_append (GTK_MENU_SHELL (menu ), select_all );
486+ gtk_menu_shell_append (GTK_MENU_SHELL (menu ), copy );
487+ gtk_menu_shell_append (GTK_MENU_SHELL (menu ), paste );
488+ gtk_menu_shell_append (GTK_MENU_SHELL (menu ), save );
444489
445490 g_signal_connect (G_OBJECT (gpdata -> vte ), "button_press_event" ,
446491 G_CALLBACK (remmina_ssh_plugin_popup_menu ), menu );
447492
448- g_signal_connect (G_OBJECT (select_all ), "activate" ,
493+ g_signal_connect (G_OBJECT (select_all ), "activate" ,
449494 G_CALLBACK (remmina_plugin_ssh_vte_select_all ), gpdata -> vte );
450- g_signal_connect (G_OBJECT (copy ), "activate" ,
495+ g_signal_connect (G_OBJECT (copy ), "activate" ,
451496 G_CALLBACK (remmina_plugin_ssh_vte_copy_clipboard ), gpdata -> vte );
452- g_signal_connect (G_OBJECT (paste ), "activate" ,
497+ g_signal_connect (G_OBJECT (paste ), "activate" ,
453498 G_CALLBACK (remmina_plugin_ssh_vte_paste_clipboard ), gpdata -> vte );
499+ g_signal_connect (G_OBJECT (save ), "activate" ,
500+ G_CALLBACK (remmina_plugin_ssh_vte_save_session ), gp );
454501
455502 gtk_widget_show_all (menu );
456503}
@@ -557,8 +604,9 @@ remmina_plugin_ssh_init (RemminaProtocolWidget *gp)
557604 gdk_rgba_parse (& cp [15 ], remmina_pref .color15 );
558605
559606 const GdkRGBA custom_palette [PALETTE_SIZE ] = {
560- cp [0 ] , cp [1 ] , cp [2 ] , cp [3 ] , cp [4 ] , cp [5 ] ,
561- cp [6 ] , cp [7 ] , cp [8 ] , cp [9 ] , cp [10 ], cp [11 ],
607+ cp [0 ], cp [1 ], cp [2 ], cp [3 ],
608+ cp [4 ], cp [5 ], cp [6 ], cp [7 ],
609+ cp [8 ], cp [9 ], cp [10 ], cp [11 ],
562610 cp [12 ], cp [13 ], cp [14 ], cp [15 ] };
563611
564612 remminavte .palette = custom_palette ;
@@ -603,6 +651,34 @@ remmina_plugin_ssh_init (RemminaProtocolWidget *gp)
603651 gtk_widget_show (vscrollbar );
604652 gtk_box_pack_start (GTK_BOX (hbox ), vscrollbar , FALSE, TRUE, 0 );
605653
654+ const gchar * dir ;
655+ const gchar * sshlogname ;
656+ const gchar * fp ;
657+ GFile * rf ;
658+
659+ rf = g_file_new_for_path (remminafile -> filename );
660+
661+ if (remmina_plugin_service -> file_get_string (remminafile , "sshlogfolder" ) == NULL )
662+ {
663+ dir = g_build_path ( "/" , g_get_user_cache_dir (), g_get_prgname (), NULL );
664+ }
665+ else
666+ {
667+ dir = remmina_plugin_service -> file_get_string (remminafile , "sshlogfolder" );
668+ }
669+
670+ if (remmina_plugin_service -> file_get_string (remminafile , "sshlogname" ) == NULL )
671+ {
672+ sshlogname = g_strconcat (g_file_get_basename (rf ), "." , "log" , NULL );
673+ }
674+ else
675+ {
676+ sshlogname = remmina_plugin_service -> file_get_string (remminafile , "sshlogname" );
677+ }
678+
679+ fp = g_strconcat (dir , "/" , sshlogname , NULL );
680+ gpdata -> vte_session_file = g_file_new_for_path (fp );
681+
606682 remmina_plugin_ssh_popup_ui (gp );
607683}
608684
@@ -636,6 +712,14 @@ remmina_plugin_ssh_close_connection (RemminaProtocolWidget *gp)
636712 TRACE_CALL ("remmina_plugin_ssh_close_connection" );
637713 RemminaPluginSshData * gpdata = GET_PLUGIN_DATA (gp );
638714
715+ RemminaFile * remminafile ;
716+
717+ remminafile = remmina_plugin_service -> protocol_plugin_get_file (gp );
718+
719+ if (remmina_file_get_int (remminafile , "sshlogenabled" , FALSE))
720+ {
721+ remmina_plugin_ssh_vte_save_session (NULL , gp );
722+ }
639723 if (gpdata -> thread )
640724 {
641725 pthread_cancel (gpdata -> thread );
@@ -677,7 +761,11 @@ remmina_plugin_ssh_call_feature (RemminaProtocolWidget *gp, const RemminaProtoco
677761 NULL , gpdata -> shell , NULL );
678762 return ;
679763 case REMMINA_PLUGIN_SSH_FEATURE_TOOL_COPY :
680- vte_terminal_copy_clipboard (VTE_TERMINAL (gpdata -> vte ));
764+ #if VTE_CHECK_VERSION (0 ,50 ,0 )
765+ vte_terminal_copy_clipboard_format (VTE_TERMINAL (gpdata -> vte ), VTE_FORMAT_TEXT );
766+ #else
767+ vte_terminal_copy_clipboard (VTE_TERMINAL (gpdata -> vte ));
768+ #endif
681769 return ;
682770 case REMMINA_PLUGIN_SSH_FEATURE_TOOL_PASTE :
683771 vte_terminal_paste_clipboard (VTE_TERMINAL (gpdata -> vte ));
@@ -809,6 +897,9 @@ static const RemminaProtocolSetting remmina_ssh_advanced_settings[] =
809897 { REMMINA_PROTOCOL_SETTING_TYPE_SELECT , "ssh_color_scheme" , N_ ("Terminal color scheme" ), FALSE, ssh_terminal_palette , NULL },
810898 { REMMINA_PROTOCOL_SETTING_TYPE_TEXT , "exec" , N_ ("Startup program" ), FALSE, NULL , NULL },
811899 { REMMINA_PROTOCOL_SETTING_TYPE_CHECK , "disablepasswordstoring" , N_ ("Disable password storing" ), FALSE, NULL , NULL },
900+ { REMMINA_PROTOCOL_SETTING_TYPE_CHECK , "sshlogenabled" , N_ ("Enable SSH session logging at exit" ), FALSE, NULL , NULL },
901+ { REMMINA_PROTOCOL_SETTING_TYPE_FOLDER , "sshlogfolder" , N_ ("SSH session log folder" ), FALSE, NULL , NULL },
902+ { REMMINA_PROTOCOL_SETTING_TYPE_TEXT , "sshlogname" , N_ ("SSH session log file name" ), FALSE, NULL , NULL },
812903 { REMMINA_PROTOCOL_SETTING_TYPE_END , NULL , NULL , FALSE, NULL , NULL }
813904};
814905
@@ -841,6 +932,7 @@ remmina_ssh_plugin_register (void)
841932 remmina_plugin_ssh_features [0 ].opt3 = GUINT_TO_POINTER (remmina_pref .vte_shortcutkey_copy );
842933 remmina_plugin_ssh_features [1 ].opt3 = GUINT_TO_POINTER (remmina_pref .vte_shortcutkey_paste );
843934 remmina_plugin_ssh_features [2 ].opt3 = GUINT_TO_POINTER (remmina_pref .vte_shortcutkey_select_all );
935+ remmina_plugin_ssh_features [3 ].opt3 = GUINT_TO_POINTER (remmina_pref .vte_shortcutkey_select_all );
844936
845937 remmina_plugin_service = & remmina_plugin_manager_service ;
846938 remmina_plugin_service -> register_plugin ((RemminaPlugin * ) & remmina_plugin_ssh );
0 commit comments