/** * Implement user searching with SQL * * NOTE: user with ID zero should never be returned * * @param string The query string * @param integer How many results to return * @param integer What result to start at (0 == first result) * @param data Filters the users searched by * can contain: * 'group' => integer, // only users in this group * 'owner' => boolean // include the group ownwer (only if group is set) * 'exclude'=> int // excludes a user * @return array A data structure containing results looking like ... * $results = array( * count => integer, // total number of results * limit => integer, // how many results are returned * offset => integer, // starting from which result * data => array( // the result records * array( * id => integer, * username => string, * institution => string, * firstname => string, * lastname => string, * preferredname => string, * email => string, * ), * array( * id => integer, * username => string, * institution => string, * firstname => string, * lastname => string, * preferredname => string, * email => string, * ), * array(...), * ), * ); */ public static function search_user($query_string, $limit, $offset = 0, $data = array()) { safe_require('artefact', 'internal'); $publicfields = array_keys(ArtefactTypeProfile::get_public_fields()); if (empty($publicfields)) { $publicfields = array('preferredname'); } if (is_postgres()) { return self::search_user_pg($query_string, $limit, $offset, $data, $publicfields); } else { if (is_mysql()) { return self::search_user_my($query_string, $limit, $offset, $data, $publicfields); } else { throw new SQLException('search_user() is not implemented for your database engine (' . get_config('dbtype') . ')'); } } }
/** * Given a query string and limits, return an array of matching users using the * search plugin defined in config.php * * @param string The query string * @param integer How many results to return * @param integer What result to start at (0 == first result) * @return array A data structure containing results looking like ... * $results = array( * count => integer, // total number of results * limit => integer, // how many results are returned * offset => integer, // starting from which result * results => array( // the result records * array( * id => integer, * username => string, * institution => string, * firstname => string, * lastname => string, * preferredname => string, * email => string, * ), * array( * id => integer, * username => string, * institution => string, * firstname => string, * lastname => string, * preferredname => string, * email => string, * ), * array(...), * ), * ); */ function search_user($query_string, $limit, $offset = 0, $data = array()) { $plugin = get_config('searchplugin'); safe_require('search', $plugin); safe_require('artefact', 'internal'); $publicfields = array_keys(ArtefactTypeProfile::get_public_fields()); if (empty($publicfields)) { $publicfields = array('preferredname'); } $fieldlist = "('" . join("','", $publicfields) . "')"; $results = call_static_method(generate_class_name('search', $plugin), 'search_user', $query_string, $limit, $offset, $data); if ($results['data']) { $userlist = '(' . join(',', array_map(create_function('$u', 'return (int)$u[\'id\'];'), $results['data'])) . ')'; $public_fields = get_records_sql_array(' SELECT u.id, a.artefacttype, a.title FROM {usr} u LEFT JOIN {artefact} a ON u.id=a.owner AND a.artefacttype IN ' . $fieldlist . ' WHERE u.id IN ' . $userlist . ' ORDER BY u.firstname, u.lastname, u.id, a.artefacttype', array()); $public_fields_byuser = array(); if (!empty($public_fields)) { foreach ($public_fields as $field) { // This will be null if the user does not have a field marked public if ($field->artefacttype !== null) { $public_fields_byuser[$field->id][$field->artefacttype] = $field->title; } } } foreach ($results['data'] as &$result) { $result['name'] = display_name($result); if (isset($public_fields_byuser[$result['id']])) { foreach ($public_fields_byuser[$result['id']] as $field => $value) { $result[$field] = $value; } } if (isset($result['country'])) { $result['country'] = get_string('country.' . $result['country']); } } } return $results; }
define('SECTION_PAGE', 'social'); define('INTERNAL_SUBPAGE', 'social'); require_once dirname(dirname(dirname(__FILE__))) . '/init.php'; define('TITLE', get_string('profile', 'artefact.internal')); require_once 'pieforms/pieform.php'; safe_require('artefact', 'internal'); if (!get_record('blocktype_installed', 'active', 1, 'name', 'socialprofile')) { // This block type is not installed. The user is not allowed in this form. throw new AccessDeniedException(get_string('accessdenied', 'error')); } $id = param_integer('id', 0); $delete = param_integer('delete', 0); if ($delete) { // Check if social profile is a mandatory system field // and if this is the last field, they can't delete it. $mandatory_fields = ArtefactTypeProfile::get_mandatory_fields(); if (isset($mandatory_fields['socialprofile'])) { $social_profiles = ArtefactTypeSocialprofile::get_social_profiles(); if (count($social_profiles) <= 1) { // they can't delete. $SESSION->add_error_msg(get_string('socialprofilerequired', 'artefact.internal')); redirect('/artefact/internal/index.php?fs=social'); } } $todelete = new ArtefactTypeSocialprofile($id); if (!$USER->can_edit_artefact($todelete)) { throw new AccessDeniedException(get_string('accessdenied', 'error')); } $deleteform = array('name' => 'deleteprofileform', 'plugintype' => 'artefact', 'pluginname' => 'internal', 'renderer' => 'div', 'elements' => array('submit' => array('type' => 'submitcancel', 'class' => 'btn-default', 'value' => array(get_string('deleteprofile', 'artefact.internal'), get_string('cancel')), 'goto' => get_config('wwwroot') . '/artefact/internal/index.php?fs=social'))); $form = pieform($deleteform); $message = get_string('deleteprofileconfirm', 'artefact.internal');
/** * Returns a snippet of an sql WHERE clause to filter users whose (visible) * names match the terms in a given query string. */ function name_search_sql($query_string, $usralias = 'u', $usrprefalias = 'h') { safe_require('artefact', 'internal'); // Get the list of searchable profile fields from the internal artefact $required = array_keys(ArtefactTypeProfile::get_always_searchable_fields()); $optional = array_diff(array_keys(ArtefactTypeProfile::get_searchable_fields()), $required); $required[] = 'username'; // Not a profile field, but used in the search query. // Get a list of match expressions to use in the WHERE clause $matches = new StdClass(); foreach (array_merge($required, $optional) as $f) { $matches->{$f} = self::match_user_field_expression($f, $usralias); } $querydata = self::split_query_string(strtolower(trim($query_string))); $hidenameallowed = get_config('userscanhiderealnames') ? 'TRUE' : 'FALSE'; $searchusernamesallowed = get_config('searchusernames') ? 'TRUE' : 'FALSE'; $termsql = "{$matches->preferredname}\n OR (\n ({$usralias}.preferredname IS NULL OR {$usralias}.preferredname = '' OR NOT {$hidenameallowed} OR {$usrprefalias}.value != '1' OR {$usrprefalias}.value IS NULL)\n AND ({$matches->firstname} OR {$matches->lastname})\n )\n OR ({$searchusernamesallowed} AND {$matches->username})"; if ($optional) { foreach ($optional as $f) { $termsql .= "\n OR {$matches->{$f}}"; } } $where = ''; $values = array(); foreach ($querydata as $term) { $where .= ' AND ( ' . $termsql . ' )'; $values = array_pad($values, count($values) + 4 + count($optional), $term); } return array($where, $values); }
function institution_submit(Pieform $form, $values) { global $SESSION, $institution, $add, $instancearray, $USER, $authinstances; db_begin(); // Update the basic institution record... $newinstitution = new StdClass(); if ($add) { $institution = $newinstitution->name = strtolower($values['name']); } $newinstitution->displayname = $values['displayname']; $newinstitution->authplugin = empty($values['authplugin']) ? null : $values['authplugin']; if (get_config('usersuniquebyusername')) { // Registering absolutely not allowed when this setting is on, it's a // security risk. See the documentation for the usersuniquebyusername // setting for more information $newinstitution->registerallowed = 0; } else { $newinstitution->registerallowed = $values['registerallowed'] ? 1 : 0; } $newinstitution->theme = empty($values['theme']) || $values['theme'] == 'sitedefault' ? null : $values['theme']; if ($institution != 'mahara') { $newinstitution->defaultmembershipperiod = $values['defaultmembershipperiod'] ? intval($values['defaultmembershipperiod']) : null; if ($USER->get('admin')) { $newinstitution->maxuseraccounts = $values['maxuseraccounts'] ? intval($values['maxuseraccounts']) : null; $newinstitution->expiry = db_format_timestamp($values['expiry']); } } if (!empty($values['authplugin'])) { $allinstances = array_merge($values['authplugin']['instancearray'], $values['authplugin']['deletearray']); if (array_diff($allinstances, $instancearray)) { throw new ConfigException('Attempt to delete or update another institution\'s auth instance'); } if (array_diff($instancearray, $allinstances)) { throw new ConfigException('One of your instances is unaccounted for in this transaction'); } foreach ($values['authplugin']['instancearray'] as $priority => $instanceid) { if (in_array($instanceid, $values['authplugin']['deletearray'])) { // Should never happen: throw new SystemException('Attempt to update AND delete an auth instance'); } $record = new StdClass(); $record->priority = $priority; $record->id = $instanceid; update_record('auth_instance', $record, array('id' => $instanceid)); } foreach ($values['authplugin']['deletearray'] as $instanceid) { // If this authinstance is the only xmlrpc authinstance that references a host, delete the host record. $hostwwwroot = null; foreach ($authinstances as $ai) { if ($ai->id == $instanceid && $ai->authname == 'xmlrpc') { $hostwwwroot = get_field_sql("SELECT \"value\" FROM {auth_instance_config} WHERE \"instance\" = ? AND field = 'wwwroot'", array($instanceid)); if ($hostwwwroot && count_records_select('auth_instance_config', "field = 'wwwroot' AND \"value\" = ?", array($hostwwwroot)) == 1) { // Unfortunately, it's possible that this host record could belong to a different institution, // so specify the institution here. delete_records('host', 'wwwroot', $hostwwwroot, 'institution', $institution); // We really need to fix this, either by removing the institution from the host table, or refusing to allow the // institution to be changed in the host record when another institution's authinstance is still pointing at it. } break; } } delete_records('auth_remote_user', 'authinstance', $instanceid); delete_records('auth_instance_config', 'instance', $instanceid); delete_records('auth_instance', 'id', $instanceid); } } if ($add) { insert_record('institution', $newinstitution); // If registration has been turned on, then we automatically insert an // internal authentication authinstance if ($newinstitution->registerallowed) { $authinstance = (object) array('instancename' => 'internal', 'priority' => 0, 'institution' => $newinstitution->name, 'authname' => 'internal'); insert_record('auth_instance', $authinstance); } } else { $where = new StdClass(); $where->name = $institution; $oldtheme = get_field('institution', 'theme', 'name', $institution); update_record('institution', $newinstitution, $where); } delete_records('institution_locked_profile_field', 'name', $institution); foreach (ArtefactTypeProfile::get_all_fields() as $field => $type) { if ($values[$field]) { $profilefield = new StdClass(); $profilefield->name = $institution; $profilefield->profilefield = $field; insert_record('institution_locked_profile_field', $profilefield); } } db_commit(); if ($add) { if ($newinstitution->registerallowed) { // If registration is not allowed, then an authinstance will not // have been created, and thus cause the institution page to add // its own error message on the next page load $SESSION->add_ok_msg(get_string('institutionaddedsuccessfully2', 'admin')); } $nexturl = '/admin/users/institutions.php?i=' . urlencode($institution); } else { $message = get_string('institutionupdatedsuccessfully', 'admin'); if (isset($values['theme']) && $oldtheme != $values['theme'] && (!empty($oldtheme) || $values['theme'] != 'sitedefault')) { $USER->update_theme(); $message .= ' ' . get_string('usersseenewthemeonlogin', 'admin'); } $SESSION->add_ok_msg($message); $nexturl = '/admin/users/institutions.php'; } redirect($nexturl); }
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL * @copyright (C) 2006-2009 Catalyst IT Ltd http://catalyst.net.nz * */ define('INTERNAL', 1); define('MENUITEM', 'profile/edit'); define('SECTION_PLUGINTYPE', 'artefact'); define('SECTION_PLUGINNAME', 'internal'); define('SECTION_PAGE', 'index'); require dirname(dirname(dirname(__FILE__))) . '/init.php'; define('TITLE', get_string('editprofile', 'artefact.internal')); require_once 'pieforms/pieform.php'; safe_require('artefact', 'internal'); $fieldset = param_alpha('fs', 'aboutme'); $element_list = call_static_method('ArtefactTypeProfile', 'get_all_fields'); $element_data = ArtefactTypeProfile::get_field_element_data(); $element_required = call_static_method('ArtefactTypeProfile', 'get_mandatory_fields'); // load existing profile information $profilefields = array(); $profile_data = get_records_select_array('artefact', "owner=? AND artefacttype IN (" . join(",", array_map(create_function('$a', 'return db_quote($a);'), array_keys($element_list))) . ")", array($USER->get('id'))); if ($profile_data) { foreach ($profile_data as $field) { $profilefields[$field->artefacttype] = $field->title; } } $lockedfields = locked_profile_fields(); $profilefields['email'] = array(); $profilefields['email']['all'] = get_records_array('artefact_internal_profile_email', 'owner', $USER->get('id')); $profilefields['email']['validated'] = array(); $profilefields['email']['unvalidated'] = array(); $profilefields['email']['unsent'] = array();
/** * Checks that all the required fields are set, and handles setting them if required. * * Checks whether the current user needs to change their password, and handles * the password changing if it's required. */ function auth_check_required_fields() { global $USER, $SESSION; if (defined('NOCHECKREQUIREDFIELDS')) { return; } $changepassword = true; $elements = array(); if (!$USER->get('passwordchange') || $USER->get('parentuser') && $USER->get('loginanyway') || defined('NOCHECKPASSWORDCHANGE')) { $changepassword = false; } // Check if the user wants to log in anyway if ($USER->get('passwordchange') && $USER->get('parentuser') && isset($_GET['loginanyway'])) { $USER->loginanyway = true; $changepassword = false; } // Do not force password change on JSON request. if (defined('JSON') && JSON == true) { $changepassword = false; } if ($changepassword) { $authobj = AuthFactory::create($USER->authinstance); if ($authobj->changepasswordurl) { redirect($authobj->changepasswordurl); exit; } if (method_exists($authobj, 'change_password')) { if ($SESSION->get('resetusername')) { $elements['username'] = array('type' => 'text', 'defaultvalue' => $USER->get('username'), 'title' => get_string('changeusername', 'account'), 'description' => get_string('changeusernamedesc', 'account', hsc(get_config('sitename')))); } $elements['password1'] = array('type' => 'password', 'title' => get_string('newpassword') . ':', 'description' => get_string('yournewpassword'), 'rules' => array('required' => true)); $elements['password2'] = array('type' => 'password', 'title' => get_string('confirmpassword') . ':', 'description' => get_string('yournewpasswordagain'), 'rules' => array('required' => true)); $elements['country'] = array('type' => 'select', 'title' => "Country", 'options' => array("ca" => "Canada", "us" => "United States"), 'defaultvalue' => "us", 'description' => "Country", 'rules' => array('required' => true)); $elements['state'] = array('type' => 'select', 'title' => "State", 'options' => array('AL' => "Alabama", 'AK' => "Alaska", 'AZ' => "Arizona", 'AR' => "Arkansas", 'CA' => "California", 'CO' => "Colorado", 'CT' => "Connecticut", 'DE' => "Delaware", 'DC' => "District of Columbia", 'FL' => "Florida", 'GA' => "Georgia", 'HI' => "Hawaii", 'ID' => "Idaho", 'IL' => "Illinois", 'IN' => "Indiana", 'IA' => "Iowa", 'KS' => "Kansas", 'KY' => "Kentucky", 'LA' => "Louisiana", 'ME' => "Maine", 'MD' => "Maryland", 'MA' => "Massachusetts", 'MI' => "Michigan", 'MN' => "Minnesota", 'MS' => "Mississippi", 'MO' => "Missouri", 'MT' => "Montana", 'NE' => "Nebraska", 'NV' => "Nevada", 'NH' => "New Hampshire", 'NJ' => "New Jersey", 'NM' => "New Mexico", 'NY' => "New York", 'NC' => "North Carolina", 'ND' => "North Dakota", 'OH' => "Ohio", 'OK' => "Oklahoma", 'OR' => "Oregon", 'PA' => "Pennsylvania", 'RI' => "Rhode Island", 'SC' => "South Carolina", 'SD' => "South Dakota", 'TN' => "Tennessee", 'TX' => "Texas", 'UT' => "Utah", 'VT' => "Vermont", 'VA' => "Virginia", 'WA' => "Washington", 'WV' => "West Virginia", 'WI' => "Wisconsin", 'WY' => "Wyoming", 'AB' => "Alberta", 'BC' => "British Columbia", 'MB' => "Manitoba", 'NB' => "New Brunswick", 'NL' => "Newfoundland and Labrador", 'NT' => "Northwest Territories", 'NS' => "Nova Scotia", 'NU' => "Nunavut", 'ON' => "Ontario", 'PE' => "Prince Edward Island", 'QC' => "Quebec", 'SK' => "Saskatchewan", 'YT' => "Yukon"), 'description' => "State", 'rules' => array('required' => true)); $elements['email'] = array('type' => 'text', 'title' => get_string('principalemailaddress', 'artefact.internal'), 'ignore' => trim($USER->get('email')) != '' && !preg_match('/@example\\.org$/', $USER->get('email')), 'rules' => array('required' => true, 'email' => true)); } } else { if (defined('JSON')) { // Don't need to check this for json requests return; } } safe_require('artefact', 'internal'); require_once 'pieforms/pieform.php'; $alwaysmandatoryfields = array_keys(ArtefactTypeProfile::get_always_mandatory_fields()); foreach (ArtefactTypeProfile::get_mandatory_fields() as $field => $type) { // Always mandatory fields are stored in the usr table, so are part of // the user session object. We can save a query by grabbing them from // the session. if (in_array($field, $alwaysmandatoryfields) && $USER->get($field) != null) { continue; } // Not cached? Get value the standard way. if (get_profile_field($USER->get('id'), $field) != null) { continue; } if ($field == 'email') { if (isset($elements['email'])) { continue; } // Use a text field for their first e-mail address, not the // emaillist element $type = 'text'; } $elements[$field] = array('type' => $type, 'title' => get_string($field, 'artefact.internal'), 'rules' => array('required' => true)); if ($field == 'socialprofile') { $elements[$field] = ArtefactTypeSocialprofile::get_new_profile_elements(); // add an element to flag that socialprofile is in the list of fields. $elements['socialprofile_hidden'] = array('type' => 'hidden', 'value' => 1); } // @todo ruthlessly stolen from artefact/internal/index.php, could be merged if ($type == 'wysiwyg') { $elements[$field]['rows'] = 10; $elements[$field]['cols'] = 60; } if ($type == 'textarea') { $elements[$field]['rows'] = 4; $elements[$field]['cols'] = 60; } if ($field == 'country') { $elements[$field]['options'] = getoptions_country(); $elements[$field]['defaultvalue'] = get_config('country'); } if ($field == 'email') { // Check if a validation email has been sent if (record_exists('artefact_internal_profile_email', 'owner', $USER->get('id'))) { $elements['email']['type'] = 'html'; $elements['email']['value'] = get_string('validationprimaryemailsent', 'auth'); $elements['email']['disabled'] = true; $elements['email']['rules'] = array('required' => false); } else { $elements[$field]['rules']['email'] = true; $elements[$field]['description'] = get_string('primaryemaildescription', 'auth'); } } } if (empty($elements)) { // No mandatory fields that aren't set return; } if (count($elements) == 1 && isset($elements['email']) && $elements['email']['type'] == 'html') { // Display a message if there is only 1 required field and this field is email whose validation has been sent $elements['submit'] = array('type' => 'submit', 'value' => get_string('continue', 'admin')); $form = pieform(array('name' => 'requiredfields', 'method' => 'post', 'action' => get_config('wwwroot') . '?logout', 'elements' => $elements)); } else { $elements['submit'] = array('type' => 'submit', 'value' => get_string('submit')); $form = pieform(array('name' => 'requiredfields', 'method' => 'post', 'action' => '', 'elements' => $elements)); } $smarty = smarty(); if ($USER->get('parentuser')) { $smarty->assign('loginasoverridepasswordchange', get_string('loginasoverridepasswordchange', 'admin', '<a class="btn" href="' . get_config('wwwroot') . '?loginanyway">', '</a>')); } $smarty->assign('changepassword', $changepassword); $smarty->assign('changeusername', $SESSION->get('resetusername')); $smarty->assign('form', $form); $smarty->display('requiredfields.tpl'); exit; }
define('INSTITUTIONALADMIN', 1); define('MENUITEM', 'configusers/uploadcsv'); require dirname(dirname(dirname(__FILE__))) . '/init.php'; define('TITLE', get_string('uploadcsv', 'admin')); require_once 'pieforms/pieform.php'; require_once 'institution.php'; require_once 'phpmailer/class.phpmailer.php'; safe_require('artefact', 'internal'); raise_memory_limit("512M"); // Turn on autodetecting of line endings, so mac newlines (\r) will work ini_set('auto_detect_line_endings', 1); $FORMAT = array(); $specialcases = array('username', 'password', 'remoteuser'); // Don't upload social profiles for now. A user can have multiple profiles. Not sure how to put that in a csv. $notallowed = array('socialprofile'); $ALLOWEDKEYS = array_keys(ArtefactTypeProfile::get_all_fields()); $ALLOWEDKEYS = array_diff($ALLOWEDKEYS, $notallowed); $maildisabled = array_search('maildisabled', $ALLOWEDKEYS); unset($ALLOWEDKEYS[$maildisabled]); $ALLOWEDKEYS = array_merge($ALLOWEDKEYS, $specialcases); $UPDATES = array(); // During validation, remember which users already exist $INSTITUTIONNAME = array(); // Mapping from institution id to display name if ($USER->get('admin')) { $authinstances = auth_get_auth_instances(); } else { $admininstitutions = $USER->get('admininstitutions'); $authinstances = auth_get_auth_instances_for_institutions($admininstitutions); if (empty($authinstances)) { $SESSION->add_info_msg(get_string('configureauthplugin', 'admin'));
public static function rebuild_users() { log_debug('Starting rebuild_users()'); self::delete_bytype('user'); $users = get_recordset('usr', 'deleted', '0'); safe_require('artefact', 'internal'); $publicfields = array_keys(ArtefactTypeProfile::get_public_fields()); while ($user = $users->FetchRow()) { if ($user['id'] == 0) { continue; } self::index_user($user); } $users->close(); log_debug('Completed rebuild_users()'); }
/** * Checks that all the required fields are set, and handles setting them if required. */ function auth_check_required_fields() { global $USER; if (defined('JSON')) { // Don't need to check this for json requests return; } safe_require('artefact', 'internal'); require_once 'pieforms/pieform.php'; $elements = array(); $alwaysmandatoryfields = array_keys(ArtefactTypeProfile::get_always_mandatory_fields()); foreach (ArtefactTypeProfile::get_mandatory_fields() as $field => $type) { // Always mandatory fields are stored in the usr table, so are part of // the user session object. We can save a query by grabbing them from // the session. if (in_array($field, $alwaysmandatoryfields) && $USER->get($field) != null) { continue; } // Not cached? Get value the standard way. if (get_profile_field($USER->get('id'), $field) != null) { continue; } if ($field == 'email') { // Use a text field for their first e-mail address, not the // emaillist element $type = 'text'; } $elements[$field] = array('type' => $type, 'title' => get_string($field, 'artefact.internal'), 'rules' => array('required' => true)); // @todo ruthlessly stolen from artefact/internal/index.php, could be merged if ($type == 'wysiwyg') { $elements[$field]['rows'] = 10; $elements[$field]['cols'] = 60; } if ($type == 'textarea') { $elements[$field]['rows'] = 4; $elements[$field]['cols'] = 60; } if ($field == 'country') { $elements[$field]['options'] = getoptions_country(); $elements[$field]['defaultvalue'] = 'nz'; } if ($field == 'email') { $elements[$field]['rules']['email'] = true; } } if (empty($elements)) { // No mandatory fields that aren't set return; } $elements['submit'] = array('type' => 'submit', 'value' => get_string('submit')); $form = pieform(array('name' => 'requiredfields', 'method' => 'post', 'action' => '', 'elements' => $elements)); $smarty = smarty(); $smarty->assign('form', $form); $smarty->display('requiredfields.tpl'); exit; }
/** * Checks that all the required fields are set, and handles setting them if required. * * Checks whether the current user needs to change their password, and handles * the password changing if it's required. */ function auth_check_required_fields() { global $USER, $SESSION; $changepassword = true; $elements = array(); if (!$USER->get('passwordchange') || $USER->get('parentuser') && $USER->get('loginanyway') || defined('NOCHECKPASSWORDCHANGE')) { $changepassword = false; } // Check if the user wants to log in anyway if ($USER->get('passwordchange') && $USER->get('parentuser') && isset($_GET['loginanyway'])) { $USER->loginanyway = true; $changepassword = false; } if ($changepassword) { $authobj = AuthFactory::create($USER->authinstance); if ($authobj->changepasswordurl) { redirect($authobj->changepasswordurl); exit; } if (method_exists($authobj, 'change_password')) { if ($SESSION->get('resetusername')) { $elements['username'] = array('type' => 'text', 'defaultvalue' => $USER->get('username'), 'title' => get_string('changeusername', 'account'), 'description' => get_string('changeusernamedesc', 'account', hsc(get_config('sitename')))); } $elements['password1'] = array('type' => 'password', 'title' => get_string('newpassword') . ':', 'description' => get_string('yournewpassword'), 'rules' => array('required' => true)); $elements['password2'] = array('type' => 'password', 'title' => get_string('confirmpassword') . ':', 'description' => get_string('yournewpasswordagain'), 'rules' => array('required' => true)); $elements['email'] = array('type' => 'text', 'title' => get_string('principalemailaddress', 'artefact.internal'), 'ignore' => trim($USER->get('email')) != '' && !preg_match('/@example\\.org$/', $USER->get('email')), 'rules' => array('required' => true, 'email' => true)); } } else { if (defined('JSON')) { // Don't need to check this for json requests return; } } safe_require('artefact', 'internal'); require_once 'pieforms/pieform.php'; $alwaysmandatoryfields = array_keys(ArtefactTypeProfile::get_always_mandatory_fields()); foreach (ArtefactTypeProfile::get_mandatory_fields() as $field => $type) { // Always mandatory fields are stored in the usr table, so are part of // the user session object. We can save a query by grabbing them from // the session. if (in_array($field, $alwaysmandatoryfields) && $USER->get($field) != null) { continue; } // Not cached? Get value the standard way. if (get_profile_field($USER->get('id'), $field) != null) { continue; } if ($field == 'email') { if (isset($elements['email'])) { continue; } // Use a text field for their first e-mail address, not the // emaillist element $type = 'text'; } $elements[$field] = array('type' => $type, 'title' => get_string($field, 'artefact.internal'), 'rules' => array('required' => true)); // @todo ruthlessly stolen from artefact/internal/index.php, could be merged if ($type == 'wysiwyg') { $elements[$field]['rows'] = 10; $elements[$field]['cols'] = 60; } if ($type == 'textarea') { $elements[$field]['rows'] = 4; $elements[$field]['cols'] = 60; } if ($field == 'country') { $elements[$field]['options'] = getoptions_country(); $elements[$field]['defaultvalue'] = get_config('country'); } if ($field == 'email') { $elements[$field]['rules']['email'] = true; } } if (empty($elements)) { // No mandatory fields that aren't set return; } $elements['submit'] = array('type' => 'submit', 'value' => get_string('submit')); $form = pieform(array('name' => 'requiredfields', 'method' => 'post', 'action' => '', 'elements' => $elements)); $smarty = smarty(); if ($USER->get('parentuser')) { $smarty->assign('loginasoverridepasswordchange', get_string('loginasoverridepasswordchange', 'admin', '<a href="' . get_config('wwwroot') . '?loginanyway">', '</a>')); } $smarty->assign('changepassword', $changepassword); $smarty->assign('changeusername', $SESSION->get('resetusername')); $smarty->assign('form', $form); $smarty->display('requiredfields.tpl'); exit; }
/** * The CSV file is parsed here so validation errors can be returned to the * user. The data from a successful parsing is stored in the <var>$CVSDATA</var> * array so it can be accessed by the submit function * * @param Pieform $form The form to validate * @param array $values The values submitted */ function uploadcsv_validate(Pieform $form, $values) { global $CSVDATA, $ALLOWEDKEYS, $FORMAT, $USER; // Don't even start attempting to parse if there are previous errors if ($form->has_errors()) { return; } if ($values['file']['size'] == 0) { $form->set_error('file', $form->i18n('rule', 'required', 'required', array())); return; } require_once 'pear/File.php'; require_once 'pear/File/CSV.php'; // Don't be tempted to use 'explode' here. There may be > 1 underscore. $break = strpos($values['authinstance'], '_'); $authinstance = substr($values['authinstance'], 0, $break); $institution = substr($values['authinstance'], $break + 1); if (!$USER->can_edit_institution($institution)) { $form->set_error('authinstance', get_string('notadminforinstitution', 'admin')); return; } $usernames = array(); $emails = array(); $conf = File_CSV::discoverFormat($values['file']['tmp_name']); $i = 0; while ($line = File_CSV::readQuoted($values['file']['tmp_name'], $conf)) { $i++; if (!is_array($line)) { // Note: the CSV parser returns true on some errors and false on // others! Yes that's retarded. No I didn't write it :( $form->set_error('file', get_string('uploadcsverrorincorrectnumberoffields', 'admin', $i)); return; } // Get the format of the file if ($i == 1) { foreach ($line as &$potentialkey) { $potentialkey = trim($potentialkey); if (!in_array($potentialkey, $ALLOWEDKEYS)) { $form->set_error('file', get_string('uploadcsverrorinvalidfieldname', 'admin', $potentialkey)); return; } } // Now we know all of the field names are valid, we need to make // sure that the required fields are included $mandatoryfields = array('username', 'password'); $mandatoryfields = array_merge($mandatoryfields, array_keys(ArtefactTypeProfile::get_mandatory_fields())); if ($lockedprofilefields = get_column('institution_locked_profile_field', 'profilefield', 'name', $institution)) { $mandatoryfields = array_merge($mandatoryfields, $lockedprofilefields); } // Add in the locked profile fields for this institution foreach ($mandatoryfields as $field) { if (!in_array($field, $line)) { $form->set_error('file', get_string('uploadcsverrorrequiredfieldnotspecified', 'admin', $field)); return; } } // The format line is valid $FORMAT = $line; log_info('FORMAT:'); log_info($FORMAT); } else { // Trim non-breaking spaces -- they get left in place by File_CSV foreach ($line as &$field) { $field = preg_replace('/^(\\s|\\xc2\\xa0)*(.*?)(\\s|\\xc2\\xa0)*$/', '$2', $field); } // We have a line with the correct number of fields, but should validate these fields // Note: This validation should really be methods on each profile class, that way // it can be used in the profile screen as well. $formatkeylookup = array_flip($FORMAT); $username = $line[$formatkeylookup['username']]; $password = $line[$formatkeylookup['password']]; $email = $line[$formatkeylookup['email']]; $authobj = AuthFactory::create($authinstance); if (method_exists($authobj, 'is_username_valid') && !$authobj->is_username_valid($username)) { $form->set_error('file', get_string('uploadcsverrorinvalidusername', 'admin', $i)); return; } if (record_exists_select('usr', 'LOWER(username) = ?', strtolower($username)) || isset($usernames[strtolower($username)])) { $form->set_error('file', get_string('uploadcsverroruseralreadyexists', 'admin', $i, $username)); return; } if (record_exists('usr', 'email', $email) || isset($emails[$email])) { $form->set_error('file', get_string('uploadcsverroremailaddresstaken', 'admin', $i, $email)); } // Note: only checks for valid form are done here, none of the checks // like whether the password is too easy. The user is going to have to // change their password on first login anyway. if (method_exists($authobj, 'is_password_valid') && !$authobj->is_password_valid($password)) { $form->set_error('file', get_string('uploadcsverrorinvalidpassword', 'admin', $i)); return; } $usernames[strtolower($username)] = 1; $emails[$email] = 1; // All OK! $CSVDATA[] = $line; } } if ($i == 1) { // There was only the title row :( $form->set_error('file', get_string('uploadcsverrornorecords', 'admin')); return; } if ($CSVDATA === null) { // Oops! Couldn't get CSV data for some reason $form->set_error('file', get_string('uploadcsverrorunspecifiedproblem', 'admin')); } }
function institution_submit(Pieform $form, $values) { global $SESSION, $institution, $add, $instancearray, $USER; db_begin(); // Update the basic institution record... $newinstitution = new StdClass(); if ($add) { $institution = $newinstitution->name = strtolower($values['name']); } $newinstitution->displayname = $values['displayname']; $newinstitution->expiry = db_format_timestamp($values['expiry']); $newinstitution->authplugin = empty($values['authplugin']) ? null : $values['authplugin']; if (get_config('usersuniquebyusername')) { // Registering absolutely not allowed when this setting is on, it's a // security risk. See the documentation for the usersuniquebyusername // setting for more information $newinstitution->registerallowed = 0; } else { $newinstitution->registerallowed = $values['registerallowed'] ? 1 : 0; } $newinstitution->theme = empty($values['theme']) || $values['theme'] == 'sitedefault' ? null : $values['theme']; if ($institution != 'mahara') { $newinstitution->defaultmembershipperiod = $values['defaultmembershipperiod'] ? intval($values['defaultmembershipperiod']) : null; if ($USER->get('admin')) { $newinstitution->maxuseraccounts = $values['maxuseraccounts'] ? intval($values['maxuseraccounts']) : null; } } if (!empty($values['authplugin'])) { $allinstances = array_merge($values['authplugin']['instancearray'], $values['authplugin']['deletearray']); if (array_diff($allinstances, $instancearray)) { // TODO wrong exception type throw new Exception('Attempt to delete or update another institution\'s auth instance'); } if (array_diff($instancearray, $allinstances)) { // TODO wrong exception type throw new Exception('One of your instances is unaccounted for in this transaction'); } foreach ($values['authplugin']['instancearray'] as $priority => $instanceid) { if (in_array($instanceid, $values['authplugin']['deletearray'])) { // Should never happen: // TODO wrong exception type throw new Exception('Attempt to update AND delete an auth instance'); } $record = new StdClass(); $record->priority = $priority; $record->id = $instanceid; update_record('auth_instance', $record, array('id' => $instanceid)); } foreach ($values['authplugin']['deletearray'] as $instanceid) { execute_sql('UPDATE {usr} SET lastauthinstance = NULL WHERE lastauthinstance = ?', array($instanceid)); delete_records('auth_remote_user', 'authinstance', $instanceid); delete_records('auth_instance_config', 'instance', $instanceid); delete_records('auth_instance', 'id', $instanceid); } } if ($add) { insert_record('institution', $newinstitution); // If registration has been turned on, then we automatically insert an // internal authentication authinstance if ($newinstitution->registerallowed) { $authinstance = (object) array('instancename' => 'internal', 'priority' => 0, 'institution' => $newinstitution->name, 'authname' => 'internal'); insert_record('auth_instance', $authinstance); } } else { $where = new StdClass(); $where->name = $institution; $oldtheme = get_field('institution', 'theme', 'name', $institution); update_record('institution', $newinstitution, $where); } delete_records('institution_locked_profile_field', 'name', $institution); foreach (ArtefactTypeProfile::get_all_fields() as $field => $type) { if ($values[$field]) { $profilefield = new StdClass(); $profilefield->name = $institution; $profilefield->profilefield = $field; insert_record('institution_locked_profile_field', $profilefield); } } db_commit(); if ($add) { if ($newinstitution->registerallowed) { // If registration is not allowed, then an authinstance will not // have been created, and thus cause the institution page to add // its own error message on the next page load $SESSION->add_ok_msg(get_string('institutionaddedsuccessfully2', 'admin')); } $nexturl = '/admin/users/institutions.php?i=' . urlencode($institution); } else { $message = get_string('institutionupdatedsuccessfully', 'admin'); if (isset($values['theme']) && $oldtheme != $values['theme'] && (!empty($oldtheme) || $values['theme'] != 'sitedefault')) { $message .= ' ' . get_string('usersseenewthemeonlogin', 'admin'); } $SESSION->add_ok_msg($message); $nexturl = '/admin/users/institutions.php'; } redirect($nexturl); }
* @copyright For copyright information on Mahara, please see the README file distributed with this software. * */ define('INTERNAL', 1); define('MENUITEM', 'content/profile'); define('SECTION_PLUGINTYPE', 'artefact'); define('SECTION_PLUGINNAME', 'internal'); define('SECTION_PAGE', 'index'); require dirname(dirname(dirname(__FILE__))) . '/init.php'; define('TITLE', get_string('profile', 'artefact.internal')); require_once 'pieforms/pieform.php'; safe_require('artefact', 'internal'); $fieldset = param_alpha('fs', 'aboutme'); $element_list = ArtefactTypeProfile::get_all_fields(); $element_data = ArtefactTypeProfile::get_field_element_data(); $element_required = ArtefactTypeProfile::get_mandatory_fields(); // load existing profile fields $profilefields = array(); $profile_data = get_records_select_array('artefact', "owner=? AND artefacttype IN (" . join(",", array_map(create_function('$a', 'return db_quote($a);'), array_keys($element_list))) . ")", array($USER->get('id'))); if ($profile_data) { foreach ($profile_data as $field) { $profilefields[$field->artefacttype] = $field->title; } } $lockedfields = locked_profile_fields(); $profilefields['email'] = array(); $profilefields['email']['all'] = get_records_array('artefact_internal_profile_email', 'owner', $USER->get('id')); $profilefields['email']['validated'] = array(); $profilefields['email']['unvalidated'] = array(); $profilefields['email']['unsent'] = array(); if ($profilefields['email']['all']) {
/** * Implement user searching with SQL * * NOTE: user with ID zero should never be returned * * @param string The query string * @param integer How many results to return * @param integer What result to start at (0 == first result) * @param data Filters the users searched by * can contain: * 'group' => integer, // only users in this group * 'owner' => boolean // include the group ownwer (only if group is set) * 'exclude'=> int // excludes a user * @return array A data structure containing results looking like ... * $results = array( * count => integer, // total number of results * limit => integer, // how many results are returned * offset => integer, // starting from which result * data => array( // the result records * array( * id => integer, * username => string, * institution => string, * firstname => string, * lastname => string, * preferredname => string, * email => string, * ), * array( * id => integer, * username => string, * institution => string, * firstname => string, * lastname => string, * preferredname => string, * email => string, * ), * array(...), * ), * ); */ public static function search_user($query_string, $limit, $offset = 0, $data = array()) { safe_require('artefact', 'internal'); $publicfields = array_keys(ArtefactTypeProfile::get_public_fields()); if (empty($publicfields)) { $publicfields = array('preferredname'); } $fieldlist = '(' . join(',', array_map('db_quote', $publicfields)) . ')'; $ilike = db_ilike(); $data = self::prepare_search_user_options($data); $sql = ' SELECT COUNT(DISTINCT u.id) FROM {artefact} a INNER JOIN {usr} u ON u.id = a.owner'; if (isset($data['group'])) { $groupadminsql = ''; if (isset($data['includeadmins']) and !$data['includeadmins']) { $groupadminsql = " AND gm.role != 'admin'"; } $groupjoin = ' INNER JOIN {group_member} gm ON (gm.member = u.id AND gm.group = ' . (int) $data['group'] . $groupadminsql . ")\n"; $sql .= $groupjoin; } $sql .= "\n LEFT OUTER JOIN {usr_account_preference} h ON (u.id = h.usr AND h.field = 'hiderealname')"; $querydata = split(' ', preg_replace('/\\s\\s+/', ' ', strtolower(trim($query_string)))); $hidenameallowed = get_config('userscanhiderealnames') ? 'TRUE' : 'FALSE'; $searchusernamesallowed = get_config('searchusernames') ? 'TRUE' : 'FALSE'; $namesql = "(u.preferredname {$ilike} '%' || ? || '%')\n OR ((u.preferredname IS NULL OR u.preferredname = '' OR NOT {$hidenameallowed} OR h.value != '1')\n AND (u.firstname {$ilike} '%' || ? || '%' OR u.lastname {$ilike} '%' || ? || '%'))\n OR ({$searchusernamesallowed} AND u.username {$ilike} '%' || ? || '%')\n OR (a.artefacttype IN {$fieldlist}\n AND ( a.title {$ilike} '%' || ? || '%'))"; $namesql = join(' OR ', array_fill(0, count($querydata), $namesql)); $values = array(); foreach ($querydata as $w) { $values = array_pad($values, count($values) + 5, $w); } $where = ' WHERE u.id <> 0 AND u.active = 1 AND u.deleted = 0 AND ( ' . $namesql . ' ) ' . (isset($data['exclude']) ? 'AND u.id != ' . $data['exclude'] : '') . ' '; $sql .= $where; $count = count_records_sql($sql, $values); $result = array('count' => $count, 'limit' => $limit, 'offset' => $offset, 'data' => false); if ($count < 1) { return $result; } if (is_postgres()) { $sql = ' SELECT DISTINCT ON (' . $data['orderby'] . ') u.id, u.username, u.firstname, u.lastname, u.preferredname, u.email, u.staff FROM {artefact} a INNER JOIN {usr} u ON u.id = a.owner'; } else { if (is_mysql()) { // @todo This is quite possibly not correct. See the postgres // query. It should be DISTINCT ON the fields as specified by the // postgres query. There is a workaround by using SELECT * followed // by GROUP BY 1, 2, 3, but it's not really valid SQL. The other // way is to rewrite the query using a self join on the usr table. $sql = ' SELECT DISTINCT u.id, u.username, u.firstname, u.lastname, u.preferredname, u.email, u.staff FROM {artefact} a INNER JOIN {usr} u ON u.id = a.owner'; } else { throw new SQLException('search_user() not implemented for your database engine (' . get_config('dbtype') . ')'); } } if (isset($data['group'])) { $sql .= $groupjoin; } $sql .= "\n LEFT OUTER JOIN {usr_account_preference} h ON (u.id = h.usr AND h.field = 'hiderealname')"; $sql .= $where . ' ORDER BY ' . $data['orderby']; $result['data'] = get_records_sql_array($sql, $values, $offset, $limit); if ($result['data']) { foreach ($result['data'] as &$item) { $item = (array) $item; } } return $result; }
/** * Checks that all the required fields are set, and handles setting them if required. * * Checks whether the current user needs to change their password, and handles * the password changing if it's required. */ function auth_check_required_fields() { global $USER, $SESSION; if (defined('NOCHECKREQUIREDFIELDS')) { return; } $changepassword = true; $elements = array(); if (!$USER->get('passwordchange') || $USER->get('parentuser') && $USER->get('loginanyway') || defined('NOCHECKPASSWORDCHANGE')) { $changepassword = false; } // Check if the user wants to log in anyway if ($USER->get('passwordchange') && $USER->get('parentuser') && isset($_GET['loginanyway'])) { $USER->loginanyway = true; $changepassword = false; } // Do not force password change on JSON request. if (defined('JSON') && JSON == true) { $changepassword = false; } if ($changepassword) { $authobj = AuthFactory::create($USER->authinstance); if ($authobj->changepasswordurl) { redirect($authobj->changepasswordurl); exit; } if (method_exists($authobj, 'change_password')) { if ($SESSION->get('resetusername')) { $elements['username'] = array('type' => 'text', 'defaultvalue' => $USER->get('username'), 'title' => get_string('changeusername', 'account'), 'description' => get_string('changeusernamedesc', 'account', hsc(get_config('sitename')))); } $elements['password1'] = array('type' => 'password', 'title' => get_string('newpassword') . ':', 'description' => get_string('yournewpassword'), 'rules' => array('required' => true)); $elements['password2'] = array('type' => 'password', 'title' => get_string('confirmpassword') . ':', 'description' => get_string('yournewpasswordagain'), 'rules' => array('required' => true)); $elements['email'] = array('type' => 'text', 'title' => get_string('principalemailaddress', 'artefact.internal'), 'ignore' => trim($USER->get('email')) != '' && !preg_match('/@example\\.org$/', $USER->get('email')), 'rules' => array('required' => true, 'email' => true)); } } else { if (defined('JSON')) { // Don't need to check this for json requests return; } } safe_require('artefact', 'internal'); require_once 'pieforms/pieform.php'; $alwaysmandatoryfields = array_keys(ArtefactTypeProfile::get_always_mandatory_fields()); foreach (ArtefactTypeProfile::get_mandatory_fields() as $field => $type) { // Always mandatory fields are stored in the usr table, so are part of // the user session object. We can save a query by grabbing them from // the session. if (in_array($field, $alwaysmandatoryfields) && $USER->get($field) != null) { continue; } // Not cached? Get value the standard way. if (get_profile_field($USER->get('id'), $field) != null) { continue; } if ($field == 'email') { if (isset($elements['email'])) { continue; } // Use a text field for their first e-mail address, not the // emaillist element $type = 'text'; } $elements[$field] = array('type' => $type, 'title' => get_string($field, 'artefact.internal'), 'rules' => array('required' => true)); if ($field == 'socialprofile') { $elements[$field] = ArtefactTypeSocialprofile::get_new_profile_elements(); // add an element to flag that socialprofile is in the list of fields. $elements['socialprofile_hidden'] = array('type' => 'hidden', 'value' => 1); } // @todo ruthlessly stolen from artefact/internal/index.php, could be merged if ($type == 'wysiwyg') { $elements[$field]['rows'] = 10; $elements[$field]['cols'] = 60; } if ($type == 'textarea') { $elements[$field]['rows'] = 4; $elements[$field]['cols'] = 60; } if ($field == 'country') { $elements[$field]['options'] = getoptions_country(); $elements[$field]['defaultvalue'] = get_config('country'); } if ($field == 'email') { // Check if a validation email has been sent if (record_exists('artefact_internal_profile_email', 'owner', $USER->get('id'))) { $elements['email']['type'] = 'html'; $elements['email']['value'] = get_string('validationprimaryemailsent', 'auth'); $elements['email']['disabled'] = true; $elements['email']['rules'] = array('required' => false); } else { $elements[$field]['rules']['email'] = true; $elements[$field]['description'] = get_string('primaryemaildescription', 'auth'); } } } if (empty($elements)) { // No mandatory fields that aren't set return; } if (count($elements) == 1 && isset($elements['email']) && $elements['email']['type'] == 'html') { // Display a message if there is only 1 required field and this field is email whose validation has been sent $elements['submit'] = array('type' => 'submit', 'value' => get_string('continue', 'admin')); $form = pieform(array('name' => 'requiredfields', 'method' => 'post', 'action' => get_config('wwwroot') . '?logout', 'elements' => $elements)); } else { $elements['submit'] = array('type' => 'submit', 'class' => 'btn-success', 'value' => get_string('submit')); $form = pieform(array('name' => 'requiredfields', 'method' => 'post', 'action' => '', 'elements' => $elements, 'dieaftersubmit' => FALSE, 'backoutaftersubmit' => TRUE)); } // Has the form been successfully submitted? Back out and let the requested URL continue. if ($form === FALSE) { return; } $smarty = smarty(); if ($USER->get('parentuser')) { $smarty->assign('loginasoverridepasswordchange', get_string('loginasoverridepasswordchange', 'admin', '<a class="" href="' . get_config('wwwroot') . '?loginanyway">', '</a>')); } $smarty->assign('changepassword', $changepassword); $smarty->assign('changeusername', $SESSION->get('resetusername')); $smarty->assign('form', $form); $smarty->display('requiredfields.tpl'); exit; }
function institution_submit(Pieform $form, $values) { global $SESSION, $institution, $add, $instancearray, $USER, $authinstances, $customthemedefaults; db_begin(); // Update the basic institution record... if ($add) { $newinstitution = new Institution(); $newinstitution->initialise($values['name'], $values['displayname']); $institution = $newinstitution->name; } else { $newinstitution = new Institution($institution); $newinstitution->displayname = $values['displayname']; $oldinstitution = get_record('institution', 'name', $institution); // Clear out any cached menus for this institution clear_menu_cache($institution); } $newinstitution->showonlineusers = !isset($values['showonlineusers']) ? 2 : $values['showonlineusers']; if (get_config('usersuniquebyusername')) { // Registering absolutely not allowed when this setting is on, it's a // security risk. See the documentation for the usersuniquebyusername // setting for more information $newinstitution->registerallowed = 0; } else { $newinstitution->registerallowed = $values['registerallowed'] ? 1 : 0; $newinstitution->registerconfirm = $values['registerconfirm'] ? 1 : 0; } if (!empty($values['lang'])) { if ($values['lang'] == 'sitedefault') { $newinstitution->lang = null; } else { $newinstitution->lang = $values['lang']; } } $newinstitution->theme = empty($values['theme']) || $values['theme'] == 'sitedefault' ? null : $values['theme']; $newinstitution->dropdownmenu = !empty($values['dropdownmenu']) ? 1 : 0; $newinstitution->skins = !empty($values['skins']) ? 1 : 0; require_once get_config('docroot') . 'artefact/comment/lib.php'; $commentoptions = ArtefactTypeComment::get_comment_options(); $newinstitution->commentsortorder = empty($values['commentsortorder']) ? $commentoptions->sort : $values['commentsortorder']; $newinstitution->commentthreaded = !empty($values['commentthreaded']) ? 1 : 0; if ($newinstitution->theme == 'custom') { if (!empty($oldinstitution->style)) { $styleid = $oldinstitution->style; delete_records('style_property', 'style', $styleid); } else { $record = (object) array('title' => get_string('customstylesforinstitution', 'admin', $newinstitution->displayname)); $styleid = insert_record('style', $record, 'id', true); } $properties = array(); $record = (object) array('style' => $styleid); foreach (array_keys($customthemedefaults) as $name) { $record->field = $name; $record->value = $values[$name]; insert_record('style_property', $record); $properties[$name] = $values[$name]; } // Cache the css $smarty = smarty_core(); $smarty->assign('data', $properties); set_field('style', 'css', $smarty->fetch('customcss.tpl'), 'id', $styleid); $newinstitution->style = $styleid; } else { $newinstitution->style = null; } if (get_config('licensemetadata')) { $newinstitution->licensemandatory = !empty($values['licensemandatory']) ? 1 : 0; $newinstitution->licensedefault = isset($values['licensedefault']) ? $values['licensedefault'] : ''; } if (!empty($values['resetcustom']) && !empty($oldinstitution->style)) { $newinstitution->style = null; } if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) { if (!empty($values['updateuserquotas']) && !empty($values['defaultquota'])) { execute_sql("UPDATE {usr} SET quota = ? WHERE id IN (SELECT usr FROM {usr_institution} WHERE institution = ?)", array($values['defaultquota'], $institution)); // get all the users from the institution and make sure that they are still below // their quota threshold if ($users = get_records_sql_array('SELECT * FROM {usr} u LEFT JOIN {usr_institution} ui ON u.id = ui.usr AND ui.institution = ?', array($institution))) { $quotanotifylimit = get_config_plugin('artefact', 'file', 'quotanotifylimit'); if ($quotanotifylimit <= 0 || $quotanotifylimit >= 100) { $quotanotifylimit = 100; } foreach ($users as $user) { $user->quota = $values['defaultquota']; // check if the user has gone over the quota notify limit $user->quotausedpercent = $user->quotaused / $user->quota * 100; $overlimit = false; if ($quotanotifylimit <= $user->quotausedpercent) { $overlimit = true; } $notified = get_field('usr_account_preference', 'value', 'field', 'quota_exceeded_notified', 'usr', $user->id); if ($overlimit && '1' !== $notified) { require_once get_config('docroot') . 'artefact/file/lib.php'; ArtefactTypeFile::notify_users_threshold_exceeded(array($user), false); // no need to email admin as we can alert them right now $SESSION->add_error_msg(get_string('useroverquotathreshold', 'artefact.file', display_name($user))); } else { if ($notified && !$overlimit) { set_account_preference($user->id, 'quota_exceeded_notified', false); } } } } } $newinstitution->defaultquota = empty($values['defaultquota']) ? get_config_plugin('artefact', 'file', 'defaultquota') : $values['defaultquota']; } if ($institution != 'mahara') { $newinstitution->defaultmembershipperiod = $values['defaultmembershipperiod'] ? intval($values['defaultmembershipperiod']) : null; if ($USER->get('admin')) { $newinstitution->maxuseraccounts = $values['maxuseraccounts'] ? intval($values['maxuseraccounts']) : null; $newinstitution->expiry = db_format_timestamp($values['expiry']); } } $newinstitution->allowinstitutionpublicviews = isset($values['allowinstitutionpublicviews']) && $values['allowinstitutionpublicviews'] ? 1 : 0; // TODO: Move handling of authentication instances within the Institution class as well? if (!empty($values['authplugin'])) { $allinstances = array_merge($values['authplugin']['instancearray'], $values['authplugin']['deletearray']); if (array_diff($allinstances, $instancearray)) { throw new ConfigException('Attempt to delete or update another institution\'s auth instance'); } if (array_diff($instancearray, $allinstances)) { throw new ConfigException('One of your instances is unaccounted for in this transaction'); } foreach ($values['authplugin']['instancearray'] as $priority => $instanceid) { if (in_array($instanceid, $values['authplugin']['deletearray'])) { // Should never happen: throw new SystemException('Attempt to update AND delete an auth instance'); } $record = new StdClass(); $record->priority = $priority; $record->id = $instanceid; update_record('auth_instance', $record, array('id' => $instanceid)); } foreach ($values['authplugin']['deletearray'] as $instanceid) { // If this authinstance is the only xmlrpc authinstance that references a host, delete the host record. $hostwwwroot = null; foreach ($authinstances as $ai) { if ($ai->id == $instanceid && $ai->authname == 'xmlrpc') { $hostwwwroot = get_field_sql("SELECT \"value\" FROM {auth_instance_config} WHERE \"instance\" = ? AND field = 'wwwroot'", array($instanceid)); if ($hostwwwroot && count_records_select('auth_instance_config', "field = 'wwwroot' AND \"value\" = ?", array($hostwwwroot)) == 1) { // Unfortunately, it's possible that this host record could belong to a different institution, // so specify the institution here. delete_records('host', 'wwwroot', $hostwwwroot, 'institution', $institution); // We really need to fix this, either by removing the institution from the host table, or refusing to allow the // institution to be changed in the host record when another institution's authinstance is still pointing at it. } break; } } delete_records('auth_remote_user', 'authinstance', $instanceid); delete_records('auth_instance_config', 'instance', $instanceid); delete_records('auth_instance', 'id', $instanceid); // Make it no longer be the parent authority to any auth instances delete_records('auth_instance_config', 'field', 'parent', 'value', $instanceid); } } // Store plugin settings. plugin_institution_prefs_submit($form, $values, $newinstitution); // Save the changes to the DB $newinstitution->commit(); if ($add) { // Automatically create an internal authentication authinstance $authinstance = (object) array('instancename' => 'internal', 'priority' => 0, 'institution' => $newinstitution->name, 'authname' => 'internal'); insert_record('auth_instance', $authinstance); // We need to add the default lines to the site_content table for this institution // We also need to set the institution to be using default static pages to begin with // so that using custom institution pages is an opt-in situation $pages = site_content_pages(); $now = db_format_timestamp(time()); foreach ($pages as $name) { $page = new stdClass(); $page->name = $name; $page->ctime = $now; $page->mtime = $now; $page->content = get_string($page->name . 'defaultcontent', 'install', get_string('staticpageconfiginstitution', 'install')); $page->institution = $newinstitution->name; insert_record('site_content', $page); $institutionconfig = new stdClass(); $institutionconfig->institution = $newinstitution->name; $institutionconfig->field = 'sitepages_' . $name; $institutionconfig->value = 'mahara'; insert_record('institution_config', $institutionconfig); } } if (is_null($newinstitution->style) && !empty($oldinstitution->style)) { delete_records('style_property', 'style', $oldinstitution->style); delete_records('style', 'id', $oldinstitution->style); } // Set the logo after updating the institution, because the institution // needs to exist before it can own the logo artefact. if (!empty($values['logo'])) { safe_require('artefact', 'file'); // Entry in artefact table $data = (object) array('institution' => $institution, 'title' => 'logo', 'description' => 'Institution logo', 'note' => $values['logo']['name'], 'size' => $values['logo']['size']); $imageinfo = getimagesize($values['logo']['tmp_name']); $data->width = $imageinfo[0]; $data->height = $imageinfo[1]; $data->filetype = $imageinfo['mime']; $artefact = new ArtefactTypeProfileIcon(0, $data); if (preg_match("/\\.([^\\.]+)\$/", $values['logo']['name'], $saved)) { $artefact->set('oldextension', $saved[1]); } $artefact->commit(); $id = $artefact->get('id'); // Move the file into the correct place. $directory = get_config('dataroot') . 'artefact/file/profileicons/originals/' . $id % 256 . '/'; check_dir_exists($directory); move_uploaded_file($values['logo']['tmp_name'], $directory . $id); // Delete the old logo if (!empty($oldinstitution->logo)) { $oldlogo = new ArtefactTypeProfileIcon($oldinstitution->logo); $oldlogo->delete(); } set_field('institution', 'logo', $id, 'name', $institution); } if (!empty($values['deletelogo'])) { execute_sql("UPDATE {institution} SET logo = NULL WHERE name = ?", array($institution)); } delete_records('institution_locked_profile_field', 'name', $institution); foreach (ArtefactTypeProfile::get_all_fields() as $field => $type) { if ($values[$field]) { $profilefield = new StdClass(); $profilefield->name = $institution; $profilefield->profilefield = $field; insert_record('institution_locked_profile_field', $profilefield); } } db_commit(); if ($add) { if (!$newinstitution->registerallowed) { // If registration is not allowed, then an authinstance will not // have been created, and thus cause the institution page to add // its own error message on the next page load $SESSION->add_ok_msg(get_string('institutionaddedsuccessfully2', 'admin')); } $nexturl = '/admin/users/institutions.php?i=' . urlencode($institution); } else { $message = get_string('institutionupdatedsuccessfully', 'admin'); if (isset($values['theme'])) { $changedtheme = $oldinstitution->theme != $values['theme'] && (!empty($oldinstitution->theme) || $values['theme'] != 'sitedefault'); if ($changedtheme || $values['theme'] == 'custom') { $message .= ' ' . get_string('usersseenewthemeonlogin', 'admin'); } $USER->reset_institutions(); } $SESSION->add_ok_msg($message); $nexturl = '/admin/users/institutions.php'; } redirect($nexturl); }
public function render_profile_element() { $data = self::get_social_profiles(); // Build pagination for 'socialprofile' artefacts table $baseurl = get_config('wwwroot') . 'artefact/internal/index.php' . '?' . http_build_query(array('fs' => 'social')); $count = count($data); $limit = 500; $offset = 0; $pagination = build_pagination(array('id' => 'socialprofiles_pagination', 'url' => $baseurl, 'datatable' => 'socialprofilelist', 'count' => $count, 'limit' => $limit, 'offset' => $offset)); // User may delete social profile if: // - there is more than 1 social profile and 'socialprofile' is a mandatory field. // - 'socialprofile' is not mandatory. $candelete = true; $mandatory_fields = ArtefactTypeProfile::get_mandatory_fields(); if (isset($mandatory_fields['socialprofile']) && count($data) <= 1) { $candelete = false; } $smarty = smarty_core(); $smarty->assign('controls', true); $smarty->assign('rows', $data); $smarty->assign('candelete', $candelete); $smarty->assign('pagination', $pagination); return array('type' => 'html', 'value' => $smarty->fetch('artefact:internal:socialprofiles.tpl')); }
/** * The CSV file is parsed here so validation errors can be returned to the * user. The data from a successful parsing is stored in the <var>$CVSDATA</var> * array so it can be accessed by the submit function * * @param Pieform $form The form to validate * @param array $values The values submitted */ function uploadcsv_validate(Pieform $form, $values) { global $CSVDATA, $ALLOWEDKEYS, $FORMAT, $USER, $INSTITUTIONNAME, $UPDATES; // Don't even start attempting to parse if there are previous errors if ($form->has_errors()) { return; } if ($values['file']['size'] == 0) { $form->set_error('file', $form->i18n('rule', 'required', 'required', array())); return; } if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) { $maxquotaenabled = get_config_plugin('artefact', 'file', 'maxquotaenabled'); $maxquota = get_config_plugin('artefact', 'file', 'maxquota'); if ($maxquotaenabled && $values['quota'] > $maxquota) { $form->set_error('quota', get_string('maxquotaexceededform', 'artefact.file', display_size($maxquota))); } } require_once 'csvfile.php'; $authinstance = (int) $values['authinstance']; $institution = get_field('auth_instance', 'institution', 'id', $authinstance); if (!$USER->can_edit_institution($institution)) { $form->set_error('authinstance', get_string('notadminforinstitution', 'admin')); return; } //OVERWRITE 2: add $authname = get_field('auth_instance', 'authname', 'id', $authinstance); if ($authname != 'internal') { $form->set_error('authinstance', get_string('notadminforinstitution', 'admin')); return; } //END OVERWRITE 2 $authobj = AuthFactory::create($authinstance); $csvusers = new CsvFile($values['file']['tmp_name']); $csvusers->set('allowedkeys', $ALLOWEDKEYS); // Now we know all of the field names are valid, we need to make // sure that the required fields are included $mandatoryfields = array('username'); if (!$values['updateusers']) { $mandatoryfields[] = 'password'; } $mandatoryfields = array_merge($mandatoryfields, array_keys(ArtefactTypeProfile::get_mandatory_fields())); if ($lockedprofilefields = get_column('institution_locked_profile_field', 'profilefield', 'name', $institution)) { $mandatoryfields = array_merge($mandatoryfields, $lockedprofilefields); } $csvusers->set('mandatoryfields', $mandatoryfields); $csvdata = $csvusers->get_data(); if (!empty($csvdata->errors['file'])) { $form->set_error('file', $csvdata->errors['file']); return; } $csverrors = new CSVErrors(); $formatkeylookup = array_flip($csvdata->format); // First pass validates usernames & passwords in the file, and builds // up a list indexed by username. $emails = array(); if (isset($formatkeylookup['remoteuser'])) { $remoteusers = array(); } $maxcsvlines = get_config('maxusercsvlines'); if ($maxcsvlines && $maxcsvlines < count($csvdata->data)) { $form->set_error('file', get_string('uploadcsverrortoomanyusers', 'admin', get_string('nusers', 'mahara', $maxcsvlines))); return; } foreach ($csvdata->data as $key => $line) { // If headers exists, increment i = key + 2 for actual line number $i = $csvusers->get('headerExists') ? $key + 2 : $key + 1; // Trim non-breaking spaces -- they get left in place by File_CSV foreach ($line as &$field) { $field = preg_replace('/^(\\s|\\xc2\\xa0)*(.*?)(\\s|\\xc2\\xa0)*$/', '$2', $field); } if (count($line) != count($csvdata->format)) { $csverrors->add($i, get_string('uploadcsverrorwrongnumberoffields', 'admin', $i)); continue; } // We have a line with the correct number of fields, but should validate these fields // Note: This validation should really be methods on each profile class, that way // it can be used in the profile screen as well. $username = $line[$formatkeylookup['username']]; $password = isset($formatkeylookup['password']) ? $line[$formatkeylookup['password']] : null; $email = $line[$formatkeylookup['email']]; if (isset($remoteusers)) { $remoteuser = strlen($line[$formatkeylookup['remoteuser']]) ? $line[$formatkeylookup['remoteuser']] : null; } if (method_exists($authobj, 'is_username_valid_admin')) { if (!$authobj->is_username_valid_admin($username)) { $csverrors->add($i, get_string('uploadcsverrorinvalidusername', 'admin', $i)); } } else { if (method_exists($authobj, 'is_username_valid')) { if (!$authobj->is_username_valid($username)) { $csverrors->add($i, get_string('uploadcsverrorinvalidusername', 'admin', $i)); } } } if (!$values['updateusers']) { // Note: only checks for valid form are done here, none of the checks // like whether the password is too easy. The user is going to have to // change their password on first login anyway. if (method_exists($authobj, 'is_password_valid') && !$authobj->is_password_valid($password)) { $csverrors->add($i, get_string('uploadcsverrorinvalidpassword', 'admin', $i)); } } // OVERWRITE 3: replacement, changed from: //if (isset($emails[$email])) { // // Duplicate email within this file. // $csverrors->add($i, get_string('uploadcsverroremailaddresstaken', 'admin', $i, $email)); //} //else if (!PHPMailer::ValidateAddress($email)) { // $csverrors->add($i, get_string('uploadcsverrorinvalidemail', 'admin', $i, $email)); //} //else if (!$values['updateusers']) { // // The email address must be new // if (record_exists('usr', 'email', $email) || record_exists('artefact_internal_profile_email', 'email', $email, 'verified', 1)) { // $csverrors->add($i, get_string('uploadcsverroremailaddresstaken', 'admin', $i, $email)); // } //} //$emails[$email] = 1; // TO: if (isset($emails[strtolower($email)])) { // Duplicate email within this file. $csverrors->add($i, get_string('uploadcsverroremailaddresstaken', 'admin', $i, $email)); } else { if (!PHPMailer::ValidateAddress($email)) { $csverrors->add($i, get_string('uploadcsverrorinvalidemail', 'admin', $i, $email)); } else { if (!$values['updateusers']) { // The email address must be new if (GcrInstitutionTable::isEmailAddressUsed($email)) { $csverrors->add($i, get_string('uploadcsverroremailaddresstaken', 'admin', $i, $email)); } } } } $emails[strtolower($email)] = 1; // END OVERWRITE 3 if (isset($remoteusers) && $remoteuser) { if (isset($remoteusers[$remoteuser])) { $csverrors->add($i, get_string('uploadcsverrorduplicateremoteuser', 'admin', $i, $remoteuser)); } else { if (!$values['updateusers']) { if ($remoteuserowner = get_record_sql(' SELECT u.username FROM {auth_remote_user} aru JOIN {usr} u ON aru.localusr = u.id WHERE aru.remoteusername = ? AND aru.authinstance = ?', array($remoteuser, $authinstance))) { $csverrors->add($i, get_string('uploadcsverrorremoteusertaken', 'admin', $i, $remoteuser, $remoteuserowner->username)); } } } $remoteusers[$remoteuser] = true; } // If we didn't even get a username, we can't check for duplicates, so move on. if (strlen($username) < 1) { continue; } if (isset($usernames[strtolower($username)])) { // Duplicate username within this file. $csverrors->add($i, get_string('uploadcsverroruseralreadyexists', 'admin', $i, $username)); } else { if (!$values['updateusers'] && record_exists_select('usr', 'LOWER(username) = ?', strtolower($username))) { $csverrors->add($i, get_string('uploadcsverroruseralreadyexists', 'admin', $i, $username)); } $usernames[strtolower($username)] = array('username' => $username, 'password' => $password, 'email' => $email, 'lineno' => $i, 'raw' => $line); if (!empty($remoteuser) && !empty($remoteusers[$remoteuser])) { $usernames[strtolower($username)]['remoteuser'] = $remoteuser; } } } // If the admin is trying to overwrite existing users, identified by username, // this second pass performs some additional checks if ($values['updateusers']) { foreach ($usernames as $lowerusername => $data) { $line = $data['lineno']; $username = $data['username']; $password = $data['password']; $email = $data['email']; // If the user already exists, they must already be in this institution. $userinstitutions = get_records_sql_assoc("\n SELECT COALESCE(ui.institution, 'mahara') AS institution, u.id\n FROM {usr} u LEFT JOIN {usr_institution} ui ON u.id = ui.usr\n WHERE LOWER(u.username) = ?", array($lowerusername)); if ($userinstitutions) { if (!isset($userinstitutions[$institution])) { if ($institution == 'mahara') { $institutiondisplay = array(); foreach ($userinstitutions as $i) { $institutiondisplay[] = $INSTITUTIONNAME[$i->institution]; } $institutiondisplay = join(', ', $institutiondisplay); $message = get_string('uploadcsverroruserinaninstitution', 'admin', $line, $username, $institutiondisplay); } else { $message = get_string('uploadcsverrorusernotininstitution', 'admin', $line, $username, $INSTITUTIONNAME[$institution]); } $csverrors->add($line, $message); } else { // Remember that this user is being updated $UPDATES[$username] = 1; } } else { // New user, check the password if (method_exists($authobj, 'is_password_valid') && !$authobj->is_password_valid($password)) { $csverrors->add($line, get_string('uploadcsverrorinvalidpassword', 'admin', $line)); } } // Check if the email already exists and if it's owned by this user. This query can return more // than one row when there are duplicate emails already on the site. If that happens, things are // already a bit out of hand, and we'll just allow an update if this user is one of the users who // owns the email. $emailowned = get_records_sql_assoc(' SELECT LOWER(u.username) AS lowerusername, ae.principal FROM {usr} u LEFT JOIN {artefact_internal_profile_email} ae ON u.id = ae.owner AND ae.verified = 1 AND ae.email = ? WHERE ae.owner IS NOT NULL OR u.email = ?', array($email, $email)); // If the email is owned by someone else, it could still be okay provided // that other user's email is also being changed in this csv file. if ($emailowned && !isset($emailowned[$lowerusername])) { foreach ($emailowned as $e) { // Only primary emails can be set in uploadcsv, so it's an error when someone else // owns the email as a secondary. if (!$e->principal) { $csverrors->add($line, get_string('uploadcsverroremailaddresstaken', 'admin', $line, $email)); break; } // It's also an error if the email owner is not being updated in this file if (!isset($usernames[$e->lowerusername])) { $csverrors->add($line, get_string('uploadcsverroremailaddresstaken', 'admin', $line, $email)); break; } // If the other user is being updated in this file, but isn't changing their // email address, it's ok, we've already notified duplicate emails within the file. } } if (isset($remoteusers) && !empty($data['remoteuser'])) { $remoteuser = $data['remoteuser']; $remoteuserowner = get_field_sql(' SELECT LOWER(u.username) FROM {usr} u JOIN {auth_remote_user} aru ON u.id = aru.localusr WHERE aru.remoteusername = ? AND aru.authinstance = ?', array($remoteuser, $authinstance)); if ($remoteuserowner && $remoteuserowner != $lowerusername && !isset($usernames[$remoteuserowner])) { // The remote username is owned by some other user who is not being updated in this file $csverrors->add($line, get_string('uploadcsverrorremoteusertaken', 'admin', $line, $remoteuser, $remoteuserowner)); } } } } if ($errors = $csverrors->process()) { $form->set_error('file', clean_html($errors)); return; } $FORMAT = $csvdata->format; $CSVDATA = $csvdata->data; }
/** * The CSV file is parsed here so validation errors can be returned to the * user. The data from a successful parsing is stored in the <var>$CVSDATA</var> * array so it can be accessed by the submit function * * @param Pieform $form The form to validate * @param array $values The values submitted */ function uploadcsv_validate(Pieform $form, $values) { global $CSVDATA, $ALLOWEDKEYS, $FORMAT, $USER, $CSVERRORS; // Don't even start attempting to parse if there are previous errors if ($form->has_errors()) { return; } if ($values['file']['size'] == 0) { $form->set_error('file', $form->i18n('rule', 'required', 'required', array())); return; } require_once 'csvfile.php'; $authinstance = (int) $values['authinstance']; $institution = get_field('auth_instance', 'institution', 'id', $authinstance); if (!$USER->can_edit_institution($institution)) { $form->set_error('authinstance', get_string('notadminforinstitution', 'admin')); return; } $usernames = array(); $emails = array(); $csvusers = new CsvFile($values['file']['tmp_name']); $csvusers->set('allowedkeys', $ALLOWEDKEYS); // Now we know all of the field names are valid, we need to make // sure that the required fields are included $mandatoryfields = array('username', 'password'); $mandatoryfields = array_merge($mandatoryfields, array_keys(ArtefactTypeProfile::get_mandatory_fields())); if ($lockedprofilefields = get_column('institution_locked_profile_field', 'profilefield', 'name', $institution)) { $mandatoryfields = array_merge($mandatoryfields, $lockedprofilefields); } $csvusers->set('mandatoryfields', $mandatoryfields); $csvdata = $csvusers->get_data(); if (!empty($csvdata->errors['file'])) { $form->set_error('file', $csvdata->errors['file']); return; } foreach ($csvdata->data as $key => $line) { // If headers exists, increment i = key + 2 for actual line number $i = $csvusers->get('headerExists') ? $key + 2 : $key + 1; // Trim non-breaking spaces -- they get left in place by File_CSV foreach ($line as &$field) { $field = preg_replace('/^(\\s|\\xc2\\xa0)*(.*?)(\\s|\\xc2\\xa0)*$/', '$2', $field); } // We have a line with the correct number of fields, but should validate these fields // Note: This validation should really be methods on each profile class, that way // it can be used in the profile screen as well. $formatkeylookup = array_flip($csvdata->format); $username = $line[$formatkeylookup['username']]; $password = $line[$formatkeylookup['password']]; $email = $line[$formatkeylookup['email']]; $authobj = AuthFactory::create($authinstance); if (method_exists($authobj, 'is_username_valid') && !$authobj->is_username_valid($username)) { $CSVERRORS[] = get_string('uploadcsverrorinvalidusername', 'admin', $i); } if (record_exists_select('usr', 'LOWER(username) = ?', strtolower($username)) || isset($usernames[strtolower($username)])) { $CSVERRORS[] = get_string('uploadcsverroruseralreadyexists', 'admin', $i, $username); } if (record_exists('usr', 'email', $email) || record_exists('artefact_internal_profile_email', 'email', $email) || isset($emails[$email])) { $CSVERRORS[] = get_string('uploadcsverroremailaddresstaken', 'admin', $i, $email); } // Note: only checks for valid form are done here, none of the checks // like whether the password is too easy. The user is going to have to // change their password on first login anyway. if (method_exists($authobj, 'is_password_valid') && !$authobj->is_password_valid($password)) { $CSVERRORS[] = get_string('uploadcsverrorinvalidpassword', 'admin', $i); } $usernames[strtolower($username)] = 1; $emails[$email] = 1; } if (!empty($CSVERRORS)) { $form->set_error('file', implode("<br />\n", $CSVERRORS)); return; } $FORMAT = $csvdata->format; $CSVDATA = $csvdata->data; }
function institution_submit(Pieform $form, $values) { global $SESSION, $institution, $add, $instancearray, $USER, $authinstances, $customthemedefaults; db_begin(); // Update the basic institution record... $newinstitution = new StdClass(); if ($add) { $institution = $newinstitution->name = strtolower($values['name']); } else { $oldinstitution = get_record('institution', 'name', $institution); } $newinstitution->displayname = $values['displayname']; $newinstitution->authplugin = empty($values['authplugin']) ? null : $values['authplugin']; $newinstitution->showonlineusers = !isset($values['showonlineusers']) ? 2 : $values['showonlineusers']; if (get_config('usersuniquebyusername')) { // Registering absolutely not allowed when this setting is on, it's a // security risk. See the documentation for the usersuniquebyusername // setting for more information $newinstitution->registerallowed = 0; } else { $newinstitution->registerallowed = $values['registerallowed'] ? 1 : 0; $newinstitution->registerconfirm = $values['registerconfirm'] ? 1 : 0; } $newinstitution->theme = empty($values['theme']) || $values['theme'] == 'sitedefault' ? null : $values['theme']; $newinstitution->dropdownmenu = !empty($values['dropdownmenu']) ? 1 : 0; $newinstitution->skins = !empty($values['skins']) ? 1 : 0; if ($newinstitution->theme == 'custom') { if (!empty($oldinstitution->style)) { $styleid = $oldinstitution->style; delete_records('style_property', 'style', $styleid); } else { $record = (object) array('title' => get_string('customstylesforinstitution', 'admin', $newinstitution->displayname)); $styleid = insert_record('style', $record, 'id', true); } $properties = array(); $record = (object) array('style' => $styleid); foreach (array_keys($customthemedefaults) as $name) { $record->field = $name; $record->value = $values[$name]; insert_record('style_property', $record); $properties[$name] = $values[$name]; } // Cache the css $smarty = smarty_core(); $smarty->assign('data', $properties); set_field('style', 'css', $smarty->fetch('customcss.tpl'), 'id', $styleid); $newinstitution->style = $styleid; } else { $newinstitution->style = null; } if (get_config('licensemetadata')) { $newinstitution->licensemandatory = !empty($values['licensemandatory']) ? 1 : 0; $newinstitution->licensedefault = isset($values['licensedefault']) ? $values['licensedefault'] : ''; } if (!empty($values['resetcustom']) && !empty($oldinstitution->style)) { $newinstitution->style = null; } if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) { if (!empty($values['updateuserquotas']) && !empty($values['defaultquota'])) { execute_sql("UPDATE {usr} SET quota = ? WHERE id IN (SELECT usr FROM {usr_institution} WHERE institution = ?)", array($values['defaultquota'], $institution)); } $newinstitution->defaultquota = empty($values['defaultquota']) ? get_config_plugin('artefact', 'file', 'defaultquota') : $values['defaultquota']; } if ($institution != 'mahara') { $newinstitution->defaultmembershipperiod = $values['defaultmembershipperiod'] ? intval($values['defaultmembershipperiod']) : null; if ($USER->get('admin')) { $newinstitution->maxuseraccounts = $values['maxuseraccounts'] ? intval($values['maxuseraccounts']) : null; $newinstitution->expiry = db_format_timestamp($values['expiry']); } } $newinstitution->allowinstitutionpublicviews = isset($values['allowinstitutionpublicviews']) && $values['allowinstitutionpublicviews'] ? 1 : 0; if (!empty($values['authplugin'])) { $allinstances = array_merge($values['authplugin']['instancearray'], $values['authplugin']['deletearray']); if (array_diff($allinstances, $instancearray)) { throw new ConfigException('Attempt to delete or update another institution\'s auth instance'); } if (array_diff($instancearray, $allinstances)) { throw new ConfigException('One of your instances is unaccounted for in this transaction'); } foreach ($values['authplugin']['instancearray'] as $priority => $instanceid) { if (in_array($instanceid, $values['authplugin']['deletearray'])) { // Should never happen: throw new SystemException('Attempt to update AND delete an auth instance'); } $record = new StdClass(); $record->priority = $priority; $record->id = $instanceid; update_record('auth_instance', $record, array('id' => $instanceid)); } foreach ($values['authplugin']['deletearray'] as $instanceid) { // If this authinstance is the only xmlrpc authinstance that references a host, delete the host record. $hostwwwroot = null; foreach ($authinstances as $ai) { if ($ai->id == $instanceid && $ai->authname == 'xmlrpc') { $hostwwwroot = get_field_sql("SELECT \"value\" FROM {auth_instance_config} WHERE \"instance\" = ? AND field = 'wwwroot'", array($instanceid)); if ($hostwwwroot && count_records_select('auth_instance_config', "field = 'wwwroot' AND \"value\" = ?", array($hostwwwroot)) == 1) { // Unfortunately, it's possible that this host record could belong to a different institution, // so specify the institution here. delete_records('host', 'wwwroot', $hostwwwroot, 'institution', $institution); // We really need to fix this, either by removing the institution from the host table, or refusing to allow the // institution to be changed in the host record when another institution's authinstance is still pointing at it. } break; } } delete_records('auth_remote_user', 'authinstance', $instanceid); delete_records('auth_instance_config', 'instance', $instanceid); delete_records('auth_instance', 'id', $instanceid); // Make it no longer be the parent authority to any auth instances delete_records('auth_instance_config', 'field', 'parent', 'value', $instanceid); } } if ($add) { insert_record('institution', $newinstitution); // If registration has been turned on, then we automatically insert an // internal authentication authinstance // OVERWRITE 4: deletion //if ($newinstitution->registerallowed) { // END OVERWRITE 4 $authinstance = (object) array('instancename' => 'internal', 'priority' => 0, 'institution' => $newinstitution->name, 'authname' => 'internal'); insert_record('auth_instance', $authinstance); // OVERWRITE 5: deletion //} // END OVERWRITE 5 } else { $where = new StdClass(); $where->name = $institution; update_record('institution', $newinstitution, $where); } if (is_null($newinstitution->style) && !empty($oldinstitution->style)) { delete_records('style_property', 'style', $oldinstitution->style); delete_records('style', 'id', $oldinstitution->style); } // Set the logo after updating the institution, because the institution // needs to exist before it can own the logo artefact. if (!empty($values['logo'])) { safe_require('artefact', 'file'); // Entry in artefact table $data = (object) array('institution' => $institution, 'title' => 'logo', 'description' => 'Institution logo', 'note' => $values['logo']['name'], 'size' => $values['logo']['size']); $imageinfo = getimagesize($values['logo']['tmp_name']); $data->width = $imageinfo[0]; $data->height = $imageinfo[1]; $data->filetype = $imageinfo['mime']; $artefact = new ArtefactTypeProfileIcon(0, $data); if (preg_match("/\\.([^\\.]+)\$/", $values['logo']['name'], $saved)) { $artefact->set('oldextension', $saved[1]); } $artefact->commit(); $id = $artefact->get('id'); // Move the file into the correct place. $directory = get_config('dataroot') . 'artefact/file/profileicons/originals/' . $id % 256 . '/'; check_dir_exists($directory); move_uploaded_file($values['logo']['tmp_name'], $directory . $id); // Delete the old logo if (!empty($oldinstitution->logo)) { $oldlogo = new ArtefactTypeProfileIcon($oldinstitution->logo); $oldlogo->delete(); } set_field('institution', 'logo', $id, 'name', $institution); } if (!empty($values['deletelogo'])) { execute_sql("UPDATE {institution} SET logo = NULL WHERE name = ?", array($institution)); } delete_records('institution_locked_profile_field', 'name', $institution); foreach (ArtefactTypeProfile::get_all_fields() as $field => $type) { if ($values[$field]) { $profilefield = new StdClass(); $profilefield->name = $institution; $profilefield->profilefield = $field; insert_record('institution_locked_profile_field', $profilefield); } } db_commit(); if ($add) { // OVERWRITE 7: insert global $CFG; $current_user = $CFG->current_app->getCurrentUser(); $mhr_usr_institution = $current_user->addMhrInstitutionMembership($newinstitution); $CFG->current_app->updateMhrTable('usr_institution', array('admin' => 1), array('usr' => $current_user->getObject()->id)); // END OVERWRITE 7 if ($newinstitution->registerallowed) { // If registration is not allowed, then an authinstance will not // have been created, and thus cause the institution page to add // its own error message on the next page load $SESSION->add_ok_msg(get_string('institutionaddedsuccessfully2', 'admin')); } $nexturl = '/admin/users/institutions.php?i=' . urlencode($institution); } else { $message = get_string('institutionupdatedsuccessfully', 'admin'); if (isset($values['theme'])) { $changedtheme = $oldinstitution->theme != $values['theme'] && (!empty($oldinstitution->theme) || $values['theme'] != 'sitedefault'); if ($changedtheme || $values['theme'] == 'custom') { $message .= ' ' . get_string('usersseenewthemeonlogin', 'admin'); } $USER->reset_institutions(); } $SESSION->add_ok_msg($message); $nexturl = '/admin/users/institutions.php'; } redirect($nexturl); }