Initial commit.

This commit is contained in:
2026-03-10 21:25:26 +08:00
commit 78739bf725
3089 changed files with 472990 additions and 0 deletions

View File

@@ -0,0 +1,389 @@
# Selima Website Content Management System
# User.pm: The user account form.
# Copyright (c) 2004-2018 imacat.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Author: imacat <imacat@mail.imacat.idv.tw>
# First written: 2004-09-30
package Selima::Form::User;
use 5.008;
use strict;
use warnings;
use base qw(Selima::Form);
use Selima::ChkPriv;
use Selima::CommText;
use Selima::DataVars qw($DBH :groups :l10n :lninfo);
use Selima::FormFunc;
use Selima::GetLang;
use Selima::HTTP;
use Selima::LnInfo;
use Selima::LogIn;
use Selima::MarkAbbr;
use Selima::ShortCut;
use Selima::UserName;
# new: Initialize the HTML form table displayer
sub new : method {
local ($_, %_);
my ($class, $status, $args, $self);
($class, $status, $args) = @_;
$args = {} if !defined $args;
# $args must be a hash reference
http_500 "type of argument 2 must be a hash reference"
if ref($args) ne "HASH";
$$args{"type"} = form_type
if !exists $$args{"type"};
$$args{"table"} = "users"
if !exists $$args{"table"};
$$args{"deltext"} = C_("Delete this user account")
if !exists $$args{"deltext"};
$$args{"https"} = ($$args{"type"} ne "del")
if !exists $$args{"https"};
if (!exists $$args{"summary"}) {
# A form to create a new item
if ($$args{"type"} eq "new") {
$$args{"summary"} = C_("This table provides you a form to add a new user account.");
# A form to edit a current item
} elsif ($$args{"type"} eq "cur") {
$$args{"summary"} = C_("This table provides you a form to update a current user account.");
# A form to delete a current item
} elsif ($$args{"type"} eq "del") {
$$args{"summary"} = C_("This table provides you a form to delete a user account.");
}
}
if (!exists $$args{"cols"}) {
# A form to create a new item
if ($$args{"type"} eq "new") {
$$args{"cols"} = [qw(id passwd name disabled supgroup)];
# A form to edit a current item
# A form to delete a current item
} elsif ($$args{"type"} eq "cur" || $$args{"type"} eq "del") {
$$args{"cols"} = [qw(sn id passwd name disabled supgroup
admin lang visits visited ip host ct
created createdby updated updatedby)];
}
}
if (!exists $$args{"title"}) {
# A form to create a new item
if ($$args{"type"} eq "new") {
$$args{"title"} = C_("Add a New User Account");
# A form to edit a current item
} elsif ($$args{"type"} eq "cur") {
$$args{"title"} = C_("Update a Current User Account");
# A form to delete a current item
} elsif ($$args{"type"} eq "del") {
$$args{"title"} = C_("Delete a User Account");
}
}
$self = $class->SUPER::new($status, $args);
${$self->{"maxlens"}}{"passwd"} = 16;
if ( $$args{"type"} eq "cur" && !is_su
&& ($self->{"cur"}->param("su") || $self->{"sn"} == get_login_sn)) {
$self->{"nodelete"} = 1;
push @{$self->{"prefmsg"}}, C_("This is a super-user. You can only change parts of her/his infomation.")
if $self->{"cur"}->param("su");
}
# Set all the available belonging groups list
$self->_set_supgroup_list();
return $self;
}
# _set_supgroup_list: Set all the available belonging groups list
sub _set_supgroup_list : method {
local ($_, %_);
my ($self, $form, %checked, $sth, $sql, $count);
my ($lndb, $lndbdef, $title);
$self = $_[0];
$form = $self->{"form"};
# Get the list of checked groups
%checked = qw();
for ($_ = 0; defined $form->param("supgroup$_" . "sn"); $_++) {
$checked{$form->param("supgroup$_" . "sn")} = 1
if defined $form->param("supgroup$_");
}
# Remove the old groups list
foreach ($form->param) {
$form->delete($_) if /^supgroup/;
}
# Get the list of all groups
if (@ALL_LINGUAS > 1) {
$lndb = getlang LN_DATABASE;
if (getlang eq $DEFAULT_LANG) {
$title = $DBH->strcat("id", "' ('", "dsc_$lndb", "')'");
} else {
$lndbdef = ln $DEFAULT_LANG, LN_DATABASE;
$title = $DBH->strcat("id", "' ('",
"COALESCE(dsc_$lndb, dsc_$lndbdef)", "')'");
}
} else {
$title = $DBH->strcat("id", "' ('", "dsc", "')'");
}
$sql = "SELECT sn AS sn, $title AS title FROM groups"
. " WHERE id!=" . $DBH->quote(SU_GROUP)
. " AND id!=" . $DBH->quote(ADMIN_GROUP)
. " AND id!=" . $DBH->quote(ALLUSERS_GROUP)
. " ORDER BY id;\n";
$sth = $DBH->prepare($sql);
$sth->execute;
$count = $sth->rows;
for ($_ = 0; $_ < $count; $_++) {
%_ = %{$sth->fetchrow_hashref};
$form->param("supgroup$_" . "sn", $_{"sn"});
$form->param("supgroup$_" . "title", $_{"title"});
$form->param("supgroup$_", 1) if exists $checked{$_{"sn"}};
}
return;
}
# _html_col_admin: Is this user an administrator?
sub _html_col_admin : method {
$_[0]->_html_coltmpl_ro_bool("admin", h_abbr(C_("Administrator?")),
h_abbr(C_("Administrator")), h_abbr(C_("Non-administrator")));
}
# _html_col_ct: The country
sub _html_col_ct : method {
$_[0]->_html_coltmpl_ro_ct("ct", h_abbr(C_("Country:")));
}
# _html_col_disabled: Disabled?
sub _html_col_disabled : method {
local ($_, %_);
my $self;
$self = $_[0];
# Read-only for a non-super-user editing herself or a super-user
if ( $self->{"type"} eq "cur" && !is_su
&& ($self->{"cur"}->param("su") || $self->{"sn"} == get_login_sn)) {
$self->_html_coltmpl_ro_bool("disabled", h_abbr(C_("Disabled?")),
h_abbr(C_("Disabled")), h_abbr(C_("Enabled")));
} else {
$self->_html_coltmpl_bool("disabled", h_abbr(C_("Disabled?")),
h_abbr(C_("Disabled")), h_abbr(C_("Enabled")),
h_abbr(C_("Disable this user account.")));
}
}
# _html_col_id: The user ID.
sub _html_col_id : method {
local ($_, %_);
my $self;
$self = $_[0];
# Read-only for a non-super-user editing a super-user
if ($self->{"type"} eq "cur" && !is_su && $self->{"cur"}->param("su")) {
$self->_html_coltmpl_ro("id", h_abbr(C_("User ID.:")));
} else {
$self->_html_coltmpl_text("id", h_abbr(C_("User ID.:")));
}
}
# _html_col_lang: The preferred language
sub _html_col_lang : method {
$_[0]->_html_coltmpl_ro_lang("lang", h_abbr(C_("Pref. language:")));
}
# _html_col_name: The name
sub _html_col_name : method {
$_[0]->_html_coltmpl_text("name", h_abbr(C_("Full name:")));
}
# _html_col_passwd: The password
sub _html_col_passwd : method {
local ($_, %_);
my ($self, $label, $dummy, $mark, $colspan);
$self = $_[0];
# Read-only for a non-super-user editing a super-user
if ($self->{"type"} eq "cur" && !is_su && $self->{"cur"}->param("su")) {
$mark = $self->_mark("passwd");
$colspan = $self->_colspan;
$label = h_abbr(C_("Password:"));
$dummy = h("*" x ${$self->{"maxlens"}}{"passwd"});
print << "EOT";
<tr>
<th colspan="2" scope="row">$mark$label</th>
<td$colspan>$dummy</td>
</tr>
EOT
} else {
$self->SUPER::_html_col_passwd();
}
}
# _html_col_supgroup: Its belonging groups
sub _html_col_supgroup : method {
local ($_, %_);
my ($self, $form, $current, $label, $orig, $new, $mark, $colspan);
$self = $_[0];
$form = $self->{"form"};
$current = $self->{"cur"};
$mark = $self->_mark("supgroup");
$colspan = $self->_colspan;
$label = h_abbr(C_("Belonging to:"));
# A form to create a new item
if ($self->{"type"} eq "new") {
print << "EOT";
<tr>
<th class="th" scope="row"><label for="supgroup0">$mark$label</label></th>
EOT
print " <td$colspan>";
for ($_ = 0, @_ = qw(); defined $form->param("supgroup$_" . "sn"); $_++) {
push @_, sprintf(" <li><input type=\"hidden\" name=\"supgroup%1\$dsn\"%2\$s />\n"
. " <input id=\"supgroup%1\$d\" type=\"checkbox\" name=\"supgroup%1\$d\"%3\$s />\n"
. " <label for=\"supgroup%1\$d\">%4\$s</label>\n"
. " </li>\n",
h($_), $self->_val_text("supgroup$_" . "sn"),
$self->_val_check("supgroup$_"),
h_abbr($form->param("supgroup$_" . "title")));
}
# Only super users can set the super-user group
if (su_group_sn != 0) {
if (is_su) {
push @_, sprintf(" <li><input id=\"su\" type=\"checkbox\" name=\"su\"%s />\n"
. " %s\n"
. " </li>\n",
$self->_val_check("su"),
group_opt_label(su_group_sn, "su"));
} else {
push @_, sprintf(" <li><input id=\"su\" type=\"checkbox\" disabled=\"disabled\" />\n"
. " %s\n"
. " </li>\n",
group_opt_label(su_group_sn));
}
}
# Attach the all-users group in any case
push @_, sprintf(" <li><input id=\"su\" type=\"checkbox\" checked=\"checked\" disabled=\"disabled\" />\n"
. " %s\n"
. " </li>\n",
group_opt_label(groupsn(ALLUSERS_GROUP)))
if defined groupsn(ALLUSERS_GROUP);
print "<ul>\n" . join("", @_) . " </ul>\n ";
print << "EOT";
</td>
</tr>
EOT
# A form to edit a current item
} elsif ($self->{"type"} eq "cur") {
# Read-only for a non-super-user editing herself or a super-user
if (!is_su && $self->{"sn"} == get_login_sn) {
print << "EOT";
<tr>
<th colspan="2" scope="row">$mark$label</th>
EOT
print " <td$colspan>";
for ($_ = 0, @_ = qw(); $_ < $current->param("supgroupcount"); $_++) {
push @_, " <li>" . h_abbr($current->param("supgroup$_" . "title")) . "</li>\n";
}
push @_, " <li>" . group_opt_label(su_group_sn) . "</li>\n"
if $current->param("su");
push @_, " <li>" . group_opt_label(groupsn(ALLUSERS_GROUP)) . "</li>\n"
if defined groupsn(ALLUSERS_GROUP);
print @_ > 0? "<ul>\n" . join("", @_) . " </ul>\n ": h_abbr(t_none);
print << "EOT";
</td>
</tr>
EOT
} else {
$orig = h_abbr(C_("Original:"));
$new = h_abbr(C_("New:"));
print << "EOT";
<tr>
<th class="th" rowspan="2" scope="row"><label for="supgroup0">$mark$label</label></th>
<th class="oldnew" scope="row">$orig</th>
EOT
print " <td$colspan>";
for ($_ = 0, @_ = qw(); $_ < $current->param("supgroupcount"); $_++) {
push @_, " <li>" . h_abbr($current->param("supgroup$_" . "title")) . "</li>\n";
}
push @_, " <li>" . group_opt_label(su_group_sn) . "</li>\n"
if $current->param("su");
push @_, " <li>" . group_opt_label(groupsn(ALLUSERS_GROUP)) . "</li>\n"
if defined groupsn(ALLUSERS_GROUP);
print @_ > 0? "<ul>\n" . join("", @_) . " </ul>\n ": h_abbr(t_none);
print << "EOT";
</td>
</tr>
<tr>
<th class="oldnew" scope="row"><label for="supgroup0">$new</label></th>
EOT
print " <td$colspan>";
for ($_ = 0, @_ = qw(); defined $form->param("supgroup$_" . "sn"); $_++) {
push @_, sprintf(" <li><input type=\"hidden\" name=\"supgroup%1\$dsn\"%2\$s />\n"
. " <input id=\"supgroup%1\$d\" type=\"checkbox\" name=\"supgroup%1\$d\"%3\$s />\n"
. " <label for=\"supgroup%1\$d\">%4\$s</label>\n"
. " </li>\n",
h($_), $self->_val_text("supgroup$_" . "sn"),
$self->_val_check("supgroup$_"),
h_abbr($form->param("supgroup$_" . "title")));
}
# Only super users can set the super-user group
if (su_group_sn != 0) {
if (is_su) {
push @_, sprintf(" <li><input id=\"su\" type=\"checkbox\" name=\"su\"%s />\n"
. " %s\n"
. " </li>\n",
$self->_val_check("su"),
group_opt_label(su_group_sn, "su"));
} else {
push @_, sprintf(" <li><input id=\"su\" type=\"checkbox\"%s disabled=\"disabled\" />\n"
. " %s\n"
. " </li>\n",
$current->param("su")? " checked=\"checked\"": "",
group_opt_label(su_group_sn));
}
}
# Attach the all-users group in any case
push @_, sprintf(" <li><input id=\"su\" type=\"checkbox\" checked=\"checked\" disabled=\"disabled\" />\n"
. " %s\n"
. " </li>\n",
group_opt_label(groupsn(ALLUSERS_GROUP)))
if defined groupsn(ALLUSERS_GROUP);
print "<ul>\n" . join("", @_) . " </ul>\n ";
print << "EOT";
</td>
</tr>
EOT
}
# A form to delete a current item
} else {
print << "EOT";
<tr>
<th class="th" scope="row">$mark$label</th>
EOT
print " <td$colspan>";
for ($_ = 0, @_ = qw(); $_ < $current->param("supgroupcount"); $_++) {
push @_, " <li>" . h_abbr($current->param("supgroup$_" . "title")) . "</li>\n";
}
push @_, " <li>" . group_opt_label(su_group_sn) . "</li>\n"
if $current->param("su");
push @_, " <li>" . group_opt_label(groupsn(ALLUSERS_GROUP)) . "</li>\n"
if defined groupsn(ALLUSERS_GROUP);
print @_ > 0? "<ul>\n" . join("", @_) . " </ul>\n ": h_abbr(t_none);
print << "EOT";
</td>
</tr>
EOT
}
return;
}
return 1;