Merge branch '2014.11' into 2015.11
[tine20] / tine20 / Tinebase / User / ActiveDirectory.php
index 15db70f..2ca44b1 100644 (file)
@@ -120,7 +120,8 @@ class Tinebase_User_ActiveDirectory extends Tinebase_User_Ldap
         $this->_domainSidPlain  = Tinebase_Ldap::decodeSid($this->_domainConfig['objectsid'][0]);
         
         $domanNameParts    = array();
-        Zend_Ldap_Dn::explodeDn($this->_domainConfig['distinguishedname'][0], $fooBar, $domanNameParts);
+        $keys = null; // not really needed
+        Zend_Ldap_Dn::explodeDn($this->_domainConfig['distinguishedname'][0], $keys, $domanNameParts);
         $this->_domainName = implode('.', $domanNameParts);
     }
     
@@ -337,27 +338,32 @@ class Tinebase_User_ActiveDirectory extends Tinebase_User_Ldap
             $plugin->inspectUpdateUser($_account, $ldapData, $ldapEntry);
         }
 
-        // no need to update this attribute, it's not allowed to change and even might not be updateable
-        unset($ldapData[$this->_userUUIDAttribute]);
-
-        if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) 
-            Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . '  $dn: ' . $ldapEntry['dn']);
-        if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) 
-            Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . '  $ldapData: ' . print_r($ldapData, true));
-
-        $this->_ldap->update($ldapEntry['dn'], $ldapData);
-        
+        // do we need to rename the entry?
+        // TODO move to rename()
         $dn = Zend_Ldap_Dn::factory($ldapEntry['dn'], null);
         $rdn = $dn->getRdn();
-        
-        // do we need to rename the entry?
         if ($rdn['CN'] != $ldapData['cn']) {
             $newDN = $this->_generateDn($_account);
-            if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) 
+            if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG))
                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . '  rename ldap entry to: ' . $newDN);
             $this->_ldap->rename($dn, $newDN);
         }
-        
+
+        // no need to update this attribute, it's not allowed to change and even might not be updateable
+        unset($ldapData[$this->_userUUIDAttribute]);
+
+        // remove cn as samba forbids updating the CN (even if it does not change...
+        // 0x43 (Operation not allowed on RDN; 00002016: Modify of RDN 'CN' on CN=...,CN=Users,DC=example,DC=org
+        // not permitted, must use 'rename' operation instead
+        unset($ldapData['cn']);
+
+        if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG))
+            Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . '  $dn: ' . $ldapEntry['dn']);
+        if (Tinebase_Core::isLogLevel(Zend_Log::TRACE))
+            Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . '  $ldapData: ' . print_r($ldapData, true));
+
+        $this->_ldap->update($ldapEntry['dn'], $ldapData);
+
         // refetch user from ldap backend
         $user = $this->getUserByPropertyFromSyncBackend('accountId', $_account, 'Tinebase_Model_FullUser');
 
@@ -380,12 +386,11 @@ class Tinebase_User_ActiveDirectory extends Tinebase_User_Ldap
             case 'objectsid':
                 return Tinebase_Ldap::decodeSid($accountId);
                 break;
-                
+
             default:
                 return $accountId;
                 break;
         }
-        
     }
     
     /**
@@ -428,7 +433,7 @@ class Tinebase_User_ActiveDirectory extends Tinebase_User_Ldap
      * @param string $_accountClass
      * @return Tinebase_Record_Abstract
      */
-    protected function _ldap2User(array $_userData, $_accountClass)
+    protected function _ldap2User(array $_userData, $_accountClass = 'Tinebase_Model_FullUser')
     {
         $errors = false;
         
@@ -443,12 +448,12 @@ class Tinebase_User_ActiveDirectory extends Tinebase_User_Ldap
                         if ($value === '0' || $value[0] === '9223372036854775807') {
                             $accountArray[$keyMapping] = null;
                         } else {
-                            $accountArray[$keyMapping] = new Tinebase_DateTime(bcsub(bcdiv($value[0], '10000000'), '11644473600'));
+                            $accountArray[$keyMapping] = self::convertADTimestamp($value[0]);
                         }
                         break;
                         
                     case 'accountLastPasswordChange':
-                        $accountArray[$keyMapping] = new Tinebase_DateTime(bcsub(bcdiv($value[0], '10000000'), '11644473600'));
+                        $accountArray[$keyMapping] = self::convertADTimestamp($value[0]);
                         break;
                         
                     case 'accountId':
@@ -496,6 +501,22 @@ class Tinebase_User_ActiveDirectory extends Tinebase_User_Ldap
         
         return $accountObject;
     }
+
+    /**
+     * convert windows nt timestamp
+     *
+     * The timestamp is the number of 100-nanoseconds intervals (1 nanosecond = one billionth of a second)
+     *  since Jan 1, 1601 UTC.
+     *
+     * @param $timestamp
+     * @return Tinebase_DateTime
+     *
+     * @see http://www.epochconverter.com/epoch/ldap-timestamp.php
+     */
+    public static function convertADTimestamp($timestamp)
+    {
+        return new Tinebase_DateTime(bcsub(bcdiv($timestamp, '10000000'), '11644473600'));
+    }
     
     /**
      * returns array of ldap data