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() |
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() |
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() |
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(); |
185
|
|
|
} |
186
|
|
|
else |
187
|
|
|
{ |
188
|
|
|
$this->handleCoppa(); |
189
|
|
|
} |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* Handle the contact form for the forum. |
194
|
|
|
* |
195
|
|
|
* This method allows for the viewing or downloading of the COPPA form. |
196
|
|
|
* Accessed by action=about;sa=coppa;form;dl;member= and action=about;sa=coppa;form;member= |
197
|
|
|
* |
198
|
|
|
* @return void |
199
|
|
|
*/ |
200
|
|
|
private function handleContactForm() |
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() |
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() |
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
|
|
|
} |