]> git.ipfire.org Git - ipfire-2.x.git/blame - html/cgi-bin/captive.cgi
Captive-Portal: redesign Webinterface
[ipfire-2.x.git] / html / cgi-bin / captive.cgi
CommitLineData
8b920789
AM
1#!/usr/bin/perl
2###############################################################################
3# #
4# IPFire.org - A linux based firewall #
5# Copyright (C) 2016 IPFire Team <alexander.marx@ipfire.org> #
6# #
7# This program is free software: you can redistribute it and/or modify #
8# it under the terms of the GNU General Public License as published by #
9# the Free Software Foundation, either version 3 of the License, or #
10# (at your option) any later version. #
11# #
12# This program is distributed in the hope that it will be useful, #
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15# GNU General Public License for more details. #
16# #
17# You should have received a copy of the GNU General Public License #
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #
19# #
20###############################################################################
21
22use strict;
23use HTML::Entities();
24# enable only the following on debugging purpose
25#use warnings;
26#use CGI::Carp 'fatalsToBrowser';
27
28require '/var/ipfire/general-functions.pl';
29require "${General::swroot}/lang.pl";
30require "${General::swroot}/header.pl";
31unless (-e "${General::swroot}/captive/settings") { system("touch ${General::swroot}/captive/settings"); }
32my %settings=();
33my %mainsettings;
34my %color;
35my %cgiparams=();
36my %netsettings=();
37my %checked=();
38my $errormessage='';
39my $voucherout="${General::swroot}/captive/voucher_out";
40my $clients="${General::swroot}/captive/clients";
41my %voucherhash=();
42my %clientshash=();
43my $settingsfile="${General::swroot}/captive/settings";
44
45unless (-e $voucherout) { system("touch $voucherout"); }
46
47&Header::getcgihash(\%cgiparams);
48
49&General::readhash("${General::swroot}/main/settings", \%mainsettings);
50&General::readhash("/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color);
51&General::readhash("$settingsfile", \%settings) if(-f $settingsfile);
52&General::readhash("${General::swroot}/ethernet/settings", \%netsettings);
53
54&Header::showhttpheaders();
55
56#actions
57if ($cgiparams{'ACTION'} eq "$Lang::tr{'save'}"){
58 #saves the Captiveportal settings to disk
59 $settings{'ENABLE_GREEN'} = $cgiparams{'ENABLE_GREEN'};
60 $settings{'ENABLE_BLUE'} = $cgiparams{'ENABLE_BLUE'};
61 $settings{'AUTH'} = $cgiparams{'AUTH'};
e01c5ab7
AM
62 $settings{'EXPIRE'} = $cgiparams{'EXP_HOUR'}+$cgiparams{'EXP_DAY'}+$cgiparams{'EXP_WEEK'}+$cgiparams{'EXP_MONTH'};
63 $settings{'EXP_HOUR'} = $cgiparams{'EXP_HOUR'};
64 $settings{'EXP_DAY'} = $cgiparams{'EXP_DAY'};
65 $settings{'EXP_WEEK'} = $cgiparams{'EXP_WEEK'};
66 $settings{'EXP_MONTH'} = $cgiparams{'EXP_MONTH'};
8b920789
AM
67 $settings{'TITLE'} = $cgiparams{'TITLE'};
68 &General::writehash("$settingsfile", \%settings);
e01c5ab7 69
8b920789
AM
70 #write Licensetext if defined
71 if ($cgiparams{'AGB'}){
72 $cgiparams{'AGB'} = &Header::escape($cgiparams{'AGB'});
73 open( FH, ">:utf8", "/var/ipfire/captive/agb.txt" ) or die("$!");
74 print FH $cgiparams{'AGB'};
75 close( FH );
76 $cgiparams{'AGB'}="";
77 }
78 #execute binary to reload firewall rules
79 system("/usr/local/bin/captivectrl");
80}
81
82if ($cgiparams{'ACTION'} eq "$Lang::tr{'Captive voucherout'}"){
83 #generates a voucher and writes it to /var/ipfire/voucher_out
84
85 #check if we already have a voucher with same code
86 &General::readhasharray("$voucherout", \%voucherhash);
87 foreach my $key (keys %voucherhash) {
88 if($voucherhash{$key}[1] eq $cgiparams{'CODE'}){
89 $errormessage=$Lang::tr{'Captive err doublevoucher'};
90 last;
91 }
92 }
93
e01c5ab7
AM
94 #check valid remark
95 if ($cgiparams{'REMARK'} ne '' && !&validremark($cgiparams{'REMARK'})){
96 $errormessage=$Lang::tr{'fwhost err remark'};
97 }
98
8b920789
AM
99 #if no error detected, write to disk
100 if (!$errormessage){
101 my $date=time(); #seconds in utc
102
103 #first get new key from hash
104 my $key=&General::findhasharraykey (\%voucherhash);
105 #initialize all fields with ''
e01c5ab7 106 foreach my $i (0 .. 3) { $voucherhash{$key}[$i] = "";}
8b920789
AM
107 #define fields
108 $voucherhash{$key}[0] = $date;
109 $voucherhash{$key}[1] = $cgiparams{'CODE'};
e01c5ab7
AM
110 $voucherhash{$key}[2] = $settings{'EXPIRE'};
111 $voucherhash{$key}[3] = $cgiparams{'REMARK'};
8b920789
AM
112 #write values to disk
113 &General::writehasharray("$voucherout", \%voucherhash);
114
115 #now prepare log entry, get expiring date for voucher and decode remark for logfile
116 my $expdate=localtime(time()+$voucherhash{$key}[3]);
117 my $rem=HTML::Entities::decode_entities($voucherhash{$key}[4]);
118
119 #write logfile entry
120 &General::log("Captive", "Generated new voucher $voucherhash{$key}[1] $voucherhash{$key}[2] hours valid expires on $expdate remark $rem");
121 }
122}
123
124if ($cgiparams{'ACTION'} eq 'delvoucherout'){
125 #deletes an already generated but unused voucher
126
127 #read all generated vouchers
128 &General::readhasharray("$voucherout", \%voucherhash);
129 foreach my $key (keys %voucherhash) {
130 if($cgiparams{'key'} eq $voucherhash{$key}[0]){
131 #write logenty with decoded remark
132 my $rem=HTML::Entities::decode_entities($voucherhash{$key}[4]);
133 &General::log("Captive", "Delete unused voucher $voucherhash{$key}[1] $voucherhash{$key}[2] hours valid expires on $voucherhash{$key}[3] remark $rem");
134 #delete line from hash
135 delete $voucherhash{$key};
136 last;
137 }
138 }
139 #write back hash
140 &General::writehasharray("$voucherout", \%voucherhash);
141}
142
143if ($cgiparams{'ACTION'} eq 'delvoucherinuse'){
144 #delete voucher and connection in use
145
146 #read all active clients
147 &General::readhasharray("$clients", \%clientshash);
148 foreach my $key (keys %clientshash) {
149 if($cgiparams{'key'} eq $clientshash{$key}[0]){
150 #prepare log entry with decoded remark
151 my $rem=HTML::Entities::decode_entities($clientshash{$key}[7]);
152 #write logentry
153 &General::log("Captive", "Delete voucher in use $clientshash{$key}[1] $clientshash{$key}[2] hours valid expires on $clientshash{$key}[3] remark $rem - Connection will be terminated");
154 #delete line from hash
155 delete $clientshash{$key};
156 last;
157 }
158 }
159 #write back hash
160 &General::writehasharray("$clients", \%clientshash);
161 #reload firewallrules to kill connection of client
162 system("/usr/local/bin/captivectrl");
163}
164
165#open webpage, print header and open box
166&Header::openpage($Lang::tr{'Captive menu'}, 1, '');
167&Header::openbigbox();
168
169#call error() to see if we have to print an errormessage on website
170&error();
171
172#call config() to display the configuration box
173&config();
174
175sub getagb(){
176 #open textfile from /var/ipfire/captive/agb.txt
177 open( my $handle, "<:utf8", "/var/ipfire/captive/agb.txt" ) or die("$!");
178 while(<$handle>){
179 #read line by line and print on screen
180 $cgiparams{'AGB'}.= HTML::Entities::decode_entities($_);
181 }
182 close( $handle );
183}
184
185sub config(){
186 #prints the config box on the website
187 &Header::openbox('100%', 'left', $Lang::tr{'Captive config'});
188 print <<END
189 <form method='post' action='$ENV{'SCRIPT_NAME'}'>\n
190 <table width='100%' border="0">
191 <tr>
192END
193;
194 #check which parameters have to be enabled (from settings file)
195 $checked{'ENABLE_GREEN'}{'off'} = '';
196 $checked{'ENABLE_GREEN'}{'on'} = '';
197 $checked{'ENABLE_GREEN'}{$settings{'ENABLE_GREEN'}} = "checked='checked'";
e01c5ab7 198
8b920789
AM
199 $checked{'ENABLE_BLUE'}{'off'} = '';
200 $checked{'ENABLE_BLUE'}{'on'} = '';
201 $checked{'ENABLE_BLUE'}{$settings{'ENABLE_BLUE'}} = "checked='checked'";
202
203 if ($netsettings{'GREEN_DEV'}){
204 print "<td width='30%'>$Lang::tr{'Captive active on'} <font color='$Header::colourgreen'>Green</font></td><td><input type='checkbox' name='ENABLE_GREEN' $checked{'ENABLE_GREEN'}{'on'} /></td></tr>";
205 }
206 if ($netsettings{'BLUE_DEV'}){
207 print "<td width='30%'>$Lang::tr{'Captive active on'} <font color='$Header::colourblue'>Blue</font></td><td><input type='checkbox' name='ENABLE_BLUE' $checked{'ENABLE_BLUE'}{'on'} /></td></tr>";
208 }
e01c5ab7 209
8b920789
AM
210 print<<END
211 </tr>
e01c5ab7
AM
212 <tr>
213 <td><br>
214 $Lang::tr{'Captive title'}
215 </td>
216 <td><br>
217 <input type='text' name='TITLE' value="$settings{'TITLE'}" size='40'>
218 </td>
219 </tr>
220END
221;
222
223
224print<<END
8b920789
AM
225 <tr>
226 <td>
227 $Lang::tr{'Captive authentication'}
228 </td>
229 <td>
230 <select name='AUTH' style='width:8em;'>
231END
232;
233 print "<option value='LICENSE' ";
234 print " selected='selected'" if ($settings{'AUTH'} eq 'LICENSE');
235 print ">$Lang::tr{'Captive auth_lic'}</option>";
e01c5ab7 236
8b920789
AM
237 print "<option value='VOUCHER' ";
238 print " selected='selected'" if ($settings{'AUTH'} eq 'VOUCHER');
239 print ">$Lang::tr{'Captive auth_vou'}</option>";
e01c5ab7 240
8b920789
AM
241 print<<END
242 </select>
243 </td>
244 </tr>
8b920789
AM
245END
246;
8b920789 247
e01c5ab7
AM
248 if($settings{'AUTH'} eq 'LICENSE'){
249 &agbbox();
250 }
8b920789 251
e01c5ab7
AM
252 print"<tr><td>$Lang::tr{'Captive vouchervalid'}</td><td>";
253
254 print "<br><table border='0' with=100%>";
255 print "<th>Stunden</th><th>Tage</th><th>Wochen</th><th>Monate</th>";
256
257 #print hour-dropdownbox
258 my $hrs=3600;
259 print "<tr><td><select name='EXP_HOUR' style='width:8em;'>";
260 print "<option value='0' ";
261 print " selected='selected'" if ($settings{'EXP_HOUR'} eq '0');
262 print ">--</option>";
263 for (my $i = 1; $i<25; $i++){
264 my $exp_sec = $i * $hrs;
265 print "<option value='$exp_sec' ";
266 print " selected='selected'" if ($settings{'EXP_HOUR'} eq $exp_sec);
267 print ">$i</option>";
268 }
269 print "</td><td>";
270
271 #print day-dropdownbox
272 my $days=3600*24;
273 print "<select name='EXP_DAY' style='width:8em;'>";
274 print "<option value='0' ";
275 print " selected='selected'" if ($settings{'EXP_DAY'} eq '0');
276 print ">--</option>";
277 for (my $i = 1; $i<8; $i++){
278 my $exp_sec = $i * $days;
279 print "<option value='$exp_sec' ";
280 print " selected='selected'" if ($settings{'EXP_DAY'} eq $exp_sec);
281 print ">$i</option>";
282 }
283 print "</td><td>";
284
285 #print week-dropdownbox
286 my $week=3600*24*7;
287 print "<select name='EXP_WEEK' style='width:8em;'>";
288 print "<option value='0' ";
289 print " selected='selected'" if ($settings{'EXP_WEEK'} eq '0');
290 print ">--</option>";
291 for (my $i = 1; $i<5; $i++){
292 my $exp_sec = $i * $week;
293 print "<option value='$exp_sec' ";
294 print " selected='selected'" if ($settings{'EXP_WEEK'} eq $exp_sec);
295 print ">$i</option>";
296 }
297 print "</td><td>";
298
299 #print month-dropdownbox
300 my $month=3600*24*30;
301 print "<select name='EXP_MONTH' style='width:8em;'>";
302 print "<option value='0' ";
303 print " selected='selected'" if ($settings{'EXP_MONTH'} eq '0');
304 print ">--</option>";
305 for (my $i = 1; $i<13; $i++){
306 my $exp_sec = $i * $month;
307 print "<option value='$exp_sec' ";
308 print " selected='selected'" if ($settings{'EXP_MONTH'} eq $exp_sec);
309 print ">$i</option>";
310 }
311 print "</td>";
8b920789 312
e01c5ab7
AM
313 print "<td>&nbsp;&nbsp;&nbsp;<input type='checkbox' name='unlimited'></td><td>&nbsp;<b>unlimited</b></td>";
314
315 print "</tr></table>";
8b920789 316
8b920789
AM
317print<<END
318 <tr>
319 <td>
320 </td>
321 <td align='right'>
322 <input type='submit' name='ACTION' value="$Lang::tr{'save'}"/>
323 </td>
324 </tr>
325 </table>
326 <br><br>
327END
328;
329 print "</form>";
e01c5ab7 330
8b920789
AM
331 &Header::closebox();
332
333 #if settings is set to use vouchers, the voucher part has to be displayed
334 if ($settings{'AUTH'} eq 'VOUCHER'){
335 &voucher();
336 }else{
337 #otherwise we show the licensepart
338 &show_license_connections();
339 }
340}
341
342sub agbbox(){
343 &getagb();
344print<<END
345 <tr>
346 <td>
347 License agreement
348 </td>
349 <td>
350 <br>
351 <textarea cols="50" rows="10" name="AGB">$cgiparams{'AGB'}</textarea>
352 </td>
353 </tr>
354END
355;
356}
357
358sub gencode(){
359 #generate a random code only letters from A-Z except 'O' and 0-9
360 my @chars = ("A".."N", "P".."Z", "0".."9");
361 my $randomstring;
362 $randomstring .= $chars[rand @chars] for 1..8;
363 return $randomstring;
364}
365
366sub voucher(){
367 #show voucher part
e01c5ab7
AM
368 #calculate expiredate
369 my $expire = sub{sprintf '%02d.%02d.%04d %02d:%02d', $_[3], $_[4]+1, $_[5]+1900, $_[2], $_[1] }->(localtime(time()+$settings{'EXPIRE'}));
370
8b920789
AM
371 &Header::openbox('100%', 'left', $Lang::tr{'Captive voucher'});
372print<<END
373 <form method='post' action='$ENV{'SCRIPT_NAME'}'>
374 <table class='tbl'>
375 <tr>
e01c5ab7 376 <th align='center' width='20%'>$Lang::tr{'Captive voucher'}</th><th th align='center' width='25%'>$Lang::tr{'Captive expire'}</th><th align='center' width='55%'>$Lang::tr{'remark'}</th></tr>
8b920789
AM
377END
378;
e01c5ab7 379
8b920789 380 $cgiparams{'CODE'} = &gencode();
e01c5ab7 381 print "<tr><td><center><b><font size='5'>$cgiparams{'CODE'}</font></b></center></td><td><center><font size='3'>$expire</font></center></td><td><input type='text' name='REMARK' align='left' size='80'></td></tr>";
8b920789
AM
382 print "</table><br>";
383 print "<center><input type='submit' name='ACTION' value='$Lang::tr{'Captive voucherout'}'><input type='hidden' name='CODE' value='$cgiparams{'CODE'}'</center></form>";
384 &Header::closebox();
385 if (! -z $voucherout) { &show_voucher_out();}
386 if (! -z $clients) { &show_voucher_in_use();}
387}
388
389sub show_license_connections(){
390 #if there are active clients, show the box with active connections
391 return if ( -z $clients || ! -f $clients );
392 my $count=0;
393 my $col;
394 &Header::openbox('100%', 'left', $Lang::tr{'Captive voactive'});
395print<<END
396 <center><table class='tbl'>
397 <tr>
398 <th align='center' width='15%'><font size='1'>$Lang::tr{'Captive mac'}</th><th align='center' width='15%'>$Lang::tr{'Captive ip'}</th><th align='center' width='15%'>$Lang::tr{'Captive voucher'}</th><th th align='center' width='15%'>$Lang::tr{'Captive activated'}</th><th th align='center' width='15%'>$Lang::tr{'Captive expire'}</th><th th align='center' width='15%'>$Lang::tr{'delete'}</th></tr>
399END
400;
401 #read all clients from hash and show table
402 &General::readhasharray("$clients", \%clientshash);
403 foreach my $key (keys %clientshash){
404 my ($sec, $min, $hour, $mday, $mon, $year) = localtime($clientshash{$key}[6]);
405 my ($secx,$minx,$hourx) = localtime($clientshash{$key}[6]+($clientshash{$key}[5]*3600));
406 $mon = '0'.++$mon if $mon<10;
407 $min = '0'.$min if $min<10;
408 $hour = '0'.$hour if $hour<10;
409 $year=$year+1900;
410 if ($count % 2){
411 print" <tr>";
412 $col="bgcolor='$color{'color20'}'";
413 }else{
414 $col="bgcolor='$color{'color22'}'";
415 print" <tr>";
416 }
417 print "<td $col><center>$clientshash{$key}[0]</td><td $col><center>$clientshash{$key}[1]</td><td $col><center>$clientshash{$key}[4]</td><td $col><center>$mday.$mon.$year ";
418 printf("%02d",$hour);
419 print ":";
420 printf("%02d",$min);
421 print "</center></td><td $col><center>$mday.$mon.$year ";
422 printf("%02d",$hourx);
423 print ":";
424 printf("%02d",$minx);
425 print "</td><td $col><form method='post'><center><input type='image' src='/images/delete.gif' align='middle' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' /><form method='post'><input type='hidden' name='ACTION' value='delvoucherinuse' /><input type='hidden' name='key' value='$clientshash{$key}[0]' /></form></tr>";
426 $count++;
427 }
428
429 print "</table>";
430 &Header::closebox();
431}
432
433sub show_voucher_out(){
434 #if there are already generated but unsused vouchers, print a table
435 return if ( -z $voucherout);
436 my $count=0;
437 my $col;
438 &Header::openbox('100%', 'left', $Lang::tr{'Captive vout'});
439 print<<END
e01c5ab7 440 <center><table class='tbl' border='0'>
8b920789 441 <tr>
e01c5ab7 442 <th align='center' width='15%'><font size='1'>$Lang::tr{'date'}</th><th align='center' width='15%'>$Lang::tr{'Captive voucher'}</th><th th align='center' width='15%'>$Lang::tr{'Captive expire'}</th><th align='center' width='60%'>$Lang::tr{'remark'}</th><th align='center' width='5%'>$Lang::tr{'delete'}</th></tr>
8b920789
AM
443END
444;
445 &General::readhasharray("$voucherout", \%voucherhash);
446 foreach my $key (keys %voucherhash)
447 {
e01c5ab7
AM
448 my $starttime = sub{sprintf '%02d.%02d.%04d %02d:%02d', $_[3], $_[4]+1, $_[5]+1900, $_[2], $_[1] }->(localtime($voucherhash{$key}[0]));
449 my $endtime = sub{sprintf '%02d.%02d.%04d %02d:%02d', $_[3], $_[4]+1, $_[5]+1900, $_[2], $_[1] }->(localtime($voucherhash{$key}[0]+$voucherhash{$key}[2]));
450
8b920789
AM
451 if ($count % 2){
452 print" <tr>";
453 $col="bgcolor='$color{'color20'}'";
454 }else{
455 $col="bgcolor='$color{'color22'}'";
456 print" <tr>";
457 }
8b920789 458
e01c5ab7
AM
459 print "<td $col><center>$starttime</td>";
460 print "<td $col><center><b>$voucherhash{$key}[1]</b></td>";
461 print "<td $col><center>$endtime</td>";
462 print "<td $col align='center'>$voucherhash{$key}[3]</td>";
8b920789
AM
463 print "<td $col><form method='post'><center><input type='image' src='/images/delete.gif' align='middle' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' /><form method='post'><input type='hidden' name='ACTION' value='delvoucherout' /><input type='hidden' name='key' value='$voucherhash{$key}[0]' /></form></tr>";
464 $count++;
465 }
466
467 print "</table>";
468 &Header::closebox();
469}
470
471sub show_voucher_in_use(){
472 #if there are active clients which use vouchers show table
473 return if ( -z $clients || ! -f $clients );
474 my $count=0;
475 my $col;
476 &Header::openbox('100%', 'left', $Lang::tr{'Captive voactive'});
477print<<END
478 <center><table class='tbl'>
479 <tr>
480 <th align='center' width='15%'><font size='1'>$Lang::tr{'Captive mac'}</th><th align='center' width='15%'>$Lang::tr{'Captive ip'}</th><th align='center' width='15%'>$Lang::tr{'Captive voucher'}</th><th th align='center' width='15%'>$Lang::tr{'Captive activated'}</th><th th align='center' width='15%'>$Lang::tr{'Captive expire'}</th><th th align='center' width='15%'>$Lang::tr{'delete'}</th></tr>
481END
482;
483 &General::readhasharray("$clients", \%clientshash);
484 foreach my $key (keys %clientshash)
485 {
486 my ($sec, $min, $hour, $mday, $mon, $year) = localtime($clientshash{$key}[6]);
e01c5ab7
AM
487 my ($secx,$minx,$hourx, $mdayx, $monx, $yearx) = localtime($clientshash{$key}[6]+$clientshash{$key}[7]);
488
8b920789
AM
489 $mon = '0'.++$mon if $mon<10;
490 $min = '0'.$min if $min<10;
491 $hour = '0'.$hour if $hour<10;
492 $year=$year+1900;
e01c5ab7
AM
493
494 $monx = '0'.++$mon if $mon<10;
495 $minx = '0'.$min if $min<10;
496 $hourx = '0'.$hour if $hour<10;
497 $yearx=$year+1900;
498
8b920789
AM
499 if ($count % 2){
500 print" <tr>";
501 $col="bgcolor='$color{'color20'}'";
502 }else{
503 $col="bgcolor='$color{'color22'}'";
504 print" <tr>";
505 }
e01c5ab7 506
8b920789
AM
507 print "<td $col><center>$clientshash{$key}[0]</td><td $col><center>$clientshash{$key}[1]</td><td $col><center>$clientshash{$key}[4]</td><td $col><center>$mday.$mon.$year ";
508 printf("%02d",$hour);
509 print ":";
510 printf("%02d",$min);
e01c5ab7 511 print "</center></td><td $col><center>$mdayx.$monx.$yearx $clientshash{$key}[3]";
8b920789
AM
512 print "</td><td $col><form method='post'><center><input type='image' src='/images/delete.gif' align='middle' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' /><form method='post'><input type='hidden' name='ACTION' value='delvoucherinuse' /><input type='hidden' name='key' value='$clientshash{$key}[0]' /></form></tr>";
513 $count++;
514 }
515
516 print "</table>";
517 &Header::closebox();
518}
519
e01c5ab7
AM
520sub validremark
521{
522 # Checks a hostname against RFC1035
523 my $remark = $_[0];
524 # Each part should be at least two characters in length
525 # but no more than 63 characters
526 if (length ($remark) < 1 || length ($remark) > 255) {
527 return 0;}
528 # Only valid characters are a-z, A-Z, 0-9 and -
529 if ($remark !~ /^[a-zäöüA-ZÖÄÜ0-9-.:;\|_()\/\s]*$/) {
530 return 0;}
531 # First character can only be a letter or a digit
532 if (substr ($remark, 0, 1) !~ /^[a-zäöüA-ZÖÄÜ0-9]*$/) {
533 return 0;}
534 # Last character can only be a letter or a digit
535 if (substr ($remark, -1, 1) !~ /^[a-zöäüA-ZÖÄÜ0-9.:;_)]*$/) {
536 return 0;}
537 return 1;
538}
539
8b920789
AM
540sub error{
541 #if an errormessage exits, show a box with errormessage
542 if ($errormessage) {
543 &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
544 print "<class name='base'>$errormessage\n";
545 print "&nbsp;</class>\n";
546 &Header::closebox();
547 }
548}
549
550&Header::closebigbox();
551&Header::closepage();