1: <?php
2: /**
3: * SieveFilters modules
4: * @package modules
5: * @subpackage sievefilters
6: */
7:
8: if (!defined('DEBUG_MODE')) { die(); }
9:
10: use PhpSieveManager\ManageSieve\Client;
11: use PhpSieveManager\Exceptions\SocketException;
12:
13: require_once APP_PATH.'modules/imap/functions.php';
14: require_once APP_PATH.'modules/imap/hm-imap.php';
15: require_once APP_PATH.'modules/sievefilters/hm-sieve.php';
16: require_once APP_PATH.'modules/sievefilters/functions.php';
17:
18: /**
19: * @subpackage sievefilters/handler
20: */
21: class Hm_Handler_sieve_edit_filter extends Hm_Handler_Module {
22: public function process() {
23: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
24:
25: foreach ($this->user_config->get('imap_servers') as $mailbox) {
26: if ($mailbox['name'] == $this->request->post['imap_account']) {
27: $imap_account = $mailbox;
28: }
29: }
30:
31: $factory = get_sieve_client_factory($this->config);
32: try {
33: $client = $factory->init($this->user_config, $imap_account, $this->module_is_supported('nux'));
34: $script = $client->getScript($this->request->post['sieve_script_name']);
35: $list = prepare_sieve_script ($script, 1, "encode");
36: $this->out('conditions', $list);
37: $list = prepare_sieve_script ($script, 2, "encode");
38: $this->out('actions', $list);
39: if (mb_strstr($script, 'allof')) {
40: $this->out('test_type', 'ALLOF');
41: } else {
42: $this->out('test_type', 'ANYOF');
43: }
44: $client->close();
45: } catch (Exception $e) {
46: Hm_Msgs::add("Sieve: {$e->getMessage()}", "danger");
47: return;
48: }
49: }
50: }
51:
52: /**
53: * @subpackage sievefilters/handler
54: */
55: class Hm_Handler_sieve_filters_enabled extends Hm_Handler_Module {
56: public function process() {
57: $this->out('sieve_filters_enabled', $this->user_config->get('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER));
58: }
59: }
60:
61: /**
62: * @subpackage sievefilters/handler
63: */
64: class Hm_Handler_sieve_filters_enabled_message_content extends Hm_Handler_Module {
65: public function process() {
66: $server = $this->user_config->get('imap_servers')[$this->request->post['imap_server_id']];
67: $sieve_filters_enabled = $this->user_config->get('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER);
68: if ($sieve_filters_enabled && !empty($server['sieve_config_host'])) {
69: $factory = get_sieve_client_factory($this->config);
70: try {
71: $client = $factory->init($this->user_config, $server, $this->module_is_supported('nux'));
72: $sieve_filters_enabled = true;
73: $this->out('sieve_filters_client', $client);
74: } catch (Exception $e) {
75: Hm_Msgs::add("Sieve: {$e->getMessage()}", "danger");
76: }
77: }
78: $this->out('sieve_filters_enabled', $sieve_filters_enabled);
79: }
80: }
81:
82: /**
83: * @subpackage sievefilters/output
84: */
85: class Hm_Output_sieve_edit_filter extends Hm_Output_Module {
86: public function output() {
87: $conditions = $this->get('conditions', '');
88: $this->out('conditions', $conditions);
89: $actions = $this->get('actions', '');
90: $this->out('actions', $actions);
91: $actions = $this->get('test_type', '');
92: $this->out('test_type', $actions);
93: }
94: }
95:
96: /**
97: * @subpackage sievefilters/handler
98: */
99: class Hm_Handler_sieve_edit_script extends Hm_Handler_Module {
100: public function process() {
101: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
102:
103: foreach ($this->user_config->get('imap_servers') as $mailbox) {
104: if ($mailbox['name'] == $this->request->post['imap_account']) {
105: $imap_account = $mailbox;
106: }
107: }
108: $factory = get_sieve_client_factory($this->config);
109: try {
110: $client = $factory->init($this->user_config, $imap_account, $this->module_is_supported('nux'));
111: $script = $client->getScript($this->request->post['sieve_script_name']);
112: $client->close();
113: $this->out('script', $script);
114: } catch (Exception $e) {
115: Hm_Msgs::add("Sieve: {$e->getMessage()}", "danger");
116: }
117: }
118: }
119:
120: /**
121: * @subpackage sievefilters/output
122: */
123: class Hm_Output_sieve_edit_output extends Hm_Output_Module {
124: public function output() {
125: $script = $this->get('script', '');
126: $this->out('script', $script);
127: }
128: }
129:
130:
131: /**
132: * @subpackage sievefilters/handler
133: */
134: class Hm_Handler_sieve_delete_filter extends Hm_Handler_Module {
135: public function process() {
136: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
137:
138: foreach ($this->user_config->get('imap_servers') as $mailbox) {
139: if ($mailbox['name'] == $this->request->post['imap_account']) {
140: $imap_account = $mailbox;
141: }
142: }
143: $factory = get_sieve_client_factory($this->config);
144: try {
145: $client = $factory->init($this->user_config, $imap_account, $this->module_is_supported('nux'));
146:
147: $scripts = $client->listScripts();
148: foreach ($scripts as $script) {
149: if ($script == 'main_script') {
150: $client->removeScripts('main_script');
151: }
152: if ($script == $this->request->post['sieve_script_name']) {
153: $client->removeScripts($this->request->post['sieve_script_name']);
154: $this->out('script_removed', true);
155: }
156: }
157: $scripts = $client->listScripts();
158: $main_script = generate_main_script($scripts);
159: save_main_script($client, $main_script, $scripts);
160: $client->activateScript('main_script');
161: $client->close();
162: Hm_Msgs::add('Script removed');
163: } catch (Exception $e) {
164: Hm_Msgs::add("Sieve: {$e->getMessage()}", "danger");
165: }
166: }
167: }
168:
169:
170: /**
171: * @subpackage sievefilters/handler
172: */
173: class Hm_Handler_sieve_delete_script extends Hm_Handler_Module {
174: public function process() {
175: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
176:
177: foreach ($this->user_config->get('imap_servers') as $mailbox) {
178: if ($mailbox['name'] == $this->request->post['imap_account']) {
179: $imap_account = $mailbox;
180: }
181: }
182: $factory = get_sieve_client_factory($this->config);
183: try {
184: $client = $factory->init($this->user_config, $imap_account, $this->module_is_supported('nux'));
185:
186: $scripts = $client->listScripts();
187: foreach ($scripts as $script) {
188: if ($script == 'main_script') {
189: $client->removeScripts('main_script');
190: }
191: if ($script == $this->request->post['sieve_script_name']) {
192: $client->removeScripts($this->request->post['sieve_script_name']);
193: $this->out('script_removed', true);
194: }
195: }
196: $scripts = $client->listScripts();
197: $main_script = generate_main_script($scripts);
198:
199: save_main_script($client, $main_script, $scripts);
200: $client->activateScript('main_script');
201: $client->close();
202: Hm_Msgs::add('Script removed');
203: } catch (Exception $e) {
204: Hm_Msgs::add("Sieve: {$e->getMessage()}", "danger");
205: }
206: }
207: }
208:
209: /**
210: * @subpackage sievefilters/handler
211: */
212: class Hm_Handler_sieve_block_domain_script extends Hm_Handler_Module {
213: public function process() {
214: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
215:
216: $imap_account = null;
217: foreach ($this->user_config->get('imap_servers') as $idx => $mailbox) {
218: if ($idx == $this->request->post['imap_server_id']) {
219: $imap_account = $mailbox;
220: break;
221: }
222: }
223:
224: $email_sender = $this->request->post['sender'];
225: $factory = get_sieve_client_factory($this->config);
226: try {
227: $client = $factory->init($this->user_config, $imap_account, $this->module_is_supported('nux'));
228: $scripts = $client->listScripts();
229:
230: $current_script = $client->getScript('blocked_senders');
231: $blocked_list = prepare_sieve_script ($current_script);
232:
233: $domain = get_domain($this->request->post['sender']);
234: $blocked_wildcard = '@'.$domain;
235: $new_blocked_list = [];
236: foreach ($blocked_list as $idx => $blocked_sender) {
237: if (!mb_strstr($blocked_sender, $blocked_wildcard)) {
238: $new_blocked_list[] = $blocked_sender;
239: }
240: }
241: $new_blocked_list[] = $blocked_wildcard;
242:
243: if(array_search('blocked_senders', $scripts, true) === false) {
244: $client->putScript(
245: 'blocked_senders',
246: ''
247: );
248: }
249:
250: // Create Block List Filter
251: $filter = \PhpSieveManager\Filters\FilterFactory::create('blocked_senders');
252: $custom_condition = new \PhpSieveManager\Filters\Condition(
253: "CYPHT GENERATED CONDITION", 'anyof'
254: );
255: foreach ($new_blocked_list as $blocked_sender) {
256: $cond = \PhpSieveManager\Filters\FilterCriteria::if('header');
257: $cond->contains('"From" ["'.$blocked_sender.'"]');
258: $custom_condition->addCriteria($cond);
259: }
260: $custom_condition->addAction(
261: new \PhpSieveManager\Filters\Actions\DiscardFilterAction()
262: );
263: $custom_condition->addAction(
264: new \PhpSieveManager\Filters\Actions\StopFilterAction()
265: );
266: $filter->setCondition($custom_condition);
267: $script_parsed = $filter->toScript();
268:
269: $main_script = generate_main_script($scripts);
270:
271: $header_obj = "# CYPHT CONFIG HEADER - DON'T REMOVE";
272: $header_obj .= "\n# ".base64_encode(json_encode($new_blocked_list));
273: $script_parsed = $header_obj."\n\n".$script_parsed;
274: $client->putScript(
275: 'blocked_senders',
276: $script_parsed
277: );
278: save_main_script($client, $main_script, $scripts);
279: $client->activateScript('main_script');
280: $client->close();
281: $this->out('reload_page', true);
282: } catch (Exception $e) {
283: Hm_Msgs::add("Sieve: {$e->getMessage()}", "danger");
284: return;
285: }
286: }
287: }
288: class Hm_Output_sieve_block_domain_output extends Hm_Output_Module {
289: public function output() {
290: $reload_page = $this->get('reload_page', false);
291: $this->out('reload_page', $reload_page);
292: }
293: }
294:
295: /**
296: * @subpackage sievefilters/handler
297: */
298: class Hm_Handler_sieve_get_mailboxes_script extends Hm_Handler_Module {
299: public function process() {
300: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
301:
302: list($success, $form) = $this->process_form(array('imap_account'));
303: if (!$success) {
304: return;
305: }
306: $imap_server_id = null;
307: foreach ($this->user_config->get('imap_servers') as $idx => $mailbox) {
308: if ($mailbox['name'] == $this->request->post['imap_account']) {
309: $imap_account = $mailbox;
310: $imap_server_id = $idx;
311: }
312: }
313: $mailbox = Hm_IMAP_List::get_connected_mailbox($imap_server_id, $this->cache);
314: if (! $mailbox || ! $mailbox->authed()) {
315: Hm_Msgs::add('IMAP Authentication Failed', 'danger');
316: return;
317: }
318: $mailboxes = [];
319: foreach ($mailbox->get_folders() as $idx => $mailbox) {
320: $mailboxes[] = $mailbox['name'];
321: }
322: $this->out('mailboxes', json_encode($mailboxes));
323: }
324: }
325:
326:
327: class Hm_Output_sieve_get_mailboxes_output extends Hm_Output_Module {
328: public function output() {
329: $mailboxes = $this->get('mailboxes', '');
330: $this->out('mailboxes', $mailboxes);
331: }
332: }
333:
334: /**
335: * @subpackage sievefilters/handler
336: */
337: class Hm_Handler_sieve_unblock_sender extends Hm_Handler_Module {
338: public function process() {
339: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
340:
341: list($success, $form) = $this->process_form(array('imap_server_id', 'sender'));
342:
343: if (!$success) {
344: return;
345: }
346:
347: foreach ($this->user_config->get('imap_servers') as $idx => $mailbox) {
348: if ($idx == $form['imap_server_id']) {
349: $imap_account = $mailbox;
350: }
351: }
352:
353: $email_sender = $this->request->post['sender'];
354: if (mb_strstr($email_sender, '*')) {
355: $email_sender = str_replace('*', '', $email_sender);
356: }
357:
358: $default_behaviour = 'Discard';
359: if ($this->user_config->get('sieve_block_default_behaviour')) {
360: if (array_key_exists($form['imap_server_id'], $this->user_config->get('sieve_block_default_behaviour'))) {
361: $default_behaviour = $this->user_config->get('sieve_block_default_behaviour')[$form['imap_server_id']];
362: }
363: }
364:
365: $factory = get_sieve_client_factory($this->config);
366: try {
367: $client = $factory->init($this->user_config, $imap_account, $this->module_is_supported('nux'));
368: $scripts = $client->listScripts();
369:
370: if(array_search('blocked_senders', $scripts, true) === false) {
371: $client->putScript(
372: 'blocked_senders',
373: ''
374: );
375: }
376:
377: $blocked_senders = [];
378: $current_script = $client->getScript('blocked_senders');
379: $unblock_sender = false;
380: if ($current_script != '') {
381: $blocked_list = prepare_sieve_script ($current_script);
382: foreach ($blocked_list as $blocked_sender) {
383: if ($blocked_sender != $email_sender) {
384: $blocked_senders[] = $blocked_sender;
385: continue;
386: }
387: $unblock_sender = true;
388: }
389: }
390: if ($unblock_sender == false || $current_script == '') {
391: $blocked_senders[] = $email_sender;
392: }
393:
394: if (count($blocked_senders) == 0 && $unblock_sender) {
395: $client->putScript(
396: 'blocked_senders',
397: ''
398: );
399: Hm_Msgs::add('Sender Unblocked');
400: return;
401: }
402:
403: // Create Block List Filter
404: $filter = \PhpSieveManager\Filters\FilterFactory::create('blocked_senders');
405: $custom_condition = new \PhpSieveManager\Filters\Condition(
406: "CYPHT GENERATED CONDITION", 'anyof'
407: );
408: foreach ($blocked_senders as $blocked_sender) {
409: $cond = \PhpSieveManager\Filters\FilterCriteria::if('header');
410: $cond->contains('"From" ["'.$blocked_sender.'"]');
411: $custom_condition->addCriteria($cond);
412: }
413:
414: if ($default_behaviour == 'Discard') {
415: $custom_condition->addAction(
416: new \PhpSieveManager\Filters\Actions\DiscardFilterAction()
417: );
418: }
419: elseif ($default_behaviour == 'Reject') {
420: $filter->addRequirement('reject');
421: $custom_condition->addAction(
422: new \PhpSieveManager\Filters\Actions\RejectFilterAction([""])
423: );
424: }
425: $custom_condition->addAction(
426: new \PhpSieveManager\Filters\Actions\StopFilterAction()
427: );
428: $filter->setCondition($custom_condition);
429: $script_parsed = $filter->toScript();
430:
431: $main_script = generate_main_script($scripts);
432:
433: $header_obj = "# CYPHT CONFIG HEADER - DON'T REMOVE";
434: $header_obj .= "\n# ".base64_encode(json_encode($blocked_senders));
435: $script_parsed = $header_obj."\n\n".$script_parsed;
436: $client->putScript(
437: 'blocked_senders',
438: $script_parsed
439: );
440: save_main_script($client, $main_script, $scripts);
441: $client->activateScript('main_script');
442: $client->close();
443:
444: if ($unblock_sender) {
445: Hm_Msgs::add('Sender Unblocked');
446: } else {
447: Hm_Msgs::add('Sender Blocked');
448: }
449: } catch (Exception $e) {
450: Hm_Msgs::add("Sieve: {$e->getMessage()}", "danger");
451: return;
452: }
453: }
454: }
455:
456: /**
457: * @subpackage sievefilters/handler
458: */
459: class Hm_Handler_sieve_block_unblock_script extends Hm_Handler_Module {
460: public function process() {
461: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
462:
463: list($success, $form) = $this->process_form(array('imap_server_id', 'block_action', 'scope'));
464: if (!$success) {
465: return;
466: }
467:
468: foreach ($this->user_config->get('imap_servers') as $idx => $mailbox) {
469: if ($idx == $this->request->post['imap_server_id']) {
470: $imap_account = $mailbox;
471: }
472: }
473: $array_email_sender = [];
474: $email_sender = null;
475:
476: if (isset($this->request->post['imap_msg_uid']) && !empty($this->request->post['imap_msg_uid'])) {
477: $form['imap_msg_uid'] = $this->request->post['imap_msg_uid'];
478: $mailbox = Hm_IMAP_List::get_connected_mailbox($this->request->post['imap_server_id'], $this->cache);
479: if (! $mailbox || ! $mailbox->authed()) {
480: Hm_Msgs::add('IMAP Authentication Failed', 'danger');
481: return;
482: }
483: $msg_header = $mailbox->get_message_headers(hex2bin($this->request->post['folder']), $form['imap_msg_uid']);
484: $test_pattern = "/(?:[a-z0-9!#$%&'*+=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/";
485: preg_match_all($test_pattern, $msg_header['From'], $email_sender);
486: $email_sender = $email_sender[0][0];
487: } elseif (!empty($this->request->post['sender'])) {
488: $email_sender = $this->request->post['sender'];
489: if (isset($this->request->post['is_screened'])) {
490: $array_email_sender = explode(",", $email_sender);
491: $email_sender = null;
492: }
493: } else {
494: Hm_Msgs::add('Sender not found', 'warning');
495: return;
496: }
497:
498: $scope = 'sender';
499: if (isset($this->request->post['scope']) && $this->request->post['scope'] == 'domain') {
500: $email_sender = '*@'.get_domain($email_sender);
501: $scope = 'domain';
502: }
503: $scope_title = ucfirst($scope);
504:
505: $factory = get_sieve_client_factory($this->config);
506: try {
507: $client = $factory->init($this->user_config, $imap_account, $this->module_is_supported('nux'));
508: $scripts = $client->listScripts();
509:
510: if(array_search('blocked_senders', $scripts, true) === false) {
511: $client->putScript(
512: 'blocked_senders',
513: ''
514: );
515: }
516:
517: $blocked_senders = [];
518: $current_script = $client->getScript('blocked_senders');
519:
520: $blocked_list_actions = [];
521: $unblock_sender = false;
522: if ($current_script != '') {
523: $blocked_list = prepare_sieve_script ($current_script);
524: if ($email_sender) {
525: foreach ($blocked_list as $blocked_sender) {
526: if ($blocked_sender != $email_sender) {
527: $blocked_senders[] = $blocked_sender;
528: continue;
529: }
530: $unblock_sender = true;
531: }
532: } else {
533: if ($array_email_sender) {
534: $blocked_senders = array_diff($array_email_sender, $blocked_list);
535: }
536: }
537: $blocked_list_actions = prepare_sieve_script ($current_script, 2);
538: }
539: if (isset($this->request->post['change_behavior']) && $unblock_sender) {
540: $unblock_sender = false;
541: }
542: if ($unblock_sender == false || $current_script == '') {
543: if ($email_sender) {
544: $blocked_senders[] = $email_sender;
545: }
546:
547: if ($array_email_sender) {
548: $blocked_senders = $array_email_sender;
549: }
550:
551: }
552:
553: $blocked_senders = array_unique($blocked_senders);
554:
555: if (count($blocked_senders) == 0 && $unblock_sender) {
556: $client->putScript(
557: 'blocked_senders',
558: ''
559: );
560: Hm_Msgs::add($scope_title . ' Unblocked');
561: return;
562: }
563:
564: $filter = \PhpSieveManager\Filters\FilterFactory::create('blocked_senders');
565: foreach ($blocked_senders as $blocked_sender) {
566: if ($blocked_sender == $email_sender || ($array_email_sender && in_array($blocked_sender, $array_email_sender))) {
567: $actions = block_filter(
568: $filter,
569: $this->user_config,
570: $this->request->post['block_action'],
571: $this->request->post['imap_server_id'],
572: $blocked_sender,
573: $this->request->post['reject_message']
574: );
575: } elseif (array_key_exists($blocked_sender, $blocked_list_actions)) {
576: $reject_message = '';
577: if ($blocked_list_actions[$blocked_sender]['action'] == 'reject_with_message') {
578: $reject_message = $blocked_list_actions[$blocked_sender]['reject_message'];
579: }
580: $actions = block_filter(
581: $filter,
582: $this->user_config,
583: $blocked_list_actions[$blocked_sender]['action'],$this->request->post['imap_server_id'],
584: $blocked_sender,
585: $reject_message
586: );
587: } else {
588: $actions = block_filter(
589: $filter,
590: $this->user_config,
591: 'default',
592: $this->request->post['imap_server_id'],
593: $blocked_sender
594: );
595: }
596: $blocked_list_actions[$blocked_sender] = $actions;
597: }
598: $script_parsed = $filter->toScript();
599:
600: $main_script = generate_main_script($scripts);
601:
602: $header_obj = "# CYPHT CONFIG HEADER - DON'T REMOVE";
603: $header_obj .= "\n# ".base64_encode(json_encode($blocked_senders));
604: $header_obj .= "\n# ".base64_encode(json_encode($blocked_list_actions));
605: $script_parsed = $header_obj."\n\n".$script_parsed;
606:
607: $client->putScript(
608: 'blocked_senders',
609: $script_parsed
610: );
611: save_main_script($client, $main_script, $scripts);
612: $client->activateScript('main_script');
613: $client->close();
614:
615: if (isset($this->request->post['change_behavior'])) {
616: Hm_Msgs::add($scope_title . ' Behavior Changed');
617: } else {
618: if ($unblock_sender) {
619: Hm_Msgs::add($scope_title . ' Unblocked');
620: } else {
621: Hm_Msgs::add($scope_title . ' Blocked');
622: }
623: }
624: } catch (Exception $e) {
625: Hm_Msgs::add("Sieve: {$e->getMessage()}", "danger");
626: return;
627: }
628: }
629: }
630:
631: /**
632: * @subpackage sievefilters/output
633: */
634: class Hm_Output_sieve_delete_output extends Hm_Output_Module {
635: public function output() {
636: $removed = $this->get('script_removed', false);
637: $this->out('script_removed', $removed);
638: }
639: }
640:
641: /**
642: * @subpackage sievefilters/output
643: */
644: class Hm_Output_sieve_save_filter_output extends Hm_Output_Module {
645: public function output() {
646: $script_details = $this->get('script_details', []);
647: $this->out('script_details', $script_details);
648: }
649: }
650:
651: /**
652: * @subpackage sievefilters/handler
653: */
654: class Hm_Handler_sieve_save_filter extends Hm_Handler_Module {
655: public function process() {
656: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
657:
658: $priority = $this->request->post['sieve_filter_priority'];
659: if ($this->request->post['sieve_filter_priority'] == '') {
660: $priority = 0;
661: }
662: foreach ($this->user_config->get('imap_servers') as $mailbox) {
663: if ($mailbox['name'] == $this->request->post['imap_account']) {
664: $imap_account = $mailbox;
665: }
666: }
667: $script_name = generate_filter_name($this->request->post['sieve_filter_name'], $priority);
668: $conditions = json_decode($this->request->post['conditions_json']);
669: $actions = json_decode($this->request->post['actions_json']);
670: $test_type = mb_strtolower($this->request->post['filter_test_type']);
671:
672: $filter = \PhpSieveManager\Filters\FilterFactory::create($script_name);
673: $custom_condition = new \PhpSieveManager\Filters\Condition(
674: "CYPHT GENERATED CONDITION", $test_type
675: );
676: foreach ($conditions as $condition) {
677: $cond = null;
678: if ($condition->condition == 'body') {
679: $filter->addRequirement('body');
680: $cond = \PhpSieveManager\Filters\FilterCriteria::if('body');
681: if ($condition->type == 'Matches') {
682: $cond->matches('"'.$condition->value.'"');
683: }
684: if ($condition->type == 'Contains') {
685: $cond->contains('"'.$condition->value.'"');
686: }
687: if ($condition->type == '!Matches') {
688: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not body');
689: $cond->matches('"'.$condition->value.'"');
690: }
691: if ($condition->type == '!Contains') {
692: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not body');
693: $cond->contains('"'.$condition->value.'"');
694: }
695: if ($condition->type == 'Regex') {
696: $filter->addRequirement('regex');
697: $cond = \PhpSieveManager\Filters\FilterCriteria::if('body');
698: $cond->regex('"'.$condition->value.'"');
699: }
700: if ($condition->type == '!Regex') {
701: $filter->addRequirement('regex');
702: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not body');
703: $cond->regex('"'.$condition->value.'"');
704: }
705: }
706: if ($condition->condition == 'subject') {
707: $cond = \PhpSieveManager\Filters\FilterCriteria::if('header');
708: if ($condition->type == 'Matches') {
709: $cond->matches('"Subject" ["'.$condition->value.'"]');
710: }
711: if ($condition->type == 'Contains') {
712: $cond->contains('"Subject" ["'.$condition->value.'"]');
713: }
714: if ($condition->type == '!Matches') {
715: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
716: $cond->matches('"Subject" ["'.$condition->value.'"]');
717: }
718: if ($condition->type == '!Contains') {
719: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
720: $cond->contains('"Subject" ["'.$condition->value.'"]');
721: }
722: if ($condition->type == 'Regex') {
723: $filter->addRequirement('regex');
724: $cond = \PhpSieveManager\Filters\FilterCriteria::if('header');
725: $cond->regex('"Subject" "'.$condition->value.'"');
726: }
727: if ($condition->type == '!Regex') {
728: $filter->addRequirement('regex');
729: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
730: $cond->regex('"Subject" "'.$condition->value.'"');
731: }
732: }
733: if ($condition->condition == 'to') {
734: $cond = \PhpSieveManager\Filters\FilterCriteria::if('header');
735: if ($condition->type == 'Matches') {
736: $cond->matches('"Delivered-To" ["'.$condition->value.'"]');
737: }
738: if ($condition->type == 'Contains') {
739: $cond->contains('"Delivered-To" ["'.$condition->value.'"]');
740: }
741: if ($condition->type == '!Matches') {
742: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
743: $cond->matches('"Delivered-To" ["'.$condition->value.'"]');
744: }
745: if ($condition->type == '!Contains') {
746: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
747: $cond->contains('"Delivered-To" ["'.$condition->value.'"]');
748: }
749: if ($condition->type == 'Regex') {
750: $filter->addRequirement('regex');
751: $cond = \PhpSieveManager\Filters\FilterCriteria::if('header');
752: $cond->regex('"Delivered-To" "'.$condition->value.'"');
753: }
754: if ($condition->type == '!Regex') {
755: $filter->addRequirement('regex');
756: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
757: $cond->regex('"Delivered-To" "'.$condition->value.'"');
758: }
759: }
760: if ($condition->condition == 'from') {
761: $cond = \PhpSieveManager\Filters\FilterCriteria::if('header');
762: if ($condition->type == 'Matches') {
763: $cond->matches('"From" ["'.$condition->value.'"]');
764: }
765: if ($condition->type == 'Contains') {
766: $cond->contains('"From" ["'.$condition->value.'"]');
767: }
768: if ($condition->type == '!Matches') {
769: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
770: $cond->matches('"From" ["'.$condition->value.'"]');
771: }
772: if ($condition->type == '!Contains') {
773: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
774: $cond->contains('"From" ["'.$condition->value.'"]');
775: }
776: if ($condition->type == 'Regex') {
777: $filter->addRequirement('regex');
778: $cond = \PhpSieveManager\Filters\FilterCriteria::if('header');
779: $cond->regex('"From" "'.$condition->value.'"');
780: }
781: if ($condition->type == '!Regex') {
782: $filter->addRequirement('regex');
783: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
784: $cond->regex('"From" "'.$condition->value.'"');
785: }
786: }
787: if ($condition->condition == 'bcc') {
788: $cond = \PhpSieveManager\Filters\FilterCriteria::if('header');
789: if ($condition->type == 'Matches') {
790: $cond->matches('"Bcc" ["'.$condition->value.'"]');
791: }
792: if ($condition->type == 'Contains') {
793: $cond->contains('"Bcc" ["'.$condition->value.'"]');
794: }
795: if ($condition->type == '!Matches') {
796: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
797: $cond->matches('"Bcc" ["'.$condition->value.'"]');
798: }
799: if ($condition->type == '!Contains') {
800: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
801: $cond->contains('"Bcc" ["'.$condition->value.'"]');
802: }
803: if ($condition->type == 'Regex') {
804: $filter->addRequirement('regex');
805: $cond = \PhpSieveManager\Filters\FilterCriteria::if('header');
806: $cond->regex('"Bcc" "'.$condition->value.'"');
807: }
808: if ($condition->type == '!Regex') {
809: $filter->addRequirement('regex');
810: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
811: $cond->regex('"Bcc" "'.$condition->value.'"');
812: }
813: }
814: if ($condition->condition == 'cc') {
815: $cond = \PhpSieveManager\Filters\FilterCriteria::if('header');
816: if ($condition->type == 'Matches') {
817: $cond->matches('"Cc" ["'.$condition->value.'"]');
818: }
819: if ($condition->type == 'Contains') {
820: $cond->contains('"Cc" ["'.$condition->value.'"]');
821: }
822: if ($condition->type == '!Matches') {
823: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
824: $cond->matches('"Cc" ["'.$condition->value.'"]');
825: }
826: if ($condition->type == '!Contains') {
827: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
828: $cond->contains('"Cc" ["'.$condition->value.'"]');
829: }
830: if ($condition->type == 'Regex') {
831: $filter->addRequirement('regex');
832: $cond = \PhpSieveManager\Filters\FilterCriteria::if('header');
833: $cond->regex('"Cc" "'.$condition->value.'"');
834: }
835: if ($condition->type == '!Regex') {
836: $filter->addRequirement('regex');
837: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
838: $cond->regex('"Cc" "'.$condition->value.'"');
839: }
840: }
841: if ($condition->condition == 'to_or_cc') {
842: $cond_to = \PhpSieveManager\Filters\FilterCriteria::if('header');
843: $cond = \PhpSieveManager\Filters\FilterCriteria::if('header');
844: if ($condition->type == 'Matches') {
845: $cond->matches('"Cc" ["'.$condition->value.'"]');
846: $cond_to->matches('"Delivered-To" ["'.$condition->value.'"]');
847: }
848: if ($condition->type == 'Contains') {
849: $cond->contains('"Cc" ["'.$condition->value.'"]');
850: $cond_to->contains('"Delivered-To" ["'.$condition->value.'"]');
851: }
852: if ($condition->type == '!Matches') {
853: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
854: $cond_to = \PhpSieveManager\Filters\FilterCriteria::if('not header');
855: $cond->matches('"Cc" ["'.$condition->value.'"]');
856: $cond_to->matches('"Delivered-To" ["'.$condition->value.'"]');
857: }
858: if ($condition->type == '!Contains') {
859: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
860: $cond_to = \PhpSieveManager\Filters\FilterCriteria::if('not header');
861: $cond->contains('"Cc" ["'.$condition->value.'"]');
862: $cond_to->contains('"Delivered-To" ["'.$condition->value.'"]');
863: }
864: if ($condition->type == 'Regex') {
865: $filter->addRequirement('regex');
866: $cond = \PhpSieveManager\Filters\FilterCriteria::if('header');
867: $cond_to = \PhpSieveManager\Filters\FilterCriteria::if('header');
868: $cond->regex('"Cc" "'.$condition->value.'"');
869: $cond_to->matches('"Delivered-To" "'.$condition->value.'"');
870: }
871: if ($condition->type == '!Regex') {
872: $filter->addRequirement('regex');
873: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
874: $cond_to = \PhpSieveManager\Filters\FilterCriteria::if('not header');
875: $cond->regex('"Cc" "'.$condition->value.'"');
876: $cond_to->matches('"Delivered-To" "'.$condition->value.'"');
877: }
878: $custom_condition->addCriteria($cond_to);
879: }
880: if ($condition->condition == 'size') {
881: $cond = \PhpSieveManager\Filters\FilterCriteria::if('size');
882: if ($condition->type == 'Over') {
883: $cond->over($condition->value.'K');
884: }
885: if ($condition->type == 'Under') {
886: $cond->under($condition->value.'K');
887: }
888: if ($condition->type == '!Over') {
889: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not size');
890: $cond->over($condition->value.'K');
891: }
892: if ($condition->type == '!Under') {
893: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not size');
894: $cond->under($condition->value.'K');
895: }
896: }
897: if ($condition->condition == 'custom') {
898: $cond = \PhpSieveManager\Filters\FilterCriteria::if('header');
899: if ($condition->type == 'Matches') {
900: $cond->matches('"'.$condition->extra_option_value.'" "'.$condition->value.'"');
901: }
902: if ($condition->type == '!Matches') {
903: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
904: $cond->matches('"'.$condition->extra_option_value.'" "'.$condition->value.'"');
905: }
906: if ($condition->type == 'Contains') {
907: $cond->contains('"'.$condition->extra_option_value.'" "'.$condition->value.'"');
908: }
909: if ($condition->type == '!Contains') {
910: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
911: $cond->contains('"'.$condition->extra_option_value.'" "'.$condition->value.'"');
912: }
913: if ($condition->type == 'Regex') {
914: $cond->regex('"'.$condition->extra_option_value.'" "'.$condition->value.'"');
915: }
916: if ($condition->type == '!Regex') {
917: $cond = \PhpSieveManager\Filters\FilterCriteria::if('not header');
918: $cond->regex('"'.$condition->extra_option_value.'" "'.$condition->value.'"');
919: }
920: }
921: if ($cond) {
922: $custom_condition->addCriteria($cond);
923: }
924: }
925:
926: foreach ($actions as $action) {
927: if ($action->action == 'discard') {
928: $custom_condition->addAction(
929: new \PhpSieveManager\Filters\Actions\DiscardFilterAction()
930: );
931: }
932: if ($action->action == 'keep') {
933: $custom_condition->addAction(
934: new \PhpSieveManager\Filters\Actions\KeepFilterAction()
935: );
936: }
937: if ($action->action == 'stop') {
938: $custom_condition->addAction(
939: new \PhpSieveManager\Filters\Actions\StopFilterAction()
940: );
941: }
942: if ($action->action == 'redirect') {
943: $custom_condition->addAction(
944: new \PhpSieveManager\Filters\Actions\RedirectFilterAction(['address' => $action->value])
945: );
946: }
947: if ($action->action == 'forward') {
948: $custom_condition->addAction(
949: new \PhpSieveManager\Filters\Actions\RedirectFilterAction(['address' => $action->value])
950: );
951: $custom_condition->addAction(
952: new \PhpSieveManager\Filters\Actions\KeepFilterAction()
953: );
954: }
955: if ($action->action == 'flag') {
956: $custom_condition->addAction(
957: new \PhpSieveManager\Filters\Actions\FlagFilterAction(['flags' => [$action->value]])
958: );
959: }
960: if ($action->action == 'addflag') {
961: $custom_condition->addAction(
962: new \PhpSieveManager\Filters\Actions\AddFlagFilterAction(['flags' => [$action->value]])
963: );
964: }
965: if ($action->action == 'removeflag') {
966: $custom_condition->addAction(
967: new \PhpSieveManager\Filters\Actions\RemoveFlagFilterAction(['flags' => [$action->value]])
968: );
969: }
970: if ($action->action == 'move') {
971: $custom_condition->addAction(
972: new \PhpSieveManager\Filters\Actions\FileIntoFilterAction(['mailbox' => $action->value])
973: );
974: }
975: if ($action->action == 'reject') {
976: $custom_condition->addAction(
977: new \PhpSieveManager\Filters\Actions\RejectFilterAction(['reason' => $action->value])
978: );
979: }
980: if ($action->action == 'copy') {
981: $custom_condition->addAction(
982: new \PhpSieveManager\Filters\Actions\FileIntoFilterAction(['mailbox' => $action->value])
983: );
984: $custom_condition->addAction(
985: new \PhpSieveManager\Filters\Actions\KeepFilterAction()
986: );
987: }
988: if ($action->action == 'autoreply') {
989: $custom_condition->addAction(
990: new \PhpSieveManager\Filters\Actions\VacationFilterAction(['reason' => $action->value, 'subject' => $action->extra_option_value])
991: );
992: }
993: }
994: $filter->setCondition($custom_condition);
995: $script_parsed = $filter->toScript();
996:
997: if ($this->request->post['gen_script']) {
998: $this->out('script_details', [
999: 'gen_script' => $script_parsed,
1000: 'filter_priority' => $priority,
1001: 'filter_name' => $this->request->post['sieve_filter_name']
1002: ]);
1003: return;
1004: }
1005:
1006: $header_obj = "# CYPHT CONFIG HEADER - DON'T REMOVE";
1007: $header_obj .= "\n# ".base64_encode($this->request->post['conditions_json']);
1008: $header_obj .= "\n# ".base64_encode($this->request->post['actions_json']);
1009: $script_parsed = $header_obj."\n\n".$script_parsed;
1010:
1011: $factory = get_sieve_client_factory($this->config);
1012: try {
1013: $client = $factory->init($this->user_config, $imap_account, $this->module_is_supported('nux'));
1014: $scripts = $client->listScripts();
1015: foreach ($scripts as $script) {
1016: if ($script == 'main_script') {
1017: $client->removeScripts('main_script');
1018: }
1019: if ($script == $this->request->post['current_editing_filter_name']) {
1020: $client->removeScripts($this->request->post['current_editing_filter_name']);
1021: }
1022: }
1023:
1024: $client->putScript(
1025: $script_name,
1026: $script_parsed
1027: );
1028:
1029: $scripts = $client->listScripts();
1030: $main_script = generate_main_script($scripts);
1031:
1032: save_main_script($client, $main_script, $scripts);
1033: $client->activateScript('main_script');
1034: $client->close();
1035: } catch (Exception $e) {
1036: Hm_Msgs::add("Sieve: {$e->getMessage()}", "danger");
1037: return;
1038: }
1039: }
1040: }
1041:
1042: /**
1043: * @subpackage sievefilters/handler
1044: */
1045: class Hm_Handler_sieve_save_script extends Hm_Handler_Module {
1046: public function process() {
1047: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
1048:
1049: $priority = $this->request->post['sieve_script_priority'];
1050: if ($this->request->post['sieve_script_priority'] == '') {
1051: $priority = 0;
1052: }
1053: $script_name = generate_script_name($this->request->post['sieve_script_name'], $priority);
1054: foreach ($this->user_config->get('imap_servers') as $mailbox) {
1055: if ($mailbox['name'] == $this->request->post['imap_account']) {
1056: $imap_account = $mailbox;
1057: }
1058: }
1059: $factory = get_sieve_client_factory($this->config);
1060: try {
1061: $client = $factory->init($this->user_config, $imap_account, $this->module_is_supported('nux'));
1062: $scripts = $client->listScripts();
1063: foreach ($scripts as $script) {
1064: if ($script == $this->request->post['current_editing_script']) {
1065: $client->removeScripts($this->request->post['current_editing_script']);
1066: }
1067: }
1068: $client->putScript(
1069: $script_name,
1070: $this->request->post['script']
1071: );
1072: } catch (Exception $e) {
1073: Hm_Msgs::add("Sieve: {$e->getMessage()}", "danger");
1074: return;
1075: }
1076: }
1077: }
1078:
1079: /**
1080: * @subpackage sievefilters/handler
1081: */
1082: class Hm_Handler_sieve_block_change_behaviour_script extends Hm_Handler_Module {
1083: public function process() {
1084: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
1085:
1086: $imap_server_id = $this->request->post['imap_server_id'];
1087: if (!$this->user_config->get('sieve_block_default_behaviour')) {
1088: $this->user_config->set('sieve_block_default_behaviour', []);
1089: }
1090: if (!$this->user_config->get('sieve_block_default_reject_message')) {
1091: $this->user_config->set('sieve_block_default_reject_message', []);
1092: }
1093: $behaviours = $this->user_config->get('sieve_block_default_behaviour');
1094: $behaviours[$imap_server_id] = $this->request->post['selected_behaviour'];
1095: $this->user_config->set('sieve_block_default_behaviour', $behaviours);
1096:
1097: $reject_messages = $this->user_config->get('sieve_block_default_reject_message');
1098: $reject_messages[$imap_server_id] = $this->request->post['reject_message'] ?? '';
1099: $this->user_config->set('sieve_block_default_reject_message', $reject_messages);
1100:
1101: $this->session->record_unsaved('Changed Sieve Block behaviour');
1102: $this->session->set('user_data', $this->user_config->dump());
1103:
1104: Hm_Msgs::add('Default behaviour changed');
1105: }
1106: }
1107:
1108: /**
1109: * @subpackage sievefilters/output
1110: */
1111: class Hm_Output_sieve_lock_change_behaviour_output extends Hm_Output_Module {
1112: public function output() {
1113:
1114: }
1115: }
1116:
1117: /**
1118: * @subpackage sievefilters/output
1119: */
1120: class Hm_Output_sieve_save_script_output extends Hm_Output_Module {
1121: public function output() {
1122:
1123: }
1124: }
1125:
1126: /**
1127: * @subpackage sievefilters/handler
1128: */
1129: class Hm_Handler_settings_load_imap extends Hm_Handler_Module {
1130: public function process() {
1131: $this->out('imap_accounts', $this->user_config->get('imap_servers'), array());
1132: $this->out('site_config', $this->config);
1133: $this->out('user_config', $this->user_config);
1134: }
1135: }
1136:
1137: /**
1138: * @subpackage sievefilters/output
1139: */
1140: class Hm_Output_sievefilters_settings_link extends Hm_Output_Module {
1141: protected function output() {
1142: if (!$this->get('sieve_filters_enabled')) {
1143: return '';
1144: }
1145: $res = '<li class="menu_sieve_filters"><a class="unread_link" href="?page=sieve_filters">';
1146: if (!$this->get('hide_folder_icons')) {
1147: $res .= '<i class="bi bi-journal-bookmark-fill fs-5 me-2"></i>';
1148: }
1149: $res .= $this->trans('Filters').'</a></li>';
1150: $res .= '<li class="menu_block_list"><a class="unread_link" href="?page=block_list">';
1151: if (!$this->get('hide_folder_icons')) {
1152: $res .= '<i class="bi bi-x-circle-fill fs-5 me-2"></i>';
1153: }
1154: $res .= $this->trans('Block List').'</a></li>';
1155: if ($this->format == 'HTML5') {
1156: return $res;
1157: }
1158: $this->concat('formatted_folder_list', $res);
1159: }
1160: }
1161:
1162: /**
1163: * @subpackage sievefilters/output
1164: */
1165: class Hm_Output_sievefilters_settings_start extends Hm_Output_Module {
1166: protected function output() {
1167: $socked_connected = $this->get('socket_connected', false);
1168: $res = '<div class="sievefilters_settings p-0"><div class="content_title px-3">'.$this->trans('Filters').'</div>';
1169: $res .= '<div class="p-3">';
1170: $res .= '<div class="p-3" id="sieve_accounts"></div>';
1171: $res .= get_classic_filter_modal_content();
1172: $res .= get_script_modal_content();
1173: return $res;
1174: }
1175: }
1176:
1177: /**
1178: * @subpackage sievefilters/output
1179: */
1180: class Hm_Output_blocklist_settings_start extends Hm_Output_Module {
1181: protected function output() {
1182: $socked_connected = $this->get('socket_connected', false);
1183: $res = '<div class="sievefilters_settings p-0"><div class="content_title px-3">'.$this->trans('Block List').'</div>';
1184: $res .= '<div class="p-3" id="sieve_accounts"></div>';
1185: $res .= get_classic_filter_modal_content();
1186: $res .= get_script_modal_content();
1187: return $res;
1188: }
1189: }
1190:
1191: /**
1192: * @subpackage sievefilters/handler
1193: */
1194: class Hm_Handler_load_behaviour extends Hm_Handler_Module
1195: {
1196: public function process()
1197: {
1198: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
1199:
1200: if ($this->user_config->get('sieve_block_default_behaviour')) {
1201: $this->out('sieve_block_default_behaviour', $this->user_config->get('sieve_block_default_behaviour'));
1202: } else {
1203: $this->out('sieve_block_default_behaviour', []);
1204: }
1205: if ($this->user_config->get('sieve_block_default_reject_message')) {
1206: $this->out('sieve_block_default_reject_message', $this->user_config->get('sieve_block_default_reject_message'));
1207: } else {
1208: $this->out('sieve_block_default_reject_message', []);
1209: }
1210: }
1211: }
1212:
1213: /**
1214: * @subpackage sievefilters/output
1215: */
1216: class Hm_Output_blocklist_settings_accounts extends Hm_Output_Module {
1217: protected function output() {
1218: if (! ($mailbox = $this->get('mailbox')) || empty($mailbox['sieve_config_host']) || !$this->get('sieve_filters_enabled')) {
1219: return;
1220: }
1221: $behaviours = $this->get('sieve_block_default_behaviour');
1222: $reject_messages = $this->get('sieve_block_default_reject_message');
1223: $default_behaviour = 'Discard';
1224: $default_reject_message = '';
1225: if (array_key_exists($mailbox['id'], $behaviours)) {
1226: $default_behaviour = $behaviours[$mailbox['id']];
1227: }
1228: if (array_key_exists($mailbox['id'], $reject_messages)) {
1229: $default_reject_message = $reject_messages[$mailbox['id']];
1230: }
1231:
1232: $default_behaviour_html = '<div class="col-xxl-12 col-xl-9 mb-4"><div class="input-group"><span class="input-group-text">Default Behaviour:</span> <select class="select_default_behaviour form-select " imap_account="' . $mailbox['id'] . '">'
1233: . '<option value="Discard"' . ($default_behaviour == 'Discard' ? ' selected' : '') . '>Discard</option>'
1234: . '<option value="Reject"' . ($default_behaviour == 'Reject' ? ' selected' : '') . '>' . $this->trans('Reject') . '</option>'
1235: . '<option value="Move" ' . ($default_behaviour == 'Move' ? ' selected' : '') . '>' . $this->trans('Move To Blocked Folder') . '</option></select>';
1236: if ($default_behaviour == 'Reject') {
1237: $default_behaviour_html .= '<input type="text" class="select_default_reject_message form-control" value="' . $default_reject_message . '" placeholder="' . $this->trans('Reject message') . '" />';
1238: }
1239: $default_behaviour_html .= '<button class="submit_default_behavior btn btn-primary">' . $this->trans('Submit') . '</button></div></div>';
1240: $blocked_senders = get_blocked_senders_array($mailbox, $this->get('site_config'), $this->get('user_config'));
1241: $num_blocked = $blocked_senders ? sizeof($blocked_senders) : 0;
1242: $res = '<div class="sievefilters_accounts_item">';
1243: $res .= '<div class="sievefilters_accounts_title settings_subtitle py-2 border-bottom cursor-pointer d-flex justify-content-between" data-num-blocked="' . $num_blocked . '">' . $mailbox['name'];
1244: $res .= '<span class="filters_count"><span id="filter_num_' . $mailbox['id'] . '">' . $num_blocked . '</span> ' . $this->trans('blocked') . '</span></div>';
1245: $res .= '<div class="sievefilters_accounts filter_block py-3 d-none"><div class="filter_subblock">';
1246: $res .= $default_behaviour_html;
1247: $res .= '<table class="filter_details table"><tbody>';
1248: $res .= '<tr><th class="col-sm-6">Sender</th><th class="col-sm-3">Behavior</th><th class="col-sm-3">Actions</th></tr>';
1249: $res .= get_blocked_senders($mailbox, $mailbox['id'], 'x-circle-fill', 'globe-europe-africa', $this->get('site_config'), $this->get('user_config'), $this);
1250: $res .= '</tbody></table>';
1251: $res .= '</div></div></div>';
1252: $this->out('sieve_detail_display', $res);
1253: }
1254: }
1255:
1256: /**
1257: * @subpackage sievefilters/output
1258: */
1259: class Hm_Output_account_sieve_filters extends Hm_Output_Module {
1260: protected function output() {
1261: if (! ($mailbox = $this->get('mailbox')) || empty($mailbox['sieve_config_host']) || !$this->get('sieve_filters_enabled')) {
1262: return;
1263: }
1264: $result = get_mailbox_filters($mailbox, $this->get('site_config'), $this->get('user_config'));
1265: $num_filters = $result['count'];
1266: $res = '<div class="sievefilters_accounts_item">';
1267: $res .= '<div class="sievefilters_accounts_title settings_subtitle py-2 d-flex justify-content-between border-bottom cursor-pointer">' . $mailbox['name'];
1268: $res .= '<span class="filters_count">' . sprintf($this->trans('%s filters'), $num_filters) . '</span></div>';
1269: $res .= '<div class="sievefilters_accounts filter_block p-3 d-none"><div class="filter_subblock">';
1270: $res .= '<button class="add_filter btn btn-primary" account="'.$mailbox['name'].'">Add Filter</button> <button account="'.$mailbox['name'].'" class="add_script btn btn-light border">Add Script</button>';
1271: $res .= '<table class="filter_details table my-3"><tbody>';
1272: $res .= '<tr><th class="text-secondary fw-light col-sm-1">Priority</th><th class="text-secondary fw-light col-sm-9">Name</th><th class="text-secondary fw-light col-sm-2">Actions</th></tr>';
1273: $res .= $result['list'];
1274: $res .= '</tbody></table>';
1275: $res .= '<div class="mb-3 d-none">
1276: <div class="d-block">
1277: <h3 class="mb-1">If conditions are not met</h3>
1278: <small>Define the actions if conditions are not met. If no actions are provided the next filter will be executed. If there are no other filters to be executed, the email will be delivered as expected.</small>
1279: </div>
1280: </div>
1281: <div class="col-sm-12 mt-5 d-none" style="background-color: #f7f2ef;">
1282: <div class="d-flex p-3">
1283: <div class="d-block">
1284: <h5 class="mt-0">Actions</h5>
1285: </div>
1286: <div class="text-end flex-grow-1">
1287: <button class="filter_modal_add_else_action_btn me-2">Add Action</button>
1288: </div>
1289: </div>
1290: <div class="d-block">
1291: <table class="filter_else_actions_modal_table">
1292: </table>
1293: </div>
1294: </div>';
1295: $res .= '</div></div></div>';
1296:
1297: $this->out('sieve_detail_display', $res);
1298: error_log('Session after: ' . print_r($_SESSION, true));
1299: }
1300: }
1301:
1302: /**
1303: * @subpackage sievefilters/output
1304: */
1305: class Hm_Output_check_filter_status extends Hm_Output_Module {
1306: protected function output() {
1307: if (!$this->get('sieve_filters_enabled')) {
1308: $res = '<div class="empty_list">' . $this->trans('Sieve filter is deactivated') . '</div>';
1309: $this->out('sieve_detail_display', $res);
1310: }
1311: }
1312: }
1313:
1314: /**
1315: * @subpackage keyboard_shortcuts/handler
1316: */
1317: class Hm_Handler_process_enable_sieve_filter_setting extends Hm_Handler_Module {
1318: public function process() {
1319: function sieve_enabled_callback($val) { return $val; }
1320: process_site_setting('enable_sieve_filter', $this, 'sieve_enabled_callback', DEFAULT_ENABLE_SIEVE_FILTER, true);
1321: }
1322: }
1323:
1324: /**
1325: * @subpackage keyboard_shortcuts/output
1326: */
1327: class Hm_Output_enable_sieve_filter_setting extends Hm_Output_Module {
1328: protected function output() {
1329: $settings = $this->get('user_settings');
1330: if ((array_key_exists('enable_sieve_filter', $settings) && $settings['enable_sieve_filter']) || DEFAULT_ENABLE_SIEVE_FILTER) {
1331: $checked = ' checked="checked"';
1332: }
1333: else {
1334: $checked = '';
1335: }
1336:
1337: if($settings['enable_sieve_filter'] != DEFAULT_ENABLE_SIEVE_FILTER) {
1338: $reset = '<span class="tooltip_restore" restore_aria_label="Restore default value"><i class="bi bi-arrow-counterclockwise refresh_list reset_default_value_checkbox"></i></span>';
1339: }else {
1340: $reset = '';
1341: }
1342: return '<tr class="general_setting"><td><label class="form-check-label" for="enable_sieve_filter">'.
1343: $this->trans('Enable sieve filter').'</label></td>'.
1344: '<td><input class="form-check-input" type="checkbox" '.$checked.
1345: ' value="1" id="enable_sieve_filter" name="enable_sieve_filter" data-default-value="'.(DEFAULT_ENABLE_SIEVE_FILTER ? 'true' : 'false') . '"/>'.$reset.'</td></tr>';
1346: }
1347: }
1348:
1349: /**
1350: * Check the status of an SIEVE server
1351: * @subpackage sieve/handler
1352: */
1353: class Hm_Handler_sieve_status extends Hm_Handler_Module {
1354: protected static $capabilities = [];
1355:
1356: /**
1357: * Output used on the info page to display the server status
1358: */
1359: public function process() {
1360: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
1361:
1362: list($success, $form) = $this->process_form(array('imap_server_ids'));
1363: if ($success) {
1364: $ids = explode(',', $form['imap_server_ids']);
1365: foreach ($ids as $id) {
1366: $imap_account = Hm_IMAP_List::get($id, true);
1367: if (isset($imap_account['sieve_config_host'])) {
1368: if (isset(self::$capabilities[$imap_account['sieve_config_host']])) {
1369: $this->out('sieve_server_capabilities', self::$capabilities[$imap_account['sieve_config_host']]);
1370: continue;
1371: }
1372:
1373: $client = initialize_sieve_client_factory($this->config, null, $imap_account);
1374:
1375: if ($client) {
1376: $this->out('sieve_server_capabilities', $client->getCapabilities());
1377: self::$capabilities[$imap_account['sieve_config_host']] = $client->getCapabilities();
1378: }
1379: }
1380: }
1381: }
1382: }
1383: }
1384:
1385: /**
1386: * Check the connection to a SIEVE server
1387: * @subpackage sieve/handler
1388: */
1389: class Hm_Handler_sieve_connect extends Hm_Handler_Module {
1390: public function process() {
1391: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
1392:
1393: if ($imap_details = $this->get('imap_connect_details')) {
1394: $factory = get_sieve_client_factory($this->site_config);
1395: try {
1396: $client = $factory->init($this->user_config, $imap_details, $this->module_is_supported('nux'));
1397: } catch (Exception $e) {
1398: Hm_Msgs::add("Failed to authenticate to the Sieve host", "danger");
1399: }
1400: }
1401: }
1402: }
1403:
1404:
1405: class Hm_Handler_sieve_toggle_script_state extends Hm_Handler_Module {
1406: public function process() {
1407: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
1408:
1409: list($success, $form) = $this->process_form(array('imap_account', 'script_state', 'sieve_script_name'));
1410: if (!$success) {
1411: $this->out('success', false);
1412: return;
1413: }
1414: $imap_account = Hm_IMAP_List::dump($form['imap_account']);
1415: $factory = get_sieve_client_factory($this->config);
1416: $success = false;
1417: try {
1418: $client = $factory->init($this->user_config, $imap_account, $this->module_is_supported('nux'));
1419: $state = $form['script_state'] ? 'enabled': 'disabled';
1420: $scripts = $client->listScripts();
1421: foreach ($scripts as $key => $script) {
1422: if ($script == 'main_script') {
1423: $client->removeScripts('main_script');
1424: }
1425: if ($script == $form['sieve_script_name']) {
1426: if (! $form['script_state']) {
1427: unset($scripts[$key]);
1428: }
1429: $client->renameScript($script, "s{$state}_");
1430: $success = true;
1431: }
1432: }
1433: $scripts = $client->listScripts();
1434: $main_script = generate_main_script($scripts);
1435: save_main_script($client, $main_script, $scripts);
1436: $client->activateScript('main_script');
1437: $client->close();
1438:
1439: Hm_Msgs::add("Script $state");
1440: } catch (Exception $e) {
1441: Hm_Msgs::add("Sieve: {$e->getMessage()}", "danger");
1442: }
1443: $this->out('success', $success);
1444: }
1445: }
1446: class Hm_Handler_list_block_sieve_script extends Hm_Handler_Module {
1447: public function process() {
1448: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
1449:
1450: list($success, $form) = $this->process_form(array('imap_server_id'));
1451: if (!$success) {
1452: return;
1453: }
1454:
1455: Hm_IMAP_List::init($this->user_config, $this->session);
1456: $imap_account = Hm_IMAP_List::get($form['imap_server_id'], true);
1457:
1458: if (empty($imap_account['sieve_config_host'])) {
1459: return;
1460: }
1461:
1462: $factory = get_sieve_client_factory($this->config);
1463: try {
1464: $client = $factory->init($this->user_config, $imap_account);
1465:
1466: $blocked_senders = [];
1467: $current_script = $client->getScript('blocked_senders');
1468: if ($current_script != '') {
1469: $blocked_list = prepare_sieve_script ($current_script);
1470: foreach ($blocked_list as $blocked_sender) {
1471: $blocked_senders[] = $blocked_sender;
1472: }
1473: }
1474: $this->out('ajax_list_block_sieve', json_encode($blocked_senders));
1475: } catch (Exception $e) {
1476: Hm_Msgs::add("ERRSieve: {$e->getMessage()}");
1477: return;
1478: }
1479: }
1480: }
1481:
1482: class Hm_Handler_check_sieve_configuration extends Hm_Handler_Module {
1483: public function process() {
1484: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
1485:
1486: Hm_IMAP_List::init($this->user_config, $this->session);
1487: $servers = Hm_IMAP_List::dump();
1488: $has_uncomplete_sieve_conf = (bool) array_filter($servers, fn($item) => $item['type'] !== 'ews' && empty($item['sieve_config_host']));
1489: if($has_uncomplete_sieve_conf) {
1490: $this->out('sieve_alert_message', 'Sieve is enabled but not fully configured on some servers. Please review and save the server configuration to complete setup.');
1491: }
1492: }
1493: }
1494:
1495: class Hm_Output_display_sieve_misconfig_alert extends Hm_Output_Module {
1496: protected function output() {
1497: if ($this->get('single_server_mode')) {
1498: return '';
1499: }
1500: $res = '';
1501: $sieve_alert_message = $this->get('sieve_alert_message');
1502: if(!empty($sieve_alert_message)) {
1503: $res = '<div class="mt-3"><div class="alert alert-warning alert-dismissible fade show" role="alert"><strong>'.$this->trans('Alert sieve!').'</strong> '. $sieve_alert_message .'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button></div></div>';
1504: }
1505: return $res;
1506: }
1507: }
1508:
1509:
1510: class Hm_Output_list_block_sieve_output extends Hm_Output_Module {
1511: public function output() {
1512: $list_block_sieve = $this->get('ajax_list_block_sieve', "");
1513: $this->out('ajax_list_block_sieve', $list_block_sieve);
1514: }
1515: }
1516:
1517: class Hm_Handler_load_account_sieve_filters extends Hm_Handler_Module
1518: {
1519: public function process()
1520: {
1521: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
1522:
1523: list($success, $form) = $this->process_form(array('imap_server_id'));
1524:
1525: if (!$success) {
1526: return;
1527: }
1528: $accounts = $this->get('imap_accounts');
1529: if (isset($accounts[$form['imap_server_id']])) {
1530: $this->out('mailbox', $accounts[$form['imap_server_id']]);
1531: $this->session->close_early();
1532: }
1533: }
1534: }
1535:
1536: class Hm_Handler_sieve_remame_folder extends Hm_Handler_Module
1537: {
1538: public function process()
1539: {
1540: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
1541:
1542: list($success, $form) = $this->process_form(array('imap_server_id', 'folder', 'new_folder'));
1543:
1544: if (!$success) {
1545: return;
1546: }
1547:
1548: $mailbox = Hm_IMAP_List::get_connected_mailbox($form['imap_server_id'], $this->cache);
1549: if ($mailbox && $mailbox->authed() && $mailbox->is_imap()) {
1550: $imap_servers = $this->user_config->get('imap_servers');
1551: $imap_account = $imap_servers[$form['imap_server_id']];
1552: $linked_mailboxes = get_sieve_linked_mailbox($imap_account, $this);
1553: if ($linked_mailboxes && in_array($form['folder'], $linked_mailboxes)) {
1554: $factory = get_sieve_client_factory($this->site_config);
1555: try {
1556: $client = $factory->init($this->user_config, $imap_account, $this->module_is_supported('nux'));
1557: $script_names = array_filter(
1558: $linked_mailboxes,
1559: function ($value) use ($form) {
1560: return $value == $form['folder'];
1561: }
1562: );
1563: $script_names = array_keys($script_names);
1564: foreach ($script_names as $script_name) {
1565: $script_parsed = $client->getScript($script_name);
1566: $script_parsed = str_replace('"'.$form['folder'].'"', '"'.$form['new_folder'].'"', $script_parsed);
1567:
1568: $old_actions = base64_decode(preg_split('#\r?\n#', $script_parsed, 0)[2]);
1569: $new_actions = base64_encode(str_replace('"'.$form['folder'].'"', '"'.$form['folder'].'"', $old_actions));
1570: $script_parsed = str_replace(base64_encode($old_actions), $new_actions, $script_parsed);
1571: $client->removeScripts($script_name);
1572: $client->putScript(
1573: $script_name,
1574: $script_parsed
1575: );
1576: }
1577: $client->close();
1578: Hm_Msgs::add('Sieve filters using the folder were also updated to use the new folder name.', 'info');
1579: } catch (Exception $e) {
1580: Hm_Msgs::add("Failed to rename folder in sieve scripts", "warning");
1581: }
1582: }
1583: }
1584: }
1585: }
1586:
1587: class Hm_Handler_sieve_can_delete_folder extends Hm_Handler_Module
1588: {
1589: public function process()
1590: {
1591: if ($this->should_skip_execution('enable_sieve_filter_setting', DEFAULT_ENABLE_SIEVE_FILTER)) return;
1592:
1593: list($success, $form) = $this->process_form(array('imap_server_id', 'folder'));
1594:
1595: if (! $success) {
1596: return;
1597: }
1598:
1599: $mailbox = Hm_IMAP_List::get_connected_mailbox($form['imap_server_id'], $this->cache);
1600: if ($mailbox && $mailbox->authed() && $mailbox->is_imap()) {
1601: $del_folder = prep_folder_name($mailbox->get_connection(), $form['folder'], true);
1602: if (is_mailbox_linked_with_filters($del_folder, $form['imap_server_id'], $this)) {
1603: $this->out('sieve_can_delete_folder', false);
1604: Hm_Msgs::add('This folder can\'t be deleted because it is used in a Sieve filter.', 'warning');
1605: }
1606: }
1607: }
1608: }
1609: