Browse Source

Better log table, some MySQL to Redis migrations, API changes, other minor changes...

andryyy 8 years ago
parent
commit
f77c40a179

+ 88 - 81
data/web/inc/functions.inc.php

@@ -1327,7 +1327,7 @@ function edit_delimiter_action($postarray) {
   // Array items
   // 'username' can be set, defaults to mailcow_cc_username
 	global $lang;
-	global $pdo;
+	global $redis;
   if (isset($postarray['username']) && filter_var($postarray['username'], FILTER_VALIDATE_EMAIL)) {
     if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $postarray['username'])) {
       $_SESSION['return'] = array(
@@ -1343,7 +1343,6 @@ function edit_delimiter_action($postarray) {
   else {
     $username = $_SESSION['mailcow_cc_username'];
   }
-  ($postarray['tagged_mail_handler'] == "subject") ? $wants_tagged_subject = '1' : $wants_tagged_subject = '0';
   if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
     $_SESSION['return'] = array(
       'type' => 'danger',
@@ -1351,17 +1350,29 @@ function edit_delimiter_action($postarray) {
     );
     return false;
   }
-  try {
-    $stmt = $pdo->prepare("UPDATE `mailbox` SET `wants_tagged_subject` = :wants_tagged_subject WHERE `username` = :username");
-    $stmt->execute(array(':username' => $username, ':wants_tagged_subject' => $wants_tagged_subject));
-    $SelectData = $stmt->fetch(PDO::FETCH_ASSOC);
+  if (isset($postarray['tagged_mail_handler']) && $postarray['tagged_mail_handler'] == "subject") {
+    try {
+      $redis->hSet('RCPT_WANTS_SUBJECT_TAG', $username, 1);
+    }
+    catch (RedisException $e) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => 'Redis: '.$e
+      );
+      return false;
+    }
   }
-  catch(PDOException $e) {
-    $_SESSION['return'] = array(
-      'type' => 'danger',
-      'msg' => 'MySQL: '.$e
-    );
-    return false;
+  else {
+    try {
+      $redis->hDel('RCPT_WANTS_SUBJECT_TAG', $username);
+    }
+    catch (RedisException $e) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => 'Redis: '.$e
+      );
+      return false;
+    }
   }
   $_SESSION['return'] = array(
     'type' => 'success',
@@ -1372,7 +1383,7 @@ function edit_delimiter_action($postarray) {
 function get_delimiter_action($username = null) {
   // 'username' can be set, defaults to mailcow_cc_username
 	global $lang;
-	global $pdo;
+	global $redis;
 	$data = array();
   if (isset($username) && filter_var($username, FILTER_VALIDATE_EMAIL)) {
     if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
@@ -1383,18 +1394,20 @@ function get_delimiter_action($username = null) {
     $username = $_SESSION['mailcow_cc_username'];
   }
   try {
-    $stmt = $pdo->prepare("SELECT `wants_tagged_subject` FROM `mailbox` WHERE `username` = :username");
-    $stmt->execute(array(':username' => $username));
-    $data = $stmt->fetch(PDO::FETCH_ASSOC);
+    if ($redis->hGet('RCPT_WANTS_SUBJECT_TAG', $username)) {
+      return "subject";
+    }
+    else {
+      return "subfolder";
+    }
   }
-  catch(PDOException $e) {
+  catch (RedisException $e) {
     $_SESSION['return'] = array(
       'type' => 'danger',
-      'msg' => 'MySQL: '.$e
+      'msg' => 'Redis: '.$e
     );
     return false;
   }
-  return $data;
 }
 function user_get_alias_details($username) {
 	global $lang;
@@ -2413,12 +2426,30 @@ function dkim_add_key($postarray) {
         ), 1, -1)
       );
     // Save public key and selector to redis
-    $redis->hSet('DKIM_PUB_KEYS', $domain, $pubKey);
-    $redis->hSet('DKIM_SELECTORS', $domain, $dkim_selector);
+    try {
+      $redis->hSet('DKIM_PUB_KEYS', $domain, $pubKey);
+      $redis->hSet('DKIM_SELECTORS', $domain, $dkim_selector);
+    }
+    catch (RedisException $e) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => 'Redis: '.$e
+      );
+      return false;
+    }
     // Export private key and save private key to redis
     openssl_pkey_export($keypair_ressource, $privKey);
     if (isset($privKey) && !empty($privKey)) {
-      $redis->hSet('DKIM_PRIV_KEYS', $dkim_selector . '.' . $domain, trim($privKey));
+      try {
+        $redis->hSet('DKIM_PRIV_KEYS', $dkim_selector . '.' . $domain, trim($privKey));
+      }
+      catch (RedisException $e) {
+        $_SESSION['return'] = array(
+          'type' => 'danger',
+          'msg' => 'Redis: '.$e
+        );
+        return false;
+      }
     }
     $_SESSION['return'] = array(
       'type' => 'success',
@@ -2438,18 +2469,7 @@ function dkim_get_key_details($domain) {
   $data = array();
   global $redis;
   if (hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
-    $dkim_pubkey_file = escapeshellarg($GLOBALS["MC_DKIM_TXTS"]. "/" . $domain . "." . "dkim");
-    if (file_exists(substr($dkim_pubkey_file, 1, -1))) {
-      $data['pubkey'] = file_get_contents($GLOBALS["MC_DKIM_TXTS"]. "/" . $domain . "." . "dkim");
-      $data['length'] = (strlen($data['pubkey']) < 391) ? 1024 : 2048;
-      $data['dkim_txt'] = 'v=DKIM1;k=rsa;t=s;s=email;p=' . file_get_contents($GLOBALS["MC_DKIM_TXTS"]. "/" . $domain . "." . "dkim");
-      $data['dkim_selector'] = 'dkim';
-      // Migrate key to redis
-      $redis->hSet('DKIM_PRIV_KEYS', $data['dkim_selector'] . '.' . $domain, trim(file_get_contents($GLOBALS["MC_DKIM_KEYS"]. "/" . $domain . "." . "dkim")));
-      $redis->hSet('DKIM_PUB_KEYS', $domain, $data['pubkey']);
-      $redis->hSet('DKIM_SELECTORS', $domain, 'dkim');
-    }
-    elseif ($redis_dkim_key_data = $redis->hGet('DKIM_PUB_KEYS', $domain)) {
+    if ($redis_dkim_key_data = $redis->hGet('DKIM_PUB_KEYS', $domain)) {
       $data['pubkey'] = $redis_dkim_key_data;
       $data['length'] = (strlen($data['pubkey']) < 391) ? 1024 : 2048;
       $data['dkim_txt'] = 'v=DKIM1;k=rsa;t=s;s=email;p=' . $redis_dkim_key_data;
@@ -2469,11 +2489,6 @@ function dkim_get_blind_keys() {
     return false;
   }
   $domains = array();
-  $dnstxt_folder = scandir($GLOBALS["MC_DKIM_TXTS"]);
-  $dnstxt_files = array_diff($dnstxt_folder, array('.', '..'));
-  foreach($dnstxt_files as $file) {
-    $domains[] = substr($file, 0, -5);
-  }
   foreach ($redis->hKeys('DKIM_PUB_KEYS') as $redis_dkim_domain) {
     $domains[] = $redis_dkim_domain;
   }
@@ -2491,13 +2506,6 @@ function dkim_delete_key($postarray) {
     );
     return false;
   }
-  // if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
-    // $_SESSION['return'] = array(
-      // 'type' => 'danger',
-      // 'msg' => sprintf($lang['danger']['access_denied'])
-    // );
-    // return false;
-  // }
   if (!is_valid_domain_name($domain)) {
     $_SESSION['return'] = array(
       'type' => 'danger',
@@ -2505,43 +2513,22 @@ function dkim_delete_key($postarray) {
     );
     return false;
   }
-  foreach (array('DKIM_PUB_KEYS', 'DKIM_SELECTORS',) as $hash) {
-    if (!$redis->hDel($hash, $domain)) {
-      $_SESSION['return'] = array(
-        'type' => 'danger',
-        'msg' => sprintf($lang['danger']['dkim_remove_failed'])
-      );
-      return false;
-    }
-  }
-  if (!empty($key_details = dkim_get_key_details($domain))) {
-    if (!$redis->hDel($hash . $key_details['dkim_selector'], $domain)) {
-      $_SESSION['return'] = array(
-        'type' => 'danger',
-        'msg' => sprintf($lang['danger']['dkim_remove_failed'])
-      );
-      return false;
+  try {
+    foreach ($redis->hGetAll('DKIM_PRIV_KEYS') as $key => $value) {
+      if (preg_match('/\.' . $domain . '$/i', $key)) {
+        $redis->hDel('DKIM_PUB_KEYS', $key);
+      }
     }
+    $redis->hDel('DKIM_PUB_KEYS', $domain);
+    $redis->hDel('DKIM_SELECTORS', $domain);
+    $redis->hDel('DKIM_PRIV_KEYS', $domain);
   }
-  
-  $redis->hDel('DKIM_PUB_KEYS', $domain);
-  $redis->hDel('DKIM_PRIV_KEYS', $domain);
-  $redis->hDel('DKIM_SELECTORS', $domain);
-  exec('rm -f ' . escapeshellarg($GLOBALS['MC_DKIM_TXTS'] . '/' . $domain . '.dkim'), $out, $return);
-  if ($return != "0") {
-    $_SESSION['return'] = array(
-      'type' => 'danger',
-      'msg' => sprintf($lang['danger']['dkim_remove_failed'])
-    );
-    return false;
-  }
-  exec('rm -f ' . escapeshellarg($GLOBALS['MC_DKIM_KEYS'] . '/' . $domain . '.dkim'), $out, $return);
-  if ($return != "0") {
-    $_SESSION['return'] = array(
-      'type' => 'danger',
-      'msg' => sprintf($lang['danger']['dkim_remove_failed'])
-    );
-    return false;
+  catch (RedisException $e) {
+		$_SESSION['return'] = array(
+			'type' => 'danger',
+			'msg' => 'Redis: '.$e
+		);
+		return false;
   }
   $_SESSION['return'] = array(
     'type' => 'success',
@@ -2654,6 +2641,16 @@ function mailbox_add_domain($postarray) {
 			':active' => $active,
 			':relay_all_recipients' => $relay_all_recipients
 		));
+    try {
+      $redis->hSet('DOMAIN_MAP', $domain, 1);
+    }
+    catch (RedisException $e) {
+      $_SESSION['return'] = array(
+        'type' => 'danger',
+        'msg' => 'Redis: '.$e
+      );
+      return false;
+    }
 		$_SESSION['return'] = array(
 			'type' => 'success',
 			'msg' => sprintf($lang['success']['domain_added'], htmlspecialchars($domain))
@@ -4646,6 +4643,16 @@ function mailbox_delete_domain($postarray) {
 		);
 		return false;
 	}
+  try {
+    $redis->hDel('DOMAIN_MAP', $domain);
+  }
+  catch (RedisException $e) {
+		$_SESSION['return'] = array(
+			'type' => 'danger',
+			'msg' => 'Redis: '.$e
+		);
+		return false;
+  }
 	$_SESSION['return'] = array(
 		'type' => 'success',
 		'msg' => sprintf($lang['success']['domain_removed'], htmlspecialchars($domain))

+ 1 - 3
data/web/inc/lib/vendor/owasp/csrf-protector-php/libs/config.php

@@ -42,8 +42,6 @@ return array(
 	"jsUrl" => get_trusted_hostname(),
 	"tokenLength" => 10,
 	"secureCookie" => false,
-	"disabledJavascriptMessage" => "This site attempts to protect users against <a href=\"https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29\">
-	Cross-Site Request Forgeries </a> attacks. In order to do so, you must have JavaScript enabled in your web browser otherwise this site will fail to work correctly for you.
-	 See details of your web browser for how to enable JavaScript.",
+	"disabledJavascriptMessage" => "",
 	 "verifyGetFor" => array()
 );

+ 9 - 9
data/web/inc/prerequisites.inc.php

@@ -1,16 +1,16 @@
 <?php
-require_once 'inc/sessions.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/sessions.inc.php';
 
-require_once 'inc/vars.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/vars.inc.php';
 if (file_exists('./inc/vars.local.inc.php')) {
 	include_once 'inc/vars.local.inc.php';
 }
 
 // Yubi OTP API
-require_once 'inc/lib/Yubico.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/lib/Yubico.php';
 
 // Autoload composer
-require_once 'inc/lib/vendor/autoload.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/lib/vendor/autoload.php';
 
 // U2F API + T/HOTP API
 $u2f = new u2flib_server\U2F('https://' . $_SERVER['HTTP_HOST']);
@@ -117,9 +117,9 @@ if (isset($_GET['lang'])) {
 		break;
 	}
 }
-require_once 'lang/lang.en.php';
-include 'lang/lang.'.$_SESSION['mailcow_locale'].'.php';
-require_once 'inc/functions.inc.php';
-require_once 'inc/init_db.inc.php';
-require_once 'inc/triggers.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/lang/lang.en.php';
+include $_SERVER['DOCUMENT_ROOT'] . '/lang/lang.'.$_SESSION['mailcow_locale'].'.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/init_db.inc.php';
+require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/triggers.inc.php';
 init_db_schema();

+ 15 - 8
data/web/inc/spf.inc.php

@@ -79,17 +79,24 @@ function get_spf_allowed_hosts($domain)
 	return $hosts;
 }
 
+
 function get_mx_hosts($domain)
 {
 	$hosts = array();
-	
-	$mx_records = dns_get_record($domain, DNS_MX);
-	foreach ($mx_records as $mx_record)
-	{
-		$new_hosts = get_a_hosts($mx_record['target']);
-		$hosts = array_unique(array_merge($hosts,$new_hosts), SORT_REGULAR);
-	}
-	
+  try {
+    $mx_records = dns_get_record($domain, DNS_MX);
+    foreach ($mx_records as $mx_record)
+    {
+      $new_hosts = get_a_hosts($mx_record['target']);
+      $hosts = array_unique(array_merge($hosts,$new_hosts), SORT_REGULAR);
+    }
+  }
+  catch (Exception $e) {
+    if ($e->getMessage() !== 'dns_get_record(): A temporary server error occurred.') {
+      throw $e;
+    }
+    $mx_records = false;
+  }
 	return $hosts;
 }
 

+ 4 - 4
data/web/js/admin.js

@@ -4,7 +4,7 @@ $(document).ready(function() {
     url: '/api/v1/get/domain-admin/all',
     jsonp: false,
     error: function () {
-      alert('Cannot draw domain administrator table');
+      console.log('Cannot draw domain admin table');
     },
     success: function (data) {
       $.each(data, function (i, item) {
@@ -53,7 +53,7 @@ $(document).ready(function() {
         url: '/api/v1/get/logs/dovecot/1000',
         jsonp: false,
         error: function () {
-          alert('Cannot draw dovecot log table');
+          console.log('Cannot draw dovecot log table');
         },
         success: function (data) {
           $.each(data, function (i, item) {
@@ -109,7 +109,7 @@ $(document).ready(function() {
         url: '/api/v1/get/logs/postfix/1000',
         jsonp: false,
         error: function () {
-          alert('Cannot draw postfix log table');
+          console.log('Cannot draw postfix log table');
         },
         success: function (data) {
           $.each(data, function (i, item) {
@@ -128,7 +128,7 @@ $(document).ready(function() {
           });
           ft_postfix_logs = FooTable.init("#postfix_log", {
             "columns": [
-              {"name":"time","formatter":function unix_time_format(tm) {var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
+              {"name":"time","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleString();},"title":lang.time,"style":{"width":"170px"}},
               {"name":"priority","title":lang.priority,"style":{"width":"80px"}},
               {"name":"message","title":lang.message},
             ],

+ 2 - 2
data/web/json_api.php

@@ -61,7 +61,7 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
           case "logs":
             switch ($object) {
               case "dovecot":
-                if (isset($extra) && !empty($extra) && is_int($extra)) {
+                if (isset($extra) && !empty($extra)) {
                   $extra = intval($extra);
                   $logs = get_logs('dovecot-mailcow', $extra);
                 }
@@ -77,7 +77,7 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
               break;
 
               case "postfix":
-                if (isset($extra) && !empty($extra) && is_int($extra)) {
+                if (isset($extra) && !empty($extra)) {
                   $extra = intval($extra);
                   $logs = get_logs('postfix-mailcow', $extra);
                 }

+ 3 - 3
data/web/user.php

@@ -125,14 +125,14 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
   <hr>
   <?php // Show tagging options ?>
   <form class="form-horizontal" role="form" method="post">
-  <?php $get_tagging_options = get_delimiter_action()['wants_tagged_subject'];?>
+  <?php $get_tagging_options = get_delimiter_action();?>
   <div class="row">
     <div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['tag_handling'];?>:</div>
     <div class="col-md-9 col-xs-7">
     <input type="hidden" name="edit_delimiter_action" value="1">
     <select name="tagged_mail_handler" class="selectpicker" onchange="this.form.submit()">
-      <option value="subfolder" <?=($get_tagging_options == "0") ? 'selected' : null; ?>><?=$lang['user']['tag_in_subfolder'];?></option>
-      <option value="subject" <?=($get_tagging_options == "1") ? 'selected' : null; ?>><?=$lang['user']['tag_in_subject'];?></option>
+      <option value="subfolder" <?=($get_tagging_options == "subfolder") ? 'selected' : null; ?>><?=$lang['user']['tag_in_subfolder'];?></option>
+      <option value="subject" <?=($get_tagging_options == "subject") ? 'selected' : null; ?>><?=$lang['user']['tag_in_subject'];?></option>
     </select>
     <p class="help-block"><?=$lang['user']['tag_help_explain'];?></p>
     <p class="help-block"><?=$lang['user']['tag_help_example'];?></p>