Remmina - The GTK+ Remote Desktop Client  v1.4.2
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.
rdp_file.c
Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2010-2011 Vic Lee
4  * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
5  * Copyright (C) 2016-2020 Antenore Gatta, Giovanni Panozzo
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  * In addition, as a special exception, the copyright holders give
23  * permission to link the code of portions of this program with the
24  * OpenSSL library under certain conditions as described in each
25  * individual source file, and distribute linked combinations
26  * including the two.
27  * You must obey the GNU General Public License in all respects
28  * for all of the code used other than OpenSSL. * If you modify
29  * file(s) with this exception, you may extend this exception to your
30  * version of the file(s), but you are not obligated to do so. * If you
31  * do not wish to do so, delete this exception statement from your
32  * version. * If you delete this exception statement from all source
33  * files in the program, then also delete it here.
34  *
35  */
36 
37 #include "common/remmina_plugin.h"
38 #include "rdp_plugin.h"
39 #include "rdp_file.h"
40 
41 gboolean remmina_rdp_file_import_test(const gchar* from_file)
42 {
43  TRACE_CALL(__func__);
44  gchar* ext;
45 
46  ext = strrchr(from_file, '.');
47 
48  if (!ext)
49  return FALSE;
50 
51  ext++;
52 
53  if (g_strcmp0(ext, "RDP") == 0)
54  return TRUE;
55 
56  if (g_strcmp0(ext, "rdp") == 0)
57  return TRUE;
58 
59  return FALSE;
60 }
61 
62 static void remmina_rdp_file_import_field(RemminaFile* remminafile, const gchar* key, const gchar* value)
63 {
64  TRACE_CALL(__func__);
65  if (g_strcmp0(key, "desktopwidth") == 0) {
66  remmina_plugin_service->file_set_string(remminafile, "resolution_width", value);
67  }else if (g_strcmp0(key, "desktopheight") == 0) {
68  remmina_plugin_service->file_set_string(remminafile, "resolution_height", value);
69  }else if (g_strcmp0(key, "session bpp") == 0) {
70  remmina_plugin_service->file_set_string(remminafile, "colordepth", value);
71  }else if (g_strcmp0(key, "keyboardhook") == 0) {
72  remmina_plugin_service->file_set_int(remminafile, "keyboard_grab", (atoi(value) == 1));
73  }else if (g_strcmp0(key, "full address") == 0) {
74  remmina_plugin_service->file_set_string(remminafile, "server", value);
75  }else if (g_strcmp0(key, "audiomode") == 0) {
76  switch (atoi(value)) {
77  case 0:
78  remmina_plugin_service->file_set_string(remminafile, "sound", "local");
79  break;
80  case 1:
81  remmina_plugin_service->file_set_string(remminafile, "sound", "remote");
82  break;
83  }
84  }else if (g_strcmp0(key, "microphone") == 0) {
85  remmina_plugin_service->file_set_int(remminafile, "microphone", (atoi(value) == 1));
86  }else if (g_strcmp0(key, "redirectprinters") == 0) {
87  remmina_plugin_service->file_set_int(remminafile, "shareprinter", (atoi(value) == 1));
88  }else if (g_strcmp0(key, "redirectsmartcard") == 0) {
89  remmina_plugin_service->file_set_int(remminafile, "sharesmartcard", (atoi(value) == 1));
90  }else if (g_strcmp0(key, "redirectclipboard") == 0) {
91  remmina_plugin_service->file_set_int(remminafile, "disableclipboard", (atoi(value) != 1));
92  }else if (g_strcmp0(key, "alternate shell") == 0) {
93  remmina_plugin_service->file_set_string(remminafile, "exec", value);
94  }else if (g_strcmp0(key, "shell working directory") == 0) {
95  remmina_plugin_service->file_set_string(remminafile, "execpath", value);
96  }else if (g_strcmp0(key, "loadbalanceinfo") == 0) {
97  remmina_plugin_service->file_set_string(remminafile, "loadbalanceinfo", value);
98  }else if (g_strcmp0(key, "gatewayhostname") == 0) {
99  remmina_plugin_service->file_set_string(remminafile, "gateway_server", value);
100  }else if (g_strcmp0(key, "gatewayusagemethod") == 0) {
101  remmina_plugin_service->file_set_int(remminafile, "gateway_usage", (atoi(value) == TSC_PROXY_MODE_DETECT));
102  } else if (g_strcmp0(key, "gatewayaccesstoken") == 0) {
103  remmina_plugin_service->file_set_string(remminafile, "gatewayaccesstoken", value);
104  } else if (g_strcmp0(key, "authentication level") == 0) {
105  remmina_plugin_service->file_set_int(remminafile, "authentication level", atoi(value));
106  }
107  /* tsclient fields, import only */
108  else if (g_strcmp0(key, "client hostname") == 0) {
109  remmina_plugin_service->file_set_string(remminafile, "clientname", value);
110  }else if (g_strcmp0(key, "domain") == 0) {
111  remmina_plugin_service->file_set_string(remminafile, "domain", value);
112  }else if (g_strcmp0(key, "username") == 0) {
113  remmina_plugin_service->file_set_string(remminafile, "username", value);
114  }else if (g_strcmp0(key, "password") == 0) {
115  remmina_plugin_service->file_set_string(remminafile, "password", value);
116  }
117 }
118 
119 static RemminaFile* remmina_rdp_file_import_channel(GIOChannel* channel)
120 {
121  TRACE_CALL(__func__);
122  gchar* p;
123  const gchar* enc;
124  gchar* line = NULL;
125  GError* error = NULL;
126  gsize bytes_read = 0;
127  RemminaFile* remminafile;
128  guchar magic[2] = { 0 };
129 
130  if (g_io_channel_set_encoding(channel, NULL, &error) != G_IO_STATUS_NORMAL) {
131  g_print("g_io_channel_set_encoding: %s\n", error->message);
132  return NULL;
133  }
134 
135  /* Try to detect the UTF-16 encoding */
136  if (g_io_channel_read_chars(channel, (gchar*)magic, 2, &bytes_read, &error) != G_IO_STATUS_NORMAL) {
137  g_print("g_io_channel_read_chars: %s\n", error->message);
138  return NULL;
139  }
140 
141  if (magic[0] == 0xFF && magic[1] == 0xFE) {
142  enc = "UTF-16LE";
143  }else if (magic[0] == 0xFE && magic[1] == 0xFF) {
144  enc = "UTF-16BE";
145  }else {
146  enc = "UTF-8";
147  if (g_io_channel_seek_position(channel, 0, G_SEEK_SET, &error) != G_IO_STATUS_NORMAL) {
148  g_print("g_io_channel_seek: failed\n");
149  return NULL;
150  }
151  }
152 
153  if (g_io_channel_set_encoding(channel, enc, &error) != G_IO_STATUS_NORMAL) {
154  g_print("g_io_channel_set_encoding: %s\n", error->message);
155  return NULL;
156  }
157 
158  remminafile = remmina_plugin_service->file_new();
159 
160  while (g_io_channel_read_line(channel, &line, NULL, &bytes_read, &error) == G_IO_STATUS_NORMAL) {
161  if (line == NULL)
162  break;
163 
164  line[bytes_read] = '\0';
165  p = strchr(line, ':');
166 
167  if (p) {
168  *p++ = '\0';
169  p = strchr(p, ':');
170 
171  if (p) {
172  p++;
173  remmina_rdp_file_import_field(remminafile, line, p);
174  }
175  }
176 
177  g_free(line);
178  }
179 
180  remmina_plugin_service->file_set_string(remminafile, "name",
181  remmina_plugin_service->file_get_string(remminafile, "server"));
182  remmina_plugin_service->file_set_string(remminafile, "protocol", "RDP");
183 
184  return remminafile;
185 }
186 
187 RemminaFile* remmina_rdp_file_import(const gchar* from_file)
188 {
189  TRACE_CALL(__func__);
190  GIOChannel* channel;
191  GError* error = NULL;
192  RemminaFile* remminafile;
193 
194  channel = g_io_channel_new_file(from_file, "r", &error);
195 
196  if (channel == NULL) {
197  g_print("Failed to import %s: %s\n", from_file, error->message);
198  return NULL;
199  }
200 
201  remminafile = remmina_rdp_file_import_channel(channel);
202  g_io_channel_shutdown(channel, TRUE, &error);
203 
204  return remminafile;
205 }
206 
208 {
209  TRACE_CALL(__func__);
210  if (g_strcmp0(remmina_plugin_service->file_get_string(remminafile, "protocol"), "RDP") == 0)
211  return TRUE;
212 
213  return FALSE;
214 }
215 
216 gboolean remmina_rdp_file_export_channel(RemminaFile* remminafile, FILE* fp)
217 {
218  TRACE_CALL(__func__);
219  const gchar* cs;
220  int w, h;
221 
222  fprintf(fp, "screen mode id:i:2\r\n");
223  w = remmina_plugin_service->file_get_int(remminafile, "resolution_width", -1);
224  h = remmina_plugin_service->file_get_int(remminafile, "resolution_height", -1);
225  if ( w > 0 && h > 0 ) {
226  fprintf(fp, "desktopwidth:i:%d\r\n", w);
227  fprintf(fp, "desktopheight:i:%d\r\n", h);
228  }
229 
230  fprintf(fp, "session bpp:i:%i\r\n", remmina_plugin_service->file_get_int(remminafile, "colordepth", 8));
231  //fprintf(fp, "winposstr:s:0,1,123,34,931,661\r\n");
232  fprintf(fp, "compression:i:1\r\n");
233  fprintf(fp, "keyboardhook:i:2\r\n");
234  fprintf(fp, "displayconnectionbar:i:1\r\n");
235  fprintf(fp, "disable wallpaper:i:1\r\n");
236  fprintf(fp, "disable full window drag:i:1\r\n");
237  fprintf(fp, "allow desktop composition:i:0\r\n");
238  fprintf(fp, "allow font smoothing:i:0\r\n");
239  fprintf(fp, "disable menu anims:i:1\r\n");
240  fprintf(fp, "disable themes:i:0\r\n");
241  fprintf(fp, "disable cursor setting:i:0\r\n");
242  fprintf(fp, "bitmapcachepersistenable:i:1\r\n");
243  cs = remmina_plugin_service->file_get_string(remminafile, "server");
244  fprintf(fp, "full address:s:%s\r\n", cs ? cs : "" );
245  if (g_strcmp0(remmina_plugin_service->file_get_string(remminafile, "sound"), "local") == 0)
246  fprintf(fp, "audiomode:i:0\r\n");
247  else if (g_strcmp0(remmina_plugin_service->file_get_string(remminafile, "sound"), "remote") == 0)
248  fprintf(fp, "audiomode:i:1\r\n");
249  else
250  fprintf(fp, "audiomode:i:2\r\n");
251  fprintf(fp, "microphone:i:%i\r\n", remmina_plugin_service->file_get_int(remminafile, "microphone", FALSE) ? 1 : 0);
252  fprintf(fp, "redirectprinters:i:%i\r\n", remmina_plugin_service->file_get_int(remminafile, "shareprinter", FALSE) ? 1 : 0);
253  fprintf(fp, "redirectsmartcard:i:%i\r\n", remmina_plugin_service->file_get_int(remminafile, "sharesmartcard", FALSE) ? 1 : 0);
254  fprintf(fp, "redirectcomports:i:0\r\n");
255  fprintf(fp, "redirectsmartcards:i:0\r\n");
256  fprintf(fp, "redirectclipboard:i:1\r\n");
257  fprintf(fp, "redirectposdevices:i:0\r\n");
258  fprintf(fp, "autoreconnection enabled:i:1\r\n");
259  fprintf(fp, "authentication level:i:0\r\n");
260  fprintf(fp, "prompt for credentials:i:1\r\n");
261  fprintf(fp, "negotiate security layer:i:1\r\n");
262  fprintf(fp, "remoteapplicationmode:i:0\r\n");
263  cs = remmina_plugin_service->file_get_string(remminafile, "exec");
264  fprintf(fp, "alternate shell:s:%s\r\n", cs ? cs : "");
265  cs = remmina_plugin_service->file_get_string(remminafile, "execpath");
266  fprintf(fp, "shell working directory:s:%s\r\n", cs ? cs : "");
267  fprintf(fp, "gatewayhostname:s:\r\n");
268  fprintf(fp, "gatewayusagemethod:i:4\r\n");
269  fprintf(fp, "gatewaycredentialssource:i:4\r\n");
270  fprintf(fp, "gatewayprofileusagemethod:i:0\r\n");
271  fprintf(fp, "precommand:s:\r\n");
272  fprintf(fp, "promptcredentialonce:i:1\r\n");
273  fprintf(fp, "drivestoredirect:s:\r\n");
274 
275  return TRUE;
276 }
277 
278 gboolean remmina_rdp_file_export(RemminaFile* remminafile, const gchar* to_file)
279 {
280  TRACE_CALL(__func__);
281  FILE* fp;
282  gchar* p;
283  gboolean ret;
284 
285  p = strrchr(to_file, '.');
286 
287  if (p && (g_strcmp0(p + 1, "rdp") == 0 || g_strcmp0(p + 1, "RDP") == 0)) {
288  p = g_strdup(to_file);
289  }else {
290  p = g_strdup_printf("%s.rdp", to_file);
291  }
292 
293  fp = g_fopen(p, "w+");
294 
295  if (fp == NULL) {
296  g_print("Failed to export %s\n", p);
297  g_free(p);
298  return FALSE;
299  }
300 
301  g_free(p);
302  ret = remmina_rdp_file_export_channel(remminafile, fp);
303  fclose(fp);
304 
305  return ret;
306 }
307 
gboolean remmina_rdp_file_export_channel(RemminaFile *remminafile, FILE *fp)
Definition: rdp_file.c:216
void(* file_set_int)(RemminaFile *remminafile, const gchar *setting, gint value)
Definition: plugin.h:202
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
Definition: types.h:41
static RemminaFile * remmina_rdp_file_import_channel(GIOChannel *channel)
Definition: rdp_file.c:119
gboolean remmina_rdp_file_export(RemminaFile *remminafile, const gchar *to_file)
Definition: rdp_file.c:278
gint(* file_get_int)(RemminaFile *remminafile, const gchar *setting, gint default_value)
Definition: plugin.h:203
gboolean remmina_rdp_file_export_test(RemminaFile *remminafile)
Definition: rdp_file.c:207
RemminaFile * remmina_rdp_file_import(const gchar *from_file)
Definition: rdp_file.c:187
static RemminaPluginService * remmina_plugin_service
static void remmina_rdp_file_import_field(RemminaFile *remminafile, const gchar *key, const gchar *value)
Definition: rdp_file.c:62
gboolean remmina_rdp_file_import_test(const gchar *from_file)
Definition: rdp_file.c:41
void(* file_set_string)(RemminaFile *remminafile, const gchar *setting, const gchar *value)
Definition: plugin.h:199
const gchar *(* file_get_string)(RemminaFile *remminafile, const gchar *setting)
Definition: plugin.h:200
RemminaFile *(* file_new)(void)
Definition: plugin.h:197