#!/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.2"; 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 Gtk2::Gdk::Keysyms; # 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 $icon_path = "/usr/lib/libDrakX/icons"; 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(); 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', ); $share_list->set_headers_clickable(1); foreach ($share_list->get_columns) { $_->set_resizable(1); } foreach (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('' => '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 = new Libconf::Glueconf::Samba::Smb_conf({ filename => '/etc/samba/smb.conf', show_commented_info => 1 }); 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"), ); 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' ], [ "/_About/Report a bug", undef, sub { unless (fork()) { exec("drakbug --report draksambashare &") } }, 1, '<StockItem>', 'gtk-stop' ], [ "/_About/About...", undef, sub { create_dialog(N("About Draksambashare"), N("Mandriva Linux \nRelease: %s\nAuthor: Antoine Ginies\n\nThis is a simple tool to easily manage Samba configuration.", $version)); }, 1, '<StockItem>', 'gtk-preferences' ], ); 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), if_($button, 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_user() { undef @listusers; foreach (cat_("/etc/samba/smbpasswd")) { 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 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->{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() { use wizards; my ($wiz_addshare_name, $wiz_addshare_comment, $wiz_addshare_path); 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 @{$share_list->{data}}, [ $pixbuf_file, $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 special printer Samba share."), data => [ { label => "", type => 'list', val => \$wiz_todo, list => [ keys %print ], format => sub { $print{$_[0]} } } ], no_back => 1, 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, }, } }; $w->process($wiz, $in); $::isWizard = 0; # gtkset_mousecursor_normal() } 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 $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); 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 $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); $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 !~ /^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; } } foreach ($read_list->get_text, $write_list->get_text, $admin_users->get_text, $valid_users->get_text) { my @users = split(" ", $_); foreach my $user (@users) { if (!any { /^$user:/ } cat_("/etc/samba/smbpasswd") and !/\@/) { 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, $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][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; local $_; foreach (cat_($conf)) { push @data, $1 if m/^([^#:]+):[^:]+:([^:]+):/ and $2 > 499; } push @data, " "; return sort(@data); } sub modify_user_info { my ($user, $passwd, $todo) = @_; my ($buser, $bpasswd); my $dialog = new Gtk2::Dialog(); $dialog->set_title("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}, ]; } } 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}, ]; } } ############### # 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 $share_list, $printer_list, $user_list; my $window = ugtk2->new("DrakSamba"); $::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 $share_list->signal_connect(button_press_event => sub { my (undef, $event) = @_; my ($selected) = $share_list->get_selected_indices; $share_list->{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) = $share_list->get_selected_indices; modify_entry($selected, $share_list); }); $menuitem2->signal_connect(activate => sub { my ($selected) = $share_list->get_selected_indices; ask_okcancel("Remove entry ?", "Remove $share_list->{data}[$selected][1]") or return; remove_entry($selected, $share_list); }); $_->show foreach $menuitem1, $menuitem2; $menupopup->append($_) foreach $menuitem1, $menuitem2; $share_list->signal_connect('button-press-event' => sub { my ($widget, $event) = @_; return unless $event->button == 3; $menupopup->popup(undef, undef, undef, undef, $event->button, $event->time); } ); $share_list->signal_connect(key_press_event => sub { my ($widget, $event) = @_; return unless $event->keyval == $Gtk2::Gdk::Keysyms{Return}; my ($selected) = $share_list->get_selected_indices; modify_entry($selected, $share_list); 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($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; ask_okcancel("Remove entry ?", "Remove $share_list->{data}[$selected][1]") or return; 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(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 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; 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("Change password")), 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, Gtk2::HSeparator->new, 0, gtksignal_connect(Gtk2::Button->new(N("Add user")), clicked => sub { eval { modify_user_info("", "", "add") }; my $err = $@; if ($err) { err_dialog(N("Error"), N("Failed to add user.") . "\n\n" . $err); } }), 0, gtksignal_connect(Gtk2::Button->new(N("Delete user")), 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, 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); # main interface $W->add(gtkpack_(Gtk2::VBox->new(0,0), 0, $menu, if_(!$::isEmbedded, 0, Gtk2::Banner->new('IC-winacces1-48', 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;