From 0f8a2668fb84d3210c238e8d45de501031f07ac0 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Wed, 22 Jul 2020 17:01:19 +0200 Subject: [PATCH] fix token was only updated on account-change, not new login or daily token rotation, also support now multiple tokens/instances registring tokens for same account --- api/src/Mail/Imap/Dovecot.php | 44 ++++++++++++++++++++++++++++++---- mail/inc/class.mail_ui.inc.php | 12 +++++----- mail/js/app.js | 4 ++++ 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/api/src/Mail/Imap/Dovecot.php b/api/src/Mail/Imap/Dovecot.php index 302d4a7dbc..0d78d3f347 100644 --- a/api/src/Mail/Imap/Dovecot.php +++ b/api/src/Mail/Imap/Dovecot.php @@ -289,6 +289,25 @@ class Dovecot extends Mail\Imap implements Mail\Imap\PushIface const METADATA_NAME = '/private/vendor/vendor.dovecot/http-notify'; const METADATA_MAILBOX = ''; const METADATA_PREFIX = 'user='; + const METADATA_SEPARATOR = ';;'; + + /** + * Generate token / user-information for push to be stored by Dovecot + * + * The user informations has the form "$account_id::$acc_id;$token@$host" + * + * @param null $account_id + * @param string $token =null default push token of instance ($account_id=='0') or user + * @return string + * @throws Api\Exception\AssertionFailed + */ + protected function pushToken($account_id=null, $token=null) + { + if (!isset($token)) $token = ((string)$account_id === '0' ? Tokens::instance() : Tokens::user($account_id)); + + return self::METADATA_PREFIX.$GLOBALS['egw_info']['user']['account_id'].'::'.$this->acc_id.';'. + $token . '@' . 'office.egroupware.org'; //Api\Header\Http::host(); + } /** * Enable push notifictions for current connection and given account_id @@ -303,11 +322,25 @@ class Dovecot extends Mail\Imap implements Mail\Imap\PushIface return false; } try { + $metadata = explode(self::METADATA_SEPARATOR, $this->getMetadata(self::METADATA_MAILBOX, [self::METADATA_NAME])) ?: []; + $my_token = $this->pushToken($account_id); + $my_token_preg = '/^'.$this->pushToken($account_id, '[^@]+').'$/'; + foreach($metadata as $key => $token) + { + // token already registered --> we're done + if ($token === $my_token) return true; + + // check old/expired token registered --> remove it + if (preg_match($my_token_preg, $token)) + { + unset($metadata[$key]); + break; + } + } + // add my token and send it to Dovecot + $metadata[] = $my_token; $this->setMetadata(self::METADATA_MAILBOX, [ - self::METADATA_NAME => self::METADATA_PREFIX.$GLOBALS['egw_info']['user']['account_id'].'::'.$this->acc_id.';'. - $this->getMailBoxUserName($GLOBALS['egw_info']['user']['account_lid']) . ';' . - ((string)$account_id === '0' ? Tokens::instance() : Tokens::user($account_id)) . '@' . - Api\Header\Http::host(), + self::METADATA_NAME => implode(self::METADATA_SEPARATOR, $metadata), ]); } catch (Horde_Imap_Client_Exception $e) { @@ -318,8 +351,9 @@ class Dovecot extends Mail\Imap implements Mail\Imap\PushIface } /** - * Check if push is available / konfigured for given server + * Check if push is available / configured for given server * + * @todo add a switch to enable push in the profile or * @return bool */ function pushAvailable() diff --git a/mail/inc/class.mail_ui.inc.php b/mail/inc/class.mail_ui.inc.php index 0c3ff31b32..07cd978289 100644 --- a/mail/inc/class.mail_ui.inc.php +++ b/mail/inc/class.mail_ui.inc.php @@ -251,12 +251,6 @@ class mail_ui if ($oldicServerID != self::$icServerID) { $this->mail_bo->openConnection(self::$icServerID); - // enable push notifications, if supported (and konfigured) by the server - if ($this->mail_bo->icServer instanceof Api\Mail\Imap\PushIface && - $this->mail_bo->icServer->pushAvailable()) - { - $this->mail_bo->icServer->enablePush(); - } } if (true) $oldicServerID = self::$icServerID; if (!Mail::storeActiveProfileIDToPref($this->mail_bo->icServer, self::$icServerID, true )) @@ -1556,6 +1550,12 @@ class mail_ui } if (empty($query['selectedFolder'])) $query['selectedFolder'] = $mail_ui->mail_bo->profileID.self::$delimiter.'INBOX'; } + // enable push notifications, if supported (and konfigured) by the server + if ($mail_ui->mail_bo->icServer instanceof Api\Mail\Imap\PushIface && + $mail_ui->mail_bo->icServer->pushAvailable()) + { + $mail_ui->mail_bo->icServer->enablePush(); + } //error_log(__METHOD__.__LINE__.' SelectedFolder:'.$query['selectedFolder'].' Start:'.$query['start'].' NumRows:'.$query['num_rows'].array2string($query['order']).'->'.array2string($query['sort'])); //Mail::$debugTimes=true; if (Mail::$debugTimes) $starttime = microtime(true); diff --git a/mail/js/app.js b/mail/js/app.js index 6d6bf4155a..ffb8f80a75 100644 --- a/mail/js/app.js +++ b/mail/js/app.js @@ -22,6 +22,10 @@ app.classes.mail = AppJS.extend( { appname: 'mail', + /** + * modified attribute in mail app to test new entries get added on top of list + */ + modification_field_name: 'date', /** * et2 widget container