|
eZ Publish
[4.1]
|
00001 <?php 00002 // 00003 // Definition of eZLDAPUser class 00004 // 00005 // Created on: <24-Jul-2003 15:48:06 wy> 00006 // 00007 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00008 // SOFTWARE NAME: eZ Publish 00009 // SOFTWARE RELEASE: 4.1.x 00010 // COPYRIGHT NOTICE: Copyright (C) 1999-2009 eZ Systems AS 00011 // SOFTWARE LICENSE: GNU General Public License v2.0 00012 // NOTICE: > 00013 // This program is free software; you can redistribute it and/or 00014 // modify it under the terms of version 2.0 of the GNU General 00015 // Public License as published by the Free Software Foundation. 00016 // 00017 // This program is distributed in the hope that it will be useful, 00018 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 // GNU General Public License for more details. 00021 // 00022 // You should have received a copy of version 2.0 of the GNU General 00023 // Public License along with this program; if not, write to the Free 00024 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00025 // MA 02110-1301, USA. 00026 // 00027 // 00028 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00029 // 00030 00031 /*! \file 00032 */ 00033 00034 /*! 00035 \class eZLDAPUser ezldapuser.php 00036 \ingroup eZDatatype 00037 \brief The class eZLDAPUser does 00038 00039 */ 00040 class eZLDAPUser extends eZUser 00041 { 00042 /*! 00043 Constructor 00044 */ 00045 function eZLDAPUser() 00046 { 00047 } 00048 00049 /*! 00050 \static 00051 Logs in the user if applied username and password is 00052 valid. The userID is returned if succesful, false if not. 00053 */ 00054 static function loginUser( $login, $password, $authenticationMatch = false ) 00055 { 00056 $http = eZHTTPTool::instance(); 00057 $db = eZDB::instance(); 00058 00059 if ( $authenticationMatch === false ) 00060 $authenticationMatch = eZUser::authenticationMatch(); 00061 00062 $loginEscaped = $db->escapeString( $login ); 00063 $passwordEscaped = $db->escapeString( $password ); 00064 00065 $loginLdapEscaped = self::ldap_escape( $login ); 00066 00067 $loginArray = array(); 00068 if ( $authenticationMatch & eZUser::AUTHENTICATE_LOGIN ) 00069 $loginArray[] = "login='$loginEscaped'"; 00070 if ( $authenticationMatch & eZUser::AUTHENTICATE_EMAIL ) 00071 $loginArray[] = "email='$loginEscaped'"; 00072 if ( count( $loginArray ) == 0 ) 00073 $loginArray[] = "login='$loginEscaped'"; 00074 $loginText = implode( ' OR ', $loginArray ); 00075 00076 $contentObjectStatus = eZContentObject::STATUS_PUBLISHED; 00077 00078 $ini = eZINI::instance(); 00079 $LDAPIni = eZINI::instance( 'ldap.ini' ); 00080 $databaseName = $db->databaseName(); 00081 // if mysql 00082 if ( $databaseName === 'mysql' ) 00083 { 00084 $query = "SELECT contentobject_id, password_hash, password_hash_type, email, login 00085 FROM ezuser, ezcontentobject 00086 WHERE ( $loginText ) AND 00087 ezcontentobject.status='$contentObjectStatus' AND 00088 ( ezcontentobject.id=contentobject_id OR ( password_hash_type=4 AND ( $loginText ) AND password_hash=PASSWORD('$passwordEscaped') ) )"; 00089 } 00090 else 00091 { 00092 $query = "SELECT contentobject_id, password_hash, password_hash_type, email, login 00093 FROM ezuser, ezcontentobject 00094 WHERE ( $loginText ) AND 00095 ezcontentobject.status='$contentObjectStatus' AND 00096 ezcontentobject.id=contentobject_id"; 00097 } 00098 00099 $users = $db->arrayQuery( $query ); 00100 $exists = false; 00101 if ( count( $users ) >= 1 ) 00102 { 00103 foreach ( $users as $userRow ) 00104 { 00105 $userID = $userRow['contentobject_id']; 00106 $hashType = $userRow['password_hash_type']; 00107 $hash = $userRow['password_hash']; 00108 $exists = eZUser::authenticateHash( $userRow['login'], $password, eZUser::site(), 00109 $hashType, 00110 $hash ); 00111 00112 // If hash type is MySql 00113 if ( $hashType == eZUser::PASSWORD_HASH_MYSQL and $databaseName === 'mysql' ) 00114 { 00115 $queryMysqlUser = "SELECT contentobject_id, password_hash, password_hash_type, email, login 00116 FROM ezuser, ezcontentobject 00117 WHERE ezcontentobject.status='$contentObjectStatus' AND 00118 password_hash_type=4 AND ( $loginText ) AND password_hash=PASSWORD('$passwordEscaped') "; 00119 $mysqlUsers = $db->arrayQuery( $queryMysqlUser ); 00120 if ( count( $mysqlUsers ) >= 1 ) 00121 $exists = true; 00122 } 00123 00124 eZDebugSetting::writeDebug( 'kernel-user', eZUser::createHash( $userRow['login'], $password, eZUser::site(), 00125 $hashType ), "check hash" ); 00126 eZDebugSetting::writeDebug( 'kernel-user', $hash, "stored hash" ); 00127 // If current user has been disabled after a few failed login attempts. 00128 $canLogin = eZUser::isEnabledAfterFailedLogin( $userID ); 00129 00130 if ( $exists ) 00131 { 00132 // We should store userID for warning message. 00133 $GLOBALS['eZFailedLoginAttemptUserID'] = $userID; 00134 00135 $userSetting = eZUserSetting::fetch( $userID ); 00136 $isEnabled = $userSetting->attribute( "is_enabled" ); 00137 if ( $hashType != eZUser::hashType() and 00138 strtolower( $ini->variable( 'UserSettings', 'UpdateHash' ) ) == 'true' ) 00139 { 00140 $hashType = eZUser::hashType(); 00141 $hash = eZUser::createHash( $login, $password, eZUser::site(), 00142 $hashType ); 00143 $db->query( "UPDATE ezuser SET password_hash='$hash', password_hash_type='$hashType' WHERE contentobject_id='$userID'" ); 00144 } 00145 break; 00146 } 00147 } 00148 } 00149 if ( $exists and $isEnabled and $canLogin ) 00150 { 00151 eZDebugSetting::writeDebug( 'kernel-user', $userRow, 'user row' ); 00152 $user = new eZUser( $userRow ); 00153 eZDebugSetting::writeDebug( 'kernel-user', $user, 'user' ); 00154 $userID = $user->attribute( 'contentobject_id' ); 00155 00156 eZUser::updateLastVisit( $userID ); 00157 eZUser::setCurrentlyLoggedInUser( $user, $userID ); 00158 00159 // Reset number of failed login attempts 00160 eZUser::setFailedLoginAttempts( $userID, 0 ); 00161 00162 return $user; 00163 } 00164 else if ( $LDAPIni->variable( 'LDAPSettings', 'LDAPEnabled' ) === 'true' ) 00165 { 00166 // read LDAP ini settings 00167 // and then try to bind to the ldap server 00168 00169 $LDAPDebugTrace = $LDAPIni->variable( 'LDAPSettings', 'LDAPDebugTrace' ) === 'enabled'; 00170 $LDAPVersion = $LDAPIni->variable( 'LDAPSettings', 'LDAPVersion' ); 00171 $LDAPServer = $LDAPIni->variable( 'LDAPSettings', 'LDAPServer' ); 00172 $LDAPPort = $LDAPIni->variable( 'LDAPSettings', 'LDAPPort' ); 00173 $LDAPFollowReferrals = (int) $LDAPIni->variable( 'LDAPSettings', 'LDAPFollowReferrals' ); 00174 $LDAPBaseDN = $LDAPIni->variable( 'LDAPSettings', 'LDAPBaseDn' ); 00175 $LDAPBindUser = $LDAPIni->variable( 'LDAPSettings', 'LDAPBindUser' ); 00176 $LDAPBindPassword = $LDAPIni->variable( 'LDAPSettings', 'LDAPBindPassword' ); 00177 $LDAPSearchScope = $LDAPIni->variable( 'LDAPSettings', 'LDAPSearchScope' ); 00178 00179 $LDAPLoginAttribute = strtolower( $LDAPIni->variable( 'LDAPSettings', 'LDAPLoginAttribute' ) ); 00180 $LDAPFirstNameAttribute = strtolower( $LDAPIni->variable( 'LDAPSettings', 'LDAPFirstNameAttribute' ) ); 00181 $LDAPFirstNameIsCN = $LDAPIni->variable( 'LDAPSettings', 'LDAPFirstNameIsCommonName' ) === 'true'; 00182 $LDAPLastNameAttribute = strtolower( $LDAPIni->variable( 'LDAPSettings', 'LDAPLastNameAttribute' ) ); 00183 $LDAPEmailAttribute = strtolower( $LDAPIni->variable( 'LDAPSettings', 'LDAPEmailAttribute' ) ); 00184 00185 $defaultUserPlacement = $ini->variable( "UserSettings", "DefaultUserPlacement" ); 00186 00187 $LDAPUserGroupAttributeType = strtolower( $LDAPIni->variable( 'LDAPSettings', 'LDAPUserGroupAttributeType' ) ); 00188 $LDAPUserGroupAttribute = strtolower( $LDAPIni->variable( 'LDAPSettings', 'LDAPUserGroupAttribute' ) ); 00189 00190 if ( $LDAPIni->hasVariable( 'LDAPSettings', 'Utf8Encoding' ) ) 00191 { 00192 $Utf8Encoding = $LDAPIni->variable( 'LDAPSettings', 'Utf8Encoding' ); 00193 if ( $Utf8Encoding == "true" ) 00194 $isUtf8Encoding = true; 00195 else 00196 $isUtf8Encoding = false; 00197 } 00198 else 00199 { 00200 $isUtf8Encoding = false; 00201 } 00202 00203 if ( $LDAPIni->hasVariable( 'LDAPSettings', 'LDAPSearchFilters' ) ) 00204 { 00205 $LDAPFilters = $LDAPIni->variable( 'LDAPSettings', 'LDAPSearchFilters' ); 00206 } 00207 if ( $LDAPIni->hasVariable( 'LDAPSettings', 'LDAPUserGroupType' ) and $LDAPIni->hasVariable( 'LDAPSettings', 'LDAPUserGroup' ) ) 00208 { 00209 $LDAPUserGroupType = $LDAPIni->variable( 'LDAPSettings', 'LDAPUserGroupType' ); 00210 $LDAPUserGroup = $LDAPIni->variable( 'LDAPSettings', 'LDAPUserGroup' ); 00211 } 00212 00213 $LDAPFilter = "( &"; 00214 if ( count( $LDAPFilters ) > 0 ) 00215 { 00216 foreach ( array_keys( $LDAPFilters ) as $key ) 00217 { 00218 $LDAPFilter .= "(" . $LDAPFilters[$key] . ")"; 00219 } 00220 } 00221 $LDAPEqualSign = trim($LDAPIni->variable( 'LDAPSettings', "LDAPEqualSign" ) ); 00222 $LDAPBaseDN = str_replace( $LDAPEqualSign, "=", $LDAPBaseDN ); 00223 $LDAPFilter = str_replace( $LDAPEqualSign, "=", $LDAPFilter ); 00224 $LDAPBindUser = str_replace( $LDAPEqualSign, "=", $LDAPBindUser ); 00225 00226 if ( $LDAPDebugTrace ) 00227 { 00228 $debugArray = array( 'stage' => '1/5: Connecting and Binding to LDAP server', 00229 'LDAPServer' => $LDAPServer, 00230 'LDAPPort' => $LDAPPort, 00231 'LDAPBindUser' => $LDAPBindUser, 00232 'LDAPVersion' => $LDAPVersion 00233 ); 00234 // Set debug trace mode for ldap connections 00235 if ( function_exists( 'ldap_set_option' ) ) 00236 ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7); 00237 eZDebug::writeNotice( var_export( $debugArray, true ), 'eZLDAPUser::loginUser' ); 00238 } 00239 00240 if ( function_exists( 'ldap_connect' ) ) 00241 $ds = ldap_connect( $LDAPServer, $LDAPPort ); 00242 else 00243 $ds = false; 00244 00245 if ( $ds ) 00246 { 00247 ldap_set_option( $ds, LDAP_OPT_PROTOCOL_VERSION, $LDAPVersion ); 00248 ldap_set_option( $ds, LDAP_OPT_REFERRALS, $LDAPFollowReferrals ); 00249 if ( $LDAPBindUser == '' ) 00250 { 00251 $r = ldap_bind( $ds ); 00252 } 00253 else 00254 { 00255 $r = ldap_bind( $ds, $LDAPBindUser, $LDAPBindPassword ); 00256 } 00257 if ( !$r ) 00258 { 00259 // Increase number of failed login attempts. 00260 eZDebug::writeError( 'Cannot bind to LDAP server, might be something wronge with connetion or bind user!', 'eZLDAPUser::loginUser()' ); 00261 if ( isset( $userID ) ) 00262 eZUser::setFailedLoginAttempts( $userID ); 00263 00264 $user = false; 00265 return $user; 00266 } 00267 00268 $LDAPFilter .= "($LDAPLoginAttribute=$loginLdapEscaped)"; 00269 $LDAPFilter .= ")"; 00270 00271 ldap_set_option( $ds, LDAP_OPT_SIZELIMIT, 0 ); 00272 ldap_set_option( $ds, LDAP_OPT_TIMELIMIT, 0 ); 00273 00274 $retrieveAttributes = array( $LDAPLoginAttribute, 00275 $LDAPFirstNameAttribute, 00276 $LDAPLastNameAttribute, 00277 $LDAPEmailAttribute ); 00278 if ( $LDAPUserGroupAttributeType ) 00279 $retrieveAttributes[] = $LDAPUserGroupAttribute; 00280 00281 if ( $LDAPDebugTrace ) 00282 { 00283 $debugArray = array( 'stage' => '2/5: finding user', 00284 'LDAPFilter' => $LDAPFilter, 00285 'retrieveAttributes' => $retrieveAttributes, 00286 'LDAPSearchScope' => $LDAPSearchScope, 00287 'LDAPBaseDN' => $LDAPBaseDN 00288 ); 00289 eZDebug::writeNotice( var_export( $debugArray, true ), 'eZLDAPUser::loginUser' ); 00290 } 00291 00292 if ( $LDAPSearchScope == "one" ) 00293 $sr = ldap_list( $ds, $LDAPBaseDN, $LDAPFilter, $retrieveAttributes ); 00294 else if ( $LDAPSearchScope == "base" ) 00295 $sr = ldap_read( $ds, $LDAPBaseDN, $LDAPFilter, $retrieveAttributes ); 00296 else 00297 $sr = ldap_search( $ds, $LDAPBaseDN, $LDAPFilter, $retrieveAttributes ); 00298 00299 $info = ldap_get_entries( $ds, $sr ) ; 00300 if ( $info['count'] > 1 ) 00301 { 00302 // More than one user with same uid, not allow login. 00303 eZDebug::writeWarning( 'More then one user with same uid, not allowed to login!', 'eZLDAPUser::loginUser()' ); 00304 $user = false; 00305 return $user; 00306 } 00307 else if ( $info['count'] < 1 ) 00308 { 00309 // Increase number of failed login attempts. 00310 if ( isset( $userID ) ) 00311 eZUser::setFailedLoginAttempts( $userID ); 00312 00313 // user DN was not found 00314 eZDebug::writeWarning( 'User DN was not found!', 'eZLDAPUser::loginUser()' ); 00315 $user = false; 00316 return $user; 00317 } 00318 else if ( $LDAPDebugTrace ) 00319 { 00320 $debugArray = array( 'stage' => '3/5: real authentication of user', 00321 'info' => $info 00322 ); 00323 eZDebug::writeNotice( var_export( $debugArray, true ), 'eZLDAPUser::loginUser' ); 00324 } 00325 00326 if( !$password ) 00327 { 00328 $password = crypt( microtime() ); 00329 } 00330 00331 // is it real authenticated LDAP user? 00332 if ( !@ldap_bind( $ds, $info[0]['dn'], $password ) ) 00333 { 00334 // Increase number of failed login attempts. 00335 if ( isset( $userID ) ) 00336 eZUser::setFailedLoginAttempts( $userID ); 00337 00338 eZDebug::writeWarning( "User $userID failed to login!", 'eZLDAPUser::loginUser()' ); 00339 $user = false; 00340 return $user; 00341 } 00342 00343 $extraNodeAssignments = array(); 00344 $userGroupClassID = $ini->variable( "UserSettings", "UserGroupClassID" ); 00345 00346 // default user group assigning 00347 if ( $LDAPUserGroupType != null ) 00348 { 00349 if ( $LDAPUserGroupType == "name" ) 00350 { 00351 if ( is_array( $LDAPUserGroup ) ) 00352 { 00353 foreach ( array_keys( $LDAPUserGroup ) as $key ) 00354 { 00355 $groupName = $LDAPUserGroup[$key]; 00356 $groupQuery = "SELECT ezcontentobject_tree.node_id 00357 FROM ezcontentobject, ezcontentobject_tree 00358 WHERE ezcontentobject.name like '$groupName' 00359 AND ezcontentobject.id=ezcontentobject_tree.contentobject_id 00360 AND ezcontentobject.contentclass_id=$userGroupClassID"; 00361 $groupObject = $db->arrayQuery( $groupQuery ); 00362 if ( count( $groupObject ) > 0 and $key == 0 ) 00363 { 00364 $defaultUserPlacement = $groupObject[0]['node_id']; 00365 } 00366 else if ( count( $groupObject ) > 0 ) 00367 { 00368 $extraNodeAssignments[] = $groupObject[0]['node_id']; 00369 } 00370 } 00371 } 00372 else 00373 { 00374 $groupName = $LDAPUserGroup; 00375 $groupQuery = "SELECT ezcontentobject_tree.node_id 00376 FROM ezcontentobject, ezcontentobject_tree 00377 WHERE ezcontentobject.name like '$groupName' 00378 AND ezcontentobject.id=ezcontentobject_tree.contentobject_id 00379 AND ezcontentobject.contentclass_id=$userGroupClassID"; 00380 $groupObject = $db->arrayQuery( $groupQuery ); 00381 00382 if ( count( $groupObject ) > 0 ) 00383 { 00384 $defaultUserPlacement = $groupObject[0]['node_id']; 00385 } 00386 } 00387 } 00388 else if ( $LDAPUserGroupType == "id" ) 00389 { 00390 if ( is_array( $LDAPUserGroup ) ) 00391 { 00392 foreach ( array_keys( $LDAPUserGroup ) as $key ) 00393 { 00394 $groupID = $LDAPUserGroup[$key]; 00395 $groupQuery = "SELECT ezcontentobject_tree.node_id 00396 FROM ezcontentobject, ezcontentobject_tree 00397 WHERE ezcontentobject.id='$groupID' 00398 AND ezcontentobject.id=ezcontentobject_tree.contentobject_id 00399 AND ezcontentobject.contentclass_id=$userGroupClassID"; 00400 $groupObject = $db->arrayQuery( $groupQuery ); 00401 if ( count( $groupObject ) > 0 and $key == 0 ) 00402 { 00403 $defaultUserPlacement = $groupObject[0]['node_id']; 00404 } 00405 else if ( count( $groupObject ) > 0 ) 00406 { 00407 $extraNodeAssignments[] = $groupObject[0]['node_id']; 00408 } 00409 } 00410 } 00411 else 00412 { 00413 $groupID = $LDAPUserGroup; 00414 $groupQuery = "SELECT ezcontentobject_tree.node_id 00415 FROM ezcontentobject, ezcontentobject_tree 00416 WHERE ezcontentobject.id='$groupID' 00417 AND ezcontentobject.id=ezcontentobject_tree.contentobject_id 00418 AND ezcontentobject.contentclass_id=$userGroupClassID"; 00419 $groupObject = $db->arrayQuery( $groupQuery ); 00420 00421 if ( count( $groupObject ) > 0 ) 00422 { 00423 $defaultUserPlacement = $groupObject[0]['node_id']; 00424 } 00425 } 00426 } 00427 } 00428 00429 // read group mapping LDAP settings 00430 $LDAPGroupMappingType = $LDAPIni->variable( 'LDAPSettings', 'LDAPGroupMappingType' ); 00431 $LDAPUserGroupMap = $LDAPIni->variable( 'LDAPSettings', 'LDAPUserGroupMap' ); 00432 00433 if ( !is_array( $LDAPUserGroupMap ) ) 00434 $LDAPUserGroupMap = array(); 00435 00436 // group mapping constants 00437 $ByMemberAttribute = 'SimpleMapping'; // by group's member attributes (with mapping) 00438 $ByMemberAttributeHierarhicaly = 'GetGroupsTree'; // by group's member attributes hierarhically 00439 $ByGroupAttribute = 'UseGroupAttribute'; // by user's group attribute (old style) 00440 $groupMappingTypes = array( $ByMemberAttribute, 00441 $ByMemberAttributeHierarhicaly, 00442 $ByGroupAttribute); 00443 00444 $userData =& $info[ 0 ]; 00445 00446 // default mapping using old style 00447 if ( !in_array( $LDAPGroupMappingType, $groupMappingTypes ) ) 00448 { 00449 $LDAPGroupMappingType = $ByGroupAttribute; 00450 } 00451 00452 if ( $LDAPDebugTrace ) 00453 { 00454 $debugArray = array( 'stage' => '4/5: group mapping init', 00455 'LDAPUserGroupType' => $LDAPUserGroupType, 00456 'LDAPGroupMappingType' => $LDAPGroupMappingType, 00457 'LDAPUserGroup' => $LDAPUserGroup, 00458 'defaultUserPlacement' => $defaultUserPlacement, 00459 'extraNodeAssignments' => $extraNodeAssignments 00460 ); 00461 eZDebug::writeNotice( var_export( $debugArray, true ), 'eZLDAPUser::loginUser' ); 00462 } 00463 00464 if ( $LDAPGroupMappingType == $ByMemberAttribute or 00465 $LDAPGroupMappingType == $ByMemberAttributeHierarhicaly ) 00466 { 00467 $LDAPGroupBaseDN = $LDAPIni->variable( 'LDAPSettings', 'LDAPGroupBaseDN' ); 00468 $LDAPGroupBaseDN = str_replace( $LDAPEqualSign, '=', $LDAPGroupBaseDN ); 00469 $LDAPGroupClass = $LDAPIni->variable( 'LDAPSettings', 'LDAPGroupClass' ); 00470 00471 $LDAPGroupNameAttribute = strtolower( $LDAPIni->variable( 'LDAPSettings', 'LDAPGroupNameAttribute' ) ); 00472 $LDAPGroupMemberAttribute = strtolower( $LDAPIni->variable( 'LDAPSettings', 'LDAPGroupMemberAttribute' ) ); 00473 $LDAPGroupDescriptionAttribute = strtolower( $LDAPIni->variable( 'LDAPSettings', 'LDAPGroupDescriptionAttribute' ) ); 00474 00475 $groupSearchingDepth = ( $LDAPGroupMappingType == '1' ) ? 1 : 1000; 00476 00477 // now, get all parents for currently ldap authenticated user 00478 $requiredParams = array(); 00479 $requiredParams[ 'LDAPLoginAttribute' ] = $LDAPLoginAttribute; 00480 $requiredParams[ 'LDAPGroupBaseDN' ] = $LDAPGroupBaseDN; 00481 $requiredParams[ 'LDAPGroupClass' ] = $LDAPGroupClass; 00482 $requiredParams[ 'LDAPGroupNameAttribute' ] = $LDAPGroupNameAttribute; 00483 $requiredParams[ 'LDAPGroupMemberAttribute' ] = $LDAPGroupMemberAttribute; 00484 $requiredParams[ 'LDAPGroupDescriptionAttribute' ] = $LDAPGroupDescriptionAttribute; 00485 $requiredParams[ 'ds' ] =& $ds; 00486 if ( $LDAPIni->variable( 'LDAPSettings', 'LDAPGroupRootNodeId' ) !== '' ) 00487 $requiredParams[ 'TopUserGroupNodeID' ] = $LDAPIni->variable( 'LDAPSettings', 'LDAPGroupRootNodeId' ); 00488 else 00489 $requiredParams[ 'TopUserGroupNodeID' ] = 5; 00490 00491 $groupsTree = array(); 00492 $stack = array(); 00493 $newfilter = '(&(objectClass=' . $LDAPGroupClass . ')(' . $LDAPGroupMemberAttribute . '=' . $userData['dn'] . '))'; 00494 00495 $groupsTree[ $userData['dn'] ] = array( 'data' => & $userData, 00496 'parents' => array(), 00497 'children' => array() ); 00498 00499 eZLDAPUser::getUserGroupsTree( $requiredParams, $newfilter, $userData['dn'], $groupsTree, $stack, $groupSearchingDepth ); 00500 $userRecord =& $groupsTree[ $userData['dn'] ]; 00501 00502 if ( $LDAPGroupMappingType == $ByMemberAttribute ) 00503 { 00504 if ( count( $userRecord[ 'parents' ] ) > 0 ) 00505 { 00506 $remappedGroupNames = array(); 00507 foreach ( array_keys( $userRecord[ 'parents' ] ) as $key ) 00508 { 00509 $parentGroup =& $userRecord[ 'parents' ][ $key ]; 00510 if ( isset( $parentGroup[ 'data' ][ $LDAPGroupNameAttribute ] ) ) 00511 { 00512 $ldapGroupName = $parentGroup[ 'data' ][ $LDAPGroupNameAttribute ]; 00513 if ( is_array( $ldapGroupName ) ) 00514 { 00515 $ldapGroupName = ( $ldapGroupName[ 'count' ] > 0 ) ? $ldapGroupName[ 0 ] : ''; 00516 } 00517 00518 // remap group name and check that group exists 00519 if ( array_key_exists( $ldapGroupName, $LDAPUserGroupMap ) ) 00520 { 00521 $remmapedGroupName = $LDAPUserGroupMap[ $ldapGroupName ]; 00522 $groupQuery = "SELECT ezcontentobject_tree.node_id 00523 FROM ezcontentobject, ezcontentobject_tree 00524 WHERE ezcontentobject.name like '$remmapedGroupName' 00525 AND ezcontentobject.id=ezcontentobject_tree.contentobject_id 00526 AND ezcontentobject.contentclass_id=$userGroupClassID"; 00527 $groupRow = $db->arrayQuery( $groupQuery ); 00528 00529 if ( count( $groupRow ) > 0 ) 00530 { 00531 $userRecord['new_parents'][] = $groupRow[ 0 ][ 'node_id' ]; 00532 } 00533 } 00534 } 00535 } 00536 } 00537 } 00538 else if ( $LDAPGroupMappingType == $ByMemberAttributeHierarhicaly ) 00539 { 00540 $stack = array(); 00541 self::goAndPublishGroups( $requiredParams, $userData['dn'], $groupsTree, $stack, $groupSearchingDepth, true ); 00542 } 00543 if ( isset( $userRecord['new_parents'] ) and 00544 count( $userRecord['new_parents'] ) > 0 ) 00545 { 00546 $defaultUserPlacement = $userRecord['new_parents'][0]; 00547 $extraNodeAssignments = array_merge( $extraNodeAssignments, $userRecord['new_parents'] ); 00548 } 00549 } 00550 else if ( $LDAPGroupMappingType == $ByGroupAttribute ) // old style mapping by group (employeetype) attribute 00551 { 00552 if ( $LDAPUserGroupAttributeType ) 00553 { 00554 $groupAttributeCount = $info[0][$LDAPUserGroupAttribute]['count']; 00555 if ( $LDAPUserGroupAttributeType == "name" ) 00556 { 00557 for ( $i = 0; $i < $groupAttributeCount; $i++ ) 00558 { 00559 if ( $isUtf8Encoding ) 00560 { 00561 $groupName = utf8_decode( $info[0][$LDAPUserGroupAttribute][$i] ); 00562 } 00563 else 00564 { 00565 $groupName = $info[0][$LDAPUserGroupAttribute][$i]; 00566 } 00567 if ( $groupName != null ) 00568 { 00569 $groupQuery = "SELECT ezcontentobject_tree.node_id 00570 FROM ezcontentobject, ezcontentobject_tree 00571 WHERE ezcontentobject.name like '$groupName' 00572 AND ezcontentobject.id=ezcontentobject_tree.contentobject_id 00573 AND ezcontentobject.contentclass_id=$userGroupClassID"; 00574 $groupObject = $db->arrayQuery( $groupQuery ); 00575 00576 if ( count( $groupObject ) > 0 and $i == 0 ) 00577 { 00578 $defaultUserPlacement = $groupObject[0]['node_id']; 00579 } 00580 else if ( count( $groupObject ) > 0 ) 00581 { 00582 $extraNodeAssignments[] = $groupObject[0]['node_id']; 00583 } 00584 } 00585 } 00586 } 00587 else if ( $LDAPUserGroupAttributeType == "id" ) 00588 { 00589 for ( $i = 0; $i < $groupAttributeCount; $i++ ) 00590 { 00591 if ( $isUtf8Encoding ) 00592 { 00593 $groupID = utf8_decode( $info[0][$LDAPUserGroupAttribute][$i] ); 00594 } 00595 else 00596 { 00597 $groupID = $info[0][$LDAPUserGroupAttribute][$i]; 00598 } 00599 00600 if ( $groupID != null ) 00601 { 00602 $groupName = "LDAP " . $groupID; 00603 $groupQuery = "SELECT ezcontentobject_tree.node_id 00604 FROM ezcontentobject, ezcontentobject_tree 00605 WHERE ezcontentobject.name like '$groupName' 00606 AND ezcontentobject.id=ezcontentobject_tree.contentobject_id 00607 AND ezcontentobject.contentclass_id=$userGroupClassID"; 00608 $groupObject = $db->arrayQuery( $groupQuery ); 00609 00610 if ( count( $groupObject ) > 0 and $i == 0 ) 00611 { 00612 $defaultUserPlacement = $groupObject[0]['node_id']; 00613 } 00614 else if ( count( $groupObject ) > 0 ) 00615 { 00616 $extraNodeAssignments[] = $groupObject[0]['node_id']; 00617 } 00618 } 00619 } 00620 } 00621 } 00622 } 00623 00624 // remove ' last_name' from first_name if cn is used for first name 00625 if ( $LDAPFirstNameIsCN && isset( $userData[ $LDAPFirstNameAttribute ] ) && isset( $userData[ $LDAPLastNameAttribute ] ) ) 00626 { 00627 $userData[ $LDAPFirstNameAttribute ][0] = str_replace( ' ' . $userData[ $LDAPLastNameAttribute ][0], '', $userData[ $LDAPFirstNameAttribute ][0] ); 00628 } 00629 00630 if ( isset( $userData[ $LDAPEmailAttribute ] ) ) 00631 $LDAPuserEmail = $userData[ $LDAPEmailAttribute ][0]; 00632 else if( trim( $LDAPIni->variable( 'LDAPSettings', 'LDAPEmailEmptyAttributeSuffix' ) ) ) 00633 $LDAPuserEmail = $login . $LDAPIni->variable( 'LDAPSettings', 'LDAPEmailEmptyAttributeSuffix' ); 00634 else 00635 $LDAPuserEmail = false; 00636 00637 00638 $userAttributes = array( 'login' => $login, 00639 'first_name' => isset( $userData[ $LDAPFirstNameAttribute ] ) ? $userData[ $LDAPFirstNameAttribute ][0] : false, 00640 'last_name' => isset( $userData[ $LDAPLastNameAttribute ] ) ? $userData[ $LDAPLastNameAttribute ][0] : false, 00641 'email' => $LDAPuserEmail ); 00642 00643 if ( $LDAPDebugTrace ) 00644 { 00645 $debugArray = array( 'stage' => '5/5: storing user', 00646 'userAttributes' => $userAttributes, 00647 'isUtf8Encoding' => $isUtf8Encoding, 00648 'defaultUserPlacement' => $defaultUserPlacement, 00649 'extraNodeAssignments' => $extraNodeAssignments 00650 ); 00651 eZDebug::writeNotice( var_export( $debugArray, true ), 'eZLDAPUser::loginUser' ); 00652 } 00653 00654 $oldUser = clone eZUser::currentUser(); 00655 $existingUser = eZLDAPUser::publishUpdateUser( $extraNodeAssignments, $defaultUserPlacement, $userAttributes, $isUtf8Encoding ); 00656 00657 if ( is_object( $existingUser ) ) 00658 { 00659 eZUser::setCurrentlyLoggedInUser( $existingUser, $existingUser->attribute( 'contentobject_id' ) ); 00660 } 00661 else 00662 { 00663 eZUser::setCurrentlyLoggedInUser( $oldUser, $oldUser->attribute( 'contentobject_id' ) ); 00664 } 00665 00666 ldap_close( $ds ); 00667 return $existingUser; 00668 } 00669 else 00670 { 00671 eZDebug::writeError( 'Cannot initialize connection for LDAP server', 'eZLDAPUser::loginUser()' ); 00672 $user = false; 00673 return $user; 00674 } 00675 } 00676 else 00677 { 00678 // Increase number of failed login attempts. 00679 if ( isset( $userID ) ) 00680 eZUser::setFailedLoginAttempts( $userID ); 00681 00682 eZDebug::writeWarning( 'User does not exist or LDAP is not enabled in php', 'eZLDAPUser::loginUser()' ); 00683 $user = false; 00684 return $user; 00685 } 00686 } 00687 00688 /* 00689 Static method, for internal usage only. 00690 Publishes new or update existing user 00691 */ 00692 static function publishUpdateUser( $parentNodeIDs, $defaultUserPlacement, $userAttributes, $isUtf8Encoding = false ) 00693 { 00694 $thisFunctionErrorLabel = 'eZLDAPUser.php, function publishUpdateUser()'; 00695 00696 if ( !is_array( $userAttributes ) or 00697 !isset( $userAttributes[ 'login' ] ) or empty( $userAttributes[ 'login' ] ) ) 00698 { 00699 eZDebug::writeWarning( 'Empty user login passed.', 00700 $thisFunctionErrorLabel ); 00701 return false; 00702 } 00703 00704 if ( ( !is_array( $parentNodeIDs ) or count( $parentNodeIDs ) < 1 ) and 00705 !is_numeric( $defaultUserPlacement ) ) 00706 { 00707 eZDebug::writeWarning( 'No one parent node IDs was passed for publishing new user (login = "' . 00708 $userAttributes[ 'login' ] . '")', 00709 $thisFunctionErrorLabel ); 00710 return false; 00711 } 00712 $parentNodeIDs[] = $defaultUserPlacement; 00713 $parentNodeIDs = array_unique( $parentNodeIDs ); 00714 00715 00716 $login = $userAttributes[ 'login' ]; 00717 $first_name = $userAttributes[ 'first_name' ]; 00718 $last_name = $userAttributes[ 'last_name' ]; 00719 $email = $userAttributes[ 'email' ]; 00720 00721 if ( $isUtf8Encoding ) 00722 { 00723 $first_name = utf8_decode( $first_name ); 00724 $last_name = utf8_decode( $last_name ); 00725 } 00726 00727 $user = eZUser::fetchByName( $login ); 00728 $createNewUser = ( is_object( $user ) ) ? false : true; 00729 00730 if ( $createNewUser ) 00731 { 00732 if ( !isset( $first_name ) or empty( $first_name ) or 00733 !isset( $last_name ) or empty( $last_name ) or 00734 !isset( $email ) or empty( $email ) ) 00735 { 00736 eZDebug::writeWarning( 'Cannot create user with empty first name (last name or email).', 00737 $thisFunctionErrorLabel ); 00738 return false; 00739 } 00740 00741 $ini = eZINI::instance(); 00742 $userClassID = $ini->variable( "UserSettings", "UserClassID" ); 00743 $userCreatorID = $ini->variable( "UserSettings", "UserCreatorID" ); 00744 $defaultSectionID = $ini->variable( "UserSettings", "DefaultSectionID" ); 00745 00746 $class = eZContentClass::fetch( $userClassID ); 00747 $contentObject = $class->instantiate( $userCreatorID, $defaultSectionID ); 00748 00749 $contentObject->store(); 00750 00751 $userID = $contentObjectID = $contentObject->attribute( 'id' ); 00752 00753 $version = $contentObject->version( 1 ); 00754 $version->setAttribute( 'modified', time() ); 00755 $version->setAttribute( 'status', eZContentObjectVersion::STATUS_DRAFT ); 00756 $version->store(); 00757 00758 $user = eZLDAPUser::create( $userID ); 00759 $user->setAttribute( 'login', $login ); 00760 } 00761 else 00762 { 00763 $userID = $contentObjectID = $user->attribute( 'contentobject_id' ); 00764 $contentObject = eZContentObject::fetch( $userID ); 00765 $version = $contentObject->attribute( 'current' ); 00766 } 00767 00768 //================= common part 1: start ======================== 00769 $contentObjectAttributes = $version->contentObjectAttributes(); 00770 00771 // find and set 'name' and 'description' attributes (as standard user group class) 00772 $firstNameIdentifier = 'first_name'; 00773 $lastNameIdentifier = 'last_name'; 00774 $firstNameAttribute = null; 00775 $lastNameAttribute = null; 00776 00777 foreach ( $contentObjectAttributes as $attribute ) 00778 { 00779 if ( $attribute->attribute( 'contentclass_attribute_identifier' ) == $firstNameIdentifier ) 00780 { 00781 $firstNameAttribute = $attribute; 00782 } 00783 else if ( $attribute->attribute( 'contentclass_attribute_identifier' ) == $lastNameIdentifier ) 00784 { 00785 $lastNameAttribute = $attribute; 00786 } 00787 } 00788 //================= common part 1: end ========================== 00789 00790 // If we are updating an existing user, we must find out if some data should be changed. 00791 // In that case, we must create a new version and publish it. 00792 if ( !$createNewUser ) 00793 { 00794 $userDataChanged = false; 00795 $firstNameChanged = false; 00796 $lastNameChanged = false; 00797 $emailChanged = false; 00798 00799 if ( $firstNameAttribute and $firstNameAttribute->attribute( 'data_text' ) != $first_name ) 00800 { 00801 $firstNameChanged = true; 00802 } 00803 $firstNameAttribute = false; // We will load this again from the new version we will create, if it has changed 00804 if ( $lastNameAttribute and $lastNameAttribute->attribute( 'data_text' ) != $last_name ) 00805 { 00806 $lastNameChanged = true; 00807 } 00808 $lastNameAttribute = false; // We will load this again from the new version we will create, if it has changed 00809 if ( $user->attribute( 'email' ) != $email ) 00810 { 00811 $emailChanged = true; 00812 } 00813 00814 if ( $firstNameChanged or $lastNameChanged or $emailChanged ) 00815 { 00816 $userDataChanged = true; 00817 // Create new version 00818 $version = $contentObject->createNewVersion(); 00819 $contentObjectAttributes = $version->contentObjectAttributes(); 00820 foreach ( $contentObjectAttributes as $attribute ) 00821 { 00822 if ( $attribute->attribute( 'contentclass_attribute_identifier' ) == $firstNameIdentifier ) 00823 { 00824 $firstNameAttribute = $attribute; 00825 } 00826 else if ( $attribute->attribute( 'contentclass_attribute_identifier' ) == $lastNameIdentifier ) 00827 { 00828 $lastNameAttribute = $attribute; 00829 } 00830 } 00831 } 00832 } 00833 00834 //================= common part 2: start ======================== 00835 if ( $firstNameAttribute ) 00836 { 00837 $firstNameAttribute->setAttribute( 'data_text', $first_name ); 00838 $firstNameAttribute->store(); 00839 } 00840 if ( $lastNameAttribute ) 00841 { 00842 $lastNameAttribute->setAttribute( 'data_text', $last_name ); 00843 $lastNameAttribute->store(); 00844 } 00845 00846 if ( !isset( $userDataChanged ) or $userDataChanged === true ) 00847 { 00848 $contentClass = $contentObject->attribute( 'content_class' ); 00849 $name = $contentClass->contentObjectName( $contentObject ); 00850 $contentObject->setName( $name ); 00851 } 00852 00853 if ( !isset( $emailChanged ) or $emailChanged === true ) 00854 { 00855 $user->setAttribute( 'email', $email ); 00856 } 00857 00858 $user->setAttribute( 'password_hash', "" ); 00859 $user->setAttribute( 'password_hash_type', 0 ); 00860 $user->store(); 00861 00862 $debugArray = array( 'Updating user data', 00863 'createNewUser' => $createNewUser, 00864 'userDataChanged' => isset( $userDataChanged ) ? $userDataChanged : null, 00865 'login' => $login, 00866 'first_name' => $first_name, 00867 'last_name' => $last_name, 00868 'email' => $email, 00869 'firstNameAttribute is_object' => is_object( $firstNameAttribute ), 00870 'lastNameAttribute is_object' => is_object( $lastNameAttribute ), 00871 'content object id' => $contentObjectID, 00872 'version id' => $version->attribute( 'version' ) 00873 ); 00874 eZDebug::writeNotice( var_export( $debugArray, true ), __METHOD__ ); 00875 //================= common part 2: end ========================== 00876 00877 if ( $createNewUser ) 00878 { 00879 reset( $parentNodeIDs ); 00880 // prepare node assignments for publishing new user 00881 foreach( $parentNodeIDs as $parentNodeID ) 00882 { 00883 $newNodeAssignment = eZNodeAssignment::create( array( 'contentobject_id' => $contentObjectID, 00884 'contentobject_version' => 1, 00885 'parent_node' => $parentNodeID, 00886 'is_main' => ( $defaultUserPlacement == $parentNodeID ? 1 : 0 ) ) ); 00887 $newNodeAssignment->setAttribute( 'parent_remote_id', uniqid( 'LDAP_' ) ); 00888 $newNodeAssignment->store(); 00889 } 00890 00891 $operationResult = eZOperationHandler::execute( 'content', 'publish', array( 'object_id' => $contentObjectID, 00892 'version' => 1 ) ); 00893 } 00894 else 00895 { 00896 if ( $userDataChanged ) 00897 { 00898 // Publish object 00899 $operationResult = eZOperationHandler::execute( 'content', 'publish', array( 'object_id' => $contentObjectID, 00900 'version' => $version->attribute( 'version' ) ) ); 00901 // Refetch object 00902 $contentObject = eZContentObject::fetch( $contentObjectID ); 00903 $version = $contentObject->attribute( 'current' ); 00904 } 00905 00906 $LDAPIni = eZINI::instance( 'ldap.ini' ); 00907 $keepGroupAssignment = ( $LDAPIni->hasVariable( 'LDAPSettings', 'KeepGroupAssignment' ) ) ? 00908 ( $LDAPIni->variable( 'LDAPSettings', 'KeepGroupAssignment' ) == "enabled" ) : false; 00909 00910 if ( $keepGroupAssignment == false ) 00911 { 00912 $objectIsChanged = false; 00913 00914 $db = eZDB::instance(); 00915 $db->begin(); 00916 00917 // First check existing assignments, remove any that should not exist 00918 $assignedNodesList = $contentObject->assignedNodes(); 00919 $existingParentNodeIDs = array(); 00920 foreach ( $assignedNodesList as $node ) 00921 { 00922 $parentNodeID = $node->attribute( 'parent_node_id' ); 00923 if ( !in_array( $parentNodeID, $parentNodeIDs ) ) 00924 { 00925 $node->removeThis(); 00926 $objectIsChanged = true; 00927 } 00928 else 00929 { 00930 $existingParentNodeIDs[] = $parentNodeID; 00931 } 00932 } 00933 00934 // Then check assignments that should exist, add them if they are missing 00935 foreach( $parentNodeIDs as $parentNodeID ) 00936 { 00937 if ( !in_array( $parentNodeID, $existingParentNodeIDs ) ) 00938 { 00939 $newNode = $contentObject->addLocation( $parentNodeID, true ); 00940 $newNode->updateSubTreePath(); 00941 $newNode->setAttribute( 'contentobject_is_published', 1 ); 00942 $newNode->sync(); 00943 $existingParentNodeIDs[] = $parentNodeID; 00944 $objectIsChanged = true; 00945 } 00946 } 00947 00948 // Then ensure that the main node is correct 00949 $currentMainParentNodeID = $contentObject->attribute( 'main_parent_node_id' ); 00950 if ( $currentMainParentNodeID != $defaultUserPlacement ) 00951 { 00952 $existingNode = eZContentObjectTreeNode::fetchNode( $contentObjectID, $defaultUserPlacement ); 00953 if ( !is_object( $existingNode ) ) 00954 { 00955 eZDebug::writeError( "Cannot find assigned node as $defaultUserPlacement's child.", __METHOD__ ); 00956 } 00957 else 00958 { 00959 $existingNodeID = $existingNode->attribute( 'node_id' ); 00960 $versionNum = $version->attribute( 'version' ); 00961 eZContentObjectTreeNode::updateMainNodeID( $existingNodeID, $contentObjectID, $versionNum, $defaultUserPlacement ); 00962 $objectIsChanged = true; 00963 } 00964 } 00965 00966 $db->commit(); 00967 00968 // Finally, clear object view cache if something was changed 00969 if ( $objectIsChanged ) 00970 { 00971 eZContentCacheManager::clearObjectViewCache( $contentObjectID, true ); 00972 } 00973 } 00974 } 00975 00976 eZUser::updateLastVisit( $userID ); 00977 //eZUser::setCurrentlyLoggedInUser( $user, $userID ); 00978 // Reset number of failed login attempts 00979 eZUser::setFailedLoginAttempts( $userID, 0 ); 00980 return $user; 00981 } 00982 00983 /* 00984 Static method, for internal usage only. 00985 Note: used user group class (see 'UserGroupClassID' ini setting, in 'UserSettings' section) 00986 must have name attribute with indentifier equal 'name' 00987 */ 00988 static function publishNewUserGroup( $parentNodeIDs, $newGroupAttributes, $isUtf8Encoding = false ) 00989 { 00990 $thisFunctionErrorLabel = 'eZLDAPUser.php, function publishNewUserGroup()'; 00991 $newNodeIDs = array(); 00992 00993 if ( !is_array( $newGroupAttributes ) or 00994 !isset( $newGroupAttributes[ 'name' ] ) or 00995 empty( $newGroupAttributes[ 'name' ] ) ) 00996 { 00997 eZDebug::writeWarning( 'Cannot create user group with empty name.', 00998 $thisFunctionErrorLabel ); 00999 return $newNodeIDs; 01000 } 01001 if ( !is_array( $parentNodeIDs ) or count( $parentNodeIDs ) < 1 ) 01002 { 01003 eZDebug::writeWarning( 'No one parent node IDs was passed for publishing new group (group name = "' . 01004 $newGroupAttributes[ 'name' ] . '")', 01005 $thisFunctionErrorLabel ); 01006 return $newNodeIDs; 01007 } 01008 01009 $ini = eZINI::instance(); 01010 $userGroupClassID = $ini->variable( "UserSettings", "UserGroupClassID" ); 01011 $userCreatorID = $ini->variable( "UserSettings", "UserCreatorID" ); 01012 $defaultSectionID = $ini->variable( "UserSettings", "DefaultSectionID" ); 01013 01014 $userGroupClass = eZContentClass::fetch( $userGroupClassID ); 01015 $contentObject = $userGroupClass->instantiate( $userCreatorID, $defaultSectionID ); 01016 01017 $contentObject->store(); 01018 01019 $contentObjectID = $contentObject->attribute( 'id' ); 01020 01021 reset( $parentNodeIDs ); 01022 $defaultPlacement = current( $parentNodeIDs ); 01023 array_shift( $parentNodeIDs ); 01024 01025 $nodeAssignment = eZNodeAssignment::create( array( 'contentobject_id' => $contentObjectID, 01026 'contentobject_version' => 1, 01027 'parent_node' => $defaultPlacement, 01028 'is_main' => 1 ) ); 01029 $nodeAssignment->setAttribute( 'parent_remote_id', uniqid( 'LDAP_' ) ); 01030 $nodeAssignment->store(); 01031 01032 foreach( $parentNodeIDs as $parentNodeID ) 01033 { 01034 $newNodeAssignment = eZNodeAssignment::create( array( 'contentobject_id' => $contentObjectID, 01035 'contentobject_version' => 1, 01036 'parent_node' => $parentNodeID, 01037 'is_main' => 0 ) ); 01038 $newNodeAssignment->setAttribute( 'parent_remote_id', uniqid( 'LDAP_' ) ); 01039 $newNodeAssignment->store(); 01040 } 01041 01042 $version = $contentObject->version( 1 ); 01043 $version->setAttribute( 'modified', time() ); 01044 $version->setAttribute( 'status', eZContentObjectVersion::STATUS_DRAFT ); 01045 $version->store(); 01046 01047 $contentObjectAttributes = $version->contentObjectAttributes(); 01048 01049 // find ant set 'name' and 'description' attributes (as standard user group class) 01050 $nameIdentifier = 'name'; 01051 $descIdentifier = 'description'; 01052 $nameContentAttribute = null; 01053 $descContentAttribute = null; 01054 foreach( $contentObjectAttributes as $attribute ) 01055 { 01056 if ( $attribute->attribute( 'contentclass_attribute_identifier' ) == $nameIdentifier ) 01057 { 01058 $nameContentAttribute = $attribute; 01059 } 01060 else if ( $attribute->attribute( 'contentclass_attribute_identifier' ) == $descIdentifier ) 01061 { 01062 $descContentAttribute = $attribute; 01063 } 01064 } 01065 if ( $nameContentAttribute ) 01066 { 01067 if ( $isUtf8Encoding ) 01068 $newGroupAttributes[ 'name' ] = utf8_decode( $newGroupAttributes[ 'name' ] ); 01069 $nameContentAttribute->setAttribute( 'data_text', $newGroupAttributes[ 'name' ] ); 01070 $nameContentAttribute->store(); 01071 } 01072 if ( $descContentAttribute and 01073 isset( $newGroupAttributes[ 'description' ] ) ) 01074 { 01075 if ( $isUtf8Encoding ) 01076 $newGroupAttributes[ 'description' ] = utf8_decode( $newGroupAttributes[ 'description' ] ); 01077 $descContentAttribute->setAttribute( 'data_text', $newGroupAttributes[ 'description' ] ); 01078 $descContentAttribute->store(); 01079 } 01080 01081 $operationResult = eZOperationHandler::execute( 'content', 'publish', array( 'object_id' => $contentObjectID, 01082 'version' => 1 ) ); 01083 $newNodes = eZContentObjectTreeNode::fetchByContentObjectID( $contentObjectID, true, 1 ); 01084 foreach ( $newNodes as $newNode ) 01085 { 01086 $newNodeIDs[] = $newNode->attribute( 'node_id' ); 01087 } 01088 01089 return $newNodeIDs; 01090 } 01091 01092 /* 01093 Static method, for internal usage only. 01094 Recursive, publishes groups by prepared tree of groups returned by getUserGroupsTree() method 01095 */ 01096 static function goAndPublishGroups( &$requiredParams, 01097 $curDN, 01098 &$groupsTree, 01099 &$stack, 01100 $depth, 01101 $isUser = false ) 01102 { 01103 $thisFunctionErrorLabel = 'eZLDAPUser.php, function goAndPublishGroups()'; 01104 if ( !isset( $groupsTree[ $curDN ] ) ) 01105 { 01106 eZDebug::writeError( 'Passed $curDN is not in result tree array.', 01107 $thisFunctionErrorLabel ); 01108 return false; 01109 } 01110 01111 array_push( $stack, $curDN ); 01112 $current =& $groupsTree[ $curDN ]; 01113 01114 // check the name 01115 if ( $isUser ) 01116 { 01117 $currentName = $current[ 'data' ][ $requiredParams[ 'LDAPLoginAttribute' ] ]; 01118 } 01119 else 01120 { 01121 $currentName = $current[ 'data' ][ $requiredParams[ 'LDAPGroupNameAttribute' ] ]; 01122 } 01123 01124 if ( is_array( $currentName ) and //count( $currentName ) > 1 and 01125 isset( $currentName[ 'count' ] ) and $currentName[ 'count' ] > 0 ) 01126 { 01127 $currentName = $currentName[ 0 ]; 01128 } 01129 01130 if ( empty( $currentName ) ) 01131 { 01132 eZDebug::writeWarning( "Cannot create/use group with empty name (dn = $curDN)", 01133 $thisFunctionErrorLabel ); 01134 return false; 01135 } 01136 01137 // go through parents 01138 if ( is_array( $current['parents'] ) and count( $current['parents'] ) > 0 ) 01139 { 01140 foreach( array_keys( $current['parents'] ) as $key ) 01141 { 01142 $parent =& $groupsTree[ $key ]; 01143 01144 if ( in_array( $parent['data']['dn'], $stack ) ) 01145 { 01146 $groupsTree[ '_recursion_detected_' ] = true; 01147 eZDebug::writeError( 'Recursion is detected in the user-groups tree while getting parent groups for ' . $curDN, 01148 $thisFunctionErrorLabel ); 01149 return false; 01150 } 01151 if ( isset( $parent[ 'nodes' ] ) and count( $parent[ 'nodes' ] ) > 0 ) 01152 { 01153 continue; 01154 } 01155 $ret = self::goAndPublishGroups( $requiredParams, 01156 $parent['data']['dn'], 01157 $groupsTree, 01158 $stack, 01159 $depth - 1 ); 01160 if ( isset( $groupsTree[ '_recursion_detected_' ] ) and $groupsTree[ '_recursion_detected_' ] ) 01161 { 01162 return false; 01163 } 01164 } 01165 } 01166 else 01167 { 01168 // We've reached a top node 01169 if ( !isset( $groupsTree[ 'root' ] ) ) 01170 { 01171 $groupsTree[ 'root' ] = array( 'data' => null, 01172 'parents' => null, 01173 'children' => array(), 01174 'nodes' => array( $requiredParams[ 'TopUserGroupNodeID' ] ) ); 01175 } 01176 if ( !isset( $groupsTree[ 'root' ][ 'children' ][ $curDN ] ) ) 01177 $groupsTree[ 'root' ][ 'children' ][ $curDN ] =& $current; 01178 if ( !isset( $current[ 'parents' ][ 'root' ] ) ) 01179 $current[ 'parents' ][ 'root' ] =& $groupsTree[ 'root' ]; 01180 } 01181 01182 if ( !isset( $current[ 'nodes' ] ) ) 01183 $current[ 'nodes' ] = array(); 01184 01185 $parentNodesForNew = array(); 01186 foreach( array_keys( $current[ 'parents' ] ) as $key ) 01187 { 01188 $parent =& $groupsTree[ $key ]; 01189 if ( is_array( $parent[ 'nodes' ] ) and count( $parent[ 'nodes' ] ) > 0 ) 01190 { 01191 foreach ( $parent[ 'nodes' ] as $parentNodeID ) 01192 { 01193 // fetch current parent node 01194 $parentNode = eZContentObjectTreeNode::fetch( $parentNodeID ); 01195 if ( is_object( $parentNode ) ) 01196 { 01197 $params = array( 'Depth' => 1, 01198 'AttributeFilter' => array( array( 'name', '=', $currentName ) ), 01199 'Limitation' => array() ); 01200 $nodes = eZContentObjectTreeNode::subTreeByNodeID( $params, $parentNodeID ); 01201 01202 if ( is_array( $nodes ) and count( $nodes ) > 0 and !$isUser ) 01203 { 01204 // if group with given name already exist under $parentNode then get fetch 01205 // group node and remember its ID 01206 $node =& $nodes[ 0 ]; 01207 $nodeID = $node->attribute( 'node_id' ); 01208 $current[ 'nodes' ][] = $nodeID; 01209 } 01210 else 01211 { 01212 // if not exist then remember $parentNodeID to publish a new one 01213 $parentNodesForNew[] = $parentNodeID; 01214 } 01215 } 01216 else 01217 { 01218 eZDebug::writeError( 'Cannot fetch parent node for creating new user group ' . $parentNodeID, 01219 $thisFunctionErrorLabel ); 01220 } 01221 } 01222 } 01223 else 01224 { 01225 eZDebug::writeError( "Cannot get any published parent group for group/user with name = '$currentName'" . 01226 " (dn = '" . $current[ 'data' ]['dn'] . "')", 01227 $thisFunctionErrorLabel ); 01228 } 01229 } 01230 01231 if ( count( $parentNodesForNew ) > 0 ) 01232 { 01233 if ( $isUser ) 01234 { 01235 $current[ 'new_parents' ] = $parentNodesForNew; 01236 $newNodeIDs = array(); 01237 } 01238 else 01239 { 01240 $newNodeIDs = eZLDAPUser::publishNewUserGroup( $parentNodesForNew, array( 'name' => $currentName, 01241 'description' => '' ) ); 01242 } 01243 $current[ 'nodes' ] = array_merge( $current[ 'nodes' ], $newNodeIDs ); 01244 } 01245 01246 array_pop( $stack ); 01247 return true; 01248 } 01249 01250 /* 01251 Static method, for internal usage only 01252 Recursive method, which parses tree of groups from ldap server 01253 */ 01254 static function getUserGroupsTree( &$requiredParams, 01255 $filter, 01256 $curDN, 01257 &$groupsTree, 01258 &$stack, // stack for recursion checking 01259 $depth = 0 ) 01260 { 01261 if ( $depth == 0 ) 01262 { 01263 return false; 01264 } 01265 $thisFunctionErrorLabel = 'eZLDAPUser.php, function getUserGroupsTree()'; 01266 01267 if ( !isset( $requiredParams[ 'LDAPGroupBaseDN' ] ) or empty( $requiredParams[ 'LDAPGroupBaseDN' ] ) or 01268 !isset( $requiredParams[ 'LDAPGroupClass' ] ) or empty( $requiredParams[ 'LDAPGroupClass' ] ) or 01269 !isset( $requiredParams[ 'LDAPGroupNameAttribute' ] ) or empty( $requiredParams[ 'LDAPGroupNameAttribute' ] ) or 01270 !isset( $requiredParams[ 'LDAPGroupMemberAttribute' ] ) or empty( $requiredParams[ 'LDAPGroupMemberAttribute' ] ) or 01271 !isset( $requiredParams[ 'ds' ] ) or !$requiredParams[ 'ds' ] ) 01272 { 01273 eZDebug::writeError( 'Missing one of required parameters.', 01274 $thisFunctionErrorLabel ); 01275 return false; 01276 } 01277 if ( !isset( $groupsTree[ $curDN ] ) ) 01278 { 01279 eZDebug::writeError( 'Passed $curDN is not in result tree array. Algorithm\'s usage error.', 01280 $thisFunctionErrorLabel ); 01281 return false; 01282 } 01283 array_push( $stack, $curDN ); 01284 01285 $LDAPGroupBaseDN =& $requiredParams[ 'LDAPGroupBaseDN' ]; 01286 $LDAPGroupClass =& $requiredParams[ 'LDAPGroupClass' ]; 01287 $LDAPGroupNameAttribute =& $requiredParams[ 'LDAPGroupNameAttribute' ]; 01288 $LDAPGroupMemberAttribute =& $requiredParams[ 'LDAPGroupMemberAttribute' ]; 01289 $LDAPGroupDescriptionAttribute =& $requiredParams[ 'LDAPGroupDescriptionAttribute' ]; 01290 $ds =& $requiredParams[ 'ds' ]; 01291 01292 $current =& $groupsTree[ $curDN ]; 01293 01294 $retrieveAttributes = array( $LDAPGroupNameAttribute, 01295 $LDAPGroupMemberAttribute ); 01296 $sr = ldap_search( $ds, $LDAPGroupBaseDN, $filter, $retrieveAttributes ); 01297 $entries = ldap_get_entries( $ds, $sr ); 01298 01299 if ( is_array( $entries ) and 01300 isset( $entries[ 'count' ] ) and $entries[ 'count' ] > 0 ) 01301 { 01302 $newfilter = '(&(objectClass=' . $LDAPGroupClass . ')'; 01303 01304 for ( $i = 0; $i < $entries[ 'count' ]; $i++ ) 01305 { 01306 $parent =& $entries[ $i ]; 01307 if ( is_null( $parent ) ) 01308 continue; 01309 01310 $parentDN =& $parent['dn']; 01311 if ( in_array( $parentDN, $stack ) ) 01312 { 01313 $requiredParams[ 'LDAPGroupNameAttribute' ]; 01314 01315 eZDebug::writeError( 'Recursion is detected in the user-groups tree while getting parent groups for ' . $curDN, 01316 $thisFunctionErrorLabel ); 01317 $groupsTree[ '_recursion_detected_' ] = true; 01318 return false; 01319 } 01320 01321 if ( !isset( $groupsTree[ $parentDN ] ) ) 01322 { 01323 $groupsTree[ $parentDN ] = array( 'data' => $parent, 01324 'parents' => array(), 01325 'children' => array() ); 01326 } 01327 $groupsTree[ $parentDN ][ 'children' ][ $curDN ] =& $current; 01328 $current[ 'parents' ][ $parentDN ] =& $groupsTree[ $parentDN ]; 01329 $newfilter1 = $newfilter . '(' . $LDAPGroupMemberAttribute . '=' . $parentDN . '))'; 01330 $ret = eZLDAPUser::getUserGroupsTree( $requiredParams, 01331 $newfilter1, 01332 $parentDN, 01333 $groupsTree, 01334 $stack, 01335 $depth - 1 ); 01336 if ( isset( $groupsTree[ '_recursion_detected_' ] ) and 01337 $groupsTree[ '_recursion_detected_' ] ) 01338 { 01339 return false; 01340 } 01341 } 01342 } 01343 else 01344 { 01345 // We've reached a top node 01346 if ( !isset( $groupsTree[ 'root' ] ) ) 01347 { 01348 $groupsTree[ 'root' ] = array( 'data' => null, 01349 'parents' => null, 01350 'children' => array(), 01351 'nodes' => array( $requiredParams[ 'TopUserGroupNodeID' ] ) ); 01352 } 01353 if ( !isset( $groupsTree[ 'root' ][ 'children' ][ $curDN ] ) ) 01354 $groupsTree[ 'root' ][ 'children' ][ $curDN ] =& $current; 01355 if ( !isset( $current[ 'parents' ][ 'root' ] ) ) 01356 $current[ 'parents' ][ 'root' ] =& $groupsTree[ 'root' ]; 01357 } 01358 01359 array_pop( $stack ); 01360 return true; 01361 } 01362 01363 01364 /* 01365 Based on a similar function suggested at: http://php.net/manual/en/function.ldap-search.php 01366 */ 01367 static function ldap_escape( $str, $for_dn = false ) 01368 { 01369 // see: RFC2254 01370 // http://msdn.microsoft.com/en-us/library/ms675768(VS.85).aspx 01371 // http://www-03.ibm.com/systems/i/software/ldap/underdn.html 01372 01373 if ( $for_dn ) 01374 { 01375 $metaChars = array( ',', '=', '+', '<', '>', ';', '\\', '"', '#' ); 01376 $quotedMetaChars = array( '\2c', '\3d', '\2b', '\3c', '\3e', '\3b', '\5c', '\22', '\23' ); 01377 } 01378 else 01379 { 01380 $metaChars = array( '*', '(', ')', '\\', chr(0) ); 01381 $quotedMetaChars = array( '\2a', '\28', '\29', '\5c', '\00' ); 01382 } 01383 01384 return str_replace( $metaChars, $quotedMetaChars, $str ); 01385 } 01386 01387 } 01388 01389 ?>