PSR-12 coding standards compliance
Add phpcs/phpcbf tooling (composer require-dev, scripts, .phpcs.xml). Auto-fix tabs to spaces across all PHP files (phpcbf). Add missing doc comments for classes and constructors. Add missing @param tags on public/private methods.
This commit is contained in:
47
.phpcs.xml
Normal file
47
.phpcs.xml
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<ruleset name="NextBridge">
|
||||||
|
<description>PSR-12 coding standard for NextBridge RoundCube plugin</description>
|
||||||
|
|
||||||
|
<!-- Use PSR-12 as base with RoundCube-specific exclusions -->
|
||||||
|
<rule ref="PSR12">
|
||||||
|
<!-- Allow longer lines for readability -->
|
||||||
|
<exclude name="Generic.Files.LineLength"/>
|
||||||
|
<!-- RoundCube plugins don't use namespaces -->
|
||||||
|
<exclude name="PSR1.Classes.ClassDeclaration.MissingNamespace"/>
|
||||||
|
<!-- RoundCube plugins use lowercase class names by convention -->
|
||||||
|
<exclude name="Squiz.Classes.ValidClassName.NotCamelCaps"/>
|
||||||
|
<!-- RoundCube plugins can have side effects (require_once) -->
|
||||||
|
<exclude name="PSR1.Files.SideEffects.FoundWithSymbols"/>
|
||||||
|
<!-- RoundCube hooks use snake_case method names by convention -->
|
||||||
|
<exclude name="PSR1.Methods.CamelCapsMethodName.NotCamelCaps"/>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<!-- Allow @url/@link in class doc comments -->
|
||||||
|
<rule ref="Squiz.Commenting.ClassComment">
|
||||||
|
<exclude name="Squiz.Commenting.ClassComment.TagNotAllowed"/>
|
||||||
|
</rule>
|
||||||
|
<rule ref="Squiz.Commenting.FunctionComment">
|
||||||
|
<exclude name="Squiz.Commenting.FunctionComment.MissingReturn"/>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<!-- Line length: warn at 120, no hard limit -->
|
||||||
|
<rule ref="Generic.Files.LineLength">
|
||||||
|
<properties>
|
||||||
|
<property name="lineLimit" value="120"/>
|
||||||
|
<property name="absoluteLineLimit" value="0"/>
|
||||||
|
</properties>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<!-- Require class documentation -->
|
||||||
|
<rule ref="Squiz.Commenting.ClassComment"/>
|
||||||
|
|
||||||
|
<!-- Require function documentation with @param and @return -->
|
||||||
|
<rule ref="Squiz.Commenting.FunctionComment"/>
|
||||||
|
|
||||||
|
<!-- Files to check -->
|
||||||
|
<file>ident_switch.php</file>
|
||||||
|
<file>lib/</file>
|
||||||
|
|
||||||
|
<!-- Exclude vendor directories -->
|
||||||
|
<exclude-pattern>*/vendor/*</exclude-pattern>
|
||||||
|
</ruleset>
|
||||||
@@ -38,6 +38,9 @@
|
|||||||
"roundcube/plugin-installer": ">=0.3.0",
|
"roundcube/plugin-installer": ">=0.3.0",
|
||||||
"ext-ctype": "*"
|
"ext-ctype": "*"
|
||||||
},
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"squizlabs/php_codesniffer": "^3.0"
|
||||||
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"boressoft/ident_switch": "*",
|
"boressoft/ident_switch": "*",
|
||||||
"elm/identity_smtp": "*",
|
"elm/identity_smtp": "*",
|
||||||
@@ -51,5 +54,14 @@
|
|||||||
"min-version": "1.6",
|
"min-version": "1.6",
|
||||||
"sql-dir": "SQL"
|
"sql-dir": "SQL"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"phpcs": "phpcs",
|
||||||
|
"phpcbf": "phpcbf"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"allow-plugins": {
|
||||||
|
"roundcube/plugin-installer": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
158
composer.lock
generated
Normal file
158
composer.lock
generated
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
{
|
||||||
|
"_readme": [
|
||||||
|
"This file locks the dependencies of your project to a known state",
|
||||||
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
|
"This file is @generated automatically"
|
||||||
|
],
|
||||||
|
"content-hash": "46b2d3558cb304fde0539d1b85971382",
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "roundcube/plugin-installer",
|
||||||
|
"version": "0.3.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/roundcube/plugin-installer.git",
|
||||||
|
"reference": "c4335e20b86cfe3a184ccf24d675c6a0338a372a"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/roundcube/plugin-installer/zipball/c4335e20b86cfe3a184ccf24d675c6a0338a372a",
|
||||||
|
"reference": "c4335e20b86cfe3a184ccf24d675c6a0338a372a",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"composer-plugin-api": "^1.0 || ^2.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"composer/composer": "*"
|
||||||
|
},
|
||||||
|
"type": "composer-plugin",
|
||||||
|
"extra": {
|
||||||
|
"class": [
|
||||||
|
"Roundcube\\Composer\\RoundcubeInstaller"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"Roundcube\\Composer": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"GPL-3.0+"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Thomas Bruederli",
|
||||||
|
"email": "thomas@roundcube.net"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Till Klampaeckel",
|
||||||
|
"email": "till@php.net"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Philip Weir",
|
||||||
|
"email": "roundcube@tehinterweb.co.uk"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A composer-installer for Roundcube plugins and skins.",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/roundcube/plugin-installer/issues",
|
||||||
|
"source": "https://github.com/roundcube/plugin-installer/tree/0.3.2"
|
||||||
|
},
|
||||||
|
"time": "2022-06-24T09:08:18+00:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"packages-dev": [
|
||||||
|
{
|
||||||
|
"name": "squizlabs/php_codesniffer",
|
||||||
|
"version": "3.13.5",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
|
||||||
|
"reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4",
|
||||||
|
"reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-simplexml": "*",
|
||||||
|
"ext-tokenizer": "*",
|
||||||
|
"ext-xmlwriter": "*",
|
||||||
|
"php": ">=5.4.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4"
|
||||||
|
},
|
||||||
|
"bin": [
|
||||||
|
"bin/phpcbf",
|
||||||
|
"bin/phpcs"
|
||||||
|
],
|
||||||
|
"type": "library",
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"BSD-3-Clause"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Greg Sherwood",
|
||||||
|
"role": "Former lead"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Juliette Reinders Folmer",
|
||||||
|
"role": "Current lead"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Contributors",
|
||||||
|
"homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
|
||||||
|
"homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
|
||||||
|
"keywords": [
|
||||||
|
"phpcs",
|
||||||
|
"standards",
|
||||||
|
"static analysis"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues",
|
||||||
|
"security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy",
|
||||||
|
"source": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
|
||||||
|
"wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/PHPCSStandards",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/jrfnl",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://opencollective.com/php_codesniffer",
|
||||||
|
"type": "open_collective"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://thanks.dev/u/gh/phpcsstandards",
|
||||||
|
"type": "thanks_dev"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-11-04T16:30:35+00:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"aliases": [],
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"stability-flags": {},
|
||||||
|
"prefer-stable": false,
|
||||||
|
"prefer-lowest": false,
|
||||||
|
"platform": {
|
||||||
|
"php": ">=8.2",
|
||||||
|
"ext-ctype": "*"
|
||||||
|
},
|
||||||
|
"platform-dev": {},
|
||||||
|
"plugin-api-version": "2.6.0"
|
||||||
|
}
|
||||||
1001
ident_switch.php
1001
ident_switch.php
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ident_switch - Background mail checker.
|
* ident_switch - Background mail checker.
|
||||||
*
|
*
|
||||||
@@ -14,250 +15,250 @@
|
|||||||
*/
|
*/
|
||||||
class IdentSwitchChecker
|
class IdentSwitchChecker
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Called on each refresh cycle.
|
* Called on each refresh cycle.
|
||||||
*
|
*
|
||||||
* Builds the list of identities to check (excluding the currently active one,
|
* Builds the list of identities to check (excluding the currently active one,
|
||||||
* including the primary account when impersonating), then checks them
|
* including the primary account when impersonating), then checks them
|
||||||
* in round-robin or all-at-once mode.
|
* in round-robin or all-at-once mode.
|
||||||
*
|
*
|
||||||
* @param array $args Hook arguments (empty for refresh hook).
|
* @param array $args Hook arguments (empty for refresh hook).
|
||||||
* @return array Unmodified hook arguments.
|
* @return array Unmodified hook arguments.
|
||||||
*/
|
*/
|
||||||
public function check_new_mail(array $args): array
|
public function check_new_mail(array $args): array
|
||||||
{
|
{
|
||||||
$rc = rcmail::get_instance();
|
$rc = rcmail::get_instance();
|
||||||
|
|
||||||
$identities = $this->get_checkable_identities($rc);
|
$identities = $this->get_checkable_identities($rc);
|
||||||
|
|
||||||
// Exclude the currently active secondary identity (RC already checks it)
|
// Exclude the currently active secondary identity (RC already checks it)
|
||||||
$activeIid = (int)($_SESSION['iid' . ident_switch::MY_POSTFIX] ?? -1);
|
$activeIid = (int)($_SESSION['iid' . ident_switch::MY_POSTFIX] ?? -1);
|
||||||
$identities = array_values(array_filter($identities, function ($id) use ($activeIid) {
|
$identities = array_values(array_filter($identities, function ($id) use ($activeIid) {
|
||||||
return (int)$id['iid'] !== $activeIid;
|
return (int)$id['iid'] !== $activeIid;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// When impersonating, also check the primary account
|
// When impersonating, also check the primary account
|
||||||
$isImpersonating = strcasecmp($rc->user->data['username'], $_SESSION['username']) !== 0;
|
$isImpersonating = strcasecmp($rc->user->data['username'], $_SESSION['username']) !== 0;
|
||||||
if ($isImpersonating) {
|
if ($isImpersonating) {
|
||||||
$primary = $this->get_primary_identity($rc);
|
$primary = $this->get_primary_identity($rc);
|
||||||
if ($primary) {
|
if ($primary) {
|
||||||
$identities[] = $primary;
|
$identities[] = $primary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($identities)) {
|
if (empty($identities)) {
|
||||||
$this->send_counts($rc);
|
$this->send_counts($rc);
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($rc->config->get('ident_switch.round_robin', false)) {
|
if ($rc->config->get('ident_switch.round_robin', false)) {
|
||||||
// Round-robin: check one identity per refresh cycle
|
// Round-robin: check one identity per refresh cycle
|
||||||
$index = ($_SESSION['ident_switch_check_index'] ?? -1) + 1;
|
$index = ($_SESSION['ident_switch_check_index'] ?? -1) + 1;
|
||||||
if ($index >= count($identities)) {
|
if ($index >= count($identities)) {
|
||||||
$index = 0;
|
$index = 0;
|
||||||
}
|
}
|
||||||
$_SESSION['ident_switch_check_index'] = $index;
|
$_SESSION['ident_switch_check_index'] = $index;
|
||||||
$this->check_identity($rc, $identities[$index]);
|
$this->check_identity($rc, $identities[$index]);
|
||||||
} else {
|
} else {
|
||||||
foreach ($identities as $identity) {
|
foreach ($identities as $identity) {
|
||||||
$this->check_identity($rc, $identity);
|
$this->check_identity($rc, $identity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->send_counts($rc);
|
$this->send_counts($rc);
|
||||||
|
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check a single identity for unseen messages and notify if new mail.
|
* Check a single identity for unseen messages and notify if new mail.
|
||||||
*
|
*
|
||||||
* @param rcmail $rc Roundcube instance.
|
* @param rcmail $rc Roundcube instance.
|
||||||
* @param array $identity Identity record from the database.
|
* @param array $identity Identity record from the database.
|
||||||
*/
|
*/
|
||||||
private function check_identity(rcmail $rc, array $identity): void
|
private function check_identity(rcmail $rc, array $identity): void
|
||||||
{
|
{
|
||||||
$counts = $_SESSION['ident_switch_counts'] ?? [];
|
$counts = $_SESSION['ident_switch_counts'] ?? [];
|
||||||
$previousCount = $counts[$identity['iid']]['unseen'] ?? 0;
|
$previousCount = $counts[$identity['iid']]['unseen'] ?? 0;
|
||||||
|
|
||||||
$count = $this->check_unseen($rc, $identity, $previousCount);
|
$count = $this->check_unseen($rc, $identity, $previousCount);
|
||||||
|
|
||||||
ident_switch::write_log("Check identity {$identity['iid']} ({$identity['email']}): unseen={$count}, previous={$previousCount}");
|
ident_switch::write_log("Check identity {$identity['iid']} ({$identity['email']}): unseen={$count}, previous={$previousCount}");
|
||||||
|
|
||||||
// Set baseline on first check; preserve it across subsequent checks
|
// Set baseline on first check; preserve it across subsequent checks
|
||||||
$baseline = $counts[$identity['iid']]['baseline'] ?? $count;
|
$baseline = $counts[$identity['iid']]['baseline'] ?? $count;
|
||||||
|
|
||||||
$counts[$identity['iid']] = [
|
$counts[$identity['iid']] = [
|
||||||
'unseen' => $count,
|
'unseen' => $count,
|
||||||
'baseline' => $baseline,
|
'baseline' => $baseline,
|
||||||
'checked_at' => time(),
|
'checked_at' => time(),
|
||||||
];
|
];
|
||||||
$_SESSION['ident_switch_counts'] = $counts;
|
$_SESSION['ident_switch_counts'] = $counts;
|
||||||
|
|
||||||
if ($count > $previousCount) {
|
if ($count > $previousCount) {
|
||||||
$this->send_notification($rc, $identity, $count);
|
$this->send_notification($rc, $identity, $count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to an identity's IMAP server and return INBOX unseen count.
|
* Connect to an identity's IMAP server and return INBOX unseen count.
|
||||||
*
|
*
|
||||||
* @param rcmail $rc Roundcube instance.
|
* @param rcmail $rc Roundcube instance.
|
||||||
* @param array $identity Identity DB record.
|
* @param array $identity Identity DB record.
|
||||||
* @param int $previousCount Previous unseen count (returned on error).
|
* @param integer $previousCount Previous unseen count (returned on error).
|
||||||
* @return int Unseen message count.
|
* @return integer Unseen message count.
|
||||||
*/
|
*/
|
||||||
private function check_unseen(rcmail $rc, array $identity, int $previousCount): int
|
private function check_unseen(rcmail $rc, array $identity, int $previousCount): int
|
||||||
{
|
{
|
||||||
$imap = new rcube_imap_generic();
|
$imap = new rcube_imap_generic();
|
||||||
|
|
||||||
$parsed = ident_switch::parse_host_scheme($identity['imap_host'] ?: 'localhost');
|
$parsed = ident_switch::parse_host_scheme($identity['imap_host'] ?: 'localhost');
|
||||||
$host = $parsed['host'];
|
$host = $parsed['host'];
|
||||||
$ssl = $parsed['scheme'] ?: null;
|
$ssl = $parsed['scheme'] ?: null;
|
||||||
|
|
||||||
if (!$ssl && !empty($identity['flags']) && ($identity['flags'] & ident_switch::DB_SECURE_IMAP_TLS)) {
|
if (!$ssl && !empty($identity['flags']) && ($identity['flags'] & ident_switch::DB_SECURE_IMAP_TLS)) {
|
||||||
$ssl = 'tls'; // Backward compat: old records without scheme in host
|
$ssl = 'tls'; // Backward compat: old records without scheme in host
|
||||||
}
|
}
|
||||||
|
|
||||||
$def_port = ($ssl === 'ssl') ? 993 : 143;
|
$def_port = ($ssl === 'ssl') ? 993 : 143;
|
||||||
$port = $identity['imap_port'] ?: $def_port;
|
$port = $identity['imap_port'] ?: $def_port;
|
||||||
|
|
||||||
$username = $identity['username'] ?: $identity['email'];
|
$username = $identity['username'] ?: $identity['email'];
|
||||||
$password = $rc->decrypt($identity['password']);
|
$password = $rc->decrypt($identity['password']);
|
||||||
if ($password === false) {
|
if ($password === false) {
|
||||||
ident_switch::write_log("Failed to decrypt password for identity {$identity['iid']}");
|
ident_switch::write_log("Failed to decrypt password for identity {$identity['iid']}");
|
||||||
return $previousCount;
|
return $previousCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $imap->connect($host, $username, $password, [
|
$result = $imap->connect($host, $username, $password, [
|
||||||
'port' => $port,
|
'port' => $port,
|
||||||
'ssl_mode' => $ssl,
|
'ssl_mode' => $ssl,
|
||||||
'timeout' => 5,
|
'timeout' => 5,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!$result) {
|
if (!$result) {
|
||||||
ident_switch::write_log("Failed to check mail for identity {$identity['iid']}: " . $imap->error);
|
ident_switch::write_log("Failed to check mail for identity {$identity['iid']}: " . $imap->error);
|
||||||
return $previousCount;
|
return $previousCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
$status = $imap->status('INBOX', ['UNSEEN']);
|
$status = $imap->status('INBOX', ['UNSEEN']);
|
||||||
$unseen = $status['UNSEEN'] ?? 0;
|
$unseen = $status['UNSEEN'] ?? 0;
|
||||||
|
|
||||||
$imap->closeConnection();
|
$imap->closeConnection();
|
||||||
|
|
||||||
return $unseen;
|
return $unseen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a virtual identity record for the primary account.
|
* Build a virtual identity record for the primary account.
|
||||||
*
|
*
|
||||||
* When the user has switched to a secondary account, the primary account's
|
* When the user has switched to a secondary account, the primary account's
|
||||||
* connection details are saved in session with the MY_POSTFIX suffix.
|
* connection details are saved in session with the MY_POSTFIX suffix.
|
||||||
*
|
*
|
||||||
* @param rcmail $rc Roundcube instance.
|
* @param rcmail $rc Roundcube instance.
|
||||||
* @return array|null Identity-like array, or null if session data is missing.
|
* @return array|null Identity-like array, or null if session data is missing.
|
||||||
*/
|
*/
|
||||||
private function get_primary_identity(rcmail $rc): ?array
|
private function get_primary_identity(rcmail $rc): ?array
|
||||||
{
|
{
|
||||||
$postfix = ident_switch::MY_POSTFIX;
|
$postfix = ident_switch::MY_POSTFIX;
|
||||||
|
|
||||||
if (!isset($_SESSION['password' . $postfix])) {
|
if (!isset($_SESSION['password' . $postfix])) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$host = $_SESSION['storage_host' . $postfix] ?? 'localhost';
|
$host = $_SESSION['storage_host' . $postfix] ?? 'localhost';
|
||||||
$port = $_SESSION['storage_port' . $postfix] ?? 143;
|
$port = $_SESSION['storage_port' . $postfix] ?? 143;
|
||||||
$ssl = $_SESSION['storage_ssl' . $postfix] ?? null;
|
$ssl = $_SESSION['storage_ssl' . $postfix] ?? null;
|
||||||
|
|
||||||
// Prepend protocol prefix so check_unseen() can parse it
|
// Prepend protocol prefix so check_unseen() can parse it
|
||||||
if ($ssl === 'ssl' && !str_starts_with(strtolower($host), 'ssl://')) {
|
if ($ssl === 'ssl' && !str_starts_with(strtolower($host), 'ssl://')) {
|
||||||
$host = 'ssl://' . $host;
|
$host = 'ssl://' . $host;
|
||||||
} elseif ($ssl === 'tls' && !str_starts_with(strtolower($host), 'tls://')) {
|
} elseif ($ssl === 'tls' && !str_starts_with(strtolower($host), 'tls://')) {
|
||||||
$host = 'tls://' . $host;
|
$host = 'tls://' . $host;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'iid' => 0,
|
'iid' => 0,
|
||||||
'imap_host' => $host,
|
'imap_host' => $host,
|
||||||
'imap_port' => $port,
|
'imap_port' => $port,
|
||||||
'flags' => 0,
|
'flags' => 0,
|
||||||
'username' => $rc->user->data['username'],
|
'username' => $rc->user->data['username'],
|
||||||
'password' => $_SESSION['password' . $postfix],
|
'password' => $_SESSION['password' . $postfix],
|
||||||
'email' => $rc->user->data['username'],
|
'email' => $rc->user->data['username'],
|
||||||
'label' => $_SESSION['global_alias'] ?? $rc->user->data['username'],
|
'label' => $_SESSION['global_alias'] ?? $rc->user->data['username'],
|
||||||
'notify_basic' => null,
|
'notify_basic' => null,
|
||||||
'notify_sound' => null,
|
'notify_sound' => null,
|
||||||
'notify_desktop' => null,
|
'notify_desktop' => null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all enabled identities that have mail checking enabled.
|
* Get all enabled identities that have mail checking enabled.
|
||||||
*
|
*
|
||||||
* @param rcmail $rc Roundcube instance.
|
* @param rcmail $rc Roundcube instance.
|
||||||
* @return array List of identity records.
|
* @return array List of identity records.
|
||||||
*/
|
*/
|
||||||
private function get_checkable_identities(rcmail $rc): array
|
private function get_checkable_identities(rcmail $rc): array
|
||||||
{
|
{
|
||||||
$sql = 'SELECT isw.iid, isw.imap_host, isw.imap_port, isw.flags, '
|
$sql = 'SELECT isw.iid, isw.imap_host, isw.imap_port, isw.flags, '
|
||||||
. 'isw.username, isw.password, isw.label, '
|
. 'isw.username, isw.password, isw.label, '
|
||||||
. 'isw.notify_basic, isw.notify_sound, isw.notify_desktop, '
|
. 'isw.notify_basic, isw.notify_sound, isw.notify_desktop, '
|
||||||
. 'ii.email '
|
. 'ii.email '
|
||||||
. 'FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' isw '
|
. 'FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' isw '
|
||||||
. 'INNER JOIN ' . $rc->db->table_name('identities') . ' ii ON isw.iid = ii.identity_id '
|
. 'INNER JOIN ' . $rc->db->table_name('identities') . ' ii ON isw.iid = ii.identity_id '
|
||||||
. 'WHERE isw.user_id = ? AND isw.flags & ? > 0 AND isw.notify_check = ? AND isw.parent_id IS NULL';
|
. 'WHERE isw.user_id = ? AND isw.flags & ? > 0 AND isw.notify_check = ? AND isw.parent_id IS NULL';
|
||||||
|
|
||||||
$q = $rc->db->query($sql, $rc->user->ID, ident_switch::DB_ENABLED, ident_switch::NOTIFY_CHECK_ENABLED);
|
$q = $rc->db->query($sql, $rc->user->ID, ident_switch::DB_ENABLED, ident_switch::NOTIFY_CHECK_ENABLED);
|
||||||
|
|
||||||
$identities = [];
|
$identities = [];
|
||||||
while ($r = $rc->db->fetch_assoc($q)) {
|
while ($r = $rc->db->fetch_assoc($q)) {
|
||||||
$identities[] = $r;
|
$identities[] = $r;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $identities;
|
return $identities;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send all cached unseen counts to client JS.
|
* Send all cached unseen counts to client JS.
|
||||||
*
|
*
|
||||||
* @param rcmail $rc Roundcube instance.
|
* @param rcmail $rc Roundcube instance.
|
||||||
*/
|
*/
|
||||||
private function send_counts(rcmail $rc): void
|
private function send_counts(rcmail $rc): void
|
||||||
{
|
{
|
||||||
$counts = $_SESSION['ident_switch_counts'] ?? [];
|
$counts = $_SESSION['ident_switch_counts'] ?? [];
|
||||||
$data = [];
|
$data = [];
|
||||||
foreach ($counts as $iid => $info) {
|
foreach ($counts as $iid => $info) {
|
||||||
$data[$iid] = [
|
$data[$iid] = [
|
||||||
'unseen' => $info['unseen'],
|
'unseen' => $info['unseen'],
|
||||||
'baseline' => $info['baseline'] ?? $info['unseen'],
|
'baseline' => $info['baseline'] ?? $info['unseen'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$rc->output->command('plugin.ident_switch.update_counts', $data);
|
$rc->output->command('plugin.ident_switch.update_counts', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send notification command to client for a specific identity.
|
* Send notification command to client for a specific identity.
|
||||||
*
|
*
|
||||||
* @param rcmail $rc Roundcube instance.
|
* @param rcmail $rc Roundcube instance.
|
||||||
* @param array $identity Identity record.
|
* @param array $identity Identity record.
|
||||||
* @param int $count New unseen count.
|
* @param integer $count New unseen count.
|
||||||
*/
|
*/
|
||||||
private function send_notification(rcmail $rc, array $identity, int $count): void
|
private function send_notification(rcmail $rc, array $identity, int $count): void
|
||||||
{
|
{
|
||||||
$basic = $identity['notify_basic'] ?? $rc->config->get('newmail_notifier_basic', false);
|
$basic = $identity['notify_basic'] ?? $rc->config->get('newmail_notifier_basic', false);
|
||||||
$sound = $identity['notify_sound'] ?? $rc->config->get('newmail_notifier_sound', false);
|
$sound = $identity['notify_sound'] ?? $rc->config->get('newmail_notifier_sound', false);
|
||||||
$desktop = $identity['notify_desktop'] ?? $rc->config->get('newmail_notifier_desktop', false);
|
$desktop = $identity['notify_desktop'] ?? $rc->config->get('newmail_notifier_desktop', false);
|
||||||
|
|
||||||
$label = $identity['label'] ?: $identity['email'];
|
$label = $identity['label'] ?: $identity['email'];
|
||||||
|
|
||||||
$rc->output->command('plugin.ident_switch.notify', [
|
$rc->output->command('plugin.ident_switch.notify', [
|
||||||
'iid' => $identity['iid'],
|
'iid' => $identity['iid'],
|
||||||
'label' => $label,
|
'label' => $label,
|
||||||
'count' => $count,
|
'count' => $count,
|
||||||
'basic' => (bool)$basic,
|
'basic' => (bool)$basic,
|
||||||
'sound' => (bool)$sound,
|
'sound' => (bool)$sound,
|
||||||
'desktop' => (bool)$desktop,
|
'desktop' => (bool)$desktop,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ident_switch - Preconfiguration handler.
|
* ident_switch - Preconfiguration handler.
|
||||||
*
|
*
|
||||||
@@ -15,111 +16,116 @@
|
|||||||
*/
|
*/
|
||||||
class IdentSwitchPreconfig
|
class IdentSwitchPreconfig
|
||||||
{
|
{
|
||||||
private ident_switch $plugin;
|
private ident_switch $plugin;
|
||||||
|
|
||||||
public function __construct(ident_switch $plugin)
|
/**
|
||||||
{
|
* Constructor.
|
||||||
$this->plugin = $plugin;
|
*
|
||||||
}
|
* @param ident_switch $plugin Parent plugin instance.
|
||||||
|
*/
|
||||||
|
public function __construct(ident_switch $plugin)
|
||||||
|
{
|
||||||
|
$this->plugin = $plugin;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load preconfigured settings for a domain from config.
|
* Load preconfigured settings for a domain from config.
|
||||||
*
|
*
|
||||||
* @param string $email Email address to extract domain from.
|
* @param string $email Email address to extract domain from.
|
||||||
* @return array|false Preconfig array for the domain, or false if not found.
|
* @return array|false Preconfig array for the domain, or false if not found.
|
||||||
*/
|
*/
|
||||||
public function get(string $email): array|false
|
public function get(string $email): array|false
|
||||||
{
|
{
|
||||||
$dom = substr(strstr($email, '@'), 1);
|
$dom = substr(strstr($email, '@'), 1);
|
||||||
if (!$dom) {
|
if (!$dom) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->plugin->load_config();
|
$this->plugin->load_config();
|
||||||
|
|
||||||
$cfg = rcmail::get_instance()->config->get('ident_switch.preconfig', []);
|
$cfg = rcmail::get_instance()->config->get('ident_switch.preconfig', []);
|
||||||
$cfg = $cfg[$dom] ?? $cfg['*'] ?? null;
|
$cfg = $cfg[$dom] ?? $cfg['*'] ?? null;
|
||||||
|
|
||||||
if ($cfg) {
|
if ($cfg) {
|
||||||
if (empty($cfg['imap_host']) && empty($cfg['host'])) {
|
if (empty($cfg['imap_host']) && empty($cfg['host'])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $cfg ?: false;
|
return $cfg ?: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply preconfigured settings to an identity form record.
|
* Apply preconfigured settings to an identity form record.
|
||||||
*
|
*
|
||||||
* Parses IMAP, SMTP, and Sieve host URLs to extract scheme, host,
|
* Parses IMAP, SMTP, and Sieve host URLs to extract scheme, host,
|
||||||
* and port, then sets the username and delimiter based on config values.
|
* and port, then sets the username and delimiter based on config values.
|
||||||
*
|
*
|
||||||
* @param array $record Identity record to modify (passed by reference).
|
* @param array $record Identity record to modify (passed by reference).
|
||||||
* @return bool True if the preconfig is readonly, false otherwise.
|
* @return boolean True if the preconfig is readonly, false otherwise.
|
||||||
*/
|
*/
|
||||||
public function apply(array &$record): bool
|
public function apply(array &$record): bool
|
||||||
{
|
{
|
||||||
$email = $record['email'] ?? '';
|
$email = $record['email'] ?? '';
|
||||||
if (empty($email)) {
|
if (empty($email)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$cfg = $this->get($email);
|
$cfg = $this->get($email);
|
||||||
if (is_array($cfg)) {
|
if (is_array($cfg)) {
|
||||||
ident_switch::write_log("Applying predefined configuration for '{$email}'.");
|
ident_switch::write_log("Applying predefined configuration for '{$email}'.");
|
||||||
|
|
||||||
// Parse each protocol URL into host, security, and port
|
// Parse each protocol URL into host, security, and port
|
||||||
$protocols = [
|
$protocols = [
|
||||||
'imap' => $cfg['imap_host'] ?? $cfg['host'] ?? '',
|
'imap' => $cfg['imap_host'] ?? $cfg['host'] ?? '',
|
||||||
'smtp' => $cfg['smtp_host'] ?? $cfg['host'] ?? '',
|
'smtp' => $cfg['smtp_host'] ?? $cfg['host'] ?? '',
|
||||||
'sieve' => $cfg['sieve_host'] ?? '',
|
'sieve' => $cfg['sieve_host'] ?? '',
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($protocols as $proto => $url) {
|
foreach ($protocols as $proto => $url) {
|
||||||
if (empty($url)) {
|
if (empty($url)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$urlArr = parse_url($url);
|
$urlArr = parse_url($url);
|
||||||
$host = !empty($urlArr['host']) ? rcube::Q($urlArr['host'], 'url') : '';
|
$host = !empty($urlArr['host']) ? rcube::Q($urlArr['host'], 'url') : '';
|
||||||
$scheme = strtolower($urlArr['scheme'] ?? '');
|
$scheme = strtolower($urlArr['scheme'] ?? '');
|
||||||
|
|
||||||
$record["ident_switch.form.{$proto}.host"] = $host;
|
$record["ident_switch.form.{$proto}.host"] = $host;
|
||||||
$record["ident_switch.form.{$proto}.security"] = in_array($scheme, ['ssl', 'tls']) ? $scheme : '';
|
$record["ident_switch.form.{$proto}.security"] = in_array($scheme, ['ssl', 'tls']) ? $scheme : '';
|
||||||
$record["ident_switch.form.{$proto}.port"] = !empty($urlArr['port']) ? intval($urlArr['port']) : '';
|
$record["ident_switch.form.{$proto}.port"] = !empty($urlArr['port']) ? intval($urlArr['port']) : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$loginSet = false;
|
$loginSet = false;
|
||||||
if (!empty($cfg['user'])) {
|
if (!empty($cfg['user'])) {
|
||||||
match (strtoupper($cfg['user'])) {
|
match (strtoupper($cfg['user'])) {
|
||||||
'EMAIL' => ($record['ident_switch.form.imap.username'] = $email) && ($loginSet = true),
|
'EMAIL' => ($record['ident_switch.form.imap.username'] = $email) && ($loginSet = true),
|
||||||
'MBOX' => ($record['ident_switch.form.imap.username'] = strstr($email, '@', true)) && ($loginSet = true),
|
'MBOX' => ($record['ident_switch.form.imap.username'] = strstr($email, '@', true)) && ($loginSet = true),
|
||||||
default => null,
|
default => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($cfg['readonly'])) {
|
if (!empty($cfg['readonly'])) {
|
||||||
$record['ident_switch.form.common.readonly'] = $loginSet ? 2 : 1;
|
$record['ident_switch.form.common.readonly'] = $loginSet ? 2 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// IMAP folder hierarchy delimiter (null or absent = auto-detect)
|
// IMAP folder hierarchy delimiter (null or absent = auto-detect)
|
||||||
if (isset($cfg['delimiter'])) {
|
if (isset($cfg['delimiter'])) {
|
||||||
$record['ident_switch.form.imap.delimiter'] = $cfg['delimiter'];
|
$record['ident_switch.form.imap.delimiter'] = $cfg['delimiter'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notification defaults from preconfig
|
// Notification defaults from preconfig
|
||||||
if (isset($cfg['notify_check'])) {
|
if (isset($cfg['notify_check'])) {
|
||||||
$record['ident_switch.form.notify.check'] = $cfg['notify_check'] ? 1 : 0;
|
$record['ident_switch.form.notify.check'] = $cfg['notify_check'] ? 1 : 0;
|
||||||
}
|
}
|
||||||
foreach (['notify_basic', 'notify_sound', 'notify_desktop'] as $key) {
|
foreach (['notify_basic', 'notify_sound', 'notify_desktop'] as $key) {
|
||||||
if (isset($cfg[$key])) {
|
if (isset($cfg[$key])) {
|
||||||
$formKey = 'ident_switch.form.notify.' . substr($key, 7);
|
$formKey = 'ident_switch.form.notify.' . substr($key, 7);
|
||||||
$record[$formKey] = $cfg[$key] === null ? '' : ($cfg[$key] ? '1' : '0');
|
$record[$formKey] = $cfg[$key] === null ? '' : ($cfg[$key] ? '1' : '0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (bool)($cfg['readonly'] ?? false);
|
return (bool)($cfg['readonly'] ?? false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ident_switch - Account switching handler.
|
* ident_switch - Account switching handler.
|
||||||
*
|
*
|
||||||
@@ -17,392 +18,394 @@
|
|||||||
*/
|
*/
|
||||||
class IdentSwitchSwitcher
|
class IdentSwitchSwitcher
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Handle the account switch action (AJAX).
|
* Handle the account switch action (AJAX).
|
||||||
*
|
*
|
||||||
* Saves current account state to session, loads the target account's
|
* Saves current account state to session, loads the target account's
|
||||||
* IMAP/SMTP configuration, and redirects to INBOX.
|
* IMAP/SMTP configuration, and redirects to INBOX.
|
||||||
* When switching back to default (id=-1), restores the original session state.
|
* When switching back to default (id=-1), restores the original session state.
|
||||||
*/
|
*/
|
||||||
public function switch_account(): void
|
public function switch_account(): void
|
||||||
{
|
{
|
||||||
$rc = rcmail::get_instance();
|
$rc = rcmail::get_instance();
|
||||||
|
|
||||||
$my_postfix_len = strlen(ident_switch::MY_POSTFIX);
|
$my_postfix_len = strlen(ident_switch::MY_POSTFIX);
|
||||||
$identId = (int)rcube_utils::get_input_value('_ident-id', rcube_utils::INPUT_POST);
|
$identId = (int)rcube_utils::get_input_value('_ident-id', rcube_utils::INPUT_POST);
|
||||||
|
|
||||||
$rc->session->remove('folders');
|
$rc->session->remove('folders');
|
||||||
$rc->session->remove('unseen_count');
|
$rc->session->remove('unseen_count');
|
||||||
|
|
||||||
// Reset baseline for the target account so delta goes back to 0
|
// Reset baseline for the target account so delta goes back to 0
|
||||||
$this->reset_baseline($identId === -1 ? 0 : null, $rc, $identId);
|
$this->reset_baseline($identId === -1 ? 0 : null, $rc, $identId);
|
||||||
|
|
||||||
if ($identId === -1) {
|
if ($identId === -1) {
|
||||||
// Switch to main account
|
// Switch to main account
|
||||||
ident_switch::write_log('Switching mailbox back to default.');
|
ident_switch::write_log('Switching mailbox back to default.');
|
||||||
|
|
||||||
// Restore everything with STORAGE*my_postfix
|
// Restore everything with STORAGE*my_postfix
|
||||||
foreach ($_SESSION as $k => $v) {
|
foreach ($_SESSION as $k => $v) {
|
||||||
if (str_starts_with(strtolower($k), 'storage') && str_ends_with($k, ident_switch::MY_POSTFIX)) {
|
if (str_starts_with(strtolower($k), 'storage') && str_ends_with($k, ident_switch::MY_POSTFIX)) {
|
||||||
$realKey = substr($k, 0, -$my_postfix_len);
|
$realKey = substr($k, 0, -$my_postfix_len);
|
||||||
$_SESSION[$realKey] = $_SESSION[$k];
|
$_SESSION[$realKey] = $_SESSION[$k];
|
||||||
$rc->session->remove($k);
|
$rc->session->remove($k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$_SESSION['imap_delimiter'] = $_SESSION['imap_delimiter' . ident_switch::MY_POSTFIX] ?? null;
|
$_SESSION['imap_delimiter'] = $_SESSION['imap_delimiter' . ident_switch::MY_POSTFIX] ?? null;
|
||||||
$_SESSION['username'] = $rc->user->data['username'];
|
$_SESSION['username'] = $rc->user->data['username'];
|
||||||
$_SESSION['password'] = $_SESSION['password' . ident_switch::MY_POSTFIX];
|
$_SESSION['password'] = $_SESSION['password' . ident_switch::MY_POSTFIX];
|
||||||
$_SESSION['iid' . ident_switch::MY_POSTFIX] = -1;
|
$_SESSION['iid' . ident_switch::MY_POSTFIX] = -1;
|
||||||
|
|
||||||
foreach (rcube_storage::$folder_types as $type) {
|
foreach (rcube_storage::$folder_types as $type) {
|
||||||
$otherKey = $type . '_mbox' . ident_switch::MY_POSTFIX;
|
$otherKey = $type . '_mbox' . ident_switch::MY_POSTFIX;
|
||||||
if (isset($_SESSION[$otherKey])) {
|
if (isset($_SESSION[$otherKey])) {
|
||||||
$rc->session->remove($otherKey);
|
$rc->session->remove($otherKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$sql = 'SELECT imap_host, flags, imap_port, imap_delimiter, drafts_mbox, sent_mbox, junk_mbox, trash_mbox, username, password, iid FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' WHERE id = ? AND user_id = ?';
|
$sql = 'SELECT imap_host, flags, imap_port, imap_delimiter, drafts_mbox, sent_mbox, junk_mbox, trash_mbox, username, password, iid FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' WHERE id = ? AND user_id = ?';
|
||||||
$q = $rc->db->query($sql, $identId, $rc->user->ID);
|
$q = $rc->db->query($sql, $identId, $rc->user->ID);
|
||||||
$r = $rc->db->fetch_assoc($q);
|
$r = $rc->db->fetch_assoc($q);
|
||||||
if (is_array($r)) {
|
if (is_array($r)) {
|
||||||
$r['username'] = ident_switch::resolve_username((int)$r['iid'], $r['username']);
|
$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']}').");
|
ident_switch::write_log("Switching mailbox to one for identity with ID = {$r['iid']} (username = '{$r['username']}').");
|
||||||
|
|
||||||
if ($_SESSION['username'] === $rc->user->data['username']) {
|
if ($_SESSION['username'] === $rc->user->data['username']) {
|
||||||
// If we are in default account now - save values
|
// If we are in default account now - save values
|
||||||
foreach ($_SESSION as $k => $v) {
|
foreach ($_SESSION as $k => $v) {
|
||||||
if (str_starts_with(strtolower($k), 'storage') && !str_ends_with($k, ident_switch::MY_POSTFIX)) {
|
if (str_starts_with(strtolower($k), 'storage') && !str_ends_with($k, ident_switch::MY_POSTFIX)) {
|
||||||
if (!isset($_SESSION[$k . ident_switch::MY_POSTFIX])) {
|
if (!isset($_SESSION[$k . ident_switch::MY_POSTFIX])) {
|
||||||
$_SESSION[$k . ident_switch::MY_POSTFIX] = $_SESSION[$k];
|
$_SESSION[$k . ident_switch::MY_POSTFIX] = $_SESSION[$k];
|
||||||
}
|
}
|
||||||
$rc->session->remove($k);
|
$rc->session->remove($k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (['password', 'imap_delimiter'] as $k) {
|
foreach (['password', 'imap_delimiter'] as $k) {
|
||||||
if (!isset($_SESSION[$k . ident_switch::MY_POSTFIX])) {
|
if (!isset($_SESSION[$k . ident_switch::MY_POSTFIX])) {
|
||||||
$_SESSION[$k . ident_switch::MY_POSTFIX] = $_SESSION[$k];
|
$_SESSION[$k . ident_switch::MY_POSTFIX] = $_SESSION[$k];
|
||||||
}
|
}
|
||||||
$rc->session->remove($k);
|
$rc->session->remove($k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$parsed = ident_switch::parse_host_scheme($r['imap_host'] ?: 'localhost');
|
$parsed = ident_switch::parse_host_scheme($r['imap_host'] ?: 'localhost');
|
||||||
$host = $parsed['host'];
|
$host = $parsed['host'];
|
||||||
$ssl = $parsed['scheme'] ?: null;
|
$ssl = $parsed['scheme'] ?: null;
|
||||||
|
|
||||||
if (!$ssl && ($r['flags'] & ident_switch::DB_SECURE_IMAP_TLS)) {
|
if (!$ssl && ($r['flags'] & ident_switch::DB_SECURE_IMAP_TLS)) {
|
||||||
$ssl = 'tls'; // Backward compat: old records without scheme in host
|
$ssl = 'tls'; // Backward compat: old records without scheme in host
|
||||||
}
|
}
|
||||||
|
|
||||||
$def_port = ($ssl === 'ssl') ? 993 : 143;
|
$def_port = ($ssl === 'ssl') ? 993 : 143;
|
||||||
$port = $r['imap_port'] ?: $def_port;
|
$port = $r['imap_port'] ?: $def_port;
|
||||||
|
|
||||||
$delimiter = $r['imap_delimiter'] ?: null;
|
$delimiter = $r['imap_delimiter'] ?: null;
|
||||||
|
|
||||||
$_SESSION['storage_host'] = $host;
|
$_SESSION['storage_host'] = $host;
|
||||||
$_SESSION['storage_ssl'] = $ssl;
|
$_SESSION['storage_ssl'] = $ssl;
|
||||||
$_SESSION['storage_port'] = $port;
|
$_SESSION['storage_port'] = $port;
|
||||||
$_SESSION['imap_delimiter'] = $delimiter;
|
$_SESSION['imap_delimiter'] = $delimiter;
|
||||||
$_SESSION['username'] = $r['username'];
|
$_SESSION['username'] = $r['username'];
|
||||||
$_SESSION['password'] = $r['password'];
|
$_SESSION['password'] = $r['password'];
|
||||||
$_SESSION['iid' . ident_switch::MY_POSTFIX] = $r['iid'];
|
$_SESSION['iid' . ident_switch::MY_POSTFIX] = $r['iid'];
|
||||||
|
|
||||||
foreach (rcube_storage::$folder_types as $type) {
|
foreach (rcube_storage::$folder_types as $type) {
|
||||||
if (!empty($r[$type . '_mbox'])) {
|
if (!empty($r[$type . '_mbox'])) {
|
||||||
$otherKey = $type . '_mbox' . ident_switch::MY_POSTFIX;
|
$otherKey = $type . '_mbox' . ident_switch::MY_POSTFIX;
|
||||||
$_SESSION[$otherKey] = $r[$type . '_mbox'];
|
$_SESSION[$otherKey] = $r[$type . '_mbox'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ident_switch::write_log("Requested remote mailbox with ID = {$identId} not found.");
|
ident_switch::write_log("Requested remote mailbox with ID = {$identId} not found.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$rc->output->redirect([
|
$rc->output->redirect([
|
||||||
'_task' => 'mail',
|
'_task' => 'mail',
|
||||||
'_mbox' => 'INBOX',
|
'_mbox' => 'INBOX',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle smtp_connect hook: configure SMTP settings for the active account.
|
* Handle smtp_connect hook: configure SMTP settings for the active account.
|
||||||
*
|
*
|
||||||
* Loads SMTP host, port, credentials, and TLS settings from the database
|
* Loads SMTP host, port, credentials, and TLS settings from the database
|
||||||
* for the currently selected identity.
|
* for the currently selected identity.
|
||||||
*
|
*
|
||||||
* @param array $args Hook arguments containing SMTP connection parameters.
|
* @param array $args Hook arguments containing SMTP connection parameters.
|
||||||
* @return array Modified hook arguments with updated SMTP settings.
|
* @return array Modified hook arguments with updated SMTP settings.
|
||||||
*/
|
*/
|
||||||
public function configure_smtp(array $args): array
|
public function configure_smtp(array $args): array
|
||||||
{
|
{
|
||||||
$iid = $_SESSION['iid' . ident_switch::MY_POSTFIX] ?? null;
|
$iid = $_SESSION['iid' . ident_switch::MY_POSTFIX] ?? null;
|
||||||
if (!is_numeric($iid) || (int)$iid === -1) {
|
if (!is_numeric($iid) || (int)$iid === -1) {
|
||||||
ident_switch::debug_log('SMTP: no active switch, resolving from _from header');
|
ident_switch::debug_log('SMTP: no active switch, resolving from _from header');
|
||||||
$requestFrom = rcube_utils::get_input_value('_from', rcube_utils::INPUT_POST);
|
$requestFrom = rcube_utils::get_input_value('_from', rcube_utils::INPUT_POST);
|
||||||
if (empty($requestFrom)) {
|
if (empty($requestFrom)) {
|
||||||
ident_switch::debug_log('SMTP: no _from parameter, using default config');
|
ident_switch::debug_log('SMTP: no _from parameter, using default config');
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
$iid = intval($requestFrom);
|
$iid = intval($requestFrom);
|
||||||
if ($iid === 0) {
|
if ($iid === 0) {
|
||||||
ident_switch::debug_log('SMTP: _from is not an integer, using default config');
|
ident_switch::debug_log('SMTP: _from is not an integer, using default config');
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$rc = rcmail::get_instance();
|
$rc = rcmail::get_instance();
|
||||||
|
|
||||||
$sql = 'SELECT parent_id, smtp_host, smtp_port, username, smtp_auth, smtp_username, smtp_password, password, iid FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' WHERE iid = ? AND user_id = ?';
|
$sql = 'SELECT parent_id, smtp_host, smtp_port, username, smtp_auth, smtp_username, smtp_password, password, iid FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' WHERE iid = ? AND user_id = ?';
|
||||||
$q = $rc->db->query($sql, $iid, $rc->user->ID);
|
$q = $rc->db->query($sql, $iid, $rc->user->ID);
|
||||||
$r = $rc->db->fetch_assoc($q);
|
$r = $rc->db->fetch_assoc($q);
|
||||||
if (is_array($r)) {
|
if (is_array($r)) {
|
||||||
// If this is an alias, follow parent_id to get the parent's SMTP config
|
// If this is an alias, follow parent_id to get the parent's SMTP config
|
||||||
if (!empty($r['parent_id'])) {
|
if (!empty($r['parent_id'])) {
|
||||||
ident_switch::debug_log("SMTP: identity {$iid} is alias, following parent_id={$r['parent_id']}");
|
ident_switch::debug_log("SMTP: identity {$iid} is alias, following parent_id={$r['parent_id']}");
|
||||||
$sql = 'SELECT smtp_host, smtp_port, username, smtp_auth, smtp_username, smtp_password, password, iid FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' WHERE id = ? AND user_id = ?';
|
$sql = 'SELECT smtp_host, smtp_port, username, smtp_auth, smtp_username, smtp_password, password, iid FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' WHERE id = ? AND user_id = ?';
|
||||||
$q = $rc->db->query($sql, $r['parent_id'], $rc->user->ID);
|
$q = $rc->db->query($sql, $r['parent_id'], $rc->user->ID);
|
||||||
$r = $rc->db->fetch_assoc($q);
|
$r = $rc->db->fetch_assoc($q);
|
||||||
if (!is_array($r)) {
|
if (!is_array($r)) {
|
||||||
ident_switch::debug_log("SMTP: parent account not found, using default config");
|
ident_switch::debug_log("SMTP: parent account not found, using default config");
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
$iid = $r['iid'];
|
$iid = $r['iid'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$r['username'] = ident_switch::resolve_username($iid, $r['username']);
|
$r['username'] = ident_switch::resolve_username($iid, $r['username']);
|
||||||
|
|
||||||
$authMode = (int)$r['smtp_auth'];
|
$authMode = (int)$r['smtp_auth'];
|
||||||
if ($authMode === ident_switch::SMTP_AUTH_CUSTOM) {
|
if ($authMode === ident_switch::SMTP_AUTH_CUSTOM) {
|
||||||
$args['smtp_user'] = $r['smtp_username'] ?: '';
|
$args['smtp_user'] = $r['smtp_username'] ?: '';
|
||||||
$args['smtp_pass'] = $r['smtp_password'] ? ($rc->decrypt($r['smtp_password']) ?: '') : '';
|
$args['smtp_pass'] = $r['smtp_password'] ? ($rc->decrypt($r['smtp_password']) ?: '') : '';
|
||||||
} elseif ($authMode === ident_switch::SMTP_AUTH_IMAP) {
|
} elseif ($authMode === ident_switch::SMTP_AUTH_IMAP) {
|
||||||
$args['smtp_user'] = $r['username'];
|
$args['smtp_user'] = $r['username'];
|
||||||
$args['smtp_pass'] = $rc->decrypt($r['password']) ?: '';
|
$args['smtp_pass'] = $rc->decrypt($r['password']) ?: '';
|
||||||
} else {
|
} else {
|
||||||
$args['smtp_user'] = '';
|
$args['smtp_user'] = '';
|
||||||
$args['smtp_pass'] = '';
|
$args['smtp_pass'] = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Host already contains scheme (ssl:// or tls://) from form
|
// Host already contains scheme (ssl:// or tls://) from form
|
||||||
$smtpHost = $r['smtp_host'] ?: 'localhost';
|
$smtpHost = $r['smtp_host'] ?: 'localhost';
|
||||||
$smtpPort = $r['smtp_port'] ?: 587;
|
$smtpPort = $r['smtp_port'] ?: 587;
|
||||||
$args['smtp_host'] = $smtpHost . ':' . $smtpPort;
|
$args['smtp_host'] = $smtpHost . ':' . $smtpPort;
|
||||||
|
|
||||||
$authLabel = match ($authMode) {
|
$authLabel = match ($authMode) {
|
||||||
ident_switch::SMTP_AUTH_IMAP => 'imap',
|
ident_switch::SMTP_AUTH_IMAP => 'imap',
|
||||||
ident_switch::SMTP_AUTH_NONE => 'none',
|
ident_switch::SMTP_AUTH_NONE => 'none',
|
||||||
ident_switch::SMTP_AUTH_CUSTOM => 'custom',
|
ident_switch::SMTP_AUTH_CUSTOM => 'custom',
|
||||||
default => "unknown({$authMode})",
|
default => "unknown({$authMode})",
|
||||||
};
|
};
|
||||||
ident_switch::debug_log("SMTP: iid={$iid}, host={$args['smtp_host']}, user={$args['smtp_user']}, auth={$authLabel}");
|
ident_switch::debug_log("SMTP: iid={$iid}, host={$args['smtp_host']}, user={$args['smtp_user']}, auth={$authLabel}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle managesieve_connect hook: configure Sieve settings for the active account.
|
* Handle managesieve_connect hook: configure Sieve settings for the active account.
|
||||||
*
|
*
|
||||||
* Loads Sieve host, port, and credentials from the database
|
* Loads Sieve host, port, and credentials from the database
|
||||||
* for the currently selected identity.
|
* for the currently selected identity.
|
||||||
*
|
*
|
||||||
* @param array $args Hook arguments containing Sieve connection parameters.
|
* @param array $args Hook arguments containing Sieve connection parameters.
|
||||||
* @return array Modified hook arguments with updated Sieve settings.
|
* @return array Modified hook arguments with updated Sieve settings.
|
||||||
*/
|
*/
|
||||||
public function configure_managesieve(array $args): array
|
public function configure_managesieve(array $args): array
|
||||||
{
|
{
|
||||||
$iid = $_SESSION['iid' . ident_switch::MY_POSTFIX] ?? null;
|
$iid = $_SESSION['iid' . ident_switch::MY_POSTFIX] ?? null;
|
||||||
if (!is_numeric($iid) || (int)$iid === -1) {
|
if (!is_numeric($iid) || (int)$iid === -1) {
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
$rc = rcmail::get_instance();
|
$rc = rcmail::get_instance();
|
||||||
|
|
||||||
$sql = 'SELECT parent_id, sieve_host, sieve_port, sieve_auth, sieve_username, sieve_password, username, password, iid FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' WHERE iid = ? AND user_id = ?';
|
$sql = 'SELECT parent_id, sieve_host, sieve_port, sieve_auth, sieve_username, sieve_password, username, password, iid FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' WHERE iid = ? AND user_id = ?';
|
||||||
$q = $rc->db->query($sql, $iid, $rc->user->ID);
|
$q = $rc->db->query($sql, $iid, $rc->user->ID);
|
||||||
$r = $rc->db->fetch_assoc($q);
|
$r = $rc->db->fetch_assoc($q);
|
||||||
if (is_array($r)) {
|
if (is_array($r)) {
|
||||||
// If this is an alias, follow parent_id to get the parent's Sieve config
|
// If this is an alias, follow parent_id to get the parent's Sieve config
|
||||||
if (!empty($r['parent_id'])) {
|
if (!empty($r['parent_id'])) {
|
||||||
ident_switch::debug_log("Sieve: identity {$iid} is alias, following parent_id={$r['parent_id']}");
|
ident_switch::debug_log("Sieve: identity {$iid} is alias, following parent_id={$r['parent_id']}");
|
||||||
$sql = 'SELECT sieve_host, sieve_port, sieve_auth, sieve_username, sieve_password, username, password, iid FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' WHERE id = ? AND user_id = ?';
|
$sql = 'SELECT sieve_host, sieve_port, sieve_auth, sieve_username, sieve_password, username, password, iid FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' WHERE id = ? AND user_id = ?';
|
||||||
$q = $rc->db->query($sql, $r['parent_id'], $rc->user->ID);
|
$q = $rc->db->query($sql, $r['parent_id'], $rc->user->ID);
|
||||||
$r = $rc->db->fetch_assoc($q);
|
$r = $rc->db->fetch_assoc($q);
|
||||||
if (!is_array($r)) {
|
if (!is_array($r)) {
|
||||||
ident_switch::debug_log("Sieve: parent account not found, using default config");
|
ident_switch::debug_log("Sieve: parent account not found, using default config");
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
$iid = $r['iid'];
|
$iid = $r['iid'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($r['sieve_host'])) {
|
if (empty($r['sieve_host'])) {
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
$r['username'] = ident_switch::resolve_username($iid, $r['username']);
|
$r['username'] = ident_switch::resolve_username($iid, $r['username']);
|
||||||
|
|
||||||
$sieveHost = $r['sieve_host'];
|
$sieveHost = $r['sieve_host'];
|
||||||
$sievePort = $r['sieve_port'] ?: 4190;
|
$sievePort = $r['sieve_port'] ?: 4190;
|
||||||
$args['host'] = $sieveHost . ':' . $sievePort;
|
$args['host'] = $sieveHost . ':' . $sievePort;
|
||||||
|
|
||||||
$authMode = (int)$r['sieve_auth'];
|
$authMode = (int)$r['sieve_auth'];
|
||||||
if ($authMode === ident_switch::SIEVE_AUTH_CUSTOM) {
|
if ($authMode === ident_switch::SIEVE_AUTH_CUSTOM) {
|
||||||
$args['user'] = $r['sieve_username'] ?: '';
|
$args['user'] = $r['sieve_username'] ?: '';
|
||||||
$args['password'] = $r['sieve_password'] ? ($rc->decrypt($r['sieve_password']) ?: '') : '';
|
$args['password'] = $r['sieve_password'] ? ($rc->decrypt($r['sieve_password']) ?: '') : '';
|
||||||
} elseif ($authMode === ident_switch::SIEVE_AUTH_IMAP) {
|
} elseif ($authMode === ident_switch::SIEVE_AUTH_IMAP) {
|
||||||
$args['user'] = $r['username'];
|
$args['user'] = $r['username'];
|
||||||
$args['password'] = $rc->decrypt($r['password']) ?: '';
|
$args['password'] = $rc->decrypt($r['password']) ?: '';
|
||||||
} else {
|
} else {
|
||||||
$args['user'] = '';
|
$args['user'] = '';
|
||||||
$args['password'] = '';
|
$args['password'] = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
ident_switch::debug_log("Sieve: iid={$iid}, host={$args['host']}, user={$args['user']}");
|
ident_switch::debug_log("Sieve: iid={$iid}, host={$args['host']}, user={$args['user']}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle preferences_list hook: customize special folders form for remote accounts.
|
* Handle preferences_list hook: customize special folders form for remote accounts.
|
||||||
*
|
*
|
||||||
* When viewing folder preferences while impersonating, shows the remote account's
|
* When viewing folder preferences while impersonating, shows the remote account's
|
||||||
* special folder assignments instead of the default ones.
|
* special folder assignments instead of the default ones.
|
||||||
*
|
*
|
||||||
* @param array $args Hook arguments containing 'section' and 'blocks' with form data.
|
* @param array $args Hook arguments containing 'section' and 'blocks' with form data.
|
||||||
* @return array Modified hook arguments with updated folder selections.
|
* @return array Modified hook arguments with updated folder selections.
|
||||||
*/
|
*/
|
||||||
public function get_special_folders_form(array $args): array
|
public function get_special_folders_form(array $args): array
|
||||||
{
|
{
|
||||||
$rc = rcmail::get_instance();
|
$rc = rcmail::get_instance();
|
||||||
|
|
||||||
if ($args['section'] === 'folders'
|
if (
|
||||||
&& strcasecmp($rc->user->data['username'], $_SESSION['username']) !== 0
|
$args['section'] === 'folders'
|
||||||
) {
|
&& strcasecmp($rc->user->data['username'], $_SESSION['username']) !== 0
|
||||||
$no_override = array_flip((array)$rc->config->get('dont_override'));
|
) {
|
||||||
$onchange = "if ($(this).val() == 'INBOX') $(this).val('')";
|
$no_override = array_flip((array)$rc->config->get('dont_override'));
|
||||||
$select = $rc->folder_selector([
|
$onchange = "if ($(this).val() == 'INBOX') $(this).val('')";
|
||||||
'noselection' => '---',
|
$select = $rc->folder_selector([
|
||||||
'realnames' => true,
|
'noselection' => '---',
|
||||||
'maxlength' => 30,
|
'realnames' => true,
|
||||||
'folder_filter' => 'mail',
|
'maxlength' => 30,
|
||||||
'folder_rights' => 'w',
|
'folder_filter' => 'mail',
|
||||||
]);
|
'folder_rights' => 'w',
|
||||||
|
]);
|
||||||
|
|
||||||
$sql = 'SELECT label FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' WHERE iid = ? AND user_id = ?';
|
$sql = 'SELECT label FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' WHERE iid = ? AND user_id = ?';
|
||||||
$q = $rc->db->query($sql, $_SESSION['iid' . ident_switch::MY_POSTFIX], $rc->user->ID);
|
$q = $rc->db->query($sql, $_SESSION['iid' . ident_switch::MY_POSTFIX], $rc->user->ID);
|
||||||
$r = $rc->db->fetch_assoc($q);
|
$r = $rc->db->fetch_assoc($q);
|
||||||
$args['blocks']['main']['name'] .= ' (' . ($r['label'] ? rcube::Q($rc->gettext('server')) . ': ' . rcube::Q($r['label']) : 'remote') . ')';
|
$args['blocks']['main']['name'] .= ' (' . ($r['label'] ? rcube::Q($rc->gettext('server')) . ': ' . rcube::Q($r['label']) : 'remote') . ')';
|
||||||
|
|
||||||
foreach (rcube_storage::$folder_types as $type) {
|
foreach (rcube_storage::$folder_types as $type) {
|
||||||
if (isset($no_override[$type . '_mbox'])) {
|
if (isset($no_override[$type . '_mbox'])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$defaultKey = $type . '_mbox_default' . ident_switch::MY_POSTFIX;
|
$defaultKey = $type . '_mbox_default' . ident_switch::MY_POSTFIX;
|
||||||
$otherKey = $type . '_mbox' . ident_switch::MY_POSTFIX;
|
$otherKey = $type . '_mbox' . ident_switch::MY_POSTFIX;
|
||||||
$selected = $_SESSION[$otherKey] ?? $_SESSION[$defaultKey] ?? '';
|
$selected = $_SESSION[$otherKey] ?? $_SESSION[$defaultKey] ?? '';
|
||||||
$attr = ['id' => '_' . $type . '_mbox', 'name' => '_' . $type . '_mbox', 'onchange' => $onchange];
|
$attr = ['id' => '_' . $type . '_mbox', 'name' => '_' . $type . '_mbox', 'onchange' => $onchange];
|
||||||
$args['blocks']['main']['options'][$type . '_mbox']['content'] = $select->show($selected, $attr);
|
$args['blocks']['main']['options'][$type . '_mbox']['content'] = $select->show($selected, $attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle preferences_save hook: persist special folder assignments for remote accounts.
|
* Handle preferences_save hook: persist special folder assignments for remote accounts.
|
||||||
*
|
*
|
||||||
* Saves folder preferences to the plugin's database table instead of the default
|
* Saves folder preferences to the plugin's database table instead of the default
|
||||||
* Roundcube preferences when impersonating a remote account.
|
* Roundcube preferences when impersonating a remote account.
|
||||||
*
|
*
|
||||||
* @param array $args Hook arguments containing 'section' and 'prefs' with folder data.
|
* @param array $args Hook arguments containing 'section' and 'prefs' with folder data.
|
||||||
* @return array Modified hook arguments, with 'abort' set to prevent default save.
|
* @return array Modified hook arguments, with 'abort' set to prevent default save.
|
||||||
*/
|
*/
|
||||||
public function save_special_folders(array $args): array
|
public function save_special_folders(array $args): array
|
||||||
{
|
{
|
||||||
$rc = rcmail::get_instance();
|
$rc = rcmail::get_instance();
|
||||||
|
|
||||||
if ($args['section'] === 'folders'
|
if (
|
||||||
&& strcasecmp($rc->user->data['username'], $_SESSION['username']) !== 0
|
$args['section'] === 'folders'
|
||||||
) {
|
&& strcasecmp($rc->user->data['username'], $_SESSION['username']) !== 0
|
||||||
$sql = 'SELECT id FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' WHERE iid = ? AND user_id = ?';
|
) {
|
||||||
$q = $rc->db->query($sql, $_SESSION['iid' . ident_switch::MY_POSTFIX], $rc->user->ID);
|
$sql = 'SELECT id FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' WHERE iid = ? AND user_id = ?';
|
||||||
$r = $rc->db->fetch_assoc($q);
|
$q = $rc->db->query($sql, $_SESSION['iid' . ident_switch::MY_POSTFIX], $rc->user->ID);
|
||||||
if ($r) {
|
$r = $rc->db->fetch_assoc($q);
|
||||||
$sql = 'UPDATE ' .
|
if ($r) {
|
||||||
$rc->db->table_name(ident_switch::TABLE) .
|
$sql = 'UPDATE ' .
|
||||||
' SET drafts_mbox = ?, sent_mbox = ?, junk_mbox = ?, trash_mbox = ?' .
|
$rc->db->table_name(ident_switch::TABLE) .
|
||||||
' WHERE id = ?';
|
' SET drafts_mbox = ?, sent_mbox = ?, junk_mbox = ?, trash_mbox = ?' .
|
||||||
|
' WHERE id = ?';
|
||||||
|
|
||||||
$rc->db->query(
|
$rc->db->query(
|
||||||
$sql,
|
$sql,
|
||||||
$args['prefs']['drafts_mbox'],
|
$args['prefs']['drafts_mbox'],
|
||||||
$args['prefs']['sent_mbox'],
|
$args['prefs']['sent_mbox'],
|
||||||
$args['prefs']['junk_mbox'],
|
$args['prefs']['junk_mbox'],
|
||||||
$args['prefs']['trash_mbox'],
|
$args['prefs']['trash_mbox'],
|
||||||
$r['id']
|
$r['id']
|
||||||
);
|
);
|
||||||
|
|
||||||
// Abort to prevent RC from saving prefs to default storage
|
// Abort to prevent RC from saving prefs to default storage
|
||||||
$args['abort'] = true;
|
$args['abort'] = true;
|
||||||
$args['result'] = true;
|
$args['result'] = true;
|
||||||
|
|
||||||
foreach (rcube_storage::$folder_types as $type) {
|
foreach (rcube_storage::$folder_types as $type) {
|
||||||
if (!empty($args['prefs'][$type . '_mbox'])) {
|
if (!empty($args['prefs'][$type . '_mbox'])) {
|
||||||
$otherKey = $type . '_mbox' . ident_switch::MY_POSTFIX;
|
$otherKey = $type . '_mbox' . ident_switch::MY_POSTFIX;
|
||||||
$_SESSION[$otherKey] = $args['prefs'][$type . '_mbox'];
|
$_SESSION[$otherKey] = $args['prefs'][$type . '_mbox'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
$args['abort'] = true;
|
$args['abort'] = true;
|
||||||
$args['result'] = false;
|
$args['result'] = false;
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (rcube_storage::$folder_types as $type) {
|
foreach (rcube_storage::$folder_types as $type) {
|
||||||
if (!empty($args['prefs'][$type . '_mbox'])) {
|
if (!empty($args['prefs'][$type . '_mbox'])) {
|
||||||
$key = $type . '_mbox_default' . ident_switch::MY_POSTFIX;
|
$key = $type . '_mbox_default' . ident_switch::MY_POSTFIX;
|
||||||
$_SESSION[$key] = $args['prefs'][$type . '_mbox'];
|
$_SESSION[$key] = $args['prefs'][$type . '_mbox'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the baseline for a target account so delta display resets to 0.
|
* Reset the baseline for a target account so delta display resets to 0.
|
||||||
*
|
*
|
||||||
* For primary account (identId=-1), iid is 0.
|
* For primary account (identId=-1), iid is 0.
|
||||||
* For secondary accounts, look up iid from the ident_switch table.
|
* For secondary accounts, look up iid from the ident_switch table.
|
||||||
*
|
*
|
||||||
* @param int|null $iid Known iid (0 for primary), or null to look up.
|
* @param integer|null $iid Known iid (0 for primary), or null to look up.
|
||||||
* @param rcmail $rc Roundcube instance.
|
* @param rcmail $rc Roundcube instance.
|
||||||
* @param mixed $identId The ident_switch.id value for secondary accounts.
|
* @param mixed $identId The ident_switch.id value for secondary accounts.
|
||||||
*/
|
*/
|
||||||
private function reset_baseline(?int $iid, rcmail $rc, mixed $identId): void
|
private function reset_baseline(?int $iid, rcmail $rc, mixed $identId): void
|
||||||
{
|
{
|
||||||
if ($iid === null) {
|
if ($iid === null) {
|
||||||
// Look up iid from ident_switch table for secondary account
|
// Look up iid from ident_switch table for secondary account
|
||||||
$sql = 'SELECT iid FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' WHERE id = ? AND user_id = ?';
|
$sql = 'SELECT iid FROM ' . $rc->db->table_name(ident_switch::TABLE) . ' WHERE id = ? AND user_id = ?';
|
||||||
$q = $rc->db->query($sql, $identId, $rc->user->ID);
|
$q = $rc->db->query($sql, $identId, $rc->user->ID);
|
||||||
$r = $rc->db->fetch_assoc($q);
|
$r = $rc->db->fetch_assoc($q);
|
||||||
if (!$r) {
|
if (!$r) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$iid = (int)$r['iid'];
|
$iid = (int)$r['iid'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$counts = $_SESSION['ident_switch_counts'] ?? [];
|
$counts = $_SESSION['ident_switch_counts'] ?? [];
|
||||||
if (isset($counts[$iid])) {
|
if (isset($counts[$iid])) {
|
||||||
unset($counts[$iid]['baseline']);
|
unset($counts[$iid]['baseline']);
|
||||||
$_SESSION['ident_switch_counts'] = $counts;
|
$_SESSION['ident_switch_counts'] = $counts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user