diff --git a/ident_switch-form.js b/ident_switch-form.js index d5dbf60..4233ad8 100644 --- a/ident_switch-form.js +++ b/ident_switch-form.js @@ -46,7 +46,7 @@ $(function() { }); // IMAP host → update SMTP/Sieve host placeholders - $("INPUT[name='_ident_switch.form.imap.host']").on('input change blur', function() { + $("INPUT[name='_ident_switch.form.imap.host']").on('change blur', function() { var imapHost = $(this).val() || 'localhost'; $("INPUT[name='_ident_switch.form.smtp.host']").attr('placeholder', imapHost); $("INPUT[name='_ident_switch.form.sieve.host']").attr('placeholder', imapHost); @@ -294,7 +294,7 @@ function plugin_switchIdent_applyJsPreconfig(cfg, email) { var port = cfg[proto].port; var defaultPort = ident_switch_portDefaults[proto][security] || ''; $("INPUT[name='_ident_switch.form." + proto + ".port']").val( - (port && port != defaultPort) ? port : '' + (port && parseInt(port) !== defaultPort) ? port : '' ); }); diff --git a/ident_switch.php b/ident_switch.php index 036d333..882e91f 100644 --- a/ident_switch.php +++ b/ident_switch.php @@ -33,7 +33,7 @@ class ident_switch extends rcube_plugin /** @var int Flag: account switching is enabled. */ public const DB_ENABLED = 1; - /** @var int Flag: use TLS for IMAP connection. */ + /** @var int Legacy flag: use TLS for IMAP. Read-only for backward compat; new records store scheme in host. */ public const DB_SECURE_IMAP_TLS = 4; /** @var int SMTP authentication: use same credentials as IMAP. */ @@ -199,13 +199,7 @@ class ident_switch extends rcube_plugin $accSelected = $r['id']; } - $lbl = $r['label']; - if (!$lbl) { - $username = $r['username'] ?: $r['email']; - $lbl = str_contains($username, '@') - ? $username - : $username . '@' . ($r['host'] ?: 'localhost'); - } + $lbl = $r['label'] ?: $r['username'] ?: $r['email']; $accNames[] = rcube::Q($lbl); } @@ -464,6 +458,44 @@ class ident_switch extends rcube_plugin return $s !== '' ? $s : null; } + /** + * Parse scheme prefix (ssl://, tls://) from a host string. + * + * @param string $host Host string, optionally prefixed with ssl:// or tls://. + * @return array{scheme: string, host: string} Parsed scheme and bare host. + */ + public static function parse_host_scheme(string $host): array + { + $lower = strtolower($host); + if (str_starts_with($lower, 'ssl://')) { + return ['scheme' => 'ssl', 'host' => substr($host, 6)]; + } + if (str_starts_with($lower, 'tls://')) { + return ['scheme' => 'tls', 'host' => substr($host, 6)]; + } + return ['scheme' => '', 'host' => $host]; + } + + /** + * Resolve username for an identity: use stored username or fall back to email. + * + * @param int $iid Identity ID. + * @param string|null $username Stored username (may be empty). + * @return string Resolved username. + */ + public static function resolve_username(int $iid, ?string $username): string + { + if (!empty($username)) { + return $username; + } + + $rc = rcmail::get_instance(); + $sql = 'SELECT email FROM ' . $rc->db->table_name('identities') . ' WHERE identity_id = ?'; + $q = $rc->db->query($sql, $iid); + $r = $rc->db->fetch_assoc($q); + return $r['email'] ?? ''; + } + /** * Write a message to the plugin's log file. * diff --git a/lib/IdentSwitchChecker.php b/lib/IdentSwitchChecker.php index 1f15dde..0358294 100644 --- a/lib/IdentSwitchChecker.php +++ b/lib/IdentSwitchChecker.php @@ -111,20 +111,12 @@ class IdentSwitchChecker { $imap = new rcube_imap_generic(); - $host = $identity['imap_host'] ?: 'localhost'; - $ssl = null; + $parsed = ident_switch::parse_host_scheme($identity['imap_host'] ?: 'localhost'); + $host = $parsed['host']; + $ssl = $parsed['scheme'] ?: null; - // Parse scheme from host field - $hostLower = strtolower($host); - if (str_starts_with($hostLower, 'ssl://')) { - $ssl = 'ssl'; - $host = substr($host, 6); - } elseif (str_starts_with($hostLower, 'tls://')) { - $ssl = 'tls'; - $host = substr($host, 6); - } elseif (!empty($identity['flags']) && ($identity['flags'] & ident_switch::DB_SECURE_IMAP_TLS)) { - // Backward compat: old records without scheme in host - $ssl = 'tls'; + if (!$ssl && !empty($identity['flags']) && ($identity['flags'] & ident_switch::DB_SECURE_IMAP_TLS)) { + $ssl = 'tls'; // Backward compat: old records without scheme in host } $def_port = ($ssl === 'ssl') ? 993 : 143; diff --git a/lib/IdentSwitchForm.php b/lib/IdentSwitchForm.php index 1ace377..80a8060 100644 --- a/lib/IdentSwitchForm.php +++ b/lib/IdentSwitchForm.php @@ -364,21 +364,11 @@ class IdentSwitchForm } /** - * Parse scheme prefix from a host string. - * - * @param string $host Host string, optionally prefixed with ssl:// or tls://. - * @return array{scheme: string, host: string} Parsed scheme and bare host. + * Delegate to ident_switch::parse_host_scheme(). */ private static function parse_host_scheme(string $host): array { - $lower = strtolower($host); - if (str_starts_with($lower, 'ssl://')) { - return ['scheme' => 'ssl', 'host' => substr($host, 6)]; - } - if (str_starts_with($lower, 'tls://')) { - return ['scheme' => 'tls', 'host' => substr($host, 6)]; - } - return ['scheme' => '', 'host' => $host]; + return ident_switch::parse_host_scheme($host); } /** diff --git a/lib/IdentSwitchSwitcher.php b/lib/IdentSwitchSwitcher.php index 387213b..362263e 100644 --- a/lib/IdentSwitchSwitcher.php +++ b/lib/IdentSwitchSwitcher.php @@ -66,13 +66,7 @@ class IdentSwitchSwitcher $q = $rc->db->query($sql, $identId, $rc->user->ID); $r = $rc->db->fetch_assoc($q); if (is_array($r)) { - if (!$r['username']) { - // Load email from identity - $sql = 'SELECT email FROM ' . $rc->db->table_name('identities') . ' WHERE identity_id = ?'; - $q = $rc->db->query($sql, $r['iid']); - $rIid = $rc->db->fetch_assoc($q); - $r['username'] = $rIid['email']; - } + $r['username'] = ident_switch::resolve_username((int)$r['iid'], $r['username']); ident_switch::write_log("Switching mailbox to one for identity with ID = {$r['iid']} (username = '{$r['username']}')."); @@ -95,20 +89,12 @@ class IdentSwitchSwitcher } } - $host = $r['imap_host'] ?: 'localhost'; - $ssl = null; + $parsed = ident_switch::parse_host_scheme($r['imap_host'] ?: 'localhost'); + $host = $parsed['host']; + $ssl = $parsed['scheme'] ?: null; - // Parse scheme from host field - $hostLower = strtolower($host); - if (str_starts_with($hostLower, 'ssl://')) { - $ssl = 'ssl'; - $host = substr($host, 6); - } elseif (str_starts_with($hostLower, 'tls://')) { - $ssl = 'tls'; - $host = substr($host, 6); - } elseif ($r['flags'] & ident_switch::DB_SECURE_IMAP_TLS) { - // Backward compat: old records without scheme in host - $ssl = 'tls'; + if (!$ssl && ($r['flags'] & ident_switch::DB_SECURE_IMAP_TLS)) { + $ssl = 'tls'; // Backward compat: old records without scheme in host } $def_port = ($ssl === 'ssl') ? 993 : 143; @@ -188,13 +174,7 @@ class IdentSwitchSwitcher $iid = $r['iid']; } - if (!$r['username']) { - // Load email from identity - $sql = 'SELECT email FROM ' . $rc->db->table_name('identities') . ' WHERE identity_id = ?'; - $q = $rc->db->query($sql, $iid); - $rIid = $rc->db->fetch_assoc($q); - $r['username'] = $rIid['email']; - } + $r['username'] = ident_switch::resolve_username($iid, $r['username']); $authMode = (int)$r['smtp_auth']; if ($authMode === ident_switch::SMTP_AUTH_CUSTOM) { @@ -264,12 +244,7 @@ class IdentSwitchSwitcher return $args; } - if (!$r['username']) { - $sql = 'SELECT email FROM ' . $rc->db->table_name('identities') . ' WHERE identity_id = ?'; - $q = $rc->db->query($sql, $iid); - $rIid = $rc->db->fetch_assoc($q); - $r['username'] = $rIid['email']; - } + $r['username'] = ident_switch::resolve_username($iid, $r['username']); $sieveHost = $r['sieve_host']; $sievePort = $r['sieve_port'] ?: 4190;