3 * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
4 * Copyright (C) 2002-2012 The Nucleus Group
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 * (see nucleus/documentation/index.html#license for more info)
12 * This script will install the Nucleus tables in your SQL-database,
13 * and initialize the data in those tables.
17 * @license http://nucleuscms.org/license.txt GNU General Public License
18 * @copyright Copyright (C) 2002-2012 The Nucleus Group
19 * @version $Id: index.php 1889 2012-06-17 08:46:45Z sakamocchi $
22 /* global values initialize */
25 /* reporting all errors for support */
26 error_reporting(E_ALL);
28 $minimum_php_version = '5.0.6';
29 $minimum_mysql_version = '3.23';
31 $page_footer_copyright = '© 2001-2012 The Nucleus Groupe . Running Nucleus CMS v4.00';
33 // begin if: server's PHP version is below the minimum; halt installation
34 if ( version_compare(PHP_VERSION, $minimum_php_version, '<') )
36 exit('<div style="font-size: xx-large;"> Nucleus requires at least PHP version ' . $minimum_php_version . '</div>');
39 // make sure there's no unnecessary escaping: # set_magic_quotes_runtime(0);
40 if ( version_compare(PHP_VERSION, '5.3.0', '<') )
42 ini_set('magic_quotes_runtime', '0');
45 /* default installed plugins and skins */
46 $aConfPlugsToInstall = array('NP_SecurityEnforcer', 'NP_SkinFiles', 'NP_Medium');
47 $aConfSkinsToImport = array('atom', 'rss2.0', 'rsd', 'default', 'admin/default', 'admin/bookmarklet');
49 // Check if some important files
52 /* i18n class is needed for internationalization */
53 include_once('../nucleus/libs/i18n.php');
54 if ( !i18n::init('UTF-8', '../nucleus/locales') )
56 exit('<div style="font-size: xx-large;"> Failed to initialize iconv or mbstring extension. Would you please contact the administrator of your PHP server? </div>');
59 // include core classes that are needed for login & plugin handling
61 // added for 3.5 sql_* wrapper
62 global $MYSQL_HANDLER;
64 if ( !isset($MYSQL_HANDLER) )
66 $MYSQL_HANDLER = array('mysql', '');
68 // check if mysql support is installed; this check may not make sense, as is, in a version past 3.5x
69 if ( !function_exists('mysql_query') && !function_exists('mysqli_query') )
71 exit('<div style="font-size: xx-large;"> Your PHP version does not have support for MySQL :( </div>');
74 include_once('../nucleus/libs/sql/sql.php');
77 if ( count($_GET) == 0 && count($_POST) == 0 )
79 unset($_SESSION['param_manager']);
82 // restore the $param from the session
83 if ( array_key_exists('param_manager', $_SESSION) )
85 $param = $_SESSION['param_manager'];
89 $param = new ParamManager();
92 // include translation file
97 // $param is saved to the session
100 $_SESSION['param_manager'] = $param;
104 unset($_SESSION['param_manager']);
115 if ( array_key_exists('action', $_POST) )
125 if ( array_key_exists('mode', $_REQUEST) )
127 if ( $_REQUEST['mode'] == 'detail' )
129 $param->set_state('detail');
131 elseif ( $_REQUEST['mode'] == 'simple' )
133 $param->set_state('mysql');
137 // input parameter check
140 switch ( $param->state )
143 $param->set_state('mysql');
147 if ( count($param->check_mysql_parameters()) == 0 )
149 $param->set_state('weblog');
154 if ( count($param->check_user_parameters()) == 0
155 && count($param->check_weblog_parameters()) == 0 )
157 $param->set_state('install');
162 if ( $param->check_all_parameters() )
164 $param->set_state('install');
173 switch ( $param->state )
176 show_select_locale_form();
179 show_database_setting_form($isPostback);
182 show_blog_setting_form($isPostback);
185 show_detail_setting_form($isPostback);
188 show_install_complete_form();
195 * header tag of the installation screens
197 function show_header()
201 /* HTTP 1.1 application for no caching */
202 header("Cache-Control: no-cache, must-revalidate");
203 header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
204 header('Content-Type: text/html; charset=' . i18n::get_current_charset());
206 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
207 <html xmlns="http://www.w3.org/1999/xhtml">
209 <title><?php echo _TITLE; ?></title>
210 <link rel="stylesheet" type="text/css" href="./styles/inst.css" />
211 <style type="text/css">
213 <?php echo _BODYFONTSTYLE; ?>
216 <script type="text/javascript">
217 function SelectText( element ) {
218 window.setTimeout( function() { element.select() }, 0 );
220 var isSubmit = false;
221 function OnceSubmit() {
224 window.setTimeout( function() { isSubmit = false; }, 10000 );
233 <div id="navigation">
234 <h1><img src="./styles/nucleus_rogo.png" alt="NucleusCMS" /></h1>
238 $label = '_LOCALE_' . strtoupper($param->locale);
239 if ( !defined($label) )
245 echo constant($label);
249 if ( in_array($param->state, array('mysql', 'weblog', 'install')) )
251 echo '<li> > ' . _STEP1, '</li><li';
252 if ( $param->state == 'mysql' )
256 echo '> > ', _STEP2, '</li><li';
257 if ( in_array($param->state, array('mysql', 'weblog')) )
261 echo '> > ', _STEP3, "</li>\n";
263 if ( in_array($param->state, array('mysql', 'weblog', 'detail')) )
265 echo '<li class="rightbox">';
266 if ( in_array($param->state, array('mysql', 'weblog')) )
268 echo '<a href="./?mode=detail">', _MODE2, '</a>';
272 echo '<a href="./?mode=simple">', _MODE1, '</a>';
284 * footer tag of the installation screens
286 function show_footer()
288 global $page_footer_copyright;
291 <?php echo $page_footer_copyright; ?>
299 * Display the form for language select
301 function show_select_locale_form()
307 <p style="font-size:152%;font-weight:bold;">
308 <?php echo _LOCALE_HEADER; ?>
310 <form method="post" action="./index.php">
313 <select name="locale">
315 $locales = i18n::get_available_locale_list();
316 foreach ( $locales as $locale )
318 if ( $param->locale != $locale )
320 echo "<option value=\"{$locale}\">";
324 echo "<option value=\"{$locale}\" selected=\"selected\">";
327 $checkfile = "./locales/{$locale}." . i18n::get_current_charset() . '.php';
328 if ( !file_exists($checkfile) )
333 $label = '_LOCALE_' . strtoupper($locale);
334 if ( !defined($label) )
340 echo constant($label);
346 <p><?php echo _LOCALE_DESC1; ?></p>
347 <p><?php echo _LOCALE_DESC2; ?></p>
348 <p><?php echo _LOCALE_NEED_HELP;?></p>
350 <button type="submit" name="action" value="locale" class="sbt_arw">START</button>
359 * Display the form to set up a database
360 * @param bool $isPostback
362 function show_database_setting_form($isPostback)
364 global $param, $minimum_mysql_version;
366 $config_writable = canConfigFileWritable();
367 $mysql_version = getMySqlVersion();
373 if ( $config_writable != '' )
375 echo '<span class="err">', $config_writable, '</span>';
377 if ( $mysql_version == '0.0.0' )
379 echo '<span class="err">', _DBVERSION_UNKOWN, '</span>';
381 elseif ( version_compare($mysql_version, $minimum_mysql_version, '<') )
383 echo '<span class="err">', sprintf(_DBVERSION_TOOLOW, $minimum_mysql_version), '</span>';
387 <form method="post" action="./index.php">
389 <h2><?php echo _DB_HEADER; ?></h2>
394 $errors = $param->check_mysql_parameters();
395 if ( is_array($errors) )
397 foreach ( $errors as $error )
399 echo '<span class="err">', $error, "</span>\n";
407 <th><span class="nam"><?php echo _DB_FIELD1; ?></span><span class="sub"><?php echo _DB_FIELD1_DESC; ?></span></th>
408 <td><input type="text" name="mysql_host" value="<?php echo $param->mysql_host; ?>" /></td>
411 <th><span class="nam"><?php echo _DB_FIELD2; ?></span><span class="sub"><?php echo _DB_FIELD2_DESC; ?></span></th>
412 <td><input type="text" name="mysql_user" value="<?php echo $param->mysql_user; ?>" /></td>
415 <th><span class="nam"><?php echo _DB_FIELD3; ?></span></th>
416 <td><input type="text" name="mysql_password" value="<?php echo $param->mysql_password; ?>" /></td>
419 <th><span class="nam"><?php echo _DB_FIELD4; ?></span><span class="sub"><?php echo _DB_FIELD4_DESC; ?></span></th>
420 <td><input type="text" name="mysql_database" value="<?php echo $param->mysql_database; ?>" /></td>
424 <button type="submit" name="mode" value="detail" class="sbt_sqr"><?php echo _MODE2; ?></button>
425 <button type="submit" name="action" value="mysql" class="sbt_arw"><?php echo _NEXT; ?></button>
428 <?php echo _DB_TEXT1; ?>
437 * Displays a form to the blog settings
438 * @param bool $isPostback
440 function show_blog_setting_form($isPostback)
446 <?php echo _SIMPLE_NAVI2; ?>
448 <form method="post" action="./index.php">
450 <h2><?php echo _BLOG_HEADER; ?></h2>
455 $errors = $param->check_weblog_parameters();
456 if ( is_array($errors) )
458 foreach ( $errors as $error )
460 echo '<span class="err">', $error, "</span>\n";
468 <th><span class="nam"><?php echo _BLOG_FIELD1; ?></span></th>
469 <td><input type="text" name="blog_name" value="<?php echo $param->blog_name; ?>" /></td>
472 <th><span class="nam"><?php echo _BLOG_FIELD2; ?></span><span class="sub"><?php echo _BLOG_FIELD2_DESC; ?></span></th>
473 <td><input type="text" name="blog_shortname" value="<?php echo $param->blog_shortname; ?>" /></td>
479 <h2><?php echo _ADMIN_HEADER; ?></h2>
484 $errors = $param->check_user_parameters();
485 if ( is_array($errors) )
487 foreach ( $errors as $error )
489 echo '<span class="err">', $error, "</span>\n";
497 <th><span class="nam"><?php echo _ADMIN_FIELD1; ?></span></th>
498 <td><input type="text" name="user_realname" value="<?php echo $param->user_realname; ?>" /></td>
501 <th><span class="nam"><?php echo _ADMIN_FIELD2; ?></span><span class="sub"><?php echo _ADMIN_FIELD2_DESC; ?></span></th>
502 <td><input type="text" name="user_name" value="<?php echo $param->user_name; ?>" /></td>
505 <th><span class="nam"><?php echo _ADMIN_FIELD3; ?></span></th>
506 <td><input type="password" name="user_password" /></td>
509 <th><span class="nam"><?php echo _ADMIN_FIELD4; ?></span></th>
510 <td><input type="password" name="user_password2" /></td>
513 <th><span class="nam"><?php echo _ADMIN_FIELD5; ?></span></th>
514 <td><input type="text" name="user_email" value="<?php echo $param->user_email; ?>" /></td>
518 <button type="submit" name="action" value="weblog" class="sbt_arw" onclick="OnceSubmit()"><?php echo _INSTALL; ?></button>
527 * Displays a form to the detail settings
528 * @param bool $isPostback
530 function show_detail_setting_form($isPostback)
532 global $param, $minimum_mysql_version;
534 $mysql_version = getMySqlVersion();
536 <div id="container_detailed">
538 <?php echo _DETAIL_NAVI1; ?>
540 if ( $isPostback && !$param->check_all_parameters() )
542 echo '<span class="err">', _VALID_ERROR, "</span>\n";
547 <li>PHP: <?php echo phpversion(); ?></li>
550 echo ($mysql_version == '0.0.0') ? _DBVERSION_UNKOWN : $mysql_version;
551 if ( version_compare($mysql_version, $minimum_mysql_version, '<') )
553 echo '<span class="err">', sprintf(_DBVERSION_TOOLOW, $minimum_mysql_version), '</span>';
557 <form method="post" action="">
560 <h2><?php echo _DETAIL_HEADER1; ?></h2>
565 $errors = $param->check_mysql_parameters();
566 if ( is_array($errors) )
568 foreach ( $errors as $error )
570 echo '<span class="err">', $error, "</span>\n";
578 <th><span class="nam"><?php echo _DB_FIELD1; ?></span><span class="sub"><?php echo _DB_FIELD1_DESC; ?></span></th>
579 <td><input type="text" name="mysql_host" value="<?php echo $param->mysql_host; ?>" /></td>
582 <th><span class="nam"><?php echo _DB_FIELD2; ?></span><span class="sub"><?php echo _DB_FIELD2_DESC; ?></span></th>
583 <td><input type="text" name="mysql_user" value="<?php echo $param->mysql_user; ?>" /></td>
586 <th><span class="nam"><?php echo _DB_FIELD3; ?></span></th>
587 <td><input type="text" name="mysql_password" value="<?php echo $param->mysql_password; ?>" /></td>
590 <th><span class="nam"><?php echo _DB_FIELD4; ?></span><span class="sub"><?php echo _DB_FIELD4_DESC; ?></span></th>
591 <td><input type="text" name="mysql_database" value="<?php echo $param->mysql_database; ?>" /></td>
594 <th><span class="nam"><?php echo _DB_FIELD5; ?></span><span class="sub"><?php echo _DB_FIELD5_DESC; ?></span></th>
595 <td><input type="text" name="mysql_tablePrefix" value="<?php echo $param->mysql_tablePrefix; ?>" /></td>
599 <h2><?php echo _DETAIL_HEADER2; ?></h2>
604 $errors = $param->check_uri_parameters();
605 if ( is_array($errors) )
607 foreach ( $errors as $error )
609 echo '<span class="err">', $error, "</span>\n";
612 $errors = $param->check_path_parameters();
613 if ( is_array($errors) )
615 foreach ( $errors as $error )
617 echo '<span class="err">', $error, "</span>\n";
625 <th><span class="nam"><?php echo _PATH_FIELD1; ?></span></th>
626 <td><input type="text" name="IndexURL" value="<?php echo $param->IndexURL; ?>" /></td>
629 <th><span class="nam"><?php echo _PATH_FIELD2; ?></span></th>
630 <td><input type="text" name="AdminURL" value="<?php echo $param->AdminURL; ?>" /></td>
633 <th><span class="nam"><?php echo _PATH_FIELD3; ?></span></th>
634 <td><input type="text" name="AdminPath" value="<?php echo $param->AdminPath; ?>" /></td>
637 <th><span class="nam"><?php echo _PATH_FIELD4; ?></span></th>
638 <td><input type="text" name="MediaURL" value="<?php echo $param->MediaURL; ?>" /></td>
641 <th><span class="nam"><?php echo _PATH_FIELD5; ?></span></th>
642 <td><input type="text" name="MediaPath" value="<?php echo $param->MediaPath; ?>" /></td>
645 <th><span class="nam"><?php echo _PATH_FIELD6; ?></span></th>
646 <td><input type="text" name="SkinsURL" value="<?php echo $param->SkinsURL; ?>" /></td>
649 <th><span class="nam"><?php echo _PATH_FIELD7; ?></span></th>
650 <td><input type="text" name="SkinsPath" value="<?php echo $param->SkinsPath; ?>" /></td>
653 <th><span class="nam"><?php echo _PATH_FIELD8; ?></span></th>
654 <td><input type="text" name="PluginURL" value="<?php echo $param->PluginURL; ?>" /></td>
657 <th><span class="nam"><?php echo _PATH_FIELD9; ?></span></th>
658 <td><input type="text" name="ActionURL" value="<?php echo $param->ActionURL; ?>" /></td>
662 <?php echo _DETAIL_TEXT3; ?>
665 <h2><?php echo _DETAIL_HEADER3; ?></h2>
671 $errors = $param->check_user_parameters();
672 if ( is_array($errors) )
674 foreach ( $errors as $error )
676 echo '<span class="err">', $error, "</span>\n";
684 <th><span class="nam"><?php echo _ADMIN_FIELD1; ?></span></th>
685 <td><input type="text" name="user_realname" value="<?php echo $param->user_realname; ?>" /></td>
688 <th><span class="nam"><?php echo _ADMIN_FIELD2; ?></span><span class="sub"><?php echo _ADMIN_FIELD2_DESC; ?></span></th>
689 <td><input type="text" name="user_name" value="<?php echo $param->user_name; ?>" /></td>
692 <th><span class="nam"><?php echo _ADMIN_FIELD3; ?></span></th>
693 <td><input type="password" name="user_password" /></td>
696 <th><span class="nam"><?php echo _ADMIN_FIELD4; ?></span></th>
697 <td><input type="password" name="user_password2" /></td>
700 <th><span class="nam"><?php echo _ADMIN_FIELD5; ?></span></th>
701 <td><input type="text" name="user_email" value="<?php echo $param->user_email; ?>" /></td>
705 <h2><?php echo _DETAIL_HEADER4; ?></h2>
711 $errors = $param->check_weblog_parameters();
712 if ( is_array($errors) )
714 foreach ( $errors as $error )
716 echo '<span class="err">', $error, "</span>\n";
724 <th><span class="nam"><?php echo _BLOG_FIELD1; ?></span></th>
725 <td><input type="text" name="blog_name" value="<?php echo $param->blog_name; ?>" /></td>
728 <th><span class="nam"><?php echo _BLOG_FIELD2; ?></span><span class="sub"><?php echo _BLOG_FIELD2_DESC; ?></span></th>
729 <td><input type="text" name="blog_shortname" value="<?php echo $param->blog_shortname; ?>" /></td>
734 <?php echo _DETAIL_TEXT6; ?>
738 <button type="submit" name="action" value="detail" class="sbt_arw" onclick="OnceSubmit()"><?php echo _INSTALL; ?></button>
747 * Displays a screen to signal the completion of the installation
749 function show_install_complete_form()
751 global $MYSQL_HANDLER, $param;
752 $errors = do_install();
757 if ( is_array($errors) && count($errors) > 0 )
760 foreach ( $errors as $error )
762 echo '<span class="err">', $error, "</span>\n";
768 if ( array_key_exists('config_data', $_SESSION) )
770 echo '<span class="err">', _INST_TEXT4, '</span>';
772 <textarea id="config_text" readonly="readonly" onfocus="SelectText(this);"><?php echo htmlentities($_SESSION['config_data'], null, i18n::get_current_charset()) ?></textarea>
777 echo '<span class="err">', _INST_TEXT5, '</span>';
781 <form method="post" action="./index.php">
783 <h2><?php echo _INST_HEADER1; ?></h2>
785 <?php echo sprintf(_INST_TEXT1, $param->blog_name); ?>
788 <button type="button" name="toBlog" onclick="location.href='<?php echo $param->IndexURL; ?>';" class="sbt_arw"><?php echo _INST_BUTTON1; ?></button>
793 <h2><?php echo _INST_HEADER2; ?></h2>
795 <?php echo _INST_TEXT2; ?>
798 <button type="button" name="toMng" onclick="location.href='<?php echo $param->AdminURL; ?>';" class="sbt_arw"><?php echo _INST_BUTTON2; ?></button>
803 <h2><?php echo _INST_HEADER3; ?></h2>
805 <?php echo _INST_TEXT3; ?>
808 <button type="button" name="toAddBlog" onclick="location.href='<?php echo $param->AdminURL; ?>index.php?action=createnewlog';" class="sbt_arw"><?php echo _INST_BUTTON3; ?></button>
821 * The installation process itself
822 * @return array error messages
824 function do_install()
827 global $MYSQL_HANDLER, $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD, $MYSQL_DATABASE, $MYSQL_PREFIX, $MYSQL_CONN;
828 global $DIR_NUCLEUS, $DIR_MEDIA, $DIR_SKINS, $DIR_PLUGINS, $DIR_LANG, $DIR_LIBS;
832 * 1. put all param-vars into vars
834 $MYSQL_HOST = $param->mysql_host;
835 $MYSQL_USER = $param->mysql_user;
836 $MYSQL_PASSWORD = $param->mysql_password;
837 $MYSQL_DATABASE = $param->mysql_database;
838 $MYSQL_PREFIX = $param->mysql_tablePrefix;
840 $DIR_NUCLEUS = $param->AdminPath;
841 $DIR_MEDIA = $param->MediaPath;
842 $DIR_SKINS = $param->SkinsPath;
843 $DIR_PLUGINS = $DIR_NUCLEUS . 'plugins/';
844 $DIR_LOCALES = $DIR_NUCLEUS . 'locales/';
845 $DIR_LIBS = $DIR_NUCLEUS . 'libs/';
848 * 2.open mySQL connection
850 $MYSQL_CONN = @DB::setConnectionInfo($MYSQL_HANDLER[1], $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD);
851 if ( $MYSQL_CONN == FALSE )
853 $errors[] = _DBCONNECT_ERROR;
858 * 3. try to create database if needed
860 if ( DB::execute("CREATE DATABASE IF NOT EXISTS {$MYSQL_DATABASE}") === FALSE )
862 $errinfo = DB::getError();
863 $errors[] = _INST_ERROR1 . ': ' . $errinfo[2];
867 * 4. try to select database
869 $MYSQL_CONN = @DB::setConnectionInfo($MYSQL_HANDLER[1], $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD, $MYSQL_DATABASE);
872 $errors[] = _INST_ERROR2;
875 if ( count($errors) > 0 )
883 $table_names = array(
897 'nucleus_activation',
901 $prefixed_table_names = array();
902 foreach ( $table_names as $table_name )
904 $prefixed_table_names[] = $MYSQL_PREFIX . $table_name;
907 // table exists check
908 $result = DB::getResult('SHOW TABLES');
909 foreach ( $result as $row )
911 if ( in_array($row[0], $prefixed_table_names) )
913 $errors[] = _INST_ERROR3;
917 if ( count($errors) > 0 )
922 $filename = 'install.sql';
923 $fd = fopen($filename, 'r');
924 $queries = fread($fd, filesize($filename));
927 $queries = preg_split('#(;\n|;\r)#', $queries);
929 foreach ( $queries as $query )
931 if ( preg_match('/\w+/', $query) )
935 $query = str_replace($table_names, $prefixed_table_names, $query);
938 if ( DB::execute($query) === FALSE )
940 $errinfo = DB::getError();
941 $errors[] = _INST_ERROR4 . ' (<small>' . $query . '</small>): ' . $errinfo[2];
947 * 6. put needed records
949 /* push first post */
950 $query = "INSERT INTO %s VALUES (1, %s, %s, %s, 1, 1, %s, 0, 0, 0, 1, 0, 1)";
951 $query = sprintf($query,
952 tableName('nucleus_item'),
953 DB::quoteValue(_1ST_POST_TITLE),
954 DB::quoteValue(_1ST_POST),
955 DB::quoteValue(_1ST_POST2),
958 if ( DB::execute($query) === FALSE )
960 $errinfo = DB::getError();
961 $errors[] = _INST_ERROR4 . ' (<small>' . $query . '</small>): ' . $errinfo[2];
964 /* push configurations */
965 array_merge($errors, updateConfig('IndexURL', $param->IndexURL));
966 array_merge($errors, updateConfig('AdminURL', $param->AdminURL));
967 array_merge($errors, updateConfig('MediaURL', $param->MediaURL));
968 array_merge($errors, updateConfig('SkinsURL', $param->SkinsURL));
969 array_merge($errors, updateConfig('PluginURL', $param->PluginURL));
970 array_merge($errors, updateConfig('ActionURL', $param->ActionURL));
971 array_merge($errors, updateConfig('AdminEmail', $param->user_email));
972 array_merge($errors, updateConfig('SiteName', $param->blog_name));
973 array_merge($errors, updateConfig('Locale', i18n::get_current_locale()));
975 /* push super admin */
976 $query = "UPDATE %s SET mname = %s, mrealname = %s, mpassword = %s, memail = %s, murl = %s, madmin = 1, mcanlogin = 1 WHERE mnumber = 1";
977 $query = sprintf($query,
978 tableName('nucleus_member'),
979 DB::quoteValue($param->user_name),
980 DB::quoteValue($param->user_realname),
981 DB::quoteValue(md5($param->user_password)),
982 DB::quoteValue($param->user_email),
983 DB::quoteValue($param->IndexURL)
985 if ( DB::execute($query) === FALSE )
987 $errinfo = DB::getError();
988 $errors[] = _INST_ERROR5 . ': ' . $errinfo[2];
991 /* push new weblog */
992 $query = "UPDATE %s SET bname = %s, bshortname = %s, burl = %s WHERE bnumber = 1";
993 $query = sprintf($query,
994 tableName('nucleus_blog'),
995 DB::quoteValue($param->blog_name),
996 DB::quoteValue($param->blog_shortname),
997 DB::quoteValue($param->IndexURL)
999 if ( DB::execute($query) === FALSE )
1001 $errinfo = DB::getError();
1002 $errors[] = _INST_ERROR6 . ': ' . $errinfo[2];
1005 /* push default category */
1006 $query = "UPDATE %s SET cname = %s, cdesc = %s WHERE catid = 1";
1007 $query = sprintf($query,
1008 tableName('nucleus_category'),
1009 DB::quoteValue(_GENERALCAT_NAME),
1010 DB::quoteValue(_GENERALCAT_DESC)
1012 if ( DB::execute($query) === FALSE )
1014 $errinfo = DB::getError();
1015 $errors[] = _INST_ERROR6 . ': ' . $errinfo[2];
1019 * 7. install default plugins and skins
1021 global $aConfPlugsToInstall, $aConfSkinsToImport;
1022 $aSkinErrors = array();
1023 $aPlugErrors = array();
1025 if ( (count($aConfPlugsToInstall) > 0) || (count($aConfSkinsToImport) > 0) )
1027 include_once($DIR_LIBS . 'globalfunctions.php');
1029 if ( !isset($manager) )
1031 $manager = new Manager();
1034 include_once($DIR_LIBS . 'skinie.php');
1036 $aSkinErrors = installCustomSkins();
1037 if ( count($aSkinErrors) > 0 )
1039 array_merge($errors, $aSkinErrors);
1042 $query = "SELECT sdnumber FROM %s WHERE sdname='admin/default'";
1043 $query = sprintf($query, tableName('nucleus_skin_desc'));
1044 $res = intval(DB::getValue($query));
1045 array_merge($errors, updateConfig('AdminSkin', $res));
1047 $query = "SELECT sdnumber FROM %s WHERE sdname='admin/bookmarklet'";
1048 $query = sprintf($query, tableName('nucleus_skin_desc'));
1049 $res = intval(DB::getValue($query));
1050 array_merge($errors, updateConfig('BookmarkletSkin', $res));
1052 $query = "SELECT sdnumber FROM %s WHERE sdname='default'";
1053 $query = sprintf($query, tableName('nucleus_skin_desc'));
1054 $defSkinID = intval(DB::getValue($query));
1056 $query = "UPDATE %s SET bdefskin=%d WHERE bnumber=1";
1057 $query = sprintf($query, tableName('nucleus_blog'), $defSkinID);
1058 DB::execute($query);
1059 $query = "UPDATE %s SET value=%d WHERE name='BaseSkin'";
1060 $query = sprintf($query, tableName('nucleus_config'), $defSkinID);
1061 DB::execute($query);
1063 $aPlugErrors = installCustomPlugs();
1064 if ( count($aPlugErrors) > 0 )
1066 array_merge($errors, $aPlugErrors);
1071 * 8. Write config file ourselves (if possible)
1073 $config_data = '<' . '?php' . "\n";
1074 $config_data .= "// mySQL connection information\n";
1075 $config_data .= "\$MYSQL_HOST = '" . $MYSQL_HOST . "';\n";
1076 $config_data .= "\$MYSQL_USER = '" . $MYSQL_USER . "';\n";
1077 $config_data .= "\$MYSQL_PASSWORD = '" . $MYSQL_PASSWORD . "';\n";
1078 $config_data .= "\$MYSQL_DATABASE = '" . $MYSQL_DATABASE . "';\n";
1079 $config_data .= "\$MYSQL_PREFIX = '" . $MYSQL_PREFIX . "';\n";
1080 $config_data .= "// new in 3.50. first element is db handler, the second is the db driver used by the handler\n";
1081 $config_data .= "// default is \$MYSQL_HANDLER = array('mysql','mysql');\n";
1082 $config_data .= "//\$MYSQL_HANDLER = array('mysql','mysql');\n";
1083 $config_data .= "//\$MYSQL_HANDLER = array('pdo','mysql');\n";
1084 $config_data .= "\$MYSQL_HANDLER = array('" . $MYSQL_HANDLER[0] . "','" . $MYSQL_HANDLER[1] . "');\n";
1085 $config_data .= "\n";
1086 $config_data .= "// main nucleus directory\n";
1087 $config_data .= "\$DIR_NUCLEUS = '" . $DIR_NUCLEUS . "';\n";
1088 $config_data .= "\n";
1089 $config_data .= "// path to media dir\n";
1090 $config_data .= "\$DIR_MEDIA = '" . $DIR_MEDIA . "';\n";
1091 $config_data .= "\n";
1092 $config_data .= "// extra skin files for imported skins\n";
1093 $config_data .= "\$DIR_SKINS = '" . $DIR_SKINS . "';\n";
1094 $config_data .= "\n";
1095 $config_data .= "// these dirs are normally sub dirs of the nucleus dir, but \n";
1096 $config_data .= "// you can redefine them if you wish\n";
1097 $config_data .= "\$DIR_PLUGINS = \$DIR_NUCLEUS . 'plugins/';\n";
1098 $config_data .= "\$DIR_LOCALES = \$DIR_NUCLEUS . 'locales/';\n";
1099 $config_data .= "\$DIR_LIBS = \$DIR_NUCLEUS . 'libs/';\n";
1100 $config_data .= "\n";
1101 $config_data .= "// include libs\n";
1102 $config_data .= "include(\$DIR_LIBS.'globalfunctions.php');\n";
1103 $config_data .= "?" . ">";
1106 if ( @!file_exists('../config.php') || is_writable('../config.php') )
1108 if ( $fp = @fopen('../config.php', 'w') )
1110 $result = @fwrite($fp, $config_data, i18n::strlen($config_data));
1117 // try to change the read-only permission.
1118 if ( strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN' )
1120 @chmod('../config.php', 0444);
1125 $_SESSION['config_data'] = $config_data;
1132 * Confirm that you can write to the configuration file
1133 * @return string error message
1135 function canConfigFileWritable()
1137 if ( @file_exists('../config.php') && @!is_writable('../config.php') )
1139 // try to change the read-write permission.
1140 if ( strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN' )
1142 @chmod('../config.php', 0666);
1145 if ( @!is_writable('../config.php') )
1147 return _INST_ERROR8;
1154 * To obtain the version of MySQL
1157 function getMySqlVersion()
1159 global $MYSQL_HANDLER, $minimum_mysql_version, $errors;
1160 // Turn on output buffer
1161 // Needed to repress the output of the sql function that are
1162 // not part of php (in this case the @ operator doesn't work)
1165 // note: this piece of code is taken from phpMyAdmin
1166 $conn = @DB::setConnectionInfo($MYSQL_HANDLER[1], 'localhost', '', '');
1170 $row = DB::getAttribute(PDO::ATTR_SERVER_VERSION);
1171 $match = preg_split('#\.#', $row);
1175 $row = @DB::getRow('SHOW VARIABLES LIKE \'version\'');
1179 $match = preg_split('#\.#', $row[1]);
1183 $output = (function_exists('shell_exec')) ? @shell_exec('mysql -V') : '0.0.0';
1184 preg_match('@[0-9]+\.[0-9]+\.[0-9]+@', $output, $version);
1185 $match = preg_split('#\.#', $version[0]);
1187 if ( $match[0] == '' )
1189 $match = array('0', '0', '0');
1196 //End and clean output buffer
1199 return implode($match, '.');
1203 * Add a table prefix if it is used
1205 * @param string $input table name with prefix
1208 function tableName($input)
1210 global $MYSQL_PREFIX;
1211 if ( $MYSQL_PREFIX )
1213 return $MYSQL_PREFIX . $input;
1222 * Install custom plugins
1224 function installCustomPlugs()
1226 global $aConfPlugsToInstall, $DIR_LIBS, $manager;
1229 if ( count($aConfPlugsToInstall) == 0 )
1234 $query = sprintf('SELECT * FROM %s', tableName('nucleus_plugin'));
1235 $res = DB::getResult($query);
1236 $numCurrent = $res->rowCount();
1238 foreach ( $aConfPlugsToInstall as $plugName )
1240 $query = sprintf('INSERT INTO %s (porder, pfile) VALUES (%d, %s)',
1241 tableName('nucleus_plugin'),
1243 DB::quoteValue($plugName));
1244 DB::execute($query);
1246 $manager->clearCachedInfo('installedPlugins');
1247 $plugin =& $manager->getPlugin($plugName);
1248 $plugin->setID($numCurrent);
1252 $query = sprintf('DELETE FROM %s WHERE pfile = %s',
1253 tableName('nucleus_plugin'),
1254 DB::quoteValue($plugName));
1255 DB::execute($query);
1257 array_push($aErrors, sprintf(_INST_ERROR9, $plugName));
1263 $query = sprintf('DELETE FROM %s', tableName('nucleus_plugin_event'));
1264 DB::execute($query);
1265 $query = sprintf('SELECT pid, pfile FROM %s', tableName('nucleus_plugin'));
1266 $res = DB::getResult($query);
1268 foreach ( $res as $row )
1270 $plug =& $manager->getPlugin($row['pfile']);
1274 $eventList = $plug->getEventList();
1275 foreach ( $eventList as $eventName )
1277 $query = sprintf('INSERT INTO %s (pid, event) VALUES (%d, %s)',
1278 tableName('nucleus_plugin_event'),
1279 intval($row['pid']),
1280 DB::quoteValue($eventName));
1281 DB::execute($query);
1289 * Install custom skins
1290 * Prepares the installation of custom skins
1292 function installCustomSkins()
1294 global $aConfSkinsToImport, $DIR_LIBS, $DIR_SKINS;
1297 if ( count($aConfSkinsToImport) == 0 )
1302 $importer = new SkinImport();
1304 foreach ( $aConfSkinsToImport as $skinName )
1307 $skinFile = $DIR_SKINS . $skinName . '/skinbackup.xml';
1309 if ( !@file_exists($skinFile) )
1311 array_push($aErrors, sprintf(_INST_ERROR10, $skinFile));
1315 $error = $importer->readFile($skinFile);
1319 array_push($aErrors, sprintf(_INST_ERROR11, $skinName) . ' : ' . $error);
1323 $error = $importer->writeToDatabase(1);
1327 array_push($aErrors, sprintf(_INST_ERROR12, $skinName) . ' : ' . $error);
1335 * Check if some important files of the Nucleus CMS installation are available
1336 * Give an error if one or more files are not accessible
1338 function do_check_files()
1340 $missingfiles = array();
1345 '../nucleus/index.php',
1346 '../nucleus/libs/ACTION.php',
1347 '../nucleus/libs/ACTIONLOG.php',
1348 '../nucleus/libs/ACTIONS.php',
1349 '../nucleus/libs/ADMIN.php',
1350 '../nucleus/libs/BaseActions.php',
1351 '../nucleus/libs/BLOG.php',
1352 '../nucleus/libs/BODYACTIONS.php',
1353 '../nucleus/libs/COMMENT.php',
1354 '../nucleus/libs/COMMENTACTIONS.php',
1355 '../nucleus/libs/COMMENTS.php',
1356 '../nucleus/libs/ENTITY.php',
1357 '../nucleus/libs/globalfunctions.php',
1358 '../nucleus/libs/i18n.php',
1359 '../nucleus/libs/ITEM.php',
1360 '../nucleus/libs/ITEMACTIONS.php',
1361 '../nucleus/libs/LINK.php',
1362 '../nucleus/libs/MANAGER.php',
1363 '../nucleus/libs/MEDIA.php',
1364 '../nucleus/libs/MEMBER.php',
1365 '../nucleus/libs/NOTIFICATION.php',
1366 '../nucleus/libs/PARSER.php',
1367 '../nucleus/libs/PLUGIN.php',
1368 '../nucleus/libs/PLUGINADMIN.php',
1369 '../nucleus/libs/SEARCH.php',
1370 '../nucleus/libs/showlist.php',
1371 '../nucleus/libs/SKIN.php',
1372 '../nucleus/libs/TEMPLATE.php',
1373 '../nucleus/libs/vars4.1.0.php',
1374 '../nucleus/libs/xmlrpc.inc.php',
1375 '../nucleus/libs/xmlrpcs.inc.php',
1376 '../nucleus/libs/sql/DB.php',
1377 '../nucleus/libs/sql/MYSQLPDO.php'
1380 $count = count($files);
1381 for ( $i = 0; $i < $count; $i++ )
1383 if ( !is_readable($files[$i]) )
1385 array_push($missingfiles, 'File <b>' . $files[$i] . '</b> is missing or not readable.<br />');
1389 if ( count($missingfiles) > 0 )
1391 exit(implode("\n", $missingfiles));
1396 * Updates the configuration in the database
1398 * @param string $name name of the config var
1399 * @param string $value new value of the config var
1402 function updateConfig($name, $value)
1406 $query = "UPDATE %s SET value = %s WHERE name = %s";
1407 $query = sprintf($query, tableName('nucleus_config'), DB::quoteValue(trim($value)), DB::quoteValue($name));
1409 if ( DB::execute($query) === FALSE )
1411 $errinfo = DB::getError();
1412 $errors[] = _INST_ERROR4 . ': ' . $errinfo[2];
1419 /* process parameter */
1423 /* mysql connection parameters */
1426 public $mysql_password;
1427 public $mysql_database;
1428 public $mysql_tablePrefix;
1430 /* weblog configuration parameters */
1432 public $blog_shortname;
1434 /* member configuration parameters */
1436 public $user_realname;
1437 public $user_password;
1438 private $user_password2;
1441 /* URI parameters */
1450 /* path parameters */
1459 public function __construct()
1464 public function init()
1466 // set default values
1467 $this->state = 'locale';
1468 $this->install_mode = 'simple';
1470 $this->mysql_host = @ini_get('mysql.default_host');
1471 $this->blog_name = 'My Nucleus CMS';
1472 $this->blog_shortname = 'mynucleuscms';
1475 $directory_separator = preg_quote(DIRECTORY_SEPARATOR, '|');
1476 $this->root_path = implode('/', preg_split("|$directory_separator|", realpath(dirname(__FILE__) . '/..')));
1477 if ( substr($this->root_path, -1, 1) !== '/' )
1479 $this->root_path .= '/';
1481 $base_path_pcre = preg_quote($this->root_path, '|');
1483 /* current directry name */
1484 $directory_name = preg_replace("#{$base_path_pcre}#", '', implode('/', preg_split("#{$directory_separator}#", realpath(dirname(__FILE__)))));
1485 $directory_name_pcre = preg_quote($directory_name, '|');
1488 $root_url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
1489 $this->root_url = preg_replace("|$directory_name_pcre(.*)$|", '', $root_url);
1491 $this->AdminPath = $this->root_path . 'nucleus/';
1492 $this->MediaPath = $this->root_path . 'media/';
1493 $this->SkinsPath = $this->root_path . 'skins/';
1495 $this->IndexURL = $this->root_url;
1496 $this->AdminURL = $this->root_url . 'nucleus/';
1497 $this->MediaURL = $this->root_url . 'media/';
1498 $this->SkinsURL = $this->root_url . 'skins/';
1499 $this->PluginURL = $this->root_url . 'nucleus/plugins/';
1500 $this->ActionURL = $this->root_url . 'action.php';
1503 private function read_parameter($parameter)
1505 foreach ( $parameter as $element )
1507 if ( array_key_exists($element, $_POST) )
1509 $this->$element = $_POST[$element];
1514 public function set_state($state)
1516 $states = array('locale', 'mysql', 'weblog', 'detail', 'install');
1517 if ( in_array($state, $states) )
1519 $this->state = $state;
1523 public function set_locale()
1525 $this->read_parameter(array('locale'));
1527 if ( !$this->locale )
1530 * default locale select simple implementation
1533 * RFC2616: Hypertext Transfer Protocol -- HTTP/1.1
1534 * http://www.ietf.org/rfc/rfc2616.txt
1536 * 14.4 Accept-Language
1538 * The Accept-Language request-header field is similar to Accept, but
1539 * restricts the set of natural languages that are preferred as a
1540 * response to the request. Language tags are defined in section 3.10.
1542 * Accept-Language = "Accept-Language" ":"
1543 * 1#( language-range [ ";" "q" "=" qvalue ] )
1544 * language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
1546 * Each language-range MAY be given an associated quality value which
1547 * represents an estimate of the user's preference for the languages
1548 * specified by that range. The quality value defaults to "q=1". For
1551 * Accept-Language: da, en-gb;q=0.8, en;q=0.7
1553 * would mean: "I prefer Danish, but will accept British English and
1554 * other types of English." A language-range matches a language-tag if
1555 * it exactly equals the tag, or if it exactly equals a prefix of the
1556 * tag such that the first tag character following the prefix is "-".
1557 * The special range "*", if present in the Accept-Language field,
1558 * matches every tag not matched by any other range present in the
1559 * Accept-Language field.
1561 * TODO: this is appropriate implement or not
1563 $languages = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
1565 /* retrieve language token of language tag from first token */
1567 if ( is_array($languages) && count($languages) > 0 )
1569 $language = preg_replace('#^([\w]+).*$#', '$1', $languages[0]);
1572 $locales = i18n::get_available_locale_list();
1573 foreach ( $locales as $locale )
1575 if ( i18n::strpos($locale, $language) === 0 )
1577 $this->locale = $locale;
1583 /* include installer translation messages */
1584 $translation_file = "./locales/{$this->locale}." . i18n::get_current_charset() . '.php';
1585 if ( !file_exists($translation_file) )
1587 $translation_file = './locales/en_Latn_US.UTF-8.php';
1589 include($translation_file);
1591 /* include global translation messages */
1592 $translation_file = "../nucleus/locales/{$this->locale}." . i18n::get_current_charset() . '.php';
1593 if ( !file_exists($translation_file) )
1595 $translation_file = './locales/en_Latn_US.UTF-8.php';
1597 include($translation_file);
1599 i18n::set_current_locale($this->locale);
1604 public function check_mysql_parameters()
1606 global $MYSQL_HANDLER;
1608 $parameters = array('mysql_host', 'mysql_user', 'mysql_password', 'mysql_database', 'mysql_tablePrefix');
1609 $this->read_parameter($parameters);
1612 if ( $this->mysql_host == '' )
1614 $errors[] = sprintf(_VALID_ERROR1, _DB_FIELD1);
1617 if ( $this->mysql_user == '' )
1619 $errors[] = sprintf(_VALID_ERROR1, _DB_FIELD2);
1622 if ( $this->mysql_user != ''
1623 && !preg_match('/^[a-z0-9_\-]+$/i', $this->mysql_user) )
1625 $errors[] = sprintf(_VALID_ERROR2, _DB_FIELD2);
1628 if ( $this->mysql_database == '' )
1630 $errors[] = sprintf(_VALID_ERROR1, _DB_FIELD4);
1633 if ( $this->mysql_database != ''
1634 && !preg_match('/^[a-z0-9_\-]+$/i', $this->mysql_database) )
1636 $errors[] = sprintf(_VALID_ERROR2, _DB_FIELD4);
1639 if ( $this->mysql_tablePrefix != ''
1640 && !preg_match('/^[a-z0-9_]+$/i', $this->mysql_tablePrefix) )
1642 $errors[] = sprintf(_VALID_ERROR3, _DB_FIELD5);
1645 if ( count($errors) == 0 )
1647 $mysql_conn = @DB::setConnectionInfo($MYSQL_HANDLER[1], $this->mysql_host, $this->mysql_user, $this->mysql_password);
1648 if ( $mysql_conn == false )
1650 $errors[] = _DBCONNECT_ERROR;
1661 public function check_user_parameters()
1663 $parameters = array('user_name', 'user_realname', 'user_password', 'user_password2', 'user_email');
1664 $this->read_parameter($parameters);
1667 if ( $this->user_realname == '' )
1669 $errors[] = sprintf(_VALID_ERROR1, _ADMIN_FIELD1);
1672 if ( $this->user_name == '' )
1674 $errors[] = sprintf(_VALID_ERROR1, _ADMIN_FIELD2);
1676 elseif ( !preg_match("/^[a-z0-9]+([ a-z0-9]*[a-z0-9]+)?$/i", $this->user_name) )
1678 $errors[] = _VALID_ERROR5;
1681 if ( $this->user_password == '' || $this->user_password2 == '' )
1683 $errors[] = sprintf(_VALID_ERROR1, _ADMIN_FIELD3);
1684 $this->user_password = '';
1686 elseif ( $this->user_password != $this->user_password2 )
1688 $errors[] = _VALID_ERROR6;
1689 $this->user_password = '';
1692 if ( !preg_match("/^[a-z0-9\._+\-]+@[a-z0-9\._\-]+\.[a-z]{2,6}$/i", $this->user_email) )
1694 $errors[] = _VALID_ERROR7;
1700 public function check_weblog_parameters()
1702 $parameters = array('blog_name', 'blog_shortname');
1703 $this->read_parameter($parameters);
1706 if ( $this->blog_name == '' )
1708 $errors[] = sprintf(_VALID_ERROR1, _BLOG_FIELD1);
1711 if ( $this->blog_shortname == '' )
1713 $errors[] = sprintf(_VALID_ERROR1, _BLOG_FIELD2);
1716 if ( !preg_match("/^[a-z0-9]+$/i", $this->blog_shortname) )
1718 $errors[] = _VALID_ERROR4;
1724 public function check_uri_parameters()
1726 $parameters = array('IndexURL', 'AdminURL', 'MediaURL', 'SkinsURL', 'PluginURL', 'ActionURL');
1727 $this->read_parameter($parameters);
1730 if ( substr($this->IndexURL, -1, 1) !== '/' )
1732 $errors[] = sprintf(_VALID_ERROR8, _PATH_FIELD1);
1735 if ( substr($this->AdminURL, -1, 1) !== '/' )
1737 $errors[] = sprintf(_VALID_ERROR8, _PATH_FIELD2);
1740 if ( substr($this->MediaURL, -1, 1) !== '/' )
1742 $errors[] = sprintf(_VALID_ERROR8, _PATH_FIELD4);
1745 if ( substr($this->SkinsURL, -1, 1) !== '/' )
1747 $errors[] = sprintf(_VALID_ERROR8, _PATH_FIELD6);
1750 if ( substr($this->PluginURL, -1, 1) !== '/' )
1752 $errors[] = sprintf(_VALID_ERROR8, _PATH_FIELD8);
1755 if ( strrchr($this->ActionURL, '/') != '/action.php' )
1757 $errors[] = sprintf(_VALID_ERROR9, _PATH_FIELD9);
1763 public function check_path_parameters()
1765 $parameters = array('AdminPath', 'MediaPath', 'SkinsPath');
1766 $this->read_parameter($parameters);
1768 $separators = array('/', DIRECTORY_SEPARATOR);
1770 if ( !in_array(substr($this->AdminPath, -1, 1), $separators) )
1772 $errors[] = sprintf(_VALID_ERROR10, _PATH_FIELD3);
1774 elseif ( !file_exists($this->AdminPath) )
1776 $errors[] = sprintf(_VALID_ERROR11, _PATH_FIELD3);
1779 if ( !in_array(substr($this->MediaPath, -1, 1), $separators) )
1781 $errors[] = sprintf(_VALID_ERROR10, _PATH_FIELD5);
1783 elseif ( !file_exists($this->MediaPath) )
1785 $errors[] = sprintf(_VALID_ERROR11, _PATH_FIELD5);
1788 if ( !in_array(substr($this->SkinsPath, -1, 1), $separators) )
1790 $errors[] = sprintf(_VALID_ERROR10, _PATH_FIELD7);
1792 elseif ( !file_exists($this->SkinsPath) )
1794 $errors[] = sprintf(_VALID_ERROR11, _PATH_FIELD7);
1801 * check all parameters
1804 public function check_all_parameters()
1806 $this->set_locale();
1809 $isValid &= (count($this->check_mysql_parameters()) == 0);
1810 $isValid &= (count($this->check_user_parameters()) == 0);
1811 $isValid &= (count($this->check_weblog_parameters()) == 0);
1812 $isValid &= (count($this->check_uri_parameters()) == 0);
1813 $isValid &= (count($this->check_path_parameters()) == 0);