Handle hostnames with upper-case letters
[webmin.git] / Webmin / Page.pm
1 package Webmin::Page;
2 use WebminCore;
3 use WebminCore;
4
5 =head2 new Webmin::Page(subheading, title, [help-name], [show-config],
6                       [no-module-index], [no-webmin-index], [rightside],
7                       [header], [body-tags], [below-text])
8 Create a new page object, with the given heading and other details
9 =cut
10 sub new
11 {
12 if (defined(&Webmin::Theme::Page::new) && caller() !~ /Webmin::Theme::Page/) {
13         return new Webmin::Theme::Page(@_[1..$#_]);
14         }
15 my ($self, $subheading, $title, $help, $config, $noindex, $nowebmin, $right,
16     $header, $body, $below) = @_;
17 $self = { 'index' => 1, 'webmin' => 1, 'image' => "" };
18 bless($self);
19 $self->set_subheading($subheading);
20 $self->set_title($title);
21 $self->set_help($help);
22 $self->set_config($config);
23 $self->set_index(!$noindex);
24 $self->set_webmin(!$nowebmin);
25 $self->set_right($right);
26 $self->set_header($header);
27 $self->set_body($body);
28 $self->set_below($below);
29 return $self;
30 }
31
32 =head2 print()
33 Actually outputs this page
34 =cut
35 sub print
36 {
37 my ($self) = @_;
38 my $rv;
39
40 # Work out if we need buffering/table
41 foreach my $c (@{$self->{'contents'}}) {
42         if (ref($c) =~ /Dynamic/) {
43                 $| = 1;
44                 if ($c->needs_unbuffered()) {
45                         $self->{'unbuffered'} = 1;
46                         }
47                 }
48         }
49
50 # Show the page header
51 my $func = $self->{'unbuffered'} ? \&ui_print_unbuffered_header
52                                  : \&ui_print_header;
53 my $scripts;
54 foreach my $s (@{$self->{'scripts'}},
55                (map { @{$_->{'scripts'}} } @{$self->{'contents'}})) {
56         $scripts .= "<script>\n".$s."\n</script>\n";
57         }
58 my $onload;
59 my @onloads = ( @{$self->{'onloads'}},
60                 map { @{$_->{'onloads'}} } @{$self->{'contents'}} );
61 if (@onloads) {
62         $onload = "onLoad='".join(" ", @onloads)."'";
63         }
64 my @args =  ( $self->{'subheading'}, $self->{'title'}, $self->{'image'},
65               $self->{'help'}, $self->{'config'}, $self->{'index'} ? undef : 1,
66               $self->{'webmin'} ? undef : 1, $self->{'right'},
67               $self->{'header'}.$scripts, $self->{'body'}.$onload,
68               $self->{'below'} );
69 while(!defined($args[$#args])) {
70         pop(@args);
71         }
72 if ($self->get_refresh()) {
73         print "Refresh: ",$self->get_refresh(),"\r\n";
74         }
75 &ui_print_header(@args);
76
77 # Add the tab top
78 if ($self->{'tabs'}) {
79         print $self->{'tabs'}->top_html();
80         }
81
82 # Add any pre-content stuff
83 print $self->pre_content();
84
85 if ($self->{'errormsg'}) {
86         # Show the error only
87         print $self->get_errormsg_html();
88         }
89 else {
90         # Generate the forms and other stuff
91         foreach my $c (@{$self->{'contents'}}) {
92                 if (!ref($c)) {
93                         # Just a message
94                         print "$c<p>\n";
95                         }
96                 else {
97                         # Convert to HTML
98                         eval { print $c->html(); };
99                         if ($@) {
100                                 print "<pre>$@</pre>";
101                                 }
102                         if (ref($c) =~ /Dynamic/ && $c->get_wait()) {
103                                 # Dynamic object .. execute now
104                                 $c->start();
105                                 }
106                         }
107                 }
108
109         # Generate buttons row
110         if ($self->{'buttons'}) {
111                 print "<hr>\n";
112                 print &ui_buttons_start();
113                 foreach my $b (@{$self->{'buttons'}}) {
114                         print &ui_buttons_row(@$b);
115                         }
116                 print &ui_buttons_end();
117                 }
118         }
119
120 # Add any post-content stuff
121 print $self->post_content();
122
123 # End of the tabs
124 if ($self->{'tabs'}) {
125         print $self->{'tabs'}->bottom_html();
126         }
127
128 # Print the footer
129 my @footerargs;
130 foreach my $f (@{$self->{'footers'}}) {
131         push(@footerargs, $f->[0], $f->[1]);
132         }
133 &ui_print_footer(@footerargs);
134
135 # Start any dynamic objects
136 foreach my $c (@{$self->{'contents'}}) {
137         if (ref($c) =~ /Dynamic/ && !$c->get_wait()) {
138                 $c->start();
139                 }
140         }
141 }
142
143 =head2 add_footer(link, title)
144 Adds a return link, typically for display at the end of the page.
145 =cut
146 sub add_footer
147 {
148 my ($self, $link, $title) = @_;
149 push(@{$self->{'footers'}}, [ $link, $title ]);
150 }
151
152 =head2 get_footer(index)
153 Returns the link for the numbered footer
154 =cut
155 sub get_footer
156 {
157 my ($self, $num) = @_;
158 return $self->{'footers'}->[$num]->[0];
159 }
160
161 =head2 add_message(text, ...)
162 Adds a text message, to appear at this point on the page
163 =cut
164 sub add_message
165 {
166 my ($self, @message) = @_;
167 push(@{$self->{'contents'}}, join("", @message));
168 }
169
170 =head2 add_error(text, [command-output])
171 Adds a an error message, possible accompanied by the command output
172 =cut
173 sub add_error
174 {
175 my ($self, $message, $out) = @_;
176 $message = "<font color=#ff0000>$message</font>";
177 if ($out) {
178         $message .= "<pre>$out</pre>";
179         }
180 push(@{$self->{'contents'}}, $message);
181 }
182
183 =head2 add_message_after(&object, text, ...)
184 Adds a message after some existing object
185 =cut
186 sub add_message_after
187 {
188 my ($self, $object, @message) = @_;
189 splice(@{$self->{'contents'}}, $self->position_of($object)+1, 0,
190         join("", @message));
191 }
192
193 =head2 add_error_after(&object, text, [command-output])
194 Adds an error message after some existing object
195 =cut
196 sub add_error_after
197 {
198 my ($self, $object, $message, $out) = @_;
199 $message = "<font color=#ff0000>$message</font>";
200 if ($out) {
201         $message .= "<pre>$out</pre>";
202         }
203 splice(@{$self->{'contents'}}, $self->position_of($object)+1, 0,
204        $message);
205 }
206
207 sub position_of
208 {
209 my ($self, $object) = @_;
210 for(my $i=0; $i<@{$self->{'contents'}}; $i++) {
211         if ($self->{'contents'}->[$i] eq $object) {
212                 return $i;
213                 }
214         }
215 print STDERR "Could not find $object in ",join(" ",@{$self->{'contents'}}),"\n";
216 return scalar(@{$self->{'contents'}});
217 }
218
219 =head2 add_form(Webmin::Form)
220 Adds a form to be displayed on this page
221 =cut
222 sub add_form
223 {
224 my ($self, $form) = @_;
225 push(@{$self->{'contents'}}, $form);
226 $form->set_page($self);
227 }
228
229 =head2 add_separator()
230 Adds some kind of separation between parts of this page, like an <hr>
231 =cut
232 sub add_separator
233 {
234 my ($self, $message) = @_;
235 push(@{$self->{'contents'}}, "<hr>");
236 }
237
238 =head2 add_button(cgi, label, description, [&hiddens], [before-button],
239                   [after-button])
240 Adds an action button associated with this page, typically for display at the end
241 =cut
242 sub add_button
243 {
244 my ($self, $cgi, $label, $desc, $hiddens, $before, $after) = @_;
245 push(@{$self->{'buttons'}}, [ $cgi, $label, $desc, join(" ", @$hiddens),
246                               $before, $after ]);
247 }
248
249 =head2 add_tabs(Webmin::Tags)
250 Tells the page to display the given set of tabs at the top
251 =cut
252 sub add_tabs
253 {
254 my ($self, $tabs) = @_;
255 $self->{'tabs'} = $tabs;
256 }
257
258 =head2 add_dynamic(Webmin::DynamicText|Webmin::DynamicProgress)
259 Adds an object that is dynamically generated, such as a text box or progress bar.
260 =cut
261 sub add_dynamic
262 {
263 my ($self, $dyn) = @_;
264 push(@{$self->{'contents'}}, $dyn);
265 $dyn->set_page($self);
266 }
267
268 sub set_subheading
269 {
270 my ($self, $subheading) = @_;
271 $self->{'subheading'} = $subheading;
272 }
273
274 sub set_title
275 {
276 my ($self, $title) = @_;
277 $self->{'title'} = $title;
278 }
279
280 sub set_help
281 {
282 my ($self, $help) = @_;
283 $self->{'help'} = $help;
284 }
285
286 sub set_config
287 {
288 my ($self, $config) = @_;
289 $self->{'config'} = $config;
290 }
291
292 sub set_index
293 {
294 my ($self, $index) = @_;
295 $self->{'index'} = $index;
296 }
297
298 sub set_webmin
299 {
300 my ($self, $webmin) = @_;
301 $self->{'webmin'} = $webmin;
302 }
303
304 sub set_right
305 {
306 my ($self, $right) = @_;
307 $self->{'right'} = $right;
308 }
309
310 sub set_header
311 {
312 my ($self, $header) = @_;
313 $self->{'header'} = $header;
314 }
315
316 sub set_body
317 {
318 my ($self, $body) = @_;
319 $self->{'body'} = $body;
320 }
321
322 sub set_below
323 {
324 my ($self, $below) = @_;
325 $self->{'below'} = $below;
326 }
327
328 sub set_unbuffered
329 {
330 my ($self, $unbuffered) = @_;
331 $self->{'unbuffered'} = $unbuffered;
332 }
333
334 =head2 set_popup(popup?)
335 If set to 1, then this is a popup window
336 =cut
337 sub set_popup
338 {
339 my ($self, $popup) = @_;
340 $self->{'popup'} = $popup;
341 }
342
343 =head2 get_myurl()
344 Returns the path part of the URL for this page, like /foo/bar.cgi
345 =cut
346 sub get_myurl
347 {
348 my @args;
349 if ($ENV{'QUERY_STRING'} && $ENV{'REQUEST_METHOD'} ne 'POST') {
350         my %in;
351         &ReadParse(\%in);
352         foreach my $i (keys %in) {
353                 if ($i !~ /^ui_/) {
354                         foreach my $v (split(/\0/, $in{$i})) {
355                                 push(@args, &urlize($i)."=".
356                                             &urlize($v));
357                                 }
358                         }
359                 }
360         }
361 return @args ? $ENV{'SCRIPT_NAME'}."?".join("&", @args)
362              : $ENV{'SCRIPT_NAME'};
363 }
364
365 =head2 set_refresh(seconds)
366 Sets the number of seconds between automatic page refreshes
367 =cut
368 sub set_refresh
369 {
370 my ($self, $refresh) = @_;
371 $self->{'refresh'} = $refresh;
372 }
373
374 sub get_refresh
375 {
376 my ($self) = @_;
377 return $self->{'refresh'};
378 }
379
380 =head2 add_onload(code)
381 Adds some Javascript code for inclusion in the onLoad tag
382 =cut
383 sub add_onload
384 {
385 my ($self, $code) = @_;
386 push(@{$self->{'onloads'}}, $code);
387 }
388
389 =head2 add_script(code)
390 Adds some Javascript code for putting in the <head> section
391 =cut
392 sub add_script
393 {
394 my ($self, $script) = @_;
395 push(@{$self->{'scripts'}}, $script);
396 }
397
398 sub pre_content
399 {
400 my ($self) = @_;
401 return undef;
402 }
403
404 sub post_content
405 {
406 my ($self) = @_;
407 return undef;
408 }
409
410 =head2 set_errormsg(message)
411 Sets an error message to be displayed instead of the page contents
412 =cut
413 sub set_errormsg
414 {
415 my ($self, $errormsg) = @_;
416 $self->{'errormsg'} = $errormsg;
417 }
418
419 sub get_errormsg_html
420 {
421 my ($self) = @_;
422 return $self->{'errormsg'}."<p>\n";
423 }
424
425 1;
426