/** * Calls any registered adapter events associated with an event group. * * @param string $dispatch Dispatcher name OR null to dispatch to all. * @param string $event The event name. * @param array $args An array of arguments. * * @return boolean Result of all function calls. * * @since 2.1 */ public static function triggerEvent($dispatch, $event, $args = null) { if (is_null($dispatch)) { $results = array(); // Loop through all dispatchers and trigger the event foreach (SHFactory::$dispatcher as $dispatcher) { array_push($results, $dispatcher->trigger($event, $args)); } } else { // Single dispatcher trigger $results = SHFactory::getDispatcher($dispatch)->trigger($event, $args); } // We want to return the actual result (false, true or blank) if (in_array(false, $results, true)) { return false; } elseif (in_array(true, $results, true)) { return true; } else { return; } }
/** * Method is called before user data is stored in the database. * * @param array $user Holds the old user data. * @param boolean $isNew True if a new user is stored. * @param array $new Holds the new user data. * * @return boolean Cancels the save if False. * * @since 2.0 */ public function onUserBeforeSave($user, $isNew, $new) { $isAdapterExisting = true; $isLdapExisting = false; // Get the correct username where new username must be used when user isNew $username = $isNew ? $new['username'] : $user['username']; try { // We want to check if this user is an existing user in an Adapter $adapter = SHFactory::getUserAdapter($username); $adapter->getId(false); } catch (Exception $e) { // We will assume this user doesnt exist in an Adapter $isAdapterExisting = false; } if ($isAdapterExisting) { // We need to check the adapter is LDAP or not $isLdapExisting = $adapter->getType('LDAP'); } if ($isLdapExisting) { $this->isLdap = true; if (SHLdapHelper::triggerEvent('onUserBeforeSave', array($user, $isNew, $new)) !== false) { try { // Commit the changes to the Adapter if present SHLdapHelper::commitChanges($adapter, true, true); SHLog::add(JText::sprintf('LIB_SHLDAPEVENTBOUNCER_DEBUG_10986', $username), 10986, JLog::DEBUG, 'ldap'); } catch (Excpetion $e) { SHLog::add($e, 10981, JLog::ERROR, 'ldap'); } // For now lets NOT block the user from logging in even with a error return true; } return false; } elseif ($isNew) { // Ask all plugins if there is a plugin willing to deal with user creation for ldap if (count($results = SHFactory::getDispatcher('ldap')->trigger('askUserCreation'))) { // First, we must create and save the user as some plugins may talk to LDAP directly and cannot be delayed $result = SHLdapHelper::triggerEvent('onUserCreation', array($new)); // Allow Ldap events to be called if ($this->isLdap = $result) { JFactory::getSession()->set('created', $username, 'ldap'); if (SHLdapHelper::triggerEvent('onUserBeforeSave', array($user, $isNew, $new)) !== false) { try { // Commit the changes to the Adapter if present $adapter = SHFactory::getUserAdapter($username); SHLdapHelper::commitChanges($adapter, true, true); } catch (Exception $e) { SHLog::add($e, 10981, JLog::ERROR, 'ldap'); } // For now lets NOT block the user from logging in even with a error return true; } } // Something went wrong with the user creation return false; } } }
/** * Loads the profile XML and passes it to the form to load the fields (excluding data). * * @param JForm $form The form to be altered. * @param array $data The associated data for the form. * * @return boolean * * @since 2.0 */ public function onContentPrepareForm($form, $data) { // Check if the profile parameter is enabled if (!$this->use_profile) { return true; } if (!($form instanceof JForm)) { $this->_subject->setError('JERROR_NOT_A_FORM'); return false; } // Check we are manipulating a valid form if (!in_array($form->getName(), $this->permittedForms)) { return true; } $showForm = true; $domain = null; // Check if this user should have a profile if ($userId = isset($data->id) ? $data->id : 0) { if (SHLdapHelper::isUserLdap($userId)) { $domain = SHUserHelper::getDomainParam($data); } else { $showForm = false; } } elseif (!JFactory::getUser()->guest) { /* * Sometimes the $data variable is not populated even when an edit is required. * This means we have to check the form post data directly for the user ID. * We do not worry about frontend registrations as we check for guest. * If there is no form posted then this could be a backend registration. */ if ($inForm = JFactory::getApplication()->input->get('jform', false, 'array')) { $id = SHUtilArrayhelper::getValue($inForm, 'id', 0, 'int'); if ($id === 0) { // Ask all plugins if there is a plugin willing to deal with user creation for ldap if (count($results = SHFactory::getDispatcher('ldap')->trigger('askUserCreation'))) { // Due to being unaware of the domain for this new user, we are forced to use the default domain $domain = SHFactory::getConfig()->get('ldap.defaultconfig'); } else { // LDAP creation not enabled $showForm = false; } } else { if (SHLdapHelper::isUserLdap($id)) { // Existing ldap user $domain = SHUserHelper::getDomainParam($id); } else { // Existing non-ldap user $showForm = false; } } } } if ($showForm) { // We have to launch the getxmlfields to correctly include languages $this->getXMLFields($domain); // Get the File and Path for the Profile XML $file = $this->getXMLFileName($domain); $xmlPath = $this->profile_base . '/' . $file . '.xml'; // Load in the profile XML file to the form if (($xml = JFactory::getXML($xmlPath, true)) && ($form->load($xml, false, false))) { // Successfully loaded in the XML return true; } } }
if (!defined('SHLDAP_VERSION')) { // Define the JMapMyLDAP version define('SHLDAP_VERSION', SHFactory::getConfig()->get('ldap.version')); } // Load the global Ldap language file JFactory::getLanguage()->load('shmanic_ldap', JPATH_ROOT); // Push the reqcert setting if defined if ($reqcert = (int) SHFactory::getConfig()->get('ldap.reqcert', 0)) { if ($reqcert === 1) { putenv('LDAPTLS_REQCERT=never'); } elseif ($reqcert === 2) { putenv('LDAPTLS_REQCERT=allow'); } elseif ($reqcert === 3) { putenv('LDAPTLS_REQCERT=try'); } elseif ($reqcert === 4) { putenv('LDAPTLS_REQCERT=hard'); } } // Setup and get the Ldap dispatcher $dispatcher = SHFactory::getDispatcher('ldap'); // Start the LDAP event debugger only if global jdebug is switched on if (defined('JDEBUG') && JDEBUG && class_exists('SHLdapEventDebug')) { new SHLdapEventDebug($dispatcher); } // Import the Ldap group and use the ldap dispatcher JPluginHelper::importPlugin('ldap', null, true, $dispatcher); // Employ the event bouncer to control the global Joomla event triggers if (class_exists('SHLdapEventBouncer')) { $dispatcher = JDispatcher::getInstance(); $instance = new SHLdapEventBouncer($dispatcher); }
/** * Return specified user attributes from LDAP. * * @param string|array $input Optional string or array of attributes to return. * @param boolean $null Include null or non existent values. * @param boolean $changes Use the attribute changes (before change commit). * * @return mixed Ldap attribute results. * * @since 2.0 * @throws SHLdapException */ public function getAttributes($input = null, $null = false, $changes = false) { if (is_null($this->_dn)) { $this->getId(false); } elseif ($this->_dn instanceof Exception) { // Do not retry. Ldap configuration or user has problems. throw $this->_dn; } $needToFind = array(); $inputFilled = array(); if (!is_null($input)) { // Have to make sure that unless its null then its in an array $input = is_string($input) ? array($input) : $input; $inputFilled = array_fill_keys($input, null); // This array is what we must find (i.e. not in the cached variable) $needToFind = (array_keys(array_diff_key($inputFilled, $this->_attributes))); /* * Combines the current cached attributes with the input attributes with null values. * This will stop the input values from being re-queried on another method call even * if they don't exist. */ $this->_attributes = (array_merge($inputFilled, $this->_attributes)); } /* * We use the "plugin get attributes" method for efficiency purposes. On the * first execution of this method, we attempt to gather Ldap user attributes * that are required from this call in addition to what the Ldap plugins require. * * This means we should only have to call for the user attributes once from Ldap. */ if ($this->_usePlugins) { // Only run the sequence once $this->_usePlugins = false; /* * -- Get the Ldap user attributes via plugins -- * This section will get an array of user detail attributes for the user * using Ldap plugins to help with discovery of required Ldap attributes. */ $extras = SHFactory::getDispatcher('ldap')->trigger( 'onLdapBeforeRead', array(&$this, array('dn' => $this->_dn, 'source' => __METHOD__)) ); // For each of the LDAP plug-ins returned, merge their extra attributes. foreach ($extras as $extra) { $needToFind = array_merge($needToFind, $extra); } // Add both of the uid and fullname to the set of attributes to get. $needToFind[] = $this->client->ldap_fullname; $needToFind[] = $this->client->ldap_uid; // Check for a fake email $fakeEmail = (strpos($this->client->ldap_email, (SHLdap::USERNAME_REPLACE)) !== false) ? true : false; // Add the email attribute only if not a fake email is supplied. if (!$fakeEmail) { $needToFind[] = $this->client->ldap_email; } // Re-order array to ensure an LDAP read is successful and no duplicates exist. $needToFind = array_values(array_unique($needToFind)); // Swap the attribute names to array keys ready for the result $filled = array_fill_keys($needToFind, null); /* * Combines the current cached attributes with the input attributes with null values. * This will stop the input values from being re-queried on another method call even * if they don't exist. */ $this->_attributes = (array_merge($filled, $this->_attributes)); // Get Ldap user attributes $result = $this->client->read($this->_dn, null, $needToFind); if ($result->countEntries()) { // Merge the extra attributes to the cache ready for returning $this->_attributes = array_replace($this->_attributes, array_intersect_key($result->getEntry(0), $this->_attributes)); } /* * Save any attributes that weren't found in Ldap and then make it unique * so theres no duplicates in the null attributes list. */ $unreturnedVals = array_diff($needToFind, array_keys($result->getEntry(0, array()))); $this->_nullAttributes = array_merge(array_diff($unreturnedVals, $this->_nullAttributes), $this->_nullAttributes); if ($fakeEmail) { // Inject the fake email by replacing the username placeholder with the username from ldap $email = str_replace(SHLdap::USERNAME_REPLACE, $this->_attributes[$this->client->ldap_uid][0], $this->client->ldap_email); $this->_attributes[$this->client->ldap_email] = array($email); // As the last instruction from the fakeEmail condition added email to null, lets remove it if (($index = array_search($this->client->ldap_email, $this->_nullAttributes)) !== false) { unset ($this->_nullAttributes[$index]); } } if (SHLdapHelper::triggerEvent( 'onLdapAfterRead', array(&$this, &$this->_attributes, array('dn' => $this->_dn, 'source' => __METHOD__)) ) === false) { // Cancelled login due to plug-in throw new RuntimeException(JText::_('LIB_SHUSERADAPTERSLDAP_ERR_10912'), 10912); } // Blank need to find as there isn't anything more need finding $needToFind = array(); } // Check if extra attributes are required if (count($needToFind)) { $result = $this->client->read($this->_dn, null, $needToFind); if ($result->countEntries()) { // Merge the extra attributes to the cache ready for returning $this->_attributes = array_replace($this->_attributes, array_intersect_key($result->getEntry(0), $this->_attributes)); } /* * Save any attributes that weren't found in Ldap and then make it unique * so theres no duplicates in the null attributes list. */ $unreturnedVals = array_diff($needToFind, array_keys($result->getEntry(0, array()))); $this->_nullAttributes = array_merge(array_diff($unreturnedVals, $this->_nullAttributes), $this->_nullAttributes); } else { // If there are no attributes then get them all from LDAP if (!count($this->_attributes)) { $this->_attributes = $this->client->read($this->_dn, null)->getEntry(0, array()); } } $return = $this->_attributes; // Remove null values from the attributes if we dont want them if (!$null) { $return = array_diff_key($this->_attributes, array_flip($this->_nullAttributes)); $inputFilled = array_diff_key($inputFilled, array_flip($this->_nullAttributes)); } // Include staged changes to the attributes $return = $changes ? array_merge($return, $this->_changes) : $return; // Returns only the specified inputs unless all attributes are wanted return is_null($input) ? $return : array_replace($inputFilled, array_intersect_key($return, $inputFilled)); }
/** * Calls any registered Ldap events associated with an event group. * * @param string $event The event name. * @param array $args An array of arguments. * * @return boolean Result of all function calls. * * @since 2.0 */ public static function triggerEvent($event, $args = null) { $results = SHFactory::getDispatcher('ldap')->trigger($event, $args); // We want to return the actual result (false, true or blank) if (in_array(false, $results, true)) { return false; } elseif (in_array(true, $results, true)) { return true; } else { return; } }