functions.inc.php 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496
  1. <?php
  2. require_once 'dkim.inc.php';
  3. require_once 'mailbox.inc.php';
  4. require_once 'domainadmin.inc.php';
  5. require_once 'admin.inc.php';
  6. function hash_password($password) {
  7. $salt_str = bin2hex(openssl_random_pseudo_bytes(8));
  8. return "{SSHA256}".base64_encode(hash('sha256', $password . $salt_str, true) . $salt_str);
  9. }
  10. function hasDomainAccess($username, $role, $domain) {
  11. global $pdo;
  12. if (!filter_var($username, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
  13. return false;
  14. }
  15. if (empty($domain) || !is_valid_domain_name($domain)) {
  16. return false;
  17. }
  18. if ($role != 'admin' && $role != 'domainadmin' && $role != 'user') {
  19. return false;
  20. }
  21. try {
  22. $stmt = $pdo->prepare("SELECT `domain` FROM `domain_admins`
  23. WHERE (
  24. `active`='1'
  25. AND `username` = :username
  26. AND (`domain` = :domain1 OR `domain` = (SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain2))
  27. )
  28. OR 'admin' = :role");
  29. $stmt->execute(array(':username' => $username, ':domain1' => $domain, ':domain2' => $domain, ':role' => $role));
  30. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  31. }
  32. catch(PDOException $e) {
  33. $_SESSION['return'] = array(
  34. 'type' => 'danger',
  35. 'msg' => 'MySQL: '.$e
  36. );
  37. return false;
  38. }
  39. if (!empty($num_results)) {
  40. return true;
  41. }
  42. return false;
  43. }
  44. function hasMailboxObjectAccess($username, $role, $object) {
  45. global $pdo;
  46. if (!filter_var($username, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
  47. return false;
  48. }
  49. if ($role != 'admin' && $role != 'domainadmin' && $role != 'user') {
  50. return false;
  51. }
  52. if ($username == $object) {
  53. return true;
  54. }
  55. try {
  56. $stmt = $pdo->prepare("SELECT `domain` FROM `mailbox` WHERE `username` = :object");
  57. $stmt->execute(array(':object' => $object));
  58. $row = $stmt->fetch(PDO::FETCH_ASSOC);
  59. if (isset($row['domain']) && hasDomainAccess($username, $role, $row['domain'])) {
  60. return true;
  61. }
  62. }
  63. catch(PDOException $e) {
  64. error_log($e);
  65. return false;
  66. }
  67. return false;
  68. }
  69. function init_db_schema() {
  70. global $pdo;
  71. try {
  72. $stmt = $pdo->prepare("SELECT NULL FROM `admin`, `imapsync`");
  73. $stmt->execute();
  74. }
  75. catch (Exception $e) {
  76. $lines = file('/web/inc/init.sql');
  77. $data = '';
  78. foreach ($lines as $line) {
  79. if (substr($line, 0, 2) == '--' || $line == '') {
  80. continue;
  81. }
  82. $data .= $line;
  83. if (substr(trim($line), -1, 1) == ';') {
  84. $pdo->query($data);
  85. $data = '';
  86. }
  87. }
  88. // Create index if not exists
  89. $stmt = $pdo->query("SHOW INDEX FROM sogo_acl WHERE KEY_NAME = 'sogo_acl_c_folder_id_idx'");
  90. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  91. if ($num_results == 0) {
  92. $pdo->query("CREATE INDEX sogo_acl_c_folder_id_idx ON sogo_acl(c_folder_id)");
  93. }
  94. $stmt = $pdo->query("SHOW INDEX FROM sogo_acl WHERE KEY_NAME = 'sogo_acl_c_uid_idx'");
  95. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  96. if ($num_results == 0) {
  97. $pdo->query("CREATE INDEX sogo_acl_c_uid_idx ON sogo_acl(c_uid)");
  98. }
  99. $_SESSION['return'] = array(
  100. 'type' => 'success',
  101. 'msg' => 'Database initialization completed.'
  102. );
  103. }
  104. // Add newly added columns
  105. $stmt = $pdo->query("SHOW COLUMNS FROM `mailbox` LIKE 'kind'");
  106. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  107. if ($num_results == 0) {
  108. $pdo->query("ALTER TABLE `mailbox` ADD `kind` varchar(100) NOT NULL DEFAULT ''");
  109. }
  110. $stmt = $pdo->query("SHOW COLUMNS FROM `mailbox` LIKE 'multiple_bookings'");
  111. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  112. if ($num_results == 0) {
  113. $pdo->query("ALTER TABLE `mailbox` ADD `multiple_bookings` tinyint(1) NOT NULL DEFAULT '0'");
  114. }
  115. $stmt = $pdo->query("SHOW COLUMNS FROM `mailbox` LIKE 'wants_tagged_subject'");
  116. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  117. if ($num_results == 0) {
  118. $pdo->query("ALTER TABLE `mailbox` ADD `wants_tagged_subject` tinyint(1) NOT NULL DEFAULT '0'");
  119. }
  120. }
  121. function verify_ssha256($hash, $password) {
  122. // Remove tag if any
  123. $hash = ltrim($hash, '{SSHA256}');
  124. // Decode hash
  125. $dhash = base64_decode($hash);
  126. // Get first 32 bytes of binary which equals a SHA256 hash
  127. $ohash = substr($dhash, 0, 32);
  128. // Remove SHA256 hash from decoded hash to get original salt string
  129. $osalt = str_replace($ohash, '', $dhash);
  130. // Check single salted SHA256 hash against extracted hash
  131. if (hash('sha256', $password . $osalt, true) == $ohash) {
  132. return true;
  133. }
  134. else {
  135. return false;
  136. }
  137. }
  138. function doveadm_authenticate($hash, $algorithm, $password) {
  139. $descr = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
  140. $pipes = array();
  141. $process = proc_open("/usr/bin/doveadm pw -s ".$algorithm." -t '".$hash."'", $descr, $pipes);
  142. if (is_resource($process)) {
  143. fputs($pipes[0], $password);
  144. fclose($pipes[0]);
  145. while ($f = fgets($pipes[1])) {
  146. if (preg_match('/(verified)/', $f)) {
  147. proc_close($process);
  148. return true;
  149. }
  150. return false;
  151. }
  152. fclose($pipes[1]);
  153. while ($f = fgets($pipes[2])) {
  154. proc_close($process);
  155. return false;
  156. }
  157. fclose($pipes[2]);
  158. proc_close($process);
  159. }
  160. return false;
  161. }
  162. function check_login($user, $pass) {
  163. global $pdo;
  164. if (!filter_var($user, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $user))) {
  165. return false;
  166. }
  167. $user = strtolower(trim($user));
  168. $stmt = $pdo->prepare("SELECT `password` FROM `admin`
  169. WHERE `superadmin` = '1'
  170. AND `username` = :user");
  171. $stmt->execute(array(':user' => $user));
  172. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  173. foreach ($rows as $row) {
  174. if (verify_ssha256($row['password'], $pass) !== false) {
  175. unset($_SESSION['ldelay']);
  176. return "admin";
  177. }
  178. }
  179. $stmt = $pdo->prepare("SELECT `password` FROM `admin`
  180. WHERE `superadmin` = '0'
  181. AND `active`='1'
  182. AND `username` = :user");
  183. $stmt->execute(array(':user' => $user));
  184. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  185. foreach ($rows as $row) {
  186. if (verify_ssha256($row['password'], $pass) !== false) {
  187. unset($_SESSION['ldelay']);
  188. return "domainadmin";
  189. }
  190. }
  191. $stmt = $pdo->prepare("SELECT `password` FROM `mailbox`
  192. WHERE `active`='1'
  193. AND `username` = :user");
  194. $stmt->execute(array(':user' => $user));
  195. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  196. foreach ($rows as $row) {
  197. if (verify_ssha256($row['password'], $pass) !== false) {
  198. unset($_SESSION['ldelay']);
  199. return "user";
  200. }
  201. }
  202. if (!isset($_SESSION['ldelay'])) {
  203. $_SESSION['ldelay'] = "0";
  204. }
  205. elseif (!isset($_SESSION['mailcow_cc_username'])) {
  206. $_SESSION['ldelay'] = $_SESSION['ldelay']+0.5;
  207. }
  208. sleep($_SESSION['ldelay']);
  209. }
  210. function formatBytes($size, $precision = 2) {
  211. if(!is_numeric($size)) {
  212. return "0";
  213. }
  214. $base = log($size, 1024);
  215. $suffixes = array(' Byte', ' KiB', ' MiB', ' GiB', ' TiB');
  216. if ($size == "0") {
  217. return "0";
  218. }
  219. return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
  220. }
  221. function set_admin_account($postarray) {
  222. global $lang;
  223. global $pdo;
  224. if ($_SESSION['mailcow_cc_role'] != "admin") {
  225. $_SESSION['return'] = array(
  226. 'type' => 'danger',
  227. 'msg' => sprintf($lang['danger']['access_denied'])
  228. );
  229. return false;
  230. }
  231. $name = $postarray['admin_user'];
  232. $name_now = $postarray['admin_user_now'];
  233. if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $name)) || empty ($name)) {
  234. $_SESSION['return'] = array(
  235. 'type' => 'danger',
  236. 'msg' => sprintf($lang['danger']['username_invalid'])
  237. );
  238. return false;
  239. }
  240. if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $name_now)) || empty ($name_now)) {
  241. $_SESSION['return'] = array(
  242. 'type' => 'danger',
  243. 'msg' => sprintf($lang['danger']['username_invalid'])
  244. );
  245. return false;
  246. }
  247. if (!empty($postarray['admin_pass']) && !empty($postarray['admin_pass2'])) {
  248. if ($postarray['admin_pass'] != $postarray['admin_pass2']) {
  249. $_SESSION['return'] = array(
  250. 'type' => 'danger',
  251. 'msg' => sprintf($lang['danger']['password_mismatch'])
  252. );
  253. return false;
  254. }
  255. $password_hashed = hash_password($postarray['admin_pass']);
  256. try {
  257. $stmt = $pdo->prepare("UPDATE `admin` SET
  258. `modified` = :modified,
  259. `password` = :password_hashed,
  260. `username` = :name
  261. WHERE `username` = :username");
  262. $stmt->execute(array(
  263. ':password_hashed' => $password_hashed,
  264. ':modified' => date('Y-m-d H:i:s'),
  265. ':name' => $name,
  266. ':username' => $name_now
  267. ));
  268. }
  269. catch (PDOException $e) {
  270. $_SESSION['return'] = array(
  271. 'type' => 'danger',
  272. 'msg' => 'MySQL: '.$e
  273. );
  274. return false;
  275. }
  276. }
  277. else {
  278. try {
  279. $stmt = $pdo->prepare("UPDATE `admin` SET
  280. `modified` = :modified,
  281. `username` = :name
  282. WHERE `username` = :name_now");
  283. $stmt->execute(array(
  284. ':name' => $name,
  285. ':modified' => date('Y-m-d H:i:s'),
  286. ':name_now' => $name_now
  287. ));
  288. }
  289. catch (PDOException $e) {
  290. $_SESSION['return'] = array(
  291. 'type' => 'danger',
  292. 'msg' => 'MySQL: '.$e
  293. );
  294. return false;
  295. }
  296. }
  297. try {
  298. $stmt = $pdo->prepare("UPDATE `domain_admins` SET
  299. `domain` = :domain,
  300. `username` = :name
  301. WHERE `username` = :name_now");
  302. $stmt->execute(array(
  303. ':domain' => 'ALL',
  304. ':name' => $name,
  305. ':name_now' => $name_now
  306. ));
  307. }
  308. catch (PDOException $e) {
  309. $_SESSION['return'] = array(
  310. 'type' => 'danger',
  311. 'msg' => 'MySQL: '.$e
  312. );
  313. return false;
  314. }
  315. $_SESSION['return'] = array(
  316. 'type' => 'success',
  317. 'msg' => sprintf($lang['success']['admin_modified'])
  318. );
  319. }
  320. function set_time_limited_aliases($postarray) {
  321. global $lang;
  322. global $pdo;
  323. (isset($postarray['username'])) ? $username = $postarray['username'] : $username = $_SESSION['mailcow_cc_username'];
  324. if ($_SESSION['mailcow_cc_role'] != "user" &&
  325. $_SESSION['mailcow_cc_role'] != "admin") {
  326. $_SESSION['return'] = array(
  327. 'type' => 'danger',
  328. 'msg' => sprintf($lang['danger']['access_denied'])
  329. );
  330. return false;
  331. }
  332. if (filter_var($username, FILTER_VALIDATE_EMAIL)) {
  333. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
  334. $_SESSION['return'] = array(
  335. 'type' => 'danger',
  336. 'msg' => sprintf($lang['danger']['access_denied'])
  337. );
  338. return false;
  339. }
  340. }
  341. try {
  342. $stmt = $pdo->prepare("SELECT `domain` FROM `mailbox` WHERE `username` = :username");
  343. $stmt->execute(array(':username' => $username));
  344. $domain = $stmt->fetch(PDO::FETCH_ASSOC)['domain'];
  345. }
  346. catch (PDOException $e) {
  347. $_SESSION['return'] = array(
  348. 'type' => 'danger',
  349. 'msg' => 'MySQL: '.$e
  350. );
  351. return false;
  352. }
  353. switch ($postarray["trigger_set_time_limited_aliases"]) {
  354. case "generate":
  355. if (!is_numeric($postarray["validity"]) || $postarray["validity"] > 672) {
  356. $_SESSION['return'] = array(
  357. 'type' => 'danger',
  358. 'msg' => sprintf($lang['danger']['validity_missing'])
  359. );
  360. return false;
  361. }
  362. $validity = strtotime("+".$postarray["validity"]." hour");
  363. $letters = 'abcefghijklmnopqrstuvwxyz1234567890';
  364. $random_name = substr(str_shuffle($letters), 0, 24);
  365. try {
  366. $stmt = $pdo->prepare("INSERT INTO `spamalias` (`address`, `goto`, `validity`) VALUES
  367. (:address, :goto, :validity)");
  368. $stmt->execute(array(
  369. ':address' => $random_name . '@' . $domain,
  370. ':goto' => $username,
  371. ':validity' => $validity
  372. ));
  373. }
  374. catch (PDOException $e) {
  375. $_SESSION['return'] = array(
  376. 'type' => 'danger',
  377. 'msg' => 'MySQL: '.$e
  378. );
  379. return false;
  380. }
  381. $_SESSION['return'] = array(
  382. 'type' => 'success',
  383. 'msg' => sprintf($lang['success']['mailbox_modified'], htmlspecialchars($username))
  384. );
  385. break;
  386. case "deleteall":
  387. try {
  388. $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `goto` = :username");
  389. $stmt->execute(array(
  390. ':username' => $username
  391. ));
  392. }
  393. catch (PDOException $e) {
  394. $_SESSION['return'] = array(
  395. 'type' => 'danger',
  396. 'msg' => 'MySQL: '.$e
  397. );
  398. return false;
  399. }
  400. $_SESSION['return'] = array(
  401. 'type' => 'success',
  402. 'msg' => sprintf($lang['success']['mailbox_modified'], htmlspecialchars($username))
  403. );
  404. break;
  405. case "delete":
  406. if (empty($postarray['item']) || !filter_var($postarray['item'], FILTER_VALIDATE_EMAIL)) {
  407. $_SESSION['return'] = array(
  408. 'type' => 'danger',
  409. 'msg' => sprintf($lang['danger']['access_denied'])
  410. );
  411. return false;
  412. }
  413. $item = $postarray['item'];
  414. try {
  415. $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `goto` = :username AND `address` = :item");
  416. $stmt->execute(array(
  417. ':username' => $username,
  418. ':item' => $item
  419. ));
  420. }
  421. catch (PDOException $e) {
  422. $_SESSION['return'] = array(
  423. 'type' => 'danger',
  424. 'msg' => 'MySQL: '.$e
  425. );
  426. return false;
  427. }
  428. $_SESSION['return'] = array(
  429. 'type' => 'success',
  430. 'msg' => sprintf($lang['success']['mailbox_modified'], htmlspecialchars($username))
  431. );
  432. break;
  433. case "extendall":
  434. try {
  435. $stmt = $pdo->prepare("UPDATE `spamalias` SET `validity` = (`validity` + 3600) WHERE
  436. `goto` = :username AND
  437. `validity` >= :validity");
  438. $stmt->execute(array(
  439. ':username' => $username,
  440. ':validity' => time(),
  441. ));
  442. }
  443. catch (PDOException $e) {
  444. $_SESSION['return'] = array(
  445. 'type' => 'danger',
  446. 'msg' => 'MySQL: '.$e
  447. );
  448. return false;
  449. }
  450. $_SESSION['return'] = array(
  451. 'type' => 'success',
  452. 'msg' => sprintf($lang['success']['mailbox_modified'], htmlspecialchars($username))
  453. );
  454. break;
  455. case "extend":
  456. if (empty($postarray['item']) || !filter_var($postarray['item'], FILTER_VALIDATE_EMAIL)) {
  457. $_SESSION['return'] = array(
  458. 'type' => 'danger',
  459. 'msg' => sprintf($lang['danger']['access_denied'])
  460. );
  461. return false;
  462. }
  463. $item = $postarray['item'];
  464. try {
  465. $stmt = $pdo->prepare("UPDATE `spamalias` SET `validity` = (`validity` + 3600) WHERE
  466. `goto` = :username AND
  467. `address` = :item AND
  468. `validity` >= :validity");
  469. $stmt->execute(array(
  470. ':username' => $username,
  471. ':item' => $item,
  472. ':validity' => time(),
  473. ));
  474. }
  475. catch (PDOException $e) {
  476. $_SESSION['return'] = array(
  477. 'type' => 'danger',
  478. 'msg' => 'MySQL: '.$e
  479. );
  480. return false;
  481. }
  482. $_SESSION['return'] = array(
  483. 'type' => 'success',
  484. 'msg' => sprintf($lang['success']['mailbox_modified'], htmlspecialchars($username))
  485. );
  486. break;
  487. }
  488. }
  489. function get_time_limited_aliases($username = null) {
  490. // 'username' can be be set, if not, default to mailcow_cc_username
  491. global $lang;
  492. global $pdo;
  493. $data = array();
  494. if (isset($username) && filter_var($username, FILTER_VALIDATE_EMAIL)) {
  495. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
  496. $_SESSION['return'] = array(
  497. 'type' => 'danger',
  498. 'msg' => sprintf($lang['danger']['access_denied'])
  499. );
  500. return false;
  501. }
  502. }
  503. else {
  504. $username = $_SESSION['mailcow_cc_username'];
  505. }
  506. try {
  507. $stmt = $pdo->prepare("SELECT `address`,
  508. `goto`,
  509. `validity`
  510. FROM `spamalias`
  511. WHERE `goto` = :username
  512. AND `validity` >= :unixnow");
  513. $stmt->execute(array(':username' => $username, ':unixnow' => time()));
  514. $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
  515. }
  516. catch(PDOException $e) {
  517. $_SESSION['return'] = array(
  518. 'type' => 'danger',
  519. 'msg' => 'MySQL: '.$e
  520. );
  521. }
  522. return $data;
  523. }
  524. function edit_user_account($postarray) {
  525. global $lang;
  526. global $pdo;
  527. if (isset($postarray['username']) && filter_var($postarray['username'], FILTER_VALIDATE_EMAIL)) {
  528. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $postarray['username'])) {
  529. $_SESSION['return'] = array(
  530. 'type' => 'danger',
  531. 'msg' => sprintf($lang['danger']['access_denied'])
  532. );
  533. return false;
  534. }
  535. else {
  536. $username = $postarray['username'];
  537. }
  538. }
  539. else {
  540. $username = $_SESSION['mailcow_cc_username'];
  541. }
  542. $password_old = $postarray['user_old_pass'];
  543. isset($postarray['togglePwNew']) ? $pwnew_active = '1' : $pwnew_active = '0';
  544. if (isset($pwnew_active) && $pwnew_active == "1") {
  545. $password_new = $postarray['user_new_pass'];
  546. $password_new2 = $postarray['user_new_pass2'];
  547. }
  548. if (!check_login($username, $password_old) == "user") {
  549. $_SESSION['return'] = array(
  550. 'type' => 'danger',
  551. 'msg' => sprintf($lang['danger']['access_denied'])
  552. );
  553. return false;
  554. }
  555. if (isset($password_new) && isset($password_new2)) {
  556. if (!empty($password_new2) && !empty($password_new)) {
  557. if ($password_new2 != $password_new) {
  558. $_SESSION['return'] = array(
  559. 'type' => 'danger',
  560. 'msg' => sprintf($lang['danger']['password_mismatch'])
  561. );
  562. return false;
  563. }
  564. if (strlen($password_new) < "6" ||
  565. !preg_match('/[A-Za-z]/', $password_new) ||
  566. !preg_match('/[0-9]/', $password_new)) {
  567. $_SESSION['return'] = array(
  568. 'type' => 'danger',
  569. 'msg' => sprintf($lang['danger']['password_complexity'])
  570. );
  571. return false;
  572. }
  573. $password_hashed = hash_password($password_new);
  574. try {
  575. $stmt = $pdo->prepare("UPDATE `mailbox` SET `modified` = :modified, `password` = :password_hashed WHERE `username` = :username");
  576. $stmt->execute(array(
  577. ':password_hashed' => $password_hashed,
  578. ':modified' => date('Y-m-d H:i:s'),
  579. ':username' => $username
  580. ));
  581. }
  582. catch (PDOException $e) {
  583. $_SESSION['return'] = array(
  584. 'type' => 'danger',
  585. 'msg' => 'MySQL: '.$e
  586. );
  587. return false;
  588. }
  589. }
  590. }
  591. $_SESSION['return'] = array(
  592. 'type' => 'success',
  593. 'msg' => sprintf($lang['success']['mailbox_modified'], $username)
  594. );
  595. }
  596. function get_spam_score($username = null) {
  597. global $pdo;
  598. $default = "5, 15";
  599. if (isset($username) && filter_var($username, FILTER_VALIDATE_EMAIL)) {
  600. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
  601. return false;
  602. }
  603. }
  604. else {
  605. $username = $_SESSION['mailcow_cc_username'];
  606. }
  607. try {
  608. $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `object` = :username AND
  609. (`option` = 'lowspamlevel' OR `option` = 'highspamlevel')");
  610. $stmt->execute(array(':username' => $username));
  611. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  612. }
  613. catch(PDOException $e) {
  614. $_SESSION['return'] = array(
  615. 'type' => 'danger',
  616. 'msg' => 'MySQL: '.$e
  617. );
  618. return false;
  619. }
  620. if (empty($num_results)) {
  621. return $default;
  622. }
  623. else {
  624. try {
  625. $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `option` = 'highspamlevel' AND `object` = :username");
  626. $stmt->execute(array(':username' => $username));
  627. $highspamlevel = $stmt->fetch(PDO::FETCH_ASSOC);
  628. $stmt = $pdo->prepare("SELECT `value` FROM `filterconf` WHERE `option` = 'lowspamlevel' AND `object` = :username");
  629. $stmt->execute(array(':username' => $username));
  630. $lowspamlevel = $stmt->fetch(PDO::FETCH_ASSOC);
  631. return $lowspamlevel['value'].', '.$highspamlevel['value'];
  632. }
  633. catch(PDOException $e) {
  634. $_SESSION['return'] = array(
  635. 'type' => 'danger',
  636. 'msg' => 'MySQL: '.$e
  637. );
  638. return false;
  639. }
  640. }
  641. }
  642. function edit_spam_score($postarray) {
  643. // Array items
  644. // 'username' can be set, defaults to mailcow_cc_username
  645. // 'lowspamlevel'
  646. // 'highspamlevel'
  647. global $lang;
  648. global $pdo;
  649. if (isset($postarray['username']) && filter_var($postarray['username'], FILTER_VALIDATE_EMAIL)) {
  650. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $postarray['username'])) {
  651. $_SESSION['return'] = array(
  652. 'type' => 'danger',
  653. 'msg' => sprintf($lang['danger']['access_denied'])
  654. );
  655. return false;
  656. }
  657. else {
  658. $username = $postarray['username'];
  659. }
  660. }
  661. else {
  662. $username = $_SESSION['mailcow_cc_username'];
  663. }
  664. $lowspamlevel = explode(',', $postarray['score'])[0];
  665. $highspamlevel = explode(',', $postarray['score'])[1];
  666. if (!is_numeric($lowspamlevel) || !is_numeric($highspamlevel)) {
  667. $_SESSION['return'] = array(
  668. 'type' => 'danger',
  669. 'msg' => sprintf($lang['danger']['access_denied'])
  670. );
  671. return false;
  672. }
  673. try {
  674. $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username
  675. AND (`option` = 'lowspamlevel' OR `option` = 'highspamlevel')");
  676. $stmt->execute(array(
  677. ':username' => $username
  678. ));
  679. $stmt = $pdo->prepare("INSERT INTO `filterconf` (`object`, `option`, `value`)
  680. VALUES (:username, 'highspamlevel', :highspamlevel)");
  681. $stmt->execute(array(
  682. ':username' => $username,
  683. ':highspamlevel' => $highspamlevel
  684. ));
  685. $stmt = $pdo->prepare("INSERT INTO `filterconf` (`object`, `option`, `value`)
  686. VALUES (:username, 'lowspamlevel', :lowspamlevel)");
  687. $stmt->execute(array(
  688. ':username' => $username,
  689. ':lowspamlevel' => $lowspamlevel
  690. ));
  691. }
  692. catch (PDOException $e) {
  693. $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username
  694. AND (`option` = 'lowspamlevel' OR `option` = 'highspamlevel')");
  695. $stmt->execute(array(
  696. ':username' => $username
  697. ));
  698. $_SESSION['return'] = array(
  699. 'type' => 'danger',
  700. 'msg' => 'MySQL: '.$e
  701. );
  702. return false;
  703. }
  704. $_SESSION['return'] = array(
  705. 'type' => 'success',
  706. 'msg' => sprintf($lang['success']['mailbox_modified'], $username)
  707. );
  708. }
  709. function get_policy_list($object = null) {
  710. // 'object' can be be set, if not, default to mailcow_cc_username
  711. global $lang;
  712. global $pdo;
  713. if (isset($object)) {
  714. if (!filter_var($object, FILTER_VALIDATE_EMAIL) && is_valid_domain_name($object)) {
  715. $object = idn_to_ascii(strtolower(trim($object)));
  716. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) {
  717. $_SESSION['return'] = array(
  718. 'type' => 'danger',
  719. 'msg' => sprintf($lang['danger']['access_denied'])
  720. );
  721. return false;
  722. }
  723. }
  724. elseif (filter_var($object, FILTER_VALIDATE_EMAIL)) {
  725. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) {
  726. $_SESSION['return'] = array(
  727. 'type' => 'danger',
  728. 'msg' => sprintf($lang['danger']['access_denied'])
  729. );
  730. return false;
  731. }
  732. }
  733. }
  734. else {
  735. $object = $_SESSION['mailcow_cc_username'];
  736. }
  737. try {
  738. // WHITELIST
  739. $stmt = $pdo->prepare("SELECT `object`, `value`, `prefid` FROM `filterconf` WHERE `option`='whitelist_from' AND (`object` = :username OR `object` = SUBSTRING_INDEX(:username_domain, '@' ,-1))");
  740. $stmt->execute(array(':username' => $object, ':username_domain' => $object));
  741. $rows['whitelist'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
  742. // BLACKLIST
  743. $stmt = $pdo->prepare("SELECT `object`, `value`, `prefid` FROM `filterconf` WHERE `option`='blacklist_from' AND (`object` = :username OR `object` = SUBSTRING_INDEX(:username_domain, '@' ,-1))");
  744. $stmt->execute(array(':username' => $object, ':username_domain' => $object));
  745. $rows['blacklist'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
  746. }
  747. catch(PDOException $e) {
  748. $_SESSION['return'] = array(
  749. 'type' => 'danger',
  750. 'msg' => 'MySQL: '.$e
  751. );
  752. }
  753. return $rows;
  754. }
  755. function add_policy_list_item($postarray) {
  756. // Array data
  757. // Either 'domain' or 'username' can be be set
  758. // If none of the above is set, default to mailcow_cc_username
  759. //
  760. // If 'delete_prefid' then delete item id
  761. global $lang;
  762. global $pdo;
  763. (isset($postarray['username'])) ? $object = $postarray['username'] : null;
  764. (isset($postarray['domain'])) ? $object = $postarray['domain'] : null;
  765. (!isset($object)) ? $object = $_SESSION['mailcow_cc_username'] : null;
  766. if (is_valid_domain_name($object)) {
  767. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) {
  768. $_SESSION['return'] = array(
  769. 'type' => 'danger',
  770. 'msg' => sprintf($lang['danger']['access_denied'])
  771. );
  772. return false;
  773. }
  774. $object = idn_to_ascii(strtolower(trim($object)));
  775. }
  776. else {
  777. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) {
  778. $_SESSION['return'] = array(
  779. 'type' => 'danger',
  780. 'msg' => sprintf($lang['danger']['access_denied'])
  781. );
  782. return false;
  783. }
  784. }
  785. ($postarray['object_list'] == "bl") ? $object_list = "blacklist_from" : null;
  786. ($postarray['object_list'] == "wl") ? $object_list = "whitelist_from" : null;
  787. $object_from = preg_replace('/\.+/', '.', rtrim(preg_replace("/\.\*/", "*", trim(strtolower($postarray['object_from']))), '.'));
  788. if (!ctype_alnum(str_replace(array('@', '.', '-', '*'), '', $object_from))) {
  789. $_SESSION['return'] = array(
  790. 'type' => 'danger',
  791. 'msg' => sprintf($lang['danger']['policy_list_from_invalid'])
  792. );
  793. return false;
  794. }
  795. if ($object_list != "blacklist_from" && $object_list != "whitelist_from") {
  796. $_SESSION['return'] = array(
  797. 'type' => 'danger',
  798. 'msg' => sprintf($lang['danger']['access_denied'])
  799. );
  800. return false;
  801. }
  802. try {
  803. $stmt = $pdo->prepare("SELECT `object` FROM `filterconf`
  804. WHERE (`option` = 'whitelist_from' OR `option` = 'blacklist_from')
  805. AND `object` = :object
  806. AND `value` = :object_from");
  807. $stmt->execute(array(':object' => $object, ':object_from' => $object_from));
  808. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  809. if ($num_results != 0) {
  810. $_SESSION['return'] = array(
  811. 'type' => 'danger',
  812. 'msg' => sprintf($lang['danger']['policy_list_from_exists'])
  813. );
  814. return false;
  815. }
  816. }
  817. catch(PDOException $e) {
  818. $_SESSION['return'] = array(
  819. 'type' => 'danger',
  820. 'msg' => 'MySQL: '.$e
  821. );
  822. return false;
  823. }
  824. try {
  825. $stmt = $pdo->prepare("INSERT INTO `filterconf` (`object`, `option` ,`value`)
  826. VALUES (:object, :object_list, :object_from)");
  827. $stmt->execute(array(
  828. ':object' => $object,
  829. ':object_list' => $object_list,
  830. ':object_from' => $object_from
  831. ));
  832. }
  833. catch (PDOException $e) {
  834. $_SESSION['return'] = array(
  835. 'type' => 'danger',
  836. 'msg' => 'MySQL: '.$e
  837. );
  838. return false;
  839. }
  840. $_SESSION['return'] = array(
  841. 'type' => 'success',
  842. 'msg' => sprintf($lang['success']['object_modified'], $object)
  843. );
  844. }
  845. function delete_policy_list_item($postarray) {
  846. // Array data
  847. // Either 'domain' or 'username' can be be set
  848. // If none of the above is set, default to mailcow_cc_username
  849. //
  850. // 'delete_prefid' is item to be deleted
  851. global $lang;
  852. global $pdo;
  853. (isset($postarray['username'])) ? $object = $postarray['username'] : null;
  854. (isset($postarray['domain'])) ? $object = $postarray['domain'] : null;
  855. (!isset($object)) ? $object = $_SESSION['mailcow_cc_username'] : null;
  856. if (is_valid_domain_name($object)) {
  857. if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) {
  858. $_SESSION['return'] = array(
  859. 'type' => 'danger',
  860. 'msg' => sprintf($lang['danger']['access_denied'])
  861. );
  862. return false;
  863. }
  864. $object = idn_to_ascii(strtolower(trim($object)));
  865. }
  866. else {
  867. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)) {
  868. $_SESSION['return'] = array(
  869. 'type' => 'danger',
  870. 'msg' => sprintf($lang['danger']['access_denied'])
  871. );
  872. return false;
  873. }
  874. }
  875. if (!is_numeric($postarray['delete_prefid'])) {
  876. $_SESSION['return'] = array(
  877. 'type' => 'danger',
  878. 'msg' => sprintf($lang['danger']['access_denied'])
  879. );
  880. return false;
  881. }
  882. try {
  883. $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :object AND `prefid` = :prefid");
  884. $stmt->execute(array(
  885. ':object' => $object,
  886. ':prefid' => $postarray['delete_prefid']
  887. ));
  888. }
  889. catch (PDOException $e) {
  890. $_SESSION['return'] = array(
  891. 'type' => 'danger',
  892. 'msg' => 'MySQL: '.$e
  893. );
  894. return false;
  895. }
  896. $_SESSION['return'] = array(
  897. 'type' => 'success',
  898. 'msg' => sprintf($lang['success']['object_modified'], $object)
  899. );
  900. return true;
  901. }
  902. function get_syncjobs($username = null) {
  903. // 'username' can be be set, if not, default to mailcow_cc_username
  904. global $lang;
  905. global $pdo;
  906. $data = array();
  907. if (isset($username) && filter_var($username, FILTER_VALIDATE_EMAIL)) {
  908. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
  909. $_SESSION['return'] = array(
  910. 'type' => 'danger',
  911. 'msg' => sprintf($lang['danger']['access_denied'])
  912. );
  913. return false;
  914. }
  915. }
  916. else {
  917. $username = $_SESSION['mailcow_cc_username'];
  918. }
  919. try {
  920. $stmt = $pdo->prepare("SELECT *, CONCAT(LEFT(`password1`, 3), '…') as `password1_short`
  921. FROM `imapsync`
  922. WHERE `user2` = :username");
  923. $stmt->execute(array(':username' => $username));
  924. $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
  925. }
  926. catch(PDOException $e) {
  927. $_SESSION['return'] = array(
  928. 'type' => 'danger',
  929. 'msg' => 'MySQL: '.$e
  930. );
  931. }
  932. return $data;
  933. }
  934. function get_syncjob_details($id) {
  935. global $lang;
  936. global $pdo;
  937. $syncjobdetails = array();
  938. if ($_SESSION['mailcow_cc_role'] != "user" &&
  939. $_SESSION['mailcow_cc_role'] != "admin") {
  940. $_SESSION['return'] = array(
  941. 'type' => 'danger',
  942. 'msg' => sprintf($lang['danger']['access_denied'])
  943. );
  944. return false;
  945. }
  946. if (!is_numeric($id)) {
  947. $_SESSION['return'] = array(
  948. 'type' => 'danger',
  949. 'msg' => sprintf($lang['danger']['access_denied'])
  950. );
  951. return false;
  952. }
  953. try {
  954. $stmt = $pdo->prepare("SELECT * FROM `imapsync` WHERE (`user2` = :username OR 'admin' = :role) AND id = :id");
  955. $stmt->execute(array(':id' => $id, ':role' => $_SESSION['mailcow_cc_role'], ':username' => $_SESSION['mailcow_cc_username']));
  956. $syncjobdetails = $stmt->fetch(PDO::FETCH_ASSOC);
  957. }
  958. catch(PDOException $e) {
  959. $_SESSION['return'] = array(
  960. 'type' => 'danger',
  961. 'msg' => 'MySQL: '.$e
  962. );
  963. }
  964. return $syncjobdetails;
  965. }
  966. function delete_syncjob($postarray) {
  967. // Array items
  968. // 'username' can be set, defaults to mailcow_cc_username
  969. global $lang;
  970. global $pdo;
  971. if (isset($postarray['username']) && filter_var($postarray['username'], FILTER_VALIDATE_EMAIL)) {
  972. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $postarray['username'])) {
  973. $_SESSION['return'] = array(
  974. 'type' => 'danger',
  975. 'msg' => sprintf($lang['danger']['access_denied'])
  976. );
  977. return false;
  978. }
  979. else {
  980. $username = $postarray['username'];
  981. }
  982. }
  983. else {
  984. $username = $_SESSION['mailcow_cc_username'];
  985. }
  986. $id = $postarray['id'];
  987. if (!is_numeric($id)) {
  988. $_SESSION['return'] = array(
  989. 'type' => 'danger',
  990. 'msg' => sprintf($lang['danger']['access_denied'])
  991. );
  992. return false;
  993. }
  994. try {
  995. $stmt = $pdo->prepare("DELETE FROM `imapsync` WHERE `user2` = :username AND `id`= :id");
  996. $stmt->execute(array(
  997. ':username' => $username,
  998. ':id' => $id,
  999. ));
  1000. }
  1001. catch (PDOException $e) {
  1002. $_SESSION['return'] = array(
  1003. 'type' => 'danger',
  1004. 'msg' => 'MySQL: '.$e
  1005. );
  1006. return false;
  1007. }
  1008. $_SESSION['return'] = array(
  1009. 'type' => 'success',
  1010. 'msg' => sprintf($lang['success']['mailbox_modified'], htmlspecialchars($username))
  1011. );
  1012. return true;
  1013. }
  1014. function add_syncjob($postarray) {
  1015. // Array items
  1016. // 'username' can be set, defaults to mailcow_cc_username
  1017. global $lang;
  1018. global $pdo;
  1019. if (isset($postarray['username']) && filter_var($postarray['username'], FILTER_VALIDATE_EMAIL)) {
  1020. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $postarray['username'])) {
  1021. $_SESSION['return'] = array(
  1022. 'type' => 'danger',
  1023. 'msg' => sprintf($lang['danger']['access_denied'])
  1024. );
  1025. return false;
  1026. }
  1027. else {
  1028. $username = $postarray['username'];
  1029. }
  1030. }
  1031. else {
  1032. $username = $_SESSION['mailcow_cc_username'];
  1033. }
  1034. isset($postarray['active']) ? $active = '1' : $active = '0';
  1035. isset($postarray['delete2duplicates']) ? $delete2duplicates = '1' : $delete2duplicates = '0';
  1036. $port1 = $postarray['port1'];
  1037. $host1 = $postarray['host1'];
  1038. $password1 = $postarray['password1'];
  1039. $exclude = $postarray['exclude'];
  1040. $maxage = $postarray['maxage'];
  1041. $subfolder2 = $postarray['subfolder2'];
  1042. $user1 = $postarray['user1'];
  1043. $mins_interval = $postarray['mins_interval'];
  1044. $enc1 = $postarray['enc1'];
  1045. if (empty($subfolder2)) {
  1046. $subfolder2 = "";
  1047. }
  1048. if (!isset($maxage) || !filter_var($maxage, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32767)))) {
  1049. $maxage = "0";
  1050. }
  1051. if (!filter_var($port1, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 65535)))) {
  1052. $_SESSION['return'] = array(
  1053. 'type' => 'danger',
  1054. 'msg' => sprintf($lang['danger']['access_denied'])
  1055. );
  1056. return false;
  1057. }
  1058. if (!filter_var($mins_interval, FILTER_VALIDATE_INT, array('options' => array('min_range' => 10, 'max_range' => 3600)))) {
  1059. $_SESSION['return'] = array(
  1060. 'type' => 'danger',
  1061. 'msg' => sprintf($lang['danger']['access_denied'])
  1062. );
  1063. return false;
  1064. }
  1065. if (!is_valid_domain_name($host1)) {
  1066. $_SESSION['return'] = array(
  1067. 'type' => 'danger',
  1068. 'msg' => sprintf($lang['danger']['access_denied'])
  1069. );
  1070. return false;
  1071. }
  1072. if ($enc1 != "TLS" && $enc1 != "SSL" && $enc1 != "PLAIN") {
  1073. $_SESSION['return'] = array(
  1074. 'type' => 'danger',
  1075. 'msg' => sprintf($lang['danger']['access_denied'])
  1076. );
  1077. return false;
  1078. }
  1079. if (@preg_match("/" . $exclude . "/", null) === false) {
  1080. $_SESSION['return'] = array(
  1081. 'type' => 'danger',
  1082. 'msg' => sprintf($lang['danger']['access_denied'])
  1083. );
  1084. return false;
  1085. }
  1086. try {
  1087. $stmt = $pdo->prepare("SELECT `user2`, `user1` FROM `imapsync`
  1088. WHERE `user2` = :user2 AND `user1` = :user1");
  1089. $stmt->execute(array(':user1' => $user1, ':user2' => $username));
  1090. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  1091. }
  1092. catch(PDOException $e) {
  1093. $_SESSION['return'] = array(
  1094. 'type' => 'danger',
  1095. 'msg' => 'MySQL: '.$e
  1096. );
  1097. return false;
  1098. }
  1099. if ($num_results != 0) {
  1100. $_SESSION['return'] = array(
  1101. 'type' => 'danger',
  1102. 'msg' => sprintf($lang['danger']['object_exists'], htmlspecialchars($host1 . ' / ' . $user1))
  1103. );
  1104. return false;
  1105. }
  1106. try {
  1107. $stmt = $pdo->prepare("INSERT INTO `imapsync` (`user2`, `exclude`, `maxage`, `subfolder2`, `host1`, `authmech1`, `user1`, `password1`, `mins_interval`, `port1`, `enc1`, `delete2duplicates`, `active`)
  1108. VALUES (:user2, :exclude, :maxage, :subfolder2, :host1, :authmech1, :user1, :password1, :mins_interval, :port1, :enc1, :delete2duplicates, :active)");
  1109. $stmt->execute(array(
  1110. ':user2' => $username,
  1111. ':exclude' => $exclude,
  1112. ':maxage' => $maxage,
  1113. ':subfolder2' => $subfolder2,
  1114. ':host1' => $host1,
  1115. ':authmech1' => 'PLAIN',
  1116. ':user1' => $user1,
  1117. ':password1' => $password1,
  1118. ':mins_interval' => $mins_interval,
  1119. ':port1' => $port1,
  1120. ':enc1' => $enc1,
  1121. ':delete2duplicates' => $delete2duplicates,
  1122. ':active' => $active,
  1123. ));
  1124. }
  1125. catch(PDOException $e) {
  1126. $_SESSION['return'] = array(
  1127. 'type' => 'danger',
  1128. 'msg' => 'MySQL: '.$e
  1129. );
  1130. return false;
  1131. }
  1132. $_SESSION['return'] = array(
  1133. 'type' => 'success',
  1134. 'msg' => sprintf($lang['success']['mailbox_modified'], $username)
  1135. );
  1136. return true;
  1137. }
  1138. function edit_syncjob($postarray) {
  1139. // Array items
  1140. // 'username' can be set, defaults to mailcow_cc_username
  1141. global $lang;
  1142. global $pdo;
  1143. if (isset($postarray['username']) && filter_var($postarray['username'], FILTER_VALIDATE_EMAIL)) {
  1144. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $postarray['username'])) {
  1145. $_SESSION['return'] = array(
  1146. 'type' => 'danger',
  1147. 'msg' => sprintf($lang['danger']['access_denied'])
  1148. );
  1149. return false;
  1150. }
  1151. else {
  1152. $username = $postarray['username'];
  1153. }
  1154. }
  1155. else {
  1156. $username = $_SESSION['mailcow_cc_username'];
  1157. }
  1158. isset($postarray['active']) ? $active = '1' : $active = '0';
  1159. isset($postarray['delete2duplicates']) ? $delete2duplicates = '1' : $delete2duplicates = '0';
  1160. $id = $postarray['id'];
  1161. $port1 = $postarray['port1'];
  1162. $host1 = $postarray['host1'];
  1163. $password1 = $postarray['password1'];
  1164. $exclude = $postarray['exclude'];
  1165. $maxage = $postarray['maxage'];
  1166. $subfolder2 = $postarray['subfolder2'];
  1167. $user1 = $postarray['user1'];
  1168. $mins_interval = $postarray['mins_interval'];
  1169. $enc1 = $postarray['enc1'];
  1170. if (empty($subfolder2)) {
  1171. $subfolder2 = "";
  1172. }
  1173. if (!isset($maxage) || !filter_var($maxage, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32767)))) {
  1174. $maxage = "0";
  1175. }
  1176. if (!filter_var($port1, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 65535)))) {
  1177. $_SESSION['return'] = array(
  1178. 'type' => 'danger',
  1179. 'msg' => sprintf($lang['danger']['access_denied'])
  1180. );
  1181. return false;
  1182. }
  1183. if (!filter_var($mins_interval, FILTER_VALIDATE_INT, array('options' => array('min_range' => 10, 'max_range' => 3600)))) {
  1184. $_SESSION['return'] = array(
  1185. 'type' => 'danger',
  1186. 'msg' => sprintf($lang['danger']['access_denied'])
  1187. );
  1188. return false;
  1189. }
  1190. if (!is_valid_domain_name($host1)) {
  1191. $_SESSION['return'] = array(
  1192. 'type' => 'danger',
  1193. 'msg' => sprintf($lang['danger']['access_denied'])
  1194. );
  1195. return false;
  1196. }
  1197. if ($enc1 != "TLS" && $enc1 != "SSL" && $enc1 != "PLAIN") {
  1198. $_SESSION['return'] = array(
  1199. 'type' => 'danger',
  1200. 'msg' => sprintf($lang['danger']['access_denied'])
  1201. );
  1202. return false;
  1203. }
  1204. if (@preg_match("/" . $exclude . "/", null) === false) {
  1205. $_SESSION['return'] = array(
  1206. 'type' => 'danger',
  1207. 'msg' => sprintf($lang['danger']['access_denied'])
  1208. );
  1209. return false;
  1210. }
  1211. try {
  1212. $stmt = $pdo->prepare("SELECT `user2` FROM `imapsync`
  1213. WHERE `user2` = :user2 AND `id` = :id");
  1214. $stmt->execute(array(':user2' => $username, ':id' => $id));
  1215. $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  1216. }
  1217. catch(PDOException $e) {
  1218. $_SESSION['return'] = array(
  1219. 'type' => 'danger',
  1220. 'msg' => 'MySQL: '.$e
  1221. );
  1222. return false;
  1223. }
  1224. if (empty($num_results)) {
  1225. $_SESSION['return'] = array(
  1226. 'type' => 'danger',
  1227. 'msg' => sprintf($lang['danger']['access_denied'])
  1228. );
  1229. return false;
  1230. }
  1231. try {
  1232. $stmt = $pdo->prepare("UPDATE `imapsync` set `maxage` = :maxage, `subfolder2` = :subfolder2, `exclude` = :exclude, `host1` = :host1, `user1` = :user1, `password1` = :password1, `mins_interval` = :mins_interval, `port1` = :port1, `enc1` = :enc1, `delete2duplicates` = :delete2duplicates, `active` = :active
  1233. WHERE `user2` = :user2 AND `id` = :id");
  1234. $stmt->execute(array(
  1235. ':user2' => $username,
  1236. ':id' => $id,
  1237. ':exclude' => $exclude,
  1238. ':maxage' => $maxage,
  1239. ':subfolder2' => $subfolder2,
  1240. ':host1' => $host1,
  1241. ':user1' => $user1,
  1242. ':password1' => $password1,
  1243. ':mins_interval' => $mins_interval,
  1244. ':port1' => $port1,
  1245. ':enc1' => $enc1,
  1246. ':delete2duplicates' => $delete2duplicates,
  1247. ':active' => $active,
  1248. ));
  1249. }
  1250. catch(PDOException $e) {
  1251. $_SESSION['return'] = array(
  1252. 'type' => 'danger',
  1253. 'msg' => 'MySQL: '.$e
  1254. );
  1255. return false;
  1256. }
  1257. $_SESSION['return'] = array(
  1258. 'type' => 'success',
  1259. 'msg' => sprintf($lang['success']['mailbox_modified'], $username)
  1260. );
  1261. return true;
  1262. }
  1263. function edit_tls_policy($postarray) {
  1264. global $lang;
  1265. global $pdo;
  1266. if (isset($postarray['username']) && filter_var($postarray['username'], FILTER_VALIDATE_EMAIL)) {
  1267. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $postarray['username'])) {
  1268. $_SESSION['return'] = array(
  1269. 'type' => 'danger',
  1270. 'msg' => sprintf($lang['danger']['access_denied'])
  1271. );
  1272. return false;
  1273. }
  1274. else {
  1275. $username = $postarray['username'];
  1276. }
  1277. }
  1278. else {
  1279. $username = $_SESSION['mailcow_cc_username'];
  1280. }
  1281. isset($postarray['tls_in']) ? $tls_in = '1' : $tls_in = '0';
  1282. isset($postarray['tls_out']) ? $tls_out = '1' : $tls_out = '0';
  1283. $username = $_SESSION['mailcow_cc_username'];
  1284. if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
  1285. $_SESSION['return'] = array(
  1286. 'type' => 'danger',
  1287. 'msg' => sprintf($lang['danger']['username_invalid'])
  1288. );
  1289. return false;
  1290. }
  1291. try {
  1292. $stmt = $pdo->prepare("UPDATE `mailbox` SET `tls_enforce_out` = :tls_out, `tls_enforce_in` = :tls_in WHERE `username` = :username");
  1293. $stmt->execute(array(
  1294. ':tls_out' => $tls_out,
  1295. ':tls_in' => $tls_in,
  1296. ':username' => $username
  1297. ));
  1298. }
  1299. catch (PDOException $e) {
  1300. $_SESSION['return'] = array(
  1301. 'type' => 'danger',
  1302. 'msg' => 'MySQL: '.$e
  1303. );
  1304. return false;
  1305. }
  1306. $_SESSION['return'] = array(
  1307. 'type' => 'success',
  1308. 'msg' => sprintf($lang['success']['mailbox_modified'], $username)
  1309. );
  1310. }
  1311. function get_tls_policy($username = null) {
  1312. global $lang;
  1313. global $pdo;
  1314. $data = array();
  1315. if (isset($username) && filter_var($username, FILTER_VALIDATE_EMAIL)) {
  1316. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
  1317. $_SESSION['return'] = array(
  1318. 'type' => 'danger',
  1319. 'msg' => sprintf($lang['danger']['access_denied'])
  1320. );
  1321. return false;
  1322. }
  1323. }
  1324. else {
  1325. $username = $_SESSION['mailcow_cc_username'];
  1326. }
  1327. try {
  1328. $stmt = $pdo->prepare("SELECT `tls_enforce_out`, `tls_enforce_in` FROM `mailbox` WHERE `username` = :username");
  1329. $stmt->execute(array(':username' => $username));
  1330. $data = $stmt->fetch(PDO::FETCH_ASSOC);
  1331. }
  1332. catch(PDOException $e) {
  1333. $_SESSION['return'] = array(
  1334. 'type' => 'danger',
  1335. 'msg' => 'MySQL: '.$e
  1336. );
  1337. return false;
  1338. }
  1339. return $data;
  1340. }
  1341. function edit_delimiter_action($postarray) {
  1342. // Array items
  1343. // 'username' can be set, defaults to mailcow_cc_username
  1344. global $lang;
  1345. global $pdo;
  1346. if (isset($postarray['username']) && filter_var($postarray['username'], FILTER_VALIDATE_EMAIL)) {
  1347. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $postarray['username'])) {
  1348. $_SESSION['return'] = array(
  1349. 'type' => 'danger',
  1350. 'msg' => sprintf($lang['danger']['access_denied'])
  1351. );
  1352. return false;
  1353. }
  1354. else {
  1355. $username = $postarray['username'];
  1356. }
  1357. }
  1358. else {
  1359. $username = $_SESSION['mailcow_cc_username'];
  1360. }
  1361. ($postarray['tagged_mail_handler'] == "subject") ? $wants_tagged_subject = '1' : $wants_tagged_subject = '0';
  1362. if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
  1363. $_SESSION['return'] = array(
  1364. 'type' => 'danger',
  1365. 'msg' => sprintf($lang['danger']['username_invalid'])
  1366. );
  1367. return false;
  1368. }
  1369. try {
  1370. $stmt = $pdo->prepare("UPDATE `mailbox` SET `wants_tagged_subject` = :wants_tagged_subject WHERE `username` = :username");
  1371. $stmt->execute(array(':username' => $username, ':wants_tagged_subject' => $wants_tagged_subject));
  1372. $SelectData = $stmt->fetch(PDO::FETCH_ASSOC);
  1373. }
  1374. catch(PDOException $e) {
  1375. $_SESSION['return'] = array(
  1376. 'type' => 'danger',
  1377. 'msg' => 'MySQL: '.$e
  1378. );
  1379. return false;
  1380. }
  1381. $_SESSION['return'] = array(
  1382. 'type' => 'success',
  1383. 'msg' => sprintf($lang['success']['mailbox_modified'], $username)
  1384. );
  1385. return true;
  1386. }
  1387. function get_delimiter_action($username = null) {
  1388. // 'username' can be set, defaults to mailcow_cc_username
  1389. global $lang;
  1390. global $pdo;
  1391. $data = array();
  1392. if (isset($username) && filter_var($username, FILTER_VALIDATE_EMAIL)) {
  1393. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
  1394. return false;
  1395. }
  1396. }
  1397. else {
  1398. $username = $_SESSION['mailcow_cc_username'];
  1399. }
  1400. try {
  1401. $stmt = $pdo->prepare("SELECT `wants_tagged_subject` FROM `mailbox` WHERE `username` = :username");
  1402. $stmt->execute(array(':username' => $username));
  1403. $data = $stmt->fetch(PDO::FETCH_ASSOC);
  1404. }
  1405. catch(PDOException $e) {
  1406. $_SESSION['return'] = array(
  1407. 'type' => 'danger',
  1408. 'msg' => 'MySQL: '.$e
  1409. );
  1410. return false;
  1411. }
  1412. return $data;
  1413. }
  1414. function user_get_alias_details($username) {
  1415. global $lang;
  1416. global $pdo;
  1417. if ($_SESSION['mailcow_cc_role'] == "user") {
  1418. $username = $_SESSION['mailcow_cc_username'];
  1419. }
  1420. if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
  1421. return false;
  1422. }
  1423. try {
  1424. $data['address'] = $username;
  1425. $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '&#10008;') AS `aliases` FROM `alias` WHERE `goto` = :username_goto AND `address` NOT LIKE '@%' AND `address` != :username_address");
  1426. $stmt->execute(array(':username_goto' => $username, ':username_address' => $username));
  1427. $run = $stmt->fetchAll(PDO::FETCH_ASSOC);
  1428. while ($row = array_shift($run)) {
  1429. $data['aliases'] = $row['aliases'];
  1430. }
  1431. $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(local_part, '@', alias_domain SEPARATOR ', '), '&#10008;') AS `ad_alias` FROM `mailbox`
  1432. LEFT OUTER JOIN `alias_domain` on `target_domain` = `domain`
  1433. WHERE `username` = :username ;");
  1434. $stmt->execute(array(':username' => $username));
  1435. $run = $stmt->fetchAll(PDO::FETCH_ASSOC);
  1436. while ($row = array_shift($run)) {
  1437. $data['ad_alias'] = $row['ad_alias'];
  1438. }
  1439. $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`send_as` SEPARATOR ', '), '&#10008;') AS `send_as` FROM `sender_acl` WHERE `logged_in_as` = :username AND `send_as` NOT LIKE '@%';");
  1440. $stmt->execute(array(':username' => $username));
  1441. $run = $stmt->fetchAll(PDO::FETCH_ASSOC);
  1442. while ($row = array_shift($run)) {
  1443. $data['aliases_also_send_as'] = $row['send_as'];
  1444. }
  1445. $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`send_as` SEPARATOR ', '), '&#10008;') AS `send_as` FROM `sender_acl` WHERE `logged_in_as` = :username AND `send_as` LIKE '@%';");
  1446. $stmt->execute(array(':username' => $username));
  1447. $run = $stmt->fetchAll(PDO::FETCH_ASSOC);
  1448. while ($row = array_shift($run)) {
  1449. $data['aliases_send_as_all'] = $row['send_as'];
  1450. }
  1451. $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '&#10008;') as `address` FROM `alias` WHERE `goto` = :username AND `address` LIKE '@%';");
  1452. $stmt->execute(array(':username' => $username));
  1453. $run = $stmt->fetchAll(PDO::FETCH_ASSOC);
  1454. while ($row = array_shift($run)) {
  1455. $data['is_catch_all'] = $row['address'];
  1456. }
  1457. return $data;
  1458. }
  1459. catch(PDOException $e) {
  1460. $_SESSION['return'] = array(
  1461. 'type' => 'danger',
  1462. 'msg' => 'MySQL: '.$e
  1463. );
  1464. return false;
  1465. }
  1466. }
  1467. function is_valid_domain_name($domain_name) {
  1468. if (empty($domain_name)) {
  1469. return false;
  1470. }
  1471. $domain_name = idn_to_ascii($domain_name);
  1472. return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name)
  1473. && preg_match("/^.{1,253}$/", $domain_name)
  1474. && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name));
  1475. }
  1476. ?>