#!/usr/bin/perl
# Mandrake Remote FrameBuffer 
#
# Copyright (C) 2001, 2002, 2003 MandrakeSoft Daouda Lo (daouda at mandrakesoft dot com)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
###############################################################################

use lib qw(/usr/lib/libDrakX/);
use standalone;
use keyboard;
use strict;
use MDK::Common;
use ugtk2 qw(:all);

c::bind_textdomain_codeset('rfbdrake', 'UTF8');
sub translate {
    my ($s) = @_;
    my $r = $s ? c::dgettext('rfbdrake', $s) : '';
    c::set_tagged_utf8($r);
    $r;
}
sub sprintf_fixutf8 {
    my $need_upgrade;
    $need_upgrade |= to_bool(c::is_tagged_utf8($_)) + 1 foreach @_;
    if ($need_upgrade == 3) { c::upgrade_utf8($_) foreach @_ };
    sprintf shift, @_;
}
sub N {
    my $s = shift @_; my $t = translate($s);
    sprintf_fixutf8 $t, @_;
}

my $_version = "0.8.2";
my $_copyright = "2001, 2002";
my $pix_dir = "/usr/share/rfbdrake/pixmaps";

set_steps();

sub get_keymaps {
    my @keymp;
    my $path2keymaps = "/usr/share/rdesktop/keymaps/";
    opendir DIR, $path2keymaps or die N("Opendir error: %s", $!);
    @keymp = grep { !/common/ && !/modifiers/ && -f "$path2keymaps/$_" } readdir(DIR);
    closedir DIR;
    my $kb = keyboard::read(); 
    my $keyboard = member($kb->{KEYBOARD}, @keymp) ? $kb->{KEYBOARD} : 'en-us';
    my ($kb_used, $keyboards) = partition { $_ eq $keyboard } @keymp; 
    unshift(@$keyboards, $kb_used->[0]);
    @$keyboards;   
}

sub set_steps {
    my $win_global = ugtk2->new(N("Rfbdrake")." ".$_version, center => 1);
    gtkset_size_request($win_global->{window}, 540, 430);
    my $nb_global = Gtk2::Notebook->new; my $nb = Gtk2::Notebook->new; 
    map { $_->set_show_tabs(0); $_->set_show_border(0) } ($nb_global, $nb);
    my $client_rad = Gtk2::RadioButton->new_with_label(undef, N("Want to take control (linux client)"));
    my $server_rad = Gtk2::RadioButton->new_with_label_from_widget($client_rad, N("Allow control of my machine (linux server)"));
    my $win_rad = Gtk2::RadioButton->new_with_label_from_widget($client_rad, N("Windows Terminal Services"));
    my $button_cancel = Gtk2::Button->new(" ".N("Cancel")." ");
    $button_cancel->signal_connect(clicked => \&quit_global);
    my $button_connect = Gtk2::Button->new(" ".N("Connection")." ");
    my $button_help = Gtk2::Button->new(" ".N("Help")." ");
    my $hbox_final = Gtk2::HBox->new(0, 1);
    $hbox_final->pack_start($button_help, 0, 0, 1); $hbox_final->pack_end($button_cancel, 0, 0, 1); $hbox_final->pack_end($button_connect,0, 0, 1);
    gtkadd($win_global->{window},
	   gtkappend_page($nb,
			  gtkpack_(Gtk2::VBox->new(0, 2),
				   0, set_darea(N("Remote Access Configuration"), "$pix_dir/remote.png"),
				   0, gtkadd(my $frame_sel = Gtk2::Frame->new(N("Remote Access Type")),
					     gtkpack(Gtk2::VBox->new(0, 0),
						     gtksignal_connect($client_rad, clicked => sub { $nb_global->set_current_page(0); $button_connect->child->set(N("Connection")) }),
						     gtksignal_connect($server_rad, clicked => sub { $nb_global->set_current_page(1); $button_connect->child->set(N("Launch server")) }),
						     gtksignal_connect($win_rad, clicked => sub { $nb_global->set_current_page(2); $button_connect->child->set(N("Connection")) }),
						    ),
					    ),
				   1, gtkappend_page($nb_global,
						     gtkadd(Gtk2::Frame->new(N("Client configuration")),
							    gtkpack_(Gtk2::VBox->new(1, 0),
								     1, create_packtable({ homogeneous => 1, col_spacings => 20, row_spacings => 20 },
											 [ N("Remote server Address"), my $host_ip = Gtk2::Combo->new() ],
											 [ N("Display Number (default = 0)"), my $display = Gtk2::Entry->new() ],
											 [ N("Enter Password"), my $pass_client = Gtk2::Entry->new() ],
											 [   "" , my $full_toggle = Gtk2::CheckButton->new(N("FullScreen")) ],
											),
								    ),
							   ),
						    ),
				   1, gtkappend_page($nb_global,
						     gtkadd(Gtk2::Frame->new(N("Server configuration")),
							    gtkpack(Gtk2::VBox->new(1, 0),
								    gtkpack_(Gtk2::HBox->new(1, 5),
									     0, gtkpack(Gtk2::Label->new(N("Set Password"))),
									     0, gtkpack(my $pass_serv = Gtk2::Entry->new),
									    ),
								   ),
							   ),
						    ),
				   1, gtkappend_page($nb_global,
						     gtkadd(Gtk2::Frame->new(N("Windows Terminal Services")),
							    gtkpack_(Gtk2::VBox->new(1, 0),
								     1, create_packtable({ homogeneous => 1, col_spacings => 20, row_spacings => 20 },
											 [ N("Windows Hostname"), my $win_serv = Gtk2::Combo->new() ],
											 [ N("Screen Size"), my $win_size = Gtk2::Combo->new() ],
											 [ N("Keyboard Language"), my $keymaps = Gtk2::Combo->new() ],
											 [   "" , my $full_wts = Gtk2::CheckButton->new(N("FullScreen")) ],
											)
								    )
							   )
						    ),
				   0, gtkpack($hbox_final)
				  )
			 ),
	   gtkappend_page($nb,
			  gtkpack_( Gtk2::VBox->new(0, 3),
				    0, set_darea(N("Help"), "$pix_dir/remote.png"),
				    1, create_scrolled_window(gtktext_insert(my $text = Gtk2::TextView->new, N(" Remote FrameBuffer - Copyright (C) %s MandrakeSoft S.A.", $_copyright)."\n\t\t\t".N("Author:")."   Daouda Lo (daouda at mandrakesoft dot com)\n\n\t ".N("The rfbdrake tool is both a client and server desktop remote control utility.")."\n\t ".N("It exports the framebuffer of the X server to one or more clients using strong\n\t compression and injects keyboard and mouse inputs from the clients into\n\t the server.")."\n\n\t ".N("Rfbdrake allows to initiate a Window Terminal Services session with a\n\t Windows 2000/XP server.")."\n\n\t ".N("The password is encrypted and one should always set it before giving the\n\t control to a remote client.\n"))),
				    0, gtksignal_connect(my $buttonok = Gtk2::Button->new(N("Click Here to return")), clicked => sub { $nb->prev_page() }),
				  ),
			 ),
	  );
    my $pass_bool = 'FALSE';
    $button_help->signal_connect("clicked", sub { $nb->set_current_page(1) });
    map { touch("$ENV{HOME}/$_") } (".rfb_hist", ".rfb_hist_win");
    -f "$ENV{HOME}/.rfb_hist" and $host_ip->set_popdown_strings(load_text("$ENV{HOME}/.rfb_hist"));
    $pass_client->get_chars(0, -1);
    -f "$ENV{HOME}/.rfb_hist_win" and $win_serv->set_popdown_strings(load_text("$ENV{HOME}/.rfb_hist_win")); $win_serv->set_use_arrows_always('TRUE');
    $win_size->set_popdown_strings("1024x768", "1280x1024", "1600x1200", "800x600");
    $keymaps->set_popdown_strings(get_keymaps());
    $pass_serv->signal_connect("changed", sub { $pass_bool = 'TRUE' });
    $pass_client->set_visibility(0); 
    $pass_serv->set_visibility(0); 
    $button_connect->signal_connect("clicked", sub {   
					my $page = $nb_global->get_current_page();
					if ($page <= 0) {
					    my $disp = $display->get_chars(0, -1);
					    my $tog = $full_toggle->get_active ? '-fullscreen' : '-shared';
					    $disp eq '' ? $disp = 0 : $disp;
					    my $host_cl = $host_ip->entry->get_text();
					    unless ($host_cl ne '') { splash_warning("\n ".N("Enter a valid address please!")." \n") }
					    else {
						my $passcli = $pass_client->get_chars(0, -1);
						refresh_host_list($host_cl, "$ENV{HOME}/.rfb_hist");
						my $vssh_script = "";
						foreach ("/usr/bin/vssh.exp", "./vssh.exp") {
						    [ -e $_ ] and $vssh_script = $_; last;
						}
						if ($passcli eq '') { 
						    foreach my $vncbin ('/usr/X11R6/bin/vncviewer', '/usr/bin/vncviewer') {
							exec("$vncbin $tog $host_cl:$disp") if -e $vncbin;
						    }
						    splash_warning(N("\nYou should install vnc client \nto connect to the server\n"));
						} else {
						    eval(exec $vssh_script, '--', $tog, $host_cl, $disp, $passcli) or splash_warning("test");
						}
					    }
					} elsif ($page == 1) {
					    if (!-e "$ENV{HOME}/.x0rfbserver" || $pass_bool eq 'TRUE') {
						my $pserv=$pass_serv->get_chars(0, -1);
						$pserv = `genpassHex '$pserv' 2>&1`;
						output "$ENV{HOME}/.x0rfbserver",
						qq([Connection]
SocketConnections = 1
Display = 0
AutoDisplay = 1
Password = $pserv
DisableRemote = 0
DisableLocal = 0

[Update]
ShowMousePointer = 1
) }						 
					    exec("/usr/bin/x0rfbserver") if -e "/usr/bin/x0rfbserver";
					    splash_warning(N("\nInstall the rfb package if you want to export \nyour desktop to a remote client\n"));
					} elsif ($page == 2) {
					    my $host_win = $win_serv->entry->get_text();
					    unless ($host_win ne '') { splash_warning("\n ".N("Enter a valid address please!")." \n") }
					    else {
						my $tog = if_($full_wts->get_active(), '-f'); 
						refresh_host_list($host_win, "$ENV{HOME}/.rfb_hist_win");
						my $size_win = "-g ".$win_size->entry->get_text()."+0+0";
						my $keymap_choice = "-k ".$keymaps->entry->get_text();
						exec("rdesktop $tog $size_win $keymap_choice $host_win") if -e "/usr/bin/rdesktop";
						splash_warning(N("\nRdesktop is not installed,\ninstall it with 'urpmi rdesktop'\n"));
					    }
					}
				    });
    $win_global->{rwindow}->show_all;
    gtkflush;
    Gtk2->main;
    ugtk2->exit(0);
}
sub set_darea {
    my ($label, $pix) = @_;
    my $darea = gtkset_size_request(Gtk2::DrawingArea->new, -1, 100);
    $darea->modify_font(Gtk2::Pango::FontDescription->from_string('Sans Italic 20'));
    my $layout = $darea->create_pango_layout($label);
    my $pixbuf_banner = gtkcreate_pixbuf($pix);
    $darea->signal_connect(expose_event => sub {
			       fill_tiled($darea,$pixbuf_banner);
			       $darea->window->draw_layout($darea->style->white_gc, (600-($layout->get_pixel_size)[0])/2, 35, $layout);
			       0;
			   });
    $darea; 
}
sub load_text {
    my ($file)=@_;
    my @list_hosts;
    open(FILE, $file) or die "load_text: missing file $file : $!";
    while (<FILE>) {
	chomp;
	unshift(@list_hosts, $_);
    }
    close(FILE);
    @list_hosts;
}
sub refresh_host_list {
  my ($hostname, $file) = @_;
  my @old_hosts = load_text($file);
  my $i = 0;
  open( FILE, "+>$file") or die "refresh_host_list : missing file $file : $!";
  foreach my $line (@old_hosts) {
      unless ($i == 4) {
	  next if $line eq $hostname;
	  print FILE "$line$/";
	  $i++;
      }
  }
  print FILE "$hostname$/";
  close(FILE);
}
sub splash_warning {
    my ($label) = @_;
    my $win_about = Gtk2::Dialog->new;
    $win_about->set_position(1);
  
    my $bbox1 = Gtk2::HButtonBox->new;
    $win_about->action_area->pack_start($bbox1, 0, 0, 0);
    
    my $button = Gtk2::Button->new(N("Close"));
    $button->signal_connect_object("clicked",$win_about => 'destroy');
    $bbox1->add($button);
    
    my $lab = Gtk2::Label->new($label);
    my $style1 = Gtk2::Style->new;
    $win_about->vbox->pack_start($lab, 1, 1, 0);
    $win_about->show_all();
    $win_about->set_modal(1);
}
sub quit_global {
    ugtk2->exit(0);
}


