PostfixAdmin - web based virtual user administration interface for Postfix mail servers https://postfixadmin.github.io/postfixadmin/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1761 lines
45 KiB

  1. <?php
  2. //
  3. // Postfix Admin
  4. // by Mischa Peters <mischa at high5 dot net>
  5. // Copyright (c) 2002 - 2005 High5!
  6. // Licensed under GPL for more info check GPL-LICENSE.TXT
  7. //
  8. // File: functions.inc.php
  9. //
  10. //error_reporting (E_NOTICE | E_ERROR | E_WARNING | E_PARSE);
  11. if (ereg ("functions.inc.php", $_SERVER['PHP_SELF']))
  12. {
  13. header ("Location: login.php");
  14. exit;
  15. }
  16. $version = '2.2 SVN';
  17. /**
  18. * check_session
  19. * Action: Check if a session already exists, if not redirect to login.php
  20. * Call: check_session ()
  21. * @return String username (e.g. foo@example.com)
  22. */
  23. function authentication_get_username()
  24. {
  25. global $CONF;
  26. if (!isset($_SESSION['sessid'])) {
  27. header ("Location: " . $CONF['postfix_admin_url'] . "/login.php");
  28. exit(0);
  29. }
  30. $SESSID_USERNAME = $_SESSION['sessid']['username'];
  31. return $SESSID_USERNAME;
  32. }
  33. /**
  34. * Returns the type of user - either 'user' or 'admin'
  35. * Returns false if neither (E.g. if not logged in)
  36. * @return String admin or user or (boolean) false.
  37. */
  38. function authentication_get_usertype() {
  39. if(isset($_SESSION['sessid'])) {
  40. if(isset($_SESSION['sessid']['type'])) {
  41. return $_SESSION['sessid']['type'];
  42. }
  43. }
  44. return false;
  45. }
  46. /**
  47. *
  48. * Used to determine whether a user has a particular role.
  49. * @param String role-name. (E.g. admin, global-admin or user)
  50. * @return boolean True if they have the requested role in their session.
  51. * Note, user < admin < global-admin
  52. */
  53. function authentication_has_role($role) {
  54. global $CONF;
  55. if(isset($_SESSION['sessid'])) {
  56. if(isset($_SESSION['sessid']['roles'])) {
  57. if(in_array($role, $_SESSION['sessid']['roles'])) {
  58. return true;
  59. }
  60. }
  61. }
  62. return false;
  63. }
  64. /**
  65. * Used to enforce that $user has a particular role when
  66. * viewing a page.
  67. * If they are lacking a role, redirect them to
  68. * $CONF['postfix_admin_url']/login.php
  69. *
  70. * Note, user < admin < global-admin
  71. */
  72. function authentication_require_role($role) {
  73. // redirect to appropriate page?
  74. if(authentication_has_role($role)) {
  75. return True;
  76. }
  77. header("Location: " . $CONF['postfix_admin_url'] . "/login.php");
  78. exit(0);
  79. }
  80. /**
  81. * @return boolean TRUE if a admin, FALSE otherwise.
  82. */
  83. function authentication_is_admin() {
  84. return authentication_get_usertype() == 'admin';
  85. }
  86. /**
  87. * @return boolean TRUE if a user, FALSE otherwise.
  88. */
  89. function authentication_is_user() {
  90. return authentication_get_usertype() == 'user';
  91. }
  92. //
  93. // check_language
  94. // Action: checks what language the browser uses
  95. // Call: check_language
  96. //
  97. function check_language ()
  98. {
  99. global $CONF;
  100. $lang = $CONF['default_language'];
  101. $supported_languages = array ('bg', 'ca', 'cn', 'cs', 'da', 'de', 'en', 'es', 'et', 'eu', 'fi', 'fo', 'fr', 'hu', 'is', 'it', 'mk', 'nl', 'nn', 'pl', 'pt-br', 'ru', 'sl', 'sv', 'tr', 'tw');
  102. if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
  103. {
  104. $lang_array = preg_split ('/(\s*,\s*)/', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
  105. for($i = 0; $i < count($lang_array); $i++)
  106. {
  107. $lang_next = $lang_array[$i];
  108. $lang_next = strtolower(substr(trim($lang_next), 0, 2));
  109. if(in_array($lang_next, $supported_languages))
  110. {
  111. $lang = $lang_next;
  112. break;
  113. }
  114. }
  115. }
  116. return $lang;
  117. }
  118. //
  119. // check_string
  120. // Action: checks if a string is valid and returns TRUE if this is the case.
  121. // Call: check_string (string var)
  122. //
  123. function check_string ($var)
  124. {
  125. if (preg_match ('/^([A-Za-z0-9 ]+)+$/', $var))
  126. {
  127. return true;
  128. }
  129. else
  130. {
  131. return false;
  132. }
  133. }
  134. //
  135. // check_domain
  136. // Action: Checks if domain is valid and returns TRUE if this is the case.
  137. // Call: check_domain (string domain)
  138. //
  139. // TODO: make check_domain able to handle as example .local domains
  140. function check_domain ($domain)
  141. {
  142. if (preg_match ('/([-0-9A-Z]+\.)+' . '([0-9A-Z]){2,4}$/i', trim ($domain)))
  143. {
  144. return true;
  145. }
  146. else
  147. {
  148. return false;
  149. }
  150. }
  151. //
  152. // check_email
  153. // Action: Checks if email is valid and returns TRUE if this is the case.
  154. // Call: check_email (string email)
  155. //
  156. // TODO: make check_email able to handle already added domains
  157. function check_email ($email)
  158. {
  159. global $CONF;
  160. $ce_email=$email;
  161. //strip the vacation domain out if we are using it
  162. if ($CONF['vacation'] == 'YES')
  163. {
  164. $vacation_domain = $CONF['vacation_domain'];
  165. $ce_email = preg_replace("/@$vacation_domain/", '', $ce_email);
  166. }
  167. if (
  168. isset($CONF['emailcheck_resolve_domain'])
  169. && 'YES'==$CONF['emailcheck_resolve_domain']
  170. && 'WINDOWS'!=(strtoupper(substr(php_uname('s'), 0, 7)))
  171. ) {
  172. // Perform non-domain-part sanity checks
  173. if (!preg_match ('/^[-!#$%&\'*+\\.\/0-9=?A-Z^_{|}~]+' . '@' . '[^@]+$/i', trim ($ce_email)))
  174. {
  175. return false;
  176. }
  177. // Determine domain name
  178. $matches=array();
  179. if (!preg_match('|@(.+)$|',$ce_email,$matches))
  180. {
  181. return false;
  182. }
  183. $domain=$matches[1];
  184. // Look for an AAAA, A, or MX record for the domain
  185. // AAAA (IPv6) is only available in PHP v. >= 5
  186. if (version_compare(phpversion(), "5.0.0", ">="))
  187. {
  188. if (checkdnsrr($domain,'AAAA')) return true;
  189. }
  190. if (checkdnsrr($domain,'A')) return true;
  191. if (checkdnsrr($domain,'MX')) return true;
  192. return false;
  193. }
  194. if (preg_match ('/^[-!#$%&\'*+\\.\/0-9=?A-Z^_{|}~]+' . '@' . '([-0-9A-Z]+\.)+' . '([0-9A-Z]){2,6}$/i', trim ($ce_email)))
  195. {
  196. return true;
  197. }
  198. else
  199. {
  200. return false;
  201. }
  202. }
  203. //
  204. // escape_string
  205. // Action: Escape a string
  206. // Call: escape_string (string string)
  207. //
  208. (ini_get('magic_quotes_gpc') ? ini_set('magic_quotes_runtime', '0') : '1');
  209. (ini_get('magic_quotes_gpc') ? ini_set('magic_quotes_sybase', '0') : '1');
  210. function escape_string ($string)
  211. {
  212. global $CONF;
  213. if (get_magic_quotes_gpc ())
  214. {
  215. $string = stripslashes($string);
  216. }
  217. if (!is_numeric($string))
  218. {
  219. $link = db_connect();
  220. if ($CONF['database_type'] == "mysql")
  221. {
  222. $escaped_string = mysql_real_escape_string($string, $link);
  223. }
  224. if ($CONF['database_type'] == "mysqli")
  225. {
  226. $escaped_string = mysqli_real_escape_string($link, $string);
  227. }
  228. if ($CONF['database_type'] == "pgsql")
  229. {
  230. // php 5.2+ allows for $link to be specified.
  231. if (version_compare(phpversion(), "5.2.0", ">="))
  232. {
  233. $escaped_string = pg_escape_string($link, $string);
  234. }
  235. else
  236. {
  237. $escaped_string = pg_escape_string($string);
  238. }
  239. }
  240. }
  241. else
  242. {
  243. $escaped_string = $string;
  244. }
  245. return $escaped_string;
  246. }
  247. //
  248. // get_domain_properties
  249. // Action: Get all the properties of a domain.
  250. // Call: get_domain_properties (string domain)
  251. //
  252. function get_domain_properties ($domain)
  253. {
  254. global $CONF;
  255. global $table_alias, $table_mailbox, $table_domain;
  256. $list = array ();
  257. $result = db_query ("SELECT COUNT(*) FROM $table_alias WHERE domain='$domain'");
  258. $row = db_row ($result['result']);
  259. $list['alias_count'] = $row[0];
  260. $result = db_query ("SELECT COUNT(*) FROM $table_mailbox WHERE domain='$domain'");
  261. $row = db_row ($result['result']);
  262. $list['mailbox_count'] = $row[0];
  263. $result = db_query ("SELECT SUM(quota) FROM $table_mailbox WHERE domain='$domain'");
  264. $row = db_row ($result['result']);
  265. $list['quota_sum'] = $row[0];
  266. $list['alias_count'] = $list['alias_count'] - $list['mailbox_count'];
  267. $list['alias_pgindex']=array ();
  268. $list['mbox_pgindex']=array ();
  269. $list['mbox_pgindex_count'] = 0;
  270. //while loop to figure index names. use page_size and loop of queries
  271. $i=0;
  272. $current=0;
  273. $page_size = $CONF['page_size'];
  274. $tmpstr="";
  275. $idxlabel="";
  276. $list['alias_pgindex_count'] = 0;
  277. if ( $list['alias_count'] > $page_size )
  278. {
  279. while ( $current < $list['alias_count'] )
  280. {
  281. $limitSql=('pgsql'==$CONF['database_type']) ? "1 OFFSET $current" : "$current, 1";
  282. $query = "SELECT $table_alias.address FROM $table_alias LEFT JOIN $table_mailbox ON $table_alias.address=$table_mailbox.username WHERE $table_alias.domain='$domain' AND $table_mailbox.maildir IS NULL ORDER BY $table_alias.address LIMIT $limitSql";
  283. $result = db_query ("$query");
  284. $row = db_array ($result['result']);
  285. $tmpstr = $row['address'];
  286. //get first 2 chars
  287. $idxlabel = $tmpstr[0] . $tmpstr[1] . "-";
  288. ($current + $page_size - 1 <= $list['alias_count']) ? $current = $current + $page_size - 1 : $current = $list['alias_count'] - 1;
  289. $limitSql=('pgsql'==$CONF['database_type']) ? "1 OFFSET $current" : "$current, 1";
  290. $query = "SELECT $table_alias.address FROM $table_alias LEFT JOIN $table_mailbox ON $table_alias.address=$table_mailbox.username WHERE $table_alias.domain='$domain' AND $table_mailbox.maildir IS NULL ORDER BY $table_alias.address LIMIT $limitSql";
  291. $result = db_query ("$query");
  292. $row = db_array ($result['result']);
  293. $tmpstr = $row['address'];
  294. $idxlabel = $idxlabel . $tmpstr[0] . $tmpstr[1];
  295. $current = $current + 1;
  296. $list['alias_pgindex'][]=$idxlabel;
  297. $i++;
  298. }
  299. $list['alias_pgindex_count']=$i;
  300. }
  301. $i=0;
  302. $current=0;
  303. $page_size = $CONF['page_size'];
  304. $tmpstr="";
  305. $idxlabel="";
  306. if ( $list['mailbox_count'] > $page_size )
  307. {
  308. while ( $current < $list['mailbox_count'] )
  309. {
  310. $limitSql=('pgsql'==$CONF['database_type']) ? "1 OFFSET $current" : "$current, 1";
  311. $query = "SELECT $table_mailbox.username FROM $table_mailbox WHERE $table_mailbox.domain='$domain' ORDER BY $table_mailbox.username LIMIT $limitSql";
  312. $result = db_query ("$query");
  313. $row = db_array ($result['result']);
  314. $tmpstr = $row['username'];
  315. //get first 2 chars
  316. $idxlabel = $tmpstr[0] . $tmpstr[1] . "-";
  317. ($current + $page_size - 1 <= $list['mailbox_count']) ? $current = $current + $page_size - 1 : $current = $list['mailbox_count'] - 1;
  318. $limitSql=('pgsql'==$CONF['database_type']) ? "1 OFFSET $current" : "$current, 1";
  319. $query = "SELECT $table_mailbox.username FROM $table_mailbox WHERE $table_mailbox.domain='$domain' ORDER BY $table_mailbox.username LIMIT $limitSql";
  320. $result = db_query ("$query");
  321. $row = db_array ($result['result']);
  322. $tmpstr = $row['username'];
  323. $idxlabel = $idxlabel . $tmpstr[0] . $tmpstr[1];
  324. $current = $current + 1;
  325. $list['mbox_pgindex'][]=$idxlabel;
  326. $i++;
  327. }
  328. $list['mbox_pgindex_count']=$i;
  329. }
  330. // end mod
  331. $query="SELECT * FROM $table_domain WHERE domain='$domain'";
  332. if ('pgsql'==$CONF['database_type'])
  333. {
  334. $query=" SELECT *, EXTRACT(epoch FROM created) AS uts_created, EXTRACT(epoch FROM modified) AS uts_modified FROM $table_domain WHERE domain='$domain' ";
  335. }
  336. $result = db_query ($query);
  337. $row = db_array ($result['result']);
  338. $list['description'] = $row['description'];
  339. $list['aliases'] = $row['aliases'];
  340. $list['mailboxes'] = $row['mailboxes'];
  341. $list['maxquota'] = $row['maxquota'];
  342. $list['quota'] = $row['quota'];
  343. $list['transport'] = $row['transport'];
  344. $list['backupmx'] = $row['backupmx'];
  345. $list['created'] = $row['created'];
  346. $list['modified'] = $row['modified'];
  347. $list['active'] = $row['active'];
  348. if ($CONF['database_type'] == "pgsql")
  349. {
  350. $list['active']=('t'==$row['active']) ? 1 : 0;
  351. $list['backupmx']=('t'==$row['backupmx']) ? 1 : 0;
  352. $list['created']= gmstrftime('%c %Z',$row['uts_created']);
  353. $list['modified']= gmstrftime('%c %Z',$row['uts_modified']);
  354. }
  355. else
  356. {
  357. $list['active'] = $row['active'];
  358. $list['backupmx'] = $row['backupmx'];
  359. }
  360. return $list;
  361. }
  362. //
  363. // get_mailbox_properties
  364. // Action: Get all the properties of a mailbox.
  365. // Call: get_mailbox_properties (string mailbox)
  366. //
  367. function get_mailbox_properties ($username)
  368. {
  369. global $CONF;
  370. global $table_mailbox;
  371. $query="SELECT * FROM $table_mailbox WHERE username='$username'";
  372. if ('pgsql'==$CONF['database_type'])
  373. {
  374. $query="
  375. SELECT
  376. *,
  377. EXTRACT(epoch FROM created) AS uts_created,
  378. EXTRACT(epoch FROM modified) AS uts_modified
  379. FROM $table_mailbox
  380. WHERE username='$username'
  381. ";
  382. }
  383. $result = db_query ($query);
  384. $row = db_array ($result['result']);
  385. $list['name'] = $row['name'];
  386. $list['maildir'] = $row['maildir'];
  387. $list['quota'] = $row['quota'];
  388. $list['domain'] = $row['domain'];
  389. $list['created'] = $row['created'];
  390. $list['modified'] = $row['modified'];
  391. $list['active'] = $row['active'];
  392. if ($CONF['database_type'] == "pgsql")
  393. {
  394. $list['active']=('t'==$row['active']) ? 1 : 0;
  395. $list['created']= gmstrftime('%c %Z',$row['uts_created']);
  396. $list['modified']= gmstrftime('%c %Z',$row['uts_modified']);
  397. }
  398. else
  399. {
  400. $list['active'] = $row['active'];
  401. }
  402. return $list;
  403. }
  404. //
  405. // check_alias
  406. // Action: Checks if the domain is still able to create aliases.
  407. // Call: check_alias (string domain)
  408. //
  409. function check_alias ($domain)
  410. {
  411. $limit = get_domain_properties ($domain);
  412. if ($limit['aliases'] == 0)
  413. {
  414. return true;
  415. }
  416. if ($limit['aliases'] < 0)
  417. {
  418. return false;
  419. }
  420. if ($limit['alias_count'] >= $limit['aliases'])
  421. {
  422. return false;
  423. }
  424. else
  425. {
  426. return true;
  427. }
  428. }
  429. //
  430. // check_mailbox
  431. // Action: Checks if the domain is still able to create mailboxes.
  432. // Call: check_mailbox (string domain)
  433. //
  434. function check_mailbox ($domain)
  435. {
  436. $limit = get_domain_properties ($domain);
  437. if ($limit['mailboxes'] == 0)
  438. {
  439. return true;
  440. }
  441. if ($limit['mailboxes'] < 0)
  442. {
  443. return false;
  444. }
  445. if ($limit['mailbox_count'] >= $limit['mailboxes'])
  446. {
  447. return false;
  448. }
  449. else
  450. {
  451. return true;
  452. }
  453. }
  454. //
  455. // check_quota
  456. // Action: Checks if the user is creating a mailbox with the correct quota
  457. // Call: check_quota (string domain)
  458. //
  459. function check_quota ($quota, $domain)
  460. {
  461. $limit = get_domain_properties ($domain);
  462. if ($limit['maxquota'] == 0)
  463. {
  464. return true;
  465. }
  466. if (($limit['maxquota'] < 0) and ($quota < 0))
  467. {
  468. return true;
  469. }
  470. if (($limit['maxquota'] > 0) and ($quota == 0))
  471. {
  472. return false;
  473. }
  474. if ($quota > $limit['maxquota'])
  475. {
  476. return false;
  477. }
  478. else
  479. {
  480. return true;
  481. }
  482. }
  483. //
  484. // multiply_quota
  485. // Action: Recalculates the quota from bytes to MBs (multiply, *)
  486. // Call: multiply_quota (string $quota)
  487. //
  488. function multiply_quota ($quota)
  489. {
  490. global $CONF;
  491. if ($quota == -1) return $quota;
  492. $value = $quota * $CONF['quota_multiplier'];
  493. return $value;
  494. }
  495. //
  496. // divide_quota
  497. // Action: Recalculates the quota from MBs to bytes (divide, /)
  498. // Call: divide_quota (string $quota)
  499. //
  500. function divide_quota ($quota)
  501. {
  502. global $CONF;
  503. if ($quota == -1) return $quota;
  504. $value = $quota / $CONF['quota_multiplier'];
  505. return $value;
  506. }
  507. //
  508. // check_owner
  509. // Action: Checks if the admin is the owner of the domain.
  510. // Call: check_owner (string admin, string domain)
  511. //
  512. function check_owner ($username, $domain)
  513. {
  514. global $table_domain_admins;
  515. $result = db_query ("SELECT 1 FROM $table_domain_admins WHERE username='$username' AND (domain='$domain' OR domain='ALL') AND active='1'");
  516. if ($result['rows'] != 1)
  517. {
  518. return false;
  519. }
  520. else
  521. {
  522. return true;
  523. }
  524. }
  525. //
  526. // check_alias_owner
  527. // Action: Checks if the admin is the owner of the alias.
  528. // Call: check_alias_owner (string admin, string alias)
  529. //
  530. function check_alias_owner ($username, $alias)
  531. {
  532. global $CONF;
  533. if (authentication_has_role('global-admin')) return true;
  534. $tmp = preg_split('/\@/', $alias);
  535. if (($CONF['special_alias_control'] == 'NO') && array_key_exists($tmp[0], $CONF['default_aliases']))
  536. {
  537. return false;
  538. }
  539. else
  540. {
  541. return true;
  542. }
  543. }
  544. //
  545. // list_domains_for_admin
  546. // Action: Lists all the domains for an admin.
  547. // Call: list_domains_for_admin (string admin)
  548. //
  549. function list_domains_for_admin ($username)
  550. {
  551. global $CONF;
  552. global $table_domain, $table_domain_admins;
  553. $list = array ();
  554. $query = "SELECT $table_domain.domain FROM $table_domain LEFT JOIN $table_domain_admins ON $table_domain.domain=$table_domain_admins.domain WHERE $table_domain_admins.username='$username' AND $table_domain.active='1' AND $table_domain.backupmx='0' ORDER BY $table_domain_admins.domain";
  555. if ('pgsql'==$CONF['database_type'])
  556. {
  557. $query = "SELECT $table_domain.domain FROM $table_domain LEFT JOIN $table_domain_admins ON $table_domain.domain=$table_domain_admins.domain WHERE $table_domain_admins.username='$username' AND $table_domain.active=true AND $table_domain.backupmx=false ORDER BY $table_domain_admins.domain";
  558. }
  559. $result = db_query ($query);
  560. if ($result['rows'] > 0)
  561. {
  562. $i = 0;
  563. while ($row = db_array ($result['result']))
  564. {
  565. $list[$i] = $row['domain'];
  566. $i++;
  567. }
  568. }
  569. return $list;
  570. }
  571. //
  572. // list_domains
  573. // Action: List all available domains.
  574. // Call: list_domains ()
  575. //
  576. function list_domains ()
  577. {
  578. global $table_domain;
  579. $list = array();
  580. $result = db_query ("SELECT domain FROM $table_domain WHERE domain!='ALL' ORDER BY domain");
  581. if ($result['rows'] > 0)
  582. {
  583. $i = 0;
  584. while ($row = db_array ($result['result']))
  585. {
  586. $list[$i] = $row['domain'];
  587. $i++;
  588. }
  589. }
  590. return $list;
  591. }
  592. //
  593. // admin_exist
  594. // Action: Checks if the admin already exists.
  595. // Call: admin_exist (string admin)
  596. //
  597. function admin_exist ($username)
  598. {
  599. global $table_admin;
  600. $result = db_query ("SELECT 1 FROM $table_admin WHERE username='$username'");
  601. if ($result['rows'] != 1)
  602. {
  603. return false;
  604. }
  605. else
  606. {
  607. return true;
  608. }
  609. }
  610. //
  611. // domain_exist
  612. // Action: Checks if the domain already exists.
  613. // Call: domain_exist (string domain)
  614. //
  615. function domain_exist ($domain)
  616. {
  617. global $table_domain;
  618. $result = db_query ("SELECT 1 FROM $table_domain WHERE domain='$domain'");
  619. if ($result['rows'] != 1)
  620. {
  621. return false;
  622. }
  623. else
  624. {
  625. return true;
  626. }
  627. }
  628. //
  629. // list_admins
  630. // Action: Lists all the admins
  631. // Call: list_admins ()
  632. //
  633. // was admin_list_admins
  634. //
  635. function list_admins ()
  636. {
  637. global $table_admin;
  638. $list = "";
  639. $result = db_query ("SELECT username FROM $table_admin ORDER BY username");
  640. if ($result['rows'] > 0)
  641. {
  642. $i = 0;
  643. while ($row = db_array ($result['result']))
  644. {
  645. $list[$i] = $row['username'];
  646. $i++;
  647. }
  648. }
  649. return $list;
  650. }
  651. //
  652. // get_admin_properties
  653. // Action: Get all the admin properties.
  654. // Call: get_admin_properties (string admin)
  655. //
  656. function get_admin_properties ($username)
  657. {
  658. global $CONF;
  659. global $table_admin, $table_domain_admins;
  660. $list = array ();
  661. $result = db_query ("SELECT * FROM $table_domain_admins WHERE username='$username' AND domain='ALL'");
  662. if ($result['rows'] == 1)
  663. {
  664. $list['domain_count'] = 'ALL';
  665. }
  666. else
  667. {
  668. $result = db_query ("SELECT COUNT(*) FROM $table_domain_admins WHERE username='$username'");
  669. $row = db_row ($result['result']);
  670. $list['domain_count'] = $row[0];
  671. }
  672. $query = "SELECT * FROM $table_admin WHERE username='$username'";
  673. if ('pgsql'==$CONF['database_type']) {
  674. $query="
  675. SELECT
  676. *,
  677. EXTRACT(epoch FROM created) AS uts_created,
  678. EXTRACT (epoch FROM modified) AS uts_modified
  679. FROM $table_admin
  680. WHERE username='$username'
  681. ";
  682. }
  683. $result = db_query ($query);
  684. $row = db_array ($result['result']);
  685. $list['created'] = $row['created'];
  686. $list['modified'] = $row['modified'];
  687. $list['active'] = $row['active'];
  688. if ('pgsql'==$CONF['database_type']) {
  689. $list['active'] = ('t'==$row['active']) ? 1 : 0;
  690. $list['created']= gmstrftime('%c %Z',$row['uts_created']);
  691. $list['modified']= gmstrftime('%c %Z',$row['uts_modified']);
  692. }
  693. return $list;
  694. }
  695. //
  696. // encode_header
  697. // Action: Encode a string according to RFC 1522 for use in headers if it contains 8-bit characters.
  698. // Call: encode_header (string header, string charset)
  699. //
  700. function encode_header ($string, $default_charset)
  701. {
  702. if (strtolower ($default_charset) == 'iso-8859-1')
  703. {
  704. $string = str_replace ("\240",' ',$string);
  705. }
  706. $j = strlen ($string);
  707. $max_l = 75 - strlen ($default_charset) - 7;
  708. $aRet = array ();
  709. $ret = '';
  710. $iEncStart = $enc_init = false;
  711. $cur_l = $iOffset = 0;
  712. for ($i = 0; $i < $j; ++$i)
  713. {
  714. switch ($string{$i})
  715. {
  716. case '=':
  717. case '<':
  718. case '>':
  719. case ',':
  720. case '?':
  721. case '_':
  722. if ($iEncStart === false)
  723. {
  724. $iEncStart = $i;
  725. }
  726. $cur_l+=3;
  727. if ($cur_l > ($max_l-2))
  728. {
  729. $aRet[] = substr ($string,$iOffset,$iEncStart-$iOffset);
  730. $aRet[] = "=?$default_charset?Q?$ret?=";
  731. $iOffset = $i;
  732. $cur_l = 0;
  733. $ret = '';
  734. $iEncStart = false;
  735. }
  736. else
  737. {
  738. $ret .= sprintf ("=%02X",ord($string{$i}));
  739. }
  740. break;
  741. case '(':
  742. case ')':
  743. if ($iEncStart !== false)
  744. {
  745. $aRet[] = substr ($string,$iOffset,$iEncStart-$iOffset);
  746. $aRet[] = "=?$default_charset?Q?$ret?=";
  747. $iOffset = $i;
  748. $cur_l = 0;
  749. $ret = '';
  750. $iEncStart = false;
  751. }
  752. break;
  753. case ' ':
  754. if ($iEncStart !== false)
  755. {
  756. $cur_l++;
  757. if ($cur_l > $max_l)
  758. {
  759. $aRet[] = substr ($string,$iOffset,$iEncStart-$iOffset);
  760. $aRet[] = "=?$default_charset?Q?$ret?=";
  761. $iOffset = $i;
  762. $cur_l = 0;
  763. $ret = '';
  764. $iEncStart = false;
  765. }
  766. else
  767. {
  768. $ret .= '_';
  769. }
  770. }
  771. break;
  772. default:
  773. $k = ord ($string{$i});
  774. if ($k > 126)
  775. {
  776. if ($iEncStart === false)
  777. {
  778. // do not start encoding in the middle of a string, also take the rest of the word.
  779. $sLeadString = substr ($string,0,$i);
  780. $aLeadString = explode (' ',$sLeadString);
  781. $sToBeEncoded = array_pop ($aLeadString);
  782. $iEncStart = $i - strlen ($sToBeEncoded);
  783. $ret .= $sToBeEncoded;
  784. $cur_l += strlen ($sToBeEncoded);
  785. }
  786. $cur_l += 3;
  787. // first we add the encoded string that reached it's max size
  788. if ($cur_l > ($max_l-2))
  789. {
  790. $aRet[] = substr ($string,$iOffset,$iEncStart-$iOffset);
  791. $aRet[] = "=?$default_charset?Q?$ret?= ";
  792. $cur_l = 3;
  793. $ret = '';
  794. $iOffset = $i;
  795. $iEncStart = $i;
  796. }
  797. $enc_init = true;
  798. $ret .= sprintf ("=%02X", $k);
  799. }
  800. else
  801. {
  802. if ($iEncStart !== false)
  803. {
  804. $cur_l++;
  805. if ($cur_l > $max_l)
  806. {
  807. $aRet[] = substr ($string,$iOffset,$iEncStart-$iOffset);
  808. $aRet[] = "=?$default_charset?Q?$ret?=";
  809. $iEncStart = false;
  810. $iOffset = $i;
  811. $cur_l = 0;
  812. $ret = '';
  813. }
  814. else
  815. {
  816. $ret .= $string{$i};
  817. }
  818. }
  819. }
  820. break;
  821. }
  822. }
  823. if ($enc_init)
  824. {
  825. if ($iEncStart !== false)
  826. {
  827. $aRet[] = substr ($string,$iOffset,$iEncStart-$iOffset);
  828. $aRet[] = "=?$default_charset?Q?$ret?=";
  829. }
  830. else
  831. {
  832. $aRet[] = substr ($string,$iOffset);
  833. }
  834. $string = implode ('',$aRet);
  835. }
  836. return $string;
  837. }
  838. //
  839. // generate_password
  840. // Action: Generates a random password
  841. // Call: generate_password ()
  842. //
  843. function generate_password ()
  844. {
  845. $password = substr (md5 (mt_rand ()), 0, 8);
  846. return $password;
  847. }
  848. //
  849. // pacrypt
  850. // Action: Encrypts password based on config settings
  851. // Call: pacrypt (string cleartextpassword)
  852. //
  853. function pacrypt ($pw, $pw_db="")
  854. {
  855. global $CONF;
  856. $pw = stripslashes($pw);
  857. $password = "";
  858. $salt = "";
  859. if ($CONF['encrypt'] == 'md5crypt') {
  860. $split_salt = preg_split ('/\$/', $pw_db);
  861. if (isset ($split_salt[2])) {
  862. $salt = $split_salt[2];
  863. }
  864. $password = md5crypt ($pw, $salt);
  865. }
  866. if ($CONF['encrypt'] == 'md5') {
  867. $password = md5($pw);
  868. }
  869. if ($CONF['encrypt'] == 'system') {
  870. if (ereg ("\$1\$", $pw_db)) {
  871. $split_salt = preg_split ('/\$/', $pw_db);
  872. $salt = $split_salt[2];
  873. }
  874. else {
  875. if (strlen($pw_db) == 0) {
  876. $salt = substr (md5 (mt_rand ()), 0, 2);
  877. }
  878. else {
  879. $salt = substr ($pw_db, 0, 2);
  880. }
  881. }
  882. $password = crypt ($pw, $salt);
  883. }
  884. if ($CONF['encrypt'] == 'cleartext') {
  885. $password = $pw;
  886. }
  887. $password = escape_string ($password);
  888. return $password;
  889. }
  890. //
  891. // md5crypt
  892. // Action: Creates MD5 encrypted password
  893. // Call: md5crypt (string cleartextpassword)
  894. //
  895. $MAGIC = "$1$";
  896. $ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  897. function md5crypt ($pw, $salt="", $magic="")
  898. {
  899. global $MAGIC;
  900. if ($magic == "") $magic = $MAGIC;
  901. if ($salt == "") $salt = create_salt ();
  902. $slist = explode ("$", $salt);
  903. if ($slist[0] == "1") $salt = $slist[1];
  904. $salt = substr ($salt, 0, 8);
  905. $ctx = $pw . $magic . $salt;
  906. $final = hex2bin (md5 ($pw . $salt . $pw));
  907. for ($i=strlen ($pw); $i>0; $i-=16)
  908. {
  909. if ($i > 16)
  910. {
  911. $ctx .= substr ($final,0,16);
  912. }
  913. else
  914. {
  915. $ctx .= substr ($final,0,$i);
  916. }
  917. }
  918. $i = strlen ($pw);
  919. while ($i > 0)
  920. {
  921. if ($i & 1) $ctx .= chr (0);
  922. else $ctx .= $pw[0];
  923. $i = $i >> 1;
  924. }
  925. $final = hex2bin (md5 ($ctx));
  926. for ($i=0;$i<1000;$i++)
  927. {
  928. $ctx1 = "";
  929. if ($i & 1)
  930. {
  931. $ctx1 .= $pw;
  932. }
  933. else
  934. {
  935. $ctx1 .= substr ($final,0,16);
  936. }
  937. if ($i % 3) $ctx1 .= $salt;
  938. if ($i % 7) $ctx1 .= $pw;
  939. if ($i & 1)
  940. {
  941. $ctx1 .= substr ($final,0,16);
  942. }
  943. else
  944. {
  945. $ctx1 .= $pw;
  946. }
  947. $final = hex2bin (md5 ($ctx1));
  948. }
  949. $passwd = "";
  950. $passwd .= to64 (((ord ($final[0]) << 16) | (ord ($final[6]) << 8) | (ord ($final[12]))), 4);
  951. $passwd .= to64 (((ord ($final[1]) << 16) | (ord ($final[7]) << 8) | (ord ($final[13]))), 4);
  952. $passwd .= to64 (((ord ($final[2]) << 16) | (ord ($final[8]) << 8) | (ord ($final[14]))), 4);
  953. $passwd .= to64 (((ord ($final[3]) << 16) | (ord ($final[9]) << 8) | (ord ($final[15]))), 4);
  954. $passwd .= to64 (((ord ($final[4]) << 16) | (ord ($final[10]) << 8) | (ord ($final[5]))), 4);
  955. $passwd .= to64 (ord ($final[11]), 2);
  956. return "$magic$salt\$$passwd";
  957. }
  958. function create_salt ()
  959. {
  960. srand ((double) microtime ()*1000000);
  961. $salt = substr (md5 (rand (0,9999999)), 0, 8);
  962. return $salt;
  963. }
  964. function hex2bin ($str)
  965. {
  966. $len = strlen ($str);
  967. $nstr = "";
  968. for ($i=0;$i<$len;$i+=2)
  969. {
  970. $num = sscanf (substr ($str,$i,2), "%x");
  971. $nstr.=chr ($num[0]);
  972. }
  973. return $nstr;
  974. }
  975. function to64 ($v, $n)
  976. {
  977. global $ITOA64;
  978. $ret = "";
  979. while (($n - 1) >= 0)
  980. {
  981. $n--;
  982. $ret .= $ITOA64[$v & 0x3f];
  983. $v = $v >> 6;
  984. }
  985. return $ret;
  986. }
  987. //
  988. // smtp_mail
  989. // Action: Sends email to new account.
  990. // Call: smtp_mail (string To, string From, string Data)
  991. //
  992. function smtp_mail ($to, $from, $data)
  993. {
  994. global $CONF;
  995. $smtpd_server = $CONF['smtp_server'];
  996. $smtpd_port = $CONF['smtp_port'];
  997. $smtp_server = $_SERVER["SERVER_NAME"];
  998. $errno = "0";
  999. $errstr = "0";
  1000. $timeout = "30";
  1001. $fh = @fsockopen ($smtpd_server, $smtpd_port, $errno, $errstr, $timeout);
  1002. if (!$fh)
  1003. {
  1004. return false;
  1005. }
  1006. else
  1007. {
  1008. fputs ($fh, "EHLO $smtp_server\r\n");
  1009. $res = smtp_get_response($fh);
  1010. fputs ($fh, "MAIL FROM:<$from>\r\n");
  1011. $res = smtp_get_response($fh);
  1012. fputs ($fh, "RCPT TO:<$to>\r\n");
  1013. $res = smtp_get_response($fh);
  1014. fputs ($fh, "DATA\r\n");
  1015. $res = smtp_get_response($fh);
  1016. fputs ($fh, "$data\r\n.\r\n");
  1017. $res = smtp_get_response($fh);
  1018. fputs ($fh, "QUIT\r\n");
  1019. $res = smtp_get_response($fh);
  1020. fclose ($fh);
  1021. }
  1022. return true;
  1023. }
  1024. //
  1025. // smtp_get_response
  1026. // Action: Get response from mail server
  1027. // Call: smtp_get_response (string FileHandle)
  1028. //
  1029. function smtp_get_response ($fh)
  1030. {
  1031. $res ='';
  1032. do
  1033. {
  1034. $line = fgets($fh, 256);
  1035. $res .= $line;
  1036. }
  1037. while (preg_match("/^\d\d\d\-/", $line));
  1038. return $res;
  1039. }
  1040. $DEBUG_TEXT = "\n
  1041. <p />\n
  1042. Please check the documentation and website for more information.\n
  1043. <p />\n
  1044. <a href=\"http://high5.net/postfixadmin/\">Postfix Admin</a><br />\n
  1045. <a href=\"http://forums.high5.net/index.php?showforum=7\">Knowledge Base</a>\n
  1046. ";
  1047. //
  1048. // db_connect
  1049. // Action: Makes a connection to the database if it doesn't exist
  1050. // Call: db_connect ()
  1051. //
  1052. function db_connect ()
  1053. {
  1054. global $CONF;
  1055. global $DEBUG_TEXT;
  1056. if ($CONF['database_type'] == "mysql")
  1057. {
  1058. if (function_exists ("mysql_connect"))
  1059. {
  1060. $link = @mysql_connect ($CONF['database_host'], $CONF['database_user'], $CONF['database_password']) or die ("<p />DEBUG INFORMATION:<br />Connect: " . mysql_error () . "$DEBUG_TEXT");
  1061. @mysql_query("SET CHARACTER SET utf8",$link);
  1062. @mysql_query("SET COLLATION_CONNECTION='utf8_general_ci'",$link);
  1063. $succes = @mysql_select_db ($CONF['database_name'], $link) or die ("<p />DEBUG INFORMATION:<br />MySQL Select Database: " . mysql_error () . "$DEBUG_TEXT");
  1064. }
  1065. else
  1066. {
  1067. print "<p />DEBUG INFORMATION:<br />MySQL 3.x / 4.0 functions not available!<br />database_type = 'mysql' in config.inc.php, are you using a different database? $DEBUG_TEXT";
  1068. die();
  1069. }
  1070. }
  1071. if ($CONF['database_type'] == "mysqli")
  1072. {
  1073. if (function_exists ("mysqli_connect"))
  1074. {
  1075. $link = @mysqli_connect ($CONF['database_host'], $CONF['database_user'], $CONF['database_password']) or die ("<p />DEBUG INFORMATION:<br />Connect: " . mysqli_connect_error () . "$DEBUG_TEXT");
  1076. @mysqli_query($link,"SET CHARACTER SET utf8");
  1077. @mysqli_query($link,"SET COLLATION_CONNECTION='utf8_general_ci'");
  1078. $success = @mysqli_select_db ($link, $CONF['database_name']) or die ("<p />DEBUG INFORMATION:<br />MySQLi Select Database: " . mysqli_error ($link) . "$DEBUG_TEXT");
  1079. }
  1080. else
  1081. {
  1082. print "<p />DEBUG INFORMATION:<br />MySQL 4.1 functions not available!<br />database_type = 'mysqli' in config.inc.php, are you using a different database? $DEBUG_TEXT";
  1083. die();
  1084. }
  1085. }
  1086. if ($CONF['database_type'] == "pgsql")
  1087. {
  1088. if (function_exists ("pg_pconnect"))
  1089. {
  1090. $connect_string = "host=" . $CONF['database_host'] . " dbname=" . $CONF['database_name'] . " user=" . $CONF['database_user'] . " password=" . $CONF['database_password'];
  1091. $link = @pg_pconnect ($connect_string) or die ("<p />DEBUG INFORMATION:<br />Connect: " . pg_last_error($link) . "$DEBUG_TEXT");
  1092. pg_set_client_encoding($link, 'UNICODE');
  1093. }
  1094. else
  1095. {
  1096. print "<p />DEBUG INFORMATION:<br />PostgreSQL functions not available!<br />database_type = 'pgsql' in config.inc.php, are you using a different database? $DEBUG_TEXT";
  1097. die();
  1098. }
  1099. }
  1100. if ($link)
  1101. {
  1102. return $link;
  1103. }
  1104. else
  1105. {
  1106. print "DEBUG INFORMATION:<br />\n";
  1107. print "Connect: Unable to connect to database<br />\n";
  1108. print "<br />\n";
  1109. print "Make sure that you have set the correct database type in the config.inc.php file<br />\n";
  1110. print $DEBUG_TEXT;
  1111. die();
  1112. }
  1113. }
  1114. //
  1115. // db_query
  1116. // Action: Sends a query to the database and returns query result and number of rows
  1117. // Call: db_query (string query)
  1118. //
  1119. function db_query ($query)
  1120. {
  1121. global $CONF;
  1122. global $DEBUG_TEXT;
  1123. $result = "";
  1124. $number_rows = "";
  1125. static $link;
  1126. if (!is_resource($link)) $link = db_connect ();
  1127. if ($CONF['database_type'] == "mysql") $result = @mysql_query ($query, $link) or die ("<p />DEBUG INFORMATION:<br />Invalid query: " . mysql_error($link) . "$DEBUG_TEXT");
  1128. if ($CONF['database_type'] == "mysqli") $result = @mysqli_query ($link, $query) or die ("<p />DEBUG INFORMATION:<br />Invalid query: " . mysqli_error($link) . "$DEBUG_TEXT");
  1129. if ($CONF['database_type'] == "pgsql")
  1130. {
  1131. $result = @pg_query ($link, $query) or die ("<p />DEBUG INFORMATION:<br />Invalid query: " . pg_last_error() . "$DEBUG_TEXT");
  1132. }
  1133. if (eregi ("^SELECT", $query))
  1134. {
  1135. // if $query was a SELECT statement check the number of rows with [database_type]_num_rows ().
  1136. if ($CONF['database_type'] == "mysql") $number_rows = mysql_num_rows ($result);
  1137. if ($CONF['database_type'] == "mysqli") $number_rows = mysqli_num_rows ($result);
  1138. if ($CONF['database_type'] == "pgsql") $number_rows = pg_num_rows ($result);
  1139. }
  1140. else
  1141. {
  1142. // if $query was something else, UPDATE, DELETE or INSERT check the number of rows with
  1143. // [database_type]_affected_rows ().
  1144. if ($CONF['database_type'] == "mysql") $number_rows = mysql_affected_rows ($link);
  1145. if ($CONF['database_type'] == "mysqli") $number_rows = mysqli_affected_rows ($link);
  1146. if ($CONF['database_type'] == "pgsql") $number_rows = pg_affected_rows ($result);
  1147. }
  1148. $return = array (
  1149. "result" => $result,
  1150. "rows" => $number_rows
  1151. );
  1152. return $return;
  1153. }
  1154. // db_row
  1155. // Action: Returns a row from a table
  1156. // Call: db_row (int result)
  1157. //
  1158. function db_row ($result)
  1159. {
  1160. global $CONF;
  1161. $row = "";
  1162. if ($CONF['database_type'] == "mysql") $row = mysql_fetch_row ($result);
  1163. if ($CONF['database_type'] == "mysqli") $row = mysqli_fetch_row ($result);
  1164. if ($CONF['database_type'] == "pgsql") $row = pg_fetch_row ($result);
  1165. return $row;
  1166. }
  1167. // db_array
  1168. // Action: Returns a row from a table
  1169. // Call: db_array (int result)
  1170. //
  1171. function db_array ($result)
  1172. {
  1173. global $CONF;
  1174. $row = "";
  1175. if ($CONF['database_type'] == "mysql") $row = mysql_fetch_array ($result);
  1176. if ($CONF['database_type'] == "mysqli") $row = mysqli_fetch_array ($result);
  1177. if ($CONF['database_type'] == "pgsql") $row = pg_fetch_array ($result);
  1178. return $row;
  1179. }
  1180. // db_assoc
  1181. // Action: Returns a row from a table
  1182. // Call: db_assoc(int result)
  1183. //
  1184. function db_assoc ($result)
  1185. {
  1186. global $CONF;
  1187. $row = "";
  1188. if ($CONF['database_type'] == "mysql") $row = mysql_fetch_assoc ($result);
  1189. if ($CONF['database_type'] == "mysqli") $row = mysqli_fetch_assoc ($result);
  1190. if ($CONF['database_type'] == "pgsql") $row = pg_fetch_assoc ($result);
  1191. return $row;
  1192. }
  1193. //
  1194. // db_delete
  1195. // Action: Deletes a row from a specified table
  1196. // Call: db_delete (string table, string where, string delete)
  1197. //
  1198. function db_delete ($table,$where,$delete)
  1199. {
  1200. $result = db_query ("DELETE FROM $table WHERE $where='$delete'");
  1201. if ($result['rows'] >= 1)
  1202. {
  1203. return $result['rows'];
  1204. }
  1205. else
  1206. {
  1207. return true;
  1208. }
  1209. }
  1210. //
  1211. // db_log
  1212. // Action: Logs actions from admin
  1213. // Call: db_log (string username, string domain, string action, string data)
  1214. //
  1215. function db_log ($username,$domain,$action,$data)
  1216. {
  1217. global $CONF;
  1218. global $table_log;
  1219. $REMOTE_ADDR = $_SERVER['REMOTE_ADDR'];
  1220. if ($CONF['logging'] == 'YES')
  1221. {
  1222. $result = db_query ("INSERT INTO $table_log (timestamp,username,domain,action,data) VALUES (NOW(),'$username ($REMOTE_ADDR)','$domain','$action','$data')");
  1223. if ($result['rows'] != 1)
  1224. {
  1225. return false;
  1226. }
  1227. else
  1228. {
  1229. return true;
  1230. }
  1231. }
  1232. }
  1233. //
  1234. // table_by_key
  1235. // Action: Return table name for given key
  1236. // Call: table_by_key (string table_key)
  1237. //
  1238. function table_by_key ($table_key)
  1239. {
  1240. global $CONF;
  1241. $table = $CONF['database_prefix'].$CONF['database_tables'][$table_key];
  1242. return $table;
  1243. }
  1244. //
  1245. // table_by_pos
  1246. // Action: Return table name for given position
  1247. // Call: table_by_pos (int pos)
  1248. //
  1249. function table_by_pos ($pos)
  1250. {
  1251. global $CONF;
  1252. $x=0;
  1253. foreach($CONF['database_tables'] as $i=>$v)
  1254. {
  1255. if($pos==$x++) return table_by_key ($i);
  1256. }
  1257. return false;
  1258. }
  1259. /*
  1260. Called after a mailbox has been created in the DBMS.
  1261. Returns: boolean.
  1262. */
  1263. function mailbox_postcreation($username,$domain,$maildir)
  1264. {
  1265. if (empty($username) || empty($domain) || empty($maildir))
  1266. {
  1267. trigger_error('In '.__FUNCTION__.': empty username, domain and/or maildir parameter',E_USER_ERROR);
  1268. return FALSE;
  1269. }
  1270. global $CONF;
  1271. $confpar='mailbox_postcreation_script';
  1272. if (!isset($CONF[$confpar]) || empty($CONF[$confpar])) return TRUE;
  1273. $cmdarg1=escapeshellarg($username);
  1274. $cmdarg2=escapeshellarg($domain);
  1275. $cmdarg3=escapeshellarg($maildir);
  1276. $command=$CONF[$confpar]." $cmdarg1 $cmdarg2 $cmdarg3";
  1277. $retval=0;
  1278. $output=array();
  1279. $firstline='';
  1280. $firstline=exec($command,$output,$retval);
  1281. if (0!=$retval)
  1282. {
  1283. error_log("Running $command yielded return value=$retval, first line of output=$firstline");
  1284. print '<p>WARNING: Problems running mailbox postcreation script!</p>';
  1285. return FALSE;
  1286. }
  1287. return TRUE;
  1288. }
  1289. /*
  1290. Called after a mailbox has been deleted in the DBMS.
  1291. Returns: boolean.
  1292. */
  1293. function mailbox_postdeletion($username,$domain)
  1294. {
  1295. global $CONF;
  1296. $confpar='mailbox_postdeletion_script';
  1297. if (!isset($CONF[$confpar]) || empty($CONF[$confpar]))
  1298. {
  1299. return true;
  1300. }
  1301. if (empty($username) || empty($domain))
  1302. {
  1303. print '<p>Warning: empty username and/or domain parameter.</p>';
  1304. return false;
  1305. }
  1306. $cmdarg1=escapeshellarg($username);
  1307. $cmdarg2=escapeshellarg($domain);
  1308. $command=$CONF[$confpar]." $cmdarg1 $cmdarg2";
  1309. $retval=0;
  1310. $output=array();
  1311. $firstline='';
  1312. $firstline=exec($command,$output,$retval);
  1313. if (0!=$retval)
  1314. {
  1315. error_log("Running $command yielded return value=$retval, first line of output=$firstline");
  1316. print '<p>WARNING: Problems running mailbox postdeletion script!</p>';
  1317. return FALSE;
  1318. }
  1319. return TRUE;
  1320. }
  1321. /*
  1322. Called after a domain has been deleted in the DBMS.
  1323. Returns: boolean.
  1324. */
  1325. function domain_postdeletion($domain)
  1326. {
  1327. global $CONF;
  1328. $confpar='domain_postdeletion_script';
  1329. if (!isset($CONF[$confpar]) || empty($CONF[$confpar]))
  1330. {
  1331. return true;
  1332. }
  1333. if (empty($domain))
  1334. {
  1335. print '<p>Warning: empty domain parameter.</p>';
  1336. return false;
  1337. }
  1338. $cmdarg1=escapeshellarg($domain);
  1339. $command=$CONF[$confpar]." $cmdarg1";
  1340. $retval=0;
  1341. $output=array();
  1342. $firstline='';
  1343. $firstline=exec($command,$output,$retval);
  1344. if (0!=$retval)
  1345. {
  1346. error_log("Running $command yielded return value=$retval, first line of output=$firstline");
  1347. print '<p>WARNING: Problems running domain postdeletion script!</p>';
  1348. return FALSE;
  1349. }
  1350. return TRUE;
  1351. }
  1352. /*
  1353. Called by mailbox_postcreation() after a mailbox has been
  1354. created. Immediately returns, unless configuration indicates
  1355. that one or more sub-folders should be created.
  1356. Triggers E_USER_ERROR if configuration error is detected.
  1357. If IMAP login fails, the problem is logged to the system log
  1358. (such as /var/log/httpd/error_log), and the function returns
  1359. FALSE.
  1360. Returns FALSE on all other errors, or TRUE if everything
  1361. succeeds.
  1362. Doesn't clean up, if only some of the folders could be
  1363. created.
  1364. */
  1365. function create_mailbox_subfolders($login,$cleartext_password)
  1366. {
  1367. global $CONF;
  1368. if (empty($login))
  1369. {
  1370. trigger_error('In '.__FUNCTION__.': empty $login',E_USER_ERROR);
  1371. return FALSE;
  1372. }
  1373. if (!isset($CONF['create_mailbox_subdirs']) || empty($CONF['create_mailbox_subdirs'])) return TRUE;
  1374. if (!is_array($CONF['create_mailbox_subdirs']))
  1375. {
  1376. trigger_error('create_mailbox_subdirs must be an array',E_USER_ERROR);
  1377. return FALSE;
  1378. }
  1379. if (!isset($CONF['create_mailbox_subdirs_host']) || empty($CONF['create_mailbox_subdirs_host']))
  1380. {
  1381. trigger_error('An IMAP/POP server host ($CONF["create_mailbox_subdirs_host"]) must be configured, if sub-folders are to be created',E_USER_ERROR);
  1382. return FALSE;
  1383. }
  1384. $s_host=$CONF['create_mailbox_subdirs_host'];
  1385. $s_options='';
  1386. $s_port='';
  1387. if (
  1388. isset($CONF['create_mailbox_subdirs_hostoptions'])
  1389. && !empty($CONF['create_mailbox_subdirs_hostoptions'])
  1390. ) {
  1391. if (!is_array($CONF['create_mailbox_subdirs_hostoptions']))
  1392. {
  1393. trigger_error('The $CONF["create_mailbox_subdirs_hostoptions"] parameter must be an array',E_USER_ERROR);
  1394. return FALSE;
  1395. }
  1396. foreach ($CONF['create_mailbox_subdirs_hostoptions'] as $o)
  1397. {
  1398. $s_options.='/'.$o;
  1399. }
  1400. }
  1401. if (isset($CONF['create_mailbox_subdirs_hostport']) && !empty($CONF['create_mailbox_subdirs_hostport']))
  1402. {
  1403. $s_port=$CONF['create_mailbox_subdirs_hostport'];
  1404. if (intval($s_port)!=$s_port)
  1405. {
  1406. trigger_error('The $CONF["create_mailbox_subdirs_hostport"] parameter must be an integer',E_USER_ERROR);
  1407. return FALSE;
  1408. }
  1409. $s_port=':'.$s_port;
  1410. }
  1411. $s='{'.$s_host.$s_port.$s_options.'}';
  1412. $i=@imap_open($s,$login,$cleartext_password);
  1413. if (FALSE==$i)
  1414. {
  1415. error_log('Could not log into IMAP/POP server: '.imap_last_error());
  1416. return FALSE;
  1417. }
  1418. foreach($CONF['create_mailbox_subdirs'] as $f)
  1419. {
  1420. $f='{'.$s_host.'}INBOX.'.$f;
  1421. $res=imap_createmailbox($i,$f);
  1422. if (!$res) {
  1423. @imap_close($i);
  1424. return FALSE;
  1425. }
  1426. @imap_subscribe($i,$f);
  1427. }
  1428. @imap_close($i);
  1429. return TRUE;
  1430. }
  1431. //
  1432. // gen_show_status
  1433. // Action: Return a string of colored &nbsp;'s that indicate
  1434. // the if an alias goto has an error or is sent to
  1435. // addresses list in show_custom_domains
  1436. // Call: gen_show_status (string alias_address)
  1437. //
  1438. function gen_show_status ($show_alias)
  1439. {
  1440. global $CONF, $table_alias;
  1441. $stat_string = "";
  1442. $stat_goto = "";
  1443. $stat_result = db_query ("SELECT goto FROM $table_alias WHERE address='$show_alias'");
  1444. if ($stat_result['rows'] > 0)
  1445. {
  1446. $row = db_row ($stat_result['result']);
  1447. $stat_goto = $row[0];
  1448. }
  1449. // UNDELIVERABLE CHECK
  1450. if ( $CONF['show_undeliverable'] == 'YES' )
  1451. {
  1452. $gotos=array();
  1453. $gotos=explode(',',$stat_goto);
  1454. $undel_string="";
  1455. //make sure this alias goes somewhere known
  1456. $stat_ok = 1;
  1457. while ( ($g=array_pop($gotos)) && $stat_ok )
  1458. {
  1459. $stat_result = db_query ("SELECT address FROM $table_alias WHERE address = '$g'");
  1460. if ($stat_result['rows'] == 0)
  1461. {
  1462. $stat_ok = 0;
  1463. }
  1464. if ( $stat_ok == 0 )
  1465. {
  1466. $stat_domain = substr($g,strpos($g,"@")+1);
  1467. $stat_vacdomain = substr($stat_domain,strpos($stat_domain,"@")+1);
  1468. if ( $stat_vacdomain == $CONF['vacation_domain'] )
  1469. {
  1470. $stat_ok = 1;
  1471. break;
  1472. }
  1473. for ($i=0; $i < sizeof($CONF['show_undeliverable_exceptions']);$i++)
  1474. {
  1475. if ( $stat_domain == $CONF['show_undeliverable_exceptions'][$i] )
  1476. {
  1477. $stat_ok = 1;
  1478. break;
  1479. }
  1480. }
  1481. }
  1482. } // while
  1483. if ( $stat_ok == 0 )
  1484. {
  1485. $stat_string .= "<span style='background-color:" . $CONF['show_undeliverable_color'] .
  1486. "'>" . $CONF['show_status_text'] . "</span>&nbsp;";
  1487. }
  1488. else
  1489. {
  1490. $stat_string .= $CONF['show_status_text'] . "&nbsp;";
  1491. }
  1492. }
  1493. else
  1494. {
  1495. $stat_string .= $CONF['show_status_text'] . "&nbsp;";
  1496. }
  1497. // POP/IMAP CHECK
  1498. if ( $CONF['show_popimap'] == 'YES' )
  1499. {
  1500. //if the address passed in appears in its own goto field, its POP/IMAP
  1501. if (preg_match ('/^' . $show_alias . '$/', $stat_goto) ||
  1502. preg_match ('/.*,' . $show_alias . ',.*$/', $stat_goto) ||
  1503. preg_match ('/,' . $show_alias . '$/', $stat_goto) )
  1504. {
  1505. $stat_string .= "<span style='background-color:" . $CONF['show_popimap_color'] .
  1506. "'>" . $CONF['show_status_text'] . "</span>&nbsp;";
  1507. }
  1508. else
  1509. {
  1510. $stat_string .= $CONF['show_status_text'] . "&nbsp;";
  1511. }
  1512. }
  1513. // CUSTOM DESTINATION CHECK
  1514. if ( $CONF['show_custom_count'] > 0 )
  1515. {
  1516. for ($i = 0; $i < sizeof ($CONF['show_custom_domains']); $i++)
  1517. {
  1518. if (preg_match ('/^.*' . $CONF['show_custom_domains'][$i] . '.*$/', $stat_goto))
  1519. {
  1520. $stat_string .= "<span style='background-color:" . $CONF['show_custom_colors'][$i] .
  1521. "'>" . $CONF['show_status_text'] . "</span>&nbsp;";
  1522. }
  1523. else
  1524. {
  1525. $stat_string .= $CONF['show_status_text'] . "&nbsp;";
  1526. }
  1527. }
  1528. }
  1529. else
  1530. {
  1531. $stat_string .= ";&nbsp;";
  1532. }
  1533. // $stat_string .= "<span style='background-color:green'> &nbsp; </span> &nbsp;" .
  1534. // "<span style='background-color:blue'> &nbsp; </span> &nbsp;";
  1535. return $stat_string;
  1536. }
  1537. $table_admin = table_by_key ('admin');
  1538. $table_alias = table_by_key ('alias');
  1539. $table_domain = table_by_key ('domain');
  1540. $table_domain_admins = table_by_key ('domain_admins');
  1541. $table_log = table_by_key ('log');
  1542. $table_mailbox = table_by_key ('mailbox');
  1543. $table_vacation = table_by_key ('vacation');
  1544. /* vim: set expandtab softtabstop=3 tabstop=3 shiftwidth=3: */