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