| | Author: Aleksander Machniak | +-----------------------------------------------------------------------+ */ if (\PHP_SAPI != 'cli') { exit('Not in shell mode (php-cli)'); } if (!defined('INSTALL_PATH')) { define('INSTALL_PATH', realpath(__DIR__ . '/../../') . '/'); } require_once INSTALL_PATH . 'program/include/iniset.php'; $rcmail = \rcmail::get_instance(0, 'test'); define('TESTS_DIR', realpath(__DIR__) . '/'); define('TESTS_USER', $rcmail->config->get('tests_username')); define('TESTS_PASS', $rcmail->config->get('tests_password')); /** * Utilities for test environment setup */ class Bootstrap { private static $imap_ready; /** * Wipe and re-initialize database */ public static function init_db() { $rcmail = \rcmail::get_instance(); $dsn = \rcube_db::parse_dsn($rcmail->config->get('db_dsnw')); $db = $rcmail->get_dbh(); if ($dsn['phptype'] == 'mysql' || $dsn['phptype'] == 'mysqli') { // drop all existing tables first $db->query('SET FOREIGN_KEY_CHECKS=0'); $sql_res = $db->query('SHOW TABLES'); while ($sql_arr = $db->fetch_array($sql_res)) { $table = reset($sql_arr); $db->query("DROP TABLE {$table}"); } self::init_db_user($db); // init database with schema system(sprintf('cat %s %s | mysql -h %s -u %s --password=%s %s', realpath(INSTALL_PATH . '/SQL/mysql.initial.sql'), realpath(TESTS_DIR . 'data/data.sql'), escapeshellarg($dsn['hostspec']), escapeshellarg($dsn['username']), escapeshellarg($dsn['password']), escapeshellarg($dsn['database']) )); } elseif ($dsn['phptype'] == 'sqlite') { $db->closeConnection(); // delete database file system(sprintf('rm -f %s', escapeshellarg($dsn['database']))); self::init_db_user($db); // load sample test data // Note: exec_script() does not really work with these queries $sql = file_get_contents(TESTS_DIR . 'data/data.sql'); $sql = preg_split('/;\n/', $sql, -1, \PREG_SPLIT_NO_EMPTY); foreach ($sql as $query) { $result = $db->query($query); if ($db->is_error($result)) { \rcube::raise_error($db->is_error(), false, true); } } } } /** * Create user/identity record for the test user */ private static function init_db_user($db) { $rcmail = \rcmail::get_instance(); $imap_host = $rcmail->config->get('imap_host'); if ($host = parse_url($imap_host, \PHP_URL_HOST)) { $imap_host = $host; } $db->query('INSERT INTO `users` (`username`, `mail_host`, `language`)' . " VALUES (?, ?, 'en_US')", TESTS_USER, $imap_host); $db->query('INSERT INTO `identities` (`user_id`, `email`, `standard`)' . " VALUES (1, ?, '1')", TESTS_USER); } /** * Wipe the configured IMAP account and fill with test data */ public static function init_imap($force = false) { if (!TESTS_USER) { return false; } elseif (!$force && self::$imap_ready !== null) { return self::$imap_ready; } self::connect_imap(TESTS_USER, TESTS_PASS); return self::$imap_ready; } /** * Authenticate to IMAP with the given credentials */ public static function connect_imap($username, $password) { $rcmail = \rcmail::get_instance(); $imap = $rcmail->get_storage(); if ($imap->is_connected()) { $imap->close(); self::$imap_ready = false; } $imap_host = $rcmail->config->get('imap_host'); $imap_port = 143; $imap_ssl = false; $a_host = parse_url($imap_host); if (!empty($a_host['host'])) { $imap_host = $a_host['host']; $imap_ssl = isset($a_host['scheme']) && in_array($a_host['scheme'], ['ssl', 'imaps', 'tls']) ? $a_host['scheme'] : false; $imap_port = $a_host['port'] ?? ($imap_ssl && $imap_ssl != 'tls' ? 993 : 143); } if (!$imap->connect($imap_host, $username, $password, $imap_port, $imap_ssl)) { \rcube::raise_error('IMAP error: unable to authenticate with user ' . TESTS_USER, false, true); } if (in_array('archive', (array) $rcmail->config->get('plugins'))) { // Register special folder type for the Archive plugin. // As we're in cli mode the plugin can't do it by its own \rcube_storage::$folder_types[] = 'archive'; } self::$imap_ready = true; } /** * Import the given file into IMAP */ public static function import_message($filename, $mailbox = 'INBOX') { if (!self::init_imap()) { \rcube::raise_error(__METHOD__ . ': IMAP connection unavailable', false, true); } $file = file_get_contents($filename); $imap = \rcmail::get_instance()->get_storage(); $imap->save_message($mailbox, $file); } /** * Delete all messages from the given mailbox */ public static function purge_mailbox($mailbox) { if (!self::init_imap()) { \rcube::raise_error(__METHOD__ . ': IMAP connection unavailable', false, true); } $imap = \rcmail::get_instance()->get_storage(); $imap->delete_message('*', $mailbox); } /** * Make sure the given mailbox exists in IMAP */ public static function ensure_mailbox($mailbox, $empty = false) { if (!self::init_imap()) { \rcube::raise_error(__METHOD__ . ': IMAP connection unavailable', false, true); } $imap = \rcmail::get_instance()->get_storage(); $folders = $imap->list_folders(); if (!in_array($mailbox, $folders)) { $imap->create_folder($mailbox, true); } elseif ($empty) { $imap->delete_message('*', $mailbox); } } /** * Make sure only special folders exist in IMAP */ public static function reset_mailboxes() { if (!self::init_imap()) { \rcube::raise_error(__METHOD__ . ': IMAP connection unavailable', false, true); } $rcmail = \rcmail::get_instance(); /** @var \rcube_imap $imap */ $imap = $rcmail->get_storage(); $got_defaults = $rcmail->config->get('create_default_folders'); $vendor = $imap->get_vendor(); // Note: We do not expect IMAP server auto-creating any folders foreach ($imap->list_folders() as $folder) { if ($folder != 'INBOX' && (!$got_defaults || !$imap->is_special_folder($folder))) { // GreenMail throws errors when unsubscribing a deleted folder if ($vendor == 'greenmail') { $imap->conn->deleteFolder($folder); } else { $imap->delete_folder($folder); } } } } /** * Check IMAP capabilities */ public static function get_storage() { if (!self::init_imap()) { \rcube::raise_error(__METHOD__ . ': IMAP connection unavailable', false, true); } return \rcmail::get_instance()->get_storage(); } /** * Return user preferences directly from database */ public static function get_prefs() { $rcmail = \rcmail::get_instance(); // Create a separate connection to the DB, otherwise // we hit some strange and hard to investigate locking issues $db = \rcube_db::factory($rcmail->config->get('db_dsnw'), $rcmail->config->get('db_dsnr'), false); $db->set_debug((bool) $rcmail->config->get('sql_debug')); $query = $db->query('SELECT preferences FROM users WHERE username = ?', TESTS_USER); $record = $db->fetch_assoc($query); return unserialize($record['preferences']); } }