1<?php 2 class setup_model extends model { 3 private $required_php_extensions = array("libxml", "mysqli", "xsl"); 4 5 /* Determine next step 6 */ 7 public function step_to_take() { 8 $missing = $this->missing_php_extensions(); 9 if (count($missing) > 0) { 10 return "php_extensions"; 11 } 12 13 if ($this->db->connected == false) { 14 $db = new MySQLi_connection(DB_HOSTNAME, DB_DATABASE, DB_USERNAME, DB_PASSWORD); 15 } else { 16 $db = $this->db; 17 } 18 19 if ($db->connected == false) { 20 /* No database connection 21 */ 22 if ((DB_HOSTNAME == "localhost") && (DB_DATABASE == "monitor") && (DB_USERNAME == "monitor") && (DB_PASSWORD == "monitor")) { 23 return "db_settings"; 24 } else if (strpos(DB_PASSWORD, "'") !== false) { 25 $this->output->add_system_message("A single quote is not allowed in the password!"); 26 return "db_settings"; 27 } 28 29 return "create_db"; 30 } 31 32 $result = $db->execute("show tables like %s", "settings"); 33 if (count($result) == 0) { 34 return "import_sql"; 35 } 36 37 if ($this->settings->database_version < $this->latest_database_version()) { 38 return "update_db"; 39 } 40 41 $result = $db->execute("select password from users where username=%s", "admin"); 42 if ($result[0]["password"] == "none") { 43 return "credentials"; 44 } 45 46 return "done"; 47 } 48 49 /* Missing PHP extensions 50 */ 51 public function missing_php_extensions() { 52 static $missing = null; 53 54 if ($missing !== null) { 55 return $missing; 56 } 57 58 $missing = array(); 59 foreach ($this->required_php_extensions as $extension) { 60 if (extension_loaded($extension) == false) { 61 array_push($missing, $extension); 62 } 63 } 64 65 return $missing; 66 } 67 68 /* Remove datase related error messages 69 */ 70 public function remove_database_errors() { 71 $errors = explode("\n", rtrim(ob_get_contents())); 72 ob_clean(); 73 74 foreach ($errors as $error) { 75 if (strtolower(substr($error, 0, 14)) != "mysqli_connect") { 76 print $error; 77 } 78 } 79 } 80 81 /* Create the MySQL database 82 */ 83 public function create_database($username, $password) { 84 $db = new MySQLi_connection(DB_HOSTNAME, "mysql", $username, $password); 85 86 if ($db->connected == false) { 87 $this->output->add_message("Error connecting to database."); 88 return false; 89 } 90 91 $db->query("begin"); 92 93 /* Create database 94 */ 95 $query = "create database if not exists %S character set utf8"; 96 if ($db->query($query, DB_DATABASE) == false) { 97 $db->query("rollback"); 98 $this->output->add_message("Error creating database."); 99 return false; 100 } 101 102 /* Create user 103 */ 104 $query = "select count(*) as count from user where User=%s"; 105 if (($users = $db->execute($query, DB_USERNAME)) === false) { 106 $db->query("rollback"); 107 $this->output->add_message("Error checking for user."); 108 return false; 109 } 110 111 if ($users[0]["count"] == 0) { 112 $query = "create user %s@%s identified by %s"; 113 if ($db->query($query, DB_USERNAME, DB_HOSTNAME, DB_PASSWORD) == false) { 114 $db->query("rollback"); 115 $this->output->add_message("Error creating user."); 116 return false; 117 } 118 } else { 119 $login_test = new MySQLi_connection(DB_HOSTNAME, DB_DATABASE, DB_USERNAME, DB_PASSWORD); 120 if ($login_test->connected == false) { 121 $db->query("rollback"); 122 $this->output->add_message("Invalid credentials in settings/website.conf."); 123 return false; 124 } 125 } 126 127 /* Set access rights 128 */ 129 $rights = array( 130 "select", "insert", "update", "delete", 131 "create", "drop", "alter", "index", "lock tables", 132 "create view", "show view"); 133 134 $query = "grant ".implode(", ", $rights)." on %S.* to %s@%s"; 135 if ($db->query($query, DB_DATABASE, DB_USERNAME, DB_HOSTNAME) == false) { 136 $db->query("rollback"); 137 $this->output->add_message("Error setting access rights."); 138 return false; 139 } 140 141 /* Commit changes 142 */ 143 $db->query("commit"); 144 $db->query("flush privileges"); 145 unset($db); 146 147 return true; 148 } 149 150 /* Import SQL script from file 151 */ 152 public function import_sql() { 153 if (($queries = file("../database/mysql.sql")) === false) { 154 $this->output->add_message("Can't read the database/mysql.sql file."); 155 return false; 156 } 157 158 if (($db_link = mysqli_connect(DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE)) === false) { 159 $this->output->add_message("Error while connecting to the database."); 160 return false; 161 } 162 163 $query = ""; 164 foreach ($queries as $line) { 165 if (($line = trim($line)) == "") { 166 continue; 167 } 168 if (substr($line, 0, 2) == "--") { 169 continue; 170 } 171 172 $query .= $line; 173 if (substr($query, -1) == ";") { 174 if (mysqli_query($db_link, $query) === false) { 175 $this->output->add_message("Error while executing query [%s].", $query); 176 return false; 177 } 178 $query = ""; 179 } 180 } 181 182 mysqli_close($db_link); 183 184 $this->db->query("update users set status=%d", USER_STATUS_CHANGEPWD); 185 $this->settings->secret_website_code = random_string(32); 186 187 return true; 188 } 189 190 /* Collect latest database version from update_database() function 191 */ 192 private function latest_database_version() { 193 $old_db = $this->db; 194 $old_settings = $this->settings; 195 $this->db = new dummy_object(); 196 $this->settings = new dummy_object(); 197 $this->settings->database_version = 0; 198 199 $this->update_database(); 200 $version = $this->settings->database_version; 201 202 unset($this->db); 203 unset($this->settings); 204 $this->db = $old_db; 205 $this->settings = $old_settings; 206 207 return $version; 208 } 209 210 /* Add setting when missing 211 */ 212 private function ensure_setting($key, $type, $value) { 213 if ($this->db->entry("settings", $key, "key") != false) { 214 return true; 215 } 216 217 $entry = array( 218 "key" => $key, 219 "type" => $type, 220 "value" => $value); 221 return $this->db->insert("settings", $entry) !== false; 222 } 223 224 /* Update database 225 */ 226 public function update_database() { 227 if ($this->settings->database_version < 101) { 228 $this->settings->database_version = 101; 229 } 230 231 if ($this->settings->database_version < 102) { 232 $this->ensure_setting("hiawatha_cache_enabled", "boolean", "false"); 233 $this->ensure_setting("hiawatha_cache_default_time", "integer", "3600"); 234 $this->ensure_setting("session_timeout", "integer", "3600"); 235 $this->ensure_setting("session_persistent", "boolean", "false"); 236 237 $this->settings->database_version = 102; 238 } 239 240 if ($this->settings->database_version < 103) { 241 $tables = array("cgi_statistics", "host_statistics", "server_statistics"); 242 foreach ($tables as $table) { 243 $this->db->query("alter table %S add %S date not null after %S", $table, "date", "id"); 244 $this->db->query("alter table %S add %S tinyint unsigned not null after %S", $table, "hour", "date"); 245 $this->db->query("update %S set %S=date(%S), %S=%d", $table, "date", "timestamp_begin", "hour", 0); 246 $this->db->query("alter table %S drop %S", $table, "timestamp_begin"); 247 $this->db->query("alter table %S drop %S", $table, "timestamp_end"); 248 } 249 250 $query = "alter table %S add index(%S)"; 251 $this->db->query($query, "cgi_statistics", "date"); 252 $this->db->query($query, "cgi_statistics", "hour"); 253 $this->db->query($query, "host_statistics", "date"); 254 $this->db->query($query, "host_statistics", "hour"); 255 $this->db->query($query, "server_statistics", "date"); 256 $this->db->query($query, "server_statistics", "hour"); 257 258 $this->settings->dashboard_threshold_change = 150; 259 $this->settings->dashboard_threshold_value = 5; 260 $this->settings->dashboard_page_refresh = 1; 261 $this->settings->report_alert_high = 300; 262 $this->settings->report_alert_medium = 150; 263 $this->settings->report_history_days = 15; 264 $this->settings->report_skip_normal = false; 265 $this->settings->report_use_median = true; 266 267 $this->settings->database_version = 103; 268 } 269 270 if ($this->settings->database_version < 104) { 271 $this->settings->database_version = 104; 272 } 273 274 if ($this->settings->database_version < 105) { 275 $this->db->query("alter table %S change %S %S varchar(128) character set utf8 collate utf8_general_ci not null", "sessions", "session_id", "session_id"); 276 277 $query = "update settings set type=%s value=%s where %S=%s"; 278 $this->db->query($query, "float", "2.5", "key", "dashboard_threshold_change"); 279 $this->db->query($query, "float", "5", "key", "report_alert_high"); 280 $this->db->query($query, "float", "2", "key", "report_alert_medium"); 281 282 $this->settings->dashboard_show_weblog = true; 283 284 $this->settings->database_version = 105; 285 } 286 } 287 288 /* Set administrator password 289 */ 290 public function set_admin_credentials($post_data) { 291 $result = true; 292 293 if (valid_input($post_data["username"], VALIDATE_LETTERS, VALIDATE_NONEMPTY) == false) { 294 $this->output->add_message("The username must consist of lowercase letters."); 295 $result = false; 296 } 297 298 if ($post_data["password"] != $post_data["repeat"]) { 299 $this->output->add_message("The passwords do not match."); 300 $result = false; 301 } 302 303 if ($result == false) { 304 return false; 305 } 306 307 $password = hash_password($post_data["password"], $post_data["username"]); 308 309 $query = "update users set username=%s, password=%s, status=%d where username=%s"; 310 if ($this->db->query($query, $post_data["username"], $password, USER_STATUS_ACTIVE, "admin") === false) { 311 $this->output->add_message("Error while setting password."); 312 return false; 313 } 314 315 return true; 316 } 317 } 318 319 class dummy_object { 320 private $cache = array(); 321 322 public function __set($key, $value) { 323 $this->cache[$key] = $value; 324 } 325 326 public function __get($key) { 327 return $this->cache[$key]; 328 } 329 330 public function __call($func, $args) { 331 return false; 332 } 333 } 334?> 335