Xataface  2.0alpha2
Xataface Application Framework
 All Data Structures Namespaces Files Functions Variables Groups Pages
forgot_password.php
Go to the documentation of this file.
1 <?php
3  public static $TABLE_RESET_PASSWORD = 'dataface__reset_password';
4  public static $EX_MULTIPLE_USERS_WITH_SAME_EMAIL = 500;
5  public static $EX_NO_USERS_WITH_EMAIL = 501;
6  public static $EX_NO_EMAIL_COLUMN_FOUND = 502;
7  public static $EX_NO_USERNAME_COLUMN_FOUND = 504;
8  public static $EX_NO_USERNAME_FOR_USER = 503;
9  public static $EX_NO_SUCH_UUID = 505;
10  public static $EX_USER_NOT_FOUND = 506;
11  public static $EX_NO_EMAIL_FOR_USER = 507;
12  public static $EX_NO_USERS_FOUND_WITH_USERNAME = 508;
14 
15  function handle($params){
16 
17 
19  $query =& $app->getQuery();
21  $jt->import('forgot_password.js');
22 
23  try {
24  if ( isset($query['--uuid']) ){
25  // A uuid was supplied,
26  $res = $this->reset_password_with_uuid($query['--uuid']);
27  if ( $res ){
28  df_display(array(), 'xataface/forgot_password/password_has_been_reset.html');
29  exit;
30  } else {
31  throw new Exception("Failed to reset password for uuid ".$query['--uuid']);
32  }
33 
34  } else if ( isset($query['--email']) ){
35 
36  $this->send_reset_email_for_email($query['--email']);
37  if ( @$query['--format'] == 'json' ){
38  $this->response(array(
39  'code'=>200,
40  'message'=>'An email has been sent to the provided email address with instructions for resetting your password.'
41  ));
42  exit;
43  } else {
44  df_display(array(), 'xataface/forgot_password/sent_email.html');
45  exit;
46  }
47 
48 
49  } else if ( isset($query['--username']) ){
50 
51  $this->send_reset_email_for_username($query['--username']);
52  if ( @$query['--format'] == 'json' ){
53  $this->response(array(
54  'code'=>200,
55  'message'=> 'An email has been sent to the email on file for this user account with instructions for resetting the password.'
56  ));
57  exit;
58  } else {
59  df_display(array(), 'xataface/forgot_password/sent_email.html');
60  exit;
61  }
62 
63 
64  } else {
65 
66 
67  df_display(array(), 'xataface/forgot_password/form.html');
68  exit;
69  }
70  } catch ( Exception $ex ){
71 
72  if ( @$query['--format'] == 'json' ){
73  $this->response(array(
74  'code'=>$ex->getCode(),
75  'message'=>$ex->getMessage()
76  ));
77  exit;
78  } else {
79  df_display(array('error'=>$ex->getMessage()), 'xataface/forgot_password/form.html');
80  }
81 
82  }
83 
84 
85 
86  }
87 
88 
89  function response($p){
90  header('Content-type: application/json; charset="'.Dataface_Application::getInstance()->_conf['oe'].'"');
91  echo json_encode($p);
92 
93  }
94 
100  $res = mysql_query("create table if not exists `{$table}` (
101  request_id int(11) auto_increment primary key,
102  request_uuid binary(32),
103  username varchar(255),
104  request_ip int(11),
105  date_created datetime,
106  expires int(11),
107  key (request_uuid) )", df_db());
108  if ( !$res ) throw new Exception(mysql_error(df_db()));
109 
110  }
111 
112 
116  function clear_expired(){
118  $res = mysql_query("delete from `{$table}` where expires < ".time(), df_db());
119  if ( !$res ) throw new Exception(mysql_error(df_db()));
120 
121 
122 
123  }
124 
125 
126  function send_reset_email_for_username($username){
128  $usernameCol = $auth->usernameColumn;
129  if ( !$usernameCol ) throw new Exception("No username Column found in the users table. Please specify one using the username_column directive in the [_auth] section of the conf.ini file.", self::$EX_NO_EMAIL_COLUMN_FOUND);
130 
131  $people = df_get_records_array($auth->usersTable, array($usernameCol => '='.$username));
132  if ( !$people ) throw new Exception("No account found with that username", self::$EX_NO_USERS_FOUND_WITH_USERNAME);
133  if ( count($people) > 1 ){
134  throw new Exception("Multiple users found with same username", self::$EX_MULTIPLE_USERS_WITH_SAME_USERNAME);
135 
136  } else {
137 
138  $this->send_reset_email_for_user($people[0]);
139 
140  }
141 
142  }
143 
144 
145 
146 
158  function send_reset_email_for_email($email){
160  $emailCol = $auth->getEmailColumn();
161  if ( !$emailCol ) throw new Exception("No Email Column found in the users table. Please specify one using the email_column directive in the [_auth] section of the conf.ini file.", self::$EX_NO_EMAIL_COLUMN_FOUND);
162 
163  $people = df_get_records_array($auth->usersTable, array($emailCol => '='.$email));
164  if ( !$people ) throw new Exception("No account found with that email address", self::$EX_NO_USERS_WITH_EMAIL);
165  if ( count($people) > 1 ){
166  throw new Exception("Multiple users found with same email address", self::$EX_MULTIPLE_USERS_WITH_SAME_EMAIL);
167 
168  } else {
169  $this->send_reset_email_for_user($people[0]);
170 
171  }
172 
173 
174  }
175 
189  $emailCol = $auth->getEmailColumn();
190  $usernameCol = $auth->usernameColumn;
191 
192  if ( !$emailCol ) throw new Exception("No Email Column found in the users table. Please specify one using the email_column directive in the [_auth] section of the conf.ini file.", self::$EX_NO_EMAIL_COLUMN_FOUND);
193  if ( !$usernameCol ) throw new Exception("No username column found in the users table. Please specify one using the username_column directive in the [_auth] section of the conf.ini file.", self::$EX_NO_USERNAME_COLUMN_FOUND);
194  if ( !$user ) throw new Exception("Cannot send email for null user", self::$EX_NO_USERS_FOUND_WITH_EMAIL);
195 
196 
197  $username = $user->val($usernameCol);
198  if ( !$username ){
199  throw new Exception("Cannot reset password for user without a username", self::$EX_NO_USERNAME_FOR_USER);
200  }
201 
202  $email = $user->val($emailCol);
203  if ( !$email ) throw new Exception("User has not email address on file", $EX_NO_EMAIL_FOR_USER);
204 
205 
206  $ip = null;
207  $val = ip2long($_SERVER['REMOTE_ADDR']);
208  if ( $val !== false ){
209  $ip = sprintf('%u', $val );
210  }
211 
212  // Insert the entry
215  $sql = "insert into `{$table}`
216  (`request_uuid`, `username`, `request_ip`, `date_created`, `expires`)
217  values
218  (UUID(),'".addslashes($username)."','".addslashes($ip)."', NOW(), ".(time()+600).")";
219  $res = mysql_query($sql, df_db());
220  if ( !$res ) throw new Exception(mysql_error(df_db()));
221  $id = mysql_insert_id(df_db());
222 
223  $res = mysql_query("select * from `{$table}` where request_id='".addslashes($id)."'", df_db());
224  if ( !$res ) throw new Exception(mysql_error(df_db()));
225 
226  $row = mysql_fetch_assoc($res);
227  if ( !$row ) throw new Exception("Failed to fetch reset password request row from database after it has been inserted. This should never happen ... must be a bug");
228 
229  $uuid = $row['request_uuid'];
230  if ( !$uuid ) throw new Exception("Blank uuid for the reset request. This should never happen. Must be a bug.");
231 
232  $url = df_absolute_url(DATAFACE_SITE_HREF.'?-action=forgot_password&--uuid='.$uuid);
233  $site_url = df_absolute_url(DATAFACE_SITE_URL);
234 
235  $msg = <<<END
236 You have requested to reset the password for the user '$username'.
237 Please go to the URL below in order to proceed with resetting your password:
238 <$url>
239 
240 If you did not make this request, please disregard this email.
241 END;
242 
243  $subject = 'Password Reset';
244 
245 
246  $del = $app->getDelegate();
247  $info = array();
248  if ( isset($del) and method_exists($del, 'getResetPasswordEmailInfo') ){
249  $info = $del->getResetPasswordEmailInfo($user, $url);
250  }
251 
252  if ( isset($info['subject']) ) $subject = $info['subject'];
253  if ( isset($info['message']) ) $msg = $info['message'];
254  $parameters = null;
255  if ( isset($info['parameters']) ) $parameters = $info['parameters'];
256 
257 
258 
259  $site_title = $app->getSiteTitle();
260  $support_email = $_SERVER['SERVER_ADMIN'];
261  if ( isset($app->_conf['admin_email']) ) $support_email = $app->_conf['admin_email'];
262  if ( isset($app->_conf['support_email']) ) $support_email = $app->_conf['support_email'];
263 
264 
265  $headers = 'From: '.$site_title.' <'.$support_email.'>'."\r\nReply-to: ".$site_title." <".$support_email.">";
266  if ( isset($info['headers']) ) $headers = $info['headers'];
267  //echo "Subject: $subject \nEmail: $email \n$msg \nHeaders: $headers";exit;
268  if ( @$app->_conf['_mail']['func'] ) $func = $app->_conf['_mail']['func'];
269  else $func = 'mail';
270  $res = $func($email,
271  $subject,
272  $msg,
273  $headers,
274  $parameters);
275  if ( !$res ){
276  throw new Exception('Failed to send activation email. Please try again later.', DATAFACE_E_ERROR);
277  } else {
278  //echo "Successfully sent mail to $email";exit;
279  return true;
280  }
281 
282 
283 
284  }
285 
286 
287 
288  public function reset_password_with_uuid($uuid){
291 
293  $this->clear_expired();
295  $res = mysql_query("select * from `{$table}` where request_uuid='".addslashes($uuid)."' limit 1", df_db());
296  if ( !$res ) throw new Exception(mysql_error(df_db()));
297  $row = mysql_fetch_assoc($res);
298  if ( !$row ) throw new Exception("No such reset request could be found", self::$EX_NO_SUCH_UUID);
299 
300  if ( !$row['username'] ){
301  throw new Exception("Attempt to reset password for user with null username", self::$EX_NO_USERNAME_FOR_USER);
302 
303  }
304  $username = $row['username'];
305 
306 
307 
308 
309  @mysql_free_result($res);
310 
311 
312 
313  // now that we have the username, let's reset the password.
314  //$rand = strval(rand())."".$uuid;
315  $rand = md5($uuid);
316  error_log("Rand is ".$rand);
317  $pw = '';
318  for ( $i=0; $i<=16; $i+=2 ){
319  $pw .= $rand{$i};
320  }
321  $password = $pw;
322  //error_log("Password is $password");
323  $user = df_get_record($auth->usersTable, array($auth->usernameColumn => '='.$username));
324  if ( !$user ){
325  throw new Exception("No user account found with that username", self::$EX_USER_NOT_FOUND);
326 
327  }
328  $emailColumn = $auth->getEmailColumn();
329  if ( !$emailColumn ) throw new Exception("No email column found in the users table", self::$EX_NO_EMAIL_COLUMN_FOUND);
330  $email = $user->val($emailColumn);
331 
332  if ( !$email ){
333  throw new Exception("User has account has no email address on record. Please contact support to reset the password", self::$EX_NO_EMAIL_FOR_USER);
334 
335  }
336 
337 
338  $user->setValue($auth->passwordColumn, $password);
339  $res = $user->save();
340  if ( PEAR::isError($res) ){
341  throw new Exception($res->getMessage());
342  }
343 
344 
345  // Let's delete this request from the password reset requests.
346  $this->delete_request_with_uuid($uuid);
347 
348  // Now let's send the email.
349  $del = $app->getDelegate();
350  $info = array();
351  if ( isset($del) and method_exists($del, 'getPasswordChangedEmailInfo') ){
352  $info = $del->getPasswordChangedEmailInfo($user, $password);
353  }
354 
355  $subject = 'Password Changed';
356  if ( isset($info['subject']) ) $subject = $info['subject'];
357 
358 
359  $site_url = df_absolute_url(DATAFACE_SITE_HREF);
360 
361  $msg = <<<END
362 Your new temporary password is
363 $password
364 
365 You can change your password as follows:
366 
367 1. Log in with your temporary password at <$site_url?-action=login>
368 2. Click on the "My Profile" link in the upper right of the page
369 3. Click on the "Edit" tab.
370 4. Change your password in the edit form and click "Save" when done.
371 END;
372 
373  if ( isset($info['message']) ) $msg = $info['message'];
374 
375  $parameters = null;
376  if ( isset($info['parameters']) ) $parameters = $info['parameters'];
377 
378 
379 
380  $site_title = $app->getSiteTitle();
381  $support_email = $_SERVER['SERVER_ADMIN'];
382  if ( isset($app->_conf['admin_email']) ) $support_email = $app->_conf['admin_email'];
383  if ( isset($app->_conf['support_email']) ) $support_email = $app->_conf['support_email'];
384 
385  $headers = 'From: '.$site_title.' <'.$support_email.'>'."\r\nReply-to: ".$site_title." <".$support_email.">";
386  if ( isset($info['headers']) ) $headers = $info['headers'];
387 
388 
389  if ( @$app->_conf['_mail']['func'] ) $func = $app->_conf['_mail']['func'];
390  else $func = 'mail';
391  $res = $func($email,
392  $subject,
393  $msg,
394  $headers,
395  $parameters);
396  if ( !$res ){
397  return PEAR::raiseError('Failed to send activation email. Please try again later.', DATAFACE_E_ERROR);
398  } else {
399  return true;
400  }
401 
402 
403 
404 
405  }
406 
407  function delete_request_with_uuid($uuid){
409  $res = mysql_query("delete from `{$table}` where request_uuid='".addslashes($uuid)."' limit 1", df_db());
410  if ( !$res ) throw new Exception(mysql_error(df_db()));
411 
412  }
413 }