Code

Removed jpgraph | qpl license doesn't match our needs
[gosa.git] / gosa-core / include / functions.inc
index 23badf7125b93de8e525471e009c05e2b48e864f..bfe31d074dd4ecdd28049ffe6b6e12e94f3c466b 100644 (file)
@@ -89,6 +89,13 @@ define ("DEBUG_ACL",    128); /*! Debug level for ACL infos */
 define ("DEBUG_SI",     256); /*! Debug level for communication with gosa-si */
 define ("DEBUG_MAIL",   512); /*! Debug level for all about mail (mailAccounts, imap, sieve etc.) */
 define ("DEBUG_FAI",   1024); // FAI (incomplete)
+define ("DEBUG_RPC",   2048); /*! Debug level for communication with remote procedures */
+
+// Define shadow states
+define ("POSIX_ACCOUNT_EXPIRED", 1);
+define ("POSIX_WARN_ABOUT_EXPIRATION", 2);
+define ("POSIX_FORCE_PASSWORD_CHANGE", 4);
+define ("POSIX_DISALLOW_PASSWORD_CHANGE", 8);
 
 /* Rewrite german 'umlauts' and spanish 'accents'
    to get better results */
@@ -144,8 +151,14 @@ spl_autoload_register('__gosa_autoload');
  */
 function class_available($name)
 {
-  global $class_mapping;
-  return(isset($class_mapping[$name]));
+  global $class_mapping, $config;
+    
+  $disabled = array();
+  if($config instanceOf config && $config->configRegistry instanceOf configRegistry){
+    $disabled = $config->configRegistry->getDisabledPlugins();
+  }
+
+  return(isset($class_mapping[$name]) && !isset($disabled[$name]));
 }
 
 
@@ -203,21 +216,26 @@ function make_seed() {
  * */
 function DEBUG($level, $line, $function, $file, $data, $info="")
 {
-  if (session::global_get('debugLevel') & $level){
-    $output= "DEBUG[$level] ";
-    if ($function != ""){
-      $output.= "($file:$function():$line) - $info: ";
-    } else {
-      $output.= "($file:$line) - $info: ";
-    }
-    echo $output;
-    if (is_array($data)){
-      print_a($data);
-    } else {
-      echo "'$data'";
+    global $config;
+    $debugLevel = 0;
+    if($config instanceOf config){
+        $debugLevel = $config->get_cfg_value('core', 'debugLevel');
+    }
+    if ($debugLevel & $level){
+        $output= "DEBUG[$level] ";
+        if ($function != ""){
+            $output.= "($file:$function():$line) - $info: ";
+        } else {
+            $output.= "($file:$line) - $info: ";
+        }
+        echo $output;
+        if (is_array($data)){
+            print_a($data);
+        } else {
+            echo "'$data'";
+        }
+        echo "<br>";
     }
-    echo "<br>";
-  }
 }
 
 
@@ -308,7 +326,7 @@ function get_template_path($filename= '', $plugin= FALSE, $path= "")
 
   /* Set theme */
   if (isset ($config)){
-       $theme= $config->get_cfg_value("core","theme", "default");
+       $theme= $config->get_cfg_value("core","theme");
   } else {
        $theme= "default";
   }
@@ -647,111 +665,128 @@ function ldap_login_user ($username, $password)
 }
 
 
-/*! \brief Test if account is about to expire
+/*! \brief      Checks the posixAccount status by comparing the shadow attributes.
  *
- * \param string 'userdn' the DN of the user
- * \param string 'username' the username
- * \return int Can be one of the following values:
- *  - 1 the account is locked
- *  - 2 warn the user that the password is about to expire and he should change
- *  his password
- *  - 3 force the user to change his password
- *  - 4 user should not be able to change his password
- * */
-function ldap_expired_account($config, $userdn, $username)
+ * @param Object    The GOsa configuration object.
+ * @param String    The 'dn' of the user to test the account status for.
+ * @param String    The 'uid' of the user we're going to test.
+ * @return Const
+ *                  POSIX_ACCOUNT_EXPIRED           - If the account is expired.
+ *                  POSIX_WARN_ABOUT_EXPIRATION     - If the account is going to expire.
+ *                  POSIX_FORCE_PASSWORD_CHANGE     - The password has to be changed.
+ *                  POSIX_DISALLOW_PASSWORD_CHANGE  - The password cannot be changed right now.
+ *
+ *
+ *
+ *      shadowLastChange
+ *      |
+ *      |---- shadowMin --->    |       <-- shadowMax --
+ *      |                       |       |
+ *      |------- shadowWarning ->       |
+ *                                      |-- shadowInactive --> DEACTIVATED
+ *                                      |
+ *                                      EXPIRED
+ *
+ */
+function ldap_expired_account($config, $userdn, $uid)
 {
+    // Skip this for the admin account, we do not want to lock him out.
+    if($uid == 'admin') return(0);
+
     $ldap= $config->get_ldap_link();
+    $ldap->cd($config->current['BASE']);
     $ldap->cat($userdn);
     $attrs= $ldap->fetch();
-    
-    /* default value no errors */
-    $expired = 0;
-    
-    $sExpire = 0;
-    $sLastChange = 0;
-    $sMax = 0;
-    $sMin = 0;
-    $sInactive = 0;
-    $sWarning = 0;
-    
-    $current= date("U");
-    
-    $current= floor($current /60 /60 /24);
-    
-    /* special case of the admin, should never been locked */
-    /* FIXME should allow any name as user admin */
-    if($username != "admin")
-    {
+    $current= floor(date("U") /60 /60 /24);
 
-      if(isset($attrs['shadowExpire'][0])){
-        $sExpire= $attrs['shadowExpire'][0];
-      } else {
-        $sExpire = 0;
-      }
-      
-      if(isset($attrs['shadowLastChange'][0])){
-        $sLastChange= $attrs['shadowLastChange'][0];
-      } else {
-        $sLastChange = 0;
-      }
-      
-      if(isset($attrs['shadowMax'][0])){
-        $sMax= $attrs['shadowMax'][0];
-      } else {
-        $smax = 0;
-      }
+    // Fetch required attributes
+    foreach(array('shadowExpire','shadowLastChange','shadowMax','shadowMin',
+                'shadowInactive','shadowWarning') as $attr){
+        $$attr = (isset($attrs[$attr][0]))? $attrs[$attr][0] : null;
+    }
 
-      if(isset($attrs['shadowMin'][0])){
-        $sMin= $attrs['shadowMin'][0];
-      } else {
-        $sMin = 0;
-      }
-      
-      if(isset($attrs['shadowInactive'][0])){
-        $sInactive= $attrs['shadowInactive'][0];
-      } else {
-        $sInactive = 0;
-      }
-      
-      if(isset($attrs['shadowWarning'][0])){
-        $sWarning= $attrs['shadowWarning'][0];
-      } else {
-        $sWarning = 0;
-      }
-      
-      /* is the account locked */
-      /* shadowExpire + shadowInactive (option) */
-      if($sExpire >0){
-        if($current >= ($sExpire+$sInactive)){
-          return(1);
+
+    // Check if the account has expired.
+    // ---------------------------------
+    // An account is locked/expired once its expiration date has reached (shadowExpire).
+    // If the optional attribute (shadowInactive) is set, we've to postpone
+    //  the account expiration by the amount of days specified in (shadowInactive).
+    if($shadowExpire != null && $shadowExpire >= $current){
+
+        // The account seems to be expired, but we've to check 'shadowInactive' additionally.
+        // ShadowInactive specifies an amount of days we've to reprieve the user.
+        // It some kind of x days' grace.
+        if($shadowInactive == null || $current > $shadowExpire + $shadowInactive){
+
+            // Finally we've detect that the account is deactivated.
+            return(POSIX_ACCOUNT_EXPIRED);
         }
-      }
-    
-      /* the user should be warned to change is password */
-      if((($sExpire >0) && ($sWarning >0)) && ($sExpire >= $current)){
-        if (($sExpire - $current) < $sWarning){
-          return(2);
+    }
+
+    // The users password is going to expire.
+    // --------------------------------------
+    // We've to warn the user in the case of an expiring account.
+    // An account is going to expire when it reaches its expiration date (shadowExpire).
+    // The user has to be warned, if the days left till expiration, match the
+    //  configured warning period (shadowWarning)
+    // --> shadowWarning: Warn x days before account expiration.
+    if($shadowExpire != null && $shadowWarning != null){
+
+        // Check if the account is still active and not already expired.
+        if($shadowExpire >= $current){
+
+            // Check if we've to warn the user by comparing the remaining
+            //  number of days till expiration with the configured amount
+            //  of days in shadowWarning.
+            if(($shadowExpire - $current) <= $shadowWarning){
+                return(POSIX_WARN_ABOUT_EXPIRATION);
+            }
         }
-      }
-      
-      /* force user to change password */
-      if(($sLastChange >0) && ($sMax) >0){
-        if($current >= ($sLastChange+$sMax)){
-          return(3);
+    }
+
+    // -- I guess this is the correct detection, isn't it? 
+    if($shadowLastChange != null && $shadowWarning != null && $shadowMax != null){
+        $daysRemaining = ($shadowLastChange + $shadowMax) - $current ;
+        if($daysRemaining > 0 && $daysRemaining <= $shadowWarning){
+                return(POSIX_WARN_ABOUT_EXPIRATION);
         }
-      }
-      
-      /* the user should not be able to change is password */
-      if(($sLastChange >0) && ($sMin >0)){
-        if (($sLastChange + $sMin) >= $current){
-          return(4);
+    }
+
+
+    // Check if we've to force the user to change his password.
+    // --------------------------------------------------------
+    // A password change is enforced when the password is older than
+    //  the configured amount of days (shadowMax).
+    // The age of the current password (shadowLastChange) plus the maximum
+    //  amount amount of days (shadowMax) has to be smaller than the
+    //  current timestamp.
+    if($shadowLastChange != null && $shadowMax != null){
+
+        // Check if we've an outdated password.
+        if($current >= ($shadowLastChange + $shadowMax)){
+            return(POSIX_FORCE_PASSWORD_CHANGE);
+        }
+    }
+
+
+    // Check if we've to freeze the users password.
+    // --------------------------------------------
+    // Once a user has changed his password, he cannot change it again
+    //  for a given amount of days (shadowMin).
+    // We should not allow to change the password within GOsa too.
+    if($shadowLastChange != null && $shadowMin != null){
+
+        // Check if we've an outdated password.
+        if(($shadowLastChange + $shadowMin) >= $current){
+            return(POSIX_DISALLOW_PASSWORD_CHANGE);
         }
-      }
     }
-   return($expired);
+
+    return(0);
 }
 
 
+
 /*! \brief Add a lock for object(s)
  *
  * Adds a lock by the specified user for one ore multiple objects.
@@ -1263,7 +1298,7 @@ function eval_sizelimit()
     if (tests::is_id($_POST['new_limit']) &&
         isset($_POST['action']) && $_POST['action']=="newlimit"){
 
-      session::global_set('size_limit', validate($_POST['new_limit']));
+      session::global_set('size_limit', get_post('new_limit'));
       session::set('size_ignore', FALSE);
     }
 
@@ -1396,7 +1431,7 @@ function get_sub_department($value)
  * Example:
  * \code
  * # Determine LDAP base where systems are stored
- * $base = get_ou("core", "userRDN")  . $this->config->current['BASE'];
+ * $base = get_ou("systemManagement", "systemRDN") . $this->config->current['BASE'];
  * $ldap->cd($base);
  * \endcode
  * */
@@ -1404,24 +1439,27 @@ function get_ou($class,$name)
 {
     global $config;
 
-
-    // Check if RDN exists.
-    if(!$config->configRegistry->propertyExists($class, $name)){
+    if(!$config->configRegistry->propertyExists($class,$name)){
         trigger_error("No department mapping found for type ".$name);
         return "";
     }
 
-    $ou = $config->get_cfg_value($class,$name);
+    $ou = $config->configRegistry->getPropertyValue($class,$name);
     if ($ou != ""){
         if (!preg_match('/^[^=]+=[^=]+/', $ou)){
             $ou = @LDAP::convert("ou=$ou");
         } else {
             $ou = @LDAP::convert("$ou");
         }
+
         if(preg_match("/".preg_quote($config->current['BASE'], '/')."$/",$ou)){
             return($ou);
         }else{
-            return("$ou,");
+            if(!preg_match("/,$/", $ou)){
+                return("$ou,");
+            }else{
+                return($ou);
+            }
         }
 
     } else {
@@ -1432,31 +1470,31 @@ function get_ou($class,$name)
 
 /*! \brief Get the OU for users 
  *
- * Frontend for get_ou("core", "userRDN")  with userRDN
+ * Frontend for get_ou() with userRDN
  * */
 function get_people_ou()
 {
-  return (get_ou("core", "userRDN") );
+  return (get_ou("core", "userRDN"));
 }
 
 
 /*! \brief Get the OU for groups
  *
- * Frontend for get_ou("core", "userRDN")  with groupRDN
+ * Frontend for get_ou() with groupRDN
  */
 function get_groups_ou()
 {
-  return (get_ou("core", "userRDN") );
+  return (get_ou("core", "groupRDN"));
 }
 
 
 /*! \brief Get the OU for winstations
  *
- * Frontend for get_ou("core", "userRDN")  with sambaMachineAccountRDN
+ * Frontend for get_ou() with sambaMachineAccountRDN
  */
 function get_winstations_ou()
 {
-  return (get_ou("core", "userRDN") );
+  return (get_ou("wingeneric", "sambaMachineAccountRDN"));
 }
 
 
@@ -2174,18 +2212,37 @@ function validate($string)
 /*! \brief Evaluate the current GOsa version from the build in revision string */
 function get_gosa_version()
 {
-  global $svn_revision, $svn_path;
+    global $svn_revision, $svn_path;
 
-  /* Extract informations */
-  $revision= preg_replace('/^[^0-9]*([0-9]+)[^0-9]*$/', '\1', $svn_revision);
+    /* Extract informations */
+    $revision= preg_replace('/^[^0-9]*([0-9]+)[^0-9]*$/', '\1', $svn_revision);
+
+    // Extract the relevant part out of the svn url
+    $release= preg_replace('%^.*/gosa/(.*)/include/functions.inc.*$%', '\1', $svn_path);
+
+    // Remove stuff which is not interesting
+    if(preg_match("/gosa-core/i", $release)) $release = preg_replace("/[\/]gosa-core/i","",$release);
+
+    // A Tagged Version
+    if(preg_match("#/tags/#i", $svn_path)){
+        $release = preg_replace("/tags[\/]*/i","",$release);
+        $release = preg_replace("/\//","",$release) ;
+        return (sprintf(_("GOsa %s"),$release));
+    }
+
+    // A Branched Version
+    if(preg_match("#/branches/#i", $svn_path)){
+        $release = preg_replace("/branches[\/]*/i","",$release);
+        $release = preg_replace("/\//","",$release) ;
+        return (sprintf(_("GOsa %s snapshot (Rev %s)"),$release , bold($revision)));
+    }
+
+    // The trunk version
+    if(preg_match("#/trunk/#i", $svn_path)){
+        return (sprintf(_("GOsa development snapshot (Rev %s)"), bold($revision)));
+    }
 
-  /* Release or development? */
-  if (preg_match('%/gosa/trunk/%', $svn_path)){
-    return (sprintf(_("GOsa development snapshot (Rev %s)"), bold($revision)));
-  } else {
-    $release= preg_replace('%^.*/([^/]+)/include/functions.inc.*$%', '\1', $svn_path);
     return (sprintf(_("GOsa $release"), $revision));
-  }
 }
 
 
@@ -2748,12 +2805,12 @@ function check_schema($cfg,$rfc2307bis = FALSE)
 
     if($rfc2307bis && isset($tmp['posixGroup']['STRUCTURAL'])){
       $checks['posixGroup']['STATUS']           = FALSE;
-      $checks['posixGroup']['MSG']              = _("RFC 2307bis group schema is enabled, but the current LDAP configuration does not support it!");
-      $checks['posixGroup']['INFO']             = _("To use RFC 2307bis groups, the objectClass 'posixGroup' must be AUXILIARY.");
+      $checks['posixGroup']['MSG']              = _("RFC2307bis schema is enabled, but the current LDAP configuration does not support it!");
+      $checks['posixGroup']['INFO']             = _("To use RFC2307bis groups, the objectClass 'posixGroup' must be AUXILIARY.");
     }
     if(!$rfc2307bis && !isset($tmp['posixGroup']['STRUCTURAL'])){
       $checks['posixGroup']['STATUS']           = FALSE;
-      $checks['posixGroup']['MSG']              = _("RFC 2307bis group schema is disabled, but the current LDAP configuration supports it!");
+      $checks['posixGroup']['MSG']              = _("RFC2307bis schema is disabled, but the current LDAP configuration supports it!");
       $checks['posixGroup']['INFO']             = _("To correct this, the objectClass 'posixGroup' must be STRUCTURAL.");
     }
   }
@@ -2838,19 +2895,75 @@ function get_languages($languages_in_own_language = FALSE,$strip_region_tag = FA
  * \return string
  * */
 function get_post($name)
+{
+    if(!isset($_POST[$name])){
+        trigger_error("Requested POST value (".$name.") does not exists, you should add a check to prevent this message.");
+        return(FALSE);
+    }
+
+    // Handle Posted Arrays
+    $tmp = array();
+    if(is_array($_POST[$name]) && !is_string($_POST[$name])){
+        foreach($_POST[$name] as $key => $val){
+            if(get_magic_quotes_gpc()){
+                $val = stripcslashes($val);
+            }
+            $tmp[$key] = $val;
+        } 
+        return($tmp);
+    }else{
+
+        if(get_magic_quotes_gpc()){
+            $val = stripcslashes($_POST[$name]);
+        }else{
+            $val = $_POST[$name];
+        }
+    }
+  return($val);
+}
+
+
+/*! \brief Returns contents of the given POST variable and check magic quotes settings
+ *
+ * Depending on the magic quotes settings this returns a stripclashed'ed version of
+ * a certain POST variable.
+ *
+ * \param string 'name' the POST var to return ($_POST[$name])
+ * \return string
+ * */
+function get_binary_post($name)
 {
   if(!isset($_POST[$name])){
     trigger_error("Requested POST value (".$name.") does not exists, you should add a check to prevent this message.");
     return(FALSE);
   }
 
+  $p = str_replace('\0', '', $_POST[$name]);
   if(get_magic_quotes_gpc()){
-    return(stripcslashes(validate($_POST[$name])));
+    return(stripcslashes($p));
   }else{
-    return(validate($_POST[$name]));
+    return($_POST[$p]);
   }
 }
 
+function set_post($value)
+{
+    // Take care of array, recursivly convert each array entry.
+    if(is_array($value)){
+        foreach($value as $key => $val){
+            $value[$key] = set_post($val);
+        }
+        return($value);
+    }
+    
+    // Do not touch boolean values, we may break them.
+    if($value === TRUE || $value === FALSE ) return($value);
+
+    // Return a fixed string which can then be used in HTML fields without 
+    //  breaking the layout or the values. This allows to use '"<> in input fields.
+    return(htmlentities($value, ENT_QUOTES, 'utf-8'));
+}
+
 
 /*! \brief Return class name in correct case */
 function get_correct_class_name($cls)
@@ -2924,6 +3037,8 @@ function change_password ($dn, $password, $mode=0, $hash= "")
 
   if($test instanceOf passwordMethod){
 
+    stats::log('global', 'global', array('users'),  $action = 'change_password', $amount = 1, 0, $test->get_hash());
+
     $deactivated = $test->is_locked($config,$dn);
 
     /* Feed password backends with information */
@@ -2944,12 +3059,17 @@ function change_password ($dn, $password, $mode=0, $hash= "")
 
     // Not for groups
     if ($mode == 0){
-      // Create SMB Password
-      $attrs= generate_smb_nt_hash($password);
 
-      if ($shadow != 0){
-        $attrs['shadowLastChange']= $shadow;
-      }
+        $tmp = $config->get_cfg_value('core','sambaHashHook');
+        if(!empty($tmp)){
+
+            // Create SMB Password
+            $attrs= generate_smb_nt_hash($password);
+
+            if ($shadow != 0){
+                $attrs['shadowLastChange']= $shadow;
+            }
+        }
     }
 
     $attrs['userPassword']= array();
@@ -3008,8 +3128,19 @@ function generate_smb_nt_hash($password)
 {
   global $config;
 
-  # Try to use gosa-si?
-  if ($config->get_cfg_value("core","gosaSupportURI") != ""){
+  // First try to retrieve values via RPC 
+  if ($config->get_cfg_value("core","gosaRpcServer") != ""){
+
+    $rpc = $config->getRpcHandle();
+    $hash = $rpc->mksmbhash($password);
+    if(!$rpc->success()){
+        msg_dialog::display(_("Error"),msgPool::rpcError($rpc->get_error()),ERROR_DIALOG);
+        return("");
+    }
+
+  }elseif ($config->get_cfg_value("core","gosaSupportURI") != ""){
+
+    // Try using gosa-si
        $res= gosaSupportDaemon::send("gosa_gen_smb_hash", "GOSA", array("password" => $password), TRUE);
     if (isset($res['XML']['HASH'])){
        $hash= $res['XML']['HASH'];
@@ -3223,9 +3354,6 @@ function update_accessTo($from,$to)
   while($attrs = $ldap->fetch()){
     $new_attrs = array("accessTo" => array());
     $dn = $attrs['dn'];
-    for($i = 0 ; $i < $attrs['objectClass']['count']; $i++){
-      $new_attrs['objectClass'][] =  $attrs['objectClass'][$i];
-    }
     for($i = 0 ; $i < $attrs['accessTo']['count']; $i++){
       if($attrs['accessTo'][$i] == $from){
         if(!empty($to)){
@@ -3305,7 +3433,7 @@ function get_next_id($attrib, $dn)
 {
   global $config;
 
-  switch ($config->get_cfg_value("core","idAllocationMethod", "traditional")){
+  switch ($config->get_cfg_value("core","idAllocationMethod")){
     case "pool":
       return get_next_id_pool($attrib);
     case "traditional":
@@ -3321,8 +3449,8 @@ function get_next_id_pool($attrib) {
   global $config;
 
   /* Fill informational values */
-  $min= $config->get_cfg_value("core","${attrib}PoolMin", 10000);
-  $max= $config->get_cfg_value("core","${attrib}PoolMax", 40000);
+  $min= $config->get_cfg_value("core","${attrib}PoolMin");
+  $max= $config->get_cfg_value("core","${attrib}PoolMax");
 
   /* Sanity check */
   if ($min >= $max) {
@@ -3345,8 +3473,8 @@ function get_next_id_pool($attrib) {
     /* If it does not exist, create one with these defaults */
     if ($ldap->count() == 0) {
       /* Fill informational values */
-      $minUserId= $config->get_cfg_value("core","uidPoolMin", 10000);
-      $minGroupId= $config->get_cfg_value("core","gidPoolMin", 10000);
+      $minUserId= $config->get_cfg_value("core","uidNumberPoolMin");
+      $minGroupId= $config->get_cfg_value("core","gidNumberPoolMin");
 
       /* Add as default */
       $attrs= array("objectClass" => array("organizationalUnit", "sambaUnixIdPool"));
@@ -3496,10 +3624,10 @@ function image($path, $action= "", $title= "", $align= "middle")
 
     // Get theme
     if (isset ($config)){
-      $theme= $config->get_cfg_value("core","theme", "default");
+      $theme= $config->get_cfg_value("core","theme");
     } else {
-      # For debuging - avoid that there's no theme set
-      die("config not set!");
+
+      // Fall back to default theme
       $theme= "default";
     }