/
usr
/
share
/
usermin
/
gray-theme
/
/usr/share/usermin/gray-theme
mkdir
upload
Name
Size
Mode
Actions
acl/
-
0755
rm
adsl-client/
-
0755
rm
apache/
-
0755
rm
at/
-
0755
rm
backup-config/
-
0755
rm
bandwidth/
-
0755
rm
bind8/
-
0755
rm
bsdfdisk/
-
0755
rm
burner/
-
0755
rm
cfengine/
-
0755
rm
change-user/
-
0755
rm
cluster-copy/
-
0755
rm
cluster-cron/
-
0755
rm
cluster-passwd/
-
0755
rm
cluster-shell/
-
0755
rm
cluster-software/
-
0755
rm
cluster-useradmin/
-
0755
rm
cluster-webmin/
-
0755
rm
cpan/
-
0755
rm
cron/
-
0755
rm
custom/
-
0755
rm
dhcpd/
-
0755
rm
dhcpd-2.0/
-
0755
rm
dnsadmin/
-
0755
rm
dovecot/
-
0755
rm
download/
-
0755
rm
escputil/
-
0755
rm
exports/
-
0755
rm
fdisk/
-
0755
rm
fetchmail/
-
0755
rm
file/
-
0755
rm
firewall/
-
0755
rm
frox/
-
0755
rm
fsdump/
-
0755
rm
generate-acls/
-
0755
rm
gnupg/
-
0755
rm
grub/
-
0755
rm
heartbeat/
-
0755
rm
help/
-
0755
rm
htaccess-htpasswd/
-
0755
rm
htpasswd-file/
-
0755
rm
idmapd/
-
0755
rm
images/
-
0755
rm
inetd/
-
0755
rm
init/
-
0755
rm
inittab/
-
0755
rm
ipchains/
-
0755
rm
ipsec/
-
0755
rm
iptables/
-
0755
rm
iscsi-client/
-
0755
rm
iscsi-server/
-
0755
rm
iscsi-target/
-
0755
rm
jabber/
-
0755
rm
jsample/
-
0755
rm
krb5/
-
0755
rm
lang/
-
0755
rm
ldap-useradmin/
-
0755
rm
lilo/
-
0755
rm
logrotate/
-
0755
rm
lpadmin/
-
0755
rm
lvm/
-
0755
rm
lvs/
-
0755
rm
mailbox/
-
0755
rm
mailboxes/
-
0755
rm
majordomo/
-
0755
rm
man/
-
0755
rm
mon/
-
0755
rm
mount/
-
0755
rm
mysql/
-
0755
rm
net/
-
0755
rm
nettools/
-
0755
rm
nis/
-
0755
rm
openslp/
-
0755
rm
pam/
-
0755
rm
pap/
-
0755
rm
passwd/
-
0755
rm
phpini/
-
0755
rm
postfix/
-
0755
rm
postgresql/
-
0755
rm
ppp-client/
-
0755
rm
pptp-client/
-
0755
rm
pptp-server/
-
0755
rm
proc/
-
0755
rm
procmail/
-
0755
rm
procyonguide/
-
0755
rm
proftpd/
-
0755
rm
pserver/
-
0755
rm
qmailadmin/
-
0755
rm
quota/
-
0755
rm
raid/
-
0755
rm
samba/
-
0755
rm
sarg/
-
0755
rm
sargreports/
-
0755
rm
sendmail/
-
0755
rm
sentry/
-
0755
rm
servers/
-
0755
rm
shell/
-
0755
rm
shorewall/
-
0755
rm
simple-firewall/
-
0755
rm
smart-status/
-
0755
rm
software/
-
0755
rm
spam/
-
0755
rm
squid/
-
0755
rm
squidguard/
-
0755
rm
squidinfo/
-
0755
rm
squidreports/
-
0755
rm
squidstat/
-
0755
rm
ssh/
-
0755
rm
sshd/
-
0755
rm
status/
-
0755
rm
stunnel/
-
0755
rm
swell-wizard/
-
0755
rm
sysgraph/
-
0755
rm
sysinfo/
-
0755
rm
syslog/
-
0755
rm
sysstats/
-
0755
rm
telnet/
-
0755
rm
template/
-
0755
rm
time/
-
0755
rm
tsunamiguide/
-
0755
rm
tunnel/
-
0755
rm
unauthenticated/
-
0755
rm
updown/
-
0755
rm
useradmin/
-
0755
rm
usermin/
-
0755
rm
vgetty/
-
0755
rm
webalizer/
-
0755
rm
webfetch/
-
0755
rm
webmin/
-
0755
rm
webmin-iptables/
-
0755
rm
webminguide/
-
0755
rm
webminlog/
-
0755
rm
wpad-wizard/
-
0755
rm
wuftpd/
-
0755
rm
xinetd/
-
0755
rm
zones/
-
0755
rm
config
337
0644
edit
dl
rm
config.cgi
3737
0755
edit
dl
rm
config_save.cgi
1754
0755
edit
dl
rm
edit_overlay.cgi
783
0755
edit
dl
rm
edit_right.cgi
3865
0755
edit
dl
rm
favicon.ico
1150
0644
edit
dl
rm
gray-theme-lib.pl
4741
0755
edit
dl
rm
index.cgi
4328
0755
edit
dl
rm
left.cgi
10357
0755
edit
dl
rm
pngfix.html
95
0644
edit
dl
rm
pngfix.js
1235
0644
edit
dl
rm
recollect.cgi
277
0755
edit
dl
rm
right.cgi
56019
0755
edit
dl
rm
save_overlay.cgi
902
0755
edit
dl
rm
save_right.cgi
1590
0755
edit
dl
rm
theme.info
151
0644
edit
dl
rm
theme.pl
35733
0755
edit
dl
rm
top.cgi
346
0755
edit
dl
rm
uconfig.cgi
3049
0755
edit
dl
rm
uconfig_save.cgi
1422
0755
edit
dl
rm
Edit:
/usr/share/usermin/gray-theme/theme.pl
(35733B)
# Virtualmin Framed Theme # Icons copyright David Vignoni, all other theme elements copyright 2005-2007 # Virtualmin, Inc. $main::cloudmin_no_create_links = 1; $main::cloudmin_no_edit_buttons = 1; $main::cloudmin_no_global_links = 1; $main::mailbox_no_addressbook_button = 1; $main::mailbox_no_folder_button = 1; $main::basic_virtualmin_menu = 1; $main::basic_virtualmin_domain = 1; $main::nocreate_virtualmin_menu = 1; $main::nosingledomain_virtualmin_mode = 1; our $ui_formcount; # Global state for wrapper # if 0, wrapper isn't on, add one and open it, if 1 close it, if 2+, subtract # but don't close $main::WRAPPER_OPEN = 0; $main::COLUMNS_WRAPPER_OPEN = 0; sub theme_ui_print_header { my ($text, @args) = @_; &header(@args); print <<EOL; <script> (function () { const body = document.querySelector('body'); try { body && body.classList.add('$module_name'); } catch (e) {} })(); </script> EOL print &ui_post_header($text); } # theme_ui_post_header([subtext]) # Returns HTML to appear directly after a standard header() call sub theme_ui_post_header { my ($text) = @_; my $rv; $rv .= "<div class='ui_post_header'>$text</div>\n" if (defined($text)); $rv .= "<p></p>" if (!defined($text)); return $rv; } # theme_ui_pre_footer() # Returns HTML to appear directly before a standard footer() call sub theme_ui_pre_footer { my $rv; $rv .= "<p></p>\n"; return $rv; } # ui_print_footer(args...) # Print HTML for a footer with the pre-footer line. Args are the same as those # passed to footer() sub theme_ui_print_footer { local @args = @_; print &ui_pre_footer(); if ($ui_formcount) { print <<EOL; <script> (function(){ var forms = document.forms || []; for(var i = 0; i < forms.length; i++){ for(var j = 0; j < forms[i].length; j++){ if(!forms[i][j].readonly != undefined && forms[i][j].type != "hidden" && forms[i][j].disabled != true && forms[i][j].style.display != 'none'){ forms[i][j].focus(); return; } } } })(); </script> EOL } &footer(@args); } sub theme_icons_table { my ($i, $need_tr); my $cols = $_[3] ? $_[3] : 4; my $per = int(100.0 / $cols); print "<div class='wrapper'>\n"; print "<table id='main' width=100% cellpadding=5 class='icons_table'>\n"; for($i=0; $i<@{$_[0]}; $i++) { if ($i%$cols == 0) { print "<tr>\n"; } print "<td width=$per% align=center valign=top>\n"; &generate_icon($_[2]->[$i], $_[1]->[$i], $_[0]->[$i], $_[4], $_[5], $_[6], $_[7]->[$i], $_[8]->[$i]); print "</td>\n"; if ($i%$cols == $cols-1) { print "</tr>\n"; } } while($i++%$cols) { print "<td width=$per%></td>\n"; $need_tr++; } print "</tr>\n" if ($need_tr); print "</table>\n"; print "</div>\n"; } sub theme_generate_icon { my $w = !defined($_[4]) ? "width=48" : $_[4] ? "width=$_[4]" : ""; my $h = !defined($_[5]) ? "height=48" : $_[5] ? "height=$_[5]" : ""; if ($tconfig{'noicons'}) { if ($_[2]) { print "$_[6]<a href=\"$_[2]\" $_[3]>$_[1]</a>$_[7]\n"; } else { print "$_[6]$_[1]$_[7]\n"; } } elsif ($_[2]) { print "<table><tr><td width=48 height=48>\n", "<a href=\"$_[2]\" $_[3]><img src=\"$_[0]\" alt=\"\" border=0 ", "$w $h></a></td></tr></table>\n"; print "$_[6]<a href=\"$_[2]\" $_[3]>$_[1]</a>$_[7]\n"; } else { print "<table><tr><td width=48 height=48>\n", "<img src=\"$_[0]\" alt=\"\" border=0 $w $h>", "</td></tr></table>\n$_[6]$_[1]$_[7]\n"; } } # theme_post_save_domain(&domain, action) # Called by Virtualmin after a domain is updated, to refresh the left menu sub theme_post_save_domain { local ($d, $action) = @_; # Refresh left side, in case options have changed print "<script>\n"; if ($action eq 'create') { # Select the new domain print "top.left.location = '@{[&get_webprefix()]}/left.cgi?mode=virtual-server&dom=$d->{'id'}';\n"; } else { # Just refresh left print "top.left.location = top.left.location;\n"; } print "</script>\n"; } # theme_post_save_domains([domain, action]+) # Called after multiple domains are updated, to refresh the left menu sub theme_post_save_domains { print "<script>\n"; print "top.left.location = top.left.location;\n"; print "</script>\n"; } # theme_post_save_server(&server, action) # Called by Cloudmin after a server is updated, to refresh the left menu sub theme_post_save_server { local ($s, $action) = @_; if ($action eq 'create' || $action eq 'delete' || !$done_theme_post_save_server++) { print "<script>\n"; print "top.left.location = top.left.location;\n"; print "</script>\n"; } } # theme_select_server(&server) # Called by Cloudmin when a page for a server is displayed, to select it on the # left menu. sub theme_select_server { local ($server) = @_; print <<EOF; <script> if (window.parent && window.parent.frames[0]) { var leftdoc = window.parent.frames[0].document; var leftform = leftdoc.forms[0]; if (leftform) { var serversel = leftform['sid']; if (serversel && serversel.value != '$server->{'id'}' || !serversel) { //if (serversel) { // // Need to change value of selector // serversel.value = '$server->{'id'}'; // } window.parent.frames[0].location = '@{[&get_webprefix()]}/left.cgi?mode=server-manager&sid=$server->{'id'}'; } } } </script> EOF } # theme_select_domain(&domain) # Called by Virtualmin when a page for a server is displayed, to select it on # the left menu. sub theme_select_domain { local ($d) = @_; print <<EOF; <script> if (window.parent && window.parent.frames[0]) { var leftdoc = window.parent.frames[0].document; var leftform = leftdoc.forms[0]; if (leftform) { var domsel = leftform['dom']; if (domsel && domsel.value != '$d->{'id'}') { // Need to change value // domsel.value = '$d->{'id'}'; window.parent.frames[0].location = '@{[&get_webprefix()]}/left.cgi?mode=virtual-server&dom=$d->{'id'}'; } } } </script> EOF } # theme_post_save_folder(&folder, action) # Called after some folder is changed, to refresh the left frame. The action # may be 'create', 'delete', 'modify' or 'read' sub theme_post_save_folder { local ($folder, $action) = @_; my $ref; if ($action eq 'create' || $action eq 'delete' || $action eq 'modify') { # Always refresh $ref = 1; } else { # Only refresh if showing unread count if (defined(&mailbox::should_show_unread) && &mailbox::should_show_unread($folder)) { $ref = 1; } } if ($ref) { print "<script>\n"; print "top.frames[0].document.location = top.frames[0].document.location;\n"; print "</script>\n"; } } sub theme_post_change_modules { print <<EOF; <script> var url = '' + top.left.location; if (url.indexOf('mode=modules') > 0) { top.left.location = url; } </script> EOF } sub theme_prebody { if ($script_name =~ /session_login.cgi/) { # Generate CSS link print "<link rel='stylesheet' type='text/css' href='@{[&get_webprefix()]}/unauthenticated/reset-fonts-grids-base.css'>\n"; print "<link rel='stylesheet' type='text/css' href='@{[&get_webprefix()]}/unauthenticated/gray-theme.css'>\n"; print "<!--[if IE]>\n"; print "<style type=\"text/css\">\n"; print "table.formsection, table.ui_table, table.loginform { border-collapse: collapse; }\n"; print "</style>\n"; print "<![endif]-->\n"; } if (get_module_name() eq "virtual-server") { # No need for Module Index link, as we have the left-side frame $tconfig{'nomoduleindex'} = 1; } } sub theme_prehead { print "<link rel='stylesheet' type='text/css' href='@{[&get_webprefix()]}/unauthenticated/reset-fonts-grids-base.css'>\n"; print "<link rel='stylesheet' type='text/css' href='@{[&get_webprefix()]}/unauthenticated/gray-theme.css' />\n"; print "<!--[if IE]>\n"; print "<style type=\"text/css\">\n"; print "table.formsection, table.ui_table, table.loginform { border-collapse: collapse; }\n"; print "</style>\n"; print "<![endif]-->\n"; print "<script>\n"; print "var rowsel = new Array();\n"; print "</script>\n"; print "<script type='text/javascript' src='@{[&get_webprefix()]}/unauthenticated/sorttable.js'></script>\n"; } sub theme_popup_prehead { return &theme_prehead(); } # ui_table_start(heading, [tabletags], [cols], [&default-tds], [right-heading]) # A table with a heading and table inside sub theme_ui_table_start { my ($heading, $tabletags, $cols, $tds, $rightheading) = @_; if (! $tabletags =~ /width/) { $tabletages .= " width=100%"; } if (defined($main::ui_table_cols)) { # Push on stack, for nested call push(@main::ui_table_cols_stack, $main::ui_table_cols); push(@main::ui_table_pos_stack, $main::ui_table_pos); push(@main::ui_table_default_tds_stack, $main::ui_table_default_tds); } my $rv; my $colspan = 1; if (!$main::WRAPPER_OPEN) { $rv .= "<table class='shrinkwrapper' $tabletags>\n"; $rv .= "<tr><td>\n"; } $main::WRAPPER_OPEN++; $rv .= "<table class='ui_table' $tabletags>\n"; if (defined($heading) || defined($rightheading)) { $rv .= "<thead><tr>"; if (defined($heading)) { $rv .= "<td><b>$heading</b></td>" } if (defined($rightheading)) { $rv .= "<td align=right>$rightheading</td>"; $colspan++; } $rv .= "</tr></thead>\n"; } $rv .= "<tbody> <tr class='ui_table_body'> <td colspan=$colspan>". "<table width=100%>\n"; $main::ui_table_cols = $cols || 4; $main::ui_table_pos = 0; $main::ui_table_default_tds = $tds; return $rv; } # ui_table_row(label, value, [cols], [&td-tags]) # Returns HTML for a row in a table started by ui_table_start, with a 1-column # label and 1+ column value. sub theme_ui_table_row { my ($label, $value, $cols, $tds, $trs) = @_; $cols ||= 1; $tds ||= $main::ui_table_default_tds; my $rv; if ($main::ui_table_pos+$cols+1 > $main::ui_table_cols && $main::ui_table_pos != 0) { # If the requested number of cols won't fit in the number # remaining, start a new row my $leftover = $main::ui_table_cols - $main::ui_table_pos; $rv .= "<td colspan=$leftover></td>\n"; $rv .= "</tr>\n"; $main::ui_table_pos = 0; } if (defined($label) && ($value =~ /id="([^"]+)"/ || $value =~ /id='([^']+)'/ || $value =~ /id=([^>\s]+)/)) { # Value contains an input with an ID my $id = $1; $label = "<label for=\""."e_escape($id)."\">$label</label>"; } my $trtags_attrs = ref($trs) eq 'ARRAY' && $trs->[0] ? " $trs->[0]" : ""; my $trtags_class = ref($trs) eq 'ARRAY' && $trs->[1] ? " $trs->[1]" : ""; $rv .= "<tr class='ui_form_pair$trtags_class'$trtags_attrs>\n" if ($main::ui_table_pos%$main::ui_table_cols == 0); $rv .= "<td class='ui_form_label' $tds->[0]><b>$label</b></td>\n" if (defined($label)); $rv .= "<td class='ui_form_value' colspan=$cols $tds->[1]>$value</td>\n"; $main::ui_table_pos += $cols+(defined($label) ? 1 : 0); if ($main::ui_table_pos%$main::ui_table_cols == 0) { $rv .= "</tr>\n"; $main::ui_table_pos = 0; } return $rv; } sub theme_ui_table_hr { my $rv; if ($main::ui_table_pos) { $rv .= "</tr>\n"; $main::ui_table_pos = 0; } $rv .= "<tr class='ui_form_pair'>\n"; $rv .= "<td class='ui_form_label' colspan=$main::ui_table_cols><hr></td>\n"; $rv .= "</tr>\n"; return $rv; } # ui_table_end() # The end of a table started by ui_table_start sub theme_ui_table_end { my $rv; if ($main::ui_table_cols == 4 && $main::ui_table_pos) { # Add an empty block to balance the table $rv .= &ui_table_row(" ", " "); } if (@main::ui_table_cols_stack) { $main::ui_table_cols = pop(@main::ui_table_cols_stack); $main::ui_table_pos = pop(@main::ui_table_pos_stack); $main::ui_table_default_tds = pop(@main::ui_table_default_tds_stack); } else { $main::ui_table_cols = undef; $main::ui_table_pos = undef; $main::ui_table_default_tds = undef; } $rv .= "</tbody></table></td></tr></table>\n"; if ($main::WRAPPER_OPEN==1) { #$rv .= "</div>\n"; $rv .= "</td></tr>\n"; $rv .= "</table>\n"; } $main::WRAPPER_OPEN--; return $rv; } # theme_ui_tabs_start(&tabs, name, selected, show-border) # Render a row of tabs from which one can be selected. Each tab is an array # ref containing a name, title and link. sub theme_ui_tabs_start { my ($tabs, $name, $sel, $border) = @_; my $rv; if (!$main::ui_hidden_start_donejs++) { $rv .= &ui_hidden_javascript(); } # Build list of tab titles and names my $tabnames = &convert_to_json([map { $_->[0] } @$tabs]); my $tabtitles = &convert_to_json([map { $_->[1] } @$tabs]); $rv .= "<script>\n"; $rv .= "document.${name}_tabnames = $tabnames;\n"; $rv .= "document.${name}_tabtitles = $tabtitles;\n"; $rv .= "</script>\n"; # Output the tabs my $imgdir = "@{[&get_webprefix()]}/images"; $rv .= &ui_hidden($name, $sel)."\n"; $rv .= "<table border=0 cellpadding=0 cellspacing=0 class='ui_tabs'>\n"; $rv .= "<tr><td bgcolor=#ffffff colspan=".(scalar(@$tabs)*2+1).">"; if ($ENV{'HTTP_USER_AGENT'} !~ /msie/i) { # For some reason, the 1-pixel space above the tabs appears huge on IE! $rv .= "<img src=$imgdir/1x1.gif>"; } $rv .= "</td></tr>\n"; $rv .= "<tr>\n"; $rv .= "<td bgcolor=#ffffff width=1><img src=$imgdir/1x1.gif></td>\n"; foreach my $t (@$tabs) { if ($t ne $tabs[0]) { # Spacer $rv .= "<td width=2 bgcolor=#ffffff class='ui_tab_spacer'>". "<img src=$imgdir/1x1.gif></td>\n"; } my $tabid = "tab_".$t->[0]; $rv .= "<td id=${tabid} class='ui_tab'>"; $rv .= "<table cellpadding=0 cellspacing=0 border=0><tr>"; if ($t->[0] eq $sel) { # Selected tab $rv .= "<td valign=top class='tabSelected'>". "<img src=$imgdir/lc2.gif alt=\"\"></td>"; $rv .= "<td class='tabSelected' nowrap>". " <b>$t->[1]</b> </td>"; $rv .= "<td valign=top class='tabSelected'>". "<img src=$imgdir/rc2.gif alt=\"\"></td>"; } else { # Other tab (which has a link) $rv .= "<td valign=top class='tabUnselected'>". "<img src=$imgdir/lc1.gif alt=\"\"></td>"; $rv .= "<td class='tabUnselected' nowrap>". " <a href='$t->[2]' ". "onClick='return select_tab(\"$name\", \"$t->[0]\")'>". "$t->[1]</a> </td>"; $rv .= "<td valign=top class='tabUnselected'>". "<img src=$imgdir/rc1.gif ". "alt=\"\"></td>"; $rv .= "</td>\n"; } $rv .= "</tr></table>"; $rv .= "</td>\n"; } $rv .= "<td bgcolor=#ffffff width=1><img src=$imgdir/1x1.gif></td>\n"; $rv .= "</table>\n"; if ($border) { # All tabs are within a grey box $rv .= "<table width=100% cellpadding=0 cellspacing=0 ". "class='ui_tabs_box'>\n"; $rv .= "<tr> <td bgcolor=#ffffff rowspan=3 width=1><img src=$imgdir/1x1.gif></td>\n"; $rv .= "<td $cb colspan=3 height=2><img src=$imgdir/1x1.gif></td> </tr>\n"; $rv .= "<tr> <td $cb width=2><img src=$imgdir/1x1.gif></td>\n"; $rv .= "<td valign=top>"; } $main::ui_tabs_selected = $sel; return $rv; } # theme_ui_columns_start(&headings, [width-percent], [noborder], [&tdtags], [title]) # Returns HTML for a multi-column table, with the given headings sub theme_ui_columns_start { my ($heads, $width, $noborder, $tdtags, $title) = @_; my ($href) = grep { $_ =~ /<a\s+href/i } @$heads; my $rv; $theme_ui_columns_row_toggle = 0; if (!$noborder && !$main::COLUMNS_WRAPPER_OPEN) { $rv .= "<table class='wrapper' width=" . ($width ? $width : "100") . "%>\n"; $rv .= "<tr><td>\n"; } if (!$noborder) { $main::COLUMNS_WRAPPER_OPEN++; } my @classes; push(@classes, "ui_table") if (!$noborder); push(@classes, "sortable") if (!$href); push(@classes, "ui_columns"); $rv .= "<table".(@classes ? " class='".join(" ", @classes)."'" : ""). (defined($width) ? " width=$width%" : "").">\n"; if ($title) { $rv .= "<thead> <tr $tb class='ui_columns_heading'>". "<td colspan=".scalar(@$heads)."><b>$title</b></td>". "</tr> </thead> <tbody>\n"; } $rv .= "<thead> <tr $tb class='ui_columns_heads'>\n"; my $i; for($i=0; $i<@$heads; $i++) { $rv .= "<td ".$tdtags->[$i]."><b>". ($heads->[$i] eq "" ? "<br>" : $heads->[$i])."</b></td>\n"; } $rv .= "</tr></thead> <tbody>\n"; $theme_ui_columns_count++; return $rv; } # theme_ui_columns_row(&columns, &tdtags) # Returns HTML for a row in a multi-column table sub theme_ui_columns_row { $theme_ui_columns_row_toggle = $theme_ui_columns_row_toggle ? '0' : '1'; local ($cols, $tdtags) = @_; my $rv; $rv .= "<tr class='ui_columns_row row$theme_ui_columns_row_toggle' onMouseOver=\"this.className='mainhigh'\" onMouseOut=\"this.className='mainbody row$theme_ui_columns_row_toggle'\">\n"; my $i; for($i=0; $i<@$cols; $i++) { $rv .= "<td ".$tdtags->[$i].">". ($cols->[$i] !~ /\S/ ? "<br>" : $cols->[$i])."</td>\n"; } $rv .= "</tr>\n"; return $rv; } # theme_ui_columns_end() # Returns HTML to end a table started by ui_columns_start sub theme_ui_columns_end { my $rv; $rv = "</tbody> </table>\n"; if ($main::COLUMNS_WRAPPER_OPEN == 1) { # Last wrapper $rv .= "</td> </tr> </table>\n"; } $main::COLUMNS_WRAPPER_OPEN--; return $rv; } # theme_ui_grid_table(&elements, columns, [width-percent], [tds], [tabletags], # [title]) # Given a list of HTML elements, formats them into a table with the given # number of columns. However, themes are free to override this to use fewer # columns where space is limited. sub theme_ui_grid_table { my ($elements, $cols, $width, $tds, $tabletags, $title) = @_; return "" if (!@$elements); my $rv = "<table class='wrapper' " . ($width ? " width=$width%" : " width=100%") . ($tabletags ? " ".$tabletags : "") . "><tr><td>\n"; $rv .= "<table class='ui_table ui_grid_table'" . ($width ? " width=$width%" : "") . ($tabletags ? " ".$tabletags : "") . ">\n"; if ($title) { $rv .= "<thead><tr class='ui_grid_heading'> ". "<td colspan=$cols><b>$title</b></td> </tr></thead>\n"; } $rv .= "<tbody>\n"; my $i; for($i=0; $i<@$elements; $i++) { $rv .= "<tr class='ui_grid_row'>" if ($i%$cols == 0); $rv .= "<td ".$tds->[$i%$cols]." valign=top class='ui_grid_cell'>". $elements->[$i]."</td>\n"; $rv .= "</tr>" if ($i%$cols == $cols-1); } if ($i%$cols) { while($i%$cols) { $rv .= "<td ".$tds->[$i%$cols]." class='ui_grid_cell'><br></td>\n"; $i++; } $rv .= "</tr>\n"; } $rv .= "</table>\n"; $rv .= "</tbody>\n"; $rv .= "</td></tr></table>\n"; # wrapper return $rv; } sub theme_ui_hidden_start { my ($title, $name, $status) = @_; my $rv; my $opened = $status ? " open" : ""; $rv .= "<details class='ui_hidden_start'$opened>"; $rv .= "<summary>$title</summary>\n"; return $rv; } =head2 ui_hidden_end(name) Returns HTML for the end of a hidden section, started by ui_hidden_start. =cut sub theme_ui_hidden_end { return "</details>\n"; } # theme_ui_hidden_table_start(heading, [tabletags], [cols], name, status, # [&default-tds], [rightheading]) # A table with a heading and table inside, and which is collapsible sub theme_ui_hidden_table_start { my ($heading, $tabletags, $cols, $name, $status, $tds, $rightheading) = @_; my $rv; if (!$main::ui_hidden_start_donejs++) { $rv .= &ui_hidden_javascript(); } my $opened = $status ? " open" : ""; my $header = defined($heading) ? "<span>$heading</span>" : ""; my $rheader = defined($rightheading) ? "<span class='rightheading'>$rightheading</span>" : ""; if (!$main::WRAPPER_OPEN) { # If we're not already inside of a wrapper, wrap it $rv .= "<div>\n"; } $main::WRAPPER_OPEN++; my $colspan = 1; $rv .= "<details data-name='$name' class='ui_hidden_table_start'$opened $tabletags>"; $rv .= "<summary>$header $rheader</summary>\n"; $rv .= "<table width=100%>\n"; $main::ui_table_cols = $cols || 4; $main::ui_table_pos = 0; $main::ui_table_default_tds = $tds; return $rv; } # ui_hidden_table_end(name) # Returns HTML for the end of table with hiding, as started by # ui_hidden_table_start sub theme_ui_hidden_table_end { local $rv = "</table></details>\n"; if ( $main::WRAPPER_OPEN == 1 ) { $main::WRAPPER_OPEN--; $rv .= "</div>\n"; } elsif ($main::WRAPPER_OPEN) { $main::WRAPPER_OPEN--; } return $rv; } # theme_select_all_link(field, form, text) # Adds support for row highlighting to the normal select all sub theme_select_all_link { local ($field, $form, $text) = @_; $form = int($form); $text ||= $text{'ui_selall'}; return "<a class='select_all' href='#' onClick='f = document.forms[$form]; ff = f.$field; ff.checked = true; r = document.getElementById(\"row_\"+ff.id); if (r) { r.className = \"mainsel\" }; for(i=0; i<f.$field.length; i++) { ff = f.${field}[i]; if (!ff.disabled) { ff.checked = true; r = document.getElementById(\"row_\"+ff.id); if (r) { r.className = \"mainsel\" } } } return false'>$text</a>"; } # theme_select_invert_link(field, form, text) # Adds support for row highlighting to the normal invert selection sub theme_select_invert_link { local ($field, $form, $text) = @_; $form = int($form); $text ||= $text{'ui_selinv'}; return "<a class='select_invert' href='#' onClick='f = document.forms[$form]; ff = f.$field; ff.checked = !f.$field.checked; r = document.getElementById(\"row_\"+ff.id); if (r) { r.className = ff.checked ? \"mainsel\" : \"mainbody\" }; for(i=0; i<f.$field.length; i++) { ff = f.${field}[i]; if (!ff.disabled) { ff.checked = !ff.checked; r = document.getElementById(\"row_\"+ff.id); if (r) { r.className = ff.checked ? \"mainsel\" : \"mainbody row\"+((i+1)%2) } } } return false'>$text</a>"; } # theme_select_status_link(name, form, &folder, &mails, start, end, status, label) # Adds support for row highlighting to read mail module selector # XXX can delete after Usermin 1.400 sub theme_select_status_link { local ($name, $formno, $folder, $mail, $start, $end, $status, $label) = @_; $formno = int($formno); local @sel; for(my $i=$start; $i<=$end; $i++) { local $read = &get_mail_read($folder, $mail->[$i]); if ($status == 0) { push(@sel, ($read&1) ? 0 : 1); } elsif ($status == 1) { push(@sel, ($read&1) ? 1 : 0); } elsif ($status == 2) { push(@sel, ($read&2) ? 1 : 0); } } my $js = "var sel = [ ".join(",", @sel)." ]; "; $js .= "var f = document.forms[$formno]; "; $js .= "for(var i=0; i<sel.length; i++) { document.forms[$formno].${name}[i].checked = sel[i]; var ff = f.${name}[i]; var r = document.getElementById(\"row_\"+ff.id); if (r) { r.className = ff.checked ? \"mainsel\" : \"mainbody row\"+((i+1)%2) } }"; $js .= "return false;"; return "<a class='select_status' href='#' onClick='$js'>$label</a>"; } sub theme_select_rows_link { local ($field, $form, $text, $rows) = @_; $form = int($form); my $js = "var sel = { ".join(",", map { "\""."e_escape($_)."\":1" } @$rows)." }; "; $js .= "for(var i=0; i<document.forms[$form].${field}.length; i++) { var ff = document.forms[$form].${field}[i]; var r = document.getElementById(\"row_\"+ff.id); ff.checked = sel[ff.value]; if (r) { r.className = ff.checked ? \"mainsel\" : \"mainbody row\"+((i+1)%2) } } "; $js .= "return false;"; return "<a class='select_rows' href='#' onClick='$js'>$text</a>"; } sub theme_ui_checked_columns_row { $theme_ui_columns_row_toggle = $theme_ui_columns_row_toggle ? '0' : '1'; local ($cols, $tdtags, $checkname, $checkvalue, $checked, $disabled, $tags) = @_; my $rv; my $cbid = "e_escape("${checkname}_${checkvalue}"); my $rid = "e_escape("row_${checkname}_${checkvalue}"); my $mycb = $cb; if ($checked) { $mycb =~ s/mainbody/mainsel/g; } $mycb =~ s/class='/class='row$theme_ui_columns_row_toggle ui_checked_columns /; $rv .= "<tr id=\"$rid\" $mycb onMouseOver=\"this.className = document.getElementById('$cbid').checked ? 'mainhighsel' : 'mainhigh'\" onMouseOut=\"this.className = document.getElementById('$cbid').checked ? 'mainsel' : 'mainbody row$theme_ui_columns_row_toggle'\">\n"; $rv .= "<td class='ui_checked_checkbox' ".$tdtags->[0].">". &ui_checkbox($checkname, $checkvalue, undef, $checked, $tags." "."onClick=\"document.getElementById('$rid').className = this.checked ? 'mainhighsel' : 'mainhigh';\"", $disabled). "</td>\n"; my $i; for($i=0; $i<@$cols; $i++) { $rv .= "<td ".$tdtags->[$i+1].">"; if ($cols->[$i] !~ /<a\s+href|<input|<select|<textarea/) { $rv .= "<label for=\"". "e_escape("${checkname}_${checkvalue}")."\">"; } $rv .= ($cols->[$i] !~ /\S/ ? "<br>" : $cols->[$i]); if ($cols->[$i] !~ /<a\s+href|<input|<select|<textarea/) { $rv .= "</label>"; } $rv .= "</td>\n"; } $rv .= "</tr>\n"; return $rv; } sub theme_ui_radio_columns_row { local ($cols, $tdtags, $checkname, $checkvalue, $checked) = @_; my $rv; my $cbid = "e_escape("${checkname}_${checkvalue}"); my $rid = "e_escape("row_${checkname}_${checkvalue}"); my $mycb = $cb; if ($checked) { $mycb =~ s/mainbody/mainsel/g; } $mycb =~ s/class='/class='ui_radio_columns /; $rv .= "<tr $mycb id=\"$rid\" onMouseOver=\"this.className = document.getElementById('$cbid').checked ? 'mainhighsel' : 'mainhigh'\" onMouseOut=\"this.className = document.getElementById('$cbid').checked ? 'mainsel' : 'mainbody'\">\n"; $rv .= "<td ".$tdtags->[0]." class='ui_radio_radio'>". &ui_oneradio($checkname, $checkvalue, undef, $checked, "onClick=\"for(i=0; i<form.$checkname.length; i++) { ff = form.${checkname}[i]; r = document.getElementById('row_'+ff.id); if (r) { r.className = 'mainbody' } } document.getElementById('$rid').className = this.checked ? 'mainhighsel' : 'mainhigh';\""). "</td>\n"; my $i; for($i=0; $i<@$cols; $i++) { $rv .= "<td ".$tdtags->[$i+1].">"; if ($cols->[$i] !~ /<a\s+href|<input|<select|<textarea/) { $rv .= "<label for=\"". "e_escape("${checkname}_${checkvalue}")."\">"; } $rv .= ($cols->[$i] !~ /\S/ ? "<br>" : $cols->[$i]); if ($cols->[$i] !~ /<a\s+href|<input|<select|<textarea/) { $rv .= "</label>"; } $rv .= "</td>\n"; } $rv .= "</tr>\n"; return $rv; } # theme_ui_nav_link(direction, url, disabled) # Returns an arrow icon linking to provided url sub theme_ui_nav_link { my ($direction, $url, $disabled) = @_; my $alt = $direction eq "left" ? '<-' : '->'; if ($disabled) { return "<img alt=\"$alt\" align=\"middle\"" . "src=\"@{[&get_webprefix()]}/images/$direction-grey.gif\">\n"; } else { return "<a href=\"$url\"><img alt=\"$alt\" align=\"top\"" . "src=\"@{[&get_webprefix()]}/images/$direction.gif\"></a>\n"; } } # theme_footer([page, name]+, [noendbody]) # Output a footer for returning to some page sub theme_footer { my $i; my $count = 0; my %module_info = get_module_info(get_module_name()); for($i=0; $i+1<@_; $i+=2) { local $url = $_[$i]; if ($url ne '/' || !$tconfig{'noindex'}) { if ($url eq '/') { $url = "/?cat=$module_info{'category'}"; } elsif ($url eq '' && get_module_name() eq 'virtual-server' || $url eq '/virtual-server/') { # Don't bother with virtualmin menu next; } elsif ($url eq '' && get_module_name() eq 'server-manager' || $url eq '/server-manager/') { # Don't bother with Cloudmin menu next; } #elsif ($url =~ /(view|edit)_domain.cgi/ && # get_module_name() eq 'virtual-server' || # $url =~ /^\/virtual-server\/(view|edit)_domain.cgi/) { # # Don't bother with link to domain details # next; # } elsif ($url =~ /edit_serv.cgi/ && get_module_name() eq 'server-manager' || $url =~ /^\/virtual-server\/edit_serv.cgi/) { # Don't bother with link to system details next; } elsif ($url eq '' && get_module_name()) { $url = "/".get_module_name()."/". $module_info{'index_link'}; } elsif ($url =~ /^\?/ && get_module_name()) { $url = "/".get_module_name()."/$url"; } $url = "@{[&get_webprefix()]}$url" if ($url =~ /^\//); if ($count++ == 0) { print theme_ui_nav_link("left", $url); } else { print " |\n"; } print " <a href=\"$url\">",&text('main_return', $_[$i+1]),"</a>\n"; } } print "<br>\n"; if (!$_[$i]) { my $postbody = $tconfig{'postbody'}; if ($postbody) { my $hostname = &get_display_hostname(); my $version = &get_webmin_version(); my $os_type = $gconfig{'real_os_type'} || $gconfig{'os_type'}; my $os_version = $gconfig{'real_os_version'} || $gconfig{'os_version'}; $postbody =~ s/%HOSTNAME%/$hostname/g; $postbody =~ s/%VERSION%/$version/g; $postbody =~ s/%USER%/$remote_user/g; $postbody =~ s/%OS%/$os_type $os_version/g; print "$postbody\n"; } if ($tconfig{'postbodyinclude'}) { local $_; open(INC, "$theme_root_directory/$tconfig{'postbodyinclude'}"); while(<INC>) { print; } close(INC); } if (defined(&theme_postbody)) { &theme_postbody(@_); } print "</body></html>\n"; } } # Don't show virtualmin menu sub theme_redirect { local ($orig, $url) = @_; if (get_module_name() eq "virtual-server" && $orig eq "" && $url =~ /^((http|https):\/\/([^\/]+))\//) { $url = "$1/right.cgi"; } print "Location: $url\n\n"; } # theme_ui_hidden_javascript() # Returns <script> and <style> sections for hiding functions and CSS sub theme_ui_hidden_javascript { my $rv; my $imgdir = "@{[&get_webprefix()]}/images"; return <<EOF; <style> .opener_shown {display:inline} .opener_hidden {display:none} </style> <script> // Open or close a hidden section function hidden_opener(divid, openerid) { var divobj = document.getElementById(divid); var openerobj = document.getElementById(openerid); if (divobj.className == 'opener_shown') { divobj.className = 'opener_hidden'; openerobj.innerHTML = '<img border=0 src=$imgdir/closed.gif>'; } else { divobj.className = 'opener_shown'; openerobj.innerHTML = '<img border=0 src=$imgdir/open.gif>'; } } // Show a tab function select_tab(name, tabname, form) { var tabnames = document[name+'_tabnames']; var tabtitles = document[name+'_tabtitles']; for(var i=0; i<tabnames.length; i++) { var tabobj = document.getElementById('tab_'+tabnames[i]); var divobj = document.getElementById('div_'+tabnames[i]); var title = tabtitles[i]; if (tabnames[i] == tabname) { // Selected table tabobj.innerHTML = '<table cellpadding=0 cellspacing=0><tr>'+ '<td valign=top class=\\'tabSelected\\'>'+ '<img src=$imgdir/lc2.gif alt=""></td>'+ '<td class=\\'tabSelected\\' nowrap>'+ ' <b>'+title+'</b> </td>'+ '<td valign=top class=\\'tabSelected\\'>'+ '<img src=$imgdir/rc2.gif alt=""></td>'+ '</tr></table>'; divobj.className = 'opener_shown'; try { var nestedForm = divobj.querySelector("form[data-form-nested]"); if (nestedForm) { var nestedFormId = nestedForm.getAttribute("data-form-nested"), formSubmitters = document .querySelectorAll( "[data-submit-nested='" + nestedFormId + "']"); if (formSubmitters) { formSubmitters.forEach(function(submitter) { submitter.setAttribute( "form", nestedForm.getAttribute('id')); }); } } } catch(e) { console.warn('Cannot set the related submitter ID of the nested form : ' + e); } } else { // Non-selected tab tabobj.innerHTML = '<table cellpadding=0 cellspacing=0><tr>'+ '<td valign=top class=\\'tabUnselected\\'>'+ '<img src=$imgdir/lc1.gif alt=""></td>'+ '<td class=\\'tabUnselected\\' nowrap>'+ ' <a href=\\'\\' onClick=\\'return select_tab("'+ name+'", "'+tabnames[i]+'")\\'>'+title+'</a> </td>'+ '<td valign=top class=\\'tabUnselected\\'>'+ '<img src=$imgdir/rc1.gif alt=""></td>'+ '</tr></table>'; divobj.className = 'opener_hidden'; } } if (document.forms[0] && document.forms[0][name]) { document.forms[0][name].value = tabname; } return false; } </script> EOF } # XXX Temporary until ui-lib.pl valign stuff gets cleaned up # # theme_ui_columns_table(&headings, width-percent, &data, &types, no-sort, title, # empty-msg) # Returns HTML for a complete table. # headings - An array ref of heading HTML # width-percent - Preferred total width # data - A 2x2 array ref of table contents. Each can either be a simple string, # or a hash ref like : # { 'type' => 'group', 'desc' => 'Some section title' } # { 'type' => 'string', 'value' => 'Foo', 'colums' => 3, # 'nowrap' => 1 } # { 'type' => 'checkbox', 'name' => 'd', 'value' => 'foo', # 'label' => 'Yes', 'checked' => 1, 'disabled' => 1 } # { 'type' => 'radio', 'name' => 'd', 'value' => 'foo', ... } # types - An array ref of data types, such as 'string', 'number', 'bytes' # or 'date' # no-sort - Set to 1 to disable sorting by theme # title - Text to appear above the table # empty-msg - Message to display if no data sub theme_ui_columns_table { my ($heads, $width, $data, $types, $nosort, $title, $emptymsg) = @_; my $rv; # Just show empty message if no data if ($emptymsg && !@$data) { $rv .= &ui_subheading($title) if ($title); $rv .= "<b>$emptymsg</b><p>\n"; return $rv; } # Are there any checkboxes in each column? If so, make those columns narrow my @tds; my $maxwidth = 0; foreach my $r (@$data) { my $cc = 0; foreach my $c (@$r) { if (ref($c) && ($c->{'type'} eq 'checkbox' || $c->{'type'} eq 'radio')) { $tds[$cc] .= " width=5" if ($tds[$cc] !~ /width=/); } $cc++; } $maxwidth = $cc if ($cc > $maxwidth); } $rv .= &ui_columns_start($heads, $width, 0, \@tds, $title); # Add the data rows foreach my $r (@$data) { my $c0; if (ref($r->[0]) && ($r->[0]->{'type'} eq 'checkbox' || $r->[0]->{'type'} eq 'radio')) { # First column is special $c0 = $r->[0]; $r = [ @$r[1..(@$r-1)] ]; } # Turn data into HTML my @rtds = @tds; my @cols; my $cn = 0; $cn++ if ($c0); foreach my $c (@$r) { if (!ref($c)) { # Plain old string push(@cols, $c); } elsif ($c->{'type'} eq 'checkbox') { # Checkbox in non-first column push(@cols, &ui_checkbox($c->{'name'}, $c->{'value'}, $c->{'label'}, $c->{'checked'}, $c->{'tags'}, $c->{'disabled'})); } elsif ($c->{'type'} eq 'radio') { # Radio button in non-first column push(@cols, &ui_oneradio($c->{'name'}, $c->{'value'}, $c->{'label'}, $c->{'checked'}, $c->{'tags'}, $c->{'disabled'})); } elsif ($c->{'type'} eq 'group') { # Header row that spans whole table $rv .= &ui_columns_header([ $c->{'desc'} ], [ "colspan=$width" ]); next; } elsif ($c->{'type'} eq 'string') { # A string, which might be special push(@cols, $c->{'value'}); if ($c->{'columns'} > 1) { splice(@rtds, $cn, $c->{'columns'}, "colspan=".$c->{'columns'}); } if ($c->{'nowrap'}) { $rtds[$cn] .= " nowrap"; } } $cn++; } # Add the row if (!$c0) { $rv .= &ui_columns_row(\@cols, \@rtds); } elsif ($c0->{'type'} eq 'checkbox') { $rv .= &ui_checked_columns_row(\@cols, \@rtds, $c0->{'name'}, $c0->{'value'}, $c0->{'checked'}, $c0->{'disabled'}, $c0->{'tags'}); } elsif ($c0->{'type'} eq 'radio') { $rv .= &ui_radio_columns_row(\@cols, \@rtds, $c0->{'name'}, $c0->{'value'}, $c0->{'checked'}, $c0->{'disabled'}, $c0->{'tags'}); } } $rv .= &ui_columns_end(); return $rv; } =yui Functions for generating YUI CSS grids markup. =cut # ui_yui_grid_start(id, type) # Return a yui grid opening div. # Available types are: # g - 1/2,1/2 # gb - 1/3, 1/3, 1/3 # gc - 2/3, 1/3 # gd - 1/3, 2/3 # ge - 3/4, 1/4 # gf - 1/4, 3/4 sub theme_ui_yui_grid_start { my ($id, $type) = @_; return "<div id='grid_$id' class='yui-$type'>\n"; } sub theme_ui_yui_grid_end { my ($id) = @_; return "</div> <!-- grid_$id -->\n"; } # ui_yui_grid_section_start(id, first?) # Return a yui grid markup section opening div. sub theme_ui_yui_grid_section_start { my ($id, $first) = @_; if ($first) { return "<div id='grid_$id' class='yui-u first'>\n"; } else { return "<div id='grid_$id' class='yui-u'>\n"; } } sub theme_ui_yui_grid_section_end { my ($id) = @_; return "</div> <!-- grid_$id -->\n"; } 1;
Save
cmd:
run