# Functions for managing the PHP configuration file BEGIN { push(@INC, ".."); }; use WebminCore; &init_config(); %access = &get_module_acl(); # Fix language strings that refer to MySQL if (&foreign_check("mysql")) { &foreign_require("mysql"); &mysql::fix_mysql_text(\%text); } # get_config_fmt(file) # Returns a format code for php.ini or FPM config files sub get_config_fmt { local ($file) = @_; return $file =~ /\.conf$/ ? "fpm" : "ini"; } # get_config([file]) # Returns an array ref of PHP configuration directives from some file sub get_config { local ($file) = @_; $file ||= &get_default_php_ini(); local $fmt = &get_config_fmt($file); if (!defined($get_config_cache{$file})) { local @rv = ( ); local $lnum = 0; local $section; open(CONFIG, "<".$file) || return undef; if ($fmt eq "ini") { # Classic php.ini format while(<CONFIG>) { s/\r|\n//g; s/\s+$//; local $uq; if (/^(;?)\s*(\S+)\s*=\s*"(.*)"/ || /^(;?)\s*(\S+)\s*=\s*'(.*)'/ || ($uq = ($_ =~ /^(;?)\s*(\S+)\s*=\s*(.*)/))) { # Found a variable (php.ini format) push(@rv, { 'name' => $2, 'value' => $3, 'enabled' => !$1, 'line' => $lnum, 'file' => $file, 'section' => $section, 'fmt' => $fmt, }); if ($uq) { # Remove any comments $rv[$#rv]->{'value'} =~ s/\s+;.*$//; } } elsif (/^\[(.*)\]/) { # A new section $section = $1; } $lnum++; } } else { # FPM config file format, with php options while(<CONFIG>) { s/\r|\n//g; s/\s+$//; if (/^(;?)(php_admin_value|php_value)\[(\S+)\]\s*=\s*(.*)/) { # Found an FPM config that sets a PHP variable push(@rv, { 'name' => $3, 'value' => $4, 'admin' => $2 eq "php_admin_value" ? 1 : 0, 'enabled' => !$1, 'line' => $lnum, 'file' => $file, 'fmt' => $fmt, }); } $lnum++; } } close(CONFIG); $get_config_cache{$file} = \@rv; } return $get_config_cache{$file}; } # find(name, &config, [disabled-mode]) # Look up a directive by name sub find { local ($name, $conf, $mode) = @_; local @rv = grep { lc($_->{'name'}) eq lc($name) && ($mode == 0 && $_->{'enabled'} || $mode == 1 && !$_->{'enabled'} || $mode == 2) } @$conf; return wantarray ? @rv : $rv[0]; } sub find_value { local @rv = map { $_->{'value'} } &find(@_); return $rv[0]; } # save_directive(&config, name, [value|&values], [newsection], [neverquote]) # Updates a single entry in the PHP config file sub save_directive { local ($conf, $name, $values, $newsection, $noquote) = @_; my @values = ref($values) ? @$values : ( $values ); $newsection ||= "PHP"; my @old = &find($name, $conf, 0); my @cmt = &find($name, $conf, 1); my $fmt = @old ? $old[0]->{'fmt'} : @$conf ? $conf->[0]->{'fmt'} : "fpm"; my $lref; for(my $i=0; $i<@old || $i<@values; $i++) { my $old = $i<@old ? $old[$i] : undef; my $value = $i<@values ? $values[$i] : undef; my $cmt = $i<@cmt ? $cmt[$i] : undef; if ($fmt eq "ini") { $newline = $name." = ". ($value !~ /\s/ || $noquote ? $value : $value =~ /"/ ? "'$value'" : "\"$value\""); } else { my $n = !$old || $old->{'admin'} ? "php_admin_value" : "php_value"; $newline = $n."[".$name."] = ".$value; } if (defined($value) && $old) { # Update existing value $lref = &read_file_lines_as_user($old->{'file'}); $lref->[$old->{'line'}] = $newline; $old->{'value'} = $value; } elsif (defined($value) && !$old && $cmt) { # Update existing commented value $lref = &read_file_lines_as_user($cmt->{'file'}); $lref->[$cmt->{'line'}] = $newline; $cmt->{'value'} = $value; $cmt->{'enabled'} = 1; } elsif (defined($value) && !$old && !$cmt) { # Add a new value, at the end of the section my ($lastline, $lastfile); if ($fmt eq "ini") { # Find last directive in requested php.ini section my $last; foreach my $c (@$conf) { if ($c->{'section'} eq $newsection) { $last = $c; } } $last || &error("Could not find any values in ". "section $newsection"); $lastfile = $last->{'file'}; $lastline = $last->{'line'}; $lref = &read_file_lines_as_user($lastfile); } else { # Just add at the end $lastfile = @$conf ? $conf->[0]->{'file'} : undef; $lastfile || &error("Don't know which file to add to"); $lref = &read_file_lines_as_user($lastfile); $lastline = scalar(@$lref); } # Found last value in the section - add after it splice(@$lref, $lastline+1, 0, $newline); &renumber($conf, $lastline, 1); push(@$conf, { 'name' => $name, 'value' => $value, 'enabled' => 1, 'file' => $lastfile, 'line' => $lastline+1, 'section' => $newsection, }); } elsif (!defined($value) && $old && $cmt) { # Totally remove a value $lref = &read_file_lines_as_user($old->{'file'}); splice(@$lref, $old->{'line'}, 1); @$conf = grep { $_ ne $old } @$conf; &renumber($conf, $old->{'line'}, -1); } elsif (!defined($value) && $old && !$cmt) { # Turn a value into a comment $lref = &read_file_lines_as_user($old->{'file'}); $old->{'enabled'} = 0; $lref->[$old->{'line'}] = "; ".$lref->[$old->{'line'}]; } } } sub renumber { local ($conf, $line, $oset) = @_; foreach my $c (@$conf) { $c->{'line'} += $oset if ($c->{'line'} > $line); } } # can_php_config(file) # Returns 1 if some config file can be edited sub can_php_config { local ($file) = @_; return &indexof($file, map { $_->[0] } &list_php_configs()) >= 0 || $access{'anyfile'}; } # get_default_php_ini() # Returns the first php.ini that exists sub get_default_php_ini { local @inis = split(/\t+/, $config{'php_ini'}); foreach my $ai (@inis) { local ($f, $d) = split(/=/, $ai); local @f = glob($f); return $f[0] if (@f && -r $f[0]); } if ($config{'alt_php_ini'} && -r $config{'alt_php_ini'} && @inis) { # Fall back to default file local ($f) = split(/=/, $inis[0]); ©_source_dest($config{'alt_php_ini'}, $f); return $f; } return undef; } # list_php_configs() # Returns a list of allowed config files and descriptions sub list_php_configs { local @rv; &get_default_php_ini(); # Force copy of sample ini file # Add system-wide INI files if ($access{'global'}) { foreach my $ai (split(/\t+/, $config{'php_ini'})) { local ($f, $d) = split(/=/, $ai); foreach my $fp (split(/,/, $f)) { foreach my $gf (glob($fp)) { push(@rv, [ $gf, $d || $text{'file_global'} ]); } } } } # Add INI files from ACL foreach my $ai (split(/\t+/, $access{'php_inis'})) { local ($f, $d) = split(/=/, $ai); foreach my $fp (split(/,/, $f)) { foreach my $gf (glob($fp)) { push(@rv, [ $gf, $d || $gf ]); } } } # Convert dirs to files foreach my $i (@rv) { if (-d $i->[0] && -r "$i->[0]/php.ini") { $i->[0] = "$i->[0]/php.ini"; } } # Add PHP INI files from Virtualmin if ($access{'global'} && &foreign_check("virtual-server")) { &foreign_require("virtual-server"); foreach my $v (&virtual_server::list_available_php_versions()) { if ($v->[0]) { my $ini = &virtual_server::get_global_php_ini($v->[0]); push(@rv, [ $ini, "PHP $v->[0]" ]) if ($ini && -r $ini); } } } my %done; return grep { !$done{$_->[0]}++ } @rv; } # get_php_ini_binary(file) # Given a php.ini path, try to guess the php command for it sub get_php_ini_binary { my ($file) = @_; # Possible php.ini under domain's home dir if (&foreign_check("virtual-server")) { &foreign_require("virtual-server"); my %vmap = map { $_->[0], $_ } &virtual_server::list_available_php_versions(); if ($file =~ /etc\/php(\S+)\/php.ini/) { my $ver = $1; my $nodot = $ver; $nodot =~ s/\.//g; my $php = $vmap{$ver} || $vmap{$nodot}; if ($php && $php->[1]) { my $binary = $php->[1]; $binary =~ s/-cgi//; return $binary; } } } # Try to get version from the path if ($fle =~ /php(\d+)/) { my $ver = $1; my $nodot = $ver; $nodot =~ s/\.//g; my $binary = &has_command("php$ver") || &has_command("php$nodot"); return $binary if ($binary); } return &has_command("php"); } # onoff_radio(name) # Returns a field for editing a binary configuration value sub onoff_radio { local ($name) = @_; local $v = &find_value($name, $conf); return &ui_radio($name, lc($v) eq "on" || lc($v) eq "true" || lc($v) eq "yes" || $v eq "1" ? "On" : $v ? "Off" : "", [ !$v ? ( [ "", $text{'default'} ] ) : ( ), [ "On", $text{'yes'} ], [ "Off", $text{'no'} ] ]); } # graceful_apache_restart([file]) # Signal a graceful Apache restart, to pick up new php.ini settings sub graceful_apache_restart { local ($file) = @_; if (&foreign_installed("apache")) { &foreign_require("apache", "apache-lib.pl"); if (&apache::is_apache_running() && $apache::httpd_modules{'core'} >= 2 && &has_command($apache::config{'apachectl_path'})) { &clean_environment(); &system_logged("$apache::config{'apachectl_path'} graceful >/dev/null 2>&1"); &reset_environment(); } } if ($file && &get_config_fmt($file) eq "fpm" && &foreign_check("virtual-server")) { # Looks like FPM format ... maybe a pool restart is needed &foreign_require("virtual-server"); if (defined(&virtual_server::restart_php_fpm_server)) { my $conf; if (-r $file) { my @conf; @conf = grep { &is_under_directory($_->{'dir'}, $file) } &virtual_server::list_php_fpm_configs(); if (@conf) { $conf = &virtual_server::get_php_fpm_config( $conf[0]->{'shortversion'}); } } &virtual_server::push_all_print(); &virtual_server::set_all_null_print(); &virtual_server::restart_php_fpm_server($conf); &virtual_server::pop_all_print(); } } if ($file && &get_config_fmt($file) eq "ini" && &foreign_installed("virtual-server") && &foreign_installed("virtualmin-nginx")) { &foreign_require("virtual-server"); &foreign_require("virtualmin-nginx", "virtual_feature.pl"); my @dom = grep { &is_under_directory($_->{'home'}, $file) } &virtual_server::list_domains(); &virtualmin_nginx::feature_restart_web_php($dom[0]) if (@dom); } } # should_switch_user(file) # Returns 1 if file ops should be done as the access user sub should_switch_user { my ($file) = @_; return $access{'user'} && $access{'user'} ne 'root' && $< == 0 && !&is_under_directory("/etc", $file); } # get_config_as_user([file]) # Like get_config, but reads with permissions of the ACL user sub get_config_as_user { local ($file) = @_; if (&should_switch_user($file)) { local $rv = &eval_as_unix_user( $access{'user'}, sub { &get_config($file) }); if ((!$rv || !@$rv) && $!) { &error(&text('file_eread', &html_escape($file), $!)); } return $rv; } else { return &get_config($file); } } # read_file_contents_as_user(file) sub read_file_contents_as_user { local ($file) = @_; if (&should_switch_user($file)) { return &eval_as_unix_user( $access{'user'}, sub { &read_file_contents($file) }); } else { return &read_file_contents($file); } } # write_file_contents_as_user(file, data) # Writes out the contents of some file sub write_file_contents_as_user { local ($file, $data) = @_; if (&should_switch_user($file)) { return &eval_as_unix_user( $access{'user'}, sub { &write_file_contents($file, $data) }); } else { &write_file_contents($file, $data); } } # read_file_lines_as_user(file, ...) sub read_file_lines_as_user { local @args = @_; if (&should_switch_user($file)) { return &eval_as_unix_user( $access{'user'}, sub { &read_file_lines(@args) }); } else { return &read_file_lines(@args); } } # flush_file_lines_as_user(file) # Writes out a file as the Unix user configured in this module's ACL sub flush_file_lines_as_user { local ($file, $eof, $ignore) = @_; if (&should_switch_user($file)) { &eval_as_unix_user($access{'user'}, sub { &flush_file_lines($file, $eof, $ignore) }); } else { &flush_file_lines($file, $eof, $ignore); } } # list_available_extensions(&conf, file) # Returns a list of all available PHP extension modules sub list_available_extensions { my ($conf, $file) = @_; my $dir = &find_value("extension_dir", $conf); if (!$dir) { # Figure it out from the PHP command my $binary = &get_php_ini_binary($file); if ($binary) { my $out = &backquote_command("$binary -i 2>/dev/null </dev/null"); if ($out =~ /extension_dir\s+=>\s+(\S+)/) { $dir = $1; } } } if ($dir) { # Get all the extensions opendir(DIR, $dir); my @exts = grep { /\.so$/ } readdir(DIR); closedir(DIR); return @exts; } return (); } 1;
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
help | Folder | 0755 |
|
|
images | Folder | 0755 |
|
|
lang | Folder | 0755 |
|
|
CHANGELOG | File | 498 B | 0644 |
|
acl_security.pl | File | 987 B | 0755 |
|
backup_config.pl | File | 625 B | 0755 |
|
cgi_args.pl | File | 247 B | 0755 |
|
config | File | 188 B | 0644 |
|
config-Ubuntu-Linux-20.0-ALL | File | 297 B | 0644 |
|
config-debian-linux | File | 180 B | 0644 |
|
config-debian-linux-10.0-ALL | File | 297 B | 0644 |
|
config-debian-linux-4.0-9.0 | File | 254 B | 0644 |
|
config-freebsd | File | 77 B | 0644 |
|
config-openbsd | File | 30 B | 0644 |
|
config-openmamba-linux | File | 25 B | 0644 |
|
config-pardus-linux | File | 33 B | 0644 |
|
config-solaris | File | 29 B | 0644 |
|
config-solaris-11-ALL | File | 32 B | 0644 |
|
config-syno-linux | File | 37 B | 0644 |
|
config.info | File | 99 B | 0644 |
|
config.info.ca | File | 107 B | 0644 |
|
config.info.cs | File | 104 B | 0644 |
|
config.info.de | File | 104 B | 0644 |
|
config.info.fr | File | 107 B | 0644 |
|
config.info.hu | File | 0 B | 0644 |
|
config.info.it | File | 107 B | 0644 |
|
config.info.ko | File | 81 B | 0644 |
|
config.info.nl | File | 101 B | 0644 |
|
config.info.no | File | 101 B | 0644 |
|
config.info.pl | File | 98 B | 0644 |
|
config.info.ru.UTF-8 | File | 0 B | 0644 |
|
defaultacl | File | 38 B | 0644 |
|
edit_db.cgi | File | 2.77 KB | 0755 |
|
edit_dirs.cgi | File | 1.66 KB | 0755 |
|
edit_errors.cgi | File | 2.34 KB | 0755 |
|
edit_limits.cgi | File | 1.57 KB | 0755 |
|
edit_manual.cgi | File | 682 B | 0755 |
|
edit_misc.cgi | File | 2.61 KB | 0755 |
|
edit_session.cgi | File | 1.79 KB | 0755 |
|
edit_vars.cgi | File | 1015 B | 0755 |
|
index.cgi | File | 1.74 KB | 0755 |
|
install_check.pl | File | 496 B | 0755 |
|
list_ini.cgi | File | 952 B | 0755 |
|
log_parser.pl | File | 369 B | 0755 |
|
module.info | File | 167 B | 0644 |
|
module.info.af | File | 0 B | 0644 |
|
module.info.af.auto | File | 124 B | 0644 |
|
module.info.ar | File | 0 B | 0644 |
|
module.info.ar.auto | File | 158 B | 0644 |
|
module.info.be | File | 0 B | 0644 |
|
module.info.be.auto | File | 186 B | 0644 |
|
module.info.bg | File | 0 B | 0644 |
|
module.info.bg.auto | File | 208 B | 0644 |
|
module.info.ca | File | 136 B | 0644 |
|
module.info.cs | File | 24 B | 0644 |
|
module.info.cs.auto | File | 105 B | 0644 |
|
module.info.da | File | 0 B | 0644 |
|
module.info.da.auto | File | 130 B | 0644 |
|
module.info.de | File | 139 B | 0644 |
|
module.info.el | File | 0 B | 0644 |
|
module.info.el.auto | File | 223 B | 0644 |
|
module.info.es | File | 0 B | 0644 |
|
module.info.es.auto | File | 140 B | 0644 |
|
module.info.eu | File | 0 B | 0644 |
|
module.info.eu.auto | File | 125 B | 0644 |
|
module.info.fa | File | 0 B | 0644 |
|
module.info.fa.auto | File | 181 B | 0644 |
|
module.info.fi | File | 0 B | 0644 |
|
module.info.fi.auto | File | 134 B | 0644 |
|
module.info.fr | File | 0 B | 0644 |
|
module.info.fr.auto | File | 142 B | 0644 |
|
module.info.he | File | 0 B | 0644 |
|
module.info.he.auto | File | 156 B | 0644 |
|
module.info.hr | File | 0 B | 0644 |
|
module.info.hr.auto | File | 134 B | 0644 |
|
module.info.hu | File | 27 B | 0644 |
|
module.info.hu.auto | File | 115 B | 0644 |
|
module.info.it | File | 30 B | 0644 |
|
module.info.it.auto | File | 103 B | 0644 |
|
module.info.ja | File | 0 B | 0644 |
|
module.info.ja.auto | File | 124 B | 0644 |
|
module.info.ko | File | 19 B | 0644 |
|
module.info.ko.auto | File | 108 B | 0644 |
|
module.info.lt | File | 0 B | 0644 |
|
module.info.lt.auto | File | 132 B | 0644 |
|
module.info.lv | File | 0 B | 0644 |
|
module.info.lv.auto | File | 138 B | 0644 |
|
module.info.ms | File | 122 B | 0644 |
|
module.info.mt | File | 0 B | 0644 |
|
module.info.mt.auto | File | 141 B | 0644 |
|
module.info.nl | File | 25 B | 0644 |
|
module.info.nl.auto | File | 103 B | 0644 |
|
module.info.no | File | 26 B | 0644 |
|
module.info.no.auto | File | 104 B | 0644 |
|
module.info.pl | File | 129 B | 0644 |
|
module.info.pt | File | 0 B | 0644 |
|
module.info.pt.auto | File | 138 B | 0644 |
|
module.info.pt_BR | File | 0 B | 0644 |
|
module.info.pt_BR.auto | File | 144 B | 0644 |
|
module.info.ro | File | 0 B | 0644 |
|
module.info.ro.auto | File | 130 B | 0644 |
|
module.info.ru | File | 0 B | 0644 |
|
module.info.ru.auto | File | 196 B | 0644 |
|
module.info.sk | File | 0 B | 0644 |
|
module.info.sk.auto | File | 131 B | 0644 |
|
module.info.sl | File | 0 B | 0644 |
|
module.info.sl.auto | File | 129 B | 0644 |
|
module.info.sv | File | 0 B | 0644 |
|
module.info.sv.auto | File | 129 B | 0644 |
|
module.info.th | File | 0 B | 0644 |
|
module.info.th.auto | File | 246 B | 0644 |
|
module.info.tr | File | 0 B | 0644 |
|
module.info.tr.auto | File | 136 B | 0644 |
|
module.info.uk | File | 0 B | 0644 |
|
module.info.uk.auto | File | 202 B | 0644 |
|
module.info.ur | File | 0 B | 0644 |
|
module.info.ur.auto | File | 194 B | 0644 |
|
module.info.vi | File | 0 B | 0644 |
|
module.info.vi.auto | File | 148 B | 0644 |
|
module.info.zh | File | 0 B | 0644 |
|
module.info.zh.auto | File | 94 B | 0644 |
|
module.info.zh_TW | File | 0 B | 0644 |
|
module.info.zh_TW.auto | File | 100 B | 0644 |
|
phpini-lib.pl | File | 12.21 KB | 0755 |
|
save_db.cgi | File | 2.56 KB | 0755 |
|
save_dirs.cgi | File | 1.16 KB | 0755 |
|
save_errors.cgi | File | 1.78 KB | 0755 |
|
save_limits.cgi | File | 1.85 KB | 0755 |
|
save_manual.cgi | File | 611 B | 0755 |
|
save_misc.cgi | File | 1.97 KB | 0755 |
|
save_session.cgi | File | 1.69 KB | 0755 |
|
save_vars.cgi | File | 654 B | 0755 |
|