PageRenderTime 26ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/phpini/phpini-lib.pl

http://github.com/webmin/webmin
Perl | 365 lines | 337 code | 8 blank | 20 comment | 31 complexity | dec0326257c7f0536cd4277eadc1b74b MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-3.0, CC-BY-SA-3.0
  1. # Functions for managing the PHP configuration file
  2. BEGIN { push(@INC, ".."); };
  3. use WebminCore;
  4. &init_config();
  5. %access = &get_module_acl();
  6. # get_config_fmt(file)
  7. # Returns a format code for php.ini or FPM config files
  8. sub get_config_fmt
  9. {
  10. local ($file) = @_;
  11. return $file =~ /\.conf$/ ? "fpm" : "ini";
  12. }
  13. # get_config([file])
  14. # Returns an array ref of PHP configuration directives from some file
  15. sub get_config
  16. {
  17. local ($file) = @_;
  18. $file ||= &get_default_php_ini();
  19. local $fmt = &get_config_fmt($file);
  20. if (!defined($get_config_cache{$file})) {
  21. local @rv = ( );
  22. local $lnum = 0;
  23. local $section;
  24. open(CONFIG, "<".$file) || return undef;
  25. if ($fmt eq "ini") {
  26. # Classic php.ini format
  27. while(<CONFIG>) {
  28. s/\r|\n//g;
  29. s/\s+$//;
  30. local $uq;
  31. if (/^(;?)\s*(\S+)\s*=\s*"(.*)"/ ||
  32. /^(;?)\s*(\S+)\s*=\s*'(.*)'/ ||
  33. ($uq = ($_ =~ /^(;?)\s*(\S+)\s*=\s*(.*)/))) {
  34. # Found a variable (php.ini format)
  35. push(@rv, { 'name' => $2,
  36. 'value' => $3,
  37. 'enabled' => !$1,
  38. 'line' => $lnum,
  39. 'file' => $file,
  40. 'section' => $section,
  41. 'fmt' => $fmt,
  42. });
  43. if ($uq) {
  44. # Remove any comments
  45. $rv[$#rv]->{'value'} =~ s/\s+;.*$//;
  46. }
  47. }
  48. elsif (/^\[(.*)\]/) {
  49. # A new section
  50. $section = $1;
  51. }
  52. $lnum++;
  53. }
  54. }
  55. else {
  56. # FPM config file format, with php options
  57. while(<CONFIG>) {
  58. s/\r|\n//g;
  59. s/\s+$//;
  60. if (/^(;?)php_admin_value\[(\S+)\]\s*=\s*(.*)/) {
  61. # Found an FPM config that sets a PHP variable
  62. push(@rv, { 'name' => $2,
  63. 'value' => $3,
  64. 'enabled' => !$1,
  65. 'line' => $lnum,
  66. 'file' => $file,
  67. 'fmt' => $fmt,
  68. });
  69. }
  70. $lnum++;
  71. }
  72. }
  73. close(CONFIG);
  74. $get_config_cache{$file} = \@rv;
  75. }
  76. return $get_config_cache{$file};
  77. }
  78. # find(name, &config, [disabled-mode])
  79. # Look up a directive by name
  80. sub find
  81. {
  82. local ($name, $conf, $mode) = @_;
  83. local @rv = grep { lc($_->{'name'}) eq lc($name) &&
  84. ($mode == 0 && $_->{'enabled'} ||
  85. $mode == 1 && !$_->{'enabled'} ||
  86. $mode == 2) } @$conf;
  87. return wantarray ? @rv : $rv[0];
  88. }
  89. sub find_value
  90. {
  91. local @rv = map { $_->{'value'} } &find(@_);
  92. return $rv[0];
  93. }
  94. # save_directive(&config, name, [value], [newsection], [neverquote])
  95. # Updates a single entry in the PHP config file
  96. sub save_directive
  97. {
  98. local ($conf, $name, $value, $newsection, $noquote) = @_;
  99. $newsection ||= "PHP";
  100. local $old = &find($name, $conf, 0);
  101. local $cmt = &find($name, $conf, 1);
  102. local $fmt = $old ? $old->{'fmt'} : @$conf ? $conf->[0]->{'fmt'} : "fpm";
  103. local $lref;
  104. if ($fmt eq "ini") {
  105. $newline = $name." = ".
  106. ($value !~ /\s/ || $noquote ? $value :
  107. $value =~ /"/ ? "'$value'" : "\"$value\"");
  108. }
  109. else {
  110. $newline = "php_admin_value[".$name."] = ".$value;
  111. }
  112. if (defined($value) && $old) {
  113. # Update existing value
  114. $lref = &read_file_lines_as_user($old->{'file'});
  115. $lref->[$old->{'line'}] = $newline;
  116. $old->{'value'} = $value;
  117. }
  118. elsif (defined($value) && !$old && $cmt) {
  119. # Update existing commented value
  120. $lref = &read_file_lines_as_user($cmt->{'file'});
  121. $lref->[$cmt->{'line'}] = $newline;
  122. $cmt->{'value'} = $value;
  123. $cmt->{'enabled'} = 1;
  124. }
  125. elsif (defined($value) && !$old && !$cmt) {
  126. # Add a new value, at the end of the section
  127. my ($lastline, $lastfile);
  128. if ($fmt eq "ini") {
  129. # Find last directive in requested php.ini section
  130. my $last;
  131. foreach my $c (@$conf) {
  132. if ($c->{'section'} eq $newsection) {
  133. $last = $c;
  134. }
  135. }
  136. $last || &error("Could not find any values in ".
  137. "section $newsection");
  138. $lastfile = $last->{'file'};
  139. $lastline = $last->{'line'};
  140. $lref = &read_file_lines_as_user($lastfile);
  141. }
  142. else {
  143. # Just add at the end
  144. $lastfile = @$conf ? $conf->[0]->{'file'} : undef;
  145. $lastfile || &error("Don't know which file to add to");
  146. $lref = &read_file_lines_as_user($lastfile);
  147. $lastline = scalar(@$lref);
  148. }
  149. # Found last value in the section - add after it
  150. splice(@$lref, $lastline+1, 0, $newline);
  151. &renumber($conf, $lastline, 1);
  152. push(@$conf, { 'name' => $name,
  153. 'value' => $value,
  154. 'enabled' => 1,
  155. 'file' => $lastfile,
  156. 'line' => $lastline+1,
  157. 'section' => $newsection,
  158. });
  159. }
  160. elsif (!defined($value) && $old && $cmt) {
  161. # Totally remove a value
  162. $lref = &read_file_lines_as_user($old->{'file'});
  163. splice(@$lref, $old->{'line'}, 1);
  164. @$conf = grep { $_ ne $old } @$conf;
  165. &renumber($conf, $old->{'line'}, -1);
  166. }
  167. elsif (!defined($value) && $old && !$cmt) {
  168. # Turn a value into a comment
  169. $lref = &read_file_lines_as_user($old->{'file'});
  170. $old->{'enabled'} = 0;
  171. $lref->[$old->{'line'}] = "; ".$lref->[$old->{'line'}];
  172. }
  173. }
  174. sub renumber
  175. {
  176. local ($conf, $line, $oset) = @_;
  177. foreach my $c (@$conf) {
  178. $c->{'line'} += $oset if ($c->{'line'} > $line);
  179. }
  180. }
  181. # can_php_config(file)
  182. # Returns 1 if some config file can be edited
  183. sub can_php_config
  184. {
  185. local ($file) = @_;
  186. return &indexof($file, map { $_->[0] } &list_php_configs()) >= 0 ||
  187. $access{'anyfile'};
  188. }
  189. # get_default_php_ini()
  190. # Returns the first php.ini that exists
  191. sub get_default_php_ini
  192. {
  193. local @inis = split(/\t+/, $config{'php_ini'});
  194. foreach my $ai (@inis) {
  195. local ($f, $d) = split(/=/, $ai);
  196. return $f if (-r $f);
  197. }
  198. if (-r $config{'alt_php_ini'} && @inis) {
  199. # Fall back to default file
  200. local ($f) = split(/=/, $inis[0]);
  201. &copy_source_dest($config{'alt_php_ini'}, $f);
  202. return $f;
  203. }
  204. return undef;
  205. }
  206. # list_php_configs()
  207. # Returns a list of allowed config files and descriptions
  208. sub list_php_configs
  209. {
  210. local @rv;
  211. &get_default_php_ini(); # Force copy of sample ini file
  212. if ($access{'global'}) {
  213. foreach my $ai (split(/\t+/, $config{'php_ini'})) {
  214. local ($f, $d) = split(/=/, $ai);
  215. push(@rv, [ $f, $d || $text{'file_global'} ]);
  216. }
  217. }
  218. foreach my $ai (split(/\t+/, $access{'php_inis'})) {
  219. local ($f, $d) = split(/=/, $ai);
  220. push(@rv, [ $f, $d || $f ]);
  221. }
  222. foreach my $i (@rv) {
  223. if (-d $i->[0] && -r "$i->[0]/php.ini") {
  224. $i->[0] = "$i->[0]/php.ini";
  225. }
  226. }
  227. if ($access{'global'} && &foreign_installed("virtual-server")) {
  228. &foreign_require("virtual-server");
  229. foreach my $v (&virtual_server::list_available_php_versions()) {
  230. if ($v->[0]) {
  231. my $ini = &virtual_server::get_global_php_ini($v->[0]);
  232. push(@rv, [ $ini, "PHP $v->[0]" ]) if ($ini && -r $ini);
  233. }
  234. }
  235. }
  236. my %done;
  237. return grep { !$done{$_->[0]}++ } @rv;
  238. }
  239. # onoff_radio(name)
  240. # Returns a field for editing a binary configuration value
  241. sub onoff_radio
  242. {
  243. local ($name) = @_;
  244. local $v = &find_value($name, $conf);
  245. return &ui_radio($name, lc($v) eq "on" || lc($v) eq "true" ||
  246. lc($v) eq "yes" || $v eq "1" ? "On" : $v ? "Off" : "",
  247. [ !$v ? ( [ "", $text{'default'} ] ) : ( ),
  248. [ "On", $text{'yes'} ],
  249. [ "Off", $text{'no'} ] ]);
  250. }
  251. # graceful_apache_restart([file])
  252. # Signal a graceful Apache restart, to pick up new php.ini settings
  253. sub graceful_apache_restart
  254. {
  255. local ($file) = @_;
  256. if (&foreign_installed("apache")) {
  257. &foreign_require("apache", "apache-lib.pl");
  258. if (&apache::is_apache_running() &&
  259. $apache::httpd_modules{'core'} >= 2 &&
  260. &has_command($apache::config{'apachectl_path'})) {
  261. &clean_environment();
  262. &system_logged("$apache::config{'apachectl_path'} graceful >/dev/null 2>&1");
  263. &reset_environment();
  264. }
  265. }
  266. if ($file && &get_config_fmt($file) eq "fpm" &&
  267. &foreign_check("virtual-server")) {
  268. # Looks like FPM format ... maybe a pool restart is needed
  269. &foreign_require("virtual-server");
  270. if (defined(&virtual_server::restart_php_fpm_server)) {
  271. &virtual_server::push_all_print();
  272. &virtual_server::set_all_null_print();
  273. &virtual_server::restart_php_fpm_server();
  274. &virtual_server::pop_all_print();
  275. }
  276. }
  277. }
  278. # get_config_as_user([file])
  279. # Like get_config, but reads with permissions of the ACL user
  280. sub get_config_as_user
  281. {
  282. local ($file) = @_;
  283. if ($access{'user'} && $access{'user'} ne 'root' && $< == 0) {
  284. local $rv = &eval_as_unix_user(
  285. $access{'user'}, sub { &get_config($file) });
  286. if ((!$rv || !@$rv) && $!) {
  287. &error(&text('file_eread', &html_escape($file), $!));
  288. }
  289. return $rv;
  290. }
  291. else {
  292. return &get_config($file);
  293. }
  294. }
  295. # read_file_contents_as_user(file)
  296. sub read_file_contents_as_user
  297. {
  298. local ($file) = @_;
  299. if ($access{'user'} && $access{'user'} ne 'root' && $< == 0) {
  300. return &eval_as_unix_user(
  301. $access{'user'}, sub { &read_file_contents($file) });
  302. }
  303. else {
  304. return &read_file_contents($file);
  305. }
  306. }
  307. # write_file_contents_as_user(file, data)
  308. # Writes out the contents of some file
  309. sub write_file_contents_as_user
  310. {
  311. local ($file, $data) = @_;
  312. if ($access{'user'} && $access{'user'} ne 'root' && $< == 0) {
  313. return &eval_as_unix_user(
  314. $access{'user'}, sub { &write_file_contents($file, $data) });
  315. }
  316. else {
  317. &write_file_contents($file, $data);
  318. }
  319. }
  320. # read_file_lines_as_user(file, ...)
  321. sub read_file_lines_as_user
  322. {
  323. local @args = @_;
  324. if ($access{'user'} && $access{'user'} ne 'root' && $< == 0) {
  325. return &eval_as_unix_user(
  326. $access{'user'}, sub { &read_file_lines(@args) });
  327. }
  328. else {
  329. return &read_file_lines(@args);
  330. }
  331. }
  332. # flush_file_lines_as_user(file)
  333. # Writes out a file as the Unix user configured in this module's ACL
  334. sub flush_file_lines_as_user
  335. {
  336. local ($file) = @_;
  337. if ($access{'user'} && $access{'user'} ne 'root' && $< == 0) {
  338. &eval_as_unix_user($access{'user'},
  339. sub { &flush_file_lines($file) });
  340. }
  341. else {
  342. &flush_file_lines($file);
  343. }
  344. }
  345. 1;