?`~'); ////////////////////////////////////////////////////////////////////////////// // Core API hooks /** * Implementation of hook_help(). */ function ldapprov_help($path, $arg) { switch ($path) { case 'user/validate': return '

'. t('Please check your e-mail and click the link in the message to confirm your address. If you are unable to click the link, you can copy the secret code from the e-mail and enter it below.') .'

'; } } /** * Implementation of hook_init(). */ function ldapprov_init() { // Initiates LDAP object. if (LDAPPROV_ENABLED) { include_once(drupal_get_path('module', 'ldapprov') .'/ldapprov.conf.inc'); _ldapprov_init(); } } /** * Implementation of hook_perm(). */ function ldapprov_perm() { return array(LDAPPROV_PERMISSION, LDAPPROV_ROLE_PERMISSION); } /** * Implementation of hook_theme(). */ function ldapprov_theme() { return array( 'ldapprov_list_form' => array( 'arguments' => array('form' => NULL), 'file' => 'ldapprov.theme.inc', ), ); } /** * Implementation of hook_menu(). */ function ldapprov_menu() { return array( 'admin/settings/ldapprov' => array( 'title' => 'LDAP Provisioning', 'description' => 'Configure LDAP provisioning settings.', 'page callback' => 'drupal_get_form', 'page arguments' => array('ldapprov_admin_settings'), 'access arguments' => array('administer site configuration'), 'file' => 'ldapprov.admin.inc', ), 'admin/user/accounts' => array( 'title' => 'Account management', 'description' => 'Configure LDAP provisioning accounts.', 'page callback' => 'ldapprov_list', 'access arguments' => array(LDAPPROV_PERMISSION), 'weight' => -1, ), 'admin/user/accounts/pending' => array( 'title' => 'Pending', 'type' => MENU_DEFAULT_LOCAL_TASK, ), 'admin/user/accounts/pending/create' => array( 'page callback' => 'drupal_get_form', 'page arguments' => array('ldapprov_create', 3), 'access arguments' => array(LDAPPROV_PERMISSION), 'type' => MENU_LOCAL_TASK, ), 'admin/user/accounts/created' => array( 'title' => 'Created', 'page callback' => 'ldapprov_list', 'page arguments' => array(3), 'access arguments' => array(LDAPPROV_PERMISSION), 'type' => MENU_LOCAL_TASK, 'weight' => 1, ), 'admin/user/accounts/created/create' => array( 'page callback' => 'drupal_get_form', 'page arguments' => array('ldapprov_create', 3), 'access arguments' => array(LDAPPROV_PERMISSION), 'type' => MENU_LOCAL_TASK, ), 'admin/user/accounts/rejected' => array( 'title' => 'Rejected', 'page callback' => 'ldapprov_list', 'page arguments' => array(3), 'access arguments' => array(LDAPPROV_PERMISSION), 'type' => MENU_LOCAL_TASK, 'weight' => 2, ), 'admin/user/accounts/rejected/create' => array( 'page callback' => 'drupal_get_form', 'page arguments' => array('ldapprov_create', 3), 'access arguments' => array(LDAPPROV_PERMISSION), 'type' => MENU_LOCAL_TASK, ), 'admin/user/accounts/deleted' => array( 'title' => 'Deleted', 'page callback' => 'ldapprov_list', 'page arguments' => array(3), 'access arguments' => array(LDAPPROV_PERMISSION), 'type' => MENU_LOCAL_TASK, 'weight' => 3, ), 'admin/user/accounts/deleted/create' => array( 'page callback' => 'drupal_get_form', 'page arguments' => array('ldapprov_create', 3), 'access arguments' => array(LDAPPROV_PERMISSION), 'type' => MENU_LOCAL_TASK, ), 'admin/user/accounts/unverified' => array( 'title' => 'Unverified', 'page callback' => 'ldapprov_list', 'page arguments' => array(3), 'access arguments' => array(LDAPPROV_PERMISSION), 'type' => MENU_LOCAL_TASK, 'weight' => 4, ), 'admin/user/accounts/unverified/create' => array( 'title' => 'Create', 'page callback' => 'drupal_get_form', 'page arguments' => array('ldapprov_create', 3), 'access arguments' => array(LDAPPROV_PERMISSION), 'type' => MENU_LOCAL_TASK, ), 'admin/user/accounts/new' => array( 'title' => 'New', 'page callback' => 'drupal_get_form', 'page arguments' => array('ldapprov_create', 3), 'access arguments' => array(LDAPPROV_PERMISSION), 'type' => MENU_LOCAL_TASK, 'weight' => 5, ), 'ldapprov/template' => array( 'title' => 'Batch upload file template', 'page callback' => '_ldapprov_template', 'page arguments' => array(2), 'access arguments' => array(LDAPPROV_PERMISSION), 'type' => MENU_CALLBACK, ), ); } /** * Implementation of hook_menu_alter(). */ function ldapprov_menu_alter(&$callbacks) { // LDAPPROV_ENABLED won't work here because the variable. // is changed on settings save. if (variable_get('ldapprov_enabled', 0)) { // Take over the registration form. $callbacks['user/register']['page arguments'] = array('ldapprov_register', 2); unset($callbacks['user/register']['file']); // Secret code validation. $callbacks['user/validate'] = array( 'title' => 'Validate e-mail', 'page callback' => 'drupal_get_form', 'page arguments' => array('ldapprov_code', 2), 'access callback' => 'user_register_access', 'type' => MENU_LOCAL_TASK, ); } if (variable_get('ldapprov_enabled', 0) && variable_get('ldapprov_disable_create', 0)) { unset($callbacks['admin/user/user/create']); } } /** * Implementation of hook_user(). */ function ldapprov_user($op, &$edit, &$account, $category = NULL) { if (LDAPPROV_ENABLED) { switch ($op) { case 'delete': _ldapprov_user_delete($edit, $account); break; case 'validate': if (isset($edit['ldap_dn']) && $account->ldap_dn != $edit['ldap_dn']) { _ldapprov_user_validate($edit, $account); } break; case 'update': // This code should live in ldapauth module. if (isset($edit['name']) && $account->name != $edit['name']) { db_query("UPDATE {authmap} SET authname = '%s' WHERE module = 'ldapauth' AND uid = %d", $edit['name'], $account->uid); } if (isset($edit['ldap_dn']) && $account->ldap_dn != $edit['ldap_dn']) { _ldapprov_user_update($edit, $account); } break; } } } /** * Implementation of hook_mail(). */ function ldapprov_mail($key, &$message, $params) { $language = $message['language']; $account = $params['account'] ? $params['account'] : (object)array(); $variables = array_merge(user_mail_tokens($account, $language), $params['variables'] ? $params['variables'] : array()); $message['subject'] .= _ldapprov_mail_text($key .'_subject', $language, $variables); $message['body'][] = _ldapprov_mail_text($key .'_body', $language, $variables); } ////////////////////////////////////////////////////////////////////////////// // Mail strings /** * Returns a mail string for a variable name. * * Used by ldapprov_mail() and the settings forms to retrieve strings. */ function _ldapprov_mail_text($key, $language = NULL, $variables = array()) { $langcode = isset($language) ? $language->language : NULL; if ($admin_setting = variable_get('ldapprov_mail_'. $key, FALSE)) { // An admin setting overrides the default string. return strtr($admin_setting, $variables); } else { // No override, return default string. switch ($key) { case 'code_subject': return t('Validate your e-mail at !site', $variables, $language->language); case 'code_body': return t("!first_name !last_name,\n\nThank you for registering at !site. You may now validate your e-mail address by entering the code\n\n!code\n\nat !validate_uri (by copying and pasting).\n\nYou may also validate the e-mail by clicking on this link or copying and pasting it in your browser:\n\n!validate_url\n\n-- !site team", $variables, $language->language); case 'reject_subject': return t('Your request at !site has been rejected', $variables, $language->language); case 'reject_body': return t("!first_name !last_name,\n\nSorry, but your account request at !site has been rejected. Please resubmit the registration form with more information.\n\n-----\n\n!message\n\n-- !site team", $variables, $language->language); case 'notify_subject': return t('New account request at !site', $variables, $language->language); case 'notify_body': return t("!first_name !last_name (!mailto) has requested the account at !site.\n\nClick this link !create_url to process the request.", $variables, $language->language); case 'create_subject': return t('The account has been created for you at !site', $variables, $language->language); case 'create_body': return t("!first_name !last_name,\n\nThe account at !site has been created for you. You may now log in to !login_uri using the following username and password:\n\nusername: !username\npassword: !password\n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\n-----\n\n!message\n\n-- !site team", $variables, $language->language); case 'delete_subject': return t('Your account has been deleted at !site', $variables, $language->language); case 'delete_body': return t("!first_name !last_name,\n\nYour account !username has been deleted at !site.\n\n-- !site team", $variables, $language->language); } } } ////////////////////////////////////////////////////////////////////////////// // Account actions /** * User validate action. */ function _ldapprov_user_validate(&$edit, &$account) { global $_ldapprov_ldap; $name = _ldapprov_get_name_from_dn($edit['ldap_dn']); // Search for the entry in LDAP. if (isset($name)) { if (!$_ldapprov_ldap->connect(LDAPPROV_DN, LDAPPROV_PASS)) { watchdog('ldapprov', 'User validate: user data could not be read in the LDAP directory. Could not bind as %dn.', array('%dn' => LDAPPROV_DN), WATCHDOG_ERROR); form_set_error('ldap_dn', t('User data could not be read in the LDAP directory. Please contact site administrator.')); return; } $basedn = $_ldapprov_ldap->getOption('basedn'); $name_attr = $_ldapprov_ldap->getOption('user_attr') ? $_ldapprov_ldap->getOption('user_attr') : LDAP_DEFAULT_USER_ATTRIBUTE; if ($ret = $_ldapprov_ldap->search($basedn, '('. $name_attr .'='. $name .')', array($name_attr))) { form_set_error('ldap_dn', t('The DN %name is already taken in LDAP.', array('%name' => $edit['ldap_dn']))); } $_ldapprov_ldap->disconnect(); } } /** * User update action. */ function _ldapprov_user_update(&$edit, &$account) { global $_ldapprov_ldap; if (!$_ldapprov_ldap->connect(LDAPPROV_DN, LDAPPROV_PASS)) { watchdog('ldapprov', 'User update: user data could not be read in the LDAP directory. Could not bind as %dn.', array('%dn' => LDAPPROV_DN), WATCHDOG_ERROR); drupal_set_message(t('User update: user data could not be read in the LDAP directory. Please contact site administrator.'), 'error'); return; } $basedn = $_ldapprov_ldap->getOption('basedn'); $name_attr = $_ldapprov_ldap->getOption('user_attr') ? $_ldapprov_ldap->getOption('user_attr') : LDAP_DEFAULT_USER_ATTRIBUTE; $name = _ldapprov_get_name_from_dn($edit['ldap_dn']); if (!$_ldapprov_ldap->rename_entry($account->ldap_dn, $name_attr .'='. $name, $basedn, TRUE)) { watchdog('ldapprov', 'User update: user %name ldap entry cannot be renamed.', array('%name' => $account->name), WATCHDOG_ERROR); } $_ldapprov_ldap->disconnect(); } /** * User delete action. */ function _ldapprov_user_delete(&$edit, &$account) { global $user, $_ldapprov_ldap; if (!$_ldapprov_ldap->connect(LDAPPROV_DN, LDAPPROV_PASS)) { watchdog('ldapprov', 'User deletion: user data could not be read in the LDAP directory. Could not bind as %dn.', array('%dn' => LDAPPROV_DN), WATCHDOG_ERROR); drupal_set_message(t('The user !name has not been deleted from the LDAP directory.', array('!name' => theme('username', $account))), 'error'); return; } $basedn = $_ldapprov_ldap->getOption('basedn'); $name_attr = $_ldapprov_ldap->getOption('user_attr') ? $_ldapprov_ldap->getOption('user_attr') : LDAP_DEFAULT_USER_ATTRIBUTE; $name = _ldapprov_get_name_from_dn($account->ldap_dn); if ($ret = $_ldapprov_ldap->search($basedn, '('. $name_attr .'='. $name .')', array($name_attr))) { if ($_ldapprov_ldap->delete_entry($account->ldap_dn)) { watchdog('ldapprov', 'User deletion: user %name has been deleted from the LDAP directory.', array('%name' => $account->name), WATCHDOG_WARNING); } else { watchdog('ldapprov', 'User deletion: user %name has not been deleted from the LDAP directory.', array('%name' => $account->name), WATCHDOG_ERROR); drupal_set_message(t('The user !name has not been deleted from the LDAP directory.', array('!name' => theme('username', $account))), 'error'); } } else { watchdog('ldapprov', 'User deletion: user %name is not found in LDAP directory.', array('%name' => $account->name), WATCHDOG_WARNING, l(t('edit'), 'user/'. $account->uid .'/edit'), WATCHDOG_ERROR); } $_ldapprov_ldap->disconnect(); // Mark registration entry as deleted. $time = time(); $result = db_query("SELECT * FROM {ldapprov} WHERE uid = %d", $account->uid); if ($row = db_fetch_object($result)) { db_query("UPDATE {ldapprov} SET name = '%s', status = '4', cuid = %d, cname = '%s', approved = %d WHERE rid = %d", $account->name, $user->uid, $user->name, $time, $row->rid); } else { db_query("INSERT INTO {ldapprov} (name, mail, status, registered, approved, cuid, cname) VALUES ('%s', '%s', '4', %d, %d, %d, '%s')", $account->name, $account->mail, $time, $time, $user->uid, $user->name); } // Mail one time deletion notification. $variables = array('!first_name' => $row->first_name, '!last_name' => $row->last_name); $params = array('account' => $account, 'variables' => $variables); $message = drupal_mail('ldapprov', 'delete', $account->mail, user_preferred_language($account), $params); if ($message['result']) { watchdog('ldapprov', 'Account deletion notification e-mail mailed to %name at %mail.', array('%name' => $account->name, '%mail' => $account->mail)); } else { watchdog('ldapprov', 'Error mailing account deletion notification to %name at %mail.', array('%name' => $account->name, '%mail' => $account->mail), WATCHDOG_ERROR); } // If this user has created other users, then capture his name in the db for the record. db_query("UPDATE {ldapprov} SET cname = '%s' WHERE cuid = %d", $account->name, $account->uid); } ////////////////////////////////////////////////////////////////////////////// // LDAP related functions /** * Initiates LDAP object. * * @return */ function _ldapprov_init() { global $_ldapprov_ldap; $server = _ldapprov_get_server(); $_ldapprov_ldap = new LDAPInterface(); $_ldapprov_ldap->setOption('name', $server->name); $_ldapprov_ldap->setOption('server', $server->server); $_ldapprov_ldap->setOption('port', $server->port); $_ldapprov_ldap->setOption('tls', $server->tls); $_ldapprov_ldap->setOption('encrypted', $server->encrypted); $_ldapprov_ldap->setOption('basedn', $server->basedn); $_ldapprov_ldap->setOption('user_attr', $server->user_attr); $_ldapprov_ldap->setOption('mail_attr', $server->mail_attr); } /** * Load server settings. * * @return * An obgject with the server settings. */ function _ldapprov_get_server() { $result = db_query("SELECT * FROM {ldapauth} WHERE sid = %d", LDAPPROV_SERVER); return db_fetch_object($result); } /** * Get a user name from a dn. * * @param $dn * A LDAP dn. * * @return * A username. */ function _ldapprov_get_name_from_dn($dn) { global $_ldapprov_ldap; $name_attr = $_ldapprov_ldap->getOption('user_attr') ? $_ldapprov_ldap->getOption('user_attr') : LDAP_DEFAULT_USER_ATTRIBUTE; foreach (explode(',', $dn) as $entry) { list($key, $val) = explode('=', trim($entry)); if ($key == $name_attr) { $name = $val; break; } } return $name; } ////////////////////////////////////////////////////////////////////////////// // USER REGISTRATION /** * User registration form. * * @param $form_state * A form state array. * @param $code * A secret code. Correct code means that email is already validated. * * @result * A form array. */ function ldapprov_register(&$form_state, $code = FALSE) { $form = array(); // User registration guidelines from User settings. $form['user_registration_help'] = array( '#value' => filter_xss_admin(variable_get('user_registration_help', '')), ); // Main registration form. $form = array_merge($form, _ldapprov_register_form()); $form['submit'] = array( '#type' => 'submit', '#value' => t('Request new account'), '#weight' => 10 ); // Unset several form elements if user is coming from invite. if (LDAPPROV_INVITE_ENABLED && $code) { $row = db_fetch_object(db_query("SELECT l.* FROM {ldapprov} l WHERE code = '%s'", $code)); if ($row->rid) { if ($row->status > 0) { drupal_set_message(t('The code %code has already been validated.', array('%code' => $code)), 'error'); } else { unset($form['account']['mail']); $form['account']['mail'] = array( '#type' => 'hidden', '#value' => $row->mail, ); $form['code'] = array( '#type' => 'hidden', '#value' => $code, ); } } else { drupal_set_message(t('The code %code is not valid or has expired.', array('%code' => $code)), 'error'); } } return $form; } /** * Main registration form. * Printed on the user registration and admin interface for a new account. * * @param $data * An array of the submitted data. * @param $disabled * If form elements should be disabled (when account is already created). * * @return * A form array. */ function _ldapprov_register_form($data = array(), $disabled = FALSE) { $form['account'] = array('#type' => 'fieldset', '#title' => t('Account information')); if (LDAPPROV_ALLOW_USERNAME) { $form['account']['name'] = array( '#type' => 'textfield', '#title' => t('Username'), '#description' => t('Your full name or your preferred username; only letters, numbers and spaces are allowed.'), '#size' => 30, '#maxlength' => 60, '#default_value' => $data['name'], '#required' => !$disabled ? TRUE : FALSE, '#disabled' => $disabled, '#weight' => -2, ); } if (!module_exists('profile') || !LDAPPROV_PROFILE || LDAPPROV_PROFILE_FIRST == '' || LDAPPROV_PROFILE_LAST == '') { $form['account']['first_name'] = array( '#type' => 'textfield', '#title' => t('First Name'), '#size' => 30, '#maxlength' => 100, '#default_value' => $data['first_name'], '#required' => !$disabled ? TRUE : FALSE, '#disabled' => $disabled, '#weight' => -1, ); $form['account']['last_name'] = array( '#type' => 'textfield', '#title' => t('Last Name'), '#size' => 30, '#maxlength' => 100, '#default_value' => $data['last_name'], '#required' => !$disabled ? TRUE : FALSE, '#disabled' => $disabled, '#weight' => 0, ); } $form['account']['mail'] = array( '#type' => 'textfield', '#title' => t('E-mail address'), '#description' => t('A password and instructions will be sent to this e-mail address, so make sure it is accurate.'), '#size' => 30, '#maxlength' => 100, '#default_value' => $data['mail'], '#required' => !$disabled ? TRUE : FALSE, '#disabled' => $disabled, '#weight' => 2, ); // Custom fields. $ldapprov_custom = variable_get('ldapprov_custom', array()); foreach (ldapprov_custom_elements() as $key => $val) { if ($ldapprov_custom[$key] > 0) { switch ($val['type']) { case 'textfield': $form['account']['custom_'. $key] = array( '#type' => 'textfield', '#title' => $val['title'], '#description' => $val['description'], '#size' => $val['size'], '#maxlength' => $val['maxlength'], '#default_value' => $data['custom_'. $key], '#disabled' => $disabled, '#weight' => $val['weigth'], ); break; case 'textarea': $form['account']['custom_'. $key] = array( '#type' => 'textarea', '#title' => $val['title'], '#description' => $val['description'], '#rows' => $val['rows'], '#default_value' => $data['custom_'. $key], '#disabled' => $disabled, '#weight' => $val['weigth'], ); break; } if ($ldapprov_custom[$key] == 2) { $form['account']['custom_'. $key]['#required'] = !$disabled ? TRUE : FALSE; } } } // Print writable ldap fields. if (module_exists('ldapdata')) { $server = _ldapprov_get_server(); $rwattrs = unserialize($server->ldapdata_rwattrs); if (!empty($rwattrs)) { $ldapdata_attributes = ldapdata_attributes(); $ldapdata_options = variable_get('ldapprov_ldapdata', array()); foreach ($rwattrs as $attribute) { if ($attr_info = $ldapdata_attributes[$attribute]) { // if this attribute should be shown ir registration. if ($ldapdata_options[$attribute] > 0) { array_shift($attr_info); $form['account']['ldap_'. $attribute] = _ldapdata_attribute_form($attribute, $data['ldap_'. $attribute], $attr_info); $form['account']['ldap_'. $attribute]['#disabled'] = $disabled; } // If this attribute is required. if ($ldapdata_options[$attribute] > 1) { $form['account']['ldap_'. $attribute]['#required'] = !$disabled ? TRUE : FALSE; } } } } } // Print profile fields. if (module_exists('profile') && LDAPPROV_PROFILE) { $extra = array(_ldapprov_profile($data, $disabled)); $form = array_merge($form, $extra); } // OG integration. if (module_exists('og') && LDAPPROV_OG) { $form_groups = module_invoke('og', 'user', 'register', NULL, NULL); if (is_array($form_groups['og_register']['og_register']) && is_array($data['og_register'])) { $form_groups['og_register']['og_register']['#default_value'] = $data['og_register']; $form_groups['og_register']['og_register']['#disabled'] = $disabled; } $form = array_merge($form, is_array($form_groups) ? $form_groups : array()); } return $form; } /** * User registration form validation. */ function ldapprov_register_validate($form, &$form_state) { // Main registration form validation. _ldapprov_register_validate($form_state['values']); } /** * Main registration form validation. * * @param $values * An array of the values to validate. * @param $messages * A flag if set, then the form errors will be set, otherwise errors will be counted. * * @return * If $messages is not set, then the number of errors. */ function _ldapprov_register_validate($values, $messages = TRUE) { global $_ldapprov_ldap; // When doing mass account creation, check for errors, but don't set form errors. $errors = 0; $basedn = $_ldapprov_ldap->getOption('basedn'); $name_attr = $_ldapprov_ldap->getOption('user_attr') ? $_ldapprov_ldap->getOption('user_attr') : LDAP_DEFAULT_USER_ATTRIBUTE; // When user is allowed to select a username. if (LDAPPROV_ALLOW_USERNAME) { if (preg_match('/^\s+/', $values['name'])) { $errors = ($messages) ? form_set_error('name', t('Username cannot begin with a space.')) : $errors + 1; } if (preg_match('/\s+$/', $values['name'])) { $errors = ($messages) ? form_set_error('name', t('Username cannot end with a space.')) : $errors + 1; } if (preg_match('/[^\w\s]+/', $values['name'])) { $errors = ($messages) ? form_set_error('name', t('Username should contain only letters, numbers and spaces.')) : $errors + 1; } $result = db_query("SELECT uid FROM {users} WHERE name = '%s'", $values['name']); if ($user = db_fetch_object($result)) { $errors = ($messages) ? form_set_error('name', t('The username %name is already taken. Please choose different one.', array('%name' => $values['name']))) : $errors + 1; } // When ldap users are in sync with drupal users, ldap search is not needed. if (!$_ldapprov_ldap->connect(LDAPPROV_DN, LDAPPROV_PASS)) { watchdog('ldapprov', 'User validate: user data could not be read in the LDAP directory. Could not bind as %dn.', array('%dn' => LDAPPROV_DN), WATCHDOG_ERROR); drupal_set_message(t('User validate: user data could not be read in the LDAP directory. Please contact site administrator.'), 'error'); return; } if ($ret = $_ldapprov_ldap->search($basedn, '('. $name_attr .'='. $values['name'] .')', array('mail'))) { $errors = ($messages) ? form_set_error('name', t('The username %name is already taken. Please choose different one.', array('%name' => $values['name']))) : $errors + 1; } $_ldapprov_ldap->disconnect(); } if (!valid_email_address($values['mail'])) { $errors = ($messages) ? form_set_error('mail', t('The e-mail address %mail is not valid.', array('%mail' => $values['mail']))) : $errors + 1; } $result = db_query("SELECT uid FROM {users} WHERE mail = '%s'", $values['mail']); if ($user = db_fetch_object($result)) { $errors = ($messages) ? form_set_error('mail', t('The user with e-mail address %mail is already registered with the system. Click !request if you forgot your login information.', array('%mail' => $values['mail'], '!request' => l(t('request new password'), 'user/password')))) : $errors + 1; } // When ldap users are in sync with drupal users, ldap search is not needed. if (!$_ldapprov_ldap->connect(LDAPPROV_DN, LDAPPROV_PASS)) { watchdog('ldapprov', 'User validate: user data could not be read in the LDAP directory. Could not bind as %dn.', array('%dn' => LDAPPROV_DN), WATCHDOG_ERROR); drupal_set_message(t('User validate: user data could not be read in the LDAP directory. Please contact site administrator.'), 'error'); return; } if ($ret = $_ldapprov_ldap->search($_ldapprov_ldap->getOption('basedn'), '(mail='. $values['mail'] .')', array('mail'))) { $errors = ($messages) ? form_set_error('mail', t('The user with e-mail address %mail is already registered with the system. Click !request if you forgot your login information.', array('%mail' => $values['mail'], '!request' => l(t('request new password'), 'user/password')))) : $errors + 1; } $_ldapprov_ldap->disconnect(); /* foreach (preg_split('//', LDAPPROV_UID_FORBIDDEN_CHAR) as $c) { if (in_array($c, preg_split('//', $values['first_name']))) { $first_bad .= $c; } if (in_array($c, preg_split('//', $values['last_name']))) { $last_bad .= $c; } } */ if (!LDAPPROV_ALLOW_USERNAME) { // Username is constructed for the user. if (preg_match('/^\s+/', $values['first_name'])) { $errors = ($messages) ? form_set_error('first_name', t('First Name cannot begin with a space.')) : $errors + 1; } if (preg_match('/\s+$/', $values['first_name'])) { $errors = ($messages) ? form_set_error('first_name', t('First Name cannot end with a space.')) : $errors + 1; } if (preg_match('/[^a-zA-Z\'-\s]+/', $values['first_name'])) { $errors = ($messages) ? form_set_error('first_name', t('First Name should contain only latin letters, apostrophe, dash or space.')) : $errors + 1; } /* elseif ($first_bad) { $errors = ($messages) ? form_set_error('first_name', t('First Name should not contain %chars characters.', array('%chars' => $first_bad))) : $errors + 1; } */ if (preg_match('/^\s+/', $values['last_name'])) { $errors = ($messages) ? form_set_error('last_name', t('Last Name cannot begin with a space.')) : $errors + 1; } if (preg_match('/\s+$/', $values['last_name'])) { $errors = ($messages) ? form_set_error('last_name', t('Last Name cannot end with a space.')) : $errors + 1; } if (preg_match('/[^a-zA-Z\'-\s]+/', $values['last_name'])) { $errors = ($messages) ? form_set_error('last_name', t('Last Name should contain only latin letters, apostrophe, dash or space.')) : $errors + 1; } /* elseif ($last_bad) { $errors = ($messages) ? form_set_error('last_name', t('Last Name should not contain %chars characters.', array('%chars' => $last_bad))) : $errors + 1; } */ } else { // Custom usernames are not allowed. if (preg_match('/^\s+$/', $values['first_name'])) { $errors = ($messages) ? form_set_error('first_name', t('First Name can not contain only whitespace characters.')) : $errors + 1; } if (preg_match('/^\s+$/', $values['last_name'])) { $errors = ($messages) ? form_set_error('last_name', t('Last Name can not contain only whitespace characters.')) : $errors + 1; } } // Checking for a batch user upload. if (!$messages) { return $errors; } } /** * User registration form submission. */ function ldapprov_register_submit($form, &$form_state) { $time = time(); $values = $form_state['values']; // Prepare data to enter into the database. $data = array(); foreach ($values as $key => $value) { if (preg_match("/(^profile_|^ldap_|^og_register|^custom_)/", $key)) { $data[$key] = $value; } } // First and last names. $first_name = (!module_exists('profile') || !LDAPPROV_PROFILE || LDAPPROV_PROFILE_FIRST == '') ? $values['first_name'] : $values[LDAPPROV_PROFILE_FIRST]; $last_name = (!module_exists('profile') || !LDAPPROV_PROFILE || LDAPPROV_PROFILE_LAST == '') ? $values['last_name'] : $values[LDAPPROV_PROFILE_LAST]; // Check if registering from an invite. if (LDAPPROV_INVITE_ENABLED && isset($values['code'])) { // Registering from an invite. E-mail is valid. $result = db_query("SELECT * FROM {ldapprov} WHERE code = '%s' AND status = '0'", $values['code']); if ($row = db_fetch_object($result)) { $data_initial = unserialize($row->data); db_query("UPDATE {ldapprov} SET name = '%s', first_name = '%s', last_name = '%s', registered = %d, data = '%s', status = '1' WHERE rid = %d", $values['name'], $first_name, $last_name, $time, serialize($data), $row->rid); drupal_set_message(t('Please wait until your account is approved. You will receive login information to your e-mail account.', array('%mail' => $row->mail))); $form_state['redirect'] = 'user'; } else { drupal_set_message(t('The code %code is not valid or has expired.', array('%code' => $values['code'])), 'error'); $form_state['redirect'] = 'user/register'; } } else { // Ordinary registration. // Create a secret code. $hash = _ldapprov_hash($values['name'] . $first_name . $last_name, $time); db_query("INSERT INTO {ldapprov} (name, mail, first_name, last_name, code, registered, data, status) VALUES ('%s', '%s', '%s', '%s', '%s', %d, '%s', '0')", $values['name'], $values['mail'], $first_name, $last_name, $hash, $time, serialize($data)); // Mail one time login URL and instructions. $variables = array('!validate_url' => url('user/validate/'. $hash, array('absolute' => TRUE)), '!validate_uri' => url('user/validate', array('absolute' => TRUE)), '!mailto' => $values['mail'], '!first_name' => $first_name, '!last_name' => $last_name, '!code' => $hash); $params = array('variables' => $variables); $message = drupal_mail('ldapprov', 'code', $values['mail'], language_default(), $params); if ($message['result']) { watchdog('ldapprov', 'E-mail validation request mailed to %first_name %last_name at %mail.', array('%first_name' => $first_name, '%last_name' => $last_name, '%mail' => $values['mail'])); drupal_set_message(t('An e-mail has been sent to the e-mail account %s to verify that you have entered a valid e-mail address.', array('%s' => $values['mail']))); } else { watchdog('ldapprov', 'Error mailing e-mail validation request to %first_name %last_name at %mail.', array('%first_name' => $first_name, '%last_name' => $last_name, '%mail' => $values['mail']), WATCHDOG_ERROR); drupal_set_message(t('Unable to send mail. Please contact the site admin.'), 'error'); } $form_state['redirect'] = 'user/validate'; } } /** * Creats a secret hash. * * @param $string * A string to calculate hash from. * @param $seed * A seed to salt the hash. * * @return * The hash. */ function _ldapprov_hash($string, $seed) { return md5($string . $seed); } ////////////////////////////////////////////////////////////////////////////// // Secret code validateion /** * Code validation form. * * @param $form_state * A form state array. * @param $code * A secret mail validation code. * * @return * A form array if there is no code. */ function ldapprov_code(&$form_state, $code = NULL) { // The code is passed as argument when clicking a link in the validation e-mail. if ($code) { if (!_ldapprov_code_validate(array('code' => $code))) { _ldapprov_code_submit(array('code' => $code)); drupal_goto('user'); } else { drupal_goto('user/validate'); } } // The code validation form. $form = array(); $form['code'] = array('#type' => 'textfield', '#title' => t('Secret Code'), '#size' => 50, '#maxlength' => 100, '#default_value' => $code, '#required' => TRUE, ); $form['submit'] = array('#type' => 'submit', '#value' => t('Validate')); return $form; } /** * Code validation form validation. */ function ldapprov_code_validate($form, &$form_state) { // Main code validation form validation. _ldapprov_code_validate($form_state['values']); } /** * Main code validation form validation. * * @param $values * A submitted data. * * @return * TRUE or FALSE depending if validation was passed. */ function _ldapprov_code_validate($values) { $result = db_query("SELECT rid, status FROM {ldapprov} WHERE code = '%s'", $values['code']); if ($row = db_fetch_object($result)) { if ($row->status > 0) { form_set_error('code', t('The code %s has already been validated.', array('%s' => $values['code']))); return TRUE; } } else { form_set_error('code', t('The code %s is not valid.', array('%s' => $values['code']))); return TRUE; } return FALSE; } /** * Code validation form submission. */ function ldapprov_code_submit($form, &$form_state) { // Main code validation form submission. _ldapprov_code_submit($form_state['values']); $form_state['redirect'] = 'user'; } /** * Main code validation form submission. * * @param $values * A submitted data. * * @return */ function _ldapprov_code_submit($values) { $result = db_query("SELECT * FROM {ldapprov} WHERE code = '%s' AND status = '0'", $values['code']); if ($row = db_fetch_object($result)) { // Check if users should be approved. if (variable_get('user_register', 1) == 2) { // User approval is needed. $time = time(); db_query("UPDATE {ldapprov} SET status = '1' WHERE code = '%s'", $values['code']); // Mail the user managers about the new request. $variables = array('!mailto' => $row->mail, '!first_name' => $row->first_name, '!last_name' => $row->last_name, '!create_url' => url('admin/user/accounts/pending/create/'. $row->rid, array('absolute' => TRUE))); $result = db_query("SELECT DISTINCT u.uid FROM {users} u INNER JOIN {users_roles} ur ON u.uid = ur.uid INNER JOIN {permission} p ON ur.rid = p.rid WHERE p.perm LIKE '%%%s%%'", LDAPPROV_PERMISSION); while ($row2 = db_fetch_object($result)) { $account = user_load($row->uid); $params = array('account' => $account, 'variables' => $variables); $message = drupal_mail('ldapprov', 'notify', $account->mail, user_preferred_language($account), $params); if ($message['result']) { watchdog('ldapprov', 'E-mail notification message about %first_name %last_name account request mailed to %mail.', array('%first_name' => $row->first_name, '%last_name' => $row->last_name, '%mail' => $row2->mail)); } else { watchdog('ldapprov', 'Error mailing notification e-mail about %first_name %last_name account request mailed to %mail.', array('%first_name' => $row->first_name, '%last_name' => $row->last_name, '%mail' => $row2->mail), WATCHDOG_EROR); } } drupal_set_message(t('Your e-mail account %mail has been validated. Please wait until your account is approved. You will receive login information to your e-mail account.', array('%mail' => $row->mail))); } else { // User approval is not needed, account is created. // Only default role can be assigned this way. unset($values['roles']); if (is_array(unserialize($row->data))) { foreach (unserialize($row->data) as $k => $v) { $values[$k] = $v; } } $values['rid'] = $row->rid; $values['name'] = $row->name; $values['first_name'] = $row->first_name; $values['last_name'] = (!empty($row->last_name)) ? $row->last_name : $row->name; $values['mail'] = $row->mail; $account = _ldapprov_create_user($values); if (is_object($account)) { drupal_set_message(t('Your password and further instructions have been sent to your e-mail address.')); } else { drupal_set_message(t('The new user was not created. Please contact site administrator.'), 'error'); } } } else { drupal_set_message(t('The code %code is not valid or has expired.', array('%code' => $values['code'])), 'error'); } } ////////////////////////////////////////////////////////////////////////////// // Account management /** * List account requests. * * @param $status * The tab clicked. * * @return * A HTML page. */ function ldapprov_list($status = 'pending') { $page = drupal_get_form('ldapprov_list_form', $status); // Print batch users upload form. if ($status == 'pending') { $page .= drupal_get_form('ldapprov_attach'); } return $page; } /** * List account requests form. * * @param $form_state * A form state array. * @param $tab * A tab clicked. * * @return * A form array. */ function ldapprov_list_form(&$form_state, $tab) { // Possible $status values are. // unverified(0), pending(1), rejected(2), created(3), deleted(4). $tabs = array('unverified', 'pending', 'rejected', 'created', 'deleted'); $status = array_search($tab, $tabs); // Action options. if ($status != 3) { $form['options'] = array( '#type' => 'fieldset', '#title' => t('Update options'), '#prefix' => '
', '#suffix' => '
', ); $options = array(); $options['create'] = t('Create the selected users'); if ($status < 2) { $options['reject'] = t('Reject the selected users'); } $form['options']['operation'] = array( '#type' => 'select', '#options' => $options, '#default_value' => 'create', ); $form['options']['submit'] = array( '#type' => 'submit', '#value' => t('Update'), ); } // Requests list. $header[] = array('data' => t('Submission Date'), 'field' => 'registered', 'sort' => 'desc'); if (LDAPPROV_ALLOW_USERNAME || $status == 4) { $header[] = array('data' => t('Username'), 'field' => 'name'); } $header[] = array('data' => t('First Name'), 'field' => 'first_name'); $header[] = array('data' => t('Last Name'), 'field' => 'last_name'); $header[] = array('data' => t('E-Mail'), 'field' => 'mail'); if (LDAPPROV_INVITE_ENEBLAED) { $header[] = array('data' => t('Inviter')); } if ($status > 1) { $header[] = array('data' => t('Approval Date'), 'field' => 'approved'); $header[] = array('data' => t('Approver'), 'field' => 'name_c'); } if ($status == 3) { $header[] = array('data' => t('Account'), 'field' => 'name_u'); } $form['header']['#value'] = $header; if (in_array($status, array(1, 2, 4))) { // Accounts are not created. $sql = "SELECT l.*, u.name name_c FROM {ldapprov} l LEFT JOIN {users} u ON l.cuid = u.uid WHERE l.status = %d"; $query_count = "SELECT COUNT(l.rid) FROM {ldapprov} l LEFT JOIN {users} u ON l.cuid = u.uid WHERE l.status = %d"; } elseif ($status == 3) { // Accounts are created. $sql = "SELECT l.*, u.name name_c, u2.name name_u FROM {ldapprov} l INNER JOIN {users} u2 ON l.uid = u2.uid LEFT JOIN {users} u ON l.cuid = u.uid WHERE l.status = %d"; $query_count = "SELECT COUNT(l.rid) FROM {ldapprov} l INNER JOIN {users} u2 ON l.uid = u2.uid LEFT JOIN {users} u ON l.cuid = u.uid WHERE l.status = %d"; } else { // Account requests with unverified e-mails. $sql = "SELECT l.* FROM {ldapprov} l WHERE status = %d"; $query_count = "SELECT COUNT(l.rid) FROM {ldapprov} l WHERE status = %d"; } $result = pager_query($sql . tablesort_sql($header), LDAPPROV_MAX_LIST_ENTRIES, 0, $query_count, $status); while ($row = db_fetch_object($result)) { $requests[$row->rid] = ''; $data = unserialize($row->data); $form['registered'][$row->rid] = array('#value' => l(format_date($row->registered, LDAPPROV_DATE_FORMAT), 'admin/user/accounts/'. $tab .'/create/'. $row->rid)); if (LDAPPROV_ALLOW_USERNAME || $status == 4) { $form['name'][$row->rid] = array('#value' => check_plain($row->name)); } $form['first_name'][$row->rid] = array('#value' => check_plain($row->first_name)); $form['last_name'][$row->rid] = array('#value' => check_plain($row->last_name)); $form['mail'][$row->rid] = array('#value' => check_plain($row->mail)); if (LDAPPROV_INVITE_ENABLAED) { $inviters = array(); $result2 = db_query("SELECT * FROM {ldapprov_invite} WHERE rid = %d", $row->rid); while ($row2 = db_fetch_object($result2)) { $inviters[] = theme('username', user_load($row2->uid)); } $form['inviter'][$row->rid] = array('#value' => !empty($inviters) ? implode(', ', $inviters) : ''); } if ($status > 1) { $form['approved'][$row->rid] = array('#value' => format_date($row->approved, LDAPPROV_DATE_FORMAT)); $form['name_c'][$row->rid] = isset($row->name_c) ? array('#value' => theme('username', user_load($row->cuid))) : array('#value' => $row->cname); } if ($status == 3) { // Set username. $form['name_u'][$row->rid] = array('#value' => theme('username', user_load($row->uid))); } } if ($status != 3) { $form['requests'] = array( '#type' => 'checkboxes', '#options' => $requests ); } $form['status'] = array( '#type' => 'hidden', '#value' => $status ); $form['#submit'][] = 'ldapprov_list_submit'; $form['pager'] = array('#value' => theme('pager', NULL, LDAPPROV_MAX_LIST_ENTRIES, 0)); return $form; } /** * List account requests form submission. */ function ldapprov_list_submit($form, &$form_state) { $values = $form_state['values']; $register_form_state = array(); $register_form = drupal_retrieve_form('ldapprov_register', $register_form_state); foreach ($values['requests'] as $rid => $v) { if ($v > 0) { switch ($values['operation']) { case 'create': unset($messages); unset($data); $result = db_query("SELECT * FROM {ldapprov} WHERE rid = %d", $rid); $row = db_fetch_object($result); $data = unserialize($row->data); $data['rid'] = $row->rid; $data['name'] = $row->name; $data['first_name'] = $row->first_name; $data['last_name'] = $row->last_name; $data['mail'] = $row->mail; // Validate the data. // Validate using common validation function. $errors = _ldapprov_register_validate($data, FALSE); // Check required fields. foreach ($data as $key => $val) { if (!isset($val) || $val == '') { $errors += _ldapprov_check_required($register_form, $key); } } if ($errors > 0) { drupal_set_message(t('User with an e-mail address %s was not created. Please, create it manually.', array('%s' => $data['mail'])), 'error'); } else { // Create a new user. $new_user = _ldapprov_create_user($data); if (isset($new_user)) { drupal_set_message(t('The new user !name has been created.', array('!name' => theme('username', $new_user)))); } else { drupal_set_message(t('The new user was not created. Please contact site administrator.'), 'error'); } } break; case 'reject': _ldapprov_reject_user(array('rid' => $rid)); break; } } } $tabs = array('unverified', 'pending', 'rejected', 'created', 'deleted'); $form_state['redirect'] = 'admin/user/accounts/'. $tabs[$values['status']]; } /** * Check if a field is required in registration form. * Recursevle checks childrens. * * @param $form_element * An array of form element. * @param $name * A name of the element. * * @return * A number of required elements. */ function _ldapprov_check_required($form_element, $name) { $err = 0; if (is_array($form_element)) { foreach ($form_element as $key => $val) { if ($key === $name) { foreach ($val as $k => $v) { if ($k == '#required' && $val[$k] == 1) { $err++; } } } else { $err += _ldapprov_check_required($val, $name); } } } return $err; } /** * Retrieve a creation form. * * @param $form_state * A form state array. * @param $tab * A tab clicked. * @param $rid * A registration ID. * * @return * A form array. */ function ldapprov_create(&$form_state, $tab, $rid = NULL) { global $user; $tabs = array('unverified', 'pending', 'rejected', 'created', 'deleted'); $status = $tab == 'new' ? NULL : array_search($tab, $tabs); if (isset($status) && is_numeric($rid)) { if ($status == 2 || $status == 4) { // Account rejected or deleted. $result = db_query("SELECT l.*, u.name AS cname FROM {ldapprov} l INNER JOIN {users} u ON l.cuid = u.uid WHERE l.rid = %d", $rid); } elseif ($status == 3) { // Account is created but we print out registration data. $result = db_query("SELECT l.*, u.name AS cname, u2.name name_u FROM {ldapprov} l INNER JOIN {users} u ON l.cuid = u.uid INNER JOIN {users} u2 ON l.uid = u2.uid WHERE l.rid = %d", $rid); } else { // Account is pending. $result = db_query("SELECT l.* FROM {ldapprov} l WHERE l.rid = %d", $rid); } if ($data = db_fetch_array($result)) { $data['data'] = unserialize($data['data']); $data = array_merge(is_array($data['data']) ? $data['data'] : array(), $data); } } $data = is_array($data) ? $data : array(); $form = array(); // Invite information. if (LDAPPROV_INVITE_ENABLED && $rid) { $result = db_query("SELECT li.*, u.name FROM {ldapprov_invite} li LEFT JOIN {users} u ON li.uid = u.uid WHERE li.rid = %d", $rid); while ($row = db_fetch_object($result)) { $invite_data = unserialize($row->data); $invites[$row->iid] = array( '#value' => '
'. t('Invited by !name', array('!name' => theme('username', user_load($row->uid)))) . (!empty($invite_data) ? t(', context: !context.', array('!context' => $invite_data['string'])) : '.') .'
', ); } if (!empty($invites)) { $form['invite'] = array_merge(array('#type' => 'fieldset', '#title' => t('Invitations'), '#collapsible' => FALSE, '#collapsed' => FALSE, '#weight' => '0'), $invites); } } // Main registration form. $form = array_merge($form, _ldapprov_register_form($data, $status == 3 ? TRUE : FALSE)); // Password field. $form['account']['password'] = array( '#type' => 'password', '#title' => t('Password'), '#description' => t('Leave this field empty and the password will be autogenerated.'), '#default_value' => '', '#weight' => 10, '#disabled' => $status == 3 ? TRUE : FALSE, ); // Get all roles except authenticated user. $roles = user_roles(1); unset($roles[DRUPAL_AUTHENTICATED_RID]); // Integration with role assign module. if (module_exists('roleassign')) { // Get roles that are available for assignment. $assignable_roles = _roleassign_assignable_roles($roles); } if (((user_access(LDAPPROV_ROLE_PERMISSION) && $roles) || user_access('assign roles') && $assignable_roles) && $status != 3) { $form['ldapprov_roles'] = array( '#type' => 'fieldset', '#title' => t('Roles'), '#collapsible' => FALSE, '#collapsed' => FALSE, '#weight' => '3', ); $roles_available = (user_access(LDAPPROV_ROLE_PERMISSION)) ? $roles : $assignable_roles; $form['ldapprov_roles']['roles'] = array( '#type' => 'checkboxes', '#title' => t('Roles'), '#default_value' => array_keys((array)$data['roles']), '#options' => $roles_available, '#description' => t('The user receives the combined permissions of the %au role, and all roles selected here.', array('%au' => t('authenticated user'))) ); } if ($status != 3) { // Account is not yet created. $form['ldapprov_messages'] = array('#type' => 'fieldset', '#title' => t('Messages'), '#collapsible' => FALSE, '#collapsed' => FALSE, '#weight' => '4'); $form['ldapprov_messages']['message'] = array( '#type' => 'textarea', '#title' => t('Message'), '#rows' => 5, '#description' => t('This message will be added to the notification e-mail sent out.'), '#default_value' => $data['message'], ); } $form['ldapprov_notes'] = array('#type' => 'fieldset', '#title' => t('Notes'), '#collapsible' => FALSE, '#collapsed' => FALSE, '#weight' => '5'); $form['ldapprov_notes']['notes'] = array( '#type' => 'textarea', '#title' => t('Notes'), '#rows' => 5, '#description' => t('Internal notes shared between account managers.'), '#default_value' => $data['notes'], ); $form['rid'] = array( '#type' => 'hidden', '#value' => $rid, ); if ($status != 3) { // Don't print create button for already created requests. $form['create'] = array( '#type' => 'submit', '#value' => t('Create account'), '#weight' => 10 ); } if ($rid && $status < 2) { // Reject button only for pending accounts. $form['reject'] = array( '#type' => 'submit', '#value' => t('Reject account'), '#weight' => 11 ); } if ($rid) { $form['save'] = array( '#type' => 'submit', '#value' => t('Save notes'), '#weight' => 12 ); } // Print account status history messages. if (empty($form_state['post'])) { if ($status == 2) { drupal_set_message(t('The request was rejected at %date by !name.', array('%date' => format_date($data['approved'], LDAPPROV_DATE_FORMAT), '!name' => theme('username', user_load($data['cuid']))))); } elseif ($status == 3) { drupal_set_message(t('The user !name was created at %date by !cname.', array('!name' => theme('username', user_load($data['uid'])), '%date' => format_date($data['approved'], LDAPPROV_DATE_FORMAT), '!cname' => theme('username', user_load($data['cuid']))))); } elseif ($status == 4) { drupal_set_message(t('The account was deleted at %date by !name.', array('%date' => format_date($data['approved'], LDAPPROV_DATE_FORMAT), '!name' => theme('username', user_load($data['cuid']))))); } // Prints a message if a user with this username already exists in the system when the form is rendered. if ($status != 3 && !LDAPPROV_ALLOW_USERNAME) { $name = _ldapprov_make_username($data['first_name'], $data['last_name']); $result = db_query("SELECT mail FROM {users} WHERE name = '%s'", $name); if ($row = db_fetch_object($result)) { drupal_set_message(t('An account with a username %name and e-mail %mail is already created in the system. If you proceed, a new account will be created with a number appended to the username.', array('%name' => $name, '%mail' => $row->mail)), 'error'); } else { // When ldap users are in sync with drupal users, ldap search is not needed. global $_ldapprov_ldap; $basedn = $_ldapprov_ldap->getOption('basedn'); $name_attr = $_ldapprov_ldap->getOption('user_attr') ? $_ldapprov_ldap->getOption('user_attr') : LDAP_DEFAULT_USER_ATTRIBUTE; if (!$_ldapprov_ldap->connect(LDAPPROV_DN, LDAPPROV_PASS)) { watchdog('ldapprov', 'User registration: user data could not be read in the LDAP directory. Could not bind as %dn.', array('%dn' => LDAPPROV_DN), WATCHDOG_ERROR); drupal_set_message(t('User registration: user data could not be read in the LDAP directory. Please contact site administrator.'), 'error'); } if ($ret = $_ldapprov_ldap->search($basedn, '('. $name_attr .'='. $name .')', array('mail'))) { drupal_set_message(t('An account with a username %name and e-mail %mail is already created in the system. If you proceed, a new account will be created with a number appended to the username.', array('%name' => $name, '%mail' => $ret[0]['mail'][0])), 'error'); } $_ldapprov_ldap->disconnect(); } } } return $form; } /** * User creation form validation. */ function ldapprov_create_validate($form, &$form_state) { $values = $form_state['values']; // Remember the tab. $status = 1; $tabs = array('unverified', 'pending', 'rejected', 'created', 'deleted'); if (isset($values['rid'])) { $result = db_query("SELECT rid, status FROM {ldapprov} WHERE rid = %d", $values['rid']); $row = db_fetch_object($result); $status = $row->status; } $form_state['values']['status'] = $status; // Main registration form validation. if ($values['op'] == t('Create account')) { _ldapprov_register_validate($form_state['values']); } } /** * User creation form submission. */ function ldapprov_create_submit($form, &$form_state) { $values = $form_state['values']; // Handle operations. if ($values['op'] == t('Reject account')) { _ldapprov_reject_user($values); } elseif ($values['op'] == t('Save notes')) { db_query("UPDATE {ldapprov} SET notes = '%s' WHERE rid = %d", $values['notes'], $values['rid']); drupal_set_message(t('The notes have been saved.')); } else { // Create a new user. $account = _ldapprov_create_user($values); if (is_object($account)) { drupal_set_message(t('The new user !name has been created.', array('!name' => theme('username', $account)))); } else { drupal_set_message(t('The new user was not created. Please contact site administrator.'), 'error'); } } $tabs = array('unverified', 'pending', 'rejected', 'created', 'deleted'); $form_state['redirect'] = 'admin/user/accounts/'. $tabs[$values['status']]; } ////////////////////////////////////////////////////////////////////////////// // User creation /** * User creation in LDAP and drupal. * * @param $data * An array of the submitted data. * * @return * A created user object. */ function _ldapprov_create_user($data) { global $user, $_ldapprov_ldap; // First and last names. $first_name = (!module_exists('profile') || !LDAPPROV_PROFILE || LDAPPROV_PROFILE_FIRST == '') ? $data['first_name'] : $data[LDAPPROV_PROFILE_FIRST]; $last_name = (!module_exists('profile') || !LDAPPROV_PROFILE || LDAPPROV_PROFILE_LAST == '') ? $data['last_name'] : $data[LDAPPROV_PROFILE_LAST]; if (LDAPPROV_ALLOW_USERNAME) { $name = $data['name']; } else { $name = _ldapprov_make_username($first_name, $last_name); } if (!$_ldapprov_ldap->connect(LDAPPROV_DN, LDAPPROV_PASS)) { watchdog('ldapprov', 'User creation: user data could not be read in the LDAP directory. Could not bind as %dn.', array('%dn' => LDAPPROV_DN), WATCHDOG_ERROR); drupal_set_message(t('Error! User data could not be read in the LDAP directory. Please contact site administrator.'), 'error'); return; } $basedn = $_ldapprov_ldap->getOption('basedn'); $name_attr = $_ldapprov_ldap->getOption('user_attr') ? $_ldapprov_ldap->getOption('user_attr') : LDAP_DEFAULT_USER_ATTRIBUTE; if ($ret = $_ldapprov_ldap->search($basedn, '('. $name_attr .'='. $name .')', array($name_attr))) { $i = 1; while ($ret = $_ldapprov_ldap->search($basedn, '('. $name_attr .'='. $name . $i .')', array($name_attr))) { $i++; } $name = $name . $i; } // ldapauth defines if we use md5 for ldap passwords. $pass = $data['password'] ? $data['password'] : user_password(); $pass_ldap = $_ldapprov_ldap->getOption('encrypted') ? '{md5}'. base64_encode(pack('H*', md5($pass))) : $pass; $ldap_vars['!uid'] = $name; $ldap_vars['!base_dn'] = $_ldapprov_ldap->getOption('basedn'); $ldap_vars['!mail'] = $data['mail']; $ldap_vars['!first_name'] = $first_name; $ldap_vars['!last_name'] = $last_name; $ldap_vars['!pass'] = $pass_ldap; $dn = $name_attr .'='. $name .','. $basedn; // Construct main user ldif entry. foreach (explode("\n", LDAPPROV_USER_ENTRY) as $line) { $line = str_replace("\r", '', $line); if (preg_match('/^\s*$/', $line)) continue; if (preg_match('/^#.*$/', $line)) continue; list($attr, $var) = explode(': ', $line); $ldif_var = strtr($var, $ldap_vars); if (!empty($ldif_var)) { $ldif[$attr][] = $ldif_var; } } // Create writable attributes from ldapdata. $server = _ldapprov_get_server(); if (module_exists('ldapdata')) { $rwattrs = unserialize($server->ldapdata_rwattrs); if (!empty($rwattrs)) { $ldapdata_attributes = ldapdata_attributes(); $ldapdata_options = variable_get('ldapprov_ldapdata', array()); foreach ($rwattrs as $attribute) { if ($attr_info = $ldapdata_attributes[$attribute]) { // if this attribute should be shown ir registration. if ($ldapdata_options[$attribute] > 0 && $data['ldap_'. $attribute]) { $ldif[$attribute][] = strtr($data['ldap_'. $attribute], $ldap_vars); } } } } } // Print ldif if debugging is enabled. if (LDAPPROV_DEBUG) { $ldif_out = "dn: $dn
"; foreach ($ldif as $key => $val) { foreach ($val as $k => $v) { $ldif_out .= "$key: $v
"; } } drupal_set_message($ldif_out); } // Create user in LDAP. if ($_ldapprov_ldap->create_entry($dn, $ldif)) { // Enter profile data. $account_profile = array(); if (module_exists('profile')) { $result = db_query("SELECT * FROM {profile_fields}"); while ($row = db_fetch_object($result)) { $profile[$row->name] = $row->fid; } $ldapdata_mappings = !empty($server->ldapdata_mappings) ? unserialize($server->ldapdata_mappings) : array(); foreach ($data as $key => $value) { if (preg_match('/^profile_/', $key) && $profile[$key] && $data[$key]) { if ($ldap_profile = $ldapdata_mappings['ldap_amap-'. $profile[$key]]) { // drupal profile will be sync with ldap on the next load. $ldap_profile_ldif[$ldap_profile][] = $data[$key]; } $account_profile[$key] = $data[$key]; } } // Profile to ldap mapping. if (isset($ldap_profile_ldif)) { $_ldapprov_ldap->writeAttributes($dn, $ldap_profile_ldif); } } // Proceed with a Drupal user only if LDAP user is created successfully. // Set user roles. $roles = $data['roles']; if ((user_access(LDAPPROV_ROLE_PERMISSION) || user_access('assign roles')) && isset($roles)) { foreach ($roles as $key => $value) { if ($value == 0) { unset($roles[$key]); } } } // Create a drupal user. $account = user_save('', array_merge(array('name' => $name, 'pass' => $pass, 'mail' => $data['mail'], 'init' => $data['mail'], 'status' => 1, 'authname_ldapauth' => $name, 'roles' => $roles, 'ldap_authentified' => TRUE, 'ldap_dn' => $dn, ldap_config => LDAPPROV_SERVER), $account_profile)); watchdog('ldapprov', 'A new external user %name was created using module %module.', array('%name' => $name, '%module' => 'ldapprov'), WATCHDOG_NOTICE, l(t('edit'), 'user/'. $account->uid .'/edit')); $time = time(); if ($user->uid == 0) { // Registration without approval. db_query("UPDATE {ldapprov} SET status = '3', cuid = %d, approved = %d, uid = %d WHERE rid = %d", $account->uid, $time, $account->uid, $data['rid']); } elseif ($data['rid']) { // Manager is approving request. db_query("UPDATE {ldapprov} SET status = '3', cuid = %d, approved = %d, uid = %d, notes = '%s' WHERE rid = %d", $user->uid, $time, $account->uid, $data['notes'], $data['rid']); } else { // User is created from the account manager interface. db_query("INSERT INTO {ldapprov} (name, mail, first_name, last_name, status, registered, data, approved, cuid, uid, notes) VALUES ('%s', '%s', '%s', '%s', '3', %d, '%s', %d, %d, %d, '%s')", $data['name'], $data['mail'], $first_name, $last_name, $time, serialize($data), $time, $user->uid, $account->uid, $data['notes']); } // Mail one time login URL and instructions. $variables = array('!mailto' => $data['mail'], '!first_name' => $first_name, '!last_name' => $last_name, '!username' => $name, '!password' => $pass, '!message' => $data['message']); $params = array('account' => $account, 'variables' => $variables); $message = drupal_mail('ldapprov', 'create', $account->mail, user_preferred_language($account), $params); if ($message['result']) { watchdog('ldapprov', 'Account creation notification e-mail mailed to %name at %mail.', array('%name' => $name, '%mail' => $data['mail'])); } else { watchdog('ldapprov', 'Error mailing account creation notification to %name at %mail.', array('%name' => $name, '%mail' => $data['mail']), WATCHDOG_ERROR); } // OG integration. if (module_exists('og') && is_array($data['og_register'])) { foreach (array_keys(array_filter($data['og_register'])) as $gid) { $return = og_subscribe_user($gid, $account); } } // Execute additional create hooks. $account->clear_pass = $pass; if ($data['rid']) $account->rid = $data['rid']; module_invoke_all('ldapuser', $account); } else { // User creation in LDAP failed. watchdog('ldapprov', 'User creation: user was not created in the LDAP directory.', array(), WATCHDOG_ERROR); } $_ldapprov_ldap->disconnect(); return $account; } /** * Creates username from the configuration template. * * @param $first * A first name. * @param $last * A last name. * * @return * A constructed username. */ function _ldapprov_make_username($first, $last) { $first = drupal_strtolower($first); $first = preg_replace('/\'/', '', $first); $first = preg_replace('/\s+/', '-', $first); $last = drupal_strtolower($last); $last = preg_replace('/\'/', '', $last); $last = preg_replace('/\s+/', '-', $last); $name = LDAPPROV_USERNAME; if (preg_match('/%f\d+/', $name)) { $no = $name; $no = preg_replace('/.*%f(\d+).*/', '\1', $no); $name = preg_replace('/%f\d+/', drupal_substr($first, 0, $no--), $name); } elseif (preg_match('/%f/', $name)) { $name = preg_replace('/%f/', $first, $name); } if (preg_match('/%l\d+/', $name)) { $no = $name; $no = preg_replace('/.*%l(\d+).*/', '\1', $no); $name = preg_replace('/%l\d+/', drupal_substr($last, 0, $no--), $name); } elseif (preg_match('/%l/', $name)) { $name = preg_replace('/%l/', $last, $name); } return $name; } ////////////////////////////////////////////////////////////////////////////// // User rejection /** * User rejection in LDAP and Drupal. * * @param $data * A submitted data, * * @return */ function _ldapprov_reject_user($data) { global $user; $time = time(); db_query("UPDATE {ldapprov} SET status = '2', cuid = %d, approved = %d WHERE rid = %d", $user->uid, $time, $data['rid']); if (isset($data['notes'])) { // We don't want to delete existing notes, so update them on separate update. db_query("UPDATE {ldapprov} SET notes = '%s' WHERE rid = %d", $data['notes'], $data['rid']); } $result = db_query("SELECT rid, mail, first_name, last_name FROM {ldapprov} WHERE rid = %d", $data['rid']); $row = db_fetch_object($result); drupal_set_message(t('The account request for %first %last (%mail) has been rejected.', array('%first' => $row->first_name, '%last' => $row->last_name, '%mail' => $row->mail))); // Mail the user about rejection. $variables = array('!mailto' => $row->mail, '!first_name' => $row->first_name, '!last_name' => $row->last_name, '!message' => $data['message']); $params = array('variables' => $variables); $message = drupal_mail('ldapprov', 'reject', $row->mail, language_default(), $params); if ($message['result']) { watchdog('ldapprov', 'E-mail rejection message mailed to %first_name %last_name at %mail.', array('%first_name' => $row->first_name, '%last_name' => $row->last_name, '%mail' => $row->mail)); } else { watchdog('ldapprov', 'Error mailing rejection e-mail to %first_name %last_name at %mail.', array('%first_name' => $row->first_name, '%last_name' => $row->last_name, '%mail' => $row->mail), WATCHDOG_ERROR); } } ////////////////////////////////////////////////////////////////////////////// // Profile API /** * Print profile fields marked for registration. * * @param $edit * A submitted data. * @param $disabled * A flag saying if the form elements should be disabled. * * @return * A form array. */ function _ldapprov_profile($edit, $disabled = FALSE) { $form = profile_form_profile($edit, NULL, NULL, TRUE); if ($disabled) { foreach ($form as $cat => $category) { foreach ($category as $field => $data) { if (is_array($data)) { $form[$cat][$field]['#disabled'] = TRUE; $form[$cat][$field]['#required'] = FALSE; } } } } return $form; } ////////////////////////////////////////////////////////////////////////////// // File upload API /** * File upload form. * * @return * A form array. */ function ldapprov_attach() { $form = array('#attributes' => array('enctype' => 'multipart/form-data')); // Attachments fieldset. $form['attachments'] = array( '#type' => 'fieldset', '#title' => t('Upload accounts'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#description' => t('Users data in xml or csv format. The templates can be downloaded in the !xml or !csv format', array('!xml' => l('xml', 'ldapprov/template/xml'), '!csv' => l('csv', 'ldapprov/template/csv'))), '#prefix' => '
', '#suffix' => '
', ); $form['attachments']['upload'] = array('#type' => 'file', '#title' => t('Attach new file'), '#size' => 40); $form['attachments']['action'] = array('#type' => 'submit', '#value' => 'Submit'); return $form; } /** * Handle file upload validate. */ function ldapprov_attach_validate($form, &$form_state) { // A file should be uploaded. $filename = $_FILES['files']['name']['upload']; if (empty($filename)) { form_set_error('upload', t('The file should be provided.')); } else { $ext = preg_replace('/^.*\.([^\.]+)$/', '$1', $filename); if (!in_array($ext, array('xml', 'csv'))) { form_set_error('upload', t('Unsupported file extension %ext.', array('%ext' => $ext))); } } } /** * Handle file upload submit. */ function ldapprov_attach_submit($form, &$form_state) { $file = file_save_upload('upload'); // Drupal adds .txt for unknown mime types. //$filename = preg_match('/\.txt$/', $file->filename) ? $filename = preg_replace('/\.txt$/', '', $file->filename) : $file->filename; _ldapprov_attach_file($file); file_delete($file->filepath); } /** * Parse the file and save data in the database. * * @param $file * A file object. * * @return */ function _ldapprov_attach_file($file) { global $user; preg_match('/[^\.]+$/', $file->filename, $matches); if (function_exists('_ldapprov_'. $matches[0] .'_parse')) { $data = call_user_func('_ldapprov_'. $matches[0] .'_parse', $file); if (is_array($data)) { $time = time(); foreach ($data as $account) { // First and last names. $account['first_name'] = (!module_exists('profile') || !LDAPPROV_PROFILE || LDAPPROV_PROFILE_FIRST == '') ? $account['first_name'] : $account[LDAPPROV_PROFILE_FIRST]; $accaount['last_name'] = (!module_exists('profile') || !LDAPPROV_PROFILE || LDAPPROV_PROFILE_LAST == '') ? $account['last_name'] : $account[LDAPPROV_PROFILE_LAST]; db_query("INSERT INTO {ldapprov} (name, mail, first_name, last_name, status, registered, data, cuid) VALUES ('%s', '%s', '%s', '%s', '1', %d, '%s', %d)", $account['name'], $account['mail'], $account['first_name'], $account['last_name'], $time, serialize($account), $user->uid); } drupal_set_message(t("The users data from the file %file has been uploaded.", array('%file' => $file->filename))); } else { drupal_set_message(t("Error: %error in file %file.", array('%error' => $data, '%file' => $file->filename)), 'error'); } } else { drupal_set_message(t("File %file has unsupported extension %extension.", array('%file' => $file->filename, '%extension' => $matches[0])), 'error'); } } /** * Prints batch upload template files. * * @param $type * A type - xml or csv. * * @return */ function _ldapprov_template($type) { if (!in_array($type, array('xml', 'csv'))) { drupal_not_found(); return; } header('Content-type: application/'. $type); header('Content-Disposition: attachment; filename="template.'. $type .'"'); $data = (!module_exists('profile') || !LDAPPROV_PROFILE || LDAPPROV_PROFILE_FIRST == '' || LDAPPROV_PROFILE_LAST == '') ? array('first_name' => t('First name') . t(' (required)'), 'last_name' => t('Last name') . t(' (required)')) : array(); $data['mail'] = t('E-mail') . t(' (required)'); if (LDAPPROV_ALLOW_USERNAME) { $data['name'] = t('Username') . t(' (required)'); } // Print writable ldap fields. if (module_exists('ldapdata')) { $server = _ldapprov_get_server(); $rwattrs = unserialize($server->ldapdata_rwattrs); if (!empty($rwattrs)) { $ldapdata_attributes = ldapdata_attributes(); $ldapdata_options = variable_get('ldapprov_ldapdata', array()); foreach ($rwattrs as $attribute) { if ($attr_info = $ldapdata_attributes[$attribute]) { // If this attribute should be shown ir registration. if ($ldapdata_options[$attribute] > 0) { $data['ldap_'. $attribute] = $attr_info['2']; } } } } } // Print profile fields. if (module_exists('profile')) { //$result = db_query('SELECT * FROM {profile_fields} WHERE visibility != %d AND register = 1 ORDER BY category, weight', PROFILE_HIDDEN); $result = _profile_get_fields('', 1); while ($field = db_fetch_object($result)) { $data[$field->name] = $field->title; if ($field->required == 1) { $data[$field->name] .= t(' (required)'); } } } // Print custom fields. $ldapprov_custom = variable_get('ldapprov_custom', array()); foreach (ldapprov_custom_elements() as $key => $val ) { if ($ldapprov_custom[$key] > 0) { $data['custom_'. $key] = $val['title']; if ($ldapprov_custom[$key] == 2) { $data['custom_'. $key] .= t(' (required)'); } } } switch ($type) { case 'xml': print "\n"; print "\n"; print " \n"; foreach ($data as $key => $val) { print " <$key>$val\n"; } print " \n"; print ""; break; case 'csv': print implode(LDAPPROV_CSV_DELIMITER, array_keys($data)) ."\n"; print implode(LDAPPROV_CSV_DELIMITER, array_values($data)); break; } exit(); } ////////////////////////////////////////////////////////////////////////////// // File parse API /** * Parse a xml file. * * param $file. * A file object. * * @return * An array of parsed file data. */ function _ldapprov_xml_parse($file) { global $_ldapprov_xml_names; global $_ldapprov_xml_values; global $_ldapprov_xml_count; $fh = fopen($file->filepath, "r"); $data = fread($fh, $file->filesize); fclose($fh); $_ldapprov_xml_count = 0; $_ldapprov_xml_names = array(); //$_ldapprov_xml_values = array(); $xml_parser = xml_parser_create(); xml_set_element_handler($xml_parser, "_ldapprov_start_element", "_ldapprov_end_element"); xml_set_character_data_handler($xml_parser, "_ldapprov_character_data"); $data = preg_replace('/[\n\r]/', '', $data); if (!xml_parse($xml_parser, $data, TRUE)) { return t('XML error: %error at line %line', array('%error' => xml_error_string(xml_get_error_code($xml_parser)), '%line' => xml_get_current_line_number($xml_parser))); } xml_parser_free($xml_parser); return $_ldapprov_xml_values; } /** * Push xml start element. */ function _ldapprov_start_element($parser, $name, $attrs) { global $_ldapprov_xml_names; array_push($_ldapprov_xml_names, $name); } /** * Pull xml start element. */ function _ldapprov_end_element($parser, $name) { global $_ldapprov_xml_names; global $_ldapprov_xml_count; array_pop($_ldapprov_xml_names); if ($name == 'USER') { $_ldapprov_xml_count++; } } /** * Extract xml data. */ function _ldapprov_character_data($parser, $data) { global $_ldapprov_xml_names; global $_ldapprov_xml_values; global $_ldapprov_xml_count; if ($_ldapprov_xml_names[0] == 'ACCOUNTS' && $_ldapprov_xml_names[1] == 'USER' && isset($_ldapprov_xml_names[2])) { $name = drupal_strtolower($_ldapprov_xml_names[2]); // xml parser makes all names upercase. if (preg_match('/^ldap_/', $name)) { $attributes = variable_get('ldap_user_attributes', array()); foreach ($attributes as $attribute) { if ($name == 'ldap_'. drupal_strtolower($attribute)) { $name = 'ldap_'. $attribute; break; } } } $_ldapprov_xml_values[$_ldapprov_xml_count][$name] = $data; } } /** * Parse a csv file. * * param $file. * A file object. * * @return * An array of parsed file data. */ function _ldapprov_csv_parse($file) { $row = 1; //$rows = array(); $columnheadings = TRUE; $fh = fopen($file->filepath, 'r'); while (($data = fgetcsv($fh, 1000, LDAPPROV_CSV_DELIMITER, LDAPPROV_CSV_ENCLOSURE )) !== FALSE) { if (!($columnheadings == FALSE) && ($row == 1)) { $heading_texts = $data; } elseif (!($columnheadings == FALSE)) { foreach ($data as $key => $value) { unset($data[$key]); $data[$heading_texts[$key]] = $value; } $rows[] = $data; } else { $rows[] = $data; } $row++; } fclose($fh); return $rows; }