Initial work done to support negative durations, some issues remain.
[timetracker.git] / WEB-INF / lib / common.lib.php
index 3644c05..747f3e0 100644 (file)
 // | https://www.anuko.com/time_tracker/credits.htm
 // +----------------------------------------------------------------------+
 
-       /**
-        * @return unknown
-        * @param file unknown
-        * @param version = "" unknown
-        * @desc Loads a class
-        */
-       function import( $class_name ) {
-           $libs = array(
-                       dirname($_SERVER["SCRIPT_FILENAME"]),
-                       LIBRARY_DIR
-               );
+// import() function loads a class.
+function import($class_name) {
+  $libs = array(
+    dirname($_SERVER["SCRIPT_FILENAME"]),
+    LIBRARY_DIR
+  );
 
            $pos = strpos($class_name, ".");
         if (!($pos === false)) {
@@ -61,7 +56,7 @@
 
                print '<br><b>load_class: error loading file "'.$filename.'"</b>';
                die();
-       }
+}
 
        // The mu_sort function is used to sort a multi-dimensional array.
        // It looks like the code example is taken from the PHP manual http://ca2.php.net/manual/en/function.sort.php
                        die($mdb2->getMessage());
                        }
 
-                       $mdb2->setOption('debug', true);
                        $mdb2->setFetchMode(MDB2_FETCHMODE_ASSOC);
                        
                        $GLOBALS["_MDB2_CONNECTION"] = $mdb2;
        }
 
 
-       function closeConnection() {
-               if (isset($GLOBALS["_DB_CONNECTION"])) {
-                       $GLOBALS["_DB_CONNECTION"]->close();
-                       unset($GLOBALS["_DB_CONNECTION"]);
-               }
-       }
-
-function time_to_decimal($a) {
-  $tmp = explode(":", $a);
-  if($tmp[1]{0}=="0") $tmp[1] = $tmp[1]{1};
+// time_to_decimal converts a time string such as 1:15 to its decimal representation such as 1.25 or 1,25.
+function time_to_decimal($val) {
+  global $user;
+  $parts = explode(':', $val); // parts[0] is hours, parts[1] is minutes.
 
-  $m = round($tmp[1]*100/60);
+  $minutePercent = round($parts[1]*100/60); // Integer value (0-98) of percent of minutes portion in the hour.
+  if($minutePercent < 10) $minutePercent = '0'.$minutePercent; // Pad small values with a 0 to always have 2 digits.
 
-  if($m<10) $m = "0".$m;
-  $time = $tmp[0].".".$m;
-  return $time;
-}
+  $decimalTime = $parts[0].$user->decimal_mark.$minutePercent; // Construct decimal representation of time value.
 
-function sec_to_time_fmt_hm($sec)
-{
-  return sprintf("%d:%02d", $sec / 3600, $sec % 3600 / 60);
+  return $decimalTime;
 }
 
 function magic_quotes_off()
 {
-  // if (get_magic_quotes_gpc()) { // This check is now done before calling this function.
-    $_POST = array_map('stripslashes_deep', $_POST);
-    $_GET = array_map('stripslashes_deep', $_GET);
-    $_COOKIE = array_map('stripslashes_deep', $_COOKIE);
-  // }
+  $_POST = array_map('stripslashes_deep', $_POST);
+  $_GET = array_map('stripslashes_deep', $_GET);
+  $_COOKIE = array_map('stripslashes_deep', $_COOKIE);
 }
 
 // check_extension checks whether a required PHP extension is loaded and dies if not so.
@@ -178,7 +160,7 @@ function check_extension($ext)
 // isTrue is a helper function to return correct false for older config.php values defined as a string 'false'.
 function isTrue($val)
 {
-  return ($val == false || $val === 'false') ? false : true;
+  return (defined($val) && constant($val) === true);
 }
 
 // ttValidString is used to check user input to validate a string.
@@ -195,6 +177,15 @@ function ttValidString($val, $emptyValid = false)
   return true;    
 }
 
+// ttValidTemplateText is used to check template-based user input.
+// When templates are used, required input parts must be filled by user.
+// We identify these parts by 3 "stop sign" emojis (aka "octagonal sign" U+1F6D1).
+function ttValidTemplateText($val)
+{
+  $valid = strpos($val, '🛑🛑🛑') === false; // no 3 "stop sign" emojis in a row.
+  return $valid;
+}
+
 // ttValidEmail is used to check user input to validate an email string.
 function ttValidEmail($val, $emptyValid = false)
 {
@@ -239,7 +230,7 @@ function ttValidFloat($val, $emptyValid = false)
     return ($emptyValid ? true : false);
     
   global $user;
-  $decimal = $user->decimal_mark;
+  $decimal = $user->getDecimalMark();
        
   if (!preg_match('/^-?[0-9'.$decimal.']+$/', $val))
     return false;
@@ -321,29 +312,112 @@ function ttValidCronSpec($val)
   return true;
 }
 
-// ttAccessCheck is used to check whether user is allowed to proceed. This function is used
-// as an initial check on all publicly available pages.
-function ttAccessCheck($required_rights)
+// ttValidCondition is used to check user input to validate a notification condition.
+function ttValidCondition($val, $emptyValid = true)
+{
+  $val = trim($val);
+  if (strlen($val) == 0)
+    return ($emptyValid ? true : false);
+
+  // String must not be XSS evil (to insert JavaScript).
+  if (stristr($val, '<script>') || stristr($val, '<script '))
+    return false;
+
+  if (!preg_match("/^count\s?(=|[<>]=?|<>)\s?\d+$/", $val))
+    return false;
+
+  return true;
+}
+
+// ttValidIP is used to check user input to validate a comma-separated
+// list of IP subnet "prefixes", for example 192.168.0 (note: no .* in the end).
+// We keep regexp checks here simple - they are not precise.
+// For example, IPv4-mapped IPv6 addresses will fail. This may need to be fixed.
+function ttValidIP($val, $emptyValid = false)
+{
+  $val = trim($val);
+  if (strlen($val) == 0 && $emptyValid)
+    return true;
+
+  $subnets = explode(',', $val);
+  foreach ($subnets as $subnet) {
+    $ipv4 = preg_match('/^\d\d?\d?(\.\d\d?\d?){0,3}\.?$/', $subnet); // Not precise check.
+    $ipv6 = preg_match('/^([0-9a-fA-F]{4})(:[0-9a-fA-F]{4}){0,7}$/', $subnet); // Not precise check.
+    if (!$ipv4 && !$ipv6)
+      return false;
+  }
+  return true;
+}
+
+// ttAccessAllowed checks whether user is allowed access to a particular page.
+// It is used as an initial check on all publicly available pages
+// (except login.php, register.php, and others where we don't have to check).
+function ttAccessAllowed($required_right)
 {
   global $auth;
   global $user;
-  
+
   // Redirect to login page if user is not authenticated.
   if (!$auth->isAuthenticated()) {
     header('Location: login.php');
     exit();
   }
-  
-  // Check rights.
-  if (!($required_rights & $user->rights))
-    return false;
-    
-  return true;
+
+  // Check IP restriction, if set.
+  if ($user->allow_ip && !$user->can('override_allow_ip')) {
+    $access_allowed = false;
+    $user_ip = $_SERVER['REMOTE_ADDR'];
+    $allowed_ip_array = explode(',', $user->allow_ip);
+    foreach ($allowed_ip_array as $allowed_ip) {
+      $len = strlen($allowed_ip);
+      if (substr($user_ip, 0, $len) === $allowed_ip) { // startsWith check.
+         $access_allowed = true;
+         break;
+      }
+    }
+    if (!$access_allowed) return false;
+  }
+
+  // Check if user has the right.
+  if (in_array($required_right, $user->rights)) {
+    import('ttUserHelper');
+    ttUserHelper::updateLastAccess();
+    return true;
+  }
+
+  return false;
+}
+
+// ttStartsWith functions checks if a string starts with a given substring.
+function ttStartsWith($string, $startString)
+{
+    $len = strlen($startString);
+    return (substr($string, 0, $len) === $startString);
 }
 
-// ttPluginEnabled is used to check whether a plugin is enabled for user.
-function ttPluginEnabled($plugin)
+// ttEndsWith functions checks if a string ends with a given substring.
+function ttEndsWith($string, $endString)
+{
+    $len = strlen($endString);
+    if ($len == 0) return true;
+    return (substr($string, -$len) === $endString);
+}
+
+// ttDateToUserFormat converts a date from database format to user format.
+function ttDateToUserFormat($date)
 {
   global $user;
-  return in_array($plugin, explode(',', $user->plugins));
+  $o_date = new DateAndTime(DB_DATEFORMAT, $date);
+  return $o_date->toString($user->date_format);
+}
+
+// ttRandomString generates a random alphanumeric string.
+function ttRandomString($length = 32) {
+  $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+  $charactersLength = strlen($characters);
+  $randomString = '';
+  for ($i = 0; $i < $length; $i++) {
+    $randomString .= $characters[rand(0, $charactersLength - 1)];
+  }
+  return $randomString;
 }