1# mod_core.pl 2# Core proftpd directives 3 4# mod_core_directives(version) 5# Returns a directive structure, like the one user by Apache. Types are : 6# 0 - Networking 7# 1 - Logging 8# 2 - Files 9# 3 - Access control 10# 4 - Misc 11# 5 - User and Group 12# 6 - Authentication 13sub mod_core_directives 14{ 15local $rv = [ 16 [ 'AccessDenyMsg', 0, 3, 'virtual anon global', 1.202 ], 17 [ 'AccessGrantMsg', 0, 3, 'virtual anon global', 0.99 ], 18 [ 'Allow Deny Order', 1, 3, 'limit', 0.99 ], 19 [ 'AllowAll DenyAll', 0, 3, 'directory anon limit ftpaccess', 0.99 ], 20 [ 'AllowFilter', 0, 3, 'virtual anon global', 1.20 ], 21 [ 'AllowForeignAddress', 0, 0, 'virtual anon global', 1.17 ], 22 [ 'AllowGroup', 1, 3, 'limit', 1.11 ], 23 [ 'AllowOverwrite', 0, 3, 'virtual anon directory ftpaccess global', 0.99 ], 24 [ 'AllowUser', 1, 3, 'limit', 1.17 ], 25 [ 'AllowRetrieveRestart', 0, 0, 'virtual anon directory global ftpaccess', 0.99 ], 26 [ 'AllowStoreRestart', 0, 0, 'virtual anon directory global ftpaccess', 0.99 ], 27 [ 'AnonRequirePassword', 0, 6, 'anon', 0.99 ], 28 [ 'AnonymousGroup', 0, 6, 'virtual global', 1.13 ], 29 [ 'AuthAliasOnly', 0, 6, 'virtual anon global', 1.13 ], 30 [ 'AuthUsingAlias', 0, 6, 'anon', 1.20 ], 31 [ 'Bind', 0, 0, 'virtual', '1.16-1.27' ], 32 [ 'DefaultAddress', 0, 0, 'virtual', '1.27' ], 33 [ 'CDPath', 1, 2, 'virtual anon global', 1.20 ], 34 [ 'Class Classes', 1, 3, 'virtual', 1.20 ], 35 [ 'CommandBufferSize', 0, 0, 'virtual global', 1.20 ], 36 [ 'DefaultServer', 0, 0, 'virtual', undef, 0.99, 8 ], 37 [ 'DefaultTransferMode', 0, 0, 'virtual global', 1.20 ], 38 [ 'DeferWelcome', 0, 0, 'virtual global', 0.99 ], 39 [ 'DeleteAbortedStores', 0, 2, 'virtual directory anon global ftpaccess', 1.20 ], 40 [ 'DenyFilter', 0, 3, 'virtual anon global', 1.20 ], 41 [ 'DenyGroup', 1, 3, 'limit', 1.11 ], 42 [ 'DenyUser', 1, 3, 'limit', 1.17 ], 43 [ 'DisplayConnect', 0, 6, 'virtual global', 1.20 ], 44 [ 'DisplayFirstChdir', 0, 2, 'virtual anon directory global', '0.99-1.31' ], 45 [ 'DisplayChdir', 0, 2, 'virtual anon directory global', 1.31 ], 46 [ 'DisplayGoAway', 0, 6, 'virtual anon global', 1.20 ], 47 [ 'DisplayLogin', 0, 6, 'virtual anon global', 0.99 ], 48 [ 'DisplayQuit', 0, 6, 'virtual anon global', 1.20 ], 49 [ 'Group', 0, 5, 'virtual anon', undef, 0.99, 9 ], 50 [ 'GroupOwner', 0, 5, 'anon directory ftpaccess', 0.99 ], 51 [ 'GroupPassword', 1, 6, 'virtual anon global', 0.99 ], 52 [ 'HiddenStor', 0, 2, 'virtual anon directory global', '1.20-1.31' ], 53 [ 'HiddenStores', 0, 2, 'virtual anon directory global', 1.31 ], 54 [ 'HideGroup', 1, 2, 'directory anon', 0.99 ], 55 [ 'HideNoAccess', 0, 2, 'directory anon', 0.99 ], 56 [ 'HideUser', 1, 2, 'directory anon', 0.99 ], 57 [ 'IdentLookups', 0, 0, 'virtual global', 1.15 ], 58 [ 'IgnoreHidden', 0, 2, 'limit', 0.99 ], 59 [ 'MasqueradeAddress', 0, 0, 'virtual', 1.202 ], 60 [ 'MaxClients', 0, 0, 'virtual anon global', 0.99 ], 61 [ 'MaxClientsPerHost', 0, 0, 'virtual anon global', 1.17 ], 62# [ 'MaxClientsPerUser', 0, 0, 'virtual anon global', 1.20 ], 63 [ 'MaxInstances', 0, 0, 'root', undef, 1.16, 8 ], 64 [ 'MaxLoginAttempts', 0, 6, 'virtual global', 0.99 ], 65 [ 'MultilineRFC2228', 0, 0, 'root', 1.20 ], 66 [ 'PassivePorts', 0, 0, 'virtual global', 1.20 ], 67 [ 'PathAllowFilter', 0, 2, 'virtual anon global', 1.17 ], 68 [ 'PathDenyFilter', 0, 2, 'virtual anon global', 1.17 ], 69 [ 'PidFile', 0, 4, 'root', 1.20 ], 70 [ 'Port', 0, 0, 'virtual', 0.99 ], 71 [ 'RequireValidShell', 0, 6, 'virtual anon global', 0.99 ], 72 [ 'RLimitCPU', 0, 4, 'root', 1.202 ], 73 [ 'RLimitMemory', 0, 4, 'root', 1.202 ], 74 [ 'RLimitOpenFiles', 0, 4, 'root', 1.202 ], 75 [ 'ScoreboardPath', 0, 4, 'root', 1.16 ], 76 [ 'ServerAdmin', 0, 4, 'virtual', 0.99 ], 77 [ 'ServerIdent', 0, 0, 'virtual global', 1.20 ], 78 [ 'ServerName', 0, 4, 'virtual', undef, 0.99, 11 ], 79 [ 'ServerType', 0, 0, 'root', undef, 0.99, 10 ], 80 [ 'ShowSymlinks', 0, 2, 'virtual anon global', 0.99 ], 81 [ 'SocketBindTight', 0, 0, 'root', 0.99 ], 82 [ 'SyslogFacility', 0, 1, 'root', 1.16 ], 83 [ 'SyslogLevel', 0, 1, 'virtual anon global', 1.20 ], 84 [ 'tcpBackLog', 0, 0, 'root', 0.99 ], 85 [ 'tcpNoDelay', 0, 0, 'virtual global', 1.20 ], 86 [ 'tcpReceiveWindow', 0, 0, 'virtual', 0.99 ], 87 [ 'tcpSendWindow', 0, 0, 'virtual', 0.99 ], 88 [ 'TimesGMT', 0, 4, 'root', 1.20 ], 89 [ 'TimeoutIdle', 0, 0, 'root', 0.99 ], 90 [ 'TimeoutLogin', 0, 0, 'root', 0.99 ], 91 [ 'TimeoutNoTransfer', 0, 0, 'root', 0.99 ], 92 [ 'TimeoutStalled', 0, 0, 'root', 1.16 ], 93 [ 'TransferLog', 0, 1, 'virtual anon global', undef, 1.14, 10 ], 94 [ 'Umask', 0, 2, 'virtual directory ftpaccess', undef, 0.99, 3 ], 95 [ 'UseFtpUsers', 0, 6, 'virtual anon global', 0.99 ], 96 [ 'UseHostsAllowFile', 0, 3, 'virtual anon', 1.20 ], 97 [ 'UseHostsDenyFile', 0, 3, 'virtual anon', 1.20 ], 98 [ 'UseReverseDNS', 0, 0, 'root', 1.17 ], 99 [ 'User', 0, 5, 'virtual anon', undef, 0.99, 10 ], 100 [ 'UserDirRoot', 0, 2, 'anon', 1.20 ], 101 [ 'UserAlias', 1, 6, 'virtual anon global', 0.99 ], 102 [ 'UserOwner', 0, 5, 'anon directory', 1.20 ], 103 [ 'UserPassword', 1, 6, 'virtual anon global', 0.99 ], 104 [ 'WtmpLog', 0, 4, 'virtual anon global', 1.17 ], 105 ]; 106return &make_directives($rv, $_[0], "mod_core"); 107} 108 109sub edit_AccessDenyMsg 110{ 111return (1, $text{'mod_core_accessdeny'}, 112 &opt_input($_[0]->{'words'}->[0], "AccessDenyMsg", $text{'default'}, 20)); 113} 114sub save_AccessDenyMsg 115{ 116return &parse_opt("AccessDenyMsg"); 117} 118 119sub edit_AccessGrantMsg 120{ 121return (1, $text{'mod_core_accessgrant'}, 122 &opt_input($_[0]->{'words'}->[0], "AccessGrantMsg", $text{'default'}, 20)); 123} 124sub save_AccessGrantMsg 125{ 126return &parse_opt("AccessGrantMsg"); 127} 128 129sub edit_Allow_Deny_Order 130{ 131local (@type, @what, @mode, $i); 132foreach $d (@{$_[0]}, @{$_[1]}) { 133 local @w = @{$d->{'words'}}; 134 shift(@w) if (lc($w[0]) eq 'from'); 135 for($i=0; $i<@w; $i++) { 136 push(@type, lc($d->{'name'}) eq "allow" ? 1 : 2); 137 push(@what, $w[$i] eq 'all' || $w[$i] eq 'none' ? undef 138 : $w[$i]); 139 if ($w[$i] eq 'all') { push(@mode, 0); } 140 elsif ($w[$i] eq 'none') { push(@mode, 1); } 141 elsif ($w[$i] =~ /^\d+\.\d+\.\d+\.\d+$/) { push(@mode, 2); } 142 elsif ($w[$i] =~ /^[0-9\.\/]+$/) { push(@mode, 3); } 143 else { push(@mode, 4); } 144 } 145 } 146push(@type, ""); push(@what, ""); push(@mode, 0); 147$rv = "<i>$text{'mod_core_order'}</i>\n". 148 &choice_input($_[2]->[0]->{'value'}, "order", "", 149 "$text{'mod_core_denyallow'},deny,allow", 150 "$text{'mod_core_allowdeny'},allow,deny", 151 "$text{'default'},")."<br>\n"; 152$rv .= "<table border>\n". 153 "<tr $tb> <td><b>$text{'mod_core_action'}</b></td> ". 154 "<td><b>$text{'mod_core_cond'}</b></td> </tr>\n"; 155@sels = map { $text{"mod_core_mode_$_"}.','.$_ } (0 .. 4); 156for($i=0; $i<@type; $i++) { 157 $rv .= "<tr $cb> <td>".&select_input($type[$i], "allow_type_$i", "0", 158 " ,0", "$text{'mod_core_allow'},1", 159 "$text{'mod_core_deny'},2")."</td>\n"; 160 $rv .= "<td>".&select_input($mode[$i], "allow_mode_$i", "0", @sels); 161 $rv .= sprintf "<input name=allow_what_$i size=20 value=\"%s\"></td>\n", 162 $mode[$i] ? $what[$i] : ""; 163 $rv .= "</tr>\n"; 164 } 165$rv .= "</table>\n"; 166return (2, $text{'mod_core_allow_deny'}, $rv); 167} 168sub save_Allow_Deny_Order 169{ 170local ($i, $type, $mode, $what, @allow, @deny); 171for($i=0; defined($type = $in{"allow_type_$i"}); $i++) { 172 $mode = $in{"allow_mode_$i"}; $what = $in{"allow_what_$i"}; 173 next if (!$type); 174 if ($mode == 0) { $what = "all"; } 175 elsif ($mode == 1) { $what = "none"; } 176 elsif ($mode == 2) { 177 &check_ipaddress($what) || &check_ip6address($what) || 178 &error(&text('mod_core_eip', $what)); 179 } 180 elsif ($mode == 3) { 181 $what =~ /^[0-9\.]+\.$/ || 182 $what =~ /^([0-9\.]+)\/\d+$/ && &check_ipaddress("$1") || 183 $what =~ /^([a-f0-9:]+)\/\d+$/ && &check_ip6address("$1") || 184 &error(&text('mod_core_enet', $what)); 185 } 186 elsif ($mode == 4) { 187 $what =~ /^[A-Za-z0-9\.\-]+$/ || 188 &error(&text('mod_core_ehost', $what)); 189 } 190 if ($type == 1) { push(@allow, $what); } 191 else { push(@deny, $what); } 192 } 193return ( \@allow, \@deny, &parse_choice("order", "")); 194} 195 196sub edit_AllowAll_DenyAll 197{ 198#local $a = @{$_[0]}, $d = @{$_[1]}; 199local $a = $_[0], $d = $_[1]; 200local $rv = sprintf "<input type=radio name=AllowAll value=0 %s> %s\n", 201 $a || $d ? "" : "checked", $text{'mod_core_addefault'}; 202$rv .= sprintf "<input type=radio name=AllowAll value=1 %s> %s\n", 203 $a ? "checked" : "", $text{'mod_core_allowall'}; 204$rv .= sprintf "<input type=radio name=AllowAll value=2 %s> %s\n", 205 $d ? "checked" : "", $text{'mod_core_denyall'}; 206return (1, $text{'mod_core_adall'}, $rv); 207} 208sub save_AllowAll_DenyAll 209{ 210return $in{'AllowAll'} == 0 ? ( [ ], [ ] ) : 211 $in{'AllowAll'} == 1 ? ( [ "" ], [ ] ) : ( [ ], [ "" ] ); 212} 213 214sub edit_AllowFilter 215{ 216return (1, $text{'mod_core_filter'}, 217 &opt_input($_[0]->{'value'}, "AllowFilter", $text{'default'}, 15)); 218} 219sub save_AllowFilter 220{ 221return &parse_opt("AllowFilter"); 222} 223 224sub edit_AllowForeignAddress 225{ 226return (1, $text{'mod_core_foreign'}, 227 &choice_input($_[0]->{'value'}, "AllowForeignAddress", "", 228 "$text{'yes'},on", "$text{'no'},off", 229 "$text{'default'},")); 230} 231sub save_AllowForeignAddress 232{ 233return &parse_choice("AllowForeignAddress", ""); 234} 235 236sub edit_AllowGroup 237{ 238local $v = @{$_[0]} ? join(" ", (map { $_->{'value'} } @{$_[0]})) : undef; 239return (2, $text{'mod_core_agroup'}, 240 &opt_input($v, "AllowGroup", $text{'mod_core_all'}, 50)); 241} 242sub save_AllowGroup 243{ 244return ( $in{'AllowGroup_def'} ? [ ] : [ split(/\s+/, $in{'AllowGroup'}) ] ); 245} 246 247sub edit_AllowOverwrite 248{ 249return (1, $text{'mod_core_overwrite'}, 250 &choice_input($_[0]->{'value'}, "AllowOverwrite", "", 251 "$text{'yes'},on", "$text{'no'},off", 252 "$text{'default'},")); 253} 254sub save_AllowOverwrite 255{ 256return &parse_choice("AllowOverwrite", ""); 257} 258 259sub edit_AllowRetrieveRestart 260{ 261return (1, $text{'mod_core_restart'}, 262 &choice_input($_[0]->{'value'}, "AllowRetrieveRestart", "", 263 "$text{'yes'},on", "$text{'no'},off", 264 "$text{'default'},")); 265} 266sub save_AllowRetrieveRestart 267{ 268return &parse_choice("AllowRetrieveRestart", ""); 269} 270 271sub edit_AllowStoreRestart 272{ 273return (1, $text{'mod_core_restart2'}, 274 &choice_input($_[0]->{'value'}, "AllowStoreRestart", "", 275 "$text{'yes'},on", "$text{'no'},off", 276 "$text{'default'},")); 277} 278sub save_AllowStoreRestart 279{ 280return &parse_choice("AllowStoreRestart", ""); 281} 282 283sub edit_AllowUser 284{ 285local $v = @{$_[0]} ? join(" ", (map { $_->{'value'} } @{$_[0]})) : undef; 286return (2, $text{'mod_core_auser'}, 287 &opt_input($v, "AllowUser", $text{'mod_core_all'}, 50)); 288} 289sub save_AllowUser 290{ 291return ( $in{'AllowUser_def'} ? [ ] : [ split(/\s+/, $in{'AllowUser'}) ] ); 292} 293 294sub edit_AnonRequirePassword 295{ 296return (1, $text{'mod_core_require'}, 297 &choice_input($_[0]->{'value'}, "AnonRequirePassword", "", 298 "$text{'yes'},on", "$text{'no'},off", 299 "$text{'default'},")); 300} 301sub save_AnonRequirePassword 302{ 303return &parse_choice("AnonRequirePassword", ""); 304} 305 306sub edit_AnonymousGroup 307{ 308return (2, $text{'mod_core_anongroup'}, 309 &opt_input($_[0]->{'value'}, "AnonymousGroup", $text{'default'}, 50)); 310 311} 312sub save_AnonymousGroup 313{ 314return &parse_opt("AnonymousGroup", '\S', $text{'mod_core_eanongroup'}); 315} 316 317sub edit_AuthAliasOnly 318{ 319return (1, $text{'mod_core_authalias'}, 320 &choice_input($_[0]->{'value'}, "AuthAliasOnly", "", 321 "$text{'yes'},on", "$text{'no'},off", 322 "$text{'default'},")); 323} 324sub save_AuthAliasOnly 325{ 326return &parse_choice("AuthAliasOnly", ""); 327} 328 329sub edit_AuthUsingAlias 330{ 331return (1, $text{'mod_core_authusingalias'}, 332 &choice_input($_[0]->{'value'}, "AuthUsingAlias", "", 333 "$text{'yes'},on", "$text{'no'},off", 334 "$text{'default'},")); 335} 336sub save_AuthUsingAlias 337{ 338return &parse_choice("AuthUsingAlias", ""); 339} 340 341sub edit_Bind 342{ 343return (1, $text{'mod_core_bind'}, 344 &opt_input($_[0]->{'value'}, "Bind", $text{'mod_core_bind_all'}, 15)); 345} 346sub save_Bind 347{ 348return &parse_opt("Bind", '^(\d+)\.(\d+)\.(\d+)\.(\d+)|([0-9:]+)$', 349 $text{'mod_core_ebind'}); 350} 351 352sub edit_DefaultAddress 353{ 354return (1, $text{'mod_core_bind'}, 355 &opt_input($_[0]->{'value'}, "DefaultAddress", $text{'mod_core_bind_all'}, 15)); 356} 357sub save_DefaultAddress 358{ 359$in{'DefaultAddress_def'} || &to_ipaddress($in{'DefaultAddress'}) || 360 &to_ip6address($in{'DefaultAddress'}) || 361 &error(text{'mod_core_ebind'}); 362return &parse_opt("DefaultAddress", '^\S+$', 363 $text{'mod_core_ebind'}); 364} 365 366sub edit_CDPath 367{ 368local $rv = "<textarea rows=3 cols=50 name=CDPath>"; 369foreach $p (@{$_[0]}) { 370 $rv .= "$p->{'value'}\n"; 371 } 372$rv .= "</textarea>\n"; 373return (2, $text{'mod_core_cdpath'}, $rv); 374} 375sub save_CDPath 376{ 377$in{'CDPath'} =~ s/\r//g; 378return ( [ split(/\s+/, $in{'CDPath'}) ] ); 379} 380 381sub edit_Class_Classes 382{ 383local $rv = $text{'mod_core_classes'}. 384 &choice_input($_[1]->[0]->{'value'}, "Classes", "", 385 "$text{'yes'},on", "$text{'no'},off", 386 "$text{'default'},")."<br>\n"; 387$rv .= "<table border>\n". 388 "<tr $tb> <td><b>$text{'mod_core_cname'}</b></td> ". 389 "<td><b>$text{'mod_core_ctype'}</b></td> </tr>\n"; 390local $i = 0; 391foreach $c (@{$_[0]}, { }) { 392 local @w = @{$c->{'words'}}; 393 $rv .= "<tr $cb>\n"; 394 $rv .= "<td><input name=Class_n_$i size=10 value='$w[0]'></td>\n"; 395 $rv .= "<td><select name=Class_t_$i>\n"; 396 $rv .= sprintf "<option value=limit %s>%s</option>\n", 397 $w[1] eq 'limit' ? 'selected' : '', $text{'mod_core_climit'}; 398 $rv .= sprintf "<option value=regex %s>%s</option>\n", 399 $w[1] eq 'regex' ? 'selected' : '', $text{'mod_core_cregex'}; 400 $rv .= sprintf "<option value=ip %s>%s</option>\n", 401 $w[1] eq 'ip' ? 'selected' : '', $text{'mod_core_cip'}; 402 $rv .= "</select>\n"; 403 $rv .= "<input name=Class_v_$i size=20 value='$w[2]'></td>\n"; 404 $rv .= "</tr>\n"; 405 $i++; 406 } 407$rv .= "</table>\n"; 408return (2, $text{'mod_core_cls'}, $rv); 409} 410sub save_Class_Classes 411{ 412local ($i, @rv); 413for($i=0; defined($in{"Class_n_$i"}); $i++) { 414 next if (!$in{"Class_n_$i"}); 415 $in{"Class_t_$i"} ne 'limit' || 416 $in{"Class_v_$i"} =~ /^\d+$/ || 417 &error($text{'mod_core_eclimit'}); 418 $in{"Class_t_$i"} ne 'regex' || 419 $in{"Class_v_$i"} =~ /\S/ || 420 &error($text{'mod_core_ecregex'}); 421 $in{"Class_t_$i"} ne 'ip' || 422 $in{"Class_v_$i"} =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)\/(\d+)$/ || 423 &error($text{'mod_core_ecip'}); 424 push(@rv, join(" ", $in{"Class_n_$i"}, $in{"Class_t_$i"}, 425 $in{"Class_v_$i"})); 426 } 427return ( \@rv, $in{'Classes'} eq 'on' ? [ 'on' ] : 428 $in{'Classes'} eq 'off' ? [ 'off' ] : [ ] ); 429} 430 431sub edit_CommandBufferSize 432{ 433return (1, $text{'mod_core_buffer'}, 434 &opt_input($_[0]->{'value'}, "CommandBufferSize", $text{'default'}, 5)); 435} 436sub save_CommandBufferSize 437{ 438return &parse_opt("CommandBufferSize", '^\d+$', $text{'mod_core_ebuffer'}); 439} 440 441sub edit_DefaultServer 442{ 443return (1, $text{'mod_core_defaultserver'}, 444 &choice_input($_[0]->{'value'}, "DefaultServer", "off", 445 "$text{'yes'},on", 446 "$text{'no'},off")); 447} 448sub save_DefaultServer 449{ 450return &parse_choice("DefaultServer", "off"); 451} 452 453sub edit_DefaultTransferMode 454{ 455return (1, $text{'mod_core_transfer'}, 456 &select_input($_[0]->{'value'}, "DefaultTransferMode", "", 457 "$text{'mod_core_ascii'},ascii", 458 "$text{'mod_core_binary'},binary", 459 "$text{'default'},")); 460} 461sub save_DefaultTransferMode 462{ 463return &parse_choice("DefaultTransferMode", ""); 464} 465 466sub edit_DeferWelcome 467{ 468return (1, $text{'mod_core_defer'}, 469 &choice_input($_[0]->{'value'}, "DeferWelcome", "", 470 "$text{'yes'},on", "$text{'no'},off", 471 "$text{'default'},")); 472} 473sub save_DeferWelcome 474{ 475return &parse_choice("DeferWelcome", ""); 476} 477 478sub edit_DeleteAbortedStores 479{ 480return (1, $text{'mod_core_aborted'}, 481 &choice_input($_[0]->{'value'}, "DeleteAbortedStores", "", 482 "$text{'yes'},on", "$text{'no'},off", 483 "$text{'default'},")); 484} 485sub save_DeleteAbortedStores 486{ 487return &parse_choice("DeleteAbortedStores", ""); 488} 489 490sub edit_DenyFilter 491{ 492return (1, $text{'mod_core_dfilter'}, 493 &opt_input($_[0]->{'value'}, "DenyFilter", $text{'default'}, 15)); 494} 495sub save_DenyFilter 496{ 497return &parse_opt("DenyFilter"); 498} 499 500sub edit_DenyGroup 501{ 502local $v = @{$_[0]} ? join(" ", (map { $_->{'value'} } @{$_[0]})) : undef; 503return (2, $text{'mod_core_dgroup'}, 504 &opt_input($v, "DenyGroup", $text{'mod_core_none'}, 50)); 505} 506sub save_DenyGroup 507{ 508return ( $in{'DenyGroup_def'} ? [ ] : [ split(/\s+/, $in{'DenyGroup'}) ] ); 509} 510 511sub edit_DenyUser 512{ 513local $v = @{$_[0]} ? join(" ", (map { $_->{'value'} } @{$_[0]})) : undef; 514return (2, $text{'mod_core_duser'}, 515 &opt_input($v, "DenyUser", $text{'mod_core_none'}, 50)); 516} 517sub save_DenyUser 518{ 519return ( $in{'DenyUser_def'} ? [ ] : [ split(/\s+/, $in{'DenyUser'}) ] ); 520} 521 522sub edit_DisplayConnect 523{ 524return (2, $text{'mod_core_display'}, 525 &opt_input($_[0]->{'value'}, "DisplayConnect", 526 $text{'mod_core_none'}, 50)); 527} 528sub save_DisplayConnect 529{ 530return &parse_opt("DisplayConnect", '\S', $text{'mod_core_edisplay'}); 531} 532 533sub edit_DisplayFirstChdir 534{ 535return (1, $text{'mod_core_firstcd'}, 536 &opt_input($_[0]->{'value'}, "DisplayFirstChdir", 537 $text{'mod_core_none'}, 15)); 538} 539sub save_DisplayFirstChdir 540{ 541return &parse_opt("DisplayFirstChdir", '^\S+$', $text{'mod_core_efirstcd'}); 542} 543 544sub edit_DisplayChdir 545{ 546return (1, $text{'mod_core_firstcd'}, 547 &opt_input($_[0]->{'words'}->[0], "DisplayChdir", 548 $text{'mod_core_none'}, 15). 549 &ui_checkbox("DisplayChdir_always", 'true', $text{'mod_core_firstcdt'}, 550 $_[0]->{'words'}->[1] eq 'true')); 551} 552sub save_DisplayChdir 553{ 554local @rv = &parse_opt("DisplayChdir", '^\S+$', $text{'mod_core_efirstcd'}); 555if ($in{'DisplayChdir_always'}) { 556 $rv[0]->[0] .= ' true'; 557 } 558return @rv; 559} 560 561sub edit_DisplayGoAway 562{ 563return (2, $text{'mod_core_goaway'}, 564 &opt_input($_[0]->{'value'}, "DisplayGoAway", 565 $text{'mod_core_none'}, 50)); 566} 567sub save_DisplayGoAway 568{ 569return &parse_opt("DisplayGoAway", '\S', $text{'mod_core_egoaway'}); 570} 571 572sub edit_DisplayLogin 573{ 574return (2, $text{'mod_core_login'}, 575 &opt_input($_[0]->{'value'}, "DisplayLogin", 576 $text{'mod_core_none'}, 50)); 577} 578sub save_DisplayLogin 579{ 580return &parse_opt("DisplayLogin", '\S', $text{'mod_core_elogin'}); 581} 582 583sub edit_DisplayQuit 584{ 585return (2, $text{'mod_core_quit'}, 586 &opt_input($_[0]->{'value'}, "DisplayQuit", 587 $text{'mod_core_none'}, 50)); 588} 589sub save_DisplayQuit 590{ 591return &parse_opt("DisplayQuit", '\S', $text{'mod_core_equit'}); 592} 593 594sub edit_Group 595{ 596local($rv, @ginfo); 597$rv = sprintf "<input type=radio name=Group value=0 %s> $text{'default'}\n", 598 $_[0] ? "" : "checked"; 599$rv .= sprintf "<input type=radio name=Group value=1 %s> %s\n", 600 $_[0] && $_[0]->{'value'} !~ /^#/ ? "checked" : "", 601 $text{'mod_core_gname'}; 602$rv .= sprintf "<input name=Group_name size=8 value=\"%s\"> %s\n", 603 $_[0]->{'value'} !~ /^#/ ? $_[0]->{'value'} : "", 604 &group_chooser_button("Group_name", 0); 605$rv .= sprintf "<input type=radio name=Group value=2 %s> %s\n", 606 $_[0]->{'value'} =~ /^#/ ? "checked" : "", 607 $text{'mod_core_gid'}; 608$rv .= sprintf "<input name=Group_id size=6 value=\"%s\">\n", 609 $_[0]->{'value'} =~ /^#(.*)$/ ? $1 : ""; 610return (2, $text{'mod_core_group'}, $rv); 611} 612sub save_Group 613{ 614if ($in{'Group'} == 0) { return ( [ ] ); } 615elsif ($in{'Group'} == 1) { return ( [ $in{'Group_name'} ] ); } 616elsif ($in{'Group_id'} !~ /^\-?\d+$/) { 617 &error(&text('core_euid', $in{'Group_id'})); 618 } 619else { return ( [ "#$in{'Group_id'}" ] ); } 620} 621 622sub edit_GroupOwner 623{ 624return (1, $text{'mod_core_gowner'}, 625 &opt_input($_[0]->{'value'}, "GroupOwner", $text{'default'}, 13, 626 &group_chooser_button("GroupOwner"))); 627} 628sub save_GroupOwner 629{ 630if ($in{'GroupOwner_def'}) { return ( [ ] ); } 631else { 632 defined(getgrnam($in{'GroupOwner'})) || &error($text{'mod_core_egowner'}); 633 return ( [ $in{'GroupOwner'} ] ); 634 } 635} 636 637sub edit_GroupPassword 638{ 639local $rv = "<table border>\n"; 640$rv .= "<tr $tb> <td><b>$text{'mod_core_gpname'}</b></td> ". 641 "<td><b>$text{'mod_core_gppass'}</b></td> </tr>\n"; 642local $i = 0; 643foreach $g (@{$_[0]}) { 644 local @v = @{$g->{'words'}}; 645 $rv .= "<tr $cb>\n"; 646 $rv .= "<td><input name=GroupPassword_n_$i size=13 value='$v[0]'></td>\n"; 647 $rv .= "<td><input type=radio name=GroupPassword_d_$i value='$v[1]' checked> $text{'mod_core_gpdef'}\n"; 648 $rv .= "<input type=radio name=GroupPassword_d_$i value=0>\n"; 649 $rv .= "<input name=GroupPassword_p_$i size=25></td> </tr>\n"; 650 $i++; 651 } 652$rv .= "<tr $cb>\n". 653 "<td><input name=GroupPassword_n_$i size=13></td>\n". 654 "<td><input name=GroupPassword_p_$i size=35></td>\n". 655 "</tr> </table>\n"; 656return (2, $text{'mod_core_grouppassword'}, $rv); 657} 658sub save_GroupPassword 659{ 660local @rv; 661for($i=0; defined($in{"GroupPassword_n_$i"}); $i++) { 662 next if (!$in{"GroupPassword_n_$i"}); 663 scalar(getgrnam($in{"GroupPassword_n_$i"})) || 664 &error($text{'mod_core_egpname'}); 665 if ($in{"GroupPassword_d_$i"}) { 666 push(@rv, $in{"GroupPassword_n_$i"}.' '. 667 $in{"GroupPassword_d_$i"}); 668 } 669 else { 670 $salt = substr(time(), 0, 2); 671 push(@rv, $in{"GroupPassword_n_$i"}.' '. 672 &unix_crypt($in{"GroupPassword_p_$i"}, $salt)); 673 } 674 } 675return ( \@rv ); 676} 677 678sub edit_HiddenStor 679{ 680return (1, $text{'mod_core_hstor'}, 681 &choice_input($_[0]->{'value'}, "HiddenStor", "", 682 "$text{'yes'},on", "$text{'no'},off", 683 "$text{'default'},")); 684} 685sub save_HiddenStor 686{ 687return &parse_choice("HiddenStor", ""); 688} 689 690sub edit_HiddenStores 691{ 692return (1, $text{'mod_core_hstor'}, 693 &choice_input($_[0]->{'value'}, "HiddenStores", "", 694 "$text{'yes'},on", "$text{'no'},off", 695 "$text{'default'},")); 696} 697sub save_HiddenStores 698{ 699return &parse_choice("HiddenStores", ""); 700} 701 702sub edit_HideGroup 703{ 704return (2, $text{'mod_core_hgroup'}, 705 sprintf "<input name=HideGroup size=50 value='%s'>", 706 join(" ", map { $_->{'value'} } @{$_[0]})); 707} 708sub save_HideGroup 709{ 710local @hg = split(/\s+/, $in{'HideGroup'}); 711foreach $g (@hg) { 712 scalar(getgrnam($g)) || &error($text{'mod_core_ehgroup'}); 713 } 714return ( \@hg ); 715} 716 717sub edit_HideNoAccess 718{ 719return (1, $text{'mod_core_hnoaccess'}, 720 &choice_input($_[0]->{'value'}, "HideNoAccess", "", 721 "$text{'yes'},on", "$text{'no'},off", 722 "$text{'default'},")); 723} 724sub save_HideNoAccess 725{ 726return &parse_choice("HideNoAccess", ""); 727} 728 729sub edit_HideUser 730{ 731return (2, $text{'mod_core_huser'}, 732 sprintf "<input name=HideUser size=50 value='%s'>", 733 join(" ", map { $_->{'value'} } @{$_[0]})); 734} 735sub save_HideUser 736{ 737local @hu = split(/\s+/, $in{'HideUser'}); 738foreach $u (@hu) { 739 defined(getpwnam($u)) || &error($text{'mod_core_ehuser'}); 740 } 741return ( \@hu ); 742} 743 744sub edit_IdentLookups 745{ 746return (1, $text{'mod_core_ident'}, 747 &choice_input($_[0]->{'value'}, "IdentLookups", "", 748 "$text{'yes'},on", "$text{'no'},off", 749 "$text{'default'},")); 750} 751sub save_IdentLookups 752{ 753return &parse_choice("IdentLookups", ""); 754} 755 756sub edit_IgnoreHidden 757{ 758return (1, $text{'mod_core_ihidden'}, 759 &choice_input($_[0]->{'value'}, "IgnoreHidden", "off", 760 "$text{'yes'},on", "$text{'no'},off")); 761} 762sub save_IgnoreHidden 763{ 764return &parse_choice("IgnoreHidden", "off"); 765} 766 767sub edit_MasqueradeAddress 768{ 769return (2, $text{'mod_core_masq'}, 770 &opt_input($_[0]->{'value'}, "MasqueradeAddress", 771 $text{'mod_core_masq_def'}, 30)); 772} 773sub save_MasqueradeAddress 774{ 775$in{'MasqueradeAddress_def'} || &to_ipaddress($in{'MasqueradeAddress'}) || 776 &error($text{'mod_core_emasq'}); 777return &parse_opt("MasqueradeAddress"); 778} 779 780sub edit_MaxClients 781{ 782return (2, $text{'mod_core_maxc'}, &edit_max($_[0], "MaxClients")); 783} 784sub save_MaxClients 785{ 786return &save_max("MaxClients"); 787} 788 789sub edit_MaxClientsPerHost 790{ 791return (2, $text{'mod_core_maxch'}, &edit_max($_[0], "MaxClientsPerHost")); 792} 793sub save_MaxClientsPerHost 794{ 795return &save_max("MaxClientsPerHost"); 796} 797 798sub edit_MaxClientsPerUser 799{ 800return (2, $text{'mod_core_maxcu'}, &edit_max($_[0], "MaxClientsPerUser")); 801} 802sub save_MaxClientsPerUser 803{ 804return &save_max("MaxClientsPerUser"); 805} 806 807sub edit_max 808{ 809local $m = !$_[0] ? 0 : 810 $_[0]->{'words'}->[0] eq 'none' ? 1 : 2; 811local $rv = sprintf "<input type=radio name=$_[1]_m value=0 %s> %s\n", 812 $m == 0 ? "checked" : "", $text{'default'}; 813$rv .= sprintf "<input type=radio name=$_[1]_m value=1 %s> %s\n", 814 $m == 1 ? "checked" : "", $text{'mod_core_maxc1'}; 815$rv .= sprintf "<input type=radio name=$_[1]_m value=2 %s>\n", 816 $m == 2 ? "checked" : ""; 817$rv .= sprintf "<input name=$_[1] size=6 value='%s'><br>\n", 818 $m == 2 ? $_[0]->{'words'}->[0] : ""; 819$rv .= sprintf "%s <input name=$_[1]_t size=40 value='%s'>\n", 820 $text{'mod_core_maxcmsg'}, $_[0]->{'words'}->[1]; 821return $rv; 822} 823sub save_max 824{ 825if ($in{"$_[0]_m"} == 0) { 826 return ( [ ] ); 827 } 828else { 829 local $n; 830 if ($in{"$_[0]_m"} == 1) { 831 $n = "none"; 832 } 833 else { 834 $in{$_[0]} =~ /^\d+$/ || &error($text{'mod_core_emaxc'}); 835 $n = $in{$_[0]}; 836 } 837 if ($in{"$_[0]_t"}) { 838 return ( [ "$n \"".$in{"$_[0]_t"}."\"" ] ); 839 } 840 else { 841 return ( [ $n ] ); 842 } 843 } 844} 845 846sub edit_MaxInstances 847{ 848return (1, $text{'mod_core_instances'}, 849 &opt_input($_[0]->{'value'}, "MaxInstances", $text{'default'}, 4)); 850} 851sub save_MaxInstances 852{ 853return &parse_opt("MaxInstances", '^\d+$', $text{'mod_core_einstances'}); 854} 855 856sub edit_MaxLoginAttempts 857{ 858return (1, $text{'mod_core_logins'}, 859 &opt_input($_[0]->{'value'}, "MaxLoginAttempts", $text{'default'}, 4)); 860} 861sub save_MaxLoginAttempts 862{ 863return &parse_opt("MaxLoginAttempts", '^\d+$', $text{'mod_core_elogins'}); 864} 865 866sub edit_MultilineRFC2228 867{ 868return (1, $text{'mod_core_rfc2228'}, 869 &choice_input($_[0]->{'value'}, "MultilineRFC2228", "", 870 "$text{'yes'},on", "$text{'no'},off", 871 "$text{'default'},")); 872} 873sub save_MultilineRFC2228 874{ 875return &parse_choice("MultilineRFC2228", ""); 876} 877 878sub edit_PassivePorts 879{ 880local $rv = sprintf "<input type=radio name=PassivePorts_def value=1 %s> %s\n", 881 $_[0] ? "" : "checked", $text{'default'}; 882$rv .= sprintf "<input type=radio name=PassivePorts_def value=0 %s> %s\n", 883 $_[0] ? "checked" : "", $text{'mod_core_pasvr'}; 884$rv .= sprintf "<input name=PassivePorts_f size=5 value='%s'> -\n", 885 $_[0]->{'words'}->[0]; 886$rv .= sprintf "<input name=PassivePorts_t size=5 value='%s'>\n", 887 $_[0]->{'words'}->[1]; 888return (1, $text{'mod_core_pasv'}, $rv); 889} 890sub save_PassivePorts 891{ 892if ($in{'PassivePorts_def'}) { 893 return ( [ ] ); 894 } 895else { 896 $in{'PassivePorts_f'} =~ /^\d+$/ || &error($text{'mod_core_epasv'}); 897 $in{'PassivePorts_t'} =~ /^\d+$/ || &error($text{'mod_core_epasv'}); 898 return ( [ "$in{'PassivePorts_f'} $in{'PassivePorts_t'}" ] ); 899 } 900} 901 902sub edit_PathAllowFilter 903{ 904return (1, $text{'mod_core_pathallow'}, 905 &opt_input($_[0]->{'words'}->[0], "PathAllowFilter", 906 $text{'mod_core_any'}, 20)); 907} 908sub save_PathAllowFilter 909{ 910return &parse_opt("PathAllowFilter"); 911} 912 913sub edit_PathDenyFilter 914{ 915return (1, $text{'mod_core_pathdeny'}, 916 &opt_input($_[0]->{'words'}->[0], "PathDenyFilter", 917 $text{'mod_core_none'}, 20)); 918} 919sub save_PathDenyFilter 920{ 921return &parse_opt("PathDenyFilter"); 922} 923 924sub edit_PidFile 925{ 926return (2, $text{'mod_core_pidfile'}, 927 &opt_input($_[0]->{'words'}->[0], "PidFile", $text{'default'}, 50, 928 &file_chooser_button("PidFile"))); 929} 930sub save_PidFile 931{ 932return &parse_opt("PidFile", '^\/\S+$', $text{'mod_core_epidfile'}); 933} 934 935sub edit_Port 936{ 937return (1, $text{'mod_core_port'}, 938 &opt_input($_[0]->{'value'}, "Port", $text{'default'}, 6)); 939} 940sub save_Port 941{ 942return &parse_opt("Port", '^\d+$', $text{'mod_core_eport'}); 943} 944 945sub edit_RequireValidShell 946{ 947return (1, $text{'mod_core_shell'}, 948 &choice_input($_[0]->{'value'}, "RequireValidShell", "", 949 "$text{'yes'},on", "$text{'no'},off", 950 "$text{'default'},")); 951} 952sub save_RequireValidShell 953{ 954return &parse_choice("RequireValidShell", ""); 955} 956 957sub edit_RLimitCPU 958{ 959return &rlimit_input("RLimitCPU", $text{'mod_core_cpulimit'}, $_[0]); 960} 961sub save_RLimitCPU 962{ 963return &parse_rlimit("RLimitCPU", $text{'mod_core_ecpulimit'}); 964} 965 966sub edit_RLimitMemory 967{ 968return &rlimit_input("RLimitMemory", $text{'mod_core_memlimit'}, $_[0]); 969} 970sub save_RLimitMemory 971{ 972return &parse_rlimit("RLimitMemory", $text{'mod_core_ememlimit'}); 973} 974 975sub edit_RLimitOpenFiles 976{ 977return &rlimit_input("RLimitOpenFiles", $text{'mod_core_filelimit'}, $_[0]); 978} 979sub save_RLimitOpenFiles 980{ 981return &parse_rlimit("RLimitOpenFiles", $text{'mod_core_efilelimit'}); 982} 983 984# rlimit_input(name, desc, value) 985sub rlimit_input 986{ 987local @w = @{$_[2]->{'words'}}; 988local $rv; 989$rv .= sprintf "<b>%s</b> <input type=radio name=%s_smax value=2 %s> %s\n", 990 $text{'mod_core_soft'}, $_[0], $w[0] ? "" : "checked", 991 $text{'default'}; 992$rv .= sprintf "<input type=radio name=%s_smax value=1 %s> %s\n", 993 $_[0], $w[0] eq 'max' ? "checked" : "", $text{'mod_core_max'}; 994$rv .= sprintf "<input type=radio name=%s_smax value=0 %s>\n", 995 $_[0], !$w[0] || $w[0] eq 'max' ? "" : "checked"; 996$rv .= sprintf "<input name=%s_soft size=6 value='%s'>\n", 997 $_[0], $w[0] eq 'max' ? '' : $w[0]; 998$rv .= " "; 999 1000$rv .= sprintf "<b>%s</b> <input type=radio name=%s_hmax value=2 %s> %s\n", 1001 $text{'mod_core_hard'}, $_[0], $w[1] ? "" : "checked", 1002 $text{'default'}; 1003$rv .= sprintf "<input type=radio name=%s_hmax value=1 %s> %s\n", 1004 $_[0], $w[1] eq 'max' ? "checked" : "", $text{'mod_core_max'}; 1005$rv .= sprintf "<input type=radio name=%s_hmax value=0 %s>\n", 1006 $_[0], !$w[1] || $w[1] eq 'max' ? "" : "checked"; 1007$rv .= sprintf "<input name=%s_hard size=6 value='%s'>\n", 1008 $_[0], $w[1] eq 'max' ? '' : $w[1]; 1009return (2, $_[1], $rv); 1010} 1011 1012# parse_rlimit(name, desc) 1013sub parse_rlimit 1014{ 1015if ($in{"$_[0]_smax"} == 2) { 1016 return ( [ ] ); 1017 } 1018local @v; 1019if ($in{"$_[0]_smax"} == 1) { 1020 push(@v, "max"); 1021 } 1022else { 1023 $in{"$_[0]_soft"} =~ /^(\d+)(G|M|K|B)?$/i || 1024 &error(&text('mod_core_esoft', $_[1])); 1025 push(@v, $in{"$_[0]_soft"}); 1026 } 1027if ($in{"$_[0]_hmax"} == 1) { 1028 push(@v, "max"); 1029 } 1030elsif ($in{"$_[0]_hmax"} == 0) { 1031 $in{"$_[0]_hard"} =~ /^(\d+)(G|M|K|B)?$/i || 1032 &error(&text('mod_core_ehard', $_[1])); 1033 push(@v, $in{"$_[0]_hard"}); 1034 } 1035return ( [ join(" ", @v) ] ); 1036} 1037 1038sub edit_ScoreboardPath 1039{ 1040return (2, $text{'mod_core_score'}, 1041 &opt_input($_[0]->{'words'}->[0], "ScoreboardPath", $text{'default'}, 1042 50, &file_chooser_button("ScoreboardPath"))); 1043} 1044sub save_ScoreboardPath 1045{ 1046return &parse_opt("ScoreboardPath", '^\/\S+$', $text{'mod_core_escore'}); 1047} 1048 1049sub edit_ServerAdmin 1050{ 1051return (2, $text{'mod_core_admin'}, 1052 &opt_input($_[0]->{'words'}->[0], "ServerAdmin", $text{'default'}, 40)); 1053} 1054sub save_ServerAdmin 1055{ 1056return &parse_opt("ServerAdmin", '^\S+\@\S+$', $text{'mod_core_eadmin'}); 1057} 1058 1059sub edit_ServerIdent 1060{ 1061local @w = @{$_[0]->{'words'}}; 1062local $rv = sprintf "<input type=radio name=ServerIdent_m value=0 %s> %s\n", 1063 $_[0] ? "" : "checked", $text{'default'}; 1064$rv .= sprintf "<input type=radio name=ServerIdent_m value=1 %s> %s\n", 1065 lc($w[0]) eq 'off' ? "checked" : "", $text{'mod_core_none'}; 1066$rv .= sprintf "<input type=radio name=ServerIdent_m value=2 %s> %s\n", 1067 lc($w[0]) eq 'on' && !$w[1] ? "checked" : "", 1068 $text{'mod_core_identmsg_def'}; 1069$rv .= sprintf "<input type=radio name=ServerIdent_m value=3 %s>\n", 1070 lc($w[0]) eq 'on' && $w[1] ? "checked" : ""; 1071$rv .= sprintf "<input name=ServerIdent size=30 value='%s'>\n", 1072 lc($w[0]) eq 'on' ? $w[1] : ""; 1073return (2, $text{'mod_core_identmsg'}, $rv); 1074} 1075sub save_ServerIdent 1076{ 1077if ($in{'ServerIdent_m'} == 0) { 1078 return ( [ ] ); 1079 } 1080elsif ($in{'ServerIdent_m'} == 1) { 1081 return ( [ "off" ] ); 1082 } 1083elsif ($in{'ServerIdent_m'} == 2) { 1084 return ( [ "on" ] ); 1085 } 1086else { 1087 return ( [ "on \"$in{'ServerIdent'}\"" ] ); 1088 } 1089} 1090 1091sub edit_ServerName 1092{ 1093return (2, $text{'mod_core_servername'}, 1094 &opt_input($_[0]->{'words'}->[0], "ServerName", $text{'default'}, 50)); 1095} 1096sub save_ServerName 1097{ 1098return &parse_opt("ServerName", '\S', $text{'mod_core_eservername'}); 1099} 1100 1101sub edit_ServerType 1102{ 1103return (1, $text{'mod_core_type'}, 1104 &select_input($_[0]->{'value'}, "ServerType", "", 1105 "$text{'mod_core_inetd'},inetd", 1106 "$text{'mod_core_stand'},standalone", 1107 "$text{'default'},")); 1108} 1109sub save_ServerType 1110{ 1111return &parse_choice("ServerType", ""); 1112} 1113 1114sub edit_ShowSymlinks 1115{ 1116return (1, $text{'mod_core_links'}, 1117 &choice_input($_[0]->{'value'}, "ShowSymlinks", "", 1118 "$text{'yes'},on", "$text{'no'},off", 1119 "$text{'default'},")); 1120} 1121sub save_ShowSymlinks 1122{ 1123return &parse_choice("ShowSymlinks", ""); 1124} 1125 1126sub edit_SocketBindTight 1127{ 1128return (1, $text{'mod_core_tight'}, 1129 &choice_input($_[0]->{'value'}, "SocketBindTight", "", 1130 "$text{'yes'},on", "$text{'no'},off", 1131 "$text{'default'},")); 1132} 1133sub save_SocketBindTight 1134{ 1135return &parse_choice("SocketBindTight", ""); 1136} 1137 1138sub edit_SyslogFacility 1139{ 1140local @facils = map { "$_,$_" } ( 'auth', 'authpriv', 'cron', 'daemon', 'kern', 'lpr', 'mail', 'news', 'user', 'uucp', 'local0', 'local1', 'local2', 'local3', 'local4', 'local5', 'local6', 'local7' ); 1141return (1, $text{'mod_core_facility'}, 1142 &select_input($_[0]->{'value'}, "SyslogFacility", "", 1143 "$text{'default'},", @facils)); 1144} 1145sub save_SyslogFacility 1146{ 1147return &parse_select("SyslogFacility", ""); 1148} 1149 1150sub edit_SyslogLevel 1151{ 1152local @levels = map { "$_,$_" } ( 'emerg', 'alert', 'crit', 'error', 'warn', 'notice', 'info', 'debug' ); 1153return (1, $text{'mod_core_level'}, 1154 &select_input($_[0]->{'value'}, "SyslogLevel", "", 1155 "$text{'default'},", @levels)); 1156} 1157sub save_SyslogLevel 1158{ 1159return &parse_select("SyslogLevel", ""); 1160} 1161 1162sub edit_TransferLog 1163{ 1164local $mode = $_[0]->{'value'} eq 'NONE' ? 2 : 1165 $_[0]->{'value'} ? 0 : 1; 1166local $rv = sprintf "<input type=radio name=TransferLog_def value=1 %s> %s\n", 1167 $mode == 1 ? "checked" : "", $text{'default'}; 1168if ($_[1]->{'version'} >= 1.17) { 1169 $rv .= sprintf"<input type=radio name=TransferLog_def value=2 %s> %s\n", 1170 $mode == 2 ? "checked" : "", $text{'mod_core_nowhere'}; 1171 } 1172$rv .= sprintf "<input type=radio name=TransferLog_def value=0 %s>\n", 1173 $mode == 0 ? "checked" : ""; 1174$rv .= sprintf "<input name=TransferLog size=50 value='%s'>\n", 1175 $mode == 0 ? $_[0]->{'value'} : ""; 1176return (2, $text{'mod_core_tlog'}, $rv); 1177} 1178sub save_TransferLog 1179{ 1180if ($in{'TransferLog_def'} == 1) { 1181 return ( [ ] ); 1182 } 1183elsif ($in{'TransferLog_def'} == 2) { 1184 return ( [ 'NONE' ] ); 1185 } 1186else { 1187 $in{'TransferLog'} =~ /^\/\S+$/ || &error($text{'mod_core_etlog'}); 1188 return ( [ $in{'TransferLog'} ] ); 1189 } 1190} 1191 1192sub edit_tcpBackLog 1193{ 1194return (1, $text{'mod_core_backlog'}, 1195 &opt_input($_[0]->{'value'}, "tcpBackLog", $text{'default'}, 6)); 1196} 1197sub save_tcpBackLog 1198{ 1199return &parse_opt("tcpBackLog", '^\d+$', $text{'mod_core_ebacklog'}); 1200} 1201 1202sub edit_tcpNoDelay 1203{ 1204return (1, $text{'mod_core_nodelay'}, 1205 &choice_input($_[0]->{'value'}, "tcpNoDelay", "", 1206 "$text{'yes'},on", "$text{'no'},off", 1207 "$text{'default'},")); 1208} 1209sub save_tcpNoDelay 1210{ 1211return &parse_choice("tcpNoDelay", ""); 1212} 1213 1214sub edit_tcpReceiveWindow 1215{ 1216return (1, $text{'mod_core_rwindow'}, 1217 &opt_input($_[0]->{'value'}, "tcpReceiveWindow", $text{'default'}, 6)); 1218} 1219sub save_tcpReceiveWindow 1220{ 1221return &parse_opt("tcpReceiveWindow", '^\d+$', $text{'mod_core_erwindow'}); 1222} 1223 1224sub edit_tcpSendWindow 1225{ 1226return (1, $text{'mod_core_swindow'}, 1227 &opt_input($_[0]->{'value'}, "tcpSendWindow", $text{'default'}, 6)); 1228} 1229sub save_tcpSendWindow 1230{ 1231return &parse_opt("tcpSendWindow", '^\d+$', $text{'mod_core_eswindow'}); 1232} 1233 1234sub edit_TimesGMT 1235{ 1236return (1, $text{'mod_core_gmt'}, 1237 &choice_input($_[0]->{'value'}, "TimesGMT", "", 1238 "$text{'yes'},on", "$text{'no'},off", 1239 "$text{'default'},")); 1240} 1241sub save_TimesGMT 1242{ 1243return &parse_choice("TimesGMT", ""); 1244} 1245 1246sub edit_TimeoutIdle 1247{ 1248return (1, $text{'mod_core_tidle'}, 1249 &opt_input($_[0]->{'value'}, "TimeoutIdle", $text{'default'}, 6, 1250 $text{'mod_core_secs'})); 1251} 1252sub save_TimeoutIdle 1253{ 1254return &parse_opt("TimeoutIdle", '^\d+$', $text{'mod_core_etidle'}); 1255} 1256 1257sub edit_TimeoutLogin 1258{ 1259return (1, $text{'mod_core_tlogin'}, 1260 &opt_input($_[0]->{'value'}, "TimeoutLogin", $text{'default'}, 6, 1261 $text{'mod_core_secs'})); 1262} 1263sub save_TimeoutLogin 1264{ 1265return &parse_opt("TimeoutLogin", '^\d+$', $text{'mod_core_etlogin'}); 1266} 1267 1268sub edit_TimeoutNoTransfer 1269{ 1270return (1, $text{'mod_core_ttransfer'}, 1271 &opt_input($_[0]->{'value'}, "TimeoutNoTransfer", $text{'default'}, 6, 1272 $text{'mod_core_secs'})); 1273} 1274sub save_TimeoutNoTransfer 1275{ 1276return &parse_opt("TimeoutNoTransfer", '^\d+$', $text{'mod_core_ettransfer'}); 1277} 1278 1279sub edit_TimeoutStalled 1280{ 1281return (1, $text{'mod_core_tstalled'}, 1282 &opt_input($_[0]->{'value'}, "TimeoutStalled", $text{'default'}, 6, 1283 $text{'mod_core_secs'})); 1284} 1285sub save_TimeoutStalled 1286{ 1287return &parse_opt("TimeoutStalled", '^\d+$', $text{'mod_core_etstalled'}); 1288} 1289 1290sub edit_Umask 1291{ 1292local $rv; 1293$rv .= sprintf "<input type=radio name=Umask_def value=1 %s> %s\n", 1294 $_[0]->{'words'}->[0] ? "" : "checked", $text{'default'}; 1295$rv .= sprintf "<input type=radio name=Umask_def value=0 %s> %s\n", 1296 $_[0]->{'words'}->[0] ? "checked" : "", $text{'mod_core_octal'}; 1297$rv .= sprintf "<input name=Umask size=5 value='%s'>\n", 1298 $_[0]->{'words'}->[0]; 1299 1300$rv .= " <b>$text{'mod_core_umask_d'}</b>\n"; 1301$rv .= sprintf "<input type=radio name=Umask_d_def value=1 %s> %s\n", 1302 $_[0]->{'words'}->[1] ? "" : "checked", $text{'default'}; 1303$rv .= sprintf "<input type=radio name=Umask_d_def value=0 %s> %s\n", 1304 $_[0]->{'words'}->[1] ? "checked" : "", $text{'mod_core_octal'}; 1305$rv .= sprintf "<input name=Umask_d size=5 value='%s'>\n", 1306 $_[0]->{'words'}->[1]; 1307 1308return (2, $text{'mod_core_umask'}, $rv); 1309} 1310sub save_Umask 1311{ 1312if ($in{'Umask_def'}) { 1313 return ( [ ] ); 1314 } 1315else { 1316 $in{'Umask'} =~ /^[0-7]{3}$/ || &error($text{'mod_core_eumask'}); 1317 if ($in{'Umask_d_def'}) { 1318 return ( [ $in{'Umask'} ] ); 1319 } 1320 else { 1321 $in{'Umask_d'} =~ /^[0-7]{3}$/ || &error($text{'mod_core_eumask'}); 1322 return ( [ $in{'Umask'}." ".$in{'Umask_d'} ] ); 1323 } 1324 } 1325} 1326 1327sub edit_UseFtpUsers 1328{ 1329return (1, $text{'mod_core_ftpusers'}, 1330 &choice_input($_[0]->{'value'}, "UseFtpUsers", "", 1331 "$text{'yes'},on", "$text{'no'},off", 1332 "$text{'default'},")); 1333} 1334sub save_UseFtpUsers 1335{ 1336return &parse_choice("UseFtpUsers", ""); 1337} 1338 1339sub edit_UseHostsAllowFile 1340{ 1341return (2, $text{'mod_core_hostsallow'}, 1342 &opt_input($_[0]->{'value'}, "UseHostsAllowFile", $text{'default'}, 50, 1343 &file_chooser_button("UseHostsAllowFile"))); 1344} 1345sub save_UseHostsAllowFile 1346{ 1347$in{'UseHostsAllowFile_def'} || -r $in{'UseHostsAllowFile'} || 1348 &error($text{'mod_core_ehostsallow'}); 1349return &parse_opt("UseHostsAllowFile"); 1350} 1351 1352sub edit_UseHostsDenyFile 1353{ 1354return (2, $text{'mod_core_hostsdeny'}, 1355 &opt_input($_[0]->{'value'}, "UseHostsDenyFile", $text{'default'}, 50, 1356 &file_chooser_button("UseHostsDenyFile"))); 1357} 1358sub save_UseHostsDenyFile 1359{ 1360$in{'UseHostsDenyFile_def'} || -r $in{'UseHostsDenyFile'} || 1361 &error($text{'mod_core_ehostsdeny'}); 1362return &parse_opt("UseHostsDenyFile"); 1363} 1364 1365sub edit_UseReverseDNS 1366{ 1367return (1, $text{'mod_core_revdns'}, 1368 &choice_input($_[0]->{'value'}, "UseReverseDNS", "", 1369 "$text{'yes'},on", "$text{'no'},off", 1370 "$text{'default'},")); 1371} 1372sub save_UseReverseDNS 1373{ 1374return &parse_choice("UseReverseDNS", ""); 1375} 1376 1377sub edit_UserDirRoot 1378{ 1379return (1, $text{'mod_core_userdir'}, 1380 &choice_input($_[0]->{'value'}, "UserDirRoot", "", 1381 "$text{'yes'},on", "$text{'no'},off", 1382 "$text{'default'},")); 1383} 1384sub save_UserDirRoot 1385{ 1386return &parse_choice("UserDirRoot", ""); 1387} 1388 1389sub edit_User 1390{ 1391local($rv, @uinfo); 1392$rv = sprintf "<input type=radio name=User value=0 %s> $text{'default'}\n", 1393 $_[0] ? "" : "checked"; 1394$rv .= sprintf "<input type=radio name=User value=1 %s> %s\n", 1395 $_[0] && $_[0]->{'value'} !~ /^#/ ? "checked" : "", 1396 $text{'mod_core_uname'}; 1397$rv .= sprintf "<input name=User_name size=8 value=\"%s\"> %s \n", 1398 $_[0]->{'value'} !~ /^#/ ? $_[0]->{'value'} : "", 1399 &user_chooser_button("User_name", 0); 1400$rv .= sprintf "<input type=radio name=User value=2 %s> %s\n", 1401 $_[0]->{'value'} =~ /^#/ ? "checked" : "", 1402 $text{'mod_core_uid'}; 1403$rv .= sprintf "<input name=User_id size=6 value=\"%s\">\n", 1404 $_[0]->{'value'} =~ /^#(.*)$/ ? $1 : ""; 1405return (2, $text{'mod_core_user'}, $rv); 1406} 1407sub save_User 1408{ 1409if ($in{'User'} == 0) { return ( [ ] ); } 1410elsif ($in{'User'} == 1) { return ( [ $in{'User_name'} ] ); } 1411elsif ($in{'User_id'} !~ /^\-?\d+$/) { 1412 &error(&text('core_egid', $in{'User_id'})); 1413 } 1414else { return ( [ "#$in{'User_id'}" ] ); } 1415} 1416 1417sub edit_UserAlias 1418{ 1419local $rv = "<table border>\n". 1420 "<tr $tb> <td><b>$text{'mod_core_afrom'}</b></td> ". 1421 "<td><b>$text{'mod_core_ato'}</b></td> </tr>\n"; 1422local $i = 0; 1423foreach $u (@{$_[0]}, { }) { 1424 local @w = @{$u->{'words'}}; 1425 $rv .= "<tr $cb>\n"; 1426 $rv .= "<td><input name=UserAlias_f_$i size=15 value='$w[0]'></td>\n"; 1427 $rv .= "<td><input name=UserAlias_t_$i size=15 value='$w[1]'></td>\n"; 1428 $rv .= "</tr>\n"; 1429 $i++; 1430 } 1431$rv .= "</table>\n"; 1432return (2, $text{'mod_core_ualias'}, $rv); 1433} 1434sub save_UserAlias 1435{ 1436local @rv; 1437for($i=0; defined($in{"UserAlias_f_$i"}); $i++) { 1438 next if (!$in{"UserAlias_f_$i"}); 1439 $in{"UserAlias_f_$i"} =~ /^\S+$/ || &error($text{'mod_core_eafrom'}); 1440 $in{"UserAlias_t_$i"} =~ /^\S+$/ || &error($text{'mod_core_eato'}); 1441 push(@rv, $in{"UserAlias_f_$i"}.' '.$in{"UserAlias_t_$i"}); 1442 } 1443return ( \@rv ); 1444} 1445 1446sub edit_UserOwner 1447{ 1448return (1, $text{'mod_core_uowner'}, 1449 &opt_input($_[0]->{'value'}, "UserOwner", $text{'default'}, 13, 1450 &user_chooser_button("UserOwner"))); 1451} 1452sub save_UserOwner 1453{ 1454if ($in{'UserOwner_def'}) { return ( [ ] ); } 1455else { 1456 getpwnam($in{'UserOwner'}) || &error($text{'mod_core_euowner'}); 1457 return ( [ $in{'UserOwner'} ] ); 1458 } 1459} 1460 1461sub edit_UserPassword 1462{ 1463local $rv = "<table border>\n"; 1464$rv .= "<tr $tb> <td><b>$text{'mod_core_upname'}</b></td> ". 1465 "<td><b>$text{'mod_core_uppass'}</b></td> </tr>\n"; 1466local $i = 0; 1467foreach $u (@{$_[0]}) { 1468 local @v = @{$u->{'words'}}; 1469 $rv .= "<tr $cb>\n"; 1470 $rv .= "<td><input name=UserPassword_n_$i size=13 value='$v[0]'></td>\n"; 1471 $rv .= "<td><input type=radio name=UserPassword_d_$i value='$v[1]' checked> $text{'mod_core_updef'}\n"; 1472 $rv .= "<input type=radio name=UserPassword_d_$i value=0>\n"; 1473 $rv .= "<input name=UserPassword_p_$i size=25></td> </tr>\n"; 1474 $i++; 1475 } 1476$rv .= "<tr $cb>\n". 1477 "<td><input name=UserPassword_n_$i size=13></td>\n". 1478 "<td><input name=UserPassword_p_$i size=35></td>\n". 1479 "</tr> </table>\n"; 1480return (2, $text{'mod_core_userpassword'}, $rv); 1481} 1482sub save_UserPassword 1483{ 1484local @rv; 1485for($i=0; defined($in{"UserPassword_n_$i"}); $i++) { 1486 next if (!$in{"UserPassword_n_$i"}); 1487 scalar(getpwnam($in{"UserPassword_n_$i"})) || 1488 &error($text{'mod_core_eupname'}); 1489 if ($in{"UserPassword_d_$i"}) { 1490 push(@rv, $in{"UserPassword_n_$i"}.' '. 1491 $in{"UserPassword_d_$i"}); 1492 } 1493 else { 1494 $salt = substr(time(), 0, 2); 1495 push(@rv, $in{"UserPassword_n_$i"}.' '. 1496 &unix_crypt($in{"UserPassword_p_$i"}, $salt)); 1497 } 1498 } 1499return ( \@rv ); 1500} 1501 1502sub edit_WtmpLog 1503{ 1504return (1, $text{'mod_core_wtmp'}, 1505 &choice_input($_[0]->{'value'}, "WtmpLog", "", 1506 "$text{'yes'},on", "$text{'no'},off", 1507 "$text{'mod_core_none'},NONE", "$text{'default'},")); 1508} 1509sub save_WtmpLog 1510{ 1511return &parse_choice("WtmpLog", ""); 1512} 1513 1514