Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

reset_password.php

Zuletzt modifiziert: 02.04.2025, 15:02 - Dateigröße: 12.20 KiB


001  <?php
002  /**
003  *
004  * This file is part of the phpBB Forum Software package.
005  *
006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
007  * @license GNU General Public License, version 2 (GPL-2.0)
008  *
009  * For full copyright and license information, please see
010  * the docs/CREDITS.txt file.
011  *
012  */
013   
014  namespace phpbb\ucp\controller;
015   
016  use phpbb\auth\auth;
017  use phpbb\config\config;
018  use phpbb\controller\helper;
019  use phpbb\db\driver\driver_interface;
020  use phpbb\event\dispatcher;
021  use phpbb\exception\http_exception;
022  use phpbb\language\language;
023  use phpbb\log\log_interface;
024  use phpbb\passwords\manager;
025  use phpbb\request\request_interface;
026  use phpbb\template\template;
027  use phpbb\user;
028  use Symfony\Component\HttpFoundation\Response;
029   
030  /**
031  * Handling forgotten passwords via reset password functionality
032  */
033  class reset_password
034  {
035      /** @var config */
036      protected $config;
037   
038      /** @var driver_interface */
039      protected $db;
040   
041      /** @var dispatcher */
042      protected $dispatcher;
043   
044      /** @var helper */
045      protected $helper;
046   
047      /** @var language */
048      protected $language;
049   
050      /** @var log_interface */
051      protected $log;
052   
053      /** @var manager */
054      protected $passwords_manager;
055   
056      /** @var request_interface */
057      protected $request;
058   
059      /** @var template */
060      protected $template;
061   
062      /** @var user */
063      protected $user;
064   
065      /** @var array phpBB DB table names */
066      protected $users_table;
067   
068      /** @var string phpBB root path */
069      protected $root_path;
070   
071      /** @var string PHP extension */
072      protected $php_ext;
073   
074      /**
075       * Reset password controller constructor.
076       *
077       * @param config $config
078       * @param driver_interface $db
079       * @param dispatcher $dispatcher
080       * @param helper $helper
081       * @param language $language
082       * @param log_interface $log
083       * @param manager $passwords_manager
084       * @param request_interface $request
085       * @param template $template
086       * @param user $user
087       * @param string $users_table
088       * @param string $root_path
089       * @param string $php_ext
090       */
091      public function __construct(config $config, driver_interface $db, dispatcher $dispatcher, helper $helper,
092                                  language $language, log_interface $log, manager $passwords_manager,
093                                  request_interface $request, template $template, user $user, string $users_table,
094                                  string $root_path, string $php_ext)
095      {
096          $this->config = $config;
097          $this->db = $db;
098          $this->dispatcher = $dispatcher;
099          $this->helper = $helper;
100          $this->language = $language;
101          $this->log = $log;
102          $this->passwords_manager = $passwords_manager;
103          $this->request = $request;
104          $this->template = $template;
105          $this->user = $user;
106          $this->users_table = $users_table;
107          $this->root_path = $root_path;
108          $this->php_ext = $php_ext;
109      }
110   
111      /**
112       * Init controller
113       */
114      protected function init_controller()
115      {
116          $this->language->add_lang('ucp');
117   
118          if (!$this->config['allow_password_reset'])
119          {
120              throw new http_exception(Response::HTTP_OK, 'UCP_PASSWORD_RESET_DISABLED', [
121                  '<a href="mailto:' . htmlspecialchars($this->config['board_contact'], ENT_COMPAT) . '">',
122                  '</a>'
123              ]);
124          }
125      }
126   
127      /**
128       * Remove reset token for specified user
129       *
130       * @param int $user_id User ID
131       */
132      protected function remove_reset_token(int $user_id)
133      {
134          $sql_ary = [
135              'reset_token'                => '',
136              'reset_token_expiration'    => 0,
137          ];
138   
139          $sql = 'UPDATE ' . $this->users_table . '
140                      SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . '
141                      WHERE user_id = ' . $user_id;
142          $this->db->sql_query($sql);
143      }
144   
145      /**
146       * Handle password reset request
147       *
148       * @return Response
149       */
150      public function request()
151      {
152          $this->init_controller();
153   
154          $submit        = $this->request->is_set_post('submit');
155          $username    = $this->request->variable('username', '', true);
156          $email        = strtolower($this->request->variable('email', ''));
157   
158          add_form_key('ucp_reset_password');
159   
160          if ($submit)
161          {
162              if (!check_form_key('ucp_reset_password'))
163              {
164                  throw new http_exception(Response::HTTP_UNAUTHORIZED, 'FORM_INVALID');
165              }
166   
167              if (empty($email))
168              {
169                  return $this->helper->message('NO_EMAIL_USER');
170              }
171   
172              $sql_array = [
173                  'SELECT'    => 'user_id, username, user_permissions, user_email, user_jabber, user_notify_type, user_type,'
174                                  . ' user_lang, user_inactive_reason, reset_token, reset_token_expiration',
175                  'FROM'        => [$this->users_table => 'u'],
176                  'WHERE'        => "user_email = '" . $this->db->sql_escape($email) . "'" .
177                      (!empty($username) ? " AND username_clean = '" . $this->db->sql_escape(utf8_clean_string($username)) . "'" : ''),
178              ];
179   
180              /**
181               * Change SQL query for fetching user data
182               *
183               * @event core.ucp_remind_modify_select_sql
184               * @var    string    email        User's email from the form
185               * @var    string    username    User's username from the form
186               * @var    array    sql_array    Fully assembled SQL query with keys SELECT, FROM, WHERE
187               * @since 3.1.11-RC1
188               * @changed 3.3.0-b1 Moved to reset password controller
189               */
190              $vars = [
191                  'email',
192                  'username',
193                  'sql_array',
194              ];
195              extract($this->dispatcher->trigger_event('core.ucp_remind_modify_select_sql', compact($vars)));
196   
197              $sql = $this->db->sql_build_query('SELECT', $sql_array);
198              $result = $this->db->sql_query_limit($sql, 2); // don't waste resources on more rows than we need
199              $rowset = $this->db->sql_fetchrowset($result);
200              $this->db->sql_freeresult($result);
201   
202              if (count($rowset) > 1)
203              {
204                  $this->template->assign_vars([
205                      'USERNAME_REQUIRED'    => true,
206                      'EMAIL'                => $email,
207                  ]);
208              }
209              else
210              {
211                  $message = $this->language->lang('PASSWORD_RESET_LINK_SENT') . '<br /><br />' . $this->language->lang('RETURN_INDEX', '<a href="' . append_sid("{$this->root_path}index.{$this->php_ext}") . '">', '</a>');
212   
213                  if (empty($rowset))
214                  {
215                      return $this->helper->message($message);
216                  }
217   
218                  $user_row = $rowset[0];
219   
220                  if ($user_row['user_type'] == USER_IGNORE || $user_row['user_type'] == USER_INACTIVE)
221                  {
222                      return $this->helper->message($message);
223                  }
224   
225                  // Do not create multiple valid reset tokens
226                  if (!empty($user_row['reset_token']) && (int) $user_row['reset_token_expiration'] >= time())
227                  {
228                      return $this->helper->message($message);
229                  }
230   
231                  // Check users permissions
232                  $auth = new auth();
233                  $auth->acl($user_row);
234   
235                  if (!$auth->acl_get('u_chgpasswd'))
236                  {
237                      return $this->helper->message($message);
238                  }
239   
240                  // Generate reset token
241                  $reset_token = strtolower(gen_rand_string(32));
242   
243                  $sql_ary = [
244                      'reset_token'                => $reset_token,
245                      'reset_token_expiration'    => $this->user::get_token_expiration(),
246                  ];
247   
248                  $sql = 'UPDATE ' . $this->users_table . '
249                      SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . '
250                      WHERE user_id = ' . $user_row['user_id'];
251                  $this->db->sql_query($sql);
252   
253                  if (!class_exists('messenger'))
254                  {
255                      include($this->root_path . 'includes/functions_messenger.' . $this->php_ext);
256                  }
257   
258                  /** @var \messenger $messenger */
259                  $messenger = new \messenger(false);
260   
261                  $messenger->template('user_forgot_password', $user_row['user_lang']);
262   
263                  $messenger->set_addresses($user_row);
264   
265                  $messenger->anti_abuse_headers($this->config, $this->user);
266   
267                  $messenger->assign_vars([
268                          'USERNAME'            => html_entity_decode($user_row['username'], ENT_COMPAT),
269                          'U_RESET_PASSWORD'    => generate_board_url(true) . $this->helper->route('phpbb_ucp_reset_password_controller', [
270                              'u'        => $user_row['user_id'],
271                              'token'    => $reset_token,
272                          ], false)
273                  ]);
274   
275                  $messenger->send(NOTIFY_EMAIL);
276   
277                  return $this->helper->message($message);
278              }
279          }
280   
281          $this->template->assign_vars([
282              'USERNAME'                    => $username,
283              'EMAIL'                        => $email,
284              'U_RESET_PASSWORD_ACTION'    => $this->helper->route('phpbb_ucp_forgot_password_controller'),
285          ]);
286   
287          return $this->helper->render('ucp_reset_password.html', $this->language->lang('RESET_PASSWORD'));
288      }
289   
290      /**
291       * Handle controller requests
292       *
293       * @return Response
294       */
295      public function reset()
296      {
297          $this->init_controller();
298   
299          $submit            = $this->request->is_set_post('submit');
300          $reset_token    = $this->request->variable('token', '');
301          $user_id        = $this->request->variable('u', 0);
302   
303          if (empty($reset_token))
304          {
305              return $this->helper->message('NO_RESET_TOKEN');
306          }
307   
308          if (!$user_id)
309          {
310              return $this->helper->message('NO_USER');
311          }
312   
313          add_form_key('ucp_reset_password');
314   
315          $sql_array = [
316              'SELECT'    => 'user_id, username, user_permissions, user_email, user_jabber, user_notify_type, user_type,'
317                  . ' user_lang, user_inactive_reason, reset_token, reset_token_expiration',
318              'FROM'        => [$this->users_table => 'u'],
319              'WHERE'        => 'user_id = ' . $user_id,
320          ];
321   
322          /**
323           * Change SQL query for fetching user data
324           *
325           * @event core.ucp_reset_password_modify_select_sql
326           * @var    int    user_id        User ID from the form
327           * @var    string    reset_token Reset token
328           * @var    array    sql_array    Fully assembled SQL query with keys SELECT, FROM, WHERE
329           * @since 3.3.0-b1
330           */
331          $vars = [
332              'user_id',
333              'reset_token',
334              'sql_array',
335          ];
336          extract($this->dispatcher->trigger_event('core.ucp_reset_password_modify_select_sql', compact($vars)));
337   
338          $sql = $this->db->sql_build_query('SELECT', $sql_array);
339          $result = $this->db->sql_query_limit($sql, 1);
340          $user_row = $this->db->sql_fetchrow($result);
341          $this->db->sql_freeresult($result);
342   
343          $message = $this->language->lang('RESET_TOKEN_EXPIRED_OR_INVALID') . '<br /><br />' . $this->language->lang('RETURN_INDEX', '<a href="' . append_sid("{$this->root_path}index.{$this->php_ext}") . '">', '</a>');
344   
345          if (empty($user_row))
346          {
347              return $this->helper->message($message);
348          }
349   
350          if (!hash_equals($reset_token, $user_row['reset_token']))
351          {
352              return $this->helper->message($message);
353          }
354   
355          if ($user_row['reset_token_expiration'] < time())
356          {
357              $this->remove_reset_token($user_id);
358   
359              return $this->helper->message($message);
360          }
361   
362          $errors = [];
363   
364          if ($submit)
365          {
366              if (!check_form_key('ucp_reset_password'))
367              {
368                  return $this->helper->message('FORM_INVALID');
369              }
370   
371              if ($user_row['user_type'] == USER_IGNORE || $user_row['user_type'] == USER_INACTIVE)
372              {
373                  return $this->helper->message($message);
374              }
375   
376              // Check users permissions
377              $auth = new auth();
378              $auth->acl($user_row);
379   
380              if (!$auth->acl_get('u_chgpasswd'))
381              {
382                  return $this->helper->message($message);
383              }
384   
385              if (!function_exists('validate_data'))
386              {
387                  include($this->root_path . 'includes/functions_user.' . $this->php_ext);
388              }
389   
390              $data = [
391                  'new_password'        => $this->request->untrimmed_variable('new_password', '', true),
392                  'password_confirm'    => $this->request->untrimmed_variable('new_password_confirm', '', true),
393              ];
394              $check_data = [
395                  'new_password'        => [
396                      ['string', false, $this->config['min_pass_chars'], 0],
397                      ['password'],
398                  ],
399                  'password_confirm'    => ['string', true, $this->config['min_pass_chars'], 0],
400              ];
401              $errors = array_merge($errors, validate_data($data, $check_data));
402              if (strcmp($data['new_password'], $data['password_confirm']) !== 0)
403              {
404                  $errors[] = $data['password_confirm'] ? 'NEW_PASSWORD_ERROR' : 'NEW_PASSWORD_CONFIRM_EMPTY';
405              }
406              if (empty($errors))
407              {
408                  $sql_ary = [
409                      'user_password'                => $this->passwords_manager->hash($data['new_password']),
410                      'user_passchg'                => time(),
411                      'user_login_attempts'        => 0,
412                      'reset_token'                => '',
413                      'reset_token_expiration'    => 0,
414                  ];
415                  $sql = 'UPDATE ' . $this->users_table . '
416                              SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . '
417                              WHERE user_id = ' . (int) $user_row['user_id'];
418                  $this->db->sql_query($sql);
419                  $this->user->reset_login_keys($user_row['user_id']);
420                  $this->log->add('user', $user_row['user_id'], $this->user->ip, 'LOG_USER_NEW_PASSWORD', false, [
421                      'reportee_id' => $user_row['user_id'],
422                      $user_row['username']
423                  ]);
424                  meta_refresh(3, append_sid("{$this->root_path}index.{$this->php_ext}"));
425                  return $this->helper->message($this->language->lang('PASSWORD_RESET'));
426              }
427          }
428   
429          $this->template->assign_vars([
430              'PASSWORD_RESET_ERRORS'        => !empty($errors) ? array_map([$this->language, 'lang'], $errors) : '',
431              'S_IS_PASSWORD_RESET'        => true,
432              'U_RESET_PASSWORD_ACTION'    => $this->helper->route('phpbb_ucp_reset_password_controller'),
433              'L_CHANGE_PASSWORD_EXPLAIN'    => $this->language->lang($this->config['pass_complex'] . '_EXPLAIN', $this->language->lang('CHARACTERS', (int) $this->config['min_pass_chars'])),
434              'S_HIDDEN_FIELDS'            => build_hidden_fields([
435                  'u'        => $user_id,
436                  'token'    => $reset_token,
437              ]),
438          ]);
439   
440          return $this->helper->render('ucp_reset_password.html', $this->language->lang('RESET_PASSWORD'));
441      }
442  }
443