aboutsummaryrefslogtreecommitdiffstats
path: root/lib/AdminPanel/Module
diff options
context:
space:
mode:
authorAngelo Naselli <anaselli@linux.it>2014-06-01 23:30:37 +0200
committerAngelo Naselli <anaselli@linux.it>2014-06-01 23:30:37 +0200
commitdd51b5f1520293c9c4a6a3ddc1d85dd779228748 (patch)
tree11e82833197e24f740d149ac2770e521e02d72bf /lib/AdminPanel/Module
parentc113abab36e1c3eaec2167017da3aa31e940f269 (diff)
downloadmanatools-dd51b5f1520293c9c4a6a3ddc1d85dd779228748.tar
manatools-dd51b5f1520293c9c4a6a3ddc1d85dd779228748.tar.gz
manatools-dd51b5f1520293c9c4a6a3ddc1d85dd779228748.tar.bz2
manatools-dd51b5f1520293c9c4a6a3ddc1d85dd779228748.tar.xz
manatools-dd51b5f1520293c9c4a6a3ddc1d85dd779228748.zip
Used our own AdminPanel::Shared modules
Diffstat (limited to 'lib/AdminPanel/Module')
-rw-r--r--lib/AdminPanel/Module/Users.pm403
1 files changed, 225 insertions, 178 deletions
diff --git a/lib/AdminPanel/Module/Users.pm b/lib/AdminPanel/Module/Users.pm
index 1deacd62..935f6e9a 100644
--- a/lib/AdminPanel/Module/Users.pm
+++ b/lib/AdminPanel/Module/Users.pm
@@ -73,15 +73,6 @@ use strict;
use POSIX qw(ceil);
# use Time::localtime;
-# TODO same translation atm
-use lib qw(/usr/lib/libDrakX);
-# i18n: IMPORTANT: to get correct namespace (userdrake instead of libDrakX)
-BEGIN { unshift @::textdomains, 'userdrake', 'libuser', 'drakconf' }
-
-use common qw(N
- translate);
-use security::level;
-# use run_program;
use Config::Auto;
use File::ShareDir ':ALL';
@@ -89,12 +80,14 @@ use File::ShareDir ':ALL';
## USER is from userdrake
use USER;
use utf8;
-use log;
+use Sys::Syslog;
use Glib;
use yui;
use AdminPanel::Shared;
+use AdminPanel::Shared::Locales;
use AdminPanel::Shared::Users;
+
use Moose;
extends qw( AdminPanel::Module );
@@ -102,11 +95,6 @@ has '+icon' => (
default => "/usr/share/icons/userdrake.png",
);
-has '+name' => (
- default => N("AdminUser"),
-);
-
-
# main dialog
has 'dialog' => (
@@ -169,6 +157,34 @@ has 'edit_tab_widgets' => (
init_arg => undef,
);
+has 'sh_users' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_SharedUsersInitialize'
+);
+
+sub _SharedUsersInitialize {
+ my $self = shift();
+
+ $self->sh_users(AdminPanel::Shared::Users->new() );
+}
+
+has 'loc' => (
+ is => 'rw',
+ init_arg => undef,
+ builder => '_localeInitialize'
+);
+
+
+sub _localeInitialize {
+ my $self = shift();
+
+ # TODO fix domain binding for translation
+ $self->loc(AdminPanel::Shared::Locales->new(domain_name => 'userdrake') );
+ # TODO if we want to give the opportunity to test locally add dir_name => 'path'
+}
+
+
#=============================================================
=head1 METHODS
@@ -229,18 +245,51 @@ sub _labeledFrameBox {
# usefull local variable to avoid duplicating
# translation point for user edit labels
-my %userEditLabel = (
- user_data => N("User Data"),
- account_info => N("Account Info"),
- password_info => N("Password Info"),
- groups => N("Groups"),
-);
+my %userEditLabel;
# usefull local variable to avoid duplicating
# translation point for group edit labels
-my %groupEditLabel = (
- group_data => N("Group Data"),
- group_users => N("Group Users"),
-);
+my %groupEditLabel;
+
+
+#=============================================================
+
+=head2 BUILD
+
+=head3 INPUT
+
+ $self: this object
+
+=head3 DESCRIPTION
+
+ The BUILD method is called after a Moose object is created,
+ Into this method additional data are initialized.
+
+=cut
+
+#=============================================================
+sub BUILD {
+ my $self = shift;
+
+ if (! $self->name) {
+ $self->name ($self->loc->N("Log viewer"));
+ }
+
+
+ %userEditLabel = (
+ user_data => $self->loc->N("User Data"),
+ account_info => $self->loc->N("Account Info"),
+ password_info => $self->loc->N("Password Info"),
+ groups => $self->loc->N("Groups"),
+ );
+ %groupEditLabel = (
+ group_data => $self->loc->N("Group Data"),
+ group_users => $self->loc->N("Group Users"),
+ );
+
+
+}
+
+
#=============================================================
=head2 ChooseGroup
@@ -270,7 +319,7 @@ sub ChooseGroup {
## push application title
my $appTitle = yui::YUI::app()->applicationTitle();
## set new title to get it in dialog
- yui::YUI::app()->setApplicationTitle(N("Choose group"));
+ yui::YUI::app()->setApplicationTitle($self->loc->N("Choose group"));
my $factory = yui::YUI::widgetFactory;
@@ -278,24 +327,24 @@ sub ChooseGroup {
my $layout = $factory->createVBox($dlg);
- my $frame = _labeledFrameBox($layout, N("A group with this name already exists. What would you like to do?"));
+ my $frame = _labeledFrameBox($layout, $self->loc->N("A group with this name already exists. What would you like to do?"));
my $rbg = $factory->createRadioButtonGroup( $frame );
$frame = $factory->createVBox( $rbg );
my $align = $factory->createLeft($frame);
- my $rb1 = $factory->createRadioButton( $align, N("Add to the existing group"), 1);
+ my $rb1 = $factory->createRadioButton( $align, $self->loc->N("Add to the existing group"), 1);
$rb1->setNotify(1);
$rbg->addRadioButton( $rb1 );
$align = $factory->createLeft($frame);
- my $rb2 = $factory->createRadioButton( $align, N("Add to the 'users' group"), 0);
+ my $rb2 = $factory->createRadioButton( $align, $self->loc->N("Add to the 'users' group"), 0);
$rb2->setNotify(1);
$rbg->addRadioButton( $rb2 );
my $hbox = $factory->createHBox($layout);
$align = $factory->createRight($hbox);
- my $cancelButton = $factory->createPushButton($align, N("Cancel"));
- my $okButton = $factory->createPushButton($hbox, N("Ok"));
+ my $cancelButton = $factory->createPushButton($align, $self->loc->N("Cancel"));
+ my $okButton = $factory->createPushButton($hbox, $self->loc->N("Ok"));
while(1) {
my $event = $dlg->waitForEvent();
my $eventType = $event->eventType();
@@ -379,7 +428,7 @@ sub _deleteGroupDialog {
## push application title
my $appTitle = yui::YUI::app()->applicationTitle();
## set new title to get it in dialog
- yui::YUI::app()->setApplicationTitle(N("Warning"));
+ yui::YUI::app()->setApplicationTitle($self->loc->N("Warning"));
my $factory = yui::YUI::widgetFactory;
my $dlg = $factory->createPopupDialog();
@@ -387,13 +436,13 @@ sub _deleteGroupDialog {
my $align = $factory->createLeft($layout);
- $factory->createLabel($align, N("Do you really want to delete the group %s?",
+ $factory->createLabel($align, $self->loc->N("Do you really want to delete the group %s?",
$groupname));
$align = $factory->createRight($layout);
my $hbox = $factory->createHBox($align);
- my $cancelButton = $factory->createPushButton($hbox, N("Cancel"));
- my $deleteButton = $factory->createPushButton($hbox, N("Delete"));
+ my $cancelButton = $factory->createPushButton($hbox, $self->loc->N("Cancel"));
+ my $deleteButton = $factory->createPushButton($hbox, $self->loc->N("Delete"));
while(1) {
my $event = $dlg->waitForEvent();
@@ -416,14 +465,14 @@ sub _deleteGroupDialog {
GLOOP: foreach my $username (@$members) {
my $userEnt = $self->ctx->LookupUserByName($username);
if ($userEnt && $userEnt->Gid($self->USER_GetValue) == $groupEnt->Gid($self->USER_GetValue)) {
- AdminPanel::Shared::msgBox(N("%s is a primary group for user %s\n Remove the user first",
+ AdminPanel::Shared::msgBox($self->loc->N("%s is a primary group for user %s\n Remove the user first",
$groupname, $username));
$continue = 0;
last GLOOP;
}
}
if ($continue) {
- log::explanations(N("Removing group: %s", $groupname));
+ Sys::Syslog::syslog('info|local1', $self->loc->N("Removing group: %s", $groupname));
eval { $self->ctx->GroupDel($groupEnt) };
$self->_refresh();
}
@@ -469,24 +518,24 @@ sub _deleteUserDialog {
## push application title
my $appTitle = yui::YUI::app()->applicationTitle();
## set new title to get it in dialog
- yui::YUI::app()->setApplicationTitle(N("Delete files or not?"));
+ yui::YUI::app()->setApplicationTitle($self->loc->N("Delete files or not?"));
my $factory = yui::YUI::widgetFactory;
my $dlg = $factory->createPopupDialog();
my $layout = $factory->createVBox($dlg);
my $align = $factory->createLeft($layout);
- $factory->createLabel($align, N("Deleting user %s\nAlso perform the following actions\n",
+ $factory->createLabel($align, $self->loc->N("Deleting user %s\nAlso perform the following actions\n",
$username));
$align = $factory->createLeft($layout);
- my $checkhome = $factory->createCheckBox($align, N("Delete Home Directory: %s", $homedir, 0));
+ my $checkhome = $factory->createCheckBox($align, $self->loc->N("Delete Home Directory: %s", $homedir), 0);
$align = $factory->createLeft($layout);
- my $checkspool = $factory->createCheckBox($align, N("Delete Mailbox: /var/spool/mail/%s",
+ my $checkspool = $factory->createCheckBox($align, $self->loc->N("Delete Mailbox: /var/spool/mail/%s",
$username), 0);
$align = $factory->createRight($layout);
my $hbox = $factory->createHBox($align);
- my $cancelButton = $factory->createPushButton($hbox, N("Cancel"));
- my $deleteButton = $factory->createPushButton($hbox, N("Delete"));
+ my $cancelButton = $factory->createPushButton($hbox, $self->loc->N("Cancel"));
+ my $deleteButton = $factory->createPushButton($hbox, $self->loc->N("Delete"));
if ($homedir !~ m!(?:/home|/var/spool)!) {
$checkhome->setDisabled();
@@ -509,7 +558,7 @@ sub _deleteUserDialog {
last;
}
elsif ($widget == $deleteButton) {
- log::explanations(N("Removing user: %s", $username));
+ Sys::Syslog::syslog('info|local1', $self->loc->N("Removing user: %s", $username));
$self->ctx->UserDel($userEnt);
$self->_updateOrDelUserInGroup($username);
#Let's check out the user's primary group
@@ -551,7 +600,7 @@ sub _addGroupDialog {
## push application title
my $appTitle = yui::YUI::app()->applicationTitle();
## set new title to get it in dialog
- yui::YUI::app()->setApplicationTitle(N("Create New Group"));
+ yui::YUI::app()->setApplicationTitle($self->loc->N("Create New Group"));
my $factory = yui::YUI::widgetFactory;
my $optional = yui::YUI::optionalWidgetFactory;
@@ -561,7 +610,7 @@ sub _addGroupDialog {
## 'group name'
my $align = $factory->createRight($layout);
my $hbox = $factory->createHBox($align);
- my $label = $factory->createLabel($hbox, N("Group Name:") );
+ my $label = $factory->createLabel($hbox, $self->loc->N("Group Name:") );
my $groupName = $factory->createInputField($hbox, "", 0);
$label->setWeight($yui::YD_HORIZ, 1);
$groupName->setWeight($yui::YD_HORIZ, 2);
@@ -571,16 +620,16 @@ sub _addGroupDialog {
# Specify group id manually
$align = $factory->createLeft($layout);
$hbox = $factory->createHBox($align);
- my $gidManually = $factory->createCheckBox($hbox, N("Specify group ID manually"), 0);
+ my $gidManually = $factory->createCheckBox($hbox, $self->loc->N("Specify group ID manually"), 0);
$factory->createHSpacing($hbox, 2);
- my $GID = $factory->createIntField($hbox, N("GID"), 1, 65000, 500);
+ my $GID = $factory->createIntField($hbox, $self->loc->N("GID"), 1, 65000, 500);
$GID->setEnabled($gidManually->value());
$gidManually->setNotify(1);
$hbox = $factory->createHBox($layout);
$align = $factory->createRight($hbox);
- my $cancelButton = $factory->createPushButton($align, N("Cancel"));
- my $okButton = $factory->createPushButton($hbox, N("Ok"));
+ my $cancelButton = $factory->createPushButton($align, $self->loc->N("Cancel"));
+ my $okButton = $factory->createPushButton($hbox, $self->loc->N("Ok"));
while(1) {
my $event = $dlg->waitForEvent();
my $eventType = $event->eventType();
@@ -602,11 +651,11 @@ sub _addGroupDialog {
elsif ($widget == $okButton) {
## check data
my $groupname = $groupName->value();
- my ($continue, $errorString) = valid_groupname($groupname);
+ my ($continue, $errorString) = $self->sh_users->valid_groupname($groupname);
my $nm = $continue && $self->ctx->LookupGroupByName($groupname);
if ($nm) {
$groupName->setValue("");
- $errorString = N("Group already exists, please choose another Group Name");
+ $errorString = $self->loc->N("Group already exists, please choose another Group Name");
$continue = 0;
}
my $groupEnt = $self->ctx->InitGroup($groupname, $is_system);
@@ -615,15 +664,15 @@ sub _addGroupDialog {
if ($continue && $gidManually->value()) {
if (($gid = $GID->value()) < 500) {
$errorString = "";
- my $gidchoice = AdminPanel::Shared::ask_YesOrNo(N(" Group Gid is < 500"),
- N("Creating a group with a GID less than 500 is not recommended.\n Are you sure you want to do this?\n\n"));
+ my $gidchoice = AdminPanel::Shared::ask_YesOrNo($self->loc->N(" Group Gid is < 500"),
+ $self->loc->N("Creating a group with a GID less than 500 is not recommended.\n Are you sure you want to do this?\n\n"));
$continue = $gidchoice and $groupEnt->Gid($gid);
} else {
my $g = $self->ctx->LookupGroupById($gid);
if ($g) {
$errorString = "";
- my $gidchoice = AdminPanel::Shared::ask_YesOrNo(N(" Group ID is already used "),
- N("Creating a group with a non unique GID?\n\n"));
+ my $gidchoice = AdminPanel::Shared::ask_YesOrNo($self->loc->N(" Group ID is already used "),
+ $self->loc->N("Creating a group with a non unique GID?\n\n"));
$continue = $gidchoice and $groupEnt->Gid($gid);
}
else {
@@ -638,7 +687,7 @@ sub _addGroupDialog {
AdminPanel::Shared::msgBox($errorString) if ($errorString);
}
else {
- log::explanations(N("Adding group: %s ", $groupname));
+ Sys::Syslog::syslog('info|local1', $self->loc->N("Adding group: %s ", $groupname));
$self->ctx->GroupAdd($groupEnt);
$self->_refresh();
last;
@@ -689,7 +738,7 @@ sub _buildUserData {
## user 'full name'
my $align = $factory->createRight($layout);
my $hbox = $factory->createHBox($align);
- my $label = $factory->createLabel($hbox, N("Full Name:") );
+ my $label = $factory->createLabel($hbox, $self->loc->N("Full Name:") );
$factory->createHSpacing($hbox, 2.0);
my $fullName = $factory->createInputField($hbox, "", 0);
$label->setWeight($yui::YD_HORIZ, 1);
@@ -698,7 +747,7 @@ sub _buildUserData {
## user 'login name'
$align = $factory->createRight($layout);
$hbox = $factory->createHBox($align);
- $label = $factory->createLabel($hbox, N("Login:") );
+ $label = $factory->createLabel($hbox, $self->loc->N("Login:") );
$factory->createHSpacing($hbox, 2.0);
my $loginName = $factory->createInputField($hbox, "", 0);
$label->setWeight($yui::YD_HORIZ, 1);
@@ -708,7 +757,7 @@ sub _buildUserData {
## user 'Password'
$align = $factory->createRight($layout);
$hbox = $factory->createHBox($align);
- $label = $factory->createLabel($hbox, N("Password:") );
+ $label = $factory->createLabel($hbox, $self->loc->N("Password:") );
my $weakness = undef;
if (yui::YUI::app()->hasImageSupport()) {
$factory->createHSpacing($hbox, 2.0);
@@ -730,7 +779,7 @@ sub _buildUserData {
## user 'confirm Password'
$align = $factory->createRight($layout);
$hbox = $factory->createHBox($align);
- $label = $factory->createLabel($hbox, N("Confirm Password:") );
+ $label = $factory->createLabel($hbox, $self->loc->N("Confirm Password:") );
$factory->createHSpacing($hbox, 2.0);
my $password1 = $factory->createInputField($hbox, "", 1);
$label->setWeight($yui::YD_HORIZ, 1);
@@ -739,7 +788,7 @@ sub _buildUserData {
## user 'Login Shell'
$align = $factory->createRight($layout);
$hbox = $factory->createHBox($align);
- $label = $factory->createLabel($hbox, N("Login Shell:") );
+ $label = $factory->createLabel($hbox, $self->loc->N("Login Shell:") );
$factory->createHSpacing($hbox, 2.0);
my $loginShell = $factory->createComboBox($hbox, "", 0);
my $itemColl = new yui::YItemCollection;
@@ -797,7 +846,7 @@ sub addUserDialog {
yui::YUI::app()->setApplicationTitle($self->name);
}
else {
- yui::YUI::app()->setApplicationTitle(N("Create New User"));
+ yui::YUI::app()->setApplicationTitle($self->loc->N("Create New User"));
}
my $factory = yui::YUI::widgetFactory;
@@ -812,11 +861,11 @@ sub addUserDialog {
## Create Home directory
my $align = $factory->createLeft($layout);
my $hbox = $factory->createHBox($align);
- my $createHome = $factory->createCheckBox($hbox, N("Create Home Directory"), 1);
+ my $createHome = $factory->createCheckBox($hbox, $self->loc->N("Create Home Directory"), 1);
## Home directory
$align = $factory->createLeft($layout);
$hbox = $factory->createHBox($align);
- my $label = $factory->createLabel($hbox, N("Home Directory:") );
+ my $label = $factory->createLabel($hbox, $self->loc->N("Home Directory:") );
$factory->createHSpacing($hbox, 2.0);
my $homeDir = $factory->createInputField($hbox, "", 0);
$label->setWeight($yui::YD_HORIZ, 1);
@@ -825,14 +874,14 @@ sub addUserDialog {
# Create private group
$align = $factory->createLeft($layout);
$hbox = $factory->createHBox($align);
- my $createGroup = $factory->createCheckBox($hbox, N("Create a private group for the user"), 1);
+ my $createGroup = $factory->createCheckBox($hbox, $self->loc->N("Create a private group for the user"), 1);
# Specify user id manually
$align = $factory->createRight($layout);
$hbox = $factory->createHBox($align);
- my $uidManually = $factory->createCheckBox($hbox, N("Specify user ID manually"), 0);
+ my $uidManually = $factory->createCheckBox($hbox, $self->loc->N("Specify user ID manually"), 0);
$factory->createHSpacing($hbox, 2.0);
- my $UID = $factory->createIntField($hbox, N("UID"), 1, 65000, 500);
+ my $UID = $factory->createIntField($hbox, $self->loc->N("UID"), 1, 65000, 500);
$UID->setEnabled($uidManually->value());
$uidManually->setNotify(1);
# $uidManually->setWeight($yui::YD_HORIZ, 2);
@@ -840,16 +889,16 @@ sub addUserDialog {
## user 'icon'
$hbox = $factory->createHBox($layout);
- $factory->createLabel($hbox, N("Click on icon to change it") );
- my $iconFace = AdminPanel::Shared::Users::GetFaceIcon();
+ $factory->createLabel($hbox, $self->loc->N("Click on icon to change it") );
+ my $iconFace = $self->sh_users->GetFaceIcon();
my $icon = $factory->createPushButton($hbox, "");
- $icon->setIcon(AdminPanel::Shared::Users::face2png($iconFace));
+ $icon->setIcon($self->sh_users->face2png($iconFace));
$icon->setLabel($iconFace);
$hbox = $factory->createHBox($layout);
$align = $factory->createRight($hbox);
- my $cancelButton = $factory->createPushButton($align, N("Cancel"));
- my $okButton = $factory->createPushButton($hbox, N("Ok"));
+ my $cancelButton = $factory->createPushButton($align, $self->loc->N("Cancel"));
+ my $okButton = $factory->createPushButton($hbox, $self->loc->N("Ok"));
while(1) {
my $event = $dlg->waitForEvent();
my $eventType = $event->eventType();
@@ -868,9 +917,9 @@ sub addUserDialog {
#remove shortcut from label
my $iconLabel = $self->_skipShortcut($icon->label());
- my $nextIcon = GetFaceIcon($icon->label(), 1);
+ my $nextIcon = $self->sh_users->GetFaceIcon($icon->label(), 1);
$icon->setLabel($nextIcon);
- $icon->setIcon(AdminPanel::Shared::Users::face2png($nextIcon));
+ $icon->setIcon($self->sh_users->face2png($nextIcon));
}
elsif ($widget == $uidManually) {
# UID inserction enabled?
@@ -887,22 +936,21 @@ sub addUserDialog {
elsif ($widget == $okButton) {
## check data
my $username = $userData{ login_name }->value();
- my ($continue, $errorString) = valid_username($username);
+ my ($continue, $errorString) = $self->sh_users->valid_username($username);
my $nm = $continue && $self->ctx->LookupUserByName($username);
if ($nm) {
$userData{ login_name }->setValue("");
$homeDir->setValue("");
- $errorString = N("User already exists, please choose another User Name");
+ $errorString = $self->loc->N("User already exists, please choose another User Name");
$continue = 0;
}
my $passwd = $continue && $userData{ password }->value();
if ($continue && $passwd ne $userData{ password1 }->value()) {
- $errorString = N("Password Mismatch");
+ $errorString = $self->loc->N("Password Mismatch");
$continue = 0;
}
- my $sec = security::level::get();
- if ($sec > 3 && length($passwd) < 6) {
- $errorString = N("This password is too simple. \n Good passwords should be > 6 characters");
+ if ($self->sh_users->weakPasswordForSecurityLevel($passwd)) {
+ $errorString = $self->loc->N("This password is too simple. \n Good passwords should be > 6 characters");
$continue = 0;
}
my $userEnt = $continue && $self->ctx->InitUser($username, $is_system);
@@ -917,8 +965,8 @@ sub addUserDialog {
if ($continue && $uidManually->value()) {
if (($uid = $UID->value()) < 500) {
$errorString = "";
- my $uidchoice = AdminPanel::Shared::ask_YesOrNo(N("User Uid is < 500"),
- N("Creating a user with a UID less than 500 is not recommended.\nAre you sure you want to do this?\n\n"));
+ my $uidchoice = AdminPanel::Shared::ask_YesOrNo($self->loc->N("User Uid is < 500"),
+ $self->loc->N("Creating a user with a UID less than 500 is not recommended.\nAre you sure you want to do this?\n\n"));
$continue = $uidchoice and $userEnt->Uid($uid);
} else {
$userEnt and $userEnt->Uid($uid);
@@ -936,9 +984,9 @@ sub addUserDialog {
$gid = $gr->Gid($self->USER_GetValue);
} elsif ($groupchoice == 1) {
# Put it in 'users' group
- log::explanations(N("Putting %s to 'users' group",
+ Sys::Syslog::syslog('info|local1', $self->loc->N("Putting %s to 'users' group",
$username));
- $gid = AdminPanel::Shared::Users::Add2UsersGroup($username, $self->ctx);
+ $gid = $self->sh_users->Add2UsersGroup($username, $self->ctx);
}
else {
$errorString = "";
@@ -947,13 +995,13 @@ sub addUserDialog {
} else {
#it's a new group: Add it
my $newgroup = $self->ctx->InitGroup($username,$is_system);
- log::explanations(N("Creating new group: %s", $username));
+ Sys::Syslog::syslog('info|local1', $self->loc->N("Creating new group: %s", $username));
$gid = $newgroup->Gid($self->USER_GetValue);
$self->ctx->GroupAdd($newgroup);
}
}
} else {
- $continue and $gid = AdminPanel::Shared::Users::Add2UsersGroup($username, $self->ctx);
+ $continue and $gid = $self->sh_users->Add2UsersGroup($username, $self->ctx);
}
if (!$continue) {
@@ -962,8 +1010,8 @@ sub addUserDialog {
}
else {
## OK let's create the user
- print N("Adding user: ") . $username . " \n";
- log::explanations(N("Adding user: %s"), $username);
+ print $self->loc->N("Adding user: ") . $username . " \n";
+ Sys::Syslog::syslog('info|local1', $self->loc->N("Adding user: %s", $username));
my $loginshell = $userData{ login_shell }->value();
my $fullname = $userData{ full_name }->value();
$userEnt->Gecos($fullname); $userEnt->LoginShell($loginshell);
@@ -973,13 +1021,13 @@ sub addUserDialog {
$self->ctx->UserAdd($userEnt, $is_system, $dontcreatehomedir);
$self->ctx->UserSetPass($userEnt, $passwd);
defined $icon->label() and
- AdminPanel::Shared::Users::addKdmIcon($username, $icon->label());
+ $self->sh_users->addKdmIcon($username, $icon->label());
### TODO Migration wizard
#
# Refresh($sysfilter, $stringsearch);
# transfugdrake::get_windows_disk()
-# and $in->ask_yesorno(N("Migration wizard"),
-# N("Do you want to run the migration wizard in order to import Windows documents and settings in your Mageia distribution?"))
+# and $in->ask_yesorno($self->loc->N("Migration wizard"),
+# $self->loc->N("Do you want to run the migration wizard in order to import Windows documents and settings in your Mageia distribution?"))
# and run_program::raw({ detach => 1 }, 'transfugdrake');
@@ -1020,13 +1068,13 @@ sub _createUserTable {
my $parent = $self->get_widget('replace_pnt');
my $factory = yui::YUI::widgetFactory;
my $yTableHeader = new yui::YTableHeader();
- $yTableHeader->addColumn(N("User Name"), $yui::YAlignBegin);
- $yTableHeader->addColumn(N("User ID"), $yui::YAlignBegin);
- $yTableHeader->addColumn(N("Primary Group"), $yui::YAlignBegin);
- $yTableHeader->addColumn(N("Full Name"), $yui::YAlignBegin);
- $yTableHeader->addColumn(N("Login Shell"), $yui::YAlignBegin);
- $yTableHeader->addColumn(N("Home Directory"), $yui::YAlignBegin);
- $yTableHeader->addColumn(N("Status"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("User Name"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("User ID"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Primary Group"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Full Name"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Login Shell"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Home Directory"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Status"), $yui::YAlignBegin);
$yTableHeader->DISOWN();
$self->set_widget(table => $factory->createTable($parent, $yTableHeader));
@@ -1066,9 +1114,9 @@ sub _createGroupTable {
my $parent = $self->get_widget('replace_pnt');
my $factory = yui::YUI::widgetFactory;
my $yTableHeader = new yui::YTableHeader();
- $yTableHeader->addColumn(N("Group Name"), $yui::YAlignBegin);
- $yTableHeader->addColumn(N("Group ID"), $yui::YAlignBegin);
- $yTableHeader->addColumn(N("Group Members"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Group Name"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Group ID"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Group Members"), $yui::YAlignBegin);
$yTableHeader->DISOWN();
$self->set_widget(table => $factory->createTable($parent, $yTableHeader));
@@ -1107,7 +1155,7 @@ sub _computeLockExpire {
my $ep = $l->ShadowExpire($self->USER_GetValue);
my $tm = ceil(time()/(24*60*60));
$ep = -1 if int($tm) <= $ep;
- my $status = $self->ctx->IsLocked($l) ? N("Locked") : ($ep != -1 ? N("Expired") : '');
+ my $status = $self->ctx->IsLocked($l) ? $self->loc->N("Locked") : ($ep != -1 ? $self->loc->N("Expired") : '');
$status;
}
@@ -1300,7 +1348,7 @@ sub _getUserInfo {
my $self = shift;
my $label = $self->_skipShortcut($self->get_widget('tabs')->selectedItem()->label());
- if ($label ne N("Users") ) {
+ if ($label ne $self->loc->N("Users") ) {
return undef;
}
@@ -1343,7 +1391,7 @@ sub _getUserInfo {
$userData{lockuser} = $self->ctx->IsLocked($userEnt);
- $userData{icon_face} = AdminPanel::Shared::Users::GetFaceIcon($userData{username});
+ $userData{icon_face} = $self->sh_users->GetFaceIcon($userData{username});
$userData{pwd_check_exp} = 0;
$userData{pwd_exp_min} = $userEnt->ShadowMin($self->USER_GetValue);
$userData{pwd_exp_max} = $userEnt->ShadowMax($self->USER_GetValue);
@@ -1390,7 +1438,7 @@ sub _getGroupInfo {
my $self = shift;
my $label = $self->_skipShortcut($self->get_widget('tabs')->selectedItem()->label());
- if ($label ne N("Groups") ) {
+ if ($label ne $self->loc->N("Groups") ) {
return undef;
}
@@ -1538,7 +1586,7 @@ sub _userDataTabWidget {
## user 'login name'
my $align = $factory->createRight($layout);
my $hbox = $factory->createHBox($align);
- my $label = $factory->createLabel($hbox, N("Home:") );
+ my $label = $factory->createLabel($hbox, $self->loc->N("Home:") );
$factory->createHSpacing($hbox, 2.0);
$userDataWidget{homedir} = $factory->createInputField($hbox, "", 0);
$label->setWeight($yui::YD_HORIZ, 1);
@@ -1611,7 +1659,7 @@ sub _groupDataTabWidget {
## user 'login name'
my $align = $factory->createRight($layout);
my $hbox = $factory->createHBox($align);
- my $label = $factory->createLabel($hbox, N("Group Name:") );
+ my $label = $factory->createLabel($hbox, $self->loc->N("Group Name:") );
$groupDataWidget{groupname} = $factory->createInputField($hbox, "", 0);
$label->setWeight($yui::YD_HORIZ, 1);
$groupDataWidget{groupname}->setWeight($yui::YD_HORIZ, 2);
@@ -1637,23 +1685,23 @@ sub _userAccountInfoTabWidget {
my $layout = $factory->createVBox($replace_pnt);
my %userAccountWidget;
- $userAccountWidget{acc_check_exp} = $factory->createCheckBoxFrame($layout, N("Enable account expiration"), 1);
+ $userAccountWidget{acc_check_exp} = $factory->createCheckBoxFrame($layout, $self->loc->N("Enable account expiration"), 1);
my $align = $factory->createRight($userAccountWidget{acc_check_exp});
my $hbox = $factory->createHBox($align);
- my $label = $factory->createLabel($hbox, N("Account expires (YYYY-MM-DD):"));
+ my $label = $factory->createLabel($hbox, $self->loc->N("Account expires (YYYY-MM-DD):"));
$userAccountWidget{acc_expy} = $factory->createIntField($hbox, "", 1970, 9999, $userData{acc_expy});
$userAccountWidget{acc_expm} = $factory->createIntField($hbox, "", 1, 12, $userData{acc_expm});
$userAccountWidget{acc_expd} = $factory->createIntField($hbox, "", 1, 31, $userData{acc_expd});
$userAccountWidget{acc_check_exp}->setValue($userData{acc_check_exp});
$label->setWeight($yui::YD_HORIZ, 2);
$align = $factory->createLeft($layout);
- $userAccountWidget{lockuser} = $factory->createCheckBox($align, N("Lock User Account"), $userData{lockuser});
+ $userAccountWidget{lockuser} = $factory->createCheckBox($align, $self->loc->N("Lock User Account"), $userData{lockuser});
$align = $factory->createLeft($layout);
$hbox = $factory->createHBox($align);
- $label = $factory->createLabel($hbox, N("Click on the icon to change it"));
+ $label = $factory->createLabel($hbox, $self->loc->N("Click on the icon to change it"));
$userAccountWidget{icon_face} = $factory->createPushButton($hbox, "");
- $userAccountWidget{icon_face}->setIcon(AdminPanel::Shared::Users::face2png($userData{icon_face}));
+ $userAccountWidget{icon_face}->setIcon($self->sh_users->face2png($userData{icon_face}));
$userAccountWidget{icon_face}->setLabel($userData{icon_face});
$replace_pnt->showChild();
@@ -1680,7 +1728,7 @@ sub _userPasswordInfoTabWidget {
my $align = $factory->createLeft($layout);
my $hbox = $factory->createHBox($align);
- my $label = $factory->createLabel($hbox, N("User last changed password on: "));
+ my $label = $factory->createLabel($hbox, $self->loc->N("User last changed password on: "));
my $dayStr = $factory->createLabel($hbox, "");
my $month = $factory->createLabel($hbox, "");
my $dayInt = $factory->createLabel($hbox, "");
@@ -1693,11 +1741,11 @@ sub _userPasswordInfoTabWidget {
$year->setValue($times->{year});
}
- $userPasswordWidget{pwd_check_exp} = $factory->createCheckBoxFrame($layout, N("Enable Password Expiration"), 1);
+ $userPasswordWidget{pwd_check_exp} = $factory->createCheckBoxFrame($layout, $self->loc->N("Enable Password Expiration"), 1);
$layout = $factory->createVBox($userPasswordWidget{pwd_check_exp});
$align = $factory->createLeft($layout);
$hbox = $factory->createHBox($align);
- $label = $factory->createLabel($hbox, N("Days before change allowed:"));
+ $label = $factory->createLabel($hbox, $self->loc->N("Days before change allowed:"));
$userPasswordWidget{pwd_exp_min} = $factory->createInputField($hbox, "", 0);
$userPasswordWidget{pwd_exp_min}->setValue("$userData{pwd_exp_min}");
$label->setWeight($yui::YD_HORIZ, 1);
@@ -1705,7 +1753,7 @@ sub _userPasswordInfoTabWidget {
$align = $factory->createLeft($layout);
$hbox = $factory->createHBox($align);
- $label = $factory->createLabel($hbox, N("Days before change required:"));
+ $label = $factory->createLabel($hbox, $self->loc->N("Days before change required:"));
$userPasswordWidget{pwd_exp_max} = $factory->createInputField($hbox, "", 0);
$userPasswordWidget{pwd_exp_max}->setValue("$userData{pwd_exp_max}");
$label->setWeight($yui::YD_HORIZ, 1);
@@ -1713,7 +1761,7 @@ sub _userPasswordInfoTabWidget {
$align = $factory->createLeft($layout);
$hbox = $factory->createHBox($align);
- $label = $factory->createLabel($hbox, N("Days warning before change:"));
+ $label = $factory->createLabel($hbox, $self->loc->N("Days warning before change:"));
$userPasswordWidget{pwd_exp_warn} = $factory->createInputField($hbox, "", 0);
$userPasswordWidget{pwd_exp_warn}->setValue("$userData{pwd_exp_warn}");
$label->setWeight($yui::YD_HORIZ, 1);
@@ -1721,7 +1769,7 @@ sub _userPasswordInfoTabWidget {
$align = $factory->createLeft($layout);
$hbox = $factory->createHBox($align);
- $label = $factory->createLabel($hbox, N("Days before account inactive:"));
+ $label = $factory->createLabel($hbox, $self->loc->N("Days before account inactive:"));
$userPasswordWidget{pwd_exp_inact} = $factory->createInputField($hbox, "", 0);
$userPasswordWidget{pwd_exp_inact}->setValue("$userData{pwd_exp_inact}");
$label->setWeight($yui::YD_HORIZ, 1);
@@ -1750,11 +1798,11 @@ sub _groupUsersTabWidget {
my %groupUsersWidget;
- my $layout = _labeledFrameBox($replace_pnt, N("Select the users to join this group:"));
+ my $layout = _labeledFrameBox($replace_pnt, $self->loc->N("Select the users to join this group:"));
my $yTableHeader = new yui::YTableHeader();
$yTableHeader->addColumn("", $yui::YAlignBegin);
- $yTableHeader->addColumn(N("User"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("User"), $yui::YAlignBegin);
$groupUsersWidget{members} = $mgaFactory->createCBTable($layout, $yTableHeader, $yui::YCBTableCheckBoxOnFirstColumn);
@@ -1796,11 +1844,11 @@ sub _userGroupsTabWidget {
my $userEnt = $self->ctx->LookupUserByName($userData{username});
my $lastchg = $userEnt->ShadowLastChange($self->USER_GetValue);
- my $layout = _labeledFrameBox($replace_pnt, N("Select groups that the user will be member of:"));
+ my $layout = _labeledFrameBox($replace_pnt, $self->loc->N("Select groups that the user will be member of:"));
my $yTableHeader = new yui::YTableHeader();
$yTableHeader->addColumn("", $yui::YAlignBegin);
- $yTableHeader->addColumn(N("Group"), $yui::YAlignBegin);
+ $yTableHeader->addColumn($self->loc->N("Group"), $yui::YAlignBegin);
$userGroupsWidget{members} = $mgaFactory->createCBTable($layout, $yTableHeader, $yui::YCBTableCheckBoxOnFirstColumn);
@@ -1826,7 +1874,7 @@ sub _userGroupsTabWidget {
my $align = $factory->createLeft($layout);
my $hbox = $factory->createHBox($align);
- my $label = $factory->createLabel($hbox, N("Primary Group"));
+ my $label = $factory->createLabel($hbox, $self->loc->N("Primary Group"));
$userGroupsWidget{primary_group} = $factory->createComboBox($hbox, "", 0);
my $itemColl = new yui::YItemCollection;
foreach my $member (@$members) {
@@ -1852,7 +1900,7 @@ sub _groupEdit_Ok {
# update last changes if any
%groupData = $self->_storeDataFromGroupEditPreviousTab(%groupData);
- my ($continue, $errorString) = valid_groupname($groupData{groupname});
+ my ($continue, $errorString) = $self->sh_users->valid_groupname($groupData{groupname});
if (!$continue) {
AdminPanel::Shared::msgBox($errorString) if ($errorString);
return $continue;
@@ -1882,7 +1930,7 @@ sub _groupEdit_Ok {
else {
if ($self->_inArray($user, $m)) {
if ($ugid == $gid) {
- AdminPanel::Shared::msgBox(N("You cannot remove user '%s' from their primary group", $user));
+ AdminPanel::Shared::msgBox($self->loc->N("You cannot remove user '%s' from their primary group", $user));
return 0;
}
else {
@@ -1905,21 +1953,20 @@ sub _userEdit_Ok {
# update last changes if any
%userData = $self->_storeDataFromUserEditPreviousTab(%userData);
- my ($continue, $errorString) = valid_username($userData{username});
+ my ($continue, $errorString) = $self->sh_users->valid_username($userData{username});
if (!$continue) {
AdminPanel::Shared::msgBox($errorString) if ($errorString);
return $continue;
}
if ( $userData{password} ne $userData{password1}) {
- AdminPanel::Shared::msgBox(N("Password Mismatch"));
+ AdminPanel::Shared::msgBox($self->loc->N("Password Mismatch"));
return 0;
}
my $userEnt = $self->ctx->LookupUserByName($userData{username});
if ($userData{password} ne '') {
- my $sec = security::level::get();
- if ($sec > 3 && length($userData{password}) < 6) {
- AdminPanel::Shared::msgBox(N("This password is too simple. \n Good passwords should be > 6 characters"));
+ if ($self->sh_users->weakPasswordForSecurityLevel($userData{password})) {
+ AdminPanel::Shared::msgBox($self->loc->N("This password is too simple. \n Good passwords should be > 6 characters"));
return 0;
}
$self->ctx->UserSetPass($userEnt, $userData{password});
@@ -1953,7 +2000,7 @@ sub _userEdit_Ok {
}
}
if ($userData{primary_group} == -1) {
- AdminPanel::Shared::msgBox(N("Please select at least one group for the user"));
+ AdminPanel::Shared::msgBox($self->loc->N("Please select at least one group for the user"));
return 0;
}
$userEnt->Gid($userData{primary_group});
@@ -1963,7 +2010,7 @@ sub _userEdit_Ok {
my $mo = $userData{acc_expm};
my $dy = $userData{acc_expd};
if (!_ValidInt($yr, $dy, $mo)) {
- AdminPanel::Shared::msgBox(N("Please specify Year, Month and Day \n for Account Expiration "));
+ AdminPanel::Shared::msgBox($self->loc->N("Please specify Year, Month and Day \n for Account Expiration "));
return 0;
}
my $Exp = _ConvTime($dy, $mo, $yr);
@@ -1985,7 +2032,7 @@ sub _userEdit_Ok {
$userEnt->ShadowInact($inactive);
}
else {
- AdminPanel::Shared::msgBox(N("Please fill up all fields in password aging\n"));
+ AdminPanel::Shared::msgBox($self->loc->N("Please fill up all fields in password aging\n"));
return 0;
}
}
@@ -2005,7 +2052,7 @@ sub _userEdit_Ok {
$self->ctx->IsLocked($userEnt) and $self->ctx->UnLock($userEnt);
}
- defined $userData{icon_face} and AdminPanel::Shared::Users::addKdmIcon($userData{username}, $userData{icon_face});
+ defined $userData{icon_face} and $self->sh_users->addKdmIcon($userData{username}, $userData{icon_face});
$self->_refresh();
return 1;
@@ -2016,7 +2063,7 @@ sub _userEdit_Ok {
sub _checkWeaknessPassword {
my ($self, $password, $weakness_widget) = @_;
- my $strongp = AdminPanel::Shared::Users::strongPassword($password);
+ my $strongp = $self->sh_users->strongPassword($password);
if (yui::YUI::app()->hasImageSupport()) {
my $file = dist_file('AdminPanel', 'images/Warning_Shield_Grey16x16.png');
if ($strongp) {
@@ -2026,7 +2073,7 @@ sub _checkWeaknessPassword {
}
else {
# For ncurses set a label
- $weakness_widget->setValue(($strongp ? N("Strong") : N("Weak")));
+ $weakness_widget->setValue(($strongp ? $self->loc->N("Strong") : $self->loc->N("Weak")));
}
}
@@ -2039,7 +2086,7 @@ sub _editUserDialog {
## push application title
my $appTitle = yui::YUI::app()->applicationTitle();
## set new title to get it in dialog
- yui::YUI::app()->setApplicationTitle(N("Edit User"));
+ yui::YUI::app()->setApplicationTitle($self->loc->N("Edit User"));
my $factory = yui::YUI::widgetFactory;
my $optional = yui::YUI::optionalWidgetFactory;
@@ -2077,8 +2124,8 @@ sub _editUserDialog {
$hbox = $factory->createHBox($vbox);
$align = $factory->createRight($hbox);
- my $cancelButton = $factory->createPushButton($align, N("Cancel"));
- my $okButton = $factory->createPushButton($hbox, N("Ok"));
+ my $cancelButton = $factory->createPushButton($align, $self->loc->N("Cancel"));
+ my $okButton = $factory->createPushButton($hbox, $self->loc->N("Ok"));
my %userData = $self->_getUserInfo();
# userData here should be tested because it could be undef
@@ -2149,9 +2196,9 @@ sub _editUserDialog {
if ($current_tab && $current_tab eq $userEditLabel{account_info}) {
if ($widget == $self->get_edit_tab_widget('icon_face')) {
my $iconLabel = $self->_skipShortcut($self->get_edit_tab_widget('icon_face')->label());
- my $nextIcon = GetFaceIcon($iconLabel, 1);
+ my $nextIcon = $self->sh_users->GetFaceIcon($iconLabel, 1);
$self->get_edit_tab_widget('icon_face')->setLabel($nextIcon);
- $self->get_edit_tab_widget('icon_face')->setIcon(AdminPanel::Shared::Users::face2png($nextIcon));
+ $self->get_edit_tab_widget('icon_face')->setIcon($self->sh_users->face2png($nextIcon));
}
}
elsif ($current_tab && $current_tab eq $userEditLabel{groups}) {
@@ -2193,7 +2240,7 @@ sub _editUserDialog {
}
else {
- AdminPanel::Shared::warningMsgBox(N("Cannot create tab widgets"));
+ AdminPanel::Shared::warningMsgBox($self->loc->N("Cannot create tab widgets"));
}
destroy $dlg;
@@ -2209,7 +2256,7 @@ sub _editGroupDialog {
## push application title
my $appTitle = yui::YUI::app()->applicationTitle();
## set new title to get it in dialog
- yui::YUI::app()->setApplicationTitle(N("Edit Group"));
+ yui::YUI::app()->setApplicationTitle($self->loc->N("Edit Group"));
my $factory = yui::YUI::widgetFactory;
my $optional = yui::YUI::optionalWidgetFactory;
@@ -2238,8 +2285,8 @@ sub _editGroupDialog {
$hbox = $factory->createHBox($vbox);
$align = $factory->createRight($hbox);
- my $cancelButton = $factory->createPushButton($align, N("Cancel"));
- my $okButton = $factory->createPushButton($hbox, N("Ok"));
+ my $cancelButton = $factory->createPushButton($align, $self->loc->N("Cancel"));
+ my $okButton = $factory->createPushButton($hbox, $self->loc->N("Ok"));
my %groupData = $self->_getGroupInfo();
# groupData here should be tested because it could be undef
@@ -2296,7 +2343,7 @@ sub _editGroupDialog {
}
else {
- AdminPanel::Shared::warningMsgBox(N("Cannot create tab widgets"));
+ AdminPanel::Shared::warningMsgBox($self->loc->N("Cannot create tab widgets"));
}
destroy $dlg;
@@ -2311,7 +2358,7 @@ sub _editUserOrGroup {
# TODO item management avoid label if possible
my $label = $self->_skipShortcut($self->get_widget('tabs')->selectedItem()->label());
- if ($label eq N("Users") ) {
+ if ($label eq $self->loc->N("Users") ) {
$self->_editUserDialog();
}
else {
@@ -2326,7 +2373,7 @@ sub _deleteUserOrGroup {
# TODO item management avoid label if possible
my $label = $self->_skipShortcut($self->get_widget('tabs')->selectedItem()->label());
- if ($label eq N("Users") ) {
+ if ($label eq $self->loc->N("Users") ) {
$self->_deleteUserDialog();
$self->_refresh();
}
@@ -2342,7 +2389,7 @@ sub _refresh {
# TODO item management avoid label if possible
my $label = $self->_skipShortcut($self->get_widget('tabs')->selectedItem()->label());
- if ($label eq N("Users") ) {
+ if ($label eq $self->loc->N("Users") ) {
$self->_refreshUsers();
}
else {
@@ -2377,11 +2424,11 @@ sub _refreshActions {
inst => undef,
);
$self->set_action_menu(
- add_user => new yui::YMenuItem(N("Add User")),
- add_group => new yui::YMenuItem(N("Add Group")),
- edit => new yui::YMenuItem(N("&Edit")),
- del => new yui::YMenuItem(N("&Delete")),
- inst => new yui::YMenuItem(N("Install guest account")),
+ add_user => new yui::YMenuItem($self->loc->N("Add User")),
+ add_group => new yui::YMenuItem($self->loc->N("Add Group")),
+ edit => new yui::YMenuItem($self->loc->N("&Edit")),
+ del => new yui::YMenuItem($self->loc->N("&Delete")),
+ inst => new yui::YMenuItem($self->loc->N("Install guest account")),
);
my $itemColl = new yui::YItemCollection;
@@ -2440,23 +2487,23 @@ sub _manageUsersDialog {
my $headRight = $factory->createHBox($head_align_right);
my %fileMenu = (
- widget => $factory->createMenuButton($headbar,N("File")),
- refresh => new yui::YMenuItem(N("Refresh")),
- quit => new yui::YMenuItem(N("&Quit")),
+ widget => $factory->createMenuButton($headbar,$self->loc->N("File")),
+ refresh => new yui::YMenuItem($self->loc->N("Refresh")),
+ quit => new yui::YMenuItem($self->loc->N("&Quit")),
);
$fileMenu{ widget }->addItem($fileMenu{ refresh });
$fileMenu{ widget }->addItem($fileMenu{ quit });
$fileMenu{ widget }->rebuildMenuTree();
- my $actionMenu = $factory->createMenuButton($headbar, N("Actions"));
+ my $actionMenu = $factory->createMenuButton($headbar, $self->loc->N("Actions"));
$actionMenu->DISOWN();
my %helpMenu = (
- widget => $factory->createMenuButton($headRight, N("&Help")),
- help => new yui::YMenuItem(N("Help")),
- report_bug => new yui::YMenuItem(N("Report Bug")),
- about => new yui::YMenuItem(N("&About")),
+ widget => $factory->createMenuButton($headRight, $self->loc->N("&Help")),
+ help => new yui::YMenuItem($self->loc->N("Help")),
+ report_bug => new yui::YMenuItem($self->loc->N("Report Bug")),
+ about => new yui::YMenuItem($self->loc->N("&About")),
);
while ( my ($key, $value) = each(%helpMenu) ) {
@@ -2469,11 +2516,11 @@ sub _manageUsersDialog {
my $hbox = $factory->createHBox($layout);
$hbox = $factory->createHBox($factory->createLeft($hbox));
$self->set_widget(
- add_user => $factory->createIconButton($hbox, $pixdir . 'user_add.png', N("Add User")),
- add_group => $factory->createIconButton($hbox, $pixdir . 'group_add.png', N("Add Group")),
- edit => $factory->createIconButton($hbox, $pixdir . 'user_conf.png', N("Edit")),
- del => $factory->createIconButton($hbox, $pixdir . 'user_del.png', N("Delete")),
- refresh => $factory->createIconButton($hbox, $pixdir . 'refresh.png', N("Refresh")),
+ add_user => $factory->createIconButton($hbox, $pixdir . 'user_add.png', $self->loc->N("Add User")),
+ add_group => $factory->createIconButton($hbox, $pixdir . 'group_add.png', $self->loc->N("Add Group")),
+ edit => $factory->createIconButton($hbox, $pixdir . 'user_conf.png', $self->loc->N("Edit")),
+ del => $factory->createIconButton($hbox, $pixdir . 'user_del.png', $self->loc->N("Delete")),
+ refresh => $factory->createIconButton($hbox, $pixdir . 'refresh.png', $self->loc->N("Refresh")),
action_menu => $actionMenu,
);
@@ -2486,14 +2533,14 @@ sub _manageUsersDialog {
my $prefs = Config::Auto::parse($self->config_file);
$sysfilter = ($prefs->{FILTER} eq 'true' or $prefs->{FILTER} eq 'true' or $prefs->{FILTER} eq '1');
}
- $self->set_widget(filter_system => $factory->createCheckBox($head_align_left, N("Filter system users"),
+ $self->set_widget(filter_system => $factory->createCheckBox($head_align_left, $self->loc->N("Filter system users"),
$sysfilter));
$factory->createHSpacing($hbox, 3);
$head_align_right = $factory->createRight($hbox);
$headRight = $factory->createHBox($head_align_right);
- $factory->createLabel($headRight, N("Search:"));
+ $factory->createLabel($headRight, $self->loc->N("Search:"));
$self->set_widget(filter => $factory->createInputField($headRight, "", 0));
- $self->set_widget(apply_filter => $factory->createPushButton($headRight, N("Apply filter")));
+ $self->set_widget(apply_filter => $factory->createPushButton($headRight, $self->loc->N("Apply filter")));
$self->get_widget('filter')->setWeight($yui::YD_HORIZ, 2);
$self->get_widget('apply_filter')->setWeight($yui::YD_HORIZ, 1);
$self->get_widget('filter_system')->setNotify(1);
@@ -2503,11 +2550,11 @@ sub _manageUsersDialog {
$hbox = $factory->createHBox($layout);
my $align = $factory->createHCenter($hbox);
$self->set_widget(tabs => $optional->createDumbTab($align));
- $tabs{users} = new yui::YItem(N("Users"));
+ $tabs{users} = new yui::YItem($self->loc->N("Users"));
$tabs{users}->setSelected();
$self->get_widget('tabs')->addItem( $tabs{users} );
$tabs{users}->DISOWN();
- $tabs{groups} = new yui::YItem(N("Groups"));
+ $tabs{groups} = new yui::YItem($self->loc->N("Groups"));
$self->get_widget('tabs')->addItem( $tabs{groups} );
$tabs{groups}->DISOWN();
my $vbox = $factory->createVBox($self->get_widget('tabs'));
@@ -2538,17 +2585,17 @@ sub _manageUsersDialog {
}
elsif ($menuLabel eq $helpMenu{about}->label()) {
my $license = translate($AdminPanel::Shared::License);
- AboutDialog({ name => N("AdminUser"),
+ AboutDialog({ name => $self->loc->N("AdminUser"),
version => $self->VERSION,
- copyright => N("Copyright (C) %s Mageia community", '2013-2014'),
+ copyright => $self->loc->N("Copyright (C) %s Mageia community", '2013-2014'),
license => $license,
- comments => N("AdminUser is a Mageia user management tool \n(from the original idea of Mandriva userdrake)."),
+ comments => $self->loc->N("AdminUser is a Mageia user management tool \n(from the original idea of Mandriva userdrake)."),
website => 'http://www.mageia.org',
- website_label => N("Mageia"),
+ website_label => $self->loc->N("Mageia"),
authors => "Angelo Naselli <anaselli\@linux.it>\nMatteo Pasotti <matteo.pasotti\@gmail.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")}
+ $self->loc->N("_: Translator(s) name(s) & email(s)\n")}
);
}
elsif ($menuLabel eq $self->get_action_menu('add_user')->label()) {
2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672
package printer::main;

# $Id$

use strict;

use common;
use run_program;
use printer::data;
use printer::services;
use printer::default;
use printer::gimp;
use printer::cups;
use printer::office;
use printer::detect;
use handle_configs;
use services;
use lang;

use vars qw(@ISA @EXPORT);

@ISA = qw(Exporter);
@EXPORT = qw(%printer_type %printer_type_inv);

#-Did we already read the subroutines of /usr/sbin/ptal-init?
my $ptalinitread = 0;

our %printer_type = (
    N("Local printer")                              => "LOCAL",
    N("Remote printer")                             => "REMOTE",
    N("Printer on remote CUPS server")              => "CUPS",
    N("Printer on remote lpd server")               => "LPD",
    N("Network printer (TCP/Socket)")               => "SOCKET",
    N("Printer on SMB/Windows 95/98/NT server")     => "SMB",
    N("Printer on NetWare server")                  => "NCP",
    N("Enter a printer device URI")                 => "URI",
    N("Pipe job into a command")                    => "POSTPIPE"
);

our %printer_type_inv = reverse %printer_type;

our %thedb;

#------------------------------------------------------------------------------

sub spooler() {
    # LPD is taken from the menu for the moment because the classic LPD is
    # highly unsecure. Depending on how the GNU lpr development is going on
    # LPD support can be reactivated by uncommenting the following line.

    #return @spooler_inv{qw(cups lpd lprng pdq)};

    # LPRng is not officially supported any more since version 9.0 of
    # this distribution, so show it only in the spooler menu when it
    # was manually installed.

    # PDQ is not officially supported any more since version 9.1, so
    # show it only in the spooler menu when it was manually installed.

    return map { $spoolers{$_}{long_name} } qw(cups), 
    if_(files_exist(qw(/usr/bin/pdq)), 'pdq'),
    if_(files_exist(qw(/usr/lib/filters/lpf /usr/sbin/lpd)), 'lprng');
}

sub printer_type($) {
    my ($printer) = @_;
    for ($printer->{SPOOLER}) {
	/cups/  and return @printer_type_inv{qw(LOCAL LPD SOCKET SMB), if_($printer->{expert}, qw(URI))};
	/lpd/   and return @printer_type_inv{qw(LOCAL LPD SOCKET SMB NCP), if_($printer->{expert}, qw(POSTPIPE URI))};
	/lprng/ and return @printer_type_inv{qw(LOCAL LPD SOCKET SMB NCP), if_($printer->{expert}, qw(POSTPIPE URI))};
	/pdq/   and return @printer_type_inv{qw(LOCAL LPD SOCKET), if_($printer->{expert}, qw(URI))};
    }
}

sub SIGHUP_daemon {
    my ($service) = @_;
    if ($service eq "cupsd") { $service = "cups" };
    # PDQ has no daemon, exit.
    if ($service eq "pdq") { return 1 };
    # CUPS needs auto-correction for its configuration
    run_program::rooted($::prefix, "/usr/sbin/correctcupsconfig") if $service eq "cups";
    # Name of the daemon
    my %daemons = (
			    "lpr" => "lpd",
			    "lpd" => "lpd",
			    "lprng" => "lpd",
			    "cups" => "cupsd",
			    "devfs" => "devfsd",
			    );
    my $daemon = $daemons{$service};
    $daemon = $service unless defined $daemon;
#    if ($service eq "cups") {
#	# The current CUPS (1.1.13) dies on SIGHUP, do the normal restart.
#	printer::services::restart($service);
#	# CUPS needs some time to come up.
#	printer::services::wait_for_cups();
#    } else {

    # Send the SIGHUP
    run_program::rooted($::prefix, "/usr/bin/killall", "-HUP", $daemon);
    if ($service eq "cups") {
	# CUPS needs some time to come up.
	printer::services::wait_for_cups();
    }

    return 1;
}


sub assure_device_is_available_for_cups {
    # Checks whether CUPS already "knows" a certain port, it does not
    # know it usually when the appropriate kernel module is loaded
    # after CUPS was started or when the printer is turned on after
    # CUPS was started. CUPS 1.1.12 and newer refuses to set up queues
    # on devices which it does not know, it points these queues to
    # file:/dev/null instead. Restart CUPS if necessary to assure that
    # CUPS knows the device.
    my ($device) = @_;
    my $sdevice = handle_configs::searchstr($device);
    my ($result, $i);
    # USB printers get special model-dependent URLs in "lpinfo -v" here
    # checking is complicated, so we simply restart CUPS then and ready.
    if ($device =~ /usb/) {
	$result = printer::services::restart("cups");
	return 1;
    }
    my $maxattempts = 3;
    for ($i = 0; $i < $maxattempts; $i++) {
	local *F; 
	open F, ($::testing ? $::prefix : "chroot $::prefix/ ") . 
	    '/bin/sh -c "export LC_ALL=C; /usr/sbin/lpinfo -v" |' or
	    die 'Could not run "lpinfo"!';
	while (my $line = <F>) {
	    if ($line =~ /$sdevice/) { # Found a line containing the device
		                       # name, so CUPS knows it.
		close F;
		return 1;
	    }
	}
	close F;
	$result = printer::services::restart("cups");
    }
    return $result;
}


sub spooler_in_security_level {
    # Was the current spooler already added to the current security level?
    my ($spooler, $level) = @_;
    my $sp;
    $sp = $spooler eq "lpr" || $spooler eq "lprng" ? "lpd" : $spooler;
    my $file = "$::prefix/etc/security/msec/server.$level";
    if (-f $file) {
	local *F; 
	open F, "< $file" or return 0;
	while (my $line = <F>) {
	    if ($line =~ /^\s*$sp\s*$/) {
		close F;
		return 1;
	    }
	}
	close F;
    }
    return 0;
}

sub add_spooler_to_security_level {
    my ($spooler, $level) = @_;
    my $sp;
    $sp = $spooler eq "lpr" || $spooler eq "lprng" ? "lpd" : $spooler;
    my $file = "$::prefix/etc/security/msec/server.$level";
    if (-f $file) {
	   eval { append_to_file($file, "$sp\n") } or return 0;
    }
    return 1;
}

sub pdq_panic_button {
    my $setting = $_[0];
    if (-f "$::prefix/usr/sbin/pdqpanicbutton") {
        run_program::rooted($::prefix, "/usr/sbin/pdqpanicbutton", "--$setting")
	    or die "Could not $setting PDQ panic buttons!";
    }
}

sub copy_printer_params($$) {
    my ($from, $to) = @_;
    map { $to->{$_} = $from->{$_} } grep { $_ ne 'configured' } keys %$from; 
    #- avoid cycles-----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}

sub getinfo($) {
    my ($prefix) = @_;
    my $printer = {};

    $::prefix = $prefix;

    # Initialize $printer data structure
    resetinfo($printer);

    return $printer;
}

#------------------------------------------------------------------------------
sub resetinfo($) {
    my ($printer) = @_;
    $printer->{QUEUE} = "";
    $printer->{OLD_QUEUE} = "";
    $printer->{OLD_CHOICE} = "";
    $printer->{ARGS} = "";
    $printer->{DBENTRY} = "";
    $printer->{DEFAULT} = "";
    $printer->{currentqueue} = {};
    # -check which printing system was used previously and load the information
    # -about its queues
    read_configured_queues($printer);
}

sub read_configured_queues($) {
    my ($printer) = @_;
    my @QUEUES;
    # Get the default spooler choice from the config file
    $printer->{SPOOLER} ||= printer::default::get_spooler();
    if (!$printer->{SPOOLER}) {
	#- Find the first spooler where there are queues
	foreach my $spooler (qw(cups pdq lprng lpd)) {
	    #- Is the spooler's daemon running?
	    my $service = $spooler;
	    if ($service eq "lprng") {
		$service = "lpd";
	    }
	    if ($service ne "pdq") {
		next unless services::is_service_running($service);
		# daemon is running, spooler found
		$printer->{SPOOLER} = $spooler;
	    }
	    #- poll queue info 
	    local *F; 
	    open F, ($::testing ? $::prefix : "chroot $::prefix/ ") . 
		"foomatic-configure -P -q -s $spooler |" or
		    die "Could not run foomatic-configure";
	    eval join('', <F>); 
	    close F;
	    if ($service eq "pdq") {
		#- Have we found queues? PDQ has no damon, so we consider
		#- it in use when there are defined printer queues
		if ($#QUEUES != -1) {
		    $printer->{SPOOLER} = $spooler;
		    last;
		}
	    } else {
		#- For other spoolers we have already found a running
		#- daemon when we have arrived here
		last;
	    }
	}
    } else {
	#- Poll the queues of the current default spooler
	local *F; 
	open F, ($::testing ? $::prefix : "chroot $::prefix/ ") . 
	    "foomatic-configure -P -q -s $printer->{SPOOLER} -r |" or
		die "Could not run foomatic-configure";
	eval join('', <F>); 
	close F;
    }
    $printer->{configured} = {};
    my $i;
    my $N = $#QUEUES + 1;
    for ($i = 0;  $i < $N; $i++) {
	# Set the default printer
	$printer->{DEFAULT} = $QUEUES[$i]{queuedata}{queue} if
	    $QUEUES[$i]{queuedata}{default};
	# Advance to the next entry if the current is a remotely defined
	# printer
	next if $QUEUES[$i]{queuedata}{remote};
	# Add an entry for a locally defined queue
	$printer->{configured}{$QUEUES[$i]{queuedata}{queue}} = 
	    $QUEUES[$i];
	if (!$QUEUES[$i]{make} || !$QUEUES[$i]{model}) {
	    if ($printer->{SPOOLER} eq "cups") {
		$printer->{OLD_QUEUE} = $QUEUES[$i]{queuedata}{queue};
		my $descr = get_descr_from_ppd($printer);
		if ($descr =~ m/^([^\|]*)\|([^\|]*)(\|.*|)$/) {
		    $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{make} ||= $1;
		    $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{model} ||= $2;
	        }
		# Read out which PPD file was originally used to set up this
		# queue
		local *F;
		if (open F, "< $::prefix/etc/cups/ppd/$QUEUES[$i]{queuedata}{queue}.ppd") {
		    while (my $line = <F>) {
			if ($line =~ /^\*%MDKMODELCHOICE:(.+)$/) {
			    $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{ppd} = $1;
			}
		    }
		    close F;
		}
		# Mark that we have a CUPS queue but do not know the name
		# the PPD file in /usr/share/cups/model
		if (!$printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{ppd}) {
		    $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{ppd} = '1';
		}
		$printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{driver} = 'PPD';
		$printer->{OLD_QUEUE} = "";
	    }
	    $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{make} ||= "";
	    $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{model} ||= N("Unknown model");
	} else {
	    $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{make} = $QUEUES[$i]{make};
	    $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{model} = $QUEUES[$i]{model};
	}
	# Fill in "options" field
	if (my $args = $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{args}) {
	    my @options;
	    foreach my $arg (@$args) {
		push(@options, "-o");
		my $optstr = $arg->{name} . "=" . $arg->{default};
		push(@options, $optstr);
	    }
	    @{$printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{options}} = @options;
	}
	# Construct an entry line for tree view in main window of
	# printerdrake
	make_menuentry($printer, $QUEUES[$i]{queuedata}{queue});
    }
}

sub make_menuentry {
    my ($printer, $queue) = @_;
    my $spooler = $spoolers{$printer->{SPOOLER}}{short_name};
    my $connect = $printer->{configured}{$queue}{queuedata}{connect};
    my $localremote = N("Configured on this machine");
    my $make = $printer->{configured}{$queue}{queuedata}{make};
    my $model = $printer->{configured}{$queue}{queuedata}{model};
    my $connection;
    if ($connect =~ m!^(file|parallel):/dev/lp(\d+)$!) {
	my $number = $2;
	$connection = N(" on parallel port #%s", $number);
    } elsif ($connect =~ m!^(file|usb):/dev/usb/lp(\d+)$!) {
	my $number = $2;
	$connection = N(", USB printer #%s", $number);
    } elsif ($connect =~ m!^usb://!) {
	$connection = N(", USB printer");
    } elsif ($connect =~ m!^ptal://?(.+?)$!) {
	my $ptaldevice = $1;
	if ($ptaldevice =~ /^mlc:par:(\d+)$/) {
	    my $number = $1;
	    $connection = N(", multi-function device on parallel port #%s",
			    $number);
	} elsif ($ptaldevice =~ /^mlc:par:/) {
	    $connection = N(", multi-function device on a parallel port");
	} elsif ($ptaldevice =~ /^mlc:usb:/) {
	    $connection = N(", multi-function device on USB");
	} elsif ($ptaldevice =~ /^hpjd:/) {
	    $connection = N(", multi-function device on HP JetDirect");
	} else {
	    $connection = N(", multi-function device");
	}
    } elsif ($connect =~ m!^file:(.+)$!) {
	$connection = N(", printing to %s", $1);
    } elsif ($connect =~ m!^lpd://([^/]+)/([^/]+)/?$!) {
	$connection = N(" on LPD server \"%s\", printer \"%s\"", $1, $2);
    } elsif ($connect =~ m!^socket://([^/:]+):([^/:]+)/?$!) {
	$connection = N(", TCP/IP host \"%s\", port %s", $1, $2);
    } elsif ($connect =~ m!^smb://([^/\@]+)/([^/\@]+)/?$! ||
	     $connect =~ m!^smb://.*/([^/\@]+)/([^/\@]+)/?$! ||
	     $connect =~ m!^smb://.*\@([^/\@]+)/([^/\@]+)/?$!) {
	$connection = N(" on SMB/Windows server \"%s\", share \"%s\"", $1, $2);
    } elsif ($connect =~ m!^ncp://([^/\@]+)/([^/\@]+)/?$! ||
	     $connect =~ m!^ncp://.*/([^/\@]+)/([^/\@]+)/?$! ||
	     $connect =~ m!^ncp://.*\@([^/\@]+)/([^/\@]+)/?$!) {
	$connection = N(" on Novell server \"%s\", printer \"%s\"", $1, $2);
    } elsif ($connect =~ m!^postpipe:(.+)$!) {
	$connection = N(", using command %s", $1);
    } else {
	$connection = ($printer->{expert} ? ", URI: $connect" : "");
    }
    my $sep = "!";
    $printer->{configured}{$queue}{queuedata}{menuentry} = 
	($printer->{expert} ? "$spooler$sep" : "") .
	"$localremote$sep$queue: $make $model$connection";
}

sub connectionstr {
    my ($connect) = @_;
    my $connection;
    if ($connect =~ m!^(file|parallel):/dev/lp(\d+)$!) {
	my $number = $2;
	$connection = N("Parallel port #%s", $number);
    } elsif ($connect =~ m!^(file|usb):/dev/usb/lp(\d+)$!) {
	my $number = $2;
	$connection = N("USB printer #%s", $number);
    } elsif ($connect =~ m!^usb://!) {
	$connection = N("USB printer");
    } elsif ($connect =~ m!^ptal://?(.+?)$!) {
	my $ptaldevice = $1;
	if ($ptaldevice =~ /^mlc:par:(\d+)$/) {
	    my $number = $1;
	    $connection = N("Multi-function device on parallel port #%s",
			    $number);
	} elsif ($ptaldevice =~ /^mlc:par:/) {
	    $connection = N("Multi-function device on a parallel port");
	} elsif ($ptaldevice =~ /^mlc:usb:/) {
	    $connection = N("Multi-function device on USB");
	} elsif ($ptaldevice =~ /^hpjd:/) {
	    $connection = N("Multi-function device on HP JetDirect");
	} else {
	    $connection = N("Multi-function device");
	}
    } elsif ($connect =~ m!^file:(.+)$!) {
	$connection = N("Prints into %s", $1);
    } elsif ($connect =~ m!^lpd://([^/]+)/([^/]+)/?$!) {
	$connection = N("LPD server \"%s\", printer \"%s\"", $1, $2);
    } elsif ($connect =~ m!^socket://([^/:]+):([^/:]+)/?$!) {
	$connection = N("TCP/IP host \"%s\", port %s", $1, $2);
    } elsif ($connect =~ m!^smb://([^/\@]+)/([^/\@]+)/?$! ||
	     $connect =~ m!^smb://.*/([^/\@]+)/([^/\@]+)/?$! ||
	     $connect =~ m!^smb://.*\@([^/\@]+)/([^/\@]+)/?$!) {
	$connection = N("SMB/Windows server \"%s\", share \"%s\"", $1, $2);
    } elsif ($connect =~ m!^ncp://([^/\@]+)/([^/\@]+)/?$! ||
	     $connect =~ m!^ncp://.*/([^/\@]+)/([^/\@]+)/?$! ||
	     $connect =~ m!^ncp://.*\@([^/\@]+)/([^/\@]+)/?$!) {
	$connection = N("Novell server \"%s\", printer \"%s\"", $1, $2);
    } elsif ($connect =~ m!^postpipe:(.+)$!) {
	$connection = N("Uses command %s", $1);
    } else {
	$connection = N("URI: %s", $connect);
    }
    return $connection;
}

sub read_printer_db {

    my ($printer, $spooler) = @_;

    local *DBPATH; #- don't have to do close ... and don't modify globals at least
    # Generate the Foomatic printer/driver overview, read it from the
    # appropriate file when it is already generated
    open DBPATH, ($::testing ? $::prefix : "chroot $::prefix/ ") . #-#
	"foomatic-configure -O -q |" or
	die "Could not run foomatic-configure";

    my $entry = {};
    my $inentry = 0;
    my $indrivers = 0;
    my $inautodetect = 0;
    my $autodetecttype = "";
    local $_;
    while (<DBPATH>) {
	chomp;
	if ($inentry) {
	    # We are inside a printer entry
	    if ($indrivers) {
		# We are inside the drivers block of a printers entry
		if (m!^\s*</drivers>\s*$!) {
		    # End of drivers block
		    $indrivers = 0;
		} elsif (m!^\s*<driver>(.+)</driver>\s*$!) {
		    push @{$entry->{drivers}}, $1;
		}
	    } elsif ($inautodetect) {
		# We are inside the autodetect block of a printers entry
		# All entries inside this block will be ignored
		if ($autodetecttype) {
		    if (m!^.*</$autodetecttype>\s*$!) {
			# End of general, parallel, USB, or SNMP section
			$autodetecttype = "";
		    } elsif (m!^\s*<manufacturer>\s*([^<>]+)\s*</manufacturer>\s*$!) {
			# Manufacturer
			$entry->{devidmake} = $1;
		    } elsif (m!^\s*<model>\s*([^<>]+)\s*</model>\s*$!) {
			# Model
			$entry->{devidmodel} = $1;
		    } elsif (m!^\s*<description>\s*([^<>]+)\s*</description>\s*$!) {
			# Description
			$entry->{deviddesc} = $1;
		    } elsif (m!^\s*<commandset>\s*([^<>]+)\s*</commandset>\s*$!) {
			# Command set
			$entry->{devidcmdset} = $1;
		    } elsif (m!^\s*<ieee1284>\s*([^<>]+)\s*</ieee1284>\s*$!) {
			# Full ID string
			my $idstr = $1;
			$idstr =~ m!(MFG|MANUFACTURER):([^;]+);!i
			    and $entry->{devidmake} = $2;
			$idstr =~ m!(MDL|MODEL):([^;]+);!i
			    and $entry->{devidmodel} = $2;
			$idstr =~ m!(DES|DESCRIPTION):([^;]+);!i
			    and $entry->{deviddesc} = $2;
			$idstr =~ m!(CMD|COMMAND\s*SET):([^;]+);!i
			    and $entry->{devidcmdset} = $2;
		    }
		} else {
		    if (m!^.*</autodetect>\s*$!) {
			# End of autodetect block
			$inautodetect = 0;
		    } elsif (m!^\s*<(general|parallel|usb|snmp)>\s*$!) {
			# Beginning of parallel, USB, or SNMP section
			$autodetecttype = $1;
		    }
		}
	    } else {
		if (m!^\s*</printer>\s*$!) {
		    # entry completed
		    $inentry = 0;
		    # Expert mode:
		    # Make one database entry per driver with the entry name
		    # manufacturer|model|driver
		    if ($printer->{expert}) {
			foreach my $driver (@{$entry->{drivers}}) {
			    my $driverstr;
			    if ($driver eq "Postscript") {
				$driverstr = "PostScript";
			    } else {
				$driverstr = "GhostScript + $driver";
			    }
			    if ($driver eq $entry->{defaultdriver}) {
				$driverstr .= " (recommended)";
			    }
			    $entry->{ENTRY} = "$entry->{make}|$entry->{model}|$driverstr";
			    $entry->{ENTRY} =~ s/^CITOH/C.ITOH/i;
			    $entry->{ENTRY} =~ 
				s/^KYOCERA[\s\-]*MITA/KYOCERA/i;
			    $entry->{driver} = $driver;
			    # Duplicate contents of $entry because it is multiply entered to the database
			    map { $thedb{$entry->{ENTRY}}{$_} = $entry->{$_} } keys %$entry;
			}
		    } else {
			# Recommended mode
			# Make one entry per printer, with the recommended
			# driver (manufacturerer|model)
			$entry->{ENTRY} = "$entry->{make}|$entry->{model}";
			$entry->{ENTRY} =~ s/^CITOH/C.ITOH/i;
			$entry->{ENTRY} =~ 
			    s/^KYOCERA[\s\-]*MITA/KYOCERA/i;
			if ($entry->{defaultdriver}) {
			    $entry->{driver} = $entry->{defaultdriver};
			    map { $thedb{$entry->{ENTRY}}{$_} = $entry->{$_} } keys %$entry;
			}
		    }
		    $entry = {};
		} elsif (m!^\s*<id>\s*([^\s<>]+)\s*</id>\s*$!) {
		    # Foomatic printer ID
		    $entry->{printer} = $1;
		} elsif (m!^\s*<make>(.+)</make>\s*$!) {
		    # Printer manufacturer
		    $entry->{make} = uc($1);
		} elsif (m!^\s*<model>(.+)</model>\s*$!) {
		    # Printer model
		    $entry->{model} = $1;
		} elsif (m!<driver>(.+)</driver>!) {
		    # Printer default driver
		    $entry->{defaultdriver} = $1;
		} elsif (m!^\s*<drivers>\s*$!) {
		    # Drivers block
		    $indrivers = 1;
		    @{$entry->{drivers}} = (); 
		} elsif (m!^\s*<autodetect>\s*$!) {
		    # Autodetect block
		    $inautodetect = 1;
		}
	    }
	} else {
	    if (m!^\s*<printer>\s*$!) {
		# new entry
		$inentry = 1;
	    }
	}
    }
    close DBPATH;

    # Add raw queue
    $entry->{ENTRY} = N("Raw printer (No driver)");
    $entry->{driver} = "raw";
    $entry->{make} = "";
    $entry->{model} = N("Unknown model");
    $thedb{$entry->{ENTRY}}{$_} = $entry->{$_} foreach keys %$entry;

    #- Load CUPS driver database if CUPS is used as spooler
    if ($spooler && $spooler eq "cups") {
        poll_ppd_base($printer);
    }

    #my @entries_db_short     = sort keys %printer::thedb;
    #%descr_to_db          = map { $printer::thedb{$_}{DESCR}, $_ } @entries_db_short;
    #%descr_to_help        = map { $printer::thedb{$_}{DESCR}, $printer::thedb{$_}{ABOUT} } @entries_db_short;
    #@entry_db_description = keys %descr_to_db;
    #db_to_descr          = reverse %descr_to_db;

}

sub read_foomatic_options ($) {
    my ($printer) = @_;
    # Generate the option data for the chosen printer/driver combo
    my $COMBODATA;
    local *F;
    open F, ($::testing ? $::prefix : "chroot $::prefix/ ") . 
	"foomatic-configure -P -q -p $printer->{currentqueue}{printer}" .
	" -d $printer->{currentqueue}{driver}" . 
	($printer->{OLD_QUEUE} ?
	 " -s $printer->{SPOOLER} -n $printer->{OLD_QUEUE}" : "") .
	 ($printer->{SPECIAL_OPTIONS} ?
	  " $printer->{SPECIAL_OPTIONS}" : "") 
	 . " |" or
	 die "Could not run foomatic-configure";
    eval join('', (<F>)); 
    close F;
    # Return the arguments field
    return $COMBODATA->{args};
}

sub read_ppd_options ($) {
    my ($printer) = @_;
    # Generate the option data for a given PPD file
    my $COMBODATA;
    local *F;
    open F, ($::testing ? $::prefix : "chroot $::prefix/ ") . 
	"foomatic-configure -P -q" .
	" --ppd /usr/share/cups/model/$printer->{currentqueue}{ppd}" .
	($printer->{OLD_QUEUE} ?
	 " -s $printer->{SPOOLER} -n $printer->{OLD_QUEUE}" : "") .
	 ($printer->{SPECIAL_OPTIONS} ?
	  " $printer->{SPECIAL_OPTIONS}" : "") 
		    . " |" or
	    die "Could not run foomatic-configure";
    eval join('', (<F>)); 
    close F;
    # Return the arguments field
    return $COMBODATA->{args};
}

my %sysconfig = getVarsFromSh("$::prefix/etc/sysconfig/printing");

sub set_cups_special_options {
    my ($queue) = $_[0];
    # Set some special CUPS options
    my @lpoptions = chomp_(cat_("$::prefix/etc/cups/lpoptions"));
    # If nothing is already configured, set text file borders of half an inch
    # and decrease the font size a little bit, so nothing of the text gets
    # cut off by unprintable borders.
    if (!any { /$queue.*\s(page-(top|bottom|left|right)|lpi|cpi)=/ } @lpoptions) {
	run_program::rooted($::prefix, "lpoptions",
			    "-p", $queue,
			    "-o", "page-top=36", "-o", "page-bottom=36",
			    "-o", "page-left=36", "-o page-right=36",
			    "-o", "cpi=12", "-o", "lpi=7", "-o", "wrap");
    }
    # Let images fill the whole page by default
    if (!any { /$queue.*\s(scaling|natural-scaling|ppi)=/ } @lpoptions) {
	run_program::rooted($::prefix, "lpoptions",
			    "-p", $queue,
			    "-o", "scaling=100");
    }
    return 1;
}

sub set_cups_autoconf {
    my ($autoconf) = @_;
    $sysconfig{CUPS_CONFIG} = $autoconf ? "automatic" : "manual";
    setVarsInSh("$::prefix/etc/sysconfig/printing", \%sysconfig);
    # Restart CUPS
    printer::services::restart("cups") if $autoconf;
    return 1;
}

sub get_cups_autoconf() { $sysconfig{CUPS_CONFIG} ne 'manual' ? 1 : 0 }

sub set_usermode {
    my ($usermode) = @_;
    $sysconfig{USER_MODE} = $usermode ? "expert" : "recommended";
    setVarsInSh("$::prefix/etc/sysconfig/printing", \%sysconfig) if !$::testing;
    return $usermode;
}

sub get_usermode() { $sysconfig{USER_MODE} eq 'expert' ? 1 : 0 }

sub set_jap_textmode {
    my $textmode = ($_[0] ? 'cjk' : '');
    substInFile {
        s!^(\s*text/plain\s+\S+\s+\d+\s+)\S+(\s*$)!$1${textmode}texttops$2!        
    } "$::prefix/etc/cups/mime.convs";
    return 1;
}

sub get_jap_textmode() {
    my @mimeconvs = cat_("$::prefix/etc/cups/mime.convs");
    (m!^\s*text/plain\s+\S+\s+\d+\s+(\S+)\s*$!m and
     $1 eq 'cjktexttops' and return 1) foreach @mimeconvs;
    return 0;
}

#----------------------------------------------------------------------
# Handling of /etc/cups/cupsd.conf

sub read_cupsd_conf() {
    cat_("$::prefix/etc/cups/cupsd.conf");
}
sub write_cupsd_conf {
    my (@cupsd_conf) = @_;

    output("$::prefix/etc/cups/cupsd.conf", @cupsd_conf);

    #- restart cups after updating configuration.
    printer::services::restart("cups");
}

sub read_location {

    # Return the lines inside the [path] location block
    #
    #   <Location [path]>
    #   ...
    #   </Location>

    my ($cupsd_conf_ptr, $path) = @_;

    my @result;
    if (any { m!^\s*<Location\s+$path\s*>! } @$cupsd_conf_ptr) {
	my $location_start = -1;
	my $location_end = -1;
	# Go through all the lines, bail out when start and end line found
	for (my $i = 0; 
	     $i <= $#{$cupsd_conf_ptr} and $location_end == -1;
	     $i++) {
	    if ($cupsd_conf_ptr->[$i] =~ m!^\s*<\s*Location\s+$path\s*>!) {
		# Start line of block
		$location_start = $i;
	    } elsif ($cupsd_conf_ptr->[$i] =~ 
		      m!^\s*<\s*/Location\s*>! &&
		     $location_start != -1) {
		# End line of block
		$location_end = $i;
		last;
	    } elsif ($location_start >= 0 && $location_end < 0) {
		# Inside the location block
		push(@result, $cupsd_conf_ptr->[$i]);
	    }
	}
    } else {
	# If there is no root location block, set the result array to
	# "undef"
	@result = undef;
    }
    return (@result);
}

sub rip_location {

    # Cut out the [path]  location block
    #
    #   <Location [path]>
    #   ...
    #   </Location>
    #
    # so that it can be treated seperately without affecting the
    # rest of the file

    my ($cupsd_conf_ptr, $path) = @_;

    my @location;
    my $location_start = -1;
    my $location_end = -1;
    if (any { m!^\s*<Location\s+$path\s*>! } @$cupsd_conf_ptr) {
	# Go through all the lines, bail out when start and end line found
	for (my $i = 0; 
	     $i <= $#{$cupsd_conf_ptr} and $location_end == -1;
	     $i++) {
	    if ($cupsd_conf_ptr->[$i] =~ m!^\s*<\s*Location\s+$path\s*>!) {
		# Start line of block
		$location_start = $i;
	    } elsif ($cupsd_conf_ptr->[$i] =~ 
		      m!^\s*<\s*/Location\s*>! &&
		     $location_start != -1) {
		# End line of block
		$location_end = $i;
		last;
	    }
	}
	# Rip out the block and store it seperately
	@location = 
	    splice(@$cupsd_conf_ptr, $location_start,
		   $location_end - $location_start + 1);
    } else {
	# If there is no location block, create one
	$location_start = $#{$cupsd_conf_ptr} + 1;
	@location = ("<Location $path>\n", "</Location>\n");
    }

    return ($location_start, @location);
}

sub insert_location {

    # Re-insert a location block ripped with "rip_location"

    my ($cupsd_conf_ptr, $location_start, @location) = @_;

    splice(@$cupsd_conf_ptr, $location_start,0,@location);
}

sub add_to_location {

    # Add a directive to a given location (only if it is not already there)

    my ($cupsd_conf_ptr, $path, $directive) = @_;

    my ($location_start, @location) = rip_location($cupsd_conf_ptr, $path);
    my $success = handle_configs::insert_directive(\@location, $directive);
    insert_location($cupsd_conf_ptr, $location_start, @location);
    return $success;
}

sub remove_from_location {

    # Remove a directive from a given location

    my ($cupsd_conf_ptr, $path, $directive) = @_;

    my ($location_start, @location) = rip_location($cupsd_conf_ptr, $path);
    my $success = handle_configs::remove_directive(\@location, $directive);
    insert_location($cupsd_conf_ptr, $location_start, @location);
    return $success;
}

sub replace_in_location {

    # Replace a directive in a given location

    my ($cupsd_conf_ptr, $path, $olddirective, $newdirective) = @_;

    my ($location_start, @location) = rip_location($cupsd_conf_ptr, $path);
    my $success = handle_configs::replace_directive(\@location, 
						    $olddirective, 
						    $newdirective);
    insert_location($cupsd_conf_ptr, $location_start, @location);
    return $success;
}

sub add_allowed_host {

    # Add a host or network which should get access to the local printer(s)
    my ($cupsd_conf_ptr, $host) = @_;
    
    return (handle_configs::insert_directive($cupsd_conf_ptr, 
					     "BrowseAddress $host") and
	    add_to_location($cupsd_conf_ptr, "/", "Allow From $host"));
}

sub remove_allowed_host {

    # Remove a host or network which should get access to the local 
    # printer(s)
    my ($cupsd_conf_ptr, $host) = @_;
    
    return (handle_configs::remove_directive($cupsd_conf_ptr, "BrowseAddress $host") and
	    remove_from_location($cupsd_conf_ptr, "/",
				 "Allow From $host"));
}

sub replace_allowed_host {

    # Remove a host or network which should get access to the local 
    # printer(s)
    my ($cupsd_conf_ptr, $oldhost, $newhost) = @_;
    
    return (handle_configs::replace_directive($cupsd_conf_ptr,
					      "BrowseAddress $oldhost",
					      "BrowseAddress $newhost") and
	    replace_in_location($cupsd_conf_ptr, "/", "Allow From $newhost",
				"Allow From $newhost"));
}

sub broadcastaddress {
    
    # Determines the broadcast address (for "BrowseAddress" line) for
    # a given network IP

    my ($address) = @_;

    if ($address =~ /^\d+\.\*$/) {
	$address =~ s/\*$/255.255.255/;
    } elsif ($address =~ /^\d+\.\d+\.\*$/) {
	$address =~ s/\*$/255.255/;
    } elsif ($address =~ /^\d+\.\d+\.\d+\.\*$/) {
	$address =~ s/\*$/255/;
    } elsif ($address =~ m!^(\d+)\.(\d+)\.(\d+)\.(\d+)/(\d+)$!) {
	my $numadr = ($1 << 24) + ($2 << 16) + ($3 << 8) + $4;
	my $mask = ((1 << $5) - 1) << (32 - $5);
	my $broadcast = $numadr | (~$mask);
	$address =
	    (($broadcast & (255 << 24)) >> 24) . '.' .
	    (($broadcast & (255 << 16)) >> 16) . '.' .
	    (($broadcast & (255 << 8)) >> 8) . '.' .
	    ($broadcast & 255);
    } elsif ($address =~
	     m!^(\d+)\.(\d+)\.(\d+)\.(\d+)/(\d+)\.(\d+)\.(\d+)\.(\d+)$!) {
	my $numadr = ($1 << 24) + ($2 << 16) + ($3 << 8) + $4;
	my $mask = ($5 << 24) + ($6 << 16) + ($7 << 8) + $8;
	my $broadcast = $numadr | (~$mask);
	$address =
	    (($broadcast & (255 << 24)) >> 24) . '.' .
	    (($broadcast & (255 << 16)) >> 16) . '.' .
	    (($broadcast & (255 << 8)) >> 8) . '.' .
	    ($broadcast & 255);
    }
    
    return $address;
}

sub networkaddress {
    
    # Guesses a network address for a given broadcast address
    
    my ($address) = @_;

    if ($address =~ /\.255$/) {
	while ($address =~ s/\.255$//) {};
	$address .= ".*";
    }
 
    return $address;
}

sub localprintersshared {

    # Do we broadcast our local printers

    my ($printer) = @_;

    return ($printer->{cupsconfig}{keys}{Browsing} !~ /off/i &&
	    $printer->{cupsconfig}{keys}{BrowseInterval} != 0 &&
	    $#{$printer->{cupsconfig}{keys}{BrowseAddress}} >= 0);
}

sub remotebroadcastsaccepted {
    
    # Do we accept broadcasts from remote CUPS servers?

    my ($printer) = @_;

    # Is browsing not turned on at all?
    if ($printer->{cupsconfig}{keys}{Browsing} =~ /off/i) {
	return 0;
    }

    # No "BrowseDeny" lines at all
    if ($#{$printer->{cupsconfig}{keys}{BrowseDeny}} < 0) {
	return 1;
    }

    my $havedenyall = 
	join('', @{$printer->{cupsconfig}{keys}{BrowseDeny}}) =~
	 /All/im;
    my $havedenylocal = 
	join('', @{$printer->{cupsconfig}{keys}{BrowseDeny}}) =~
	 /\@LOCAL/im;
    my $orderallowdeny =
	$printer->{cupsconfig}{keys}{BrowseOrder} =~
	 /allow\s*,\s*deny/i;
    my $haveallowremote = 0;
    foreach my $allowline (@{$printer->{cupsconfig}{keys}{BrowseAllow}}) {
	next if 
	    $allowline =~ /^\s*(localhost|0*127\.0+\.0+\.0*1|none)\s*$/i;
	$haveallowremote = 1;
    }

    # A line denying all (or at least the all LANs) together with the order
    # "allow,deny" or without "BrowseAllow" lines (which allow the
    # broadcasts of at least one remote resource).
    if (($havedenyall || $havedenylocal) &&
	($orderallowdeny || !$haveallowremote)) {
	return 0;
    }

    return 1;
}

sub clientnetworks {

    # Determine the client networks to which the printers will be
    # shared If the configuration is supported by our simplified
    # interface ("Deny From All", "Order Deny,Allow", "Allow From ..."
    # lines in "<location /> ... </location>", a "BrowseAddress ..."
    # line for each "Allow From ..." line), return the list of allowed
    # client networks ("Allow"/"BrowseAddress" lines), if not, return
    # the list of all items which are at least one of the
    # "BrowseAddresse"s or one of the "Allow From" addresses together
    # with a flag that the setup is not supported.

    my ($printer) = @_;

    # Check for a "Deny From All" line
    my $havedenyfromall =
	(join('', @{$printer->{cupsconfig}{root}{DenyFrom}}) =~
	 /All/im ? 1 : 0);

    # Check for "Deny From XXX" with XXX != All
    my $havedenyfromnotall =
	($#{$printer->{cupsconfig}{root}{DenyFrom}} - $havedenyfromall < 0 ?
	 0 : 1);
    
    # Check for a "BrowseDeny All" line
    my $havebrowsedenyall =
	(join('', @{$printer->{cupsconfig}{keys}{BrowseDeny}}) =~
	 /All/im ? 1 : 0);

    # Check for "BrowseDeny XXX" with XXX != All
    my $havebrowsedenynotall =
	($#{$printer->{cupsconfig}{keys}{BrowseDeny}} - 
	 $havebrowsedenyall < 0 ? 0 : 1);
    
    my @sharehosts;
    my $haveallowfromlocalhost = 0;
    my $haveallowedhostwithoutbrowseaddress = 0;
    my $haveallowedhostwithoutbrowseallow = 0;
    # Go through all "Allow From" lines
    foreach my $line (@{$printer->{cupsconfig}{root}{AllowFrom}}) {
	if ($line =~ /^\s*(localhost|0*127\.0+\.0+\.0*1)\s*$/i) {
	    # Line pointing to localhost
	    $haveallowfromlocalhost = 1;
	} elsif ($line =~ /^\s*(none)\s*$/i) {
	    # Skip "Allow From None" lines
	} elsif (!member($line, @sharehosts)) {
	    # Line pointing to remote server
	    push(@sharehosts, $line);
	    if (!member(broadcastaddress($line),
			@{$printer->{cupsconfig}{keys}{BrowseAddress}})) {
		$haveallowedhostwithoutbrowseaddress = 1;
	    }
	    if (!member($line,
			@{$printer->{cupsconfig}{keys}{BrowseAllow}})) {
		$haveallowedhostwithoutbrowseallow = 1;
	    }
	}
    }
    my $havebrowseaddresswithoutallowedhost = 0;
    # Go through all "BrowseAdress" lines
    foreach my $line (@{$printer->{cupsconfig}{keys}{BrowseAddress}}) {
	if ($line =~ /^\s*(localhost|0*127\.0+\.0+\.0*1)\s*$/i) {
	    # Skip lines pointing to localhost
	} elsif ($line =~ /^\s*(none)\s*$/i) {
	    # Skip "Allow From None" lines
	} elsif (!member($line, map { broadcastaddress($_) } @sharehosts)) {
	    # Line pointing to remote server
	    push(@sharehosts, networkaddress($line));
	    if ($printer->{cupsconfig}{localprintersshared}) {
		$havebrowseaddresswithoutallowedhost = 1;
	    }
	}
    }
    my $havebrowseallowwithoutallowedhost = 0;
    # Go through all "BrowseAllow" lines
    foreach my $line (@{$printer->{cupsconfig}{keys}{BrowseAllow}}) {
	if ($line =~ /^\s*(localhost|0*127\.0+\.0+\.0*1)\s*$/i) {
	    # Skip lines pointing to localhost
	} elsif ($line =~ /^\s*(none)\s*$/i) {
	    # Skip "BrowseAllow None" lines
	} elsif (!member($line, @sharehosts)) {
	    # Line pointing to remote server
	    push(@sharehosts, $line);
	    #$havebrowseallowwithoutallowedhost = 1;
	}
    }

    my $configunsupported = (!$havedenyfromall || $havedenyfromnotall ||
			     !$havebrowsedenyall || $havebrowsedenynotall ||
			     !$haveallowfromlocalhost ||
			     $haveallowedhostwithoutbrowseaddress ||
			     $havebrowseaddresswithoutallowedhost ||
			     $haveallowedhostwithoutbrowseallow ||
			     $havebrowseallowwithoutallowedhost);

    return ($configunsupported, @sharehosts);
}

sub makesharehostlist {

    # Human-readable strings for hosts onto which the local printers
    # are shared

    my ($printer) = @_;

    my @sharehostlist; 
    my %sharehosthash;
    foreach my $host (@{$printer->{cupsconfig}{clientnetworks}}) {
	if ($host =~ /\@LOCAL/i) {
	    $sharehosthash{$host} = N("Local network(s)");
	} elsif ($host =~ /\@IF\((.*)\)/i) {
	    $sharehosthash{$host} = N("Interface \"%s\"", $1);
	} elsif ($host =~ m!(/|^\*|\*$|^\.)!) {
	    $sharehosthash{$host} = N("Network %s", $host);
	} else {
	    $sharehosthash{$host} = N("Host %s", $host);
	}
	push(@sharehostlist, $sharehosthash{$host});
    }
    my %sharehosthash_inv = reverse %sharehosthash;

    return { list => \@sharehostlist, 
	     hash => \%sharehosthash, 
	     invhash => \%sharehosthash_inv };
}

sub makebrowsepolllist {

    # Human-readable strings for hosts from which the print queues are
    # polled

    my ($printer) = @_;

    my @browsepolllist; 
    my %browsepollhash;
    foreach my $host (@{$printer->{cupsconfig}{BrowsePoll}}) {
	my ($ip, $port);
	if ($host =~ /^([^:]+):([^:]+)$/) {
	    $ip = $1;
	    $port = $2;
	} else {
	    $ip = $host;
	    $port = '631';
	}
	$browsepollhash{$host} = N("%s (Port %s)", $ip, $port);
	push(@browsepolllist, $browsepollhash{$host});
    }
    my %browsepollhash_inv = reverse %browsepollhash;

    return { list => \@browsepolllist, 
	     hash => \%browsepollhash, 
	     invhash => \%browsepollhash_inv };
}

sub is_network_ip {

    # Determine whwther the given string is a valid network IP

    my ($address) = @_;

    $address =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ ||
	$address =~ /^(\d+\.){1,3}\*$/ ||
	$address =~ m!^(\d+)\.(\d+)\.(\d+)\.(\d+)/(\d+)$! ||
	$address =~
	 m!^(\d+)\.(\d+)\.(\d+)\.(\d+)/(\d+)\.(\d+)\.(\d+)\.(\d+)$!;

}

sub read_cups_config {
    
    # Read the information relevant to the printer sharing dialog from
    # the CUPS configuration

    my ($printer) = @_;

    # From /etc/cups/cupsd.conf

    # Keyword "Browsing" 
    $printer->{cupsconfig}{keys}{Browsing} =
	handle_configs::read_unique_directive($printer->{cupsconfig}{cupsd_conf},
					      'Browsing', 'On');

    # Keyword "BrowseInterval"
    $printer->{cupsconfig}{keys}{BrowseInterval} =
	handle_configs::read_unique_directive($printer->{cupsconfig}{cupsd_conf},
					      'BrowseInterval', '30');

    # Keyword "BrowseAddress" 
    @{$printer->{cupsconfig}{keys}{BrowseAddress}} =
	handle_configs::read_directives($printer->{cupsconfig}{cupsd_conf},
					'BrowseAddress');

    # Keyword "BrowseAllow" 
    @{$printer->{cupsconfig}{keys}{BrowseAllow}} =
	handle_configs::read_directives($printer->{cupsconfig}{cupsd_conf},
					'BrowseAllow');

    # Keyword "BrowseDeny" 
    @{$printer->{cupsconfig}{keys}{BrowseDeny}} =
	handle_configs::read_directives($printer->{cupsconfig}{cupsd_conf},
					'BrowseDeny');

    # Keyword "BrowseOrder" 
    $printer->{cupsconfig}{keys}{BrowseOrder} =
	handle_configs::read_unique_directive($printer->{cupsconfig}{cupsd_conf},
					      'BrowseOrder', 'deny,allow');

    # Keyword "BrowsePoll" (needs "Browsing On")
    if ($printer->{cupsconfig}{keys}{Browsing} !~ /off/i) {
	@{$printer->{cupsconfig}{BrowsePoll}} =
	    handle_configs::read_directives($printer->{cupsconfig}{cupsd_conf},
					    'BrowsePoll');
    }

    # Root location
    @{$printer->{cupsconfig}{rootlocation}} =
	read_location($printer->{cupsconfig}{cupsd_conf}, '/');

    # Keyword "Allow from" 
    @{$printer->{cupsconfig}{root}{AllowFrom}} =
	handle_configs::read_directives($printer->{cupsconfig}{rootlocation},
					'Allow From');
    # Remove the IPs pointing to the local machine
    my @localips = printer::detect::getIPsOfLocalMachine();
    @{$printer->{cupsconfig}{root}{AllowFrom}} =
	grep {
	    !member($_, @localips)
	} @{$printer->{cupsconfig}{root}{AllowFrom}};

    # Keyword "Deny from" 
    @{$printer->{cupsconfig}{root}{DenyFrom}} =
	handle_configs::read_directives($printer->{cupsconfig}{rootlocation},
					'Deny From');

    # Keyword "Order" 
    $printer->{cupsconfig}{root}{Order} =
	handle_configs::read_unique_directive($printer->{cupsconfig}{rootlocation},
					      'Order', 'Deny,Allow');

    # Widget settings

    # Local printers available to other machines?
    $printer->{cupsconfig}{localprintersshared} = 
	localprintersshared($printer);

    # This machine is accepting printers shared by remote machines?
    $printer->{cupsconfig}{remotebroadcastsaccepted} =
	remotebroadcastsaccepted($printer);

    # To which machines are the local printers available?
    ($printer->{cupsconfig}{customsharingsetup},
     @{$printer->{cupsconfig}{clientnetworks}}) =
	 clientnetworks($printer);

}

sub write_cups_config {
    
    # Write the information edited via the printer sharing dialog into
    # the CUPS configuration

    my ($printer) = @_;

    # Local printers available to other machines?
    if ($printer->{cupsconfig}{localprintersshared}) {
	handle_configs::set_directive($printer->{cupsconfig}{cupsd_conf},
				      'Browsing On');
	if ($printer->{cupsconfig}{keys}{BrowseInterval} == 0) {
	    handle_configs::set_directive($printer->{cupsconfig}{cupsd_conf},
					  'BrowseInterval 30');
	}  
    } else {
	handle_configs::set_directive($printer->{cupsconfig}{cupsd_conf},
				      'BrowseInterval 0');
    }

    # This machine is accepting printers shared by remote machines?
    if ($printer->{cupsconfig}{remotebroadcastsaccepted}) {
	handle_configs::set_directive($printer->{cupsconfig}{cupsd_conf},
				      'Browsing On');
	if (!$printer->{cupsconfig}{customsharingsetup}) {
	    # If we broadcast our printers, let's accept the broadcasts
	    # from the machines to which we broadcast
	    handle_configs::set_directive($printer->{cupsconfig}{cupsd_conf},
					  'BrowseDeny All');
	    handle_configs::set_directive($printer->{cupsconfig}{cupsd_conf},
					  'BrowseOrder Deny,Allow');
	}
    } else {
	if ($printer->{cupsconfig}{localprintersshared} ||
	    $#{$printer->{cupsconfig}{BrowsePoll}} >= 0) {
	    # Deny all broadcasts, but leave all "BrowseAllow" lines
	    # untouched
	    handle_configs::set_directive($printer->{cupsconfig}{cupsd_conf},
					  'BrowseDeny All');
	      handle_configs::set_directive($printer->{cupsconfig}{cupsd_conf},
					    'BrowseOrder Allow,Deny');
	} else {
	    # We also do not share printers, if we also do not
	    # "BrowsePoll", we turn browsing off to do not need to deal 
	    # with any addresses
	    handle_configs::set_directive($printer->{cupsconfig}{cupsd_conf},
					  'Browsing Off');
	}
    }

    # To which machines are the local printers available?
    if (!$printer->{cupsconfig}{customsharingsetup}) {
	my @localips = printer::detect::getIPsOfLocalMachine();
	# root location block
	@{$printer->{cupsconfig}{rootlocation}} =
	    "<Location />\n" .
	    "Order Deny,Allow\n" .
	    "Deny From All\n" .
	    "Allow From 127.0.0.1\n" .
	    (@localips ?
	     "Allow From " .
	     join("\nAllow From ", @localips) .
	     "\n" : "") .
	    ($printer->{cupsconfig}{localprintersshared} &&
	     $#{$printer->{cupsconfig}{clientnetworks}} >= 0 ?
	     "Allow From " .
	     join("\nAllow From ", 
		  grep {
		      !member($_, @localips)
		  } @{$printer->{cupsconfig}{clientnetworks}}) .
	     "\n" : "") .
	    "</Location>\n";
	my ($location_start, @_location) = 
	    rip_location($printer->{cupsconfig}{cupsd_conf}, "/");
	insert_location($printer->{cupsconfig}{cupsd_conf}, $location_start,
			@{$printer->{cupsconfig}{rootlocation}});
	# "BrowseAddress" lines
	if ($#{$printer->{cupsconfig}{clientnetworks}} >= 0) {
	    handle_configs::set_directive($printer->{cupsconfig}{cupsd_conf},
					  'BrowseAddress ' .
					  join("\nBrowseAddress ",
						map { broadcastaddress($_) }
						@{$printer->{cupsconfig}{clientnetworks}}));
	} else {
	    handle_configs::comment_directive($printer->{cupsconfig}{cupsd_conf},
					      'BrowseAddress')
	}
	# Set "BrowseAllow" lines
	if ($#{$printer->{cupsconfig}{clientnetworks}} >= 0) {
	    handle_configs::set_directive($printer->{cupsconfig}{cupsd_conf},
					  'BrowseAllow ' .
					  join("\nBrowseAllow ", 
						@{$printer->{cupsconfig}{clientnetworks}}));
	} else {
	    handle_configs::comment_directive($printer->{cupsconfig}{cupsd_conf},
					      'BrowseAllow');
	}
    }

    # Set "BrowsePoll" lines
    if ($#{$printer->{cupsconfig}{BrowsePoll}} >= 0) {
	handle_configs::set_directive($printer->{cupsconfig}{cupsd_conf},
				      'BrowsePoll ' .
				      join("\nBrowsePoll ", 
					    @{$printer->{cupsconfig}{BrowsePoll}}));
	# "Browsing" must be on for "BrowsePoll" to work
	handle_configs::set_directive($printer->{cupsconfig}{cupsd_conf},
				      'Browsing On');
    } else {
	handle_configs::comment_directive($printer->{cupsconfig}{cupsd_conf},
					  'BrowsePoll');
    }

}

sub clean_cups_config {
    
    # Clean $printer data structure from all settings not related to
    # the CUPS printer sharing dialog

    my ($printer) = @_;

    delete $printer->{cupsconfig}{keys};
    delete $printer->{cupsconfig}{root};
    delete $printer->{cupsconfig}{cupsd_conf};
    delete $printer->{cupsconfig}{rootlocation};
}

#----------------------------------------------------------------------
sub read_printers_conf {
    my ($printer) = @_;
    my $current;

    #- read /etc/cups/printers.conf file.
    #- according to this code, we are now using the following keys for each queues.
    #-    DeviceURI > lpd://printer6/lp
    #-    Info      > Info Text
    #-    Location  > Location Text
    #-    State     > Idle|Stopped
    #-    Accepting > Yes|No
    local *PRINTERS; open PRINTERS, "$::prefix/etc/cups/printers.conf" or return;
    local $_;
    while (<PRINTERS>) {
	chomp;
	/^\s*#/ and next;
	if (/^\s*<(?:DefaultPrinter|Printer)\s+([^>]*)>/) { $current = { mode => 'cups', QUEUE => $1, } }
	elsif (m!\s*</Printer>!) { $current->{QUEUE} && $current->{DeviceURI} or next; #- minimal check of synthax.
				   add2hash($printer->{configured}{$current->{QUEUE}} ||= {}, $current); $current = undef }
	elsif (/\s*(\S*)\s+(.*)/) { $current->{$1} = $2 }
    }
    close PRINTERS;

    #- assume this printing system.
    $printer->{SPOOLER} ||= 'cups';
}

sub get_direct_uri() {
    #- get the local printer to access via a Device URI.
    my @direct_uri;
    local *F; open F, ($::testing ? $::prefix : "chroot $::prefix/ ") . "/usr/sbin/lpinfo -v |";
    local $_;
    while (<F>) {
	/^(direct|usb|serial)\s+(\S*)/ and push @direct_uri, $2;
    }
    close F;
    @direct_uri;
}

sub checkppd {
    # Check whether the PPD file is valid
    my ($printer, $ppdfile) = @_;
    return 1 if $printer->{SPOOLER} ne "cups";
    return run_program::rooted($::prefix, "cupstestppd", "-q",
			       $ppdfile);
}

sub installppd {
    # Install the PPD file in /usr/share/cups/model/printerdrake/
    my ($printer, $ppdfile) = @_;
    return "" if !$ppdfile;
    # Install PPD file
    mkdir_p("$::prefix/usr/share/cups/model/printerdrake");
    # "cp_f()" is broken, it hangs infinitely
    # cp_f($ppdfile, "$::prefix/usr/share/cups/model/printerdrake");
    run_program::rooted($::prefix, "cp", "-f", "$ppdfile",
			"$::prefix/usr/share/cups/model/printerdrake");
    $ppdfile =~ s!^(.*)(/[^/]+)$!/usr/share/cups/model/printerdrake$2!;
    chmod 0644, "$::prefix$ppdfile";
    # Restart CUPS to register new PPD file
    printer::services::restart("cups") if $printer->{SPOOLER} eq "cups";
    # Re-read printer database
    %thedb = ();
    read_printer_db($printer, $printer->{SPOOLER});
    # Return description string of the PPD file
    my $ppdentry = get_descr_from_ppdfile($printer, $ppdfile);
    return $ppdentry;
}

sub clean_manufacturer_name {
    my ($make) = @_;
    # Clean some manufacturer's names so that every manufacturer has only
    # one entry in the tree list
    $make =~ s/^CANON\W.*$/CANON/i;
    $make =~ s/^LEXMARK.*$/LEXMARK/i;
    $make =~ s/^HEWLETT?[\s\-]*PACKARD/HP/i;
    $make =~ s/^SEIKO[\s\-]*EPSON/EPSON/i;
    $make =~ s/^KYOCERA[\s\-]*MITA/KYOCERA/i;
    $make =~ s/^CITOH/C.ITOH/i;
    $make =~ s/^OKI(|[\s\-]*DATA)\s*$/OKIDATA/i;
    $make =~ s/^(SILENTWRITER2?|COLORMATE)/NEC/i;
    $make =~ s/^(XPRINT|MAJESTIX)/XEROX/i;
    $make =~ s/^QMS-PS/QMS/i;
    $make =~ s/^(PERSONAL|LASERWRITER)/APPLE/i;
    $make =~ s/^DIGITAL/DEC/i;
    $make =~ s/\s+Inc\.//i;
    $make =~ s/\s+Corp\.//i;
    $make =~ s/\s+SA\.//i;
    $make =~ s/\s+S\.\s*A\.//i;
    $make =~ s/\s+Ltd\.//i;
    $make =~ s/\s+International//i;
    $make =~ s/\s+Int\.//i;
    return uc($make);
}    

sub ppd_entry_str {
    my ($mf, $descr, $lang) = @_;
    my ($model, $driver);
    if ($descr) {
	# Apply the beautifying rules of poll_ppd_base
	if ($descr =~ /Foomatic \+ Postscript/) {
	    $descr =~ s/Foomatic \+ Postscript/PostScript/;
	} elsif ($descr =~ /Foomatic/i) {
	    $descr =~ s/Foomatic/GhostScript/i;
	} elsif ($descr =~ /CUPS\+GIMP-print/i) {
	    $descr =~ s/CUPS\+GIMP-print/CUPS + GIMP-Print/i;
	} elsif ($descr =~ /Series CUPS/i) {
	    $descr =~ s/Series CUPS/Series, CUPS/i;
	} elsif ($descr !~ /(PostScript|GhostScript|CUPS|Foomatic)/i) {
	    $descr .= ", PostScript";
	}
	# Split model and driver
	$descr =~ s/\s*Series//i;
	$descr =~ s/\((.*?(PostScript|PS.*).*?)\)/$1/i;
	if ($descr =~
	     /^\s*(Generic\s*PostScript\s*Printer)\s*,?\s*(.*)$/i ||
	    $descr =~
	     /^\s*(PostScript\s*Printer)\s*,?\s*(.*)$/i ||
	    $descr =~ /^([^,]+[^,\s])\s*,?\s*(Foomatic.*)$/i ||
	    $descr =~ /^([^,]+[^,\s])\s*,?\s*(GhostScript.*)$/i ||
	    $descr =~ /^([^,]+[^,\s])\s*,?\s*(CUPS.*)$/i ||
	    $descr =~ /^([^,]+[^,\s])\s*,?\s+(PS.*)$/i ||
	    $descr =~
	     /^([^,]+[^,\s])\s*,?\s*(\(v?\.?\s*\d\d\d\d\.\d\d\d\).*)$/i ||
	    $descr =~ /^([^,]+[^,\s])\s*,?\s*(v\d+\.\d+.*)$/i ||
	    $descr =~ /^([^,]+[^,\s])\s*,?\s*(PostScript.*)$/i ||
	    $descr =~ /^([^,]+)\s*,?\s*(.+)$/) {
	    $model = $1;
	    $driver = $2;
	    $model =~ s/[\-\s,]+$//;
	    $driver =~ s/\b(PS|PostScript\b)/PostScript/gi;
	    $driver =~ s/(PostScript)(.*)(PostScript)/$1$2/i;
	    $driver =~ 
	      s/^\s*(\(?v?\.?\s*\d\d\d\d\.\d\d\d\)?|v\d+\.\d+)([,\s]*)(.*?)\s*$/$3$2$1/i;
	    $driver =~ s/,\s*\(/ (/g;
	    $driver =~ s/[\-\s,]+$//;
	    $driver =~ s/^[\-\s,]+//;
	    $driver =~ s/\s+/ /g;
	    if ($driver !~ /[a-z]/i) {
		$driver = "PostScript " . $driver;
		$driver =~ s/ $//;
	    }
	} else {
	    # Some PPDs do not have the ", <driver>" part.
	    $model = $descr;
	    $driver = "PostScript";
	}
    }
    # Remove manufacturer's name from the beginning of the model
    # name (do not do this with manufacturer names which contain
    # odd characters)
    $model =~ s/^$mf[\s\-]+//i 
	if $mf && $mf !~ m![\\/\(\)\[\]\|\.\$\@\%\*\?]!;
    # Clean some manufacturer's names
    $mf = clean_manufacturer_name($mf);
    # Rename Canon "BJC XXXX" models into "BJC-XXXX" so that the 
    # models do not appear twice
    if ($mf eq "CANON") {
	$model =~ s/BJC\s+/BJC-/;
    }
    # New MF devices from Epson have mis-spelled name in PPD files for
    # native CUPS drivers of GIMP-Print
    if ($mf eq "EPSON") {
	$model =~ s/Stylus CX\-/Stylus CX/;
    }
    # Remove the "Oki" from the beginning of the model names of Okidata
    # printers
    if ($mf eq "OKIDATA") {
	$model =~ s/Oki\s+//i;
    }
    # Try again to remove manufacturer's name from the beginning of the 
    # model name, this with the cleaned manufacturer name
    $model =~ s/^$mf[\s\-]+//i 
	if $mf && $mf !~ m![\\/\(\)\[\]\|\.\$\@\%\*\?]!;
    # Put out the resulting description string
    uc($mf) . '|' . $model . '|' . $driver .
      ($lang && " (" . lang::locale_to_main_locale($lang) . ")");
}

sub get_descr_from_ppd {
    my ($printer) = @_;
    #- if there is no ppd, this means this is a raw queue.
    if (! -r "$::prefix/etc/cups/ppd/$printer->{OLD_QUEUE}.ppd") {
	return "|" . N("Unknown model");
    }
    return get_descr_from_ppdfile($printer, "/etc/cups/ppd/$printer->{OLD_QUEUE}.ppd");
}

sub get_descr_from_ppdfile {
    my ($printer, $ppdfile) = @_;
    my %ppd;

    # Remove ".gz" from end of file name, so that "catMaybeCompressed" works
    $ppdfile =~ s/\.gz$//;

    eval {
	local $_;
	foreach (catMaybeCompressed("$::prefix$ppdfile")) {
	    # "OTHERS|Generic PostScript printer|PostScript (en)";
	    /^\*([^\s:]*)\s*:\s*\"([^\"]*)\"/ and
		do { $ppd{$1} = $2; next };
	    /^\*([^\s:]*)\s*:\s*([^\s\"]*)/   and
		do { $ppd{$1} = $2; next };
	}
    };
    my $descr = ($ppd{NickName} || $ppd{ShortNickName} || $ppd{ModelName});
    my $make = $ppd{Manufacturer};
    my $lang = $ppd{LanguageVersion};
    my $entry = ppd_entry_str($make, $descr, $lang);
    if (!$printer->{expert}) {
	# Remove driver from printer list entry when in recommended mode
	$entry =~ s/^([^\|]+\|[^\|]+)\|.*$/$1/;
    }
    return $entry;
}

sub ppd_devid_data {
    my ($ppd) = @_;
    $ppd = "$::prefix/usr/share/cups/model/$ppd";
    my @content;
    if ($ppd =~ /\.gz$/i) {
	@content = cat_("$::prefix/bin/zcat $ppd |") or return ("", "");
    } else {
	@content = cat_($ppd) or return ("", "");
    }
    my ($devidmake, $devidmodel);
    /^\*Manufacturer:\s*\"(.*)\"\s*$/ and $devidmake = $1
	foreach @content;
    /^\*Product:\s*\"\(?(.*?)\)?\"\s*$/ and $devidmodel = $1 
	foreach @content;
    return ($devidmake, $devidmodel);
}

sub poll_ppd_base() {
    my ($printer) = @_;
    #- Before trying to poll the ppd database available to cups, we have 
    #- to make sure the file /etc/cups/ppds.dat is no more modified.
    #- If cups continue to modify it (because it reads the ppd files 
    #- available), the poll_ppd_base program simply cores :-)
    # else cups will not be happy! and ifup lo don't run ?
    run_program::rooted($::prefix, 'ifconfig', 'lo', '127.0.0.1');
    printer::services::start_not_running_service("cups");
    my $driversthere = scalar(keys %thedb);
    foreach (1..60) {
	local *PPDS; open PPDS, ($::testing ? $::prefix :