mirror of
https://github.com/webmin/webmin.git
synced 2026-02-03 14:13:29 +00:00
Use new module
This commit is contained in:
44
Webmin/All.pm
Normal file
44
Webmin/All.pm
Normal file
@@ -0,0 +1,44 @@
|
||||
use Webmin::Page;
|
||||
use Webmin::ResultPage;
|
||||
use Webmin::ErrorPage;
|
||||
use Webmin::ConfirmPage;
|
||||
use Webmin::Form;
|
||||
use Webmin::Section;
|
||||
use Webmin::Textbox;
|
||||
use Webmin::OptTextbox;
|
||||
use Webmin::OptTextarea;
|
||||
use Webmin::Submit;
|
||||
use Webmin::Password;
|
||||
use Webmin::Checkbox;
|
||||
use Webmin::Select;
|
||||
use Webmin::Radios;
|
||||
use Webmin::Checkboxes;
|
||||
use Webmin::Table;
|
||||
use Webmin::Menu;
|
||||
use Webmin::LinkTable;
|
||||
use Webmin::Tabs;
|
||||
use Webmin::Textarea;
|
||||
use Webmin::Upload;
|
||||
use Webmin::DynamicText;
|
||||
use Webmin::DynamicBar;
|
||||
use Webmin::DynamicWait;
|
||||
use Webmin::DynamicHTML;
|
||||
use Webmin::Properties;
|
||||
use Webmin::User;
|
||||
use Webmin::Group;
|
||||
use Webmin::File;
|
||||
use Webmin::Button;
|
||||
use Webmin::JavascriptButton;
|
||||
use Webmin::PlainText;
|
||||
use Webmin::Multiline;
|
||||
use Webmin::Date;
|
||||
use Webmin::Time;
|
||||
use Webmin::TitleList;
|
||||
use Webmin::Columns;
|
||||
use Webmin::Icon;
|
||||
use Webmin::TableAction;
|
||||
use Webmin::InputTable;
|
||||
use WebminCore;
|
||||
|
||||
1;
|
||||
|
||||
61
Webmin/Button.pm
Normal file
61
Webmin/Button.pm
Normal file
@@ -0,0 +1,61 @@
|
||||
package Webmin::Button;
|
||||
use Webmin::Input;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Input" );
|
||||
|
||||
=head2 new Webmin::Button(cgi, label, [name])
|
||||
Creates a button that when clicked will link to some other page
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Button::new) &&
|
||||
caller() !~ /Webmin::Theme::Button/) {
|
||||
return new Webmin::Theme::Button(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $cgi, $value, $name) = @_;
|
||||
$self = { };
|
||||
bless($self);
|
||||
$self->set_cgi($cgi);
|
||||
$self->set_value($value);
|
||||
$self->set_name($name) if ($name);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns HTML for this button
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv = "<form action=".$self->get_cgi().">";
|
||||
foreach my $h (@{$self->{'hiddens'}}) {
|
||||
$rv .= &ui_hidden($h->[0], $h->[1])."\n";
|
||||
}
|
||||
$rv .= &ui_submit($self->get_value(), $self->get_name(),
|
||||
$self->get_disabled())."</form>";
|
||||
return $rv;
|
||||
}
|
||||
|
||||
sub set_cgi
|
||||
{
|
||||
my ($self, $cgi) = @_;
|
||||
$self->{'cgi'} = $cgi;
|
||||
}
|
||||
|
||||
sub get_cgi
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'cgi'};
|
||||
}
|
||||
|
||||
=head2 add_hidden(name, value)
|
||||
Adds some hidden input to this button, for passing to the CGI
|
||||
=cut
|
||||
sub add_hidden
|
||||
{
|
||||
my ($self, $name, $value) = @_;
|
||||
push(@{$self->{'hiddens'}}, [ $name, $value ]);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
64
Webmin/Checkbox.pm
Normal file
64
Webmin/Checkbox.pm
Normal file
@@ -0,0 +1,64 @@
|
||||
package Webmin::Checkbox;
|
||||
use Webmin::Input;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Input" );
|
||||
|
||||
=head2 new Webmin::Checkbox(name, return, label, checked, [disabled])
|
||||
Create a single checkbox field
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Checkbox::new)) {
|
||||
return new Webmin::Theme::Checkbox(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $name, $return, $label, $checked, $disabled) = @_;
|
||||
$self = { };
|
||||
bless($self);
|
||||
$self->set_name($name);
|
||||
$self->set_return($return);
|
||||
$self->set_label($label);
|
||||
$self->set_value($checked);
|
||||
$self->set_disabled($disabled);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this single checkbox
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $dis = $self->{'form'}->get_changefunc($self);
|
||||
return &ui_checkbox($self->get_name(), $self->get_return(),
|
||||
$self->get_label(), $self->get_value(),
|
||||
$dis ? "onClick='$dis'" : undef,
|
||||
$self->get_disabled()).
|
||||
&ui_hidden("ui_exists_".$self->get_name(), 1);
|
||||
}
|
||||
|
||||
sub set_return
|
||||
{
|
||||
my ($self, $return) = @_;
|
||||
$self->{'return'} = $return;
|
||||
}
|
||||
|
||||
sub set_label
|
||||
{
|
||||
my ($self, $label) = @_;
|
||||
$self->{'label'} = $label;
|
||||
}
|
||||
|
||||
sub get_return
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'return'};
|
||||
}
|
||||
|
||||
sub get_label
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'label'};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
119
Webmin/Checkboxes.pm
Normal file
119
Webmin/Checkboxes.pm
Normal file
@@ -0,0 +1,119 @@
|
||||
package Webmin::Checkboxes;
|
||||
use Webmin::Input;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Input" );
|
||||
|
||||
=head2 new Webmin::Checkboxes(name, value|&values, &options, [disabled])
|
||||
Create a list of checkboxes, of which zero or more may be selected
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Checkboxes::new)) {
|
||||
return new Webmin::Theme::Checkboxes(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $name, $value, $options, $disabled) = @_;
|
||||
$self = { };
|
||||
bless($self);
|
||||
$self->set_name($name);
|
||||
$self->set_value($value);
|
||||
$self->set_options($options);
|
||||
$self->set_disabled($disabled);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 add_option(name, [label])
|
||||
=cut
|
||||
sub add_option
|
||||
{
|
||||
my ($self, $name, $label) = @_;
|
||||
push(@{$self->{'options'}}, [ $name, $label ]);
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for all the checkboxes, one after the other
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
for(my $i=0; $i<@{$self->{'options'}}; $i++) {
|
||||
$rv .= $self->one_html($i)."\n";
|
||||
}
|
||||
return $rv;
|
||||
}
|
||||
|
||||
=head2 one_html(number)
|
||||
Returns the HTML for a single one of the checkboxes
|
||||
=cut
|
||||
sub one_html
|
||||
{
|
||||
my ($self, $num) = @_;
|
||||
my $opt = $self->{'options'}->[$num];
|
||||
my $value = $self->get_value();
|
||||
my %sel = map { $_, 1 } (ref($value) ? @$value : ( $value ));
|
||||
return &ui_checkbox($self->get_name(), $opt->[0],
|
||||
defined($opt->[1]) ? $opt->[1] : $opt->[0],
|
||||
$sel{$opt->[0]}, undef, $self->get_disabled()).
|
||||
($num == 0 ? &ui_hidden("ui_exists_".$self->get_name(), 1) : "");
|
||||
}
|
||||
|
||||
=head2 get_value()
|
||||
Returns a hash ref of all selected values
|
||||
=cut
|
||||
sub get_value
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $in = $self->{'form'} ? $self->{'form'}->{'in'} : undef;
|
||||
if ($in && (defined($in->{$self->{'name'}}) ||
|
||||
defined($in->{"ui_exists_".$self->{'name'}}))) {
|
||||
return [ split(/\0/, $in->{$self->{'name'}}) ];
|
||||
}
|
||||
elsif ($in && defined($in->{"ui_value_".$self->{'name'}})) {
|
||||
return [ split(/\0/, $in->{"ui_value_".$self->{'name'}}) ];
|
||||
}
|
||||
else {
|
||||
return $self->{'value'};
|
||||
}
|
||||
}
|
||||
|
||||
sub set_options
|
||||
{
|
||||
my ($self, $options) = @_;
|
||||
$self->{'options'} = $options;
|
||||
}
|
||||
|
||||
sub get_options
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'options'};
|
||||
}
|
||||
|
||||
=head2 validate()
|
||||
Returns a list of error messages for this field
|
||||
=cut
|
||||
sub validate
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $value = $self->get_value();
|
||||
if ($self->{'mandatory'} && !@$value) {
|
||||
return ( $self->{'mandmesg'} || $text{'ui_checkmandatory'} );
|
||||
}
|
||||
return ( );
|
||||
}
|
||||
|
||||
=head2 get_input_names()
|
||||
Returns the actual names of all HTML elements that make up this input
|
||||
=cut
|
||||
sub get_input_names
|
||||
{
|
||||
my ($self) = @_;
|
||||
my @rv;
|
||||
for(my $i=0; $i<@{$self->{'options'}}; $i++) {
|
||||
push(@rv, $self->{'name'}."[".$i."]");
|
||||
}
|
||||
return @rv;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
82
Webmin/Columns.pm
Normal file
82
Webmin/Columns.pm
Normal file
@@ -0,0 +1,82 @@
|
||||
package Webmin::Columns;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::Columns(cols)
|
||||
Displays some page elements in a multi-column table
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
my ($self, $cols) = @_;
|
||||
if (defined(&Webmin::Theme::Columns::new)) {
|
||||
return new Webmin::Theme::Columns(@_[1..$#_]);
|
||||
}
|
||||
$self = { 'columns' => 2 };
|
||||
bless($self);
|
||||
$self->set_columns($cols) if (defined($cols));
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns HTML for the objects, arranged in columns
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
my $n = scalar(@{$self->{'contents'}});
|
||||
$rv .= "<table width=100% cellpadding=4><tr>\n";
|
||||
my $h = int($n / $self->{'columns'})+1;
|
||||
my $i = 0;
|
||||
my $pc = int(100/$self->{'columns'});
|
||||
foreach my $c (@{$self->{'contents'}}) {
|
||||
if ($i%$h == 0) {
|
||||
$rv .= "<td valign=top width=$pc%>";
|
||||
}
|
||||
$rv .= $c->html()."<p>\n";
|
||||
$i++;
|
||||
if ($i%$h == 0) {
|
||||
$rv .= "</td>\n";
|
||||
}
|
||||
}
|
||||
$rv .= "</tr></table>\n";
|
||||
return $rv;
|
||||
}
|
||||
|
||||
=head2 add(object)
|
||||
Adds some Webmin:: object to this list
|
||||
=cut
|
||||
sub add
|
||||
{
|
||||
my ($self, $object) = @_;
|
||||
push(@{$self->{'contents'}}, $object);
|
||||
if ($self->{'page'}) {
|
||||
$object->set_page($self->{'page'});
|
||||
}
|
||||
}
|
||||
|
||||
sub set_columns
|
||||
{
|
||||
my ($self, $columns) = @_;
|
||||
$self->{'columns'} = $columns;
|
||||
}
|
||||
|
||||
sub get_columns
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'columns'};
|
||||
}
|
||||
|
||||
=head2 set_page(Webmin::Page)
|
||||
Called when this menu is added to a page
|
||||
=cut
|
||||
sub set_page
|
||||
{
|
||||
my ($self, $page) = @_;
|
||||
$self->{'page'} = $page;
|
||||
foreach my $c (@{$self->{'contents'}}) {
|
||||
$c->set_page($page);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
47
Webmin/ConfirmPage.pm
Normal file
47
Webmin/ConfirmPage.pm
Normal file
@@ -0,0 +1,47 @@
|
||||
package Webmin::ConfirmPage;
|
||||
use Webmin::Page;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Page" );
|
||||
|
||||
=head2 new Webmin::ConfirmPage(subheading, title, message, cgi, &in, [ok-message],
|
||||
[cancel-message], [help-name])
|
||||
Create a new page object that asks if the user is sure if he wants to
|
||||
do something or not.
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::ConfirmPage::new)) {
|
||||
return new Webmin::Theme::ConfirmPage(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $subheading, $title, $message, $cgi, $in, $ok, $cancel, $help) = @_;
|
||||
$self = new Webmin::Page($subheading, $title, $help);
|
||||
$self->{'in'} = $in;
|
||||
$self->add_message($message);
|
||||
my $form = new Webmin::Form($cgi, "get");
|
||||
$form->set_input($in);
|
||||
$self->add_form($form);
|
||||
foreach my $i (keys %$in) {
|
||||
foreach my $v (split(/\0/, $in->{$i})) {
|
||||
$form->add_hidden($i, $v);
|
||||
}
|
||||
}
|
||||
$form->add_button(new Webmin::Submit($ok || "OK", "ui_confirm"));
|
||||
$form->add_button(new Webmin::Submit($cancel || $text{'cancel'}, "ui_cancel"));
|
||||
bless($self);
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub get_confirm
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'in'}->{'ui_confirm'} ? 1 : 0;
|
||||
}
|
||||
|
||||
sub get_cancel
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'in'}->{'ui_cancel'} ? 1 : 0;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
96
Webmin/Date.pm
Normal file
96
Webmin/Date.pm
Normal file
@@ -0,0 +1,96 @@
|
||||
package Webmin::Date;
|
||||
use Webmin::Input;
|
||||
use Time::Local;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Input" );
|
||||
|
||||
=head2 new Webmin::Date(name, time, [disabled])
|
||||
Create a new field for selecting a date
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Date::new)) {
|
||||
return new Webmin::Theme::Date(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $name, $value, $disabled) = @_;
|
||||
bless($self = { });
|
||||
$self->set_name($name);
|
||||
$self->set_value($value);
|
||||
$self->set_disabled($disabled) if (defined($disabled));
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for the date chooser
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
my @tm = localtime($self->get_value());
|
||||
my $name = $self->get_name();
|
||||
$rv .= &ui_date_input($tm[3], $tm[4]+1, $tm[5]+1900,
|
||||
"day_".$name, "month_".$name, "year_".$name,
|
||||
$self->get_disabled())." ".
|
||||
&date_chooser_button("day_".$name, "month_".$name, "year_".$name);
|
||||
return $rv;
|
||||
}
|
||||
|
||||
=head2 get_value()
|
||||
Returns the date as a Unix time number (for zero o'clock)
|
||||
=cut
|
||||
sub get_value
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $in = $self->{'form'} ? $self->{'form'}->{'in'} : undef;
|
||||
if ($in && defined($in->{"day_".$self->{'name'}})) {
|
||||
my $rv = $self->to_time($in);
|
||||
return defined($rv) ? $rv : $self->{'value'};
|
||||
}
|
||||
elsif ($in && defined($in->{"ui_value_".$self->{'name'}})) {
|
||||
return $in->{"ui_value_".$self->{'name'}};
|
||||
}
|
||||
else {
|
||||
return $self->{'value'};
|
||||
}
|
||||
}
|
||||
|
||||
sub to_time
|
||||
{
|
||||
my ($self, $in) = @_;
|
||||
my $day = $in->{"day_".$self->{'name'}};
|
||||
return undef if ($day !~ /^\d+$/);
|
||||
my $month = $in->{"month_".$self->{'name'}}-1;
|
||||
my $year = $in->{"year_".$self->{'name'}}-1900;
|
||||
return undef if ($year !~ /^\d+$/);
|
||||
my $rv = eval { timelocal(0, 0, 0, $day, $month, $year) };
|
||||
return $@ ? undef : $rv;
|
||||
}
|
||||
|
||||
sub set_validation_func
|
||||
{
|
||||
my ($self, $func) = @_;
|
||||
$self->{'validation_func'} = $func;
|
||||
}
|
||||
|
||||
=head2 validate()
|
||||
Ensures that the date is valid
|
||||
=cut
|
||||
sub validate
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $tm = $self->to_time($self->{'form'}->{'in'});
|
||||
if (!defined($tm)) {
|
||||
return ( $text{'ui_edate'} );
|
||||
}
|
||||
if ($self->{'validation_func'}) {
|
||||
my $err = &{$self->{'validation_func'}}($self->get_value(),
|
||||
$self->{'name'},
|
||||
$self->{'form'});
|
||||
return ( $err ) if ($err);
|
||||
}
|
||||
return ( );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
119
Webmin/DynamicBar.pm
Normal file
119
Webmin/DynamicBar.pm
Normal file
@@ -0,0 +1,119 @@
|
||||
package Webmin::DynamicBar;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::DynamicBar(&start-function, max)
|
||||
A page element for displaying progress towards some goal, like the download of
|
||||
a file.
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
my ($self, $func, $max) = @_;
|
||||
$self = { 'func' => $func,
|
||||
'name' => "dynamic".++$dynamic_count,
|
||||
'width' => 80,
|
||||
'max' => $max };
|
||||
bless($self);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 set_message(text)
|
||||
Sets the text describing what we are waiting for
|
||||
=cut
|
||||
sub set_message
|
||||
{
|
||||
my ($self, $message) = @_;
|
||||
$self->{'message'} = $message;
|
||||
}
|
||||
|
||||
sub get_message
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'message'};
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for the text field
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
if ($self->get_message()) {
|
||||
$rv .= $self->get_message()."<p>\n";
|
||||
}
|
||||
$rv .= "<form name=form_$self->{'name'}>";
|
||||
$rv .= "<input name=bar_$self->{'name'} size=$self->{'width'} disabled=true style='font-family: courier'>";
|
||||
$rv .= " ";
|
||||
$rv .= "<input name=pc_$self->{'name'} size=3 disabled=true style='font-family: courier'>%";
|
||||
$rv .= "</form>";
|
||||
return $rv;
|
||||
}
|
||||
|
||||
=head2 start()
|
||||
Called by the page to begin the progress
|
||||
=cut
|
||||
sub start
|
||||
{
|
||||
my ($self) = @_;
|
||||
&{$self->{'func'}}($self);
|
||||
}
|
||||
|
||||
=head2 update(pos)
|
||||
Called by the function to update the position of the bar.
|
||||
=cut
|
||||
sub update
|
||||
{
|
||||
my ($self, $pos) = @_;
|
||||
my $pc = int(100*$pos/$self->{'max'});
|
||||
if ($pc != $self->{'lastpc'}) {
|
||||
my $xn = int($self->{'width'}*$pos/$self->{'max'});
|
||||
my $xes = "X" x $xn;
|
||||
print "<script>window.document.forms[\"form_$self->{'name'}\"].pc_$self->{'name'}.value = \"$pc\";</script>\n";
|
||||
print "<script>window.document.forms[\"form_$self->{'name'}\"].bar_$self->{'name'}.value = \"$xes\";</script>\n";
|
||||
$self->{'lastpc'} = $pc;
|
||||
}
|
||||
}
|
||||
|
||||
=head2 set_wait(wait)
|
||||
If called with a non-zero arg, generation of the page should wait until this
|
||||
the progress is complete. Otherwise, the page will be generated completely before
|
||||
the start function is called
|
||||
=cut
|
||||
sub set_wait
|
||||
{
|
||||
my ($self, $wait) = @_;
|
||||
$self->{'wait'} = $wait;
|
||||
}
|
||||
|
||||
sub get_wait
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'wait'};
|
||||
}
|
||||
|
||||
=head2 set_page(Webmin::Page)
|
||||
Called when this dynamic text box is added to a page
|
||||
=cut
|
||||
sub set_page
|
||||
{
|
||||
my ($self, $page) = @_;
|
||||
$self->{'page'} = $page;
|
||||
}
|
||||
|
||||
sub set_width
|
||||
{
|
||||
my ($self, $width) = @_;
|
||||
$self->{'width'} = $width;
|
||||
}
|
||||
|
||||
=head2 needs_unbuffered()
|
||||
Must return 1 if the page needs to be in un-buffered and no-table mode
|
||||
=cut
|
||||
sub needs_unbuffered
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
76
Webmin/DynamicHTML.pm
Normal file
76
Webmin/DynamicHTML.pm
Normal file
@@ -0,0 +1,76 @@
|
||||
package Webmin::DynamicHTML;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::DynamicHTML(&function, &args, [before])
|
||||
When the page is being rendered, executes the given function and prints any
|
||||
text that it returns.
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
my ($self, $func, $args, $before) = @_;
|
||||
$self = { 'func' => $func,
|
||||
'args' => $args,
|
||||
'before' => $before };
|
||||
bless($self);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 set_before(text)
|
||||
Sets the text describing what we are waiting for
|
||||
=cut
|
||||
sub set_before
|
||||
{
|
||||
my ($self, $before) = @_;
|
||||
$self->{'before'} = $before;
|
||||
}
|
||||
|
||||
sub get_before
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'before'};
|
||||
}
|
||||
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
if ($self->get_before()) {
|
||||
$rv .= $self->get_before()."<p>\n";
|
||||
}
|
||||
return $rv;
|
||||
}
|
||||
|
||||
=head2 start()
|
||||
Called by the page to begin the dynamic output.
|
||||
=cut
|
||||
sub start
|
||||
{
|
||||
my ($self) = @_;
|
||||
&{$self->{'func'}}($self, @$args);
|
||||
}
|
||||
|
||||
sub get_wait
|
||||
{
|
||||
my ($self) = @_;
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head2 needs_unbuffered()
|
||||
Must return 1 if the page needs to be in un-buffered and no-table mode
|
||||
=cut
|
||||
sub needs_unbuffered
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head2 set_page(Webmin::Page)
|
||||
Called when this dynamic HTML element is added to a page
|
||||
=cut
|
||||
sub set_page
|
||||
{
|
||||
my ($self, $page) = @_;
|
||||
$self->{'page'} = $page;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
123
Webmin/DynamicText.pm
Normal file
123
Webmin/DynamicText.pm
Normal file
@@ -0,0 +1,123 @@
|
||||
# XXX should support non-Javascript mode?
|
||||
package Webmin::DynamicText;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::DynamicText(&start-function, &args)
|
||||
A page element for displaying text that takes time to generate, such as from
|
||||
a long-running script. Uses a non-editable text box, updated via Javascript.
|
||||
The function will be called when it is time to start producing output, with this
|
||||
object as a parameter. It must call the add_line function on the object for each
|
||||
new line to be added.
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
my ($self, $func, $args) = @_;
|
||||
$self = { 'func' => $func,
|
||||
'args' => $args,
|
||||
'name' => "dynamic".++$dynamic_count,
|
||||
'rows' => 20,
|
||||
'cols' => 80 };
|
||||
bless($self);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 set_message(text)
|
||||
Sets the text describing what we are waiting for
|
||||
=cut
|
||||
sub set_message
|
||||
{
|
||||
my ($self, $message) = @_;
|
||||
$self->{'message'} = $message;
|
||||
}
|
||||
|
||||
sub get_message
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'message'};
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for the text box
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
if ($self->get_message()) {
|
||||
$rv .= $self->get_message()."<p>\n";
|
||||
}
|
||||
$rv .= "<form name=form_$self->{'name'}>";
|
||||
$rv .= "<textarea name=$self->{'name'} rows=$self->{'rows'} cols=$self->{'cols'} wrap=off disabled=true>";
|
||||
$rv .= "</textarea>\n";
|
||||
$rv .= "</form>";
|
||||
return $rv;
|
||||
}
|
||||
|
||||
=head2 start()
|
||||
Called by the page to begin the dynamic output.
|
||||
=cut
|
||||
sub start
|
||||
{
|
||||
my ($self) = @_;
|
||||
&{$self->{'func'}}($self, @$args);
|
||||
}
|
||||
|
||||
=head2 add_line(line)
|
||||
Called by the function to add a line of text to this output
|
||||
=cut
|
||||
sub add_line
|
||||
{
|
||||
my ($self, $line) = @_;
|
||||
$line =~ s/\r|\n//g;
|
||||
$line = "e_escape($line);
|
||||
print "<script>window.document.forms[\"form_$self->{'name'}\"].$self->{'name'}.value += \"$line\"+\"\\n\";</script>\n";
|
||||
}
|
||||
|
||||
=head2 set_wait(wait)
|
||||
If called with a non-zero arg, generation of the page should wait until this
|
||||
text box is complete. Otherwise, the page will be generated completely before the
|
||||
start function is called
|
||||
=cut
|
||||
sub set_wait
|
||||
{
|
||||
my ($self, $wait) = @_;
|
||||
$self->{'wait'} = $wait;
|
||||
}
|
||||
|
||||
sub get_wait
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'wait'};
|
||||
}
|
||||
|
||||
=head2 set_page(Webmin::Page)
|
||||
Called when this dynamic text box is added to a page
|
||||
=cut
|
||||
sub set_page
|
||||
{
|
||||
my ($self, $page) = @_;
|
||||
$self->{'page'} = $page;
|
||||
}
|
||||
|
||||
sub set_rows
|
||||
{
|
||||
my ($self, $rows) = @_;
|
||||
$self->{'rows'} = $rows;
|
||||
}
|
||||
|
||||
sub set_cols
|
||||
{
|
||||
my ($self, $cols) = @_;
|
||||
$self->{'cols'} = $cols;
|
||||
}
|
||||
|
||||
=head2 needs_unbuffered()
|
||||
Must return 1 if the page needs to be in un-buffered and no-table mode
|
||||
=cut
|
||||
sub needs_unbuffered
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
129
Webmin/DynamicWait.pm
Normal file
129
Webmin/DynamicWait.pm
Normal file
@@ -0,0 +1,129 @@
|
||||
package Webmin::DynamicWait;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::DynamicWait(&start-function, [&args])
|
||||
A page element indicating that something is happening.
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
my ($self, $func, $args) = @_;
|
||||
$self = { 'func' => $func,
|
||||
'args' => $args,
|
||||
'name' => "dynamic".++$dynamic_count,
|
||||
'width' => 80,
|
||||
'delay' => 20 };
|
||||
bless($self);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 set_message(text)
|
||||
Sets the text describing what we are waiting for
|
||||
=cut
|
||||
sub set_message
|
||||
{
|
||||
my ($self, $message) = @_;
|
||||
$self->{'message'} = $message;
|
||||
}
|
||||
|
||||
sub get_message
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'message'};
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for the text field used to indicate progress
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
if ($self->get_message()) {
|
||||
$rv .= $self->get_message()."<p>\n";
|
||||
}
|
||||
$rv .= "<form name=form_$self->{'name'}>";
|
||||
$rv .= "<input name=$self->{'name'} size=$self->{'width'} disabled=true style='font-family: courier'>";
|
||||
$rv .= "</form>";
|
||||
return $rv;
|
||||
}
|
||||
|
||||
=head2 start()
|
||||
Called by the page to begin the progress. Also starts a process to update the
|
||||
Javascript text box
|
||||
=cut
|
||||
sub start
|
||||
{
|
||||
my ($self) = @_;
|
||||
$self->{'pid'} = fork();
|
||||
if (!$self->{'pid'}) {
|
||||
my $pos = 0;
|
||||
while(1) {
|
||||
select(undef, undef, undef, $self->{'delay'}/1000.0);
|
||||
my $str = (" " x $pos) . ("x" x 10);
|
||||
print "<script>window.document.forms[\"form_$self->{'name'}\"].$self->{'name'}.value = \"$str\";</script>\n";
|
||||
$pos++;
|
||||
$pos = 0 if ($pos == $self->{'width'});
|
||||
}
|
||||
exit;
|
||||
}
|
||||
&{$self->{'func'}}($self, @{$self->{'args'}});
|
||||
}
|
||||
|
||||
=head2 stop()
|
||||
Called back by the function when whatever we were waiting for is done
|
||||
=cut
|
||||
sub stop
|
||||
{
|
||||
my ($self) = @_;
|
||||
if ($self->{'pid'}) {
|
||||
kill('TERM', $self->{'pid'});
|
||||
}
|
||||
my $str = (" " x ($self->{'width'}/2 - 2)) . "DONE";
|
||||
print "<script>window.document.forms[\"form_$self->{'name'}\"].$self->{'name'}.value = \"$str\";</script>\n";
|
||||
}
|
||||
|
||||
=head2 set_wait(wait)
|
||||
If called with a non-zero arg, generation of the page should wait until this
|
||||
the progress is complete. Otherwise, the page will be generated completely before
|
||||
the start function is called
|
||||
=cut
|
||||
sub set_wait
|
||||
{
|
||||
my ($self, $wait) = @_;
|
||||
$self->{'wait'} = $wait;
|
||||
}
|
||||
|
||||
sub get_wait
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'wait'};
|
||||
}
|
||||
|
||||
=head2 set_page(Webmin::Page)
|
||||
Called when this dynamic text box is added to a page
|
||||
=cut
|
||||
sub set_page
|
||||
{
|
||||
my ($self, $page) = @_;
|
||||
$self->{'page'} = $page;
|
||||
}
|
||||
|
||||
sub set_width
|
||||
{
|
||||
my ($self, $width) = @_;
|
||||
$self->{'width'} = $width;
|
||||
}
|
||||
|
||||
=head2 needs_unbuffered()
|
||||
Must return 1 if the page needs to be in un-buffered and no-table mode
|
||||
=cut
|
||||
sub needs_unbuffered
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
1;
|
||||
|
||||
20
Webmin/ErrorPage.pm
Normal file
20
Webmin/ErrorPage.pm
Normal file
@@ -0,0 +1,20 @@
|
||||
package Webmin::ErrorPage;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::ErrorPage(subheading, title, message, [program-output], [help-name])
|
||||
Create a new page object for showing an error of some kind
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::ErrorPage::new)) {
|
||||
return new Webmin::Theme::ErrorPage(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $subheading, $title, $message, $output, $help) = @_;
|
||||
$self = new Webmin::Page($subheading, $title, $help);
|
||||
$self->add_message("<b>",$text{'error'}," : ",$message,"</b>");
|
||||
$self->add_message("<pre>",$output,"</pre>");
|
||||
return $self;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
70
Webmin/File.pm
Normal file
70
Webmin/File.pm
Normal file
@@ -0,0 +1,70 @@
|
||||
package Webmin::File;
|
||||
use Webmin::Textbox;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Textbox" );
|
||||
|
||||
=head2 new Webmin::File(name, value, size, [directory], [disabled])
|
||||
A text box for selecting a file
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::File::new)) {
|
||||
return new Webmin::Theme::File(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $name, $value, $size, $directory, $disabled) = @_;
|
||||
$self = new Webmin::Textbox($name, $value, $size, $disabled);
|
||||
bless($self);
|
||||
$self->set_directory($directory);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this file input
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv = Webmin::Textbox::html($self);
|
||||
my $name = $self->get_name();
|
||||
my $directory = $self->get_directory();
|
||||
my $add = 0;
|
||||
my $chroot = $self->get_chroot();
|
||||
$rv .= "<input type=button name=${name}_button onClick='ifield = form.$name; chooser = window.open(\"$gconfig{'webprefix'}/chooser.cgi?add=$add&type=$directory&chroot=$chroot&file=\"+escape(ifield.value), \"chooser\", \"toolbar=no,menubar=no,scrollbar=no,width=400,height=300\"); chooser.ifield = ifield; window.ifield = ifield' value=\"...\">\n";
|
||||
return $rv;
|
||||
}
|
||||
|
||||
sub set_directory
|
||||
{
|
||||
my ($self, $directory) = @_;
|
||||
$self->{'directory'} = $directory;
|
||||
}
|
||||
|
||||
sub get_directory
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'directory'};
|
||||
}
|
||||
|
||||
sub set_chroot
|
||||
{
|
||||
my ($self, $chroot) = @_;
|
||||
$self->{'chroot'} = $chroot;
|
||||
}
|
||||
|
||||
sub get_chroot
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'chroot'};
|
||||
}
|
||||
|
||||
=head2 get_input_names()
|
||||
Returns the actual names of all HTML elements that make up this input
|
||||
=cut
|
||||
sub get_input_names
|
||||
{
|
||||
my ($self) = @_;
|
||||
return ( $self->{'name'}, $self->{'name'}."_button" );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
405
Webmin/Form.pm
Normal file
405
Webmin/Form.pm
Normal file
@@ -0,0 +1,405 @@
|
||||
package Webmin::Form;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::Form(cgi, [method])
|
||||
Creates a new form, which submits to the given CGI
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Form::new)) {
|
||||
return new Webmin::Theme::Form(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $program, $method) = @_;
|
||||
$self = { 'method' => 'get',
|
||||
'name' => "form".++$form_count };
|
||||
bless($self);
|
||||
$self->set_program($program);
|
||||
$self->set_method($method) if ($method);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML that makes up this form
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
if ($self->get_align()) {
|
||||
$rv .= "<div align=".$self->get_align().">\n";
|
||||
}
|
||||
$rv .= $self->form_start();
|
||||
if ($self->get_heading()) {
|
||||
if (defined(&ui_subheading)) {
|
||||
$rv .= &ui_subheading($self->get_heading());
|
||||
}
|
||||
else {
|
||||
$rv .= "<h3>".$self->get_heading()."</h3>\n";
|
||||
}
|
||||
}
|
||||
|
||||
# Add the sections
|
||||
foreach my $h (@{$self->{'hiddens'}}) {
|
||||
$rv .= &ui_hidden($h->[0], $h->[1])."\n";
|
||||
}
|
||||
foreach my $s (@{$self->{'sections'}}) {
|
||||
$rv .= $s->html();
|
||||
}
|
||||
|
||||
# Check if we have any inputs that need disabling
|
||||
my @dis = $self->list_disable_inputs();
|
||||
if (@dis) {
|
||||
# Yes .. generate a function for them
|
||||
$rv .= "<script>\n";
|
||||
$rv .= "function ui_disable_".$self->{'name'}."(form) {\n";
|
||||
foreach my $i (@dis) {
|
||||
foreach my $n ($i->get_input_names()) {
|
||||
$rv .= " form.".$n.".disabled = (".
|
||||
$i->get_disable_code().");\n";
|
||||
}
|
||||
}
|
||||
$rv .= "}\n";
|
||||
$rv .= "</script>\n";
|
||||
}
|
||||
|
||||
# Add the buttons at the end of the form
|
||||
my @buttonargs;
|
||||
foreach my $b (@{$self->{'buttons'}}) {
|
||||
if (ref($b)) {
|
||||
# An array of inputs
|
||||
my $ihtml = join(" ", map { $_->html() } @$b);
|
||||
push(@buttonargs, $ihtml);
|
||||
}
|
||||
else {
|
||||
# A spacer
|
||||
push(@buttonargs, "");
|
||||
}
|
||||
}
|
||||
$rv .= &ui_form_end(\@buttonargs);
|
||||
|
||||
if ($self->get_align()) {
|
||||
$rv .= "</div>\n";
|
||||
}
|
||||
|
||||
# Call the Javascript disable function
|
||||
if (@dis) {
|
||||
$rv .= "<script>\n";
|
||||
$rv .= "ui_disable_".$self->{'name'}."(window.document.forms[\"$self->{'name'}\"]);\n";
|
||||
$rv .= "</script>\n";
|
||||
}
|
||||
|
||||
return $rv;
|
||||
}
|
||||
|
||||
sub form_start
|
||||
{
|
||||
my ($self) = @_;
|
||||
return "<form action='$self->{'program'}' ".
|
||||
($self->{'method'} eq "post" ? "method=post" :
|
||||
$self->{'method'} eq "form-data" ?
|
||||
"method=post enctype=multipart/form-data" :
|
||||
"method=get")." name=$self->{'name'}>\n";
|
||||
}
|
||||
|
||||
=head2 add_section(section)
|
||||
Adds a Webmin::Section object to this form
|
||||
=cut
|
||||
sub add_section
|
||||
{
|
||||
my ($self, $section) = @_;
|
||||
push(@{$self->{'sections'}}, $section);
|
||||
$section->set_form($self);
|
||||
}
|
||||
|
||||
=head2 get_section(idx)
|
||||
=cut
|
||||
sub get_section
|
||||
{
|
||||
my ($self, $idx) = @_;
|
||||
return $self->{'sections'}->[$idx];
|
||||
}
|
||||
|
||||
=head2 add_button(button, [beside, ...])
|
||||
Adds a Webmin::Submit object to this form, for display at the bottom
|
||||
=cut
|
||||
sub add_button
|
||||
{
|
||||
my ($self, $button, @beside) = @_;
|
||||
push(@{$self->{'buttons'}}, [ $button, @beside ]);
|
||||
}
|
||||
|
||||
=head2 add_button_spacer()
|
||||
Adds a gap between buttons, for grouping
|
||||
=cut
|
||||
sub add_button_spacer
|
||||
{
|
||||
my ($self, $spacer) = @_;
|
||||
push(@{$self->{'buttons'}}, $spacer);
|
||||
}
|
||||
|
||||
=head2 add_hidden(name, value)
|
||||
Adds some hidden input to this form, for passing to the CGI
|
||||
=cut
|
||||
sub add_hidden
|
||||
{
|
||||
my ($self, $name, $value) = @_;
|
||||
push(@{$self->{'hiddens'}}, [ $name, $value ]);
|
||||
}
|
||||
|
||||
=head2 validate()
|
||||
Validates all form inputs, based on the current CGI input hash. Returns a list
|
||||
of errors, each of which is field name and error message.
|
||||
=cut
|
||||
sub validate
|
||||
{
|
||||
my ($self) = @_;
|
||||
my @errs;
|
||||
foreach my $s (@{$self->{'sections'}}) {
|
||||
push(@errs, $s->validate($self->{'in'}));
|
||||
}
|
||||
return @errs;
|
||||
}
|
||||
|
||||
=head2 validate_redirect(page, [&extra-errors])
|
||||
Validates the form, and if any errors are found re-directs to the given page
|
||||
with the errors, so that they can be displayed.
|
||||
=cut
|
||||
sub validate_redirect
|
||||
{
|
||||
my ($self, $page, $extras) = @_;
|
||||
if ($self->{'in'}->{'ui_redirecting'}) {
|
||||
# If this page is displayed as part of a redirect, no need to validate!
|
||||
return;
|
||||
}
|
||||
my @errs = $self->validate();
|
||||
push(@errs, @$extras);
|
||||
if (@errs) {
|
||||
my (@errlist, @vallist);
|
||||
foreach my $e (@errs) {
|
||||
push(@errlist, &urlize("ui_error_".$e->[0])."=".
|
||||
&urlize($e->[1]));
|
||||
}
|
||||
foreach my $i ($self->list_inputs()) {
|
||||
my $v = $i->get_value();
|
||||
my @vals = ref($v) ? @$v : ( $v );
|
||||
@vals = ( undef ) if (!@vals);
|
||||
foreach $v (@vals) {
|
||||
push(@vallist,
|
||||
&urlize("ui_value_".$i->get_name())."=".
|
||||
&urlize($v));
|
||||
}
|
||||
}
|
||||
foreach my $h (@{$self->{'hiddens'}}) {
|
||||
push(@vallist,
|
||||
&urlize($h->[0])."=".&urlize($h->[1]));
|
||||
}
|
||||
if ($page =~ /\?/) { $page .= "&"; }
|
||||
else { $page .= "?"; }
|
||||
&redirect($page.join("&", "ui_redirecting=1", @errlist, @vallist));
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
=head2 validate_error(whatfailed)
|
||||
Validates the form, and if any errors are found displays an error page.
|
||||
=cut
|
||||
sub validate_error
|
||||
{
|
||||
my ($self, $whatfailed) = @_;
|
||||
my @errs = $self->validate();
|
||||
&error_setup($whatfailed);
|
||||
if (@errs == 1) {
|
||||
&error($errs[0]->[2] ? "$errs[0]->[2] : $errs[0]->[1]"
|
||||
: $errs[0]->[1]);
|
||||
}
|
||||
elsif (@errs > 1) {
|
||||
my $msg = $text{'ui_errors'}."<br>";
|
||||
foreach my $e (@errs) {
|
||||
$msg .= $e->[2] ? "$e->[2] : $e->[1]<br>\n"
|
||||
: "$e->[1]<br>\n";
|
||||
}
|
||||
&error($msg);
|
||||
}
|
||||
}
|
||||
|
||||
=head2 field_errors(name)
|
||||
Returns a list of error messages associated with the field of some name, from
|
||||
the input passed to set_input
|
||||
=cut
|
||||
sub field_errors
|
||||
{
|
||||
my ($self, $name) = @_;
|
||||
my @errs;
|
||||
my $in = $self->{'in'};
|
||||
foreach my $i (keys %$in) {
|
||||
if ($i eq "ui_error_".$name) {
|
||||
push(@errs, split(/\0/, $in->{$i}));
|
||||
}
|
||||
}
|
||||
return @errs;
|
||||
}
|
||||
|
||||
=head2 set_input(&input)
|
||||
Passes the form input hash to this form object, for use by the validate
|
||||
functions and for displaying errors next to fields.
|
||||
=cut
|
||||
sub set_input
|
||||
{
|
||||
my ($self, $in) = @_;
|
||||
$self->{'in'} = $in;
|
||||
}
|
||||
|
||||
=head2 get_value(input-name)
|
||||
Returns the value of the input with the given name.
|
||||
=cut
|
||||
sub get_value
|
||||
{
|
||||
my ($self, $name) = @_;
|
||||
foreach my $s (@{$self->{'sections'}}) {
|
||||
my $rv = $s->get_value($name);
|
||||
return $rv if (defined($rv));
|
||||
}
|
||||
return $self->{'in'}->{$name};
|
||||
}
|
||||
|
||||
=head2 get_input(name)
|
||||
Returns the input with the given name
|
||||
=cut
|
||||
sub get_input
|
||||
{
|
||||
my ($self, $name) = @_;
|
||||
foreach my $i ($self->list_inputs()) {
|
||||
return $i if ($i->get_name() eq $name);
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub set_program
|
||||
{
|
||||
my ($self, $program) = @_;
|
||||
$self->{'program'} = $program;
|
||||
}
|
||||
|
||||
sub set_method
|
||||
{
|
||||
my ($self, $method) = @_;
|
||||
$self->{'method'} = $method;
|
||||
}
|
||||
|
||||
=head2 list_inputs()
|
||||
Returns all inputs in all form sections
|
||||
=cut
|
||||
sub list_inputs
|
||||
{
|
||||
my ($self) = @_;
|
||||
my @rv;
|
||||
foreach my $s (@{$self->{'sections'}}) {
|
||||
push(@rv, $s->list_inputs());
|
||||
}
|
||||
return @rv;
|
||||
}
|
||||
|
||||
=head2 list_disable_inputs()
|
||||
Returns a list of inputs that have disable functions
|
||||
=cut
|
||||
sub list_disable_inputs
|
||||
{
|
||||
my ($self) = @_;
|
||||
my @dis;
|
||||
foreach my $i ($self->list_inputs()) {
|
||||
push(@dis, $i) if ($i->get_disable_code());
|
||||
}
|
||||
return @dis;
|
||||
}
|
||||
|
||||
=head2 set_page(Webmin::Page)
|
||||
Called when this form is added to a page
|
||||
=cut
|
||||
sub set_page
|
||||
{
|
||||
my ($self, $page) = @_;
|
||||
$self->{'page'} = $page;
|
||||
}
|
||||
|
||||
=head2 get_changefunc(&input)
|
||||
Called by some input, to return the Javascript that should be called when this
|
||||
input changes it's value.
|
||||
=cut
|
||||
sub get_changefunc
|
||||
{
|
||||
my ($self, $input) = @_;
|
||||
my @dis = $self->list_disable_inputs();
|
||||
if (@dis) {
|
||||
return "ui_disable_".$self->{'name'}."(form)";
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
=head2 set_heading(text)
|
||||
Sets the heading to be displayed above the form
|
||||
=cut
|
||||
sub set_heading
|
||||
{
|
||||
my ($self, $heading) = @_;
|
||||
$self->{'heading'} = $heading;
|
||||
}
|
||||
|
||||
sub get_heading
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'heading'};
|
||||
}
|
||||
|
||||
=head2 get_formno()
|
||||
Returns the index of this form on the page
|
||||
=cut
|
||||
sub get_formno
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $n = 0;
|
||||
foreach my $f (@{$self->{'page'}->{'contents'}}) {
|
||||
if ($f eq $self) {
|
||||
return $n;
|
||||
}
|
||||
elsif (ref($f) =~ /Form/) {
|
||||
$n++;
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
=head2 add_onload(code)
|
||||
Adds some Javascript code for inclusion in the onLoad tag
|
||||
=cut
|
||||
sub add_onload
|
||||
{
|
||||
my ($self, $code) = @_;
|
||||
push(@{$self->{'onloads'}}, $code);
|
||||
}
|
||||
|
||||
=head2 add_script(code)
|
||||
Adds some Javascript code for putting in the <head> section
|
||||
=cut
|
||||
sub add_script
|
||||
{
|
||||
my ($self, $script) = @_;
|
||||
push(@{$self->{'scripts'}}, $script);
|
||||
}
|
||||
|
||||
=head2 set_align(align)
|
||||
Sets the alignment on the page (left, center, right)
|
||||
=cut
|
||||
sub set_align
|
||||
{
|
||||
my ($self, $align) = @_;
|
||||
$self->{'align'} = $align;
|
||||
}
|
||||
|
||||
sub get_align
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'align'};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
57
Webmin/Group.pm
Normal file
57
Webmin/Group.pm
Normal file
@@ -0,0 +1,57 @@
|
||||
package Webmin::Group;
|
||||
use Webmin::Textbox;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Textbox" );
|
||||
|
||||
=head2 new Webmin::Group(name, value, [multiple], [disabled])
|
||||
A text box for entering or selecting one or many Unix groupnames
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Group::new)) {
|
||||
return new Webmin::Theme::Group(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $name, $value, $multiple, $disabled) = @_;
|
||||
$self = new Webmin::Textbox($name, $value, $multiple ? 40 : 15, $disabled);
|
||||
bless($self);
|
||||
$self->set_multiple($multiple);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this group input
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv = Webmin::Textbox::html($self);
|
||||
my $name = $self->get_name();
|
||||
my $multiple = $self->get_multiple();
|
||||
local $w = $multiple ? 500 : 300;
|
||||
$rv .= " <input type=button name=${name}_button onClick='ifield = form.$name; chooser = window.open(\"$gconfig{'webprefix'}/group_chooser.cgi?multi=$multiple&group=\"+escape(ifield.value), \"chooser\", \"toolbar=no,menubar=no,scrollbars=yes,width=$w,height=200\"); chooser.ifield = ifield; window.ifield = ifield' value=\"...\">\n";
|
||||
return $rv;
|
||||
}
|
||||
|
||||
sub set_multiple
|
||||
{
|
||||
my ($self, $multiple) = @_;
|
||||
$self->{'multiple'} = $multiple;
|
||||
}
|
||||
|
||||
sub get_multiple
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'multiple'};
|
||||
}
|
||||
|
||||
=head2 get_input_names()
|
||||
Returns the actual names of all HTML elements that make up this input
|
||||
=cut
|
||||
sub get_input_names
|
||||
{
|
||||
my ($self) = @_;
|
||||
return ( $self->{'name'}, $self->{'name'}."_button" );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
64
Webmin/Icon.pm
Normal file
64
Webmin/Icon.pm
Normal file
@@ -0,0 +1,64 @@
|
||||
package Webmin::Icon;
|
||||
use WebminCore;
|
||||
|
||||
=head2 Webmin::Icon(type, [message])
|
||||
This object generates an icon indicating some status. Possible types are :
|
||||
ok - OK
|
||||
critial - A serious problem
|
||||
major - A relatively serious problem
|
||||
minor - A small problem
|
||||
Can be used inside tables and property lists
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Icon::new) && caller() !~ /Webmin::Theme::Icon/) {
|
||||
return new Webmin::Theme::Icon(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $type, $message) = @_;
|
||||
$self = { };
|
||||
bless($self);
|
||||
$self->set_type($type);
|
||||
$self->set_message($message) if (defined($message));
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns HTML for the icon
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
$rv .= "<img src=/images/".$self->get_type().".gif align=middle>";
|
||||
if ($self->get_message()) {
|
||||
$rv .= " ".$self->get_message();
|
||||
}
|
||||
return $rv;
|
||||
}
|
||||
|
||||
sub set_type
|
||||
{
|
||||
my ($self, $type) = @_;
|
||||
$self->{'type'} = $type;
|
||||
}
|
||||
|
||||
sub get_type
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'type'};
|
||||
}
|
||||
|
||||
sub set_message
|
||||
{
|
||||
my ($self, $message) = @_;
|
||||
$self->{'message'} = $message;
|
||||
}
|
||||
|
||||
sub get_message
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'message'};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
134
Webmin/Input.pm
Normal file
134
Webmin/Input.pm
Normal file
@@ -0,0 +1,134 @@
|
||||
package Webmin::Input;
|
||||
use WebminCore;
|
||||
|
||||
sub set_form
|
||||
{
|
||||
my ($self, $form) = @_;
|
||||
$self->{'form'} = $form;
|
||||
}
|
||||
|
||||
sub set_name
|
||||
{
|
||||
my ($self, $name) = @_;
|
||||
$self->{'name'} = $name;
|
||||
}
|
||||
|
||||
sub get_name
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'name'};
|
||||
}
|
||||
|
||||
sub set_disabled
|
||||
{
|
||||
my ($self, $disabled) = @_;
|
||||
$self->{'disabled'} = $disabled;
|
||||
}
|
||||
|
||||
sub get_disabled
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'disabled'};
|
||||
}
|
||||
|
||||
=head2 validate()
|
||||
No validation is done by default
|
||||
=cut
|
||||
sub validate
|
||||
{
|
||||
return ( );
|
||||
}
|
||||
|
||||
sub set_value
|
||||
{
|
||||
my ($self, $value) = @_;
|
||||
$self->{'value'} = $value;
|
||||
}
|
||||
|
||||
=head2 get_value()
|
||||
Returns the current value for this field as entered by the user, the value
|
||||
set when the form is re-displayed due to an error, or the initial value.
|
||||
=cut
|
||||
sub get_value
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $in = $self->{'form'} ? $self->{'form'}->{'in'} : undef;
|
||||
if ($in && (defined($in->{$self->{'name'}}) ||
|
||||
defined($in->{"ui_exists_".$self->{'name'}}))) {
|
||||
return $in->{$self->{'name'}};
|
||||
}
|
||||
elsif ($in && defined($in->{"ui_value_".$self->{'name'}})) {
|
||||
return $in->{"ui_value_".$self->{'name'}};
|
||||
}
|
||||
else {
|
||||
return $self->{'value'};
|
||||
}
|
||||
}
|
||||
|
||||
=head2 set_disable_code(javascript)
|
||||
Must be provided with a Javascript expression that will return true when this
|
||||
input should be disabled. May refer to other fields, via the variable 'form'.
|
||||
ie. form.mode.value = "0"
|
||||
Will be called every time any field's value changes.
|
||||
=cut
|
||||
sub set_disable_code
|
||||
{
|
||||
my ($self, $code) = @_;
|
||||
$self->{'disablecode'} = $code;
|
||||
}
|
||||
|
||||
sub get_disable_code
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'disablecode'};
|
||||
}
|
||||
|
||||
=head2 get_input_names()
|
||||
Returns the actual names of all HTML elements that make up this input
|
||||
=cut
|
||||
sub get_input_names
|
||||
{
|
||||
my ($self) = @_;
|
||||
return ( $self->{'name'} );
|
||||
}
|
||||
|
||||
=head2 set_label(text)
|
||||
Sets HTML to be displayed before this field
|
||||
=cut
|
||||
sub set_label
|
||||
{
|
||||
my ($self, $label) = @_;
|
||||
$self->{'label'} = $label;
|
||||
}
|
||||
|
||||
sub get_label
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'label'};
|
||||
}
|
||||
|
||||
sub set_mandatory
|
||||
{
|
||||
my ($self, $mandatory, $mandmesg) = @_;
|
||||
$self->{'mandatory'} = $mandatory;
|
||||
$self->{'mandmesg'} = $mandmesg if (defined($mandmesg));
|
||||
}
|
||||
|
||||
sub get_mandatory
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'mandatory'};
|
||||
}
|
||||
|
||||
=head2 get_errors()
|
||||
Returns a list of errors associated with this field
|
||||
=cut
|
||||
sub get_errors
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'form'} ? $self->{'form'}->field_errors($self->get_name())
|
||||
: ( );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
137
Webmin/InputTable.pm
Normal file
137
Webmin/InputTable.pm
Normal file
@@ -0,0 +1,137 @@
|
||||
package Webmin::InputTable;
|
||||
use Webmin::Table;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Table" );
|
||||
|
||||
=head2 new Webmin::InputTable(&headings, [width], [name], [heading])
|
||||
A table containing multiple rows of inputs, each of which is the same
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::InputTable::new) &&
|
||||
caller() !~ /Webmin::Theme::InputTable/) {
|
||||
return new Webmin::Theme::InputTable(@_[1..$#_]);
|
||||
}
|
||||
my $self = defined(&Webmin::Theme::Table::new) ? Webmin::Theme::Table::new(@_)
|
||||
: Webmin::Table::new(@_);
|
||||
bless($self);
|
||||
$self->{'rowcount'} = 0;
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 set_inputs(&inputs)
|
||||
Sets the objects to be used for each row
|
||||
=cut
|
||||
sub set_inputs
|
||||
{
|
||||
my ($self, $classes) = @_;
|
||||
$self->{'classes'} = $classes;
|
||||
}
|
||||
|
||||
=head2 add_values(&values)
|
||||
Adds a row of inputs, with the given values
|
||||
=cut
|
||||
sub add_values
|
||||
{
|
||||
my ($self, $values) = @_;
|
||||
my @row;
|
||||
for(my $i=0; $i<@$values; $i++) {
|
||||
my $cls = $self->{'classes'}->[$i];
|
||||
my $newin = { %$cls };
|
||||
bless($newin, ref($cls));
|
||||
$newin->set_value($values->[$i]);
|
||||
$newin->set_name($newin->get_name()."_".$self->{'rowcount'});
|
||||
$newin->set_form($self->{'form'}) if ($self->{'form'});
|
||||
push(@row, $newin);
|
||||
}
|
||||
$self->add_row(\@row);
|
||||
$self->{'rowcount'}++;
|
||||
}
|
||||
|
||||
=head2 get_values(row)
|
||||
Returns the values of the inputs in the given row
|
||||
=cut
|
||||
sub get_values
|
||||
{
|
||||
my ($self, $row) = @_;
|
||||
my @rv;
|
||||
foreach my $i (@{$self->{'rows'}->[$row]}) {
|
||||
if (ref($i) && $i->isa("Webmin::Input")) {
|
||||
push(@rv, $i->get_value());
|
||||
}
|
||||
}
|
||||
return @rv;
|
||||
}
|
||||
|
||||
=head2 list_inputs()
|
||||
=cut
|
||||
sub list_inputs
|
||||
{
|
||||
my ($self) = @_;
|
||||
my @rv = Webmin::Table::list_inputs($self);
|
||||
foreach my $r (@{$self->{'rows'}}) {
|
||||
foreach my $i (@$r) {
|
||||
if ($i && ref($i) && $i->isa("Webmin::Input")) {
|
||||
push(@rv, $i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return @rv;
|
||||
}
|
||||
|
||||
sub get_rowcount
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'rowcount'};
|
||||
}
|
||||
|
||||
=head2 validate()
|
||||
Validates all inputs, and returns a list of error messages
|
||||
=cut
|
||||
sub validate
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $seli = $self->{'selectinput'};
|
||||
my @errs;
|
||||
if ($seli) {
|
||||
push(@errs, map { [ $seli->get_name(), $_ ] } $seli->validate());
|
||||
}
|
||||
foreach my $i (@{$self->{'inputs'}}) {
|
||||
foreach my $e ($i->validate()) {
|
||||
push(@errs, [ $i->get_name(), $e ]);
|
||||
}
|
||||
}
|
||||
my $k = 1;
|
||||
foreach my $r (@{$self->{'rows'}}) {
|
||||
my $j = 0;
|
||||
my $skip;
|
||||
if (defined($self->{'control'})) {
|
||||
if ($r->[$self->{'control'}]->get_value() eq "") {
|
||||
$skip = 1;
|
||||
}
|
||||
}
|
||||
foreach my $i (@$r) {
|
||||
if ($i && ref($i) && $i->isa("Webmin::Input") && !$skip) {
|
||||
my $label = &text('ui_rowlabel', $k, $self->{'headings'}->[$j]);
|
||||
foreach my $e ($i->validate()) {
|
||||
push(@errs, [ $i->get_name(), $label." ".$e ]);
|
||||
}
|
||||
}
|
||||
$j++;
|
||||
}
|
||||
$k++;
|
||||
}
|
||||
return @errs;
|
||||
}
|
||||
|
||||
=head2 set_control(column)
|
||||
Sets the column for which an empty value means no validation should be done
|
||||
=cut
|
||||
sub set_control
|
||||
{
|
||||
my ($self, $control) = @_;
|
||||
$self->{'control'} = $control;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
47
Webmin/JavascriptButton.pm
Normal file
47
Webmin/JavascriptButton.pm
Normal file
@@ -0,0 +1,47 @@
|
||||
package Webmin::JavascriptButton;
|
||||
use Webmin::Input;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Input" );
|
||||
|
||||
=head2 new Webmin::JavascriptButton(label, script, [disabled])
|
||||
Create a button that runs some Javascript when clicked
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::JavascriptButton::new) &&
|
||||
caller() !~ /Webmin::Theme::JavascriptButton/) {
|
||||
return new Webmin::Theme::JavascriptButton(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $value, $script, $disabled) = @_;
|
||||
$self = { };
|
||||
bless($self);
|
||||
$self->set_value($value);
|
||||
$self->set_script($script);
|
||||
$self->set_disabled($disabled) if ($disabled);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this text input
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
return "<input type=button value=\""."e_escape($self->get_value())."\" ".
|
||||
"onClick=\"".$self->get_script()."\">";
|
||||
}
|
||||
|
||||
sub set_script
|
||||
{
|
||||
my ($self, $script) = @_;
|
||||
$self->{'script'} = $script;
|
||||
}
|
||||
|
||||
sub get_script
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'script'};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
314
Webmin/LinkTable.pm
Normal file
314
Webmin/LinkTable.pm
Normal file
@@ -0,0 +1,314 @@
|
||||
package Webmin::LinkTable;
|
||||
use Webmin::Table;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::LinkTable(heading, [columns], [width], [name])
|
||||
Creates a new table that just displays links, like in the Users and Groups module
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::LinkTable::new) &&
|
||||
caller() !~ /Webmin::Theme::LinkTable/) {
|
||||
return new Webmin::Theme::LinkTable(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $heading, $columns, $width, $name) = @_;
|
||||
$self = { 'sorter' => \&Webmin::Table::default_sorter,
|
||||
'columns' => 4,
|
||||
'sortable' => 1 };
|
||||
bless($self);
|
||||
$self->set_heading($heading);
|
||||
$self->set_name($name) if (defined($name));
|
||||
$self->set_width($width) if (defined($width));
|
||||
$self->set_columns($columns) if (defined($columns));
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 add_entry(name, link)
|
||||
Adds one item to appear in the table
|
||||
=cut
|
||||
sub add_entry
|
||||
{
|
||||
my ($self, $name, $link) = @_;
|
||||
push(@{$self->{'entries'}}, [ $name, $link ]);
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this table.
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
|
||||
# Prepare the selector
|
||||
my @srows = @{$self->{'entries'}};
|
||||
my %selmap;
|
||||
if (defined($self->{'selectinput'})) {
|
||||
my $i = 0;
|
||||
foreach my $r (@srows) {
|
||||
$selmap{$r} = $self->{'selectinput'}->one_html($i);
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
# Sort the entries
|
||||
my $sortdir = $self->get_sortdir();
|
||||
if (defined($sortdir)) {
|
||||
my $func = $self->{'sorter'};
|
||||
@srows = sort { my $so = &$func($a->[0], $b->[0]);
|
||||
$sortdir ? -$so : $so } @srows;
|
||||
}
|
||||
|
||||
# Build the sorter
|
||||
my $head;
|
||||
my $thisurl = $self->{'form'}->{'page'}->get_myurl();
|
||||
$thisurl .= $thisurl =~ /\?/ ? "&" : "?";
|
||||
my $name = $self->get_name();
|
||||
if ($self->get_sortable()) {
|
||||
$head = "<table cellpadding=0 cellspacing=0 width=100%><tr>";
|
||||
$head .= "<td><b>".$self->get_heading()."</b></td> <td align=right>";
|
||||
if (!defined($sortdir)) {
|
||||
# Not sorting .. show grey button
|
||||
$head .= "<a href='${thisurl}ui_sortdir_${name}=0'>".
|
||||
"<img src=/images/nosort.gif border=0></a>";
|
||||
}
|
||||
else {
|
||||
# Sorting .. show button to switch mode
|
||||
my $notsort = !$sortdir;
|
||||
$head .= "<a href='${thisurl}ui_sortdir_${name}=$notsort'>".
|
||||
"<img src=/images/sort.gif border=0></a>";
|
||||
}
|
||||
$head .= "</td></tr></table>";
|
||||
}
|
||||
else {
|
||||
$head = $self->get_heading();
|
||||
}
|
||||
|
||||
# Find any errors
|
||||
my $rv;
|
||||
if ($self->{'selectinput'}) {
|
||||
# Get any errors for inputs
|
||||
my @errs = $self->{'form'}->field_errors(
|
||||
$self->{'selectinput'}->get_name());
|
||||
if (@errs) {
|
||||
foreach my $e (@errs) {
|
||||
$rv .= "<font color=#ff0000>$e</font><br>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Create the actual table
|
||||
$rv .= &ui_table_start($head,
|
||||
defined($self->{'width'}) ? "width=$self->{'width'}"
|
||||
: undef, 1);
|
||||
$rv .= "<td colspan=2><table width=100%>";
|
||||
my $i = 0;
|
||||
my $cols = $self->get_columns();
|
||||
my $pc = 100/$cols;
|
||||
foreach my $r (@srows) {
|
||||
$rv .= "<tr>\n" if ($i%$cols == 0);
|
||||
$rv .= "<td width=$pc%>".$selmap{$r}."<a href='$r->[1]'>".
|
||||
&html_escape($r->[0])."</a></td>\n";
|
||||
$rv .= "<tr>\n" if ($i%$cols == $cols-1);
|
||||
$i++;
|
||||
}
|
||||
if ($i%$cols) {
|
||||
# Finish off row
|
||||
while($i++%$cols != $cols-1) {
|
||||
$rv .= "<td width=$pc%></td>\n";
|
||||
}
|
||||
$rv .= "</tr>\n";
|
||||
}
|
||||
$rv .= "</table></td>";
|
||||
$rv .= &ui_table_end();
|
||||
return $rv;
|
||||
}
|
||||
|
||||
=head2 set_heading(text)
|
||||
Sets the heading text to appear above the table
|
||||
=cut
|
||||
sub set_heading
|
||||
{
|
||||
my ($self, $heading) = @_;
|
||||
$self->{'heading'} = $heading;
|
||||
}
|
||||
|
||||
sub get_heading
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'heading'};
|
||||
}
|
||||
|
||||
sub set_name
|
||||
{
|
||||
my ($self, $name) = @_;
|
||||
$self->{'name'} = $name;
|
||||
}
|
||||
|
||||
=head2 get_name()
|
||||
Returns the name for indentifying this table in HTML
|
||||
=cut
|
||||
sub get_name
|
||||
{
|
||||
my ($self) = @_;
|
||||
if (defined($self->{'name'})) {
|
||||
return $self->{'name'};
|
||||
}
|
||||
elsif ($self->{'form'}) {
|
||||
my $secs = $self->{'form'}->{'sections'};
|
||||
for(my $i=0; $i<@$secs; $i++) {
|
||||
return "table".$i if ($secs->[$i] eq $self);
|
||||
}
|
||||
}
|
||||
return "table";
|
||||
}
|
||||
|
||||
=head2 set_sorter(function)
|
||||
Sets a function used for sorting fields. Will be called with two values to compare
|
||||
=cut
|
||||
sub set_sorter
|
||||
{
|
||||
my ($self, $func) = @_;
|
||||
$self->{'sorter'} = $func;
|
||||
}
|
||||
|
||||
=head2 default_sorter(value1, value2)
|
||||
=cut
|
||||
sub default_sorter
|
||||
{
|
||||
my ($value1, $value2, $col) = @_;
|
||||
return lc($value1) cmp lc($value2);
|
||||
}
|
||||
|
||||
=head2 set_sortable(sortable?)
|
||||
Tells the table if sorting is allowed or not. By default, it is.
|
||||
=cut
|
||||
sub set_sortable
|
||||
{
|
||||
my ($self, $sortable) = @_;
|
||||
$self->{'sortable'} = $sortable;
|
||||
}
|
||||
|
||||
sub get_sortable
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'sortable'};
|
||||
}
|
||||
|
||||
=head2 get_sortdir()
|
||||
Returns the order to sort in (1 for descending)
|
||||
=cut
|
||||
sub get_sortdir
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $in = $self->{'form'} ? $self->{'form'}->{'in'} : undef;
|
||||
my $name = $self->get_name();
|
||||
if ($in && defined($in->{"ui_sortdir_".$name})) {
|
||||
return ( $in->{"ui_sortdir_".$name} );
|
||||
}
|
||||
else {
|
||||
return ( $self->{'sortdir'} );
|
||||
}
|
||||
}
|
||||
|
||||
=head2 set_sortdir(descending?)
|
||||
Sets the default sort direction, unless overridden by the user.
|
||||
=cut
|
||||
sub set_sortcolumn
|
||||
{
|
||||
my ($self, $desc) = @_;
|
||||
$self->{'sortdir'} = $desc;
|
||||
}
|
||||
|
||||
=head2 set_width([number|number%])
|
||||
Sets the width of this entire table. Can be called with 100%, 500 or undef to use
|
||||
the minimum possible width.
|
||||
=cut
|
||||
sub set_width
|
||||
{
|
||||
my ($self, $width) = @_;
|
||||
$self->{'width'} = $width;
|
||||
}
|
||||
|
||||
=head2 set_columns(cols)
|
||||
Sets the number of columns to display
|
||||
=cut
|
||||
sub set_columns
|
||||
{
|
||||
my ($self, $columns) = @_;
|
||||
$self->{'columns'} = $columns;
|
||||
}
|
||||
|
||||
sub get_columns
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'columns'};
|
||||
}
|
||||
|
||||
=head2 set_form(form)
|
||||
Called by the Webmin::Form object when this table is added to it
|
||||
=cut
|
||||
sub set_form
|
||||
{
|
||||
my ($self, $form) = @_;
|
||||
$self->{'form'} = $form;
|
||||
if ($self->{'selectinput'}) {
|
||||
$self->{'selectinput'}->set_form($form);
|
||||
}
|
||||
}
|
||||
|
||||
=head2 set_selector(input)
|
||||
Takes a Webmin::Checkboxes or Webmin::Radios object, and uses it to add checkboxes
|
||||
to all the entries
|
||||
=cut
|
||||
sub set_selector
|
||||
{
|
||||
my ($self, $input) = @_;
|
||||
$self->{'selectinput'} = $input;
|
||||
$input->set_form($form);
|
||||
}
|
||||
|
||||
=head2 get_selector()
|
||||
Returns the UI element used for selecting rows
|
||||
=cut
|
||||
sub get_selector
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'selectinput'};
|
||||
}
|
||||
|
||||
=head2 validate()
|
||||
Validates the selector input
|
||||
=cut
|
||||
sub validate
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $seli = $self->{'selectinput'};
|
||||
if ($seli) {
|
||||
return map { [ $seli->get_name(), $_ ] } $seli->validate();
|
||||
}
|
||||
return ( );
|
||||
}
|
||||
|
||||
=head2 get_value(input-name)
|
||||
Returns the value of the input with the given name.
|
||||
=cut
|
||||
sub get_value
|
||||
{
|
||||
my ($self, $name) = @_;
|
||||
if ($self->{'selectinput'} && $self->{'selectinput'}->get_name() eq $name) {
|
||||
return $self->{'selectinput'}->get_value();
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
=head2 list_inputs()
|
||||
Returns all inputs in all form sections
|
||||
=cut
|
||||
sub list_inputs
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'selectinput'} ? ( $self->{'selectinput'} ) : ( );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
86
Webmin/Menu.pm
Normal file
86
Webmin/Menu.pm
Normal file
@@ -0,0 +1,86 @@
|
||||
package Webmin::Menu;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::Menu(&options, [columns])
|
||||
Generates a menu of options, typically using icons.
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
my ($self, $options, $columns) = @_;
|
||||
if (defined(&Webmin::Theme::Menu::new)) {
|
||||
return new Webmin::Theme::Menu(@_[1..$#_]);
|
||||
}
|
||||
$self = { 'columns' => 4 };
|
||||
bless($self);
|
||||
$self->set_options($options);
|
||||
$self->set_columns($columns) if (defined($columns));
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for the table
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my (@links, @titles, @icons, @hrefs);
|
||||
foreach my $o (@{$self->{'options'}}) {
|
||||
push(@links, $o->{'link'});
|
||||
if ($o->{'link2'}) {
|
||||
push(@titles, "$o->{'title'}</a> <a href='$o->{'link2'}'>$o->{'title2'}");
|
||||
}
|
||||
else {
|
||||
push(@titles, $o->{'title'});
|
||||
}
|
||||
push(@icons, $o->{'icon'});
|
||||
push(@hrefs, $o->{'href'});
|
||||
}
|
||||
my $rv = &capture_function_output(\&icons_table,
|
||||
\@links, \@titles, \@icons, $self->get_columns(),
|
||||
\@hrefs);
|
||||
return $rv;
|
||||
}
|
||||
|
||||
=head2 add_option(&option)
|
||||
=cut
|
||||
sub add_option
|
||||
{
|
||||
my ($self, $option) = @_;
|
||||
push(@{$self->{'options'}}, $option);
|
||||
}
|
||||
|
||||
sub set_options
|
||||
{
|
||||
my ($self, $options) = @_;
|
||||
$self->{'options'} = $options;
|
||||
}
|
||||
|
||||
sub get_options
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'options'};
|
||||
}
|
||||
|
||||
sub set_columns
|
||||
{
|
||||
my ($self, $columns) = @_;
|
||||
$self->{'columns'} = $columns;
|
||||
}
|
||||
|
||||
sub get_columns
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'columns'};
|
||||
}
|
||||
|
||||
=head2 set_page(Webmin::Page)
|
||||
Called when this menu is added to a page
|
||||
=cut
|
||||
sub set_page
|
||||
{
|
||||
my ($self, $page) = @_;
|
||||
$self->{'page'} = $page;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
40
Webmin/Multiline.pm
Normal file
40
Webmin/Multiline.pm
Normal file
@@ -0,0 +1,40 @@
|
||||
package Webmin::Multiline;
|
||||
use Webmin::Textarea;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Textarea" );
|
||||
|
||||
=head2 new Webmin::Multiline(name, &lines, rows, cols, [disabled])
|
||||
Create a new input for entering multiple text entries. By default, just uses
|
||||
a textbox
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Multiline::new)) {
|
||||
return new Webmin::Theme::Multiline(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $name, $lines, $rows, $cols, $wrap, $disabled) = @_;
|
||||
$self = new Webmin::Textarea($name, join("\n", @$lines), $rows, $cols, undef, $disabled);
|
||||
bless($self);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 set_lines(&lines)
|
||||
Sets the lines to display
|
||||
=cut
|
||||
sub set_lines
|
||||
{
|
||||
my ($self, $lines) = @_;
|
||||
$self->set_value(join("\n", @$lines));
|
||||
}
|
||||
|
||||
=head2 get_lines()
|
||||
Returns an array ref of lines to display
|
||||
=cut
|
||||
sub get_lines
|
||||
{
|
||||
my ($self) = @_;
|
||||
return [ split(/[\r|\n]+/, $self->get_value()) ];
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
120
Webmin/OptTextarea.pm
Normal file
120
Webmin/OptTextarea.pm
Normal file
@@ -0,0 +1,120 @@
|
||||
package Webmin::OptTextarea;
|
||||
use Webmin::Textarea;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Textarea" );
|
||||
|
||||
=head2 new Webmin::OptTextarea(name, value, rows, cols, [default-msg], [other-msg])
|
||||
Create a text area whose value is optional.
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::OptTextarea::new)) {
|
||||
return new Webmin::Theme::OptTextarea(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $name, $value, $rows, $cols, $default, $other) = @_;
|
||||
$self = new Webmin::Textarea($name, $value, $rows, $cols);
|
||||
bless($self);
|
||||
$self->set_default($default || $text{'default'});
|
||||
$self->set_other($other) if ($other);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this optional text input
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
my $name = $self->get_name();
|
||||
my $value = $self->get_value();
|
||||
my $dis = $self->get_disabled();
|
||||
my $rows = $self->get_rows();
|
||||
my $columns = $self->get_cols();
|
||||
my $dis1 = &js_disable_inputs([ $name ], [ ]);
|
||||
my $dis2 = &js_disable_inputs([ ], [ $name ]);
|
||||
my $opt1 = $self->get_default();
|
||||
my $opt2 = $self->get_other();
|
||||
$rv .= "<input type=radio name=\""."e_escape($name."_def")."\" ".
|
||||
"value=1 ".($value ne '' ? "" : "checked").
|
||||
($dis ? " disabled=true" : "")." onClick='$dis1'> ".$opt1."\n";
|
||||
$rv .= "<input type=radio name=\""."e_escape($name."_def")."\" ".
|
||||
"value=0 ".($value ne '' ? "checked" : "").
|
||||
($dis ? " disabled=true" : "")." onClick='$dis2'> ".$opt2."<br>\n";
|
||||
$rv .= "<textarea name=\""."e_escape($name)."\" ".
|
||||
($value eq "" || $dis ? " disabled=true" : "").
|
||||
"rows=$rows columns=$columns>".&html_escape($value)."</textarea>\n";
|
||||
return $rv;
|
||||
|
||||
}
|
||||
|
||||
=head2 validate(&inputs)
|
||||
=cut
|
||||
sub validate
|
||||
{
|
||||
my ($self, $in) = @_;
|
||||
if (defined($self->get_value())) {
|
||||
if ($self->get_value() eq "") {
|
||||
return ( $text{'ui_nothing'} );
|
||||
}
|
||||
return Webmin::Textbox::validate($self);
|
||||
}
|
||||
return ( );
|
||||
}
|
||||
|
||||
sub set_default
|
||||
{
|
||||
my ($self, $default) = @_;
|
||||
$self->{'default'} = $default;
|
||||
}
|
||||
|
||||
sub get_default
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'default'};
|
||||
}
|
||||
|
||||
sub set_other
|
||||
{
|
||||
my ($self, $other) = @_;
|
||||
$self->{'other'} = $other;
|
||||
}
|
||||
|
||||
sub get_other
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'other'};
|
||||
}
|
||||
|
||||
=head2 get_value()
|
||||
Returns the specified initial value for this field, or the value set when the
|
||||
form is re-displayed due to an error.
|
||||
=cut
|
||||
sub get_value
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $in = $self->{'form'} ? $self->{'form'}->{'in'} : undef;
|
||||
if ($in && (defined($in->{$self->{'name'}}) ||
|
||||
defined($in->{$self->{'name'}.'_def'}))) {
|
||||
return $in->{$self->{'name'}.'_def'} ? undef : $in->{$self->{'name'}};
|
||||
}
|
||||
elsif ($in && defined($in->{"ui_value_".$self->{'name'}})) {
|
||||
return $in->{"ui_value_".$self->{'name'}};
|
||||
}
|
||||
else {
|
||||
return $self->{'value'};
|
||||
}
|
||||
}
|
||||
|
||||
=head2 get_input_names()
|
||||
Returns the actual names of all HTML elements that make up this input
|
||||
=cut
|
||||
sub get_input_names
|
||||
{
|
||||
my ($self) = @_;
|
||||
return ( $self->{'name'}, $self->{'name'}."_def[0]",
|
||||
$self->{'name'}."_def[1]" );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
90
Webmin/OptTextbox.pm
Normal file
90
Webmin/OptTextbox.pm
Normal file
@@ -0,0 +1,90 @@
|
||||
package Webmin::OptTextbox;
|
||||
use Webmin::Textbox;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Textbox" );
|
||||
|
||||
=head2 new Webmin::OptTextbox(name, value, size, [default-msg], [other-msg])
|
||||
Create a text field whose value is optional.
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::OptTextbox::new)) {
|
||||
return new Webmin::Theme::OptTextbox(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $name, $value, $size, $default, $other) = @_;
|
||||
$self = new Webmin::Textbox($name, $value, $size);
|
||||
bless($self);
|
||||
$self->set_default($default || $text{'default'});
|
||||
$self->set_other($other) if ($other);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this optional text input
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
return &ui_opt_textbox($self->get_name(), $self->get_value(),
|
||||
$self->{'size'}, $self->{'default'},
|
||||
$self->{'other'});
|
||||
}
|
||||
|
||||
=head2 validate(&inputs)
|
||||
=cut
|
||||
sub validate
|
||||
{
|
||||
my ($self, $in) = @_;
|
||||
if (defined($self->get_value())) {
|
||||
if ($self->get_value() eq "") {
|
||||
return ( $text{'ui_nothing'} );
|
||||
}
|
||||
return Webmin::Textbox::validate($self);
|
||||
}
|
||||
return ( );
|
||||
}
|
||||
|
||||
sub set_default
|
||||
{
|
||||
my ($self, $default) = @_;
|
||||
$self->{'default'} = $default;
|
||||
}
|
||||
|
||||
sub set_other
|
||||
{
|
||||
my ($self, $other) = @_;
|
||||
$self->{'other'} = $other;
|
||||
}
|
||||
|
||||
=head2 get_value()
|
||||
Returns the specified initial value for this field, or the value set when the
|
||||
form is re-displayed due to an error.
|
||||
=cut
|
||||
sub get_value
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $in = $self->{'form'} ? $self->{'form'}->{'in'} : undef;
|
||||
if ($in && (defined($in->{$self->{'name'}}) ||
|
||||
defined($in->{$self->{'name'}.'_def'}))) {
|
||||
return $in->{$self->{'name'}.'_def'} ? undef : $in->{$self->{'name'}};
|
||||
}
|
||||
elsif ($in && defined($in->{"ui_value_".$self->{'name'}})) {
|
||||
return $in->{"ui_value_".$self->{'name'}};
|
||||
}
|
||||
else {
|
||||
return $self->{'value'};
|
||||
}
|
||||
}
|
||||
|
||||
=head2 get_input_names()
|
||||
Returns the actual names of all HTML elements that make up this input
|
||||
=cut
|
||||
sub get_input_names
|
||||
{
|
||||
my ($self) = @_;
|
||||
return ( $self->{'name'}, $self->{'name'}."_def[0]",
|
||||
$self->{'name'}."_def[1]" );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
426
Webmin/Page.pm
Normal file
426
Webmin/Page.pm
Normal file
@@ -0,0 +1,426 @@
|
||||
package Webmin::Page;
|
||||
use WebminCore;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::Page(subheading, title, [help-name], [show-config],
|
||||
[no-module-index], [no-webmin-index], [rightside],
|
||||
[header], [body-tags], [below-text])
|
||||
Create a new page object, with the given heading and other details
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Page::new) && caller() !~ /Webmin::Theme::Page/) {
|
||||
return new Webmin::Theme::Page(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $subheading, $title, $help, $config, $noindex, $nowebmin, $right,
|
||||
$header, $body, $below) = @_;
|
||||
$self = { 'index' => 1, 'webmin' => 1, 'image' => "" };
|
||||
bless($self);
|
||||
$self->set_subheading($subheading);
|
||||
$self->set_title($title);
|
||||
$self->set_help($help);
|
||||
$self->set_config($config);
|
||||
$self->set_index(!$noindex);
|
||||
$self->set_webmin(!$nowebmin);
|
||||
$self->set_right($right);
|
||||
$self->set_header($header);
|
||||
$self->set_body($body);
|
||||
$self->set_below($below);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 print()
|
||||
Actually outputs this page
|
||||
=cut
|
||||
sub print
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
|
||||
# Work out if we need buffering/table
|
||||
foreach my $c (@{$self->{'contents'}}) {
|
||||
if (ref($c) =~ /Dynamic/) {
|
||||
$| = 1;
|
||||
if ($c->needs_unbuffered()) {
|
||||
$self->{'unbuffered'} = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Show the page header
|
||||
my $func = $self->{'unbuffered'} ? \&ui_print_unbuffered_header
|
||||
: \&ui_print_header;
|
||||
my $scripts;
|
||||
foreach my $s (@{$self->{'scripts'}},
|
||||
(map { @{$_->{'scripts'}} } @{$self->{'contents'}})) {
|
||||
$scripts .= "<script>\n".$s."\n</script>\n";
|
||||
}
|
||||
my $onload;
|
||||
my @onloads = ( @{$self->{'onloads'}},
|
||||
map { @{$_->{'onloads'}} } @{$self->{'contents'}} );
|
||||
if (@onloads) {
|
||||
$onload = "onLoad='".join(" ", @onloads)."'";
|
||||
}
|
||||
my @args = ( $self->{'subheading'}, $self->{'title'}, $self->{'image'},
|
||||
$self->{'help'}, $self->{'config'}, $self->{'index'} ? undef : 1,
|
||||
$self->{'webmin'} ? undef : 1, $self->{'right'},
|
||||
$self->{'header'}.$scripts, $self->{'body'}.$onload,
|
||||
$self->{'below'} );
|
||||
while(!defined($args[$#args])) {
|
||||
pop(@args);
|
||||
}
|
||||
if ($self->get_refresh()) {
|
||||
print "Refresh: ",$self->get_refresh(),"\r\n";
|
||||
}
|
||||
&ui_print_header(@args);
|
||||
|
||||
# Add the tab top
|
||||
if ($self->{'tabs'}) {
|
||||
print $self->{'tabs'}->top_html();
|
||||
}
|
||||
|
||||
# Add any pre-content stuff
|
||||
print $self->pre_content();
|
||||
|
||||
if ($self->{'errormsg'}) {
|
||||
# Show the error only
|
||||
print $self->get_errormsg_html();
|
||||
}
|
||||
else {
|
||||
# Generate the forms and other stuff
|
||||
foreach my $c (@{$self->{'contents'}}) {
|
||||
if (!ref($c)) {
|
||||
# Just a message
|
||||
print "$c<p>\n";
|
||||
}
|
||||
else {
|
||||
# Convert to HTML
|
||||
eval { print $c->html(); };
|
||||
if ($@) {
|
||||
print "<pre>$@</pre>";
|
||||
}
|
||||
if (ref($c) =~ /Dynamic/ && $c->get_wait()) {
|
||||
# Dynamic object .. execute now
|
||||
$c->start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Generate buttons row
|
||||
if ($self->{'buttons'}) {
|
||||
print "<hr>\n";
|
||||
print &ui_buttons_start();
|
||||
foreach my $b (@{$self->{'buttons'}}) {
|
||||
print &ui_buttons_row(@$b);
|
||||
}
|
||||
print &ui_buttons_end();
|
||||
}
|
||||
}
|
||||
|
||||
# Add any post-content stuff
|
||||
print $self->post_content();
|
||||
|
||||
# End of the tabs
|
||||
if ($self->{'tabs'}) {
|
||||
print $self->{'tabs'}->bottom_html();
|
||||
}
|
||||
|
||||
# Print the footer
|
||||
my @footerargs;
|
||||
foreach my $f (@{$self->{'footers'}}) {
|
||||
push(@footerargs, $f->[0], $f->[1]);
|
||||
}
|
||||
&ui_print_footer(@footerargs);
|
||||
|
||||
# Start any dynamic objects
|
||||
foreach my $c (@{$self->{'contents'}}) {
|
||||
if (ref($c) =~ /Dynamic/ && !$c->get_wait()) {
|
||||
$c->start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
=head2 add_footer(link, title)
|
||||
Adds a return link, typically for display at the end of the page.
|
||||
=cut
|
||||
sub add_footer
|
||||
{
|
||||
my ($self, $link, $title) = @_;
|
||||
push(@{$self->{'footers'}}, [ $link, $title ]);
|
||||
}
|
||||
|
||||
=head2 get_footer(index)
|
||||
Returns the link for the numbered footer
|
||||
=cut
|
||||
sub get_footer
|
||||
{
|
||||
my ($self, $num) = @_;
|
||||
return $self->{'footers'}->[$num]->[0];
|
||||
}
|
||||
|
||||
=head2 add_message(text, ...)
|
||||
Adds a text message, to appear at this point on the page
|
||||
=cut
|
||||
sub add_message
|
||||
{
|
||||
my ($self, @message) = @_;
|
||||
push(@{$self->{'contents'}}, join("", @message));
|
||||
}
|
||||
|
||||
=head2 add_error(text, [command-output])
|
||||
Adds a an error message, possible accompanied by the command output
|
||||
=cut
|
||||
sub add_error
|
||||
{
|
||||
my ($self, $message, $out) = @_;
|
||||
$message = "<font color=#ff0000>$message</font>";
|
||||
if ($out) {
|
||||
$message .= "<pre>$out</pre>";
|
||||
}
|
||||
push(@{$self->{'contents'}}, $message);
|
||||
}
|
||||
|
||||
=head2 add_message_after(&object, text, ...)
|
||||
Adds a message after some existing object
|
||||
=cut
|
||||
sub add_message_after
|
||||
{
|
||||
my ($self, $object, @message) = @_;
|
||||
splice(@{$self->{'contents'}}, $self->position_of($object)+1, 0,
|
||||
join("", @message));
|
||||
}
|
||||
|
||||
=head2 add_error_after(&object, text, [command-output])
|
||||
Adds an error message after some existing object
|
||||
=cut
|
||||
sub add_error_after
|
||||
{
|
||||
my ($self, $object, $message, $out) = @_;
|
||||
$message = "<font color=#ff0000>$message</font>";
|
||||
if ($out) {
|
||||
$message .= "<pre>$out</pre>";
|
||||
}
|
||||
splice(@{$self->{'contents'}}, $self->position_of($object)+1, 0,
|
||||
$message);
|
||||
}
|
||||
|
||||
sub position_of
|
||||
{
|
||||
my ($self, $object) = @_;
|
||||
for(my $i=0; $i<@{$self->{'contents'}}; $i++) {
|
||||
if ($self->{'contents'}->[$i] eq $object) {
|
||||
return $i;
|
||||
}
|
||||
}
|
||||
print STDERR "Could not find $object in ",join(" ",@{$self->{'contents'}}),"\n";
|
||||
return scalar(@{$self->{'contents'}});
|
||||
}
|
||||
|
||||
=head2 add_form(Webmin::Form)
|
||||
Adds a form to be displayed on this page
|
||||
=cut
|
||||
sub add_form
|
||||
{
|
||||
my ($self, $form) = @_;
|
||||
push(@{$self->{'contents'}}, $form);
|
||||
$form->set_page($self);
|
||||
}
|
||||
|
||||
=head2 add_separator()
|
||||
Adds some kind of separation between parts of this page, like an <hr>
|
||||
=cut
|
||||
sub add_separator
|
||||
{
|
||||
my ($self, $message) = @_;
|
||||
push(@{$self->{'contents'}}, "<hr>");
|
||||
}
|
||||
|
||||
=head2 add_button(cgi, label, description, [&hiddens], [before-button],
|
||||
[after-button])
|
||||
Adds an action button associated with this page, typically for display at the end
|
||||
=cut
|
||||
sub add_button
|
||||
{
|
||||
my ($self, $cgi, $label, $desc, $hiddens, $before, $after) = @_;
|
||||
push(@{$self->{'buttons'}}, [ $cgi, $label, $desc, join(" ", @$hiddens),
|
||||
$before, $after ]);
|
||||
}
|
||||
|
||||
=head2 add_tabs(Webmin::Tags)
|
||||
Tells the page to display the given set of tabs at the top
|
||||
=cut
|
||||
sub add_tabs
|
||||
{
|
||||
my ($self, $tabs) = @_;
|
||||
$self->{'tabs'} = $tabs;
|
||||
}
|
||||
|
||||
=head2 add_dynamic(Webmin::DynamicText|Webmin::DynamicProgress)
|
||||
Adds an object that is dynamically generated, such as a text box or progress bar.
|
||||
=cut
|
||||
sub add_dynamic
|
||||
{
|
||||
my ($self, $dyn) = @_;
|
||||
push(@{$self->{'contents'}}, $dyn);
|
||||
$dyn->set_page($self);
|
||||
}
|
||||
|
||||
sub set_subheading
|
||||
{
|
||||
my ($self, $subheading) = @_;
|
||||
$self->{'subheading'} = $subheading;
|
||||
}
|
||||
|
||||
sub set_title
|
||||
{
|
||||
my ($self, $title) = @_;
|
||||
$self->{'title'} = $title;
|
||||
}
|
||||
|
||||
sub set_help
|
||||
{
|
||||
my ($self, $help) = @_;
|
||||
$self->{'help'} = $help;
|
||||
}
|
||||
|
||||
sub set_config
|
||||
{
|
||||
my ($self, $config) = @_;
|
||||
$self->{'config'} = $config;
|
||||
}
|
||||
|
||||
sub set_index
|
||||
{
|
||||
my ($self, $index) = @_;
|
||||
$self->{'index'} = $index;
|
||||
}
|
||||
|
||||
sub set_webmin
|
||||
{
|
||||
my ($self, $webmin) = @_;
|
||||
$self->{'webmin'} = $webmin;
|
||||
}
|
||||
|
||||
sub set_right
|
||||
{
|
||||
my ($self, $right) = @_;
|
||||
$self->{'right'} = $right;
|
||||
}
|
||||
|
||||
sub set_header
|
||||
{
|
||||
my ($self, $header) = @_;
|
||||
$self->{'header'} = $header;
|
||||
}
|
||||
|
||||
sub set_body
|
||||
{
|
||||
my ($self, $body) = @_;
|
||||
$self->{'body'} = $body;
|
||||
}
|
||||
|
||||
sub set_below
|
||||
{
|
||||
my ($self, $below) = @_;
|
||||
$self->{'below'} = $below;
|
||||
}
|
||||
|
||||
sub set_unbuffered
|
||||
{
|
||||
my ($self, $unbuffered) = @_;
|
||||
$self->{'unbuffered'} = $unbuffered;
|
||||
}
|
||||
|
||||
=head2 set_popup(popup?)
|
||||
If set to 1, then this is a popup window
|
||||
=cut
|
||||
sub set_popup
|
||||
{
|
||||
my ($self, $popup) = @_;
|
||||
$self->{'popup'} = $popup;
|
||||
}
|
||||
|
||||
=head2 get_myurl()
|
||||
Returns the path part of the URL for this page, like /foo/bar.cgi
|
||||
=cut
|
||||
sub get_myurl
|
||||
{
|
||||
my @args;
|
||||
if ($ENV{'QUERY_STRING'} && $ENV{'REQUEST_METHOD'} ne 'POST') {
|
||||
my %in;
|
||||
&ReadParse(\%in);
|
||||
foreach my $i (keys %in) {
|
||||
if ($i !~ /^ui_/) {
|
||||
foreach my $v (split(/\0/, $in{$i})) {
|
||||
push(@args, &urlize($i)."=".
|
||||
&urlize($v));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return @args ? $ENV{'SCRIPT_NAME'}."?".join("&", @args)
|
||||
: $ENV{'SCRIPT_NAME'};
|
||||
}
|
||||
|
||||
=head2 set_refresh(seconds)
|
||||
Sets the number of seconds between automatic page refreshes
|
||||
=cut
|
||||
sub set_refresh
|
||||
{
|
||||
my ($self, $refresh) = @_;
|
||||
$self->{'refresh'} = $refresh;
|
||||
}
|
||||
|
||||
sub get_refresh
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'refresh'};
|
||||
}
|
||||
|
||||
=head2 add_onload(code)
|
||||
Adds some Javascript code for inclusion in the onLoad tag
|
||||
=cut
|
||||
sub add_onload
|
||||
{
|
||||
my ($self, $code) = @_;
|
||||
push(@{$self->{'onloads'}}, $code);
|
||||
}
|
||||
|
||||
=head2 add_script(code)
|
||||
Adds some Javascript code for putting in the <head> section
|
||||
=cut
|
||||
sub add_script
|
||||
{
|
||||
my ($self, $script) = @_;
|
||||
push(@{$self->{'scripts'}}, $script);
|
||||
}
|
||||
|
||||
sub pre_content
|
||||
{
|
||||
my ($self) = @_;
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub post_content
|
||||
{
|
||||
my ($self) = @_;
|
||||
return undef;
|
||||
}
|
||||
|
||||
=head2 set_errormsg(message)
|
||||
Sets an error message to be displayed instead of the page contents
|
||||
=cut
|
||||
sub set_errormsg
|
||||
{
|
||||
my ($self, $errormsg) = @_;
|
||||
$self->{'errormsg'} = $errormsg;
|
||||
}
|
||||
|
||||
sub get_errormsg_html
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'errormsg'}."<p>\n";
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
32
Webmin/Password.pm
Normal file
32
Webmin/Password.pm
Normal file
@@ -0,0 +1,32 @@
|
||||
package Webmin::Password;
|
||||
@ISA = ( "Webmin::Textbox" );
|
||||
use Webmin::Textbox;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::Password(name, value, [size])
|
||||
Create a new text input field, for a password
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Password::new)) {
|
||||
return new Webmin::Theme::Password(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $name, $value, $size) = @_;
|
||||
$self = new Webmin::Textbox($name, $value, $size);
|
||||
bless($self);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this password input
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
return &ui_password($self->get_name(), $self->get_value(),
|
||||
$self->{'size'},
|
||||
$self->{'$disabled'});
|
||||
}
|
||||
|
||||
|
||||
|
||||
97
Webmin/PlainText.pm
Normal file
97
Webmin/PlainText.pm
Normal file
@@ -0,0 +1,97 @@
|
||||
package Webmin::PlainText;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::PlainText(text, columns)
|
||||
Displays a block of plain fixed-width text, within a page or form.
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::PlainText::new) &&
|
||||
caller() !~ /Webmin::Theme::PlainText/) {
|
||||
return new Webmin::Theme::PlainText(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $text, $columns) = @_;
|
||||
$self = { 'columns' => 80 };
|
||||
bless($self);
|
||||
$self->set_text($text);
|
||||
$self->set_columns($columns) if (defined($columns));
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
$rv .= "<table border><tr $cb><td><pre>";
|
||||
foreach my $l (&wrap_lines($self->get_text(), $self->get_columns())) {
|
||||
if (length($l) < $self->get_columns()) {
|
||||
$l .= (" " x $self->get_columns() - length($l));
|
||||
}
|
||||
$rv .= &html_escape($l)."\n";
|
||||
}
|
||||
if (!$self->get_text()) {
|
||||
print (" " x $self->get_columns()),"\n";
|
||||
}
|
||||
$rv .= "</pre></td></tr></table>\n";
|
||||
return $rv;
|
||||
}
|
||||
|
||||
sub set_text
|
||||
{
|
||||
my ($self, $text) = @_;
|
||||
$self->{'text'} = $text;
|
||||
}
|
||||
|
||||
sub get_text
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'text'};
|
||||
}
|
||||
|
||||
sub set_columns
|
||||
{
|
||||
my ($self, $columns) = @_;
|
||||
$self->{'columns'} = $columns;
|
||||
}
|
||||
|
||||
sub get_columns
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'columns'};
|
||||
}
|
||||
|
||||
# wrap_lines(text, width)
|
||||
# Given a multi-line string, return an array of lines wrapped to
|
||||
# the given width
|
||||
sub wrap_lines
|
||||
{
|
||||
local @rv;
|
||||
local $w = $_[1];
|
||||
foreach $rest (split(/\n/, $_[0])) {
|
||||
if ($rest =~ /\S/) {
|
||||
while($rest =~ /^(.{1,$w}\S*)\s*([\0-\377]*)$/) {
|
||||
push(@rv, $1);
|
||||
$rest = $2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
# Empty line .. keep as it is
|
||||
push(@rv, $rest);
|
||||
}
|
||||
}
|
||||
return @rv;
|
||||
}
|
||||
|
||||
=head2 set_page(Webmin::Page)
|
||||
Called when this form is added to a page
|
||||
=cut
|
||||
sub set_page
|
||||
{
|
||||
my ($self, $page) = @_;
|
||||
$self->{'page'} = $page;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
132
Webmin/Properties.pm
Normal file
132
Webmin/Properties.pm
Normal file
@@ -0,0 +1,132 @@
|
||||
package Webmin::Properties;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::Properties([heading], [columns], [width])
|
||||
Creates a read-only properties list
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Properties::new) &&
|
||||
caller() !~ /Webmin::Theme::Properties/) {
|
||||
return new Webmin::Theme::Properties(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $heading, $columns, $width) = @_;
|
||||
$self = { 'columns' => 2 };
|
||||
bless($self);
|
||||
$self->set_heading($heading) if (defined($heading));
|
||||
$self->set_columns($columns) if (defined($columns));
|
||||
$self->set_width($width) if (defined($width));
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 add_row(label, value, ...)
|
||||
Adds one row to the properties table
|
||||
=cut
|
||||
sub add_row
|
||||
{
|
||||
my ($self, @row) = @_;
|
||||
push(@{$self->{'rows'}}, \@row);
|
||||
}
|
||||
|
||||
=head2 set_heading_row(head1, head2, ...)
|
||||
Adds a row of headings
|
||||
=cut
|
||||
sub set_heading_row
|
||||
{
|
||||
my ($self, @row) = @_;
|
||||
$self->{'heading_row'} = \@row;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this properties list
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
my $width = $self->get_width();
|
||||
$rv .= "<table border ".($width ? "width=$width" : "").">\n";
|
||||
$rv .= "<tr><td><table width=100% cellspacing=0 cellpadding=3>\n";
|
||||
my $cols = $self->get_columns();
|
||||
if ($self->get_heading()) {
|
||||
$rv .= "<tr $tb><td colspan=$cols><b>".
|
||||
$self->get_heading()."</b></td> </tr>\n";
|
||||
}
|
||||
if ($self->{'heading_row'}) {
|
||||
$rv .= "<tr $tb>\n";
|
||||
foreach my $r (@{$self->{'heading_row'}}) {
|
||||
$rv .= "<td><b>$r</b></td>\n";
|
||||
}
|
||||
$rv .= "</tr>\n";
|
||||
}
|
||||
foreach my $r (@{$self->{'rows'}}) {
|
||||
$rv .= "<tr $cb>\n";
|
||||
$rv .= "<td><b>$r->[0]</b></td>\n";
|
||||
for(my $i=1; $i<@$r || $i<$cols; $i++) {
|
||||
$rv .= "<td>".(ref($r->[$i]) ? $r->[$i]->html()
|
||||
: $r->[$i])."</td>\n";
|
||||
}
|
||||
$rv .= "</tr>\n";
|
||||
}
|
||||
$rv .= "</table></td></tr></table>\n";
|
||||
return $rv;
|
||||
}
|
||||
|
||||
=head2 set_width([number|number%])
|
||||
Sets the width of this section. Can be called with 100%, 500, or undef to use
|
||||
the minimum possible width.
|
||||
=cut
|
||||
sub set_width
|
||||
{
|
||||
my ($self, $width) = @_;
|
||||
$self->{'width'} = $width;
|
||||
}
|
||||
|
||||
sub get_width
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'width'};
|
||||
}
|
||||
|
||||
=head2 set_columns(number)
|
||||
Sets the number of columns in the properties table, including the title column
|
||||
=cut
|
||||
sub set_columns
|
||||
{
|
||||
my ($self, $columns) = @_;
|
||||
$self->{'columns'} = $columns;
|
||||
}
|
||||
|
||||
sub get_columns
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'columns'};
|
||||
}
|
||||
|
||||
=head2 set_heading(number)
|
||||
Sets the heading to appear above the properties list
|
||||
=cut
|
||||
sub set_heading
|
||||
{
|
||||
my ($self, $heading) = @_;
|
||||
$self->{'heading'} = $heading;
|
||||
}
|
||||
|
||||
sub get_heading
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'heading'};
|
||||
}
|
||||
|
||||
|
||||
=head2 set_page(Webmin::Page)
|
||||
Called when this form is added to a page
|
||||
=cut
|
||||
sub set_page
|
||||
{
|
||||
my ($self, $page) = @_;
|
||||
$self->{'page'} = $page;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
77
Webmin/Radios.pm
Normal file
77
Webmin/Radios.pm
Normal file
@@ -0,0 +1,77 @@
|
||||
package Webmin::Radios;
|
||||
use Webmin::Input;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Input" );
|
||||
|
||||
=head2 new Webmin::Radios(name, value, &options, [disabled])
|
||||
Create a list of radio buttons, of which one may be selected
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Radios::new)) {
|
||||
return new Webmin::Theme::Radios(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $name, $value, $options, $disabled) = @_;
|
||||
$self = { };
|
||||
bless($self);
|
||||
$self->set_name($name);
|
||||
$self->set_value($value);
|
||||
$self->set_options($options);
|
||||
$self->set_disabled($disabled);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 add_option(name, [label])
|
||||
=cut
|
||||
sub add_option
|
||||
{
|
||||
my ($self, $name, $label) = @_;
|
||||
push(@{$self->{'options'}}, [ $name, $label ]);
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for all the radio buttons, one after the other
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $dis = $self->{'form'}->get_changefunc($self);
|
||||
my $opts = $self->get_options();
|
||||
if ($dis) {
|
||||
foreach my $o (@$opts) {
|
||||
$o->[2] = "onClick='$dis'";
|
||||
}
|
||||
}
|
||||
return &ui_radio($self->get_name(), $self->get_value(),
|
||||
$opts, $self->get_disabled());
|
||||
}
|
||||
|
||||
=head2 one_html(number)
|
||||
Returns the HTML for a single one of the radio buttons
|
||||
=cut
|
||||
sub one_html
|
||||
{
|
||||
my ($self, $num) = @_;
|
||||
my $opt = $self->{'options'}->[$num];
|
||||
my $dis = $self->{'form'}->get_changefunc($self);
|
||||
return &ui_oneradio($self->get_name(), $opt->[0],
|
||||
defined($opt->[1]) ? $opt->[1] : $opt->[0],
|
||||
$self->get_value() eq $opt->[0],
|
||||
$dis ? "onClick='$dis'" : undef,
|
||||
$self->get_disabled());
|
||||
}
|
||||
|
||||
sub set_options
|
||||
{
|
||||
my ($self, $options) = @_;
|
||||
$self->{'options'} = $options;
|
||||
}
|
||||
|
||||
sub get_options
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'options'};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
20
Webmin/ResultPage.pm
Normal file
20
Webmin/ResultPage.pm
Normal file
@@ -0,0 +1,20 @@
|
||||
package Webmin::ResultPage;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::ResultPage(subheading, title, message, [help-name])
|
||||
Create a new page object for showing some success message.
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::ResultPage::new) &&
|
||||
caller() !~ /Webmin::Theme::ResultPage/) {
|
||||
return new Webmin::Theme::ResultPage(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $subheading, $title, $message, $help) = @_;
|
||||
$self = new Webmin::Page($subheading, $title, $help);
|
||||
$self->add_message("<b>$message</b>");
|
||||
return $self;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
172
Webmin/Section.pm
Normal file
172
Webmin/Section.pm
Normal file
@@ -0,0 +1,172 @@
|
||||
package Webmin::Section;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::Section(header, [columns], [title], [width])
|
||||
Create a new form section, which has a header and contains some inputs
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Section::new) &&
|
||||
caller() !~ /Webmin::Theme::Section/) {
|
||||
return new Webmin::Theme::Section(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $header, $columns, $title, $width) = @_;
|
||||
$self = { 'columns' => 4 };
|
||||
bless($self);
|
||||
$self->set_header($header);
|
||||
$self->set_columns($columns) if (defined($columns));
|
||||
$self->set_title($title) if (defined($title));
|
||||
$self->set_width($width) if (defined($width));
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this form section
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
$rv .= &ui_table_start($self->{'header'},
|
||||
$self->{'width'} ? "width=$self->{'width'}" : undef,
|
||||
$self->{'columns'});
|
||||
foreach my $i (@{$self->{'inputs'}}) {
|
||||
if (is_input($i->[1])) {
|
||||
my $errs;
|
||||
my @errs = $self->{'form'}->field_errors($i->[1]->get_name());
|
||||
if (@errs) {
|
||||
foreach my $e (@errs) {
|
||||
$errs .= "<br><font color=#ff0000>$e</font>\n";
|
||||
}
|
||||
}
|
||||
$rv .= &ui_table_row($i->[0], $i->[1]->html().$errs,
|
||||
$i->[2]);
|
||||
}
|
||||
else {
|
||||
$rv .= &ui_table_row($i->[0],
|
||||
ref($i->[1]) ? $i->[1]->html() : $i->[1], $i->[2]);
|
||||
}
|
||||
}
|
||||
$rv .= &ui_table_end();
|
||||
return $rv;
|
||||
}
|
||||
|
||||
=head2 add_input(label, input, [columns])
|
||||
Adds some Webmin::Input object to this form section
|
||||
=cut
|
||||
sub add_input
|
||||
{
|
||||
my ($self, $label, $input, $cols) = @_;
|
||||
push(@{$self->{'inputs'}}, [ $label, $input, $cols ]);
|
||||
$input->set_form($self->{'form'});
|
||||
}
|
||||
|
||||
=head2 add_row(label, text, [columns])
|
||||
Adds a non-editable row to this form section
|
||||
=cut
|
||||
sub add_row
|
||||
{
|
||||
my ($self, $label, $text, $cols) = @_;
|
||||
push(@{$self->{'inputs'}}, [ $label, $text, $cols ]);
|
||||
}
|
||||
|
||||
=head2 add_separator()
|
||||
Adds some kind of separator at this point in the section
|
||||
=cut
|
||||
sub add_separator
|
||||
{
|
||||
my ($self) = @_;
|
||||
push(@{$self->{'inputs'}}, [ undef, "<hr>", $self->{'columns'} ]);
|
||||
}
|
||||
|
||||
sub set_header
|
||||
{
|
||||
my ($self, $header) = @_;
|
||||
$self->{'header'} = $header;
|
||||
}
|
||||
|
||||
sub set_columns
|
||||
{
|
||||
my ($self, $columns) = @_;
|
||||
$self->{'columns'} = $columns;
|
||||
}
|
||||
|
||||
sub set_title
|
||||
{
|
||||
my ($self, $title) = @_;
|
||||
$self->{'title'} = $title;
|
||||
}
|
||||
|
||||
=head2 set_width([number|number%])
|
||||
Sets the width of this section. Can be called with 100%, 500, or undef to use
|
||||
the minimum possible width.
|
||||
=cut
|
||||
sub set_width
|
||||
{
|
||||
my ($self, $width) = @_;
|
||||
$self->{'width'} = $width;
|
||||
}
|
||||
|
||||
=head2 validate()
|
||||
Validates all form inputs, based on the given CGI input hash. Returns a list
|
||||
of errors, each of which is field name, error message and field label.
|
||||
=cut
|
||||
sub validate
|
||||
{
|
||||
my ($self) = @_;
|
||||
my @errs;
|
||||
foreach my $i (@{$self->{'inputs'}}) {
|
||||
if (is_input($i->[1])) {
|
||||
foreach my $e ($i->[1]->validate()) {
|
||||
push(@errs, [ $i->[1]->get_name(), $e, $i->[0] ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return @errs;
|
||||
}
|
||||
|
||||
=head2 get_value(input-name)
|
||||
Returns the value of the input with the given name.
|
||||
=cut
|
||||
sub get_value
|
||||
{
|
||||
my ($self, $name) = @_;
|
||||
foreach my $i (@{$self->{'inputs'}}) {
|
||||
if (is_input($i->[1]) && $i->[1]->get_name() eq $name) {
|
||||
return $i->[1]->get_value();
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
=head2 set_form(form)
|
||||
Called by the Webmin::Form object when this section is added to it
|
||||
=cut
|
||||
sub set_form
|
||||
{
|
||||
my ($self, $form) = @_;
|
||||
$self->{'form'} = $form;
|
||||
foreach my $i (@{$self->{'inputs'}}) {
|
||||
if (is_input($i->[1])) {
|
||||
$i->[1]->set_form($form);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub list_inputs
|
||||
{
|
||||
my ($self) = @_;
|
||||
return map { $_->[1] } grep { is_input($_->[1]) } @{$self->{'inputs'}};
|
||||
}
|
||||
|
||||
=head2 is_input(object)
|
||||
=cut
|
||||
sub is_input
|
||||
{
|
||||
my ($object) = @_;
|
||||
return ref($object) && ref($object) =~ /::/ &&
|
||||
$object->isa("Webmin::Input");
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
135
Webmin/Select.pm
Normal file
135
Webmin/Select.pm
Normal file
@@ -0,0 +1,135 @@
|
||||
package Webmin::Select;
|
||||
use Webmin::Input;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Input" );
|
||||
|
||||
=head2 new Webmin::Select(name, value|&values, &options, [multiple-size],
|
||||
[add-missing], [disabled])
|
||||
Create a menu or multiple-selection field
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Select::new)) {
|
||||
return new Webmin::Theme::Select(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $name, $value, $options, $size, $missing, $disabled) = @_;
|
||||
$self = { 'size' => 1 };
|
||||
bless($self);
|
||||
$self->set_name($name);
|
||||
$self->set_value($value);
|
||||
$self->set_options($options);
|
||||
$self->set_size($size) if (defined($size));
|
||||
$self->set_missing($missing);
|
||||
$self->set_disabled($disabled);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 add_option(name, [label])
|
||||
=cut
|
||||
sub add_option
|
||||
{
|
||||
my ($self, $name, $label) = @_;
|
||||
push(@{$self->{'options'}}, [ $name, $label ]);
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this menu or multi-select input
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $dis = $self->{'form'}->get_changefunc($self);
|
||||
return &ui_select($self->get_name(), $self->get_value(),
|
||||
$self->get_options(),
|
||||
$self->get_size() > 1 ? $self->get_size() : undef,
|
||||
$self->get_size() > 1 ? 1 : 0,
|
||||
undef,
|
||||
$self->get_disabled(),
|
||||
$dis ? "onChange='$dis'" : undef).
|
||||
($self->get_size() > 1 ?
|
||||
&ui_hidden("ui_exists_".$self->get_name(), 1) : "");
|
||||
}
|
||||
|
||||
=head2 get_value()
|
||||
For a multi-select field, returns an array ref of all values. For a menu,
|
||||
return just the one value.
|
||||
=cut
|
||||
sub get_value
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $in = $self->{'form'} ? $self->{'form'}->{'in'} : undef;
|
||||
if ($in && (defined($in->{$self->{'name'}}) ||
|
||||
defined($in->{"ui_exists_".$self->{'name'}}))) {
|
||||
if ($self->get_size() > 1) {
|
||||
return [ split(/\0/, $in->{$self->{'name'}}) ];
|
||||
}
|
||||
else {
|
||||
return $in->{$self->{'name'}};
|
||||
}
|
||||
}
|
||||
elsif ($in && defined($in->{"ui_value_".$self->{'name'}})) {
|
||||
if ($self->get_size() > 1) {
|
||||
return [ split(/\0/, $in->{"ui_value_".$self->{'name'}}) ];
|
||||
}
|
||||
else {
|
||||
return $in->{"ui_value_".$self->{'name'}};
|
||||
}
|
||||
}
|
||||
else {
|
||||
return $self->{'value'};
|
||||
}
|
||||
}
|
||||
|
||||
sub set_options
|
||||
{
|
||||
my ($self, $options) = @_;
|
||||
$self->{'options'} = $options;
|
||||
}
|
||||
|
||||
sub set_size
|
||||
{
|
||||
my ($self, $size) = @_;
|
||||
$self->{'size'} = $size;
|
||||
}
|
||||
|
||||
sub set_missing
|
||||
{
|
||||
my ($self, $missing) = @_;
|
||||
$self->{'missing'} = $missing;
|
||||
}
|
||||
|
||||
sub get_options
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'options'};
|
||||
}
|
||||
|
||||
sub get_size
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'size'};
|
||||
}
|
||||
|
||||
sub get_missing
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'missing'};
|
||||
}
|
||||
|
||||
=head2 validate()
|
||||
Returns a list of error messages for this field
|
||||
=cut
|
||||
sub validate
|
||||
{
|
||||
my ($self) = @_;
|
||||
if ($self->{'size'} > 1) {
|
||||
my $value = $self->get_value();
|
||||
if ($self->{'mandatory'} && !@$value) {
|
||||
return ( $self->{'mandatorymsg'} || $text{'ui_mandatory'} );
|
||||
}
|
||||
}
|
||||
return ( );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
41
Webmin/Submit.pm
Normal file
41
Webmin/Submit.pm
Normal file
@@ -0,0 +1,41 @@
|
||||
package Webmin::Submit;
|
||||
use Webmin::Input;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Input" );
|
||||
|
||||
=head2 new Webmin::Submit(label, [name], [disabled])
|
||||
Create a form submit button
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Submit::new) &&
|
||||
caller() !~ /Webmin::Theme::Submit/) {
|
||||
return new Webmin::Theme::Submit(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $value, $name, $disabled) = @_;
|
||||
$self = { };
|
||||
bless($self);
|
||||
$self->set_value($value);
|
||||
$self->set_name($name) if ($name);
|
||||
$self->set_disabled($disabled) if ($disabled);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this form submit button
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
return &ui_submit($self->get_value(), $self->get_name(),
|
||||
$self->get_disabled());
|
||||
}
|
||||
|
||||
sub get_value
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'value'};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
660
Webmin/Table.pm
Normal file
660
Webmin/Table.pm
Normal file
@@ -0,0 +1,660 @@
|
||||
package Webmin::Table;
|
||||
use Webmin::JavascriptButton;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::Table(&headings, [width], [name], [heading])
|
||||
Create a multi-column table, with support for sorting, paging and so on
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Table::new) &&
|
||||
caller() !~ /Webmin::Theme::Table/) {
|
||||
return new Webmin::Theme::Table(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $headings, $width, $name, $heading) = @_;
|
||||
$self = { 'sorter' => [ map { \&default_sorter } @$headings ] };
|
||||
bless($self);
|
||||
$self->set_headings($headings);
|
||||
$self->set_name($name) if (defined($name));
|
||||
$self->set_width($width) if (defined($width));
|
||||
$self->set_heading($heading) if (defined($heading));
|
||||
$self->set_all_sortable(1);
|
||||
$self->set_paging(1);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 add_row(&fields)
|
||||
Adds a row to the table. Each element in the row can be either an input of some
|
||||
kind, or a piece of text.
|
||||
=cut
|
||||
sub add_row
|
||||
{
|
||||
my ($self, $fields) = @_;
|
||||
push(@{$self->{'rows'}}, $fields);
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this table. The actual ordering may depend upon sort headers
|
||||
clicked by the user. The rows to display may be limited by the page size.
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my @srows = @{$self->{'rows'}};
|
||||
my $thisurl = $self->{'form'}->{'page'}->get_myurl();
|
||||
my $name = $self->get_name();
|
||||
my $rv;
|
||||
|
||||
# Add the heading
|
||||
if ($self->get_heading()) {
|
||||
$rv .= &ui_subheading($self->get_heading())."\n";
|
||||
}
|
||||
|
||||
my $sm = $self->get_searchmax();
|
||||
if (defined($sm) && @srows > $sm) {
|
||||
# Too many rows to show .. add a search form. This will need to close
|
||||
# the parent form, and then re-open it after the search form, as nested
|
||||
# forms aren't allowed!
|
||||
if ($self->get_searchmsg()) {
|
||||
$rv .= $self->get_searchmsg()."<br>\n";
|
||||
}
|
||||
|
||||
my $form = new Webmin::Form($thisurl, "get");
|
||||
$form->set_input($self->{'form'}->{'in'});
|
||||
my $section = new Webmin::Section(undef, 2);
|
||||
$form->add_section($section);
|
||||
|
||||
my $col = new Webmin::Select("ui_searchcol_".$name, undef);
|
||||
my $i = 0;
|
||||
foreach my $h (@{$self->get_headings()}) {
|
||||
if ($self->{'sortable'}->[$i]) {
|
||||
$col->add_option($i, $h);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
$section->add_input($text{'ui_searchcol'}, $col);
|
||||
|
||||
my $for = new Webmin::Textbox("ui_searchfor_".$name, undef, 30);
|
||||
$section->add_input($text{'ui_searchfor'}, $for);
|
||||
|
||||
$rv .= $section->html();
|
||||
my $url = $self->make_url(undef, undef, undef, undef, 1);
|
||||
my $jsb = new Webmin::JavascriptButton($text{'ui_searchok'},
|
||||
"window.location = '$url'+'&'+'ui_searchfor_${name}'+'='+escape(form.ui_searchfor_${name}.value)+'&'+'ui_searchcol_${name}'+'='+escape(form.ui_searchcol_${name}.selectedIndex)");
|
||||
$rv .= $jsb->html();
|
||||
$rv .= "<br>\n";
|
||||
|
||||
# Limit records to current search
|
||||
if (defined($col->get_value())) {
|
||||
my $sf = $for->get_value();
|
||||
@srows = grep { $_->[$col->get_value()] =~ /\Q$sf\E/i } @srows;
|
||||
}
|
||||
else {
|
||||
@srows = ( );
|
||||
}
|
||||
}
|
||||
|
||||
# Prepare the selector
|
||||
my $selc = $self->{'selectcolumn'};
|
||||
my $seli = $self->{'selectinput'};
|
||||
my %selmap;
|
||||
if (defined($selc)) {
|
||||
my $i = 0;
|
||||
foreach my $r (@srows) {
|
||||
$selmap{$r,$selc} = $seli->one_html($i);
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
# Sort the rows
|
||||
my ($sortcol, $sortdir) = $self->get_sortcolumn();
|
||||
if (defined($sortcol)) {
|
||||
my $func = $self->{'sorter'}->[$sortcol];
|
||||
@srows = sort { my $so = &$func($a->[$sortcol], $b->[$sortcol], $sortcol);
|
||||
$sortdir ? -$so : $so } @srows;
|
||||
}
|
||||
|
||||
# Build the td attributes
|
||||
my @tds = map { "valign=top" } @{$self->{'headings'}};
|
||||
if ($self->{'widths'}) {
|
||||
my $i = 0;
|
||||
foreach my $w (@{$self->{'widths'}}) {
|
||||
$tds[$i++] .= " width=$w";
|
||||
}
|
||||
}
|
||||
if ($self->{'aligns'}) {
|
||||
my $i = 0;
|
||||
foreach my $a (@{$self->{'aligns'}}) {
|
||||
$tds[$i++] .= " align=$a";
|
||||
}
|
||||
}
|
||||
|
||||
# Find the page we want
|
||||
my $page = $self->get_pagepos();
|
||||
my ($start, $end, $origsize);
|
||||
if ($self->get_paging() && $self->get_pagesize()) {
|
||||
# Restrict view to rows within some page
|
||||
$start = $self->get_pagesize()*$page;
|
||||
$end = $self->get_pagesize()*($page+1) - 1;
|
||||
if ($start >= @srows) {
|
||||
# Gone off end!
|
||||
$start = 0;
|
||||
$end = $self->get_pagesize()-1;
|
||||
}
|
||||
if ($end >= @srows) {
|
||||
# End is too far
|
||||
$end = @srows-1;
|
||||
}
|
||||
$origsize = scalar(@srows);
|
||||
@srows = @srows[$start..$end];
|
||||
}
|
||||
|
||||
# Generate the headings, with sorters
|
||||
$thisurl .= $thisurl =~ /\?/ ? "&" : "?";
|
||||
my @sheadings;
|
||||
my $i = 0;
|
||||
foreach my $h (@{$self->get_headings()}) {
|
||||
if ($self->{'sortable'}->[$i]) {
|
||||
# Column can be sorted!
|
||||
my $hh = "<table cellpadding=0 cellspacing=0 width=100%><tr>";
|
||||
$hh .= "<td><b>$h</b></td> <td align=right>";
|
||||
if (!defined($sortcol) || $sortcol != $i) {
|
||||
# Not sorting on this column .. show grey button
|
||||
my $url = $self->make_url($i, 0, undef, undef);
|
||||
$hh .= "<a href='$url'>".
|
||||
"<img src=/images/nosort.gif border=0></a>";
|
||||
}
|
||||
else {
|
||||
# Sorting .. show button to switch mode
|
||||
my $notsort = !$sortdir;
|
||||
my $url = $self->make_url($i, $sortdir ? 0 : 1, undef, undef);
|
||||
$hh .= "<a href='$url'>".
|
||||
"<img src=/images/sort.gif border=0></a>";
|
||||
}
|
||||
$hh .= "</td></tr></table>";
|
||||
push(@sheadings, $hh);
|
||||
}
|
||||
else {
|
||||
push(@sheadings, $h);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
# Get any errors for inputs
|
||||
my @errs = map { $_->get_errors() } $self->list_inputs();
|
||||
if (@errs) {
|
||||
foreach my $e (@errs) {
|
||||
$rv .= "<font color=#ff0000>$e</font><br>\n";
|
||||
}
|
||||
}
|
||||
|
||||
# Build links for top and bottom
|
||||
my $links;
|
||||
if (ref($seli) =~ /Checkboxes/) {
|
||||
# Add select all/none links
|
||||
my $formno = $self->{'form'}->get_formno();
|
||||
$links .= &select_all_link($seli->get_name(), $formno,
|
||||
$text{'ui_selall'})."\n";
|
||||
$links .= &select_invert_link($seli->get_name(), $formno,
|
||||
$text{'ui_selinv'})."\n";
|
||||
$links .= " \n";
|
||||
}
|
||||
foreach my $l (@{$self->{'links'}}) {
|
||||
$links .= "<a href='$l->[0]'>$l->[1]</a>\n";
|
||||
}
|
||||
$links .= "<br>" if ($links);
|
||||
|
||||
# Build list of inputs for bottom
|
||||
my $inputs;
|
||||
foreach my $i (@{$self->{'inputs'}}) {
|
||||
$inputs .= $i->html()."\n";
|
||||
}
|
||||
$inputs .= "<br>" if ($inputs);
|
||||
|
||||
# Create the pager
|
||||
if ($self->get_paging() && $origsize) {
|
||||
my $lastpage = int(($origsize-1)/$self->get_pagesize());
|
||||
$rv .= "<center>";
|
||||
if ($page != 0) {
|
||||
# Add start and left arrows
|
||||
my $surl = $self->make_url(undef, undef, undef, 0);
|
||||
$rv .= "<a href='$surl'><img src=/images/first.gif border=0 align=middle></a>\n";
|
||||
my $lurl = $self->make_url(undef, undef, undef, $page-1);
|
||||
$rv .= "<a href='$lurl'><img src=/images/left.gif border=0 align=middle></a>\n";
|
||||
}
|
||||
else {
|
||||
# Start and left are disabled
|
||||
$rv .= "<img src=/images/first-grey.gif border=0 align=middle>\n";
|
||||
$rv .= "<img src=/images/left-grey.gif border=0 align=middle>\n";
|
||||
}
|
||||
$rv .= &text('ui_paging', $start+1, $end+1, $origsize);
|
||||
if ($end < $origsize-1) {
|
||||
# Add right and end arrows
|
||||
my $rurl = $self->make_url(undef, undef, undef, $page+1);
|
||||
$rv .= "<a href='$rurl'><img src=/images/right.gif border=0 align=middle></a>\n";
|
||||
my $eurl = $self->make_url(undef, undef, undef, $lastpage);
|
||||
$rv .= "<a href='$eurl'><img src=/images/last.gif border=0 align=middle></a>\n";
|
||||
}
|
||||
else {
|
||||
# Right and end are disabled
|
||||
$rv .= "<img src=/images/right-grey.gif border=0 align=middle>\n";
|
||||
$rv .= "<img src=/images/last-grey.gif border=0 align=middle>\n";
|
||||
}
|
||||
$rv .= "</center>\n";
|
||||
}
|
||||
|
||||
# Create actual table
|
||||
if (@srows) {
|
||||
$rv .= $links;
|
||||
$rv .= &ui_columns_start(\@sheadings, $self->{'width'}, 0, \@tds);
|
||||
foreach my $r (@srows) {
|
||||
my @row;
|
||||
for(my $i=0; $i<@$r || $i<@sheadings; $i++) {
|
||||
if (ref($r->[$i]) eq "ARRAY") {
|
||||
my $j = $r->[$i]->[0] &&
|
||||
$r->[$i]->[0]->isa("Webmin::TableAction")
|
||||
? " | " : " ";
|
||||
$row[$i] = $selmap{$r,$i}.
|
||||
join($j, map { ref($_) ? $_->html() : $_ }
|
||||
@{$r->[$i]});
|
||||
}
|
||||
elsif (ref($r->[$i])) {
|
||||
$row[$i] = $selmap{$r,$i}.$r->[$i]->html();
|
||||
}
|
||||
else {
|
||||
$row[$i] = $selmap{$r,$i}.$r->[$i];
|
||||
}
|
||||
}
|
||||
$rv .= &ui_columns_row(\@row, \@tds);
|
||||
}
|
||||
$rv .= &ui_columns_end();
|
||||
}
|
||||
elsif ($self->{'emptymsg'}) {
|
||||
$rv .= $self->{'emptymsg'}."<p>\n";
|
||||
}
|
||||
$rv .= $links;
|
||||
$rv .= $inputs;
|
||||
return $rv;
|
||||
}
|
||||
|
||||
=head2 set_form(form)
|
||||
Called by the Webmin::Form object when this table is added to it
|
||||
=cut
|
||||
sub set_form
|
||||
{
|
||||
my ($self, $form) = @_;
|
||||
$self->{'form'} = $form;
|
||||
foreach my $i ($self->list_inputs()) {
|
||||
$i->set_form($form);
|
||||
}
|
||||
}
|
||||
|
||||
=head2 set_sorter(function, [column])
|
||||
Sets a function used for sorting fields. Will be called with two field values to
|
||||
compare, and a column number.
|
||||
=cut
|
||||
sub set_sorter
|
||||
{
|
||||
my ($self, $func, $col) = @_;
|
||||
if (defined($col)) {
|
||||
$self->{'sorter'}->[$col] = $func;
|
||||
}
|
||||
else {
|
||||
$self->{'sorter'} = [ map { $func } @{$self->{'headings'}} ];
|
||||
}
|
||||
}
|
||||
|
||||
=head2 default_sorter(value1, value2, col)
|
||||
=cut
|
||||
sub default_sorter
|
||||
{
|
||||
my ($value1, $value2, $col) = @_;
|
||||
if (ref($value1) && $value1->isa("Webmin::TableAction")) {
|
||||
$value1 = $value1->get_value();
|
||||
$value2 = $value2->get_value();
|
||||
}
|
||||
return lc($value1) cmp lc($value2);
|
||||
}
|
||||
|
||||
=head2 numeric_sorter(value1, value2, col)
|
||||
=cut
|
||||
sub numeric_sorter
|
||||
{
|
||||
my ($value1, $value2, $col) = @_;
|
||||
return $value1 <=> $value2;
|
||||
}
|
||||
|
||||
=head2 set_sortable(column, sortable?)
|
||||
Tells the table if some column should allow sorting or not. By default, all are.
|
||||
=cut
|
||||
sub set_sortable
|
||||
{
|
||||
my ($self, $col, $sortable) = @_;
|
||||
$self->{'sortable'}->[$col] = $sortable;
|
||||
}
|
||||
|
||||
=head2 set_all_sortable(sortable?)
|
||||
Enabled or disables sorting for all columns
|
||||
=cut
|
||||
sub set_all_sortable
|
||||
{
|
||||
my ($self, $sortable) = @_;
|
||||
$self->{'sortable'} = [ map { $sortable } @{$self->{'headings'}} ];
|
||||
}
|
||||
|
||||
=head2 get_sortcolumn()
|
||||
Returns the column to sort on and the order (1 for descending), or undef for none
|
||||
=cut
|
||||
sub get_sortcolumn
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $in = $self->{'form'} ? $self->{'form'}->{'in'} : undef;
|
||||
my $name = $self->get_name();
|
||||
if ($in && defined($in->{"ui_sortcolumn_".$name})) {
|
||||
return ( $in->{"ui_sortcolumn_".$name},
|
||||
$in->{"ui_sortdir_".$name} );
|
||||
}
|
||||
else {
|
||||
return ( $self->{'sortcolumn'}, $self->{'sortdir'} );
|
||||
}
|
||||
}
|
||||
|
||||
=head2 set_sortcolumn(num, descending?)
|
||||
Sets the default column on which sorting will be done, unless overridden by
|
||||
the user.
|
||||
=cut
|
||||
sub set_sortcolumn
|
||||
{
|
||||
my ($self, $col, $desc) = @_;
|
||||
$self->{'sortcolumn'} = $col;
|
||||
$self->{'sortdir'} = $desc;
|
||||
}
|
||||
|
||||
=head2 get_paging()
|
||||
Returns 1 if page-by-page display should be used
|
||||
=cut
|
||||
sub get_paging
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $in = $self->{'form'} ? $self->{'form'}->{'in'} : undef;
|
||||
my $name = $self->get_name();
|
||||
if ($in && defined($in->{"ui_paging_".$name})) {
|
||||
return ( $in->{"ui_paging_".$name} );
|
||||
}
|
||||
else {
|
||||
return ( $self->{'paging'} );
|
||||
}
|
||||
}
|
||||
|
||||
=head2 set_paging(paging?)
|
||||
Turns page-by-page display of the table on or off
|
||||
=cut
|
||||
sub set_paging
|
||||
{
|
||||
my ($self, $paging) = @_;
|
||||
$self->{'paging'} = $paging;
|
||||
}
|
||||
|
||||
sub set_name
|
||||
{
|
||||
my ($self, $name) = @_;
|
||||
$self->{'name'} = $name;
|
||||
}
|
||||
|
||||
=head2 get_name()
|
||||
Returns the name for indentifying this table in HTML
|
||||
=cut
|
||||
sub get_name
|
||||
{
|
||||
my ($self) = @_;
|
||||
if (defined($self->{'name'})) {
|
||||
return $self->{'name'};
|
||||
}
|
||||
elsif ($self->{'form'}) {
|
||||
my $secs = $self->{'form'}->{'sections'};
|
||||
for(my $i=0; $i<@$secs; $i++) {
|
||||
return "table".$i if ($secs->[$i] eq $self);
|
||||
}
|
||||
}
|
||||
return "table";
|
||||
}
|
||||
|
||||
sub set_headings
|
||||
{
|
||||
my ($self, $headings) = @_;
|
||||
$self->{'headings'} = $headings;
|
||||
}
|
||||
|
||||
sub get_headings
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'headings'};
|
||||
}
|
||||
|
||||
=head2 set_selector(column, input)
|
||||
Takes a Webmin::Checkboxes or Webmin::Radios object, and uses it to add checkboxes
|
||||
in the specified column.
|
||||
=cut
|
||||
sub set_selector
|
||||
{
|
||||
my ($self, $col, $input) = @_;
|
||||
$self->{'selectcolumn'} = $col;
|
||||
$self->{'selectinput'} = $input;
|
||||
$input->set_form($form);
|
||||
}
|
||||
|
||||
=head2 get_selector()
|
||||
Returns the UI element used for selecting rows
|
||||
=cut
|
||||
sub get_selector
|
||||
{
|
||||
my ($self) = @_;
|
||||
return wantarray ? ( $self->{'selectinput'}, $self->{'selectcolumn'} )
|
||||
: $self->{'selectinput'};
|
||||
}
|
||||
|
||||
=head2 set_widths(&widths)
|
||||
Given an array reference of widths (like 50 or 20%), uses them for the columns
|
||||
in the table.
|
||||
=cut
|
||||
sub set_widths
|
||||
{
|
||||
my ($self, $widths) = @_;
|
||||
$self->{'widths'} = $widths;
|
||||
}
|
||||
|
||||
=head2 set_width([number|number%])
|
||||
Sets the width of this entire table. Can be called with 100%, 500 or undef to use
|
||||
the minimum possible width.
|
||||
=cut
|
||||
sub set_width
|
||||
{
|
||||
my ($self, $width) = @_;
|
||||
$self->{'width'} = $width;
|
||||
}
|
||||
|
||||
=head2 set_aligns(&aligns)
|
||||
Given an array reference of horizontal alignments (like left or right), uses them
|
||||
for the columns in the table.
|
||||
=cut
|
||||
sub set_aligns
|
||||
{
|
||||
my ($self, $aligns) = @_;
|
||||
$self->{'aligns'} = $aligns;
|
||||
}
|
||||
|
||||
=head2 validate()
|
||||
Validates all inputs, and returns a list of error messages
|
||||
=cut
|
||||
sub validate
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $seli = $self->{'selectinput'};
|
||||
my @errs;
|
||||
if ($seli) {
|
||||
push(@errs, map { [ $seli->get_name(), $_ ] } $seli->validate());
|
||||
}
|
||||
foreach my $i ($self->list_inputs()) {
|
||||
foreach my $e ($i->validate()) {
|
||||
push(@errs, [ $i->get_name(), $e ]);
|
||||
}
|
||||
}
|
||||
return @errs;
|
||||
}
|
||||
|
||||
=head2 get_value(input-name)
|
||||
Returns the value of the input with the given name.
|
||||
=cut
|
||||
sub get_value
|
||||
{
|
||||
my ($self, $name) = @_;
|
||||
if ($self->{'selectinput'} && $self->{'selectinput'}->get_name() eq $name) {
|
||||
return $self->{'selectinput'}->get_value();
|
||||
}
|
||||
foreach my $i ($self->list_inputs()) {
|
||||
if ($i->get_name() eq $name) {
|
||||
return $i->get_value();
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
=head2 list_inputs()
|
||||
Returns all inputs in all form sections
|
||||
=cut
|
||||
sub list_inputs
|
||||
{
|
||||
my ($self) = @_;
|
||||
my @rv = @{$self->{'inputs'}};
|
||||
push(@rv, $self->{'selectinput'}) if ($self->{'selectinput'});
|
||||
return @rv;
|
||||
}
|
||||
|
||||
=head2 set_searchmax(num, [message])
|
||||
Sets the maximum number of table rows to display before showing a search form
|
||||
=cut
|
||||
sub set_searchmax
|
||||
{
|
||||
my ($self, $searchmax, $searchmsg) = @_;
|
||||
$self->{'searchmax'} = $searchmax;
|
||||
$self->{'searchmsg'} = $searchmsg;
|
||||
}
|
||||
|
||||
sub get_searchmax
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'searchmax'};
|
||||
}
|
||||
|
||||
sub get_searchmsg
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'searchmsg'};
|
||||
}
|
||||
|
||||
=head2 add_link(link, message)
|
||||
Adds a link to the table, for example for adding a new entry
|
||||
=cut
|
||||
sub add_link
|
||||
{
|
||||
my ($self, $link, $msg) = @_;
|
||||
push(@{$self->{'links'}}, [ $link, $msg ]);
|
||||
}
|
||||
|
||||
=head2 add_input(input)
|
||||
Adds some input to be displayed at the bottom of the table
|
||||
=cut
|
||||
sub add_input
|
||||
{
|
||||
my ($self, $input) = @_;
|
||||
push(@{$self->{'inputs'}}, $input);
|
||||
$input->set_form($self->{'form'});
|
||||
}
|
||||
|
||||
=head2 set_emptymsg(message)
|
||||
Sets the message to display when the table is empty
|
||||
=cut
|
||||
sub set_emptymsg
|
||||
{
|
||||
my ($self, $emptymsg) = @_;
|
||||
$self->{'emptymsg'} = $emptymsg;
|
||||
}
|
||||
|
||||
=head2 set_heading(text)
|
||||
Sets the heading text to appear above the table
|
||||
=cut
|
||||
sub set_heading
|
||||
{
|
||||
my ($self, $heading) = @_;
|
||||
$self->{'heading'} = $heading;
|
||||
}
|
||||
|
||||
sub get_heading
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'heading'};
|
||||
}
|
||||
|
||||
=head2 set_pagesize(pagesize)
|
||||
Sets the size of a page. Set to 0 to turn off completely.
|
||||
=cut
|
||||
sub set_pagesize
|
||||
{
|
||||
my ($self, $pagesize) = @_;
|
||||
$self->{'pagesize'} = $pagesize;
|
||||
}
|
||||
|
||||
=head2 get_pagesize()
|
||||
Returns the size of a page, or 0 if paging is turned off totally
|
||||
=cut
|
||||
sub get_pagesize
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'pagesize'};
|
||||
}
|
||||
|
||||
sub get_pagepos
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $in = $self->{'form'} ? $self->{'form'}->{'in'} : undef;
|
||||
my $name = $self->get_name();
|
||||
if ($in && defined($in->{"ui_pagepos_".$name})) {
|
||||
return ( $in->{"ui_pagepos_".$name} );
|
||||
}
|
||||
else {
|
||||
return ( $self->{'pagepos'} );
|
||||
}
|
||||
}
|
||||
|
||||
=head2 make_url(sortcol, sortdir, paging, page, [no-searchargs], [no-pagearg])
|
||||
Returns a link to this table's page, with the defaults for the various state
|
||||
fields overriden by the parameters (where defined)
|
||||
=cut
|
||||
sub make_url
|
||||
{
|
||||
my ($self, $newsortcol, $newsortdir, $newpaging, $newpagepos,
|
||||
$nosearch, $nopage) = @_;
|
||||
my ($sortcol, $sortdir) = $self->get_sortcolumn();
|
||||
$sortcol = $newsortcol if (defined($newsortcol));
|
||||
$sortdir = $newsortdir if (defined($newsortdir));
|
||||
my $paging = $self->get_paging();
|
||||
$paging = $newpaging if (defined($newpaging));
|
||||
my $pagepos = $self->get_pagepos();
|
||||
$pagepos = $newpagepos if (defined($newpagepos));
|
||||
|
||||
my $thisurl = $self->{'form'}->{'page'}->get_myurl();
|
||||
my $name = $self->get_name();
|
||||
$thisurl .= $thisurl =~ /\?/ ? "&" : "?";
|
||||
my $in = $self->{'form'}->{'in'};
|
||||
return "${thisurl}ui_sortcolumn_${name}=$sortcol".
|
||||
"&ui_sortdir_${name}=$sortdir".
|
||||
"&ui_paging_${name}=$paging".
|
||||
($nopage ? "" : "&ui_pagepos_${name}=$pagepos").
|
||||
($nosearch ? "" : "&ui_searchfor_${name}=".
|
||||
&urlize($in->{"ui_searchfor_${name}"}).
|
||||
"&ui_searchcol_${name}=".
|
||||
&urlize($in->{"ui_searchcol_${name}"}));
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
92
Webmin/TableAction.pm
Normal file
92
Webmin/TableAction.pm
Normal file
@@ -0,0 +1,92 @@
|
||||
package Webmin::TableAction;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::TableAction(cgi, label, &args, disabled)
|
||||
An object of this class can be added to a table or properties object to create
|
||||
a link or action button of some kind.
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::TableAction::new) &&
|
||||
caller() !~ /Webmin::Theme::TableAction/) {
|
||||
return new Webmin::Theme::TableAction(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $cgi, $value, $args, $disabled) = @_;
|
||||
$self = { };
|
||||
bless($self);
|
||||
$self->set_value($value);
|
||||
$self->set_cgi($cgi);
|
||||
$self->set_args($args) if (defined($args));
|
||||
$self->set_disabled($disabled) if (defined($disabled));
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
if ($self->get_disabled()) {
|
||||
$rv .= "<u><i>".$self->get_value()."</i></u>";
|
||||
}
|
||||
else {
|
||||
my $link = $self->get_cgi();
|
||||
my $i = 0;
|
||||
foreach my $a (@{$self->get_args()}) {
|
||||
$link .= ($i++ ? "&" : "?");
|
||||
$link .= &urlize($a->[0])."=".&urlize($a->[1]);
|
||||
}
|
||||
$rv .= "<a href='$link'>".$self->get_value()."</a>";
|
||||
}
|
||||
return $rv;
|
||||
}
|
||||
|
||||
sub set_value
|
||||
{
|
||||
my ($self, $value) = @_;
|
||||
$self->{'value'} = $value;
|
||||
}
|
||||
|
||||
sub get_value
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'value'};
|
||||
}
|
||||
|
||||
sub set_cgi
|
||||
{
|
||||
my ($self, $cgi) = @_;
|
||||
$self->{'cgi'} = $cgi;
|
||||
}
|
||||
|
||||
sub get_cgi
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'cgi'};
|
||||
}
|
||||
|
||||
sub set_args
|
||||
{
|
||||
my ($self, $args) = @_;
|
||||
$self->{'args'} = $args;
|
||||
}
|
||||
|
||||
sub get_args
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'args'};
|
||||
}
|
||||
|
||||
sub set_disabled
|
||||
{
|
||||
my ($self, $disabled) = @_;
|
||||
$self->{'disabled'} = $disabled;
|
||||
}
|
||||
|
||||
sub get_disabled
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'disabled'};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
142
Webmin/Tabs.pm
Normal file
142
Webmin/Tabs.pm
Normal file
@@ -0,0 +1,142 @@
|
||||
package Webmin::Tabs;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::Tabs([&tabs])
|
||||
Displayed at the top of a page, to allow selection of various pages
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
my ($self, $tabs) = @_;
|
||||
if (defined(&Webmin::Theme::Tabs::new)) {
|
||||
return new Webmin::Theme::Tabs(@_[1..$#_]);
|
||||
}
|
||||
$self = { 'tabs' => [ ],
|
||||
'tab' => 0 };
|
||||
bless($self);
|
||||
$self->set_tabs($tabs) if (defined($tabs));
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 add_tab(name, link)
|
||||
=cut
|
||||
sub add_tab
|
||||
{
|
||||
my ($self, $name, $link) = @_;
|
||||
push(@{$self->{'tabs'}}, [ $name, $link ]);
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for the top of the page
|
||||
=cut
|
||||
sub top_html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
$rv .= "<table border=0 cellpadding=0 cellspacing=0 width=100% height=20><tr>";
|
||||
$rv .= "<td valign=bottom>";
|
||||
$rv .= "<table border=0 cellpadding=0 cellspacing=0 height=20><tr>";
|
||||
my $i = 0;
|
||||
my ($high, $low) = ("#cccccc", "#9999ff");
|
||||
my ($lowlc, $lowrc) = ( "/images/lc1.gif", "/images/rc1.gif" );
|
||||
my ($highlc, $highrc) = ( "/images/lc2.gif", "/images/rc2.gif" );
|
||||
foreach my $t (@{$self->get_tabs()}) {
|
||||
if ($i == $self->get_tab()) {
|
||||
# This is the selected tab
|
||||
$rv .= "<td valign=top bgcolor=$high>".
|
||||
"<img src=$highlc alt=\"\"></td>";
|
||||
if ($self->get_link()) {
|
||||
# Link
|
||||
$rv .= "<td bgcolor=$high> ".
|
||||
"<a href=$t->[1]><b>$t->[0]</b></a> </td>";
|
||||
}
|
||||
else {
|
||||
# Don't link
|
||||
$rv .= "<td bgcolor=$high> <b>$t->[0]</b> </td>";
|
||||
}
|
||||
$rv .= "<td valign=top bgcolor=$high>".
|
||||
"<img src=$highrc alt=\"\"></td>\n";
|
||||
}
|
||||
else {
|
||||
# Not selected
|
||||
$rv .= "<td valign=top bgcolor=$low>".
|
||||
"<img src=$lowlc alt=\"\"></td>";
|
||||
$rv .= "<td bgcolor=$low> ".
|
||||
"<a href=$t->[1]><b>$t->[0]</b></a> </td>";
|
||||
$rv .= "<td valign=top bgcolor=$low>".
|
||||
"<img src=$lowrc alt=\"\"></td>\n";
|
||||
}
|
||||
$i++;
|
||||
if ($self->{'wrap'} && $i%$self->{'wrap'} == 0) {
|
||||
# New row
|
||||
$rv .= "</tr><tr>";
|
||||
}
|
||||
}
|
||||
$rv .= "</tr></table></td>\n";
|
||||
$rv .= "</tr></table>\n";
|
||||
$rv .= "<table border=1 cellpadding=10 cellspacing=0 width=100%><tr><td>\n";
|
||||
return $rv;
|
||||
}
|
||||
|
||||
=head2 bottom_html()
|
||||
Returns the HTML for the bottom of the page
|
||||
=cut
|
||||
sub bottom_html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv = "</td></tr></table>\n";
|
||||
return $rv;
|
||||
}
|
||||
|
||||
=head2 set_tab(number|link)
|
||||
Sets the tab that is currently highlighted
|
||||
=cut
|
||||
sub set_tab
|
||||
{
|
||||
my ($self, $tab) = @_;
|
||||
if ($tab =~ /^\d+$/) {
|
||||
$self->{'tab'} = $tab;
|
||||
}
|
||||
else {
|
||||
for(my $i=0; $i<@{$self->{'tabs'}}; $i++) {
|
||||
if ($self->{'tabs'}->[$i]->[1] eq $tab) {
|
||||
$self->{'tab'} = $i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub get_tab
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'tab'};
|
||||
}
|
||||
|
||||
=head2 set_link(link)
|
||||
If called with a non-zero parameter, even the highlighted tab will be a link
|
||||
=cut
|
||||
sub set_link
|
||||
{
|
||||
my ($self, $link) = @_;
|
||||
$self->{'link'} = $link;
|
||||
}
|
||||
|
||||
sub get_link
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'link'};
|
||||
}
|
||||
|
||||
sub set_tabs
|
||||
{
|
||||
my ($self, $tabs) = @_;
|
||||
$self->{'tabs'} = $tabs;
|
||||
}
|
||||
|
||||
sub get_tabs
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'tabs'};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
122
Webmin/Textarea.pm
Normal file
122
Webmin/Textarea.pm
Normal file
@@ -0,0 +1,122 @@
|
||||
package Webmin::Textarea;
|
||||
use Webmin::Input;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Input" );
|
||||
|
||||
=head2 new Webmin::Textarea(name, value, rows, cols, [wrap], [disabled])
|
||||
Create a new text box, with the given size
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Textarea::new)) {
|
||||
return new Webmin::Theme::Textarea(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $name, $value, $rows, $cols, $wrap, $disabled) = @_;
|
||||
$self = { };
|
||||
bless($self);
|
||||
$self->set_name($name);
|
||||
$self->set_value($value);
|
||||
$self->set_rows($rows);
|
||||
$self->set_cols($cols);
|
||||
$self->set_disabled($disabled);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this text area
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
return &ui_textarea($self->get_name(), $self->get_value(),
|
||||
$self->get_rows(), $self->get_cols(),
|
||||
$self->get_wrap(), $self->get_disabled());
|
||||
}
|
||||
|
||||
sub set_rows
|
||||
{
|
||||
my ($self, $rows) = @_;
|
||||
$self->{'rows'} = $rows;
|
||||
}
|
||||
|
||||
sub get_rows
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'rows'};
|
||||
}
|
||||
|
||||
sub set_cols
|
||||
{
|
||||
my ($self, $cols) = @_;
|
||||
$self->{'cols'} = $cols;
|
||||
}
|
||||
|
||||
sub get_cols
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'cols'};
|
||||
}
|
||||
|
||||
sub set_wrap
|
||||
{
|
||||
my ($self, $wrap) = @_;
|
||||
$self->{'wrap'} = $wrap;
|
||||
}
|
||||
|
||||
sub get_wrap
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'wrap'};
|
||||
}
|
||||
|
||||
sub set_validation_func
|
||||
{
|
||||
my ($self, $func) = @_;
|
||||
$self->{'validation_func'} = $func;
|
||||
}
|
||||
|
||||
=head2 set_validation_regexp(regexp, message)
|
||||
=cut
|
||||
sub set_validation_regexp
|
||||
{
|
||||
my ($self, $regexp, $message) = @_;
|
||||
$self->{'validation_regexp'} = $regexp;
|
||||
$self->{'validation_message'} = $message;
|
||||
}
|
||||
|
||||
=head2 validate()
|
||||
Returns a list of error messages for this field
|
||||
=cut
|
||||
sub validate
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $value = $self->get_value();
|
||||
if ($self->{'mandatory'} && $value eq '') {
|
||||
return ( $self->{'mandmesg'} || $text{'ui_mandatory'} );
|
||||
}
|
||||
if ($self->{'validation_func'}) {
|
||||
my $err = &{$self->{'validation_func'}}($value, $self->{'name'},
|
||||
$self->{'form'});
|
||||
return ( $err ) if ($err);
|
||||
}
|
||||
if ($self->{'validation_regexp'}) {
|
||||
if ($value !~ /$self->{'validation_regexp'}/) {
|
||||
return ( $self->{'validation_message'} );
|
||||
}
|
||||
}
|
||||
return ( );
|
||||
}
|
||||
|
||||
=head2 get_value()
|
||||
Returns the value, without any \r characters
|
||||
=cut
|
||||
sub get_value
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv = Webmin::Input::get_value($self);
|
||||
$rv =~ s/\r//g;
|
||||
return $rv;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
80
Webmin/Textbox.pm
Normal file
80
Webmin/Textbox.pm
Normal file
@@ -0,0 +1,80 @@
|
||||
package Webmin::Textbox;
|
||||
use Webmin::Input;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Input" );
|
||||
|
||||
=head2 new Webmin::Textbox(name, value, [size], [disabled])
|
||||
Create a new text input field
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Textbox::new)) {
|
||||
return new Webmin::Theme::Textbox(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $name, $value, $size, $disabled) = @_;
|
||||
$self = { 'size' => 30 };
|
||||
bless($self);
|
||||
$self->{'name'} = $name;
|
||||
$self->{'value'} = $value;
|
||||
$self->{'size'} = $size if ($size);
|
||||
$self->set_disabled($disabled) if (defined($disabled));
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this text input
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
return &ui_textbox($self->get_name(), $self->get_value(),
|
||||
$self->{'size'},
|
||||
$self->{'$disabled'});
|
||||
}
|
||||
|
||||
sub set_size
|
||||
{
|
||||
my ($self, $size) = @_;
|
||||
$self->{'size'} = $size;
|
||||
}
|
||||
|
||||
sub set_validation_func
|
||||
{
|
||||
my ($self, $func) = @_;
|
||||
$self->{'validation_func'} = $func;
|
||||
}
|
||||
|
||||
=head2 set_validation_regexp(regexp, message)
|
||||
=cut
|
||||
sub set_validation_regexp
|
||||
{
|
||||
my ($self, $regexp, $message) = @_;
|
||||
$self->{'validation_regexp'} = $regexp;
|
||||
$self->{'validation_message'} = $message;
|
||||
}
|
||||
|
||||
=head2 validate()
|
||||
Returns a list of error messages for this field
|
||||
=cut
|
||||
sub validate
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $value = $self->get_value();
|
||||
if ($self->{'mandatory'} && $value eq '') {
|
||||
return ( $self->{'mandmesg'} || $text{'ui_mandatory'} );
|
||||
}
|
||||
if ($self->{'validation_func'}) {
|
||||
my $err = &{$self->{'validation_func'}}($value, $self->{'name'},
|
||||
$self->{'form'});
|
||||
return ( $err ) if ($err);
|
||||
}
|
||||
if ($self->{'validation_regexp'}) {
|
||||
if ($value !~ /$self->{'validation_regexp'}/) {
|
||||
return ( $self->{'validation_message'} );
|
||||
}
|
||||
}
|
||||
return ( );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
168
Webmin/Time.pm
Normal file
168
Webmin/Time.pm
Normal file
@@ -0,0 +1,168 @@
|
||||
package Webmin::Time;
|
||||
use Webmin::Input;
|
||||
use Time::Local;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Input" );
|
||||
|
||||
=head2 new Webmin::Time(name, time, [disabled])
|
||||
Create a new field for selecting a time
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Time::new)) {
|
||||
return new Webmin::Theme::Time(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $name, $value, $disabled) = @_;
|
||||
bless($self = { });
|
||||
$self->set_name($name);
|
||||
$self->set_value($value);
|
||||
$self->set_disabled($disabled) if (defined($disabled));
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for the time chooser
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
my $val = $self->get_value();
|
||||
my $hour = ($val/3600) % 24;
|
||||
my $min = ($val/60) % 60;
|
||||
my $sec = ($val/1) % 60;
|
||||
my $name = $self->get_name();
|
||||
$rv .= &ui_textbox("hour_".$name, pad2($hour), 2,$self->get_disabled()).":".
|
||||
&ui_textbox("min_".$name, pad2($min), 2, $self->get_disabled()).":".
|
||||
&ui_textbox("sec_".$name, pad2($sec), 2, $self->get_disabled());
|
||||
return $rv;
|
||||
}
|
||||
|
||||
sub pad2
|
||||
{
|
||||
return $_[0] < 10 ? "0".$_[0] : $_[0];
|
||||
}
|
||||
|
||||
sub set_value
|
||||
{
|
||||
my ($self, $value) = @_;
|
||||
$self->{'value'} = timegm(localtime($value));
|
||||
}
|
||||
|
||||
=head2 get_value()
|
||||
Returns the date as a Unix time number (for 1st jan 1970)
|
||||
=cut
|
||||
sub get_value
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $in = $self->{'form'} ? $self->{'form'}->{'in'} : undef;
|
||||
if ($in && defined($in->{"hour_".$self->{'name'}})) {
|
||||
my $rv = $self->to_time($in);
|
||||
return defined($rv) ? $rv : $self->{'value'};
|
||||
}
|
||||
elsif ($in && defined($in->{"ui_value_".$self->{'name'}})) {
|
||||
return $in->{"ui_value_".$self->{'name'}};
|
||||
}
|
||||
else {
|
||||
return $self->{'value'};
|
||||
}
|
||||
}
|
||||
|
||||
sub to_time
|
||||
{
|
||||
my ($self, $in) = @_;
|
||||
my $hour = $in->{"hour_".$self->{'name'}};
|
||||
return undef if ($hour !~ /^\d+$/ || $hour < 0 || $hour > 23);
|
||||
my $min = $in->{"min_".$self->{'name'}};
|
||||
return undef if ($min !~ /^\d+$/ || $min < 0 || $min > 59);
|
||||
my $sec = $in->{"sec_".$self->{'name'}};
|
||||
return undef if ($sec !~ /^\d+$/ || $sec < 0 || $sec > 59);
|
||||
return $hour*60*60 + $min*60 + $sec;
|
||||
}
|
||||
|
||||
sub set_validation_func
|
||||
{
|
||||
my ($self, $func) = @_;
|
||||
$self->{'validation_func'} = $func;
|
||||
}
|
||||
|
||||
=head2 validate()
|
||||
Ensures that the date is valid
|
||||
=cut
|
||||
sub validate
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $tm = $self->to_time($self->{'form'}->{'in'});
|
||||
if (!defined($tm)) {
|
||||
return ( $text{'ui_etime'} );
|
||||
}
|
||||
if ($self->{'validation_func'}) {
|
||||
my $err = &{$self->{'validation_func'}}($self->get_value(),
|
||||
$self->{'name'},
|
||||
$self->{'form'});
|
||||
return ( $err ) if ($err);
|
||||
}
|
||||
return ( );
|
||||
}
|
||||
|
||||
=head2 set_auto(auto?)
|
||||
If set to 1, the time will be automatically incremented by Javascript
|
||||
=cut
|
||||
sub set_auto
|
||||
{
|
||||
my ($self, $auto) = @_;
|
||||
$self->{'auto'} = $auto;
|
||||
if ($auto) {
|
||||
# XXX incorrect!!
|
||||
my $formno = $self->{'form'}->get_formno();
|
||||
$self->{'form'}->add_onload("F=[0]; timeInit(F); setTimeout(\"timeUpdate(F)\", 5000)");
|
||||
my $as = $autoscript;
|
||||
$as =~ s/NAME/$self->{'name'}/g;
|
||||
$self->{'form'}->add_script($as);
|
||||
}
|
||||
}
|
||||
|
||||
$autoscript = <<EOF;
|
||||
function timeInit(F) {
|
||||
secs = new Array();
|
||||
mins = new Array();
|
||||
hours = new Array();
|
||||
for(i=0; i<F.length; i++){
|
||||
secs[i] = document.forms[F[i]].sec_NAME;
|
||||
mins[i] = document.forms[F[i]].min_NAME;
|
||||
hours[i] = document.forms[F[i]].hour_NAME;
|
||||
}
|
||||
}
|
||||
function timeUpdate(F) {
|
||||
for(i=0; i<F.length; i++){
|
||||
s = parseInt(secs[i].value);
|
||||
s = s ? s : 0;
|
||||
s = s+5;
|
||||
if( s>59 ){
|
||||
s -= 60;
|
||||
m = parseInt(mins[i].value);
|
||||
m= m ? m : 0;
|
||||
m+=1;
|
||||
if( m>59 ){
|
||||
m -= 60;
|
||||
h = parseInt(hours[i].value);
|
||||
h = h ? h : 0;
|
||||
h+=1;
|
||||
if( h>23 ){
|
||||
h -= 24;
|
||||
}
|
||||
hours[i].value = packNum(h);
|
||||
}
|
||||
mins[i].value = packNum(m);
|
||||
}
|
||||
secs[i].value = packNum(s);
|
||||
}
|
||||
setTimeout('timeUpdate(F)', 5000);
|
||||
}
|
||||
function packNum(t) {
|
||||
return (t < 10 ? '0'+t : t);
|
||||
}
|
||||
EOF
|
||||
|
||||
1;
|
||||
|
||||
101
Webmin/TitleList.pm
Normal file
101
Webmin/TitleList.pm
Normal file
@@ -0,0 +1,101 @@
|
||||
package Webmin::TitleList;
|
||||
use WebminCore;
|
||||
|
||||
=head2 new Webmin::TitleList(title, &links, [alt-text])
|
||||
Generates a title with a list of links under it
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
my ($self, $title, $links, $alt) = @_;
|
||||
if (defined(&Webmin::Theme::TitleList::new)) {
|
||||
return new Webmin::Theme::TitleList(@_[1..$#_]);
|
||||
}
|
||||
$self = { };
|
||||
bless($self);
|
||||
$self->set_title($title);
|
||||
$self->set_links($links);
|
||||
$self->set_alt($alt) if (defined($alt));
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the list
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv;
|
||||
if (defined(&ui_subheading)) {
|
||||
$rv .= &ui_subheading($self->get_title());
|
||||
}
|
||||
else {
|
||||
$rv .= "<h3>".$self->get_title()."</h3>\n";
|
||||
}
|
||||
$rv .= "<hr>\n";
|
||||
foreach my $l (@{$self->get_links()}) {
|
||||
if ($l->[1]) {
|
||||
$rv .= "<a href='$l->[1]'>$l->[0]</a><br>\n";
|
||||
}
|
||||
else {
|
||||
$rv .= $l->[0]."<br>\n";
|
||||
}
|
||||
}
|
||||
return $rv;
|
||||
}
|
||||
|
||||
sub set_title
|
||||
{
|
||||
my ($self, $title) = @_;
|
||||
$self->{'title'} = $title;
|
||||
}
|
||||
|
||||
sub get_title
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'title'};
|
||||
}
|
||||
|
||||
sub set_links
|
||||
{
|
||||
my ($self, $links) = @_;
|
||||
$self->{'links'} = $links;
|
||||
}
|
||||
|
||||
sub get_links
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'links'};
|
||||
}
|
||||
|
||||
sub set_alt
|
||||
{
|
||||
my ($self, $alt) = @_;
|
||||
$self->{'alt'} = $alt;
|
||||
}
|
||||
|
||||
sub get_alt
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'alt'};
|
||||
}
|
||||
|
||||
=head2 add_link(name, link)
|
||||
Adds a link to be displayed in the list
|
||||
=cut
|
||||
sub add_link
|
||||
{
|
||||
my ($self, $name, $link) = @_;
|
||||
push(@{$self->{'links'}}, [ $name, $link ]);
|
||||
}
|
||||
|
||||
=head2 set_page(Webmin::Page)
|
||||
Called when this menu is added to a page
|
||||
=cut
|
||||
sub set_page
|
||||
{
|
||||
my ($self, $page) = @_;
|
||||
$self->{'page'} = $page;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
77
Webmin/Upload.pm
Normal file
77
Webmin/Upload.pm
Normal file
@@ -0,0 +1,77 @@
|
||||
package Webmin::Upload;
|
||||
use Webmin::Input;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Input" );
|
||||
|
||||
=head2 new Webmin::Upload(name, [size])
|
||||
Create a new file upload field
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::Upload::new)) {
|
||||
return new Webmin::Theme::Upload(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $name, $size) = @_;
|
||||
$self = { 'size' => 30 };
|
||||
bless($self);
|
||||
$self->{'name'} = $name;
|
||||
$self->{'size'} = $size if ($size);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this text input
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
return &ui_upload($self->get_name(), $self->{'size'},
|
||||
$self->{'$disabled'});
|
||||
}
|
||||
|
||||
sub set_size
|
||||
{
|
||||
my ($self, $size) = @_;
|
||||
$self->{'size'} = $size;
|
||||
}
|
||||
|
||||
sub set_validation_func
|
||||
{
|
||||
my ($self, $func) = @_;
|
||||
$self->{'validation_func'} = $func;
|
||||
}
|
||||
|
||||
=head2 set_validation_regexp(regexp, message)
|
||||
=cut
|
||||
sub set_validation_regexp
|
||||
{
|
||||
my ($self, $regexp, $message) = @_;
|
||||
$self->{'validation_regexp'} = $regexp;
|
||||
$self->{'validation_message'} = $message;
|
||||
}
|
||||
|
||||
=head2 validate()
|
||||
Returns a list of error messages for this field
|
||||
=cut
|
||||
sub validate
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $value = $self->get_value();
|
||||
if ($self->{'mandatory'} && $value eq '') {
|
||||
return ( $self->{'mandmesg'} || $text{'ui_mandatory'} );
|
||||
}
|
||||
if ($self->{'validation_func'}) {
|
||||
my $err = &{$self->{'validation_func'}}($value, $self->{'name'},
|
||||
$self->{'in'});
|
||||
return ( $err ) if ($err);
|
||||
}
|
||||
if ($self->{'validation_regexp'}) {
|
||||
if ($value !~ /$self->{'validation_regexp'}/) {
|
||||
return ( $self->{'validation_message'} );
|
||||
}
|
||||
}
|
||||
return ( );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
57
Webmin/User.pm
Normal file
57
Webmin/User.pm
Normal file
@@ -0,0 +1,57 @@
|
||||
package Webmin::User;
|
||||
use Webmin::Textbox;
|
||||
use WebminCore;
|
||||
@ISA = ( "Webmin::Textbox" );
|
||||
|
||||
=head2 new Webmin::User(name, value, [multiple], [disabled])
|
||||
A text box for entering or selecting one or many Unix usernames
|
||||
=cut
|
||||
sub new
|
||||
{
|
||||
if (defined(&Webmin::Theme::User::new)) {
|
||||
return new Webmin::Theme::User(@_[1..$#_]);
|
||||
}
|
||||
my ($self, $name, $value, $multiple, $disabled) = @_;
|
||||
$self = new Webmin::Textbox($name, $value, $multiple ? 40 : 15, $disabled);
|
||||
bless($self);
|
||||
$self->set_multiple($multiple);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head2 html()
|
||||
Returns the HTML for this user input
|
||||
=cut
|
||||
sub html
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $rv = Webmin::Textbox::html($self);
|
||||
my $name = $self->get_name();
|
||||
my $multiple = $self->get_multiple();
|
||||
local $w = $multiple ? 500 : 300;
|
||||
$rv .= " <input type=button name=${name}_button onClick='ifield = form.$name; chooser = window.open(\"$gconfig{'webprefix'}/user_chooser.cgi?multi=$multiple&user=\"+escape(ifield.value), \"chooser\", \"toolbar=no,menubar=no,scrollbars=yes,width=$w,height=200\"); chooser.ifield = ifield; window.ifield = ifield' value=\"...\">\n";
|
||||
return $rv;
|
||||
}
|
||||
|
||||
sub set_multiple
|
||||
{
|
||||
my ($self, $multiple) = @_;
|
||||
$self->{'multiple'} = $multiple;
|
||||
}
|
||||
|
||||
sub get_multiple
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'multiple'};
|
||||
}
|
||||
|
||||
=head2 get_input_names()
|
||||
Returns the actual names of all HTML elements that make up this input
|
||||
=cut
|
||||
sub get_input_names
|
||||
{
|
||||
my ($self) = @_;
|
||||
return ( $self->{'name'}, $self->{'name'}."_button" );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
Reference in New Issue
Block a user