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.

308 lines
11 KiB

7 years ago
7 years ago
7 years ago
7 years ago
  1. <?php
  2. # $Id$
  3. class VacationHandler extends PFAHandler
  4. {
  5. /**
  6. * @var string
  7. */
  8. protected $db_table = 'vacation';
  9. /**
  10. * @var string
  11. */
  12. protected $id_field = 'email';
  13. /**
  14. * @var string
  15. */
  16. protected $domain_field = 'domain';
  17. public function init(string $id) : bool
  18. {
  19. throw new \Exception('VacationHandler is not yet ready to be used with *Handler methods');
  20. }
  21. /**
  22. * @return void
  23. */
  24. protected function initStruct()
  25. {
  26. $this->struct=array(
  27. # field name allow display in... type $PALANG label $PALANG description default / options / ...
  28. # editing? form list
  29. 'email' => pacol($this->new, 1, 1, 'text', 'pLogin_username' , '' , '' ),
  30. 'domain' => pacol(1, 0, 0, 'text', '' , '' , '' ),
  31. 'subject' => pacol(1, 1, 0, 'text', 'pUsersVacation_subject' , '' , '' ),
  32. 'body' => pacol(1, 1, 0, 'text', 'pUsersVacation_body' , '' , '' ),
  33. 'activefrom' => pacol(1, 1, 1, 'text', 'pUsersVacation_activefrom' , '' , '' ),
  34. 'activeuntil' => pacol(1, 1, 1, 'text', 'pUsersVacation_activeuntil' , '' , '' ),
  35. 'active' => pacol(1, 1, 1, 'bool', 'active' , '' , 1 ),
  36. 'created' => pacol(0, 0, 1, 'ts', 'created' , '' ),
  37. 'modified' => pacol(0, 0, 1, 'ts', 'last_modified' , '' ),
  38. # TODO: add virtual 'notified' column and allow to display who received a vacation response?
  39. );
  40. if ( ! db_pgsql() ) {
  41. $this->struct['cache'] = pacol(0, 0, 0, 'text', '' , '' , '' ); # leftover from 2.2
  42. }
  43. }
  44. /**
  45. * @return void
  46. */
  47. protected function initMsg()
  48. {
  49. $this->msg['error_already_exists'] = 'pCreate_mailbox_username_text_error1'; # TODO: better error message
  50. $this->msg['error_does_not_exist'] = 'pCreate_mailbox_username_text_error1'; # TODO: better error message
  51. $this->msg['confirm_delete'] = 'confirm_delete_vacation'; # unused?
  52. if ($this->new) {
  53. $this->msg['logname'] = 'edit_vacation';
  54. $this->msg['store_error'] = 'pVacation_result_error';
  55. $this->msg['successmessage'] = 'pVacation_result_removed'; # TODO: or pVacation_result_added - depends on 'active'... -> we probably need a new message
  56. } else {
  57. $this->msg['logname'] = 'edit_vacation';
  58. $this->msg['store_error'] = 'pVacation_result_error';
  59. $this->msg['successmessage'] = 'pVacation_result_removed'; # TODO: or pVacation_result_added - depends on 'active'... -> we probably need a new message
  60. }
  61. }
  62. /**
  63. * @return array
  64. */
  65. public function webformConfig()
  66. {
  67. return array(
  68. # $PALANG labels
  69. 'formtitle_create' => 'pUsersVacation_welcome',
  70. 'formtitle_edit' => 'pUsersVacation_welcome',
  71. 'create_button' => 'save',
  72. # various settings
  73. 'required_role' => 'admin',
  74. 'listview' => 'list-virtual.php',
  75. 'early_init' => 1, # 0 for create-domain
  76. );
  77. }
  78. protected function validate_new_id()
  79. {
  80. # vacation can only be enabled if a mailbox with this name exists
  81. if ($this->is_admin) {
  82. $handler = new MailboxHandler(0, $this->admin_username);
  83. if ($handler->init($this->id)) {
  84. return true;
  85. }
  86. } else {
  87. if ($this->id == $this->username) {
  88. return true;
  89. }
  90. }
  91. # still here? This means the mailbox doesn't exist or the admin/user doesn't have permissions to view it
  92. $this->errormsg[] = Config::Lang('invalid_parameter');
  93. return false;
  94. }
  95. /**
  96. * @return bool
  97. */
  98. public function delete()
  99. {
  100. $this->errormsg[] = '*** deletion not implemented yet ***';
  101. return false; # XXX function aborts here! XXX
  102. }
  103. /**
  104. * @var string
  105. */
  106. protected $username;
  107. /**
  108. * @param string $username
  109. */
  110. public function __construct($username)
  111. {
  112. $this->username = $username;
  113. $this->id = $username;
  114. }
  115. /**
  116. * Removes the autoreply alias etc for this user; namely, if they're away we remove their vacation alias and
  117. * set the vacation table record to false.
  118. * @return boolean true on success.
  119. */
  120. public function remove()
  121. {
  122. if (!$this->updateAlias(0)) {
  123. return false;
  124. }
  125. // tidy up vacation table.
  126. $vacation_data = array(
  127. 'active' => db_get_boolean(false),
  128. );
  129. $result = db_update('vacation', 'email', $this->username, $vacation_data);
  130. $result = db_delete('vacation_notification', 'on_vacation', $this->username);
  131. # TODO db_log() call (maybe except if called from set_away?)
  132. /* crap error handling; oh for exceptions... */
  133. return true;
  134. }
  135. /**
  136. * @return boolean true indicates this server supports vacation messages, and users are able to change their own.
  137. */
  138. public function vacation_supported()
  139. {
  140. return Config::bool('vacation') && Config::bool('vacation_control');
  141. }
  142. /**
  143. * @return boolean true if on vacation, otherwise false
  144. * Why do we bother storing true/false in the vacation table if the alias dictates it anyway?
  145. */
  146. public function check_vacation()
  147. {
  148. $handler = new AliasHandler();
  149. if (!$handler->init($this->id)) {
  150. # print_r($handler->errormsg); # TODO: error handling
  151. return false;
  152. }
  153. if (!$handler->view()) {
  154. # print_r($handler->errormsg); # TODO: error handling
  155. return false;
  156. }
  157. $result = $handler->result();
  158. if ($result['on_vacation']) {
  159. return true;
  160. }
  161. return false;
  162. }
  163. /**
  164. * Retrieve information on someone who is on vacation
  165. * @return array|boolean stored information on vacation - array(subject - string, message - string, active - boolean, activeFrom - date, activeUntil - date)
  166. * will return false if no existing data
  167. */
  168. public function get_details()
  169. {
  170. $table_vacation = table_by_key('vacation');
  171. $sql = "SELECT * FROM $table_vacation WHERE email = :username";
  172. $result = db_query_all($sql, array('username' => $this->username));
  173. if (sizeof($result) != 1) {
  174. return false;
  175. }
  176. $row = $result[0];
  177. if (!is_array($row)) {
  178. return false;
  179. }
  180. $boolean = ($row['active'] == db_get_boolean(true));
  181. # TODO: only return true and store the db result array in $this->whatever for consistency with the other classes
  182. return array(
  183. 'subject' => isset($row['subject']) ? $row['subject'] : null,
  184. 'body' => isset($row['body']) ? $row['body'] : null,
  185. 'active' => $boolean,
  186. 'interval_time' => isset($row['interval_time']) ? $row['interval_time'] : null,
  187. 'activeFrom' => isset($row['activefrom']) ? $row['activefrom'] : null,
  188. 'activeUntil' => isset($row['activeuntil']) ? $row['activeuntil'] : null
  189. );
  190. }
  191. /**
  192. * @param string $subject
  193. * @param string $body
  194. * @param int $interval_time
  195. * @param string $activeFrom - something strtotime understands
  196. * @param string $activeUntil - something strtotime understands
  197. * @return boolean
  198. */
  199. public function set_away($subject, $body, $interval_time, $activeFrom, $activeUntil)
  200. {
  201. $this->remove(); // clean out any notifications that might already have been sent.
  202. if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $activeFrom)) {
  203. $activeFrom .= ' 00:00:00';
  204. }
  205. if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $activeUntil)) {
  206. $activeUntil .= ' 23:59:59';
  207. }
  208. $activeFrom = date("Y-m-d H:i", strtotime($activeFrom)); # TODO check if result looks like a valid date
  209. $activeUntil = date("Y-m-d H:i", strtotime($activeUntil)); # TODO check if result looks like a valid date
  210. list(/*NULL*/, $domain) = explode('@', $this->username);
  211. $vacation_data = array(
  212. 'email' => $this->username,
  213. 'domain' => $domain,
  214. 'subject' => $subject,
  215. 'body' => $body,
  216. 'interval_time' => $interval_time,
  217. 'active' => db_get_boolean(true),
  218. 'activefrom' => $activeFrom,
  219. 'activeuntil' => $activeUntil,
  220. );
  221. if (! db_pgsql()) {
  222. $vacation_data['cache'] = ''; # leftover from 2.2
  223. }
  224. // is there an entry in the vacaton table for the user, or do we need to insert?
  225. $table_vacation = table_by_key('vacation');
  226. $result = db_query_one("SELECT * FROM $table_vacation WHERE email = ?", array($this->username));
  227. if (!empty($result)) {
  228. $result = db_update('vacation', 'email', $this->username, $vacation_data);
  229. } else {
  230. $result = db_insert('vacation', $vacation_data);
  231. }
  232. # TODO error check
  233. # TODO wrap whole function in db_begin / db_commit (or rollback)?
  234. return $this->updateAlias(1);
  235. }
  236. /**
  237. * add/remove the vacation alias
  238. * @param int $vacationActive
  239. * @return boolean
  240. */
  241. protected function updateAlias($vacationActive)
  242. {
  243. $handler = new AliasHandler();
  244. if (!$handler->init($this->id)) {
  245. # print_r($handler->errormsg); # TODO: error handling
  246. return false;
  247. }
  248. $values = array(
  249. 'on_vacation' => $vacationActive,
  250. );
  251. if (!$handler->set($values)) {
  252. # print_r($handler->errormsg); # TODO: error handling
  253. return false;
  254. }
  255. # TODO: supress logging in AliasHandler if called from VacationHandler (VacationHandler should log itsself)
  256. if (!$handler->save()) {
  257. print_r($handler->errormsg); # TODO: error handling
  258. return false;
  259. }
  260. # still here? then everything worked
  261. return true;
  262. }
  263. }
  264. /* vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */