website.inc.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. <?php
  2. /**
  3. * Website management
  4. *
  5. * @package siteadm
  6. */
  7. class website_manager extends db_object_manager
  8. {
  9. static protected $name = "website";
  10. }
  11. /**
  12. * Website
  13. *
  14. * @package siteadm
  15. */
  16. class website extends db_object
  17. {
  18. static protected $_name = "website";
  19. static protected $_db_table = "website";
  20. static public $_f = array
  21. (
  22. "domain_id" => array("type"=>"object", "otype"=>"domain"),
  23. "account_id" => array("type"=>"object", "otype"=>"account"),
  24. "name" => array("type"=>"string", "nonempty"=>true),
  25. "folder" => array("type"=>"string"),
  26. "name" => array("type"=>"string", "nonempty"=>true),
  27. "charset_default" => array("type"=>"select", "list"=>array("utf-8", "iso-8859-1")),
  28. "webmaster_email" => array("type"=>"string"),
  29. "ssl" => array("type"=>"bool"),
  30. "ssl_force_redirect" => array("type"=>"bool"),
  31. "index_files" => array("type"=>"string"),
  32. "folder_auth" => array("type"=>"bool"),
  33. "webapp_id" => array("type"=>"object", "otype"=>"webapp"),
  34. "phppool_id" => array("type"=>"object", "otype"=>"phppool"),
  35. "php_error_reporting" => array("type"=>"string", "default"=>PHP_ERROR_REPORTING),
  36. "php_open_basedir" => array("type"=>"string"),
  37. "php_include_path" => array("type"=>"string"),
  38. "php_apc_stat" => array("type"=>"bool"),
  39. "php_short_open_tag" => array("type"=>"bool"),
  40. "php_max_execution_time" => array("type"=>"int"),
  41. "php_max_input_time" => array("type"=>"int"),
  42. "php_memory_limit" => array("type"=>"int"),
  43. "php_memory_limit" => array("type"=>"int"),
  44. "php_enable_dl" => array("type"=>"bool"),
  45. "php_file_uploads" => array("type"=>"bool"),
  46. "php_upload_max_filesize" => array("type"=>"int"),
  47. "php_max_file_upload" => array("type"=>"int"),
  48. );
  49. /**
  50. * @see db_object::__toString()
  51. */
  52. function __toString()
  53. {
  54. return $this->name();
  55. }
  56. /**
  57. * Website complete name
  58. * @return string
  59. */
  60. public function name()
  61. {
  62. $domain = $this->domain();
  63. if ($this->name)
  64. return $this->name.".".$domain->name;
  65. else
  66. return $domain->name;
  67. }
  68. // ACCESS
  69. /**
  70. * Returnd associated domain
  71. * @return domain
  72. */
  73. public function domain()
  74. {
  75. return domain()->get($this->domain_id);
  76. }
  77. /**
  78. * Returns associated webapp
  79. * @return webapp
  80. */
  81. public function webapp()
  82. {
  83. return webapp()->get($this->webapp_id);
  84. }
  85. /**
  86. * Returns associated phppool
  87. * @return phppool
  88. */
  89. public function phppool()
  90. {
  91. return phppool()->get($this->phppool_id);
  92. }
  93. /**
  94. * Returns associated account
  95. * @return account
  96. */
  97. public function account()
  98. {
  99. if ($account=account()->get($this->account_id))
  100. return $account;
  101. elseif (($domain=$this->domain()) && ($account=$domain->account()))
  102. return $account;
  103. else
  104. return account_common();
  105. }
  106. /**
  107. * @return []website_alias
  108. */
  109. function alias_list()
  110. {
  111. $list = array();
  112. if ($this->id)
  113. {
  114. $query_string = "SELECT website_alias.alias_name, domain.name
  115. FROM website_alias
  116. LEFT JOIN domain ON domain.id=website_alias.domain_id
  117. WHERE website_alias.website_id='".$this->id."'";
  118. $query = mysql_query($query_string);
  119. while(list($alias_name, $domain_name)=mysql_fetch_row($query))
  120. {
  121. if ($domain_name && $alias_name)
  122. $list[] = "$alias_name.$domain_name";
  123. elseif ($domain_name)
  124. $list[] = "$domain_name";
  125. else
  126. $list[] = "$alias_name.*";
  127. }
  128. }
  129. return $list;
  130. }
  131. // FOLDERS
  132. /**
  133. * Returns storage folder name
  134. * @return string
  135. */
  136. public function folder()
  137. {
  138. return $this->public_folder();
  139. }
  140. public function public_folder()
  141. {
  142. return $this->account()->public_folder()."/".$this->folder;
  143. }
  144. public function private_folder()
  145. {
  146. return $this->account()->private_folder()."/".$this->folder;
  147. }
  148. /**
  149. * Returns config folder name
  150. * @warning This is a global account config folder
  151. * @return string
  152. */
  153. function config_folder()
  154. {
  155. return $this->account()->public_folder()."/config";
  156. }
  157. /**
  158. * Returns apache log folder name
  159. * @return string
  160. */
  161. function apache_log_folder()
  162. {
  163. return $this->account()->log_folder()."/apache";
  164. }
  165. /**
  166. * Returns apache config folder name
  167. * @return string
  168. */
  169. function apache_conf_folder()
  170. {
  171. return $this->account()->conf_folder()."/apache";
  172. }
  173. /**
  174. * Returns apache config folder name
  175. * @return string
  176. */
  177. function awstats_log_folder()
  178. {
  179. return $this->account()->log_folder()."/awstats";
  180. }
  181. /**
  182. * Returns apache config folder name
  183. * @return string
  184. */
  185. function awstats_conf_folder()
  186. {
  187. return $this->account()->conf_folder()."/awstats";
  188. }
  189. /**
  190. * Returns php log folder name
  191. * @return string
  192. */
  193. function php_log_folder()
  194. {
  195. return $this->account()->log_folder()."/php";
  196. }
  197. /**
  198. * Returns php config folder name
  199. * @return string
  200. */
  201. function php_conf_folder()
  202. {
  203. return $this->account()->conf_folder()."/php";
  204. }
  205. /**
  206. * @return string
  207. */
  208. function php_vhost_folder()
  209. {
  210. return $this->account()->conf_folder()."/php/vhost";
  211. }
  212. // FILES
  213. /**
  214. * Returns access log filename
  215. * @return string
  216. */
  217. public function accesslog_file()
  218. {
  219. return $this->apache_log_folder()."/".$this->name().".access.log";
  220. }
  221. /**
  222. * Returns error log filename
  223. * @return string
  224. */
  225. public function errorlog_file()
  226. {
  227. return $this->apache_log_folder()."/".$this->name().".error.log";
  228. }
  229. /**
  230. * Returns PHP error log filename
  231. * @return string
  232. */
  233. public function phperrorlog_file()
  234. {
  235. return $this->php_log_folder()."/".$this->name().".php_error.log";
  236. }
  237. /**
  238. * @return string
  239. */
  240. public function htpasswd_file()
  241. {
  242. return $this->apache_conf_folder()."/".$this->name().".htpasswd";
  243. }
  244. /**
  245. * @return string
  246. */
  247. function awstats_conf_file()
  248. {
  249. return $this->awstats_conf_folder()."/".$this->name.".".$this->domain()->name.".conf";
  250. }
  251. /**
  252. * @return string
  253. */
  254. function apache_conf_file()
  255. {
  256. return $this->apache_conf_folder()."/".$this->name().".conf";
  257. }
  258. /**
  259. * @return string
  260. */
  261. function php_ini_file()
  262. {
  263. return $this->php_vhost_folder()."/".$this->name().".ini";
  264. }
  265. // PERM
  266. /**
  267. * @see db_object::insert_perm()
  268. */
  269. static public function insert_perm()
  270. {
  271. // Admin
  272. if (login()->perm("admin"))
  273. {
  274. return "admin";
  275. }
  276. // Special account access
  277. elseif (login()->perm("manager"))
  278. {
  279. return "domain_manager";
  280. }
  281. // Domain User
  282. elseif (login()->id)
  283. {
  284. return "domain_user";
  285. }
  286. else
  287. {
  288. return false;
  289. }
  290. }
  291. /**
  292. * @see db_object::update_perm()
  293. */
  294. public function update_perm()
  295. {
  296. // Admin
  297. if (login()->perm("admin"))
  298. {
  299. return "admin";
  300. }
  301. // Special account access
  302. elseif ($account=account($this->account_id))
  303. {
  304. if ($this->account_id == login()->id)
  305. return "user";
  306. elseif ($account->manager_id == login()->id)
  307. return "manager";
  308. else
  309. return false;
  310. }
  311. // Domain Manager
  312. elseif (($domain=$this->domain()) && ($account=$domain->account()) && $account->manager_id == login()->id)
  313. {
  314. return "domain_manager";
  315. }
  316. // Domain User
  317. elseif (($domain=$this->domain()) && $domain->account_id == login()->id)
  318. {
  319. return "domain_user";
  320. }
  321. else
  322. {
  323. return false;
  324. }
  325. }
  326. // UPDATE
  327. /**
  328. * @see db_object::insert()
  329. */
  330. public function insert($infos)
  331. {
  332. if (!($perm=static::insert_perm()))
  333. return false;
  334. if (isset($infos["account_id"]) && $perm != "admin" && ($perm != "manager" || !isset($infos["account_id"]) || !($account=account($infos["account_id"])) || $account->manager_id != login()->id) && ($infos["account_id"] != login()->id))
  335. {
  336. unset($infos["account_id"]);
  337. }
  338. //var_dump($infos);
  339. return db_object::insert($infos);
  340. }
  341. /**
  342. * @see db_object::update()
  343. */
  344. public function update($infos)
  345. {
  346. if (!($perm=$this->update_perm()))
  347. return false;
  348. if (isset($infos["account_id"]) && $perm != "admin" && ($perm != "manager" || !($account=account($infos["account_id"])) || $account->manager_id != login()->id))
  349. {
  350. unset($infos["account_id"]);
  351. }
  352. if (isset($infos["domain_id"]))
  353. unset($infos["domain_id"]);
  354. if (isset($infos["name"]))
  355. unset($infos["name"]);
  356. return db_object::update($infos);
  357. }
  358. // DB
  359. /**
  360. * @see db_object::db_update_more()
  361. */
  362. function db_update_more($infos)
  363. {
  364. $return = false;
  365. if (isset($infos["php_extension"]))
  366. {
  367. $query_list = array();
  368. foreach($infos["php_extension"] as $ext_id)
  369. $query_list[] = "('$this->id', '$ext_id')";
  370. mysql_query("DELETE FROM website_phpext_ref WHERE website_id='$this->id'");
  371. if (count($query_list))
  372. mysql_query("INSERT INTO website_phpext_ref (website_id, phpext_id) VALUES ".implode(" , ",$query_list));
  373. $return = true;
  374. unset($infos["php_extension"]);
  375. }
  376. if (isset($infos["php_disable_functions"]))
  377. {
  378. $query_list = array();
  379. foreach($infos["php_disable_functions"] as $fct_id)
  380. $query_list[] = "('$this->id', '$fct_id')";
  381. mysql_query("DELETE FROM website_php_disable_functions_ref WHERE website_id='$this->id'");
  382. if (count($query_list))
  383. mysql_query("INSERT INTO website_php_disable_functions_ref (website_id, function_id) VALUES ".implode(" , ",$query_list));
  384. $return = true;
  385. unset($infos["php_disable_functions"]);
  386. }
  387. return $return;
  388. }
  389. // ROOT ACCESS SCRIPTS
  390. /**
  391. * @see db_object::root_preupdate()
  392. */
  393. protected function root_preupdate($infos)
  394. {
  395. if (!$this->id || !is_array($infos))
  396. return;
  397. $update = false;
  398. if (isset($infos["name"]))
  399. {
  400. $name = $infos["name"];
  401. $update = true;
  402. }
  403. else
  404. $name = "";
  405. if (isset($infos["domain_id"]))
  406. {
  407. $domain_id = $infos["domain_id"];
  408. $update = true;
  409. }
  410. else
  411. $domain_id = "";
  412. if (isset($infos["account_id"]))
  413. {
  414. $account_id = $infos["account_id"];
  415. $update = true;
  416. }
  417. else
  418. $account_id = "";
  419. if ($update)
  420. {
  421. $this->root_update("preupdate", $name, $domain_id, $account_id);
  422. }
  423. }
  424. /**
  425. * Returns access log
  426. */
  427. public function root_accesslog()
  428. {
  429. $command = "sudo ".SITEADM_SCRIPT_DIR."/db_object.psh ".get_called_class()." $this->id accesslog";
  430. return shell_exec($command);
  431. }
  432. /* REPLACE MAP */
  433. /**
  434. * Config files vars replacement map
  435. * @return array
  436. */
  437. function replace_map()
  438. {
  439. $domain = $this->domain();
  440. $account = $this->account();
  441. // @todo : alias_list
  442. $map = array
  443. (
  444. "{WEBSITE_LOG_ACCESS}" => $this->accesslog_file(),
  445. "{WEBSITE_LOG_ERROR}" => $this->errorlog_file(),
  446. "{WEBSITE_NAME}" => $this->name(),
  447. "{WEBSITE_ALIAS}" => (count($alias_list=$this->alias_list())?implode(" ", $alias_list):$this->name()),
  448. "{WEBSITE_INDEX_FILES}" => $this->index_files,
  449. "{AWSTATS_DATA_DIR}" => $this->awstats_log_folder(),
  450. "{WEBSITE_CGI_PATH}" => $account->folder()."/cgi-bin",
  451. "{WEBSITE_PUBLIC_DIR}" => $this->public_folder(),
  452. "{WEBSITE_PRIVATE_DIR}" => $this->private_folder(),
  453. "{WEBSITE_CONFIG_DIR}" => $this->config_folder(),
  454. "{WEBSITE_CHARSET}" => $this->charset_default,
  455. "{WEBSITE_PHP_ERROR_LOG}" => $this->phperrorlog_file(),
  456. "{WEBSITE_FOLDER_ALIAS}" => "",
  457. "{WEBSITE_FOLDER_AUTH}" => "",
  458. "{PHP_SHORT_OPEN_TAG}" => $this->php_short_open_tag,
  459. "{PHP_OPEN_BASEDIR}" => ($this->php_open_basedir!==null) ?$this->php_open_basedir :$this->public_folder().":".$this->private_folder(),
  460. "{PHP_INCLUDE_PATH}" => ($this->php_include_path) ?$this->php_include_path :$this->private_folder().":.",
  461. "{PHP_APC_STAT}" => $this->php_apc_stat,
  462. );
  463. if ($this->webmaster_email)
  464. $map["{WEBMASTER_EMAIL}"] = $this->webmaster_email;
  465. else
  466. $map["{WEBMASTER_EMAIL}"] = $account->email;
  467. if ($webapp=$this->webapp())
  468. {
  469. if ($webapp->php_open_basedir !== null)
  470. $map["{PHP_OPEN_BASEDIR}"] .= ":$webapp->php_open_basedir";
  471. if ($webapp->php_include_folder !== null)
  472. $map["{PHP_INCLUDE_PATH}"] .= ":$webapp->php_include_folder";
  473. if ($webapp->php_short_open_tag !== null)
  474. $map["{PHP_SHORT_OPEN_TAG}"] = $webapp->php_short_open_tag;
  475. if ($webapp->folder_alias !== null)
  476. {
  477. $folder_alias_list = json_decode($webapp->folder_alias, true);
  478. $map["{WEBSITE_FOLDER_ALIAS}"] = "";
  479. if (is_array($folder_alias_list))
  480. {
  481. foreach($folder_alias_list as $i=>$j)
  482. $map["{WEBSITE_FOLDER_ALIAS}"] .= "Alias $i $j\n";
  483. }
  484. }
  485. }
  486. if ($this->folder_auth)
  487. $map["{WEBSITE_FOLDER_AUTH}"] = 'AuthName "Authentification requise"
  488. AuthUserFile '.$this->htpasswd_file().'
  489. AuthGroupFile /dev/null
  490. AuthType Basic
  491. require valid-user';
  492. replace_map_merge($map, $domain->replace_map());
  493. if ($phppool=$this->phppool())
  494. replace_map_merge($map, $phppool->replace_map());
  495. return $map;
  496. }
  497. /* ROOT SCRIPTS */
  498. /**
  499. * @see db_object::script_structure()
  500. */
  501. function script_structure()
  502. {
  503. $domain = $this->domain();
  504. $account = $this->account();
  505. $phppool = $this->phppool();
  506. $account->mkdir($this->apache_conf_folder(), "750", "root");
  507. $account->mkdir($this->awstats_conf_folder(), "750", "root");
  508. $account->mkdir($this->php_conf_folder(), "750", "root");
  509. $account->mkdir($this->apache_log_folder(), "1750", "root");
  510. $account->mkdir($this->awstats_log_folder(), "1750", "root");
  511. $account->mkdir($this->php_log_folder(), "1770", "root");
  512. $account->mkdir($this->public_folder(), "755");
  513. $account->mkdir($this->private_folder(), "750");
  514. $account->mkdir($this->config_folder(), "750");
  515. filesystem::link($this->public_folder(), SITEADM_WEBSITE_DIR."/".$this->name());
  516. $replace_map = $this->replace_map();
  517. // Default public files
  518. if (!file_exists($this->public_folder()."/index.html"))
  519. $account->copy_tpl("website/index.html", $this->public_folder()."/index.html", $replace_map, "0644");
  520. if ($phppool && !file_exists($this->folder()."/phpinfo.php"))
  521. $account->copy_tpl("website/phpinfo.php", $this->public_folder()."/phpinfo.php", $replace_map, "0644");
  522. }
  523. /**
  524. * @see db_object::script_update()
  525. */
  526. function script_update()
  527. {
  528. $domain = $this->domain();
  529. $account = $this->account();
  530. $replace_map = $this->replace_map();
  531. // PHP vhost config file
  532. if (($phppool=$this->phppool()) && ($phpapp=$phppool->phpapp()))
  533. {
  534. $account->copy_tpl("php/vhost.conf", $this->php_ini_file(), $replace_map, "0644", "root");
  535. $phpapp->script_update();
  536. //$phpapp->script_vhost();
  537. //$phpapp->script_reload();
  538. }
  539. // SSL
  540. if ($this->ssl && !file_exists($domain->ssl_key_file()))
  541. $domain->script_ssl_create();
  542. // Folder Auth (.htaccess)
  543. if ($this->folder_auth && !file_exists($this->htpasswd_file()))
  544. exec("touch ".$this->htpasswd_file());
  545. // Webserver config file
  546. if ($this->ssl && $this->ssl_force_redirect)
  547. $apache_tpl_file = "apache/vhost-ssl-redirect.conf";
  548. elseif ($this->ssl)
  549. $apache_tpl_file = "apache/vhost-ssl.conf";
  550. else
  551. $apache_tpl_file = "apache/vhost.conf";
  552. $account->copy_tpl($apache_tpl_file, $this->apache_conf_file(), $replace_map, "0644", "root");
  553. filesystem::link($this->apache_conf_file(), APACHE_VHOST_DIR."/$this->name.$domain->name.conf");
  554. // Awstats
  555. $account->copy_tpl("awstats/awstats.website.conf", $this->awstats_conf_file(), $replace_map, "644", "root");
  556. filesystem::link($this->awstats_conf_file(), AWSTATS_CONF_DIR."/awstats.$this->name.$domain->name.conf");
  557. // Reload webserver
  558. $this->script_reload();
  559. }
  560. /**
  561. * @see db_object::script_preupdate()
  562. * @param string $name
  563. * @param int $domain_id
  564. * @param int $account_id
  565. */
  566. function script_preupdate($name, $domain_id, $account_id)
  567. {
  568. // @todo : penser à copier les données en backup pour l'ancien compte ou l'ancien nom de domaine
  569. // Déplacer vers un autre compte
  570. if ($account_id)
  571. {
  572. }
  573. // Changer le nom de domaine
  574. if ($name || $domain_id)
  575. {
  576. }
  577. }
  578. /**
  579. * @see db_object::script_reload()
  580. */
  581. function script_reload()
  582. {
  583. static::script_webserver_reload();
  584. }
  585. static function script_webserver_reload()
  586. {
  587. // Reload apache
  588. script_exec("apache.sh", "reload");
  589. }
  590. }
  591. ?>