~vanvugt/+junk/remmina-ppa

« back to all changes in this revision

Viewing changes to src/remminaprotocolwidget.c

  • Committer: Bazaar Package Importer
  • Author(s): Luca Falavigna
  • Date: 2010-07-11 23:40:47 UTC
  • mfrom: (1.2.1 upstream) (8.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20100711234047-id2bdu1gb59e34n4
* New upstream release.
* debian/control:
  - Bump Standards-Version to 3.9.0, no changes required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Remmina - The GTK+ Remote Desktop Client
 
3
 * Copyright (C) 2009-2010 Vic Lee 
 
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., 59 Temple Place, Suite 330, 
 
18
 * Boston, MA 02111-1307, USA.
 
19
 */
 
20
 
 
21
#include <gtk/gtk.h>
 
22
#include <glib/gi18n.h>
 
23
#include <stdlib.h>
 
24
#include "config.h"
 
25
#include "remminapublic.h"
 
26
#include "remminapref.h"
 
27
#include "remminassh.h"
 
28
#include "remminachatwindow.h"
 
29
#include "remminapluginmanager.h"
 
30
#include "remminaconnectionwindow.h"
 
31
#include "remminaprotocolwidget.h"
 
32
 
 
33
struct _RemminaProtocolWidgetPriv
 
34
{
 
35
    GtkWidget *init_dialog;
 
36
 
 
37
    RemminaFile *remmina_file;
 
38
    RemminaProtocolPlugin *plugin;
 
39
 
 
40
    gint width;
 
41
    gint height;
 
42
    gboolean scale;
 
43
    gboolean expand;
 
44
 
 
45
    gboolean has_error;
 
46
    gchar *error_message;
 
47
    RemminaSSHTunnel *ssh_tunnel;
 
48
    RemminaTunnelInitFunc init_func;
 
49
 
 
50
    GtkWidget *chat_window;
 
51
 
 
52
    gboolean closed;
 
53
 
 
54
    RemminaHostkeyFunc hostkey_func;
 
55
    gpointer hostkey_func_data;
 
56
};
 
57
 
 
58
G_DEFINE_TYPE (RemminaProtocolWidget, remmina_protocol_widget, GTK_TYPE_EVENT_BOX)
 
59
 
 
60
enum {
 
61
    CONNECT_SIGNAL,
 
62
    DISCONNECT_SIGNAL,
 
63
    DESKTOP_RESIZE_SIGNAL,
 
64
    LAST_SIGNAL
 
65
};
 
66
 
 
67
typedef struct _RemminaProtocolWidgetSignalData
 
68
{
 
69
    RemminaProtocolWidget *gp;
 
70
    const gchar *signal_name;
 
71
} RemminaProtocolWidgetSignalData;
 
72
 
 
73
static guint remmina_protocol_widget_signals[LAST_SIGNAL] = { 0 };
 
74
 
 
75
static void
 
76
remmina_protocol_widget_class_init (RemminaProtocolWidgetClass *klass)
 
77
{
 
78
    remmina_protocol_widget_signals[CONNECT_SIGNAL] =
 
79
        g_signal_new ("connect",
 
80
            G_TYPE_FROM_CLASS (klass),
 
81
            G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
 
82
            G_STRUCT_OFFSET (RemminaProtocolWidgetClass, connect),
 
83
            NULL, NULL,
 
84
            g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
 
85
    remmina_protocol_widget_signals[DISCONNECT_SIGNAL] =
 
86
        g_signal_new ("disconnect",
 
87
            G_TYPE_FROM_CLASS (klass),
 
88
            G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
 
89
            G_STRUCT_OFFSET (RemminaProtocolWidgetClass, disconnect),
 
90
            NULL, NULL,
 
91
            g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
 
92
    remmina_protocol_widget_signals[DESKTOP_RESIZE_SIGNAL] =
 
93
        g_signal_new ("desktop-resize",
 
94
            G_TYPE_FROM_CLASS (klass),
 
95
            G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
 
96
            G_STRUCT_OFFSET (RemminaProtocolWidgetClass, desktop_resize),
 
97
            NULL, NULL,
 
98
            g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
 
99
}
 
100
 
 
101
static void
 
102
remmina_protocol_widget_init_cancel (RemminaInitDialog *dialog, gint response_id, RemminaProtocolWidget *gp)
 
103
{
 
104
    if ((response_id == GTK_RESPONSE_CANCEL || response_id == GTK_RESPONSE_DELETE_EVENT)
 
105
        && dialog->mode == REMMINA_INIT_MODE_CONNECTING)
 
106
    {
 
107
        remmina_protocol_widget_close_connection (gp);
 
108
    }
 
109
}
 
110
 
 
111
static void
 
112
remmina_protocol_widget_show_init_dialog (RemminaProtocolWidget *gp, const gchar *name)
 
113
{
 
114
    if (gp->priv->init_dialog)
 
115
    {
 
116
        gtk_widget_destroy (gp->priv->init_dialog);
 
117
    }
 
118
    gp->priv->init_dialog = remmina_init_dialog_new (_("Connecting to '%s'..."), (name ? name : "*"));
 
119
    g_signal_connect (G_OBJECT (gp->priv->init_dialog), "response", G_CALLBACK (remmina_protocol_widget_init_cancel), gp);
 
120
    gtk_widget_show (gp->priv->init_dialog);
 
121
}
 
122
 
 
123
static void
 
124
remmina_protocol_widget_hide_init_dialog (RemminaProtocolWidget *gp)
 
125
{
 
126
    if (gp->priv->init_dialog && GTK_IS_WIDGET (gp->priv->init_dialog))
 
127
    {
 
128
        gtk_widget_destroy (gp->priv->init_dialog);
 
129
    }
 
130
    gp->priv->init_dialog = NULL;
 
131
}
 
132
 
 
133
static void
 
134
remmina_protocol_widget_destroy (RemminaProtocolWidget *gp, gpointer data)
 
135
{
 
136
    remmina_protocol_widget_hide_init_dialog (gp);
 
137
    g_free (gp->priv->error_message);
 
138
    g_free (gp->priv);
 
139
}
 
140
 
 
141
static void
 
142
remmina_protocol_widget_connect (RemminaProtocolWidget *gp, gpointer data)
 
143
{
 
144
    remmina_protocol_widget_hide_init_dialog (gp);
 
145
}
 
146
 
 
147
static void
 
148
remmina_protocol_widget_disconnect (RemminaProtocolWidget *gp, gpointer data)
 
149
{
 
150
    remmina_protocol_widget_hide_init_dialog (gp);
 
151
}
 
152
 
 
153
void
 
154
remmina_protocol_widget_grab_focus (RemminaProtocolWidget *gp)
 
155
{
 
156
    GtkWidget *child;
 
157
 
 
158
    child = gtk_bin_get_child (GTK_BIN (gp));
 
159
    if (child)
 
160
    {
 
161
        GTK_WIDGET_SET_FLAGS (child, GTK_CAN_FOCUS);
 
162
        gtk_widget_grab_focus (child);
 
163
    }
 
164
}
 
165
 
 
166
static void
 
167
remmina_protocol_widget_init (RemminaProtocolWidget *gp)
 
168
{
 
169
    RemminaProtocolWidgetPriv *priv;
 
170
 
 
171
    priv = g_new0 (RemminaProtocolWidgetPriv, 1);
 
172
    gp->priv = priv;
 
173
 
 
174
    g_signal_connect (G_OBJECT (gp), "destroy", G_CALLBACK (remmina_protocol_widget_destroy), NULL);
 
175
    g_signal_connect (G_OBJECT (gp), "connect", G_CALLBACK (remmina_protocol_widget_connect), NULL);
 
176
    g_signal_connect (G_OBJECT (gp), "disconnect", G_CALLBACK (remmina_protocol_widget_disconnect), NULL);
 
177
}
 
178
 
 
179
void
 
180
remmina_protocol_widget_open_connection_real (gpointer data)
 
181
{
 
182
    RemminaProtocolWidget *gp = REMMINA_PROTOCOL_WIDGET (data);
 
183
    RemminaProtocolPlugin *plugin;
 
184
    RemminaFile *remminafile = gp->priv->remmina_file;
 
185
 
 
186
    /* Locate the protocol plugin */
 
187
    plugin = (RemminaProtocolPlugin *) remmina_plugin_manager_get_plugin (REMMINA_PLUGIN_TYPE_PROTOCOL, remminafile->protocol);
 
188
    if (!plugin || !plugin->init || !plugin->open_connection)
 
189
    {
 
190
        remmina_protocol_widget_set_error (gp, _("Protocol %s is not supported."), remminafile->protocol);
 
191
        remmina_protocol_widget_close_connection (gp);
 
192
        return;
 
193
    }
 
194
 
 
195
    plugin->init (gp);
 
196
 
 
197
    gp->priv->plugin = plugin;
 
198
 
 
199
    if (! plugin->open_connection (gp))
 
200
    {
 
201
        remmina_protocol_widget_close_connection (gp);
 
202
    }
 
203
}
 
204
 
 
205
void
 
206
remmina_protocol_widget_open_connection (RemminaProtocolWidget *gp, RemminaFile *remminafile)
 
207
{
 
208
    gp->priv->remmina_file = remminafile;
 
209
    gp->priv->scale =  remminafile->scale;
 
210
 
 
211
    remmina_protocol_widget_show_init_dialog (gp, remminafile->name);
 
212
 
 
213
    remmina_protocol_widget_open_connection_real (gp);
 
214
}
 
215
 
 
216
gboolean
 
217
remmina_protocol_widget_close_connection (RemminaProtocolWidget *gp)
 
218
{
 
219
    if (!GTK_IS_WIDGET (gp) || gp->priv->closed) return FALSE;
 
220
    gp->priv->closed = TRUE;
 
221
    gdk_keyboard_ungrab (GDK_CURRENT_TIME);
 
222
 
 
223
    if (gp->priv->chat_window)
 
224
    {
 
225
        gtk_widget_destroy (gp->priv->chat_window);
 
226
        gp->priv->chat_window = NULL;
 
227
    }
 
228
 
 
229
#ifdef HAVE_LIBSSH
 
230
    if (gp->priv->ssh_tunnel)
 
231
    {
 
232
        remmina_ssh_tunnel_free (gp->priv->ssh_tunnel);
 
233
        gp->priv->ssh_tunnel = NULL;
 
234
    }
 
235
#endif
 
236
 
 
237
    if (!gp->priv->plugin->close_connection)
 
238
    {
 
239
        remmina_protocol_widget_emit_signal (gp, "disconnect");
 
240
        return FALSE;
 
241
    }
 
242
 
 
243
    return gp->priv->plugin->close_connection (gp);
 
244
}
 
245
 
 
246
static gboolean
 
247
remmina_protocol_widget_emit_signal_timeout (gpointer user_data)
 
248
{
 
249
    RemminaProtocolWidgetSignalData *data = (RemminaProtocolWidgetSignalData*) user_data;
 
250
    g_signal_emit_by_name (G_OBJECT (data->gp), data->signal_name);
 
251
    g_free (data);
 
252
    return FALSE;
 
253
}
 
254
 
 
255
void
 
256
remmina_protocol_widget_emit_signal (RemminaProtocolWidget *gp, const gchar *signal_name)
 
257
{
 
258
    RemminaProtocolWidgetSignalData *data;
 
259
 
 
260
    data = g_new (RemminaProtocolWidgetSignalData, 1);
 
261
    data->gp = gp;
 
262
    data->signal_name = signal_name;
 
263
    TIMEOUT_ADD (0, remmina_protocol_widget_emit_signal_timeout, data);
 
264
}
 
265
 
 
266
gpointer
 
267
remmina_protocol_widget_query_feature (RemminaProtocolWidget *gp, RemminaProtocolFeature feature)
 
268
{
 
269
    switch (feature)
 
270
    {
 
271
        case REMMINA_PROTOCOL_FEATURE_TOOL:
 
272
            return GINT_TO_POINTER (1);
 
273
#ifdef HAVE_LIBSSH
 
274
        case REMMINA_PROTOCOL_FEATURE_TOOL_SFTP:
 
275
        case REMMINA_PROTOCOL_FEATURE_TOOL_SSHTERM:
 
276
            return (gp->priv->ssh_tunnel ? GINT_TO_POINTER (1) : NULL);
 
277
#endif
 
278
        default:
 
279
            return gp->priv->plugin->query_feature (gp, feature);
 
280
    }
 
281
}
 
282
 
 
283
void
 
284
remmina_protocol_widget_call_feature (RemminaProtocolWidget *gp, RemminaProtocolFeature feature, const gpointer data)
 
285
{
 
286
    switch (feature)
 
287
    {
 
288
#ifdef HAVE_LIBSSH
 
289
    case REMMINA_PROTOCOL_FEATURE_TOOL_SFTP:
 
290
        if (!gp->priv->ssh_tunnel) return;
 
291
        remmina_connection_window_open_from_file_full (
 
292
            remmina_file_dup_temp_protocol (gp->priv->remmina_file, "SFTP"), NULL, gp->priv->ssh_tunnel, NULL);
 
293
        return;
 
294
 
 
295
    case REMMINA_PROTOCOL_FEATURE_TOOL_SSHTERM:
 
296
        if (!gp->priv->ssh_tunnel) return;
 
297
        remmina_connection_window_open_from_file_full (
 
298
            remmina_file_dup_temp_protocol (gp->priv->remmina_file, "SSH"), NULL, gp->priv->ssh_tunnel, NULL);
 
299
        return;
 
300
#endif
 
301
    case REMMINA_PROTOCOL_FEATURE_UNFOCUS:
 
302
        break;
 
303
    default:
 
304
        break;
 
305
    }
 
306
    gp->priv->plugin->call_feature (gp, feature, data);
 
307
}
 
308
 
 
309
static gboolean
 
310
remmina_protocol_widget_on_key_press (GtkWidget *widget, GdkEventKey *event, RemminaProtocolWidget *gp)
 
311
{
 
312
    if (gp->priv->hostkey_func)
 
313
    {
 
314
        return gp->priv->hostkey_func (gp, event->keyval, FALSE, gp->priv->hostkey_func_data);
 
315
    }
 
316
    return FALSE;
 
317
}
 
318
 
 
319
static gboolean
 
320
remmina_protocol_widget_on_key_release (GtkWidget *widget, GdkEventKey *event, RemminaProtocolWidget *gp)
 
321
{
 
322
    if (gp->priv->hostkey_func)
 
323
    {
 
324
        return gp->priv->hostkey_func (gp, event->keyval, TRUE, gp->priv->hostkey_func_data);
 
325
    }
 
326
    return FALSE;
 
327
}
 
328
 
 
329
void
 
330
remmina_protocol_widget_register_hostkey (RemminaProtocolWidget *gp, GtkWidget *widget)
 
331
{
 
332
    g_signal_connect (G_OBJECT (widget), "key-press-event", G_CALLBACK (remmina_protocol_widget_on_key_press), gp);
 
333
    g_signal_connect (G_OBJECT (widget), "key-release-event", G_CALLBACK (remmina_protocol_widget_on_key_release), gp);
 
334
}
 
335
 
 
336
void
 
337
remmina_protocol_widget_set_hostkey_func (RemminaProtocolWidget *gp, RemminaHostkeyFunc func, gpointer data)
 
338
{
 
339
    gp->priv->hostkey_func = func;
 
340
    gp->priv->hostkey_func_data = data;
 
341
}
 
342
 
 
343
#ifdef HAVE_LIBSSH
 
344
static gboolean
 
345
remmina_protocol_widget_init_tunnel (RemminaProtocolWidget *gp)
 
346
{
 
347
    RemminaSSHTunnel *tunnel;
 
348
    gint ret;
 
349
 
 
350
    /* Reuse existing SSH connection if it's reconnecting to destination */
 
351
    if (gp->priv->ssh_tunnel == NULL)
 
352
    {
 
353
        tunnel = remmina_ssh_tunnel_new_from_file (gp->priv->remmina_file);
 
354
 
 
355
        THREADS_ENTER
 
356
        remmina_init_dialog_set_status (REMMINA_INIT_DIALOG (gp->priv->init_dialog),
 
357
            _("Connecting to SSH server %s..."), REMMINA_SSH (tunnel)->server);
 
358
        THREADS_LEAVE
 
359
 
 
360
        if (!remmina_ssh_init_session (REMMINA_SSH (tunnel)))
 
361
        {
 
362
            remmina_protocol_widget_set_error (gp, REMMINA_SSH (tunnel)->error);
 
363
            remmina_ssh_tunnel_free (tunnel);
 
364
            return FALSE;
 
365
        }
 
366
 
 
367
        ret = remmina_ssh_auth_gui (REMMINA_SSH (tunnel), REMMINA_INIT_DIALOG (gp->priv->init_dialog), TRUE);
 
368
        if (ret <= 0)
 
369
        {
 
370
            if (ret == 0)
 
371
            {
 
372
                remmina_protocol_widget_set_error (gp, REMMINA_SSH (tunnel)->error);
 
373
            }
 
374
            remmina_ssh_tunnel_free (tunnel);
 
375
            return FALSE;
 
376
        }
 
377
 
 
378
        gp->priv->ssh_tunnel = tunnel;
 
379
    }
 
380
 
 
381
    return TRUE;
 
382
}
 
383
#endif
 
384
 
 
385
gchar*
 
386
remmina_protocol_widget_start_direct_tunnel (RemminaProtocolWidget *gp, gint default_port, gboolean port_plus)
 
387
{
 
388
    gchar *host, *dest;
 
389
    gint port;
 
390
 
 
391
    if (!gp->priv->remmina_file->server || gp->priv->remmina_file->server[0] == '\0')
 
392
    {
 
393
        return g_strdup("");
 
394
    }
 
395
 
 
396
    remmina_public_get_server_port (gp->priv->remmina_file->server, default_port, &host, &port);
 
397
 
 
398
    if (port_plus && port < 100)
 
399
    {
 
400
        /* Protocols like VNC supports using instance number :0, :1, etc as port number. */
 
401
        port += default_port;
 
402
    }
 
403
 
 
404
#ifdef HAVE_LIBSSH
 
405
    if (!gp->priv->remmina_file->ssh_enabled)
 
406
    {
 
407
        dest = g_strdup_printf ("[%s]:%i", host, port);
 
408
        g_free (host);
 
409
        return dest;
 
410
    }
 
411
 
 
412
    if (!remmina_protocol_widget_init_tunnel (gp))
 
413
    {
 
414
        g_free (host);
 
415
        return NULL;
 
416
    }
 
417
 
 
418
    THREADS_ENTER
 
419
    remmina_init_dialog_set_status (REMMINA_INIT_DIALOG (gp->priv->init_dialog),
 
420
        _("Connecting to %s through SSH tunnel..."), gp->priv->remmina_file->server);
 
421
    THREADS_LEAVE
 
422
 
 
423
    if (gp->priv->remmina_file->ssh_loopback)
 
424
    {
 
425
        g_free (host);
 
426
        host = g_strdup ("127.0.0.1");
 
427
    }
 
428
 
 
429
    if (!remmina_ssh_tunnel_open (gp->priv->ssh_tunnel, host, port, remmina_pref.sshtunnel_port))
 
430
    {
 
431
        g_free (host);
 
432
        remmina_protocol_widget_set_error (gp, REMMINA_SSH (gp->priv->ssh_tunnel)->error);
 
433
        return NULL;
 
434
    }
 
435
 
 
436
    g_free (host);
 
437
    return g_strdup_printf ("127.0.0.1:%i", remmina_pref.sshtunnel_port);
 
438
 
 
439
#else
 
440
 
 
441
    dest = g_strdup_printf ("[%s]:%i", host, port);
 
442
    g_free (host);
 
443
    return dest;
 
444
 
 
445
#endif
 
446
}
 
447
 
 
448
gboolean
 
449
remmina_protocol_widget_start_reverse_tunnel (RemminaProtocolWidget *gp, gint local_port)
 
450
{
 
451
#ifdef HAVE_LIBSSH
 
452
    if (!gp->priv->remmina_file->ssh_enabled)
 
453
    {
 
454
        return TRUE;
 
455
    }
 
456
 
 
457
    if (!remmina_protocol_widget_init_tunnel (gp))
 
458
    {
 
459
        return FALSE;
 
460
    }
 
461
 
 
462
    THREADS_ENTER
 
463
    remmina_init_dialog_set_status (REMMINA_INIT_DIALOG (gp->priv->init_dialog),
 
464
        _("Waiting for an incoming SSH tunnel at port %i..."), gp->priv->remmina_file->listenport);
 
465
    THREADS_LEAVE
 
466
 
 
467
    if (!remmina_ssh_tunnel_reverse (gp->priv->ssh_tunnel, gp->priv->remmina_file->listenport, local_port))
 
468
    {
 
469
        remmina_protocol_widget_set_error (gp, REMMINA_SSH (gp->priv->ssh_tunnel)->error);
 
470
        return FALSE;
 
471
    }
 
472
#endif
 
473
 
 
474
    return TRUE;
 
475
}
 
476
 
 
477
gboolean
 
478
remmina_protocol_widget_ssh_exec (RemminaProtocolWidget *gp, gboolean wait, const gchar *fmt, ...)
 
479
{
 
480
#ifdef HAVE_LIBSSH
 
481
    RemminaSSHTunnel *tunnel = gp->priv->ssh_tunnel;
 
482
    ssh_channel channel;
 
483
    gint status;
 
484
    gboolean ret = FALSE;
 
485
    gchar *cmd, *ptr;
 
486
    va_list args;
 
487
 
 
488
    if ((channel = channel_new (REMMINA_SSH (tunnel)->session)) == NULL)
 
489
    {
 
490
        return FALSE;
 
491
    }
 
492
 
 
493
    va_start (args, fmt);
 
494
    cmd = g_strdup_vprintf (fmt, args);
 
495
    va_end (args);
 
496
 
 
497
    if (channel_open_session (channel) == SSH_OK &&
 
498
        channel_request_exec (channel, cmd) == SSH_OK)
 
499
    {
 
500
        if (wait)
 
501
        {
 
502
            channel_send_eof (channel);
 
503
            status = channel_get_exit_status (channel);
 
504
            ptr = strchr (cmd, ' ');
 
505
            if (ptr) *ptr = '\0';
 
506
            switch (status)
 
507
            {
 
508
            case 0:
 
509
                ret = TRUE;
 
510
                break;
 
511
            case 127:
 
512
                remmina_ssh_set_application_error (REMMINA_SSH (tunnel),
 
513
                    _("Command %s not found on SSH server"), cmd);
 
514
                break;
 
515
            default:
 
516
                remmina_ssh_set_application_error (REMMINA_SSH (tunnel),
 
517
                    _("Command %s failed on SSH server (status = %i)."), cmd, status);
 
518
                break;
 
519
            }
 
520
        }
 
521
        else
 
522
        {
 
523
            ret = TRUE;
 
524
        }
 
525
    }
 
526
    else
 
527
    {
 
528
        remmina_ssh_set_error (REMMINA_SSH (tunnel), _("Failed to execute command: %s"));
 
529
    }
 
530
    g_free (cmd);
 
531
    if (wait) channel_close (channel);
 
532
    channel_free (channel);
 
533
    return ret;
 
534
 
 
535
#else
 
536
 
 
537
    return FALSE;
 
538
 
 
539
#endif
 
540
}
 
541
 
 
542
#ifdef HAVE_LIBSSH
 
543
static gboolean
 
544
remmina_protocol_widget_tunnel_init_callback (RemminaSSHTunnel *tunnel, gpointer data)
 
545
{
 
546
    RemminaProtocolWidget *gp = REMMINA_PROTOCOL_WIDGET (data);
 
547
    gchar *server;
 
548
    gint port;
 
549
    gboolean ret;
 
550
 
 
551
    remmina_public_get_server_port (gp->priv->remmina_file->server, 177, &server, &port);
 
552
    ret = ((RemminaXPortTunnelInitFunc) gp->priv->init_func) (gp,
 
553
        tunnel->remotedisplay, (tunnel->bindlocalhost ? "localhost" : server), port);
 
554
    g_free (server);
 
555
 
 
556
    return ret;
 
557
}
 
558
 
 
559
static gboolean
 
560
remmina_protocol_widget_tunnel_connect_callback (RemminaSSHTunnel *tunnel, gpointer data)
 
561
{
 
562
    return TRUE;
 
563
}
 
564
 
 
565
static gboolean
 
566
remmina_protocol_widget_tunnel_disconnect_callback (RemminaSSHTunnel *tunnel, gpointer data)
 
567
{
 
568
    RemminaProtocolWidget *gp = REMMINA_PROTOCOL_WIDGET (data);
 
569
 
 
570
    if (REMMINA_SSH (tunnel)->error)
 
571
    {
 
572
        remmina_protocol_widget_set_error (gp, "%s", REMMINA_SSH (tunnel)->error);
 
573
    }
 
574
    IDLE_ADD ((GSourceFunc) remmina_protocol_widget_close_connection, gp);
 
575
    return TRUE;
 
576
}
 
577
#endif
 
578
 
 
579
gboolean
 
580
remmina_protocol_widget_start_xport_tunnel (RemminaProtocolWidget *gp, RemminaXPortTunnelInitFunc init_func)
 
581
{
 
582
#ifdef HAVE_LIBSSH
 
583
    gboolean bindlocalhost;
 
584
    gchar *server;
 
585
 
 
586
    if (!remmina_protocol_widget_init_tunnel (gp)) return FALSE;
 
587
 
 
588
    THREADS_ENTER
 
589
    remmina_init_dialog_set_status (REMMINA_INIT_DIALOG (gp->priv->init_dialog),
 
590
        _("Connecting to %s through SSH tunnel..."), gp->priv->remmina_file->server);
 
591
    THREADS_LEAVE
 
592
 
 
593
    gp->priv->init_func = init_func;
 
594
    gp->priv->ssh_tunnel->init_func = remmina_protocol_widget_tunnel_init_callback;
 
595
    gp->priv->ssh_tunnel->connect_func = remmina_protocol_widget_tunnel_connect_callback;
 
596
    gp->priv->ssh_tunnel->disconnect_func = remmina_protocol_widget_tunnel_disconnect_callback;
 
597
    gp->priv->ssh_tunnel->callback_data = gp;
 
598
 
 
599
    remmina_public_get_server_port (gp->priv->remmina_file->server, 0, &server, NULL);
 
600
    bindlocalhost = (g_strcmp0 (REMMINA_SSH (gp->priv->ssh_tunnel)->server, server) == 0);
 
601
    g_free (server);
 
602
 
 
603
    if (!remmina_ssh_tunnel_xport (gp->priv->ssh_tunnel, bindlocalhost))
 
604
    {
 
605
        remmina_protocol_widget_set_error (gp, "Failed to open channel : %s",
 
606
            ssh_get_error (REMMINA_SSH (gp->priv->ssh_tunnel)->session));
 
607
        return FALSE;
 
608
    }
 
609
 
 
610
    return TRUE;
 
611
 
 
612
#else
 
613
    return FALSE;
 
614
#endif
 
615
}
 
616
 
 
617
void
 
618
remmina_protocol_widget_set_display (RemminaProtocolWidget *gp, gint display)
 
619
{
 
620
#ifdef HAVE_LIBSSH
 
621
    if (gp->priv->ssh_tunnel->localdisplay) g_free (gp->priv->ssh_tunnel->localdisplay);
 
622
    gp->priv->ssh_tunnel->localdisplay = g_strdup_printf ("unix:%i", display);
 
623
#endif
 
624
}
 
625
 
 
626
GtkWidget*
 
627
remmina_protocol_widget_get_init_dialog (RemminaProtocolWidget *gp)
 
628
{
 
629
    return gp->priv->init_dialog;
 
630
}
 
631
 
 
632
gint
 
633
remmina_protocol_widget_get_width (RemminaProtocolWidget *gp)
 
634
{
 
635
    return gp->priv->width;
 
636
}
 
637
 
 
638
void
 
639
remmina_protocol_widget_set_width (RemminaProtocolWidget *gp, gint width)
 
640
{
 
641
    gp->priv->width = width;
 
642
}
 
643
 
 
644
gint
 
645
remmina_protocol_widget_get_height (RemminaProtocolWidget *gp)
 
646
{
 
647
    return gp->priv->height;
 
648
}
 
649
 
 
650
void
 
651
remmina_protocol_widget_set_height (RemminaProtocolWidget *gp, gint height)
 
652
{
 
653
    gp->priv->height = height;
 
654
}
 
655
 
 
656
gboolean
 
657
remmina_protocol_widget_get_scale (RemminaProtocolWidget *gp)
 
658
{
 
659
    return gp->priv->scale;
 
660
}
 
661
 
 
662
void
 
663
remmina_protocol_widget_set_scale (RemminaProtocolWidget *gp, gboolean scale)
 
664
{
 
665
    gp->priv->scale = scale;
 
666
}
 
667
 
 
668
gboolean
 
669
remmina_protocol_widget_get_expand (RemminaProtocolWidget *gp)
 
670
{
 
671
    return gp->priv->expand;
 
672
}
 
673
 
 
674
void
 
675
remmina_protocol_widget_set_expand (RemminaProtocolWidget *gp, gboolean expand)
 
676
{
 
677
    gp->priv->expand = expand;
 
678
}
 
679
 
 
680
gboolean
 
681
remmina_protocol_widget_has_error (RemminaProtocolWidget *gp)
 
682
{
 
683
    return gp->priv->has_error;
 
684
}
 
685
 
 
686
gchar*
 
687
remmina_protocol_widget_get_error_message (RemminaProtocolWidget *gp)
 
688
{
 
689
    return gp->priv->error_message;
 
690
}
 
691
 
 
692
void
 
693
remmina_protocol_widget_set_error (RemminaProtocolWidget *gp, const gchar *fmt, ...)
 
694
{
 
695
    va_list args;
 
696
 
 
697
    if (gp->priv->error_message) g_free (gp->priv->error_message);
 
698
 
 
699
    va_start (args, fmt);
 
700
    gp->priv->error_message = g_strdup_vprintf (fmt, args);
 
701
    va_end (args);
 
702
 
 
703
    gp->priv->has_error = TRUE;
 
704
}
 
705
 
 
706
gboolean
 
707
remmina_protocol_widget_is_closed (RemminaProtocolWidget *gp)
 
708
{
 
709
    return gp->priv->closed;
 
710
}
 
711
 
 
712
RemminaFile*
 
713
remmina_protocol_widget_get_file (RemminaProtocolWidget *gp)
 
714
{
 
715
    return gp->priv->remmina_file;
 
716
}
 
717
 
 
718
gint
 
719
remmina_protocol_widget_init_authpwd (RemminaProtocolWidget *gp, RemminaAuthpwdType authpwd_type)
 
720
{
 
721
    RemminaFile *remminafile = gp->priv->remmina_file;
 
722
    gchar *s;
 
723
    gint ret;
 
724
 
 
725
    switch (authpwd_type)
 
726
    {
 
727
    case REMMINA_AUTHPWD_TYPE_PROTOCOL:
 
728
        s = g_strdup_printf (_("%s Password"), remminafile->protocol);
 
729
        break;
 
730
    case REMMINA_AUTHPWD_TYPE_SSH_PWD:
 
731
        s = g_strdup (_("SSH Password"));
 
732
        break;
 
733
    case REMMINA_AUTHPWD_TYPE_SSH_PRIVKEY:
 
734
        s = g_strdup (_("SSH Private Key Passphrase"));
 
735
        break;
 
736
    default:
 
737
        s = g_strdup (_("Password"));
 
738
        break;
 
739
    }
 
740
    ret = remmina_init_dialog_authpwd (REMMINA_INIT_DIALOG (gp->priv->init_dialog), s, 
 
741
        remminafile->filename != NULL &&
 
742
        authpwd_type != REMMINA_AUTHPWD_TYPE_SSH_PWD &&
 
743
        authpwd_type != REMMINA_AUTHPWD_TYPE_SSH_PRIVKEY);
 
744
    g_free (s);
 
745
 
 
746
    return ret;
 
747
}
 
748
 
 
749
gint
 
750
remmina_protocol_widget_init_authuserpwd (RemminaProtocolWidget *gp)
 
751
{
 
752
    RemminaFile *remminafile = gp->priv->remmina_file;
 
753
 
 
754
    return remmina_init_dialog_authuserpwd (REMMINA_INIT_DIALOG (gp->priv->init_dialog),
 
755
        remminafile->username, (remminafile->filename != NULL));
 
756
}
 
757
 
 
758
gchar*
 
759
remmina_protocol_widget_init_get_username (RemminaProtocolWidget *gp)
 
760
{
 
761
    return g_strdup (REMMINA_INIT_DIALOG (gp->priv->init_dialog)->username);
 
762
}
 
763
 
 
764
gchar*
 
765
remmina_protocol_widget_init_get_password (RemminaProtocolWidget *gp)
 
766
{
 
767
    return g_strdup (REMMINA_INIT_DIALOG (gp->priv->init_dialog)->password);
 
768
}
 
769
 
 
770
gint
 
771
remmina_protocol_widget_init_authx509 (RemminaProtocolWidget *gp)
 
772
{
 
773
    RemminaFile *remminafile = gp->priv->remmina_file;
 
774
 
 
775
    return remmina_init_dialog_authx509 (REMMINA_INIT_DIALOG (gp->priv->init_dialog),
 
776
        remminafile->cacert, remminafile->cacrl, remminafile->clientcert, remminafile->clientkey);
 
777
}
 
778
 
 
779
gchar*
 
780
remmina_protocol_widget_init_get_cacert (RemminaProtocolWidget *gp)
 
781
{
 
782
    gchar *s;
 
783
 
 
784
    s = REMMINA_INIT_DIALOG (gp->priv->init_dialog)->cacert;
 
785
    return (s && s[0] ? g_strdup (s) : NULL);
 
786
}
 
787
 
 
788
gchar*
 
789
remmina_protocol_widget_init_get_cacrl (RemminaProtocolWidget *gp)
 
790
{
 
791
    gchar *s;
 
792
 
 
793
    s = REMMINA_INIT_DIALOG (gp->priv->init_dialog)->cacrl;
 
794
    return (s && s[0] ? g_strdup (s) : NULL);
 
795
}
 
796
 
 
797
gchar*
 
798
remmina_protocol_widget_init_get_clientcert (RemminaProtocolWidget *gp)
 
799
{
 
800
    gchar *s;
 
801
 
 
802
    s = REMMINA_INIT_DIALOG (gp->priv->init_dialog)->clientcert;
 
803
    return (s && s[0] ? g_strdup (s) : NULL);
 
804
}
 
805
 
 
806
gchar*
 
807
remmina_protocol_widget_init_get_clientkey (RemminaProtocolWidget *gp)
 
808
{
 
809
    gchar *s;
 
810
 
 
811
    s = REMMINA_INIT_DIALOG (gp->priv->init_dialog)->clientkey;
 
812
    return (s && s[0] ? g_strdup (s) : NULL);
 
813
}
 
814
 
 
815
void
 
816
remmina_protocol_widget_init_save_cred (RemminaProtocolWidget *gp)
 
817
{
 
818
    RemminaFile *remminafile = gp->priv->remmina_file;
 
819
    gchar *s;
 
820
    gboolean save = FALSE;
 
821
 
 
822
    /* Save user name and certificates if any; save the password if it's requested to do so */
 
823
    s = REMMINA_INIT_DIALOG (gp->priv->init_dialog)->username;
 
824
    if (s && s[0])
 
825
    {
 
826
        if (remminafile->username) g_free (remminafile->username);
 
827
        remminafile->username = g_strdup (s);
 
828
        save = TRUE;
 
829
    }
 
830
    s = REMMINA_INIT_DIALOG (gp->priv->init_dialog)->cacert;
 
831
    if (s && s[0])
 
832
    {
 
833
        if (remminafile->cacert) g_free (remminafile->cacert);
 
834
        remminafile->cacert = g_strdup (s);
 
835
        save = TRUE;
 
836
    }
 
837
    s = REMMINA_INIT_DIALOG (gp->priv->init_dialog)->cacrl;
 
838
    if (s && s[0])
 
839
    {
 
840
        if (remminafile->cacrl) g_free (remminafile->cacrl);
 
841
        remminafile->cacrl = g_strdup (s);
 
842
        save = TRUE;
 
843
    }
 
844
    s = REMMINA_INIT_DIALOG (gp->priv->init_dialog)->clientcert;
 
845
    if (s && s[0])
 
846
    {
 
847
        if (remminafile->clientcert) g_free (remminafile->clientcert);
 
848
        remminafile->clientcert = g_strdup (s);
 
849
        save = TRUE;
 
850
    }
 
851
    s = REMMINA_INIT_DIALOG (gp->priv->init_dialog)->clientkey;
 
852
    if (s && s[0])
 
853
    {
 
854
        if (remminafile->clientkey) g_free (remminafile->clientkey);
 
855
        remminafile->clientkey = g_strdup (s);
 
856
        save = TRUE;
 
857
    }
 
858
    if (REMMINA_INIT_DIALOG (gp->priv->init_dialog)->save_password)
 
859
    {
 
860
        if (remminafile->password) g_free (remminafile->password);
 
861
        remminafile->password =
 
862
            g_strdup (REMMINA_INIT_DIALOG (gp->priv->init_dialog)->password);
 
863
        save = TRUE;
 
864
    }
 
865
    if (save)
 
866
    {
 
867
        remmina_file_save_credential (remminafile);
 
868
    }
 
869
}
 
870
 
 
871
void
 
872
remmina_protocol_widget_init_show_listen (RemminaProtocolWidget *gp, gint port)
 
873
{
 
874
    remmina_init_dialog_set_status (REMMINA_INIT_DIALOG (gp->priv->init_dialog),
 
875
        _("Listening on Port %i for an Incoming %s Connection..."),
 
876
        port, gp->priv->remmina_file->protocol);
 
877
}
 
878
 
 
879
void
 
880
remmina_protocol_widget_init_show_retry (RemminaProtocolWidget *gp)
 
881
{
 
882
    remmina_init_dialog_set_status_temp (REMMINA_INIT_DIALOG (gp->priv->init_dialog),
 
883
        _("Authentication failed. Trying to reconnect..."));
 
884
}
 
885
 
 
886
void
 
887
remmina_protocol_widget_init_show (RemminaProtocolWidget *gp)
 
888
{
 
889
    gtk_widget_show (gp->priv->init_dialog);
 
890
}
 
891
 
 
892
void
 
893
remmina_protocol_widget_init_hide (RemminaProtocolWidget *gp)
 
894
{
 
895
    gtk_widget_hide (gp->priv->init_dialog);
 
896
}
 
897
 
 
898
static void
 
899
remmina_protocol_widget_chat_on_destroy (RemminaProtocolWidget *gp)
 
900
{
 
901
    gp->priv->chat_window = NULL;
 
902
}
 
903
 
 
904
void
 
905
remmina_protocol_widget_chat_open (RemminaProtocolWidget *gp, const gchar *name,
 
906
    void(*on_send)(RemminaProtocolWidget *gp, const gchar *text),
 
907
    void(*on_destroy)(RemminaProtocolWidget *gp))
 
908
{
 
909
    if (gp->priv->chat_window)
 
910
    {
 
911
        gtk_window_present (GTK_WINDOW (gp->priv->chat_window));
 
912
    }
 
913
    else
 
914
    {
 
915
        gp->priv->chat_window = remmina_chat_window_new (
 
916
            GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (gp))),
 
917
            name);
 
918
        g_signal_connect_swapped (G_OBJECT (gp->priv->chat_window), "send", G_CALLBACK (on_send), gp);
 
919
        g_signal_connect_swapped (G_OBJECT (gp->priv->chat_window), "destroy", G_CALLBACK (remmina_protocol_widget_chat_on_destroy), gp);
 
920
        g_signal_connect_swapped (G_OBJECT (gp->priv->chat_window), "destroy", G_CALLBACK (on_destroy), gp);
 
921
        gtk_widget_show (gp->priv->chat_window);
 
922
    }
 
923
}
 
924
 
 
925
void
 
926
remmina_protocol_widget_chat_close (RemminaProtocolWidget *gp)
 
927
{
 
928
    if (gp->priv->chat_window)
 
929
    {
 
930
        gtk_widget_destroy (gp->priv->chat_window);
 
931
    }
 
932
}
 
933
 
 
934
void
 
935
remmina_protocol_widget_chat_receive (RemminaProtocolWidget *gp, const gchar *text)
 
936
{
 
937
    if (gp->priv->chat_window)
 
938
    {
 
939
        remmina_chat_window_receive (REMMINA_CHAT_WINDOW (gp->priv->chat_window), _("Server"), text);
 
940
        gtk_window_present (GTK_WINDOW (gp->priv->chat_window));
 
941
    }
 
942
}
 
943
 
 
944
GtkWidget*
 
945
remmina_protocol_widget_new (void)
 
946
{
 
947
    return GTK_WIDGET (g_object_new (REMMINA_TYPE_PROTOCOL_WIDGET, NULL));
 
948
}
 
949