Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details. */ set_exception_handler('myExceptionHandler'); # Check old config file require_once('./db/config.php'); if (!isset($config['db'])) { if(isset($config['mysql'])) { $config['db'] = 'mysql'; $config['mysql.host'] = $config['mysql'][0]; $config['mysql.db'] = $config['mysql'][3]; $config['mysql.user'] = $config['mysql'][1]; $config['mysql.password'] = $config['mysql'][2]; } else { $config['db'] = 'sqlite'; } if(isset($config['allow']) && $config['allow'] == 'read') $config['allowread'] = 1; } if ($config['db'] != '') { require_once('./includes/class.config.php'); Config::$noDatabase = true; //will not load settings from database in init.php require_once('./init.php'); if ( !is_logged() ) { die("Access denied!
Disable password protection or Log in."); } $db = DBConnection::instance(); $dbtype = (strtolower(get_class($db)) == 'database_mysql') ? 'mysql' : 'sqlite'; } else { if (!defined('MTTPATH')) define('MTTPATH', dirname(__FILE__) .'/'); if (!defined('MTTINC')) define('MTTINC', MTTPATH. 'includes/'); require_once(MTTINC. 'common.php'); require_once(MTTINC. 'class.dbconnection.php'); require_once(MTTINC. 'class.config.php'); Config::$noDatabase = true; Config::loadDbConfig($config); unset($config); $db = null; $dbtype = ''; } $lastVer = '1.7'; echo 'myTinyTodo @VERSION Setup'; echo "myTinyTodo @VERSION Setup

"; # determine current installed version $ver = $db ? get_ver($db, $dbtype) : ''; if (!$ver) { if (!isset($_POST['installdb']) && !isset($_POST['install']) && $db !== null) { # We already have settings file and need to create tables. exitMessage("
Click next to create tables in '". htmlspecialchars($dbtype). "' database.

"); } else if (!isset($_POST['installdb']) && !isset($_POST['install'])) { # Specify database type and connection settings to save. exitMessage("
Select database type to use:





"); } elseif(isset($_POST['installdb'])) { # Save configuration $dbtype = ($_POST['installdb'] == 'mysql') ? 'mysql' : 'sqlite'; Config::set('db', $dbtype); if($dbtype == 'mysql') { Config::set('mysql.host', _post('mysql_host')); Config::set('mysql.db', _post('mysql_db')); Config::set('mysql.user', _post('mysql_user')); Config::set('mysql.password', _post('mysql_password')); Config::set('prefix', trim(_post('prefix'))); } if(!testConnect($error)) { exitMessage("Database connection error: ". htmlspecialchars($error)); } if(!is_writable('./db/config.php')) { exitMessage("Config file ('db/config.php') is not writable."); } Config::saveDbConfig(); exitMessage("This will create myTinyTodo database
"); } # install database if($dbtype == 'mysql') { try { $db->ex( "CREATE TABLE {$db->prefix}lists ( `id` INT UNSIGNED NOT NULL auto_increment, `uuid` CHAR(36) NOT NULL default '', `ow` INT NOT NULL default 0, `name` VARCHAR(50) NOT NULL default '', `d_created` INT UNSIGNED NOT NULL default 0, `d_edited` INT UNSIGNED NOT NULL default 0, `sorting` TINYINT UNSIGNED NOT NULL default 0, `published` TINYINT UNSIGNED NOT NULL default 0, `taskview` INT UNSIGNED NOT NULL default 0, PRIMARY KEY(`id`), UNIQUE KEY(`uuid`) ) CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci "); $db->ex( "CREATE TABLE {$db->prefix}todolist ( `id` INT UNSIGNED NOT NULL auto_increment, `uuid` CHAR(36) NOT NULL default '', `list_id` INT UNSIGNED NOT NULL default 0, `d_created` INT UNSIGNED NOT NULL default 0, /* time() timestamp */ `d_completed` INT UNSIGNED NOT NULL default 0, /* time() timestamp */ `d_edited` INT UNSIGNED NOT NULL default 0, /* time() timestamp */ `compl` TINYINT UNSIGNED NOT NULL default 0, `title` VARCHAR(250) NOT NULL, `note` TEXT, `prio` TINYINT NOT NULL default 0, /* priority -,0,+ */ `ow` INT NOT NULL default 0, /* order weight */ `tags` VARCHAR(600) NOT NULL default '', /* for fast access to task tags */ `tags_ids` VARCHAR(250) NOT NULL default '', /* no more than 22 tags (x11 chars) */ `duedate` DATE default NULL, PRIMARY KEY(`id`), KEY(`list_id`), UNIQUE KEY(`uuid`) ) CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci "); $db->ex( "CREATE TABLE {$db->prefix}tags ( `id` INT UNSIGNED NOT NULL auto_increment, `name` VARCHAR(50) NOT NULL, PRIMARY KEY(`id`), UNIQUE KEY `name` (`name`) ) CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci "); $db->ex( "CREATE TABLE {$db->prefix}tag2task ( `tag_id` INT UNSIGNED NOT NULL, `task_id` INT UNSIGNED NOT NULL, `list_id` INT UNSIGNED NOT NULL, KEY(`tag_id`), KEY(`task_id`), KEY(`list_id`) /* for tagcloud */ ) CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci "); $db->ex( "CREATE TABLE {$db->prefix}settings ( `param_key` VARCHAR(100) NOT NULL default '', `param_value` TEXT, UNIQUE KEY `param_key` (`param_key`) ) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci "); $db->ex( "CREATE TABLE {$db->prefix}sessions ( `id` VARCHAR(64) NOT NULL default '', /* upto 64 bytes for sha256 */ `data` TEXT, `last_access` INT UNSIGNED NOT NULL default 0, /* time() timestamp */ `expires` INT UNSIGNED NOT NULL default 0, /* time() timestamp */ UNIQUE KEY `id` (`id`) ) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci "); } catch (Exception $e) { exitMessage("Error: ". htmlarray($e->getMessage())); } } else #sqlite { try { $db->ex( "CREATE TABLE {$db->prefix}lists ( id INTEGER PRIMARY KEY, uuid CHAR(36) NOT NULL, ow INTEGER NOT NULL default 0, name VARCHAR(50) NOT NULL, d_created INTEGER UNSIGNED NOT NULL default 0, d_edited INTEGER UNSIGNED NOT NULL default 0, sorting TINYINT UNSIGNED NOT NULL default 0, published TINYINT UNSIGNED NOT NULL default 0, taskview INTEGER UNSIGNED NOT NULL default 0 ) "); $db->ex("CREATE UNIQUE INDEX lists_uuid ON {$db->prefix}lists (uuid)"); $db->ex( "CREATE TABLE {$db->prefix}todolist ( id INTEGER PRIMARY KEY, uuid CHAR(36) NOT NULL, list_id INTEGER UNSIGNED NOT NULL default 0, d_created INTEGER UNSIGNED NOT NULL default 0, d_completed INTEGER UNSIGNED NOT NULL default 0, d_edited INTEGER UNSIGNED NOT NULL default 0, compl TINYINT UNSIGNED NOT NULL default 0, title VARCHAR(250) NOT NULL, note TEXT, prio TINYINT NOT NULL default 0, ow INTEGER NOT NULL default 0, tags VARCHAR(600) NOT NULL default '', tags_ids VARCHAR(250) NOT NULL default '', duedate DATE default NULL ) "); $db->ex("CREATE INDEX todo_list_id ON {$db->prefix}todolist (list_id)"); $db->ex("CREATE UNIQUE INDEX todo_uuid ON {$db->prefix}todolist (uuid)"); $db->ex( "CREATE TABLE {$db->prefix}tags ( id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(50) NOT NULL COLLATE NOCASE ) "); $db->ex("CREATE UNIQUE INDEX tags_name ON {$db->prefix}tags (name COLLATE NOCASE)"); $db->ex( "CREATE TABLE {$db->prefix}tag2task ( tag_id INTEGER NOT NULL, task_id INTEGER NOT NULL, list_id INTEGER NOT NULL ) "); $db->ex("CREATE INDEX tag2task_tag_id ON {$db->prefix}tag2task (tag_id)"); $db->ex("CREATE INDEX tag2task_task_id ON {$db->prefix}tag2task (task_id)"); $db->ex("CREATE INDEX tag2task_list_id ON {$db->prefix}tag2task (list_id)"); /* for tagcloud */ $db->ex( "CREATE TABLE {$db->prefix}settings ( param_key VARCHAR(100) NOT NULL default '', param_value TEXT ) "); $db->ex("CREATE UNIQUE INDEX settings_key ON {$db->prefix}settings (param_key COLLATE NOCASE)"); $db->ex( "CREATE TABLE {$db->prefix}sessions ( id VARCHAR(64) NOT NULL default '', data TEXT, last_access INTEGER UNSIGNED NOT NULL default 0, expires INTEGER UNSIGNED NOT NULL default 0 ) "); $db->ex("CREATE UNIQUE INDEX sessions_id ON {$db->prefix}sessions (id COLLATE NOCASE)"); } catch (Exception $e) { exitMessage("Error: ". htmlarray($e->getMessage())); } } # create default list $db->ex( "INSERT INTO {$db->prefix}lists (uuid,name,d_created,taskview) VALUES (?,?,?,?)", array(generateUUID(), 'Todo', time(), 1) ); Config::save(); Config::saveDbConfig(); } elseif($ver == $lastVer) { exitMessage("Installed version does not require database update."); } else { if (!in_array($ver, array('1.4'))) { exitMessage(htmlspecialchars("Can not update. Unsupported database version ($ver).")); } if (!isset($_POST['update'])) { exitMessage(htmlspecialchars("Update database v$ver to v$lastVer"). "

"); } # update process if ($ver == '1.4') { update_14_17($db, $dbtype); } } echo "Done

Attention! Delete this file for security reasons."; printFooter(); function get_ver(Database_Abstract $db, $dbtype) { if ( !$db || $dbtype == '' ) return ''; if ( !$db->tableExists($db->prefix.'todolist') ) return ''; $v = '1.0'; if ( !$db->tableExists($db->prefix.'tags') ) return $v; $v = '1.1'; if ( !db_has_field($dbtype, $db, $db->prefix.'todolist', 'duedate') ) return $v; $v = '1.2'; if ( !$db->tableExists($db->prefix.'lists') ) return $v; $v = '1.3.0'; if ( !db_has_field($dbtype, $db, $db->prefix.'todolist', 'd_completed') ) return $v; $v = '1.3.1'; if ( !db_has_field($dbtype, $db, $db->prefix.'todolist', 'd_edited') ) return $v; $v = '1.4'; if ( !$db->tableExists($db->prefix.'settings') ) return $v; $v = '1.7'; return $v; } function exitMessage($s) { echo $s; printFooter(); exit; } function printFooter() { echo ""; } function db_has_field($dbtype, Database_Abstract $db, $table, $field) { if ($dbtype == 'mysql') return has_field_mysql($db, $table, $field); elseif ($dbtype == 'sqlite') return has_field_sqlite($db, $table, $field); else throw new Exception("Unexpected database type"); } function has_field_sqlite(Database_Abstract $db, $table, $field) { $q = $db->dq("PRAGMA table_info(". $db->quote($table). ")"); while($r = $q->fetchRow()) { if($r[1] == $field) return true; } return false; } function has_field_mysql(Database_Abstract $db, $table, $field) { $q = $db->dq("DESCRIBE `$table`"); while($r = $q->fetchRow()) { if($r[0] == $field) return true; } return false; } function testConnect(&$error) { try { if(Config::get('db') == 'mysql') { if (defined('PDO::MYSQL_ATTR_FOUND_ROWS')) { require_once(MTTINC. 'class.db.mysql.php'); Config::set('mysqli', 0); } else if (function_exists("mysqli_connect")) { require_once(MTTINC. 'class.db.mysqli.php'); Config::set('mysqli', 1); } else { $text = "Required PHP extension 'PDO mysql' is not installed."; throw new Exception($text); } $db = new Database_Mysql; $db->connect(array( 'host' => Config::get('mysql.host'), 'user' => Config::get('mysql.user'), 'password' => Config::get('mysql.password'), 'db' => Config::get('mysql.db') )); } else { if(false === $f = @fopen(MTTPATH. 'db/todolist.db', 'a+')) throw new Exception("database file is not readable/writable"); else fclose($f); if(!is_writable(MTTPATH. 'db/')) throw new Exception("database directory ('db') is not writable"); require_once(MTTINC. 'class.db.sqlite3.php'); $db = new Database_Sqlite3; $db->connect( array( 'filename' => MTTPATH. 'db/todolist.db' ) ); } } catch(Exception $e) { $error = $e->getMessage(); return 0; } return 1; } function debugExceptionHandler($e) { echo '
Error: \''. htmlspecialchars($e->getMessage()) .'\' in '. htmlspecialchars($e->getFile() .':'. $e->getLine()). ''. "\n
". htmlspecialchars($e->getTraceAsString()) . "
\n"; exit; } function myExceptionHandler($e) { echo '
Error: '. htmlspecialchars($e->getMessage()) ; exit; } ### update v1.4 to v1.7 ########## function update_14_17(Database_Abstract $db, $dbtype) { $db->ex("BEGIN"); if($dbtype=='mysql') { # convert charset to utf8mb4 $db->ex("ALTER TABLE {$db->prefix}lists CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); $db->ex("ALTER TABLE {$db->prefix}todolist CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); $db->ex("ALTER TABLE {$db->prefix}tags CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); $db->ex("ALTER TABLE {$db->prefix}tag2task CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); # create settings table $db->ex( "CREATE TABLE {$db->prefix}settings ( `param_key` VARCHAR(100) NOT NULL default '', `param_value` TEXT, UNIQUE KEY `param_key` (`param_key`) ) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci "); # create sessions table $db->ex( "CREATE TABLE {$db->prefix}sessions ( `id` VARCHAR(64) NOT NULL default '', `data` TEXT, `last_access` INT UNSIGNED NOT NULL default 0, `expires` INT UNSIGNED NOT NULL default 0, UNIQUE KEY `id` (`id`) ) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci "); } else #sqlite { $db->ex( "CREATE TABLE {$db->prefix}settings ( param_key VARCHAR(100) NOT NULL default '', param_value TEXT ) "); $db->ex("CREATE UNIQUE INDEX settings_key ON {$db->prefix}settings (param_key COLLATE NOCASE)"); # sessions $db->ex( "CREATE TABLE {$db->prefix}sessions ( id VARCHAR(100) NOT NULL default '', data TEXT, last_access INTEGER UNSIGNED NOT NULL default 0, expires INTEGER UNSIGNED NOT NULL default 0 ) "); $db->ex("CREATE UNIQUE INDEX sessions_id ON {$db->prefix}sessions (id COLLATE NOCASE)"); } $db->ex("COMMIT"); Config::save(); Config::saveDbConfig(); } ### end of 1.7 #####