phppool.inc.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. <?php
  2. /**
  3. * PHP Pool associated to a PHP account management
  4. *
  5. * @package siteadm
  6. */
  7. class phppool_manager extends db_object_manager
  8. {
  9. static protected $name = "phppool";
  10. }
  11. /**
  12. * PHP Pool associated to a PHP account
  13. *
  14. * @package siteadm
  15. */
  16. class phppool extends db_object
  17. {
  18. static protected $_name = "phppool";
  19. static protected $_db_table = "phppool";
  20. // Extensions
  21. public $extension = array();
  22. // Functions
  23. public $disable_functions = array();
  24. static public $_f = array
  25. (
  26. "name" => array("type"=>"string", "nonempty"=>true),
  27. "account_id" => array("type"=>"object", "otype"=>"account"),
  28. "phpapp_id" => array("type"=>"object", "otype"=>"phpapp", "nonempty"=>true),
  29. "worker_nb_max" => array("type"=>"int", "default"=>PHP_WORKER_NB_MAX),
  30. "worker_max_requests" => array("type"=>"int", "default"=>PHP_WORKER_MAX_REQUESTS),
  31. "webmaster_email" => array("type"=>"string"),
  32. "error_reporting" => array("type"=>"string", "default"=>PHP_ERROR_REPORTING),
  33. "error_display" => array("type"=>"bool", "default"=>PHP_ERROR_DISPLAY),
  34. "error_filesave" => array("type"=>"bool", "default"=>PHP_ERROR_FILESAVE),
  35. "max_execution_time" => array("type"=>"int", "default"=>PHP_MAX_EXECUTION_TIME),
  36. "max_input_time" => array("type"=>"int", "default"=>PHP_MAX_INPUT_TIME),
  37. "memory_limit" => array("type"=>"int", "default"=>PHP_MEMORY_LIMIT),
  38. "post_max_size" => array("type"=>"int", "default"=>PHP_POST_MAX_SIZE),
  39. "file_uploads" => array("type"=>"bool", "default"=>PHP_FILE_UPLOADS),
  40. "upload_max_filesize" => array("type"=>"int", "default"=>PHP_UPLOAD_MAX_FILESIZE),
  41. "max_file_upload" => array("type"=>"int", "default"=>PHP_MAX_FILE_UPLOAD),
  42. "short_open_tag" => array("type"=>"bool", "default"=>PHP_SHORT_OPEN_TAG),
  43. "include_path" => array("type"=>"string", "default"=>PHP_INCLUDE_PATH),
  44. "open_basedir" => array("type"=>"string"),
  45. "apc_stat" => array("type"=>"bool", "default"=>PHP_APC_STAT),
  46. "apc_lazy" => array("type"=>"bool", "default"=>PHP_APC_LAZY),
  47. "extension" => array(),
  48. );
  49. /**
  50. * @see db_object::__toString()
  51. */
  52. function __toString()
  53. {
  54. return $this->account()."-".$this->name;
  55. }
  56. /**
  57. * @see db_object::url()
  58. */
  59. function url()
  60. {
  61. return "php.php?pool_id=$this->id";
  62. }
  63. function system_user()
  64. {
  65. return $this->account()->php_user();
  66. }
  67. function system_group()
  68. {
  69. return $this->account()->php_group();
  70. }
  71. /* ACCESS */
  72. /**
  73. * Retrieve managing account
  74. * @return account
  75. */
  76. public function account()
  77. {
  78. if ($account=account()->get($this->account_id))
  79. return $account;
  80. else
  81. return account_common();
  82. }
  83. /**
  84. * Retrieve phpapp
  85. * @return phpapp
  86. */
  87. public function phpapp()
  88. {
  89. return phpapp()->get($this->phpapp_id);
  90. }
  91. /**
  92. * @return language_bin
  93. */
  94. public function language_bin()
  95. {
  96. if ($phpapp=$this->phpapp())
  97. return $phpapp->language_bin();
  98. }
  99. public function phpext_list()
  100. {
  101. $list = array();
  102. if (is_array($this->extension) && count($this->extension))
  103. {
  104. $query_string = "SELECT * FROM language_php_ext WHERE id IN (".implode(", ", $this->extension).")";
  105. $query = mysql_query($query_string);
  106. while($row=mysql_fetch_assoc($query))
  107. $list[$row["id"]] = $row;
  108. }
  109. return $list;
  110. }
  111. /* FOLDERS */
  112. /**
  113. * @return string
  114. */
  115. public function log_folder()
  116. {
  117. return $this->account()->log_folder()."/php";
  118. }
  119. /**
  120. * @return string
  121. */
  122. public function conf_folder()
  123. {
  124. return $this->account()->conf_folder()."/php/pool";
  125. }
  126. /**
  127. * @return string
  128. */
  129. public function socket_folder()
  130. {
  131. return $this->account()->socket_folder();
  132. }
  133. /**
  134. * @return string
  135. */
  136. public function app_pool_folder()
  137. {
  138. if ($phpapp=$this->phpapp())
  139. return $phpapp->pool_folder();
  140. }
  141. /**
  142. * @return string
  143. */
  144. public function apache_conf_folder()
  145. {
  146. return $this->account()->conf_folder()."/apache";
  147. }
  148. /**
  149. * @return string
  150. */
  151. public function session_folder()
  152. {
  153. return $this->account()->session_folder();
  154. }
  155. /* FILES */
  156. /**
  157. * Returns error log filename
  158. * @return string
  159. */
  160. public function errorlog_file()
  161. {
  162. return $this->log_folder()."/pool-".$this->name."_error.log";
  163. }
  164. /**
  165. * Returns mail log filename
  166. * @return string
  167. */
  168. public function maillog_file()
  169. {
  170. return $this->log_folder()."/pool-".$this->name."_mail.log";
  171. }
  172. /**
  173. * Returns slow log filename
  174. * @return string
  175. */
  176. public function slowlog_file()
  177. {
  178. return $this->log_folder()."/pool-".$this->name."_slow.log";
  179. }
  180. /**
  181. * @return string
  182. */
  183. function socket_file()
  184. {
  185. return $this->socket_folder()."/pool-".$this->name.".sock";
  186. }
  187. /**
  188. * @return string
  189. */
  190. function config_file()
  191. {
  192. return $this->conf_folder()."/".$this->name.".conf";
  193. }
  194. /**
  195. * @return string
  196. */
  197. function app_pool_file()
  198. {
  199. return $this->app_pool_folder()."/".$this->account()->name."-".$this->name.".conf";
  200. }
  201. /**
  202. * @return string
  203. */
  204. function ini_file()
  205. {
  206. return $this->conf_folder()."/".$this->name.".ini";
  207. }
  208. /**
  209. * @return string
  210. */
  211. function apache_file()
  212. {
  213. return $this->apache_conf_folder()."/php-".$this->name.".conf";
  214. }
  215. /**
  216. * @return string
  217. */
  218. function pid_file()
  219. {
  220. return $this->conf_folder()."/".$this->name.".pid";
  221. }
  222. /**
  223. * Returns PID
  224. * @return int
  225. */
  226. public function pid()
  227. {
  228. return (int)file_get_contents($this->pid_file());
  229. }
  230. // PERM
  231. /**
  232. * @see db_object::insert_perm()
  233. */
  234. static function insert_perm()
  235. {
  236. // Admin
  237. if (login()->perm("admin"))
  238. {
  239. return "admin";
  240. }
  241. // Manager
  242. elseif (login()->perm("manager"))
  243. {
  244. return "manager";
  245. }
  246. // User
  247. elseif (login()->id)
  248. {
  249. return "user";
  250. }
  251. else
  252. {
  253. return false;
  254. }
  255. }
  256. /**
  257. * @see db_object::update_perm()
  258. */
  259. public function update_perm()
  260. {
  261. // Admin
  262. if (login()->perm("admin"))
  263. {
  264. return "admin";
  265. }
  266. // Manager
  267. elseif (($account=$this->account()) && $account->manager_id == login()->id)
  268. {
  269. return "manager";
  270. }
  271. // User
  272. elseif ($this->account_id == login()->id)
  273. {
  274. return "user";
  275. }
  276. else
  277. {
  278. return false;
  279. }
  280. }
  281. // UPDATE
  282. /**
  283. * @see db_object::insert()
  284. */
  285. public function insert($infos)
  286. {
  287. if (!($perm=static::insert_perm()) || !is_array($infos))
  288. return false;
  289. if ($perm != "admin" && ($perm != "manager" || !isset($infos["account_id"]) || !($account=account($infos["account_id"])) || $account->manager_id != login()->id))
  290. {
  291. $infos["account_id"] = login()->id;
  292. }
  293. if (isset($infos["phpapp_id"]) && (!($phpapp=phpapp()->get($infos["phpapp_id"])) || (!login()->perm("admin") && $phpapp->account_id && $phpapp->account_id != login()->id)))
  294. {
  295. unset($infos["phpapp_id"]);
  296. }
  297. return db_object::insert($infos);
  298. }
  299. /**
  300. * @see db_object::update()
  301. */
  302. public function update($infos)
  303. {
  304. if (!($perm=$this->update_perm()))
  305. return false;
  306. if (isset($infos["account_id"]) && $perm != "admin" && ($perm != "manager" || !($account=account($infos["account_id"])) || $account->manager_id != login()->id))
  307. {
  308. unset($infos["account_id"]);
  309. }
  310. if (isset($infos["phpapp_id"]) && ($phpapp=phpapp($infos["phpapp_id"])) && $phpapp->account_id && $phpapp->account_id != login()->id)
  311. {
  312. unset($infos["phpapp_id"]);
  313. }
  314. if (isset($infos["name"]))
  315. unset($infos["name"]);
  316. return db_object::update($infos);
  317. }
  318. // DB
  319. /**
  320. * @see db_object::db_retrieve()
  321. */
  322. function db_retrieve($id)
  323. {
  324. if (db_object::db_retrieve($id))
  325. {
  326. // Extensions
  327. $this->extension = array();
  328. $query = mysql_query("SELECT ext_id FROM phppool_ext_ref WHERE phppool_id='$this->id'");
  329. while(list($ext_id)=mysql_fetch_row($query))
  330. $this->extension[] = $ext_id;
  331. // Disabled functions
  332. $this->disable_functions = array();
  333. $query = mysql_query("SELECT function_id FROM phppool_disable_functions_ref WHERE phppool_id='$this->id'");
  334. while(list($function_id)=mysql_fetch_row($query))
  335. $this->disable_functions[] = $function_id;
  336. }
  337. }
  338. /**
  339. * @see db_object::db_update()
  340. */
  341. function db_update($infos)
  342. {
  343. //var_dump($infos);
  344. $return = false;
  345. if (isset($infos["extension"]))
  346. {
  347. mysql_query("DELETE FROM phppool_ext_ref WHERE phppool_id='$this->id'");
  348. if (is_array($infos["extension"]))
  349. {
  350. $query_list = array();
  351. foreach($infos["extension"] as $ext_id)
  352. $query_list[] = "('$this->id', '$ext_id')";
  353. if (count($query_list))
  354. {
  355. $query_string = "INSERT INTO phppool_ext_ref (phppool_id, ext_id) VALUES ".implode(" , ",$query_list);
  356. mysql_query($query_string);
  357. }
  358. }
  359. $return = true;
  360. }
  361. if (isset($infos["disable_functions"]))
  362. {
  363. mysql_query("DELETE FROM phppool_disable_functions_ref WHERE phppool_id='$this->id'");
  364. if (is_array($infos["disable_functions"]))
  365. {
  366. $query_list = array();
  367. foreach($infos["disable_functions"] as $fct_id)
  368. $query_list[] = "('$this->id', '$fct_id')";
  369. if (count($query_list))
  370. {
  371. $query_string = "INSERT INTO phppool_disable_functions_ref (phppool_id, function_id) VALUES ".implode(" , ",$query_list);
  372. mysql_query($query_string);
  373. }
  374. }
  375. $return = true;
  376. }
  377. return (db_object::db_update($infos) || $return);
  378. }
  379. /* REPLACE MAP */
  380. /**
  381. * Parameters for template files
  382. * @return array
  383. */
  384. function replace_map()
  385. {
  386. $phpapp = $this->phpapp();
  387. $account = $this->account();
  388. $map = array
  389. (
  390. "{PHP_POOL_NAME}" => $this->name,
  391. "{PHP_WRAPPER}" => $account->folder()."/cgi-bin/php-".$this->name, // Only for apache fastcgi config compatibility
  392. "{PHP_SYSTEM_USER}" => $this->system_user(),
  393. "{PHP_SYSTEM_GROUP}" => $this->system_group(),
  394. "{PHP_SOCK_SYSTEM_GROUP}" => $this->system_group(),
  395. "{PHP_SOCK}" => $this->socket_file(),
  396. "{PHP_CONF}" => $this->config_file(),
  397. "{PHP_INI}" => $this->ini_file(),
  398. "{PHP_PID}" => $this->pid_file(),
  399. "{PHP_TMP_DIR}" => $account->tmp_folder(),
  400. "{PHP_SESSION_DIR}" => $this->session_folder(),
  401. "{WEBSERVER_GROUP}" => WEBSERVER_GROUP,
  402. "{PHP_WORKER_NB_MAX}" => $this->worker_nb_max,
  403. "{PHP_WORKER_SPARE_NB_MIN}" => 1,
  404. "{PHP_WORKER_SPARE_NB_MAX}" => 1,
  405. "{PHP_WORKER_MAX_REQUESTS}" => $this->worker_max_requests,
  406. "{PHP_ERROR_LOG}" => $this->errorlog_file(),
  407. "{PHP_MAIL_LOG}" => $this->maillog_file(),
  408. "{PHP_SLOW_LOG}" => $this->slowlog_file(),
  409. "{PHP_WEBMASTER_EMAIL}" => $this->webmaster_email,
  410. "{PHP_DISABLE_FUNCTIONS}" => "",
  411. "{PHP_ERROR_REPORTING}" => $this->error_reporting,
  412. "{PHP_SHORT_OPEN_TAG}" => $this->short_open_tag,
  413. "{PHP_MAX_EXECUTION_TIME}" => $this->max_execution_time,
  414. "{PHP_MAX_INPUT_TIME}" => $this->max_input_time,
  415. "{PHP_MEMORY_LIMIT}" => $this->memory_limit,
  416. "{PHP_POST_MAX_SIZE}" => $this->post_max_size,
  417. "{PHP_FILE_UPLOADS}" => $this->file_uploads,
  418. "{PHP_UPLOAD_MAX_FILESIZE}" => $this->upload_max_filesize,
  419. "{PHP_MAX_FILE_UPLOAD}" => $this->max_file_upload,
  420. "{PHP_INCLUDE_PATH}" => ($this->include_path ?$this->include_path : "."),
  421. "{PHP_OPEN_BASEDIR}" => ($this->open_basedir ?$this->open_basedir : $account->private_folder().":".$account->public_folder()),
  422. "{PHP_APC_STAT}" => $this->apc_stat,
  423. "{PHP_APC_LAZY}" => $this->apc_lazy,
  424. "{PHP_POOL_EXTENSIONS}" => "",
  425. );
  426. if ($this->worker_nb_max > 2)
  427. {
  428. $map["{PHP_WORKER_SPARE_NB_MIN}"] = floor($this->worker_nb_max/3);
  429. $map["{PHP_WORKER_SPARE_NB_MAX}"] = ceil($this->worker_nb_max*2/3);
  430. }
  431. // @todo : à retravailler
  432. if (isset($this->system_user) && !is_null($this->system_user))
  433. {
  434. $map["{PHP_SYSTEM_USER}"] = $this->system_user;
  435. }
  436. if (isset($this->system_group) && !is_null($this->system_group))
  437. {
  438. $map["{PHP_SYSTEM_GROUP}"] = $this->system_group;
  439. $map["{PHP_SOCK_SYSTEM_GROUP}"] = $this->system_group;
  440. }
  441. $phpapp_ext_list = $phpapp->phpext_loaded_list();
  442. foreach($this->phpext_list() as $ext)
  443. {
  444. if (!isset($phpapp_ext_list[$ext["id"]]))
  445. {
  446. $map["{PHP_POOL_EXTENSIONS}"] .= "php_admin_value[extension] = ".$ext["name"].".so\n";
  447. }
  448. }
  449. replace_map_merge($map, $phpapp->replace_map());
  450. return $map;
  451. }
  452. /* ROOT SCRIPTS */
  453. /**
  454. * @see db_object::script_structure()
  455. */
  456. function script_structure()
  457. {
  458. $account = $this->account();
  459. $account->mkdir($this->conf_folder(), "750", "root");
  460. $account->mkdir($this->log_folder(), "1750", "root");
  461. }
  462. /**
  463. * @see db_object::script_update()
  464. */
  465. function script_update()
  466. {
  467. $phpapp = $this->phpapp();
  468. $account = $this->account();
  469. $replace_map = $this->replace_map();
  470. copy_tpl("php/php-fpm-app.conf", $this->config_file(), $replace_map, "0644");
  471. filesystem::link($this->config_file(), $this->app_pool_file());
  472. // Webserver handler
  473. $account->copy_tpl("apache/php.conf", $this->apache_file(), $replace_map, "0644");
  474. filesystem::link($this->apache_file(), APACHE_VHOST_DIR."/php-".$account->name."-".$this->name.".conf");
  475. $phpapp->script_update();
  476. website::script_webserver_reload();
  477. //$this->script_reload();
  478. }
  479. /**
  480. * @see db_object::script_reload()
  481. */
  482. public function script_reload()
  483. {
  484. $this->phpapp()->script_reload();
  485. website::script_webserver_reload();
  486. }
  487. }
  488. ?>