diff options
Diffstat (limited to 'bin/draksambashare')
-rwxr-xr-x | bin/draksambashare | 1474 |
1 files changed, 1474 insertions, 0 deletions
diff --git a/bin/draksambashare b/bin/draksambashare new file mode 100755 index 0000000..52684fe --- /dev/null +++ b/bin/draksambashare @@ -0,0 +1,1474 @@ +#!/usr/bin/perl +# -*- coding: utf-8 -*- +# Copyright (C) 2006-2008 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. + +use utf8; + +use lib qw(/usr/lib/libDrakX); + +# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX) +BEGIN { unshift @::textdomains, 'drakx-net' } +use standalone; +use common; +use network::network; +use interactive; +use mygtk2 qw(gtknew); +use ugtk2 qw(:ask :wrappers :create :dialogs); +use Gtk2::SimpleList; +use Gtk2::Gdk::Keysyms; +use run_program; + +# 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 exit(1); + +#if (!-f "/etc/sysconfig/wizard_samba") { +# $in->do_pkgs->ensure_is_installed('drakwizard', '/usr/sbin/drakwizard'); +# err_dialog(N("Error"), N("Please setup a samba server")) and return; +#} + +my $draksambashare = "/etc/sysconfig/draksambashare_first"; +my $icon_path = "/usr/lib/libDrakX/icons"; +my $sambaicon = "/usr/share/mcc/themes/default/diskdrake_samba.png"; +my $fileshare_icon = "$icon_path/IC-winacces2-16.png"; +my $printershare_icon = "$icon_path/IC-sambaprt-16.png"; +my $sambauser_icon = "$icon_path/ic82-users-16.png"; +my $pixbuf_file = Gtk2::Gdk::Pixbuf->new_from_file($fileshare_icon); +my $pixbuf_printer = Gtk2::Gdk::Pixbuf->new_from_file($printershare_icon); +my $pixbuf_user = Gtk2::Gdk::Pixbuf->new_from_file($sambauser_icon); + +my $printer_list = create_printer_list(); +my $share_list = create_share_list(); +my $user_list = create_user_list(); +my $display_share = create_display_share(); + +sub create_user_list() { + my $user_list = Gtk2::SimpleList->new('' => 'pixbuf', + N("User name") => 'text', + ); + $user_list; +} + +sub create_share_list() { + my $share_list = Gtk2::SimpleList->new('' => 'pixbuf', + 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', + ); + foreach (1, 2, 3) { + $share_list->get_column($_)->set_sort_column_id($_ == 0 ? 1 : $_ + 2); + } + $share_list; + } + +sub create_display_share() { + my $display_share = Gtk2::SimpleList->new('' => 'pixbuf', + N("Share name") => 'text', + N("Share directory") => 'text', + N("Comment") => 'text', + ); + $display_share->set_headers_clickable(1); + foreach ($share_list->get_columns) { + $_->set_resizable(1); + } + foreach (1, 2, 3) { + $display_share->get_column($_)->signal_connect('clicked', \&sort_by_column, $display_share->get_model); + $display_share->get_column($_)->set_sort_column_id($_ == 0 ? 1 : $_ + 2); + } + $display_share; +} + +sub create_printer_list() { + my $printer_list = Gtk2::SimpleList->new('' => 'pixbuf', + 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 (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 = Libconf::Glueconf::Samba::Smb_conf->new({ filename => '/etc/samba/smb.conf' }); +my (@listshare, @listprinters, @listusers); +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"), + ); + +my $window; + +sub get_items() { + my @items = ( + [ N("/_File"), undef, undef, undef, '<Branch>', ], + [ N("/_File") . N("/_Write conf"), undef, \&write_conf, 1, '<Item>', ], + [ N("/_File") . N("/_Quit"), N("<control>Q"), \&quit_all, 1, '<Item>', ], + + [ N("/_Samba Server"), undef, undef, undef, '<Branch>', ], + [ N("/_Samba Server") . N("/_Configure"), undef, \&launch_samba_wizard, 1, '<Item>', ], + [ N("/_Samba Server") . N("/_Restart"), undef, \&restart_dialog, 1, '<Item>', ], + [ N("/_Samba Server") . N("/R_eload"), undef, \&reload_dialog, 1, '<Item>', ], + + [ N("/_Help") . N("/_Samba Documentation"), undef, sub { + $in->do_pkgs->ensure_is_installed('samba-doc', '/usr/share/doc/samba-doc'); + system("/usr/bin/www-browser /usr/share/doc/samba-doc/htmldocs/index.html &") + }, + 1, '<Item>', ], + + [ N("/_About") . N("/_Report Bug"), undef, sub { run_program::raw({ detach => 1 }, 'drakbug', '--report', 'draksambashare') }, 1, '<Item>', ], + [ N("/_About") . N("/_About..."), undef, sub { + my $license = formatAlaTeX(translate($::license)); + $license =~ s/\n/\n\n/sg; # nicer formatting + my $w = gtknew('AboutDialog', name => N("Draksambashare"), + version => '2008', + copyright => N("Copyright (C) %s by Mandriva", '2001-2008'), + license => $license, wrap_license => 1, + comments => N("This is a simple tool to easily manage Samba configuration."), + website => 'http://mandrivalinux.com', + website_label => N("Mandriva Linux"), + authors => 'Antoine Ginies <aginies@mandriva.com>', + artists => 'Hélène Durosini <ln@mandriva.com>', + translator_credits => + #-PO: put here name(s) and email(s) of translator(s) (eg: "John Smith <jsmith@nowhere.com>") + N("_: Translator(s) name(s) & email(s)\n"), + transient_for => $window->{real_window}, modal => 1, position_policy => 'center-on-parent', + ); + $w->show_all; + $w->run; + }, 1, '<Item>', ], + ); + 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("Please wait"), 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), + if_($button, 0, gtkadd_widget($size_groups{button}, $button)), + ); +}; + +sub show_file_dialog { + my ($data) = @_; + my $file_dlg = gtknew('FileChooserDialog', title => N("Directory selection"), action => 'select_folder', + modal => 1, transient_for => $dlg); + $file_dlg->set_filename($data->get_text); + $file_dlg->show; + my $answer = $file_dlg->run; + if ($answer eq 'ok') { + my $file = $file_dlg->get_filename; + -d $file or err_dialog(N("Error!"), N("Should be a directory.")) and return; + $data->set_text($file); + } + $file_dlg->hide; + $file_dlg->destroy; +}; + +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'}, + inherit_permissions => $samba->{$clef}{'inherit permissions'}, + 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'}, + }; + } + } + return @listshare; +} + +sub get_samba_user() { + undef @listusers; + foreach (split '\n', `pdbedit -L -w`) { + my ($user) = m!^([\w-]+):!; + $user and push @listusers, { + user_name => $user, + }; + } + return @listusers; +} + + +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 write_conf() { + $samba->write_conf("/etc/samba/smb.conf"); +} + + +sub printdollar_section() { + $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'}{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}{comment} = "All Printers"; + $samba->{printers}{browseable} = "no"; + $samba->{printers}{'guest ok'} = "yes"; + $samba->{printers}{'create mode'} = "0700"; + $samba->{printers}{path} = "/var/spool/samba"; + $samba->{printers}{writable} = "no"; + $samba->{printers}{printable} = "yes"; + $samba->{printers}{'print command'} = 'lpr-cups -P %p -o raw %s -r'; + $samba->{printers}{'use client driver'} = "yes"; +} + +sub add_entry() { + my ($addshare_name, $addshare_comment, $addshare_dir); + $_ = Gtk2::Entry->new foreach $addshare_name, $addshare_comment, $addshare_dir; + my $button = Gtk2::Button->new(N("Open")); + $button->signal_connect(clicked => sub { show_file_dialog($addshare_dir); }); + + my $dialog = _create_dialog(N("DrakSamba add entry"), { transient_for => $::main_window, modal => 1 }); + local $::main_window = $dialog; + + gtkpack_($dialog->vbox, + 0, gtkadd(Gtk2::Frame->new(N("Add a share")), + gtkpack_(gtkset_border_width(Gtk2::VBox->new, 3), + 0, gtkpack_(gtkset_border_width(Gtk2::VBox->new, 1), + 0, $label_and_widgets->(N("Name of the share:"), $addshare_name, ""), + 0, $label_and_widgets->(N("Comment:"), $addshare_comment, ""), + 0, $label_and_widgets->(N("Directory:"), $addshare_dir, $button), + ), + 0, gtkpack_(gtkset_border_width(Gtk2::VBox->new, 1), + 0, create_okcancel({ + cancel_clicked => sub { $dialog->destroy }, + ok_clicked => sub { + my $share = $addshare_name->get_text; + my $comment = $addshare_comment->get_text; + my $test_dir = $addshare_dir->get_text; + foreach my $clef (keys %$samba) { + if ($clef =~ /\b$share\b/) { + err_dialog(N("Error"), N("Share with the same name already exist or share name empty, please choose another name.")) and return; + } + } + if ($share ne 'homes' && !-d $test_dir) { + err_dialog(N("Error!"), N("Please enter a directory to share.")) and return; + } + if (! -d $test_dir) { + mkdir_p($test_dir) or err_dialog(N("Error"), N("Can't create the directory, please enter a correct path.")) and return; + } + if (! $comment) { + err_dialog(N("Error"), N("Please enter a Comment for this share.")) and return; + } + push @{$share_list->{data}}, [ + $pixbuf_file, + $share, + $test_dir, + $comment, + ]; + push @{$display_share->{data}}, [ + $pixbuf_file, + $share, + $test_dir, + $comment, + ]; + # update listshare + push @listshare, { + share_name => $share, + path => $test_dir, + comment => $comment, + }; + # update samba conf + $samba->{$share}{path} = $test_dir; + $samba->{$share}{comment} = $comment; + $dialog->destroy; + } + } + ), + ), + ), + ), + ); + $dialog->show_all; +} + +sub add_printers_entry() { + require wizards; + my %print = ( + 1 => N("pdf-gen - a PDF generator"), + 2 => N("printers - all printers available"), + ); + my $wiz_todo; + my $wiz = wizards->new({ + name => N("Add Special Printer share"), + pages => { + welcome => { + name => N("Goal of this wizard is to easily create a new special printer Samba share."), + data => [ + { label => "", type => 'list', val => \$wiz_todo, list => [ keys %print ], format => sub { $print{$_[0]} } } + ], + next => 'end_add', + post => sub { + if ($wiz_todo == 1) { + exists $samba->{'pdf-gen'} and err_dialog(N("Error"), N("A PDF generator already exists.")) and return 'welcome'; + &pdf_section; + push @{$printer_list->{data}}, [ + $pixbuf_printer, + 'pdf-gen', + $samba->{'pdf-gen'}{path}, + $samba->{'pdf-gen'}{comment}, "", + $samba->{'pdf-gen'}{printable}, + $samba->{'pdf-gen'}{'print command'}, + $samba->{'pdf-gen'}{'lpq command'}, + $samba->{'pdf-gen'}{'guest ok'}, "", "", "", + $samba->{'pdf-gen'}{printing}, "", "", + ]; + push @listprinters, { + share_name => $samba->{'pdf-gen'}, + path => $samba->{'pdf-gen'}{path}, + comment => $samba->{'pdf-gen'}{comment}, + printebale => $samba->{'pdf-gen'}{printable}, + printing => $samba->{'pdf-gen'}{printing}, + print_command => $samba->{'pdf-gen'}{'print command'}, + lpq_command => $samba->{'pdf-gen'}{'lpq command'}, + guest_ok => $samba->{'pdf-gen'}{'guest ok'}, + }; + } elsif ($wiz_todo == 2) { + exists $samba->{'print$'} || exists $samba->{printers} and err_dialog(N("Error"), N("Printers and print\$ already exist.")) and return 'welcome'; + &printdollar_section; + &printers_section; + push @{$printer_list->{data}}, [ + $pixbuf_printer, + 'print$', + $samba->{'print$'}{path}, "", + $samba->{'print$'}{browseable}, "", "", "", + $samba->{'print$'}{'guest ok'}, "", + $samba->{'print$'}{'write list'}, + $samba->{'print$'}{'inherit permissions'}, + ]; + push @{$printer_list->{data}}, [ + $pixbuf_printer, + 'printers', + $samba->{printers}{path}, + $samba->{printers}{comment}, + $samba->{printers}{browseable}, + $samba->{printers}{printable}, + $samba->{printers}{'print command'}, "", + $samba->{printers}{'guest ok'}, + $samba->{printers}{writable}, "", "", "", + $samba->{printers}{'create mode'}, + $samba->{printers}{'use client driver'}, + ]; + push @listprinters, { + share_name => 'print$', + path => $samba->{'print$'}{path}, + browseable => $samba->{'print$'}{browseable}, + write_list => $samba->{'print$'}{'write list'}, + guest_ok => $samba->{'print$'}{'guest ok'}, + inherit_permissions => $samba->{'print$'}{'inherit permissions'}, + }; + push @listprinters, { + share_name => "printers", + comment => $samba->{printers}{comment}, + browseable => $samba->{printers}{browseable}, + guest_ok => $samba->{printers}{'guest ok'}, + create_mode => $samba->{printers}{'create mode'}, + path => $samba->{printers}{path}, + writable => $samba->{printers}{writable}, + printable => $samba->{printers}{printable}, + print_command => $samba->{printers}{'print command'}, + use_client_driver => $samba->{printers}{'use client driver'}, + }; + } + return; + }, + }, + end_add => { + name => N("Congratulations"), + data => [ { label => N("The wizard successfully added the printer Samba share") } ], + no_back => 1, + end => 1, + next => 0, + }, + } + }); + $wiz->process($in); + $::isWizard = 0; +} + +sub modify_printers_entry { + my ($selected) = @_; + my ($dir, $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, $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; + + + my $s = $printer_list->{data}[$selected][1]; + $s 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($s); + $dir->set_text($printer_list->{data}[$selected][2]); + $comment->set_text($printer_list->{data}[$selected][3]); + $browseable->set_text($printer_list->{data}[$selected][4]); + $printable->set_text($printer_list->{data}[$selected][5]); + $print_command->set_text($printer_list->{data}[$selected][6]); + $lpq_command->set_text($printer_list->{data}[$selected][7]); + $guest_ok->set_text($printer_list->{data}[$selected][8]); + $writable->set_text($printer_list->{data}[$selected][9]); + $write_list->set_text($printer_list->{data}[$selected][10]); + $inherit_permissions->set_text($printer_list->{data}[$selected][11]); + $printing->set_text($printer_list->{data}[$selected][12]); + $create_mode->set_text($printer_list->{data}[$selected][13]); + $use_client_driver->set_text($printer_list->{data}[$selected][14]); + + my $button = Gtk2::Button->new(N("Open")); + $button->signal_connect(clicked => sub { show_file_dialog($dir); }); + + my $dialog = _create_dialog(N("DrakSamba Printers entry"), { transient_for => $::main_window, modal => 1 }); + + local $::main_window = $dialog; + + if ($s eq "printers") { $printable->set_text("yes"); + $printing->set_text(""); + $_->set_sensitive(0) foreach $printable, $printing; + } + if ($s eq "pdf-gen") { $printing->set_text("bsd"); + $printing->set_sensitive(0); + } + + gtkpack_($dialog->vbox, + 0, gtkadd(Gtk2::Frame->new(N("Printer share")), + gtkpack_(gtkset_border_width(Gtk2::HBox->new, 3), + 0, gtkpack_(gtkset_border_width(Gtk2::VBox->new, 1), + 0, $label_and_widgets->(N("Printer name:"), $share_name, ""), + 0, $label_and_widgets->(N("Comment:"), $comment, ""), + 0, $label_and_widgets->(N("Directory:"), $dir, $button), + ), + 0, Gtk2::VSeparator->new, + 0, gtkpack_(gtkset_border_width(Gtk2::VBox->new, 1), + 0, $label_and_widgets->(N("Writable:"), $writable, ""), + 0, $label_and_widgets->(N("Browseable:"), $browseable, ""), + 0, $label_and_widgets->(N("Printable"), $printable, ""), + ), + ), + ), + 0, gtkadd(Gtk2::Frame->new(N("Advanced options")), + gtkpack_(gtkset_border_width(Gtk2::HBox->new, 3), + 0, gtkadd(Gtk2::Frame->new(N("Printer access")), + gtkpack_(gtkset_border_width(Gtk2::VBox->new, 1), + 0, $label_and_widgets->(N("Write list"), $write_list, ""), + 0, $label_and_widgets->(N("Inherit permissions"), $inherit_permissions, ""), + 0, $label_and_widgets->(N("Guest ok:"), $guest_ok, ""), + 0, $label_and_widgets->(N("Create mode:"), $create_mode, ""), + ), + ), + 0, Gtk2::VSeparator->new, + 0, gtkadd(Gtk2::Frame->new(N("Printer command")), + gtkpack_(gtkset_border_width(Gtk2::VBox->new, 1), + 0, $label_and_widgets->(N("Print command:"), $print_command, ""), + 0, $label_and_widgets->(N("LPQ command:"), $lpq_command, ""), + 0, $label_and_widgets->(N("Printing:"), $printing, ""), + ), + ), + ), + ), + 0, create_okcancel({ + cancel_clicked => sub { $dialog->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 (!-d $test_dir) { + err_dialog(N("Error!"), N("Please enter a directory to share.")) and return; + } + foreach ($create_mode->get_text) { + if ($_ && !/^\d+$/) { + err_dialog(N("Error"), N("create mode should be numeric. ie: 0755.")) and return 1; + } + } + # update gui SimpleList + remove_entry($selected, $printer_list); + push @{$printer_list->{data}}, [ + $pixbuf_printer, + $share, + $dir->get_text, + $comment->get_text, + $browseable->get_text, + $printable->get_text, + $print_command->get_text, + $lpq_command->get_text, + $guest_ok->get_text, + $writable->get_text, + $write_list->get_text, + $inherit_permissions->get_text, + $printing->get_text, + $create_mode->get_text, + $use_client_driver->get_text, + ]; + # update $samba + $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}; + $printable->get_text and $samba->{$share}{printable} = $printable->get_text || delete $samba->{$share}{printable}; + $print_command->get_text and $samba->{$share}{'print command'} = $print_command->get_text || delete $samba->{$share}{'print command'}; + $lpq_command->get_text and $samba->{$share}{'lpq command'} = $lpq_command->get_text || delete $samba->{$share}{'lpq command'}; + $guest_ok->get_text and $samba->{$share}{'guest ok'} = $guest_ok->get_text || delete $samba->{$share}{'guest ok'}; + $writable->get_text and $samba->{$share}{writable} = $writable->get_text || delete $samba->{$share}{writable}; + $write_list->get_text and $samba->{$share}{'write list'} = $write_list->get_text || delete $samba->{$share}{'write list'}; + $inherit_permissions->get_text and $samba->{$share}{'inherit permissions'} = $inherit_permissions->get_text || delete $samba->{$share}{'inherit permissions'}; + $printing->get_text and $samba->{$share}{printing} = $printing->get_text || delete $samba->{$share}{printing}; + $create_mode->get_text and $samba->{$share}{'create mode'} = $create_mode->get_text || delete $samba->{$share}{'create mode'}; + $use_client_driver->get_text and $samba->{$share}{'use client driver'} = $use_client_driver->get_text || delete $samba->{$share}{'use client driver'}; + + # + $dialog->destroy; + } + }, + ), + ); + $dialog->show_all; +} + +sub modify_entry { + my ($selected) = @_; + my ($dir, $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, $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 $button = Gtk2::Button->new(N("Open")); + $button->signal_connect(clicked => sub { show_file_dialog($dir); }); + + my $w = ugtk2->new(N("DrakSamba entry")); + $w->{window}->set_modal(1); + $w->{window}->set_position('center'); + + my $s = $share_list->{data}[$selected][1]; + $s 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($s); + $dir->set_text($share_list->{data}[$selected][2]); + $comment->set_text($share_list->{data}[$selected][3]); + $browseable->set_text($share_list->{data}[$selected][4]); + $public->set_text($share_list->{data}[$selected][5]); + $writable->set_text($share_list->{data}[$selected][6]); + $create_mask->set_text($share_list->{data}[$selected][7]); + $directory_mask->set_text($share_list->{data}[$selected][8]); + $read_list->set_text($share_list->{data}[$selected][9]); + $write_list->set_text($share_list->{data}[$selected][10]); + $admin_users->set_text($share_list->{data}[$selected][11]); + $valid_users->set_text($share_list->{data}[$selected][12]); + $inherit_permissions->set_text($share_list->{data}[$selected][13]); + $hide_dot_files->set_text($share_list->{data}[$selected][14]); + $hide_files->set_text($share_list->{data}[$selected][15]); + $preserve_case->set_text($share_list->{data}[$selected][16]); + $force_create_mode->set_text($share_list->{data}[$selected][17]); + $force_group->set_text($share_list->{data}[$selected][18]); + $default_case->set_text($share_list->{data}[$selected][19]); + + 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 ne 'homes' && !-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; + } + } + foreach ($read_list->get_text, $write_list->get_text, $admin_users->get_text, $valid_users->get_text) { + my @users = split(" ", $_); + my @known_users = split("\n", `pdbedit -L -w`); + foreach my $user (@users) { + if (!(any { /^$user:/ } @known_users) && !/\@/) { + err_dialog(N("Error"), N("Please create this Samba user: %s", $user)) and return; + } + } + } + # update gui SimpleList + remove_entry($selected, $share_list); + push @{$share_list->{data}}, [ + $pixbuf_file, + $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, + $inherit_permissions->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, + ]; + remove_entry($selected, $display_share); + push @{$display_share->{data}}, [ + $pixbuf_file, + $share_name->get_text, + $dir->get_text, + $comment->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'}; + $inherit_permissions->get_text and $samba->{$share}{'inherit permissions'} = $inherit_permissions->get_text || delete $samba->{$share}{'inherit permissions'}; + $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'}; + + # 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'}, + inherit_permissions => $samba->{$share}{'inherit permissions'}, + 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'}, + }; + $w->destroy; + }, + }, + ), + ] + ), + ); + $w->{window}->show_all; +} + +sub remove_entry { + my ($selected, $list) = @_; + my $share_name = $list->{data}[$selected][1]; + splice @{$list->{data}}, $selected, 1; + delete $samba->{$share_name}; +} + +sub remove_user { + my ($user) = @_; + system("smbpasswd -x $user"); +} + +sub get_user() { + my $conf = "/etc/passwd"; + my @data = map { if_(m/^([^#:]+):[^:]+:([^:]+):/ && $2 > 499, $1) } cat_($conf); + return sort(@data, " "); +} + + +sub modify_user_info { + my ($user, $_passwd, $todo) = @_; + my ($buser, $bpasswd); + my $dialog = new Gtk2::Dialog(); + $dialog->set_title(N("Add Samba user")); + $dialog->set_modal(1); + $dialog->set_position('center'); + $dialog->set_resizable(0); + if ($todo eq "add") { + $buser = Gtk2::ComboBox->new_with_strings([ get_user() ]); + $buser->set_wrap_width(3); + } else { + $buser = Gtk2::Label->new; + $buser->set_text($user); + } + $bpasswd = Gtk2::Entry->new; + $bpasswd->set_visibility(0); + + gtkpack_($dialog->vbox, + 0, gtkadd(Gtk2::Frame->new(N("User information")), + gtkpack_(gtkset_border_width(Gtk2::VBox->new, 5), + 0, $label_and_widgets->(N("User name:"), $buser, ""), + 0, $label_and_widgets->(N("Password:"), $bpasswd, ""), + ), + ), + 0, create_okcancel({ + cancel_clicked => sub { $dialog->destroy }, + ok_clicked => sub { + my $user_selected = $buser->get_text; + if ($todo eq "add") { + if (any { /^$user_selected:/ } cat_("/etc/samba/smbpasswd")) { + err_dialog(N("Error"), ("Samba User already exist")) and return; + } + system("smbpasswd -a $user_selected -n"); + push @{$user_list->{data}}, [ + $pixbuf_user, + $user_selected, + ]; + push @listusers, { + user_name => $user_selected, + }; + } + my $passwd_e = $bpasswd->get_text; + set_user_passwd($user_selected, $passwd_e); + $dialog->destroy; + } + }, + ), + ); + $dialog->show_all; +} + +sub set_user_passwd { + my ($user, $passwd) = @_; + my $F; + open($F, '|' . qq(smbpasswd $user -s)); + print $F "$passwd\n"; + print $F "$passwd\n"; + close $F; +} + +sub add_data_share_list { + my ($share_list) = @_; + get_samba_share(); + + foreach my $data (@listshare) { + push @{$share_list->{data}}, [ + $pixbuf_file, + $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}, + ]; + push @{$display_share->{data}}, [ + $pixbuf_file, + $data->{share_name}, + $data->{path}, + $data->{comment}, + ]; + } +} + +sub add_data_user_list { + my ($user_list) = @_; + get_samba_user(); + foreach my $data (@listusers) { + push @{$user_list->{data}}, [ + $pixbuf_user, + $data->{user_name}, + ]; + } +} + +sub add_data_printer_list { + my ($printer_list) = @_; + get_samba_printers(); + foreach my $data (@listprinters) { + push @{$printer_list->{data}}, [ + $pixbuf_printer, + $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}, + ]; + } +} + + +sub configure_samba { + require wizards; + my %type = ( + 2 => N("PDC - primary domain controller"), + 3 => N("Standalone - standalone server"), + ); + my @yesorno = qw(yes no); push @yesorno, ""; + my @loglevel = qw(0 1 2 3 4 5 6 7 8 9); + my @security_list = qw(share user domain); + my $wiz = wizards->new({ + name => N("Samba Wizard"), + pages => { + welcome => { + name => N("Samba server configuration Wizard") . "\n\n" . N("Samba allows your server to behave as a file and print server for workstations running non-Linux systems."), + #no_back => 1, + pre => sub { + $o->{var}{wiz_type} = "3"; + }, + post => sub { + if ($o->{var}{wiz_type} == 2) { + return 'pdc' } + elsif ($o->{var}{wiz_type} == 3) { + return 'ask_workgroup' } + }, + data => [ + { label => "", val => \$o->{var}{wiz_type}, type => 'list', list => [ sort keys %type ], format => sub { $type{$_[0]} } }, + ], + }, + pdc => { + name => N("PDC server: primary domain controller") . "\n\n" . N("Server configured as a PDC is responsible for Windows authentication throughout the domain.") . "\n" . N("Single server installations may use smbpasswd or tdbsam password backends") . "\n" . N("Domain master = yes, causes the server to register the NetBIOS name <pdc name>. This name will be recognized by other servers."), + pre => sub { + $o->{var}{wiz_domain_master} = "yes"; + $o->{var}{wiz_security} = "user"; + $o->{var}{wiz_domain_logons} = "yes"; + $o->{var}{wiz_wins_support} ||= $samba->{global}{'wins support'}; + $o->{var}{wiz_oslevel} = "128"; + if (exists $samba->{global}{'passdb backend'}) { + $o->{var}{wiz_passdb_backend_yn} = "yes"; + } + else { + $o->{var}{wiz_passdb_backend_yn} = "no"; + } + }, + data => [ + #{ label => N("Domain logons:"), val_ref => \$o->{var}{wiz_domain_logons} }, + #{ label => N("Domain master:"), val_ref => \$o->{var}{wiz_domain_master} }, + { label => N("Wins support:"), val => \$o->{var}{wiz_wins_support}, list => \@yesorno }, + { label => N("admin users:"), val => \$o->{var}{wiz_admin_users}, help => N("root \@adm") }, + { label => N("Os level:"), val_ref => \$o->{var}{wiz_oslevel}, help => N("The global os level option dictates the operating system level at which Samba will masquerade during a browser election. If you wish to have Samba win an election and become the master browser, you can set the level above that of the operating system on your network with the highest current value. ie: os level = 34") }, + ], + complete => sub { + if (!$o->{var}{wiz_domain_master}) { + $in->ask_warn(N("Error"), N("The domain is wrong.")); + return 1; + } else { return 0 } + }, + next => 'ask_workgroup', + }, + ask_workgroup => { + name => N("Workgroup") . "\n\n" . N("Samba needs to know the Windows Workgroup it will serve."), + pre => sub { + $o->{var}{wiz_workgroup} ||= $samba->{global}{workgroup}; + $o->{var}{wiz_netbios} ||= $samba->{global}{netbios}; + $o->{var}{wiz_netbios_name} ||= $samba->{global}{"netbios name"}; + }, + data => [ + { label => N("Workgroup:"), val => \$o->{var}{wiz_workgroup} }, + { label => N("Netbios name:"), val => \$o->{var}{wiz_netbios_name} }, + ], + complete => sub { + if (!$o->{var}{wiz_workgroup}) { + $in->ask_warn(N("Error"), N("The Workgroup is wrong.")); + return 1; + } else { return 0 } + }, + next => 'ask_security', + }, + ask_security => { + name => N("Security mode") . "\n\n" . N("User level: the client sends a session setup request directly following protocol negotiation. This request provides a username and password.") . "\n" . N("Share level: the client authenticates itself separately for each share") . "\n" . N("Domain level: provides a mechanism for storing all user and group accounts in a central, shared, account repository. The centralized account repository is shared between domain (security) controllers."), + pre => sub { + $o->{var}{wiz_security} ||= $samba->{global}{security}; + $o->{var}{host_allow} ||= $samba->{global}{'hosts allow'}; + if ($o->{var}{wiz_type} == 3) { + # remove domain security mode for standalone server + pop(@security_list); + } + }, + data => [ + { label => N("Security mode"), val => \$o->{var}{wiz_security}, list => \@security_list }, + { label => N("Hosts allow"), val => \$o->{var}{hosts_allow}, help => "127. 192.168.0. 192.168.1.253" }, + ], + next => 'ask_banner', + }, + ask_banner => { + name => N("Server Banner.") . "\n\n" . N("The banner is the way this server will be described in the Windows workstations."), + pre => sub { + $o->{var}{wiz_banner} ||= $samba->{global}{'server string'}; + }, + data => [ + { label => N("Banner:"), val => \$o->{var}{wiz_banner}, help => "Samba Server %v" }, + ], + complete => sub { + if (!$o->{var}{wiz_banner}) { + $in->ask_warn(N("Error"), N("The Server Banner is incorrect.")); + return 1; + } else { return 0 } + }, + next => 'ask_log', + }, + ask_log => { + name => N("Samba Log") . "\n" . N("Log file: use file.%m to use a separate log file for each machine that connects") . "\n" . N("Log level: set the log (verbosity) level (0 <= log level <= 10)") . "\n" . N("Max Log size: put a capping on the size of the log files (in Kb)."), + pre => sub { + $o->{var}{wiz_log_file} ||= $samba->{global}{'log file'}; + $o->{var}{wiz_log_level} ||= $samba->{global}{'log level'}; + $o->{var}{wiz_max_log_size} ||= $samba->{global}{'max log size'}; + }, + data => [ + { label => N("Log file:"), val => \$o->{var}{wiz_log_file}, help => "/var/log/samba/log.%m" }, + { label => N("Max log size:"), val => \$o->{var}{wiz_max_log_size}, help => "50" }, + { label => N("Log level:"), val => \$o->{var}{wiz_log_level}, list => \@loglevel }, + ], + next => 'summary', + }, + summary => { + name => N("The wizard collected the following parameters to configure Samba.") . "\n\n" . N("To accept these values, and configure your server, click the Next button or use the Back button to correct them.") . "\n" . N("If you have previously create some shares, they will appear in this configuration. Run 'drakwizard sambashare' to manage your shares."), + pre => sub { + $o->{var}{wiz_sambatype} = $type{$o->{var}{wiz_type}}; + $o->{var}{wiz_unixcharset} ||= $samba->{global}{'unix charset'}; + $o->{var}{wiz_doscharset} ||= $samba->{global}{'dos charset'}; + $o->{var}{wiz_displaycharset} ||= $samba->{global}{'display charset'}; + }, + data => [ + { label => N("Samba type:"), val_ref => \$o->{var}{wiz_sambatype} }, + { label => N("Workgroup:"), val_ref => \$o->{var}{wiz_workgroup} }, + { label => N("Server banner:"), val_ref => \$o->{var}{wiz_banner} }, + { label => N("Log file:"), val_ref => \$o->{var}{wiz_log_file} }, + { text => N(" "), advanced => 1 }, + { label => N("Unix Charset:"), val => \$o->{var}{wiz_unixcharset}, help => "Unix Charset pecifies the charset the unix machine Samba runs on uses.", advanced => 1 }, + { label => N("Dos Charset:"), val => \$o->{var}{wiz_doscharset}, help => "Dos Charset specifies which charset Samba should talk to DOS clients.", advanced => 1 }, + { label => N("Display Charset:"), val => \$o->{var}{wiz_displaycharset}, help=> "Display Charset specifies the charset that samba will use to print messages to stdout and stderr. The default value is 'LOCALE', which means automatically set, depending on the current locale.", advanced => 1 }, + ], + post => sub { + $samba->{global}{workgroup} = $o->{var}{wiz_workgroup}; + $o->{var}{wiz_netbios_name} ? $samba->{global}{"netbios name"} = $o->{var}{wiz_netbios_name} : delete $samba->{global}{"netbios name"}; + $samba->{global}{'server string'} = $o->{var}{wiz_banner}; + $o->{var}{wiz_log_file} and $samba->{global}{'log file'} = $o->{var}{wiz_log_file}; + $o->{var}{wiz_log_level} and $samba->{global}{'log level'} = $o->{var}{wiz_log_level}; + $o->{var}{wiz_max_log_size} and $samba->{global}{'max log size'} = $o->{var}{wiz_max_log_size}; + global_special_options(); + }, + next => 'endconf', + }, + endconf => { + pre => sub { output($draksambashare, "draksambshare check") }, + name => N("Congratulations") . "\n\n" . N("The wizard successfully configured your Samba server."), + no_back => 1, + end => 1, + }, + }, + }); + $wiz->process($in); + $::isWizard = 0; +} + +sub global_special_options() { + # set charset + $o->{var}{wiz_doscharset} ? $samba->{global}{'dos charset'} = $o->{var}{wiz_doscharset} : delete $samba->{global}{'dos charset'}; + $o->{var}{wiz_unixcharset} ? $samba->{global}{'unix charset'} = $o->{var}{wiz_unixcharset} : delete $samba->{global}{'unix charset'}; + $o->{var}{wiz_displaycharset} ? $samba->{global}{'display charset'} = $o->{var}{wiz_displaycharset} : delete $samba->{global}{'display charset'}; + $o->{var}{wiz_security} ? $samba->{global}{security} = $o->{var}{wiz_security} : delete $samba->{global}{security}; + $o->{var}{hosts_allow} ? $samba->{global}{'hosts allow'} = $o->{var}{hosts_allow} : delete $samba->{global}{'hosts allow'}; +# $samba->{global}{security} = $o->{var}{wiz_security}; + # detect Samba type 3 is standalone + if ($o->{var}{wiz_type} == "3") { + exists $samba->{global}{domain_master} and delete $samba->{global}{domain_master}; + exists $samba->{global}{'domain logons'} and delete $samba->{global}{'domain logons'}; + exists $samba->{global}{'wins support'} and delete $samba->{global}{'wins support'}; + exists $samba->{global}{'os level'} and delete $samba->{global}{'os level'}; + } else { + # so pdc + $o->{var}{wiz_local_master} and $samba->{global}{'local master'} = $o->{var}{wiz_local_master}; + $o->{var}{wiz_preferred_master} and $samba->{global}{'preferred master'} = $o->{var}{wiz_preferred_master}; + $o->{var}{wiz_wins_server} and $samba->{global}{'wins server'} = $o->{var}{wiz_wins_server}; + $o->{var}{wiz_name_resolve_order} and $samba->{global}{'name resolve order'} = $o->{var}{wiz_name_resolve_order}; + $o->{var}{wiz_dns_proxy} and $samba->{global}{'dns proxy'} = $o->{var}{wiz_dns_proxy}; + $o->{var}{wiz_domain_master} and $samba->{global}{'domain master'} = $o->{var}{wiz_domain_master}; + $o->{var}{wiz_domain_logons} and $samba->{global}{'domain logons'} = $o->{var}{wiz_domain_logons}; + $o->{var}{wiz_oslevel} and $samba->{global}{'os level'} = $o->{var}{wiz_oslevel}; + $o->{var}{wiz_passdb_backend} and $samba->{global}{'passdb backend'} = $o->{var}{wiz_passdb_backend}; + $o->{var}{wiz_wins_support} and $samba->{global}{'wins support'} = $o->{var}{wiz_wins_support}; + $o->{var}{wiz_password_server} and $samba->{global}{'password server'} = $o->{var}{wiz_password_server}; + $o->{var}{wiz_admin_users} and $samba->{global}{'admin users'} = $o->{var}{wiz_admin_users}; + $samba->{global}{'add machine script'} = "/usr/sbin/useradd -d /dev/null -g machines -c 'Machine Account' -s /bin/false -M '%u'"; + + } + my $conf = "/etc/group"; + my @groups; + foreach (cat_($conf)) { + push @groups, $1 if m/^([^#:]+):[^:]+:([^:]+):/ and $2 > 499; + } + foreach (@groups) { + system("net groupmap add unixgroup=$_ ntgroup=$_"); + } +} + +sub launch_samba_wizard() { + eval { configure_samba() }; + my $err = $@; + if ($err && $err !~ /wizcancel/) { + err_dialog(N("Error"), N("The Samba wizard has unexpectedly failed:") . "\n\n" . $err); + } +} + +############### +# Main Program +############### +# create model +add_data_share_list($share_list); +add_data_printer_list($printer_list); +add_data_user_list($user_list); +$_->set_rules_hint(1) foreach $display_share, $printer_list, $user_list; + +$ugtk2::wm_icon = $fileshare_icon; +$window = ugtk2->new(N("Manage Samba configuration")); +$::main_window = $window->{real_window}; +$window->{rwindow}->set_size_request(600, 410) 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 +$display_share->signal_connect(button_press_event => sub { + my (undef, $event) = @_; + my ($selected) = $display_share->get_selected_indices; + $display_share->{data}[$selected][1] 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; + $printer_list->{data}[$selected][1] and modify_printers_entry($selected) if $event->type eq '2button-press'; + }); + +$user_list->signal_connect(button_press_event => sub { + my (undef, $event) = @_; + my ($selected) = $user_list->get_selected_indices; + $user_list->{data}[$selected][1] and modify_user_info($user_list->{data}[$selected][1], "", "change") if $event->type eq '2button-press'; + }); + +# dont know why "$event->type eq '2button-press'" when starting draksambashare so i can't use mapn :/ +#mapn { +# $_[0]->signal_connect(button_press_event => sub { +# my (undef, $event) = @_; +# my ($selected) = $_[0]->get_selected_indices; +# return unless $event->type eq '2button-press'; +# $_[0]->{data}[$selected][1] and $_[1]($selected); # if $event->type eq '2button-press'; +# }); +#} [ $share_list, $printer_list, $user_list ], [ modify_entry, modify_printers_entry, modify_user_info ]; + +# create popup menu +my $menupopup = Gtk2::Menu->new; +my $menuitem1 = Gtk2::MenuItem->new(N("Modify")); +my $menuitem2 = Gtk2::MenuItem->new(N("Remove")); +$menuitem1->signal_connect(activate => sub { + my ($selected) = $display_share->get_selected_indices; + modify_entry($selected); + }); +$menuitem2->signal_connect(activate => sub { + my ($selected) = $display_share->get_selected_indices; + ask_okcancel("Remove entry ?", "Remove $display_share->{data}[$selected][1]") or return; + remove_entry($selected, $display_share); + }); +$_->show foreach $menuitem1, $menuitem2; +$menupopup->append($_) foreach $menuitem1, $menuitem2; +$display_share->signal_connect('button-press-event' => sub { + my (undef, $event) = @_; + return unless $event->button == 3; + $menupopup->popup(undef, undef, undef, undef, $event->button, $event->time); + } + ); + +$display_share->signal_connect(key_press_event => sub { + my (undef, $event) = @_; + return unless $event->keyval == $Gtk2::Gdk::Keysyms{Return}; + my ($selected) = $display_share->get_selected_indices; + modify_entry($selected); + return 1; +}); + +# 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($display_share), + 0, gtkpack_(create_vbox('start'), + 0, gtksignal_connect(Gtk2::Button->new(N("Add")), clicked => \&add_entry), + 0, Gtk2::HSeparator->new, + 0, gtksignal_connect(Gtk2::Button->new(N("Modify")), clicked => sub { + my ($selected) = $display_share->get_selected_indices; + eval { modify_entry($selected) }; + 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) = $display_share->get_selected_indices; + ask_okcancel("Remove entry ?", "Remove $display_share->{data}[$selected][1]") or return; + eval { remove_entry($selected, $display_share) }; + my $err = $@; + if ($err) { + err_dialog(N("Error"), N("Failed to remove a Samba share.") . "\n\n" . $err); + } + }), + ), + ), + gtkshow(gtkpack_(Gtk2::HBox->new(0,0), + 0, Gtk2::Image->new_from_file($fileshare_icon), + 0, 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")), clicked => \&add_printers_entry), + 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; + ask_okcancel("Remove entry ?", "Remove $printer_list->{data}[$selected][1]") or return; + eval { remove_entry($selected, $printer_list) }; + my $err = $@; + if ($err) { + err_dialog(N("Error"), N("Failed to remove.") . "\n\n" . $err); + } + }), + ), + ), + gtkshow(gtkpack_(Gtk2::HBox->new(0,0), + 0, Gtk2::Image->new_from_file($printershare_icon), + 0, Gtk2::Label->new(N("Printers")), + ), + ), + ); + +gtkappend_page($nb, gtkpack_(gtkset_border_width(Gtk2::HBox->new, 0), + 1, create_scrolled_window($user_list), + 0, gtkpack_(create_vbox('start'), + 0, gtksignal_connect(Gtk2::Button->new(N("Add")), clicked => sub { + eval { modify_user_info("", "", "add") }; + my $err = $@; + if ($err) { + err_dialog(N("Error"), N("Failed to add user.") . "\n\n" . $err); + } + }), + 0, Gtk2::HSeparator->new, + 0, gtksignal_connect(Gtk2::Button->new(N("Modify")), clicked => sub { + my ($selected) = $user_list->get_selected_indices; + eval { modify_user_info($user_list->{data}[$selected][1], "", "change") }; + my $err = $@; + if ($err) { + err_dialog(N("Error"), N("Failed to change user password.") . "\n\n" . $err); + } + }), + 0, gtksignal_connect(Gtk2::Button->new(N("Remove")), clicked => sub { + my ($selected) = $user_list->get_selected_indices; + ask_okcancel("Remove entry ?", "Remove $user_list->{data}[$selected][1]") or return; + eval { + remove_user($user_list->{data}[$selected][1]); + remove_entry($selected, $user_list); + }; + my $err = $@; + if ($err) { + err_dialog(N("Error"), N("Failed to delete user.") . "\n\n" . $err); + } + }), + 0, Gtk2::HSeparator->new, + # FIXME: Why do we have both an "add" button and a "userdrake" one ??? + 0, gtksignal_connect(Gtk2::Button->new(N("Userdrake")), clicked => sub { + run_program::raw({ detach => 1 }, 'userdrake'); + } + ), + ), + ), + gtkshow(gtkpack_(Gtk2::HBox->new(0,0), + 0, Gtk2::Image->new_from_file($sambauser_icon), + 0, Gtk2::Label->new(N("Samba Users"))), + ), + ); + +$nb->set_show_border(0); + +sub check_first_launch() { + if (!-f $draksambashare) { + info_dialog(N("Please configure your Samba server"), N("It seems this is the first time you run this tool.\nA wizard will appear to configure a basic Samba server")); +# local $::isEmbedded = 0; + launch_samba_wizard(); + } +} + +# main interface +$W->add(gtkpack_(Gtk2::VBox->new(0,0), + 0, $menu, + 0, Gtk2::Banner->new($sambaicon, N("DrakSamba manage Samba shares")), + #if_($::isEmbedded, 0, Gtk2::Label->new("Here you can add, remove and alter Samba shares.")), + 1, $nb, + 0, $okcancel, + ), + ); + +check_first_launch; +$W->show_all; +Gtk2->main; |