Sponsorenverwaltung - Team StarCraft e.V.
 All Data Structures Files Functions Variables
functions_usercake.php
Go to the documentation of this file.
1 <?php
2  /**
3  * @file functions_usercake.php
4  *
5  * @brief This file provides almost all functions used for the usermanagement.
6  *
7  * @details
8  * This file provides the vast majority of functions used for usermanagement
9  * and its interaction with the sponsormanagement part.
10  *
11  * For more details please consider reading the documentation of the certain
12  * function you're interestend in.
13  *
14  * This file is based on funcs.php from UserCake Version: 2.0.2
15  * with modifications by Alexander Vorndran and Daniel Seichter
16  *
17  * This file depends on inc/common.php and inc/libs/usercake/config_usercake.php.
18  *
19  * @copyright 2013, Team StarCraft e.V.
20  * @version 1.0.0
21  * @author Usercake (http://usercake.com)
22  * @author Alexander Vorndran
23  * @author Daniel Seichter
24  * @date 02.07.2013
25  */
26 
27  //Functions that do not interact with DB
28  //------------------------------------------------------------------------------
29 
30  /**
31  * Retrieve a list of all .php files in languages
32  * @return array an array that contains the name of all language files in languages
33  * @author Usercake (http://usercake.com)
34  */
35  function getLanguageFiles() {
36  $directory = ABS_PATH."inc/libs/usercake/languages/";
37  $languages = glob($directory . "*.php");
38  //print each file name
39  return $languages;
40  }
41 
42  /**
43  * Retrieve a list of all .css files in site-templates
44  * @return array an array that contains the names of all css-files in site-templates
45  * @author Usercake (http://usercake.com)
46  */
47  function getTemplateFiles() {
48  $directory = ABS_PATH."inc/libs/usercake/site-templates/";
49  $languages = glob($directory . "*.css");
50  //print each file name
51  return $languages;
52  }
53 
54  /**
55  * Retrieve a list of all .php files in root files folder
56  * @return array an array that contains the names
57  * @author Usercake (http://usercake.com)
58  */
59  function getPageFiles() {
60  $directory = "";
61  $pages = glob($directory . "*.php");
62  //print each file name
63  foreach ($pages as $page) {
64  $row[$page] = $page;
65  }
66  return $row;
67  }
68 
69  /**
70  * Destroy a session as part of logout
71  * @param string $name the name of the session variable that should be unset
72  * @author Usercake (http://usercake.com)
73  */
74  function destroySession($name) {
75  if (isset($_SESSION[$name])) {
76  $_SESSION[$name] = NULL;
77  unset($_SESSION[$name]);
78  session_unset();
79  session_destroy();
80  }
81  }
82 
83  /**
84  * Generate a unique code
85  * @param string $length the length of the generated unique code
86  * @return string the generated unique code
87  * @author Usercake (http://usercake.com)
88  */
89  function getUniqueCode($length = "") {
90  $code = hash('sha256', uniqid(rand(), true));
91  if ($length != "") {
92  return substr($code, 0, $length);
93  } else {
94  return $code;
95  }
96  }
97 
98  /**
99  * Generate an activation key
100  * @return string the generated alphanumeric activation token
101  * @author Usercake (http://usercake.com)
102  */
104  $gen = "";
105  do {
106  $gen = md5(uniqid(mt_rand(), false));
107  } while (validateActivationToken($gen));
108  return $gen;
109  }
110 
111  /**
112  * Generates a hash from the given password using bcrypt with a random salt.
113  * If salt is NULL the salt from the given hash is used.
114  * @param mixed $password the password to hash
115  * @param mixed $hash [optional]
116  * - the hash to compare against
117  * - Default: NULL in this case a random salt is generated
118  * @param integer $rounds [optional]
119  * - how often the hashing algorithm should be repeated
120  * - Default: WORKING_FACTOR
121  * @see config_usercake.php
122  * @return mixed the hash for the given password
123  * if it's less then 13 characters an error occurred
124  * @author Alexander Vorndran
125  */
126  function generateImprovedHash($password, $hash = NULL, $rounds = WORKING_FACTOR) {
127  if (function_exists('openssl_random_pseudo_bytes')) {
128  // using openssl generator if possible
129  if ($hash === NULL) {
130  $random = bin2hex(openssl_random_pseudo_bytes(32));
131  $salt = substr(md5(uniqid($random, true)), 0, 22);
132  return crypt($password, sprintf('$2y$%02d$', $rounds) . $salt);
133  } else {
134  return crypt($password, $hash);
135  }
136  } else {
137  if ($hash === NULL) {
138  $salt = substr(md5(uniqid(rand(), true)), 0, 22);
139  return crypt($password, sprintf('$2y$%02d$', $rounds) . $salt);
140  } else {
141  return crypt($password, $hash);
142  }
143  }
144  }
145 
146  /**
147  * Inputs language strings from selected language.
148  * @param string $key The key of the language string in the corresponding language file
149  * @param array $markers Replacements for gaps in the language string
150  * @return string the language string for the key with replacements
151  * @author Usercake (http://usercake.com)
152  */
153  function lang($key, $markers = NULL) {
154  global $lang;
155  $key = strtoupper($key);
156  if ($markers == NULL) {
157  $str = $lang[$key];
158  } else {
159  //Replace any dyamic markers
160  $str = $lang[$key];
161  $iteration = 1;
162  foreach ($markers as $marker) {
163  $str = str_replace("%m" . $iteration . "%", $marker, $str);
164  $iteration++;
165  }
166  }
167  //Ensure we have something to return
168  if ($str == "") {
169  return ("No language key found");
170  } else {
171  return $str;
172  }
173  }
174 
175  /**
176  * Checks if a (trimed) string is within a min and max length
177  * @param integer $min the minimal length
178  * @param integer $max the maximal length
179  * @param string $what the string to check
180  * @return boolean
181  * - FALSE if the string is within min and max length
182  * - TRUE if not
183  * @author Usercake (http://usercake.com)
184  */
185  function minMaxRange($min, $max, $what) {
186  if (strlen(trim($what)) < $min)
187  return true;
188  else if (strlen(trim($what)) > $max)
189  return true;
190  else
191  return false;
192  }
193 
194  /**
195  * Replaces hooks with specified text
196  * @param string $str the string containing the detault hooks
197  * @return string the input string with the default replacements
198  * @author Usercake (http://usercake.com)
199  */
200  function replaceDefaultHook($str) {
202  return (str_replace($default_hooks, $default_replace, $str));
203  }
204 
205  /**
206  * Makes the string lowercase, removes trailing/leading whitespace and strips tags
207  * @param string $str input string
208  * @return string the sanitized string
209  * @author Usercake (http://usercake.com)
210  */
211  function sanitize($str) {
212  return strtolower(strip_tags(trim(($str))));
213  }
214 
215 
216  /**
217  * Prepares first- and lastname to be used as usernames
218  * e.g. replaces whitespace with '-'
219  * @param string $str the input string
220  * @return string the modified input string
221  * @author Alexander Vorndran
222  */
223  function prepareNamesForUsername($str) {
224  $result = trim($str);
225 
226  // replace Umlaute
227  $result = str_replace('ü', 'ue', $result);
228  $result = str_replace('Ü', 'Ue', $result);
229  $result = str_replace('ä', 'ae', $result);
230  $result = str_replace('Ä', 'Ae', $result);
231  $result = str_replace('ö', 'oe', $result);
232  $result = str_replace('Ö', 'Oe', $result);
233  $result = preg_replace("/(ò|ó)/", "o", $result);
234  $result = preg_replace("/(Ò|Ó)/", "O", $result);
235  $result = preg_replace("/(á|à)/", "a", $result);
236  $result = preg_replace("/(Á|À)/", "A", $result);
237  $result = preg_replace("/ß/", "ss", $result);
238  $result = preg_replace(array("(ú|ù)","(Ú|Ù)"), array("u","U"), $result);
239  $result = preg_replace(array("(é|è)","(É|È)"), array("e","E"), $result);
240  $result = preg_replace(array('(í|ì)','(Í|Ì)'), array('i','I'), $result);
241 
242  // replace all remaining non-alphanumerical chars
243  $result = preg_replace("/[^A-Za-z0-9\.-_]/", "", $result);
244 
245  // replace whitespace
246  $pattern = "\s{1,}";
247  $result = strtolower(preg_replace("/$pattern/", "-", $result));
248 
249  return $result;
250  }
251 
252  /**
253  * Prepares names for the database e.g. removes trailing and leading
254  * whitespace, reduces multiple whitespace to a single one and so on
255  * @param string $name the name to prepare
256  * @return string the prepared version of the input
257  * @author Alexander Vorndran
258  */
259  function prepareNameForDatabase($name) {
260  // remove trailing and leading whitespace
261  $result = trim($name);
262 
263  // replace multiple whitespace with a single one
264  $pattern = "\s{1,}";
265  $result = preg_replace("/$pattern/", " ", $result);
266 
267  // replace all characters that are not alphabetical or whitespace with ''
268  $pattern = "[^A-Za-z _\-üÜäÄöÖòóÒÓáàÁÀAéèÉÈíìÍÌúùÚÙ\'\.ß]";
269  $result = preg_replace("/$pattern/", '', $result);
270  $pattern = "('|\"){1,}";
271  $result = preg_replace("/$pattern/", "'", $result);
272 
273  return $result;
274  }
275 
276  /**
277  * Checks whether the name only contains alphabetical values and
278  * values that might be allowed by prepare... functions
279  * @param string $name the name to check
280  * @return boolean
281  * - TRUE if the name is valid
282  * - FALSE if not
283  * @author Alexander Vorndran
284  */
285  function isValidName($name) {
286  $pattern = "[A-Za-z _\-üÜäÄöÖòóÒÓáàÁÀAéèÉÈíìÍÌúùÚÙ\'\.ß]{1,}";
287  return (preg_match("/$pattern$/", $name)==1);
288  }
289 
290  /**
291  * Generate a unique session id
292  * @return string an unique session-id to identify a session
293  * @author Alexander Vorndran
294  */
295  function generateSessionId() {
296  $sessionId = "";
297  do {
298  $sessionId = hash('sha1', uniqid(mt_rand(), true));
299  } while(sessionIdExists($sessionId)===TRUE);
300  return $sessionId;
301  }
302 
303  /**
304  * Checks if a sessionid exists in the database
305  * @param string $sessionId
306  * @return boolean
307  * - TRUE if the sessionid exists
308  * - FALSE if not
309  * @author Alexander Vorndran
310  */
311  function sessionIdExists($sessionId) {
312  if(ctype_alnum($sessionId)) {
313  global $mysqli, $db;
314  $qry = "SELECT id
315  FROM ". $db['users'] . "
316  WHERE session_id = ?";
317  $stmt = $mysqli->prepare($qry);
318  $stmt->bind_param("s", $sessionId);
319  $stmt->execute();
320  $stmt->store_result();
321  $numrows = $stmt->num_rows;
322  $stmt->close();
323  if($numrows > 0 || $numrows === FALSE) {
324  return true;
325  } else {
326  return false;
327  }
328  }
329  }
330 
331  //Functions that interact mainly with users table
332  //------------------------------------------------------------------------------
333 
334  /**
335  * Marks a defined array of users as deleted
336  * @param array $userId the ids of the users
337  * @return mixed
338  * - On success: number of successfull deletions
339  * - On failure: FALSE
340  * @author Usercake (http://usercake.com)
341  * @author Alexander Vorndran
342  */
343  function deleteUsers($userId) {
344  // this action is only for administrators
345  if(isUserAdministrator()) {
346  global $mysqli, $db,$loggedInUser;
347  $i = 0;
348  $stmt = $mysqli->prepare(
349  "UPDATE " . $db['users'] . "
350  SET `password` = 'deleted', `valid_email` = -1, `activation_token` = 'deleted',
351  `last_activation_request` = 'deleted', `active` = -1, `last_sign_in_stamp` = UNIX_TIMESTAMP()
352  WHERE id = ?");
353  $stmt2 = $mysqli->prepare("DELETE FROM " . $db['user_permission'] . "
354  WHERE user_id = ?");
355  foreach ($userId as $id) {
356  // the user can only be deleted if he is not the root user
357  if ($id <> DEFAULT_ADMIN_ACCOUNT) {
358  // only the root and admins can delete accounts
359  if(isUserAdministrator()||$loggedInUser->userId==DEFAULT_ADMIN_ACCOUNT) {
360  $stmt->bind_param("i", $id);
361  $stmt->execute();
362  $stmt2->bind_param("i", $id);
363  $stmt2->execute();
364  $i++;
365  } else {
366  // forbidden action
367  return -1;
368  }
369  } else {
370  // forbidden action
371  return -1;
372  }
373  }
374  $stmt->close();
375  $stmt2->close();
376  return $i;
377  } else {
378  // forbidden action
379  return -1;
380  }
381  }
382 
383  /**
384  * Delete a defined array of users permanentaly
385  * Permits deletion if the user is responsible for changes
386  * @param array $users the array of users that should be deleted from the database
387  * @return mixed
388  * - On success: number of successful deletions
389  * - On failure: FALSE
390  * @author Alexander Vorndran
391  */
392  function deleteUsersPermanently($users) {
393  // this action is only for administrators
394  if(isUserAdministrator()) {
395  global $mysqli, $db,$errors;
396  $i = 0;
397  $stmt = $mysqli->prepare("DELETE FROM " . $db['users'] . "
398  WHERE id = ?");
399  $stmt2 = $mysqli->prepare("DELETE FROM " . $db['user_permission'] . "
400  WHERE user_id = ?");
401  foreach ($users as $id) {
402  // the user can only be deleted if he is not the root user
403  if ($id <> DEFAULT_ADMIN_ACCOUNT) {
404  // only the root can delete accounts permanentaly
405  if(isUserRoot()) {
406  $numref = countUserReferences($id);
407  if(countUserReferences($id)==0) {
408  $stmt->bind_param("i", $id);
409  $stmt->execute();
410  $stmt2->bind_param("i", $id);
411  $stmt2->execute();
412  $i++;
413  } else {
414  if($numref==1) {
415  $errors[] = "Der Benutzer ". fetchUsername($id)." ist noch für eine Änderung verantwortlich.";
416  } else {
417  $errors[] = "Der Benutzer ". fetchUsername($id)." ist noch für ".$numref." Änderungen verantwortlich.";
418  }
419 
420  }
421  } else {
422  // forbidden action
423  $errors[] = "Sie verfügen nicht über die notwendigen Rechte.";
424 // return -1;
425  }
426  } else {
427  // forbidden action
428 // return -1;
429  }
430  }
431  $stmt->close();
432  $stmt2->close();
433  return $i;
434  } else {
435  // forbidden action
436  return -1;
437  }
438  }
439 
440  /**
441  * Sets the autoincrement value for user ids to 1000
442  * @author Alexander Vorndran
443  */
444  function setUserIDIncrement() {
445  global $mysqli, $db;
446  $sql = "ALTER TABLE `" . $db['users'] . "` AUTO_INCREMENT = 1000";
447  $stmt = $mysqli->prepare($sql);
448  if (is_object($stmt)) {
449  $stmt->execute();
450  $stmt->close();
451  }
452  }
453 
454  /**
455  * Check if an email exists in the DB
456  * @param string $email The email-address to check
457  * @author Usercake (http://usercake.com)
458  */
459  function emailExists($email) {
460  global $mysqli, $db;
461  $stmt = $mysqli->prepare("SELECT active
462  FROM " . $db['users'] . "
463  WHERE
464  email = ?
465  LIMIT 1");
466  $stmt->bind_param("s", $email);
467  $stmt->execute();
468  $stmt->store_result();
469  $num_returns = $stmt->num_rows;
470  $stmt->close();
471 
472  if ($num_returns > 0) {
473  return true;
474  } else {
475  return false;
476  }
477  }
478 
479  /**
480  * Check whether a mobile number is already in the database
481  * @param string $mobile the mobile number to check
482  * @return boolean true if the mobile is in the database already false otherwise
483  * @author Alexander Vorndran
484  */
485  function mobileExists($mobile) {
486  global $mysqli, $db;
487  $stmt = $mysqli->prepare("SELECT active
488  FROM " . $db['users'] . "
489  WHERE
490  mobile = ?
491  LIMIT 1");
492  $stmt->bind_param("s", $mobile);
493  $stmt->execute();
494  $stmt->store_result();
495  $num_returns = $stmt->num_rows;
496  $stmt->close();
497 
498  if ($num_returns > 0) {
499  return true;
500  } else {
501  return false;
502  }
503  }
504 
505  /**
506  * Check if a user name and email belong to the same user
507  * @param string $email the email-address of the user
508  * @param string $username the username of the user
509  * @return boolean
510  * - TRUE if username and email-address belong to the same user
511  * - FALSE else
512  */
513  function emailUsernameLinked($email, $username) {
514  global $mysqli, $db;
515  $stmt = $mysqli->prepare("SELECT active
516  FROM " . $db['users'] . "
517  WHERE user_name = ?
518  AND
519  email = ?
520  LIMIT 1
521  ");
522  $stmt->bind_param("ss", $username, $email);
523  $stmt->execute();
524  $stmt->store_result();
525  $num_returns = $stmt->num_rows;
526  $stmt->close();
527 
528  if ($num_returns > 0) {
529  return true;
530  } else {
531  return false;
532  }
533  }
534 
535  /**
536  * Retrieve information for all users
537  * @return mixed
538  * - an array containig all the users and their details
539  * - FALSE on failure
540  */
541  function fetchAllUsers() {
542  global $mysqli, $db;
543  $stmt = $mysqli->prepare("SELECT
544  id,
545  user_name,
546  first_name,
547  last_name,
548  password,
549  email,
550  activation_token,
551  last_activation_request,
552  lost_password_request,
553  active,
554  title,
555  sign_up_stamp,
556  last_sign_in_stamp
557  FROM " . $db['users']);
558  $stmt->execute();
559  $stmt->bind_result($id, $user, $first, $last, $password, $email, $token,
560  $activationRequest, $passwordRequest, $active, $title, $signUp, $signIn);
561 
562  while ($stmt->fetch()) {
563  $row[] = array('id' => $id, 'username' => $user, 'firstname' => $first,
564  'lastname' => $last, 'password' => $password, 'email' => $email,
565  'activation_token' => $token, 'lastActivationRequest' => $activationRequest,
566  'lostPasswordRequest' => $passwordRequest, 'active' => $active,
567  'title' => htmlspecialchars_decode($title), 'signUpStamp' => $signUp,
568  'lastSignInStamp' => $signIn);
569  }
570  $stmt->close();
571  return ($row);
572  }
573 
574  /**
575  * Retrieve complete user information by username, token or ID
576  * @param string $username
577  * @param string $token
578  * @param integer $userId
579  * @return mixed
580  * - an array containing the userdetails
581  * - FALSE if an error occurred
582  */
583  function fetchUserDetails($username = NULL, $token = NULL, $userId = NULL) {
584  if ($username != NULL) {
585  $column = "user_name";
586  $data = $username;
587  } elseif ($token != NULL) {
588  $column = "activation_token";
589  $data = $token;
590  } elseif ($userId != NULL) {
591  $column = "id";
592  $data = $userId;
593  } else {
594  return FALSE;
595  }
596  global $mysqli, $db;
597  $stmt = $mysqli->prepare("SELECT
598  id,
599  user_name,
600  first_name,
601  last_name,
602  password,
603  email,
604  mobile,
605  activation_token,
606  last_activation_request,
607  lost_password_request,
608  active,
609  valid_email,
610  title,
611  sign_up_stamp,
612  last_sign_in_stamp
613  FROM " . $db['users'] . "
614  WHERE
615  $column = ?
616  LIMIT 1");
617  $stmt->bind_param("s", $data);
618 
619  $stmt->execute();
620  $stmt->bind_result($userId, $user, $first, $last, $password, $email,
621  $mobile, $token, $activationRequest, $passwordRequest, $active,
622  $validEmail, $title, $signUp, $signIn);
623  while ($stmt->fetch()) {
624  $row = array('id' => $userId, 'username' => $user, 'firstname' => $first,
625  'lastname' => $last, 'password' => $password, 'email' => $email,
626  'mobile' => $mobile, 'activation_token' => $token,
627  'lastActivationRequest' => $activationRequest,
628  'lostPasswordRequest' => $passwordRequest,
629  'active' => $active, 'valid_email'=> $validEmail, 'title' => htmlspecialchars_decode($title),
630  'signUpStamp' => $signUp, 'lastSignInStamp' => $signIn);
631  }
632  $stmt->close();
633  if (isset($row)) {
634  return $row;
635  } else {
636  return FALSE;
637  }
638  }
639 
640  /**
641  * Fetches the username for a given userid
642  * @param integer $userId the userid of the user
643  * @return string
644  * - the username if the user exists
645  * - ' - ' if not
646  * - FALSE on failure
647  */
648  function fetchUsername($userId) {
649  global $db, $mysqli;
650  $qry = "SELECT user_name
651  FROM ". $db['users'] . "
652  WHERE id = ?";
653  $stmt = $mysqli->prepare($qry);
654  $stmt->bind_param('i',$userId);
655  $stmt->execute();
656  $stmt->bind_result($uname);
657  while ($stmt->fetch()) {
658  $username =$uname;
659  }
660  return !empty($username) ? $username : ' - ';
661  }
662 
663  /**
664  * Returns the session that is saved in the database
665  * @param integer $user_id identifies the user from whom we want to get the stored session
666  * @return mixed
667  * - returns the alphanumerical session id of the user
668  * - FALSE on failure
669  */
670  function getStoredSession($user_id) {
671  if (isset($user_id)) {
672  global $mysqli, $db;
673  $stmt = $mysqli->prepare("
674  SELECT session_id
675  FROM " . $db['users'] . "
676  WHERE id = ?
677  LIMIT 1
678  ");
679  $stmt->bind_param("i", $user_id) || fail('MySQL bind_param', $mysqli->error);
680  $stmt->bind_result($storedSession) || fail('MySQL bind_result', $mysqli->error);
681  $stmt->execute() || fail('MySQL execute', $mysqli->error);
682  if ($stmt->fetch()) {
683  $retval = $storedSession;
684  }
685  $stmt->close();
686 
687  /* @var $storedSession String */
688  return $retval;
689  } else {
690  return FALSE;
691  }
692  }
693 
694  /**
695  * Toggle lost password request flag on or off
696  * @param integer $userId the id of the user
697  * @param integer $value the value of the password flag
698  * - 0 nothing
699  * - 1 open password request
700  * - -1 user has received a temporary password
701  * - -2 user has used his temporary password
702  * - -3 the user has not changed his password but logged out
703  * @return mixed
704  * - 1 on success
705  * - FALSE on failure
706  * @author Usercake (http://www.usercake.com)
707  * @author Alexander Vorndran
708  */
709  function flagPassword($userId, $value) {
710  global $mysqli, $db;
711  $stmt = $mysqli->prepare("UPDATE " . $db['users'] . "
712  SET lost_password_request = ?
713  WHERE
714  id = ?
715  LIMIT 1
716  ");
717  $stmt->bind_param("ii", $value, $userId);
718  $result = $stmt->execute();
719  $stmt->close();
720  return $result;
721  }
722 
723  /**
724  * Check if the current user is logged in if his session isn't valid any more destroy it
725  * @return boolean
726  * - TRUE if the user is logged in
727  * - FALSE if not
728  * @author Alexander Vorndran
729  */
730  function isUserLoggedIn() {
731  global $loggedInUser, $mysqli, $db;
732  $stmt = $mysqli->prepare("SELECT
733  id,
734  password
735  FROM " . $db['users'] . "
736  WHERE
737  id = ?
738  AND
739  password = ?
740  AND
741  session_id = ?
742  AND
743  active = 1
744  LIMIT 1");
745  $stmt->bind_param("iss", $loggedInUser->userId, $loggedInUser->passwordHash, $loggedInUser->sessionId);
746  $stmt->execute();
747  $stmt->store_result();
748  $num_returns = $stmt->num_rows;
749  $stmt->close();
750 
751  if ($loggedInUser == NULL) {
752  return false;
753  } else {
754  if ($num_returns > 0) {
755  //if (!hasSessionTimedOut($loggedInUser->user_id)||true) {
756  if($loggedInUser->sessionId == getStoredSession($loggedInUser->userId)) {
757  // session is still valid, renew timestamp
758  $loggedInUser->updateLastActivity();
759  return true;
760  } else {
761  // session isn't valid any more, log the user out
762  $loggedInUser->userLogOut();
763  return false;
764  }
765  } else {
766  destroySession("userCakeUser");
767  return false;
768  }
769  }
770  }
771 
772  /**
773  * Checks if the current user is an administrator
774  * @return boolean
775  * - TRUE if he is an administrator
776  * - FALSE if not
777  * @author Alexander Vorndran
778  */
779  function isUserAdministrator() {
780  global $loggedInUser, $mysqli, $db;
781  if (isUserLoggedIn()) {
782  if(isUserRoot()) {
783  return true;
784  } else {
785  $adminPermission = ADMIN_PERMISSION;
786  $stmt = $mysqli->prepare("SELECT COUNT(
787  id)
788  FROM " . $db['user_permission'] . "
789  WHERE
790  user_id = ?
791  AND
792  permission_id = ?");
793  $stmt->bind_param("ii", $loggedInUser->userId, $adminPermission);
794  $stmt->execute();
795  $stmt->bind_result($count);
796  if ($stmt->fetch()) {
797  $retval = $count;
798  }
799  $stmt->close();
800  if (isset($retval)) {
801  if ($retval > 0) { // one (or more) entries -> administrator
802  return true;
803  } else {
804  return false;
805  }
806  } else {
807  fail("Überprüfung konnte nicht ausgeführt werden.");
808  return false;
809  }
810  }
811  } else {
812  return false;
813  }
814  }
815 
816  /**
817  * Checks if the current user is the root-user
818  * @return boolean
819  * - TRUE if yes
820  * - FALSE if not
821  * @author Alexander Vorndran
822  */
823  function isUserRoot() {
824  if(isUserLoggedIn()) {
825  global $loggedInUser;
826  if($loggedInUser->userId==DEFAULT_ADMIN_ACCOUNT||$loggedInUser->userId==MASTER_ACCOUNT) {
827  return true;
828  } else {
829  return false;
830  }
831  } else {
832  return false;
833  }
834  }
835 
836  /**
837  * Check if a certain user is an administrator
838  * @param integer $id the user id of the user whose rights should be checked
839  * @return boolean
840  * - true if the user is an administrator
841  * - false if not
842  */
843  function isAdministrator($id) {
844  // if the user has a master account ommit database check
845  if($id == MASTER_ACCOUNT || $id == DEFAULT_ADMIN_ACCOUNT) {
846  return true;
847  } else {
848  // check the database for administrator entries
849  global $mysqli, $db;
850  $adminPermission = ADMIN_PERMISSION;
851  $stmt = $mysqli->prepare(
852  "SELECT COUNT(id)
853  FROM " . $db['user_permission'] . "
854  WHERE user_id = ?
855  AND
856  permission_id = ?");
857  $stmt->bind_param("ii", $id, $adminPermission);
858  $stmt->execute();
859  $stmt->bind_result($count);
860  if ($stmt->fetch()) {
861  $retval = $count;
862  }
863  $stmt->close();
864  if (isset($retval)) {
865  if ($retval > 0) {
866  // one (or more) entries -> administrator
867  return true;
868  } else {
869  return false;
870  }
871  } else {
872  fail("Couldn't perform check.");
873  return false;
874  }
875  }
876  }
877 
878  /**
879  * Checks wheter or not a user has root priviliges
880  * @param integer $userId
881  * @return boolean TRUE if the user is a root user
882  * @author Alexander Vorndran
883  */
884  function isRoot($userId) {
885  return $userId == MASTER_ACCOUNT || $userId == DEFAULT_ADMIN_ACCOUNT;
886  }
887 
888  /**
889  * Check if the current session has timed out
890  * @return boolean
891  * - TRUE if the session has timed out
892  * - FALSE if not
893  * @author Alexander Vorndran
894  */
895  function hasSessionTimedOut($user_id) {
896  if (AUTO_TIMEOUT > 0) {
897  if (time() - getLastActivity($user_id) > AUTO_TIMEOUT||getStoredSession($user_id)==RESET_SESSION_ID) {
898  return true;
899  } else {
900  return false;
901  }
902  } else {
903  return false;
904  }
905  }
906 
907 
908  /**
909  * returns the timestamp for the last sign in
910  * @return mixed
911  * - the time of the last sign in
912  * - FALSE on failure
913  * @author Usercake (http://www.usercake.com)
914  */
915  function getLastActivity($userId) {
916  if (isset($userId)) {
917  global $mysqli, $db;
918  $stmt = $mysqli->prepare("
919  SELECT last_sign_in_stamp
920  FROM " . $db['users'] . "
921  WHERE id = ?
922  LIMIT 1
923  ");
924  $stmt->bind_param("i", $userId);
925  $stmt->bind_result($lastSignIn);
926  $stmt->execute();
927  if ($stmt->fetch()) {
928  $retval = $lastSignIn;
929  }
930  $stmt->close();
931  return $retval;
932  } else {
933  return FALSE;
934  }
935  }
936 
937  /**
938  * Change a user from inactive to active
939  * @param string $token the alphanumerical activation token
940  * @return mixed
941  * - 1 on success
942  * - FALSE on failure
943  */
944  function setUserActive($token) {
945  global $mysqli, $db;
946  $stmt = $mysqli->prepare("UPDATE " . $db['users'] . "
947  SET active = 1
948  WHERE
949  activation_token = ?
950  LIMIT 1");
951  $stmt->bind_param("s", $token);
952  $result = $stmt->execute();
953  $stmt->close();
954  return $result;
955  }
956 
957  /**
958  * Change the valid_email-flag to valid
959  * @param string $token the alphanumerical token
960  * @return boolean
961  * - TRUE if the validation was a success
962  * - FALSE if not
963  */
964  function setMailValid($token) {
965  global $mysqli, $db;
966  $stmt = $mysqli->prepare("UPDATE " . $db['users'] . "
967  SET valid_email = 1
968  WHERE
969  activation_token = ?
970  LIMIT 1");
971  $stmt->bind_param("s", $token);
972  $result = $stmt->execute();
973  $stmt->close();
974 
975  return ($result > 0) ? true : false;
976  }
977 
978  /**
979  * Change a user from active to locked
980  * @param mixed $userId the id of the user who should get locked
981  * @author Alexander Vorndran
982  */
983  function setUserLocked($userId) {
984  global $mysqli, $db;
985  if ($userId <> DEFAULT_ADMIN_ACCOUNT) {
986  $stmt = $mysqli->prepare("UPDATE " . $db['users'] . "
987  SET active = 2, session_id = '0'
988  WHERE
989  id = ?
990  LIMIT 1");
991  $stmt->bind_param("i", $userId);
992  $result = $stmt->execute();
993  $stmt->close();
994  return $result;
995  } else {
996  return FALSE;
997  }
998  }
999 
1000  /**
1001  * Change a user's firstname
1002  * @param mixed $userId
1003  * @param string $newFirstname the new firstname of the user
1004  * @return mixed
1005  * - 1 on success
1006  * - FALSE on failure
1007  * @author Alexander Vorndran
1008  */
1009  function updateFirstname($userId, $newFirstname) {
1010  global $mysqli, $db;
1011  $stmt = $mysqli->prepare("UPDATE " . $db['users'] . "
1012  SET first_name = ?
1013  WHERE
1014  id = ?
1015  LIMIT 1");
1016  $stmt->bind_param("si", $newFirstname, $userId);
1017  $result = $stmt->execute();
1018  $stmt->close();
1019  return $result;
1020  }
1021 
1022  /**
1023  * Change a user's username
1024  * @param mixed $userId
1025  * @param string $newUsername
1026  * @return boolean
1027  * - TRUE on success
1028  * - FALSE on failure
1029  * @author Alexander Vorndran
1030  */
1031  function updateUsername($userId, $newUsername) {
1032  global $mysqli, $db;
1033  $stmt = $mysqli->prepare("UPDATE " . $db['users'] . "
1034  SET user_name = ?
1035  WHERE
1036  id = ?
1037  LIMIT 1");
1038  $stmt->bind_param("si", $newUsername, $userId);
1039  $result = $stmt->execute();
1040  $stmt->close();
1041  return ($result > 0) ? true : false;;
1042  }
1043 
1044  /**
1045  * Change a user's lastname
1046  * @param mixed $userId
1047  * @param string $newLastname
1048  * @return mixed
1049  * - TRUE on success
1050  * - FALSE on failure
1051  * @author Alexander Vorndran
1052  */
1053  function updateLastname($userId, $newLastname) {
1054  global $mysqli, $db;
1055  $stmt = $mysqli->prepare("UPDATE " . $db['users'] . "
1056  SET last_name = ?
1057  WHERE
1058  id = ?
1059  LIMIT 1");
1060  $stmt->bind_param("si", $newLastname, $userId);
1061  $result = $stmt->execute();
1062  $stmt->close();
1063  return ($result > 0) ? true : false;
1064  }
1065 
1066  /**
1067  * Update a user's email
1068  * @param mixed $userId
1069  * @param string $newEmail the new email-address
1070  * @return mixed
1071  * - TRUE on success
1072  * - FALSE on failure
1073  * @author Usercake (http://www.usercake.com)
1074  */
1075  function updateEmail($userId, $newEmail) {
1076  global $mysqli, $db;
1077  $stmt = $mysqli->prepare("UPDATE " . $db['users'] . "
1078  SET
1079  email = ?
1080  WHERE
1081  id = ?");
1082  $stmt->bind_param("si", $newEmail, $userId);
1083  $result = $stmt->execute();
1084  $stmt->close();
1085  return ($result > 0) ? true : false;
1086  }
1087 
1088  /**
1089  * Update a user's mobilephone number
1090  * @param mixed $userId
1091  * @param string $mobile the new email-address
1092  * @return mixed
1093  * - TRUE on success
1094  * - FALSE on failure
1095  * @author Alexander Vorndran
1096  */
1097  function updateMobile($userId, $mobile) {
1098  global $mysqli, $db;
1099  $stmt = $mysqli->prepare("UPDATE " . $db['users'] . "
1100  SET
1101  mobile = ?
1102  WHERE
1103  id = ?");
1104  $stmt->bind_param("si", $mobile, $userId);
1105  $result = $stmt->execute();
1106  $stmt->close();
1107  return ($result > 0) ? true : false;
1108  }
1109 
1110  /**
1111  * Input new activation token, and update the time of the most recent activation request
1112  * @param string $newActivationToken the new alphanumerical activation token
1113  * @param string $username the username of the user
1114  * @param string $email the email-address of the user
1115  * @return boolean
1116  * - TRUE on success
1117  * - FALSE on failure
1118  * @author Usercake (http://www.usercake.com)
1119  */
1120  function updateLastActivationRequest($newActivationToken, $username, $email) {
1121  global $mysqli, $db;
1122  $stmt = $mysqli->prepare("UPDATE " . $db['users'] . "
1123  SET activation_token = ?,
1124  last_activation_request = ?
1125  WHERE email = ?
1126  AND
1127  user_name = ?");
1128  $stmt->bind_param("ssss", $newActivationToken, time(), $email, $username);
1129  $result = $stmt->execute();
1130  $stmt->close();
1131  return ($result > 0) ? true : false;
1132  }
1133 
1134  /**
1135  * Sets a new token for the confirmation of the email-adress
1136  * @param string $new_confirm_token the new token
1137  * @param string $username the username of the user where the token should be set
1138  * @return boolean
1139  * - TRUE on success
1140  * - FALSE on failure
1141  * @author Usercake (http://www.usercake.com)
1142  */
1143  function updateMailConfirmationToken($new_confirm_token, $username) {
1144  global $mysqli, $db;
1145  $time = time();
1146  $stmt = $mysqli->prepare("UPDATE " . $db['users'] . "
1147  SET activation_token = ?,
1148  last_activation_request = ?
1149  WHERE user_name = ?");
1150  $stmt->bind_param("sss", $new_confirm_token, $time, $username);
1151  $result = $stmt->execute();
1152  $stmt->close();
1153  return ($result > 0) ? true : false;
1154  }
1155 
1156  /**
1157  * Generate a random password and new token
1158  * @param type $newPasswordHash
1159  * @param type $oldToken
1160  * @return boolean
1161  * - TRUE on success
1162  * - FALSE on failure
1163  * @author Usercake (http://www.usercake.com)
1164  */
1165  function updatePasswordFromToken($newPasswordHash, $oldToken) {
1166  global $mysqli, $db;
1167  $newActivationToken = generateActivationToken();
1168  $stmt = $mysqli->prepare("UPDATE " . $db['users'] . "
1169  SET password = ?,
1170  activation_token = ?
1171  WHERE
1172  activation_token = ?");
1173  $stmt->bind_param("sss", $newPasswordHash, $newActivationToken, $oldToken);
1174  $result = $stmt->execute();
1175  $stmt->close();
1176  return ($result > 0) ? true : false;
1177  }
1178 
1179  /**
1180  * Update a user's title
1181  * @param integer $userId the user-id of the user whos title is changed
1182  * @param string $title the new title of the user
1183  * @return boolean
1184  * - TRUE on success
1185  * - FALSE else
1186  * @author Usercake (http://www.usercake.com)
1187  */
1188  function updateTitle($userId, $title) {
1189  global $mysqli, $db;
1190  $stmt = $mysqli->prepare("UPDATE " . $db['users'] . "
1191  SET
1192  title = ?
1193  WHERE
1194  id = ?");
1195  $stmt->bind_param("si", $title, $userId);
1196  $result = $stmt->execute();
1197  $stmt->close();
1198  return ($result > 0) ? true : false;
1199  }
1200 
1201  /**
1202  * Check if a user ID exists in the DB
1203  * @param integer $userId the user-id to check
1204  * @return boolean
1205  * - TRUE if the id exists in the database
1206  * - FALSE if not
1207  * @author Usercake (http://www.usercake.com)
1208  */
1209  function userIdExists($userId) {
1210  global $mysqli, $db;
1211  $stmt = $mysqli->prepare("SELECT active
1212  FROM " . $db['users'] . "
1213  WHERE
1214  id = ?
1215  LIMIT 1");
1216  $stmt->bind_param("i", $userId);
1217  $stmt->execute();
1218  $stmt->store_result();
1219  $num_returns = $stmt->num_rows;
1220  $stmt->close();
1221 
1222  if ($num_returns > 0) {
1223  return true;
1224  } else {
1225  return false;
1226  }
1227  }
1228 
1229  /**
1230  * Checks if a username exists in the DB
1231  * @param string $username the username to check
1232  * @return boolean
1233  * - TRUE if the username exists in the database and is valid
1234  * - FALSE if not
1235  * @author Usercake (http://www.usercake.com)
1236  */
1237  function usernameExists($username) {
1238  if (isValidName($username)) {
1239  global $mysqli, $db;
1240  $stmt = $mysqli->prepare("SELECT active
1241  FROM " . $db['users'] . "
1242  WHERE
1243  user_name = ?
1244  LIMIT 1");
1245  $stmt->bind_param("s", $username);
1246  $stmt->execute();
1247  $stmt->store_result();
1248  $num_returns = $stmt->num_rows;
1249  $stmt->close();
1250 
1251  if ($num_returns > 0) {
1252  return true;
1253  } else {
1254  return false;
1255  }
1256  } else {
1257  return false;
1258  }
1259  }
1260 
1261  /**
1262  * Check if activation token exists in DB
1263  * @param string $token the token that should be validated
1264  * @param mixed $lostpass [optional]
1265  * - FALSE if the token was generated for activation purposes
1266  * - TRUE if the token was generated for password purposes
1267  * @return boolean
1268  * - TRUE if the token is present in the database
1269  * - FALSE if not
1270  * @author Usercake (http://www.usercake.com)
1271  */
1272  function validateActivationToken($token, $lostpass = FALSE) {
1273  global $mysqli, $db;
1274  if ($lostpass == FALSE) {
1275  $stmt = $mysqli->prepare("SELECT active
1276  FROM " . $db['users'] . "
1277  WHERE `valid_email` = 0
1278  AND
1279  activation_token = ?
1280  LIMIT 1");
1281  } else {
1282  $stmt = $mysqli->prepare("SELECT active
1283  FROM " . $db['users'] . "
1284  WHERE active = 1
1285  AND
1286  activation_token = ?
1287  AND
1288  (lost_password_request = 1 OR lost_password_request = 2)
1289  LIMIT 1");
1290  }
1291  $stmt->bind_param("s", $token);
1292  $stmt->execute();
1293  $stmt->store_result();
1294  $num_returns = $stmt->num_rows;
1295  $stmt->close();
1296 
1297  if ($num_returns > 0) {
1298  return true;
1299  } else {
1300  return false;
1301  }
1302  }
1303 
1304  //Functions that interact mainly with .permissions table
1305  //------------------------------------------------------------------------------
1306 
1307  /**
1308  * Create a permission level in DB
1309  * @param string $permissionName the name of the new permission
1310  * @return integer number of changes
1311  */
1312  function createPermission($permissionName) {
1313  global $mysqli, $db;
1314  $stmt = $mysqli->prepare("INSERT INTO " . $db['permissions'] . " (
1315  name
1316  )
1317  VALUES (
1318  ?
1319  )");
1320  $stmt->bind_param("s", $permissionName);
1321  $result = $stmt->execute();
1322  $stmt->close();
1323  return $result;
1324  }
1325 
1326  /**
1327  * Delete a permission level from the DB
1328  * @param integer $permissionId the id of the permission that should be deleted
1329  * @return integer number of changes
1330  */
1331  function deletePermission($permissionId) {
1332  global $mysqli, $db, $errors;
1333  $i = 0;
1334  $stmt = $mysqli->prepare("DELETE FROM " . $db['permissions'] . "
1335  WHERE id = ?");
1336  $stmt2 = $mysqli->prepare("DELETE FROM " . $db['user_permission'] . "
1337  WHERE permission_id = ?");
1338  foreach ($permissionId as $id) {
1339  if ($id == 1) {
1340  $errors[] = lang("CANNOT_DELETE_ADMIN");
1341  } elseif ($id == 2) {
1342  $errors[] = lang("CANNOT_DELETE_NEWUSER");
1343  } else {
1344  $stmt->bind_param("i", $id);
1345  $stmt->execute();
1346  $stmt2->bind_param("i", $id);
1347  $stmt2->execute();
1348  $i++;
1349  }
1350  }
1351  $stmt->close();
1352  $stmt2->close();
1353  return $i;
1354  }
1355 
1356  /**
1357  * Retrieve information for all permission levels
1358  * @return array an array containg the ids and names of all permission levels
1359  */
1360  function fetchAllPermissions() {
1361  global $mysqli, $db;
1362  $stmt = $mysqli->prepare("SELECT
1363  id,
1364  name
1365  FROM " . $db['permissions'] . "");
1366  $stmt->execute();
1367  $stmt->bind_result($id, $name);
1368  while ($stmt->fetch()) {
1369  if ($id <> 0)
1370  $row[] = array('id' => $id, 'name' => $name);
1371  }
1372  $stmt->close();
1373  return ($row);
1374  }
1375 
1376  /**
1377  * Retrieve information for a single permission level
1378  * @param integer $permissionId
1379  * @return array an array containing the information for the given permission-id
1380  */
1381  function fetchPermissionDetails($permissionId) {
1382  global $mysqli, $db;
1383  $stmt = $mysqli->prepare("SELECT
1384  id,
1385  name
1386  FROM " . $db['permissions'] . "
1387  WHERE
1388  id = ?
1389  LIMIT 1");
1390  $stmt->bind_param("i", $permissionId);
1391  $stmt->execute();
1392  $stmt->bind_result($permissionId, $name);
1393  while ($stmt->fetch()) {
1394  $row = array('id' => $permissionId, 'name' => $name);
1395  }
1396  $stmt->close();
1397  return ($row);
1398  }
1399 
1400  /**
1401  * Check if a permission level ID exists in the DB
1402  * @param integer $permissionId the permission-id to check
1403  * @return boolean TRUE if the id exists FALSE else
1404  */
1405  function permissionIdExists($permissionId) {
1406  global $mysqli, $db;
1407  $stmt = $mysqli->prepare("SELECT id
1408  FROM " . $db['permissions'] . "
1409  WHERE
1410  id = ?
1411  LIMIT 1");
1412  $stmt->bind_param("i", $permissionId);
1413  $stmt->execute();
1414  $stmt->store_result();
1415  $num_returns = $stmt->num_rows;
1416  $stmt->close();
1417 
1418  if ($num_returns > 0) {
1419  return true;
1420  } else {
1421  return false;
1422  }
1423  }
1424 
1425  /**
1426  * Check if a permission level name exists in the DB
1427  * @param string $permission the name of the permission to check
1428  * @return boolean TRUE if the name exists FALSE if not
1429  */
1430  function permissionNameExists($permission) {
1431  global $mysqli, $db;
1432  $stmt = $mysqli->prepare("SELECT id
1433  FROM " . $db['permissions'] . "
1434  WHERE
1435  name = ?
1436  LIMIT 1");
1437  $stmt->bind_param("s", $permission);
1438  $stmt->execute();
1439  $stmt->store_result();
1440  $num_returns = $stmt->num_rows;
1441  $stmt->close();
1442 
1443  if ($num_returns > 0) {
1444  return true;
1445  } else {
1446  return false;
1447  }
1448  }
1449 
1450  /**
1451  * Change a permission level's name
1452  * @param integer $permissionId
1453  * @param type $newName
1454  * @return number of changes
1455  */
1456  function updatePermissionName($permissionId, $newName) {
1457  global $mysqli, $db;
1458  $stmt = $mysqli->prepare("UPDATE " . $db['permissions'] . "
1459  SET name = ?
1460  WHERE
1461  id = ?
1462  LIMIT 1");
1463  $stmt->bind_param("si", $newName, $permissionId);
1464  $result = $stmt->execute();
1465  $stmt->close();
1466  return $result;
1467  }
1468 
1469  //Functions that interact mainly with .user_permission_matches table
1470  //------------------------------------------------------------------------------
1471 
1472  /**
1473  * Match permission level(s) with user(s)
1474  * @param array $permissionId the id of the permission
1475  * @param array $userId the id of the user
1476  * @return integer number of changes
1477  * @author Usercake (http://www.usercake.com)
1478  */
1479  function addPermission($permissionId, $userId) {
1480  global $mysqli, $db;
1481  $i = 0;
1482  $stmt = $mysqli->prepare("INSERT INTO " . $db['user_permission'] . " (
1483  permission_id,
1484  user_id
1485  )
1486  VALUES (
1487  ?,
1488  ?
1489  )");
1490  if (is_array($permissionId)) {
1491  foreach ($permissionId as $id) {
1492  $stmt->bind_param("ii", $id, $userId);
1493  $stmt->execute();
1494  $i++;
1495  }
1496  } elseif (is_array($userId)) {
1497  foreach ($userId as $id) {
1498  $stmt->bind_param("ii", $permissionId, $id);
1499  $stmt->execute();
1500  $i++;
1501  }
1502  } else {
1503  $stmt->bind_param("ii", $permissionId, $userId);
1504  $stmt->execute();
1505  $i++;
1506  }
1507  $stmt->close();
1508  return $i;
1509  }
1510 
1511  /**
1512  * Retrieve information for all user/permission level matches
1513  * @return array array containing id, user id and matching permission id
1514  * @author Usercake (http://www.usercake.com)
1515  */
1516  function fetchAllMatches() {
1517  global $mysqli, $db;
1518  $stmt = $mysqli->prepare("SELECT
1519  id,
1520  user_id,
1521  permission_id
1522  FROM " . $db['user_permission'] . "");
1523  $stmt->execute();
1524  $stmt->bind_result($id, $user, $permission);
1525  while ($stmt->fetch()) {
1526  $row[] = array('id' => $id, 'user_id' => $user, 'permission_id' => $permission);
1527  }
1528  $stmt->close();
1529  return ($row);
1530  }
1531 
1532  /**
1533  * Retrieve list of permission levels a user has
1534  * @param integer $userId the id of the user
1535  * @return array all permission levels for the given user-id
1536  * @author Usercake (http://www.usercake.com)
1537  */
1538  function fetchUserPermissions($userId) {
1539  global $mysqli, $db;
1540  $stmt = $mysqli->prepare("SELECT
1541  id,
1542  permission_id
1543  FROM " . $db['user_permission'] . "
1544  WHERE user_id = ?
1545  ");
1546  $stmt->bind_param("i", $userId);
1547  $stmt->execute();
1548  $stmt->bind_result($id, $permission);
1549  while ($stmt->fetch()) {
1550  $row[$permission] = array('id' => $id, 'permission_id' => $permission);
1551  }
1552  $stmt->close();
1553  if (isset($row)) {
1554  return ($row);
1555  }
1556  }
1557 
1558  /**
1559  * Retrieve list of users who have a permission level
1560  * @param integer $permission_id
1561  * @return array contains all users with the given permission level
1562  * @author Usercake (http://www.usercake.com)
1563  */
1564  function fetchPermissionUsers($permission_id) {
1565  global $mysqli, $db;
1566  $stmt = $mysqli->prepare("SELECT id, user_id
1567  FROM " . $db['user_permission'] . "
1568  WHERE permission_id = ?
1569  ");
1570  $stmt->bind_param("i", $permission_id);
1571  $stmt->execute();
1572  $stmt->bind_result($id, $user);
1573  while ($stmt->fetch()) {
1574  $row[$user] = array('id' => $id, 'user_id' => $user);
1575  }
1576  $stmt->close();
1577  if (isset($row)) {
1578  return ($row);
1579  }
1580  }
1581 
1582  /**
1583  * Unmatch permission level(s) from user(s)
1584  * @param mixed $permissionId
1585  * @param mixed $userId
1586  * @return integer number of successful removed permissions
1587  * @author Usercake (http://www.usercake.com)
1588  */
1589  function removePermission($permissionId, $userId) {
1590  global $mysqli, $db;
1591  $i = 0;
1592  $forbidden = 0;
1593  $stmt = $mysqli->prepare("DELETE FROM " . $db['user_permission'] . "
1594  WHERE permission_id = ?
1595  AND user_id =?");
1596  if (is_array($permissionId)) {
1597  foreach ($permissionId as $id) {
1598  if ($id <> ADMIN_PERMISSION) {
1599  $stmt->bind_param("ii", $id, $userId);
1600  $stmt->execute();
1601  } else {
1602  $forbidden++;
1603  }
1604  $i++;
1605  }
1606  } elseif (is_array($userId)) {
1607  foreach ($userId as $id) {
1608  if ($id <> DEFAULT_ADMIN_ACCOUNT) {
1609  $stmt->bind_param("ii", $permissionId, $id);
1610  $stmt->execute();
1611  } else {
1612  $forbidden++;
1613  }
1614  $i++;
1615  }
1616  } else {
1617  if ($userId <> DEFAULT_ADMIN_ACCOUNT/* && $permission <> ADMIN_PERMISSION */) {
1618  $stmt->bind_param("ii", $permissionId, $userId);
1619  $stmt->execute();
1620  } else {
1621  $forbidden++;
1622  }
1623  $i++;
1624  }
1625  $stmt->close();
1626  return $i - $forbidden;
1627  }
1628 
1629  /**
1630  * Checks if a given file has the UserCake-typical security header
1631  * @param string $filename the name of the file to check
1632  * @return mixed
1633  * - TRUE if the header was found
1634  * - FALSE if the header was not found,
1635  * -1 if something went wrong
1636  * @author Alexander Vorndran
1637  */
1639  if (file_exists($filename)) {
1640  $content = file_get_contents($filename);
1641 
1642  $securityHeaderPattern = "~if\s*\(\!accessGranted\([\.\$_A-Z\['\])\(\)]*\)\)\s*\{[A-Za-z\s\(\)\{\}'.;üäÜÄöÖ,0-9]*\}~i";
1643 
1644  $hasSecurityHeader = preg_match($securityHeaderPattern, $content);
1645  if ($hasSecurityHeader === 0) {
1646  return FALSE;
1647  } else if ($hasSecurityHeader === 1) {
1648  return TRUE;
1649  } else {
1650  return -1;
1651  }
1652  } else {
1653  return -1;
1654  }
1655  }
1656 
1657  //Functions that interact mainly with .configuration table
1658  //------------------------------------------------------------------------------
1659 
1660  //Functions that interact mainly with .pages table
1661  //------------------------------------------------------------------------------
1662 
1663  /**
1664  * Add a page to the DB
1665  * @param array $pages the names of the pages that should be added to the database
1666  * @return integer number of pages that were added successfully
1667  * @author Usercake (http://www.usercake.com)
1668  */
1669  function createPages($pages) {
1670  global $mysqli, $db;
1671  $page_access = STANDARD_PAGE_ACCESS;
1672  $stmt = $mysqli->prepare("INSERT INTO " . $db['pages'] . " (
1673  page, state
1674  )
1675  VALUES (
1676  ?,?
1677  )");
1678  $i = 0;
1679  foreach ($pages as $page) {
1680  $stmt->bind_param("si", $page, $page_access);
1681  if ($stmt->execute()) {
1682  $i++;
1683  }
1684  }
1685  $stmt->close();
1686  return $i;
1687  }
1688 
1689  /**
1690  * Delete a page from the DB
1691  * @param array $pages the page-ids of the pages
1692  * that should be deleted from the database
1693  * @author Usercake (http://www.usercake.com)
1694  */
1695  function deletePages($pages) {
1696  global $mysqli, $db;
1697  $stmt = $mysqli->prepare("DELETE FROM " . $db['pages'] . "
1698  WHERE id = ?");
1699  foreach ($pages as $id) {
1700  $stmt->bind_param("i", $id);
1701  $stmt->execute();
1702  }
1703  $stmt->close();
1704  }
1705 
1706  /**
1707  * Fetch information on all pages
1708  * @return array an array containing the details of all pages
1709  * @author Usercake (http://www.usercake.com)
1710  */
1711  function fetchAllPages() {
1712  global $mysqli, $db;
1713  $stmt = $mysqli->prepare("SELECT
1714  id,
1715  page,
1716  state
1717  FROM " . $db['pages'] . "
1718  ORDER BY page");
1719  $stmt->execute();
1720  $stmt->bind_result($id, $page, $state);
1721  while ($stmt->fetch()) {
1722  $row[$page] = array('id' => $id, 'page' => $page, 'state' => $state);
1723  }
1724  $stmt->close();
1725  if (isset($row)) {
1726  return ($row);
1727  }
1728  }
1729 
1730  /**
1731  * Fetch information for a specific page
1732  * @param integer $pageId
1733  * @return array the page information
1734  * @author Usercake (http://www.usercake.com)
1735  */
1736  function fetchPageDetails($pageId) {
1737  global $mysqli, $db;
1738  $stmt = $mysqli->prepare("SELECT
1739  id,
1740  page,
1741  state
1742  FROM " . $db['pages'] . "
1743  WHERE
1744  id = ?
1745  LIMIT 1");
1746  $stmt->bind_param("i", $pageId);
1747  $stmt->execute();
1748  $stmt->bind_result($pageId, $page, $state);
1749  while ($stmt->fetch()) {
1750  $row = array('id' => $pageId, 'page' => $page, 'state' => $state);
1751  }
1752  $stmt->close();
1753  return ($row);
1754  }
1755 
1756  /**
1757  * Check if a page ID exists
1758  * @param integer $pageId the id to check
1759  * @return boolean
1760  * - TRUE if the pageId exists
1761  * - FALSE if not
1762  * @author Usercake (http://www.usercake.com)
1763  */
1764  function pageIdExists($pageId) {
1765  global $mysqli, $db;
1766  $stmt = $mysqli->prepare("SELECT state
1767  FROM " . $db['pages'] . "
1768  WHERE
1769  id = ?
1770  LIMIT 1");
1771  $stmt->bind_param("i", $pageId);
1772  $stmt->execute();
1773  $stmt->store_result();
1774  $num_returns = $stmt->num_rows;
1775  $stmt->close();
1776 
1777  if ($num_returns > 0) {
1778  return true;
1779  } else {
1780  return false;
1781  }
1782  }
1783 
1784  /**
1785  * Toggle private/public/locked setting of a page
1786  * @param integer $pageId
1787  * @param integer $state PAGE_PUBLIC, PAGE_PRIVATE, PAGE_LOCK
1788  * @return integer number of affected rows in the database
1789  * @author Usercake (http://www.usercake.com)
1790  * @author Alexander Vorndran
1791  */
1792  function updatePageState($pageId, $state) {
1793  global $mysqli, $db;
1794  $stmt = $mysqli->prepare("UPDATE " . $db['pages'] . "
1795  SET
1796  state = ?
1797  WHERE
1798  id = ?");
1799  $stmt->bind_param("ii", $state, $pageId);
1800  $result = $stmt->execute();
1801  $stmt->close();
1802  return $result;
1803  }
1804 
1805  /**
1806  * Resets the session-id to default value
1807  * forces logout of the corresponding user
1808  * @param integer $userId
1809  * @return mixed
1810  * - FALSE or 0 if the action has failed
1811  * - TRUE if it was a success
1812  * @author Alexander Vorndran
1813  */
1814  function resetStoredSession($userId) {
1815  global $mysqli, $db;
1816  $default_id = RESET_SESSION_ID;
1817  $qry = "UPDATE " . $db['users'] . "
1818  SET `session_id` = ?
1819  WHERE id = ?";
1820  $stmt = $mysqli->prepare($qry);
1821  $stmt->bind_param("si", $default_id, $userId);
1822  $result = $stmt->execute();
1823  $stmt->close();
1824 
1825  return ($result > 0) ? true : false;
1826  }
1827 
1828  /**
1829  * Checks if the current user has access to the given resource
1830  * @param string $uri uniform resource identifier of the website
1831  * @return boolean
1832  * - TRUE if the user has access
1833  * - FALSE if not
1834  * @author Daniel Seichter
1835  * @author Alexander Vorndran
1836  */
1837  function accessGranted($uri) {
1838  if(isUserRoot()) {
1839  return true;
1840  } else {
1841  //Separate document name from uri
1842  $tokens = explode('/', $uri);
1843  $pageName = $tokens[sizeof($tokens) - 1];
1844  global $mysqli, $db, $errors;
1845  //retrieve page details
1846  $stmt = $mysqli->prepare("SELECT
1847  id,
1848  page,
1849  state
1850  FROM " . $db['pages'] . "
1851  WHERE
1852  page = ?
1853  LIMIT 1");
1854  $stmt->bind_param("s", $pageName);
1855  $stmt->execute();
1856  $stmt->bind_result($id, $page, $state);
1857  while ($stmt->fetch()) {
1858  $pageDetails = array('id' => $id, 'page' => $page, 'state' => $state);
1859  }
1860  $stmt->close();
1861  //If page does not exist in DB add it and grant access if user is administrator
1862  if (empty($pageDetails)) {
1863  if (createPages(array($pageName)) > 0) {
1864  $pageId = fetchPageIdForName($pageName);
1865  updatePageState($pageId, PAGE_PRIVATE);
1866  if (isUserLoggedIn()) {
1867  return true;
1868  } else {
1869  return false;
1870  }
1871  } else {
1872  $errors[] = "Die Seite konnte nicht zur Datenbank hinzugefuegt werden.";
1873  return isUserAdministrator();
1874  }
1875  }
1876  //If page is public, allow access
1877  else
1878  if ($pageDetails['state'] == PAGE_PUBLIC) {
1879  return true;
1880  }
1881  //If user is not logged in and page is private deny access
1882  else
1883  if ($pageDetails['state'] == PAGE_PRIVATE) {
1884  if (isUserLoggedIn()) {
1885  return TRUE;
1886  } else {
1887  return FALSE;
1888  }
1889  } else
1890  if ($pageDetails['state'] == PAGE_LOCK) {
1891  if (!isUserAdministrator()) {
1892  return false;
1893  } else {
1894  return true;
1895  }
1896  }
1897  }
1898  }
1899 
1900  /**
1901  * Checks if the user has a validated email-address
1902  * @param integer $userId the id of the user
1903  * @return boolean
1904  * - TRUE if it's valid
1905  * - FALSE if not
1906  * @author Alexander Vorndran
1907  */
1908  function hasValidMail($userId) {
1909  global $mysqli, $db;
1910  $stmt = $mysqli->prepare("SELECT valid_email
1911  FROM " . $db['users'] . "
1912  WHERE
1913  id = ?
1914  LIMIT 1");
1915  $stmt->bind_param("i", $userId);
1916  $stmt->execute();
1917  $stmt->bind_result($validMail);
1918 
1919  if($stmt->fetch()) {
1920  return ($validMail==1)? true : false;
1921  } else {
1922  return false;
1923  }
1924  }
1925 
1926  /**
1927  * Resets the valid mail status
1928  * @param string $token the alphanumerical token to identify the user
1929  * @return boolean
1930  * - TRUE on success
1931  * - FALSE on failure
1932  * @author Alexander Vorndran
1933  */
1934  function resetValidMail($token) {
1935  global $mysqli, $db;
1936  $qry = "UPDATE " . $db['users'] . "
1937  SET `valid_email` = 0
1938  WHERE `activation_token` = ?";
1939  $stmt = $mysqli->prepare($qry);
1940  $stmt->bind_param("s", $token);
1941  $result = $stmt->execute();
1942  $stmt->close();
1943 
1944  return ($result > 0) ? true : false;
1945  }
1946 
1947  /**
1948  * Sets the email valid for a given token
1949  * @param string $token defines the user
1950  * @return boolean
1951  * - TRUE on success
1952  * - FALSE on failure
1953  * @author Alexander Vorndran
1954  */
1955  function setValidMail($token) {
1956  global $mysqli, $db;
1957  $qry = "UPDATE " . $db['users'] . "
1958  SET `valid_email` = 1
1959  WHERE `activation_token` = ?";
1960  $stmt = $mysqli->prepare($qry);
1961  $stmt->bind_param("i", $token);
1962  $result = $stmt->execute();
1963  $stmt->close();
1964 
1965  return ($result > 0) ? true : false;
1966  }
1967 
1968  /**
1969  * Fetch the id for given page
1970  * @param string $page the name of the page
1971  * @return mixed
1972  * - FALSE if the querie has failed
1973  * - returns the id
1974  * @author Usercake (http://www.usercake.com)
1975  */
1976  function fetchPageIdForName($page) {
1977  global $mysqli, $db;
1978  $stmt = $mysqli->prepare("SELECT
1979  id
1980  FROM " . $db['pages'] . "
1981  WHERE page = ?");
1982  $stmt->bind_param("s", $page);
1983  $stmt->bind_result($id);
1984  $stmt->execute();
1985  if ($stmt->fetch()) {
1986  return $id;
1987  } else {
1988  return false;
1989  }
1990  }
1991 
1992  /**
1993  * Checks wheter the user has a onetime password
1994  * @param integer $userId the id of the user that should be checked
1995  * @return boolean
1996  * - TRUE if the user has a passwordFlag less than 0
1997  * - FALSE else
1998  * @author Alexander Vorndran
1999  */
2000  function hasOnetimePassword($userId) {
2001  global $mysqli, $db;
2002  $stmt = $mysqli->prepare("SELECT lost_password_request
2003  FROM " . $db['users'] . "
2004  WHERE
2005  id = ?
2006  LIMIT 1");
2007  $stmt->bind_param("i", $userId);
2008  $stmt->execute();
2009  $stmt->bind_result($passwordFlag);
2010 
2011  if($stmt->fetch()) {
2012  return ($passwordFlag<0)? true : false;
2013  } else {
2014  return false;
2015  }
2016  }
2017 
2018  /**
2019  * Checks if the user has an expired onetime password
2020  * @param integer $userId the id of the user that should be checked
2021  * @return boolean
2022  * - TRUE if the user has a passwordFlag less than -1
2023  * - FALSE else
2024  * @author Alexander Vorndran
2025  */
2026  function hasOnetimePasswordExpired($userId) {
2027  global $mysqli, $db;
2028  $stmt = $mysqli->prepare("SELECT lost_password_request
2029  FROM " . $db['users'] . "
2030  WHERE
2031  id = ?
2032  LIMIT 1");
2033  $stmt->bind_param("i", $userId);
2034  $stmt->execute();
2035  $stmt->bind_result($passwordFlag);
2036 
2037  if($stmt->fetch()) {
2038  return ($passwordFlag<-1)? true : false;
2039  } else {
2040  return false;
2041  }
2042  }
2043 
2044  /**
2045  * Returns the number of changes the user is responsible for
2046  * @param integer $userId the id of the user
2047  * @return mixed
2048  * - the number of changes
2049  * - FALSE if an error occurred
2050  * @author Florian Wirthmüller
2051  * @author Alexander Vorndran
2052  */
2053  function countUserReferences($userId) {
2054  global $mysqli,$dbBackup;
2055  // Set MySQL variable
2056  $qryInit = "SET @userId = ?";
2057  $stmt = $mysqli->prepare($qryInit);
2058  $stmt->bind_param("i",$userId);
2059  $stmt->execute();
2060  $stmt->close();
2061 
2062  // main query
2063  $qry = "SELECT SUM(count)
2064  FROM(
2065  SELECT COUNT(id) AS count
2066  FROM ".$dbBackup['car']."
2067  WHERE bup_last_change_by = @userId
2068  UNION
2069  SELECT COUNT(id) AS count
2070  FROM ".$dbBackup['category']."
2071  WHERE bup_last_change_by = @userId
2072  UNION
2073  SELECT COUNT(id) AS count
2074  FROM ".$dbBackup['contact_person']."
2075  WHERE bup_last_change_by = @userId
2076  UNION
2077  SELECT COUNT(id) AS count
2078  FROM ".$dbBackup['production_facility']."
2079  WHERE bup_last_change_by = @userId
2080  UNION
2081  SELECT COUNT(id) AS count
2082  FROM ".$dbBackup['sc_attachment']."
2083  WHERE bup_last_change_by = @userId
2084  UNION
2085  SELECT COUNT(id) AS count
2086  FROM ".$dbBackup['sc_event']."
2087  WHERE bup_last_change_by = @userId
2088  UNION
2089  SELECT COUNT(id) AS count
2090  FROM ".$dbBackup['sc_financial_donation']."
2091  WHERE bup_last_change_by = @userId
2092  UNION
2093  SELECT COUNT(id) AS count
2094  FROM ".$dbBackup['sc_material_donation']."
2095  WHERE bup_last_change_by = @userId
2096  UNION
2097  SELECT COUNT(id) AS count
2098  FROM ".$dbBackup['sc_produced_part']."
2099  WHERE bup_last_change_by = @userId
2100  UNION
2101  SELECT COUNT(id) AS count
2102  FROM ".$dbBackup['sponsor']."
2103  WHERE bup_last_change_by = @userId
2104  UNION
2105  SELECT COUNT(id) AS count
2106  FROM ".$dbBackup['sponsor_car']."
2107  WHERE bup_last_change_by = @userId
2108  UNION
2109  SELECT COUNT(id) AS count
2110  FROM ".$dbBackup['sp_production_facility']."
2111  WHERE bup_last_change_by = @userId
2112  UNION
2113  SELECT COUNT(id) AS count
2114  FROM ".$dbBackup['status']."
2115  WHERE bup_last_change_by = @userId)AS t1
2116  LIMIT 1";
2117  $stmt = $mysqli->prepare($qry);
2118  $stmt->execute();
2119  $stmt->bind_result($numOfChanges);
2120  if($stmt->fetch()) {
2121  $result = $numOfChanges;
2122  } else {
2123  $result = false;
2124  }
2125  $stmt->close();
2126 
2127  // Unset variable
2128  $qryEnd = "SET @userId = ?";
2129  $stmt = $mysqli->prepare($qryEnd);
2130  $reset = NULL;
2131  $stmt->bind_param("i",$reset);
2132  $stmt->execute();
2133  $stmt->close();
2134 
2135  return $result;
2136  }
2137 
2138  /**
2139  * Does token validation and sends a new password to the user via email
2140  * @param string $token alphanumerical token to identify the user
2141  * @author Usercake (http://usercake.com)
2142  * @author Alexander Vorndran
2143  */
2144  function acceptPasswordRequest($token) {
2145  global $successes, $errors;
2146  if ($token == "" || !validateActivationToken($token, TRUE)) {
2147  $errors[] = lang("FORGOTPASS_INVALID_TOKEN");
2148  } else {
2149  $rand_pass = getUniqueCode(15); //Get unique code
2150  $secure_pass = generateImprovedHash($rand_pass); //Generate random hash
2151  $userdetails = fetchUserDetails(NULL, $token); //Fetchs user details
2152  $mail = new UserCakeMail();
2153 
2154  //Setup our custom hooks
2155  $hooks = array(
2156  "searchStrs" => array("#GENERATED-PASS#", "#USERNAME#"),
2157  "subjectStrs" => array($rand_pass, $userdetails["user_name"])
2158  );
2159 
2160  if (!$mail->newTemplateMsg("your-lost-password.txt", $hooks)) {
2161  $errors[] = lang("MAIL_TEMPLATE_BUILD_ERROR");
2162  } else {
2163  if (!$mail->sendMail($userdetails["email"], "Neues Passwort")) {
2164  $errors[] = lang("MAIL_ERROR");
2165  } else {
2166  if (!updatePasswordFromToken($secure_pass, $token)) {
2167  $errors[] = lang("SQL_ERROR");
2168  } else {
2169  if (!flagPassword($userdetails["id"], -1)) {
2170  $errors[] = lang("SQL_ERROR");
2171  } else {
2172  $successes[] = lang("FORGOTPASS_NEW_PASS_EMAIL");
2173  }
2174  }
2175  }
2176  }
2177  }
2178  }
2179 
2180  /**
2181  * Resets the state of the password request
2182  * @param string $token alphanumerical token to identify the user
2183  * @author Usercake (http://usercake.com)
2184  * @author Alexander Vorndran
2185  */
2186  function denyPasswordRequest($token) {
2187  global $successes, $errors;
2188  if ($token == "" || !validateActivationToken($token, TRUE)) {
2189  $errors[] = lang("FORGOTPASS_INVALID_TOKEN");
2190  } else {
2191 
2192  $userdetails = fetchUserDetails(NULL, $token);
2193  switch ($userdetails['lostPasswordRequest']) {
2194  case 1:
2195  if (!flagPassword($userdetails["id"], 0)) {
2196  $errors[] = lang("SQL_ERROR");
2197  } else {
2198  $successes[] = lang("FORGOTPASS_REQUEST_CANNED");
2199  }
2200  break;
2201  case 2:
2202  if (!flagPassword($userdetails["id"], -3)) {
2203  $errors[] = lang("SQL_ERROR");
2204  } else {
2205  $successes[] = lang("FORGOTPASS_REQUEST_CANNED");
2206  }
2207  break;
2208  default:
2209  break;
2210  }
2211 
2212  }
2213  }
2214 ?>