/**
  * Test {@link locale_from_httpaccept()}
  */
 function test_locale_from_httpaccept()
 {
     $this->change_global('locales', array());
     $this->change_global('default_locale', '_DEFAULT_');
     // to make it distinct
     $this->change_server('HTTP_ACCEPT_LANGUAGE', 'de,en;q=0.8,zh-hk;q=0.7,zh-cn;q=0.5,en-us;q=0.3,de-de;q=0.2');
     $this->assertEqual('_DEFAULT_', locale_from_httpaccept());
     $this->assertEqual('_DEFAULT_', locale_from_httpaccept());
     $this->change_global('locales', array('de-CH' => array('enabled' => true), 'de-DE' => array('enabled' => true), 'en-US' => array('enabled' => true), 'zh-hk' => array('enabled' => true)));
     $this->change_server('HTTP_ACCEPT_LANGUAGE', 'de,en;q=0.8,zh-hk;q=0.7,zh-cn;q=0.5,en-us;q=0.3,de-de;q=0.2');
     $this->assertEqual('de-DE', locale_from_httpaccept());
     $this->change_server('HTTP_ACCEPT_LANGUAGE', 'de,en;q=0.8,zh-hk;q=0.7,zh-cn;q=0.5,en-us;q=0.3');
     $this->assertEqual('de-DE', locale_from_httpaccept());
     $this->change_global('locales', array('en-US' => array('enabled' => true), 'zh-hk' => array('enabled' => true), 'de-CH' => array('enabled' => true)));
     $this->change_server('HTTP_ACCEPT_LANGUAGE', 'de,en;q=0.8,zh-hk;q=0.7,zh-cn;q=0.5,en-us;q=0.3');
     $this->assertEqual('de-CH', locale_from_httpaccept());
     $this->change_server('HTTP_ACCEPT_LANGUAGE', 'de,en,zh-hk;q=0.7,zh-cn;q=0.5,en-uk;q=0.3');
     $this->assertEqual('de-CH', locale_from_httpaccept());
     $this->change_global('locales', array('en-US' => array('enabled' => true), 'en-UK' => array('enabled' => true), 'de-DE' => array('enabled' => true)));
     $this->change_server('HTTP_ACCEPT_LANGUAGE', 'en-uk');
     $this->assertEqual('en-UK', locale_from_httpaccept());
     $this->change_server('HTTP_ACCEPT_LANGUAGE', 'en,en-uk');
     $this->assertEqual('en-UK', locale_from_httpaccept());
     $this->change_server('HTTP_ACCEPT_LANGUAGE', 'en,de-DE,en-uk;q=0.3');
     $this->assertEqual('en-UK', locale_from_httpaccept());
     // not sure here, if it should be "de-DE" instead: same prio, but more specific
     $this->change_server('HTTP_ACCEPT_LANGUAGE', 'de-DE,en,en-uk;q=0.3');
     $this->assertEqual('de-DE', locale_from_httpaccept());
     // test "not acceptable" (q=0)
     $this->change_server('HTTP_ACCEPT_LANGUAGE', 'de-DE;q=0,foo');
     $this->assertEqual('_DEFAULT_', locale_from_httpaccept());
     $this->change_server('HTTP_ACCEPT_LANGUAGE', '');
     $this->assertEqual('_DEFAULT_', locale_from_httpaccept());
 }
Beispiel #2
0
load_funcs('items/model/_item.funcs.php');
load_class('comments/model/_commentlist.class.php');
load_funcs('sessions/model/_hitlog.funcs.php');
// referer logging
load_funcs('_core/ui/forms/_form.funcs.php');
load_funcs('_core/ui/forms/_form.class.php');
load_class('items/model/_itemquery.class.php');
load_funcs('_ext/_swfcharts.php');
$Timer->pause('_main.inc:requires');
/**
 * Locale selection:
 */
$Debuglog->add('default_locale from conf: ' . $default_locale, 'locale');
locale_overwritefromDB();
$Debuglog->add('default_locale from DB: ' . $default_locale, 'locale');
$default_locale = locale_from_httpaccept();
// set default locale by autodetect
$Debuglog->add('default_locale from HTTP_ACCEPT: ' . $default_locale, 'locale');
if (($locale_from_get = param('locale', 'string', NULL, true)) && $locale_from_get != $default_locale && isset($locales[$locale_from_get])) {
    $default_locale = $locale_from_get;
    $Debuglog->add('Overriding locale from REQUEST: ' . $default_locale, 'locale');
}
/**
 * Activate default locale:
 */
locale_activate($default_locale);
/*
 * Login procedure: {{{
 * TODO: dh> the meat of this login procedure should be moved to an extra file IMHO so that if a session exists (in most cases) it does not trigger parsing the meat of this code
 * !!! fp> a session can and wil exist before a user is already logged in.
 */
 /**
  * Event handler: called when a user attemps to login.
  *
  * This function will check if the user exists in the LDAP directory and create it locally if it does not.
  *
  * @param array 'login', 'pass' and 'pass_md5'
  */
 function LoginAttempt(&$params)
 {
     global $localtimenow;
     global $Settings, $Hit, $evo_charset;
     // Check if LDAP is available:
     if (!function_exists('ldap_connect')) {
         $this->debug_log('This PHP installation does not support LDAP functions.');
         return false;
         // Login failed!
     }
     // Get ready to go through ALL LDAP Servers configured in the plugin:
     $search_sets = $this->Settings->get('search_sets');
     if (empty($search_sets)) {
         $this->debug_log('No LDAP servers have been configured in the LDAP plugin settings.');
         return false;
         // Login failed!
     }
     // Detect if we already have a local user with the same login:
     $UserCache =& get_Cache('UserCache');
     if ($local_User =& $UserCache->get_by_login($params['login'])) {
         $this->debug_log('User <b>' . $params['login'] . '</b> already exists locally. We will UPDATE it with the latest LDAP attibutes.');
         $update_mode = true;
         // Try to find a number of a search set which was used on successful logging previous time by current user:
         $user_search_set_num = intval($this->UserSettings->get('search_set_num', $local_User->ID));
         if ($user_search_set_num > 0 && isset($search_sets[$user_search_set_num])) {
             // We have found this, Reorder the array to use the successful set firstly:
             $success_search_set = $search_sets[$user_search_set_num];
             unset($search_sets[$user_search_set_num]);
             $search_sets = array($user_search_set_num => $success_search_set) + $search_sets;
         }
     } else {
         $update_mode = false;
     }
     $this->debug_log(sprintf('LDAP plugin will attempt to login with login=<b>%s</b> / pass=<b>%s</b> / MD5 pass=<b>%s</b>', $params['login'], $params['pass'], $params['pass_md5']));
     // ------ Loop through list of configured LDAP Servers: ------
     foreach ($search_sets as $l_id => $l_set) {
         $this->debug_log('Step 1 : STARTING LDAP AUTH WITH SERVER #' . $l_id);
         // --- CONNECT TO SERVER ---
         $server_port = explode(':', $l_set['server']);
         $server = $server_port[0];
         $port = isset($server_port[1]) ? $server_port[1] : 389;
         if (!empty($l_set['disabled'])) {
             $this->debug_log('Skipping disabled LDAP server &laquo;' . $server . ':' . $port . '&raquo;!');
             continue;
         }
         if (!($ldap_conn = @ldap_connect($server, $port))) {
             $this->debug_log('Could not connect to LDAP server &laquo;' . $server . ':' . $port . '&raquo;!');
             continue;
         }
         $this->debug_log('Connected to server &laquo;' . $server . ':' . $port . '&raquo;..');
         $ldap_rdn = str_replace('%s', $params['login'], $l_set['rdn']);
         $this->debug_log('Using RDN &laquo;' . $ldap_rdn . '&raquo; for binding...');
         // --- SET PROTOCOL VERSION ---
         // Get protocol version to use:
         if (!ldap_get_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, $initial_protocol_version)) {
             $this->debug_log('Failed to get LDAP_OPT_PROTOCOL_VERSION.');
             $initial_protocol_version = null;
         }
         $protocol_version = isset($l_set['protocol_version']) ? $l_set['protocol_version'] : 'auto';
         // new setting in 2.01
         if ($protocol_version[0] == 'v') {
             // transform "vX" => "X"
             $try_versions = array(substr($protocol_version, 1));
         } else {
             // "auto"
             $try_versions = array(3, 2);
             if (isset($initial_protocol_version)) {
                 array_unshift($try_versions, $initial_protocol_version);
             }
             $try_versions = array_unique($try_versions);
         }
         $this->debug_log('We will try protocol versions: ' . implode(', ', $try_versions));
         // --- VERIFY USER CREDENTIALS BY BINDING TO SERVER ---
         // you might use this for testing with Apache DS: if( !@ldap_bind($ldap_conn, 'uid=admin,ou=system', 'secret') )
         // Bind:
         $bound = false;
         $bind_errors = array();
         foreach ($try_versions as $try_version) {
             $this->debug_log(sprintf('Trying to connect with protocol version: %s / RDN: %s / pass: %s', $try_version, $ldap_rdn, $params['pass']));
             ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, $try_version);
             if (@ldap_bind($ldap_conn, $ldap_rdn, $params['pass'])) {
                 // Success
                 $this->debug_log('Binding worked.');
                 $bound = true;
                 break;
             } else {
                 $this->debug_log('Binding failed. Errno: ' . ldap_errno($ldap_conn) . ' Error: ' . ldap_error($ldap_conn));
             }
         }
         if (!$bound) {
             if (isset($initial_protocol_version)) {
                 // Reset this for the next search set:
                 ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, $initial_protocol_version);
             }
             continue;
         }
         $this->debug_log('User successfully bound to server.');
         // --- STEP 2 : TRY TO OBTAIN MORE INFO ABOUT USER ---
         // Search user info
         $filter = str_replace('%s', $params['login'], $l_set['search_filter']);
         $this->debug_log(sprintf('Step 2 : Now querying for additional user info. base_dn: <b>%s</b>, filter: <b>%s</b>', $l_set['base_dn'], $filter));
         $search_result = @ldap_search($ldap_conn, $l_set['base_dn'], $filter);
         if (!$search_result) {
             // this may happen with an empty base_dn
             $this->debug_log('Invalid ldap_search result. Skipping to next search set. Errno: ' . ldap_errno($ldap_conn) . ' Error: ' . ldap_error($ldap_conn));
             continue;
         }
         $search_info = ldap_get_entries($ldap_conn, $search_result);
         //$this->debug_log( 'Results returned by LDAP Server: <pre>'.var_export( $search_info, true ).'</pre>' );
         if ($search_info['count'] != 1) {
             // We have found 0 or more than 1 users, which is a problem...
             $this->debug_log('# of entries found with search: ' . $search_info['count'] . ' - Skipping...');
             /*
             for ($i=0; $i<$search_info["count"]; $i++) {
             	echo "dn: ". $search_info[$i]["dn"] ."<br>";
             	echo "first cn entry: ". $search_info[$i]["cn"][0] ."<br>";
             	echo "first email entry: ". $search_info[$i]["mail"][0] ."<p>";
             }
             */
             continue;
         }
         $this->debug_log('User info has been found.');
         // --- CREATE OR UPDATE USER ACCOUNT IN B2EVO ---
         if ($update_mode == false) {
             $this->debug_log('Step 3 : Creating a local user in b2evolution...');
             $local_User = new User();
             $local_User->set('login', $params['login']);
             $local_User->set('locale', locale_from_httpaccept());
             // use the browser's locale
             $local_User->set_datecreated($localtimenow);
             // $local_User->set( 'level', 1 );
         } else {
             // User exists already exists
             $this->debug_log('Step 3 : Updating the existing local user.');
         }
         $this->debug_log('Randomize password in b2evolution DB and autoactivate user.');
         // Generate a random password (we never want LDAP users to be able to login without a prior LDAP check) (also on update, just in case...
         $local_User->set_password(generate_random_passwd(32));
         // $params['pass'] );
         $local_User->set('status', 'autoactivated');
         // Activate the user automatically (no email activation necessary)
         // Convert each input string to current server encoding:
         $exclude_encoding_fields = array('uid', 'mail', 'jpegphoto');
         if (isset($search_info[0]) && is_array($search_info[0])) {
             foreach ($search_info[0] as $search_info_key => $search_info_data) {
                 if (isset($search_info_data[0]) && is_string($search_info_data[0]) && !in_array($search_info_key, $exclude_encoding_fields)) {
                     // Convert string from LDAP server encoding to current server encoding:
                     $search_info[0][$search_info_key][0] = convert_charset($search_info_data[0], $l_set['encoding'], $evo_charset);
                 }
             }
         }
         // Make some updates:
         // mail -> email:
         if (isset($search_info[0]['mail'][0])) {
             $local_User->set_email($search_info[0]['mail'][0]);
         }
         // uid -> nickname
         if (isset($search_info[0]['uid'][0])) {
             $this->debug_log('UID: <b>' . $search_info[0]['uid'][0] . '</b>');
             $local_User->set('nickname', $search_info[0]['uid'][0]);
         } else {
             // if not found, use login.
             $local_User->set('nickname', $params['login']);
         }
         // givenname -> Firstname:
         if (isset($search_info[0]['givenname'][0])) {
             $this->debug_log('First name (givenname): <b>' . $search_info[0]['givenname'][0] . '</b>');
             $local_User->set('firstname', $search_info[0]['givenname'][0]);
         }
         // sn -> Lastname:
         if (isset($search_info[0]['sn'][0])) {
             $this->debug_log('Last name (sn): <b>' . $search_info[0]['sn'][0] . '</b>');
             $local_User->set('lastname', $search_info[0]['sn'][0]);
         }
         // roomnumber -> user field "roomnumber" (if not found, autocreate it in group "Address")
         if (isset($search_info[0]['roomnumber'][0])) {
             $this->debug_log('Room number: <b>' . $search_info[0]['roomnumber'][0] . '</b>');
             $this->userfield_update_by_code($local_User, 'roomnumber', $search_info[0]['roomnumber'][0], 'Address', 'Room Number', 'word');
         }
         // businesscategory -> user field "businesscategory" (if not found, autocreate it in group "About me")
         if (isset($search_info[0]['businesscategory'][0])) {
             $this->debug_log('Business Category: <b>' . $search_info[0]['businesscategory'][0] . '</b>');
             $this->userfield_update_by_code($local_User, 'businesscategory', $search_info[0]['businesscategory'][0], 'About me', 'Business Category', 'text');
         }
         // telephonenumber -> user field "officephone" (if not found, autocreate it in group "Phone")
         if (isset($search_info[0]['telephonenumber'][0])) {
             $this->debug_log('Office phone: <b>' . $search_info[0]['telephonenumber'][0] . '</b>');
             $this->userfield_update_by_code($local_User, 'officephone', $search_info[0]['telephonenumber'][0], 'Phone', 'Office phone', 'phone');
         }
         // mobile -> user field "cellphone" (if not found, autocreate it in group "Phone")
         if (isset($search_info[0]['mobile'][0])) {
             $this->debug_log('Cell phone: <b>' . $search_info[0]['mobile'][0] . '</b>');
             $this->userfield_update_by_code($local_User, 'cellphone', $search_info[0]['mobile'][0], 'Phone', 'Cell phone', 'phone');
         }
         // employeenumber -> user field "employeenumber" (if not found, autocreate it in group "About me")
         if (isset($search_info[0]['employeenumber'][0])) {
             $this->debug_log('Employee number: <b>' . $search_info[0]['employeenumber'][0] . '</b>');
             $this->userfield_update_by_code($local_User, 'employeenumber', $search_info[0]['employeenumber'][0], 'About me', 'Employee number', 'word');
         }
         // title -> user field "title" (if not found, autocreate it in group "About me")
         if (isset($search_info[0]['title'][0])) {
             $this->debug_log('Title: <b>' . $search_info[0]['title'][0] . '</b>');
             $this->userfield_update_by_code($local_User, 'title', $search_info[0]['title'][0], 'About me', 'Title', 'word');
             $userfield_title = $search_info[0]['title'][0];
             // Use this as role for all organizations below
         } else {
             $userfield_title = '';
         }
         // departmentnumber -> join Organization with the same name (create if doesn't exist)
         if (isset($search_info[0]['departmentnumber'][0])) {
             $this->debug_log('Department Number: <b>' . $search_info[0]['departmentnumber'][0] . '</b>');
             $this->userorg_update_by_name($local_User, $search_info[0]['departmentnumber'][0], $userfield_title);
         }
         // o -> join Organization with the same name (create if doesn't exist)
         if (isset($search_info[0]['o'][0])) {
             $this->debug_log('Organization: <b>' . $search_info[0]['o'][0] . '</b>');
             $this->userorg_update_by_name($local_User, $search_info[0]['o'][0], $userfield_title);
         }
         // telexnumber -> user field "officefax" (if not found, autocreate it in group "Phone")
         if (isset($search_info[0]['telexnumber'][0])) {
             $this->debug_log('Office FAX: <b>' . $search_info[0]['telexnumber'][0] . '</b>');
             $this->userfield_update_by_code($local_User, 'officefax', $search_info[0]['telexnumber'][0], 'Phone', 'Office FAX', 'phone');
         }
         // ---- GROUP STUFF ----
         if ($update_mode == true) {
             // Updating existing user
             $this->debug_log('Updating existing user: we do NOT touch the primary group.');
             $local_User->dbupdate();
             $this->debug_log('OK -- User has been updated.');
         } else {
             // Try to assign prilary group from the search results:
             $assigned_group = false;
             if (!empty($l_set['assign_user_to_group_by'])) {
                 $this->debug_log('Plugin is configured to assign the Primary Group by the ' . $l_set['assign_user_to_group_by'] . ' key...');
                 if (isset($search_info[0][$l_set['assign_user_to_group_by']]) && isset($search_info[0][$l_set['assign_user_to_group_by']][0])) {
                     // There is info we want to assign by
                     $assign_by_value = $search_info[0][$l_set['assign_user_to_group_by']][0];
                     $this->debug_log('User info says has ' . $l_set['assign_user_to_group_by'] . ' = "<b>' . $assign_by_value . '</b>"');
                     $GroupCache =& get_Cache('GroupCache');
                     if ($users_Group =& $GroupCache->get_by_name($assign_by_value, false)) {
                         // A group with the users value returned exists.
                         $local_User->set_Group($users_Group);
                         $assigned_group = true;
                         $this->debug_log('Assigning User to existing Primary Group.');
                     } else {
                         $this->debug_log('Group with that name does not exist...');
                         if ($new_Group =& $this->usergroup_create($l_set['tpl_new_grp_ID'], $assign_by_value)) {
                             // Link the user to new created group:
                             $local_User->set_Group($new_Group);
                             $assigned_group = true;
                             $this->debug_log('Assigned User to new Primary Group.');
                         }
                     }
                 }
             }
             if (!$assigned_group) {
                 // Default group:
                 $this->debug_log('Falling back to default primary group...');
                 $users_Group = NULL;
                 $fallback_grp_ID = $this->Settings->get('fallback_grp_ID');
                 if (empty($fallback_grp_ID)) {
                     $this->debug_log('No default/fallback primary group configured.');
                     $this->debug_log('User NOT created, try next LDAP server...');
                     //Continue to next LDAP server:
                     continue;
                 } else {
                     $GroupCache =& get_Cache('GroupCache');
                     $users_Group =& $GroupCache->get_by_ID($fallback_grp_ID);
                     if ($users_Group) {
                         // either $this->default_group_name is not given or wrong
                         $local_User->set_Group($users_Group);
                         $assigned_group = true;
                         $this->debug_log('Using default/fallback primary group: <b>' . $users_Group->get('name') . '</b>');
                     } else {
                         $this->debug_log('Default/fallback primary group does not exist (' . $fallback_grp_ID . ').');
                         $this->debug_log('User NOT created, try next LDAP server...');
                         //Continue to next LDAP server:
                         continue;
                     }
                 }
             }
             $local_User->dbinsert();
             $UserCache->add($local_User);
             $this->debug_log('OK -- User has been created.');
         }
         // Remember this settings number in order use this first in next logging time by current user:
         $this->UserSettings->set('search_set_num', $l_id, $local_User->ID);
         $this->UserSettings->dbupdate();
         // Assign user to organizations:
         $this->userorg_assign_to_user($local_User);
         // jpegphoto -> Save as profile pictue "ldap.jpeg" and associate with user
         if (isset($search_info[0]['jpegphoto'][0])) {
             $this->debug_log('Photo: <img src="data:image/jpeg;base64,' . base64_encode($search_info[0]['jpegphoto'][0]) . '" />');
             // Save to disk and attach to user:
             $this->userimg_attach_photo($local_User, $search_info[0]['jpegphoto'][0], !empty($l_set['expand_pics']));
         }
         // --- EXTRA GROUPS ---
         if (!empty($l_set['secondary_grp_search_filter'])) {
             global $app_version;
             if (evo_version_compare($app_version, '6.7.0-alpha') < 0) {
                 // The plugin is used on b2evo 6.6
                 $this->debug_log('Secondary groups not handled. This feature requires b2evolution v6.7.0-alpha or newer.');
             } elseif (empty($l_set['secondary_grp_name_attribute'])) {
                 $this->debug_log('Missing name attribute for secondary groups');
             } else {
                 $filter = str_replace('%s', $params['login'], $l_set['secondary_grp_search_filter']);
                 $grp_name_attribute = $l_set['secondary_grp_name_attribute'];
                 $this->debug_log(sprintf('Step 4 : Now querying for secondary groups. base_dn: <b>%s</b>, filter: <b>%s</b>, name attribue=<b>%s</b>', $l_set['secondary_grp_base_dn'], $filter, $grp_name_attribute));
                 $search_result = @ldap_search($ldap_conn, $l_set['secondary_grp_base_dn'], $filter, array($grp_name_attribute));
                 if (!$search_result) {
                     // this may happen with an empty base_dn
                     $this->debug_log('Invalid ldap_search result. No secondary groups will be assigned. Errno: ' . ldap_errno($ldap_conn) . ' Error: ' . ldap_error($ldap_conn));
                 } else {
                     $search_info = ldap_get_entries($ldap_conn, $search_result);
                     // $this->debug_log( 'Results returned by LDAP Server: <pre>'.var_export( $search_info, true ).'</pre>' );
                     $secondary_groups = array();
                     // $this->debug_log( 'Secondary groups name prefix: <pre>'.var_export( $l_set['secondary_grp_name_prefix'], true ).'</pre>' );
                     // Walk through results:
                     foreach ($search_info as $group_candidate) {
                         if (is_array($group_candidate) && isset($group_candidate[$grp_name_attribute][0])) {
                             $group_candidate_cn = $group_candidate[$grp_name_attribute][0];
                             if (empty($l_set['secondary_grp_name_prefix']) || strpos($group_candidate_cn, $l_set['secondary_grp_name_prefix']) === 0) {
                                 // prefix is ok
                                 $this->debug_log('Accepted Secondary Group: ' . $group_candidate_cn);
                                 $secondary_groups[] = $group_candidate_cn;
                             } else {
                                 // prefix is NOT ok
                                 $this->debug_log('REJECTED Secondary Group: ' . $group_candidate_cn);
                             }
                         }
                     }
                     // Hardcode two secondary groups:
                     // $secondary_groups = array( 'Blog B members', 'Blog D Members' );
                     $this->debug_log('Secondary groups to be assigned: <pre>' . var_export($secondary_groups, true) . '</pre>');
                     // Update secondary groups for the User:
                     $this->usersecgroup_update($local_User, $secondary_groups, $l_set['tpl_new_secondary_grp_ID']);
                 }
             }
         }
         if (isset($initial_protocol_version)) {
             ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, $initial_protocol_version);
         }
         // --- CONSIDER THE LOGIN ATTEMPT TO BE SUCCESSFUL AND WE ACCEPT IT ---
         // Update this value which has been passed by REFERENCE:
         $params['pass_ok'] = true;
         return true;
         // Login was a success (but return "true" does not trigger anything special in b2evolution)
     }
     if (isset($initial_protocol_version)) {
         ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, $initial_protocol_version);
     }
     return false;
     // Login failed!
 }