--- loncom/interface/lonuserutils.pm 2007/12/22 00:39:52 1.22 +++ loncom/interface/lonuserutils.pm 2007/12/22 19:12:51 1.28 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Utility functions for managing LON-CAPA user accounts # -# $Id: lonuserutils.pm,v 1.22 2007/12/22 00:39:52 raeburn Exp $ +# $Id: lonuserutils.pm,v 1.28 2007/12/22 19:12:51 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -738,13 +738,13 @@ sub print_upload_manager_footer { } if ($context eq 'author') { $Str .= '
\n".'
'."\n".
- &mt('(only do if you know what you are doing.)')."
\n";
+ &mt('(only do if you know what you are doing.)')."\n";
if ($context eq 'domain') {
- $output .= '
\n". @@ -2227,18 +2276,38 @@ END $r->print("
'.$lt{'fors'}.'
'; - } elsif ($env{'form.shorole'} eq 'Any') { + } elsif ($env{'form.showrole'} eq 'Any') { $output .= ''.$lt{'fors'}.'
'. ''.$lt{'forn'}.' ';
$info = $lt{'reta'};
@@ -2585,7 +2672,6 @@ END
} else {
$info = '';
}
- my $sections_select .= &course_sections(\%sections_count,$env{'form.showrole'});
my $rowtitle = &mt('New section to assign');
my $secbox = §ion_picker($cdom,$cnum,$env{'form.showrole'},$rowtitle,$permission,$context);
$output .= $info.$secbox;
@@ -2628,13 +2714,15 @@ sub section_picker {
}
sub results_header_row {
- my ($rolefilter,$statusmode,$context,$permission) = @_;
+ my ($rolefilter,$statusmode,$context,$permission,$mode) = @_;
my ($description,$showfilter);
if ($rolefilter ne 'Any') {
$showfilter = $rolefilter;
}
if ($context eq 'course') {
- $description = &mt('Course - ').$env{'course.'.$env{'request.course.id'}.'.description'}.': ';
+ if ($mode eq 'csv' || $mode eq 'excel') {
+ $description = &mt('Course - ').$env{'course.'.$env{'request.course.id'}.'.description'}.': ';
+ }
if ($statusmode eq 'Expired') {
$description .= &mt('Users in course with expired [_1] roles',$showfilter);
} elsif ($statusmode eq 'Future') {
@@ -2648,11 +2736,12 @@ sub results_header_row {
$description .= &mt('All users in course with [_1] roles',$rolefilter);
}
}
- if (exists($permission->{'view_section'})) {
+ my $viewablesec = &viewable_section($permission);
+ if ($viewablesec ne '') {
if ($env{'form.showrole'} eq 'st') {
- $description .= ' '.&mt('(section [_1] only)',$permission->{'view_section'});
- } elsif ($env{'form.showrole'} eq 'any') {
- $description .= ' '.&mt('(section [_1] only)',$permission->{'view_section'});
+ $description .= ' '.&mt('(section [_1] only)',$viewablesec);
+ } elsif ($env{'form.showrole'} ne 'cc') {
+ $description .= ' '.&mt('(only users affiliated with no section or section [_1])',$viewablesec);
}
}
} elsif ($context eq 'author') {
@@ -2974,7 +3063,7 @@ sub upfile_drop_add {
#
my ($startdate,$enddate) = &get_dates_from_form();
if ($env{'form.makedatesdefault'}) {
- $r->print(&make_dates_default($startdate,$enddate));
+ $r->print(&make_dates_default($startdate,$enddate,$context));
}
# Determine domain and desired host (home server)
my $domain=$env{'request.role.domain'};
@@ -3027,22 +3116,59 @@ sub upfile_drop_add {
$defaultrole = $env{'form.defaultrole'};
} elsif ($setting eq 'course') {
$defaultrole = $env{'form.courserole'};
+ $defaultsec = $env{'form.sections'};
}
} elsif ($context eq 'author') {
$defaultrole = $env{'form.defaultrole'};
- }
- if ($context eq 'domain' && $setting eq 'course') {
- if ($env{'form.newsec'} ne '') {
- $defaultsec = $env{'form.newsec'};
- } elsif ($env{'form.defaultsec'} ne '') {
- $defaultsec = $env{'form.defaultsec'}
- }
+ } elsif ($context eq 'course') {
+ $defaultrole = $env{'form.defaultrole'};
+ $defaultsec = $env{'form.sections'};
}
if ($env{'request.course.id'} ne '') {
$cid = $env{'request.course.id'};
- } elsif ($env{'form.defaultdomain'} ne '' && $env{'form.defaultcourse'} ne '') {
- $cid = $env{'form.defaultdomain'}.'_'.
- $env{'form.defaultcourse'};
+ } elsif ($setting eq 'course') {
+ if (&Apache::lonnet::is_course($env{'form.dcdomain'},$env{'form.dccourse'})) {
+ $cid = $env{'form.dcdomain'}.'_'.$env{'form.dccourse'};
+ }
+ }
+ # Check to see if user information can be changed
+ my @userinfo = ('firstname','middlename','lastname','generation',
+ 'permanentemail','id');
+ my %canmodify;
+ if (&Apache::lonnet::allowed('mau',$domain)) {
+ foreach my $field (@userinfo) {
+ $canmodify{$field} = 1;
+ }
+ }
+ my (%userlist,%modifiable_fields,@poss_roles);
+ my $secidx = &Apache::loncoursedata::CL_SECTION();
+ my @courseroles = &roles_by_context('course',1);
+ if (!&Apache::lonnet::allowed('mau',$domain)) {
+ if ($context eq 'course' || $context eq 'author') {
+ @poss_roles = &curr_role_permissions($context);
+ my @statuses = ('active','future');
+ my ($indexhash,$keylist) = &make_keylist_array();
+ my %info;
+ foreach my $role (@poss_roles) {
+ %{$modifiable_fields{$role}} = &can_modify_userinfo($context,$domain,
+ \@userinfo,[$role]);
+ }
+ if ($context eq 'course') {
+ my ($cnum,$cdom) = &get_course_identity();
+ my $roster = &Apache::loncoursedata::get_classlist();
+ %userlist = %{$roster};
+ my %advrolehash = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,
+ \@statuses,\@poss_roles);
+ &gather_userinfo($context,'view',\%userlist,$indexhash,\%info,
+ \%advrolehash,$permission);
+ } elsif ($context eq 'author') {
+ my %cstr_roles = &Apache::lonnet::get_my_roles(undef,undef,undef,
+ \@statuses,\@poss_roles);
+ &gather_userinfo($context,'view',\%userlist,$indexhash,\%info,
+ \%cstr_roles,$permission);
+
+ }
+ }
}
if ( $domain eq &LONCAPA::clean_domain($domain)
&& ($amode ne '')) {
@@ -3063,16 +3189,50 @@ sub upfile_drop_add {
);
my $flushc=0;
my %student=();
- my %curr_groups;
+ my (%curr_groups,@sections,@cleansec,@secs,$defaultwarn,$groupwarn);
my %userchg;
- if ($context eq 'course') {
- # Get information about course groups
- %curr_groups = &Apache::longroup::coursegroups();
+ if ($context eq 'course' || $setting eq 'course') {
+ if ($context eq 'course') {
+ # Get information about course groups
+ %curr_groups = &Apache::longroup::coursegroups();
+ } elsif ($setting eq 'course') {
+ if ($cid) {
+ %curr_groups =
+ &Apache::longroup::coursegroups($env{'form.dcdomain'},
+ $env{'form.dccourse'});
+ }
+ }
+ # determine section number
+ if ($defaultsec =~ /,/) {
+ push(@sections,split(/,/,$defaultsec));
+ } else {
+ push(@sections,$defaultsec);
+ }
+ # remove non alphanumeric values from section
+ foreach my $item (@sections) {
+ $item =~ s/\W//g;
+ if ($item eq "none" || $item eq 'all') {
+ $defaultwarn = &mt('Default section name [_1] could not be used as it is a reserved word.',$item);
+ } elsif ($item ne '' && exists($curr_groups{$item})) {
+ $groupwarn = &mt('Default section name "[_1]" is the name of a course group. Section names and group names must be distinct.',$item);
+ } elsif ($item ne '') {
+ push(@cleansec,$item);
+ }
+ }
+ if ($defaultwarn) {
+ $r->print($defaultwarn.'
');
+ }
+ if ($groupwarn) {
+ $r->print($groupwarn.'
');
+ }
}
my (%curr_rules,%got_rules,%alerts);
+ my %customroles = &my_custom_roles();
+ my ($custom_ok,@permitted_roles) =
+ &roles_on_upload($context,%customroles);
# Get new users list
- foreach (@userdata) {
- my %entries=&Apache::loncommon::record_sep($_);
+ foreach my $line (@userdata) {
+ my %entries=&Apache::loncommon::record_sep($line);
# Determine user name
unless (($entries{$fields{'username'}} eq '') ||
(!defined($entries{$fields{'username'}}))) {
@@ -3100,30 +3260,43 @@ sub upfile_drop_add {
&mt('[_1]: Unacceptable username for user [_2] [_3] [_4] [_5]',
$entries{$fields{'username'}},$fname,$mname,$lname,$gen).
'');
+ next;
} else {
my $username = $entries{$fields{'username'}};
- my $sec;
- if ($context eq 'course' || $setting eq 'course') {
- # determine section number
- if (defined($fields{'sec'})) {
- if (defined($entries{$fields{'sec'}})) {
- $sec=$entries{$fields{'sec'}};
+ if (defined($fields{'sec'})) {
+ if (defined($entries{$fields{'sec'}})) {
+ my $item = $entries{$fields{'sec'}};
+ $item =~ s/(\s+$|^\s+)//g;
+ if ($item eq "none" || $item eq 'all') {
+ $r->print('
'.&mt('[_1]: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]" - this is a reserved word.',$username,$fname,$mname,$lname,$gen,$item));
+ next;
+ } elsif (exists($curr_groups{$item})) {
+ $r->print('
'.&mt('[_1]: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]" - this is a course group.',$username,$fname,$mname,$lname,$gen,$item).' '.&mt('Section names and group names must be distinct.'));
+ next;
+ } else {
+ push(@secs,$item);
}
- } else {
- $sec = $defaultsec;
}
- # remove non alphanumeric values from section
- $sec =~ s/\W//g;
- if ($sec eq "none" || $sec eq 'all') {
- $r->print('
'.
- &mt('[_1]: Unable to enroll: section name "[_2]" for user [_3] [_4] [_5] [_6] is a reserved word.',
- $username,$sec,$fname,$mname,$lname,$gen));
- next;
- } elsif (($sec ne '') && (exists($curr_groups{$sec}))) {
- $r->print('
'.
- &mt('[_1]: Unable to enroll: section name "[_2]" for user [_3] [_4] [_5] [_6] is a course group. Section names and group names must be distinct.',
- $username,$sec,$fname,$mname,$lname,$gen));
- next;
+ }
+ if ($env{'request.course.sec'} ne '') {
+ @secs = ($env{'request.course.sec'});
+ if (ref($userlist{$username.':'.$domain}) eq 'ARRAY') {
+ my $currsec = $userlist{$username.':'.$domain}[$secidx];
+ if ($currsec ne $env{'request.course.sec'}) {
+ $r->print('
'.&mt('[_1]: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]".',$username,$fname,$mname,$lname,$gen,$secs[0]).'
');
+ if ($currsec eq '') {
+ $r->print(&mt('This user already has an active/future student role in the course, unaffiliated to any section.'));
+
+ } else {
+ $r->print(&mt('This user already has an active/future role in section "[_1]" of the course.',$currsec));
+ }
+ $r->print('
'.&mt('Although your current role has privileges to add students to section "[_1]", you do not have privileges to modify existing enrollments in other sections.',$secs[0]).'
');
+ next;
+ }
+ }
+ } elsif ($context eq 'course' || $setting eq 'course') {
+ if (@secs == 0) {
+ @secs = @cleansec;
}
}
# determine id number
@@ -3152,12 +3325,17 @@ sub upfile_drop_add {
my $role = '';
if (defined($fields{'role'})) {
if ($entries{$fields{'role'}}) {
- my @poss_roles =
- &curr_role_permissions($context,$setting);
- if (grep(/^\Q$entries{$fields{'role'}}\E/,@poss_roles)) {
+ if (grep(/^\Q$entries{$fields{'role'}}\E$/,@permitted_roles)) {
$role=$entries{$fields{'role'}};
- } else {
- my $rolestr = join(', ',@poss_roles);
+ $role =~ s/(\s+$|^\s+)//g;
+ }
+ if ($custom_ok) {
+ if ($customroles{$role}) {
+ $role = 'cr_'.$env{'user.domain'}.'_'.$env{'user.name'}.'_'.$entries{$fields{'role'}};
+ }
+ }
+ if ($role eq '') {
+ my $rolestr = join(', ',@permitted_roles);
$r->print('
'.
&mt('[_1]: You do not have permission to add the requested role [_2] for the user.',$entries{$fields{'username'}},$entries{$fields{'role'}}).'
'.&mt('Allowable role(s) is/are: [_1].',$rolestr)."\n");
next;
@@ -3169,7 +3347,7 @@ sub upfile_drop_add {
}
# Clean up whitespace
foreach (\$domain,\$username,\$id,\$fname,\$mname,
- \$lname,\$gen,\$sec,\$role) {
+ \$lname,\$gen) {
$$_ =~ s/(\s+$|^\s+)//g;
}
# check against rules
@@ -3192,7 +3370,35 @@ sub upfile_drop_add {
}
}
} else {
-# FIXME check if user info can be updated.
+ if ($context eq 'course' || $context eq 'author') {
+ if ($role eq '') {
+ my @checkroles;
+ foreach my $role (@poss_roles) {
+ my $endkey;
+ if ($role ne 'st') {
+ $endkey = ':'.$role;
+ }
+ if (exists($userlist{$username.':'.$domain.$endkey})) {
+ if (!grep(/^\Q$role\E$/,@checkroles)) {
+ push(@checkroles,$role);
+ }
+ }
+ }
+ if (@checkroles > 0) {
+ %canmodify = &can_modify_userinfo($context,$domain,\@userinfo,\@checkroles);
+ }
+ } elsif (ref($modifiable_fields{$role}) eq 'HASH') {
+ %canmodify = %{$modifiable_fields{$role}};
+ }
+ }
+ my @newinfo = (\$fname,\$mname,\$lname,\$gen,\$email,\$id);
+ for (my $i=0; $i<@userinfo; $i++) {
+ if (${$newinfo[$i]} ne '') {
+ if (!$canmodify{$userinfo[$i]}) {
+ ${$newinfo[$i]} = '';
+ }
+ }
+ }
}
if ($id ne '') {
if (!$newuser) {
@@ -3217,29 +3423,73 @@ sub upfile_drop_add {
}
}
if ($password || $env{'form.login'} eq 'loc') {
- my ($userresult,$authresult,$roleresult);
+ my $multiple = 0;
+ my ($userresult,$authresult,$roleresult,$idresult);
+ my (%userres,%authres,%roleres,%idres);
if ($role eq 'st') {
- &modifystudent($domain,$username,$cid,$sec,
- $desiredhost);
- $roleresult =
- &Apache::lonnet::modifystudent
- ($domain,$username,$id,$amode,$password,
- $fname,$mname,$lname,$gen,$sec,$enddate,
- $startdate,$env{'form.forceid'},
- $desiredhost,$email);
+ my $sec;
+ if ($cid) {
+ if (@secs > 0) {
+ $sec = $secs[0];
+ }
+ &modifystudent($domain,$username,$cid,$sec,
+ $desiredhost);
+ $roleresult =
+ &Apache::lonnet::modifystudent
+ ($domain,$username,$id,$amode,$password,
+ $fname,$mname,$lname,$gen,$sec,$enddate,
+ $startdate,$env{'form.forceid'},
+ $desiredhost,$email,'manual','',$cid);
+ $userresult = $roleresult;
+ }
+ } else {
+ if (($context eq 'course') ||
+ (grep(/^\Q$role\E$/,@courseroles))) {
+ if (!$cid) {
+ next;
+ }
+ }
+ my $singlesec;
+ if ((grep(/^\Q$role\E$/,@courseroles)) && ($role ne 'cc')) {
+ if (@secs > 1) {
+ $multiple = 1;
+ foreach my $sec (@secs) {
+ ($userres{$sec},$authres{$sec},$roleres{$sec},$idres{$sec}) =
+ &modifyuserrole($context,$setting,
+ $changeauth,$cid,$domain,$username,
+ $id,$amode,$password,$fname,
+ $mname,$lname,$gen,$sec,
+ $env{'form.forceid'},$desiredhost,
+ $email,$role,$enddate,$startdate,$checkid);
+ }
+ } elsif (@secs > 0) {
+ $singlesec = $secs[0];
+ }
+ }
+ if (!$multiple) {
+ ($userresult,$authresult,$roleresult,$idresult) =
+ &modifyuserrole($context,$setting,
+ $changeauth,$cid,$domain,$username,
+ $id,$amode,$password,$fname,
+ $mname,$lname,$gen,$singlesec,
+ $env{'form.forceid'},$desiredhost,
+ $email,$role,$enddate,$startdate,$checkid);
+ }
+ }
+ if ($multiple) {
+ foreach my $sec (sort(keys(%userres))) {
+ $flushc =
+ &user_change_result($r,$userres{$sec},$authres{$sec},
+ $roleres{$sec},$idres{$sec},\%counts,$flushc,
+ $username,\%userchg);
+
+ }
} else {
- ($userresult,$authresult,$roleresult) =
- &modifyuserrole($context,$setting,
- $changeauth,$cid,$domain,$username,
- $id,$amode,$password,$fname,
- $mname,$lname,$gen,$sec,
- $env{'form.forceid'},$desiredhost,
- $email,$role,$enddate,$startdate,$checkid);
+ $flushc =
+ &user_change_result($r,$userresult,$authresult,
+ $roleresult,$idresult,\%counts,$flushc,
+ $username,%userchg);
}
- $flushc =
- &user_change_result($r,$userresult,$authresult,
- $roleresult,\%counts,$flushc,
- $username,%userchg);
} else {
if ($context eq 'course') {
$r->print('
'.
@@ -3482,7 +3732,6 @@ sub update_user_list {
}
}
my $plrole = &Apache::lonnet::plaintext($role);
- my ($uid,$first,$middle,$last,$gene,$sec);
my $start = $env{'form.'.$item.'_start'};
my $end = $env{'form.'.$item.'_end'};
if ($choice eq 'drop') {
@@ -3502,15 +3751,12 @@ sub update_user_list {
&Apache::lonnet::revokerole($udom,$uname,$scope,$role);
}
} elsif ($choice eq 'delete') {
- $start = -1;
- $end = -1;
if ($role eq 'st') {
-# FIXME - how does role deletion affect classlist?
&Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid);
} else {
$result =
&Apache::lonnet::assignrole($udom,$uname,$scope,$role,$now,
- 0,1);
+ $start,1);
}
} else {
#reenable, activate, change access dates or change section
@@ -3553,27 +3799,36 @@ sub update_user_list {
$nochg = 1;
}
} else {
- if (!grep(/^\Q$sec\E$/,@newsecs)) {
- $revresult =
- &Apache::lonnet::revokerole($udom,$uname,$scope,$role);
+ if (@newsecs > 0) {
+ if (grep(/^\Q$sec\E$/,@newsecs)) {
+ push(@retained,$sec);
+ } else {
+ $revresult =
+ &Apache::lonnet::revokerole($udom,$uname,
+ $scope,$role);
+ }
} else {
- push(@retained,$sec);
+ $revresult =
+ &Apache::lonnet::revokerole($udom,$uname,
+ $scope,$role);
}
}
} else {
- push(@retained,$sec);
+ if ($sec eq '') {
+ $nochg = 1;
+ } else {
+ push(@retained,$sec);
+ }
}
# add new sections
if (@newsecs == 0) {
if (!$nochg) {
- if ($sec ne '') {
- if ($role eq 'st') {
- $result =
- &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,undef,$end,$start,$type,$locktype,$cid);
- } else {
- my $newscope = $scopestem;
- $result = &Apache::lonnet::assignrole($udom,$uname,$newscope,$role,$end,$start);
- }
+ if ($role eq 'st') {
+ $result =
+ &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,undef,$end,$start,$type,$locktype,$cid);
+ } else {
+ my $newscope = $scopestem;
+ $result = &Apache::lonnet::assignrole($udom,$uname,$newscope,$role,$end,$start);
}
}
} else {
@@ -3736,16 +3991,27 @@ sub get_groupslist {
}
sub setsections_javascript {
- my ($form,$groupslist) = @_;
- my ($checkincluded,$finish,$roleplace,$setsection_js);
- if ($form eq 'cu') {
+ my ($formname,$groupslist,$mode) = @_;
+ my ($checkincluded,$finish,$rolecode,$setsection_js);
+ if ($mode eq 'upload') {
+ $checkincluded = 'formname.name == "'.$formname.'"';
+ $finish = "return 'ok';";
+ $rolecode = "var role = formname.defaultrole.options[formname.defaultrole.selectedIndex].value;\n";
+ } elsif ($formname eq 'cu') {
$checkincluded = 'formname.elements[i-1].checked == true';
$finish = 'formname.submit()';
- $roleplace = 3;
+ $rolecode = "var match = str.split('_');
+ var role = match[3];\n";
+ } elsif ($formname eq 'enrollstudent') {
+ $checkincluded = 'formname.name == "'.$formname.'"';
+ $finish = 'formname.submit()';
+ $rolecode = "var match = str.split('_');
+ var role = match[1];\n";
} else {
- $checkincluded = 'formname.name == "'.$form.'"';
+ $checkincluded = 'formname.name == "'.$formname.'"';
$finish = "seccheck = 'ok';";
- $roleplace = 1;
+ $rolecode = "var match = str.split('_');
+ var role = match[1];\n";
$setsection_js = "var seccheck = 'alert';";
}
my %alerts = &Apache::lonlocal::texthash(
@@ -3770,8 +4036,7 @@ function setSections(formname) {
var checkcurr = str.match(re1);
if (checkcurr != null) {
if ($checkincluded) {
- var match = str.split('_');
- var role = match[$roleplace];
+ $rolecode
if (role == 'cc') {
alert("$alerts{'secd'}\\n$alerts{'accr'}");
}
@@ -3846,6 +4111,9 @@ sub can_create_user {
my ($dom,$context,$usertype) = @_;
my %domconf = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom);
my $cancreate = 1;
+ if (&Apache::lonnet::allowed('mau',$dom)) {
+ return $cancreate;
+ }
if (ref($domconf{'usercreation'}) eq 'HASH') {
if (ref($domconf{'usercreation'}{'cancreate'}) eq 'HASH') {
if ($context eq 'course' || $context eq 'author') {
@@ -4000,7 +4268,8 @@ sub get_permission {
} else {
my @allroles = &roles_by_context($context);
foreach my $role (@allroles) {
- if (&Apache::lonnet::allowed('c'.$role,$env{'request.role.domain'})) { $permission{'cusr'} = 1;
+ if (&Apache::lonnet::allowed('c'.$role,$env{'request.role.domain'})) {
+ $permission{'cusr'} = 1;
last;
}
}
@@ -4029,6 +4298,27 @@ sub authorpriv {
|| (&Apache::lonnet::allowed('caa',$audom.'/'.$auname))) { return ''; } return 1;
}
+sub roles_on_upload {
+ my ($context,%customroles) = @_;
+ my (@possible_roles,@permitted_roles);
+ if ($context eq 'domain') {
+ @possible_roles = &curr_role_permissions($context,undef,1);
+ push(@possible_roles,&curr_role_permissions($context,'course',1));
+ } else {
+ @possible_roles = &curr_role_permissions($context,undef,1);
+ }
+ my $custom_ok = 0;
+ foreach my $role (@possible_roles) {
+ if ($role eq 'cr') {
+ $custom_ok = 1;
+ push(@permitted_roles,keys(%customroles));
+ } else {
+ push(@permitted_roles,$role);
+ }
+ }
+ return ($custom_ok,@permitted_roles);
+}
+
sub get_course_identity {
my ($cid) = @_;
my ($cnum,$cdom,$cdesc);
@@ -4188,6 +4478,5 @@ sub sectioncheck_alerts {
return %alerts;
}
-
1;