PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/install.lib.php

https://gitlab.com/x33n/ampache
PHP | 514 lines | 388 code | 63 blank | 63 comment | 82 complexity | 50662fa6ed64a12c23e6b182834e25b7 MD5 | raw file
  1. <?php
  2. /* vim:set softtabstop=4 shiftwidth=4 expandtab: */
  3. /**
  4. *
  5. * LICENSE: GNU General Public License, version 2 (GPLv2)
  6. * Copyright 2001 - 2015 Ampache.org
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License v2
  10. * as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20. *
  21. */
  22. /**
  23. * split_sql
  24. * splits up a standard SQL dump file into distinct sql queries
  25. */
  26. function split_sql($sql)
  27. {
  28. $sql = trim($sql);
  29. $sql = preg_replace("/\n#[^\n]*\n/", "\n", $sql);
  30. $buffer = array();
  31. $ret = array();
  32. $in_string = false;
  33. for ($i=0; $i<strlen($sql)-1; $i++) {
  34. if ($sql[$i] == ";" && !$in_string) {
  35. $ret[] = substr($sql, 0, $i);
  36. $sql = substr($sql, $i + 1);
  37. $i = 0;
  38. }
  39. if ($in_string && ($sql[$i] == $in_string) && $buffer[1] != "\\") {
  40. $in_string = false;
  41. } elseif (!$in_string && ($sql[$i] == '"' || $sql[$i] == "'") && (!isset($buffer[0]) || $buffer[0] != "\\")) {
  42. $in_string = $sql[$i];
  43. }
  44. if (isset($buffer[1])) {
  45. $buffer[0] = $buffer[1];
  46. }
  47. $buffer[1] = $sql[$i];
  48. }
  49. if (!empty($sql)) {
  50. $ret[] = $sql;
  51. }
  52. return($ret);
  53. } // split_sql
  54. /**
  55. * install_check_status
  56. * this function checks to see if we actually
  57. * still need to install ampache. This function is
  58. * very important, we don't want to reinstall over top of an existing install
  59. */
  60. function install_check_status($configfile)
  61. {
  62. /*
  63. Check and see if the config file exists
  64. if it does they can't use the web interface
  65. to install ampache.
  66. */
  67. if (!file_exists($configfile)) {
  68. return true;
  69. } else {
  70. //Error::add('general', T_('Config file already exists, install is probably completed'));
  71. }
  72. /*
  73. Check and see if they've got _any_ account
  74. if they don't then they're cool
  75. */
  76. $results = parse_ini_file($configfile);
  77. AmpConfig::set_by_array($results, true);
  78. if (!Dba::check_database()) {
  79. Error::add('general', T_('Unable to connect to database, check your ampache config'));
  80. return false;
  81. }
  82. $sql = 'SELECT * FROM `user`';
  83. $db_results = Dba::read($sql);
  84. if (!$db_results) {
  85. Error::add('general', T_('Unable to query database, check your ampache config'));
  86. return false;
  87. }
  88. if (!Dba::num_rows($db_results)) {
  89. return true;
  90. } else {
  91. Error::add('general', T_('Existing Database detected, unable to continue installation'));
  92. return false;
  93. }
  94. } // install_check_status
  95. function install_check_server_apache()
  96. {
  97. return (strpos($_SERVER['SERVER_SOFTWARE'], "Apache/") === 0);
  98. }
  99. function install_check_rewrite_rules($file, $web_path, $fix = false)
  100. {
  101. if (!is_readable($file)) {
  102. $file .= '.dist';
  103. }
  104. $valid = true;
  105. $htaccess = file_get_contents($file);
  106. $new_lines = array();
  107. $lines = explode("\n", $htaccess);
  108. foreach ($lines as $line) {
  109. $parts = explode(' ', $line);
  110. for ($i = 0; $i < count($parts); $i++) {
  111. // Matching url rewriting rule syntax
  112. if ($parts[$i] == 'RewriteRule' && $i < (count($parts) - 2)) {
  113. $reprule = $parts[$i + 2];
  114. if (!empty($web_path) && strpos($reprule, $web_path) !== 0) {
  115. $reprule = $web_path . $reprule;
  116. if ($fix) {
  117. $parts[$i + 2] = $reprule;
  118. $line = implode(' ', $parts);
  119. } else {
  120. $valid = false;
  121. }
  122. }
  123. break;
  124. }
  125. }
  126. if ($fix) {
  127. $new_lines[] = $line;
  128. }
  129. }
  130. if ($fix) {
  131. return implode("\n", $new_lines);
  132. }
  133. return $valid;
  134. }
  135. function install_rewrite_rules($file, $web_path, $download)
  136. {
  137. $final = install_check_rewrite_rules($file, $web_path, true);
  138. if (!$download) {
  139. if (!file_put_contents($file, $final)) {
  140. Error::add('general', T_('Error writing config file'));
  141. return false;
  142. }
  143. } else {
  144. $browser = new Horde_Browser();
  145. $browser->downloadHeaders(basename($file), 'text/plain', false, strlen($final));
  146. echo $final;
  147. exit();
  148. }
  149. return true;
  150. }
  151. /**
  152. * install_insert_db
  153. *
  154. * Inserts the database using the values from Config.
  155. */
  156. function install_insert_db($db_user = null, $db_pass = null, $create_db = true, $overwrite = false, $create_tables = true)
  157. {
  158. $database = AmpConfig::get('database_name');
  159. // Make sure that the database name is valid
  160. preg_match('/([^\d\w\_\-])/', $database, $matches);
  161. if (count($matches)) {
  162. Error::add('general', T_('Error: Invalid database name.'));
  163. return false;
  164. }
  165. if (!Dba::check_database()) {
  166. Error::add('general', sprintf(T_('Error: Unable to make database connection: %s'), Dba::error()));
  167. return false;
  168. }
  169. $db_exists = Dba::read('SHOW TABLES');
  170. if ($db_exists && $create_db) {
  171. if ($overwrite) {
  172. Dba::write('DROP DATABASE `' . $database . '`');
  173. } else {
  174. Error::add('general', T_('Error: Database already exists and overwrite not checked'));
  175. return false;
  176. }
  177. }
  178. if ($create_db) {
  179. if (!Dba::write('CREATE DATABASE `' . $database . '`')) {
  180. Error::add('general', sprintf(T_('Error: Unable to create database: %s'), Dba::error()));
  181. return false;
  182. }
  183. }
  184. Dba::disconnect();
  185. // Check to see if we should create a user here
  186. if (strlen($db_user) && strlen($db_pass)) {
  187. $db_host = AmpConfig::get('database_hostname');
  188. $sql = 'GRANT ALL PRIVILEGES ON `' . Dba::escape($database) . '`.* TO ' .
  189. "'" . Dba::escape($db_user) . "'";
  190. if ($db_host == 'localhost' || strpos($db_host, '/') === 0) {
  191. $sql .= "@'localhost'";
  192. }
  193. $sql .= "IDENTIFIED BY '" . Dba::escape($db_pass) . "' WITH GRANT OPTION";
  194. if (!Dba::write($sql)) {
  195. Error::add('general', sprintf(T_('Error: Unable to create user %1$s with permissions to %2$s on %3$s: %4$s'), $db_user, $database, $db_host, Dba::error()));
  196. return false;
  197. }
  198. } // end if we are creating a user
  199. if ($create_tables) {
  200. $sql_file = AmpConfig::get('prefix') . '/sql/ampache.sql';
  201. $query = fread(fopen($sql_file, 'r'), filesize($sql_file));
  202. $pieces = split_sql($query);
  203. $errors = array();
  204. for ($i=0; $i<count($pieces); $i++) {
  205. $pieces[$i] = trim($pieces[$i]);
  206. if (!empty($pieces[$i]) && $pieces[$i] != '#') {
  207. if (!$result = Dba::write($pieces[$i])) {
  208. $errors[] = array ( Dba::error(), $pieces[$i] );
  209. }
  210. }
  211. }
  212. }
  213. if ($create_db) {
  214. $sql = 'ALTER DATABASE `' . $database . '` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci';
  215. Dba::write($sql);
  216. }
  217. // If they've picked something other than English update default preferences
  218. if (AmpConfig::get('lang') != 'en_US') {
  219. // FIXME: 31? I hate magic.
  220. $sql = 'UPDATE `preference` SET `value`= ? WHERE `id` = 31';
  221. Dba::write($sql, array(AmpConfig::get('lang')));
  222. $sql = 'UPDATE `user_preference` SET `value` = ? WHERE `preference` = 31';
  223. Dba::write($sql, array(AmpConfig::get('lang')));
  224. }
  225. return true;
  226. }
  227. /**
  228. * install_create_config
  229. *
  230. * Attempts to write out the config file or offer it as a download.
  231. */
  232. function install_create_config($download = false)
  233. {
  234. $config_file = AmpConfig::get('prefix') . '/config/ampache.cfg.php';
  235. /* Attempt to make DB connection */
  236. Dba::dbh();
  237. $params = AmpConfig::get_all();
  238. if (empty($params['database_username']) || (empty($params['database_password']) && strpos($params['database_hostname'], '/') !== 0)) {
  239. Error::add('general', T_("Invalid configuration settings"));
  240. return false;
  241. }
  242. // Connect to the DB
  243. if (!Dba::check_database()) {
  244. Error::add('general', T_("Database Connection Failed Check Hostname, Username and Password"));
  245. return false;
  246. }
  247. $final = generate_config($params);
  248. // Make sure the directory is writable OR the empty config file is
  249. if (!$download) {
  250. if (!check_config_writable()) {
  251. Error::add('general', T_('Config file is not writable'));
  252. return false;
  253. } else {
  254. // Given that $final is > 0, we can ignore lazy comparison problems
  255. if (!file_put_contents($config_file, $final)) {
  256. Error::add('general', T_('Error writing config file'));
  257. return false;
  258. }
  259. }
  260. } else {
  261. $browser = new Horde_Browser();
  262. $browser->downloadHeaders('ampache.cfg.php', 'text/plain', false, strlen($final));
  263. echo $final;
  264. exit();
  265. }
  266. return true;
  267. }
  268. /**
  269. * install_create_account
  270. * this creates your initial account and sets up the preferences for the -1 user and you
  271. */
  272. function install_create_account($username, $password, $password2)
  273. {
  274. if (!strlen($username) OR !strlen($password)) {
  275. Error::add('general', T_('No Username/Password specified'));
  276. return false;
  277. }
  278. if ($password !== $password2) {
  279. Error::add('general', T_('Passwords do not match'));
  280. return false;
  281. }
  282. if (!Dba::check_database()) {
  283. Error::add('general', sprintf(T_('Database connection failed: %s'), Dba::error()));
  284. return false;
  285. }
  286. if (!Dba::check_database_inserted()) {
  287. Error::add('general', sprintf(T_('Database select failed: %s'), Dba::error()));
  288. return false;
  289. }
  290. $username = Dba::escape($username);
  291. $password = Dba::escape($password);
  292. $insert_id = User::create($username,'Administrator','','',$password,'100');
  293. if (!$insert_id) {
  294. Error::add('general', sprintf(T_('Administrative user creation failed: %s'), Dba::error()));
  295. return false;
  296. }
  297. // Fix the system users preferences
  298. User::fix_preferences('-1');
  299. return true;
  300. } // install_create_account
  301. function command_exists($command)
  302. {
  303. if (!function_exists('proc_open')) {
  304. return false;
  305. }
  306. $whereIsCommand = (PHP_OS == 'WINNT') ? 'where' : 'which';
  307. $process = proc_open(
  308. "$whereIsCommand $command",
  309. array(
  310. 0 => array("pipe", "r"), //STDIN
  311. 1 => array("pipe", "w"), //STDOUT
  312. 2 => array("pipe", "w"), //STDERR
  313. ),
  314. $pipes
  315. );
  316. if ($process !== false) {
  317. $stdout = stream_get_contents($pipes[1]);
  318. stream_get_contents($pipes[2]);
  319. fclose($pipes[1]);
  320. fclose($pipes[2]);
  321. proc_close($process);
  322. return $stdout != '';
  323. }
  324. return false;
  325. }
  326. /**
  327. * install_get_transcode_modes
  328. * get transcode modes available on this machine.
  329. */
  330. function install_get_transcode_modes()
  331. {
  332. $modes = array();
  333. if (command_exists('ffmpeg')) {
  334. $modes[] = 'ffmpeg';
  335. }
  336. if (command_exists('avconv')) {
  337. $modes[] = 'avconv';
  338. }
  339. return $modes;
  340. } // install_get_transcode_modes
  341. function install_config_transcode_mode($mode)
  342. {
  343. $trconfig = array(
  344. 'encode_target' => 'mp3',
  345. 'encode_video_target' => 'webm',
  346. 'transcode_m4a' => 'required',
  347. 'transcode_flac' => 'required',
  348. 'transcode_mpc' => 'required',
  349. 'transcode_ogg' => 'allowed',
  350. 'transcode_wav' => 'required',
  351. 'transcode_avi' => 'allowed',
  352. 'transcode_mpg' => 'allowed',
  353. 'transcode_mkv' => 'allowed',
  354. );
  355. if ($mode == 'ffmpeg' || $mode == 'avconv') {
  356. $trconfig['transcode_cmd'] = $mode;
  357. $trconfig['transcode_input'] = '-i %FILE%';
  358. $trconfig['waveform'] = 'true';
  359. $trconfig['generate_video_preview'] = 'true';
  360. AmpConfig::set_by_array($trconfig, true);
  361. }
  362. }
  363. function install_config_use_case($case)
  364. {
  365. $trconfig = array(
  366. 'use_auth' => 'true',
  367. 'ratings' => 'true',
  368. 'userflags' => 'true',
  369. 'sociable' => 'true',
  370. 'notify' => 'true',
  371. 'licensing' => 'false',
  372. 'wanted' => 'true',
  373. 'channel' => 'true',
  374. 'live_stream' => 'true',
  375. 'allow_public_registration' => 'false',
  376. 'cookie_disclaimer' => 'false',
  377. 'share' => 'false'
  378. );
  379. $dbconfig = array(
  380. 'download' => '1',
  381. 'share' => '0',
  382. 'allow_video' => '1',
  383. 'home_now_playing' => '1',
  384. 'home_recently_played' => '1'
  385. );
  386. switch ($case) {
  387. case 'minimalist':
  388. $trconfig['ratings'] = 'false';
  389. $trconfig['userflags'] = 'false';
  390. $trconfig['sociable'] = 'false';
  391. $trconfig['notify'] = 'false';
  392. $trconfig['wanted'] = 'false';
  393. $trconfig['channel'] = 'false';
  394. $trconfig['live_stream'] = 'false';
  395. $dbconfig['download'] = '0';
  396. $dbconfig['allow_video'] = '0';
  397. // Hide sidebar by default to have a better 'minimalist first look'.
  398. setcookie('sidebar_state', 'collapsed', time() + (30 * 24 * 60 * 60), '/');
  399. break;
  400. case 'community':
  401. $trconfig['use_auth'] = 'false';
  402. $trconfig['licensing'] = 'true';
  403. $trconfig['wanted'] = 'false';
  404. $trconfig['live_stream'] = 'false';
  405. $trconfig['allow_public_registration'] = 'true';
  406. $trconfig['cookie_disclaimer'] = 'true';
  407. $trconfig['share'] = 'true';
  408. $dbconfig['download'] = '0';
  409. $dbconfig['share'] = '1';
  410. $dbconfig['home_now_playing'] = '0';
  411. $dbconfig['home_recently_played'] = '0';
  412. break;
  413. default:
  414. break;
  415. }
  416. AmpConfig::set_by_array($trconfig, true);
  417. foreach ($dbconfig as $preference => $value) {
  418. Preference::update($preference, -1, $value, true, true);
  419. }
  420. }
  421. function install_config_backends(Array $backends)
  422. {
  423. $dbconfig = array(
  424. 'subsonic_backend' => '0',
  425. 'plex_backend' => '0',
  426. 'daap_backend' => '0',
  427. 'upnp_backend' => '0',
  428. 'stream_beautiful_url' => '0'
  429. );
  430. foreach ($backends as $backend) {
  431. switch ($backend) {
  432. case 'subsonic':
  433. $dbconfig['subsonic_backend'] = '1';
  434. break;
  435. case 'plex':
  436. $dbconfig['plex_backend'] = '1';
  437. break;
  438. case 'upnp':
  439. $dbconfig['upnp_backend'] = '1';
  440. $dbconfig['stream_beautiful_url'] = '1';
  441. break;
  442. case 'daap':
  443. $dbconfig['daap_backend'] = '1';
  444. break;
  445. }
  446. }
  447. foreach ($dbconfig as $preference => $value) {
  448. Preference::update($preference, -1, $value, true, true);
  449. }
  450. }