elkarte /
Elkarte
| 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') |
||||
|
0 ignored issues
–
show
Bug
Best Practice
introduced
by
Loading history...
|
|||||
| 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(); |
||||
|
0 ignored issues
–
show
It seems like you do not handle an error condition for
ob_end_clean(). This can introduce security issues, and is generally not recommended.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
|
|||||
| 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 |