From a203a0d07fa0dfb74d9365ed5825df9352e4c1bf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=B4me=20Chilliet?= <come.chilliet@fusiondirectory.org>
Date: Thu, 6 May 2021 14:09:06 +0200
Subject: [PATCH] :ambulance: fix(zimbra) Correctly support quota from COS in
 zimbra plugin

issue #6104
---
 .../mail/class_MailQuotaAttribute.inc         | 21 ++++++--
 mail/personal/mail/class_mail-methods.inc     | 10 +++-
 mail/personal/mail/class_mailTabPlugin.inc    |  2 +-
 .../class_mail-methods-zimbra.inc             | 48 ++++++++++++++++++-
 .../personal/mail/mail-methods/zimbraSoap.php |  2 +-
 5 files changed, 73 insertions(+), 10 deletions(-)

diff --git a/mail/personal/mail/class_MailQuotaAttribute.inc b/mail/personal/mail/class_MailQuotaAttribute.inc
index bdf9b8fec3..a8191086b5 100644
--- a/mail/personal/mail/class_MailQuotaAttribute.inc
+++ b/mail/personal/mail/class_MailQuotaAttribute.inc
@@ -21,7 +21,16 @@
 
 class MailQuotaAttribute extends UnitIntAttribute
 {
+  /**
+   * @var int Quota usage in MiB, -1 if unknown
+   */
   private $quotaUsage;
+  /**
+   * @var string Quota limit in MiB, empty string if unlimited
+   *
+   * The same as $this->value, unless there is an inherited group limit
+   */
+  private $quotaLimit;
 
   function __construct ($label, $description, $ldapName, $required, $min = FALSE, $max = FALSE, $defaultValue = "", $acl = "")
   {
@@ -39,6 +48,7 @@ class MailQuotaAttribute extends UnitIntAttribute
       /* Read quota */
       $this->setValue((string) $mailMethod->getQuota($this->getValue()));
       $this->quotaUsage = $mailMethod->getQuotaUsage();
+      $this->quotaLimit = $mailMethod->getQuotaLimit($this->getValue());
     } catch (MailMethodError $e) {
       $error = new SimplePluginError(
         $this,
@@ -60,7 +70,7 @@ class MailQuotaAttribute extends UnitIntAttribute
       'htmlid'        => $this->getHtmlId().'_usage',
       'label'         => '{literal}'._('Quota usage').'{/literal}',
       'description'   => _('Part of the quota which is used'),
-      'input'         => static::quotaToImage($this->quotaUsage, $this->getValue()),
+      'input'         => static::quotaToImage($this->quotaUsage, $this->quotaLimit),
       'subattribute'  => FALSE,
       'required'      => FALSE,
       'readable'      => $readable,
@@ -68,15 +78,16 @@ class MailQuotaAttribute extends UnitIntAttribute
     ];
   }
 
-  static function quotaToImage ($use, $quota): string
+  static function quotaToImage (int $use, string $quota): string
   {
     if ($use == -1) {
-      return '&nbsp;&nbsp;'._('Unknown');
+      return '&nbsp;&nbsp;'.htmlescape(_('Unknown'));
     } elseif (empty($quota)) {
-      return '&nbsp;&nbsp;'._('Unlimited');
+      return '&nbsp;&nbsp;'.htmlescape(sprintf(_('Unlimited (%dMiB used)'), $use));
     } else {
       $usage = round(($use / $quota) * 100);
-      return '<img src="progress.php?x=100&amp;y=17&amp;p='.$usage.'" alt="'.$usage.'%"/>';
+      $alt = htmlescape(sprintf(_('%d%% (%dMiB)'), $usage, $use));
+      return '<img src="progress.php?x=100&amp;y=17&amp;p='.$usage.'" alt="'.$alt.'" title="'.$alt.'"/>';
     }
   }
 }
diff --git a/mail/personal/mail/class_mail-methods.inc b/mail/personal/mail/class_mail-methods.inc
index a8d6510a87..a2e39198af 100644
--- a/mail/personal/mail/class_mail-methods.inc
+++ b/mail/personal/mail/class_mail-methods.inc
@@ -269,7 +269,7 @@ class mailMethod
     return -1;
   }
 
-  /*! \brief  Returns the quota restrictions.
+  /*! \brief  Returns the quota restrictions specific to this user.
       @return string quota value, numeric string or empty string
    */
   public function getQuota (string $quotaValue): string
@@ -277,6 +277,14 @@ class mailMethod
     return $quotaValue;
   }
 
+  /*! \brief  Returns the quota restrictions specific or inherited by this user.
+      @return string quota value, numeric string or empty string
+   */
+  public function getQuotaLimit (string $quotaValue): string
+  {
+    return $quotaValue;
+  }
+
   /*! \brief  Sets the mail quota
    */
   public function setQuota (string $number)
diff --git a/mail/personal/mail/class_mailTabPlugin.inc b/mail/personal/mail/class_mailTabPlugin.inc
index 192355c07f..64ba695e02 100644
--- a/mail/personal/mail/class_mailTabPlugin.inc
+++ b/mail/personal/mail/class_mailTabPlugin.inc
@@ -70,7 +70,7 @@ class mailTabPlugin extends simplePlugin
 
   public function mailServerChanged ()
   {
-    $this->mailMethod = mailMethod::getInstanceFromServer($this->gosaMailServer, $this);
+    $this->mailMethod = mailMethod::getInstanceFromServer($this->attributesAccess[$this->serverAttr]->getValue(), $this);
     if ($this->initialMailMethod === NULL) {
       $this->initialMailMethod = $this->mailMethod;
     }
diff --git a/zimbra/personal/mail/mail-methods/class_mail-methods-zimbra.inc b/zimbra/personal/mail/mail-methods/class_mail-methods-zimbra.inc
index f63c534ba6..6a358f5068 100644
--- a/zimbra/personal/mail/mail-methods/class_mail-methods-zimbra.inc
+++ b/zimbra/personal/mail/mail-methods/class_mail-methods-zimbra.inc
@@ -682,8 +682,11 @@ class mailMethodZimbra extends mailMethod
   public function getQuota (string $quotaValue): string
   {
     if ($this->cacheAccount()) {
-      /* Server sends quota in bytes */
-      if (isset($this->cachedAccount['account']['zimbraMailQuota']) && is_numeric($this->cachedAccount['account']['zimbraMailQuota'])) {
+      if (
+        isset($this->cachedAccount['account']['zimbraMailQuota']) &&
+        is_numeric($this->cachedAccount['account']['zimbraMailQuota'])
+      ) {
+        /* Server sends quota in bytes */
         return (string)floor($this->cachedAccount['account']['zimbraMailQuota'] / (1024 * 1024));
       } else {
         return '';
@@ -692,6 +695,35 @@ class mailMethodZimbra extends mailMethod
     return $quotaValue;
   }
 
+  /*! \brief  Returns the quota restrictions specific or inherited by this user.
+      @return string quota value, numeric string or empty string
+   */
+  public function getQuotaLimit (string $quotaValue): string
+  {
+    if (empty($quotaValue) && $this->cacheAccount()) {
+      if (
+        isset($this->cachedAccount['account']['zimbraCOSId']) &&
+        ($this->cachedAccount['account']['zimbraCOSId'] !== '')
+      ) {
+        $cosOptions = $this->getCosOptions();
+        foreach ($cosOptions as $cosOption) {
+          if ($cosOption['id'] === $this->cachedAccount['account']['zimbraCOSId']) {
+            if (
+              isset($cosOption['attributes']['zimbraMailQuota']) &&
+              is_numeric($cosOption['attributes']['zimbraMailQuota']) &&
+              ($cosOption['attributes']['zimbraMailQuota'] > 0)
+            ) {
+              /* Server sends quota in bytes */
+              return (string)floor($cosOption['attributes']['zimbraMailQuota'] / (1024 * 1024));
+            }
+            break;
+          }
+        }
+      }
+    }
+    return $quotaValue;
+  }
+
   public function additionalAttributes (string $acl): array
   {
     $attributes = [];
@@ -716,6 +748,18 @@ class mailMethodZimbra extends mailMethod
           (isset($this->cachedAccount['account']['zimbraAccountStatus']) ? $this->cachedAccount['account']['zimbraAccountStatus'] : _('Unknown')),
           $acl
         );
+        $cosLimit = $this->getQuotaLimit('');
+        if ($cosLimit !== '') {
+          array_unshift(
+            $attributes,
+            new DisplayAttribute(
+              _('COS quota'), _('Quota limit set in the class of service'),
+              'zimbraCOSQuota', FALSE,
+              sprintf(_('%sMiB'), $cosLimit),
+              $acl
+            )
+          );
+        }
       }
       $cosOptions = $this->getCosOptions();
       $choices  = [];
diff --git a/zimbra/personal/mail/mail-methods/zimbraSoap.php b/zimbra/personal/mail/mail-methods/zimbraSoap.php
index 92be3b1cf6..fabc24ef79 100644
--- a/zimbra/personal/mail/mail-methods/zimbraSoap.php
+++ b/zimbra/personal/mail/mail-methods/zimbraSoap.php
@@ -390,7 +390,7 @@ class getAllCosResponse extends Response {
   {
     return array_map(
       function($cos) {
-        return ['id' => $cos->id, 'name' => $cos->name];
+        return ['id' => $cos->id, 'name' => $cos->name, 'attributes' => static::attributesListToArray($cos->a)];
       },
       $this->cos
     );
-- 
GitLab