diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index 465ab2ac..a7f8f54f 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -62,69 +62,6 @@ function hasMailboxObjectAccess($username, $role, $object) { } return false; } -function init_db_schema() { - // This will be much better in future releases... - global $pdo; - try { - $stmt = $pdo->prepare("SELECT NULL FROM `admin`, `imapsync`, `tfa`"); - $stmt->execute(); - } - catch (Exception $e) { - $lines = file('/web/inc/init.sql'); - $data = ''; - foreach ($lines as $line) { - if (substr($line, 0, 2) == '--' || $line == '') { - continue; - } - $data .= $line; - if (substr(trim($line), -1, 1) == ';') { - $pdo->query($data); - $data = ''; - } - } - // Create index if not exists - $stmt = $pdo->query("SHOW INDEX FROM sogo_acl WHERE KEY_NAME = 'sogo_acl_c_folder_id_idx'"); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results == 0) { - $pdo->query("CREATE INDEX sogo_acl_c_folder_id_idx ON sogo_acl(c_folder_id)"); - } - $stmt = $pdo->query("SHOW INDEX FROM sogo_acl WHERE KEY_NAME = 'sogo_acl_c_uid_idx'"); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results == 0) { - $pdo->query("CREATE INDEX sogo_acl_c_uid_idx ON sogo_acl(c_uid)"); - } - $_SESSION['return'] = array( - 'type' => 'success', - 'msg' => 'Database initialization completed.' - ); - } - // Add newly added columns - $stmt = $pdo->query("SHOW COLUMNS FROM `mailbox` LIKE 'kind'"); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results == 0) { - $pdo->query("ALTER TABLE `mailbox` ADD `kind` VARCHAR(100) NOT NULL DEFAULT ''"); - } - $stmt = $pdo->query("SHOW COLUMNS FROM `mailbox` LIKE 'multiple_bookings'"); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results == 0) { - $pdo->query("ALTER TABLE `mailbox` ADD `multiple_bookings` tinyint(1) NOT NULL DEFAULT '0'"); - } - $stmt = $pdo->query("SHOW COLUMNS FROM `imapsync` LIKE 'delete1'"); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results == 0) { - $pdo->query("ALTER TABLE `imapsync` ADD `delete1` tinyint(1) NOT NULL DEFAULT '0'"); - } - $stmt = $pdo->query("SHOW COLUMNS FROM `mailbox` LIKE 'wants_tagged_subject'"); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results == 0) { - $pdo->query("ALTER TABLE `mailbox` ADD `wants_tagged_subject` tinyint(1) NOT NULL DEFAULT '0'"); - } - $stmt = $pdo->query("SHOW COLUMNS FROM `tfa` LIKE 'key_id'"); - $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); - if ($num_results == 0) { - $pdo->query("ALTER TABLE `tfa` ADD `key_id` VARCHAR(255) DEFAULT 'unidentified'"); - } -} function verify_ssha256($hash, $password) { // Remove tag if any $hash = ltrim($hash, '{SSHA256}'); @@ -287,13 +224,11 @@ function edit_admin_account($postarray) { $password_hashed = hash_password($password); try { $stmt = $pdo->prepare("UPDATE `admin` SET - `modified` = :modified, `password` = :password_hashed, `username` = :username1 WHERE `username` = :username2"); $stmt->execute(array( ':password_hashed' => $password_hashed, - ':modified' => date('Y-m-d H:i:s'), ':username1' => $username, ':username2' => $username_now )); @@ -309,12 +244,10 @@ function edit_admin_account($postarray) { else { try { $stmt = $pdo->prepare("UPDATE `admin` SET - `modified` = :modified, `username` = :username1 WHERE `username` = :username2"); $stmt->execute(array( ':username1' => $username, - ':modified' => date('Y-m-d H:i:s'), ':username2' => $username_now )); } @@ -608,10 +541,9 @@ function edit_user_account($postarray) { } $password_hashed = hash_password($password_new); try { - $stmt = $pdo->prepare("UPDATE `mailbox` SET `modified` = :modified, `password` = :password_hashed WHERE `username` = :username"); + $stmt = $pdo->prepare("UPDATE `mailbox` SET `password` = :password_hashed WHERE `username` = :username"); $stmt->execute(array( ':password_hashed' => $password_hashed, - ':modified' => date('Y-m-d H:i:s'), ':username' => $username )); } @@ -1633,13 +1565,11 @@ function add_domain_admin($postarray) { } } try { - $stmt = $pdo->prepare("INSERT INTO `admin` (`username`, `password`, `superadmin`, `created`, `modified`, `active`) - VALUES (:username, :password_hashed, '0', :created, :modified, :active)"); + $stmt = $pdo->prepare("INSERT INTO `admin` (`username`, `password`, `superadmin`, `active`) + VALUES (:username, :password_hashed, '0', :active)"); $stmt->execute(array( ':username' => $username, ':password_hashed' => $password_hashed, - ':created' => date('Y-m-d H:i:s'), - ':modified' => date('Y-m-d H:i:s'), ':active' => $active )); } @@ -2228,12 +2158,11 @@ function edit_domain_admin($postarray) { } $password_hashed = hash_password($password); try { - $stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username1, `modified` = :modified, `active` = :active, `password` = :password_hashed WHERE `username` = :username2"); + $stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username1, `active` = :active, `password` = :password_hashed WHERE `username` = :username2"); $stmt->execute(array( ':password_hashed' => $password_hashed, ':username1' => $username, ':username2' => $username_now, - ':modified' => date('Y-m-d H:i:s'), ':active' => $active )); if (isset($postarray['disable_tfa'])) { @@ -2255,11 +2184,10 @@ function edit_domain_admin($postarray) { } else { try { - $stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username1, `modified` = :modified, `active` = :active WHERE `username` = :username2"); + $stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username1, `active` = :active WHERE `username` = :username2"); $stmt->execute(array( ':username1' => $username, ':username2' => $username_now, - ':modified' => date('Y-m-d H:i:s'), ':active' => $active )); if (isset($postarray['disable_tfa'])) { @@ -2321,10 +2249,9 @@ function edit_domain_admin($postarray) { } $password_hashed = hash_password($password_new); try { - $stmt = $pdo->prepare("UPDATE `admin` SET `modified` = :modified, `password` = :password_hashed WHERE `username` = :username"); + $stmt = $pdo->prepare("UPDATE `admin` SET `password` = :password_hashed WHERE `username` = :username"); $stmt->execute(array( ':password_hashed' => $password_hashed, - ':modified' => date('Y-m-d H:i:s'), ':username' => $username )); } @@ -2356,7 +2283,7 @@ function get_admin_details() { return false; } try { - $stmt = $pdo->prepare("SELECT `username`, `modified`, `created` FROM `admin`WHERE `superadmin`='1' AND active='1'"); + $stmt = $pdo->prepare("SELECT `username`, `modified`, `created` FROM `admin` WHERE `superadmin`='1' AND active='1'"); $stmt->execute(); $data = $stmt->fetch(PDO::FETCH_ASSOC); } @@ -2601,8 +2528,8 @@ function mailbox_add_domain($postarray) { } try { - $stmt = $pdo->prepare("INSERT INTO `domain` (`domain`, `description`, `aliases`, `mailboxes`, `maxquota`, `quota`, `transport`, `backupmx`, `created`, `modified`, `active`, `relay_all_recipients`) - VALUES (:domain, :description, :aliases, :mailboxes, :maxquota, :quota, 'virtual', :backupmx, :created, :modified, :active, :relay_all_recipients)"); + $stmt = $pdo->prepare("INSERT INTO `domain` (`domain`, `description`, `aliases`, `mailboxes`, `maxquota`, `quota`, `transport`, `backupmx`, `active`, `relay_all_recipients`) + VALUES (:domain, :description, :aliases, :mailboxes, :maxquota, :quota, 'virtual', :backupmx, :active, :relay_all_recipients)"); $stmt->execute(array( ':domain' => $domain, ':description' => $description, @@ -2612,8 +2539,6 @@ function mailbox_add_domain($postarray) { ':quota' => $quota, ':backupmx' => $backupmx, ':active' => $active, - ':created' => date('Y-m-d H:i:s'), - ':modified' => date('Y-m-d H:i:s'), ':relay_all_recipients' => $relay_all_recipients )); $_SESSION['return'] = array( @@ -2789,16 +2714,14 @@ function mailbox_add_alias($postarray) { $goto = implode(",", $gotos); try { - $stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `goto`, `domain`, `created`, `modified`, `active`) - VALUES (:address, :goto, :domain, :created, :modified, :active)"); + $stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `goto`, `domain`, `active`) + VALUES (:address, :goto, :domain, :active)"); if (!filter_var($address, FILTER_VALIDATE_EMAIL) === true) { $stmt->execute(array( ':address' => '@'.$domain, ':goto' => $goto, ':domain' => $domain, - ':created' => date('Y-m-d H:i:s'), - ':modified' => date('Y-m-d H:i:s'), ':active' => $active )); } @@ -2807,8 +2730,6 @@ function mailbox_add_alias($postarray) { ':address' => $address, ':goto' => $goto, ':domain' => $domain, - ':created' => date('Y-m-d H:i:s'), - ':modified' => date('Y-m-d H:i:s'), ':active' => $active )); } @@ -2909,13 +2830,11 @@ function mailbox_add_alias_domain($postarray) { } try { - $stmt = $pdo->prepare("INSERT INTO `alias_domain` (`alias_domain`, `target_domain`, `created`, `modified`, `active`) - VALUES (:alias_domain, :target_domain, :created, :modified, :active)"); + $stmt = $pdo->prepare("INSERT INTO `alias_domain` (`alias_domain`, `target_domain`, `active`) + VALUES (:alias_domain, :target_domain, :active)"); $stmt->execute(array( ':alias_domain' => $alias_domain, ':target_domain' => $target_domain, - ':created' => date('Y-m-d H:i:s'), - ':modified' => date('Y-m-d H:i:s'), ':active' => $active )); $_SESSION['return'] = array( @@ -3118,8 +3037,8 @@ function mailbox_add_mailbox($postarray) { } try { - $stmt = $pdo->prepare("INSERT INTO `mailbox` (`username`, `password`, `name`, `maildir`, `quota`, `local_part`, `domain`, `created`, `modified`, `active`) - VALUES (:username, :password_hashed, :name, :maildir, :quota_b, :local_part, :domain, :created, :modified, :active)"); + $stmt = $pdo->prepare("INSERT INTO `mailbox` (`username`, `password`, `name`, `maildir`, `quota`, `local_part`, `domain`, `active`) + VALUES (:username, :password_hashed, :name, :maildir, :quota_b, :local_part, :domain, :active)"); $stmt->execute(array( ':username' => $username, ':password_hashed' => $password_hashed, @@ -3128,8 +3047,6 @@ function mailbox_add_mailbox($postarray) { ':quota_b' => $quota_b, ':local_part' => $local_part, ':domain' => $domain, - ':created' => date('Y-m-d H:i:s'), - ':modified' => date('Y-m-d H:i:s'), ':active' => $active )); @@ -3137,14 +3054,12 @@ function mailbox_add_mailbox($postarray) { VALUES (:username, '0', '0')"); $stmt->execute(array(':username' => $username)); - $stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `goto`, `domain`, `created`, `modified`, `active`) - VALUES (:username1, :username2, :domain, :created, :modified, :active)"); + $stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `goto`, `domain`, `active`) + VALUES (:username1, :username2, :domain, :active)"); $stmt->execute(array( ':username1' => $username, ':username2' => $username, ':domain' => $domain, - ':created' => date('Y-m-d H:i:s'), - ':modified' => date('Y-m-d H:i:s'), ':active' => $active )); @@ -3274,15 +3189,13 @@ function mailbox_add_resource($postarray) { } try { - $stmt = $pdo->prepare("INSERT INTO `mailbox` (`username`, `password`, `name`, `maildir`, `quota`, `local_part`, `domain`, `created`, `modified`, `active`, `multiple_bookings`, `kind`) - VALUES (:name, 'RESOURCE', :description, 'RESOURCE', 0, :local_part, :domain, :created, :modified, :active, :multiple_bookings, :kind)"); + $stmt = $pdo->prepare("INSERT INTO `mailbox` (`username`, `password`, `name`, `maildir`, `quota`, `local_part`, `domain`, `active`, `multiple_bookings`, `kind`) + VALUES (:name, 'RESOURCE', :description, 'RESOURCE', 0, :local_part, :domain, :active, :multiple_bookings, :kind)"); $stmt->execute(array( ':name' => $name, ':description' => $description, ':local_part' => $local_part, ':domain' => $domain, - ':created' => date('Y-m-d H:i:s'), - ':modified' => date('Y-m-d H:i:s'), ':active' => $active, ':kind' => $kind, ':multiple_bookings' => $multiple_bookings @@ -3373,12 +3286,10 @@ function mailbox_edit_alias_domain($postarray) { try { $stmt = $pdo->prepare("UPDATE `alias_domain` SET `alias_domain` = :alias_domain, - `active` = :active, - `modified` = :modified + `active` = :active WHERE `alias_domain` = :alias_domain_now"); $stmt->execute(array( ':alias_domain' => $alias_domain, - ':modified' => date('Y-m-d H:i:s'), ':alias_domain_now' => $alias_domain_now, ':active' => $active )); @@ -3454,14 +3365,12 @@ function mailbox_edit_alias($postarray) { try { $stmt = $pdo->prepare("UPDATE `alias` SET `goto` = :goto, - `active`= :active, - `modified` = :modified + `active`= :active WHERE `address` = :address"); $stmt->execute(array( ':goto' => $goto, ':active' => $active, - ':address' => $address, - ':modified' => date('Y-m-d H:i:s'), + ':address' => $address )); $_SESSION['return'] = array( 'type' => 'success', @@ -3506,11 +3415,9 @@ function mailbox_edit_domain($postarray) { isset($postarray['active']) ? $active = '1' : $active = '0'; try { $stmt = $pdo->prepare("UPDATE `domain` SET - `modified`= :modified, `description` = :description WHERE `domain` = :domain"); $stmt->execute(array( - ':modified' => date('Y-m-d H:i:s'), ':description' => $description, ':domain' => $domain )); @@ -3614,7 +3521,6 @@ function mailbox_edit_domain($postarray) { } try { $stmt = $pdo->prepare("UPDATE `domain` SET - `modified`= :modified, `relay_all_recipients` = :relay_all_recipients, `backupmx` = :backupmx, `active` = :active, @@ -3632,7 +3538,6 @@ function mailbox_edit_domain($postarray) { ':maxquota' => $maxquota, ':mailboxes' => $mailboxes, ':aliases' => $aliases, - ':modified' => date('Y-m-d H:i:s'), ':description' => $description, ':domain' => $domain )); @@ -3844,23 +3749,19 @@ function mailbox_edit_mailbox($postarray) { $password_hashed = hash_password($password); try { $stmt = $pdo->prepare("UPDATE `alias` SET - `modified` = :modified, `active` = :active WHERE `address` = :address"); $stmt->execute(array( ':address' => $username, - ':modified' => date('Y-m-d H:i:s'), ':active' => $active )); $stmt = $pdo->prepare("UPDATE `mailbox` SET - `modified` = :modified, `active` = :active, `password` = :password_hashed, `name`= :name, `quota` = :quota_b WHERE `username` = :username"); $stmt->execute(array( - ':modified' => date('Y-m-d H:i:s'), ':password_hashed' => $password_hashed, ':active' => $active, ':name' => $name, @@ -3883,23 +3784,19 @@ function mailbox_edit_mailbox($postarray) { } try { $stmt = $pdo->prepare("UPDATE `alias` SET - `modified` = :modified, `active` = :active WHERE `address` = :address"); $stmt->execute(array( ':address' => $username, - ':modified' => date('Y-m-d H:i:s'), ':active' => $active )); $stmt = $pdo->prepare("UPDATE `mailbox` SET - `modified` = :modified, `active` = :active, `name`= :name, `quota` = :quota_b WHERE `username` = :username"); $stmt->execute(array( ':active' => $active, - ':modified' => date('Y-m-d H:i:s'), ':name' => $name, ':quota_b' => $quota_b, ':username' => $username @@ -3962,7 +3859,6 @@ function mailbox_edit_resource($postarray) { try { $stmt = $pdo->prepare("UPDATE `mailbox` SET - `modified` = :modified, `active` = :active, `name`= :description, `kind`= :kind, @@ -3970,7 +3866,6 @@ function mailbox_edit_resource($postarray) { WHERE `username` = :name"); $stmt->execute(array( ':active' => $active, - ':modified' => date('Y-m-d H:i:s'), ':description' => $description, ':multiple_bookings' => $multiple_bookings, ':kind' => $kind, @@ -4796,12 +4691,10 @@ function mailbox_delete_mailbox($postarray) { } $gotos_rebuild = implode(',', $goto_exploded); $stmt = $pdo->prepare("UPDATE `alias` SET - `goto` = :goto, - `modified` = :modified, + `goto` = :goto WHERE `address` = :address"); $stmt->execute(array( ':goto' => $gotos_rebuild, - ':modified' => date('Y-m-d H:i:s'), ':address' => $gotos['address'] )); } diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php new file mode 100644 index 00000000..37c04a12 --- /dev/null +++ b/data/web/inc/init_db.inc.php @@ -0,0 +1,584 @@ +query("SHOW TABLES LIKE 'versions'"); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $stmt = $pdo->query("SELECT `version` FROM `versions`"); + if ($stmt->fetch(PDO::FETCH_ASSOC)['version'] == $db_version) { + return true; + } + } + + $views = array( + "grouped_mail_aliases" => "CREATE VIEW grouped_mail_aliases (username, aliases) AS + SELECT goto, IFNULL(GROUP_CONCAT(address SEPARATOR ' '), '') AS address FROM alias + WHERE address!=goto + AND active = '1' + AND address NOT LIKE '@%' + GROUP BY goto;", + "grouped_sender_acl" => "CREATE VIEW grouped_sender_acl (username, send_as) AS + SELECT logged_in_as, IFNULL(GROUP_CONCAT(send_as SEPARATOR ' '), '') AS send_as FROM sender_acl + WHERE send_as NOT LIKE '@%' + GROUP BY logged_in_as;", + "grouped_domain_alias_address" => "CREATE VIEW grouped_domain_alias_address (username, ad_alias) AS + SELECT username, IFNULL(GROUP_CONCAT(local_part, '@', alias_domain SEPARATOR ' '), '') AS ad_alias FROM mailbox + LEFT OUTER JOIN alias_domain on target_domain=domain GROUP BY username;" + ); + + $tables = array( + "versions" => array( + "cols" => array( + "application" => "VARCHAR(255) NOT NULL", + "version" => "VARCHAR(100) NOT NULL", + "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", + ), + "keys" => array( + "primary" => array( + "" => array("application") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "admin" => array( + "cols" => array( + "username" => "VARCHAR(255) NOT NULL", + "password" => "VARCHAR(255) NOT NULL", + "superadmin" => "TINYINT(1) NOT NULL DEFAULT '0'", + "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", + "modified" => "DATETIME ON UPDATE NOW(0)", + "active" => "TINYINT(1) NOT NULL DEFAULT '1'" + ), + "keys" => array( + "primary" => array( + "" => array("username") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "alias" => array( + "cols" => array( + "address" => "VARCHAR(255) NOT NULL", + "goto" => "TEXT NOT NULL", + "domain" => "VARCHAR(255) NOT NULL", + "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", + "modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP", + "active" => "TINYINT(1) NOT NULL DEFAULT '1'" + ), + "keys" => array( + "primary" => array( + "" => array("address") + ), + "key" => array( + "domain" => array("domain") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "sender_acl" => array( + "cols" => array( + "logged_in_as" => "VARCHAR(255) NOT NULL", + "send_as" => "VARCHAR(255) NOT NULL" + ), + "keys" => array(), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "domain" => array( + "cols" => array( + "domain" => "VARCHAR(255) NOT NULL", + "description" => "VARCHAR(255)", + "aliases" => "INT(10) NOT NULL DEFAULT '0'", + "mailboxes" => "INT(10) NOT NULL DEFAULT '0'", + "maxquota" => "BIGINT(20) NOT NULL DEFAULT '0'", + "quota" => "BIGINT(20) NOT NULL DEFAULT '0'", + "transport" => "VARCHAR(255) NOT NULL", + "backupmx" => "TINYINT(1) NOT NULL DEFAULT '0'", + "relay_all_recipients" => "TINYINT(1) NOT NULL DEFAULT '0'", + "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", + "modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP", + "active" => "TINYINT(1) NOT NULL DEFAULT '1'" + ), + "keys" => array( + "primary" => array( + "" => array("domain") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "alias_domain" => array( + "cols" => array( + "alias_domain" => "VARCHAR(255) NOT NULL", + "target_domain" => "VARCHAR(255) NOT NULL", + "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", + "modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP", + "active" => "TINYINT(1) NOT NULL DEFAULT '1'" + ), + "keys" => array( + "primary" => array( + "" => array("alias_domain") + ), + "key" => array( + "active" => array("active"), + "target_domain" => array("target_domain") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "spamalias" => array( + "cols" => array( + "address" => "VARCHAR(255) NOT NULL", + "goto" => "TEXT NOT NULL", + "validity" => "INT(11) NOT NULL" + ), + "keys" => array( + "primary" => array( + "" => array("address") + ), + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "filterconf" => array( + "cols" => array( + "object" => "VARCHAR(255) NOT NULL DEFAULT ''", + "option" => "VARCHAR(50) NOT NULL DEFAULT ''", + "value" => "VARCHAR(100) NOT NULL DEFAULT ''", + "prefid" => "INT(11) NOT NULL AUTO_INCREMENT" + ), + "keys" => array( + "primary" => array( + "" => array("prefid") + ), + "key" => array( + "object" => array("object") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "quota2" => array( + "cols" => array( + "username" => "VARCHAR(255) NOT NULL", + "bytes" => "BIGINT(20) NOT NULL DEFAULT '0'", + "messages" => "BIGINT(20) NOT NULL DEFAULT '0'" + ), + "keys" => array( + "primary" => array( + "" => array("username") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "mailbox" => array( + "cols" => array( + "username" => "VARCHAR(255) NOT NULL", + "password" => "VARCHAR(255) NOT NULL", + "name" => "VARCHAR(255)", + "maildir" => "VARCHAR(255) NOT NULL", + "quota" => "BIGINT(20) NOT NULL DEFAULT '0'", + "local_part" => "VARCHAR(255) NOT NULL", + "domain" => "VARCHAR(255) NOT NULL", + "tls_enforce_in" => "TINYINT(1) NOT NULL DEFAULT '0'", + "tls_enforce_out" => "TINYINT(1) NOT NULL DEFAULT '0'", + "kind" => "VARCHAR(100) NOT NULL DEFAULT ''", + "multiple_bookings" => "TINYINT(1) NOT NULL DEFAULT '0'", + "wants_tagged_subject" => "TINYINT(1) NOT NULL DEFAULT '0'", + "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", + "modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP", + "active" => "TINYINT(1) NOT NULL DEFAULT '1'" + ), + "keys" => array( + "primary" => array( + "" => array("username") + ), + "key" => array( + "domain" => array("domain") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "domain_admins" => array( + "cols" => array( + "username" => "VARCHAR(255) NOT NULL", + "domain" => "VARCHAR(255) NOT NULL", + "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", + "active" => "TINYINT(1) NOT NULL DEFAULT '1'" + ), + "keys" => array( + "key" => array( + "username" => array("username") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "imapsync" => array( + "cols" => array( + "id" => "INT NOT NULL AUTO_INCREMENT", + "user2" => "VARCHAR(255) NOT NULL", + "host1" => "VARCHAR(255) NOT NULL", + "authmech1" => "ENUM('PLAIN','LOGIN','CRAM-MD5') DEFAULT 'PLAIN'", + "regextrans2" => "VARCHAR(255) DEFAULT ''", + "authmd51" => "TINYINT(1) NOT NULL DEFAULT 0", + "domain2" => "VARCHAR(255) NOT NULL DEFAULT ''", + "subfolder2" => "VARCHAR(255) NOT NULL DEFAULT ''", + "user1" => "VARCHAR(255) NOT NULL", + "password1" => "VARCHAR(255) NOT NULL", + "exclude" => "VARCHAR(500) NOT NULL DEFAULT ''", + "maxage" => "SMALLINT NOT NULL DEFAULT '0'", + "mins_interval" => "VARCHAR(50) NOT NULL", + "port1" => "SMALLINT NOT NULL", + "enc1" => "ENUM('TLS','SSL','PLAIN') DEFAULT 'TLS'", + "delete2duplicates" => "TINYINT(1) NOT NULL DEFAULT '1'", + "returned_text" => "TEXT", + "last_run" => "TIMESTAMP NULL DEFAULT NULL", + "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", + "modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP", + "active" => "TINYINT(1) NOT NULL DEFAULT '0'" + ), + "keys" => array( + "primary" => array( + "" => array("id") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "tfa" => array( + "cols" => array( + "id" => "INT NOT NULL AUTO_INCREMENT", + "username" => "VARCHAR(255) NOT NULL", + "authmech" => "ENUM('yubi_otp', 'u2f', 'hotp', 'totp')", + "secret" => "VARCHAR(255) DEFAULT NULL", + "keyHandle" => "VARCHAR(255) DEFAULT NULL", + "publicKey" => "VARCHAR(255) DEFAULT NULL", + "counter" => "INT NOT NULL DEFAULT '0'", + "certificate" => "TEXT", + "active" => "TINYINT(1) NOT NULL DEFAULT '0'" + ), + "keys" => array( + "primary" => array( + "" => array("id") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "sogo_acl" => array( + "cols" => array( + "c_folder_id" => "INT NOT NULL", + "c_object" => "VARCHAR(255) NOT NULL", + "c_uid" => "VARCHAR(255) NOT NULL", + "c_role" => "VARCHAR(80) NOT NULL" + ), + "keys" => array( + "key" => array( + "sogo_acl_c_folder_id_idx" => array("c_folder_id"), + "sogo_acl_c_uid_idx" => array("c_uid") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "sogo_alarms_folder" => array( + "cols" => array( + "c_path" => "VARCHAR(255) NOT NULL", + "c_name" => "VARCHAR(255) NOT NULL", + "c_uid" => "VARCHAR(255) NOT NULL", + "c_recurrence_id" => "INT(11) DEFAULT NULL", + "c_alarm_number" => "INT(11) NOT NULL", + "c_alarm_date" => "INT(11) NOT NULL" + ), + "keys" => array(), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "sogo_cache_folder" => array( + "cols" => array( + "c_uid" => "VARCHAR(255) NOT NULL", + "c_path" => "VARCHAR(255) NOT NULL", + "c_parent_path" => "VARCHAR(255) DEFAULT NULL", + "c_type" => "TINYINT(3) unsigned NOT NULL", + "c_creationdate" => "INT(11) NOT NULL", + "c_lastmodified" => "INT(11) NOT NULL", + "c_version" => "INT(11) NOT NULL DEFAULT '0'", + "c_deleted" => "TINYINT(4) NOT NULL DEFAULT '0'", + "c_content" => "LONGTEXT" + ), + "keys" => array( + "primary" => array( + "" => array("c_uid", "c_path") + ), + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "sogo_folder_info" => array( + "cols" => array( + "c_folder_id" => "BIGINT(20) unsigned NOT NULL AUTO_INCREMENT", + "c_path" => "VARCHAR(255) NOT NULL", + "c_path1" => "VARCHAR(255) NOT NULL", + "c_path2" => "VARCHAR(255) DEFAULT NULL", + "c_path3" => "VARCHAR(255) DEFAULT NULL", + "c_path4" => "VARCHAR(255) DEFAULT NULL", + "c_foldername" => "VARCHAR(255) NOT NULL", + "c_location" => "INT NULL", + "c_quick_location" => "VARCHAR(2048) DEFAULT NULL", + "c_acl_location" => "VARCHAR(2048) DEFAULT NULL", + "c_folder_type" => "VARCHAR(255) NOT NULL" + ), + "keys" => array( + "primary" => array( + "" => array("c_path") + ), + "unique" => array( + "c_folder_id" => array("c_folder_id") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "sogo_quick_appointment" => array( + "cols" => array( + "c_folder_id" => "INT NOT NULL", + "c_name" => "VARCHAR(255) NOT NULL", + "c_uid" => "VARCHAR(255) NOT NULL", + "c_startdate" => "INT", + "c_enddate" => "INT", + "c_cycleenddate" => "INT", + "c_title" => "VARCHAR(1000) NOT NULL", + "c_participants" => "TEXT", + "c_isallday" => "INT", + "c_iscycle" => "INT", + "c_cycleinfo" => "TEXT", + "c_classification" => "INT NOT NULL", + "c_isopaque" => "INT NOT NULL", + "c_status" => "INT NOT NULL", + "c_priority" => "INT", + "c_location" => "VARCHAR(255)", + "c_orgmail" => "VARCHAR(255)", + "c_partmails" => "TEXT", + "c_partstates" => "TEXT", + "c_category" => "VARCHAR(255)", + "c_sequence" => "INT", + "c_component" => "VARCHAR(10) NOT NULL", + "c_nextalarm" => "INT", + "c_description" => "TEXT" + ), + "keys" => array( + "primary" => array( + "" => array("c_folder_id", "c_name") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "sogo_quick_contact" => array( + "cols" => array( + "c_folder_id" => "INT NOT NULL", + "c_name" => "VARCHAR(255) NOT NULL", + "c_givenname" => "VARCHAR(255)", + "c_cn" => "VARCHAR(255)", + "c_sn" => "VARCHAR(255)", + "c_screenname" => "VARCHAR(255)", + "c_l" => "VARCHAR(255)", + "c_mail" => "VARCHAR(255)", + "c_o" => "VARCHAR(255)", + "c_ou" => "VARCHAR(255)", + "c_telephonenumber" => "VARCHAR(255)", + "c_categories" => "VARCHAR(255)", + "c_component" => "VARCHAR(10) NOT NULL" + ), + "keys" => array( + "primary" => array( + "" => array("c_folder_id", "c_name") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "sogo_sessions_folder" => array( + "cols" => array( + "c_id" => "VARCHAR(255) NOT NULL", + "c_value" => "VARCHAR(255) NOT NULL", + "c_creationdate" => "INT(11) NOT NULL", + "c_lastseen" => "INT(11) NOT NULL" + ), + "keys" => array( + "primary" => array( + "" => array("c_id") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "sogo_store" => array( + "cols" => array( + "c_folder_id" => "INT NOT NULL", + "c_name" => "VARCHAR(255) NOT NULL", + "c_content" => "MEDIUMTEXT NOT NULL", + "c_creationdate" => "INT NOT NULL", + "c_lastmodified" => "INT NOT NULL", + "c_version" => "INT NOT NULL", + "c_deleted" => "INT" + ), + "keys" => array( + "primary" => array( + "" => array("c_folder_id", "c_name") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), + "sogo_user_profile" => array( + "cols" => array( + "c_uid" => "VARCHAR(255) NOT NULL", + "c_defaults" => "TEXT", + "c_settings" => "TEXT" + ), + "keys" => array( + "primary" => array( + "" => array("c_uid") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ) + ); + + foreach ($tables as $table => $properties) { + $stmt = $pdo->query("SHOW TABLES LIKE '" . $table . "'"); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + foreach($properties['cols'] as $column => $type) { + $stmt = $pdo->query("SHOW COLUMNS FROM `" . $table . "` LIKE '" . $column . "'"); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results == 0) { + $pdo->query("ALTER TABLE `" . $table . "` ADD `" . $column . "` " . $type); + } + else { + $pdo->query("ALTER TABLE `" . $table . "` MODIFY COLUMN `" . $column . "` " . $type); + } + } + foreach($properties['keys'] as $key_type => $key_content) { + if (strtolower($key_type) == 'primary') { + foreach ($key_content as $key_values) { + $fields = "`" . implode("`, `", $key_values) . "`"; + $stmt = $pdo->query("SHOW KEYS FROM `" . $table . "` WHERE Key_name = 'PRIMARY'"); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + $is_drop = ($num_results != 0) ? "DROP PRIMARY KEY, " : ""; + $pdo->query("ALTER TABLE `" . $table . "` " . $is_drop . "ADD PRIMARY KEY (" . $fields . ")"); + } + } + if (strtolower($key_type) == 'key') { + foreach ($key_content as $key_name => $key_values) { + $fields = "`" . implode("`, `", $key_values) . "`"; + $stmt = $pdo->query("SHOW KEYS FROM `" . $table . "` WHERE Key_name = '" . $key_name . "'"); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + $is_drop = ($num_results != 0) ? "DROP INDEX `" . $key_name . "`, " : ""; + $pdo->query("ALTER TABLE `" . $table . "` " . $is_drop . "ADD KEY `" . $key_name . "` (" . $fields . ")"); + } + } + if (strtolower($key_type) == 'unique') { + foreach ($key_content as $key_name => $key_values) { + $fields = "`" . implode("`, `", $key_values) . "`"; + $stmt = $pdo->query("SHOW KEYS FROM `" . $table . "` WHERE Key_name = '" . $key_name . "'"); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + $is_drop = ($num_results != 0) ? "DROP INDEX `" . $key_name . "`, " : ""; + $pdo->query("ALTER TABLE `" . $table . "` " . $is_drop . "ADD UNIQUE KEY `" . $key_name . "` (" . $fields . ")"); + } + } + } + // Drop all vanished columns + $stmt = $pdo->query("SHOW COLUMNS FROM `" . $table . "`"); + $cols_in_table = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($row = array_shift($cols_in_table)) { + if (!array_key_exists($row['Field'], $properties['cols'])) { + $pdo->query("ALTER TABLE `" . $table . "` DROP COLUMN `" . $row['Field'] . "`;"); + } + } + + // Step 1: Get all non-primary keys, that currently exist and those that should exist + $stmt = $pdo->query("SHOW KEYS FROM `" . $table . "` WHERE `Key_name` != 'PRIMARY'"); + $keys_in_table = $stmt->fetchAll(PDO::FETCH_ASSOC); + $keys_to_exist = array(); + if (isset($properties['keys']['unique']) && is_array($properties['keys']['unique'])) { + foreach ($properties['keys']['unique'] as $key_name => $key_values) { + $keys_to_exist[] = $key_name; + } + } + if (isset($properties['keys']['key']) && is_array($properties['keys']['key'])) { + foreach ($properties['keys']['key'] as $key_name => $key_values) { + $keys_to_exist[] = $key_name; + } + } + // Step 2: Drop all vanished indexes + while ($row = array_shift($keys_in_table)) { + if (!in_array($row['Key_name'], $keys_to_exist)) { + $pdo->query("ALTER TABLE `" . $table . "` DROP INDEX `" . $row['Key_name'] . "`"); + } + } + // Step 3: Drop all vanished primary keys + if (!isset($properties['keys']['primary'])) { + $stmt = $pdo->query("SHOW KEYS FROM `" . $table . "` WHERE Key_name = 'PRIMARY'"); + $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); + if ($num_results != 0) { + $pdo->query("ALTER TABLE `" . $table . "` DROP PRIMARY KEY"); + } + } + } + else { + // Create table if it is missing + $sql = "CREATE TABLE IF NOT EXISTS `" . $table . "` ("; + foreach($properties['cols'] as $column => $type) { + $sql .= $column . " " . $type . ","; + } + foreach($properties['keys'] as $key_type => $key_content) { + if (strtolower($key_type) == 'primary') { + foreach ($key_content as $key_values) { + $fields = "`" . implode("`, `", $key_values) . "`"; + $sql .= "PRIMARY KEY (" . $fields . ")" . ","; + } + } + elseif (strtolower($key_type) == 'key') { + foreach ($key_content as $key_name => $key_values) { + $fields = "`" . implode("`, `", $key_values) . "`"; + $sql .= "KEY `" . $key_name . "` (" . $fields . ")" . ","; + } + } + elseif (strtolower($key_type) == 'unique') { + foreach ($key_content as $key_name => $key_values) { + $fields = "`" . implode("`, `", $key_values) . "`"; + $sql .= "UNIQUE KEY `" . $key_name . "` (" . $fields . ")" . ","; + } + } + } + $sql = rtrim($sql, ","); + $sql .= ") " . $properties['attr']; + $pdo->query($sql); + } + // Reset table attributes + $pdo->query("ALTER TABLE `" . $table . "` " . $properties['attr'] . ";"); + } + + // Recreate SQL views + foreach ($views as $view => $create) { + $pdo->query("DROP VIEW IF EXISTS `" . $view . "`;"); + $pdo->query($create); + } + + // Inject admin if not exists + $stmt = $pdo->query("INSERT INTO `admin` (`username`, `password`, `superadmin`, `created`, `modified`, `active`) + SELECT 'admin', '{SSHA256}K8eVJ6YsZbQCfuJvSUbaQRLr0HPLz5rC9IAp0PAFl0tmNDBkMDc0NDAyOTAxN2Rk', 1, NOW(), NOW(), 1 + WHERE NOT EXISTS (SELECT * FROM `admin`);"); + $stmt = $pdo->query("DELETE FROM `domain_admins`;"); + $stmt = $pdo->query("INSERT INTO `domain_admins` (`username`, `domain`, `created`, `active`) + SELECT `username`, 'ALL', NOW(), 1 FROM `admin` + WHERE superadmin='1' AND `username` NOT IN (SELECT `username` FROM `domain_admins`);"); + + // Insert new DB schema version + $stmt = $pdo->query("REPLACE INTO `versions` (`application`, `version`) VALUES ('db_schema', '" . $db_version . "');"); + + $_SESSION['return'] = array( + 'type' => 'success', + 'msg' => 'Database initialisation completed' + ); + } + catch (PDOException $e) { + $_SESSION['return'] = array( + 'type' => 'danger', + 'msg' => 'Database initialisation failed: ' . $e->getMessage() + ); + } +} +?> \ No newline at end of file diff --git a/data/web/inc/prerequisites.inc.php b/data/web/inc/prerequisites.inc.php index 1959ae18..c766e780 100644 --- a/data/web/inc/prerequisites.inc.php +++ b/data/web/inc/prerequisites.inc.php @@ -29,18 +29,28 @@ require_once 'inc/lib/U2F.php'; $u2f = new u2flib_server\U2F('https://' . $_SERVER['SERVER_NAME']); // PDO -$dsn = "$database_type:host=$database_host;dbname=$database_name"; +// Calculate offset +$now = new DateTime(); +$mins = $now->getOffset() / 60; +$sgn = ($mins < 0 ? -1 : 1); +$mins = abs($mins); +$hrs = floor($mins / 60); +$mins -= $hrs * 60; +$offset = sprintf('%+d:%02d', $hrs*$sgn, $mins); + +$dsn = $database_type . ":host=" . $database_host . ";dbname=" . $database_name; $opt = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, + PDO::MYSQL_ATTR_INIT_COMMAND => "SET time_zone = '" . $offset . "'", ]; try { $pdo = new PDO($dsn, $database_user, $database_pass, $opt); } catch (PDOException $e) { ?> -
🐮 Connection failed, database may be in warm-up state, please try again later.

The following error was reported:
getMessage();?>
+
?? Connection failed, database may be in warm-up state, please try again later.

The following error was reported:
getMessage();?>