#!/usr/bin/perl
#
# Copyright (C) 2005 by Mandriva aginies _ateuh_ mandriva.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.

my $version = "0.1 test release";

use strict;
use lib qw(/usr/lib/libDrakX);
use standalone;
use common;
use network::network;
use interactive;
use ugtk2 qw(:ask :wrappers :create :dialogs);
use mygtk2 qw(gtknew);
use Gtk2::SimpleList;

# use libconf 
use Libconf::Templates;
use Libconf::Glueconf::Samba::Smb_conf;

my $in = 'interactive'->vnew('su');
$in->do_pkgs->ensure_is_installed('samba-server', '/usr/sbin/smbd') or return;

my $printer_list = create_printer_list();
my $share_list = create_share_list();

sub create_share_list() {
  my $share_list = Gtk2::SimpleList->new(N("Share name") => 'text',
					 N("Share directory") => 'text',
					 N("Comment") => 'text',
					 N("Browseable") => 'text',
					 N("Public") => 'text',
					 N("Writable") => 'text',
					 N("Create mask") => 'text',
					 N("Directory mask") => 'text',
					 N("Read list") => 'text',
					 N("Write list") => 'text',
					 N("Admin users") => 'text',
					 N("Valid users") => 'text',
					 N("Inherit Permissions") => 'text',
					 N("Hide dot files") => 'text',
					 N("Hide files") => 'text',
					 N("Preserve case") => 'text',
					 N("Force create mode") => 'text',
					 N("Force group") => 'text',
					 N("Default case") => 'text',
					);
  $share_list->set_headers_clickable(1);
  foreach (0, 1, 2, 3) {
    $share_list->get_column($_)->signal_connect('clicked', \&sort_by_column, $share_list->get_model);
    $share_list->get_column($_)->set_sort_column_id($_ == 0 ? 1 : $_ + 2);
  }
  $share_list;
}

sub create_printer_list() {
   my $printer_list = Gtk2::SimpleList->new(N("Printer name") => 'text',
                                           N("Path") => 'text',
                                           N("Comment") => 'text',
                                           N("Browseable") => 'text',
                                           N("Printable") => 'text',
                                           N("Print Command") => 'text',
                                           N("LPQ command") => 'text',
                                           N("Guest ok") => 'text',
                                           N("Writable") => 'text',
                                           N("Write list") => 'text',
                                           N("Inherit permissions") => 'text',
                                           N("Printing") => 'text',
                                           N("Create mode") => 'text',
                                           N("Use client driver") => 'text',
					  );
  $printer_list->set_headers_clickable(1);
  foreach (0, 1, 2, 3) {
    $printer_list->get_column($_)->signal_connect('clicked', \&sort_by_column, $printer_list->get_model);
    $printer_list->get_column($_)->set_sort_column_id($_ == 0 ? 1 : $_ + 2);
  }
  $printer_list;
}

sub sort_by_column {
    my ($column, $model) = @_;
    my $col_id = $column->get_sort_column_id;
    my ($old_id, $old_order) = $model->get_sort_column_id;
    $model->set_sort_column_id($col_id, $old_id == $col_id && $old_order ne 'descending' ? 'ascending' : 'descending');
}

#path comment browseable printable print command guest ok writable write list inherit permissions printing lpq command create mode use client driver


my $samba = new Libconf::Glueconf::Samba::Smb_conf({ filename => '/etc/samba/smb.conf', show_commented_info => 1 });
my (@listshare, @listprinters);
my @yesno = qw(yes no); push @yesno, ""; 
my @default_case = qw(upper lower); push @default_case, "";

my %adv_options = (
		   read_list => N("Read List"),
		   write_list => N("Write List"),
		   admin_users => N("Admin users"),
		   valid_users => N("Valid users"),
		   hide_dot_files => N("Hide dot files"),
		   hide_files => N("Hide files"),
		   force_group => N("Force Group"),
		   force_create_mode => N("Force create group"),
		   default_case => N("Default case"),
		   preserve_case => N("Preserve case"),
		   create_mask => N("Create mask"),
		   directory_mask => N("Directory mask"),
		   inherit_permissions => N("Inherit permissions"),
		  );

sub get_items() {
    my @items = (
		 [ "/_File", undef, undef, undef, '<Branch>', ],
		 [ "/_File/_Write conf", undef, \&write_conf, 1, '<StockItem>', 'gtk-execute' ],
		 [ "/_File/_Exit", undef, \&quit_all, 1, '<StockItem>', 'gtk-quit' ],

		 [ "/_Samba Server", undef, undef, undef, '<Branch>', ],
		 [ "/_Samba Server/_Restart", undef, \&restart_dialog, 1, '<StockItem>', 'gtk-execute' ],
		 [ "/_Samba Server/R_eload", undef, \&reload_dialog, 1, '<StockItem>', 'gtk-refresh' ],
		 );
    return @items;
}

sub quit_all() {
  ugtk2->exit;
}

sub restart_dialog() {
  wait_action("service smb restart");
}

sub reload_dialog() {
  wait_action("service smb reload");
}

sub wait_action {
    my ($cmd) = @_;
    my $w = $in->wait_message(N("Samba server"), N("Restarting/Reloading Samba server..."));
    run_program::get_stdout($cmd) !~ /unknown|error/ or err_dialog(N("Error!"), N("Error Restarting/Reloading Samba server")) and return;
    undef $w;
}

my %size_groups = map { $_ => Gtk2::SizeGroup->new('horizontal') } qw(label widget button);
my $label_and_widgets = sub {
  my ($label, $widget, $button) = @_;
  gtkpack_(Gtk2::HBox->new(0,1),
           0, gtkadd_widget($size_groups{label}, $label),
           0, gtkadd_widget($size_groups{widget}, $widget),
	   0, gtkadd_widget($size_groups{button}, $button),
          );
};

my $fdwidget = sub {
  my ($data) = @_;
  my $fd = new Gtk2::FileSelection(N("Directory Selection"));
  $fd->set_modal(1);
  $fd->signal_connect("destroy", sub { $fd->hide });
  $fd->ok_button->signal_connect(clicked => sub {
				   my $file = $fd->get_filename;
				   -d $file or err_dialog(N("Error!"), N("Should be a directory.")) and return;
				   $data->set_text($file);
				   $fd->hide;
				 }, $fd);
  $fd->cancel_button->signal_connect(clicked => sub { $fd->hide });
  return $fd;
};

sub get_samba_share() {
  undef @listshare;
  foreach my $clef (keys %$samba) {
    if ($samba->{$clef}{printable} =~ /yes/i || $clef =~ /print\$/) {
      print "$clef is a printer\n";
    } elsif ($clef =~ /global/ || $clef =~ /cdrom$/ || $clef eq "Profiles") {
      print "unwanted (special shares)\n";
    } else {
      push @listshare, {
			share_name => $clef,
			path => $samba->{$clef}{path},
			comment => $samba->{$clef}{comment},
			browseable => $samba->{$clef}{browseable},
			public => $samba->{$clef}{public},
			writable => $samba->{$clef}{writable},
			create_mask => $samba->{$clef}{'create mask'},
			directory_mask => $samba->{$clef}{'directory mask'},
			read_list => $samba->{$clef}{'read list'},
			write_list => $samba->{$clef}{'write list'},
			admin_users => $samba->{$clef}{'admin users'},
			valid_users => $samba->{$clef}{'valid users'},
			hide_dot_files => $samba->{$clef}{'hide dot files'},
			hide_files => $samba->{$clef}{'hide files'},
			preserve_case => $samba->{$clef}{'preserve case'},
			force_create_mode => $samba->{$clef}{'force create mode'},
			force_group => $samba->{$clef}{'force group'},
			default_case => $samba->{$clef}{'default case'},
			inherit_permissions => $samba->{$clef}{'inherit permissions'},
		       };
    }
  }
  return @listshare;
}

sub get_samba_printers() {
  undef @listprinters;
  foreach my $clef (keys %$samba) {
    if ($samba->{$clef}{printable} =~ /yes/i || $clef =~ /print\$/) {
      push @listprinters, {
			   share_name => $clef,
			   path => $samba->{$clef}{path},
			   comment => $samba->{$clef}{comment},
			   browseable => $samba->{$clef}{browseable},
			   printable => $samba->{$clef}{printable},
			   print_command => $samba->{$clef}{'print command'},
			   lpq_command => $samba->{$clef}{'lpq command'},
			   guest_ok => $samba->{$clef}{'guest ok'},
			   writable => $samba->{$clef}{writable},
			   write_list => $samba->{$clef}{'write list'},
			   inherit_permissions => $samba->{$clef}{'inherit permissions'},
			   printing => $samba->{$clef}{printing},
			   create_mode => $samba->{$clef}{'create mode'},
			   use_client_driver => $samba->{$clef}{'use client driver'},
			  };
    }
  }
  return @listprinters;
}

sub create_smbuser {
  my ($list) = @_;
  my @users = split(" ", $list);
  foreach my $user (@users) {
    if (!any { /^$user:/ } cat_("/etc/samba/smbpasswd")) {
      system("smbpasswd -a $user -n");
    }
  }
}

sub write_conf() {
  $samba->write_conf("/etc/samba/smb.conf");
}

sub create_pango_help_box {
  # perl code from draksec
  my ($help) = @_;
  my $text = Gtk2::TextView->new;
  use Gtk2::Pango;
  my %common_opts = ('left-margin' => '10', 'right-margin' => '10');
  gtktext_insert($text, [ map  {
    if (s!^/span>!!) {
      [ $_, \%common_opts ];
    } elsif (s!span !!) {
      my %tags = %common_opts;
      while (s!(\w+?)="(\w+?)"!!) {
	$tags{weight} ||= Gtk2::Pango->PANGO_WEIGHT_BOLD if $1 eq 'foreground';
	$tags{$1} = $2 eq "bold" ? Gtk2::Pango->PANGO_WEIGHT_BOLD : $2;
      }
      s/^>//;
      [ $_, \%tags ];
    } else {
      [ $_, \%common_opts ];
    }
  } split("<", formatAlaTeX($help)) ]);
  gtkset_size_request(create_scrolled_window($text), 350, 300);
}

sub help_b {
  my ($help_data) = @_;
  gtksignal_connect(new Gtk2::Button->new_from_stock('gtk-dialog-info'), clicked => sub {
		      my $dialog = _create_dialog();
		      $dialog->set_transient_for($::main_window);
		      $dialog->set_title(N("Help"));
		      $dialog->set_modal(1);
		      gtkpack_($dialog->vbox,
			       1, create_pango_help_box($help_data),
			       0, gtksignal_connect(Gtk2::Button->new_from_stock('gtk-close'), clicked => sub {
				   $dialog->destroy;
						    }
						   ),
			      );
		      $dialog->show_all;
		    }
		    );
}

sub printdollar_section() {
  $samba->{'print$'};
  $samba->{'print$'}{browseable} = "yes";
  $samba->{'print$'}{path} = "/var/lib/samba/printers";
  $samba->{'print$'}{browseable} = "yes";
  $samba->{'print$'}{'write list'} = "\@adm root";
  $samba->{'print$'}{'guest ok'} = "yes";
  $samba->{'print$'}{'inherit permissions'} = "yes";
}

sub pdf_section() {
  $samba->{'pdf-gen'};
  $samba->{'pdf-gen'}{path} = "/var/tmp";
  $samba->{'pdf-gen'}{'guest ok'} = "no";
  $samba->{'pdf-gen'}{printable} = "yes";
  $samba->{'pdf-gen'}{comment} = "PDF Generator (only valid users)";
  $samba->{'pdf-gen'}{printing} = "bsd";
  $samba->{'pdf-gen'}{'print command'} = '/usr/share/samba/scripts/print-pdf %s %H \//%L/%u\ %m %I %J &';
  $samba->{'pdf-gen'}{'lpq command'} = "/bin/true";
}

sub printers_section() {
  $samba->{printers};
  $samba->{comment} = "All Printers";
  $samba->{browseable} = "no";
  $samba->{'guest ok'} = "yes";
  $samba->{'create mode'} = "0700";
  $samba->{path} = "/var/spool/samba";
  $samba->{writable} = "no";
  $samba->{printable} = "yes";
  $samba->{'print command'} = 'lpr-cups -P %p -o raw %s -r';
  $samba->{'use client driver'} = "yes";
}

sub add_entry {
  use wizards;
  my ($wiz_addshare_name, $wiz_addshare_comment, $wiz_addshare_path, $wiz_addshare_browseable, $wiz_addshare_public);
  my $w = wizards->new;
  my $wiz = {
	     name => N("Add a Samba share"),
	     pages => {
		       welcome => {
				   name => N("Goal of this wizard is to easily create a new Samba share."),
				   data => [
					    { label => N("Name of the share:"), val => \$wiz_addshare_name },
					    { label => N("Comment:"), val => \$wiz_addshare_comment },
					    { label => N("Path:"), val => \$wiz_addshare_path },
					     ],
				   complete => sub {
				     foreach my $clef (keys %$samba) {
				       if ($clef =~ /$wiz_addshare_name/) {
					 err_dialog(N("Error"), N("Share with the same name already exist or share name empty, please choose another name.")) and return 'welcome';
				       }
				     }
				     if (!$wiz_addshare_path) {
				       err_dialog(N("Error"), N("Can\'t create the directory, please enter a correct path.")) and return 'welcome';
				     }
				     if (!$wiz_addshare_comment) {
				       err_dialog(N("Error"), N("Please enter a Comment for this share.")) and return 'welcome';
				     }
				     if (! -d $wiz_addshare_path) {
				       mkdir_p($wiz_addshare_path) or err_dialog(N("Error"), N("Can\'t create the directory, please enter a correct path.")) and return 'welcome';
				     }
				   },
				   post => sub {
				     push @{$printer_list->{data}}, [
								     $wiz_addshare_name,
								     $wiz_addshare_path,
								     $wiz_addshare_comment,
								    ];
				     my $share = $wiz_addshare_name;
				     # update listshare
				     push @listshare, {
						       share_name => $share,
						       path => $wiz_addshare_path,
						       comment => $wiz_addshare_comment,
						      };
				     # update samba conf
				     $samba->{$share};
				     $samba->{$share}{path} = $wiz_addshare_path;
				     $samba->{$share}{comment} = $wiz_addshare_comment;
				     return;
				   },
				   no_back => 1,
				   next => 'end_add',
				  },
		       end_add => {
				   name => N("Congratulations"),
				   data => [ { label => N("The wizard successfully added the Samba share. Now just double click on it in treeview to modify it") } ],
				   no_back => 1,
				   end => 1,
				   next => 0,
				  },
		      }
	    };
  $w->process($wiz, $in);
  $::isWizard = 0;
  gtkset_mousecursor_normal();
}

sub add_printers_entry {
  use wizards;
  my $w = wizards->new;
  my %print = (
	       1 => N("pdf-gen - a pdf generator"),
	       2 => N("printers - all printers available"),
	      );
  my $wiz_todo;
  my $wiz = {
	     name => N("Add Special Printer share"),
	     pages => {
		       welcome => {
				   name => N("Goal of this wizard is to easily create a new Samba share."),
				   data => [
					    { label => "", type => 'list', val => \$wiz_todo, list => [ keys %print ], format => sub { $print{$_[0]} } }
					   ],
				   no_back => 1,
				   post => sub {
				     if ($wiz_todo == 1) {
				       pdf_section;
				     } elsif ($wiz_todo == 2) {
				       printdollar_section;
				       printers_section;
				     }
				     return;
				   },
				  },
		       end_add => {
				   name => N("Congratulations"),
				   data => [ { label => N("The wizard successfully the Samba share") } ],
				   no_back => 1,
				   end => 1,
				   next => 0,
				  },
		      }
	    };
  $w->process($wiz, $in);
  $::isWizard = 0;
  #  gtkset_mousecursor_normal()
}

sub modify_printers_entry {
  my ($selected) = @_;
  my ($dir, $i, $path, $comment, $print_command, $guest_ok, $share_name, $browseable, $printable, $write_list, $printing, $lpq_command, $create_mode, $writable, $use_client_driver, $inherit_permissions);

  $share_name = Gtk2::Label->new;
  $_ = Gtk2::Entry->new foreach $dir, $path, $comment, $print_command, $write_list, $printing, $lpq_command, $create_mode;
  $_ = Gtk2::OptionMenu->new foreach $browseable, $printable, $guest_ok, $writable, $use_client_driver, $inherit_permissions;
  $_->set_popdown_strings(@yesno) foreach $browseable, $printable, $guest_ok, $writable, $use_client_driver, $inherit_permissions;

  $selected or info_dialog(N("Error"), N("Please add or select a Samba printer share to be able to modify it.")) and return;
  $share_name->set_text($printer_list->{data}[$selected][0]);
  $dir->set_text($printer_list->{data}[$selected][1]);
  $comment->set_text($printer_list->{data}[$selected][2]);
  $browseable->set_text($printer_list->{data}[$selected][3]);
  $printable->set_text($printer_list->{data}[$selected][4]);
  $print_command->set_text($printer_list->{data}[$selected][5]);
  $lpq_command->set_text($printer_list->{data}[$selected][6]);
  $guest_ok->set_text($printer_list->{data}[$selected][7]);
  $writable->set_text($printer_list->{data}[$selected][8]);
  $write_list->set_text($printer_list->{data}[$selected][9]);
  $inherit_permissions->set_text($printer_list->{data}[$selected][10]);
  $printing->set_text($printer_list->{data}[$selected][11]);
  $create_mode->set_text($printer_list->{data}[$selected][12]);
  $use_client_driver->set_text($printer_list->{data}[$selected][13]);

  my $file_dialog = $fdwidget->($dir, "");
  my $button = Gtk2::Button->new_from_stock('gtk-open');
  $button->signal_connect(clicked => sub { $file_dialog->show });

  my $dialog = _create_dialog();
  $dialog->set_transient_for($::main_window);
  local $::main_window = $dialog;
  $dialog->set_title("DrakSamba Printers entry");
  $dialog->set_position('center');
  $dialog->set_modal(1);
  $dialog->set_resizable(1);

  gtkpack_($dialog->vbox,
           0, gtkadd(Gtk2::Frame->new(N("Printer share")),
                     gtkpack_(gtkset_border_width(Gtk2::VBox->new, 5),
			      0, $label_and_widgets->(N("Printer name:"), $share_name, ""),
			      0, $label_and_widgets->(N("Directory:"), $dir, $button),
			      ),
                     ),
           0, gtkadd(Gtk2::Frame->new(N("Options")),
                     gtkpack_(gtkset_border_width(Gtk2::VBox->new, 5),
			      0, $label_and_widgets->(N("Printable"), $printable, ""),
			      0, $label_and_widgets->(N("Browseable:"), $browseable, ""),
			      0, $label_and_widgets->(N("Guest ok:"), $guest_ok, ""),
			      0, $label_and_widgets->(N("Print command:"), $print_command, ""),
			      ),
                     ),
	   0, create_okcancel({
			       cancel_clicked => sub { $dialog->destroy },
			       ok_clicked => sub {
				 $dialog->destroy;
			       }
			      },
			     ),
	   );
  $dialog->show_all;
}

sub modify_entry {
  my ($selected) = @_;
  my ($dir, $i, $path, $comment, $create_mask, $directory_mask, $read_list, $write_list, $admin_users, $valid_users, $force_group, $browseable, $public, $writable, $hide_files, $hide_dot_files, $force_create_mode, $preserve_case, $default_case, $inherit_permissions, $share_name);

  $share_name = Gtk2::Label->new;
  $_ = Gtk2::Entry->new foreach $dir, $path, $comment, $create_mask, $directory_mask, $hide_files;
  $_ = Gtk2::Entry->new foreach $read_list, $write_list, $admin_users, $valid_users, $force_group, $force_create_mode;
  $_ = Gtk2::OptionMenu->new foreach $browseable, $public, $writable, $default_case, $preserve_case, $hide_dot_files, $inherit_permissions;

  $default_case->set_popdown_strings(@default_case);
  $_->set_popdown_strings(@yesno) foreach $browseable, $public, $writable, $hide_dot_files, $preserve_case, $inherit_permissions;

  my $file_dialog = $fdwidget->($dir, "");
  my $button = Gtk2::Button->new_from_stock('gtk-open');
  $button->signal_connect(clicked => sub { $file_dialog->show });

  my $w = ugtk2->new(N("DrakSamba entry"));
  $w->{window}->set_modal(1);

  $selected or info_dialog(N("Error"), N("Please add or select a Samba share to be able to modify it.")) and return;

  $share_name->set_text($share_list->{data}[$selected][0]);
  $dir->set_text($share_list->{data}[$selected][1]);
  $comment->set_text($share_list->{data}[$selected][2]);
  $browseable->set_text($share_list->{data}[$selected][3]);
  $public->set_text($share_list->{data}[$selected][4]);
  $writable->set_text($share_list->{data}[$selected][5]);
  $create_mask->set_text($share_list->{data}[$selected][6]);
  $directory_mask->set_text($share_list->{data}[$selected][7]);
  $read_list->set_text($share_list->{data}[$selected][8]);
  $write_list->set_text($share_list->{data}[$selected][9]);
  $admin_users->set_text($share_list->{data}[$selected][10]);
  $valid_users->set_text($share_list->{data}[$selected][11]);
  $inherit_permissions->set_text($share_list->{data}[$selected][12]);
  $hide_dot_files->set_text($share_list->{data}[$selected][13]);
  $hide_files->set_text($share_list->{data}[$selected][14]);
  $preserve_case->set_text($share_list->{data}[$selected][15]);
  $force_create_mode->set_text($share_list->{data}[$selected][16]);
  $force_group->set_text($share_list->{data}[$selected][17]);
  $default_case->set_text($share_list->{data}[$selected][18]);

  my $expander_user = Gtk2::Expander->new('User options (user access, mask option, force mode)');
  $expander_user->add(gtkpack_(Gtk2::HBox->new,
			       0, gtkadd(Gtk2::Frame->new(N("Samba user access")),
					 gtkpack_(gtkset_border_width(Gtk2::VBox->new, 1),
						  0, $label_and_widgets->($adv_options{read_list}, $read_list, ""),
						  0, $label_and_widgets->($adv_options{write_list}, $write_list, ""),
						  0, $label_and_widgets->($adv_options{admin_users}, $admin_users, ""),
						  0, $label_and_widgets->($adv_options{valid_users}, $valid_users, ""),
						  ),
					 ),
			       0, gtkadd(Gtk2::Frame->new(N("Mask options")),
					 gtkpack_(gtkset_border_width(Gtk2::VBox->new, 1),
						  0, $label_and_widgets->($adv_options{create_mask}, $create_mask, ""),
						  0, $label_and_widgets->($adv_options{directory_mask}, $directory_mask, ""),
						  0, $label_and_widgets->($adv_options{force_group}, $force_group, ""),
						  0, $label_and_widgets->($adv_options{force_create_mode}, $force_create_mode, ""),
						  0, $label_and_widgets->($adv_options{inherit_permissions}, $inherit_permissions, ""),
						  ),
					 ),
			       ),
		      );
  
  my $expander_file = Gtk2::Expander->new('File options (hide files, case)');
  $expander_file->add(gtkpack_(Gtk2::VBox->new,
			       0, gtkadd(Gtk2::Frame->new(N("Display options")),
					 gtkpack_(gtkset_border_width(Gtk2::HBox->new, 1),
						  0, gtkpack_(gtkset_border_width(Gtk2::VBox->new, 0),
							      0, $label_and_widgets->($adv_options{hide_dot_files}, $hide_dot_files, ""),
							      0, $label_and_widgets->($adv_options{hide_files}, $hide_files, ""),
							      ),
						  0, Gtk2::VSeparator->new,
						  0, gtkpack_(gtkset_border_width(Gtk2::VBox->new, 0),
							      0, $label_and_widgets->($adv_options{default_case}, $default_case, ""),
							      0, $label_and_widgets->($adv_options{preserve_case}, $preserve_case, ""),
							      ),
						  ),
					 ),
			       ),
		      );

  $_->signal_connect(activate => sub {
		       $w->shrink_topwindow;
		     }) foreach $expander_file, $expander_user;

  gtkadd($w->{window},
	 gtknew('VBox', spacing => 0, children_loose => [
							 gtkadd(Gtk2::Frame->new(N("Samba share directory")),
								gtkpack_(gtkset_border_width(Gtk2::HBox->new, 1),
									 0, gtkpack_(gtkset_border_width(Gtk2::VBox->new, 0),
										     0, $label_and_widgets->(N("Share name:"), $share_name),
										     0, $label_and_widgets->(N("Directory:"), $dir, $button),
										     0, $label_and_widgets->(N("Comment:"), $comment, ""),
										     ),
									 0, Gtk2::VSeparator->new,
									 0, gtkpack_(gtkset_border_width(Gtk2::VBox->new, 0),
										     0, $label_and_widgets->(N("Public:"), $public, ""),
										     0, $label_and_widgets->(N("Writable:"), $writable, ""),
										     0, $label_and_widgets->(N("Browseable:"), $browseable, ""),
										    ),
									 ),
								),
							 gtkadd(Gtk2::Frame->new("Advanced options"),
								gtkpack_(gtkset_border_width(Gtk2::VBox->new, 1),
									 0, $expander_user,
									 0, Gtk2::HSeparator->new,
									 0, $expander_file,
									 ),
								),
							 create_okcancel({
							     cancel_clicked => sub { $w->destroy },
							     ok_clicked => sub {
							       my $share = $share_name->get_text;
							       my $test_dir = $dir->get_text;
							       $comment->get_text or err_dialog(N("Information"), N("Please enter a Comment for this share.")) and return 1;
							       if ($share !~ /^homes$/ and !-d $test_dir) {
								   err_dialog(N("Error!"), N("Please enter a directory to share.")) and return;
							       }
							       foreach ($create_mask->get_text, $directory_mask->get_text) {
								   if ($_ && !/^\d+$/) {
								       err_dialog(N("Error"), N("Create mask, create mode and directory mask should be numeric. ie: 0755.")) and return 1;
								   }
							       }
							       # update gui SimpleList
                                                               remove_entry($selected, $share_list);
							       push @{$share_list->{data}}, [
											     $share_name->get_text,
											     $dir->get_text,
											     $comment->get_text,
											     $browseable->get_text,
											     $public->get_text,
											     $writable->get_text,
											     $create_mask->get_text,
											     $directory_mask->get_text,
											     $read_list->get_text,
											     $write_list->get_text,
											     $admin_users->get_text,
											     $valid_users->get_text,
											     $hide_dot_files->get_text,
											     $hide_files->get_text,
											     $preserve_case->get_text,
											     $force_create_mode->get_text,
											     $force_group->get_text,
											     $default_case->get_text,
											     $inherit_permissions->get_text,
											    ];
							       # update $samba with the new value
							       # $samba->{$share};
							       $samba->{$share}{path} = $dir->get_text;
							       $samba->{$share}{comment} = $comment->get_text;
							       $browseable->get_text and $samba->{$share}{browseable} = $browseable->get_text || delete $samba->{$share}{browseable};
							       $public->get_text and $samba->{$share}{public} = $public->get_text || delete $samba->{$share}{public};
							       $writable->get_text and $samba->{$share}{writable} = $writable->get_text || delete $samba->{$share}{writable};
							       $create_mask->get_text and $samba->{$share}{'create mask'} = $create_mask->get_text || delete $samba->{$share}{'create mask'};
							       $directory_mask->get_text and $samba->{$share}{'directory mask'} = $directory_mask->get_text || delete $samba->{$share}{'directory mask'};
							       $read_list->get_text and $samba->{$share}{'read list'} = $read_list->get_text || delete $samba->{$share}{'read list'};
							       $write_list->get_text and $samba->{$share}{'write list'} = $write_list->get_text || delete $samba->{$share}{'write list'};
							       $admin_users->get_text and $samba->{$share}{'admin users'} = $admin_users->get_text || delete $samba->{$share}{'admin users'};
							       $valid_users->get_text and $samba->{$share}{'valid users'} = $valid_users->get_text || delete $samba->{$share}{'valid users'};
							       $hide_dot_files->get_text and $samba->{$share}{'hide dot files'} = $hide_dot_files->get_text || delete $samba->{$share}{'hide dot files'};
							       $hide_files->get_text and $samba->{$share}{'hide files'} = $hide_files->get_text || delete $samba->{$share}{'hide files'};
							       $preserve_case->get_text and $samba->{$share}{'preserve case'} = $preserve_case->get_text || delete $samba->{$share}{'preserve case'};
							       $force_create_mode->get_text and $samba->{$share}{'force create mode'} = $force_create_mode->get_text || delete $samba->{$share}{'force create mode'};
							       $force_group->get_text and $samba->{$share}{'force group'} = $force_group->get_text || delete $samba->{$share}{'force group'};
							       $default_case->get_text and $samba->{$share}{'default case'} = $default_case->get_text || delete $samba->{$share}{'default case'};
							       $inherit_permissions->get_text and $samba->{$share}{'inherit permissions'} = $inherit_permissions->get_text || delete $samba->{$share}{'inherit permissions'};

							       # update listshare
							       push @listshare, {
										 share_name => $share,
										 path => $samba->{$share}{path},
										 comment => $samba->{$share}{comment},
										 browseable => $samba->{$share}{browseable},
										 public => $samba->{$share}{public},
										 writable => $samba->{$share}{writable},
										 create_mask => $samba->{$share}{'create mask'},
										 directory_mask => $samba->{$share}{'directory mask'},
										 read_list => $samba->{$share}{'read list'},
										 write_list => $samba->{$share}{'write list'},
										 admin_users => $samba->{$share}{'admin users'},
										 valid_users => $samba->{$share}{'valid users'},
										 hide_dot_files => $samba->{$share}{'hide dot files'},
										 hide_files => $samba->{$share}{'hide files'},
										 preserve_case => $samba->{$share}{'preserve case'},
										 force_create_mode => $samba->{$share}{'force create mode'},
										 force_group => $samba->{$share}{'force group'},
										 default_case => $samba->{$share}{'default case'},
										 inherit_permissions => $samba->{$share}{'inherit permissions'},
										};

							       $w->destroy;
							     },
									 },
									),
							]
	       ),
	);
  $w->{window}->show_all;
}

sub remove_entry {
  my ($selected, $list) = @_;
  my $share_name = $list->{data}[$selected][0];
  ask_okcancel("Remove entry ?", "Remove $share_name") or return;
  splice @{$list->{data}}, $selected, 1;
  delete $samba->{$share_name};
}

sub add_data_share_list {
  my ($share_list) = @_;
  get_samba_share();
  foreach my $data (@listshare) {
    push @{$share_list->{data}}, [
				  $data->{share_name},
				  $data->{path},
				  $data->{comment},
				  $data->{browseable},
				  $data->{public},
				  $data->{writable},
				  $data->{create_mask},
				  $data->{directory_mask},
				  $data->{read_list},
				  $data->{write_list},
				  $data->{admin_users},
				  $data->{valid_users},
				  $data->{inherit_permissions},
				  $data->{hide_dot_files},
				  $data->{hide_files},
				  $data->{preserve_case},
				  $data->{force_create_mode},
				  $data->{force_group},
				  $data->{default_case},
				 ];
  }
}

sub add_data_printer_list {
  my ($printer_list) = @_;
  get_samba_printers();
  foreach my $data (@listprinters) {
    push @{$printer_list->{data}}, [
				    $data->{share_name},
				    $data->{path},
				    $data->{comment},
				    $data->{browseable},
				    $data->{printable},
				    $data->{print_command},
				    $data->{lpq_command},
				    $data->{guest_ok},
				    $data->{writable},
				    $data->{write_list},
				    $data->{inherit_permissions},
				    $data->{printing},
				    $data->{create_mode},
				    $data->{use_client_driver},
				   ];
  }
}

###############
# Main Program
###############
# create model
add_data_share_list($share_list);
add_data_printer_list($printer_list);

my $window = ugtk2->new("DrakSamba $version");
$::main_window = $window->{real_window};
$window->{rwindow}->set_size_request(550, 400) unless $::isEmbedded;
$window->{rwindow}->set_position('center') if !$::isEmbedded;
my $W = $window->{window};
$W->signal_connect(delete_event => sub { ugtk2->exit });

# double clic and popup modify window
$share_list->signal_connect(button_press_event => sub {
			      my (undef, $event) = @_;
			      my ($selected) = $share_list->get_selected_indices;
			      $selected and modify_entry($selected) if $event->type eq '2button-press';
			    });

$printer_list->signal_connect(button_press_event => sub {
				my (undef, $event) = @_;
				my ($selected) = $printer_list->get_selected_indices;
				$selected and modify_printers_entry($selected) if $event->type eq '2button-press';
			      });

# create menu
my @items = get_items();
my $factory = Gtk2::ItemFactory->new('Gtk2::MenuBar', '<main>', undef);
$factory->create_items('menu', @items);
my $menu = $factory->get_widget('<main>');

my $okcancel = create_okcancel({
				cancel_clicked => sub { ugtk2->exit },
				ok_clicked => sub { write_conf; ugtk2->exit },
			       },
			      );

gtkappend_page(my $nb = Gtk2::Notebook->new, gtkpack_(gtkset_border_width(Gtk2::HBox->new, 0),
                                                      1, create_scrolled_window($share_list),
						      0, gtkpack_(create_vbox('start'),
								  0, gtksignal_connect(Gtk2::Button->new(N("Add")), clicked => sub {
											 eval { add_entry() };
											 my $err = $@;
											 $::WizardWindow->destroy if defined $::WizardWindow;
											 undef $::WizardWindow;
											 if ($err && $err !~ /wizcancel/) {
											   err_dialog(N("Error"), N("Failed to add Samba share.") . "\n\n" . $err);
											 }
										       }),
								  0, Gtk2::HSeparator->new,
								  0, gtksignal_connect(Gtk2::Button->new(N("Modify")), clicked => sub {
											 my ($selected) = $share_list->get_selected_indices;
											 eval { modify_entry($selected, $share_list) };
											 my $err = $@;
											 if ($err) {
											   err_dialog(N("Error"), N("Failed to Modify Samba share.") . "\n\n" . $err);
											 }
										       }),
								  0, gtksignal_connect(Gtk2::Button->new(N("Remove")), clicked => sub {
											 my ($selected) = $share_list->get_selected_indices;
											 eval { remove_entry($selected, $share_list) };
											 my $err = $@;
											 if ($err) {
											   err_dialog(N("Error"), N("Failed to remove a Samba share.") . "\n\n" . $err);
											 }
										       }),
								 ),
						     ),
               gtkshow(Gtk2::Label->new(N("File Share"))));

gtkappend_page($nb, gtkpack_(gtkset_border_width(Gtk2::HBox->new, 0),
			     1, create_scrolled_window($printer_list),
                             0, gtkpack_(create_vbox('start'),
					 0, gtksignal_connect(Gtk2::Button->new(N("Add printers")), clicked => sub {
                                                                eval { add_printers_entry() };
                                                                my $err = $@;
								$::WizardWindow->destroy if defined $::WizardWindow;
								undef $::WizardWindow;
								if ($err && $err !~ /wizcancel/) {
                                                                  err_dialog(N("Error"), N("Failed to add printers.") . "\n\n" . $err);
                                                                }
                                                              }),
                                         0, Gtk2::HSeparator->new,
                                         0, gtksignal_connect(Gtk2::Button->new(N("Modify")), clicked => sub {
								my ($selected) = $printer_list->get_selected_indices;
                                                                eval { modify_printers_entry($selected) };
                                                                my $err = $@;
                                                                if ($err) {
                                                                  err_dialog(N("Error"), N("Failed to Modify.") . "\n\n" . $err);
                                                                }
                                                              }),
                                         0, gtksignal_connect(Gtk2::Button->new(N("Remove")), clicked => sub {
								my ($selected) = $printer_list->get_selected_indices;
                                                                eval { remove_entry($selected, $printer_list) };
                                                                my $err = $@;
                                                                if ($err) {
                                                                  err_dialog(N("Error"), N("Failed to remove.") . "\n\n" . $err);
                                                                }
                                                              }),
					),
			    ),
	       gtkshow(Gtk2::Label->new(N("Printers"))));
$nb->set_show_border(0);

# main interface
$W->add(gtkpack_(Gtk2::VBox->new(0,0),
		 0, $menu,
		 if_(!$::isEmbedded, 0, Gtk2::Banner->new('drakgw', N("DrakSamba manage Samba shares"))),
		 if_($::isEmbedded, 0, Gtk2::Label->new("Here you can add, remove and alter Samba shares.")),
		 1, $nb,
		 0, $okcancel,
		 ),
	);

$W->show_all;
Gtk2->main;