git subrepo commit (merge) mailcow/src/mailcow-dockerized

subrepo: subdir:   "mailcow/src/mailcow-dockerized"
  merged:   "c7b1dc37"
upstream: origin:   "https://github.com/mailcow/mailcow-dockerized.git"
  branch:   "master"
  commit:   "a366494c"
git-subrepo: version:  "0.4.6"
  origin:   "???"
  commit:   "???"
Change-Id: Id574ecd4e02e3c4fbf8a1efd49be11c0b6d19a3f
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.mailbox.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.mailbox.inc.php
index d67fa3e..68cb50f 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.mailbox.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.mailbox.inc.php
@@ -1250,9 +1250,27 @@
             ));

           }

           else {

-            $stmt = $pdo->prepare("INSERT INTO `user_acl` (`username`) VALUES (:username)");

+            $stmt = $pdo->prepare("INSERT INTO `user_acl` 

+              (`username`, `spam_alias`, `tls_policy`, `spam_score`, `spam_policy`, `delimiter_action`, `syncjobs`, `eas_reset`, `sogo_profile_reset`,

+               `pushover`, `quarantine`, `quarantine_attachments`, `quarantine_notification`, `quarantine_category`, `app_passwds`) 

+              VALUES (:username, :spam_alias, :tls_policy, :spam_score, :spam_policy, :delimiter_action, :syncjobs, :eas_reset, :sogo_profile_reset,

+               :pushover, :quarantine, :quarantine_attachments, :quarantine_notification, :quarantine_category, :app_passwds) ");

             $stmt->execute(array(

-              ':username' => $username

+              ':username' => $username,

+              ':spam_alias' => 0,

+              ':tls_policy' => 0,

+              ':spam_score' => 0,

+              ':spam_policy' => 0,

+              ':delimiter_action' => 0,

+              ':syncjobs' => 0,

+              ':eas_reset' => 0,

+              ':sogo_profile_reset' => 0,

+              ':pushover' => 0,

+              ':quarantine' => 0,

+              ':quarantine_attachments' => 0,

+              ':quarantine_notification' => 0,

+              ':quarantine_category' => 0,

+              ':app_passwds' => 0

             ));

           }

 

@@ -1264,11 +1282,13 @@
             ));

           }

 

+          update_sogo_static_view($username);

           $_SESSION['return'][] = array(

             'type' => 'success',

             'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

             'msg' => array('mailbox_added', htmlspecialchars($username))

           );

+          return true;

         break;

         case 'resource':

           $domain             = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);

@@ -1531,20 +1551,20 @@
             $attr['acl_app_passwds'] = (in_array('app_passwds', $_data['acl'])) ? 1 : 0;

           } else {

             $_data['acl'] = (array)$_data['acl'];

-            $attr['acl_spam_alias'] = 1;

-            $attr['acl_tls_policy'] = 1;

-            $attr['acl_spam_score'] = 1;

-            $attr['acl_spam_policy'] = 1;

-            $attr['acl_delimiter_action'] = 1;

+            $attr['acl_spam_alias'] = 0;

+            $attr['acl_tls_policy'] = 0;

+            $attr['acl_spam_score'] = 0;

+            $attr['acl_spam_policy'] = 0;

+            $attr['acl_delimiter_action'] = 0;

             $attr['acl_syncjobs'] = 0;

-            $attr['acl_eas_reset'] = 1;

+            $attr['acl_eas_reset'] = 0;

             $attr['acl_sogo_profile_reset'] = 0;

-            $attr['acl_pushover'] = 1;

-            $attr['acl_quarantine'] = 1;

-            $attr['acl_quarantine_attachments'] = 1;

-            $attr['acl_quarantine_notification'] = 1;

-            $attr['acl_quarantine_category'] = 1;

-            $attr['acl_app_passwds'] = 1;

+            $attr['acl_pushover'] = 0;

+            $attr['acl_quarantine'] = 0;

+            $attr['acl_quarantine_attachments'] = 0;

+            $attr['acl_quarantine_notification'] = 0;

+            $attr['acl_quarantine_category'] = 0;

+            $attr['acl_app_passwds'] = 0;

           }

 

 

@@ -2879,67 +2899,68 @@
                 $_SESSION['return'][] = array(

                   'type' => 'danger',

                   'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

-                  'msg' => 'access_denied'

+                  'msg' => 'extended_sender_acl_denied'

                 );

-                return false;

               }

-              $extra_acls = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['extended_sender_acl']));

-              foreach ($extra_acls as $i => &$extra_acl) {

-                if (empty($extra_acl)) {

-                  continue;

-                }

-                if (substr($extra_acl, 0, 1) === "@") {

-                  $extra_acl = ltrim($extra_acl, '@');

-                }

-                if (!filter_var($extra_acl, FILTER_VALIDATE_EMAIL) && !is_valid_domain_name($extra_acl)) {

-                  $_SESSION['return'][] = array(

-                    'type' => 'danger',

-                    'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

-                    'msg' => array('extra_acl_invalid', htmlspecialchars($extra_acl))

-                  );

-                  unset($extra_acls[$i]);

-                  continue;

-                }

-                $domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains'));

-                if (filter_var($extra_acl, FILTER_VALIDATE_EMAIL)) {

-                  $extra_acl_domain = idn_to_ascii(substr(strstr($extra_acl, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);

-                  if (in_array($extra_acl_domain, $domains)) {

+              else {

+                $extra_acls = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['extended_sender_acl']));

+                foreach ($extra_acls as $i => &$extra_acl) {

+                  if (empty($extra_acl)) {

+                    continue;

+                  }

+                  if (substr($extra_acl, 0, 1) === "@") {

+                    $extra_acl = ltrim($extra_acl, '@');

+                  }

+                  if (!filter_var($extra_acl, FILTER_VALIDATE_EMAIL) && !is_valid_domain_name($extra_acl)) {

                     $_SESSION['return'][] = array(

                       'type' => 'danger',

                       'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

-                      'msg' => array('extra_acl_invalid_domain', $extra_acl_domain)

+                      'msg' => array('extra_acl_invalid', htmlspecialchars($extra_acl))

                     );

                     unset($extra_acls[$i]);

                     continue;

                   }

-                }

-                else {

-                  if (in_array($extra_acl, $domains)) {

-                    $_SESSION['return'][] = array(

-                      'type' => 'danger',

-                      'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

-                      'msg' => array('extra_acl_invalid_domain', $extra_acl_domain)

-                    );

-                    unset($extra_acls[$i]);

-                    continue;

+                  $domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains'));

+                  if (filter_var($extra_acl, FILTER_VALIDATE_EMAIL)) {

+                    $extra_acl_domain = idn_to_ascii(substr(strstr($extra_acl, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);

+                    if (in_array($extra_acl_domain, $domains)) {

+                      $_SESSION['return'][] = array(

+                        'type' => 'danger',

+                        'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

+                        'msg' => array('extra_acl_invalid_domain', $extra_acl_domain)

+                      );

+                      unset($extra_acls[$i]);

+                      continue;

+                    }

                   }

-                  $extra_acl = '@' . $extra_acl;

+                  else {

+                    if (in_array($extra_acl, $domains)) {

+                      $_SESSION['return'][] = array(

+                        'type' => 'danger',

+                        'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

+                        'msg' => array('extra_acl_invalid_domain', $extra_acl_domain)

+                      );

+                      unset($extra_acls[$i]);

+                      continue;

+                    }

+                    $extra_acl = '@' . $extra_acl;

+                  }

                 }

-              }

-              $extra_acls = array_filter($extra_acls);

-              $extra_acls = array_values($extra_acls);

-              $extra_acls = array_unique($extra_acls);

-              $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `external` = 1 AND `logged_in_as` = :username");

-              $stmt->execute(array(

-                ':username' => $username

-              ));

-              foreach ($extra_acls as $sender_acl_external) {

-                $stmt = $pdo->prepare("INSERT INTO `sender_acl` (`send_as`, `logged_in_as`, `external`)

-                  VALUES (:sender_acl, :username, 1)");

+                $extra_acls = array_filter($extra_acls);

+                $extra_acls = array_values($extra_acls);

+                $extra_acls = array_unique($extra_acls);

+                $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `external` = 1 AND `logged_in_as` = :username");

                 $stmt->execute(array(

-                  ':sender_acl' => $sender_acl_external,

                   ':username' => $username

                 ));

+                foreach ($extra_acls as $sender_acl_external) {

+                  $stmt = $pdo->prepare("INSERT INTO `sender_acl` (`send_as`, `logged_in_as`, `external`)

+                    VALUES (:sender_acl, :username, 1)");

+                  $stmt->execute(array(

+                    ':sender_acl' => $sender_acl_external,

+                    ':username' => $username

+                  ));

+                }

               }

             }

             if (isset($_data['sender_acl'])) {

@@ -3129,7 +3150,10 @@
               'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

               'msg' => array('mailbox_modified', $username)

             );

+

+            update_sogo_static_view($username);

           }

+          return true;

         break;

         case 'mailbox_templates':

           if ($_SESSION['mailcow_cc_role'] != "admin") {

@@ -3314,6 +3338,45 @@
             );

           }

         break;

+        case 'domain_wide_footer':

+          $domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);

+          if (!is_valid_domain_name($domain)) {

+            $_SESSION['return'][] = array(

+              'type' => 'danger',

+              'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

+              'msg' => 'domain_invalid'

+            );

+            return false;

+          }

+          if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {

+            $_SESSION['return'][] = array(

+              'type' => 'danger',

+              'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

+              'msg' => 'access_denied'

+            );

+            return false;

+          }

+

+          $footers = array();

+          $footers['html'] = isset($_data['footer_html']) ? $_data['footer_html'] : '';

+          $footers['plain'] = isset($_data['footer_plain']) ? $_data['footer_plain'] : '';

+          try {

+            $redis->hSet('DOMAIN_WIDE_FOOTER', $domain, json_encode($footers));

+          }

+          catch (RedisException $e) {

+            $_SESSION['return'][] = array(

+              'type' => 'danger',

+              'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

+              'msg' => array('redis_error', $e)

+            );

+            return false;

+          }

+          $_SESSION['return'][] = array(

+            'type' => 'success',

+            'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

+            'msg' => array('domain_footer_modified', htmlspecialchars($domain))

+          );

+        break;

       }

     break;

     case 'get':

@@ -3959,6 +4022,39 @@
           }

           return $aliasdomaindata;

         break;

+        case 'shared_aliases':

+          $shared_aliases = array();

+          $stmt = $pdo->query("SELECT `address` FROM `alias`

+            WHERE `goto` REGEXP ','

+            AND `address` NOT LIKE '@%'

+            AND `goto` != `address`");

+          $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

+          while($row = array_shift($rows)) {

+            $domain = explode("@", $row['address'])[1];

+            if (hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {

+              $shared_aliases[] = $row['address'];

+            }

+          }

+

+          return $shared_aliases;

+        break;

+        case 'direct_aliases':

+          $direct_aliases = array();

+          $stmt = $pdo->query("SELECT `address` FROM `alias`

+            WHERE `goto` NOT LIKE '%,%'

+            AND `address` NOT LIKE '@%'

+            AND `goto` != `address`");

+          $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

+

+          while($row = array_shift($rows)) {

+            $domain = explode("@", $row['address'])[1];

+            if (hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {

+              $direct_aliases[] = $row['address'];

+            }

+          }

+

+          return $direct_aliases;

+        break;

         case 'domains':

           $domains = array();

           if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {

@@ -4393,6 +4489,40 @@
           }

           return $resourcedata;

         break;

+        case 'domain_wide_footer':

+          $domain = idn_to_ascii(strtolower(trim($_data)), 0, INTL_IDNA_VARIANT_UTS46);

+          if (!is_valid_domain_name($domain)) {

+            $_SESSION['return'][] = array(

+              'type' => 'danger',

+              'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

+              'msg' => 'domain_invalid'

+            );

+            return false;

+          }

+          if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {

+            $_SESSION['return'][] = array(

+              'type' => 'danger',

+              'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

+              'msg' => 'access_denied'

+            );

+            return false;

+          }

+

+          try {

+            $footers = $redis->hGet('DOMAIN_WIDE_FOOTER', $domain);

+            $footers = json_decode($footers, true);

+          }

+          catch (RedisException $e) {

+            $_SESSION['return'][] = array(

+              'type' => 'danger',

+              'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

+              'msg' => array('redis_error', $e)

+            );

+            return false;

+          }

+

+          return $footers;

+        break;

       }

     break;

     case 'delete':

@@ -4891,13 +5021,19 @@
             if (!empty($mailbox_details['domain']) && !empty($mailbox_details['local_part'])) {

               $maildir = $mailbox_details['domain'] . '/' . $mailbox_details['local_part'];

               $exec_fields = array('cmd' => 'maildir', 'task' => 'cleanup', 'maildir' => $maildir);

-              $maildir_gc = json_decode(docker('post', 'dovecot-mailcow', 'exec', $exec_fields), true);

-              if ($maildir_gc['type'] != 'success') {

-                $_SESSION['return'][] = array(

-                  'type' => 'warning',

-                  'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

-                  'msg' => 'Could not move maildir to garbage collector: ' . $maildir_gc['msg']

-                );

+

+              if (getenv("CLUSTERMODE") == "replication") {

+                // broadcast to each dovecot container

+                docker('broadcast', 'dovecot-mailcow', 'exec', $exec_fields);

+              } else {

+                $maildir_gc = json_decode(docker('post', 'dovecot-mailcow', 'exec', $exec_fields), true);

+                if ($maildir_gc['type'] != 'success') {

+                  $_SESSION['return'][] = array(

+                    'type' => 'warning',

+                    'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

+                    'msg' => 'Could not move maildir to garbage collector: ' . $maildir_gc['msg']

+                  );

+                }

               }

             }

             else {

@@ -4950,9 +5086,10 @@
             $stmt->execute(array(

               ':username' => $username

             ));

-            $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username");

+            $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :logged_in_as OR `send_as` = :send_as");

             $stmt->execute(array(

-              ':username' => $username

+              ':logged_in_as' => $username,

+              ':send_as' => $username

             ));

             // fk, better safe than sorry

             $stmt = $pdo->prepare("DELETE FROM `user_acl` WHERE `username` = :username");

@@ -5052,12 +5189,15 @@
               );

               continue;

             }

+            

+            update_sogo_static_view($username);

             $_SESSION['return'][] = array(

               'type' => 'success',

               'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

               'msg' => array('mailbox_removed', htmlspecialchars($username))

             );

           }

+          return true;

         break;

         case 'mailbox_templates':

           if ($_SESSION['mailcow_cc_role'] != "admin") {

@@ -5170,15 +5310,6 @@
           $tags = $_data['tags'];

           if (!is_array($tags)) $tags = array();

 

-          

-          if ($_SESSION['mailcow_cc_role'] != "admin") {

-            $_SESSION['return'][] = array(

-              'type' => 'danger',

-              'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

-              'msg' => 'access_denied'

-            );

-            return false;

-          }

 

           $wasModified = false;

           foreach ($domains as $domain) {            

@@ -5190,7 +5321,15 @@
               );

               continue;

             }

-

+            if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {

+              $_SESSION['return'][] = array(

+                'type' => 'danger',

+                'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

+                'msg' => 'access_denied'

+              );

+              return false;

+            }

+            

             foreach($tags as $tag){

               // delete tag

               $wasModified = true;

@@ -5264,7 +5403,7 @@
       }

     break;

   }

-  if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'mailbox', 'resource'))) {

+  if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'resource')) && getenv('SKIP_SOGO') != "y") {

     update_sogo_static_view();

   }

 }