]>
git.ipfire.org Git - ipfire-2.x.git/blob - html/cgi-bin/captive.cgi
2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2016 IPFire Team <alexander.marx@ipfire.org> #
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. #
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. #
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/>. #
20 ###############################################################################
26 # enable only the following on debugging purpose
28 #use CGI::Carp 'fatalsToBrowser';
30 require '/var/ipfire/general-functions.pl' ;
31 require "${General::swroot}/lang.pl" ;
32 require "${General::swroot}/header.pl" ;
36 my $coupons = "${General::swroot}/captive/coupons" ;
39 my $logo = "${General::swroot}/captive/logo.dat" ;
48 my $clients = "${General::swroot}/captive/clients" ;
50 my $settingsfile = "${General::swroot}/captive/settings" ;
51 unless (- e
$settingsfile ) { system ( "touch $settingsfile " ); }
53 & Header
:: getcgihash
( \
%cgiparams );
55 & General
:: readhash
( "${General::swroot}/main/settings" , \
%mainsettings );
56 & General
:: readhash
( "/srv/web/ipfire/html/themes/" . $mainsettings { 'THEME' }. "/include/colors.txt" , \
%color );
57 & General
:: readhash
( " $settingsfile " , \
%settings ) if (- f
$settingsfile );
58 & General
:: readhash
( "${General::swroot}/ethernet/settings" , \
%netsettings );
60 & Header
:: showhttpheaders
();
62 if ( $cgiparams { 'ACTION' } eq $Lang :: tr
{ 'save' }) {
63 my $file = $cgiparams { 'logo' };
65 # Check if the file extension is PNG/JPEG
68 my ( $name , $path , $ext ) = fileparse
( $file , qr/\.[^.]*$/ );
69 if ( $ext ne ".png" && $ext ne ".jpg" && $ext ne ".jpeg" ) {
70 $errormessage = $Lang :: tr
{ 'Captive wrong ext' };
74 $settings { 'ENABLE_GREEN' } = $cgiparams { 'ENABLE_GREEN' };
75 $settings { 'ENABLE_BLUE' } = $cgiparams { 'ENABLE_BLUE' };
76 $settings { 'AUTH' } = $cgiparams { 'AUTH' };
77 $settings { 'TITLE' } = $cgiparams { 'TITLE' };
78 $settings { 'COLOR' } = $cgiparams { 'COLOR' };
79 $settings { 'SESSION_TIME' } = $cgiparams { 'SESSION_TIME' };
82 #Check if we need to upload a new logo
85 my ( $filehandle ) = CGI
:: upload
( "logo" );
91 while (< $filehandle >) {
97 & General
:: writehash
( " $settingsfile " , \
%settings );
100 $cgiparams { 'TERMS' } = & Header
:: escape
( $cgiparams { 'TERMS' });
101 open ( FH
, ">:utf8" , "/var/ipfire/captive/terms.txt" ) or die ( "$!" );
102 print FH
$cgiparams { 'TERMS' };
104 $cgiparams { 'TERMS' } = "" ;
106 #execute binary to reload firewall rules
107 system ( "/usr/local/bin/captivectrl" );
109 if ( $cgiparams { 'ENABLE_BLUE' } eq 'on' ){
110 system ( "/usr/local/bin/wirelessctrl" );
115 if ( $cgiparams { 'ACTION' } eq " $Lang ::tr{'Captive generate coupon'}" ) {
117 if ( $cgiparams { 'EXP_HOUR' } + $cgiparams { 'EXP_DAY' } + $cgiparams { 'EXP_WEEK' } + $cgiparams { 'EXP_MONTH' } == 0 && $cgiparams { 'UNLIMITED' } == '' ) {
118 $errormessage = $Lang :: tr
{ 'Captive noexpiretime' };
122 if ( $cgiparams { 'REMARK' } ne '' && !& validremark
( $cgiparams { 'REMARK' })){
123 $errormessage = $Lang :: tr
{ 'fwhost err remark' };
126 if (! $errormessage ) {
127 # Remember selected values
128 foreach my $val (( "UNLIMITED" , "EXP_HOUR" , "EXP_DAY" , "EXP_WEEK" , "EXP_MONTH" )) {
129 $settings { $val } = $cgiparams { $val };
131 & General
:: writehash
( $settingsfile , \
%settings );
133 & General
:: readhasharray
( $coupons , \
%couponhash ) if (- e
$coupons );
136 # Calculate expiry time in seconds
139 if ( $settings { 'UNLIMITED' } ne 'on' ) {
140 $expires += $settings { 'EXP_HOUR' };
141 $expires += $settings { 'EXP_DAY' };
142 $expires += $settings { 'EXP_WEEK' };
143 $expires += $settings { 'EXP_MONTH' };
146 my $count = $cgiparams { 'COUNT' } || 1 ;
147 while ( $count -- > 0 ) {
148 # Generate a new code
149 my $code = & gencode
();
151 # Check if the coupon code already exists
152 foreach my $key ( keys %couponhash ) {
153 if ( $couponhash { $key }[ 1 ] eq $code ) {
154 # Code already exists, so try again
161 next if ( $code eq "" );
163 # Get a new key from hash
164 my $key = & General
:: findhasharraykey
( \
%couponhash );
166 # Initialize all fields
167 foreach my $i ( 0 .. 3 ) { $couponhash { $key }[ $i ] = "" ; }
169 $couponhash { $key }[ 0 ] = $now ;
170 $couponhash { $key }[ 1 ] = $code ;
171 $couponhash { $key }[ 2 ] = $expires ;
172 $couponhash { $key }[ 3 ] = $cgiparams { 'REMARK' };
175 # Save everything to disk
176 & General
:: writehasharray
( $coupons , \
%couponhash );
180 if ( $cgiparams { 'ACTION' } eq 'delete-coupon' ) {
181 #deletes an already generated but unused voucher
183 #read all generated vouchers
184 & General
:: readhasharray
( $coupons , \
%couponhash ) if (- e
$coupons );
185 foreach my $key ( keys %couponhash ) {
186 if ( $cgiparams { 'key' } eq $couponhash { $key }[ 0 ]){
187 #write logenty with decoded remark
188 my $rem = HTML
:: Entities
:: decode_entities
( $couponhash { $key }[ 4 ]);
189 & General
:: log ( "Captive" , "Delete unused coupon $couponhash { $key }[1] $couponhash { $key }[2] hours valid expires on $couponhash { $key }[3] remark $rem " );
190 #delete line from hash
191 delete $couponhash { $key };
196 & General
:: writehasharray
( $coupons , \
%couponhash );
199 if ( $cgiparams { 'ACTION' } eq 'delete-client' ) {
200 #delete voucher and connection in use
202 #read all active clients
203 & General
:: readhasharray
( $clients , \
%clientshash ) if (- e
$clients );
204 foreach my $key ( keys %clientshash ) {
205 if ( $cgiparams { 'key' } eq $clientshash { $key }[ 0 ]){
206 #prepare log entry with decoded remark
207 my $rem = HTML
:: Entities
:: decode_entities
( $clientshash { $key }[ 7 ]);
209 & General
:: log ( "Captive" , "Deleted client in use $clientshash { $key }[1] $clientshash { $key }[2] hours valid expires on $clientshash { $key }[3] remark $rem - Connection will be terminated" );
210 #delete line from hash
211 delete $clientshash { $key };
216 & General
:: writehasharray
( " $clients " , \
%clientshash );
217 #reload firewallrules to kill connection of client
218 system ( "/usr/local/bin/captivectrl" );
221 #open webpage, print header and open box
222 & Header
:: openpage
( $Lang :: tr
{ 'Captive menu' }, 1 , '' );
223 & Header
:: openbigbox
();
225 # If an error message exists, show a box with the error message
227 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'error messages' });
232 # Prints the config box on the website
233 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'Captive config' });
235 <form method='post' action=' $ENV {'SCRIPT_NAME'}' enctype="multipart/form-data"> \n
236 <table width='100%' border="0">
241 #check which parameters have to be enabled (from settings file)
242 $checked { 'ENABLE_GREEN' }{ 'off' } = '' ;
243 $checked { 'ENABLE_GREEN' }{ 'on' } = '' ;
244 $checked { 'ENABLE_GREEN' }{ $settings { 'ENABLE_GREEN' }} = "checked='checked'" ;
246 $checked { 'ENABLE_BLUE' }{ 'off' } = '' ;
247 $checked { 'ENABLE_BLUE' }{ 'on' } = '' ;
248 $checked { 'ENABLE_BLUE' }{ $settings { 'ENABLE_BLUE' }} = "checked='checked'" ;
250 $checked { 'UNLIMITED' }{ 'off' } = '' ;
251 $checked { 'UNLIMITED' }{ 'on' } = '' ;
252 $checked { 'UNLIMITED' }{ $settings { 'UNLIMITED' }} = "checked='checked'" ;
254 $selected { 'AUTH' } = ();
255 $selected { 'AUTH' }{ 'COUPON' } = "" ;
256 $selected { 'AUTH' }{ 'TERMS' } = "" ;
257 $selected { 'AUTH' }{ $settings { 'AUTH' }} = "selected" ;
259 if ( $netsettings { 'GREEN_DEV' }){
260 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>" ;
262 if ( $netsettings { 'BLUE_DEV' }){
263 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>" ;
270 $Lang ::tr{'Captive authentication'}
274 <option value="TERMS" $selected {'AUTH'}{'TERMS'} > $Lang ::tr{'Captive terms'}</option>
275 <option value="COUPON" $selected {'AUTH'}{'COUPON'}> $Lang ::tr{'Captive coupon'}</option>
282 if ( $settings { 'AUTH' } eq 'TERMS' ) {
283 $selected { 'SESSION_TIME' } = ();
284 $selected { 'SESSION_TIME' }{ '0' } = "" ;
285 $selected { 'SESSION_TIME' }{ '3600' } = "" ;
286 $selected { 'SESSION_TIME' }{ '28800' } = "" ;
287 $selected { 'SESSION_TIME' }{ '86400' } = "" ;
288 $selected { 'SESSION_TIME' }{ '604800' } = "" ;
289 $selected { 'SESSION_TIME' }{ '18144000' } = "" ;
290 $selected { 'SESSION_TIME' }{ $settings { 'SESSION_TIME' }} = "selected" ;
294 <td> $Lang ::tr{'Captive client session expiry time'}</td>
296 <select name="SESSION_TIME">
297 <option value="0" $selected {'SESSION_TIME'}{'0'}>- $Lang ::tr{'unlimited'} -</option>
298 <option value="3600" $selected {'SESSION_TIME'}{'3600'}> $Lang ::tr{'one hour'}</option>
299 <option value="28800" $selected {'SESSION_TIME'}{'28800'}> $Lang ::tr{'eight hours'}</option>
300 <option value="86400" $selected {'SESSION_TIME'}{'86400'}> $Lang ::tr{'24 hours'}</option>
301 <option value="604800" $selected {'SESSION_TIME'}{'604800'}> $Lang ::tr{'one week'}</option>
302 <option value="18144000" $selected {'SESSION_TIME'}{'18144000'}> $Lang ::tr{'one month'}</option>
313 <strong> $Lang ::tr{'Captive branding'}</strong>
318 $Lang ::tr{'Captive title'}
321 <input type='text' name='TITLE' value=" $settings {'TITLE'}" size='40'>
325 <td> $Lang ::tr{'Captive brand color'}</td>
327 <input type="color" name="COLOR" value=" $settings {'COLOR'}">
332 $Lang ::tr{'Captive upload logo'}
335 <input type="file" name="logo">
336 <br> $Lang ::tr{'Captive upload logo recommendations'}
344 <td> $Lang ::tr{'Captive logo uploaded'}</td>
345 <td> $Lang ::tr{'yes'}</td>
350 my $terms = & getterms
();
355 <textarea cols="50" rows="10" name="TERMS"> $terms </textarea>
361 <input type='submit' name='ACTION' value=" $Lang ::tr{'save'}"/>
369 #if settings is set to use coupons, the coupon part has to be displayed
370 if ( $settings { 'AUTH' } eq 'COUPON' ) {
374 # Show active clients
380 open ( FILE
, "<:utf8" , "/var/ipfire/captive/terms.txt" );
382 push ( @ret , HTML
:: Entities
:: decode_entities
( $_ ));
386 return join ( /\n/ , @ret );
390 #generate a random code only letters from A-Z except 'O' and 0-9
391 my @chars = ( "A" .. "N" , "P" .. "Z" , "0" .. "9" );
393 $randomstring .= $chars [ rand @chars ] for 1 . .8 ;
394 return $randomstring ;
398 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'Captive generate coupon' });
400 <form method='post' action=' $ENV {'SCRIPT_NAME'}'>
401 <table border='0' width='100%'>
404 $Lang ::tr{'Captive vouchervalid'}
407 <table class='tbl' border='0' width='100%'>
409 <th> $Lang ::tr{'hours'}</th>
410 <th> $Lang ::tr{'days'}</th>
411 <th> $Lang ::tr{'weeks'}</th>
412 <th> $Lang ::tr{'months'}</th>
417 #print hour-dropdownbox
419 print "<tr height='40px'><td><select name='EXP_HOUR' style='width:8em;'>" ;
420 print "<option value='0' " ;
421 print " selected='selected'" if ( $settings { 'EXP_HOUR' } eq '0' );
422 print ">--</option>" ;
423 for ( my $i = 1 ; $i < 25 ; $i ++){
424 my $exp_sec = $i * $hrs ;
425 print "<option value=' $exp_sec ' " ;
426 print " selected='selected'" if ( $settings { 'EXP_HOUR' } eq $exp_sec );
427 print "> $i </option>" ;
431 #print day-dropdownbox
433 print "<select name='EXP_DAY' style='width:8em;'>" ;
434 print "<option value='0' " ;
435 print " selected='selected'" if ( $settings { 'EXP_DAY' } eq '0' );
436 print ">--</option>" ;
437 for ( my $i = 1 ; $i < 8 ; $i ++){
438 my $exp_sec = $i * $days ;
439 print "<option value=' $exp_sec ' " ;
440 print " selected='selected'" if ( $settings { 'EXP_DAY' } eq $exp_sec );
441 print "> $i </option>" ;
445 #print week-dropdownbox
447 print "<select name='EXP_WEEK' style='width:8em;'>" ;
448 print "<option value='0' " ;
449 print " selected='selected'" if ( $settings { 'EXP_WEEK' } eq '0' );
450 print ">--</option>" ;
451 for ( my $i = 1 ; $i < 5 ; $i ++){
452 my $exp_sec = $i * $week ;
453 print "<option value=' $exp_sec ' " ;
454 print " selected='selected'" if ( $settings { 'EXP_WEEK' } eq $exp_sec );
455 print "> $i </option>" ;
459 #print month-dropdownbox
460 my $month = 3600 * 24 * 30 ;
461 print "<select name='EXP_MONTH' style='width:8em;'>" ;
462 print "<option value='0' " ;
463 print " selected='selected'" if ( $settings { 'EXP_MONTH' } eq '0' );
464 print ">--</option>" ;
465 for ( my $i = 1 ; $i < 13 ; $i ++){
466 my $exp_sec = $i * $month ;
467 print "<option value=' $exp_sec ' " ;
468 print " selected='selected'" if ( $settings { 'EXP_MONTH' } eq $exp_sec );
469 print "> $i </option>" ;
475 <input type='checkbox' name='UNLIMITED' $checked {'UNLIMITED'}{'on'} />
476 $Lang ::tr{'Captive nolimit'}
484 <td> $Lang ::tr{'remark'}</td>
486 <input type='text' style='width: 98%;' name='REMARK' align='left'>
492 <select name="COUNT">
493 <option value="1">1</option>
494 <option value="2">2</option>
495 <option value="3">3</option>
496 <option value="4">4</option>
497 <option value="5">5</option>
498 <option value="6">6</option>
499 <option value="7">7</option>
500 <option value="8">8</option>
501 <option value="9">9</option>
502 <option value="10">10</option>
503 <option value="20">20</option>
504 <option value="50">50</option>
505 <option value="100">100</option>
508 <input type="submit" name="ACTION" value=" $Lang ::tr{'Captive generate coupon'}">
515 # Show all coupons if exist
522 & General
:: readhasharray
( $coupons , \
%couponhash ) if (- e
$coupons );
524 #if there are already generated but unsused coupons, print a table
525 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'Captive issued coupons' });
528 <table class='tbl' border='0'>
530 <th align='center' width='15%'>
531 $Lang ::tr{'Captive coupon'}
533 <th align='center' width='15%'> $Lang ::tr{'Captive expiry time'}</th>
534 <th align='center' width='65%'> $Lang ::tr{'remark'}</th>
535 <th align='center' width='5%'> $Lang ::tr{'delete'}</th>
539 foreach my $key ( keys %couponhash ) {
540 my $expirytime = $Lang :: tr
{ 'Captive nolimit' };
541 if ( $couponhash { $key }[ 2 ] > 0 ) {
542 $expirytime = & General
:: format_time
( $couponhash { $key }[ 2 ]);
546 $col = "bgcolor=' $color {'color20'}'" ;
548 $col = "bgcolor=' $color {'color22'}'" ;
553 <td $col align="center">
554 <b> $couponhash { $key }[1]</b>
556 <td $col align="center">
559 <td $col align="center">
562 <td $col align="center">
564 <input type='image' src='/images/delete.gif' align='middle' alt=' $Lang ::tr{'delete'}' title=' $Lang ::tr{'delete'}' />
565 <input type='hidden' name='ACTION' value='delete-coupon' />
566 <input type='hidden' name='key' value=' $couponhash { $key }[0]' />
579 # if there are active clients which use coupons show table
580 return if ( - z
$clients || ! - f
$clients );
585 & Header
:: openbox
( '100%' , 'left' , $Lang :: tr
{ 'Captive clients' });
588 <table class='tbl' width='100%'>
590 <th align='center' width='15%'> $Lang ::tr{'Captive coupon'}</th>
591 <th align='center' width='15%'> $Lang ::tr{'Captive activated'}</th>
592 <th align='center' width='15%'> $Lang ::tr{'Captive expiry time'}</th>
593 <th align='center' width='10%'> $Lang ::tr{'Captive mac'}</th>
594 <th align='center' width='43%'> $Lang ::tr{'remark'}</th>
595 <th align='center' width='5%'> $Lang ::tr{'delete'}</th>
599 & General
:: readhasharray
( $clients , \
%clientshash ) if (- e
$clients );
600 foreach my $key ( keys %clientshash ) {
601 #calculate time from clientshash (starttime)
602 my $starttime = sub { sprintf ' %02d . %02d . %04d %02d : %02d ' , $_ [ 3 ], $_ [ 4 ]+ 1 , $_ [ 5 ]+ 1900 , $_ [ 2 ], $_ [ 1 ] }->( localtime ( $clientshash { $key }[ 2 ]));
604 #calculate endtime from clientshash
606 if ( $clientshash { $key }[ 3 ] eq '0' ){
607 $endtime = $Lang :: tr
{ 'Captive nolimit' };
609 $endtime = sub { sprintf ' %02d . %02d . %04d %02d : %02d ' , $_ [ 3 ], $_ [ 4 ]+ 1 , $_ [ 5 ]+ 1900 , $_ [ 2 ], $_ [ 1 ] }->( localtime ( $clientshash { $key }[ 2 ]+ $clientshash { $key }[ 3 ]));
613 $col = "bgcolor=' $color {'color20'}'" ;
615 $col = "bgcolor=' $color {'color22'}'" ;
618 my $coupon = ( $clientshash { $key }[ 4 ] eq "LICENSE" ) ?
$Lang :: tr
{ 'Captive terms short' } : $clientshash { $key }[ 4 ];
622 <td $col align="center"><b> $coupon </b></td>
623 <td $col align="center"> $starttime </td>
624 <td $col align="center"> $endtime </td>
625 <td $col align="center"> $clientshash { $key }[0]</td>
626 <td $col align="center"> $clientshash { $key }[5]</td>
627 <td $col align="center">
629 <input type='image' src='/images/delete.gif' align='middle' alt=' $Lang ::tr{'delete'}' title=' $Lang ::tr{'delete'}' />
630 <input type='hidden' name='ACTION' value='delete-client' />
631 <input type='hidden' name='key' value=' $clientshash { $key }[0]' />
645 # Checks a hostname against RFC1035
647 # Each part should be at least two characters in length
648 # but no more than 63 characters
649 if ( length ( $remark ) < 1 || length ( $remark ) > 255 ) {
651 # Only valid characters are a-z, A-Z, 0-9 and -
652 if ( $remark !~ /^[a-zäöüA-ZÖÄÜ0-9-.:;\|_()\/ \s
]*$/) {
654 # First character can only be a letter or a digit
655 if ( substr ( $remark , 0 , 1 ) !~ /^[a-zäöüA-ZÖÄÜ0-9]*$/ ) {
657 # Last character can only be a letter or a digit
658 if ( substr ( $remark , - 1 , 1 ) !~ /^[a-zöäüA-ZÖÄÜ0-9.:;_)]*$/ ) {
663 & Header
:: closebigbox
();
664 & Header
:: closepage
();