1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2011 Marc-Andre Moreau
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA  02110-1301, USA.
19  *
20  *  In addition, as a special exception, the copyright holders give
21  *  permission to link the code of portions of this program with the
22  *  OpenSSL library under certain conditions as described in each
23  *  individual source file, and distribute linked combinations
24  *  including the two.
25  *  You must obey the GNU General Public License in all respects
26  *  for all of the code used other than OpenSSL. *  If you modify
27  *  file(s) with this exception, you may extend this exception to your
28  *  version of the file(s), but you are not obligated to do so. *  If you
29  *  do not wish to do so, delete this exception statement from your
30  *  version. *  If you delete this exception statement from all source
31  *  files in the program, then also delete it here.
32  *
33  */
34 
35 #include <gtk/gtk.h>
36 #include <glib/gi18n.h>
37 #include <glib/gstdio.h>
38 #include <stdlib.h>
39 #include "remmina/types.h"
40 #include "remmina_public.h"
41 #include "remmina_external_tools.h"
42 #include "remmina/remmina_trace_calls.h"
43 
44 static gboolean remmina_external_tools_launcher(const gchar* filename, const gchar* scriptname, const gchar* shortname);
45 
view_popup_menu_onDoSomething(GtkWidget * menuitem,gpointer userdata)46 static void view_popup_menu_onDoSomething(GtkWidget *menuitem, gpointer userdata)
47 {
48 	TRACE_CALL(__func__);
49 	gchar *remminafilename = g_object_get_data(G_OBJECT(menuitem), "remminafilename");
50 	gchar *scriptfilename = g_object_get_data(G_OBJECT(menuitem), "scriptfilename");
51 	gchar *scriptshortname = g_object_get_data(G_OBJECT(menuitem), "scriptshortname");
52 
53 	remmina_external_tools_launcher(remminafilename, scriptfilename, scriptshortname);
54 }
55 
remmina_external_tools_from_filename(RemminaMain * remminamain,gchar * remminafilename)56 gboolean remmina_external_tools_from_filename(RemminaMain *remminamain, gchar* remminafilename)
57 {
58 	TRACE_CALL(__func__);
59 	GtkWidget *menu, *menuitem;
60 	gchar dirname[MAX_PATH_LEN];
61 	gchar filename[MAX_PATH_LEN];
62 	GDir* dir;
63 	const gchar* name;
64 
65 	strcpy(dirname, REMMINA_RUNTIME_EXTERNAL_TOOLS_DIR);
66 	dir = g_dir_open(dirname, 0, NULL);
67 
68 	if (dir == NULL)
69 		return FALSE;
70 
71 	menu = gtk_menu_new();
72 
73 	while ((name = g_dir_read_name(dir)) != NULL) {
74 		if (!g_str_has_prefix(name, "remmina_"))
75 			continue;
76 		g_snprintf(filename, MAX_PATH_LEN, "%s/%s", dirname, name);
77 
78 		menuitem = gtk_menu_item_new_with_label(name + 8);
79 		g_object_set_data_full(G_OBJECT(menuitem), "remminafilename", g_strdup(remminafilename), g_free);
80 		g_object_set_data_full(G_OBJECT(menuitem), "scriptfilename", g_strdup(filename), g_free);
81 		g_object_set_data_full(G_OBJECT(menuitem), "scriptshortname", g_strdup(name), g_free);
82 		g_signal_connect(menuitem, "activate", (GCallback)view_popup_menu_onDoSomething, NULL);
83 		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
84 	}
85 	g_dir_close(dir);
86 
87 	gtk_widget_show_all(menu);
88 
89 	/* Note: event can be NULL here when called from view_onPopupMenu;
90 	 *  gdk_event_get_time() accepts a NULL argument
91 	 */
92 #if GTK_CHECK_VERSION(3, 22, 0)
93 	gtk_menu_popup_at_pointer(GTK_MENU(menu), NULL);
94 #else
95 	gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, 0);
96 #endif
97 
98 	return TRUE;
99 }
100 
remmina_external_tools_launcher(const gchar * filename,const gchar * scriptname,const gchar * shortname)101 static gboolean remmina_external_tools_launcher(const gchar* filename, const gchar* scriptname, const gchar* shortname)
102 {
103 	TRACE_CALL(__func__);
104 	RemminaFile *remminafile;
105 	const char *env_format = "%s=%s";
106 	char *env;
107 	size_t envstrlen;
108 	gchar launcher[MAX_PATH_LEN];
109 
110 	g_snprintf(launcher, MAX_PATH_LEN, "%s/launcher.sh", REMMINA_RUNTIME_EXTERNAL_TOOLS_DIR);
111 
112 	remminafile = remmina_file_load(filename);
113 	if (!remminafile)
114 		return FALSE;
115 	GHashTableIter iter;
116 	const gchar *key, *value;
117 	g_hash_table_iter_init(&iter, remminafile->settings);
118 	while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&value)) {
119 		envstrlen = strlen(key) + strlen(value) + strlen(env_format) + 1;
120 		env = (char*)malloc(envstrlen);
121 		if (env == NULL) {
122 			return -1;
123 		}
124 
125 		int retval = snprintf(env, envstrlen, env_format, key, value);
126 		if (retval > 0 && (size_t)retval <= envstrlen) {
127 			if (putenv(env) != 0) {
128 				/* If putenv fails, we must free the unused space */
129 				free(env);
130 			}
131 		}
132 	}
133 	/* Adds the window title for the terminal window */
134 	const char *term_title_key = "remmina_term_title";
135 	const char *term_title_val_prefix = "Remmina external tool";
136 	envstrlen = strlen(term_title_key) + strlen(term_title_val_prefix) + strlen(shortname) + 7;
137 	env = (char*)malloc(envstrlen);
138 	if (env != NULL) {
139 		if (snprintf(env, envstrlen, "%s=%s: %s", term_title_key, term_title_val_prefix, shortname) ) {
140 			if (putenv(env) != 0) {
141 				/* If putenv fails, we must free the unused space */
142 				free(env);
143 			}
144 		}
145 	}
146 
147 	const size_t cmdlen = strlen(launcher) + strlen(scriptname) + 2;
148 	gchar *cmd = (gchar*)malloc(cmdlen);
149 	g_snprintf(cmd, cmdlen, "%s %s", launcher, scriptname);
150 	system(cmd);
151 	free(cmd);
152 
153 	remmina_file_free(remminafile);
154 
155 	return TRUE;
156 }
157