Completed
Pull Request — development (#2330)
by Joshua
41:37 queued 30:33
created

list_maillist_unapproved()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2
Metric Value
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 4
crap 2
1
<?php
2
3
/**
4
 * This file contains maillist functions that are specifically done by administrators
5
 * and those with approve email permission
6
 *
7
 * @name      ElkArte Forum
8
 * @copyright ElkArte Forum contributors
9
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
10
 *
11
 * @version 1.1 dev
12
 *
13
 */
14
15
if (!defined('ELK'))
16
	die('No access...');
17
18
/**
19
 * This class is the administration maillist controller.
20
 *
21
 *  - handles maillist configuration
22
 *  - handles the showing, repairing, deleting and bouncing failed emails
23
 *  - handles the adding / editing / removing of both filters and parsers
24
 *
25
 * @package Maillist
26
 */
27
class ManageMaillist_Controller extends Action_Controller
28
{
29
	/**
30
	 * Basic feature settings form
31
	 * @var Settings_Form
32
	 */
33
	protected $_maillistSettings;
34
35
	/**
36
	 * Basic filter settings form
37
	 * @var Settings_Form
38
	 */
39
	protected $_filtersSettings;
40
41
	/**
42
	 * Parsers settings form
43
	 * @var Settings_Form
44
	 */
45
	protected $_parsersSettings;
46
47
	/**
48
	 * Main dispatcher.
49
	 *
50
	 * This function checks permissions and passes control to the sub action.
51
	 *
52
	 * @see Action_Controller::action_index()
53
	 * @uses Maillist template
54
	 */
55
	public function action_index()
56
	{
57
		global $context, $txt;
58
59
		// Template & language
60
		loadTemplate('Maillist');
61
		loadLanguage('Maillist');
62
63
		// All the functions available
64
		$subActions = array(
65
			'emaillist' => array($this, 'action_unapproved_email', 'permission' => 'approve_emails'),
66
			'approve' => array($this, 'action_approve_email', 'permission' => 'approve_emails'),
67
			'delete' => array($this, 'action_delete_email', 'permission' => 'approve_emails'),
68
			'bounce' => array($this, 'action_bounce_email', 'permission' => 'approve_emails'),
69
			'emailtemplates' => array($this, 'action_view_bounce_templates', 'permission' => 'approve_emails'),
70
			'view' => array($this, 'action_view_email', 'permission' => 'approve_emails'),
71
			'emailsettings' => array($this, 'action_settings', 'permission' => 'admin_forum'),
72
			'emailfilters' => array($this, 'action_list_filters', 'permission' => 'admin_forum'),
73
			'editfilter' => array($this, 'action_edit_filters', 'permission' => 'admin_forum'),
74
			'deletefilter' => array($this, 'action_delete_filters', 'permission' => 'admin_forum'),
75
			'emailparser' => array($this, 'action_list_parsers', 'permission' => 'admin_forum'),
76
			'editparser' => array($this, 'action_edit_parsers', 'permission' => 'admin_forum'),
77
			'deleteparser' => array($this, 'action_delete_parsers', 'permission' => 'admin_forum'),
78
			'sortparsers' => array($this, 'action_sort_parsers', 'permission' => 'admin_forum'),
79
			'sortfilters' => array($this, 'action_sort_filters', 'permission' => 'admin_forum'),
80
		);
81
82
		// Action Controller
83
		$action = new Action('manage_maillist');
84
85
		// Help is needed in most places, so load it up front
86
		require_once(SUBSDIR . '/Maillist.subs.php');
87
88
		// Create the title area for the template.
89
		$context[$context['admin_menu_name']]['tab_data'] = array(
90
			'title' => $txt['ml_admin_configuration'],
91
			'help' => 'maillist_help_short',
92
			'description' => $txt['ml_configuration_desc'],
93
		);
94
95
		// Default to sub action 'emaillist' if none was given, call integrate_sa_manage_maillist
96
		$subAction = isset($this->_req->query->sa) && isset($subActions[$this->_req->query->sa]) && (empty($subActions[$this->_req->query->sa]['permission']) || allowedTo($subActions[$this->_req->query->sa]['permission'])) ? $this->_req->query->sa : 'emaillist';
97
		$subAction = $action->initialize($subActions, $subAction);
98
99
		// Final bits
100
		$context['page_title'] = $txt['ml_admin_configuration'];
101
		$context['sub_action'] = $subAction;
102
103
		// If you have the permissions, then go Play
104
		$action->dispatch($subAction);
105
	}
106
107
	/**
108
	 * Main listing of failed emails.
109
	 *
110
	 * What it does
111
	 * - shows the sender, key and subject of the email
112
	 * - Will show the found key if it was missing or possible sender if it was wrong
113
	 * - icons to view, bounce, delete or approve a failure
114
	 * - Accessed by ?action=admin;area=maillist;sa=emaillist
115
	 *
116
	 * @uses showlist sub template
117
	 */
118
	public function action_unapproved_email()
0 ignored issues
show
Coding Style introduced by
action_unapproved_email uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
119
	{
120
		global $context, $scripturl, $modSettings, $txt;
121
122
		// Set an id if none was supplied
123
		$id = $this->_req->getQuery('e_id', 'intval', 0);
124
		if (empty($id) || $id <= 0)
125
			$id = 0;
126
127
		createToken('admin-ml', 'get');
128
129
		// Build the list option array to display the email data
130
		$listOptions = array(
131
			'id' => 'view_email_errors',
132
			'title' => $txt['ml_emailerror'],
133
			'items_per_page' => $modSettings['defaultMaxMessages'],
134
			'no_items_label' => $txt['ml_emailerror_none'],
135
			'base_href' => $scripturl . '?action=admin;area=maillist',
136
			'default_sort_col' => 'id_email',
137
			'get_items' => array(
138
				'function' => array($this, 'list_maillist_unapproved'),
139
				'params' => array(
140
					$id,
141
				),
142
			),
143
			'get_count' => array(
144
				'function' => 'list_maillist_count_unapproved',
145
			),
146
			'columns' => array(
147
				'id_email' => array(
148
					'header' => array(
149
						'value' => $txt['id'],
150
						'class' => 'nowrap',
151
					),
152
					'data' => array(
153
						'db' => 'id_email',
154
					),
155
					'sort' => array(
156
						'default' => 'id_email ',
157
						'reverse' => 'id_email DESC',
158
					),
159
				),
160
				'error' => array(
161
					'header' => array(
162
						'value' => $txt['error'],
163
					),
164
					'data' => array(
165
						'function' => function($rowData) {
166
							$error = $rowData['error_code'];
167
							if ($error === 'error_pm_not_found')
168
								return '<span class="error">' . $rowData['error'] . '<span>';
169
							else
170
								return $rowData['error'];
171
						},
172
					),
173
					'sort' => array(
174
						'default' => 'error ',
175
						'reverse' => 'error DESC',
176
					),
177
				),
178
				'subject' => array(
179
					'header' => array(
180
						'value' => $txt['subject'],
181
					),
182
					'data' => array(
183
						'db' => 'subject',
184
					),
185
					'sort' => array(
186
						'default' => 'subject',
187
						'reverse' => 'subject DESC',
188
					),
189
				),
190
				'key' => array(
191
					'header' => array(
192
						'value' => $txt['key'],
193
					),
194
					'data' => array(
195
						'db' => 'key',
196
						'class' => 'wordbreak'
197
					),
198
					'sort' => array(
199
						'default' => 'message_key',
200
						'reverse' => 'message_key DESC',
201
					),
202
				),
203
				'message' => array(
204
					'header' => array(
205
						'value' => $txt['message_id'],
206
					),
207
					'data' => array(
208
						'sprintf' => array(
209
							'format' => '<a href="%1$s">%2$s</a>',
210
							'params' => array(
211
								'link' => true,
212
								'message' => true,
213
							),
214
						),
215
					),
216
					'sort' => array(
217
						'default' => 'message_id',
218
						'reverse' => 'message_id DESC',
219
					),
220
				),
221
				'from' => array(
222
					'header' => array(
223
						'value' => $txt['from'],
224
					),
225
					'data' => array(
226
						'db' => 'from',
227
					),
228
					'sort' => array(
229
						'default' => 'email_from',
230
						'reverse' => 'email_from DESC',
231
					),
232
				),
233
				'type' => array(
234
					'header' => array(
235
						'value' => $txt['message_type'],
236
					),
237
					'data' => array(
238
						'function' => function ($rowData) {
239
							global $txt;
240
241
							// Do we have a type?
242
							if (empty($rowData['type']))
243
								return $txt['not_applicable'];
244
							// Personal?
245
							elseif ($rowData['type'] === 'p')
246
								return $txt['personal_message'];
247
							// New Topic?
248
							elseif ($rowData['type'] === 'x')
249
								return $txt['new_topic'];
250
							// Ah a Reply then
251
							else
252
								return $txt['topic'] . ' ' . $txt['reply'];
253
						},
254
					),
255
					'sort' => array(
256
						'default' => 'message_type',
257
						'reverse' => 'message_type DESC',
258
					),
259
				),
260
				'action' => array(
261
					'header' => array(
262
						'value' => $txt['message_action'],
263
					),
264
					'data' => array(
265
						'function' => function($rowData) {
266
							global $context, $txt, $settings;
267
268
							$id = $rowData['id_email'] . ';';
269
							$commands = array();
270
							$security = $context['session_var'] . '=' . $context['session_id'] . ';' . $context['admin-ml_token_var'] . '=' . $context['admin-ml_token'];
271
272
							if ($rowData['error_code'] === 'error_pm_not_found')
273
								$commands[] = '<a href="?action=admin;area=maillist;sa=approve;item=' . $id . $security . '" onclick="return confirm(' . JavaScriptEscape($txt['pm_approve_warning']) . ') && submitThisOnce(this);"><img title="' . $txt['approve'] . '" src="' . $settings['images_url'] . '/icons/field_valid.png" alt="*" /></a>&nbsp;';
274
							else
275
								$commands[] = '<a href="?action=admin;area=maillist;sa=approve;item=' . $id . $security . '"><img title="' . $txt['approve'] . '" src="' . $settings['images_url'] . '/icons/field_valid.png" alt="*" /></a>&nbsp;';
276
277
							$commands[] = '<a href="?action=admin;area=maillist;sa=delete;item=' . $id . $security . '" onclick="return confirm(' . JavaScriptEscape($txt['delete_warning']) . ') && submitThisOnce(this);" accesskey="d"><img title="' . $txt['delete'] . '" src="' . $settings['images_url'] . '/icons/quick_remove.png" alt="*" /></a><br />';
278
							$commands[] = '<a href="?action=admin;area=maillist;sa=bounce;item=' . $id . $security . '"><img title="' . $txt['bounce'] . '" src="' . $settings['images_url'] . '/icons/pm_replied.png" alt="*" /></a>&nbsp;';
279
							$commands[] = '<a href="?action=admin;area=maillist;sa=view;item=' . $id . $security . '"><img title="' . $txt['view'] . '" src="' . $settings['images_url'] . '/icons/pm_read.png" alt="*" /></a>';
280
281
							return implode('', $commands);
282
						},
283
					),
284
					'class' => 'listaction',
285
				),
286
			),
287
			'form' => array(
288
				'href' => $scripturl . '?action=admin;area=maillist;sa=emaillist',
289
				'include_sort' => true,
290
				'include_start' => true,
291
			),
292
			'additional_rows' => array(
293
				array(
294
					'position' => 'top_of_list',
295
					'value' => isset($this->_req->session->email_error) ? '<div class="' . (isset($this->_req->session->email_error_type) ? 'successbox' : 'errorbox') . '">' . $this->_req->session->email_error . '</div>' : $txt['heading'],
296
				),
297
			),
298
		);
299
300
		// Clear any errors
301
		unset($_SESSION['email_error'], $_SESSION['email_error_type']);
302
303
		// Set the context values for the template
304
		$context['page_title'] = $txt['emailerror_title'];
305
		$context['sub_template'] = 'show_list';
306
		$context['default_list'] = 'view_email_errors';
307
308
		// Create the list.
309
		createList($listOptions);
310
	}
311
312
	/**
313
	 * Show a failed email for review by the moderation team
314
	 *
315
	 * - Will not show a PM if it has been identified as such
316
	 * - Accessed by ?action=admin;area=maillist;sa=view;item=?
317
	 *
318
	 * @uses show_email sub template
319
	 */
320
	public function action_view_email()
321
	{
322
		global $txt, $context;
323
324
		allowedTo('approve_emails');
325
		checkSession('get');
326
		validateToken('admin-ml', 'get');
327
328
		$id = (int) $this->_req->query->item;
329
		if (!empty($id))
330
		{
331
			// Load up the email details, no funny biz ;)
332
			$temp_email = list_maillist_unapproved($id);
333
334
			if (!empty($temp_email))
335
			{
336
				if ($temp_email[0]['type'] !== 'p' && allowedTo('approve_emails'))
337
				{
338
					// The raw email that failed
339
					$data = $temp_email[0]['body'];
340
341
					// Read/parse this message for viewing
342
					$controller = new Emailpost_Controller();
343
					$result = $controller->action_pbe_preview($data);
344
					$text = isset($result['body']) ? $result['body'] : '';
345
					$email_to = isset($result['to']) ? $result['to'] : '';
346
				}
347
				else
348
				{
349
					// PM's mean just that ...
350
					$text = $txt['noaccess'];
351
					$email_to = $txt['private'];
352
				}
353
			}
354
			else
355
				$text = $txt['badid'];
356
		}
357
		else
358
			$text = $txt['badid'];
359
360
		$parser = \BBC\ParserWrapper::getInstance();
361
		// Prep and show the template with what we found
362
		$context['body'] = $parser->parseEmail($text);
363
		$context['to'] = $txt['to'] . ' ' . (isset($email_to) ? $email_to : '');
364
		$context['notice_subject'] = isset($temp_email[0]['subject']) ? $txt['subject'] . ': ' . $temp_email[0]['subject'] : '';
365
		$context['notice_from'] = isset($temp_email[0]['from']) ? $txt['from'] . ': ' . $temp_email[0]['from'] : '';
366
		$context['page_title'] = $txt['show_notice'];
367
		$context['error_code'] = isset($temp_email[0]['error_code']) && isset($txt[$temp_email[0]['error_code']]) ? $txt[$temp_email[0]['error_code']] : '';
368
		$context['sub_template'] = 'show_email';
369
	}
370
371
	/**
372
	 * Deletes an entry from the database
373
	 *
374
	 * - Flushes the moderator menu todo numbers so the menu numbers update
375
	 * - Accessed by ?action=admin;area=maillist;sa=delete;item=?'
376
	 * - Redirects to ?action=admin;area=maillist;sa=emaillist
377
	 */
378
	public function action_delete_email()
379
	{
380
		allowedTo('approve_emails');
381
		checkSession('get');
382
		validateToken('admin-ml', 'get');
383
384
		$id = (int) $this->_req->query->item;
385
386
		// Remove this entry
387
		if (!empty($id))
388
			maillist_delete_error_entry($id);
389
390
		// Flush the cache
391
		Cache::instance()->put('num_menu_errors', null, 900);
392
393
		// Back to the failed list we go
394
		redirectexit('action=admin;area=maillist;sa=emaillist');
395
	}
396
397
	/**
398
	 * Attempts to approve and post a failed email
399
	 *
400
	 * - Reviews the data to see if the email error function fixed typical issues like key and wrong id
401
	 * - Submits the fixed email to the main function which will post it or fail it again
402
	 * - If successful will remove the entry from the failed log
403
	 * - Accessed by ?action=admin;area=maillist;sa=approve;item=?'
404
	 * - Redirects to action=admin;area=maillist;sa=emaillist
405
	 */
406
	public function action_approve_email()
0 ignored issues
show
Coding Style introduced by
action_approve_email uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
407
	{
408
		global $txt;
409
410
		allowedTo('approve_emails');
411
		checkSession('get');
412
		validateToken('admin-ml', 'get');
413
414
		// Get the id to approve
415
		$id = (int) $this->_req->query->item;
416
417
		if (!empty($id) && $id !== -1)
418
		{
419
			// Load up the email data
420
			$temp_email = list_maillist_unapproved($id);
421
			if (!empty($temp_email))
422
			{
423
				// Do we have the needed data to approve this, after all it failed for a reason yes?
424
				if (!empty($temp_email[0]['key']) && (!in_array($temp_email[0]['error_code'], array('error_no_message', 'error_not_find_board', 'error_topic_gone'))))
425
				{
426
					// Set up the details needed to get this posted
427
					$force = true;
428
					$key = $temp_email[0]['key'];
429
					$data = $temp_email[0]['body'];
430
431
					// Unknown from email?  Update the message ONLY if we found an appropriate one during the error checking process
432
					if (in_array($temp_email[0]['error_code'], array('error_not_find_member', 'error_key_sender_match')))
433
					{
434
						// did we actually find a potential correct name, if so we post from the valid member
435
						$check_emails = array_pad(explode('=>', $temp_email[0]['from']), 2, '');
436
437
						if (!empty($check_emails[1]))
438
							$data = preg_replace('~(From: )(.*<)?(' . preg_quote(trim($check_emails[0])) . ')(>)?(\n)~i', '$1$2' . trim($check_emails[1]) . '$4$5', $data);
439
					}
440
441
					// Lets TRY AGAIN to make a post!
442
					include_once(CONTROLLERDIR . '/Emailpost.controller.php');
443
					$controller = new Emailpost_Controller();
444
					$text = $controller->action_pbe_post($data, $force, $key);
445
446
					// Assuming all went well, remove this entry and file since we are done.
447
					if ($text === true)
448
					{
449
						maillist_delete_error_entry($id);
450
451
						// Flush the menu count cache
452
						Cache::instance()->put('num_menu_errors', null, 900);
453
454
						$_SESSION['email_error'] = $txt['approved'];
455
						$_SESSION['email_error_type'] = 1;
456
					}
457
					else
458
						$_SESSION['email_error'] = $txt['error_approved'];
459
				}
460
				else
461
					$_SESSION['email_error'] = $txt['cant_approve'];
462
			}
463
			else
464
				$_SESSION['email_error'] = $txt['badid'];
465
		}
466
		else
467
			$_SESSION['email_error'] = $txt['badid'];
468
469
		// back to the list we go
470
		redirectexit('action=admin;area=maillist;sa=emaillist');
471
	}
472
473
	/**
474
	 * Allows the admin to choose from predefined and custom templates
475
	 *
476
	 * - Uses the selected template to send a bounce notification with
477
	 * details as specified by the template
478
	 * - Accessed by ?action=admin;area=maillist;sa=bounce;item=?'
479
	 * - Redirects to action=admin;area=maillist;sa=bounced
480
	 *
481
	 * @uses bounce_email sub-template
482
	 */
483
	public function action_bounce_email()
484
	{
485
		global $context, $txt, $modSettings, $scripturl, $mbname;
486
487
		if (!isset($this->_req->query->bounce))
488
		{
489
			checkSession('get');
490
			validateToken('admin-ml', 'get');
491
		}
492
493
		require_once(SUBSDIR . '/Mail.subs.php');
494
495
		// We should have been sent an email ID
496
		if (isset($this->_req->query->item))
497
		{
498
			// Needs to be an int!
499
			$id = (int) $this->_req->query->item;
500
501
			// Load up the email details, no funny biz yall ;)
502
			$temp_email = list_maillist_unapproved($id);
503
504
			if (!empty($temp_email))
505
			{
506
				// Set the options
507
				$this->_req->post->item = (int) $temp_email[0]['id_email'];
508
				$fullerrortext = $txt[$temp_email[0]['error_code']];
509
510
				// Build the template selection area, first the standard ones
511
				$bounce = array('bounce', 'inform');
512
				foreach ($bounce as $k => $type)
513
				{
514
					$context['bounce_templates'][$k]['body'] = $txt['ml_' . $type . '_body'];
515
					$context['bounce_templates'][$k]['subject'] = $txt['ml_' . $type . '_subject'];
516
					$context['bounce_templates'][$k]['title'] = $txt['ml_' . $type . '_title'];
517
				}
518
519
				// And now any custom ones available for this moderator
520
				$context['bounce_templates'] += array_merge($context['bounce_templates'], maillist_templates('bnctpl', $txt['ml_bounce_template_subject_default']));
521
522
				// Replace all the variables in the templates
523
				foreach ($context['bounce_templates'] as $k => $name)
524
				{
525
					$context['bounce_templates'][$k]['body'] = strtr($name['body'], array(
526
						'{MEMBER}' => un_htmlspecialchars($temp_email[0]['name']),
527
						'{SCRIPTURL}' => $scripturl,
528
						'{FORUMNAME}' => $mbname,
529
						'{REGARDS}' => replaceBasicActionUrl($txt['regards_team']),
530
						'{SUBJECT}' => $temp_email[0]['subject'],
531
						'{ERROR}' => $fullerrortext,
532
						'{FORUMNAMESHORT}' => (!empty($modSettings['maillist_sitename']) ? $modSettings['maillist_sitename'] : $mbname),
533
						'{EMAILREGARDS}' => (!empty($modSettings['maillist_sitename_regards']) ? $modSettings['maillist_sitename_regards'] : ''),
534
					));
535
				}
536
			}
537
			else
538
				$context['settings_message'] = $txt['badid'];
539
		}
540
		else
541
			$context['settings_message'] = $txt['badid'];
542
543
		// Check if they are sending the notice
544
		if (isset($this->_req->query->bounce) && isset($temp_email))
545
		{
546
			checkSession('post');
547
			validateToken('admin-ml');
548
549
			// They did check the box, how else could they have posted
550
			if (isset($this->_req->post->warn_notify))
551
			{
552
				// lets make sure we have the items to send it
553
				$check_emails = explode('=>', $temp_email[0]['from']);
554
				$to = trim($check_emails[0]);
555
				$subject = trim($this->_req->post->warn_sub);
556
				$body = trim($this->_req->post->warn_body);
557
558
				if (empty($body) || empty($subject))
559
					$context['settings_message'] = $txt['bad_bounce'];
560
				else
561
				{
562
					// Time for someone to get a we're so sorry message!
563
					sendmail($to, $subject, $body, null, null, false, 5);
564
					redirectexit('action=admin;area=maillist;bounced');
565
				}
566
			}
567
		}
568
569
		// Prepare and show the template
570
		createToken('admin-ml');
571
		$context['warning_data'] = array('notify' => '', 'notify_subject' => '', 'notify_body' => '');
572
		$context['body'] = isset($fullerrortext) ? \BBC\ParserWrapper::getInstance()->parseEmail($fullerrortext) : '';
573
		$context['item'] = isset($this->_req->post->item) ? $this->_req->post->item : '';
574
		$context['notice_to'] = $txt['to'] . ' ' . isset($temp_email[0]['from']) ? $temp_email[0]['from'] : '';
0 ignored issues
show
Bug introduced by
The variable $temp_email does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
575
		$context['page_title'] = $txt['bounce_title'];
576
		$context['sub_template'] = 'bounce_email';
577
	}
578
579
	/**
580
	 * List all the filters in the system
581
	 *
582
	 * - Allows to add/edit or delete filters
583
	 * - Filters are used to alter text in a post, to remove crud that comes with emails
584
	 * - Filters can be defined as regex, the system will check it for valid syntax
585
	 * - Accessed by ?action=admin;area=maillist;sa=emailfilters;
586
	 */
587
	public function action_list_filters()
588
	{
589
		global $context, $scripturl, $txt, $settings, $modSettings;
590
591
		$id = 0;
592
593
		// Build the listoption array to display the filters
594
		$listOptions = array(
595
			'id' => 'email_filter',
596
			'title' => $txt['filters'],
597
			'items_per_page' => $modSettings['defaultMaxMessages'],
598
			'no_items_label' => $txt['no_filters'],
599
			'base_href' => $scripturl . '?action=admin;area=maillist;sa=emailfilters',
600
			'default_sort_col' => 'name',
601
			'get_items' => array(
602
				'function' => array($this, 'load_filter_parser'),
603
				'params' => array(
604
					$id,
605
					'filter'
606
				),
607
			),
608
			'get_count' => array(
609
				'function' => array($this, 'count_filter_parser'),
610
				'params' => array(
611
					$id,
612
					'filter'
613
				),
614
			),
615
			'columns' => array(
616
				'name' => array(
617
					'header' => array(
618
						'value' => $txt['filter_name'],
619
						'style' => 'white-space: nowrap;'
620
					),
621
					'data' => array(
622
						'db' => 'filter_name',
623
					),
624
					'sort' => array(
625
						'default' => 'filter_name, id_filter',
626
						'reverse' => 'filter_name DESC, id_filter DESC',
627
					),
628
				),
629
				'from' => array(
630
					'header' => array(
631
						'value' => $txt['filter_from'],
632
					),
633
					'data' => array(
634
						'db' => 'filter_from',
635
					),
636
					'sort' => array(
637
						'default' => 'filter_from, id_filter',
638
						'reverse' => 'filter_from DESC, id_filter DESC',
639
					),
640
				),
641
				'to' => array(
642
					'header' => array(
643
						'value' => $txt['filter_to'],
644
						'style' => 'width:10em;',
645
					),
646
					'data' => array(
647
						'db' => 'filter_to',
648
					),
649
					'sort' => array(
650
						'default' => 'filter_to, id_filter',
651
						'reverse' => 'filter_to DESC, id_filter DESC',
652
					),
653
				),
654
				'type' => array(
655
					'header' => array(
656
						'value' => $txt['filter_type'],
657
					),
658
					'data' => array(
659
						'db' => 'filter_type',
660
					),
661
					'sort' => array(
662
						'default' => 'filter_type, id_filter',
663
						'reverse' => 'filter_type DESC, id_filter DESC',
664
					),
665
				),
666
				'action' => array(
667
					'header' => array(
668
						'value' => $txt['message_action'],
669
						'class' => 'centertext',
670
					),
671
					'data' => array(
672
						'sprintf' => array(
673
							'format' => '<a href="?action=admin;area=maillist;sa=editfilter;f_id=%1$s;' . $context['session_var'] . '=' . $context['session_id'] . '">
674
										<img title="' . $txt['modify'] . '" src="' . $settings['images_url'] . '/buttons/modify.png" alt="*" />
675
									</a>
676
									<a href="?action=admin;area=maillist;sa=deletefilter;f_id=%1$s;' . $context['session_var'] . '=' . $context['session_id'] . '" onclick="return confirm(' . JavaScriptEscape($txt['filter_delete_warning']) . ') && submitThisOnce(this);" accesskey="d">
677
										<img title="' . $txt['delete'] . '" src="' . $settings['images_url'] . '/buttons/delete.png" alt="*" />
678
									</a>',
679
							'params' => array(
680
								'id_filter' => true,
681
							),
682
						),
683
						'class' => 'centertext',
684
						'style' => 'white-space:nowrap;',
685
					),
686
				),
687
			),
688
			'form' => array(
689
				'href' => $scripturl . '?action=admin;area=maillist;sa=editfilter;',
690
				'include_sort' => true,
691
				'include_start' => true,
692
				'hidden_fields' => array(
693
					$context['session_var'] => $context['session_id'],
694
				),
695
			),
696
			'additional_rows' => array(
697
				array(
698
					'position' => isset($this->_req->query->saved) ? 'top_of_list' : 'after_title',
699
					'value' => isset($this->_req->query->saved) ? '<div class="successbox">' . $txt['saved'] . '</div>' : $txt['filters_title'],
700
				),
701
				array(
702
					'position' => 'below_table_data',
703
					'class' => 'submitbutton',
704
					'value' => '<input type="submit" name="addfilter" value="' . $txt['add_filter'] . '" />
705
						<a class="linkbutton" href="' . $scripturl . '?action=admin;area=maillist;sa=sortfilters">' . $txt['sort_filter'] . '</a>',
706
				),
707
			),
708
		);
709
710
		// Set the context values
711
		$context['page_title'] = $txt['filters'];
712
		$context['sub_template'] = 'show_list';
713
		$context['default_list'] = 'email_filter';
714
715
		// Create the list.
716
		createList($listOptions);
717
	}
718
719
	/**
720
	 * Show a full list of all the filters in the system for drag/drop sorting
721
	 */
722
	public function action_sort_filters()
723
	{
724
		global $context, $scripturl, $txt;
725
726
		$id = 0;
727
		$token = createToken('admin-sort');
728
729
		// build the listoption array to display the data
730
		$listOptions = array(
731
			'id' => 'sort_email_fp',
732
			'title' => $txt['sort_filter'],
733
			'sortable' => true,
734
			'items_per_page' => 0,
735
			'no_items_label' => $txt['no_filters'],
736
			'base_href' => $scripturl . '?action=admin;area=maillist;sa=sortfilters',
737
			'get_items' => array(
738
				'function' => array($this, 'load_filter_parser'),
739
				'params' => array(
740
					$id,
741
					'filter'
742
				),
743
			),
744
			'get_count' => array(
745
				'function' => array($this, 'count_filter_parser'),
746
				'params' => array(
747
					$id,
748
					'filter'
749
				),
750
			),
751
			'columns' => array(
752
				'filterorder' => array(
753
					'header' => array(
754
						'value' => '',
755
						'class' => 'hide',
756
					),
757
					'data' => array(
758
						'db' => 'filter_order',
759
						'class' => 'hide',
760
					),
761
				),
762
				'name' => array(
763
					'header' => array(
764
						'value' => $txt['filter_name'],
765
						'style' => 'white-space: nowrap;width: 10em'
766
					),
767
					'data' => array(
768
						'db' => 'filter_name',
769
					),
770
				),
771
				'from' => array(
772
					'header' => array(
773
						'value' => $txt['filter_from'],
774
					),
775
					'data' => array(
776
						'db' => 'filter_from',
777
					),
778
				),
779
				'to' => array(
780
					'header' => array(
781
						'value' => $txt['filter_to'],
782
						'style' => 'width:10em;',
783
					),
784
					'data' => array(
785
						'db' => 'filter_to',
786
					),
787
				),
788
				'type' => array(
789
					'header' => array(
790
						'value' => $txt['filter_type'],
791
					),
792
					'data' => array(
793
						'db' => 'filter_type',
794
					),
795
				),
796
			),
797
			'form' => array(
798
				'href' => $scripturl . '?action=admin;area=maillist;sa=sortfilters',
799
				'hidden_fields' => array(
800
					$context['session_var'] => $context['session_id'],
801
				),
802
			),
803
			'additional_rows' => array(
804
				array(
805
					'position' => 'after_title',
806
					'value' => $txt['filter_sort_description'],
807
				),
808
			),
809
			'javascript' => '
810
				$().elkSortable({
811
					sa: "parserorder",
812
					placeholder: "ui-state-highlight",
813
					containment: "#sort_email_fp",
814
					error: "' . $txt['admin_order_error'] . '",
815
					title: "' . $txt['admin_order_title'] . '",
816
					href: "?action=admin;area=maillist;sa=sortfilters",
817
					token: {token_var: "' . $token['admin-sort_token_var'] . '", token_id: "' . $token['admin-sort_token'] . '"}
818
				});
819
			',
820
		);
821
822
		// Set the context values
823
		$context['page_title'] = $txt['filters'];
824
		$context['sub_template'] = 'show_list';
825
		$context['default_list'] = 'sort_email_fp';
826
		$context[$context['admin_menu_name']]['current_subsection'] = 'emailfilters';
827
828
		// Create the list.
829
		createList($listOptions);
830
	}
831
832
	/**
833
	 * Returns the number of filters or parsers in the system
834
	 *
835
	 * - Callback for createList()
836
	 *
837
	 * @param int $id 0 for all of a certain style
838
	 * @param string $style one of filter or parser
839
	 */
840
	public function count_filter_parser($id, $style)
841
	{
842
		return list_count_filter_parser($id, $style);
843
	}
844
845
	/**
846
	 * Returns the details for the filters or parsers in the system
847
	 *
848
	 * - Callback for createList()
849
	 *
850
	 * @param int $start The item to start with (for pagination purposes)
851
	 * @param int $items_per_page The number of items to show per page
852
	 * @param string $sort A string indicating how to sort the results
853
	 * @param int $id
854
	 * @param string $style
855
	 */
856
	public function load_filter_parser($start, $items_per_page, $sort, $id, $style)
857
	{
858
		return list_get_filter_parser($start, $items_per_page, $sort, $id, $style);
859
	}
860
861
	/**
862
	 * Edit or Add a filter
863
	 *
864
	 * - If regex will check for proper syntax before saving to the database
865
	 */
866
	public function action_edit_filters()
867
	{
868
		global $context, $scripturl, $txt, $modSettings;
869
870
		// Editing an existing filter?
871
		if (isset($this->_req->query->f_id))
872
		{
873
			// Needs to be an int!
874
			$id = (int) $this->_req->query->f_id;
875
			if (empty($id) || $id <= 0)
876
				Errors::instance()->fatal_lang_error('error_no_id_filter');
877
878
			// Load it up and set it as the current values
879
			$row = maillist_load_filter_parser($id, 'filter');
880
			$modSettings['id_filter'] = $row['id_filter'];
881
			$modSettings['filter_type'] = $row['filter_type'];
882
			$modSettings['filter_to'] = $row['filter_to'];
883
			$modSettings['filter_from'] = $row['filter_from'];
884
			$modSettings['filter_name'] = $row['filter_name'];
885
886
			// Some items for the form
887
			$context['page_title'] = $txt['edit_filter'];
888
			$context['editing'] = true;
889
			$context['settings_message'] = array();
890
		}
891
		else
892
		{
893
			// Setup place holders for adding a new one instead
894
			$modSettings['filter_type'] = '';
895
			$modSettings['filter_to'] = '';
896
			$modSettings['filter_from'] = '';
897
			$modSettings['filter_name'] = '';
898
899
			$context['page_title'] = $txt['add_filter'];
900
			$context['editing'] = false;
901
			$context['settings_message'] = array();
902
		}
903
904
		// Initialize the filer settings form
905
		$this->_initFiltersSettingsForm();
906
907
		// Initialize it with our settings
908
		$config_vars = $this->_filtersSettings->settings();
909
910
		// Saving the new or edited entry?
911
		if (isset($this->_req->query->save))
912
		{
913
			checkSession();
914
915
			call_integration_hook('integrate_save_filter_settings');
916
917
			// Editing an entry?
918
			$editid = (isset($this->_req->query->edit)) ? (int) $this->_req->query->edit : -1;
919
			$editname = (isset($this->_req->query->edit)) ? 'id_filter' : '';
920
921
			// If its regex we do a quick check to see if its valid or not
922
			if ($this->_req->post->filter_type === 'regex')
923
			{
924
				$valid = (@preg_replace($this->_req->post->filter_from, $this->_req->post->filter_to, 'ElkArte') === null) ? false : true;
925
				if (!$valid)
926
				{
927
					// Seems to be bad ... reload the form, set the message
928
					$context['error_type'] = 'notice';
929
					$context['settings_message'][] = $txt['regex_invalid'];
930
					$modSettings['filter_type'] = $this->_req->post->filter_type;
931
					$modSettings['filter_to'] = $this->_req->post->filter_to;
932
					$modSettings['filter_from'] = $this->_req->post->filter_from;
933
					$modSettings['filter_name'] = $this->_req->post->filter_name;
934
				}
935
			}
936
937
			if (empty($this->_req->post->filter_type) || empty($this->_req->post->filter_from))
938
			{
939
				$context['error_type'] = 'notice';
940
				$context['settings_message'][] = $txt['filter_invalid'];
941
			}
942
943
			// if we are good to save, so save it ;)
944
			if (empty($context['settings_message']))
945
			{
946
				// And ... its a filter
947
				$config_vars[] = array('text', 'filter_style');
948
				$this->_req->post->filter_style = 'filter';
949
950
				Email_Settings::saveTableSettings($config_vars, 'postby_emails_filters', $this->_req->post, array(), $editid, $editname);
951
				writeLog();
952
				redirectexit('action=admin;area=maillist;sa=emailfilters;saved');
953
			}
954
		}
955
956
		// Prepare some final context for the template
957
		$title = !empty($this->_req->query->saved) ? 'saved_filter' : ($context['editing'] == true ? 'edit_filter' : 'add_filter');
958
		$context['post_url'] = $scripturl . '?action=admin;area=maillist;sa=editfilter' . ($context['editing'] ? ';edit=' . $modSettings['id_filter'] : ';new') . ';save';
959
		$context['settings_title'] = $txt[$title];
960
		$context['linktree'][] = array(
961
			'url' => $scripturl . '?action=admin;area=maillist;sa=editfilter',
962
			'name' => ($context['editing']) ? $txt['edit_filter'] : $txt['add_filter'],
963
		);
964
		$context[$context['admin_menu_name']]['tab_data'] = array(
965
			'title' => $txt[$title],
966
			'description' => $txt['filters_title'],
967
		);
968
		$context[$context['admin_menu_name']]['current_subsection'] = 'emailfilters';
969
970
		// Load and show
971
		Email_Settings::prepare_db($config_vars);
972
		loadTemplate('Admin');
973
		loadCSSFile('admin.css');
974
		$context['sub_template'] = 'show_settings';
975
	}
976
977
	/**
978
	 * Initialize Mailist settings form.
979
	 */
980
	private function _initFiltersSettingsForm()
981
	{
982
		global $txt;
983
984
		// Instantiate the extended parser form
985
		$this->_filtersSettings = new Email_Settings();
986
987
		// Set up the config_vars for the form
988
		$config_vars = array(
989
			array('text', 'filter_name', 25, 'subtext' => $txt['filter_name_desc']),
990
			array('select', 'filter_type',
991
				array(
992
					'standard' => $txt['option_standard'],
993
					'regex' => $txt['option_regex'],
994
				),
995
			),
996
			array('large_text', 'filter_from', 4, 'subtext' => $txt['filter_from_desc']),
997
			array('text', 'filter_to', 25, 'subtext' => $txt['filter_to_desc']),
998
		);
999
1000
		call_integration_hook('integrate_modify_maillist_filter_settings', array(&$config_vars));
1001
1002
		return $this->_filtersSettings->settings($config_vars);
1003
	}
1004
1005
	/**
1006
	 * Deletes a filter from the system / database
1007
	 */
1008
	public function action_delete_filters()
1009
	{
1010
		// Removing the filter?
1011
		if (isset($this->_req->query->f_id))
1012
		{
1013
			checkSession('get');
1014
			$id = (int) $this->_req->query->f_id;
1015
1016
			maillist_delete_filter_parser($id);
1017
			redirectexit('action=admin;area=maillist;sa=emailfilters;deleted');
1018
		}
1019
	}
1020
1021
	/**
1022
	 * Show a list of all the parsers in the system
1023
	 *
1024
	 * - Allows to add/edit or delete parsers
1025
	 * - Parsers are used to split a message at a line of text
1026
	 * - Parsers can only be defined as regex, the system will check it for valid syntax
1027
	 * - Accessed by ?action=admin;area=maillist;sa=emailparser;
1028
	 */
1029
	public function action_list_parsers()
1030
	{
1031
		global $context, $scripturl, $txt, $settings, $modSettings;
1032
1033
		$id = 0;
1034
1035
		// Build the listoption array to display the data
1036
		$listOptions = array(
1037
			'id' => 'email_parser',
1038
			'title' => $txt['parsers'],
1039
			'items_per_page' => $modSettings['defaultMaxMessages'],
1040
			'no_items_label' => $txt['no_parsers'],
1041
			'base_href' => $scripturl . '?action=admin;area=maillist;sa=emailparser',
1042
			'get_items' => array(
1043
				'function' => array($this, 'load_filter_parser'),
1044
				'params' => array(
1045
					$id,
1046
					'parser'
1047
				),
1048
			),
1049
			'get_count' => array(
1050
				'function' => array($this, 'count_filter_parser'),
1051
				'params' => array(
1052
					$id,
1053
					'parser'
1054
				),
1055
			),
1056
			'columns' => array(
1057
				'name' => array(
1058
					'header' => array(
1059
						'value' => $txt['parser_name'],
1060
						'style' => 'white-space: nowrap;'
1061
					),
1062
					'data' => array(
1063
						'db' => 'filter_name',
1064
					),
1065
					'sort' => array(
1066
						'default' => 'filter_name',
1067
						'reverse' => 'filter_name DESC',
1068
					),
1069
				),
1070
				'from' => array(
1071
					'header' => array(
1072
						'value' => $txt['parser_from'],
1073
					),
1074
					'data' => array(
1075
						'db' => 'filter_from',
1076
					),
1077
					'sort' => array(
1078
						'default' => 'filter_from',
1079
						'reverse' => 'filter_from DESC',
1080
					),
1081
				),
1082
				'type' => array(
1083
					'header' => array(
1084
						'value' => $txt['parser_type'],
1085
					),
1086
					'data' => array(
1087
						'db' => 'filter_type',
1088
					),
1089
					'sort' => array(
1090
						'default' => 'filter_type',
1091
						'reverse' => 'filter_type DESC',
1092
					),
1093
				),
1094
				'action' => array(
1095
					'header' => array(
1096
						'value' => $txt['message_action'],
1097
						'class' => 'centertext',
1098
					),
1099
					'data' => array(
1100
						'sprintf' => array(
1101
							'format' => '<a href="?action=admin;area=maillist;sa=editparser;f_id=%1$s;' . $context['session_var'] . '=' . $context['session_id'] . '">
1102
										<img title="' . $txt['modify'] . '" src="' . $settings['images_url'] . '/buttons/modify.png" alt="*" />
1103
									</a>
1104
									<a href="?action=admin;area=maillist;sa=deleteparser;f_id=%1$s;' . $context['session_var'] . '=' . $context['session_id'] . '" onclick="return confirm(' . JavaScriptEscape($txt['parser_delete_warning']) . ') && submitThisOnce(this);" accesskey="d">
1105
										<img title="' . $txt['delete'] . '" src="' . $settings['images_url'] . '/buttons/delete.png" alt="*" />
1106
									</a>',
1107
							'params' => array(
1108
								'id_filter' => true,
1109
							),
1110
						),
1111
						'class' => 'centertext',
1112
						'style' => 'white-space:nowrap;',
1113
					),
1114
				),
1115
			),
1116
			'form' => array(
1117
				'href' => $scripturl . '?action=admin;area=maillist;sa=editparser',
1118
				'include_sort' => true,
1119
				'include_start' => true,
1120
				'hidden_fields' => array(
1121
					$context['session_var'] => $context['session_id'],
1122
				),
1123
			),
1124
			'additional_rows' => array(
1125
				array(
1126
					'position' => isset($this->_req->query->saved) ? 'top_of_list' : 'after_title',
1127
					'value' => isset($this->_req->query->saved) ? '<div class="successbox">' . $txt['saved'] . '</div>' : $txt['parsers_title'],
1128
				),
1129
				array(
1130
					'position' => 'below_table_data',
1131
					'class' => 'submitbutton',
1132
					'value' => '
1133
						<input type="submit" name="addparser" value="' . $txt['add_parser'] . '" class="right_submit" />
1134
						<a class="linkbutton" href="' . $scripturl . '?action=admin;area=maillist;sa=sortparsers">' . $txt['sort_parser'] . '</a>',
1135
					),
1136
			),
1137
		);
1138
1139
		// Set the context values
1140
		$context['page_title'] = $txt['parsers'];
1141
		$context['sub_template'] = 'show_list';
1142
		$context['default_list'] = 'email_parser';
1143
1144
		// Create the list.
1145
		createList($listOptions);
1146
	}
1147
1148
	/**
1149
	 * Show a full list of all the parsers in the system for drag/drop sorting
1150
	 */
1151
	public function action_sort_parsers()
1152
	{
1153
		global $context, $scripturl, $txt;
1154
1155
		$id = 0;
1156
		$token = createToken('admin-sort');
1157
1158
		// Build the listoption array to display the data
1159
		$listOptions = array(
1160
			'id' => 'sort_email_fp',
1161
			'title' => $txt['sort_parser'],
1162
			'sortable' => true,
1163
			'items_per_page' => 0,
1164
			'no_items_label' => $txt['no_parsers'],
1165
			'base_href' => $scripturl . '?action=admin;area=maillist;sa=sortparsers',
1166
			'default_sort_col' => 'filterorder',
1167
			'get_items' => array(
1168
				'function' => array($this, 'load_filter_parser'),
1169
				'params' => array(
1170
					$id,
1171
					'parser'
1172
				),
1173
			),
1174
			'get_count' => array(
1175
				'function' => array($this, 'count_filter_parser'),
1176
				'params' => array(
1177
					$id,
1178
					'parser'
1179
				),
1180
			),
1181
			'columns' => array(
1182
				'filterorder' => array(
1183
					'header' => array(
1184
						'value' => '',
1185
						'class' => 'hide',
1186
					),
1187
					'data' => array(
1188
						'db' => 'filter_order',
1189
						'class' => 'hide',
1190
					),
1191
				),
1192
				'name' => array(
1193
					'header' => array(
1194
						'value' => $txt['parser_name'],
1195
						'style' => 'white-space: nowrap;width: 10em'
1196
					),
1197
					'data' => array(
1198
						'db' => 'filter_name',
1199
					),
1200
				),
1201
				'from' => array(
1202
					'header' => array(
1203
						'value' => $txt['parser_from'],
1204
					),
1205
					'data' => array(
1206
						'db' => 'filter_from',
1207
					),
1208
				),
1209
				'type' => array(
1210
					'header' => array(
1211
						'value' => $txt['parser_type'],
1212
					),
1213
					'data' => array(
1214
						'db' => 'filter_type',
1215
					),
1216
				),
1217
			),
1218
			'form' => array(
1219
				'href' => $scripturl . '?action=admin;area=maillist;sa=sortparsers',
1220
				'hidden_fields' => array(
1221
					$context['session_var'] => $context['session_id'],
1222
				),
1223
			),
1224
			'additional_rows' => array(
1225
				array(
1226
					'position' => 'after_title',
1227
					'value' => $txt['parser_sort_description'],
1228
				),
1229
			),
1230
			'javascript' => '
1231
				$().elkSortable({
1232
					sa: "parserorder",
1233
					placeholder: "ui-state-highlight",
1234
					containment: "#sort_email_fp",
1235
					error: "' . $txt['admin_order_error'] . '",
1236
					title: "' . $txt['admin_order_title'] . '",
1237
					href: "?action=admin;;area=maillist;sa=sortparsers",
1238
					token: {token_var: "' . $token['admin-sort_token_var'] . '", token_id: "' . $token['admin-sort_token'] . '"}
1239
				});
1240
			',
1241
		);
1242
1243
		// Set the context values
1244
		$context['page_title'] = $txt['parsers'];
1245
		$context['sub_template'] = 'show_list';
1246
		$context['default_list'] = 'sort_email_fp';
1247
		$context[$context['admin_menu_name']]['current_subsection'] = 'emailparser';
1248
1249
		// Create the list.
1250
		createList($listOptions);
1251
	}
1252
1253
	/**
1254
	 * Adds or Edits an existing parser
1255
	 *
1256
	 * - All parsers are assumed regex
1257
	 */
1258
	public function action_edit_parsers()
1259
	{
1260
		global $context, $scripturl, $txt, $modSettings;
1261
1262
		// Editing an existing filter?
1263
		if (isset($this->_req->query->f_id))
1264
		{
1265
			// Needs to be an int!
1266
			$id = (int) $this->_req->query->f_id;
1267
			if (empty($id) || $id < 0)
1268
				Errors::instance()->fatal_lang_error('error_no_id_filter');
1269
1270
			// Load this filter so we can edit it
1271
			$row = maillist_load_filter_parser($id, 'parser');
1272
1273
			$modSettings['id_filter'] = $row['id_filter'];
1274
			$modSettings['filter_type'] = $row['filter_type'];
1275
			$modSettings['filter_from'] = $row['filter_from'];
1276
			$modSettings['filter_name'] = $row['filter_name'];
1277
1278
			$context['page_title'] = $txt['edit_parser'];
1279
			$context['editing'] = true;
1280
		}
1281
		else
1282
		{
1283
			// Setup place holders for adding a new one instead
1284
			$modSettings['filter_type'] = '';
1285
			$modSettings['filter_name'] = '';
1286
			$modSettings['filter_from'] = '';
1287
1288
			// To the template we go
1289
			$context['page_title'] = $txt['add_parser'];
1290
			$context['editing'] = false;
1291
		}
1292
1293
		// Initialize the mailparser settings form
1294
		$this->_initParsersSettingsForm();
1295
1296
		// Initialize it with our settings
1297
		$config_vars = $this->_parsersSettings->settings();
1298
1299
		// Check if they are saving the changes
1300
		if (isset($this->_req->query->save))
1301
		{
1302
			checkSession();
1303
1304
			call_integration_hook('integrate_save_parser_settings');
1305
1306
			// Editing a parser?
1307
			$editid = isset($this->_req->query->edit) ? (int) $this->_req->query->edit : -1;
1308
			$editname = isset($this->_req->query->edit) ? 'id_filter' : '';
1309
1310
			// Test the regex
1311
			if ($this->_req->post->filter_type === 'regex' && !empty($this->_req->post->filter_from))
1312
			{
1313
				$valid = (preg_replace($this->_req->post->filter_from, '', 'ElkArte') === null) ? false : true;
1314
				if (!$valid)
1315
				{
1316
					// Regex did not compute .. Danger, Will Robinson
1317
					$context['settings_message'] = $txt['regex_invalid'];
1318
					$context['error_type'] = 'notice';
1319
1320
					$modSettings['filter_type'] = $this->_req->post->filter_type;
1321
					$modSettings['filter_from'] = $this->_req->post->filter_from;
1322
					$modSettings['filter_name'] = $this->_req->post->filter_name;
1323
				}
1324
			}
1325
1326
			if (empty($this->_req->post->filter_type) || empty($this->_req->post->filter_from))
1327
			{
1328
				$context['error_type'] = 'notice';
1329
				$context['settings_message'][] = $txt['filter_invalid'];
1330
			}
1331
1332
			// All clear to save?
1333
			if (empty($context['settings_message']))
1334
			{
1335
				// Shhh ... its really a parser
1336
				$config_vars[] = array('text', 'filter_style');
1337
				$this->_req->post->filter_style = 'parser';
1338
1339
				// Save, log, show
1340
				Email_Settings::saveTableSettings($config_vars, 'postby_emails_filters', $this->_req->post, array(), $editid, $editname);
1341
				writeLog();
1342
				redirectexit('action=admin;area=maillist;sa=emailparser;saved');
1343
			}
1344
		}
1345
1346
		// Prepare the context for viewing
1347
		$title = ((isset($this->_req->query->saved) && $this->_req->query->saved == '1') ? 'saved_parser' : ($context['editing'] == true ? 'edit_parser' : 'add_parser'));
1348
		$context['settings_title'] = $txt[$title];
1349
		$context['post_url'] = $scripturl . '?action=admin;area=maillist;sa=editparser' . ($context['editing'] ? ';edit=' . $modSettings['id_filter'] : ';new') . ';save';
1350
		$context['linktree'][] = array(
1351
			'url' => $scripturl . '?action=admin;area=maillist;sa=editparser',
1352
			'name' => ($context['editing']) ? $txt['edit_parser'] : $txt['add_parser'],
1353
		);
1354
		$context[$context['admin_menu_name']]['tab_data'] = array(
1355
			'title' => $txt[$title],
1356
			'description' => $txt['parsers_title'],
1357
		);
1358
		$context[$context['admin_menu_name']]['current_subsection'] = 'emailparser';
1359
1360
		// prep it, load it, show it
1361
		Email_Settings::prepare_db($config_vars);
1362
		loadTemplate('Admin');
1363
		loadCSSFile('admin.css');
1364
		$context['sub_template'] = 'show_settings';
1365
	}
1366
1367
	/**
1368
	 * Initialize Mailist settings form.
1369
	 */
1370
	private function _initParsersSettingsForm()
1371
	{
1372
		global $txt;
1373
1374
		// Instantiate the extended parser form
1375
		$this->_parsersSettings = new Email_Settings();
1376
1377
		// Define the menu array
1378
		$config_vars = array(
1379
			array('text', 'filter_name', 25, 'subtext' => $txt['parser_name_desc']),
1380
			array('select', 'filter_type', 'subtext' => $txt['parser_type_desc'],
1381
				array(
1382
					'regex' => $txt['option_regex'],
1383
					'standard' => $txt['option_standard'],
1384
				),
1385
			),
1386
			array('large_text', 'filter_from', 4, 'subtext' => $txt['parser_from_desc']),
1387
		);
1388
1389
		call_integration_hook('integrate_modify_maillist_parser_settings', array(&$config_vars));
1390
1391
		return $this->_parsersSettings->settings($config_vars);
1392
	}
1393
1394
	/**
1395
	 * Removes a parser from the system and database
1396
	 */
1397
	public function action_delete_parsers()
1398
	{
1399
		// Removing the filter?
1400
		if (isset($this->_req->query->f_id))
1401
		{
1402
			checkSession('get');
1403
			$id = (int) $this->_req->query->f_id;
1404
1405
			maillist_delete_filter_parser($id);
1406
			redirectexit('action=admin;area=maillist;sa=emailparser;deleted');
1407
		}
1408
	}
1409
1410
	/**
1411
	 * All the post by email settings, used to control how the feature works
1412
	 *
1413
	 * @uses Admin language
1414
	 */
1415
	public function action_settings()
1416
	{
1417
		global $scripturl, $context, $txt, $modSettings;
1418
1419
		// Be nice, show them we did something
1420
		if (isset($this->_req->query->saved))
1421
			$context['settings_message'] = $txt['saved'];
1422
1423
		// Templates and language
1424
		loadLanguage('Admin');
1425
		loadTemplate('Admin');
1426
		loadCSSFile('admin.css');
1427
1428
		// Load any existing email => board values used for new topic creation
1429
		$context['maillist_from_to_board'] = array();
1430
		$data = (!empty($modSettings['maillist_receiving_address'])) ? unserialize($modSettings['maillist_receiving_address']) : array();
1431
		foreach ($data as $key => $addr)
1432
		{
1433
			$context['maillist_from_to_board'][$key] = array(
1434
				'id' => $key,
1435
				'emailfrom' => $addr[0],
1436
				'boardto' => $addr[1],
1437
			);
1438
		}
1439
1440
		// Initialize the maillist settings form
1441
		$this->_initMaillistSettingsForm();
1442
1443
		// Retrieve the config settings
1444
		$config_vars = $this->_maillistSettings->settings();
1445
1446
		// Saving settings?
1447
		if (isset($this->_req->query->save))
1448
		{
1449
			checkSession();
1450
1451
			call_integration_hook('integrate_save_maillist_settings');
1452
1453
			$email_error = false;
1454
			$board_error = false;
1455
			$maillist_receiving_address = array();
1456
1457
			// Basic checking of the email addresses
1458
			if (!Data_Validator::is_valid($this->_req->post, array('maillist_sitename_address' => 'valid_email'), array('maillist_sitename_address' => 'trim')))
1459
				$email_error = $this->_req->post->maillist_sitename_address;
1460
			if (!Data_Validator::is_valid($this->_req->post, array('maillist_sitename_help' => 'valid_email'), array('maillist_sitename_help' => 'trim')))
1461
				$email_error = $this->_req->post->maillist_sitename_help;
1462
			if (!Data_Validator::is_valid($this->_req->post, array('maillist_mail_from' => 'valid_email'), array('maillist_mail_from' => 'trim')))
1463
				$email_error = $this->_req->post->maillist_mail_from;
1464
1465
			// Inbound email set up then we need to check for both valid email and valid board
1466
			if (!$email_error && !empty($this->_req->post->emailfrom))
1467
			{
1468
				// Get the board ids for a quick check
1469
				$boards = maillist_board_list();
1470
1471
				// Check the receiving emails and the board id as well
1472
				$boardtocheck = !empty($this->_req->post->boardto) ? $this->_req->post->boardto : array();
1473
				$addresstocheck = !empty($this->_req->post->emailfrom) ? $this->_req->post->emailfrom : array();
1474
1475
				foreach ($addresstocheck as $key => $checkme)
1476
				{
1477
					// Valid email syntax
1478
					if (!Data_Validator::is_valid($addresstocheck, array($key => 'valid_email'), array($key => 'trim')))
1479
					{
1480
						$email_error = $checkme;
1481
						$context['error_type'] = 'notice';
1482
						continue;
1483
					}
1484
1485
					// Valid board id?
1486
					if (!isset($boardtocheck[$key]) || !isset($boards[$key]))
1487
					{
1488
						$board_error = $checkme;
1489
						$context['error_type'] = 'notice';
1490
						continue;
1491
					}
1492
1493
					// Decipher as [0] emailaddress and [1] board id
0 ignored issues
show
Unused Code Comprehensibility introduced by
40% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1494
					$maillist_receiving_address[] = array($checkme, $boardtocheck[$key]);
1495
				}
1496
			}
1497
1498
			// Enable or disable the fake cron
1499
			enable_maillist_imap_cron(!empty($this->_req->post->maillist_imap_cron));
1500
1501
			// Check and set any errors or give the go ahead to save
1502
			if ($email_error)
1503
				$context['settings_message'] = sprintf($txt['email_not_valid'], $email_error);
1504
			elseif ($board_error)
1505
				$context['settings_message'] = sprintf($txt['board_not_valid'], $board_error);
1506
			else
1507
			{
1508
				// Clear the moderation count cache
1509
				Cache::instance()->put('num_menu_errors', null, 900);
1510
1511
				// Should be off if mail posting is on, we ignore it anyway but this at least updates the ACP
1512
				if (!empty($this->_req->post->maillist_enabled))
1513
					updateSettings(array('disallow_sendBody' => ''));
1514
1515
				updateSettings(array('maillist_receiving_address' => serialize($maillist_receiving_address)));
1516
				Settings_Form::save_db($config_vars, $this->_req->post);
1517
				writeLog();
1518
				redirectexit('action=admin;area=maillist;sa=emailsettings;saved');
1519
			}
1520
		}
1521
1522
		// Javascript vars for the "add more" buttons in the receive_email callback
1523
		$board_list = maillist_board_list();
1524
		$script = '';
1525
		$i = 0;
1526
1527
		// Create the board selection list
1528
		foreach ($board_list as $board_id => $board_name)
1529
			$script .= $i++ . ': {id:' . $board_id . ', name:' . JavaScriptEscape($board_name) . '},';
1530
1531
		addInlineJavascript('
1532
		var sEmailParent = \'add_more_email_placeholder\',
1533
			oEmailOptionsdt = {size: \'50\', name: \'emailfrom[]\', class: \'input_text\'},
1534
			oEmailOptionsdd = {size: \'1\', type: \'select\', name: \'boardto[]\', class: \'input_select\'},
1535
			oEmailSelectData = {' . $script . '};
1536
1537
			document.getElementById(\'add_more_board_div\').style.display = \'block\';', true
1538
		);
1539
1540
		$context['boards'] = $board_list;
1541
		$context['settings_title'] = $txt['ml_emailsettings'];
1542
		$context['page_title'] = $txt['ml_emailsettings'];
1543
		$context['post_url'] = $scripturl . '?action=admin;area=maillist;sa=emailsettings;save';
1544
		$context['sub_template'] = 'show_settings';
1545
		Settings_Form::prepare_db($config_vars);
1546
	}
1547
1548
	/**
1549
	 * Initialize Maillist settings form.
1550
	 */
1551
	private function _initMaillistSettingsForm()
1552
	{
1553
		// Instantiate the form
1554
		$this->_maillistSettings = new Settings_Form();
1555
1556
		// Initialize it with our settings
1557
		$config_vars = $this->_settings();
1558
1559
		return $this->_maillistSettings->settings($config_vars);
1560
	}
1561
1562
	/**
1563
	 * Load up the config var array for settings display etc.
1564
	 */
1565
	private function _settings()
1566
	{
1567
		global $txt;
1568
1569
		// Define the menu
1570
		$config_vars = array(
1571
				array('desc', 'maillist_help'),
1572
				array('check', 'maillist_enabled'),
1573
				array('check', 'pbe_post_enabled'),
1574
				array('check', 'pbe_pm_enabled'),
1575
				array('check', 'pbe_no_mod_notices', 'subtext' => $txt['pbe_no_mod_notices_desc'], 'postinput' => $txt['recommended']),
1576
				array('check', 'pbe_bounce_detect', 'subtext' => $txt['pbe_bounce_detect_desc'], 'postinput' => $txt['experimental']),
1577
				array('check', 'pbe_bounce_record', 'subtext' => $txt['pbe_bounce_record_desc'], 'postinput' => $txt['experimental']),
1578
			array('title', 'maillist_outbound'),
1579
				array('desc', 'maillist_outbound_desc'),
1580
				array('check', 'maillist_group_mode'),
1581
				array('check', 'maillist_digest_enabled'),
1582
				array('text', 'maillist_sitename', 40, 'subtext' => $txt['maillist_sitename_desc'], 'postinput' => $txt['maillist_sitename_post']),
1583
				array('text', 'maillist_sitename_address', 40, 'subtext' => $txt['maillist_sitename_address_desc'], 'postinput' => $txt['maillist_sitename_address_post']),
1584
				array('text', 'maillist_mail_from', 40, 'subtext' => $txt['maillist_mail_from_desc'], 'postinput' => $txt['maillist_mail_from_post']),
1585
				array('text', 'maillist_sitename_help', 40, 'subtext' => $txt['maillist_sitename_help_desc'], 'postinput' => $txt['maillist_sitename_help_post']),
1586
				array('text', 'maillist_sitename_regards', 40, 'subtext' => $txt['maillist_sitename_regards_desc']),
1587
			array('title', 'maillist_inbound'),
1588
				array('desc', 'maillist_inbound_desc'),
1589
				array('check', 'maillist_newtopic_change'),
1590
				array('check', 'maillist_newtopic_needsapproval', 'subtext' => $txt['maillist_newtopic_needsapproval_desc'], 'postinput' => $txt['recommended']),
1591
				array('callback', 'maillist_receive_email_list'),
1592
			array('title', 'misc'),
1593
				array('check', 'maillist_allow_attachments'),
1594
				array('int', 'maillist_key_active', 2, 'subtext' => $txt['maillist_key_active_desc']),
1595
			'',
1596
				array('text', 'maillist_leftover_remove', 40, 'subtext' => $txt['maillist_leftover_remove_desc']),
1597
				array('text', 'maillist_sig_keys', 40, 'subtext' => $txt['maillist_sig_keys_desc']),
1598
				array('int', 'maillist_short_line', 2, 'subtext' => $txt['maillist_short_line_desc']),
1599
		);
1600
1601
		// Imap?
1602
		if (!function_exists('imap_open'))
1603
			$config_vars = array_merge($config_vars,
1604
				array(
1605
					array('title', 'maillist_imap_missing'),
1606
				)
1607
			);
1608
		else
1609
			$config_vars = array_merge($config_vars,
1610
				array(
1611
					array('title', 'maillist_imap'),
1612
					array('title', 'maillist_imap_reason'),
1613
						array('text', 'maillist_imap_host', 45, 'subtext' => $txt['maillist_imap_host_desc'], 'disabled' => !function_exists('imap_open')),
1614
						array('text', 'maillist_imap_mailbox', 20, 'postinput' => $txt['maillist_imap_mailbox_desc'], 'disabled' => !function_exists('imap_open')),
1615
						array('text', 'maillist_imap_uid', 20, 'postinput' => $txt['maillist_imap_uid_desc'], 'disabled' => !function_exists('imap_open')),
1616
						array('password', 'maillist_imap_pass', 20, 'postinput' => $txt['maillist_imap_pass_desc'], 'disabled' => !function_exists('imap_open')),
1617
						array('select', 'maillist_imap_connection',
1618
							array(
1619
								'imap' => $txt['maillist_imap_unsecure'],
1620
								'pop3' => $txt['maillist_pop3_unsecure'],
1621
								'imaptls' => $txt['maillist_imap_tls'],
1622
								'imapssl' => $txt['maillist_imap_ssl'],
1623
								'pop3tls' => $txt['maillist_pop3_tls'],
1624
								'pop3ssl' => $txt['maillist_pop3_ssl']
1625
							), 'postinput' => $txt['maillist_imap_connection_desc'], 'disabled' => !function_exists('imap_open'),
1626
						),
1627
						array('check', 'maillist_imap_delete', 20, 'subtext' => $txt['maillist_imap_delete_desc'], 'disabled' => !function_exists('imap_open')),
1628
						array('check', 'maillist_imap_cron', 20, 'subtext' => $txt['maillist_imap_cron_desc'], 'disabled' => !function_exists('imap_open')),
1629
				)
1630
			);
1631
1632
		call_integration_hook('integrate_modify_maillist_settings', array(&$config_vars));
1633
1634
		return $config_vars;
1635
	}
1636
1637
	/**
1638
	 * Return the form settings for use in admin search
1639
	 */
1640
	public function settings_search()
1641
	{
1642
		return $this->_settings();
1643
	}
1644
1645
	/**
1646
	 * View all the custom email bounce templates.
1647
	 *
1648
	 * - Shows all the bounce templates in the system available to this user
1649
	 * - Provides for actions to add or delete them
1650
	 * - Accessed by ?action=admin;area=maillist;sa=emailtemplates;
1651
	 */
1652
	public function action_view_bounce_templates()
1653
	{
1654
		global $modSettings, $context, $txt, $scripturl;
1655
1656
		// We'll need this, because bounce templates are stored with warning templates.
1657
		require_once(SUBSDIR . '/Moderation.subs.php');
1658
1659
		// Submitting a new one or editing an existing one then pass this request off
1660
		if (isset($this->_req->post->add) || isset($this->_req->post->save) || isset($this->_req->query->tid))
1661
			return $this->action_modify_bounce_templates();
1662
		// Deleting and existing one
1663
		elseif (isset($this->_req->post->delete) && !empty($this->_req->post->deltpl))
1664
		{
1665
			checkSession('post');
1666
			validateToken('mod-mlt');
1667
			removeWarningTemplate($this->_req->post->deltpl, 'bnctpl');
1668
		}
1669
1670
		// This is all the information required for showing the email templates.
1671
		$listOptions = array(
1672
			'id' => 'bounce_template_list',
1673
			'title' => $txt['ml_bounce_templates_title'],
1674
			'items_per_page' => $modSettings['defaultMaxMessages'],
1675
			'no_items_label' => $txt['ml_bounce_templates_none'],
1676
			'base_href' => $scripturl . '?action=admin;area=maillist;sa=emailtemplates;' . $context['session_var'] . '=' . $context['session_id'],
1677
			'default_sort_col' => 'title',
1678
			'get_items' => array(
1679
				'function' => array($this, 'list_getBounceTemplates'),
1680
			),
1681
			'get_count' => array(
1682
				'function' => array($this, 'list_getBounceTemplateCount'),
1683
				'params' => array('bnctpl'),
1684
			),
1685
			'columns' => array(
1686
				'title' => array(
1687
					'header' => array(
1688
						'value' => $txt['ml_bounce_templates_name'],
1689
					),
1690
					'data' => array(
1691
						'sprintf' => array(
1692
							'format' => '<a href="' . $scripturl . '?action=admin;area=maillist;sa=emailtemplates;tid=%1$d">%2$s</a>',
1693
							'params' => array(
1694
								'id_comment' => false,
1695
								'title' => false,
1696
								'body' => false,
1697
							),
1698
						),
1699
					),
1700
					'sort' => array(
1701
						'default' => 'template_title',
1702
						'reverse' => 'template_title DESC',
1703
					),
1704
				),
1705
				'creator' => array(
1706
					'header' => array(
1707
						'value' => $txt['ml_bounce_templates_creator'],
1708
					),
1709
					'data' => array(
1710
						'db' => 'creator',
1711
					),
1712
					'sort' => array(
1713
						'default' => 'creator_name',
1714
						'reverse' => 'creator_name DESC',
1715
					),
1716
				),
1717
				'time' => array(
1718
					'header' => array(
1719
						'value' => $txt['ml_bounce_templates_time'],
1720
					),
1721
					'data' => array(
1722
						'db' => 'time',
1723
					),
1724
					'sort' => array(
1725
						'default' => 'lc.log_time DESC',
1726
						'reverse' => 'lc.log_time',
1727
					),
1728
				),
1729
				'delete' => array(
1730
					'header' => array(
1731
						'value' => '<input type="checkbox" class="input_check" onclick="invertAll(this, this.form);" />',
1732
						'style' => 'width: 4%;',
1733
						'class' => 'centertext',
1734
					),
1735
					'data' => array(
1736
						'function' => function ($rowData) {
1737
							return '<input type="checkbox" name="deltpl[]" value="' . $rowData['id_comment'] . '" class="input_check" />';
1738
						},
1739
						'class' => 'centertext',
1740
					),
1741
				),
1742
			),
1743
			'form' => array(
1744
				'href' => $scripturl . '?action=admin;area=maillist;sa=emailtemplates',
1745
				'token' => 'mod-mlt',
1746
			),
1747
			'additional_rows' => array(
1748
				array(
1749
					'class' => 'submitbutton',
1750
					'position' => 'below_table_data',
1751
					'value' => '
1752
					<input type="submit" name="delete" value="' . $txt['ml_bounce_template_delete'] . '" onclick="return confirm(\'' . $txt['ml_bounce_template_delete_confirm'] . '\');" class="right_submit" />
1753
					<input type="submit" name="add" value="' . $txt['ml_bounce_template_add'] . '" class="right_submit" />',
1754
				),
1755
			),
1756
		);
1757
1758
		// Create the template list.
1759
		$context['page_title'] = $txt['ml_bounce_templates_title'];
1760
		createToken('mod-mlt');
1761
1762
		createList($listOptions);
1763
1764
		// Show the list
1765
		$context['sub_template'] = 'show_list';
1766
		$context['default_list'] = 'bounce_template_list';
1767
	}
1768
1769
	/**
1770
	 * Edit a 'it bounced' template.
1771
	 *
1772
	 * @uses bounce_template sub template
1773
	 */
1774
	public function action_modify_bounce_templates()
1775
	{
1776
		global $context, $txt, $user_info;
1777
1778
		require_once(SUBSDIR . '/Moderation.subs.php');
1779
1780
		$context['id_template'] = isset($this->_req->query->tid) ? (int) $this->_req->query->tid : 0;
1781
		$context['is_edit'] = (bool) $context['id_template'];
1782
1783
		// Standard template things, you know the drill
1784
		$context['page_title'] = $context['is_edit'] ? $txt['ml_bounce_template_modify'] : $txt['ml_bounce_template_add'];
1785
		$context['sub_template'] = 'bounce_template';
1786
		$context[$context['admin_menu_name']]['current_subsection'] = 'templates';
1787
1788
		// Defaults to show
1789
		$context['template_data'] = array(
1790
			'title' => '',
1791
			'body' => $txt['ml_bounce_template_body_default'],
1792
			'subject' => $txt['ml_bounce_template_subject_default'],
1793
			'personal' => false,
1794
			'can_edit_personal' => true,
1795
		);
1796
1797
		// If it's an edit load it.
1798
		if ($context['is_edit'])
1799
			modLoadTemplate($context['id_template'], 'bnctpl');
1800
1801
		// Wait, we are saving?
1802
		if (isset($this->_req->post->save))
1803
		{
1804
			checkSession('post');
1805
			validateToken('mod-mlt');
1806
1807
			// To check the BBC is good...
1808
			require_once(SUBSDIR . '/Post.subs.php');
1809
1810
			// Bit of cleaning!
1811
			$template_body = trim($this->_req->post->template_body);
1812
			$template_title = trim($this->_req->post->template_title);
1813
1814
			// Need something in both boxes.
1815
			if (!empty($template_body) && !empty($template_title))
1816
			{
1817
				// Safety first.
1818
				$template_title = Util::htmlspecialchars($template_title);
1819
1820
				// Clean up BBC.
1821
				preparsecode($template_body);
1822
1823
				// But put line breaks back!
1824
				$template_body = strtr($template_body, array('<br />' => "\n"));
1825
1826
				// Is this personal?
1827
				$recipient_id = !empty($this->_req->post->make_personal) ? $user_info['id'] : 0;
1828
1829
				// Updating or adding ?
1830
				if ($context['is_edit'])
1831
				{
1832
					// Simple update...
1833
					modAddUpdateTemplate($recipient_id, $template_title, $template_body, $context['id_template'], true, 'bnctpl');
1834
1835
					// If it wasn't visible and now is they've effectively added it.
1836
					if ($context['template_data']['personal'] && !$recipient_id)
1837
						logAction('add_bounce_template', array('template' => $template_title));
1838
					// Conversely if they made it personal it's a delete.
1839
					elseif (!$context['template_data']['personal'] && $recipient_id)
1840
						logAction('delete_bounce_template', array('template' => $template_title));
1841
					// Otherwise just an edit.
1842
					else
1843
						logAction('modify_bounce_template', array('template' => $template_title));
1844
				}
1845
				else
1846
				{
1847
					modAddUpdateTemplate($recipient_id, $template_title, $template_body, $context['id_template'], false, 'bnctpl');
1848
					logAction('add_bounce_template', array('template' => $template_title));
1849
				}
1850
1851
				// Get out of town...
1852
				redirectexit('action=admin;area=maillist;sa=emailtemplates');
1853
			}
1854
			else
1855
			{
1856
				$context['warning_errors'] = array();
1857
				$context['template_data']['title'] = !empty($template_title) ? $template_title : '';
1858
				$context['template_data']['body'] = !empty($template_body) ? $template_body : $txt['ml_bounce_template_body_default'];
1859
				$context['template_data']['personal'] = !empty($this->_req->post->make_personal);
1860
1861
				if (empty($template_title))
1862
					$context['warning_errors'][] = $txt['ml_bounce_template_error_no_title'];
1863
1864
				if (empty($template_body))
1865
					$context['warning_errors'][] = $txt['ml_bounce_template_error_no_body'];
1866
			}
1867
		}
1868
1869
		createToken('mod-mlt');
1870
	}
1871
1872
	/**
1873
	 * Get all the bounce templates from the system
1874
	 *
1875
	 * - Callback for createList()
1876
	 *
1877
	 * @param int $start The item to start with (for pagination purposes)
1878
	 * @param int $items_per_page  The number of items to show per page
1879
	 * @param string $sort A string indicating how to sort the results
1880
	 */
1881
	public function list_getBounceTemplates($start, $items_per_page, $sort)
1882
	{
1883
		return warningTemplates($start, $items_per_page, $sort, 'bnctpl');
1884
	}
1885
1886
	/**
1887
	 * Get the number of bounce templates in the system
1888
	 *
1889
	 * - Callback for createList() to warningTemplateCount
1890
	 */
1891
	public function list_getBounceTemplateCount()
1892
	{
1893
		return warningTemplateCount('bnctpl');
1894
	}
1895
1896
	/**
1897
	 * Get the number of unapproved emails
1898
	 *
1899
	 * - Callback for createList() to list_maillist_unapproved
1900
	 *
1901
	 * @param int $start The item to start with (for pagination purposes)
1902
	 * @param int $items_per_page The number of items to show per page
1903
	 * @param string $sort A string indicating how to sort the results
1904
	 * @param int $id = 0
1905
	 */
1906
	public function list_maillist_unapproved($start, $items_per_page, $sort = '', $id = 0)
1907
	{
1908
		return list_maillist_unapproved($id, $start, $items_per_page, $sort);
1909
	}
1910
}