Completed
Branch development (176841)
by Elk
06:59
created

PersonalMessage.template.php ➔ template_folder()   F

Complexity

Conditions 48
Paths > 20000

Size

Total Lines 245

Duplication

Lines 49
Ratio 20 %

Importance

Changes 0
Metric Value
cc 48
nc 55297
nop 0
dl 49
loc 245
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * @package   ElkArte Forum
5
 * @copyright ElkArte Forum contributors
6
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
7
 *
8
 * This file contains code covered by:
9
 * copyright: 2011 Simple Machines (http://www.simplemachines.org)
10
 *
11
 * @version 2.0 dev
12
 *
13
 */
14
15
/**
16
 * Loads the template of the poster area
17
 */
18
function template_PersonalMessage_init()
19
{
20
	theme()->getTemplates()->load('GenericMessages');
21
}
22
23
/**
24
 * This is the main sidebar for the personal messages section.
25
 * @todo - Started markup clean up in this template. More stuffz to check later.
26
 */
27
function template_pm_above()
28
{
29
	global $context, $txt;
30
31
	// The every helpful javascript!
32
	echo '
33
					<script>
34
						var allLabels = {},
35
							currentLabels = {},
36
							txt_pm_msg_label_remove = "', $txt['pm_msg_label_remove'], '",
37
							txt_pm_msg_label_apply = "', $txt['pm_msg_label_apply'], '";
38
					</script>
39
					<div id="personal_messages">';
40
41
	// Show the capacity bar, if available. @todo - This needs work.
42
	if (!empty($context['limit_bar']))
43
		echo '
44
						<h2 class="category_header">
45
							<span class="floatleft">', $txt['pm_capacity'], ':</span>
46
							<span class="floatleft capacity_bar">
47
								<span class="', $context['limit_bar']['percent'] > 85 ? 'full' : ($context['limit_bar']['percent'] > 40 ? 'filled' : 'empty'), '" style="width: ', $context['limit_bar']['percent'] / 10, 'em;"></span>
48
							</span>
49
							<span class="floatright', $context['limit_bar']['percent'] > 90 ? ' alert' : '', '">', $context['limit_bar']['text'], '</span>
50
						</h2>';
51
52
	// Message sent? Show a small indication.
53
	if (isset($context['pm_sent']))
54
		echo '
55
						<div class="successbox">
56
							', $txt['pm_sent'], '
57
						</div>';
58
59
	if (!empty($context['pm_form_url']))
60
		echo '
61
						<form action="', $context['pm_form_url'], '" method="post" accept-charset="UTF-8" name="pmFolder">';
62
}
63
64
/**
65
 * The end of the index bar, for personal messages page.
66
 */
67
function template_pm_below()
68
{
69
	global $context;
70
71
	echo '
72
							<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />', !empty($context['pm_form_url']) ? '
73
						</form>' : '', '
74
					</div>';
75
}
76
77
/**
78
 * Messages folder, used to viewing a listing of messages
79
 */
80
function template_folder()
81
{
82
	global $context, $scripturl, $options, $txt;
83
84
	$start = true;
85
	$reset = true;
86
87
	echo '
88
					<div id="forumposts">';
89
90
	// Do we have some messages to display?
91
	$controller = $context['get_pmessage'][0];
92
	while ($message = $controller->{$context['get_pmessage'][1]}($reset))
93
	{
94
		$reset = false;
95
96
		// Show the helpful titlebar - generally.
97
		if ($start && $context['display_mode'] != 1)
98
		{
99
			echo '
100
						<h2 class="category_header">
101
							', $context['display_mode'] == 0 ? $txt['messages'] : $txt['conversation'] . ': ' . $message['subject'], '
102
						</h2>';
103
			$start = false;
104
		}
105
106
		echo '
107
						<a class="pm_anchor" id="msg_', $message['id'], '"></a>
108
						<div class="forumposts">';
109
110
		// Showing the sidebar posting area?
111
		if (empty($options['hide_poster_area']))
112
			echo '
113
							<ul class="poster">', template_build_poster_div($message), '</ul>';
0 ignored issues
show
Security Cross-Site Scripting introduced by
template_build_poster_div($message) can contain request data and is used in output context(s) leading to a potential security vulnerability.

8 paths for user data to reach this point

  1. Path: Read from $_REQUEST, and $context is assigned in sources/ElkArte/Controller/Post.php on line 320
  1. Read from $_REQUEST, and $context is assigned
    in sources/ElkArte/Controller/Post.php on line 320
  2. $context is assigned
    in sources/ElkArte/Controller/Post.php on line 351
  3. $context is assigned
    in sources/ElkArte/Controller/Post.php on line 352
  4. $context is assigned
    in sources/ElkArte/Controller/Post.php on line 353
  5. $context is assigned
    in sources/ElkArte/Controller/Post.php on line 366
  6. $context is assigned
    in sources/ElkArte/Controller/Post.php on line 367
  7. $context['name'] is passed to ValuesContainer::__set()
    in sources/ElkArte/Controller/Post.php on line -1
  8. ValuesContainer::$data is assigned
    in sources/ElkArte/ValuesContainer.php on line 53
  9. Tainted property ValuesContainer::$data is read
    in sources/ElkArte/ValuesContainer.php on line 65
  10. ValuesContainer::__get() returns tainted data, and $str is assigned
    in sources/Subs.php on line 456
  11. $str is passed through strftime()
    in sources/Subs.php on line 492
  12. standardTime() returns tainted data
    in themes/default/GenericMessages.template.php on line 64
  13. $poster_div is assigned
    in themes/default/GenericMessages.template.php on line 63
  14. template_build_poster_div() returns tainted data
    in themes/default/PersonalMessage.template.php on line 113
  2. Path: Read from $_POST in sources/ElkArte/Controller/Post.php on line 946
  1. Read from $_POST
    in sources/ElkArte/Controller/Post.php on line 946
  2. $_POST['guestname'] is passed to ValuesContainer::__set()
    in sources/ElkArte/Controller/Post.php on line -1
  3. ValuesContainer::$data is assigned
    in sources/ElkArte/ValuesContainer.php on line 53
  4. Tainted property ValuesContainer::$data is read
    in sources/ElkArte/ValuesContainer.php on line 65
  5. ValuesContainer::__get() returns tainted data, and $str is assigned
    in sources/Subs.php on line 456
  6. $str is passed through strftime()
    in sources/Subs.php on line 492
  7. standardTime() returns tainted data
    in themes/default/GenericMessages.template.php on line 64
  8. $poster_div is assigned
    in themes/default/GenericMessages.template.php on line 63
  9. template_build_poster_div() returns tainted data
    in themes/default/PersonalMessage.template.php on line 113
  3. Path: Read from $_REQUEST, and $_REQUEST['params'] ?? '' is passed to SearchParams::__construct() in sources/ElkArte/Controller/Search.php on line 151
  1. Read from $_REQUEST, and $_REQUEST['params'] ?? '' is passed to SearchParams::__construct()
    in sources/ElkArte/Controller/Search.php on line 151
  2. SearchParams::$_search_string is assigned
    in sources/ElkArte/Search/SearchParams.php on line 100
  3. Tainted property SearchParams::$_search_string is read, and $this->_search_string is passed through str_replace(), and str_replace(array('-', '_', '.'), array('+', '/', '='), $this->_search_string) is decoded by base64_decode(), and $temp_params is assigned
    in sources/ElkArte/Search/SearchParams.php on line 160
  4. !empty($temp_params2) ? $temp_params2 : $temp_params is passed through explode(), and $temp_params is assigned
    in sources/ElkArte/Search/SearchParams.php on line 164
  5. $data is assigned
    in sources/ElkArte/Search/SearchParams.php on line 166
  6. $data is passed through explode(), and explode('|\'|', $data) is passed through array_pad(), and $v is assigned
    in sources/ElkArte/Search/SearchParams.php on line 168
  7. SearchParams::$_search_params is assigned
    in sources/ElkArte/Search/SearchParams.php on line 169
  8. Tainted property SearchParams::$_search_params is read, and ValuesContainer::$data is assigned
    in sources/ElkArte/Search/SearchParams.php on line 102
  9. Tainted property ValuesContainer::$data is read
    in sources/ElkArte/ValuesContainer.php on line 65
  10. ValuesContainer::__get() returns tainted data, and $str is assigned
    in sources/Subs.php on line 456
  11. $str is passed through strftime()
    in sources/Subs.php on line 492
  12. standardTime() returns tainted data
    in themes/default/GenericMessages.template.php on line 64
  13. $poster_div is assigned
    in themes/default/GenericMessages.template.php on line 63
  14. template_build_poster_div() returns tainted data
    in themes/default/PersonalMessage.template.php on line 113
  4. Path: Read from $_REQUEST, and $_REQUEST['params'] ?? '' is passed to SearchParams::__construct() in sources/ElkArte/Controller/Search.php on line 280
  1. Read from $_REQUEST, and $_REQUEST['params'] ?? '' is passed to SearchParams::__construct()
    in sources/ElkArte/Controller/Search.php on line 280
  2. SearchParams::$_search_string is assigned
    in sources/ElkArte/Search/SearchParams.php on line 100
  3. Tainted property SearchParams::$_search_string is read, and $this->_search_string is passed through str_replace(), and str_replace(array('-', '_', '.'), array('+', '/', '='), $this->_search_string) is decoded by base64_decode(), and $temp_params is assigned
    in sources/ElkArte/Search/SearchParams.php on line 160
  4. !empty($temp_params2) ? $temp_params2 : $temp_params is passed through explode(), and $temp_params is assigned
    in sources/ElkArte/Search/SearchParams.php on line 164
  5. $data is assigned
    in sources/ElkArte/Search/SearchParams.php on line 166
  6. $data is passed through explode(), and explode('|\'|', $data) is passed through array_pad(), and $v is assigned
    in sources/ElkArte/Search/SearchParams.php on line 168
  7. SearchParams::$_search_params is assigned
    in sources/ElkArte/Search/SearchParams.php on line 169
  8. Tainted property SearchParams::$_search_params is read, and ValuesContainer::$data is assigned
    in sources/ElkArte/Search/SearchParams.php on line 102
  9. Tainted property ValuesContainer::$data is read
    in sources/ElkArte/ValuesContainer.php on line 65
  10. ValuesContainer::__get() returns tainted data, and $str is assigned
    in sources/Subs.php on line 456
  11. $str is passed through strftime()
    in sources/Subs.php on line 492
  12. standardTime() returns tainted data
    in themes/default/GenericMessages.template.php on line 64
  13. $poster_div is assigned
    in themes/default/GenericMessages.template.php on line 63
  14. template_build_poster_div() returns tainted data
    in themes/default/PersonalMessage.template.php on line 113
  5. Path: Read from $_REQUEST, and $_REQUEST is passed to SearchParams::merge() in sources/ElkArte/Controller/Search.php on line 281
  1. Read from $_REQUEST, and $_REQUEST is passed to SearchParams::merge()
    in sources/ElkArte/Controller/Search.php on line 281
  2. SearchParams::$_search_params is assigned
    in sources/ElkArte/Search/SearchParams.php on line 256
  3. Tainted property SearchParams::$_search_params is read, and ValuesContainer::$data is assigned
    in sources/ElkArte/Search/SearchParams.php on line 102
  4. Tainted property ValuesContainer::$data is read
    in sources/ElkArte/ValuesContainer.php on line 65
  5. ValuesContainer::__get() returns tainted data, and $str is assigned
    in sources/Subs.php on line 456
  6. $str is passed through strftime()
    in sources/Subs.php on line 492
  7. standardTime() returns tainted data
    in themes/default/GenericMessages.template.php on line 64
  8. $poster_div is assigned
    in themes/default/GenericMessages.template.php on line 63
  9. template_build_poster_div() returns tainted data
    in themes/default/PersonalMessage.template.php on line 113
  6. Path: Read from $_POST, and SearchParams::$_search_params is assigned in sources/ElkArte/Search/SearchParams.php on line 478
  1. Read from $_POST, and SearchParams::$_search_params is assigned
    in sources/ElkArte/Search/SearchParams.php on line 478
  2. Tainted property SearchParams::$_search_params is read, and ValuesContainer::$data is assigned
    in sources/ElkArte/Search/SearchParams.php on line 102
  3. Tainted property ValuesContainer::$data is read
    in sources/ElkArte/ValuesContainer.php on line 65
  4. ValuesContainer::__get() returns tainted data, and $str is assigned
    in sources/Subs.php on line 456
  5. $str is passed through strftime()
    in sources/Subs.php on line 492
  6. standardTime() returns tainted data
    in themes/default/GenericMessages.template.php on line 64
  7. $poster_div is assigned
    in themes/default/GenericMessages.template.php on line 63
  8. template_build_poster_div() returns tainted data
    in themes/default/PersonalMessage.template.php on line 113
  7. Path: Read from $_REQUEST, and $_REQUEST['guestname'] is passed through trim(), and $context is assigned in sources/ElkArte/Controller/Post.php on line 366
  1. Read from $_REQUEST, and $_REQUEST['guestname'] is passed through trim(), and $context is assigned
    in sources/ElkArte/Controller/Post.php on line 366
  2. $context is assigned
    in sources/ElkArte/Controller/Post.php on line 367
  3. $context['name'] is passed to ValuesContainer::__set()
    in sources/ElkArte/Controller/Post.php on line -1
  4. ValuesContainer::$data is assigned
    in sources/ElkArte/ValuesContainer.php on line 53
  5. Tainted property ValuesContainer::$data is read
    in sources/ElkArte/ValuesContainer.php on line 65
  6. ValuesContainer::__get() returns tainted data, and $str is assigned
    in sources/Subs.php on line 456
  7. $str is passed through strftime()
    in sources/Subs.php on line 492
  8. standardTime() returns tainted data
    in themes/default/GenericMessages.template.php on line 64
  9. $poster_div is assigned
    in themes/default/GenericMessages.template.php on line 63
  10. template_build_poster_div() returns tainted data
    in themes/default/PersonalMessage.template.php on line 113
  8. Path: Read from $_REQUEST, and $_REQUEST['email'] is passed through trim(), and $context is assigned in sources/ElkArte/Controller/Post.php on line 367
  1. Read from $_REQUEST, and $_REQUEST['email'] is passed through trim(), and $context is assigned
    in sources/ElkArte/Controller/Post.php on line 367
  2. $context['name'] is passed to ValuesContainer::__set()
    in sources/ElkArte/Controller/Post.php on line -1
  3. ValuesContainer::$data is assigned
    in sources/ElkArte/ValuesContainer.php on line 53
  4. Tainted property ValuesContainer::$data is read
    in sources/ElkArte/ValuesContainer.php on line 65
  5. ValuesContainer::__get() returns tainted data, and $str is assigned
    in sources/Subs.php on line 456
  6. $str is passed through strftime()
    in sources/Subs.php on line 492
  7. standardTime() returns tainted data
    in themes/default/GenericMessages.template.php on line 64
  8. $poster_div is assigned
    in themes/default/GenericMessages.template.php on line 63
  9. template_build_poster_div() returns tainted data
    in themes/default/PersonalMessage.template.php on line 113

Preventing Cross-Site-Scripting Attacks

Cross-Site-Scripting allows an attacker to inject malicious code into your website - in particular Javascript code, and have that code executed with the privileges of a visiting user. This can be used to obtain data, or perform actions on behalf of that visiting user.

In order to prevent this, make sure to escape all user-provided data:

// for HTML
$sanitized = htmlentities($tainted, ENT_QUOTES);

// for URLs
$sanitized = urlencode($tainted);

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
114
115
		echo '
116
							<div class="postarea', empty($options['hide_poster_area']) ? '' : '2', '">
117
								<div class="keyinfo">
118
									', (!empty($options['hide_poster_area']) ? '<ul class="poster poster2">' . template_build_poster_div($message) . '</ul>' : ''), '
0 ignored issues
show
Security Cross-Site Scripting introduced by
!empty($options['hide_po...message) . '</ul>' : '' can contain request data and is used in output context(s) leading to a potential security vulnerability.

8 paths for user data to reach this point

  1. Path: Read from $_REQUEST, and $context is assigned in sources/ElkArte/Controller/Post.php on line 320
  1. Read from $_REQUEST, and $context is assigned
    in sources/ElkArte/Controller/Post.php on line 320
  2. $context is assigned
    in sources/ElkArte/Controller/Post.php on line 351
  3. $context is assigned
    in sources/ElkArte/Controller/Post.php on line 352
  4. $context is assigned
    in sources/ElkArte/Controller/Post.php on line 353
  5. $context is assigned
    in sources/ElkArte/Controller/Post.php on line 366
  6. $context is assigned
    in sources/ElkArte/Controller/Post.php on line 367
  7. $context['name'] is passed to ValuesContainer::__set()
    in sources/ElkArte/Controller/Post.php on line -1
  8. ValuesContainer::$data is assigned
    in sources/ElkArte/ValuesContainer.php on line 53
  9. Tainted property ValuesContainer::$data is read
    in sources/ElkArte/ValuesContainer.php on line 65
  10. ValuesContainer::__get() returns tainted data, and $str is assigned
    in sources/Subs.php on line 456
  11. $str is passed through strftime()
    in sources/Subs.php on line 492
  12. standardTime() returns tainted data
    in themes/default/GenericMessages.template.php on line 64
  13. $poster_div is assigned
    in themes/default/GenericMessages.template.php on line 63
  14. template_build_poster_div() returns tainted data
    in themes/default/PersonalMessage.template.php on line 118
  2. Path: Read from $_POST in sources/ElkArte/Controller/Post.php on line 946
  1. Read from $_POST
    in sources/ElkArte/Controller/Post.php on line 946
  2. $_POST['guestname'] is passed to ValuesContainer::__set()
    in sources/ElkArte/Controller/Post.php on line -1
  3. ValuesContainer::$data is assigned
    in sources/ElkArte/ValuesContainer.php on line 53
  4. Tainted property ValuesContainer::$data is read
    in sources/ElkArte/ValuesContainer.php on line 65
  5. ValuesContainer::__get() returns tainted data, and $str is assigned
    in sources/Subs.php on line 456
  6. $str is passed through strftime()
    in sources/Subs.php on line 492
  7. standardTime() returns tainted data
    in themes/default/GenericMessages.template.php on line 64
  8. $poster_div is assigned
    in themes/default/GenericMessages.template.php on line 63
  9. template_build_poster_div() returns tainted data
    in themes/default/PersonalMessage.template.php on line 118
  3. Path: Read from $_REQUEST, and $_REQUEST['params'] ?? '' is passed to SearchParams::__construct() in sources/ElkArte/Controller/Search.php on line 151
  1. Read from $_REQUEST, and $_REQUEST['params'] ?? '' is passed to SearchParams::__construct()
    in sources/ElkArte/Controller/Search.php on line 151
  2. SearchParams::$_search_string is assigned
    in sources/ElkArte/Search/SearchParams.php on line 100
  3. Tainted property SearchParams::$_search_string is read, and $this->_search_string is passed through str_replace(), and str_replace(array('-', '_', '.'), array('+', '/', '='), $this->_search_string) is decoded by base64_decode(), and $temp_params is assigned
    in sources/ElkArte/Search/SearchParams.php on line 160
  4. !empty($temp_params2) ? $temp_params2 : $temp_params is passed through explode(), and $temp_params is assigned
    in sources/ElkArte/Search/SearchParams.php on line 164
  5. $data is assigned
    in sources/ElkArte/Search/SearchParams.php on line 166
  6. $data is passed through explode(), and explode('|\'|', $data) is passed through array_pad(), and $v is assigned
    in sources/ElkArte/Search/SearchParams.php on line 168
  7. SearchParams::$_search_params is assigned
    in sources/ElkArte/Search/SearchParams.php on line 169
  8. Tainted property SearchParams::$_search_params is read, and ValuesContainer::$data is assigned
    in sources/ElkArte/Search/SearchParams.php on line 102
  9. Tainted property ValuesContainer::$data is read
    in sources/ElkArte/ValuesContainer.php on line 65
  10. ValuesContainer::__get() returns tainted data, and $str is assigned
    in sources/Subs.php on line 456
  11. $str is passed through strftime()
    in sources/Subs.php on line 492
  12. standardTime() returns tainted data
    in themes/default/GenericMessages.template.php on line 64
  13. $poster_div is assigned
    in themes/default/GenericMessages.template.php on line 63
  14. template_build_poster_div() returns tainted data
    in themes/default/PersonalMessage.template.php on line 118
  4. Path: Read from $_REQUEST, and $_REQUEST['params'] ?? '' is passed to SearchParams::__construct() in sources/ElkArte/Controller/Search.php on line 280
  1. Read from $_REQUEST, and $_REQUEST['params'] ?? '' is passed to SearchParams::__construct()
    in sources/ElkArte/Controller/Search.php on line 280
  2. SearchParams::$_search_string is assigned
    in sources/ElkArte/Search/SearchParams.php on line 100
  3. Tainted property SearchParams::$_search_string is read, and $this->_search_string is passed through str_replace(), and str_replace(array('-', '_', '.'), array('+', '/', '='), $this->_search_string) is decoded by base64_decode(), and $temp_params is assigned
    in sources/ElkArte/Search/SearchParams.php on line 160
  4. !empty($temp_params2) ? $temp_params2 : $temp_params is passed through explode(), and $temp_params is assigned
    in sources/ElkArte/Search/SearchParams.php on line 164
  5. $data is assigned
    in sources/ElkArte/Search/SearchParams.php on line 166
  6. $data is passed through explode(), and explode('|\'|', $data) is passed through array_pad(), and $v is assigned
    in sources/ElkArte/Search/SearchParams.php on line 168
  7. SearchParams::$_search_params is assigned
    in sources/ElkArte/Search/SearchParams.php on line 169
  8. Tainted property SearchParams::$_search_params is read, and ValuesContainer::$data is assigned
    in sources/ElkArte/Search/SearchParams.php on line 102
  9. Tainted property ValuesContainer::$data is read
    in sources/ElkArte/ValuesContainer.php on line 65
  10. ValuesContainer::__get() returns tainted data, and $str is assigned
    in sources/Subs.php on line 456
  11. $str is passed through strftime()
    in sources/Subs.php on line 492
  12. standardTime() returns tainted data
    in themes/default/GenericMessages.template.php on line 64
  13. $poster_div is assigned
    in themes/default/GenericMessages.template.php on line 63
  14. template_build_poster_div() returns tainted data
    in themes/default/PersonalMessage.template.php on line 118
  5. Path: Read from $_REQUEST, and $_REQUEST is passed to SearchParams::merge() in sources/ElkArte/Controller/Search.php on line 281
  1. Read from $_REQUEST, and $_REQUEST is passed to SearchParams::merge()
    in sources/ElkArte/Controller/Search.php on line 281
  2. SearchParams::$_search_params is assigned
    in sources/ElkArte/Search/SearchParams.php on line 256
  3. Tainted property SearchParams::$_search_params is read, and ValuesContainer::$data is assigned
    in sources/ElkArte/Search/SearchParams.php on line 102
  4. Tainted property ValuesContainer::$data is read
    in sources/ElkArte/ValuesContainer.php on line 65
  5. ValuesContainer::__get() returns tainted data, and $str is assigned
    in sources/Subs.php on line 456
  6. $str is passed through strftime()
    in sources/Subs.php on line 492
  7. standardTime() returns tainted data
    in themes/default/GenericMessages.template.php on line 64
  8. $poster_div is assigned
    in themes/default/GenericMessages.template.php on line 63
  9. template_build_poster_div() returns tainted data
    in themes/default/PersonalMessage.template.php on line 118
  6. Path: Read from $_POST, and SearchParams::$_search_params is assigned in sources/ElkArte/Search/SearchParams.php on line 478
  1. Read from $_POST, and SearchParams::$_search_params is assigned
    in sources/ElkArte/Search/SearchParams.php on line 478
  2. Tainted property SearchParams::$_search_params is read, and ValuesContainer::$data is assigned
    in sources/ElkArte/Search/SearchParams.php on line 102
  3. Tainted property ValuesContainer::$data is read
    in sources/ElkArte/ValuesContainer.php on line 65
  4. ValuesContainer::__get() returns tainted data, and $str is assigned
    in sources/Subs.php on line 456
  5. $str is passed through strftime()
    in sources/Subs.php on line 492
  6. standardTime() returns tainted data
    in themes/default/GenericMessages.template.php on line 64
  7. $poster_div is assigned
    in themes/default/GenericMessages.template.php on line 63
  8. template_build_poster_div() returns tainted data
    in themes/default/PersonalMessage.template.php on line 118
  7. Path: Read from $_REQUEST, and $_REQUEST['guestname'] is passed through trim(), and $context is assigned in sources/ElkArte/Controller/Post.php on line 366
  1. Read from $_REQUEST, and $_REQUEST['guestname'] is passed through trim(), and $context is assigned
    in sources/ElkArte/Controller/Post.php on line 366
  2. $context is assigned
    in sources/ElkArte/Controller/Post.php on line 367
  3. $context['name'] is passed to ValuesContainer::__set()
    in sources/ElkArte/Controller/Post.php on line -1
  4. ValuesContainer::$data is assigned
    in sources/ElkArte/ValuesContainer.php on line 53
  5. Tainted property ValuesContainer::$data is read
    in sources/ElkArte/ValuesContainer.php on line 65
  6. ValuesContainer::__get() returns tainted data, and $str is assigned
    in sources/Subs.php on line 456
  7. $str is passed through strftime()
    in sources/Subs.php on line 492
  8. standardTime() returns tainted data
    in themes/default/GenericMessages.template.php on line 64
  9. $poster_div is assigned
    in themes/default/GenericMessages.template.php on line 63
  10. template_build_poster_div() returns tainted data
    in themes/default/PersonalMessage.template.php on line 118
  8. Path: Read from $_REQUEST, and $_REQUEST['email'] is passed through trim(), and $context is assigned in sources/ElkArte/Controller/Post.php on line 367
  1. Read from $_REQUEST, and $_REQUEST['email'] is passed through trim(), and $context is assigned
    in sources/ElkArte/Controller/Post.php on line 367
  2. $context['name'] is passed to ValuesContainer::__set()
    in sources/ElkArte/Controller/Post.php on line -1
  3. ValuesContainer::$data is assigned
    in sources/ElkArte/ValuesContainer.php on line 53
  4. Tainted property ValuesContainer::$data is read
    in sources/ElkArte/ValuesContainer.php on line 65
  5. ValuesContainer::__get() returns tainted data, and $str is assigned
    in sources/Subs.php on line 456
  6. $str is passed through strftime()
    in sources/Subs.php on line 492
  7. standardTime() returns tainted data
    in themes/default/GenericMessages.template.php on line 64
  8. $poster_div is assigned
    in themes/default/GenericMessages.template.php on line 63
  9. template_build_poster_div() returns tainted data
    in themes/default/PersonalMessage.template.php on line 118

Preventing Cross-Site-Scripting Attacks

Cross-Site-Scripting allows an attacker to inject malicious code into your website - in particular Javascript code, and have that code executed with the privileges of a visiting user. This can be used to obtain data, or perform actions on behalf of that visiting user.

In order to prevent this, make sure to escape all user-provided data:

// for HTML
$sanitized = htmlentities($tainted, ENT_QUOTES);

// for URLs
$sanitized = urlencode($tainted);

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
119
									<span id="post_subject_', $message['id'], '" class="post_subject">', $message['subject'], '</span>
120
									<h5 id="info_', $message['id'], '">';
121
122
		// @todo - above needs fixing re document outlining (a11y stuffz).
123
		// Show who the message was sent to.
124
		echo '
125
										<strong>', $txt['sent_to'], ': </strong>';
126
127
		// People it was sent directly to....
128 View Code Duplication
		if (!empty($message['recipients']['to']))
129
			echo
130
			implode(', ', $message['recipients']['to']);
131
		// Otherwise, we're just going to say "some people"...
132
		elseif ($context['folder'] != 'sent')
133
			echo
134
			'(', $txt['pm_undisclosed_recipients'], ')';
135
136
		echo '
137
										<strong> ', $txt['on'], ': </strong>', $message['time'];
138
139
		// If we're in the sent items folder, show who it was sent to besides the "To:" people.
140
		if (!empty($message['recipients']['bcc']))
141
			echo '
142
										<br /><strong> ', $txt['pm_bcc'], ': </strong>', implode(', ', $message['recipients']['bcc']);
143
144
		if (!empty($message['is_replied_to']))
145
			echo '
146
										<br />', $txt['pm_is_replied_to'];
147
148
		echo '
149
									</h5>
150
								</div>';
151
152
		// Done with the information about the poster... on to the post itself.
153
		echo '
154
								<div class="inner">', $message['body'], '</div>';
155
156
		// Show our quick buttons like quote and reply
157
		echo '
158
								<ul class="quickbuttons">';
159
160
		// Showing all then give a remove item checkbox
161
		if (empty($context['display_mode']))
162
			echo '
163
									<li class="listlevel1 quickmod_check">
164
										<input type="checkbox" name="pms[]" id="deletedisplay', $message['id'], '" value="', $message['id'], '" onclick="document.getElementById(\'deletelisting', $message['id'], '\').checked = this.checked;" />
165
									</li>';
166
167
		// Maybe there is something...more :P (this is the more button)
168
		if (!empty($context['additional_pm_drop_buttons']))
169
		{
170
			echo '
171
									<li class="listlevel1 subsections" aria-haspopup="true">
172
										<a class="linklevel1 post_options">', $txt['post_options'], '</a>
173
										<ul class="menulevel2">';
174
175
			foreach ($context['additional_pm_drop_buttons'] as $key => $button)
176
				echo '
177
											<li class="listlevel2">
178
												<a href="' . $button['href'] . '" class="linklevel2 ', $key, '">' . $button['text'] . '</a>
179
											</li>';
180
181
			echo '
182
										</ul>
183
									</li>';
184
		}
185
186
		// Remove is always an option
187
		echo '
188
									<li class="listlevel1">
189
										<a href="', $scripturl, '?action=pm;sa=pmactions;pm_actions%5B', $message['id'], '%5D=delete;f=', $context['folder'], ';start=', $context['start'], $context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '', ';', $context['session_var'], '=', $context['session_id'], '" onclick="return confirm(\'', addslashes($txt['remove_message']), '?\');" class="linklevel1 remove_button">', $txt['delete'], '</a>
190
									</li>';
191
192
		// Show reply buttons if you have the permission to send PMs.
193
		if ($context['can_send_pm'])
194
		{
195
			// You can't really reply if the member is gone.
196
			if (!$message['member']['is_guest'])
197
			{
198
				// Is there than more than one recipient you can reply to?
199 View Code Duplication
				if ($message['number_recipients'] > 1)
200
					echo '
201
									<li class="listlevel1">
202
										<a href="', $scripturl, '?action=pm;sa=send;f=', $context['folder'], $context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '', ';pmsg=', $message['id'], ';quote;u=all" class="linklevel1 reply_all_button">', $txt['reply_to_all'], '</a></li>';
203
204
				echo '
205
									<li class="listlevel1">
206
										<a href="', $scripturl, '?action=pm;sa=send;f=', $context['folder'], $context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '', ';pmsg=', $message['id'], ';u=', $message['member']['id'], '" class="linklevel1 reply_button">', $txt['reply'], '</a>
207
									</li>
208
									<li class="listlevel1">
209
										<a href="', $scripturl, '?action=pm;sa=send;f=', $context['folder'], $context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '', ';pmsg=', $message['id'], ';quote', $context['folder'] == 'sent' ? '' : ';u=' . $message['member']['id'], '" class="linklevel1 quote_button">', $txt['quote'], '</a>
210
									</li>';
211
			}
212
			// This is for "forwarding" - even if the member is gone.
213 View Code Duplication
			else
214
				echo '
215
									<li class="listlevel1">
216
										<a href="', $scripturl, '?action=pm;sa=send;f=', $context['folder'], $context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '', ';pmsg=', $message['id'], ';quote" class="linklevel1 quote_button">', $txt['reply_quote'], '</a>
217
									</li>';
218
		}
219
220
		// Anything else added by mods for example?
221 View Code Duplication
		if (!empty($context['additional_quick_pm_buttons']))
222
		{
223
			foreach ($context['additional_quick_pm_buttons'] as $key => $button)
224
				echo '
225
									<li class="listlevel1">
226
										<a href="' . $button['href'] . '" class="linklevel1 ', $key, '">' . $button['text'] . '</a>
227
									</li>';
228
		}
229
230
		echo '
231
								</ul>';
232
233
		// Add a selection box if we have labels enabled.
234
		if ($context['folder'] !== 'sent' && !empty($context['currently_using_labels']) && $context['display_mode'] != 2)
235
		{
236
			echo '
237
								<div class="labels">';
238
239
			// Add the label drop down box.
240
			if (!empty($context['currently_using_labels']))
241
			{
242
				echo '
243
									<select name="pm_actions[', $message['id'], ']" onchange="if (this.options[this.selectedIndex].value) form.submit();">
244
										<option value="">', $txt['pm_msg_label_title'], ':</option>
245
										<option value="" disabled="disabled">' . str_repeat('&#8212;', strlen($txt['pm_msg_label_title'])) . '</option>';
246
247
				// Are there any labels which can be added to this?
248
				if (!$message['fully_labeled'])
249
				{
250
					echo '
251
										<option value="" disabled="disabled">', $txt['pm_msg_label_apply'], ':</option>';
252
253
					foreach ($context['labels'] as $label)
254
					{
255
						if (!isset($message['labels'][$label['id']]))
256
							echo '
257
										<option value="', $label['id'], '">&nbsp;', $label['name'], '</option>';
258
					}
259
				}
260
261
				// ... and are there any that can be removed?
262
				if (!empty($message['labels']) && (count($message['labels']) > 1 || !isset($message['labels'][-1])))
263
				{
264
					echo '
265
										<option value="" disabled="disabled">', $txt['pm_msg_label_remove'], ':</option>';
266
267
					foreach ($message['labels'] as $label)
268
						echo '
269
										<option value="', $label['id'], '">&nbsp;', $label['name'], '</option>';
270
				}
271
272
				echo '
273
									</select>
274
									<noscript>
275
										<input type="submit" value="', $txt['pm_apply'], '" />
276
									</noscript>';
277
			}
278
279
			echo '
280
								</div>';
281
		}
282
283
		// Are there any custom profile fields for above the signature?
284
		// Show them if signatures are enabled and you want to see them.
285 View Code Duplication
		if (!empty($message['member']['custom_fields']) && empty($options['show_no_signatures']) && $context['signature_enabled'])
286
		{
287
			$shown = false;
288
			foreach ($message['member']['custom_fields'] as $custom)
289
			{
290
				if ($custom['placement'] != 2 || empty($custom['value']))
291
					continue;
292
293
				if (!$shown)
294
				{
295
					$shown = true;
296
					echo '
297
								<div class="custom_fields_above_signature">
298
									<ul>';
299
				}
300
301
				echo '
302
										<li>', $custom['value'], '</li>';
303
			}
304
305
			if ($shown)
306
				echo '
307
									</ul>
308
								</div>';
309
		}
310
311
		// Show the member's signature?
312
		if (!empty($message['member']['signature']) && empty($options['show_no_signatures']) && $context['signature_enabled'])
313
			echo '
314
								<div class="signature">', $message['member']['signature'], '</div>';
315
316
		echo '
317
							</div>
318
						</div>';
319
	}
320
321
	echo '
322
					</div>';
323
324
}
325
326
/**
327
 * Used to display items above the page, like page navigation
328
 */
329
function template_pm_pages_and_buttons_above()
330
{
331
	global $context;
332
333
	// Show a few buttons if we are in conversation mode and outputting the first message.
334
	if ($context['display_mode'] == 2)
335
		template_pagesection('conversation_buttons', 'right', array('page_index' => false));
336
	else
337
		template_pagesection();
338
}
339
340
/**
341
 * Used to display items below the page, like page navigation
342
 */
343
function template_pm_pages_and_buttons_below()
344
{
345
	global $context, $txt;
346
347
	if (empty($context['display_mode']))
348
		template_pagesection(false, '', array('extra' => '<input type="submit" name="del_selected" value="' . $txt['quickmod_delete_selected'] . '" style="font-weight: normal;" onclick="if (!confirm(\'' . $txt['delete_selected_confirm'] . '\')) return false;" class="right_submit" />'));
349
	// Show a few buttons if we are in conversation mode and outputting the first message.
350
	elseif ($context['display_mode'] == 2 && isset($context['conversation_buttons']))
351
		template_pagesection('conversation_buttons', 'right', array('page_index' => false));
352
}
353
354
/**
355
 * Just list all the personal message subjects - to make templates easier.
356
 * Unfortunately a bit ugly at the moment
357
 */
358
function template_subject_list_above()
359
{
360
	global $context;
361
362
	// If we are not in single display mode show the subjects on the top!
363
	if ($context['display_mode'] != 1)
364
	{
365
		template_subject_list();
366
367
		echo '
368
					<hr class="clear" />';
369
	}
370
}
371
372
/**
373
 * Template layer to show items below the subject list
374
 */
375
function template_subject_list_below()
376
{
377
	global $context;
378
379
	// Individual messages = button list!
380
	if ($context['display_mode'] == 1)
381
		template_subject_list();
382
}
383
384
/**
385
 * Template layer to show the PM subject listing
386
 */
387
function template_subject_list()
388
{
389
	global $context, $settings, $txt, $scripturl;
390
391
	echo '
392
					<table class="table_grid">
393
						<thead>
394
							<tr class="table_head">
395
								<th class="pm_icon">
396
									<a href="', $scripturl, '?action=pm;view;f=', $context['folder'], ';start=', $context['start'], ';sort=', $context['sort_by'], ($context['sort_direction'] === 'up' ? ';asc' : ';desc'), ($context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : ''), '">
397
										<i class="icon i-shuffle" title="', $txt['pm_change_view'], '"><s>', $txt['pm_change_view'], '</s></i>
398
									</a>
399
								</th>
400
								<th class="pm_date">
401
									<a href="', $scripturl, '?action=pm;f=', $context['folder'], ';start=', $context['start'], ';sort=date', ($context['sort_by'] === 'date' && $context['sort_direction'] === 'up' ? ';desc' : ';asc'), $context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '', '">
402
										', $txt['date'], $context['sort_by'] === 'date' ? ' <i class="icon icon-small i-sort-numeric-' . $context['sort_direction'] . '"></i>' : '', '
403
									</a>
404
								</th>
405
								<th class="pm_subject">
406
									<a href="', $scripturl, '?action=pm;f=', $context['folder'], ';start=', $context['start'], ';sort=subject', ($context['sort_by'] === 'subject' && $context['sort_direction'] === 'up' ? ';desc' : ';asc'), $context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '', '">
407
										', $txt['subject'], $context['sort_by'] === 'subject' ? ' <i class="icon icon-small i-sort-alpha-' . $context['sort_direction'] . '"></i>' : '', '
408
									</a>
409
								</th>
410
								<th class="pm_from">
411
									<a href="', $scripturl, '?action=pm;f=', $context['folder'], ';start=', $context['start'], ';sort=name', ($context['sort_by'] === 'name' && $context['sort_direction'] === 'up' ? ';desc' : ';asc'), $context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '', '">
412
										', ($context['from_or_to'] === 'from' ? $txt['from'] : $txt['to']), $context['sort_by'] === 'name' ? ' <i class="icon icon-small i-sort-alpha-' . $context['sort_direction'] . '"></i>' : '', '
413
									</a>
414
								</th>
415
								<th class="pm_quickmod">
416
									<input type="checkbox" onclick="invertAll(this, this.form);" />
417
								</th>
418
							</tr>
419
						</thead>
420
						<tbody>';
421
422
	if (!$context['show_delete'])
423
		echo '
424
							<tr class="standard_row">
425
								<td colspan="5">', $txt['pm_alert_none'], '</td>
426
							</tr>';
427
428
	// Use the query callback to get the subject list
429
	$controller = $context['get_psubject'][0];
430
	while ($message = $controller->{$context['get_psubject'][1]}())
431
	{
432
		$discussion_url = $context['display_mode'] == 0 || $context['current_pm'] == $message['id'] ? '' : ($scripturl . '?action=pm;pmid=' . $message['id'] . ';kstart;f=' . $context['folder'] . ';start=' . $context['start'] . ';sort=' . $context['sort_by'] . ($context['sort_direction'] == 'up' ? ';asc' : ';desc') . ($context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : ''));
433
434
		echo '
435
							<tr class="standard_row">
436
								<td class="pm_icon">
437
									<script>
438
										currentLabels[', $message['id'], '] = {';
439
440
		if (!empty($message['labels']))
441
		{
442
			$first = true;
443
			foreach ($message['labels'] as $label)
444
			{
445
				echo $first ? '' : ',', '
446
										"', $label['id'], '": "', $label['name'], '"';
447
				$first = false;
448
			}
449
		}
450
451
		echo '
452
										};
453
									</script>
454
									', $message['is_replied_to'] ? '<img src="' . $settings['images_url'] . '/icons/pm_replied.png" alt="' . $txt['pm_replied'] . '" />' : '<i class="icon i-comment-blank"></i>', '</td>
455
								<td class="pm_date">', $message['time'], '</td>
456
								<td class="pm_subject">',
457
									$context['display_mode'] != 0 && $context['current_pm'] == $message['id'] ? '<img src="' . $settings['images_url'] . '/selected.png" alt="*" />' : '',
458
									$message['is_unread'] ? '<a href="' . $discussion_url . '#msg_' . $message['id'] . '" class="new_posts">' . $txt['new'] . '</a>' : '', '
459
									<a href="', $discussion_url, '#msg_', $message['id'], '">
460
										', $message['subject'], '
461
									</a>
462
								</td>
463
								<td class="pm_from">
464
									', ($context['from_or_to'] == 'from' ? $message['member']['link'] : (empty($message['recipients']['to']) ? '' : implode(', ', $message['recipients']['to']))), '
465
								</td>
466
								<td class="pm_quickmod">
467
									<input type="checkbox" name="pms[]" id="deletelisting', $message['id'], '" value="', $message['id'], '"', $message['is_selected'] ? ' checked="checked"' : '', ' onclick="if (document.getElementById(\'deletedisplay', $message['id'], '\')) document.getElementById(\'deletedisplay', $message['id'], '\').checked = this.checked;" />
468
								</td>
469
							</tr>';
470
	}
471
472
	echo '
473
						</tbody>
474
					</table>';
475
476
	$extra = '
477
					<ul class="label_pms">';
478
479
	if ($context['show_delete'])
480
	{
481
		if (!empty($context['currently_using_labels']) && $context['folder'] != 'sent')
482
		{
483
			$extra .= '
484
						<li>
485
							<select name="pm_action" onchange="if (this.options[this.selectedIndex].value) this.form.submit();" onfocus="loadLabelChoices();">
486
								<option value="">' . $txt['pm_sel_label_title'] . ':</option>
487
								<option value="" disabled="disabled">' . str_repeat('&#8212;', strlen($txt['pm_sel_label_title'])) . '</option>';
488
489
			$extra .= '
490
								<option value="" disabled="disabled">' . $txt['pm_msg_label_apply'] . ':</option>';
491
492
			foreach ($context['labels'] as $label)
493
			{
494
				if ($label['id'] != $context['current_label_id'])
495
					$extra .= '
496
								<option value="add_' . $label['id'] . '">&#10148;&nbsp;' . $label['name'] . '</option>';
497
			}
498
499
			$extra .= '
500
								<option value="" disabled="disabled">' . $txt['pm_msg_label_remove'] . ':</option>';
501
502
			foreach ($context['labels'] as $label)
503
			{
504
				$extra .= '
505
								<option value="rem_' . $label['id'] . '">&#10148;&nbsp;' . $label['name'] . '</option>';
506
			}
507
508
			$extra .= '
509
							</select>
510
							<noscript>
511
								<input type="submit" value="' . $txt['pm_apply'] . '" class="right_submit" />
512
							</noscript>
513
						</li>';
514
		}
515
516
		$extra .= '
517
						<li><input type="submit" name="del_selected" value="' . $txt['quickmod_delete_selected'] . '" onclick="if (!confirm(\'' . $txt['delete_selected_confirm'] . '\')) return false;" class="right_submit" /></li>';
518
	}
519
520
	$extra .= '
521
					</ul>';
522
523
	template_pagesection(false, '', array('extra' => $extra));
524
}
525
526
/**
527
 * Page to search in PMs.
528
 */
529
function template_search()
530
{
531
	global $context, $scripturl, $txt;
532
533
	echo '
534
	<form id="searchform" action="', $scripturl, '?action=pm;sa=search2" method="post" accept-charset="UTF-8" name="searchform" >
535
		<h2 class="category_header">', $txt['pm_search_title'], '</h2>';
536
537
	// Any search errors we need to let them know about
538 View Code Duplication
	if (!empty($context['search_errors']))
539
		echo '
540
		<p class="errorbox">', implode('<br />', $context['search_errors']['messages']), '</p>';
541
542
	// Start with showing the basic search input box
543
	echo '
544
		<fieldset id="simple_search" class="content">
545
			<div id="search_term_input">
546
				<label for="search">
547
					<strong>', $txt['pm_search_text'], ':</strong>
548
				</label>
549
				<input type="search" id="search" class="input_text" name="search"', !empty($context['search_params']['search']) ? ' value="' . $context['search_params']['search'] . '"' : '', ' size="40" placeholder="', $txt['search'], '" required="required" autofocus="autofocus" />
550
				<input type="submit" name="pm_search" value="', $txt['pm_search_go'], '" />
551
			</div>';
552
553
	// Now all the advanced options, hidden or shown by JS based on the users minmax choices
554
	echo '
555
			<div id="advanced_search">
556
				<dl id="search_options">
557
					<dt class="righttext">
558
						<label for="searchtype">', $txt['search_match'], ':</label>
559
					</dt>
560
					<dd>
561
						<select name="searchtype">
562
							<option value="1"', empty($context['search_params']['searchtype']) ? ' selected="selected"' : '', '>', $txt['pm_search_match_all'], '</option>
563
							<option value="2"', !empty($context['search_params']['searchtype']) ? ' selected="selected"' : '', '>', $txt['pm_search_match_any'], '</option>
564
						</select>
565
					</dd>
566
					<dt>
567
						<label for="userspec">', $txt['pm_search_user'], ':</label>
568
					</dt>
569
					<dd>
570
						<input type="text" name="userspec" value="', empty($context['search_params']['userspec']) ? '*' : $context['search_params']['userspec'], '" size="40" class="input_text" />
571
					</dd>
572
					<dt>
573
						<label for="sort">', $txt['pm_search_order'], ':</label>
574
					</dt>
575
					<dd>
576
						<select name="sort" id="sort">
577
							<option value="relevance|desc">', $txt['pm_search_orderby_relevant_first'], '</option>
578
							<option value="id_pm|desc">', $txt['pm_search_orderby_recent_first'], '</option>
579
							<option value="id_pm|asc">', $txt['pm_search_orderby_old_first'], '</option>
580
						</select>
581
					</dd>
582
					<dt class="options">
583
						', $txt['pm_search_options'], ':
584
					</dt>
585
					<dd class="options">
586
						<input type="checkbox" name="show_complete" id="show_complete" value="1"', !empty($context['search_params']['show_complete']) ? ' checked="checked"' : '', ' />
587
						<label for="show_complete">', $txt['pm_search_show_complete'], '</label><br />
588
						<input type="checkbox" name="subject_only" id="subject_only" value="1"', !empty($context['search_params']['subject_only']) ? ' checked="checked"' : '', ' />
589
						<label for="subject_only">', $txt['pm_search_subject_only'], '</label><br />
590
						<input type="checkbox" name="sent_only" id="sent_only" value="1"', !empty($context['search_params']['sent_only']) ? ' checked="checked"' : '', ' />
591
						<label for="sent_only">', $txt['pm_search_sent_only'], '</label>
592
					</dd>
593
					<dt class="righttext between">
594
						', $txt['pm_search_post_age'], ':
595
					</dt>
596
					<dd>
597
						<label for="minage">', $txt['pm_search_between'], '</label>&nbsp;
598
						 <input type="text" id="minage" name="minage" value="', empty($context['search_params']['minage']) ? '0' : $context['search_params']['minage'], '" size="5" maxlength="5" class="input_text" />
599
						<label for="maxage">', $txt['pm_search_between_and'], '&nbsp;</label>
600
						<input type="text" name="maxage" id="maxage" value="', empty($context['search_params']['maxage']) ? '9999' : $context['search_params']['maxage'], '" size="5" maxlength="5" class="input_text" />', $txt['pm_search_between_days'], '
601
					</dd>
602
				</dl>
603
			</div>
604
			<a id="upshrink_link" href="', $scripturl, '?action=search;advanced" class="linkbutton hide">', $txt['pm_search_simple'], '</a>';
605
606
	// Set the initial search style for the form
607
	echo '
608
			<input id="advanced" type="hidden" name="advanced" value="1" />
609
		</fieldset>';
610
611
	// Do we have some labels setup? If so offer to search by them!
612
	if ($context['currently_using_labels'])
613
	{
614
		echo '
615
		<fieldset class="content">
616
			<h3 class="secondary_header panel_toggle">
617
					<i id="advanced_panel_toggle" class="chevricon i-chevron-', empty($context['minmax_preferences']['pm']) ? 'up' : 'down', ' hide" title="', $txt['hide'], '"></i>
618
				<a href="#" id="advanced_panel_link">', $txt['pm_search_choose_label'], '</a>
619
			</h3>
620
			<div id="advanced_panel_div" class="well', empty($context['minmax_preferences']['pm']) ? '"' : ' hide"', '>
621
				<ul id="searchLabelsExpand">';
622
623
		foreach ($context['search_labels'] as $label)
624
			echo '
625
					<li>
626
						<label for="searchlabel_', $label['id'], '"><input type="checkbox" id="searchlabel_', $label['id'], '" name="searchlabel[', $label['id'], ']" value="', $label['id'], '" ', $label['checked'] ? 'checked="checked"' : '', ' />
627
						', $label['name'], '</label>
628
					</li>';
629
630
		echo '
631
				</ul>
632
			</div>
633
			<div class="submitbuttons">
634
				<input type="checkbox" name="all" id="check_all" value="" ', $context['check_all'] ? 'checked="checked"' : '', ' onclick="invertAll(this, this.form, \'searchlabel\');" /><em> <label for="check_all">', $txt['check_all'], '</label></em>
635
			</div>
636
		</fieldset>';
637
638
		// And now some javascript for the advanced label toggling
639
		theme()->addInlineJavascript('
640
			createEventListener(window);
641
			window.addEventListener("load", initSearch, false);
642
643
			var oAdvancedPanelToggle = new elk_Toggle({
644
				bToggleEnabled: true,
645
				bCurrentlyCollapsed: ' . (empty($context['minmax_preferences']['pm']) ? 'false' : 'true') . ',
646
				aSwappableContainers: [
647
					\'advanced_panel_div\'
648
				],
649
				aSwapClasses: [
650
					{
651
						sId: \'advanced_panel_toggle\',
652
						classExpanded: \'chevricon i-chevron-up\',
653
						titleExpanded: ' . JavaScriptEscape($txt['hide']) . ',
654
						classCollapsed: \'chevricon i-chevron-down\',
655
						titleCollapsed: ' . JavaScriptEscape($txt['show']) . '
656
					}
657
				],
658
				aSwapLinks: [
659
					{
660
						sId: \'advanced_panel_link\',
661
						msgExpanded: ' . JavaScriptEscape($txt['pm_search_choose_label']) . ',
662
						msgCollapsed: ' . JavaScriptEscape($txt['pm_search_choose_label']) . '
663
					}
664
				],
665
				oThemeOptions: {
666
					bUseThemeSettings: ' . ($context['user']['is_guest'] ? 'false' : 'true') . ',
667
					sOptionName: \'minmax_preferences\',
668
					sSessionId: elk_session_id,
669
					sSessionVar: elk_session_var,
670
					sAdditionalVars: \';minmax_key=pm\'
671
				},
672
			});', true);
673
	}
674
675
	// And the JS to make the advanced / basic form work
676
	theme()->addInlineJavascript('
677
		// Set the search style
678
		document.getElementById(\'advanced\').value = "' . (empty($context['minmax_preferences']['pmsearch']) ? '1' : '0') . '";
679
680
		// And allow for the collapsing of the advanced search options
681
		var oSearchToggle = new elk_Toggle({
682
			bToggleEnabled: true,
683
			bCurrentlyCollapsed: ' . (empty($context['minmax_preferences']['pmsearch']) ? 'false' : 'true') . ',
684
			funcOnBeforeCollapse: function () {
685
				document.getElementById(\'advanced\').value = \'0\';
686
			},
687
			funcOnBeforeExpand: function () {
688
				document.getElementById(\'advanced\').value = \'1\';
689
			},
690
			aSwappableContainers: [
691
				\'advanced_search\'
692
			],
693
			aSwapLinks: [
694
				{
695
					sId: \'upshrink_link\',
696
					msgExpanded: ' . JavaScriptEscape($txt['search_simple']) . ',
697
					msgCollapsed: ' . JavaScriptEscape($txt['search_advanced']) . '
698
				}
699
			],
700
			oThemeOptions: {
701
				bUseThemeSettings: ' . ($context['user']['is_guest'] ? 'false' : 'true') . ',
702
				sOptionName: \'minmax_preferences\',
703
				sSessionId: elk_session_id,
704
				sSessionVar: elk_session_var,
705
				sAdditionalVars: \';minmax_key=pmsearch\'
706
			},
707
		});', true);
708
709
	echo '
710
	</form>';
711
}
712
713
/**
714
 * Template for the results of search in PMs.
715
 */
716
function template_search_results()
717
{
718
	global $context, $scripturl, $txt;
719
720
	echo '
721
		<div class="search_results_posts', empty($context['search_params']['show_complete']) ? ' compact_view' : '', '">
722
			<h2 class="category_header hdicon cat_img_search">
723
				', $txt['mlist_search_results'], ':&nbsp;', $context['search_params']['search'], '
724
			</h2>';
725
726
	// Was anything even found?
727
	if (!empty($context['personal_messages']))
728
		template_pagesection();
729
	else
730
		echo '
731
			<div class="well">', $txt['find_no_results'], '</div>';
732
733
	// Showing complete results?
734
	if (empty($context['search_params']['show_complete']))
735
		echo '
736
			<table class="table_grid">
737
				<thead>
738
					<tr class="table_head">
739
						<th class="lefttext grid30">', $txt['date'], '</th>
740
						<th class="lefttext grid50">', $txt['subject'], '</th>
741
						<th class="lefttext grid20">', $txt['from'], '</th>
742
					</tr>
743
				</thead>
744
				<tbody>';
745
	else
746
		echo '
747
			<ul class="forumposts topic_listing search_results_posts">';
748
749
	// Print each message out...
750
	foreach ($context['personal_messages'] as $message)
751
	{
752
		if (!empty($context['search_params']['show_complete']))
753
		{
754
			echo '
755
				<li class="basic_row">
756
					<div class="topic_details">
757
						<div class="counter">', $message['counter'], '</div>
758
						<h5><a href="', $message['href'], '">', $message['subject'], '</a>&nbsp;<span class="smalltext">&#171;&nbsp;', $txt['search_on'], ': ', $message['time'], '&nbsp;&#187;</h5>
759
						<span class="smalltext">', $txt['from'], ': ', $message['member']['link'], ', ', $txt['to'], ': ';
760
761
			// Show the recipients.
762
			// @todo This doesn't deal with the sent item searching quite right for bcc.
763 View Code Duplication
			if (!empty($message['recipients']['to']))
764
				echo implode(', ', $message['recipients']['to']);
765
			// Otherwise, we're just going to say "some people"...
766
			elseif ($context['folder'] !== 'sent')
767
				echo '(', $txt['pm_undisclosed_recipients'], ')';
768
769
			echo '
770
						</span>
771
					</div>
772
					<div class="topic_body">
773
						', $message['body'], '
774
					</div>';
775
776
			if ($context['can_send_pm'])
777
			{
778
				echo '
779
					<ul class="quickbuttons">';
780
781
				// You can only reply if they are not a guest...
782
				if (!$message['member']['is_guest'])
783
					echo '
784
						<li class="listlevel1"><a class="linklevel1 reply_button" href="', $scripturl, '?action=pm;sa=send;f=', $context['folder'], $context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '', ';pmsg=', $message['id'], ';u=', $message['member']['id'], '">', $txt['reply'], '</a></li>
785
						<li class="listlevel1"><a class="linklevel1 quote_button" href="', $scripturl, '?action=pm;sa=send;f=', $context['folder'], $context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '', ';pmsg=', $message['id'], ';quote;u=', $context['folder'] == 'sent' ? '' : $message['member']['id'], '">', $txt['quote'], '</a></li>';
786
				// This is for "forwarding" - even if the member is gone.
787 View Code Duplication
				else
788
					echo '
789
						<li class="listlevel1"><a class="linklevel1 quote_button" href="', $scripturl, '?action=pm;sa=send;f=', $context['folder'], $context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '', ';pmsg=', $message['id'], ';quote">', $txt['quote'], '</a></li>';
790
				echo '
791
					</ul>';
792
			}
793
794
			echo '
795
				</li>';
796
		}
797
		// Otherwise just a simple list!
798
		else
799
		{
800
			// @todo No context at all of the search?
801
			echo '
802
					<tr>
803
						<td>', $message['time'], '</td>
804
						<td>', $message['link'], '</td>
805
						<td>', $message['member']['link'], '</td>
806
					</tr>';
807
		}
808
	}
809
810
	if (!empty($context['search_params']['show_complete']))
811
		echo '
812
			</ul>';
813
	else
814
		echo '
815
				</tbody>
816
			</table>';
817
818
	// If we have results show a page index
819
	if (!empty($context['personal_messages']))
820
		template_pagesection();
821
822
	echo '
823
		</div>';
824
}
825
826
/**
827
 * Show the send a new pm form, including the editor, preview section and load
828
 * drafts if enabled.
829
 */
830
function template_send()
831
{
832
	global $context, $scripturl, $modSettings, $txt;
833
834
	// Show which messages were sent successfully and which failed.
835
	if (!empty($context['send_log']))
836
	{
837
		echo '
838
			<div class="forumposts">
839
				<h2 class="category_header">', $txt['pm_send_report'], '</h2>
840
				<div class="content">';
841
842 View Code Duplication
		if (!empty($context['send_log']['sent']))
843
			foreach ($context['send_log']['sent'] as $log_entry)
844
				echo '
845
					<span class="error">', $log_entry, '</span><br />';
846
847 View Code Duplication
		if (!empty($context['send_log']['failed']))
848
			foreach ($context['send_log']['failed'] as $log_entry)
849
				echo '
850
					<span class="error">', $log_entry, '</span><br />';
851
852
		echo '
853
				</div>
854
			</div>';
855
	}
856
857
	// Show the preview of the personal message.
858
	echo '
859
		<div id="preview_section"', isset($context['preview_message']) ? '' : ' class="hide"', '>
860
			<h2 class="category_header">
861
				<span id="preview_subject">', empty($context['preview_subject']) ? '' : $context['preview_subject'], '</span>
862
			</h2>
863
			<div id="preview_body">
864
				', empty($context['preview_message']) ? '<br />' : $context['preview_message'], '
865
			</div>
866
		</div>';
867
868
	// Main message editing box.
869
	echo '
870
	<form id="pmFolder" action="', $scripturl, '?action=pm;sa=send2" method="post" accept-charset="UTF-8" name="pmFolder" onsubmit="submitonce(this);smc_saveEntities(\'pmFolder\', [\'subject\', \'message\']);">
871
		<h2 class="category_header hdicon cat_img_write">
872
			', $txt['new_message'], '
873
		</h2>';
874
875
	echo '
876
		<div class="content forumposts">
877
			<div class="editor_wrapper">';
878
879
	// If there were errors for sending the PM, show them.
880
	template_show_error('post_error');
881
882
	if (!empty($modSettings['drafts_pm_enabled']))
883
		echo '
884
				<div id="draft_section" class="successbox', isset($context['draft_saved']) ? '"' : ' hide"', '>',
885
					sprintf($txt['draft_pm_saved'], $scripturl . '?action=pm;sa=showpmdrafts'), '
886
				</div>';
887
888
	echo '
889
				<dl id="post_header">';
890
891
	// To and bcc. Include a button to search for members.
892
	echo '
893
					<dt>
894
						<label for="to_control"', (isset($context['post_error']['no_to']) || isset($context['post_error']['bad_to']) ? ' class="error"' : ''), ' id="caption_to">', $txt['pm_to'], ':</label>
895
					</dt>';
896
897
	// Autosuggest will be added by the javascript later on.
898
	echo '
899
					<dd id="pm_to" class="clear_right">
900
						<input type="text" name="to" id="to_control" value="', $context['to_value'], '" tabindex="', $context['tabindex']++, '" size="40" style="width: 130px;" class="input_text" />';
901
902
	// A link to add BCC, only visible with javascript enabled.
903
	echo '
904
						<span id="bcc_link_container" class="smalltext hide"></span>';
905
906
	// A div that'll contain the items found by the autosuggest.
907
	echo '
908
						<div id="to_item_list_container"></div>';
909
910
	echo '
911
					</dd>';
912
913
	// This BCC row will be hidden by default if javascript is enabled.
914
	echo '
915
					<dt id="bcc_div" class="clear_left" >
916
						<label for="bcc_control"', (isset($context['post_error']['no_to']) || isset($context['post_error']['bad_bcc']) ? ' class="error"' : ''), ' id="caption_bbc">', $txt['pm_bcc'], ':</label>
917
					</dt>
918
					<dd id="bcc_div2">
919
						<input type="text" name="bcc" id="bcc_control" value="', $context['bcc_value'], '" tabindex="', $context['tabindex']++, '" size="40" style="width: 130px;" class="input_text" />
920
						<div id="bcc_item_list_container"></div>
921
					</dd>';
922
923
	// The subject of the PM.
924
	echo '
925
					<dt class="clear_left">
926
						<label for="subject"', (isset($context['post_error']['no_subject']) ? ' class="error"' : ''), ' id="caption_subject">', $txt['subject'], ':</label>
927
					</dt>
928
					<dd id="pm_subject">
929
						<input type="text" id="subject" name="subject" value="', $context['subject'], '" tabindex="', $context['tabindex']++, '" size="80" maxlength="80"', isset($context['post_error']['no_subject']) ? ' class="error"' : ' class="input_text"', ' placeholder="', $txt['subject'], '" required="required" />
930
					</dd>
931
				</dl>';
932
933
	// Show BBC buttons, smileys and textbox.
934
	echo '
935
				', template_control_richedit($context['post_box_name'], 'smileyBox_message', 'bbcBox_message');
936
937
	// Require an image to be typed to save spamming?
938 View Code Duplication
	if (!empty($context['require_verification']))
939
		template_verification_controls($context['visual_verification_id'], '
940
				<div class="post_verification">
941
					<strong>' . $txt['pm_visual_verification_label'] . ':</strong>
942
					', '
943
				</div>');
944
945
	// Send, Preview, spellchecker buttons.
946
	echo '
947
				<div id="post_confirm_buttons" class="submitbutton">
948
					', template_control_richedit_buttons($context['post_box_name']), '
949
				</div>
950
				<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
951
				<input type="hidden" name="seqnum" value="', $context['form_sequence_number'], '" />
952
				<input type="hidden" name="replied_to" value="', !empty($context['quoted_message']['id']) ? $context['quoted_message']['id'] : 0, '" />
953
				<input type="hidden" name="pm_head" value="', !empty($context['quoted_message']['pm_head']) ? $context['quoted_message']['pm_head'] : 0, '" />
954
				<input type="hidden" name="f" value="', isset($context['folder']) ? $context['folder'] : '', '" />
955
				<input type="hidden" name="l" value="', isset($context['current_label_id']) ? $context['current_label_id'] : -1, '" />';
956
957
	// If the admin enabled the pm drafts feature, show a draft selection box
958
	if (!empty($context['drafts_pm_save']) && !empty($context['drafts']))
959
	{
960
		echo '
961
				<h3 id="postDraftOptionsHeader" class="category_header panel_toggle">
962
						<i id="postDraftExpand" class="chevricon i-chevron-', empty($context['minmax_preferences']['pmdraft']) ? 'up' : 'down', ' hide" title="', $txt['hide'], '"></i>
963
					<a href="#" id="postDraftExpandLink">', $txt['draft_load'], '</a>
964
				</h3>
965
				<div id="postDraftOptions" class="load_drafts padding', empty($context['minmax_preferences']['pmdraft']) ? '"' : ' hide"', '>
966
					<dl class="settings">
967
						<dt><strong>', $txt['subject'], '</strong></dt>
968
						<dd><strong>', $txt['draft_saved_on'], '</strong></dd>';
969
970
		foreach ($context['drafts'] as $draft)
971
			echo '
972
						<dt>', $draft['link'], '</dt>
973
						<dd>', $draft['poster_time'], '</dd>';
974
975
		echo '
976
					</dl>
977
				</div>';
978
	}
979
980
	echo '
981
			</div>
982
		</div>
983
	</form>';
984
985
	// The vars used to preview a personal message without loading a new page.
986
	echo '
987
	<script>
988
		var form_name = "pmFolder",
989
			preview_area = "pm",
990
			txt_preview_title = "', $txt['preview_title'], '",
991
			txt_preview_fetch = "', $txt['preview_fetch'], '";
992
	</script>';
993
994
	// Code for showing and hiding drafts
995
	if (!empty($context['drafts']))
996
		theme()->addInlineJavascript('
997
		var oSwapDraftOptions = new elk_Toggle({
998
			bToggleEnabled: true,
999
			bCurrentlyCollapsed: ' . (empty($context['minmax_preferences']['pmdraft']) ? 'false' : 'true') . ',
1000
			aSwappableContainers: [
1001
				\'postDraftOptions\',
1002
			],
1003
			aSwapClasses: [
1004
				{
1005
					sId: \'postDraftExpand\',
1006
					classExpanded: \'chevricon i-chevron-up\',
1007
					titleExpanded: ' . JavaScriptEscape($txt['hide']) . ',
1008
					classCollapsed: \'chevricon i-chevron-down\',
1009
					titleCollapsed: ' . JavaScriptEscape($txt['show']) . '
1010
				}
1011
			],
1012
			aSwapLinks: [
1013
				{
1014
					sId: \'postDraftExpandLink\',
1015
					msgExpanded: ' . JavaScriptEscape($txt['draft_hide']) . ',
1016
					msgCollapsed: ' . JavaScriptEscape($txt['draft_load']) . '
1017
				}
1018
			],
1019
			oThemeOptions: {
1020
				bUseThemeSettings: ' . ($context['user']['is_guest'] ? 'false' : 'true') . ',
1021
				sOptionName: \'minmax_preferences\',
1022
				sSessionId: elk_session_id,
1023
				sSessionVar: elk_session_var,
1024
				sAdditionalVars: \';minmax_key=pmdraft\'
1025
			},
1026
		});', true);
1027
1028
	// Show the message you're replying to.
1029
	if ($context['reply'])
1030
		echo '
1031
1032
	<div class="forumposts">
1033
		<h2 class="category_header">', $txt['subject'], ': ', $context['quoted_message']['subject'], '</h2>
1034
		<div class="content">
1035
			<div class="clear">
1036
				<span class="smalltext floatright">', $txt['on'], ': ', $context['quoted_message']['time'], '</span>
1037
				<strong>', $txt['from'], ': ', $context['quoted_message']['member']['name'], '</strong>
1038
			</div>
1039
			<hr />
1040
			', $context['quoted_message']['body'], '
1041
		</div>
1042
	</div>';
1043
1044
	echo '
1045
		<script>
1046
			new elk_PersonalMessageSend({
1047
				sSessionId: elk_session_id,
1048
				sSessionVar: elk_session_var,
1049
				sTextDeleteItem: ', JavaScriptEscape($txt['autosuggest_delete_item']), ',
1050
				sToControlId: \'to_control\',
1051
				aToRecipients: [';
1052
1053 View Code Duplication
	foreach ($context['recipients']['to'] as $i => $member)
1054
		echo '
1055
					{
1056
						sItemId: ', JavaScriptEscape($member['id']), ',
1057
						sItemName: ', JavaScriptEscape($member['name']), '
1058
					}', $i == count($context['recipients']['to']) - 1 ? '' : ',';
1059
1060
	echo '
1061
				],
1062
				aBccRecipients: [';
1063
1064 View Code Duplication
	foreach ($context['recipients']['bcc'] as $i => $member)
1065
		echo '
1066
					{
1067
						sItemId: ', JavaScriptEscape($member['id']), ',
1068
						sItemName: ', JavaScriptEscape($member['name']), '
1069
					}', $i == count($context['recipients']['bcc']) - 1 ? '' : ',';
1070
1071
	echo '
1072
				],
1073
				sBccControlId: \'bcc_control\',
1074
				sBccDivId: \'bcc_div\',
1075
				sBccDivId2: \'bcc_div2\',
1076
				sBccLinkId: \'bcc_link\',
1077
				sBccLinkContainerId: \'bcc_link_container\',
1078
				bBccShowByDefault: ', empty($context['recipients']['bcc']) && empty($context['bcc_value']) ? 'false' : 'true', ',
1079
				sShowBccLinkTemplate: ', JavaScriptEscape('
1080
					<a href="#" id="bcc_link">' . $txt['make_bcc'] . '</a> <a href="' . $scripturl . '?action=quickhelp;help=pm_bcc" onclick="return reqOverlayDiv(this.href);" class="helpicon i-help"><s>' . $txt['help'] . '</s></a>'
1081
				), '
1082
			});
1083
		</script>';
1084
}
1085
1086
/**
1087
 * This template asks the user whether they wish to empty out their folder/messages.
1088
 */
1089
function template_ask_delete()
1090
{
1091
	global $context, $scripturl, $txt;
1092
1093
	echo '
1094
		<h2 class="category_header">', ($context['delete_all'] ? $txt['delete_message'] : $txt['delete_all']), '</h2>
1095
		<div class="content">
1096
			<p>', $txt['delete_all_confirm'], '</p><br />
1097
			<strong><a href="', $scripturl, '?action=pm;sa=removeall2;f=', $context['folder'], ';', $context['current_label_id'] != -1 ? ';l=' . $context['current_label_id'] : '', ';', $context['session_var'], '=', $context['session_id'], '">', $txt['yes'], '</a> - <a href="javascript:window.location.assign(document.referrer);">', $txt['no'], '</a></strong>
1098
		</div>';
1099
}
1100
1101
/**
1102
 * This template asks the user what messages they want to prune.
1103
 */
1104
function template_prune()
1105
{
1106
	global $context, $scripturl, $txt;
1107
1108
	echo '
1109
	<form id="prune_pm" action="', $scripturl, '?action=pm;sa=prune" method="post" accept-charset="UTF-8" onsubmit="return confirm(\'', $txt['pm_prune_warning'], '\');">
1110
		<h2 class="category_header">', $txt['pm_prune'], '</h2>
1111
		<div class="content">
1112
			<p>
1113
				<label for="age">', sprintf($txt['pm_prune_desc'], '<input type="text" id="age" name="age" size="3" value="14" class="input_text" />'), '</label>
1114
			</p>
1115
			<div class="submitbutton">
1116
				<input type="submit" value="', $txt['delete'], '" />
1117
				<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
1118
			</div>
1119
		</div>
1120
	</form>';
1121
}
1122
1123
/**
1124
 * Here we allow the user to setup labels, remove labels and change rules for labels (i.e, do quite a bit)
1125
 */
1126
function template_labels()
1127
{
1128
	global $context, $scripturl, $txt;
1129
1130
	echo '
1131
	<form class="flow_auto" action="', $scripturl, '?action=pm;sa=manlabels" method="post" accept-charset="UTF-8">
1132
		<h2 class="category_header">', $txt['pm_manage_labels'], '</h2>
1133
		<div class="description">
1134
			', $txt['pm_labels_desc'], '
1135
		</div>
1136
		<table class="table_grid">
1137
		<thead>
1138
			<tr class="table_head">
1139
				<th class="lefttext">
1140
					', $txt['pm_label_name'], '
1141
				</th>
1142
				<th style="width: 4%;">';
1143
1144
	if (count($context['labels']) > 2)
1145
		echo '
1146
					<input type="checkbox" onclick="invertAll(this, this.form);" />';
1147
1148
	echo '
1149
				</th>
1150
			</tr>
1151
		</thead>
1152
		<tbody>';
1153
1154
	if (count($context['labels']) < 2)
1155
		echo '
1156
			<tr>
1157
				<td colspan="2" class="centertext">', $txt['pm_labels_no_exist'], '</td>
1158
			</tr>';
1159
	else
1160
	{
1161
		foreach ($context['labels'] as $label)
1162
		{
1163
			if ($label['id'] == -1)
1164
				continue;
1165
1166
			echo '
1167
			<tr>
1168
				<td>
1169
					<input type="text" name="label_name[', $label['id'], ']" value="', $label['name'], '" size="30" maxlength="30" class="input_text" />
1170
				</td>
1171
				<td style="width: 4%;">
1172
					<input type="checkbox" name="delete_label[', $label['id'], ']" />
1173
				</td>
1174
			</tr>';
1175
		}
1176
	}
1177
1178
	echo '
1179
		</tbody>
1180
		</table>';
1181
1182
	if (!count($context['labels']) < 2)
1183
		echo '
1184
		<div class="submitbutton">
1185
			<input type="submit" name="save" value="', $txt['save'], '" />
1186
			<input type="submit" name="delete" value="', $txt['quickmod_delete_selected'], '" onclick="return confirm(\'', $txt['pm_labels_delete'], '\');" />
1187
		</div>';
1188
1189
	echo '
1190
		<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
1191
	</form>
1192
	<br />
1193
	<form class="flow_auto" action="', $scripturl, '?action=pm;sa=manlabels" method="post" accept-charset="UTF-8" style="margin-top: 1ex;">
1194
		<h2 class="category_header">', $txt['pm_label_add_new'], '</h2>
1195
		<div class="content">
1196
			<dl class="settings">
1197
				<dt>
1198
					<label for="add_label">', $txt['pm_label_name'], ':</label>
1199
				</dt>
1200
				<dd>
1201
					<input type="text" id="add_label" name="label" value="" size="30" maxlength="30" class="input_text" />
1202
				</dd>
1203
			</dl>
1204
			<div class="submitbutton">
1205
				<input type="submit" name="add" value="', $txt['pm_label_add_new'], '" />
1206
				<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
1207
			</div>
1208
		</div>
1209
	</form>';
1210
}
1211
1212
/**
1213
 * Template for reporting a personal message.
1214
 */
1215
function template_report_message()
1216
{
1217
	global $context, $txt, $scripturl;
1218
1219
	echo '
1220
	<form action="', $scripturl, '?action=pm;sa=report;l=', $context['current_label_id'], '" method="post" accept-charset="UTF-8">
1221
		<h2 class="category_header">', $txt['pm_report_title'], '</h2>
1222
		<div class="description">
1223
			', $txt['pm_report_desc'], '
1224
		</div>
1225
		<div class="content">
1226
			<dl class="settings">
1227
				<dt>
1228
					', $txt['pm_report_reason'], ':
1229
				</dt>
1230
				<dd>
1231
					<textarea id="reason" name="reason" rows="4" cols="70" style="width: 95%;"></textarea>
1232
				</dd>
1233
			</dl>
1234
			<div class="submitbutton">
1235
				<input type="submit" name="report" value="', $txt['pm_report_message'], '" />
1236
				<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
1237
				<input type="hidden" name="pmsg" value="', $context['pm_id'], '" />
1238
			</div>
1239
		</div>
1240
	</form>';
1241
}
1242
1243
/**
1244
 * Little template just to say "Yep, it's been reported".
1245
 */
1246
function template_report_message_complete()
1247
{
1248
	global $context, $txt, $scripturl;
1249
1250
	echo '
1251
		<h2 class="category_header hdicon cat_img_moderation">', $txt['pm_report_title'], '</h2>
1252
		<div class="well">
1253
			<div class="content">
1254
				<p>', $txt['pm_report_done'], '</p>
1255
				<a class="linkbutton_right" href="', $scripturl, '?action=pm;l=', $context['current_label_id'], '">', $txt['pm_report_return'], '</a>
1256
			</div>
1257
		</div>';
1258
}
1259
1260
/**
1261
 * Manage rules.
1262
 */
1263
function template_rules()
1264
{
1265
	global $context, $txt, $scripturl;
1266
1267
	echo '
1268
	<form action="', $scripturl, '?action=pm;sa=manrules" method="post" accept-charset="UTF-8" name="manRules" id="manrules">
1269
		<h2 class="category_header">', $txt['pm_manage_rules'], '</h2>
1270
		<div class="description">
1271
			', $txt['pm_manage_rules_desc'], '
1272
		</div>
1273
		<table class="table_grid">
1274
		<thead>
1275
			<tr class="table_head">
1276
				<th class="lefttext">
1277
					', $txt['pm_rule_title'], '
1278
				</th>
1279
				<th style="width: 4%;">';
1280
1281
	if (!empty($context['rules']))
1282
		echo '
1283
					<input type="checkbox" onclick="invertAll(this, this.form);" />';
1284
1285
	echo '
1286
				</th>
1287
			</tr>
1288
		</thead>
1289
		<tbody>';
1290
1291
	if (empty($context['rules']))
1292
		echo '
1293
			<tr>
1294
				<td colspan="2" class="centertext">
1295
					', $txt['pm_rules_none'], '
1296
				</td>
1297
			</tr>';
1298
1299
	foreach ($context['rules'] as $rule)
1300
	{
1301
		echo '
1302
			<tr>
1303
				<td>
1304
					<a href="', $scripturl, '?action=pm;sa=manrules;add;rid=', $rule['id'], '">', $rule['name'], '</a>
1305
				</td>
1306
				<td style="width: 4%;">
1307
					<input type="checkbox" name="delrule[', $rule['id'], ']" />
1308
				</td>
1309
			</tr>';
1310
	}
1311
1312
	echo '
1313
		</tbody>
1314
		</table>
1315
		<div class="submitbutton">
1316
			<a class="linkbutton" href="', $scripturl, '?action=pm;sa=manrules;add;rid=0">', $txt['pm_add_rule'], '</a>';
1317
1318 View Code Duplication
	if (!empty($context['rules']))
1319
		echo '
1320
			<a class="linkbutton" href="', $scripturl, '?action=pm;sa=manrules;apply;', $context['session_var'], '=', $context['session_id'], '" onclick="return confirm(\'', $txt['pm_js_apply_rules_confirm'], '\');">', $txt['pm_apply_rules'], '</a>';
1321
1322 View Code Duplication
	if (!empty($context['rules']))
1323
		echo '
1324
			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
1325
			<input type="submit" name="delselected" value="', $txt['pm_delete_selected_rule'], '" onclick="return confirm(\'', $txt['pm_js_delete_rule_confirm'], '\');" />';
1326
1327
	echo '
1328
		</div>
1329
	</form>';
1330
}
1331
1332
/**
1333
 * Template for adding/editing a rule.
1334
 */
1335
function template_add_rule()
1336
{
1337
	global $context, $txt, $scripturl;
1338
1339
	echo '
1340
	<form action="', $scripturl, '?action=pm;sa=manrules;save;rid=', $context['rid'], '" method="post" accept-charset="UTF-8" name="addrule" id="addrule" class="flow_hidden">
1341
		<h2 class="category_header">', $context['rid'] == 0 ? $txt['pm_add_rule'] : $txt['pm_edit_rule'], '</h2>
1342
		<div class="content">
1343
			<dl class="addrules">
1344
				<dt class="floatleft">
1345
					<label for="rule_name">', $txt['pm_rule_name'], ':</label><br />
1346
					<span class="smalltext">', $txt['pm_rule_name_desc'], '</span>
1347
				</dt>
1348
				<dd class="floatleft">
1349
					<input type="text" id="rule_name" name="rule_name" value="', empty($context['rule']['name']) ? $txt['pm_rule_name_default'] : $context['rule']['name'], '" size="50" class="input_text" />
1350
				</dd>
1351
			</dl>
1352
			<fieldset id="criteria">
1353
				<legend>', $txt['pm_rule_criteria'], '</legend>';
1354
1355
	// For each criteria print it out.
1356
	$isFirst = true;
1357
	foreach ($context['rule']['criteria'] as $k => $criteria)
1358
	{
1359 View Code Duplication
		if (!$isFirst && $criteria['t'] == '')
1360
			echo '
1361
				<div id="removeonjs1">';
1362
		elseif (!$isFirst)
1363
			echo '
1364
				<br />';
1365
1366
		echo '
1367
					<select class="criteria" name="ruletype[', $k, ']" id="ruletype', $k, '" data-optnum="', $k, '">
1368
						<option value="">', $txt['pm_rule_criteria_pick'], ':</option>';
1369
1370
		foreach ($context['known_rules'] as $rule)
1371
			echo '
1372
						<option value="', $rule, '" ', $criteria['t'] == $rule ? 'selected="selected"' : '', '>', $txt['pm_rule_' . $rule], '</option>';
1373
1374
		echo '
1375
					</select>
1376
					<span id="defdiv', $k, '" ', !in_array($criteria['t'], array('gid', 'bud')) ? '' : 'class="hide"', '>
1377
						<input type="text" name="ruledef[', $k, ']" id="ruledef', $k, '" value="', in_array($criteria['t'], array('mid', 'sub', 'msg')) ? $criteria['v'] : '', '" class="input_text" />
1378
					</span>
1379
					<span id="defseldiv', $k, '" ', $criteria['t'] == 'gid' ? '' : 'class="hide"', '>
1380
						<select class="criteria" name="ruledefgroup[', $k, ']" id="ruledefgroup', $k, '">
1381
							<option value="">', $txt['pm_rule_sel_group'], '</option>';
1382
1383
		foreach ($context['groups'] as $id => $group)
1384
			echo '
1385
							<option value="', $id, '" ', $criteria['t'] == 'gid' && $criteria['v'] == $id ? 'selected="selected"' : '', '>', $group, '</option>';
1386
1387
		echo '
1388
						</select>
1389
					</span>';
1390
1391
		// If this is the dummy we add a means to hide for non js users.
1392
		if ($isFirst)
1393
			$isFirst = false;
1394
		elseif ($criteria['t'] == '')
1395
			echo '
1396
				</div>';
1397
	}
1398
1399
	echo '
1400
				<span id="criteriaAddHere"></span>
1401
				<br />
1402
				<a id="addonjs1" class="linkbutton hide" href="#" onclick="addCriteriaOption(); return false;">', $txt['pm_rule_criteria_add'], '</a>
1403
				<br /><br />
1404
				', $txt['pm_rule_logic'], ':
1405
				<select name="rule_logic" id="logic">
1406
					<option value="and" ', $context['rule']['logic'] == 'and' ? 'selected="selected"' : '', '>', $txt['pm_rule_logic_and'], '</option>
1407
					<option value="or" ', $context['rule']['logic'] == 'or' ? 'selected="selected"' : '', '>', $txt['pm_rule_logic_or'], '</option>
1408
				</select>
1409
			</fieldset>
1410
			<fieldset id="actions">
1411
				<legend>', $txt['pm_rule_actions'], '</legend>';
1412
1413
	// As with criteria - add a dummy action for "expansion".
1414
	$context['rule']['actions'][] = array('t' => '', 'v' => '');
1415
1416
	// Print each action.
1417
	$isFirst = true;
1418
	foreach ($context['rule']['actions'] as $k => $action)
1419
	{
1420 View Code Duplication
		if (!$isFirst && $action['t'] == '')
1421
			echo '
1422
				<div id="removeonjs2">';
1423
		elseif (!$isFirst)
1424
			echo '
1425
				<br />';
1426
1427
		echo '
1428
					<select name="acttype[', $k, ']" id="acttype', $k, '" data-actnum="', $k, '">
1429
						<option value="">', $txt['pm_rule_sel_action'], ':</option>
1430
						<option value="lab" ', $action['t'] == 'lab' ? 'selected="selected"' : '', '>', $txt['pm_rule_label'], '</option>
1431
						<option value="del" ', $action['t'] == 'del' ? 'selected="selected"' : '', '>', $txt['pm_rule_delete'], '</option>
1432
					</select>
1433
					<span id="labdiv', $k, '">
1434
						<select name="labdef[', $k, ']" id="labdef', $k, '">
1435
							<option value="">', $txt['pm_rule_sel_label'], '</option>';
1436
1437
		foreach ($context['labels'] as $label)
1438
			if ($label['id'] != -1)
1439
				echo '
1440
							<option value="', ($label['id'] + 1), '" ', $action['t'] == 'lab' && $action['v'] == $label['id'] ? 'selected="selected"' : '', '>', $label['name'], '</option>';
1441
1442
		echo '
1443
						</select>
1444
					</span>';
1445
1446
		if ($isFirst)
1447
			$isFirst = false;
1448
		elseif ($action['t'] == '')
1449
			echo '
1450
				</div>';
1451
	}
1452
1453
	echo '
1454
				<span id="actionAddHere"></span><br />
1455
				<a href="#" id="addonjs2" class="linkbutton hide" onclick="addActionOption(); return false;">', $txt['pm_rule_add_action'], '</a>
1456
			</fieldset>
1457
		</div>
1458
		<h2 class="category_header">', $txt['pm_rule_description'], '</h2>
1459
		<div class="information">
1460
			<div id="ruletext">', $txt['pm_rule_js_disabled'], '</div>
1461
		</div>
1462
		<div class="submitbutton">
1463
			<input type="hidden" name="', $context['session_var'], '" value="', $context['session_id'], '" />
1464
			<input type="submit" name="save" value="', $txt['pm_rule_save'], '" />
1465
		</div>
1466
	</form>';
1467
1468
	// Now setup all the bits!
1469
	echo '
1470
	<script>
1471
		initUpdateRulesActions();';
1472
1473
	// If this isn't a new rule and we have JS enabled remove the JS compatibility stuff.
1474
	if ($context['rid'])
1475
		echo '
1476
			document.getElementById("removeonjs1").className = "hide";
1477
			document.getElementById("removeonjs2").className = "hide";';
1478
1479
	echo '
1480
			document.getElementById("addonjs1").style.display = "";
1481
			document.getElementById("addonjs2").style.display = "";';
1482
1483
	echo '
1484
		</script>';
1485
}
1486
1487
/**
1488
 * Template for showing all the PM drafts of the user.
1489
 */
1490
function template_showPMDrafts()
1491
{
1492
	global $context, $scripturl, $txt;
1493
1494
	echo '
1495
		<h2 class="category_header hdicon cat_img_talk">
1496
			', $txt['drafts_show'], '
1497
		</h2>';
1498
	template_pagesection();
1499
1500
	// No drafts? Just show an informative message.
1501
	if (empty($context['drafts']))
1502
		echo '
1503
		<div class="information centertext">
1504
			', $txt['draft_none'], '
1505
		</div>';
1506
	else
1507
	{
1508
		// For every draft to be displayed, give it its own div, and show the important details of the draft.
1509
		foreach ($context['drafts'] as $draft)
1510
		{
1511
			echo '
1512
		<div class="content">
1513
			<div class="counter">', $draft['counter'], '</div>
1514
			<div class="topic_details">
1515
				<h5>
1516
					<strong>', $draft['subject'], '</strong>&nbsp;
1517
				</h5>
1518
				<span class="smalltext">&#171;&nbsp;<strong>', $txt['draft_saved_on'], ':</strong> ', sprintf($txt['draft_days_ago'], $draft['age']), (!empty($draft['remaining']) ? ', ' . sprintf($txt['draft_retain'], $draft['remaining']) : ''), '&#187;</span>
1519
				<br />
1520
				<span class="smalltext">&#171;&nbsp;<strong>', $txt['to'], ':</strong> ', implode(', ', $draft['recipients']['to']), '&nbsp;&#187;</span>
1521
				<br />
1522
				<span class="smalltext">&#171;&nbsp;<strong>', $txt['pm_bcc'], ':</strong> ', implode(', ', $draft['recipients']['bcc']), '&nbsp;&#187;</span>
1523
			</div>
1524
			<div class="inner">
1525
				', $draft['body'], '
1526
			</div>
1527
			<ul class="quickbuttons">
1528
				<li class="listlevel1">
1529
					<a href="', $scripturl, '?action=pm;sa=showpmdrafts;id_draft=', $draft['id_draft'], ';', $context['session_var'], '=', $context['session_id'], '" class="linklevel1 reply_button">', $txt['draft_edit'], '</a>
1530
				</li>
1531
				<li class="listlevel1">
1532
					<a href="', $scripturl, '?action=pm;sa=showpmdrafts;delete=', $draft['id_draft'], ';', $context['session_var'], '=', $context['session_id'], '" onclick="return confirm(\'', $txt['draft_remove'], '?\');" class="linklevel1 remove_button">', $txt['draft_delete'], '</a>
1533
				</li>
1534
			</ul>
1535
		</div>';
1536
		}
1537
	}
1538
1539
	// Show page numbers.
1540
	template_pagesection();
1541
}