Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
page_password_reset.inc
1 <?php
17 require_once SQ_CORE_PACKAGE_PATH.'/page/page.inc';
18 require_once SQ_FUDGE_PATH.'/general/text.inc';
19 require_once SQ_LIB_PATH.'/html_form/html_form.inc';
20 
33 {
34 
42  var $default_state = 'request';
43 
44 
53  function __construct($assetid=0)
54  {
55  $this->_ser_attrs = TRUE;
56  parent::__construct($assetid);
57 
58  }//end constructor
59 
60 
75  function create(&$link)
76  {
77  // Set default value for email format attr
78  $val = Array();
79  $val['subject'] = translate('cms_password_reset_email_subject');
80  $val['text_format'] = translate('cms_password_reset_email_msg', '%asset_attribute_username%', '%password_reset_url%');
81  $val['html_format'] = '<p>'.translate('cms_password_reset_email_msg', '%asset_attribute_username%', '<a href="%password_reset_url%">%password_reset_url%</a>').'</p>';
82  $val['from'] = SQ_CONF_SYSTEM_NAME.' <'.SQ_CONF_DEFAULT_EMAIL.'>';
83  $this->setAttrVAlue('request_email_format', $val);
84 
85  return parent::create($link);
86 
87  }//end create()
88 
89 
98  function _createAdditional(&$link)
99  {
100  if (!parent::_createAdditional($link)) return FALSE;
101 
102  // Add a group of users
103  $GLOBALS['SQ_SYSTEM']->am->includeAsset('user_group');
104  $group_link = Array('asset' => &$this, 'link_type' => SQ_LINK_TYPE_2, 'is_dependant' => 1, 'is_exclusive' => 1, 'value' => 'pending_accounts');
105 
106  $group = new User_Group();
107 
108  $group->setAttrValue('name', translate('cms_password_reset_pending_group'));
109  if (!$group->create($group_link)) return FALSE;
110  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($group);
111 
112  // Add a bodycopy to this page when creating
113  $GLOBALS['SQ_SYSTEM']->am->includeAsset('bodycopy');
114  $copy_link = Array('asset' => &$this, 'link_type' => SQ_LINK_TYPE_2, 'is_dependant' => 1, 'is_exclusive' => 1, 'value' => '');
115 
116  foreach ($this->_getBodycopies() as $value => $details) {
117  $bodycopy = new Bodycopy();
118  $copy_link['value'] = $value;
119 
120  $bodycopy->setAttrValue('name', $details['name']);
121  unset($details['name']);
122  if (!$bodycopy->create($copy_link, $details)) {
123  return FALSE;
124  }
125  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($bodycopy);
126  }
127  return TRUE;
128 
129  }//end _createAdditional()
130 
131 
139  function _getAllowedLinks()
140  {
141  $allowed_links = parent::_getAllowedLinks();
142 
143  $allowed_links[SQ_LINK_TYPE_2]['bodycopy'] = Array('card' => count($this->_getBodycopies()), 'exclusive' => TRUE);
144  $allowed_links[SQ_LINK_TYPE_2]['user_group'] = Array('card' => '1', 'exclusive' => TRUE);
145 
146  return $allowed_links;
147 
148  }//end _getAllowedLinks()
149 
150 
157  function printBody()
158  {
159  // Since we are going a lot of changes here, tie the paint and process
160  // together using db2
161  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
162 
163  $password_reset_action = $this->default_state;
164  if (isset($_REQUEST['action'])) { // Handle form submission.
165  $password_reset_action = $_REQUEST['action'];
166  }
167  echo $this->_printContents($password_reset_action);
168 
169  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
170 
171  }//end printBody()
172 
173 
184  function onRequestKeywords(&$broadcaster, $vars=Array())
185  {
186  if (!isset($vars['keywords'])) return;
187 
188  // which bodycopy?
189  $parents = $GLOBALS['SQ_SYSTEM']->am->getParents($broadcaster->id, 'bodycopy', TRUE);
190  $type_links = $GLOBALS['SQ_SYSTEM']->am->getLinks($this->id, SQ_LINK_TYPE_2, 'bodycopy');
191  foreach ($type_links as $link_info) {
192  if (isset($parents[$link_info['minorid']])) {
193  $bodycopy_type = $link_info['value'];
194  }
195  }
196 
197  // Make sure this is a bodycopy we can replace keywords for...?
198  if (!isset($bodycopy_type) || empty($bodycopy_type)) {
199  return;
200  }
201  if (!in_array($bodycopy_type, array_keys($this->_getBodycopies()))) {
202  return;
203  }
204 
205  // Generate the name of the function we should call for keywords
206  $tmp_type = strtr($bodycopy_type, '_', ' ');
207  $tmp_type = ucwords($tmp_type);
208  $tmp_type = preg_replace('/\s+/', '', $tmp_type);
209  $type_func = '_get'.$tmp_type.'Keywords';
210 
211  if (method_exists($this, $type_func)) {
212  $vars['keywords'] = array_merge($vars['keywords'], $this->$type_func());
213  }
214 
215  }//end onRequestKeywords()
216 
217 
226  function _printContents($action)
227  {
228  if (empty($action)) $action = $this->default_state;
229 
230  // Generate the name of the function we should call for processing
231  $tmp_process = strtr($action, '_', ' ');
232  $tmp_process = ucwords($tmp_process);
233  $tmp_process = preg_replace('/\s+/', '', $tmp_process);
234  $process_func = '_print'.$tmp_process.'Action';
235 
236  if (method_exists($this, $process_func)) {
237  return $this->$process_func();
238  }
239  return;
240 
241  }//end _printContents()
242 
243 
254  {
255  $replacements['password_reset_error'] = '';
256 
257  return $this->_buildContents('request', $replacements);
258 
259  }//end _printRequestAction()
260 
261 
273  {
274  $replacements = Array();
275  if (!isset($_POST['username']) || empty($_POST['username'])) {
276  $replacements['password_reset_error'] = translate('cms_password_reset_message_empty_username');
277  return $this->_buildContents('request', $replacements);
278  } else {
279  $username = $_POST['username'];
280  $auth_folder = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('authentication_folder');
281  if (is_null($auth_folder)) {
282  trigger_localised_error('SYS0249', E_USER_ERROR);
283  return Array();
284  }
285  $auth_systems = $auth_folder->getAuthSystems();
286 
287  $user = NULL;
288  foreach ($auth_systems as $systemid) {
289  $system = $GLOBALS['SQ_SYSTEM']->am->getAsset($systemid);
290  if (is_null($system)) continue;
291 
292  if (method_exists($system, 'locateUser')) {
293  $user = $system->locateUser($username);
294  if (!is_null($user) && $user->canLogin()) {
295  break;
296  }
297  }
298  }
299 
300  $failure = FALSE;
301  if (is_null($user)) {
302  $failure = TRUE;
303  // Shall we tell that the given user doesn't exits?
304  if ($this->attr('invalid_user_error')) {
305  $replacements['password_reset_error'] = translate('cms_password_reset_message_invalid_username');
306  return $this->_buildContents('request', $replacements);
307  }
308 
309  } else {
310  foreach ($user->getAvailableKeywords() as $keyword => $description) {
311  $replacements[$keyword] = $user->getKeywordReplacement($keyword);
312  }
313  $user_hash = $this->_createResetLink($user->id);
314  if (!$user_hash) $failure = TRUE;
315  }
316 
317  // Do not attempt to send mail to anyone if we're not going to go ahead with this, especially
318  // if we did't create any link!
319  if (!$failure) {
320  $email_replacements = $replacements;
321  $email_replacements['password_reset_url'] = current_url().'?action=reset&prid='.$user_hash;
322 
323  $email_attr = $this->getAttribute('request_email_format');
324  $email_value = unserialize($email_attr->value);
325  $email_value['to'][] = $user->attr('email');
326  $email_attr->value = serialize($email_value);
327 
328  @$email_attr->sendMail($email_replacements);
329  }
330 
331  }//end else
332 
333  return $this->_buildContents('request_receipt', $replacements);
334 
335  }//end _printRequestReceiptAction()
336 
337 
348  function _printResetAction()
349  {
350  $replacements = Array();
351  $replacements['password_reset_error'] = '';
352 
353  $action = 'request';
354 
355  if (!isset($_REQUEST['prid']) || empty($_REQUEST['prid'])) {
356  $replacements['password_reset_error'] = translate('cms_password_reset_message_no_prid');
357  } else {
358  $prid = $_REQUEST['prid'];
359  $user_link = $this->_getResetLink($prid);
360  if (empty($user_link)) {
361  $replacements['password_reset_error'] = translate('cms_password_reset_message_invalid_prid');
362  } else {
363  $userid = $user_link['minorid'];
364  $user = $GLOBALS['SQ_SYSTEM']->am->getAsset($userid);
365  if (is_null($user)) {
366  $replacements['password_reset_error'] = translate('cms_password_reset_message_no_user');
367  } else {
368  foreach ($user->getAvailableKeywords() as $keyword => $description) {
369  $replacements[$keyword] = $user->getKeywordReplacement($keyword);
370  }
371  $action = 'reset';
372  }
373  }
374  }
375  return $this->_buildContents($action, $replacements);
376 
377  }//end _printResetAction()
378 
379 
391  {
392  $replacements = Array();
393  $replacements['password_reset_error'] = '';
394 
395  $action = 'request';
396 
397  if (!isset($_POST['password']) || empty($_POST['password'])) {
398  $replacements['password_reset_error'] = translate('cms_password_reset_message_empty_password');
399  } else if (!isset($_REQUEST['prid']) || empty($_REQUEST['prid'])) {
400  $replacements['password_reset_error'] = translate('cms_password_reset_message_no_prid');
401  } else {
402  $password_parts = array_unique($_POST['password']);
403 
404  $prid = $_REQUEST['prid'];
405  $user_link = $this->_getResetLink($prid);
406  if (empty($user_link)) {
407  $replacements['password_reset_error'] = translate('cms_password_reset_message_invalid_prid');
408  } else {
409  $userid = $user_link['minorid'];
410  $user = $GLOBALS['SQ_SYSTEM']->am->getAsset($userid);
411  if (is_null($user)) {
412  $replacements['password_reset_error'] = translate('cms_password_reset_message_no_user');
413  } else {
414  foreach ($user->getAvailableKeywords() as $keyword => $description) {
415  $replacements[$keyword] = $user->getKeywordReplacement($keyword);
416  }
417  $action = 'reset';
418  }
419  }
420  if (count($password_parts) == 1) {
421  if ($this->_resetPassword($user, reset($password_parts))) {
422  // The password was reset sucessfully!
423  $action = 'reset_receipt';
424  } else {
425  $replacements['password_reset_error'] = translate('cms_password_reset_message_generic_password_error');
426  }
427  } else {
428  $replacements['password_reset_error'] = translate('cms_password_reset_message_different_passwords');
429  }
430  }
431 
432  $field = '';
433  if (isset($prid)) {
434  ob_start();
435  hidden_field('prid', $prid);
436  $field = ob_get_clean();
437  }
438  return $this->_buildContents($action, $replacements, $field);
439 
440  }//end _printResetReceiptAction()
441 
442 
453  function _buildContents($action, $new_replacements=Array(), $extra='')
454  {
455  $replacements = Array();
456 
457  ob_start();
458  $bodycopy = $this->_getBodycopy($action);
459  $keywords = $bodycopy->getKeywords();
460 
461  foreach ($keywords as $keyword) {
462  if (!in_array($keyword, array_keys($new_replacements))) {
463  $replacements[$keyword] = $this->getKeywordReplacement($keyword);
464  } else {
465  $replacements[$keyword] = $new_replacements[$keyword];
466  }
467  }
468  $bodycopy->setKeywordReplacements($replacements);
469  $bodycopy->printBody();
470 
471  echo $extra;
472 
473  if (in_array($action, Array('request', 'reset'))) {
474  return $this->_buildForm(ob_get_clean(), $action.'_receipt');
475  }
476  return ob_get_clean();
477 
478  }//end _buildContents()
479 
480 
493  function _buildForm($body_contents, $action)
494  {
495  ob_start();
496  ?><form id="<?php echo $this->getPrefix() ?>_<?php echo $action; ?>_form" method="post" action="<?php echo htmlentities(replace_query_string_vars(Array())); ?>" enctype="multipart/form-data">
497  <?php echo hidden_field('action', $action); ?>
498  <?php echo $body_contents; ?>
499  </form><?php
500  return ob_get_clean();
501 
502  }//end _buildForm()
503 
504 
514  function _resetPassword(&$user, $new_password)
515  {
516  $GLOBALS['SQ_SYSTEM']->setRunLevel(SQ_RUN_LEVEL_FORCED);
517  $result = @$user->setAttrValue('password', $new_password);
518 
519  if ($result) {
520  $user->saveAttributes();
521 
522  $parentid = $this->_getPendingAccountsGroupId();
523  if ($parentid == 0) return FALSE;
524 
525  $parent = $GLOBALS['SQ_SYSTEM']->am->getAsset($parentid, 'user_group');
526  if (is_null($parent)) return FALSE;
527 
528  // Remove this user completly from our pending reset group.
529  $links = $GLOBALS['SQ_SYSTEM']->am->getLinkByAsset($parentid, $user->id, SQ_LINK_TYPE_1, NULL, 'major', TRUE);
530  foreach ($links as $link) {
531  $parent->deleteLink($link['linkid']);
532  }
533  }
534  $GLOBALS['SQ_SYSTEM']->restoreRunLevel();
535 
536  // There should probably be an attribute that turns this functionality on/off.
537  $GLOBALS['SQ_SYSTEM']->loginUser($user);
538 
539  return $result;
540 
541  }//end _resetPassword()
542 
543 
555  function _createResetLink($assetid)
556  {
557  if (empty($assetid)) return FALSE;
558 
559  // The user asset.
560  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
561  if (is_null($asset)) return FALSE;
562 
563  $parentid = $this->_getPendingAccountsGroupId();
564  if ($parentid == 0) return FALSE;
565 
566  // The user group asset.
567  $parent = $GLOBALS['SQ_SYSTEM']->am->getAsset($parentid, 'user_group');
568  if (is_null($parent)) return FALSE;
569 
570  $GLOBALS['SQ_SYSTEM']->setRunLevel(SQ_RUN_LEVEL_FORCED);
571  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
572 
573  // That's right, delete any existing links.
574  $links = $GLOBALS['SQ_SYSTEM']->am->getLinkByAsset($parent->id, $assetid, SQ_LINK_TYPE_1, NULL, 'major', TRUE);
575  foreach ($links as $link) {
576  $GLOBALS['SQ_SYSTEM']->am->deleteAssetLink($link['linkid']);
577  }
578 
579  $hash_value = MD5(implode('::', Array($this->id, $asset->id, $asset->name, (time() * rand()))));
580 
581  $return_value = FALSE;
582  if ($parent->createLink($asset, SQ_LINK_TYPE_1, $hash_value)) {
583  $return_value = $hash_value;
584  }
585 
586  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
587  $GLOBALS['SQ_SYSTEM']->restoreRunLevel();
588 
589 
590  return $return_value;
591 
592  }//end _createResetLink()
593 
594 
606  function _getResetLink($value)
607  {
608  if (empty($value)) return Array();
609 
610  $parentid = $this->_getPendingAccountsGroupId();
611  if ($parentid == 0) return FALSE;
612 
613  // This should return just the one link hopefully, otherwise we're in trouble ($value is a hash
614  // and should be very unique).
615  return $GLOBALS['SQ_SYSTEM']->am->getLink($parentid, SQ_LINK_TYPE_1, '', FALSE, $value);
616 
617  }//end _getResetLink()
618 
619 
627  {
628  $keywords = Array();
629 
630  $keywords['submit_button'] = 'The submit button';
631  $keywords['password_reset_error'] = 'Error messages';
632 
633  return $keywords;
634 
635  }//end _getStandardKeywords()
636 
637 
645  {
646  $keywords = $this->_getStandardKeywords();
647 
648  $keywords['username_input'] = 'The input field for username';
649 
650  return $keywords;
651 
652  }//end _getRequestKeywords()
653 
654 
662  {
663  $keywords = $this->_getStandardKeywords();
664 
665  return $keywords;
666 
667  }//end _getRequestReceiptKeywords()
668 
669 
676  function _getResetKeywords()
677  {
678  $keywords = $this->_getStandardKeywords();
679 
680  $keywords['password_input'] = 'The input fields for password reset (new and confirmation password input fields)';
681  $keywords['password_new'] = 'Input field for the new password';
682  $keywords['password_confirmation'] = 'Input field for the Confirmation of the new password';
683 
684  return $keywords;
685 
686  }//end _getResetKeywords()
687 
688 
696  {
697  $keywords = $this->_getStandardKeywords();
698 
699  return $keywords;
700 
701  }//end _getResetReceiptKeywords()
702 
703 
711  {
712  $value = '';
713  if (isset($_POST['username'])) {
714  $value = $_POST['username'];
715  }
716 
717  ob_start();
718  text_box('username', '');
719  return ob_get_clean();
720 
721  }//end getUsernameInputKeywordReplacement()
722 
723 
731  {
732  ob_start();
733  password_box('password[]');
734  password_box('password[]');
735  return ob_get_clean();
736 
737  }//end getPasswordInputKeywordReplacement()
738 
739 
747  {
748  ob_start();
749  password_box('password[]');
750  return ob_get_clean();
751 
752  }//end getPasswordNewKeywordReplacement()
753 
754 
762  {
763  ob_start();
764  password_box('password[]');
765  return ob_get_clean();
766 
767  }//end getPasswordConfirmationKeywordReplacement()
768 
769 
777  {
778  ob_start();
779  submit_button('', translate('submit'));
780  return ob_get_clean();
781 
782  }//end getSubmitButtonKeywordReplacement()
783 
784 
792  {
793  $link = $GLOBALS['SQ_SYSTEM']->am->getLink($this->id, SQ_LINK_TYPE_2, 'user_group', FALSE, 'pending_accounts');
794  if (empty($link)) return 0;
795 
796  return $link['minorid'];
797 
798  }//end _getPendingAccountsGroupId()
799 
800 
809  function &_getBodycopy($link_value)
810  {
811  $null = NULL;
812 
813  $bodycopy_data = $GLOBALS['SQ_SYSTEM']->am->getLink($this->id, SQ_LINK_TYPE_2, 'bodycopy', TRUE, $link_value, 'major', '1');
814  if (empty($bodycopy_data)) $null;
815 
816  $bodycopy = $GLOBALS['SQ_SYSTEM']->am->getAsset($bodycopy_data['minorid'], $bodycopy_data['minor_type_code']);
817  if (is_null($bodycopy)) $null;
818 
819  return $bodycopy;
820 
821  }//end _getBodycopy()
822 
823 
830  function _getBodycopies()
831  {
832  $res = Array();
833  $res['request']['name'] = translate('cms_password_reset_request');
834  $res['request']['content'] = '<p>%password_reset_error%</p><p>'.translate('cms_password_reset_request_msg').'</p><p>%username_input% %submit_button% </p>';
835 
836  $res['request_receipt']['name'] = translate('cms_password_reset_request_receipt');
837  $res['request_receipt']['content'] = '<p>'.translate('cms_password_reset_request_receipt_msg').'</p>';
838 
839  $res['reset']['name'] = translate('cms_password_reset_reset');
840  $res['reset']['content'] = '<p>%password_reset_error%</p><p>'.translate('cms_password_reset_reset_msg').'</p><p>%password_input%&nbsp;%submit_button%</p>';
841 
842  $res['reset_receipt']['name'] = translate('cms_password_reset_reset_receipt');
843  $res['reset_receipt']['content'] = '<p>'.translate('cms_password_reset_reset_receipt_msg').'</p>';
844 
845  return $res;
846 
847  }//end _getBodycopies()
848 
849 
850 }//end class