Permalink
Browse files

MDL-16919 - Allow username to contain alphanumeric lowercase characte…

…rs, underscore (_), hyphen (-), period (.) or at symbol (@)
  • Loading branch information...
1 parent 8c594bb commit 07ed083e4e99e18db440341a56a2e8b6ef11df13 Rossiani Wijaya committed Jan 13, 2010
View
@@ -265,10 +265,8 @@
}
// normalize username
- $user->username = $textlib->strtolower($user->username);
- if (empty($CFG->extendedusernamechars)) {
- $user->username = preg_replace('/[^(-\.[:alnum:])]/i', '', $user->username);
- }
+ $user->username = clean_param($user->username, PARAM_USERNAME);
+
if (empty($user->username)) {
$upt->track('status', get_string('missingfield', 'error', 'username'), 'error');
$upt->track('username', $errorstr, 'error');
@@ -748,36 +746,106 @@
echo $OUTPUT->heading_with_help(get_string('uploaduserspreview', 'admin'), 'uploadusers2');
-$ci = 0;
$ri = 0;
-
-echo '<table id="uupreview" class="generaltable boxaligncenter" summary="'.get_string('uploaduserspreview', 'admin').'">';
-echo '<tr class="heading r'.$ri++.'">';
-foreach ($columns as $col) {
- echo '<th class="header c'.$ci++.'" scope="col">'.s($col).'</th>';
-}
-echo '</tr>';
-
$cir->init();
+
+$filerows = array();
while ($fields = $cir->next()) {
+ $ci = 0;
if ($ri > $previewrows) {
- echo '<tr class="r'.$ri++.'">';
+ $arow .= '<tr class="r'.$ri++.'">';
foreach ($fields as $field) {
- echo '<td class="cell c'.$ci++.'">...</td>';;
+ $arow .= '<td class="cell c'.$ci++.'">...</td>';
}
+ $arow .= '</tr>';
break;
}
- $ci = 0;
- echo '<tr class="r'.$ri++.'">';
- foreach ($fields as $field) {
- echo '<td class="cell c'.$ci++.'">'.s($field).'</td>';;
+
+ $arow = '';
+ $errormsg = array();
+ $filerows[$ri] = array();
+ $arow .= '<tr class="r'.$ri.'">';
+ foreach ($fields as $key => $field) {
+ $errorclass = '';
+ if ($ci == 0) { //username field
+ $newusername = clean_param($field, PARAM_USERNAME);
+ if (strcmp($field, $newusername) != 0){
+ $errorclass = 'uuerror';
+ $errormsg[] = get_string('invalidusernameupload');
+ } else if ($DB->record_exists('user', array('username'=>$field)) || $DB->record_exists('user', array('username'=>$field)) ) {
+ $errorclass = 'uuerror';
+ $errormsg[] = get_string('usernameexists');
+ }
+ } else {
+ if ($ci == 4) { //email field
+ if ($DB->record_exists('user', array('email'=>$field))) {
+ $errorclass = 'uuerror';
+ $errormsg[] = get_string('emailexists');
+
+ } else if (!validate_email($field)) {
+ $errorclass = 'uuerror';
+ $errormsg[] = get_string('invalidemail');
+ }
+ }
+ }
+ $arow .= '<td class="cell c'.$ci++.'">';
+ $arow .= '<div class="'.$errorclass.'">'.s($field). '</div>';
+ $arow .= '</td>';
+
+ if ($key == (count($fields) - 1) && !empty($errormsg)) {
+ $errormsg = implode('<br />', $errormsg);
+ $arow .= '<td>' . $errormsg . '</td>';
+ $filerows[$ri]['error'] = $errormsg;
+ }
}
- echo '</tr>';
-}
+ $arow .= '</tr>';
+ $filerows[$ri]['content'] = $arow;
+ $ri++;
+}
$cir->close();
+$validcontent = array();
+$invalidcontent = array();
+foreach ($filerows as $arow) {
+ if (array_key_exists('error', $arow)){
+ $invalidcontent[] = $arow['content'];
+ $mform = new admin_uploaduser_form3();
+ } else {
+ $validcontent[] = $arow['content'];
+ }
+}
+
+$ri = 0;
+$ci = 0;
+echo '<table id="uupreview" class="generaltable boxaligncenter" summary="'.get_string('uploaduserspreview', 'admin').'">';
+echo '<tr class="heading r'.$ri++.'">';
+foreach ($columns as $col) {
+ echo '<th class="header c'.$ci++.'" scope="col">'.s($col).'</th>';
+}
+if (!empty($invalidcontent)) {
+ echo '<th class="header c'.$ci++.'" scope="col">'.moodle_strtolower(get_string('error', 'moodle')).'</th>';
+}
+echo '</tr>';
+
+$countcontent = 0;
+if (empty($invalidcontent)) {
+ $countcontent = count($validcontent);
+ echo implode('', $validcontent);
+} else {
+ $countcontent = count($invalidcontent);
+ echo implode('', $invalidcontent);
+}
echo '</table>';
-echo '<div class="centerpara">'.get_string('uupreprocessedcount', 'admin', $readcount).'</div>';
+
+if (!empty($invalidcontent)) {
+ echo '<div class="centerpara">'.get_string('uploadinvalidpreprocessedcount', 'moodle', $countcontent).'</div>';
+ echo '<div class="">'.get_string('invalidusername', 'moodle').'</div>';
+ echo '<div class="">'.get_string('uploadfilecontainerror', 'moodle').'</div>';
+} else {
+ echo '<div class="">'.get_string('uupreprocessedcount', 'admin', $countcontent).'</div>';
+}
+
+//echo '<div class="centerpara">'.get_string('uupreprocessedcount', 'admin', $readcount).'</div>';
$mform->display();
echo $OUTPUT->footer();
die;
@@ -822,10 +890,13 @@ function flush() {
}
$ci = 0;
$ri = 1;
- echo '<tr class="r'.$ri++.'">';
- foreach ($this->_row as $field) {
+ echo '<tr class="r'.$ri.'">';
+ foreach ($this->_row as $key=>$field) {
foreach ($field as $type=>$content) {
if ($field[$type] !== '') {
+ if ($key == 'username' && $type == 'normal') {
+ $field[$type] = clean_param($field[$type], PARAM_USERNAME);
+ }
$field[$type] = '<span class="uu'.$type.'">'.$field[$type].'</span>';
} else {
unset($field[$type]);
@@ -353,3 +353,10 @@ function get_data() {
}
}
+class admin_uploaduser_form3 extends moodleform {
+ function definition (){
+ global $CFG, $USER;
+ $mform =& $this->_form;
+ $this->add_action_buttons(false, get_string('uploadnewfile'));
+ }
+}
View
@@ -863,6 +863,7 @@ function sync_users ($do_updates = true) {
$user->lang = $CFG->lang;
}
+ //TODO - username required to use PARAM_USERNAME before inserting into user table (MDL-16919)
if ($id = $DB->insert_record('user', $user)) {
echo "\t"; print_string('auth_dbinsertuser', 'auth_db', array($user->username, $id)); echo "\n";
$userobj = $this->update_user_record($user->username);
View
@@ -364,6 +364,8 @@ function sync_users($do_updates=false) {
$user->id = $old_user->id;
$DB->set_field('user', 'deleted', 0, array('username'=>$user->username));
echo "\t"; print_string('auth_dbreviveuser', 'auth_db', array($user->username, $user->id)); echo "\n";
+
+ //TODO - username required to use PARAM_USERNAME before inserting into user table (MDL-16919)
} elseif ($id = $DB->insert_record ('user',$user)) { // it is truly a new user
echo "\t"; print_string('auth_dbinsertuser','auth_db',array($user->username, $id)); echo "\n";
// if relevant, tag for password generation
View
@@ -73,12 +73,13 @@ function can_signup() {
* @param object $user new user object
* @param boolean $notify print notice with link and terminate
*/
- function user_signup($user, $notify=true) {
+ function user_signup($user, $notify=true) {
global $CFG, $DB;
require_once($CFG->dirroot.'/user/profile/lib.php');
$user->password = hash_internal_user_password($user->password);
+ //TODO - username required to use PARAM_USERNAME before inserting into user table (MDL-16919)
if (! ($user->id = $DB->insert_record('user', $user)) ) {
print_error('auth_emailnoinsert','auth_email');
}
@@ -94,7 +95,7 @@ function user_signup($user, $notify=true) {
}
if ($notify) {
- global $CFG;
+ global $CFG, $PAGE, $OUTPUT;
$emailconfirm = get_string('emailconfirm');
$PAGE->navbar->add($emailconfirm);
$PAGE->set_title($emailconfirm);
View
@@ -419,6 +419,7 @@ function user_signup($user, $notify=true) {
print_error('auth_ldap_create_error', 'auth_ldap');
}
+ //TODO - username required to use PARAM_USERNAME before inserting into user table (MDL-16919)
if (! ($user->id = $DB->insert_record('user', $user)) ) {
print_error('auth_emailnoinsert', 'auth_email');
}
@@ -795,6 +796,7 @@ function sync_users($do_updates=true) {
$user->lang = $CFG->lang;
}
+ //TODO - username required to use PARAM_USERNAME before inserting into user table (MDL-16919)
if ($id = $DB->insert_record('user', $user)) {
echo "\t"; print_string('auth_dbinsertuser', 'auth_db', array($user->username, $id)); echo "\n";
$userobj = $this->update_user_record($user->username);
View
@@ -298,6 +298,8 @@ function confirm_mnet_session($token, $remotewwwroot) {
}
$remoteuser->mnethostid = $remotehost->id;
$remoteuser->firstaccess = time(); // First time user in this server, grab it here
+
+ //TODO - username required to use PARAM_USERNAME before inserting into user table (MDL-16919)
$remoteuser->id = $DB->insert_record('user', $remoteuser);
$firsttime = true;
$localuser = $remoteuser;
@@ -646,6 +646,7 @@ function process_person_tag($tagcontents){
$person->confirmed = 1;
$person->timemodified = time();
$person->mnethostid = $CFG->mnet_localhost_id;
+ //TODO - username required to use PARAM_USERNAME before inserting into user table (MDL-16919)
if($id = $DB->insert_record('user', $person)){
/*
Photo processing is deactivated until we hear from Moodle dev forum about modification to gdlib.
@@ -310,6 +310,7 @@ function enrol_user($user, $courseid) {
$userrecord->lastname = $user['lastname'];
$userrecord->mnethostid = $MNET_REMOTE_CLIENT->id;
+ //TODO - username required to use PARAM_USERNAME before inserting into user table (MDL-16919)
if ($userrecord->id = $DB->insert_record('user', $userrecord)) {
$userrecord = $DB->get_record('user', array('id'=>$userrecord->id));
} else {
@@ -165,7 +165,7 @@
$string['configenrolmentplugins'] = 'Please choose the enrolment plugins you wish to use. Don\'t forget to configure the settings properly.<br /><br />You have to indicate which plugins are enabled, and <strong>one</strong> plugin can be set as the default plugin for <em>interactive</em> enrolment. To disable interactive enrolment, set \"enrollable\" to \"No\" in required courses.';
$string['configerrorlevel'] = 'Choose the amount of PHP warnings that you want to be displayed. Normal is usually the best choice.';
$string['configexperimentalsplitrestore'] = 'If enabled, course backup files will be checked for XML errors and split into smaller parts for use in the restore process. This will result in improvements to restore robustness and execution times, particularly for medium to large course backups.';
-$string['configextendedusernamechars'] = 'Enable this setting to allow students to use any characters in their usernames (note this does not affect their actual names). The default is \"false\" which restricts usernames to be alphanumeric characters only';
+$string['configextendedusernamechars'] = 'Enable this setting to allow students to use any characters in their usernames (note this does not affect their actual names). The default is \"false\" which restricts usernames to be alphanumeric lowercase characters, underscore (_), hyphen (-), period (.) or at symbol (@).';
$string['configextramemorylimit'] = 'Some scripts like search, backup/restore or cron require more memory. Set higher values for large sites.';
$string['configextrauserselectorfields'] = 'Select which fields are searched and displayed, in addition to full names, when selecting users, for example when assigning roles or when adding users to a group. For security reasons, it is recommended that the username field is NOT selected.';
$string['configfilterall'] = 'Filter all strings, including headings, titles, navigation bar and so on. This is mostly useful when using the multilang filter, otherwise it will just create extra load on your site for little gain.';
@@ -112,7 +112,9 @@
$string['allparticipants'] = 'All participants';
$string['allteachers'] = 'All teachers';
$string['alphabet'] = 'A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z';
-$string['alphanumerical'] = 'Can only contain alphabetical letters or numbers';
+$string['alphanumerical'] = 'Can only contain alphanumeric characters, hyphen (-) or period (.)';
+$string['invalidusername'] = 'The username can only contain alphanumeric lowercase characters, underscore (_), hyphen (-), period (.) or at symbol (@)';
+$string['invalidusernameupload'] = "Invalid username";
$string['alreadyconfirmed'] = 'Registration has already been confirmed';
$string['always'] = 'Always';
$string['and'] = '$a->one and $a->two';
@@ -1683,6 +1685,9 @@
$string['uploadserverlimit'] = 'Uploaded file exceeded the maximum size limit set by the server';
$string['uploadthisfile'] = 'Upload this file';
$string['uploadusers'] = 'Upload users';
+$string['uploadnewfile'] = 'Upload new file';
+$string['uploadinvalidpreprocessedcount'] = 'Number of invalid preprocessed records: $a';
+$string['uploadfilecontainerror'] = 'The uploaded file has not been processed due to the error(s) specified. Please amend the file before uploading it again.';
$string['url'] = 'URL';
$string['used'] = 'Used';
$string['usedinnplaces'] = 'Used in $a places';
View
@@ -219,6 +219,10 @@
*/
define('PARAM_URL', 'url');
+/**
+ * PARAM_USERNAME - Clean username to only contains specified characters.
+ */
+define('PARAM_USERNAME', 'username');
///// DEPRECATED PARAM TYPES OR ALIASES - DO NOT USE FOR NEW CODE /////
@@ -463,6 +467,7 @@ function validate_param($param, $type, $allownull=false, $debuginfo='') {
* @uses PARAM_BASE64
* @uses PARAM_TAG
* @uses PARAM_SEQUENCE
+ * @uses PARAM_USERNAME
* @param mixed $param the variable we are cleaning
* @param int $type expected format of param after cleaning.
* @return mixed
@@ -722,6 +727,17 @@ function clean_param($param, $type) {
return ''; // Specified theme is not installed
}
+ case PARAM_USERNAME:
+ $param = str_replace(" " , "", $param);
+ if (empty($CFG->extendedusernamechars)) {
+ // regular expression, eliminate all chars EXCEPT:
+ // alphanum, dash (-), underscore (_), at sign (@) and period (.) characters.
+ $param = preg_replace('/[^-\.@_a-z0-9]/', '', $param);
+ } else {
+ $param = preg_replace('/[A-Z]/', '', $param);
+ }
+ return $param;
+
default: // throw error, switched parameters in optional_param or another serious problem
print_error("unknownparamtype", '', '', $type);
}
@@ -266,6 +266,7 @@ function test_optional_param() {
* @uses PARAM_LOCALURL
* @uses PARAM_CLEANHTML
* @uses PARAM_SEQUENCE
+ * @uses PARAM_USERNAME
* @param mixed $param the variable we are cleaning
* @param int $type expected format of param after cleaning.
* @return mixed
@@ -295,6 +296,35 @@ function test_clean_param() {
$this->assertEqual(clean_param('/just/a/path', PARAM_LOCALURL), '/just/a/path');
$this->assertEqual(clean_param('funny:thing', PARAM_LOCALURL), '');
$this->assertEqual(clean_param('course/view.php?id=3', PARAM_LOCALURL), 'course/view.php?id=3');
+
+ $currentstatus = $CFG->extendedusernamechars;
+
+ // Run tests with extended character == FALSE;
+ $CFG->extendedusernamechars = FALSE;
+ $this->assertEqual(clean_param('johndoe123', PARAM_USERNAME), 'johndoe123' );
+ $this->assertEqual(clean_param('john.doe', PARAM_USERNAME), 'john.doe');
+ $this->assertEqual(clean_param('john-doe', PARAM_USERNAME), 'john-doe');
+ $this->assertEqual(clean_param('john- doe', PARAM_USERNAME), 'john-doe');
+ $this->assertEqual(clean_param('john_doe', PARAM_USERNAME), 'john_doe');
+ $this->assertEqual(clean_param('john@doe', PARAM_USERNAME), 'john@doe');
+ $this->assertEqual(clean_param('john~doe', PARAM_USERNAME), 'johndoe');
+ $this->assertEqual(clean_param('john´doe', PARAM_USERNAME), 'johndoe');
+ $this->assertEqual(clean_param('john#$%&() ', PARAM_USERNAME), 'john');
+ $this->assertEqual(clean_param('JOHNdóé ', PARAM_USERNAME), 'd');
+ $this->assertEqual(clean_param('john.,:;-_/|\ñÑ[]A_X-,D {} ~!@#$%^&*()_+ ?><[] ščřžžý ?ýáž?žý??šdoe ', PARAM_USERNAME), 'john.-__-@_doe');
+
+
+ // Test success condition, if extendedusernamechars == ENABLE;
+ $CFG->extendedusernamechars = TRUE;
+ $this->assertEqual(clean_param('john_doe', PARAM_USERNAME), 'john_doe');
+ $this->assertEqual(clean_param('john@doe', PARAM_USERNAME), 'john@doe');
+ $this->assertEqual(clean_param('john# $%&()+_^', PARAM_USERNAME), 'john#$%&()+_^');
+ $this->assertEqual(clean_param('john~doe', PARAM_USERNAME), 'john~doe');
+ $this->assertEqual(clean_param('joHN´doe', PARAM_USERNAME), 'jo´doe');
+ $this->assertEqual(clean_param('johnDOE', PARAM_USERNAME), 'john');
+ $this->assertEqual(clean_param('johndóé ', PARAM_USERNAME), 'johndóé');
+
+ $CFG->extendedusernamechars = $currentstatus;
}
function test_validate_param() {
View
@@ -105,7 +105,7 @@
$frm->username = trim(moodle_strtolower($frm->username));
if (is_enabled_auth('none') && empty($CFG->extendedusernamechars)) {
- $string = preg_replace("~[^(-\.[:alnum:])]~i", "", $frm->username);
+ $string = clean_param($frm->username, PARAM_USERNAME);
if (strcmp($frm->username, $string)) {
$errormsg = get_string('username').': '.get_string("alphanumerical");
$errorcode = 2;
View
@@ -88,8 +88,6 @@ function definition() {
function definition_after_data(){
$mform =& $this->_form;
-
- $mform->applyFilter('username', 'moodle_strtolower');
$mform->applyFilter('username', 'trim');
}
@@ -102,10 +100,15 @@ function validation($data, $files) {
if ($DB->record_exists('user', array('username'=>$data['username'], 'mnethostid'=>$CFG->mnet_localhost_id))) {
$errors['username'] = get_string('usernameexists');
} else {
- if (empty($CFG->extendedusernamechars)) {
- $string = preg_replace("~[^(-\.[:alnum:])]~i", '', $data['username']);
- if (strcmp($data['username'], $string)) {
- $errors['username'] = get_string('alphanumerical');
+ //check allowed characters
+ if ($data['username'] !== moodle_strtolower($data['username'])) {
+ $errors['username'] = get_string('usernamelowercase');
+ } else {
+ if (empty($CFG->extendedusernamechars)) {
+ $string = clean_param($data['username'], PARAM_USERNAME);
+ if (strcmp($data['username'], $string)) {
+ $errors['username'] = get_string('invalidusername');
+ }
}
}
}
Oops, something went wrong. Retry.

0 comments on commit 07ed083

Please sign in to comment.