|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* Handle credits, license, privacy policy?, cookie policy?, registration agreement?, contact |
|
5
|
|
|
* staff, COPPA contact |
|
6
|
|
|
* |
|
7
|
|
|
* @package ElkArte Forum |
|
8
|
|
|
* @copyright ElkArte Forum contributors |
|
9
|
|
|
* @license BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file) |
|
10
|
|
|
* |
|
11
|
|
|
* @version 2.0 dev |
|
12
|
|
|
* |
|
13
|
|
|
*/ |
|
14
|
|
|
|
|
15
|
|
|
namespace ElkArte\Controller; |
|
16
|
|
|
|
|
17
|
|
|
use ArrayObject; |
|
18
|
|
|
use ElkArte\AbstractController; |
|
19
|
|
|
use ElkArte\Action; |
|
20
|
|
|
use ElkArte\Exceptions\Exception; |
|
21
|
|
|
use ElkArte\Helper\DataValidator; |
|
22
|
|
|
use ElkArte\Http\Headers; |
|
23
|
|
|
use ElkArte\Languages\Txt; |
|
24
|
|
|
|
|
25
|
|
|
/** |
|
26
|
|
|
* About Controller |
|
27
|
|
|
*/ |
|
28
|
|
|
class About extends AbstractController |
|
29
|
|
|
{ |
|
30
|
|
|
private const STATUS_AWAITING_COPPA = 5; |
|
31
|
|
|
|
|
32
|
|
|
/** |
|
33
|
|
|
* Default action of this class. |
|
34
|
|
|
* Accessed with ?action=about |
|
35
|
|
|
*/ |
|
36
|
|
|
public function action_index() :void |
|
37
|
|
|
{ |
|
38
|
|
|
// Add an subaction array to act accordingly |
|
39
|
|
|
$subActions = [ |
|
40
|
|
|
'credits' => [$this, 'action_credits'], |
|
41
|
|
|
'contact' => [$this, 'action_contact'], |
|
42
|
|
|
'coppa' => [$this, 'action_coppa'], |
|
43
|
|
|
]; |
|
44
|
|
|
|
|
45
|
|
|
// Setup the action handler |
|
46
|
|
|
$action = new Action(); |
|
47
|
|
|
$subAction = $action->initialize($subActions, 'credits'); |
|
48
|
|
|
|
|
49
|
|
|
// Call the action |
|
50
|
|
|
$action->dispatch($subAction); |
|
51
|
|
|
} |
|
52
|
|
|
|
|
53
|
|
|
/** |
|
54
|
|
|
* Shows the contact form for the user to fill out |
|
55
|
|
|
* |
|
56
|
|
|
* - Functionality needs to be enabled in the ACP for this to be used |
|
57
|
|
|
* - Triggers the verify_contact event |
|
58
|
|
|
*/ |
|
59
|
|
|
public function action_contact(): void |
|
60
|
|
|
{ |
|
61
|
|
|
global $context, $txt, $modSettings; |
|
62
|
|
|
|
|
63
|
|
|
// Users have no need to use this, just send a PM |
|
64
|
|
|
// Disabled, you cannot enter. |
|
65
|
|
|
if ($this->user->is_guest === false || empty($modSettings['enable_contactform']) || $modSettings['enable_contactform'] === 'disabled') |
|
|
|
|
|
|
66
|
|
|
{ |
|
67
|
|
|
redirectexit(); |
|
68
|
|
|
} |
|
69
|
|
|
|
|
70
|
|
|
Txt::load('Login'); |
|
71
|
|
|
theme()->getTemplates()->load('Register'); |
|
72
|
|
|
|
|
73
|
|
|
// Submitted the contact form? |
|
74
|
|
|
if (isset($this->_req->post->send)) |
|
75
|
|
|
{ |
|
76
|
|
|
checkSession(); |
|
77
|
|
|
validateToken('contact'); |
|
78
|
|
|
|
|
79
|
|
|
// Can't send a lot of these in a row, no sir! |
|
80
|
|
|
spamProtection('contact'); |
|
81
|
|
|
|
|
82
|
|
|
// No errors, yet. |
|
83
|
|
|
$context['errors'] = []; |
|
84
|
|
|
Txt::load('Errors'); |
|
85
|
|
|
|
|
86
|
|
|
// Could they get the right send topic verification code? |
|
87
|
|
|
require_once(SUBSDIR . '/Members.subs.php'); |
|
88
|
|
|
|
|
89
|
|
|
// Form validation |
|
90
|
|
|
$validator = new DataValidator(); |
|
91
|
|
|
$validator->sanitation_rules([ |
|
92
|
|
|
'emailaddress' => 'trim', |
|
93
|
|
|
'contactmessage' => 'trim' |
|
94
|
|
|
]); |
|
95
|
|
|
$validator->validation_rules([ |
|
96
|
|
|
'emailaddress' => 'required|valid_email', |
|
97
|
|
|
'contactmessage' => 'required' |
|
98
|
|
|
]); |
|
99
|
|
|
$validator->text_replacements([ |
|
100
|
|
|
'emailaddress' => $txt['error_email'], |
|
101
|
|
|
'contactmessage' => $txt['error_message'] |
|
102
|
|
|
]); |
|
103
|
|
|
|
|
104
|
|
|
// Any form errors |
|
105
|
|
|
if (!$validator->validate($this->_req->post)) |
|
106
|
|
|
{ |
|
107
|
|
|
$context['errors'] = $validator->validation_errors(); |
|
108
|
|
|
} |
|
109
|
|
|
|
|
110
|
|
|
// Get the clean data |
|
111
|
|
|
$this->_req->post = new ArrayObject($validator->validation_data(), ArrayObject::ARRAY_AS_PROPS); |
|
112
|
|
|
|
|
113
|
|
|
// Trigger the verify contact event for captcha checks |
|
114
|
|
|
$this->_events->trigger('verify_contact', []); |
|
115
|
|
|
|
|
116
|
|
|
// No errors, then send the PM to the admins |
|
117
|
|
|
if (empty($context['errors'])) |
|
118
|
|
|
{ |
|
119
|
|
|
$admins = admins(); |
|
120
|
|
|
if (!empty($admins)) |
|
121
|
|
|
{ |
|
122
|
|
|
require_once(SUBSDIR . '/PersonalMessage.subs.php'); |
|
123
|
|
|
sendpm(['to' => array_keys($admins), 'bcc' => []], $txt['contact_subject'], $this->_req->post->contactmessage, false, ['id' => 0, 'name' => $this->_req->post->emailaddress, 'username' => $this->_req->post->emailaddress]); |
|
124
|
|
|
} |
|
125
|
|
|
|
|
126
|
|
|
// Send the PM |
|
127
|
|
|
redirectexit('action=about;sa=contact;done'); |
|
128
|
|
|
} |
|
129
|
|
|
else |
|
130
|
|
|
{ |
|
131
|
|
|
$context['emailaddress'] = $this->_req->post->emailaddress; |
|
132
|
|
|
$context['contactmessage'] = $this->_req->post->contactmessage; |
|
133
|
|
|
} |
|
134
|
|
|
} |
|
135
|
|
|
|
|
136
|
|
|
// Show the contact done form or the form itself |
|
137
|
|
|
if (isset($this->_req->query->done)) |
|
138
|
|
|
{ |
|
139
|
|
|
$context['sub_template'] = 'contact_form_done'; |
|
140
|
|
|
} |
|
141
|
|
|
else |
|
142
|
|
|
{ |
|
143
|
|
|
loadJavascriptFile('ext/mailcheck.min.js'); |
|
144
|
|
|
$context['sub_template'] = 'contact_form'; |
|
145
|
|
|
$context['page_title'] = $txt['admin_contact_form']; |
|
146
|
|
|
|
|
147
|
|
|
// Setup any contract form events, like validation |
|
148
|
|
|
$this->_events->trigger('setup_contact', []); |
|
149
|
|
|
} |
|
150
|
|
|
|
|
151
|
|
|
createToken('contact'); |
|
152
|
|
|
} |
|
153
|
|
|
|
|
154
|
|
|
/** |
|
155
|
|
|
* This function will display the contact information for the forum, as well a form to fill in. |
|
156
|
|
|
* |
|
157
|
|
|
* - Accessed by action=about;sa=coppa |
|
158
|
|
|
*/ |
|
159
|
|
|
public function action_coppa(): void |
|
160
|
|
|
{ |
|
161
|
|
|
global $context, $modSettings, $txt; |
|
162
|
|
|
|
|
163
|
|
|
Txt::load('Login'); |
|
164
|
|
|
theme()->getTemplates()->load('About'); |
|
165
|
|
|
|
|
166
|
|
|
// No User ID?? |
|
167
|
|
|
if (!isset($this->_req->query->member)) |
|
168
|
|
|
{ |
|
169
|
|
|
throw new Exception('no_access', false); |
|
170
|
|
|
} |
|
171
|
|
|
|
|
172
|
|
|
// Get the user details... |
|
173
|
|
|
require_once(SUBSDIR . '/Members.subs.php'); |
|
174
|
|
|
$member = getBasicMemberData((int) $this->_req->query->member, ['authentication' => true]); |
|
175
|
|
|
|
|
176
|
|
|
// If doesn't exist or not pending coppa |
|
177
|
|
|
if (empty($member) || (int) $member['is_activated'] !== self::STATUS_AWAITING_COPPA) |
|
178
|
|
|
{ |
|
179
|
|
|
throw new Exception('no_access', false); |
|
180
|
|
|
} |
|
181
|
|
|
|
|
182
|
|
|
if (isset($this->_req->query->form)) |
|
183
|
|
|
{ |
|
184
|
|
|
$this->handleContactForm($member); |
|
185
|
|
|
} |
|
186
|
|
|
else |
|
187
|
|
|
{ |
|
188
|
|
|
$this->handleCoppa(); |
|
189
|
|
|
} |
|
190
|
|
|
} |
|
191
|
|
|
|
|
192
|
|
|
/** |
|
193
|
|
|
* Handle the contact form for member registration. |
|
194
|
|
|
* |
|
195
|
|
|
* This method sets the necessary variables in the global $context for displaying the contact form. |
|
196
|
|
|
* If the query parameter `dl` is set, the method outputs a file for download, otherwise it shows the contact form template. |
|
197
|
|
|
* |
|
198
|
|
|
* @param array $member The member data from getBasicMemberData()) |
|
199
|
|
|
*/ |
|
200
|
|
|
private function handleContactForm($member): void |
|
201
|
|
|
{ |
|
202
|
|
|
global $context, $modSettings, $txt; |
|
203
|
|
|
|
|
204
|
|
|
// Some simple contact stuff for the forum. |
|
205
|
|
|
$context['forum_contacts'] = (empty($modSettings['coppaPost']) ? '' : $modSettings['coppaPost'] . '<br /><br />') . (empty($modSettings['coppaFax']) ? '' : $modSettings['coppaFax'] . '<br />'); |
|
206
|
|
|
$context['forum_contacts'] = empty($context['forum_contacts']) ? '' : $context['forum_name_html_safe'] . '<br />' . $context['forum_contacts']; |
|
207
|
|
|
|
|
208
|
|
|
// Showing template? |
|
209
|
|
|
if (!isset($this->_req->query->dl)) |
|
210
|
|
|
{ |
|
211
|
|
|
// Shortcut for producing underlines. |
|
212
|
|
|
$context['ul'] = '<span class="underline"> </span>'; |
|
213
|
|
|
theme()->getLayers()->removeAll(); |
|
214
|
|
|
$context['sub_template'] = 'coppa_form'; |
|
215
|
|
|
$context['page_title'] = replaceBasicActionUrl($txt['coppa_form_title']); |
|
216
|
|
|
$context['coppa_body'] = str_replace(['{PARENT_NAME}', '{CHILD_NAME}', '{USER_NAME}'], [$context['ul'], $context['ul'], $member['member_name']], replaceBasicActionUrl($txt['coppa_form_body'])); |
|
217
|
|
|
} |
|
218
|
|
|
// Downloading. |
|
219
|
|
|
else |
|
220
|
|
|
{ |
|
221
|
|
|
// Set up to output a file to the users browser |
|
222
|
|
|
while (ob_get_level() > 0) |
|
223
|
|
|
{ |
|
224
|
|
|
@ob_end_clean(); |
|
|
|
|
|
|
225
|
|
|
} |
|
226
|
|
|
|
|
227
|
|
|
// The data. |
|
228
|
|
|
$ul = ' '; |
|
229
|
|
|
$crlf = "\r\n"; |
|
230
|
|
|
$data = $context['forum_contacts'] . $crlf . $txt['coppa_form_address'] . ':' . $crlf . $txt['coppa_form_date'] . ':' . $crlf . $crlf . $crlf . replaceBasicActionUrl($txt['coppa_form_body']); |
|
231
|
|
|
$data = str_replace(['{PARENT_NAME}', '{CHILD_NAME}', '{USER_NAME}', '<br />', '<br />'], [$ul, $ul, $member['member_name'], $crlf, $crlf], $data); |
|
232
|
|
|
|
|
233
|
|
|
// Send the headers. |
|
234
|
|
|
Headers::instance() |
|
235
|
|
|
->removeHeader('all') |
|
236
|
|
|
->header('Content-Encoding', 'none') |
|
237
|
|
|
->header('Pragma', 'no-cache') |
|
238
|
|
|
->header('Cache-Control', 'no-cache') |
|
239
|
|
|
->header('Connection', 'close') |
|
240
|
|
|
->header('Content-Disposition', 'attachment; filename="approval.txt"') |
|
241
|
|
|
->contentType('application/octet-stream', '') |
|
242
|
|
|
->sendHeaders(); |
|
243
|
|
|
|
|
244
|
|
|
echo $data; |
|
245
|
|
|
|
|
246
|
|
|
obExit(false, false); |
|
247
|
|
|
} |
|
248
|
|
|
} |
|
249
|
|
|
|
|
250
|
|
|
/** |
|
251
|
|
|
* Handle the Children's Online Privacy Protection Act (COPPA) for member registration. |
|
252
|
|
|
* |
|
253
|
|
|
* This method sets the necessary variables in the global $context for displaying the COPPA page. |
|
254
|
|
|
* |
|
255
|
|
|
* @return void |
|
256
|
|
|
*/ |
|
257
|
|
|
private function handleCoppa(): void |
|
258
|
|
|
{ |
|
259
|
|
|
global $context, $modSettings, $txt; |
|
260
|
|
|
|
|
261
|
|
|
$context += [ |
|
262
|
|
|
'page_title' => $txt['coppa_title'], |
|
263
|
|
|
'sub_template' => 'coppa', |
|
264
|
|
|
]; |
|
265
|
|
|
|
|
266
|
|
|
$context['coppa'] = [ |
|
267
|
|
|
'body' => str_replace('{MINIMUM_AGE}', $modSettings['coppaAge'], replaceBasicActionUrl($txt['coppa_after_registration'])), |
|
268
|
|
|
'many_options' => !empty($modSettings['coppaPost']) && !empty($modSettings['coppaFax']), |
|
269
|
|
|
'post' => empty($modSettings['coppaPost']) ? '' : $modSettings['coppaPost'], |
|
270
|
|
|
'fax' => empty($modSettings['coppaFax']) ? '' : $modSettings['coppaFax'], |
|
271
|
|
|
'phone' => empty($modSettings['coppaPhone']) ? '' : str_replace('{PHONE_NUMBER}', $modSettings['coppaPhone'], $txt['coppa_send_by_phone']), |
|
272
|
|
|
'id' => $this->_req->query->member, |
|
273
|
|
|
]; |
|
274
|
|
|
} |
|
275
|
|
|
|
|
276
|
|
|
/** |
|
277
|
|
|
* It prepares credit and copyright information for the credits page or the admin page. |
|
278
|
|
|
* |
|
279
|
|
|
* - Accessed by ?action=who;sa=credits |
|
280
|
|
|
* |
|
281
|
|
|
* @uses Who language file |
|
282
|
|
|
* @uses template_credits() sub template in Who.template, |
|
283
|
|
|
*/ |
|
284
|
|
|
public function action_credits(): void |
|
285
|
|
|
{ |
|
286
|
|
|
global $context, $txt; |
|
287
|
|
|
|
|
288
|
|
|
require_once(SUBSDIR . '/About.subs.php'); |
|
289
|
|
|
Txt::load('About'); |
|
290
|
|
|
|
|
291
|
|
|
$context += prepareCreditsData(); |
|
292
|
|
|
|
|
293
|
|
|
theme()->getTemplates()->load('About'); |
|
294
|
|
|
$context['sub_template'] = 'credits'; |
|
295
|
|
|
$context['robot_no_index'] = true; |
|
296
|
|
|
$context['page_title'] = $txt['credits']; |
|
297
|
|
|
} |
|
298
|
|
|
} |
|
299
|
|
|
|