Remmina - The GTK+ Remote Desktop Client  v1.4.34
Remmina is a remote desktop client written in GTK+, aiming to be useful for system administrators and travellers, who need to work with lots of remote computers in front of either large monitors or tiny netbooks. Remmina supports multiple network protocols in an integrated and consistent user interface. Currently RDP, VNC, NX, XDMCP and SSH are supported.
remmina_external_tools.c
Go to the documentation of this file.
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_file.h"
40 #include "remmina/types.h"
41 #include "remmina_public.h"
42 #include "remmina_external_tools.h"
44 
45 static gboolean remmina_external_tools_launcher(const gchar* filename, const gchar* scriptname, const gchar* shortname);
46 
47 static void view_popup_menu_onDoSomething(GtkWidget *menuitem, gpointer userdata)
48 {
49  TRACE_CALL(__func__);
50  gchar *remminafilename = g_object_get_data(G_OBJECT(menuitem), "remminafilename");
51  gchar *scriptfilename = g_object_get_data(G_OBJECT(menuitem), "scriptfilename");
52  gchar *scriptshortname = g_object_get_data(G_OBJECT(menuitem), "scriptshortname");
53 
54  remmina_external_tools_launcher(remminafilename, scriptfilename, scriptshortname);
55 }
56 
58 {
59  TRACE_CALL(__func__);
60  GtkWidget *menu, *menuitem;
61  gchar dirname[MAX_PATH_LEN];
62  gchar filename[MAX_PATH_LEN];
63  GDir* dir;
64  const gchar* name;
65 
66  strcpy(dirname, REMMINA_RUNTIME_EXTERNAL_TOOLS_DIR);
67  dir = g_dir_open(dirname, 0, NULL);
68 
69  if (dir == NULL)
70  return FALSE;
71 
72  menu = gtk_menu_new();
73 
74  while ((name = g_dir_read_name(dir)) != NULL) {
75  if (!g_str_has_prefix(name, "remmina_"))
76  continue;
77  g_snprintf(filename, MAX_PATH_LEN, "%s/%s", dirname, name);
78 
79  menuitem = gtk_menu_item_new_with_label(name + 8);
80  g_object_set_data_full(G_OBJECT(menuitem), "remminafilename", g_strdup(remminafilename), g_free);
81  g_object_set_data_full(G_OBJECT(menuitem), "scriptfilename", g_strdup(filename), g_free);
82  g_object_set_data_full(G_OBJECT(menuitem), "scriptshortname", g_strdup(name), g_free);
83  g_signal_connect(menuitem, "activate", (GCallback)view_popup_menu_onDoSomething, NULL);
84  gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
85  }
86  g_dir_close(dir);
87 
88  gtk_widget_show_all(menu);
89 
90  /* Note: event can be NULL here when called from view_onPopupMenu;
91  * gdk_event_get_time() accepts a NULL argument
92  */
93 #if GTK_CHECK_VERSION(3, 22, 0)
94  gtk_menu_popup_at_pointer(GTK_MENU(menu), NULL);
95 #else
96  gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, 0);
97 #endif
98 
99  return TRUE;
100 }
101 
102 static gboolean remmina_external_tools_launcher(const gchar* filename, const gchar* scriptname, const gchar* shortname)
103 {
104  TRACE_CALL(__func__);
105  RemminaFile *remminafile;
106  const char *env_format = "%s=%s";
107  char *env;
108  size_t envstrlen;
109  gchar launcher[MAX_PATH_LEN];
110 
111  g_snprintf(launcher, MAX_PATH_LEN, "%s/launcher.sh", REMMINA_RUNTIME_EXTERNAL_TOOLS_DIR);
112 
113  remminafile = remmina_file_load(filename);
114  if (!remminafile)
115  return FALSE;
116  GHashTableIter iter;
117  const gchar *key, *value;
118  g_hash_table_iter_init(&iter, remminafile->settings);
119  while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&value)) {
120  envstrlen = strlen(key) + strlen(value) + strlen(env_format) + 1;
121  env = (char*)malloc(envstrlen);
122  if (env == NULL) {
123  return -1;
124  }
125 
126  int retval = snprintf(env, envstrlen, env_format, key, value);
127  if (retval > 0 && (size_t)retval <= envstrlen) {
128  if (putenv(env) != 0) {
129  /* If putenv fails, we must free the unused space */
130  free(env);
131  }
132  }
133  }
134  /* Adds the window title for the terminal window */
135  const char *term_title_key = "remmina_term_title";
136  const char *term_title_val_prefix = "Remmina external tool";
137  envstrlen = strlen(term_title_key) + strlen(term_title_val_prefix) + strlen(shortname) + 7;
138  env = (char*)malloc(envstrlen);
139  if (env != NULL) {
140  if (snprintf(env, envstrlen, "%s=%s: %s", term_title_key, term_title_val_prefix, shortname) ) {
141  if (putenv(env) != 0) {
142  /* If putenv fails, we must free the unused space */
143  free(env);
144  }
145  }
146  }
147 
148  const size_t cmdlen = strlen(launcher) + strlen(scriptname) + 2;
149  gchar *cmd = (gchar*)malloc(cmdlen);
150  g_snprintf(cmd, cmdlen, "%s %s", launcher, scriptname);
151  system(cmd);
152  free(cmd);
153 
154  remmina_file_free(remminafile);
155 
156  return TRUE;
157 }
gboolean remmina_external_tools_from_filename(RemminaMain *remminamain, gchar *remminafilename)
static gboolean remmina_external_tools_launcher(const gchar *filename, const gchar *scriptname, const gchar *shortname)
static void view_popup_menu_onDoSomething(GtkWidget *menuitem, gpointer userdata)
void remmina_file_free(RemminaFile *remminafile)
Definition: remmina_file.c:710
RemminaFile * remmina_file_load(const gchar *filename)
Definition: remmina_file.c:351
static RemminaMain * remminamain
Definition: remmina_main.c:71
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
Definition: types.h:44